interface IPrimitive {
    afterAutoscale(): void;
    attached(host: PrimitiveHost): void;
    autoscaleInfo(): null | { max: number; min: number };
    detached(): void;
    draw(ctx: CanvasRenderingContext2D, rc: PrimitiveRenderContext): void;
    hitBounds(
        rc: PrimitiveRenderContext,
    ): null | { bottom: number; left: number; right: number; top: number };
    hitTest(
        x: number,
        y: number,
        rc: PrimitiveRenderContext,
    ): null | PrimitiveHit;
    zOrder(): ZOrder;
}

Implemented by

Methods

  • Optional: run once per frame after every scale on the pane has been measured, and before anything is painted.

    draw is too late for anything that has to change a scale, because the price axis is painted near the top of paintBase while primitives draw further down: a range corrected in draw labels its axis one frame late, and on a static chart that frame never comes. A comparison overlay lining its scale up with the pane's own is the case this exists for.

    Returns void

  • Optional: expand the pane's autoscale range so this primitive isn't clipped.

    Returns null | { max: number; min: number }

  • Optional: the box, in the coordinates hitTest receives, outside which it answers null, or null when nothing of this primitive can be hit at all. Edges are inclusive, and an unbounded side may be infinite.

    A pointer move then asks hitTest only of primitives whose box it is in, so a pane carrying hundreds of them pays for the few near the pointer. The pane asks for the box once and reuses it while nothing it can follow changes: the time scale and the bars' times, the pane's price scales, its size and axes, the pixel ratio, the hover and drag state, and the primitive's own state, which it announces through requestUpdate. A box that follows anything else, such as bar prices, has to request an update when that changes, or leave this out. Work the box out from the same geometry hitTest answers from, rc or what the last draw recorded: a box asked for between a change and the frame that paints it is asked for again once that frame is painted. Absent, every pointer move asks hitTest.

    Returns null | { bottom: number; left: number; right: number; top: number }