Move commands to TS.

This commit is contained in:
Paulo Gustavo Veiga 2022-01-24 22:09:30 -08:00
parent 560aa567c5
commit 2b40f429b4
22 changed files with 378 additions and 370 deletions

View File

@ -1,111 +0,0 @@
/* eslint-disable no-unused-vars */
/*
* 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.
*/
import { $assert } from '@wisemapping/core-js';
import Events from './Events';
class ActionDispatcher extends Events {
constructor(commandContext) {
$assert(commandContext, 'commandContext can not be null');
super();
}
addRelationship(model, mindmap) {
throw new Error('method must be implemented.');
}
addTopics(models, parentTopicId) {
throw new Error('method must be implemented.');
}
deleteEntities(topicsIds, relIds) {
throw new Error('method must be implemented.');
}
dragTopic(topicId, position, order, parentTopic) {
throw new Error('method must be implemented.');
}
moveTopic(topicId, position) {
throw new Error('method must be implemented.');
}
moveControlPoint(ctrlPoint, point) {
throw new Error('method must be implemented.');
}
changeFontFamilyToTopic(topicIds, fontFamily) {
throw new Error('method must be implemented.');
}
changeFontStyleToTopic(topicsIds) {
throw new Error('method must be implemented.');
}
changeFontColorToTopic(topicsIds, color) {
throw new Error('method must be implemented.');
}
changeFontSizeToTopic(topicsIds, size) {
throw new Error('method must be implemented.');
}
changeBackgroundColorToTopic(topicsIds, color) {
throw new Error('method must be implemented.');
}
changeBorderColorToTopic(topicsIds, color) {
throw new Error('method must be implemented.');
}
changeShapeTypeToTopic(topicsIds, shapeType) {
throw new Error('method must be implemented.');
}
changeFontWeightToTopic(topicsIds) {
throw new Error('method must be implemented.');
}
changeTextToTopic(topicsIds, text) {
throw new Error('method must be implemented.');
}
shrinkBranch(topicsIds, collapse) {
throw new Error('method must be implemented.');
}
addFeatureToTopic(topicId, type, attributes) {
throw new Error('method must be implemented.');
}
changeFeatureToTopic(topicId, featureId, attributes) {
throw new Error('method must be implemented.');
}
removeFeatureFromTopic(topicId, featureId) {
throw new Error('method must be implemented.');
}
}
ActionDispatcher.setInstance = (dispatcher) => {
ActionDispatcher._instance = dispatcher;
};
ActionDispatcher.getInstance = () => ActionDispatcher._instance;
export default ActionDispatcher;

View File

@ -0,0 +1,82 @@
/* eslint-disable import/no-cycle */
/* eslint-disable no-use-before-define */
/*
* 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.
*/
import { $assert } from '@wisemapping/core-js';
import Point from '@wisemapping/web2d';
import { Mindmap } from '..';
import CommandContext from './CommandContext';
import Events from './Events';
import NodeModel from './model/NodeModel';
import RelationshipModel from './model/RelationshipModel';
import Topic from './Topic';
abstract class ActionDispatcher extends Events {
static _instance: ActionDispatcher;
constructor(commandContext: CommandContext) {
$assert(commandContext, 'commandContext can not be null');
super();
}
abstract addRelationship(model: RelationshipModel, mindmap: Mindmap);
abstract addTopics(models: NodeModel[], parentTopicId: any[]);
abstract deleteEntities(topicsIds: number[], relIds: number[]);
abstract dragTopic(topicId: number, position: Point, order: number, parentTopic: Topic);
abstract moveTopic(topicId: number, position: any);
abstract moveControlPoint(ctrlPoint: this, point: any);
abstract changeFontFamilyToTopic(topicIds: number[], fontFamily: string);
abstract changeFontStyleToTopic(topicsIds: number[]);
abstract changeFontColorToTopic(topicsIds: number[], color: string);
abstract changeFontSizeToTopic(topicsIds: number[], size: number);
abstract changeBackgroundColorToTopic(topicsIds: number[], color: string);
abstract changeBorderColorToTopic(topicsIds: number[], color: string);
abstract changeShapeTypeToTopic(topicsIds: number[], shapeType: string);
abstract changeFontWeightToTopic(topicsIds: number[]);
abstract changeTextToTopic(topicsIds: number[], text: string);
abstract shrinkBranch(topicsIds: number[], collapse: boolean);
abstract addFeatureToTopic(topicId: number, type: string, attributes: object);
abstract changeFeatureToTopic(topicId: number, featureId: any, attributes: object);
abstract removeFeatureFromTopic(topicId: number, featureId: number);
static setInstance = (dispatcher: ActionDispatcher) => {
this._instance = dispatcher;
};
static getInstance = (): ActionDispatcher => ActionDispatcher._instance;
}
export default ActionDispatcher;

View File

@ -16,42 +16,32 @@
* limitations under the License. * limitations under the License.
*/ */
import { $defined } from '@wisemapping/core-js'; import { $defined } from '@wisemapping/core-js';
import CommandContext from './CommandContext';
abstract class Command {
private _id: number;
static _uuid: number;
class Command {
/**
* @classdesc The command base class for handling do/undo mindmap operations
* @constructs
*/
constructor() { constructor() {
this._id = Command._nextUUID(); this._id = Command._nextUUID();
} }
// eslint-disable-next-line no-unused-vars abstract execute(commandContext:CommandContext):void;
execute(commandContext) {
throw new Error('execute must be implemented.');
}
// eslint-disable-next-line no-unused-vars abstract undoExecute(commandContext:CommandContext):void;
undoExecute(commandContext) {
throw new Error('undo must be implemented.');
}
/** getId():number {
* Returns the unique id of this command
* @returns {Number} command id
*/
getId() {
return this._id; return this._id;
} }
}
Command._nextUUID = function _nextUUID() { static _nextUUID() {
if (!$defined(Command._uuid)) { if (!$defined(this._uuid)) {
Command._uuid = 1; this._uuid = 1;
}
this._uuid += 1;
return this._uuid;
}
} }
Command._uuid += 1;
return Command._uuid;
};
export default Command; export default Command;

