import { Board } from "../board" import { Events } from "../event" import { BUILT_IN_FONTS, FontFamilysChecker, IFontInfo } from "../fonts" import type { CrossData, CrossTool, HalfTickData, HalfTickTool, LinesData, LinesTool, OvalData, OvalTool, PenData, PenTool, PolygonData, PolygonTool, RectData, RectTool, ShapeCross, ShapeEnum, ShapeHalfTick, ShapeLines, ShapeOval, ShapePen, ShapePolygon, ShapeRect, ShapeText, ShapeTick, TextData, TextTool, TickData, TickTool } from "../shape" import type { IShapeData, Shape, ShapeData } from "../shape/base" import { ShapeType, getShapeName } from "../shape/ShapeEnum" import { SelectorTool } from "../tools" import type { ITool } from "../tools/base/Tool" import { ToolEnum, ToolType, getToolName } from "../tools/ToolEnum" import type { FactoryEnum, FactoryType } from "./FactoryEnum" import type { IFactory } from "./IFactory" export interface IFactoryInfomation { readonly name: string readonly desc: string } export interface IFactoryCreater { (): F } export interface IToolInfomation { readonly name: string readonly desc: string readonly shape: S } export interface IShapeInfomation { readonly name: string readonly desc: string readonly type: S } export interface IToolCreater { (): T } export interface IShapeDataCreater { (): D } export interface IShapeCreater { (data: D): S } const Tag = 'Gaia' export class Gaia { private static _fonts = new Map(); private static _tools = new Map(); private static _toolInfos = new Map() private static _shapeDatas = new Map>() private static _shapes = new Map>() private static _shapeInfos = new Map() private static _factorys = new Map() private static _factoryInfos = new Map() private static _fonts_ininted = false static get fonts(): ReadonlyMap { if (!this._fonts_ininted) { this.registerFont(BUILT_IN_FONTS) this._fonts_ininted = true; } return this._fonts; } static checkFont: (fontFamily: string) => boolean = FontFamilysChecker.check; static registerFont(infos: IFontInfo[]) { for (const info of infos) { if (this._fonts.has(info.family)) { console.warn(`[${Tag}::registerFont] font info already exists, family: "${info.family}"`); continue; } const t = Date.now() const ok = this.checkFont(info.family) if (ok) this._fonts.set(info.family, info) else console.warn(`[${Tag}::registerFont] font not supported, family: "${info.family}", name: "${info.name}", desc: "${info.desc}"`) console.log(`[${Tag}::registerFont] checking, family: "${info.family}", duration: ${Date.now() - t}ms`) }; } /** * 注册工厂 * * @static * @param {FactoryType} type 工厂类型 * @param {IFactoryCreater} creator * @param {IFactoryInfomation} info * @memberof Gaia */ static registerFactory(type: FactoryType, creator: IFactoryCreater, info: IFactoryInfomation): void { if (this._factorys.has(type)) { console.warn(`[${Tag}::registerFactory] factory '${type}' already exists!`); } else if (this._factoryInfos.has(type)) { console.warn(`[${Tag}::registerFactory] factory info '${type}' already exists!`); } this._factorys.set(type, creator); this._factoryInfos.set(type, info); } /** * 列出工厂类型 * * @static * @return {FactoryType[]} * @memberof Gaia */ static listFactories(): FactoryType[] { return Array.from(this._factoryInfos.keys()) } static factory(type: K): FactoryEnumFactoryMap[K]; static factory(type: FactoryType): IFactoryCreater | undefined; static factory(type: FactoryType): IFactoryCreater | undefined { return this._factorys.get(type); } static registerTool(type: ToolType, creator: IToolCreater, info?: Partial): void { if (this._tools.has(type)) { console.warn(`${Tag}::registerTool`, `tool '${type}' already exists!`); } else if (this._toolInfos.has(type)) { console.warn(`${Tag}::registerTool`, `tool info '${type}' already exists!`); } this._tools.set(type, creator); this._toolInfos.set(type, { shape: info?.shape, name: info?.name || getToolName(type), desc: info?.desc || getToolName(type), }) } static listTools(): ToolType[] { return Array.from(this._tools.keys()); } static tool(type: K): ToolEnumToolMap[K]; static tool(type: ToolType): IToolCreater | undefined; static tool(type: ToolType): IToolCreater | undefined { return this._tools.get(type); } static toolInfo(type: K): ToolEnumToolInfoMap[K]; static toolInfo(type: ToolType): IToolInfomation | undefined; static toolInfo(type: ToolType): IToolInfomation | undefined { return this._toolInfos.get(type); } static editToolInfo(type: K, func: (i: ToolEnumToolInfoMap[K]) => ToolEnumToolInfoMap[K]): void; static editToolInfo(type: ToolType, func: (i: IToolInfomation) => IToolInfomation): void; static editToolInfo(type: ToolType, func: (i: IToolInfomation) => IToolInfomation): void { let info = this._toolInfos.get(type); if (!info) { return; } info = func(info); this._toolInfos.set(type, info); } static registerShape( type: ShapeType, dataCreator: IShapeDataCreater, shapeCreator: IShapeCreater, info?: Partial ): void { if (this._shapeInfos.has(type)) { console.warn(`${Tag}::registerShape`, `shape info '${type}' already exists!`); } else if (this._shapeDatas.has(type)) { console.warn(`${Tag}::registerShape`, `shape data'${type}' already exists!`); } else if (this._shapes.has(type)) { console.warn(`${Tag}::registerShape`, `shape '${type}' already exists!`); } this._shapeInfos.set(type, { name: info?.name || getShapeName(type), desc: info?.desc || getShapeName(type), type }) this._shapeDatas.set(type, dataCreator); this._shapes.set(type, shapeCreator); } static listShapes(): ShapeType[] { return Array.from(this._shapes.keys()); } static shapeInfo(type: K): ShapEnumShapeInfoMap[K]; static shapeInfo(type: ShapeType): IShapeInfomation | undefined; static shapeInfo(type: ShapeType): IShapeInfomation | undefined { return this._shapeInfos.get(type) } static shapeData(type: K): ShapeEnumShapeDataMap[K]; static shapeData(type: ShapeType): IShapeDataCreater | undefined; static shapeData(type: ShapeType): IShapeDataCreater | undefined { return this._shapeDatas.get(type); } static shape(type: K): ShapeEnumShapeMap[K]; static shape(type: ShapeType): IShapeCreater | undefined; static shape(type: ShapeType): IShapeCreater | undefined { return this._shapes.get(type); } static registAction(eventType: K, handler: ActionHandler): void; static registAction(eventType: string, handler: ActionHandler): void { this._actionHandler.set(eventType, handler); } static listActions(): string[] { return Array.from(this._actionHandler.keys()) } static action(eventType: string): ActionHandler | undefined { return this._actionHandler.get(eventType); } private static _actionHandler = new Map() } export interface ActionHandler { isAction(board: Board, e: D): boolean, undo(board: Board, e: D): void; redo(board: Board, e: D): void; } export interface FactoryEnumFactoryMap { /* Built-in factory */ [FactoryEnum.Default]: IFactoryCreater } export interface ToolEnumToolMap { /* Built-in tool */ [ToolEnum.Selector]: IToolCreater; [ToolEnum.Pen]: IToolCreater; [ToolEnum.Rect]: IToolCreater; [ToolEnum.Oval]: IToolCreater; [ToolEnum.Text]: IToolCreater; [ToolEnum.Polygon]: IToolCreater; [ToolEnum.Tick]: IToolCreater; [ToolEnum.Cross]: IToolCreater; [ToolEnum.HalfTick]: IToolCreater; [ToolEnum.Lines]: IToolCreater; } export interface ToolEnumToolInfoMap { /* Built-in tool info */ [ToolEnum.Selector]: IToolInfomation; [ToolEnum.Pen]: IToolInfomation; [ToolEnum.Rect]: IToolInfomation; [ToolEnum.Oval]: IToolInfomation; [ToolEnum.Text]: IToolInfomation; [ToolEnum.Polygon]: IToolInfomation; [ToolEnum.Tick]: IToolInfomation; [ToolEnum.Cross]: IToolInfomation; [ToolEnum.HalfTick]: IToolInfomation; [ToolEnum.Lines]: IToolInfomation; } export interface ShapEnumShapeInfoMap { /* Built-in shape info */ [ShapeEnum.Pen]: IShapeInfomation; [ShapeEnum.Rect]: IShapeInfomation; [ShapeEnum.Oval]: IShapeInfomation; [ShapeEnum.Text]: IShapeInfomation; [ShapeEnum.Polygon]: IShapeInfomation; [ShapeEnum.Tick]: IShapeInfomation; [ShapeEnum.Cross]: IShapeInfomation; [ShapeEnum.HalfTick]: IShapeInfomation; [ShapeEnum.Lines]: IShapeInfomation; } export interface ShapeEnumShapeDataMap { /* Built-in shape data */ [ShapeEnum.Pen]: IShapeDataCreater; [ShapeEnum.Rect]: IShapeDataCreater; [ShapeEnum.Oval]: IShapeDataCreater; [ShapeEnum.Text]: IShapeDataCreater; [ShapeEnum.Polygon]: IShapeDataCreater; [ShapeEnum.Tick]: IShapeDataCreater; [ShapeEnum.Cross]: IShapeDataCreater; [ShapeEnum.HalfTick]: IShapeDataCreater; [ShapeEnum.Lines]: IShapeDataCreater; } export interface ShapeEnumShapeMap { /* Built-in shape data */ [ShapeEnum.Pen]: IShapeCreater; [ShapeEnum.Rect]: IShapeCreater; [ShapeEnum.Oval]: IShapeCreater; [ShapeEnum.Text]: IShapeCreater; [ShapeEnum.Polygon]: IShapeCreater; [ShapeEnum.Tick]: IShapeCreater; [ShapeEnum.Cross]: IShapeCreater; [ShapeEnum.HalfTick]: IShapeCreater; [ShapeEnum.Lines]: IShapeCreater; }