diff --git a/packages/designer/src/builtins/drag-ghost/ghost.tsx b/packages/designer/src/builtins/drag-ghost/ghost.tsx
deleted file mode 100644
index 972516abe..000000000
--- a/packages/designer/src/builtins/drag-ghost/ghost.tsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import { Component } from 'react';
-import { observer, obx } from '@ali/recore';
-import { dragon } from '../../globals/dragon';
-
-import './ghost.less';
-import { OutlineBoardID } from '../builtin-panes/outline-pane/outline-board';
-// import { INode } from '../../document/node';
-
-type offBinding = () => any;
-
-@observer
-export default class Ghost extends Component {
- private dispose: offBinding[] = [];
- @obx.ref private dragment: any = null;
- @obx.ref private x = 0;
- @obx.ref private y = 0;
-
- componentWillMount() {
- this.dispose = [
- dragon.onDragstart(e => {
- this.dragment = e.dragTarget;
- this.x = e.clientX;
- this.y = e.clientY;
- }),
- dragon.onDrag(e => {
- this.x = e.clientX;
- this.y = e.clientY;
- }),
- dragon.onDragend(() => {
- this.dragment = null;
- this.x = 0;
- this.y = 0;
- }),
- ];
- }
-
- shouldComponentUpdate() {
- return false;
- }
-
- componentWillUnmount() {
- if (this.dispose) {
- this.dispose.forEach(off => off());
- }
- }
-
- renderGhostGroup() {
- const dragment = this.dragment;
- if (Array.isArray(dragment)) {
- return dragment.map((node: any, index: number) => {
- const ghost = (
-
- );
- return ghost;
- });
- } else {
- return (
-
- );
- }
- }
-
- render() {
- if (!this.dragment) {
- return null;
- }
-
- // let x = this.x;
- // let y = this.y;
-
- // todo: 考虑多个图标、title、不同 sensor 区域的形态
- if (dragon.activeSensor && dragon.activeSensor.id === OutlineBoardID) {
- // const nodeId = (this.dragment as INode).id;
- // const elt = document.querySelector(`[data-id="${nodeId}"`) as HTMLDivElement;
- //
- // if (elt) {
- // // do something
- // // const target = elt.cloneNode(true) as HTMLDivElement;
- // console.log('>>> target', elt);
- // elt.classList.remove('hidden');
- // elt.classList.add('dragging');
- // elt.style.transform = `translate(${this.x}px, ${this.y}px)`;
- // }
- //
- // return null;
- // x -= 30;
- // y += 30;
- }
-
- return (
-
- {this.renderGhostGroup()}
-
- );
- }
-}
diff --git a/packages/designer/src/designer/canvas.less b/packages/designer/src/designer/canvas.less
deleted file mode 100644
index cfc57d730..000000000
--- a/packages/designer/src/designer/canvas.less
+++ /dev/null
@@ -1,47 +0,0 @@
-.my-canvas {
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- margin: 10px;
- box-shadow: 0 2px 10px 0 rgba(31,56,88,.15);
-}
-
-html.my-show-topbar .my-canvas {
- top: var(--topbar-height);
-}
-html.my-show-toolbar .my-canvas {
- top: var(--toolbar-height);
-}
-html.my-show-topbar.my-show-toolbar .my-canvas {
- top: calc(var(--topbar-height) + var(--topbar-height));
-}
-
-.my-screen {
- top: 0;
- bottom: 0;
- width: 100%;
- left: 0;
- position: absolute;
- overflow: hidden;
-}
-
-.my-doc-shell {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- width: 100%;
- overflow: hidden;
- .my-doc-frame {
- border: none;
- transform-origin: 0 0;
- height: 100%;
- width: 100%;
- }
-}
-
-.my-drag-pane-mode .my-doc-shell {
- pointer-events: none;
-}
diff --git a/packages/designer/src/designer/canvas.tsx b/packages/designer/src/designer/canvas.tsx
deleted file mode 100644
index 3a6daadf3..000000000
--- a/packages/designer/src/designer/canvas.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import { Component } from 'react';
-import { observer } from '@ali/recore';
-import { getCurrentDocument, screen, progressing } from '../../globals';
-import { AutoFit } from '../../document/viewport';
-import { AuxiliaryView } from '../auxiliary';
-import { PreLoaderView } from '../widgets/pre-loader';
-import DocumentContext from '../../document/document-context';
-import FocusingArea from '../widgets/focusing-area';
-import './canvas.less';
-
-const Canvas = () => (
- {
- const doc = getCurrentDocument();
- if (doc) {
- doc.selection.clear();
- }
- return false;
- }}
- >
-
-
-);
-
-export default Canvas;
-
-@observer
-class Screen extends Component {
- render() {
- const doc = getCurrentDocument();
- // TODO: thinkof multi documents
- return (
- screen.mount(elmt)} className="my-screen">
- {progressing.visible ?
: null}
-
- {doc ?
: null}
-
- );
- }
-}
-
-@observer
-class DocumentView extends Component<{ doc: DocumentContext }> {
- componentWillUnmount() {
- this.props.doc.sleep();
- }
-
- render() {
- const { doc } = this.props;
- const viewport = doc.viewport;
- let shellStyle = {};
- let frameStyle = {};
- if (viewport.width !== AutoFit && viewport.height !== AutoFit) {
- const shellWidth = viewport.width * viewport.scale;
- const screenWidth = screen.width;
- const shellLeft = shellWidth < screenWidth ? `calc((100% - ${shellWidth}px) / 2)` : 0;
- shellStyle = {
- width: shellWidth,
- left: shellLeft,
- };
- frameStyle = {
- transform: `scale(${viewport.scale})`,
- height: viewport.height,
- width: viewport.width,
- };
- }
-
- return (
-
-
- );
- }
-}
diff --git a/packages/designer/src/designer/designer.ts b/packages/designer/src/designer/designer.ts
index 56d027064..7993b2eba 100644
--- a/packages/designer/src/designer/designer.ts
+++ b/packages/designer/src/designer/designer.ts
@@ -1,17 +1,149 @@
-class Designer {
- id: string = guid();
- hotkey: Hotkey;
+import Dragon, { isDragNodeObject, isDragNodeDataObject } from "./dragon";
+import Project from './project';
+import { ProjectSchema } from './schema';
+import DocumentModel from './document/document-model';
+import BuiltinSimulatorView from '../builtins/simulator/master';
+import { Component } from 'react';
+import { obx, computed } from '@recore/obx';
+import ActiveTracker from './active-tracker';
+import Location, { LocationData, isLocationChildrenDetail } from './location';
+import Node, { insertChildren } from './document/node/node';
- constructor(options: BuilderOptions): Builder;
+export interface DesignerProps {
+ className?: string;
+ style?: object;
+ defaultSchema?: ProjectSchema;
+ hotkeys?: object;
+ simulatorProps?: object | ((document: DocumentModel) => object);
+ simulatorComponent?: Component;
+ dragGhostComponent?: Component;
+ suspensed?: boolean;
+ onMount?: (designer: Designer) => void;
+ onDragstart?: (designer: Designer) => void;
+ onDrag?: (designer: Designer) => void;
+ onDragend?: (designer: Designer) => void;
+ // TODO: ...add other events support
+ [key: string]: any;
+}
- getValue(): ProjectSchema;
- setValue(schema: ProjectSchema): void;
- project: Project;
- dragboost(locateEvent: LocateEvent): void;
- addDropSensor(dropSensor: DropSensor): void;
+export default class Designer {
+ // readonly hotkey: Hotkey;
+ readonly dragon = new Dragon(this);
+ readonly activeTracker = new ActiveTracker();
+ readonly project: Project;
+ constructor(props: DesignerProps) {
+ this.project = new Project(this, props.defaultSchema);
- private _suspensed: boolean = false;
+ this.dragon.onDragstart(({ dragObject }) => {
+ if (isDragNodeObject(dragObject) && dragObject.nodes.length === 1) {
+ // ensure current selecting
+ dragObject.nodes[0].select();
+ }
+ });
+
+ this.dragon.onDragend(({ dragObject, copy }) => {
+ const loc = this._dropLocation;
+ if (loc) {
+ if (isLocationChildrenDetail(loc.detail)) {
+ let nodes: Node[] | undefined;
+ if (isDragNodeObject(dragObject)) {
+ nodes = insertChildren(loc.target, dragObject.nodes, loc.detail.index, copy);
+ } else if (isDragNodeDataObject(dragObject)) {
+ // process nodeData
+ const nodeData = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data];
+ nodes = insertChildren(loc.target, nodeData, loc.detail.index);
+ }
+ if (nodes) {
+ loc.document.selection.selectAll(nodes.map(o => o.id));
+ setTimeout(() => this.activeTracker.track(nodes![0]), 10);
+ }
+ }
+ }
+ this.clearLocation();
+ // this.enableEdging();
+ });
+
+ this.activeTracker.onChange(({ node, detail }) => {
+ node.document.simulator?.scrollToNode(node, detail);
+ });
+
+ this.setProps(props);
+ }
+
+ private _dropLocation?: Location;
+ /**
+ * 创建插入位置
+ */
+ createLocation(locationData: LocationData): Location {
+ const loc = new Location(locationData);
+ this._dropLocation = loc;
+ loc.document.internalSetDropLocation(loc);
+ this.activeTracker.track({ node: loc.target, detail: loc.detail });
+ return loc;
+ }
+
+ /**
+ * 清除插入位置
+ */
+ private clearLocation() {
+ if (this._dropLocation) {
+ this._dropLocation.document.internalSetDropLocation(null);
+ }
+ this._dropLocation = undefined;
+ }
+
+ private props?: DesignerProps;
+ setProps(props: DesignerProps) {
+ if (this.props) {
+ // check hotkeys
+ // TODO:
+ // check simulatorConfig
+ if (props.simulatorComponent !== this.props.simulatorComponent) {
+ this._simulatorComponent = props.simulatorComponent;
+ }
+ if (props.simulatorProps !== this.props.simulatorProps) {
+ this._simulatorProps = props.simulatorProps;
+ }
+ if (props.suspensed !== this.props.suspensed && props.suspensed != null) {
+ this.suspensed = props.suspensed;
+ }
+ } else {
+ // init hotkeys
+ // todo:
+ // init simulatorConfig
+ if (props.simulatorComponent) {
+ this._simulatorComponent = props.simulatorComponent;
+ }
+ if (props.simulatorProps) {
+ this._simulatorProps = props.simulatorProps;
+ }
+ // init suspensed
+ if (props.suspensed != null) {
+ this.suspensed = props.suspensed;
+ }
+ }
+ this.props = props;
+ }
+
+ get(key: string): any {
+ return this.props ? this.props[key] : null;
+ }
+
+ @obx.ref private _simulatorComponent?: Component;
+ @obx.ref private _simulatorProps?: object;
+ @computed get simulatorConfig(): {
+ Component: Component;
+ props: object;
+ } {
+ const config: any = {
+ Component: this._simulatorComponent || BuiltinSimulatorView,
+ props: this._simulatorProps || {},
+ };
+ return config;
+ }
+
+ @obx.ref private _suspensed: boolean = false;
get suspensed(): boolean {
return this._suspensed;
@@ -25,9 +157,15 @@ class Designer {
}
}
- // 事件 & 消息
- onActiveChange(): () => void;
- onDragstart(): void;
- onDragend(): void;
- //....
+ get schema(): ProjectSchema {
+ return this.project.schema;
+ }
+
+ set schema(schema: ProjectSchema) {
+ // todo:
+ }
+
+ purge() {
+
+ }
}
diff --git a/packages/designer/src/designer/document/document-context.ts b/packages/designer/src/designer/document/document-context.ts
deleted file mode 100644
index 2aff7f7f9..000000000
--- a/packages/designer/src/designer/document/document-context.ts
+++ /dev/null
@@ -1,300 +0,0 @@
-import Project from '../project';
-import { RootSchema, NodeData, isDOMText, isJSExpression, NodeSchema } from '../schema';
-import Node, { isNodeParent, insertChildren, insertChild, NodeParent } from './node/node';
-import { Selection } from './selection';
-import RootNode from './node/root-node';
-import { SimulatorInterface } from '../simulator-interface';
-import { computed } from '@recore/obx';
-
-export default class DocumentContext {
- /**
- * 根节点 类型有:Page/Component/Block
- */
- readonly rootNode: RootNode;
- /**
- * 文档编号
- */
- readonly id: string;
- /**
- * 选区控制
- */
- readonly selection: Selection = new Selection(this);
- /**
- * 操作记录控制
- */
- // TODO
- // readonly history: History = new History(this);
-
- private nodesMap = new Map();
- private nodes = new Set();
- private seqId = 0;
- private _simulator?: SimulatorInterface;
-
- /**
- * 模拟器
- */
- get simulator(): SimulatorInterface | null {
- return this._simulator || null;
- }
-
- get fileName() {
- return this.rootNode.extras.get('fileName')?.value as string;
- }
-
- set fileName(fileName: string) {
- this.rootNode.extras.get('fileName', true).value = fileName;
- }
-
- constructor(readonly project: Project, schema: RootSchema) {
- this.rootNode = new RootNode(this, schema);
- this.id = this.rootNode.id;
- }
-
- /**
- * 生成唯一id
- */
- nextId() {
- return (++this.seqId).toString(36).toLocaleLowerCase();
- }
-
- /**
- * 根据 id 获取节点
- */
- getNode(id: string): Node | null {
- return this.nodesMap.get(id) || null;
- }
-
- /**
- * 是否存在节点
- */
- hasNode(id: string): boolean {
- const node = this.getNode(id);
- return node ? !node.isPurged : false;
- }
-
- /**
- * 根据 schema 创建一个节点
- */
- createNode(data: NodeData): Node {
- let schema: any;
- if (isDOMText(data) || isJSExpression(data)) {
- schema = {
- componentName: '#frag',
- children: data,
- };
- } else {
- schema = data;
- }
- const node = new Node(this, schema);
- this.nodesMap.set(node.id, node);
- this.nodes.add(node);
- return node;
- }
-
- /**
- * 插入一个节点
- */
- insertNode(parent: NodeParent, thing: Node | NodeData, at?: number | null, copy?: boolean): Node {
- return insertChild(parent, thing, at, copy);
- }
-
- /**
- * 插入多个节点
- */
- insertNodes(parent: NodeParent, thing: Node[] | NodeData[], at?: number | null, copy?: boolean) {
- return insertChildren(parent, thing, at, copy);
- }
-
- /**
- * 移除一个节点
- */
- removeNode(idOrNode: string | Node) {
- let id: string;
- let node: Node | null;
- if (typeof idOrNode === 'string') {
- id = idOrNode;
- node = this.getNode(id);
- } else {
- node = idOrNode;
- id = node.id;
- }
- if (!node) {
- return;
- }
- this.internalRemoveAndPurgeNode(node);
- }
-
- /**
- * 内部方法,请勿调用
- */
- internalRemoveAndPurgeNode(node: Node) {
- if (!this.nodes.has(node)) {
- return;
- }
- this.nodesMap.delete(node.id);
- this.nodes.delete(node);
- node.remove();
- }
-
- /**
- * 包裹当前选区中的节点
- */
- wrapWith(schema: NodeSchema): Node | null {
- const nodes = this.selection.getTopNodes();
- if (nodes.length < 1) {
- return null;
- }
- const wrapper = this.createNode(schema);
- if (isNodeParent(wrapper)) {
- const first = nodes[0];
- // TODO: check nesting rules x 2
- insertChild(first.parent!, wrapper, first.index);
- insertChildren(wrapper, nodes);
- this.selection.select(wrapper.id);
- return wrapper;
- }
-
- this.removeNode(wrapper);
- return null;
- }
-
- /**
- * 导出 schema 数据
- */
- get schema(): NodeSchema {
- return this.rootNode.schema;
- }
-
- /**
- * 导出节点数据
- */
- getNodeSchema(id: string): NodeData | null {
- const node = this.getNode(id);
- if (node) {
- return node.schema;
- }
- return null;
- }
-
- /**
- * 是否已修改
- */
- isModified() {
- // return !this.history.isSavePoint();
- }
-
- /**
- * 提供给模拟器的参数
- */
- @computed get simulatorProps(): object {
- let simulatorProps = this.project.simulatorProps;
- if (typeof simulatorProps === 'function') {
- simulatorProps = simulatorProps(this);
- }
- return {
- ...simulatorProps,
- documentContext: this,
- onMount: this.mountSimulator.bind(this),
- };
- }
-
- private mountSimulator(simulator: SimulatorInterface) {
- this._simulator = simulator;
- // TODO: emit simulator mounted
- }
-
- /**
- * 根据节点取得视图实例,在循环等场景会有多个,依赖 simulator 的接口
- */
- getViewInstance(node: Node): ViewInstance[] | null {
- if (this.simulator) {
- this.simulator.getViewInstance(node.id);
- }
- return null;
- }
-
- /**
- * 通过 DOM 节点获取节点,依赖 simulator 的接口
- */
- getNodeFromElement(target: Element | null): Node | null {
- if (!this.simulator || !target) {
- return null;
- }
-
- const id = this.simulator.getClosestNodeId(target);
- if (!id) {
- return null;
- }
- return this.getNode(id) as Node;
- }
-
- /**
- * 获得到的结果是一个数组
- * 表示一个实例对应多个外层 DOM 节点,依赖 simulator 的接口
- */
- getDOMNodes(viewInstance: ViewInstance): Array | null {
- if (!this.simulator) {
- return null;
- }
-
- if (isElement(viewInstance)) {
- return [viewInstance];
- }
-
- return this.simulator.findDOMNodes(viewInstance);
- }
-
- getComponent(componentName: string): any {
- return this.simulator!.getCurrentComponent(componentName);
- }
-
- private _opened: boolean = true;
- private _suspensed: boolean = false;
-
- /**
- * 是否不是激活的
- */
- get suspensed(): boolean {
- return this._suspensed;
- }
-
- /**
- * 与 suspensed 相反,是否是激活的,这个函数可能用的更多一点
- */
- get actived(): boolean {
- return !this._suspensed;
- }
-
- /**
- * 切换激活,只有打开的才能激活
- * 不激活,打开之后切换到另外一个时发生,比如 tab 视图,切换到另外一个标签页
- */
- set suspensed(flag: boolean) {
- if (!this._opened && !flag) {
- return;
- }
- this._suspensed = flag;
- }
-
- /**
- * 打开,已载入,默认建立时就打开状态,除非手动关闭
- */
- open(): void {
- this._opened = true;
- }
-
- /**
- * 关闭,相当于 sleep,仍然缓存,停止一切响应,如果有发生的变更没被保存,仍然需要去取数据保存
- */
- close(): void {
- this.suspensed = true;
- this._opened = false;
- }
-
- /**
- * 从项目中移除
- */
- remove() {
-
- }
-}
diff --git a/packages/designer/src/designer/document/document.tsx b/packages/designer/src/designer/document/document.tsx
index e69de29bb..6ed62dd47 100644
--- a/packages/designer/src/designer/document/document.tsx
+++ b/packages/designer/src/designer/document/document.tsx
@@ -0,0 +1,27 @@
+import { Component, createContext } from 'react';
+import DocumentModel from './document-model';
+
+export const DocumentContext = createContext(null as any);
+
+export default class DocumentView extends Component<{ documentModel: DocumentModel }> {
+ render() {
+ const { documentModel } = this.props;
+ return (
+
+
+ {/* 这一层将来做缩放用途 */}
+
+
+
+
+
+
+ )
+ }
+}
+
+class DocumentInfoView extends Component {
+ render() {
+ return null;
+ }
+}
diff --git a/packages/designer/src/designer/document/location.ts b/packages/designer/src/designer/document/location.ts
deleted file mode 100644
index 1b26523a9..000000000
--- a/packages/designer/src/designer/document/location.ts
+++ /dev/null
@@ -1,123 +0,0 @@
-import ComponentNode, { NodeParent } from './node/node';
-import DocumentContext from './document-context';
-
-export interface LocationData {
- target: NodeParent; // shadowNode | ConditionFlow | ElementNode | RootNode
- detail: LocationDetail;
-}
-
-export enum LocationDetailType {
- Children = 'Children',
- Prop = 'Prop',
-}
-
-export interface LocationChildrenDetail {
- type: LocationDetailType.Children;
- index: number;
- near?: {
- node: ComponentNode;
- pos: 'before' | 'after';
- rect?: Rect;
- align?: 'V' | 'H';
- };
-}
-
-export interface LocationPropDetail {
- // cover 形态,高亮 domNode,如果 domNode 为空,取 container 的值
- type: LocationDetailType.Prop;
- name: string;
- domNode?: HTMLElement;
-}
-
-export type LocationDetail = LocationChildrenDetail | LocationPropDetail | { type: string; [key: string]: any };
-
-export interface Point {
- clientX: number;
- clientY: number;
-}
-
-export type Rects = Array & {
- elements: Array;
-};
-
-export type Rect = (ClientRect | DOMRect) & {
- elements: Array;
- computed?: boolean;
-};
-
-export function isLocationData(obj: any): obj is LocationData {
- return obj && obj.target && obj.detail;
-}
-
-export function isLocationChildrenDetail(obj: any): obj is LocationChildrenDetail {
- return obj && obj.type === LocationDetailType.Children;
-}
-
-export function isRowContainer(container: Element | Text, win?: Window) {
- if (isText(container)) {
- return true;
- }
- const style = (win || getWindow(container)).getComputedStyle(container);
- const display = style.getPropertyValue('display');
- if (/flex$/.test(display)) {
- const direction = style.getPropertyValue('flex-direction') || 'row';
- if (direction === 'row' || direction === 'row-reverse') {
- return true;
- }
- }
- return false;
-}
-
-export function isChildInline(child: Element | Text, win?: Window) {
- if (isText(child)) {
- return true;
- }
- const style = (win || getWindow(child)).getComputedStyle(child);
- return /^inline/.test(style.getPropertyValue('display'));
-}
-
-export function getRectTarget(rect: Rect | null) {
- if (!rect || rect.computed) {
- return null;
- }
- const els = rect.elements;
- return els && els.length > 0 ? els[0]! : null;
-}
-
-export function isVerticalContainer(rect: Rect | null) {
- const el = getRectTarget(rect);
- if (!el) {
- return false;
- }
- return isRowContainer(el);
-}
-
-export function isVertical(rect: Rect | null) {
- const el = getRectTarget(rect);
- if (!el) {
- return false;
- }
- return isChildInline(el) || (el.parentElement ? isRowContainer(el.parentElement) : false);
-}
-
-function isText(elem: any): elem is Text {
- return elem.nodeType === Node.TEXT_NODE;
-}
-
-function isDocument(elem: any): elem is Document {
- return elem.nodeType === Node.DOCUMENT_NODE;
-}
-
-export function getWindow(elem: Element | Document): Window {
- return (isDocument(elem) ? elem : elem.ownerDocument!).defaultView!;
-}
-
-export default class Location {
- readonly target: NodeParent;
- readonly detail: LocationDetail;
-
- constructor(readonly document: DocumentContext, { target, detail }: LocationData) {
- this.target = target;
- this.detail = detail;
- }
-}
diff --git a/packages/designer/src/designer/document/selection.ts b/packages/designer/src/designer/document/selection.ts
index fba7959ed..62e16bd01 100644
--- a/packages/designer/src/designer/document/selection.ts
+++ b/packages/designer/src/designer/document/selection.ts
@@ -1,11 +1,11 @@
import Node, { comparePosition } from './node/node';
import { obx } from '@recore/obx';
-import DocumentContext from './document-context';
+import DocumentModel from './document-model';
export class Selection {
@obx.val private selected: string[] = [];
- constructor(private doc: DocumentContext) {}
+ constructor(private doc: DocumentModel) {}
/**
* 选中
diff --git a/packages/designer/src/designer/dragon.ts b/packages/designer/src/designer/dragon.ts
index fc670095d..ec611e91a 100644
--- a/packages/designer/src/designer/dragon.ts
+++ b/packages/designer/src/designer/dragon.ts
@@ -1,11 +1,11 @@
import { EventEmitter } from 'events';
import { obx } from '@recore/obx';
-import Location from './document/location';
-import Project from './project';
-import DocumentContext from './document/document-context';
+import Location from './location';
+import DocumentModel from './document/document-model';
import { NodeData } from './schema';
import { SimulatorInterface } from './simulator-interface';
import Node from './document/node/node';
+import Designer from './designer';
export interface LocateEvent {
readonly type: 'LocateEvent';
@@ -34,7 +34,7 @@ export interface LocateEvent {
/**
* 激活或目标文档
*/
- document?: DocumentContext;
+ document?: DocumentModel;
/**
* 事件订正标识,初始构造时,从发起端构造,缺少 canvasX,canvasY, 需要经过订正才有
*/
@@ -44,7 +44,7 @@ export interface LocateEvent {
/**
* 拖拽敏感板
*/
-export interface SensorInterface {
+export interface ISensor {
/**
* 是否可响应,比如面板被隐藏,可设置该值 false
*/
@@ -76,7 +76,7 @@ export enum DragObjectType {
export interface DragNodeObject {
type: DragObjectType.Node;
- node: Node | Node[];
+ nodes: Node[];
}
export interface DragNodeDataObject {
type: DragObjectType.NodeData;
@@ -126,32 +126,25 @@ export function setShaken(e: any) {
e.shaken = true;
}
-function getTopDocument(e: MouseEvent, local: Document) {
- return e.view!.document === local ? null : document;
+function isFromTopDocument(e: MouseEvent) {
+ return e.view!.document === document;
}
export default class Dragon {
- private sensors: ISenseAble[] = [];
+ private sensors: ISensor[] = [];
/**
* current actived sensor
*/
- private _activeSensor: ISenseAble | undefined;
- get activeSensor(): ISenseAble | undefined {
+ private _activeSensor: ISensor | undefined;
+ get activeSensor(): ISensor | undefined {
return this._activeSensor;
}
@obx.ref dragging = false;
private emitter = new EventEmitter();
- private get master(): MasterBoard | undefined {
- const doc = getCurrentDocument();
- if (!doc) {
- return undefined;
- }
- return doc.masterBoard;
- }
- constructor(readonly project: Project) {}
+ constructor(readonly designer: Designer) {}
from(shell: Element, boost: (e: MouseEvent) => DragObject | null) {
const mousedown = (e: MouseEvent) => {
@@ -174,22 +167,28 @@ export default class Dragon {
};
}
+ getMasterSensors(): SimulatorInterface[] {
+ return this.designer.project.documents.map(doc => (doc.actived && doc.simulator) || null).filter(Boolean);
+ }
+
+ get master(): DocumentModel {
+
+ }
+
/**
* dragTarget should be a INode | INode[] | NodeData | NodeData[]
*/
boost(dragObject: DragObject, boostEvent: MouseEvent) {
- if (!this.master) {
- return;
- }
- const master = this.master;
- const doc = master.contentDocument;
- const viewport = master.document.viewport;
- const topDoc = getTopDocument(boostEvent, doc);
- const newBie = dragObject.type !== DragTargetType.Nodes;
+ const doc = document;
+ const fromTop = isFromTopDocument(boostEvent);
let lastLocation: any = null;
- let lastSensor: ISenseAble | undefined;
+ let lastSensor: ISensor | undefined;
this.dragging = false;
- master.setNativeSelection(false);
+ const masterSensors = this.getMasterSensors();
+ masterSensors.forEach((sensor) => {
+ sensor.setNativeSelection(false);
+ });
+ //
const checkesc = (e: KeyboardEvent) => {
if (e.keyCode === 27) {
@@ -269,19 +268,25 @@ export default class Dragon {
master.releaseCursor();
- doc.removeEventListener('mousemove', move, true);
- doc.removeEventListener('mouseup', over, true);
- doc.removeEventListener('mousedown', over, true);
- doc.removeEventListener('keydown', checkesc, false);
- doc.removeEventListener('keydown', checkcopy as any, false);
- doc.removeEventListener('keyup', checkcopy as any, false);
- if (topDoc) {
- topDoc.removeEventListener('mousemove', move, true);
- topDoc.removeEventListener('mouseup', over, true);
- topDoc.removeEventListener('mousedown', over, true);
- topDoc.removeEventListener('keydown', checkesc, false);
- topDoc.removeEventListener('keydown', checkcopy as any, false);
- topDoc.removeEventListener('keyup', checkcopy as any, false);
+ if (fromTop) {
+ doc.removeEventListener('mousemove', move, true);
+ doc.removeEventListener('mouseup', over, true);
+ doc.removeEventListener('mousedown', over, true);
+ doc.removeEventListener('keydown', checkesc, false);
+ doc.removeEventListener('keydown', checkcopy as any, false);
+ doc.removeEventListener('keyup', checkcopy as any, false);
+ } else {
+ masterSensors.forEach(item => {
+ const odoc = item.ownerDocument;
+ if (odoc && odoc !== doc) {
+ odoc.removeEventListener('mousemove', move, true);
+ odoc.removeEventListener('mouseup', over, true);
+ odoc.removeEventListener('mousedown', over, true);
+ odoc.removeEventListener('keydown', checkesc, false);
+ odoc.removeEventListener('keydown', checkcopy as any, false);
+ odoc.removeEventListener('keyup', checkcopy as any, false);
+ }
+ });
}
if (exception) {
throw exception;
@@ -318,13 +323,13 @@ export default class Dragon {
if (!isDragNodeObject(dragObject)) {
return null;
}
- return (Array.isArray(dragObject.node) ? dragObject.node[0] : dragObject.node)?.document.simulator || null;
+ return (Array.isArray(dragObject.nodes) ? dragObject.nodes[0] : dragObject.nodes)?.document.simulator || null;
}
const simSensors = this.project.documents.map(doc => (doc.actived && doc.simulator) || null).filter(Boolean);
const sourceSensor = getSourceSensor(dragObject);
// check simulator is empty
- const sensors: SensorInterface[] = simSensors.concat(this.sensors);
+ const sensors: ISensor[] = simSensors.concat(this.sensors);
const chooseSensor = (e: LocateEvent) => {
let sensor = sensors.find(s => s.sensorAvailable && s.isEnter(e));
if (!sensor) {
@@ -390,7 +395,7 @@ export default class Dragon {
};
}
- onDragend(func: (x: { dragTarget: DragObject; copy: boolean }, location: Location) => any) {
+ onDragend(func: (x: { dragObject: DragObject; copy: boolean }, location: Location) => any) {
this.emitter.on('dragend', func);
return () => {
this.emitter.removeListener('dragend', func);
diff --git a/packages/designer/src/designer/project.ts b/packages/designer/src/designer/project.ts
index d12015184..4b89ce3f0 100644
--- a/packages/designer/src/designer/project.ts
+++ b/packages/designer/src/designer/project.ts
@@ -1,17 +1,25 @@
import { obx } from '@recore/obx';
-import { DocumentSchema, ProjectSchema } from './schema';
+import { ProjectSchema } from './schema';
import { EventEmitter } from 'events';
+import Designer from './designer';
+import DocumentModel from './document/document-model';
export default class Project {
- @obx documents: DocumentContext[];
- displayMode: 'exclusive' | 'tabbed' | 'split'; // P2
private emitter = new EventEmitter();
+ @obx.val readonly documents: DocumentModel[] = [];
private data: ProjectSchema = {};
+ @obx.ref displayMode: 'exclusive' | 'tabbed' | 'split' = 'exclusive';
+
// 考虑项目级别 History
- constructor(schema: ProjectSchema) {
- this.data = { ...schema };
+ constructor(readonly designer: Designer, schema?: ProjectSchema) {
+ this.data = {
+ version: '1.0.0',
+ componentsMap: [],
+ componentsTree: [],
+ ...schema
+ };
}
getDocument(fileName: string): DocumentContext {}
@@ -23,16 +31,19 @@ export default class Project {
/**
* 获取项目整体 schema
*/
- getSchema(): ProjectSchema {
+ get schema(): ProjectSchema {
return {
...this.data,
componentsTree: this.documents.map(doc => doc.getSchema()),
};
}
+
/**
* 整体设置项目 schema
*/
- setSchema(schema: ProjectSchema): void {}
+ set schema(schema: ProjectSchema) {
+
+ }
/**
* 分字段设置储存数据,不记录操作记录
diff --git a/packages/designer/src/designer/simulator-interface.ts b/packages/designer/src/designer/simulator-interface.ts
index f1cc26172..d38e2aa3b 100644
--- a/packages/designer/src/designer/simulator-interface.ts
+++ b/packages/designer/src/designer/simulator-interface.ts
@@ -1,9 +1,10 @@
import { NpmInfo } from './schema';
import { ComponentClass as ReactComponentClass, Component } from 'react';
-import { LocateEvent, SensorInterface } from './dragon';
-import { Point } from './document/location';
+import { LocateEvent, ISensor } from './dragon';
+import { Point } from './location';
+import Node from './document/node/node';
-export interface SimulatorInterface extends SensorInterface {
+export interface SimulatorInterface
extends ISensor {
/**
* 获得边界维度等信息
*/
diff --git a/packages/designer/src/designer/workspace.tsx b/packages/designer/src/designer/workspace.tsx
deleted file mode 100644
index e69de29bb..000000000