/* * Copyright (C) con terra GmbH */ /** * Utility type to create more specific parameter typings for {@link Stateful.watch}'s callback. * * This allows us to make the types of the callback's value parameters * dependent on the callback's name parameter. This way, handler code like * the following is well-typed: * ```ts * let stateful: Stateful<{id: string, priority: number}>; * stateful.watch('*', (name, oldValue, newValue) => { * if (name === 'id') { * // TypeScript can now infer that newValue is a string * console.log(newValue.substring(0, 4)); * } * if (name === 'priority') { * // TypeScript can now infer that oldValue and newValue are numbers * console.log(newValue - oldValue); * } * }); * ``` * * This uses TypeScript's distributive behavior in conditional types to turn * a union of properties into a union of tuples. * * @see https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types */ type WatchCallbackParams = P extends unknown ? [name: P, oldValue: T[P], newValue: T[P]] : never; type Stateful = T & { watch: ( property: Prop, handler: (...args: WatchCallbackParams) => void ) => { remove: () => void }; set: (property: Prop, value: T[Prop]) => void; get: (property: Prop) => T[Prop]; }; /** Placeholder type for parameters to all the Evented functions. */ type UnknownEvent = unknown; /** Utility type for all the handler functions in Tool. */ type HandlerFn = ((this: This, event: Event) => Result) | undefined; type TooltipPosition = "above" | "below" | "after" | "before"; /** A partial copy of the declaration in ct/tools/Tool adapted for TypeScript. The types are mostly educated guesses. */ interface ToolProperties { /** * Given tool id. */ id: string; /** * The title of the tool. */ title: string | undefined; /** * A description of the tool. */ description: string | undefined; /** * A tool tip. */ tooltip: string | undefined; /** * The tooltip positions. * e.g. ["above","below","after","before"] */ tooltipPositions: TooltipPosition[] | undefined; /** * Priority is used to ensure an ordering of tools. * Tools with high priority are first, equal priority means sort by id. */ priority: number; /** * A tool group this information is also added as css class to the root node of the created button or menu. */ toolGroup: string; /** * A tool class appended to the root node of the created button or menu. * Note that ctTool_${id} is always added */ toolClass: string; /** * A tool icon class appended to the icon node of the created button or menu. * Note that ctToolIcon_${id} is always added */ iconClass: string; /** * The visible state of the tool. * On change the onShow/onHide events are fired. */ visibility: boolean; /** * The enabled state of the tool. * On change the onDisabled, onEnabled events are fired. */ enabled: boolean; /** * The active state of the tool, this is only of interest if the tool is togglable. * On change the onActivate, onDeactivate events are fired. */ active: boolean; /** * The togglable state of the tool, this marks that the tool can be toggled. * It should be set in the constructor and the state value should never dynamically change. */ togglable: boolean; /** * The processing state of the tool, this marks that the tool is currently processing something. * The state is toggled by the fireProcess* methods and independent from any other state of the tool. */ processing: boolean; /** * The self reference. Please see the ToolReference class to note that this property allows * to handle a tool like a tool reference, which makes code expecting references to be used with tools directly. */ tool: Tool; /** * Flag auto disables the tool if it becomes hidden. * default: true. */ disableOnHide: boolean; /** * Flag auto enables the tool if it becomes visible. * default: true. */ enableOnShow: boolean; /** * Flag auto deactivates the tool if it is disabled. * default: true. */ deactivateOnDisable: boolean; /** * Flag auto activates the tool if it is enabled. * default: false. */ activateOnEnable: boolean; /** * Flag auto enables the tool if set("active",true) is called. */ enableOnActivate: boolean; /** * The scope of the default handler functions. */ handlerScope: object | null; /** * The handler function called if the tool is clicked. */ clickHandler: HandlerFn; /** * The handler function called if the tool is double clicked. */ dblClickHandler: HandlerFn; /** * The handler function called before the onActivate event is fired. */ beforeActivateHandler: HandlerFn; /** * The handler function called if the tool is activated. */ activateHandler: HandlerFn; /** * The handler function called before the onDeactivate event is fired. */ beforeDeactivateHandler: HandlerFn; /** * The handler function called if the tool is deactivated. */ deactivateHandler: HandlerFn; /** * The handler function called if the tool becomes enabled. */ enabledHandler: HandlerFn; /** * The handler function called if the tool becomes disabled. */ disabledHandler: HandlerFn; /** * The handler function called if the tool becomes visible. */ showHandler: HandlerFn; /** * The handler function called if the tool becomes hidden. */ hideHandler: HandlerFn; /** * The handler function called if the tool starts a processing task. */ processStartHandler: HandlerFn; /** * The handler function called if the tool ends a processing task. */ processEndHandler: HandlerFn; /** * Rules flag read by the toolrules bundle (optional). */ rules: object | null; /** * The handler function called to check a condition before activating a togglable tool. * The function has to return true if condition is fulfilled and false if not. */ activationConditionHandler: HandlerFn< ToolProperties["activationConditionHandlerScope"] | Tool, UnknownEvent, boolean >; /** * The scope of the activation condition handler function. */ activationConditionHandlerScope: object | null; /** * If true real click,check/uncheck,dblclick events are delegated async into the tool model, * so that the browser event flow is not broken. */ async: boolean; /** * Simulates a click on the tool. * Please note that this does not change the active state. * A client have to call set("active",true|false) to change the state. */ click(evt: UnknownEvent): void; /** * Simulates a dbl click on the tool. */ dblClick(evt: UnknownEvent): void; /** * Sends a info message to the tool. It simple fires the onInfoMessage() event. * Such a message is normally produced in the backend, to indicate a "please click me" state on the tool. */ infoMsg(msgObj: { message: string }): void; /** * The onClick event */ onClick(event: UnknownEvent): void; /** * The onDoubleClick event **/ onDblClick(event: UnknownEvent): void; /** * The onInfoMessage event, transports a message from the backend to the tool widget. **/ onInfoMessage(event: UnknownEvent): void; /** * The onBeforeActivate event, it is called short before onActivate. **/ onBeforeActivate(event: UnknownEvent): void; /** * The onActivate event **/ onActivate(event: UnknownEvent): void; /** * The onDeactivate event **/ onDeactivate(event: UnknownEvent): void; /** * The onBeforeDeactivate event, it is called short before onDeactivate. **/ onBeforeDeactivate(event: UnknownEvent): void; /** * The onEnabled event, if the tool becomes enabled (available for pressing) **/ onEnabled(event: UnknownEvent): void; /** * The onDisabled event, if the tool becomes disabled (not available for pressing) **/ onDisabled(event: UnknownEvent): void; /** * The onShow event, if the tool becomes visible (allowed to show on screen) **/ onShow(event: UnknownEvent): void; /** * The onHide event, if the tool becomes hidden (not allowed to show on screen) **/ onHide(event: UnknownEvent): void; /** * `onProcessStart` is called when an external process is started */ onProcessStart(event: UnknownEvent): void; /** * `onProcessEnd` is called when an external process is stopped */ onProcessEnd(event: UnknownEvent): void; } interface ToolConstructor { new (props?: Partial): Tool; } type Tool = Stateful; // Declaring a type and a variable of the same name is a technique used by // TypeScript's type declarations for standard library types such as Date. declare const Tool: ToolConstructor; export { Tool as default }; export type { TooltipPosition };