From 66f6918a6908c297f31c70d7d4524243308994a1 Mon Sep 17 00:00:00 2001 From: liujuping Date: Thu, 27 Oct 2022 19:53:21 +0800 Subject: [PATCH] feat: add APIs for plugin-outline-pane which will be splitted in near future --- packages/designer/src/designer/detecting.ts | 4 +++ packages/designer/src/designer/index.ts | 1 + packages/engine/src/modules/designer-cabin.ts | 25 ++++++++++++- packages/engine/src/modules/symbols.ts | 2 ++ packages/engine/src/modules/utils.ts | 2 +- .../plugin-outline-pane/src/views/tree.tsx | 2 +- packages/shell/src/detecting.ts | 8 +++++ packages/shell/src/document-model.ts | 36 +++++++++++++++---- packages/shell/src/node.ts | 24 +++++++++++-- packages/shell/src/project.ts | 15 ++++++-- packages/shell/src/prop.ts | 7 ++++ packages/shell/src/selection.ts | 11 ++++++ packages/shell/src/symbols.ts | 3 +- packages/types/src/editor.ts | 2 +- 14 files changed, 127 insertions(+), 15 deletions(-) diff --git a/packages/designer/src/designer/detecting.ts b/packages/designer/src/designer/detecting.ts index 4fc60adf9..011142ffb 100644 --- a/packages/designer/src/designer/detecting.ts +++ b/packages/designer/src/designer/detecting.ts @@ -7,6 +7,10 @@ const DETECTING_CHANGE_EVENT = 'detectingChange'; export class Detecting { @obx.ref private _enable = true; + /** + * 控制大纲树 hover 时是否出现悬停效果 + * TODO: 将该逻辑从设计器中抽离出来 + */ get enable() { return this._enable; } diff --git a/packages/designer/src/designer/index.ts b/packages/designer/src/designer/index.ts index 79982c45b..8c98a3507 100644 --- a/packages/designer/src/designer/index.ts +++ b/packages/designer/src/designer/index.ts @@ -8,3 +8,4 @@ export * from './location'; export * from './offset-observer'; export * from './scroller'; export * from './setting'; +export * from './active-tracker'; diff --git a/packages/engine/src/modules/designer-cabin.ts b/packages/engine/src/modules/designer-cabin.ts index 812f53a76..0ba28c701 100644 --- a/packages/engine/src/modules/designer-cabin.ts +++ b/packages/engine/src/modules/designer-cabin.ts @@ -5,11 +5,18 @@ import { TransformStage, LiveEditing, isDragNodeDataObject, + isDragNodeObject, + isDragAnyObject, DragObjectType, isNode, + isShaken, + contains, + LocationDetailType, + isLocationChildrenDetail, + ScrollTarget, } from '@alilc/lowcode-designer'; import { Editor } from '@alilc/lowcode-editor-core'; -import { Dragon } from '@alilc/lowcode-shell'; +import { designerCabinSymbol, Dragon } from '@alilc/lowcode-shell'; export default function getDesignerCabin(editor: Editor) { const designer = editor.get('designer') as Designer; @@ -23,5 +30,21 @@ export default function getDesignerCabin(editor: Editor) { DragObjectType, isDragNodeDataObject, isNode, + [designerCabinSymbol]: { + isDragNodeObject, + isDragAnyObject, + isShaken, + contains, + LocationDetailType, + isLocationChildrenDetail, + ScrollTarget, + isSettingField, + TransformStage, + SettingField, + LiveEditing, + DragObjectType, + isDragNodeDataObject, + isNode, + }, }; } \ No newline at end of file diff --git a/packages/engine/src/modules/symbols.ts b/packages/engine/src/modules/symbols.ts index f40e81654..a022b848a 100644 --- a/packages/engine/src/modules/symbols.ts +++ b/packages/engine/src/modules/symbols.ts @@ -8,6 +8,7 @@ import { editorSymbol, settingPropEntrySymbol, settingTopEntrySymbol, + designerCabinSymbol, } from '@alilc/lowcode-shell'; export default { @@ -20,4 +21,5 @@ export default { designerSymbol, settingPropEntrySymbol, settingTopEntrySymbol, + designerCabinSymbol, }; diff --git a/packages/engine/src/modules/utils.ts b/packages/engine/src/modules/utils.ts index 6fa569c75..7e7cf6206 100644 --- a/packages/engine/src/modules/utils.ts +++ b/packages/engine/src/modules/utils.ts @@ -1,6 +1,6 @@ import { isFormEvent, compatibleLegaoSchema, getNodeSchemaById } from '@alilc/lowcode-utils'; import { isNodeSchema } from '@alilc/lowcode-types'; -import { getConvertedExtraKey, getOriginalExtraKey } from '@alilc/lowcode-designer'; +import { getConvertedExtraKey, getOriginalExtraKey, isNode, isSettingField } from '@alilc/lowcode-designer'; const utils = { isNodeSchema, diff --git a/packages/plugin-outline-pane/src/views/tree.tsx b/packages/plugin-outline-pane/src/views/tree.tsx index db99987d4..98cdd4233 100644 --- a/packages/plugin-outline-pane/src/views/tree.tsx +++ b/packages/plugin-outline-pane/src/views/tree.tsx @@ -1,6 +1,6 @@ import { Component, MouseEvent as ReactMouseEvent } from 'react'; import { observer, Editor, globalContext } from '@alilc/lowcode-editor-core'; -import { isRootNode, Node, DragObjectType, isShaken } from '@alilc/lowcode-designer'; +import { Node, DragObjectType, isShaken } from '@alilc/lowcode-designer'; import { isFormEvent, canClickNode } from '@alilc/lowcode-utils'; import { Tree } from '../tree'; import RootTreeNodeView from './root-tree-node'; diff --git a/packages/shell/src/detecting.ts b/packages/shell/src/detecting.ts index 998636542..d8e6c7fbb 100644 --- a/packages/shell/src/detecting.ts +++ b/packages/shell/src/detecting.ts @@ -1,3 +1,4 @@ +import Node from './node'; import { Detecting as InnerDetecting, DocumentModel as InnerDocumentModel, @@ -13,6 +14,13 @@ export default class Detecting { this[detectingSymbol] = document.designer.detecting; } + /** + * 当前 hover 的节点 + */ + get current() { + return Node.create(this[detectingSymbol].current); + } + /** * hover 指定节点 * @param id 节点 id diff --git a/packages/shell/src/document-model.ts b/packages/shell/src/document-model.ts index e4e79ddae..3f4fc4398 100644 --- a/packages/shell/src/document-model.ts +++ b/packages/shell/src/document-model.ts @@ -2,15 +2,15 @@ import { Editor } from '@alilc/lowcode-editor-core'; import { DocumentModel as InnerDocumentModel, Node as InnerNode, - ParentalNode, IOnChangeOptions as InnerIOnChangeOptions, - PropChangeOptions as InnerPropChangeOptions, + DragObject as InnerDragObject, + DragNodeObject, + DragNodeDataObject, + isDragNodeObject, } from '@alilc/lowcode-designer'; import { TransformStage, RootSchema, - NodeSchema, - NodeData, GlobalEvent, } from '@alilc/lowcode-types'; import Node from './node'; @@ -40,6 +40,8 @@ const Events = { IMPORT_SCHEMA: 'shell.document.importSchema', }; +const shellDocSymbol = Symbol('shellDocSymbol'); + export default class DocumentModel { private readonly [documentSymbol]: InnerDocumentModel; private readonly [editorSymbol]: Editor; @@ -61,8 +63,13 @@ export default class DocumentModel { } static create(document: InnerDocumentModel | undefined | null) { - if (document == undefined) return null; - return new DocumentModel(document); + if (!document) return null; + // @ts-ignore 直接返回已挂载的 shell doc 实例 + if (document[shellDocSymbol]) return document[shellDocSymbol]; + const shellDoc = new DocumentModel(document); + // @ts-ignore 直接返回已挂载的 shell doc 实例 + document[shellDocSymbol] = shellDoc; + return shellDoc; } /** @@ -200,6 +207,23 @@ export default class DocumentModel { return this[documentSymbol].getComponentsMap(extraComps); } + /** + * 检查拖拽放置的目标节点是否可以放置该拖拽对象 + * @param dropTarget 拖拽放置的目标节点 + * @param dragObject 拖拽的对象 + * @returns boolean 是否可以放置 + */ + checkNesting(dropTarget: Node, dragObject: DragNodeObject | DragNodeDataObject): boolean { + let innerDragObject: InnerDragObject = dragObject; + if (isDragNodeObject(dragObject)) { + innerDragObject.nodes = innerDragObject.nodes.map((node: Node) => (node[nodeSymbol] || node)); + } + return this[documentSymbol].checkNesting( + (dropTarget[nodeSymbol] || dropTarget) as any, + innerDragObject as any, + ); + } + /** * 当前 document 新增节点事件 */ diff --git a/packages/shell/src/node.ts b/packages/shell/src/node.ts index ca061dcb5..417640a1b 100644 --- a/packages/shell/src/node.ts +++ b/packages/shell/src/node.ts @@ -128,6 +128,13 @@ export default class Node { return true; } + /** + * 获取当前节点的锁定状态 + */ + get isLocked() { + return this[nodeSymbol].isLocked; + } + /** * 下标 */ @@ -314,6 +321,14 @@ export default class Node { return this[nodeSymbol].isConditionalVisible(); } + /** + * 设置节点锁定状态 + * @param flag + */ + lock(flag?: boolean) { + this[nodeSymbol].lock(flag); + } + /** * @deprecated use .props instead */ @@ -347,10 +362,11 @@ export default class Node { * 获取指定 path 的属性模型实例, * 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级 * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @param createIfNone 当没有属性的时候,是否创建一个属性 * @returns */ - getExtraProp(path: string): Prop | null { - return Prop.create(this[nodeSymbol].getProp(getConvertedExtraKey(path))); + getExtraProp(path: string, createIfNone?: boolean): Prop | null { + return Prop.create(this[nodeSymbol].getExtraProp(path, createIfNone)); } /** @@ -460,4 +476,8 @@ export default class Node { remove() { this[nodeSymbol].remove(); } + + internalToShellNode() { + return this; + } } diff --git a/packages/shell/src/project.ts b/packages/shell/src/project.ts index c6a29c4eb..ce1667bde 100644 --- a/packages/shell/src/project.ts +++ b/packages/shell/src/project.ts @@ -4,18 +4,20 @@ import { PropsReducer as PropsTransducer, TransformStage, } from '@alilc/lowcode-designer'; -import { RootSchema, ProjectSchema } from '@alilc/lowcode-types'; +import { RootSchema, ProjectSchema, IEditor } from '@alilc/lowcode-types'; import DocumentModel from './document-model'; import SimulatorHost from './simulator-host'; -import { projectSymbol, simulatorHostSymbol, simulatorRendererSymbol, documentSymbol } from './symbols'; +import { editorSymbol, projectSymbol, simulatorHostSymbol, simulatorRendererSymbol, documentSymbol } from './symbols'; export default class Project { private readonly [projectSymbol]: InnerProject; + private readonly [editorSymbol]: IEditor; private [simulatorHostSymbol]: BuiltinSimulatorHost; private [simulatorRendererSymbol]: any; constructor(project: InnerProject) { this[projectSymbol] = project; + this[editorSymbol] = project?.designer.editor; } static create(project: InnerProject) { @@ -132,6 +134,15 @@ export default class Project { this[projectSymbol].designer.addPropsReducer(transducer, stage); } + /** + * 绑定删除文档事件 + * @param fn + * @returns + */ + onRemoveDocument(fn: (data: { id: string}) => void) { + return this[editorSymbol].on('designer.document.remove', (data: { id: string }) => fn(data)); + } + /** * 当前 project 内的 document 变更事件 */ diff --git a/packages/shell/src/prop.ts b/packages/shell/src/prop.ts index aba59ca73..b386d0593 100644 --- a/packages/shell/src/prop.ts +++ b/packages/shell/src/prop.ts @@ -71,6 +71,13 @@ export default class Prop { return this[propSymbol].getValue(); } + /** + * 移除值 + */ + remove() { + this[propSymbol].remove(); + } + /** * 导出值 * @param stage diff --git a/packages/shell/src/selection.ts b/packages/shell/src/selection.ts index 8e29384d0..b5b9e7a16 100644 --- a/packages/shell/src/selection.ts +++ b/packages/shell/src/selection.ts @@ -84,4 +84,15 @@ export default class Selection { getNodes(): Node[] { return this[selectionSymbol].getNodes().map((node: InnerNode) => Node.create(node)); } + + /** + * 获取选区的顶层节点 + * for example: + * getNodes() returns [A, subA, B], then + * getTopNodes() will return [A, B], subA will be removed + * @returns + */ + getTopNodes(): Node[] { + return this[selectionSymbol].getTopNodes().map((node: InnerNode) => Node.create(node)); + } } diff --git a/packages/shell/src/symbols.ts b/packages/shell/src/symbols.ts index baeb4452a..04ba9d17e 100644 --- a/packages/shell/src/symbols.ts +++ b/packages/shell/src/symbols.ts @@ -23,4 +23,5 @@ export const dropLocationSymbol = Symbol('dropLocation'); export const simulatorHostSymbol = Symbol('simulatorHost'); export const simulatorRendererSymbol = Symbol('simulatorRenderer'); export const dragObjectSymbol = Symbol('dragObject'); -export const locateEventSymbol = Symbol('locateEvent'); \ No newline at end of file +export const locateEventSymbol = Symbol('locateEvent'); +export const designerCabinSymbol = Symbol('designerCabin'); \ No newline at end of file diff --git a/packages/types/src/editor.ts b/packages/types/src/editor.ts index 7db0a5990..a11c7eaf7 100644 --- a/packages/types/src/editor.ts +++ b/packages/types/src/editor.ts @@ -156,7 +156,7 @@ export interface Utils { } export interface PluginProps { - editor: IEditor; + editor?: IEditor; config: PluginConfig; [key: string]: any; }