View File

@ -16,16 +16,32 @@
* limitations under the License. * limitations under the License.
*/ */
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert, $defined } from '@wisemapping/core-js';
import Point from '@wisemapping/web2d';
import { Designer } from '..';
import EventBus from './layout/EventBus'; import EventBus from './layout/EventBus';
import NodeModel from './model/NodeModel';
import RelationshipModel from './model/RelationshipModel';
import Relationship from './Relationship';
import Topic from './Topic';
class CommandContext { class CommandContext {
constructor(designer) { private _designer: Designer;
constructor(designer: Designer) {
$assert(designer, 'designer can not be null'); $assert(designer, 'designer can not be null');
this._designer = designer; this._designer = designer;
} }
public get designer(): Designer {
return this._designer;
}
public set designer(value: Designer) {
this._designer = value;
}
/** */ /** */
findTopics(topicIds) { findTopics(topicIds: number[]): Topic[] {
$assert($defined(topicIds), 'topicsIds can not be null'); $assert($defined(topicIds), 'topicsIds can not be null');
const topicsIds = Array.isArray(topicIds) ? topicIds : [topicIds]; const topicsIds = Array.isArray(topicIds) ? topicIds : [topicIds];
const designerTopics = this._designer.getModel().getTopics(); const designerTopics = this._designer.getModel().getTopics();
@ -45,51 +61,51 @@ class CommandContext {
} }
/** */ /** */
deleteTopic(topic) { deleteTopic(topic: Topic) {
this._designer.removeTopic(topic); this._designer.removeTopic(topic);
} }
/** */ /** */
createTopic(model) { createTopic(model: NodeModel) {
$assert(model, 'model can not be null'); $assert(model, 'model can not be null');
return this._designer.nodeModelToTopic(model); return this._designer.nodeModelToTopic(model);
} }
/** */ // /** */
createModel() { // createModel() {
const mindmap = this._designer.getMindmap(); // const mindmap = this._designer.getMindmap();
return mindmap.createNode('MainTopic'); // return mindmap.createNode('MainTopic');
} // }
/** */ /** */
addTopic(topic) { addTopic(topic: Topic) {
const mindmap = this._designer.getMindmap(); const mindmap = this._designer.getMindmap();
return mindmap.addBranch(topic.getModel()); return mindmap.addBranch(topic.getModel());
} }
/** */ /** */
connect(childTopic, parentTopic) { connect(childTopic: Topic, parentTopic: Topic) {
childTopic.connectTo(parentTopic, this._designer._workspace); childTopic.connectTo(parentTopic, this._designer.getWorkSpace());
} }
/** */ /** */
disconnect(topic) { disconnect(topic: Topic) {
topic.disconnect(this._designer._workspace); topic.disconnect(this._designer.getWorkSpace());
} }
/** */ /** */
addRelationship(model) { addRelationship(model: RelationshipModel) {
$assert(model, 'model cannot be null'); $assert(model, 'model cannot be null');
return this._designer.addRelationship(model); return this._designer.addRelationship(model);
} }
/** */ /** */
deleteRelationship(relationship) { deleteRelationship(relationship: Relationship) {
this._designer.deleteRelationship(relationship); this._designer.deleteRelationship(relationship);
} }
/** */ /** */
findRelationships(relationshipIds) { findRelationships(relationshipIds: number[]) {
$assert($defined(relationshipIds), 'relId can not be null'); $assert($defined(relationshipIds), 'relId can not be null');
const relIds = Array.isArray(relationshipIds) ? relationshipIds : [relationshipIds]; const relIds = Array.isArray(relationshipIds) ? relationshipIds : [relationshipIds];
@ -98,7 +114,7 @@ class CommandContext {
} }
/** */ /** */
moveTopic(topic, position) { moveTopic(topic: Topic, position: Point) {
$assert(topic, 'topic cannot be null'); $assert(topic, 'topic cannot be null');
$assert(position, 'position cannot be null'); $assert(position, 'position cannot be null');
EventBus.instance.fireEvent(EventBus.events.NodeMoveEvent, { EventBus.instance.fireEvent(EventBus.events.NodeMoveEvent, {
@ -107,5 +123,4 @@ class CommandContext {
}); });
} }
} }
// eslint-disable-next-line import/prefer-default-export
export default CommandContext; export default CommandContext;

View File

@ -75,9 +75,9 @@ class Designer extends Events {
private _relPivot: RelationshipPivot; private _relPivot: RelationshipPivot;
private _clipboard: any[]; private _clipboard: NodeModel[];
private _cleanScreen: any; private _cleanScreen: () => void;
constructor(options: DesignerOptions, divElement: JQuery) { constructor(options: DesignerOptions, divElement: JQuery) {
$assert(options, 'options must be defined'); $assert(options, 'options must be defined');
@ -625,11 +625,11 @@ class Designer extends Events {
} }
undo(): void { undo(): void {
this._actionDispatcher._actionRunner.undo(); this._actionDispatcher.actionRunner.undo();
} }
redo(): void { redo(): void {
this._actionDispatcher._actionRunner.redo(); this._actionDispatcher.actionRunner.redo();
} }
/** */ /** */
@ -839,18 +839,19 @@ class Designer extends Events {
} }
/** */ /** */
changeFontColor(color) { changeFontColor(color: string) {
$assert(color, 'color can not be null'); $assert(color, 'color can not be null');
const topicsIds = this.getModel() const topicsIds = this.getModel()
.filterTopicsIds(); .filterTopicsIds();
if (topicsIds.length > 0) { if (topicsIds.length > 0) {
this._actionDispatcher.changeFontColorToTopic(topicsIds, color); this._actionDispatcher.changeFontColorToTopic(topicsIds, color);
} }
} }
/** */ /** */
changeBackgroundColor(color) { changeBackgroundColor(color: string) {
const validateFunc = (topic) => topic.getShapeType() !== TopicShape.LINE; const validateFunc = (topic) => topic.getShapeType() !== TopicShape.LINE;
const validateError = 'Color can not be set to line topics.'; const validateError = 'Color can not be set to line topics.';

View File

@ -106,7 +106,7 @@ class DesignerModel extends Events {
this._relationships.push(rel); this._relationships.push(rel);
} }
filterTopicsIds(validate: (topic: Topic) => boolean = null, errorMsg = null): Topic[] { filterTopicsIds(validate: (topic: Topic) => boolean = null, errorMsg = null): number[] {
const result = []; const result = [];
const topics = this.filterSelectedTopics(); const topics = this.filterSelectedTopics();

View File

@ -92,8 +92,8 @@ class DragManager {
event.preventDefault(); event.preventDefault();
}; };
// allowed param reassign to avoid risks of existing code relying in this side-effect // allowed param reassign to avoid risks of existing code relying in this side-effect
// eslint-disable-next-line no-param-reassign
dragManager._mouseMoveListener = result; dragManager._mouseMoveListener = result;
return result; return result;
} }
@ -110,10 +110,8 @@ class DragManager {
// Help GC // Help GC
// allowed param reassign to avoid risks of existing code relying in this side-effect // allowed param reassign to avoid risks of existing code relying in this side-effect
/* eslint-disable no-param-reassign */
dragManager._mouseMoveListener = null; dragManager._mouseMoveListener = null;
dragManager._mouseUpListener = null; dragManager._mouseUpListener = null;
/* eslint-enable no-param-reassign */
workspace.enableWorkspaceEvents(true); workspace.enableWorkspaceEvents(true);
// Change the cursor to the default. // Change the cursor to the default.
@ -130,7 +128,6 @@ class DragManager {
me._isDragInProcess = false; me._isDragInProcess = false;
} }
}; };
// eslint-disable-next-line no-param-reassign
dragManager._mouseUpListener = result; dragManager._mouseUpListener = result;
return result; return result;
} }

