Migrate to ts node graph.

This commit is contained in:
Paulo Gustavo Veiga 2022-02-03 23:07:34 -08:00
parent c58f434509
commit 49efa9c340
16 changed files with 135 additions and 82 deletions

View File

@ -56,6 +56,7 @@ import { DesignerOptions } from './DesignerOptionsBuilder';
import MainTopic from './MainTopic'; import MainTopic from './MainTopic';
import DragTopic from './DragTopic'; import DragTopic from './DragTopic';
import CentralTopic from './CentralTopic'; import CentralTopic from './CentralTopic';
import FeatureType from './model/FeatureType';
class Designer extends Events { class Designer extends Events {
private _mindmap: Mindmap; private _mindmap: Mindmap;
@ -890,7 +891,7 @@ class Designer extends Events {
addIconType(iconType: string): void { addIconType(iconType: string): void {
const topicsIds = this.getModel().filterTopicsIds(); const topicsIds = this.getModel().filterTopicsIds();
if (topicsIds.length > 0) { if (topicsIds.length > 0) {
this._actionDispatcher.addFeatureToTopic(topicsIds[0], TopicFeatureFactory.Icon.id, { this._actionDispatcher.addFeatureToTopic(topicsIds[0], TopicFeatureFactory.Icon.id as FeatureType, {
id: iconType, id: iconType,
}); });
} }

View File

@ -17,11 +17,11 @@
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import PersistenceManager from './PersistenceManager'; import PersistenceManager from './PersistenceManager';
import { Size } from './Size'; import SizeType from './SizeType';
export type DesignerOptions = { export type DesignerOptions = {
zoom: number, zoom: number,
containerSize?: Size, containerSize?: SizeType,
readOnly?: boolean, readOnly?: boolean,
mapId?: string, mapId?: string,
container: string, container: string,

View File

@ -16,17 +16,29 @@
* limitations under the License. * limitations under the License.
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import { ElementClass } from '@wisemapping/web2d';
import TopicConfig from './TopicConfig'; import TopicConfig from './TopicConfig';
import NodeModel from './model/NodeModel';
import Workspace from './Workspace';
import DragTopic from './DragTopic'; import DragTopic from './DragTopic';
import LayoutManager from './layout/LayoutManager';
import SizeType from './SizeType';
import PositionType from './PositionType';
class NodeGraph { abstract class NodeGraph {
/** private _mouseEvents: boolean;
* @constructs
* @param {mindplot.model.NodeModel} nodeModel private _options;
* @param {Object<Number, String, Boolean>} options
* @throws will throw an error if nodeModel is null or undefined private _onFocus: boolean;
*/
constructor(nodeModel, options) { private _size: SizeType;
private _model: NodeModel;
private _elem2d: ElementClass;
constructor(nodeModel: NodeModel, options) {
$assert(nodeModel, 'model can not be null'); $assert(nodeModel, 'model can not be null');
this._options = options; this._options = options;
@ -36,46 +48,33 @@ class NodeGraph {
this._size = { width: 50, height: 20 }; this._size = { width: 50, height: 20 };
} }
/** @return true if option is set to read-only */ isReadOnly(): boolean {
isReadOnly() {
return this._options.readOnly; return this._options.readOnly;
} }
/** @return model type */ getType(): string {
getType() {
const model = this.getModel(); const model = this.getModel();
return model.getType(); return model.getType();
} }
/** setId(id: number) {
* @param {String} id
* @throws will throw an error if the topic id is not a number
*/
setId(id) {
$assert(typeof id === 'number', `id is not a number:${id}`); $assert(typeof id === 'number', `id is not a number:${id}`);
this.getModel().setId(id); this.getModel().setId(id);
} }
_set2DElement(elem2d) { protected _set2DElement(elem2d: ElementClass) {
this._elem2d = elem2d; this._elem2d = elem2d;
} }
/** get2DElement(): ElementClass {
* @return 2D element
* @throws will throw an error if the element is null or undefined within node graph
*/
get2DElement() {
$assert(this._elem2d, 'NodeGraph has not been initialized properly'); $assert(this._elem2d, 'NodeGraph has not been initialized properly');
return this._elem2d; return this._elem2d;
} }
/** @abstract */ abstract setPosition(point, fireEvent): void;
setPosition(point, fireEvent) {
throw new Error('Unsupported operation');
}
/** */ /** */
addEvent(type, listener) { addEvent(type: string, listener) {
const elem = this.get2DElement(); const elem = this.get2DElement();
elem.addEvent(type, listener); elem.addEvent(type, listener);
} }
@ -102,41 +101,30 @@ class NodeGraph {
return this._mouseEvents; return this._mouseEvents;
} }
/** @return {Object<Number>} size */ getSize(): SizeType {
getSize() {
return this._size; return this._size;
} }
/** @param {Object<Number>} size */
setSize(size) { setSize(size) {
this._size.width = parseInt(size.width, 10); this._size.width = parseInt(size.width, 10);
this._size.height = parseInt(size.height, 10); this._size.height = parseInt(size.height, 10);
} }
/** getModel(): NodeModel {
* @return {mindplot.model.NodeModel} the node model
*/
getModel() {
$assert(this._model, 'Model has not been initialized yet'); $assert(this._model, 'Model has not been initialized yet');
return this._model; return this._model;
} }
/** setModel(model: NodeModel) {
* @param {mindplot.NodeModel} model the node model
* @throws will throw an error if model is null or undefined
*/
setModel(model) {
$assert(model, 'Model can not be null'); $assert(model, 'Model can not be null');
this._model = model; this._model = model;
} }
/** */ getId(): number {
getId() {
return this._model.getId(); return this._model.getId();
} }
/** */ setOnFocus(focus: boolean) {
setOnFocus(focus) {
if (this._onFocus !== focus) { if (this._onFocus !== focus) {
this._onFocus = focus; this._onFocus = focus;
const outerShape = this.getOuterShape(); const outerShape = this.getOuterShape();
@ -157,29 +145,30 @@ class NodeGraph {
} }
} }
/** @return {Boolean} true if the node graph is on focus */ abstract closeEditors(): void;
isOnFocus() {
abstract setCursor(type: string): void;
abstract getOuterShape(): ElementClass;
isOnFocus(): boolean {
return this._onFocus; return this._onFocus;
} }
/** */ dispose(workspace: Workspace) {
dispose(workspace) {
this.setOnFocus(false); this.setOnFocus(false);
workspace.removeChild(this); workspace.removeChild(this);
} }
/** */ /** */
createDragNode(layoutManager) { createDragNode(layoutManager: LayoutManager) {
const dragShape = this._buildDragShape(); const dragShape = this._buildDragShape();
return new DragTopic(dragShape, this, layoutManager); return new DragTopic(dragShape, this, layoutManager);
} }
_buildDragShape() { abstract _buildDragShape();
$assert(false, '_buildDragShape must be implemented by all nodes.');
}
/** */ getPosition(): PositionType {
getPosition() {
const model = this.getModel(); const model = this.getModel();
return model.getPosition(); return model.getPosition();
} }

View File

@ -0,0 +1,20 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
type PositionType = { x: number, y: number };
export default PositionType;

View File

@ -154,8 +154,8 @@ class RelationshipPivot {
const controlPoint = Shape.calculateDefaultControlPoints(sourcePosition, toPosition); const controlPoint = Shape.calculateDefaultControlPoints(sourcePosition, toPosition);
const spoint = new Point(); const spoint = new Point();
spoint.x = parseInt(controlPoint[0].x, 10) + parseInt(sourcePosition.x, 10); spoint.x = parseInt(controlPoint[0].x, 10) + sourcePosition.x;
spoint.y = parseInt(controlPoint[0].y, 10) + parseInt(sourcePosition.y, 10); spoint.y = parseInt(controlPoint[0].y, 10) + sourcePosition.y;
return Shape.calculateRelationShipPointCoordinates(this._sourceTopic, spoint); return Shape.calculateRelationShipPointCoordinates(this._sourceTopic, spoint);
} }

View File

@ -1,4 +0,0 @@
export type Size = {
width: number;
height: number;
};

View File

@ -0,0 +1,23 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
type SizeType = {
width: number;
height: number;
};
export default SizeType;

View File

@ -34,6 +34,7 @@ import NodeModel from './model/NodeModel';
import RelationshipModel from './model/RelationshipModel'; import RelationshipModel from './model/RelationshipModel';
import Topic from './Topic'; import Topic from './Topic';
import Command from './Command'; import Command from './Command';
import FeatureType from './model/FeatureType';
class StandaloneActionDispatcher extends ActionDispatcher { class StandaloneActionDispatcher extends ActionDispatcher {
private _actionRunner: DesignerActionRunner; private _actionRunner: DesignerActionRunner;
@ -252,7 +253,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
addFeatureToTopic(topicId: number, featureType: string, attributes) { addFeatureToTopic(topicId: number, featureType: FeatureType, attributes) {
const command = new AddFeatureToTopicCommand(topicId, featureType, attributes); const command = new AddFeatureToTopicCommand(topicId, featureType, attributes);
this.execute(command); this.execute(command);
} }

View File

@ -18,7 +18,7 @@
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert, $defined } from '@wisemapping/core-js';
import { Workspace as Workspace2D, ElementClass as Element2D } from '@wisemapping/web2d'; import { Workspace as Workspace2D, ElementClass as Element2D } from '@wisemapping/web2d';
import ScreenManager from './ScreenManager'; import ScreenManager from './ScreenManager';
import { Size } from './Size'; import SizeType from './SizeType';
class Workspace { class Workspace {
private _zoom: number; private _zoom: number;
@ -27,13 +27,13 @@ class Workspace {
private _isReadOnly: boolean; private _isReadOnly: boolean;
private _containerSize: Size; private _containerSize: SizeType;
private _workspace: Workspace2D; private _workspace: Workspace2D;
private _eventsEnabled: boolean; private _eventsEnabled: boolean;
private _visibleAreaSize: Size; private _visibleAreaSize: SizeType;
constructor(screenManager: ScreenManager, zoom: number, isReadOnly: boolean) { constructor(screenManager: ScreenManager, zoom: number, isReadOnly: boolean) {
// Create a suitable container ... // Create a suitable container ...
@ -61,7 +61,7 @@ class Workspace {
this._eventsEnabled = true; this._eventsEnabled = true;
// Readjust if the window is resized ... // Readjust if the window is resized ...
window.addEventListener('resize', (event) => { window.addEventListener('resize', () => {
this._adjustWorkspace(); this._adjustWorkspace();
}); });
@ -123,7 +123,7 @@ class Workspace {
this._workspace.removeEvent(type, listener); this._workspace.removeEvent(type, listener);
} }
getSize():Size { getSize(): SizeType {
return this._workspace.getCoordSize(); return this._workspace.getCoordSize();
} }

View File

@ -18,11 +18,12 @@
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert, $defined } from '@wisemapping/core-js';
import Command from '../Command'; import Command from '../Command';
import CommandContext from '../CommandContext'; import CommandContext from '../CommandContext';
import FeatureType from '../model/FeatureType';
class AddFeatureToTopicCommand extends Command { class AddFeatureToTopicCommand extends Command {
private _topicId: number; private _topicId: number;
private _featureType: string; private _featureType: FeatureType;
private _attributes: object; private _attributes: object;
@ -38,7 +39,7 @@ class AddFeatureToTopicCommand extends Command {
* @extends mindplot.Command * @extends mindplot.Command
* @see mindplot.model.FeatureModel and subclasses * @see mindplot.model.FeatureModel and subclasses
*/ */
constructor(topicId: number, featureType: string, attributes: object) { constructor(topicId: number, featureType: FeatureType, attributes: object) {
$assert($defined(topicId), 'topicId can not be null'); $assert($defined(topicId), 'topicId can not be null');
$assert(featureType, 'featureType can not be null'); $assert(featureType, 'featureType can not be null');
$assert(attributes, 'attributes can not be null'); $assert(attributes, 'attributes can not be null');

View File

@ -16,8 +16,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import FeatureType from './FeatureType';
export type FeatureType = 'note' | 'link' | 'icon';
class FeatureModel { class FeatureModel {
static _next_id = 0; static _next_id = 0;

View File

@ -2,7 +2,8 @@ import { $assert } from '@wisemapping/core-js';
import IconModel from './IconModel'; import IconModel from './IconModel';
import LinkModel from './LinkModel'; import LinkModel from './LinkModel';
import NoteModel from './NoteModel'; import NoteModel from './NoteModel';
import FeatureModel, { FeatureType } from './FeatureModel'; import FeatureModel from './FeatureModel';
import FeatureType from './FeatureType';
interface NodeById { interface NodeById {
id: FeatureType, id: FeatureType,

View File

@ -0,0 +1,20 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
type FeatureType = 'note' | 'link' | 'icon';
export default FeatureType;

View File

@ -17,6 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert, $defined } from '@wisemapping/core-js';
import PositionType from '../PositionType';
import FeatureModel from './FeatureModel'; import FeatureModel from './FeatureModel';
import Mindmap from './Mindmap'; import Mindmap from './Mindmap';
@ -76,7 +77,7 @@ abstract class INodeModel {
this.putProperty('position', `{x:${x},y:${y}}`); this.putProperty('position', `{x:${x},y:${y}}`);
} }
getPosition(): { x: number, y: number } { getPosition(): PositionType {
const value = this.getProperty('position') as string; const value = this.getProperty('position') as string;
let result; let result;
if (value != null) { if (value != null) {

View File

@ -19,8 +19,9 @@ import { $assert, $defined } from '@wisemapping/core-js';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import INodeModel, { NodeModelType } from './INodeModel'; import INodeModel, { NodeModelType } from './INodeModel';
import FeatureModelFactory from './FeatureModelFactory'; import FeatureModelFactory from './FeatureModelFactory';
import FeatureModel, { FeatureType } from './FeatureModel'; import FeatureModel from './FeatureModel';
import Mindmap from './Mindmap'; import Mindmap from './Mindmap';
import FeatureType from './FeatureType';
class NodeModel extends INodeModel { class NodeModel extends INodeModel {
private _properties: Record<string, string | number | boolean>; private _properties: Record<string, string | number | boolean>;

View File

@ -22,9 +22,9 @@ import { TopicShape } from '../model/INodeModel';
import ConnectionLine from '../ConnectionLine'; import ConnectionLine from '../ConnectionLine';
import FeatureModelFactory from '../model/FeatureModelFactory'; import FeatureModelFactory from '../model/FeatureModelFactory';
import NodeModel from '../model/NodeModel'; import NodeModel from '../model/NodeModel';
import { FeatureType } from '../model/FeatureModel';
import RelationshipModel from '../model/RelationshipModel'; import RelationshipModel from '../model/RelationshipModel';
import XMLMindmapSerializer from './XMLMindmapSerializer'; import XMLMindmapSerializer from './XMLMindmapSerializer';
import FeatureType from '../model/FeatureType';
class XMLSerializerPela implements XMLMindmapSerializer { class XMLSerializerPela implements XMLMindmapSerializer {
private static MAP_ROOT_NODE = 'map'; private static MAP_ROOT_NODE = 'map';