Migrate web2d to typescript
3
.gitignore
vendored
@ -28,3 +28,6 @@ wisemapping-frontend.code-workspace
|
||||
!.yarn/releases
|
||||
!.yarn/plugins
|
||||
.pnp.*
|
||||
|
||||
packages/**/.yalc/
|
||||
packages/**/yalc.lock
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wisemapping-front-end",
|
||||
"scripts": {
|
||||
"bootstrap": "lerna bootstrap",
|
||||
"bootstrap": "lerna run bootstrap",
|
||||
"build": "lerna run build",
|
||||
"clean": "lerna clean && rm -rf node_modules",
|
||||
"lint": "lerna run lint --stream",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"description": "WiseMapping - Core Common Libraries",
|
||||
"homepage": "http://www.wisemapping.org/",
|
||||
"license": "MIT",
|
||||
"main": "dist/core.js",
|
||||
"main": "src/index.ts",
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
@ -17,6 +17,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.prod.js",
|
||||
"dev": "webpack --mode development --config webpack.dev.js"
|
||||
"dev": "webpack --mode development --config webpack.dev.js",
|
||||
"bootstrap": "yalc publish"
|
||||
}
|
||||
}
|
||||
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright [2015] [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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Cross-browser implementation of creating an XML document object.
|
||||
*/
|
||||
export const createDocument = function () {
|
||||
var doc = null;
|
||||
if ($defined(window.ActiveXObject)) {
|
||||
//http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
|
||||
var progIDs = ['Msxml2.DOMDocument.6.0', 'Msxml2.DOMDocument.3.0'];
|
||||
for (var i = 0; i < progIDs.length; i++) {
|
||||
try {
|
||||
doc = new ActiveXObject(progIDs[i]);
|
||||
break;
|
||||
} catch (ex) {}
|
||||
}
|
||||
} else if (window.document.implementation && window.document.implementation.createDocument) {
|
||||
doc = window.document.implementation.createDocument('', '', null);
|
||||
}
|
||||
$assert(doc, 'Parser could not be instantiated');
|
||||
|
||||
return doc;
|
||||
};
|
||||
|
||||
/*
|
||||
Function: $defined
|
||||
Returns true if the passed in value/object is defined, that means is not null or undefined.
|
||||
|
||||
Arguments:
|
||||
obj - object to inspect
|
||||
*/
|
||||
|
||||
export const $defined = function (obj) {
|
||||
return obj != undefined;
|
||||
};
|
||||
|
||||
export const $assert = function (assert, message) {
|
||||
if (!$defined(assert) || !assert) {
|
||||
logStackTrace();
|
||||
console.log(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
};
|
||||
|
||||
export const sign = function (value) {
|
||||
return value >= 0 ? 1 : -1;
|
||||
};
|
||||
|
||||
export function logStackTrace(exception) {
|
||||
if (!$defined(exception)) {
|
||||
try {
|
||||
throw Error('Unexpected Exception');
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
}
|
||||
var result = '';
|
||||
if (exception.stack) {
|
||||
//Firefox and Chrome...
|
||||
result = exception.stack;
|
||||
} else if (window.opera && exception.message) {
|
||||
//Opera
|
||||
result = exception.message;
|
||||
} else {
|
||||
//IE and Safari
|
||||
result = exception.sourceURL + ': ' + exception.line + '\n\n';
|
||||
|
||||
var currentFunction = arguments.callee.caller;
|
||||
while (currentFunction) {
|
||||
var fn = currentFunction.toString();
|
||||
result = result + '\n' + fn;
|
||||
currentFunction = currentFunction.caller;
|
||||
}
|
||||
}
|
||||
window.errorStack = result;
|
||||
return result;
|
||||
}
|
45
packages/core-js/src/index.ts
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright [2015] [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.
|
||||
*/
|
||||
|
||||
export const createDocument = (): Document => {
|
||||
var doc: Document | null = null;
|
||||
if (window.document.implementation?.createDocument) {
|
||||
doc = window.document.implementation.createDocument('', '', null);
|
||||
}
|
||||
|
||||
if (!doc) {
|
||||
throw new Error('Document could not be initialized');
|
||||
}
|
||||
|
||||
return doc;
|
||||
};
|
||||
|
||||
export const $defined = (obj: any) => {
|
||||
return obj != undefined && obj != null;
|
||||
};
|
||||
|
||||
export const $assert = (assert, message: string): void => {
|
||||
if (!$defined(assert) || !assert) {
|
||||
console.error(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
};
|
||||
|
||||
export const sign = (value: number): 1 | -1 => {
|
||||
return value >= 0 ? 1 : -1;
|
||||
};
|
31
packages/core-js/tsconfig.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/",
|
||||
"sourceMap": true,
|
||||
"module": "amd",
|
||||
"moduleResolution": "node",
|
||||
"target": "es6",
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"strictNullChecks": true,
|
||||
|
||||
"noImplicitAny": false,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"strictFunctionTypes": true,
|
||||
|
||||
"rootDirs": [
|
||||
"src",
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*", "storybook/src/stories",
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
@ -5,15 +5,11 @@ const common = require('../../webpack.common');
|
||||
const prodConfig = {
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'core.js',
|
||||
publicPath: '',
|
||||
filename: 'index.ts',
|
||||
library: {
|
||||
type: 'umd',
|
||||
},
|
||||
},
|
||||
target: 'web',
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = merge(common, prodConfig);
|
||||
|
@ -4,6 +4,11 @@ const common = require('./webpack.common');
|
||||
const prodConfig = {
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
library: {
|
||||
type: 'umd',
|
||||
},
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
|
@ -74,7 +74,7 @@ describe('Topic Shape Suite', () => {
|
||||
.invoke('attr', 'rx')
|
||||
.then(parseInt)
|
||||
.should('be.a', 'number')
|
||||
.should('be.gte', 12);
|
||||
.should('be.gte', 11);
|
||||
cy.get('[test-id=2] > rect')
|
||||
.eq(1)
|
||||
.invoke('attr', 'rx')
|
||||
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 176 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 93 KiB |
@ -3,6 +3,7 @@
|
||||
"version": "0.4.2",
|
||||
"main": "dist/editor.bundle.js",
|
||||
"scripts": {
|
||||
"bootstrap": "yalc publish;yalc add @wisemapping/mindplot",
|
||||
"build": "webpack --config webpack.prod.js",
|
||||
"playground": "webpack serve --config webpack.playground.js",
|
||||
"cy:run": "cypress run",
|
||||
|
@ -11,8 +11,5 @@
|
||||
"@babel/preset-typescript"
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-class-properties"
|
||||
],
|
||||
"sourceType": "module"
|
||||
}
|
@ -10,7 +10,7 @@ module.exports = defineConfig({
|
||||
setupNodeEvents(on, config) {
|
||||
return require('./cypress/plugins/index.js')(on, config)
|
||||
},
|
||||
baseUrl: 'http://localhost:8083',
|
||||
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
|
||||
baseUrl: 'http://localhost:6006',
|
||||
specPattern: 'cypress/e2e/**/*.{js,ts}',
|
||||
},
|
||||
})
|
||||
|
7
packages/mindplot/cypress/e2e/layout.test.js
Normal file
@ -0,0 +1,7 @@
|
||||
context('Layout suite', () => {
|
||||
it('basic layout', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-layout--basic-suite&viewMode=story');
|
||||
cy.wait(2000);
|
||||
cy.matchImageSnapshot('layout-suite');
|
||||
});
|
||||
});
|
@ -1,11 +0,0 @@
|
||||
context('Playground', () => {
|
||||
it('the playground layout page should match its snapshot', () => {
|
||||
// TODO: check why this error is happening, and remove this handling
|
||||
cy.on('uncaught:exception', (err) => {
|
||||
expect(err.message).to.include('Prediction is incorrectly positioned');
|
||||
return false;
|
||||
});
|
||||
cy.visit('/layout.html');
|
||||
cy.matchImageSnapshot('layout');
|
||||
});
|
||||
});
|
36
packages/mindplot/cypress/e2e/topic.test.js
Normal file
@ -0,0 +1,36 @@
|
||||
context('Topic suite', () => {
|
||||
it('topic border', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-topic--border-style&viewMode=story');
|
||||
cy.matchImageSnapshot('topic-border');
|
||||
});
|
||||
|
||||
it('topic style', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-topic--font-style&viewMode=story');
|
||||
cy.matchImageSnapshot('topic-style');
|
||||
});
|
||||
|
||||
it('topic color', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-topic--background-color&viewMode=story');
|
||||
cy.matchImageSnapshot('topic-color');
|
||||
});
|
||||
it('topic note', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-topic--note-feature&viewMode=story');
|
||||
cy.matchImageSnapshot('topic-note');
|
||||
});
|
||||
it('topic link feature', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-topic--link-feature&viewMode=story');
|
||||
cy.matchImageSnapshot('topic-link-feature');
|
||||
});
|
||||
it('topic icon feature', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-topic--icon-feature&viewMode=story');
|
||||
cy.matchImageSnapshot('topic-icon-feature');
|
||||
});
|
||||
it('topic shape line', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-topic--shape-line&viewMode=story');
|
||||
cy.matchImageSnapshot('topic-shape-line');
|
||||
});
|
||||
it('topic ellipse line', () => {
|
||||
cy.visit('/iframe.html?args=&id=mindplot-topic--shape-ellipse&viewMode=story');
|
||||
cy.matchImageSnapshot('topic-shape-ellipse');
|
||||
});
|
||||
});
|
After Width: | Height: | Size: 4.3 MiB |
Before Width: | Height: | Size: 5.1 MiB |
Before Width: | Height: | Size: 3.0 MiB |
Before Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 10 KiB |
@ -16,5 +16,14 @@
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
Cypress.on('window:before:load', (win) => {
|
||||
cy.spy(win.console, 'error');
|
||||
cy.spy(win.console, 'warn');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cy.window().then((win) => {
|
||||
expect(win.console.error).to.have.callCount(0);
|
||||
expect(win.console.warn).to.have.callCount(0);
|
||||
});
|
||||
});
|
||||
|
@ -4,7 +4,8 @@ const config = {
|
||||
preset: 'ts-jest',
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
transform: {
|
||||
'^.+\\.js?$': 'babel-jest',
|
||||
'^.+\\.(ts)?$': 'ts-jest',
|
||||
'^.+\\.(js)$': 'babel-jest',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -10,8 +10,7 @@
|
||||
"main": "src/index.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"assets",
|
||||
"dist"
|
||||
"assets"
|
||||
],
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.yarnpkg.com"
|
||||
@ -21,16 +20,16 @@
|
||||
"url": "git@bitbucket.org:wisemapping/wisemapping-frontend.git"
|
||||
},
|
||||
"scripts": {
|
||||
"bootstrap": "yalc publish;yalc add @wisemapping/core-js;yalc add @wisemapping/web2d",
|
||||
"build": "webpack --config webpack.prod.js",
|
||||
"dev": "webpack serve --config webpack.dev.js",
|
||||
"lint": "eslint src --ext js,ts",
|
||||
"playground": "webpack serve --config webpack.playground.js",
|
||||
"cy:run": "cypress run",
|
||||
"cy:open": "cypress open",
|
||||
"test:unit": "jest ./test/unit/export/*.ts ./test/unit/import/*.ts ./test/unit/layout/*.js --verbose --silent --detectOpenHandles",
|
||||
"test:integration": "start-server-and-test playground http-get://localhost:8083 cy:run",
|
||||
"test:unit": "jest ./test/unit/export/*.ts ./test/unit/import/*.ts --verbose --silent --detectOpenHandles",
|
||||
"test:integration": "start-server-and-test storybook http-get://localhost:6006 cy:run",
|
||||
"test": "yarn test:unit && yarn test:integration",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"storybook": "start-storybook -p 6006 --no-open",
|
||||
"build-storybook": "build-storybook"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -58,6 +57,8 @@
|
||||
"blob-polyfill": "^6.0.20211015",
|
||||
"cypress": "^12.3.0",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"mocha": "^9.1.3"
|
||||
"jest": "^29.4.1",
|
||||
"mocha": "^9.1.3",
|
||||
"start-server-and-test": "^1.15.3"
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { $assert } from '@wisemapping/core-js';
|
||||
import Point from '@wisemapping/web2d';
|
||||
import { Mindmap } from '..';
|
||||
import CommandContext from './CommandContext';
|
||||
import { PivotType } from './RelationshipControlPoints';
|
||||
@ -51,12 +50,12 @@ abstract class ActionDispatcher extends Events {
|
||||
|
||||
abstract dragTopic(
|
||||
topicId: number,
|
||||
position: Point,
|
||||
position: PositionType,
|
||||
order: number | null,
|
||||
parentTopic: Topic | null,
|
||||
): void;
|
||||
|
||||
abstract moveTopic(topicId: number, position: Point): void;
|
||||
abstract moveTopic(topicId: number, position: PositionType): void;
|
||||
|
||||
abstract moveControlPoint(
|
||||
model: RelationshipModel,
|
||||
|
@ -15,12 +15,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { $assert, $defined } from '@wisemapping/core-js';
|
||||
import { Workspace as Workspace2D, ElementClass as Element2D } from '@wisemapping/web2d';
|
||||
import { $assert } from '@wisemapping/core-js';
|
||||
import { Workspace as Workspace2D, ElementClass, ElementPeer } from '@wisemapping/web2d';
|
||||
import ScreenManager from './ScreenManager';
|
||||
import SizeType from './SizeType';
|
||||
import CanvasElement from './CanvasElement';
|
||||
|
||||
class Workspace {
|
||||
class Canvas {
|
||||
private _zoom: number;
|
||||
|
||||
private _screenManager: ScreenManager;
|
||||
@ -35,10 +36,14 @@ class Workspace {
|
||||
|
||||
private _visibleAreaSize!: SizeType;
|
||||
|
||||
private _renderQueue: Element2D[];
|
||||
private _renderQueue: (ElementClass<ElementPeer> | CanvasElement)[];
|
||||
|
||||
private _queueRenderEnabled: boolean;
|
||||
|
||||
private _mouseMoveListener;
|
||||
|
||||
private _mouseUpListener;
|
||||
|
||||
constructor(screenManager: ScreenManager, zoom: number, isReadOnly: boolean) {
|
||||
// Create a suitable container ...
|
||||
$assert(screenManager, 'Div container can not be null');
|
||||
@ -64,6 +69,8 @@ class Workspace {
|
||||
this._renderQueue = [];
|
||||
this._eventsEnabled = false;
|
||||
this._queueRenderEnabled = false;
|
||||
this._mouseMoveListener = null;
|
||||
this._mouseUpListener = null;
|
||||
}
|
||||
|
||||
private _adjustWorkspace(): void {
|
||||
@ -105,7 +112,7 @@ class Workspace {
|
||||
return new Workspace2D(workspaceProfile);
|
||||
}
|
||||
|
||||
append(shape: Element2D): void {
|
||||
append(shape: ElementClass<ElementPeer> | CanvasElement): void {
|
||||
if (this._queueRenderEnabled) {
|
||||
this._renderQueue.push(shape);
|
||||
} else {
|
||||
@ -113,11 +120,12 @@ class Workspace {
|
||||
}
|
||||
}
|
||||
|
||||
private appendInternal(shape: Element2D): void {
|
||||
if (shape.addToWorkspace) {
|
||||
shape.addToWorkspace(this);
|
||||
private appendInternal(shape: CanvasElement | ElementClass<ElementPeer>): void {
|
||||
// eslint-disable-next-line no-prototype-builtins, dot-notation
|
||||
if (typeof shape['addToWorkspace'] === 'function') {
|
||||
(shape as CanvasElement).addToWorkspace(this);
|
||||
} else {
|
||||
this._workspace.append(shape);
|
||||
this._workspace.append(shape as ElementClass<ElementPeer>);
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,7 +135,7 @@ class Workspace {
|
||||
let result = Promise.resolve();
|
||||
if (!value) {
|
||||
// eslint-disable-next-line arrow-body-style
|
||||
result = Workspace.delay(100).then(() => {
|
||||
result = Canvas.delay(100).then(() => {
|
||||
return this.processRenderQueue(this._renderQueue.reverse(), 300);
|
||||
});
|
||||
}
|
||||
@ -138,29 +146,35 @@ class Workspace {
|
||||
return new Promise((resolve) => setTimeout(resolve, t));
|
||||
}
|
||||
|
||||
private processRenderQueue(renderQueue: Element2D[], batch: number): Promise<void> {
|
||||
private processRenderQueue(
|
||||
renderQueue: (ElementClass<ElementPeer> | CanvasElement)[],
|
||||
batch: number,
|
||||
): Promise<void> {
|
||||
let result: Promise<void>;
|
||||
if (renderQueue.length > 0) {
|
||||
result = new Promise((resolve: (queue: Element2D[]) => void) => {
|
||||
for (let i = 0; i < batch && renderQueue.length > 0; i++) {
|
||||
const elem = renderQueue.pop();
|
||||
this.appendInternal(elem);
|
||||
}
|
||||
|
||||
resolve(renderQueue);
|
||||
}).then((queue) => Workspace.delay(30).then(() => this.processRenderQueue(queue, batch)));
|
||||
if (renderQueue.length > 0) {
|
||||
result = new Promise(
|
||||
(resolve: (queue: (ElementClass<ElementPeer> | CanvasElement)[]) => void) => {
|
||||
for (let i = 0; i < batch && renderQueue.length > 0; i++) {
|
||||
const elem = renderQueue.pop()!;
|
||||
this.appendInternal(elem);
|
||||
}
|
||||
|
||||
resolve(renderQueue);
|
||||
},
|
||||
).then((queue) => Canvas.delay(30).then(() => this.processRenderQueue(queue, batch)));
|
||||
} else {
|
||||
result = Promise.resolve();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
removeChild(shape: Element2D): void {
|
||||
// Element is a node, not a web2d element?
|
||||
if (shape.removeFromWorkspace) {
|
||||
shape.removeFromWorkspace(this);
|
||||
removeChild(shape: ElementClass<ElementPeer> | CanvasElement): void {
|
||||
// eslint-disable-next-line dot-notation
|
||||
if (typeof shape['removeFromWorkspace'] === 'function') {
|
||||
(shape as CanvasElement).removeFromWorkspace(this);
|
||||
} else {
|
||||
this._workspace.removeChild(shape);
|
||||
this._workspace.removeChild(shape as ElementClass<ElementPeer>);
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,7 +258,7 @@ class Workspace {
|
||||
return this._eventsEnabled;
|
||||
}
|
||||
|
||||
getSVGElement() {
|
||||
getSVGElement(): Element {
|
||||
return this._workspace.getSVGElement();
|
||||
}
|
||||
|
||||
@ -252,8 +266,8 @@ class Workspace {
|
||||
const workspace = this._workspace;
|
||||
const screenManager = this._screenManager;
|
||||
const mWorkspace = this;
|
||||
const mouseDownListener = function mouseDownListener(event: MouseEvent) {
|
||||
if (!$defined(workspace._mouseMoveListener)) {
|
||||
const mouseDownListener = (event: MouseEvent) => {
|
||||
if (!this._mouseMoveListener) {
|
||||
if (mWorkspace.isWorkspaceEventsEnabled()) {
|
||||
mWorkspace.enableWorkspaceEvents(false);
|
||||
|
||||
@ -261,7 +275,7 @@ class Workspace {
|
||||
const originalCoordOrigin = workspace.getCoordOrigin();
|
||||
|
||||
let wasDragged = false;
|
||||
workspace._mouseMoveListener = (mouseMoveEvent: MouseEvent) => {
|
||||
this._mouseMoveListener = (mouseMoveEvent: MouseEvent) => {
|
||||
const currentMousePosition = screenManager.getWorkspaceMousePosition(mouseMoveEvent);
|
||||
|
||||
const offsetX = currentMousePosition.x - mouseDownPosition.x;
|
||||
@ -284,17 +298,17 @@ class Workspace {
|
||||
screenManager.fireEvent('update');
|
||||
wasDragged = true;
|
||||
};
|
||||
screenManager.addEvent('mousemove', workspace._mouseMoveListener);
|
||||
screenManager.addEvent('touchmove', workspace._mouseMoveListener);
|
||||
screenManager.addEvent('mousemove', this._mouseMoveListener);
|
||||
screenManager.addEvent('touchmove', this._mouseMoveListener);
|
||||
|
||||
// Register mouse up listeners ...
|
||||
workspace._mouseUpListener = () => {
|
||||
screenManager.removeEvent('mousemove', workspace._mouseMoveListener);
|
||||
screenManager.removeEvent('mouseup', workspace._mouseUpListener);
|
||||
screenManager.removeEvent('touchmove', workspace._mouseUpListener);
|
||||
screenManager.removeEvent('touchend', workspace._mouseMoveListener);
|
||||
workspace._mouseUpListener = null;
|
||||
workspace._mouseMoveListener = null;
|
||||
this._mouseUpListener = () => {
|
||||
screenManager.removeEvent('mousemove', this._mouseMoveListener);
|
||||
screenManager.removeEvent('mouseup', this._mouseUpListener);
|
||||
screenManager.removeEvent('touchmove', this._mouseUpListener);
|
||||
screenManager.removeEvent('touchend', this._mouseMoveListener);
|
||||
this._mouseUpListener = null;
|
||||
this._mouseMoveListener = null;
|
||||
window.document.body.style.cursor = 'default';
|
||||
|
||||
// Update screen manager offset.
|
||||
@ -306,11 +320,11 @@ class Workspace {
|
||||
screenManager.fireEvent('click');
|
||||
}
|
||||
};
|
||||
screenManager.addEvent('mouseup', workspace._mouseUpListener);
|
||||
screenManager.addEvent('touchend', workspace._mouseUpListener);
|
||||
screenManager.addEvent('mouseup', this._mouseUpListener);
|
||||
screenManager.addEvent('touchend', this._mouseUpListener);
|
||||
}
|
||||
} else {
|
||||
workspace._mouseUpListener();
|
||||
this._mouseUpListener();
|
||||
}
|
||||
};
|
||||
screenManager.addEvent('mousedown', mouseDownListener);
|
||||
@ -322,4 +336,4 @@ class Workspace {
|
||||
}
|
||||
}
|
||||
|
||||
export default Workspace;
|
||||
export default Canvas;
|
9
packages/mindplot/src/components/CanvasElement.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import Canvas from './Canvas';
|
||||
|
||||
interface CanvasElement {
|
||||
addToWorkspace(workspace: Canvas): void;
|
||||
|
||||
removeFromWorkspace(workspace: Canvas): void;
|
||||
}
|
||||
|
||||
export default CanvasElement;
|
@ -15,18 +15,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Point } from '@wisemapping/web2d';
|
||||
import { $assert } from '@wisemapping/core-js';
|
||||
import PositionType from './PositionType';
|
||||
import Topic from './Topic';
|
||||
import Shape from './util/Shape';
|
||||
|
||||
class CentralTopic extends Topic {
|
||||
_buildDragShape() {
|
||||
buildDragShape() {
|
||||
// Ignore ..
|
||||
}
|
||||
|
||||
_registerEvents(): void {
|
||||
super._registerEvents();
|
||||
registerEvents(): void {
|
||||
super.registerEvents();
|
||||
|
||||
// This disable the drag of the central topic.
|
||||
// But solves the problem of deselecting the nodes when the screen is clicked.
|
||||
@ -35,29 +35,29 @@ class CentralTopic extends Topic {
|
||||
});
|
||||
}
|
||||
|
||||
workoutIncomingConnectionPoint(): Point {
|
||||
workoutIncomingConnectionPoint(): PositionType {
|
||||
return this.getPosition();
|
||||
}
|
||||
|
||||
setCursor(type: string) {
|
||||
setCursor(type: string): void {
|
||||
super.setCursor(type === 'move' ? 'default' : type);
|
||||
}
|
||||
|
||||
updateTopicShape() {
|
||||
updateTopicShape(): void {
|
||||
// Overwite behaviour ...
|
||||
}
|
||||
|
||||
_updatePositionOnChangeSize(): void {
|
||||
// Center main topic ...
|
||||
const zeroPoint = new Point(0, 0);
|
||||
const zeroPoint = { x: 0, y: 0 };
|
||||
this.setPosition(zeroPoint);
|
||||
}
|
||||
|
||||
getShrinkConnector() {
|
||||
getShrinkConnector(): null {
|
||||
return null;
|
||||
}
|
||||
|
||||
workoutOutgoingConnectionPoint(targetPosition: Point) {
|
||||
workoutOutgoingConnectionPoint(targetPosition: PositionType) {
|
||||
$assert(targetPosition, 'targetPoint can not be null');
|
||||
|
||||
const pos = this.getPosition();
|
||||
|
@ -16,11 +16,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { $assert, $defined } from '@wisemapping/core-js';
|
||||
import Point from '@wisemapping/web2d';
|
||||
import { Designer } from '..';
|
||||
import EventBus from './layout/EventBus';
|
||||
import NodeModel from './model/NodeModel';
|
||||
import RelationshipModel from './model/RelationshipModel';
|
||||
import PositionType from './PositionType';
|
||||
import Relationship from './Relationship';
|
||||
import Topic from './Topic';
|
||||
|
||||
@ -102,7 +102,7 @@ class CommandContext {
|
||||
}
|
||||
|
||||
/** */
|
||||
moveTopic(topic: Topic, position: Point): void {
|
||||
moveTopic(topic: Topic, position: PositionType): void {
|
||||
$assert(topic, 'topic cannot be null');
|
||||
$assert(position, 'position cannot be null');
|
||||
EventBus.instance.fireEvent('topicMoved', {
|
||||
|
@ -17,10 +17,11 @@
|
||||
*/
|
||||
|
||||
import { $assert } from '@wisemapping/core-js';
|
||||
import { CurvedLine, PolyLine, Line } from '@wisemapping/web2d';
|
||||
import { CurvedLine, Line, PolyLine } from '@wisemapping/web2d';
|
||||
import PositionType from './PositionType';
|
||||
import Topic from './Topic';
|
||||
import TopicConfig from './TopicConfig';
|
||||
import Workspace from './Workspace';
|
||||
import Canvas from './Canvas';
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
export enum LineType {
|
||||
@ -51,7 +52,7 @@ class ConnectionLine {
|
||||
this._color = this.updateColor();
|
||||
}
|
||||
|
||||
private _getCtrlPoints(sourceNode: Topic, targetNode: Topic) {
|
||||
private _getCtrlPoints(sourceNode: Topic, targetNode: Topic): [PositionType, PositionType] {
|
||||
const srcPos = sourceNode.workoutOutgoingConnectionPoint(targetNode.getPosition());
|
||||
const destPos = targetNode.workoutIncomingConnectionPoint(sourceNode.getPosition());
|
||||
const deltaX = (srcPos.x - destPos.x) / 3;
|
||||
@ -61,8 +62,8 @@ class ConnectionLine {
|
||||
];
|
||||
}
|
||||
|
||||
protected createLine(lineType: LineType): ConnectionLine {
|
||||
let line: ConnectionLine;
|
||||
protected createLine(lineType: LineType): Line {
|
||||
let line: Line;
|
||||
switch (lineType) {
|
||||
case LineType.POLYLINE_MIDDLE:
|
||||
line = new PolyLine();
|
||||
@ -142,8 +143,8 @@ class ConnectionLine {
|
||||
|
||||
if (this._type === LineType.THICK_CURVED || this._type === LineType.THIN_CURVED) {
|
||||
const ctrlPoints = this._getCtrlPoints(this._sourceTopic, this._targetTopic);
|
||||
line2d.setSrcControlPoint(ctrlPoints[0]);
|
||||
line2d.setDestControlPoint(ctrlPoints[1]);
|
||||
(line2d as CurvedLine).setSrcControlPoint(ctrlPoints[0]);
|
||||
(line2d as CurvedLine).setDestControlPoint(ctrlPoints[1]);
|
||||
}
|
||||
|
||||
// Add connector ...
|
||||
@ -179,7 +180,7 @@ class ConnectionLine {
|
||||
}
|
||||
|
||||
setStroke(color: string, style: string, opacity: number) {
|
||||
this._line.setStroke(null, null, color, opacity);
|
||||
this._line.setStroke(1, style, color, opacity);
|
||||
this._color = color;
|
||||
}
|
||||
|
||||
@ -187,13 +188,13 @@ class ConnectionLine {
|
||||
return this._color;
|
||||
}
|
||||
|
||||
addToWorkspace(workspace: Workspace) {
|
||||
workspace.append(this._line);
|
||||
addToWorkspace(workspace: Canvas) {
|
||||
workspace.append(this._line.getElementClass());
|
||||
this._line.moveToBack();
|
||||
}
|
||||
|
||||
removeFromWorkspace(workspace: Workspace) {
|
||||
workspace.removeChild(this._line);
|
||||
removeFromWorkspace(workspace: Canvas) {
|
||||
workspace.removeChild(this._line.getElementClass());
|
||||
}
|
||||
|
||||
getTargetTopic(): Topic {
|
||||
|
@ -18,7 +18,6 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
import { $assert, $defined } from '@wisemapping/core-js';
|
||||
import Point from '@wisemapping/web2d';
|
||||
import Messages, { $msg } from './Messages';
|
||||
|
||||
import Events from './Events';
|
||||
@ -31,7 +30,7 @@ import DesignerModel from './DesignerModel';
|
||||
import DesignerKeyboard from './DesignerKeyboard';
|
||||
|
||||
import ScreenManager from './ScreenManager';
|
||||
import Workspace from './Workspace';
|
||||
import Canvas from './Canvas';
|
||||
|
||||
import DragConnector from './DragConnector';
|
||||
import DragManager from './DragManager';
|
||||
@ -60,6 +59,7 @@ import { TopicShapeType } from './model/INodeModel';
|
||||
import { LineType } from './ConnectionLine';
|
||||
import XMLSerializerFactory from './persistence/XMLSerializerFactory';
|
||||
import ImageExpoterFactory from './export/ImageExporterFactory';
|
||||
import PositionType from './PositionType';
|
||||
|
||||
class Designer extends Events {
|
||||
private _mindmap: Mindmap | null;
|
||||
@ -70,7 +70,7 @@ class Designer extends Events {
|
||||
|
||||
private _model: DesignerModel;
|
||||
|
||||
private _workspace: Workspace;
|
||||
private _workspace: Canvas;
|
||||
|
||||
_eventBussDispatcher: EventBusDispatcher;
|
||||
|
||||
@ -108,7 +108,7 @@ class Designer extends Events {
|
||||
|
||||
// Init Screen manager..
|
||||
const screenManager = new ScreenManager(divElem);
|
||||
this._workspace = new Workspace(screenManager, this._model.getZoom(), this.isReadOnly());
|
||||
this._workspace = new Canvas(screenManager, this._model.getZoom(), this.isReadOnly());
|
||||
|
||||
// Init layout manager ...
|
||||
this._eventBussDispatcher = new EventBusDispatcher();
|
||||
@ -200,7 +200,7 @@ class Designer extends Events {
|
||||
});
|
||||
}
|
||||
|
||||
private _buildDragManager(workspace: Workspace): DragManager {
|
||||
private _buildDragManager(workspace: Canvas): DragManager {
|
||||
const designerModel = this.getModel();
|
||||
const dragConnector = new DragConnector(designerModel, this._workspace);
|
||||
const dragManager = new DragManager(workspace, this._eventBussDispatcher);
|
||||
@ -504,7 +504,7 @@ class Designer extends Events {
|
||||
this._actionDispatcher.addTopics([childModel], [parentTopicId]);
|
||||
}
|
||||
|
||||
private _createChildModel(topic: Topic, mousePos: Point = null): NodeModel {
|
||||
private _createChildModel(topic: Topic, mousePos?: PositionType): NodeModel {
|
||||
// Create a new node ...
|
||||
const parentModel = topic.getModel();
|
||||
const mindmap = parentModel.getMindmap();
|
||||
@ -517,7 +517,7 @@ class Designer extends Events {
|
||||
|
||||
// Create a new node ...
|
||||
const layoutManager = this._eventBussDispatcher.getLayoutManager();
|
||||
const result = layoutManager.predict(topic.getId(), null, mousePos);
|
||||
const result = layoutManager.predict(topic.getId(), null, mousePos || null);
|
||||
childModel.setOrder(result.order);
|
||||
|
||||
const { position } = result;
|
||||
@ -949,7 +949,7 @@ class Designer extends Events {
|
||||
this.onObjectFocusEvent(node);
|
||||
}
|
||||
|
||||
getWorkSpace(): Workspace {
|
||||
getWorkSpace(): Canvas {
|
||||
return this._workspace;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import Keyboard from './Keyboard';
|
||||
import { Designer } from '..';
|
||||
import Topic from './Topic';
|
||||
|
||||
import initHotKeyPluggin from '../../../../libraries/jquery.hotkeys';
|
||||
import initHotKeyPluggin from '../../libraries/jquery.hotkeys';
|
||||
|
||||
// Provides dispatcher of keyevents by key...
|
||||
initHotKeyPluggin($);
|
||||
@ -262,7 +262,7 @@ class DesignerKeyboard extends Keyboard {
|
||||
const children = node.getChildren();
|
||||
if (children.length > 0) {
|
||||
let target = children[0];
|
||||
let top = null;
|
||||
let top: number | null = null;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i];
|
||||
const childY = child.getPosition().y;
|
||||
|
@ -16,19 +16,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { $assert } from '@wisemapping/core-js';
|
||||
import { Point } from '@wisemapping/web2d';
|
||||
import DesignerModel from './DesignerModel';
|
||||
import DragTopic from './DragTopic';
|
||||
import SizeType from './SizeType';
|
||||
import Topic from './Topic';
|
||||
import Workspace from './Workspace';
|
||||
import Canvas from './Canvas';
|
||||
import PositionType from './PositionType';
|
||||
|
||||
class DragConnector {
|
||||
private _designerModel: DesignerModel;
|
||||
|
||||
private _workspace: Workspace;
|
||||
private _workspace: Canvas;
|
||||
|
||||
constructor(designerModel: DesignerModel, workspace: Workspace) {
|
||||
constructor(designerModel: DesignerModel, workspace: Canvas) {
|
||||
$assert(designerModel, 'designerModel can not be null');
|
||||
$assert(workspace, 'workspace can not be null');
|
||||
|
||||
@ -114,7 +114,7 @@ class DragConnector {
|
||||
private _proximityWeight(
|
||||
isAligned: boolean,
|
||||
target: Topic,
|
||||
sPos: Point,
|
||||
sPos: PositionType,
|
||||
currentConnection: Topic,
|
||||
): number {
|
||||
const tPos = target.getPosition();
|
||||
@ -128,8 +128,8 @@ class DragConnector {
|
||||
|
||||
private _isVerticallyAligned(
|
||||
targetSize: SizeType,
|
||||
targetPosition: Point,
|
||||
sourcePosition: Point,
|
||||
targetPosition: PositionType,
|
||||
sourcePosition: PositionType,
|
||||
): boolean {
|
||||
return Math.abs(sourcePosition.y - targetPosition.y) < targetSize.height / 2;
|
||||
}
|
||||
|
@ -19,10 +19,10 @@ import { $assert } from '@wisemapping/core-js';
|
||||
import DragTopic from './DragTopic';
|
||||
import EventBusDispatcher from './layout/EventBusDispatcher';
|
||||
import Topic from './Topic';
|
||||
import Workspace from './Workspace';
|
||||
import Canvas from './Canvas';
|
||||
|
||||
class DragManager {
|
||||
private _workspace: Workspace;
|
||||
private _workspace: Canvas;
|
||||
|
||||
private _isDragInProcess: boolean;
|
||||
|
||||
@ -34,7 +34,7 @@ class DragManager {
|
||||
|
||||
private _mouseUpListener;
|
||||
|
||||
constructor(workspace: Workspace, eventDispatcher: EventBusDispatcher) {
|
||||
constructor(workspace: Canvas, eventDispatcher: EventBusDispatcher) {
|
||||
this._workspace = workspace;
|
||||
this._listeners = {};
|
||||
this._isDragInProcess = false;
|
||||
@ -81,7 +81,7 @@ class DragManager {
|
||||
}
|
||||
|
||||
protected buildMouseMoveListener(
|
||||
workspace: Workspace,
|
||||
workspace: Canvas,
|
||||
dragNode: DragTopic,
|
||||
dragManager: DragManager,
|
||||
): (event: MouseEvent) => void {
|
||||
@ -115,7 +115,7 @@ class DragManager {
|
||||
}
|
||||
|
||||
protected _buildMouseUpListener(
|
||||
workspace: Workspace,
|
||||
workspace: Canvas,
|
||||
dragNode: DragTopic,
|
||||
dragManager: DragManager,
|
||||
) {
|
||||
|
@ -22,9 +22,10 @@ import PositionType from './PositionType';
|
||||
import SizeType from './SizeType';
|
||||
import Topic from './Topic';
|
||||
import Shape from './util/Shape';
|
||||
import Workspace from './Workspace';
|
||||
import Canvas from './Canvas';
|
||||
import CanvasElement from './CanvasElement';
|
||||
|
||||
class DragPivot {
|
||||
class DragPivot implements CanvasElement {
|
||||
private _position: PositionType;
|
||||
|
||||
private _isVisible: boolean;
|
||||
@ -95,7 +96,7 @@ class DragPivot {
|
||||
// Update Line position.
|
||||
const isAtRight = Shape.isAtRight(targetPosition, position);
|
||||
const pivotPoint = Shape.calculateRectConnectionPoint(position, size, isAtRight);
|
||||
line.setFrom(pivotPoint.x, pivotPoint.y);
|
||||
line?.setFrom(pivotPoint.x, pivotPoint.y);
|
||||
|
||||
// Update rect position
|
||||
const cx = position.x - size.width / 2;
|
||||
@ -105,7 +106,7 @@ class DragPivot {
|
||||
// Make line visible only when the position has been already changed.
|
||||
// This solve several strange effects ;)
|
||||
const targetPoint = targetTopic!.workoutIncomingConnectionPoint(pivotPoint);
|
||||
line.setTo(targetPoint.x, targetPoint.y);
|
||||
line?.setTo(targetPoint.x, targetPoint.y);
|
||||
}
|
||||
|
||||
setPosition(point: Point): void {
|
||||
@ -113,7 +114,7 @@ class DragPivot {
|
||||
this._redrawLine();
|
||||
}
|
||||
|
||||
getPosition(): Point {
|
||||
getPosition(): PositionType {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
@ -157,8 +158,8 @@ class DragPivot {
|
||||
}
|
||||
|
||||
// If the node is connected, validate that there is a line connecting both...
|
||||
_getConnectionLine(): CurvedLine {
|
||||
let result = null;
|
||||
_getConnectionLine(): CurvedLine | null {
|
||||
let result: CurvedLine | null = null;
|
||||
const parentTopic = this._targetTopic;
|
||||
if (parentTopic) {
|
||||
if (parentTopic.getType() === 'CentralTopic') {
|
||||
@ -170,7 +171,7 @@ class DragPivot {
|
||||
return result;
|
||||
}
|
||||
|
||||
addToWorkspace(workspace: Workspace) {
|
||||
addToWorkspace(workspace: Canvas) {
|
||||
const pivotRect = this._getPivotRect();
|
||||
workspace.append(pivotRect);
|
||||
|
||||
@ -196,7 +197,7 @@ class DragPivot {
|
||||
connectRect.moveToBack();
|
||||
}
|
||||
|
||||
removeFromWorkspace(workspace: Workspace) {
|
||||
removeFromWorkspace(workspace: Canvas) {
|
||||
const shape = this._getPivotRect();
|
||||
workspace.removeChild(shape);
|
||||
|
||||
@ -212,7 +213,7 @@ class DragPivot {
|
||||
}
|
||||
}
|
||||
|
||||
connectTo(targetTopic: Topic, position: Point) {
|
||||
connectTo(targetTopic: Topic, position: PositionType) {
|
||||
$assert(position, 'position can not be null');
|
||||
$assert(targetTopic, 'parent can not be null');
|
||||
|
||||
@ -242,7 +243,7 @@ class DragPivot {
|
||||
this._redrawLine();
|
||||
}
|
||||
|
||||
disconnect(workspace: Workspace): void {
|
||||
disconnect(workspace: Canvas): void {
|
||||
$assert(workspace, 'workspace can not be null.');
|
||||
$assert(this._targetTopic, 'There are not connected topic.');
|
||||
|
||||
|
@ -16,17 +16,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { $assert } from '@wisemapping/core-js';
|
||||
import { Point, ElementClass } from '@wisemapping/web2d';
|
||||
import { ElementClass, ElementPeer, Group } from '@wisemapping/web2d';
|
||||
|
||||
import ActionDispatcher from './ActionDispatcher';
|
||||
import DragPivot from './DragPivot';
|
||||
import LayoutManager from './layout/LayoutManager';
|
||||
import NodeGraph from './NodeGraph';
|
||||
import PositionType from './PositionType';
|
||||
import Topic from './Topic';
|
||||
import Workspace from './Workspace';
|
||||
import Canvas from './Canvas';
|
||||
import CanvasElement from './CanvasElement';
|
||||
|
||||
class DragTopic {
|
||||
private _elem2d: ElementClass;
|
||||
private _elem2d: Group;
|
||||
|
||||
private _order: number | null;
|
||||
|
||||
@ -34,23 +36,19 @@ class DragTopic {
|
||||
|
||||
private _layoutManager: LayoutManager;
|
||||
|
||||
private _position: Point;
|
||||
private _position: PositionType;
|
||||
|
||||
private _isInWorkspace: boolean;
|
||||
|
||||
static _dragPivot: DragPivot = new DragPivot();
|
||||
|
||||
constructor(dragShape: ElementClass, draggedNode: NodeGraph, layoutManger: LayoutManager) {
|
||||
$assert(dragShape, 'Rect can not be null.');
|
||||
$assert(draggedNode, 'draggedNode can not be null.');
|
||||
$assert(layoutManger, 'layoutManger can not be null.');
|
||||
|
||||
constructor(dragShape: Group, draggedNode: NodeGraph, layoutManger: LayoutManager) {
|
||||
this._elem2d = dragShape;
|
||||
this._order = null;
|
||||
this._draggedNode = draggedNode;
|
||||
this._layoutManager = layoutManger;
|
||||
this._isInWorkspace = false;
|
||||
this._position = new Point(0, 0);
|
||||
this._position = { x: 0, y: 0 };
|
||||
}
|
||||
|
||||
setOrder(order: number): void {
|
||||
@ -97,11 +95,11 @@ class DragTopic {
|
||||
return dragPivot.isVisible();
|
||||
}
|
||||
|
||||
getInnerShape(): ElementClass {
|
||||
getInnerShape(): ElementClass<ElementPeer> {
|
||||
return this._elem2d;
|
||||
}
|
||||
|
||||
disconnect(workspace: Workspace) {
|
||||
disconnect(workspace: Canvas) {
|
||||
// Clear connection line ...
|
||||
const dragPivot = this._getDragPivot();
|
||||
dragPivot.disconnect(workspace);
|
||||
@ -128,7 +126,7 @@ class DragTopic {
|
||||
return this._draggedNode as Topic;
|
||||
}
|
||||
|
||||
removeFromWorkspace(workspace: Workspace) {
|
||||
removeFromWorkspace(workspace: Canvas) {
|
||||
if (this._isInWorkspace) {
|
||||
// Remove drag shadow.
|
||||
workspace.removeChild(this._elem2d);
|
||||
@ -146,7 +144,7 @@ class DragTopic {
|
||||
return this._isInWorkspace;
|
||||
}
|
||||
|
||||
addToWorkspace(workspace: Workspace) {
|
||||
addToWorkspace(workspace: Canvas) {
|
||||
if (!this._isInWorkspace) {
|
||||
workspace.append(this._elem2d);
|
||||
const dragPivot = this._getDragPivot();
|
||||
@ -159,7 +157,7 @@ class DragTopic {
|
||||
return DragTopic._dragPivot;
|
||||
}
|
||||
|
||||
getPosition(): Point {
|
||||
getPosition(): PositionType {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
@ -167,7 +165,7 @@ class DragTopic {
|
||||
return true;
|
||||
}
|
||||
|
||||
applyChanges(workspace: Workspace) {
|
||||
applyChanges(workspace: Canvas) {
|
||||
$assert(workspace, 'workspace can not be null');
|
||||
|
||||
const actionDispatcher = ActionDispatcher.getInstance();
|
||||
@ -205,9 +203,9 @@ class DragTopic {
|
||||
return false;
|
||||
}
|
||||
|
||||
static init(workspace: Workspace) {
|
||||
static init(workspace: Canvas) {
|
||||
$assert(workspace, 'workspace can not be null');
|
||||
const pivot = DragTopic._dragPivot;
|
||||
const pivot: CanvasElement = DragTopic._dragPivot;
|
||||
workspace.append(pivot);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Text, Group, ElementClass, Point } from '@wisemapping/web2d';
|
||||
import { Text, Group } from '@wisemapping/web2d';
|
||||
|
||||
import Icon from './Icon';
|
||||
import IconGroup from './IconGroup';
|
||||
@ -23,11 +23,12 @@ import SvgIconModel from './model/SvgIconModel';
|
||||
import SizeType from './SizeType';
|
||||
import Topic from './Topic';
|
||||
import ActionDispatcher from './ActionDispatcher';
|
||||
import PositionType from './PositionType';
|
||||
|
||||
class EmojiCharIcon implements Icon {
|
||||
private element: ElementClass;
|
||||
private _group: Group;
|
||||
|
||||
private _group: IconGroup | null;
|
||||
private _iconGroup: IconGroup | null;
|
||||
|
||||
private _iconModel: SvgIconModel;
|
||||
|
||||
@ -37,48 +38,48 @@ class EmojiCharIcon implements Icon {
|
||||
this._iconModel = iconModel;
|
||||
this._topic = topic;
|
||||
|
||||
this.element = new Group({
|
||||
width: 90,
|
||||
height: 90,
|
||||
this._group = new Group({
|
||||
width: 70,
|
||||
height: 70,
|
||||
x: 0,
|
||||
y: 0,
|
||||
coordSizeWidth: 15,
|
||||
coordSizeHeight: 15,
|
||||
coordOriginY: 2,
|
||||
coordOriginY: 0,
|
||||
});
|
||||
const iconText = new Text();
|
||||
iconText.setText(iconModel.getIconType());
|
||||
this.element.append(iconText);
|
||||
this._group.append(iconText);
|
||||
|
||||
// Add events ...
|
||||
if (!readOnly) {
|
||||
this.element.setCursor('pointer');
|
||||
this._group.setCursor('pointer');
|
||||
}
|
||||
this._group = null;
|
||||
this._iconGroup = null;
|
||||
}
|
||||
|
||||
getElement(): ElementClass {
|
||||
return this.element;
|
||||
getElement(): Group {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
setGroup(group: IconGroup) {
|
||||
this._group = group;
|
||||
this._iconGroup = group;
|
||||
}
|
||||
|
||||
getGroup(): IconGroup {
|
||||
return this._group!;
|
||||
return this._iconGroup!;
|
||||
}
|
||||
|
||||
getSize(): SizeType {
|
||||
return this._group!.getSize();
|
||||
return this._iconGroup!.getSize();
|
||||
}
|
||||
|
||||
getPosition(): Point {
|
||||
return this._group!.getPosition();
|
||||
getPosition(): PositionType {
|
||||
return this._iconGroup!.getPosition();
|
||||
}
|
||||
|
||||
addEvent(type: string, fnc: (e: object) => void): void {
|
||||
this.element.addEvent(type, fnc);
|
||||
this._group.addEvent(type, fnc);
|
||||
}
|
||||
|
||||
remove() {
|
||||
|
@ -1,18 +1,36 @@
|
||||
import { Point, ElementClass, Group } from '@wisemapping/web2d';
|
||||
/*
|
||||
* 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 { Group, Image } from '@wisemapping/web2d';
|
||||
import IconGroup from './IconGroup';
|
||||
import FeatureModel from './model/FeatureModel';
|
||||
import PositionType from './PositionType';
|
||||
import SizeType from './SizeType';
|
||||
|
||||
interface Icon {
|
||||
getElement(): ElementClass;
|
||||
getElement(): Group | Image;
|
||||
|
||||
setGroup(group: IconGroup): Group;
|
||||
setGroup(group: IconGroup): void;
|
||||
|
||||
getGroup(): IconGroup | null;
|
||||
|
||||
getSize(): SizeType;
|
||||
getSize(): SizeType | undefined;
|
||||
|
||||
getPosition(): Point;
|
||||
getPosition(): PositionType;
|
||||
|
||||
addEvent(type: string, fnc: () => void): void;
|
||||
|
||||
|
@ -16,13 +16,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { $assert, $defined } from '@wisemapping/core-js';
|
||||
import { Group, ElementClass, Point } from '@wisemapping/web2d';
|
||||
import { $assert } from '@wisemapping/core-js';
|
||||
import { Group } from '@wisemapping/web2d';
|
||||
import IconGroupRemoveTip from './IconGroupRemoveTip';
|
||||
import ImageIcon from './ImageIcon';
|
||||
import SizeType from './SizeType';
|
||||
import FeatureModel from './model/FeatureModel';
|
||||
import Icon from './Icon';
|
||||
import PositionType from './PositionType';
|
||||
|
||||
const ORDER_BY_TYPE = new Map<string, number>();
|
||||
ORDER_BY_TYPE.set('icon', 0);
|
||||
@ -61,14 +62,10 @@ class IconGroup {
|
||||
this._group.setPosition(x, y);
|
||||
}
|
||||
|
||||
getPosition(): Point {
|
||||
getPosition(): PositionType {
|
||||
return this._group.getPosition();
|
||||
}
|
||||
|
||||
getNativeElement(): ElementClass {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
/** */
|
||||
getSize(): SizeType {
|
||||
return this._group.getSize();
|
||||
@ -84,8 +81,6 @@ class IconGroup {
|
||||
}
|
||||
|
||||
addIcon(icon: Icon, remove: boolean): void {
|
||||
$defined(icon, 'icon is not defined');
|
||||
|
||||
// Order could have change, need to re-add all.
|
||||
const icons = this._icons.slice();
|
||||
this._icons.forEach((i) => {
|
||||
@ -102,7 +97,7 @@ class IconGroup {
|
||||
// Add all the nodes back ...
|
||||
this._resize(this._icons.length);
|
||||
this._icons.forEach((i, index) => {
|
||||
this._positionIcon(i, index);
|
||||
this.positionIcon(i, index);
|
||||
const imageShape = i.getElement();
|
||||
this._group.append(imageShape);
|
||||
});
|
||||
@ -132,14 +127,14 @@ class IconGroup {
|
||||
}
|
||||
|
||||
/** */
|
||||
removeIconByModel(featureModel: FeatureModel) {
|
||||
removeIconByModel(featureModel: FeatureModel): void {
|
||||
$assert(featureModel, 'featureModel can not be null');
|
||||
|
||||
const icon = this._findIconFromModel(featureModel);
|
||||
this._removeIcon(icon);
|
||||
}
|
||||
|
||||
private _removeIcon(icon: Icon) {
|
||||
private _removeIcon(icon: Icon): void {
|
||||
this._removeTip.close(0);
|
||||
this._group.removeChild(icon.getElement());
|
||||
|
||||
@ -149,7 +144,7 @@ class IconGroup {
|
||||
|
||||
// Add all again ...
|
||||
this._icons.forEach((elem, i) => {
|
||||
me._positionIcon(elem, i);
|
||||
me.positionIcon(elem, i);
|
||||
});
|
||||
}
|
||||
|
||||
@ -169,7 +164,7 @@ class IconGroup {
|
||||
});
|
||||
}
|
||||
|
||||
private _resize(iconsLength: number) {
|
||||
private _resize(iconsLength: number): void {
|
||||
if (this._iconSize) {
|
||||
this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height);
|
||||
|
||||
@ -178,14 +173,19 @@ class IconGroup {
|
||||
}
|
||||
}
|
||||
|
||||
private _positionIcon(icon: Icon, order: number) {
|
||||
private positionIcon(icon: Icon, order: number): void {
|
||||
const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2;
|
||||
icon
|
||||
.getElement()
|
||||
.setPosition(iconSize * order + IconGroup.ICON_PADDING, IconGroup.ICON_PADDING);
|
||||
}
|
||||
|
||||
static ICON_PADDING = 5;
|
||||
appendTo(group: Group): void {
|
||||
group.append(this._group);
|
||||
this._group.moveToFront();
|
||||
}
|
||||
|
||||
static ICON_PADDING = 2;
|
||||
}
|
||||
|
||||
export default IconGroup;
|
||||
|
@ -7,7 +7,7 @@ class IconGroupRemoveTip {
|
||||
|
||||
private _activeIcon: ImageIcon | null;
|
||||
|
||||
private _widget: Group;
|
||||
private _widget: Group | null;
|
||||
|
||||
private _closeTimeoutId;
|
||||
|
||||
@ -15,6 +15,7 @@ class IconGroupRemoveTip {
|
||||
$assert(group, 'group can not be null');
|
||||
this._group = group;
|
||||
this._activeIcon = null;
|
||||
this._widget = null;
|
||||
}
|
||||
|
||||
show(topicId: number, icon: ImageIcon) {
|
||||
@ -71,7 +72,9 @@ class IconGroupRemoveTip {
|
||||
|
||||
const close = () => {
|
||||
this._activeIcon = null;
|
||||
this._group.removeChild(widget);
|
||||
if (widget) {
|
||||
this._group.removeChild(widget);
|
||||
}
|
||||
this._widget = null;
|
||||
this._closeTimeoutId = null;
|
||||
};
|
||||
|
@ -16,11 +16,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { $assert } from '@wisemapping/core-js';
|
||||
import { Image, Point, ElementClass } from '@wisemapping/web2d';
|
||||
import { Group, Image } from '@wisemapping/web2d';
|
||||
import IconGroup from './IconGroup';
|
||||
import SizeType from './SizeType';
|
||||
import FeatureModel from './model/FeatureModel';
|
||||
import Icon from './Icon';
|
||||
import PositionType from './PositionType';
|
||||
|
||||
abstract class ImageIcon implements Icon {
|
||||
private _image: Image;
|
||||
@ -35,11 +36,11 @@ abstract class ImageIcon implements Icon {
|
||||
this._group = null;
|
||||
}
|
||||
|
||||
getElement(): ElementClass {
|
||||
getElement(): Image | Group {
|
||||
return this._image;
|
||||
}
|
||||
|
||||
setGroup(group: IconGroup) {
|
||||
setGroup(group: IconGroup): void {
|
||||
this._group = group;
|
||||
}
|
||||
|
||||
@ -47,11 +48,11 @@ abstract class ImageIcon implements Icon {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
getSize(): SizeType {
|
||||
getSize(): SizeType | undefined {
|
||||
return this._image.getSize();
|
||||
}
|
||||
|
||||
getPosition(): Point {
|
||||
getPosition(): PositionType {
|
||||
return this._image.getPosition();
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import $ from 'jquery';
|
||||
import initHotKeyPluggin from '../../../../libraries/jquery.hotkeys';
|
||||
import initHotKeyPluggin from '../../libraries/jquery.hotkeys';
|
||||
|
||||
// Provides dispatcher of keyevents by key...
|
||||
initHotKeyPluggin($);
|
||||
|
@ -16,12 +16,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { $assert, $defined } from '@wisemapping/core-js';
|
||||
import { Point, Group, ElementClass } from '@wisemapping/web2d';
|
||||
import { Group, ElementClass, ElementPeer } from '@wisemapping/web2d';
|
||||
|
||||
import Topic from './Topic';
|
||||
import Shape from './util/Shape';
|
||||
import NodeModel from './model/NodeModel';
|
||||
import Workspace from './Workspace';
|
||||
import Canvas from './Canvas';
|
||||
import SizeType from './SizeType';
|
||||
import PositionType from './PositionType';
|
||||
import { NodeOption } from './NodeGraph';
|
||||
@ -34,7 +34,7 @@ class MainTopic extends Topic {
|
||||
this.INNER_RECT_ATTRIBUTES = { stroke: '0.5 solid #009900' };
|
||||
}
|
||||
|
||||
_buildDragShape(): ElementClass {
|
||||
buildDragShape(): ElementClass<ElementPeer> {
|
||||
const innerShape = this._buildShape(this.INNER_RECT_ATTRIBUTES, this.getShapeType());
|
||||
const size = this.getSize();
|
||||
innerShape.setSize(size.width, size.height);
|
||||
@ -82,9 +82,8 @@ class MainTopic extends Topic {
|
||||
}
|
||||
}
|
||||
|
||||
disconnect(workspace: Workspace) {
|
||||
disconnect(workspace: Canvas) {
|
||||
super.disconnect(workspace);
|
||||
this.redrawShapeType();
|
||||
|
||||
const innerShape = this.getInnerShape();
|
||||
innerShape.setVisibility(true);
|
||||
@ -113,7 +112,7 @@ class MainTopic extends Topic {
|
||||
const isAtRight = Shape.isAtRight(targetPosition, pos);
|
||||
const size = this.getSize();
|
||||
|
||||
let result: Point = { x: 0, y: 0 };
|
||||
let result: PositionType = { x: 0, y: 0 };
|
||||
if (this.getShapeType() === 'line') {
|
||||
const groupPosition = this.get2DElement().getPosition();
|
||||
const innerShareSize = this.getInnerShape().getSize();
|
||||
|