View File

@ -28,17 +28,17 @@ class RelationshipPivot {
private _designer: Designer; private _designer: Designer;
private _mouseMoveEvent: any; private _mouseMoveEvent: MouseEvent;
private _onClickEvent: any; private _onClickEvent: (event: MouseEvent) => void;
private _onTopicClick: any; private _onTopicClick: (event: MouseEvent) => void;;
private _sourceTopic: Topic; private _sourceTopic: Topic;
private _pivot: any; private _pivot: any;
private _startArrow: any; private _startArrow: Arrow;
constructor(workspace: Workspace, designer: Designer) { constructor(workspace: Workspace, designer: Designer) {
$assert(workspace, 'workspace can not be null'); $assert(workspace, 'workspace can not be null');

View File

@ -17,6 +17,7 @@
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import { Point } from '@wisemapping/web2d'; import { Point } from '@wisemapping/web2d';
import Topic from './Topic';
class ScreenManager { class ScreenManager {
private _divContainer: JQuery; private _divContainer: JQuery;
@ -83,7 +84,7 @@ class ScreenManager {
} }
} }
_getElementPosition(elem: { getPosition: () => any; }) { private _getElementPosition(elem: Topic) {
// Retrieve current element position. // Retrieve current element position.
const elementPosition = elem.getPosition(); const elementPosition = elem.getPosition();
let { x } = elementPosition; let { x } = elementPosition;

View File

@ -16,6 +16,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { $defined, $assert } from '@wisemapping/core-js'; import { $defined, $assert } from '@wisemapping/core-js';
import { Point } from '@wisemapping/web2d';
import ActionDispatcher from './ActionDispatcher'; import ActionDispatcher from './ActionDispatcher';
import DesignerActionRunner from './DesignerActionRunner'; import DesignerActionRunner from './DesignerActionRunner';
import AddTopicCommand from './commands/AddTopicCommand'; import AddTopicCommand from './commands/AddTopicCommand';
@ -28,39 +29,52 @@ import GenericFunctionCommand from './commands/GenericFunctionCommand';
import MoveControlPointCommand from './commands/MoveControlPointCommand'; import MoveControlPointCommand from './commands/MoveControlPointCommand';
import ChangeFeatureToTopicCommand from './commands/ChangeFeatureToTopicCommand'; import ChangeFeatureToTopicCommand from './commands/ChangeFeatureToTopicCommand';
import EventBus from './layout/EventBus'; import EventBus from './layout/EventBus';
import CommandContext from './CommandContext';
import NodeModel from './model/NodeModel';
import RelationshipModel from './model/RelationshipModel';
import Topic from './Topic';
import Command from './Command';
class StandaloneActionDispatcher extends ActionDispatcher { class StandaloneActionDispatcher extends ActionDispatcher {
constructor(commandContext) { private _actionRunner: DesignerActionRunner;
public get actionRunner(): DesignerActionRunner {
return this._actionRunner;
}
public set actionRunner(value: DesignerActionRunner) {
this._actionRunner = value;
}
constructor(commandContext: CommandContext) {
super(commandContext); super(commandContext);
this._actionRunner = new DesignerActionRunner(commandContext, this); this._actionRunner = new DesignerActionRunner(commandContext, this);
} }
/** */ addTopics(models: NodeModel[], parentTopicsId: number[] = undefined) {
addTopics(models, parentTopicsId) {
const command = new AddTopicCommand(models, parentTopicsId); const command = new AddTopicCommand(models, parentTopicsId);
this.execute(command); this.execute(command);
} }
/** */ addRelationship(model: RelationshipModel) {
addRelationship(model) {
const command = new AddRelationshipCommand(model); const command = new AddRelationshipCommand(model);
this.execute(command); this.execute(command);
} }
/** */ /** */
deleteEntities(topicsIds, relIds) { deleteEntities(topicsIds: number[], relIds: number[]) {
const command = new DeleteCommand(topicsIds, relIds); const command = new DeleteCommand(topicsIds, relIds);
this.execute(command); this.execute(command);
} }
/** */ /** */
dragTopic(topicId, position, order, parentTopic) { dragTopic(topicId: number, position: Point, order: number, parentTopic: Topic) {
const command = new DragTopicCommand(topicId, position, order, parentTopic); const command = new DragTopicCommand(topicId, position, order, parentTopic);
this.execute(command); this.execute(command);
} }
/** */ /** */
moveTopic(topicId, position) { moveTopic(topicId: number, position: Point) {
$assert($defined(topicId), 'topicsId can not be null'); $assert($defined(topicId), 'topicsId can not be null');
$assert($defined(position), 'position can not be null'); $assert($defined(position), 'position can not be null');
@ -73,19 +87,19 @@ class StandaloneActionDispatcher extends ActionDispatcher {
return result; return result;
}; };
const command = new GenericFunctionCommand(commandFunc, topicId, position); const command = new GenericFunctionCommand(commandFunc, [topicId], position);
this.execute(command); this.execute(command);
} }
/** */ /** */
moveControlPoint(ctrlPoint, point) { moveControlPoint(ctrlPoint: Point, point: Point) {
const command = new MoveControlPointCommand(ctrlPoint, point); const command = new MoveControlPointCommand(ctrlPoint, point);
this.execute(command); this.execute(command);
} }
/** */ /** */
changeFontStyleToTopic(topicsIds) { changeFontStyleToTopic(topicsIds: number[]) {
const commandFunc = (topic) => { const commandFunc = (topic: Topic) => {
const result = topic.getFontStyle(); const result = topic.getFontStyle();
const style = result === 'italic' ? 'normal' : 'italic'; const style = result === 'italic' ? 'normal' : 'italic';
topic.setFontStyle(style, true); topic.setFontStyle(style, true);
@ -96,10 +110,10 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
changeTextToTopic(topicsIds, text) { changeTextToTopic(topicsIds: number[], text: string) {
$assert($defined(topicsIds), 'topicsIds can not be null'); $assert($defined(topicsIds), 'topicsIds can not be null');
const commandFunc = (topic, value) => { const commandFunc = (topic: Topic, value: object) => {
const result = topic.getText(); const result = topic.getText();
topic.setText(value); topic.setText(value);
return result; return result;
@ -111,11 +125,11 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
changeFontFamilyToTopic(topicIds, fontFamily) { changeFontFamilyToTopic(topicIds: number[], fontFamily: string) {
$assert(topicIds, 'topicIds can not be null'); $assert(topicIds, 'topicIds can not be null');
$assert(fontFamily, 'fontFamily can not be null'); $assert(fontFamily, 'fontFamily can not be null');
const commandFunc = (topic, commandFontFamily) => { const commandFunc = (topic: Topic, commandFontFamily: string) => {
const result = topic.getFontFamily(); const result = topic.getFontFamily();
topic.setFontFamily(commandFontFamily, true); topic.setFontFamily(commandFontFamily, true);
@ -128,7 +142,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
changeFontColorToTopic(topicsIds, color) { changeFontColorToTopic(topicsIds: number[], color: string) {
$assert(topicsIds, 'topicIds can not be null'); $assert(topicsIds, 'topicIds can not be null');
$assert(color, 'color can not be null'); $assert(color, 'color can not be null');
@ -144,7 +158,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
changeBackgroundColorToTopic(topicsIds, color) { changeBackgroundColorToTopic(topicsIds: number[], color: string) {
$assert(topicsIds, 'topicIds can not be null'); $assert(topicsIds, 'topicIds can not be null');
$assert(color, 'color can not be null'); $assert(color, 'color can not be null');
@ -160,7 +174,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
changeBorderColorToTopic(topicsIds, color) { changeBorderColorToTopic(topicsIds: number[], color: string): void {
$assert(topicsIds, 'topicIds can not be null'); $assert(topicsIds, 'topicIds can not be null');
$assert(color, 'topicIds can not be null'); $assert(color, 'topicIds can not be null');
@ -176,7 +190,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
changeFontSizeToTopic(topicsIds, size) { changeFontSizeToTopic(topicsIds: number[], size: number) {
$assert(topicsIds, 'topicIds can not be null'); $assert(topicsIds, 'topicIds can not be null');
$assert(size, 'size can not be null'); $assert(size, 'size can not be null');
@ -193,7 +207,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
changeShapeTypeToTopic(topicsIds, shapeType) { changeShapeTypeToTopic(topicsIds: number[], shapeType: string) {
$assert(topicsIds, 'topicsIds can not be null'); $assert(topicsIds, 'topicsIds can not be null');
$assert(shapeType, 'shapeType can not be null'); $assert(shapeType, 'shapeType can not be null');
@ -208,7 +222,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
changeFontWeightToTopic(topicsIds) { changeFontWeightToTopic(topicsIds: number[]) {
$assert(topicsIds, 'topicsIds can not be null'); $assert(topicsIds, 'topicsIds can not be null');
const commandFunc = (topic) => { const commandFunc = (topic) => {
@ -225,38 +239,38 @@ class StandaloneActionDispatcher extends ActionDispatcher {
} }
/** */ /** */
shrinkBranch(topicsIds, collapse) { shrinkBranch(topicsIds: number[], collapse: boolean) {
$assert(topicsIds, 'topicsIds can not be null'); $assert(topicsIds, 'topicsIds can not be null');
const commandFunc = (topic, isShrink) => { const commandFunc = (topic: Topic, isShrink: boolean) => {
topic.setChildrenShrunken(isShrink); topic.setChildrenShrunken(isShrink);
return !isShrink; return !isShrink;
}; };
const command = new GenericFunctionCommand(commandFunc, topicsIds, collapse); const command = new GenericFunctionCommand(commandFunc, topicsIds, collapse);
this.execute(command, false); this.execute(command);
} }
/** */ /** */
addFeatureToTopic(topicId, featureType, attributes) { addFeatureToTopic(topicId: number, featureType: string, attributes) {
const command = new AddFeatureToTopicCommand(topicId, featureType, attributes); const command = new AddFeatureToTopicCommand(topicId, featureType, attributes);
this.execute(command); this.execute(command);
} }
/** */ /** */
changeFeatureToTopic(topicId, featureId, attributes) { changeFeatureToTopic(topicId: number, featureId: number, attributes) {
const command = new ChangeFeatureToTopicCommand(topicId, featureId, attributes); const command = new ChangeFeatureToTopicCommand(topicId, featureId, attributes);
this.execute(command); this.execute(command);
} }
/** */ /** */
removeFeatureFromTopic(topicId, featureId) { removeFeatureFromTopic(topicId: number, featureId: number) {
const command = new RemoveFeatureFromTopicCommand(topicId, featureId); const command = new RemoveFeatureFromTopicCommand(topicId, featureId);
this.execute(command); this.execute(command);
} }
/** */ /** */
execute(command) { execute(command: Command) {
this._actionRunner.execute(command); this._actionRunner.execute(command);
} }
} }

View File

@ -17,8 +17,17 @@
*/ */
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';
class AddFeatureToTopicCommand extends Command { class AddFeatureToTopicCommand extends Command {
private _topicId: number;
private _featureType: string;
private _attributes: object;
private _featureModel: any;
/* /*
* @classdesc This command class handles do/undo of adding features to topics, e.g. an * @classdesc This command class handles do/undo of adding features to topics, e.g. an
* icon or a note. For a reference of existing features, refer to {@link mindplot.TopicFeature} * icon or a note. For a reference of existing features, refer to {@link mindplot.TopicFeature}
@ -29,7 +38,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, featureType, attributes) { constructor(topicId: number, featureType: string, 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');
@ -44,8 +53,8 @@ class AddFeatureToTopicCommand extends Command {
/** /**
* Overrides abstract parent method * Overrides abstract parent method
*/ */
execute(commandContext) { execute(commandContext: CommandContext) {
const topic = commandContext.findTopics(this._topicId)[0]; const topic = commandContext.findTopics([this._topicId])[0];
// Feature must be created only one time. // Feature must be created only one time.
if (!this._featureModel) { if (!this._featureModel) {
@ -59,8 +68,8 @@ class AddFeatureToTopicCommand extends Command {
* Overrides abstract parent method * Overrides abstract parent method
* @see {@link mindplot.Command.undoExecute} * @see {@link mindplot.Command.undoExecute}
*/ */
undoExecute(commandContext) { undoExecute(commandContext: CommandContext) {
const topic = commandContext.findTopics(this._topicId)[0]; const topic = commandContext.findTopics([this._topicId])[0];
topic.removeFeature(this._featureModel); topic.removeFeature(this._featureModel);
} }
} }

View File

@ -17,15 +17,15 @@
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import Command from '../Command'; import Command from '../Command';
import RelationshipModel from '../model/RelationshipModel';
class AddRelationshipCommand extends Command { class AddRelationshipCommand extends Command {
private _model: RelationshipModel;
/** /**
* @classdesc This command class handles do/undo of adding a relationship to a topic. * @classdesc This command class handles do/undo of adding a relationship to a topic.
* @constructs
* @param {XMLDOM} model
* @extends mindplot.Command
*/ */
constructor(model) { constructor(model:RelationshipModel) {
$assert(model, 'Relationship model can not be null'); $assert(model, 'Relationship model can not be null');
super(); super();

View File

@ -17,18 +17,19 @@
*/ */
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 NodeModel from '../model/NodeModel';
class AddTopicCommand extends Command { class AddTopicCommand extends Command {
private _models: NodeModel[];
private _parentsIds: number[];
/** /**
* @classdesc This command class handles do/undo of adding one or multiple topics to * @classdesc This command class handles do/undo of adding one or multiple topics to
* the mindmap. * the mindmap.
* @constructs
* @param {Array<mindplot.model.NodeModel>} models one or multiple models
* @param {Array<String>} parentTopicsId ids of the parent topics to add the children to, or null
* when attaching a dragged node or a node/branch from clipboard
* @extends mindplot.Command
*/ */
constructor(models, parentTopicsId) { constructor(models: NodeModel[], parentTopicsId: number[]) {
$assert(models, 'models can not be null'); $assert(models, 'models can not be null');
$assert(parentTopicsId == null || parentTopicsId.length === models.length, 'parents and models must have the same size'); $assert(parentTopicsId == null || parentTopicsId.length === models.length, 'parents and models must have the same size');
@ -40,7 +41,7 @@ class AddTopicCommand extends Command {
/** /**
* Overrides abstract parent method * Overrides abstract parent method
*/ */
execute(commandContext) { execute(commandContext: CommandContext) {
const me = this; const me = this;
this._models.forEach((model, index) => { this._models.forEach((model, index) => {
// Add a new topic ... // Add a new topic ...
@ -50,7 +51,7 @@ class AddTopicCommand extends Command {
if (me._parentsIds) { if (me._parentsIds) {
const parentId = me._parentsIds[index]; const parentId = me._parentsIds[index];
if ($defined(parentId)) { if ($defined(parentId)) {
const parentTopic = commandContext.findTopics(parentId)[0]; const parentTopic = commandContext.findTopics([parentId])[0];
commandContext.connect(topic, parentTopic); commandContext.connect(topic, parentTopic);
} }
} else { } else {
@ -58,7 +59,7 @@ class AddTopicCommand extends Command {
} }
// Select just created node ... // Select just created node ...
const designer = commandContext._designer; const { designer } = commandContext;
designer.onObjectFocusEvent(topic); designer.onObjectFocusEvent(topic);
topic.setOnFocus(true); topic.setOnFocus(true);
@ -71,7 +72,7 @@ class AddTopicCommand extends Command {
* Overrides abstract parent method * Overrides abstract parent method
* @see {@link mindplot.Command.undoExecute} * @see {@link mindplot.Command.undoExecute}
*/ */
undoExecute(commandContext) { undoExecute(commandContext: CommandContext) {
// Delete disconnected the nodes. Create a copy of the topics ... // Delete disconnected the nodes. Create a copy of the topics ...
const clonedModel = []; const clonedModel = [];
this._models.forEach((model) => { this._models.forEach((model) => {
@ -79,9 +80,9 @@ class AddTopicCommand extends Command {
}); });
// Finally, remove the nodes ... // Finally, remove the nodes ...
this._models.forEach((model) => { this._models.forEach((model: NodeModel) => {
const topicId = model.getId(); const topicId = model.getId();
const topic = commandContext.findTopics(topicId)[0]; const topic = commandContext.findTopics([topicId])[0];
commandContext.deleteTopic(topic); commandContext.deleteTopic(topic);
}); });

View File

@ -17,19 +17,16 @@
*/ */
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';
class ChangeFeatureToTopicCommand extends Command { class ChangeFeatureToTopicCommand extends Command {
/** private _featureId: number;
* @extends mindplot.Command
* @constructs private _topicId: number;
* @param topicId
* @param featureId private _attributes: any;
* @param attributes
* @throws will throw an error if topicId is null or undefined constructor(topicId: number, featureId: number, attributes: any) {
* @throws will throw an error if featureId is null or undefined
* @throws will throw an error if attributes is null or undefined
*/
constructor(topicId, featureId, attributes) {
$assert($defined(topicId), 'topicId can not be null'); $assert($defined(topicId), 'topicId can not be null');
$assert($defined(featureId), 'featureId can not be null'); $assert($defined(featureId), 'featureId can not be null');
$assert($defined(attributes), 'attributes can not be null'); $assert($defined(attributes), 'attributes can not be null');
@ -43,8 +40,8 @@ class ChangeFeatureToTopicCommand extends Command {
/** /**
* Overrides abstract parent method * Overrides abstract parent method
*/ */
execute(commandContext) { execute(commandContext: CommandContext) {
const topic = commandContext.findTopics(this._topicId)[0]; const topic = commandContext.findTopics([this._topicId])[0];
const feature = topic.findFeatureById(this._featureId); const feature = topic.findFeatureById(this._featureId);
const oldAttributes = feature.getAttributes(); const oldAttributes = feature.getAttributes();
@ -56,7 +53,7 @@ class ChangeFeatureToTopicCommand extends Command {
* Overrides abstract parent method * Overrides abstract parent method
* @see {@link mindplot.Command.undoExecute} * @see {@link mindplot.Command.undoExecute}
*/ */
undoExecute(commandContext) { undoExecute(commandContext: any) {
this.execute(commandContext); this.execute(commandContext);
} }
} }

View File

@ -17,16 +17,20 @@
*/ */
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';
class DeleteCommand extends Command { class DeleteCommand extends Command {
/** private _relIds: number[];
* @classdesc This command class handles do/undo of deleting a topic.
* @constructs private _topicIds: number[];
* @param {Array<String>} topicIds ids of the topics to delete
* @param {Array<String>} relIds ids of the relationships connected to the topics private _deletedTopicModels: any[];
* @extends mindplot.Command
*/ private _deletedRelModel: any[];
constructor(topicIds, relIds) {
private _parentTopicIds: any[];
constructor(topicIds: number[], relIds: number[]) {
$assert($defined(relIds), 'topicIds can not be null'); $assert($defined(relIds), 'topicIds can not be null');
super(); super();
@ -40,7 +44,7 @@ class DeleteCommand extends Command {
/** /**
* Overrides abstract parent method * Overrides abstract parent method
*/ */
execute(commandContext) { execute(commandContext: CommandContext) {
// If a parent has been selected for deletion, the children must be excluded from the delete ... // If a parent has been selected for deletion, the children must be excluded from the delete ...
const topics = this._filterChildren(this._topicIds, commandContext); const topics = this._filterChildren(this._topicIds, commandContext);
@ -89,7 +93,7 @@ class DeleteCommand extends Command {
* Overrides abstract parent method * Overrides abstract parent method
* @see {@link mindplot.Command.undoExecute} * @see {@link mindplot.Command.undoExecute}
*/ */
undoExecute(commandContext) { undoExecute(commandContext: CommandContext) {
// Add all the topics ... // Add all the topics ...
this._deletedTopicModels.forEach((model) => { this._deletedTopicModels.forEach((model) => {
commandContext.createTopic(model); commandContext.createTopic(model);

View File

@ -16,19 +16,25 @@
* limitations under the License. * limitations under the License.
*/ */
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert, $defined } from '@wisemapping/core-js';
import Point from '@wisemapping/web2d';
import Command from '../Command'; import Command from '../Command';
import CommandContext from '../CommandContext';
import Topic from '../Topic';
class DragTopicCommand extends Command { class DragTopicCommand extends Command {
private _topicsId: number;
private _parentId: any;
private _position: Point;
private _order: number;
/** /**
* @classdesc This command class handles do/undo of dragging a topic to a new position. * @classdesc This command class handles do/undo of dragging a topic to a new position.
* @constructs * @constructs
* @param {String} topicId id of the topic to drag
* @param {Object} position
* @param {Number} order the order property (children are displayed in order from 0 to n)
* @param {mindplot.Topic} parentTopic the topic to be made the dragged topic's new parent
* @extends mindplot.Command
*/ */
constructor(topicId, position, order, parentTopic) { constructor(topicId: number, position: Point, order: number, parentTopic: Topic) {
$assert(topicId, 'topicId must be defined'); $assert(topicId, 'topicId must be defined');
super(); super();
@ -44,8 +50,8 @@ class DragTopicCommand extends Command {
/** /**
* Overrides abstract parent method * Overrides abstract parent method
*/ */
execute(commandContext) { execute(commandContext: CommandContext): void {
const topic = commandContext.findTopics(this._topicsId)[0]; const topic = commandContext.findTopics([this._topicsId])[0];
topic.setVisibility(false); topic.setVisibility(false);
// Save old position ... // Save old position ...
@ -89,11 +95,7 @@ class DragTopicCommand extends Command {
this._position = origPosition; this._position = origPosition;
} }
/** undoExecute(commandContext: CommandContext): void {
* Overrides abstract parent method
* @see {@link mindplot.Command.undoExecute}
*/
undoExecute(commandContext) {
this.execute(commandContext); this.execute(commandContext);
} }
} }

View File

@ -17,20 +17,23 @@
*/ */
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 Topic from '../Topic';
class GenericFunctionCommand extends Command { class GenericFunctionCommand extends Command {
/** private _discardDuplicated: string;
* @classdesc This command handles do/undo of different actions, e.g. moving topics to
* a different position, changing text or font,... (for full reference check the private _value: string | object | boolean | number;
* StandaloneActionDispatcher i.e. the ActionDispatcher subclass in use)
* @constructs private _topicsId: number[];
* @param {Function} commandFunc the function the command shall execute
* @param {String|Array<String>} topicsIds the ids of the topics affected private _commandFunc: (topic: Topic, value: string | object | boolean | number) => string | object | boolean;
* @param {Object} [value] value arbitrary value necessary for the execution of the function,
* e.g. color, font family or text private _oldValues: any[];
* @extends mindplot.Command
*/ private _applied: boolean;
constructor(commandFunc, topicsIds, value) {
constructor(commandFunc: (topic: Topic, value: string | object | boolean) => string | object | boolean, topicsIds: number[], value: string | object | boolean | number = undefined) {
$assert(commandFunc, 'commandFunc must be defined'); $assert(commandFunc, 'commandFunc must be defined');
$assert($defined(topicsIds), 'topicsIds must be defined'); $assert($defined(topicsIds), 'topicsIds must be defined');
@ -39,58 +42,51 @@ class GenericFunctionCommand extends Command {
this._topicsId = topicsIds; this._topicsId = topicsIds;
this._commandFunc = commandFunc; this._commandFunc = commandFunc;
this._oldValues = []; this._oldValues = [];
this.discardDuplicated = undefined;
} }
/** /**
* Overrides abstract parent method * Overrides abstract parent method
*/ */
execute(commandContext) { execute(commandContext: CommandContext) {
if (!this.applied) { if (!this._applied) {
let topics = null; const topics = commandContext.findTopics(this._topicsId);
try {
topics = commandContext.findTopics(this._topicsId);
} catch (e) {
if (this._commandFunc.commandType !== 'changeTextToTopic') {
// Workaround: For some reason, there is a combination of events that involves
// making some modification and firing out of focus event. This is causing
// that a remove node try to be removed.
// In some other life, I will come with the solution. Almost aways occurs with IE9.
// I could be related with some change of order in sets o something similar.
throw e;
}
}
if (topics != null) { if (topics != null) {
const me = this; const me = this;
topics.forEach((topic) => { topics.forEach((topic: Topic) => {
const oldValue = me._commandFunc(topic, me._value); const oldValue = me._commandFunc(topic, me._value);
me._oldValues.push(oldValue); me._oldValues.push(oldValue);
}); });
} }
this.applied = true; this._applied = true;
} else { } else {
throw new Error('Command can not be applied two times in a row.'); throw new Error('Command can not be applied two times in a row.');
} }
} }
/** undoExecute(commandContext: CommandContext): void {
* Overrides abstract parent method if (this._applied) {
* @see {@link mindplot.Command.undoExecute}
*/
undoExecute(commandContext) {
if (this.applied) {
const topics = commandContext.findTopics(this._topicsId); const topics = commandContext.findTopics(this._topicsId);
topics.forEach(((topic, index) => { topics.forEach(((topic: Topic, index: number) => {
this._commandFunc(topic, this._oldValues[index]); this._commandFunc(topic, this._oldValues[index]);
})); }));
this.applied = false; this._applied = false;
this._oldValues = []; this._oldValues = [];
} else { } else {
throw new Error('undo can not be applied.'); throw new Error('undo can not be applied.');
} }
} }
public get disardDuplicated(): string {
return this._discardDuplicated;
}
public set discardDuplicated(value: string) {
this._discardDuplicated = value;
}
} }
export default GenericFunctionCommand; export default GenericFunctionCommand;

View File

@ -17,20 +17,32 @@
*/ */
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert, $defined } from '@wisemapping/core-js';
import Command from '../Command'; import Command from '../Command';
import ControlPoint from '../ControlPoint';
class MoveControlPointCommand extends Command { class MoveControlPointCommand extends Command {
private _ctrlPointControler: ControlPoint;
private _line: any;
private _controlPoint: any;
private _oldControlPoint: any;
private _originalEndPoint: any;
private _wasCustom: any;
private _endPoint: any;
private _point: number;
/** /**
* @classdesc This command handles do/undo of changing the control points of a relationship * @classdesc This command handles do/undo of changing the control points of a relationship
* arrow. These are the two points that appear when the relationship is on focus. They * arrow. These are the two points that appear when the relationship is on focus. They
* influence how the arrow is drawn (not the source or the destination topic nor the arrow * influence how the arrow is drawn (not the source or the destination topic nor the arrow
* direction) * direction)
* @constructs
* @param {ControlPoint} ctrlPointController
* @param {Number} point 0 for the destination control point, 1 for the source control point
* @param ctrlPointController {ControlPoint}
* @param point {Number} 0 for the destination control point, 1 for the source control point
*/ */
constructor(ctrlPointController, point) { constructor(ctrlPointController: ControlPoint, point: number) {
$assert(ctrlPointController, 'line can not be null'); $assert(ctrlPointController, 'line can not be null');
$assert($defined(point), 'point can not be null'); $assert($defined(point), 'point can not be null');

View File

@ -17,17 +17,20 @@
*/ */
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';
class RemoveFeatureFromTopicCommand extends Command { class RemoveFeatureFromTopicCommand extends Command {
private _topicId: number;
private _featureId: number;
private _oldFeature: any;
/** /**
* @classdesc This command handles do/undo of removing a feature from a topic, e.g. an icon or * @classdesc This command handles do/undo of removing a feature from a topic, e.g. an icon or
* a note. For a reference of existing features, refer to {@link mindplot.TopicFeature}. * a note. For a reference of existing features, refer to {@link mindplot.TopicFeature}.
* @constructs
* @param {String} topicId id of the topic to remove the feature from
* @param {String} featureId id of the feature to remove
* @extends mindplot.Command
*/ */
constructor(topicId, featureId) { constructor(topicId: number, featureId: number) {
$assert($defined(topicId), 'topicId can not be null'); $assert($defined(topicId), 'topicId can not be null');
$assert(featureId, 'iconModel can not be null'); $assert(featureId, 'iconModel can not be null');
@ -40,8 +43,8 @@ class RemoveFeatureFromTopicCommand extends Command {
/** /**
* Overrides abstract parent method * Overrides abstract parent method
*/ */
execute(commandContext) { execute(commandContext:CommandContext):void {
const topic = commandContext.findTopics(this._topicId)[0]; const topic = commandContext.findTopics([this._topicId])[0];
const feature = topic.findFeatureById(this._featureId); const feature = topic.findFeatureById(this._featureId);
topic.removeFeature(feature); topic.removeFeature(feature);
this._oldFeature = feature; this._oldFeature = feature;
@ -51,8 +54,8 @@ class RemoveFeatureFromTopicCommand extends Command {
* Overrides abstract parent method * Overrides abstract parent method
* @see {@link mindplot.Command.undoExecute} * @see {@link mindplot.Command.undoExecute}
*/ */
undoExecute(commandContext) { undoExecute(commandContext:CommandContext) {
const topic = commandContext.findTopics(this._topicId)[0]; const topic = commandContext.findTopics([this._topicId])[0];
topic.addFeature(this._oldFeature); topic.addFeature(this._oldFeature);
this._oldFeature = null; this._oldFeature = null;
} }

View File

@ -81,8 +81,7 @@ abstract class IMindmap {
abstract deleteRelationship(relationship: RelationshipModel): void; abstract deleteRelationship(relationship: RelationshipModel): void;
/** */ inspect():string {
inspect() {
let result = ''; let result = '';
result = '{ '; result = '{ ';
@ -103,19 +102,15 @@ abstract class IMindmap {
return result; return result;
} }
/** copyTo(target:IMindmap) {
* @param target const version = this.getVersion();
*/
copyTo(target) {
const source = this;
const version = source.getVersion();
target.setVersion(version); target.setVersion(version);
const desc = this.getDescription(); const desc = this.getDescription();
target.setDescription(desc); target.setDescription(desc);
// Then the rest of the branches ... // Then the rest of the branches ...
const sbranchs = source.getBranches(); const sbranchs = this.getBranches();
sbranchs.forEach((snode) => { sbranchs.forEach((snode) => {
const tnode = target.createNode(snode.getType(), snode.getId()); const tnode = target.createNode(snode.getType(), snode.getId());
snode.copyTo(tnode); snode.copyTo(tnode);

View File

@ -37,6 +37,7 @@ class NodeModel extends INodeModel {
$assert(type, 'Node type can not be null'); $assert(type, 'Node type can not be null');
$assert(mindmap, 'mindmap can not be null'); $assert(mindmap, 'mindmap can not be null');
super(mindmap); super(mindmap);
this._properties = {}; this._properties = {};
this.setId(id); this.setId(id);
this.setType(type); this.setType(type);

View File

@ -15,7 +15,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable import/no-unresolved */
import jquery from 'jquery'; import jquery from 'jquery';
import * as DesignerBuilder from './components/DesignerBuilder'; import * as DesignerBuilder from './components/DesignerBuilder';
import Mindmap from './components/model/Mindmap'; import Mindmap from './components/model/Mindmap';