import { type XYWH } from "@thegraid/common-lib"; import { type DisplayObject, Graphics, Shape, type Text } from "@thegraid/easeljs-module"; import { NamedContainer } from "./named-container"; export interface Paintable extends DisplayObject { /** * paint with given or current color; updateCache() * @param colorn [current color] color to paint * @param force [false] repaint even if same color. */ paint(colorn?: string, force?: boolean): Graphics; /** Paintable can compute its own Bounds. setBounds(undefined, 0, 0, 0) */ setBounds(x: undefined | null | number, y: number, width: number, height: number): void; /** compute bounds of this Paintable */ calcBounds(): XYWH; /** ensure Paintable is cached; expect setBounds() already done. */ setCacheID(): void; } /** Create/Color Graphics Function (color, g0); extend graphics with additional instructions. * g0 is clone of "baseline" Graphics. (may be clear) */ export type CGF = (color: string, g?: Graphics) => Graphics; /** * Usage: * @example * class MyShape extends PaintableShape { * constructor() { * super((fillc) => this.mycgf(fillc), fillc, g0); // 'this' is allowed! * this._cgf = this.mycgf; // without => wrapper * } * mycgf(color: string, g = this.g0) => { * return g.f(color).dc(0, 0, rad); * } * } * ... * ms.paint(red); --> ms.graphics = g.f(red) --> new CG(red); */ export declare class PaintableShape extends Shape implements Paintable { _cgf: CGF; colorn: string; static defaultRadius: number; /** if supplied in contructor, cgf extends a clone [otherwise use new Graphics()] */ _g0?: Graphics; /** initial/baseline Graphics, cgf extends to create cgfGraphics */ get g0(): Graphics; /** previous/current Graphics that were rendered. (optimization... paint(color, true) to override) */ cgfGraphics: Graphics; /** * * @param _cgf Create Graphics Function * @param colorn paint with this color * @param g0 Graphics to clone (or create); used as baseline Graphics for each paint() */ constructor(_cgf: CGF, colorn?: string, g0?: Graphics); updateCacheInPaint: boolean; get cgf(): CGF; /** set new cgf; and clear "previously rendered Graphics" */ set cgf(cgf: CGF); /** render graphics from cgf. */ paint(colorn?: string, force?: boolean): Graphics; /** * Paintable shape can & should calculate its Bounds. * * Subclasses should override to calculate their bounds. * @param x * * undefined -> calculate bounds, * * null -> remove bounds, * * number -> set to {x, y, width, height} * @param y * @param width * @param height */ setBounds(x: number | undefined | null, y: number, width: number, height: number): void; /** subclass to override to compute actual bounds of their Shape. */ calcBounds(): XYWH; /** ensure PaintableShape is cached; uses getBounds() ?? calcBounds(). * * @param scale [1] scale to use if cache is created */ setCacheID(scale?: number): void; } /** an n-sided Polygon, tilted */ export declare class PolyShape extends PaintableShape { rad: number; nsides: number; pSize: number; tilt: number; fillc: string; strokec: string; /** * pscgf() invokes drawPoly(0,0,...); * * To adjust (x,y): supply g0 = new Graphics().mt(x,y) * @param params \{ rad, nsides, pSize, tilt, fillc, strokec } * @param g0 Graphics base */ constructor({ rad, nsides, pSize, tilt, fillc, strokec }: { rad?: number; nsides?: number; pSize: number; tilt?: number; fillc?: string; strokec?: string; }, g0?: Graphics); readonly degToRadians: number; /** set fillc and strokec, invoke drawPoly(0, 0, ...) */ pscgf(fillc: string, g?: Graphics): Graphics; setBounds(x: number | undefined | null, y: number, width: number, height: number): void; } export declare class EllipseShape extends PaintableShape { fillc: string; radx: number; rady: number; strokec: string; /** * ellipse centered on (0,0), axis is NS/EW, rotate after. * @param radx radius in x dir * @param rady radisu in y dir * retain g0, to use as baseline Graphics for each paint() */ constructor(fillc?: string, radx?: number, rady?: number, strokec?: string, g0?: Graphics); /** EllispseShape.cgf */ escgf(fillc: string, g?: Graphics): Graphics; setBounds(x: number | undefined | null, y: number, width: number, height: number): void; } /** * Circle centered on (0,0) * @param rad radius * retain g0, to use as baseline Graphics for each paint() */ export declare class CircleShape extends EllipseShape { constructor(fillc?: string, rad?: number, strokec?: string, g0?: Graphics); } /** XYWH & cornerRadius & strokeSize */ type XYWHRS = Partial & { r?: number; s?: number; rr?: [tl: number, tr: number, bl: number, br: number]; }; /** a Rectangular Shape, maybe with rounded corners */ export declare class RectShape extends PaintableShape { /** the XYWH rectangle to draw & fill; components set by setRectRad() */ readonly _rect: XYWH; /** complex RoundedRect, each corner can be different */ _rr?: [tl: number, tr: number, bl: number, br: number]; /** _cRad used if _rr is undefined */ _cRad: number; /** stroke size. For no stroke use strokec = ''; ({ s: 0 } is not effective) */ _sSiz: number; strokec: string; /** * Paint a rectangle (possibly with rounded corners) with fillc and stroke. * * corner radius: rr = [tl, tr, br, bl] OR r = radius for all 4 * * rscgf(fillc) uses rect, strokec, cRad, sSiz, g0 to paint a rectangle. * @param rect \{ x=0, y=0, w=rad, h=rad, r=0, s=1 } origin, extent, corner radius, stroke width. * @param fillc [C.white] color to paint the rectangle, '' for no fill * @param strokec [C.black] stroke color, '' for no stroke * @param g0 [new Graphics()] Graphics to clone and extend during paint() */ constructor({ x, y, w, h, r, s, rr }: XYWHRS, fillc?: string, strokec?: string, g0?: Graphics); /** update any of {x, y, w, h, r, s} & setBoundsNull(); for future paint() */ setRectRad({ x, y, w, h, r, s, rr }: XYWHRS): void; setBounds(x: number | undefined | null, y: number, width: number, height: number): void; /** draw rectangle, maybe with rounded corner, maybe with ss & strokec * * RectShape tweaks things so the border stroke is drawn outside the given xywh rectangle. * * the bounds are computed by rounding sSize up to an even int. */ rscgf(fillc: string, g?: Graphics): Graphics; } /** Container with a colored RectShape behind the given DisplayObject. * * The RectShape extends by 'border' around the bounds of the DisplayObject. * * To tweak border extents, set: .borders, .dx, .dy, .dx0, .dx1, .dy0, .dy1 * */ export declare class RectWithDisp extends NamedContainer implements Paintable { /** * Create Container a RectShape behind the given DisplayOBject. * * The RectShape extends around (disp.getBounds() ?? { 0, 0, 10, 10 }) * @param disp a DisplayObject * @param options * * color [WHITE] of background RectShape. * * border [5] extend RectShape around disp * * corner [0] corner radius * @param cgf [rscgf] CGF for the RectShape */ constructor(disp: DisplayObject, options: RectWithDispOptions, cgf?: CGF); /** a RectShape using calcBounds[borders, disp], no strokec. */ rectShape: RectShape; /** DisplayObject displayed above a RectShape of color */ readonly disp: DisplayObject; dx0: number; dx1: number; dy0: number; dy1: number; /** * set dx0 (left) & dx1 (right) border size. * * Note: call setBounds(undefined, 0, 0, 0) after adjusting dx* or dy* */ set dx(dx: number); /** * set dy0 (top) & dy1 (bottom) border size. * * Note: call setBounds(undefined, 0, 0, 0) after adjusting dx* or dy* */ set dy(dy: number); /** extend RectShape around DisplayObject bounds. */ set border(b: number); /** [dx0, dx1, dy0, dy1] are [left, right, top, bottom] margins */ get borders(): [number | undefined, number | undefined, number | undefined, number | undefined]; /** * set any of [dx0, dx1, dy0, dy1] * * Note: setBounds(undefined, 0, 0, 0) after adjusting borders */ set borders(db: [number | undefined, number | undefined, number | undefined, number | undefined]); _corner: number; /** corner radius, does not repaint/recache */ get corner(): number; set corner(r: number); /** RectWithDisp.paint(color) paints rectShape with new color and XYWHRS. */ paint(color?: string, force?: boolean): Graphics; /** uses PaintableShape.setCacheID. */ setCacheID(): void; /** Extend around (disp.getBound() ?? {0, 0, 10, 10}) * * override if (disp.bounds +/- border) is not what you want. */ calcBounds(): XYWH; /** * Note: if you addChild() to this Container, setBounds(undefined) won't consider them * unless you override calcBounds() to do a Rectangle.union() */ setBounds(x: number | undefined | null, y: number, width: number, height: number): void; } /** A Text label above a colored RectShape. * * Configure the border width [.3] and corner radius [0]. */ export declare class TextInRect extends RectWithDisp implements Paintable, TextStyle { disp: Text; /** Text object displayed above a RectShape of color */ get label(): Text; /** * Create Container with Text above a RectShape. * @param text label as Text or string * @param options [{}] border, corner, fontSize, textColor * @param cgf [rscgf] CGF for the RectShape * @options * * bgColor: [C.WHITE] color of background RectShape * * border: [.3] extend RectShape around Text; fraction of fontSize * * corner: [0] corner radius of background; fraction of fontSize * * fontSize: [defaultRadius/2] if label is a string * * textColor: [C.BLACK] initial text.color if label is a string (deprecated) * * textColors: [[C.BLACK, C.WHITE]] pick best contrast when paint(color); OR false to retain textColor * * textColor is retained when textColors == false or if paint() is not called. */ constructor(label: Text | string, options?: TextInRectOptions, cgf?: CGF); textColors: string[]; /** * Advise rectShape.cgf so textColor is updated with C.pickTextColor when paint() invokes rectShape.cgf; * @param textColors [this.textColors] set/retain as this.textColors * @param cgf [this.rectShape.cgf] the cgf to wrap and set as rectShape.cgf */ alsoPickTextColor(textColors?: string[], cgf?: CGF): void; get fontSize(): number; get fontName(): string; get textWidth(): number; get textColor(): string; get bgColor(): string; /** extend RectShape around Text bounds, in per-LineHeight units; * * sets: dx = dy = tb * * actual border size will be: tb * (LineHeight of text) * @param tb fraction of line height. */ set border(tb: number); /** set all the borders, in per-LineHeight units */ set borders(db: [number, number, number, number]); /** get all the borders, in pixel units; as used by calcBounds */ get borders(): [number, number, number, number]; /** corner radius; fraction of line height. */ get corner(): number; set corner(tr: number); /** the string inside the Text label. aka innerText */ get label_text(): string | undefined; set label_text(txt: string | undefined); } export type TextStyle = { fontSize?: number; fontName?: string; textColor?: string; textAlign?: string; }; /** RectWithDispOptions */ export type RectWithDispOptions = { bgColor?: string; border?: number; corner?: number; }; export type TextInRectOptions = RectWithDispOptions & TextStyle & { textColors?: string[] | false; }; export type UtilButtonOptions = { rollover?: (mouseIn: boolean) => void; active?: boolean; visible?: boolean; }; /** Construct a CenterText for a TextInRect. */ export declare class UtilButton extends TextInRect { /** * Create Container with CenterText above a RectShape. * * on(rollover|rollout, this.rollover(mouseIn)) * * initially visible & mouseEnabled, but deactivated. * @param label if not instanceof Text: new CenterText(label, fontSize, textColor) * @param options * * bgColor: [C.WHITE] color of background RectShape * * rollover: [undefined] invoked for rollover/rollout with (true/false) * * visible: [false] initial visibility * * active: [false] supply true|false to activate(active, visible) including stage?.update() * * border: [.3] extend RectShape around Text; fraction of fontSize * * corner: [0] corner radius of background; fraction of fontSize * * fontSize: [F.defaultSize] if label is a string * * textColor: [C.BLACK] if label is a string * * textColors: [[C.BLACK, C.WHITE]] pick best contrast when paint(color); OR false * @param cgf [rscgf] CGF for the RectShape */ constructor(label: string | Text, options?: UtilButtonOptions & TextInRectOptions, cgf?: CGF); /** When activated, this.rollover(mouseIn) is invoked when mouse enter/exits this button. */ rollover: (mouseIn: boolean) => void; _active: boolean; /** indicates if this button is currently activated. */ get isActive(): boolean; /** * Activate (or deactivate) this UtilButton. * * When activated: visible, mouseEnabled, enable rollover(mouseIn). * * @param active [true] false to deactivate * @param vis [active] true or false to set this.visible * @param update [vis !== this.visible] if true then stage.update() * @returns this */ activate(active?: boolean, vis?: boolean, update?: boolean): this; /** * Maybe hide/deactivate this UtilButton, repaint the stage, then call function/method. * * Allow Chrome to finish stage.update() before proceeding with after(). * * @param after [() => {}] callback on('drawend') when stage.update is done [none] * @param scope [this] thisArg for after [this UtilButton] * @param hide [false] true to deactivate this UtilButton * @deprecated use easeljs-lib.afterUpdate(dispObj, after, scope) directly */ updateWait(after?: () => void, scope?: any, hide?: boolean): void; } export {};