├── .gitignore
├── demo
├── index.less
├── index.html
├── index.jsx
├── shape-config
│ ├── card-shape.js
│ └── image-shape.js
├── my-editor.less
├── toolbar.less
├── sidebar.less
└── my-editor.jsx
├── src
└── index.js
├── resources
├── js
│ ├── index.txt
│ ├── io
│ │ ├── mxGraphCodec.js
│ │ ├── mxTerminalChangeCodec.js
│ │ ├── mxDefaultPopupMenuCodec.js
│ │ ├── mxRootChangeCodec.js
│ │ ├── mxModelCodec.js
│ │ ├── mxGenericChangeCodec.js
│ │ ├── mxDefaultKeyHandlerCodec.js
│ │ ├── mxCodecRegistry.js
│ │ ├── mxChildChangeCodec.js
│ │ └── mxCellCodec.js
│ ├── util
│ │ ├── mxImage.js
│ │ ├── mxPoint.js
│ │ ├── mxObjectIdentity.js
│ │ ├── mxAnimation.js
│ │ ├── mxEventObject.js
│ │ ├── mxDictionary.js
│ │ ├── mxUrlConverter.js
│ │ ├── mxImageBundle.js
│ │ ├── mxDivResizer.js
│ │ ├── mxRectangle.js
│ │ ├── mxImageExport.js
│ │ ├── mxEventSource.js
│ │ ├── mxForm.js
│ │ ├── mxEffects.js
│ │ ├── mxAutoSaveManager.js
│ │ ├── mxUndoableEdit.js
│ │ └── mxMouseEvent.js
│ ├── shape
│ │ ├── mxTriangle.js
│ │ ├── mxHexagon.js
│ │ ├── mxStencilRegistry.js
│ │ ├── mxLine.js
│ │ ├── mxEllipse.js
│ │ ├── mxRhombus.js
│ │ ├── mxCloud.js
│ │ ├── mxActor.js
│ │ ├── mxPolyline.js
│ │ ├── mxCylinder.js
│ │ ├── mxDoubleEllipse.js
│ │ ├── mxRectangleShape.js
│ │ ├── mxArrow.js
│ │ └── mxConnector.js
│ ├── layout
│ │ ├── hierarchical
│ │ │ ├── stage
│ │ │ │ ├── mxHierarchicalLayoutStage.js
│ │ │ │ ├── mxSwimlaneOrdering.js
│ │ │ │ └── mxMinimumCycleRemover.js
│ │ │ └── model
│ │ │ │ ├── mxGraphHierarchyEdge.js
│ │ │ │ └── mxGraphAbstractHierarchyCell.js
│ │ ├── mxCompositeLayout.js
│ │ ├── mxEdgeLabelLayout.js
│ │ └── mxCircleLayout.js
│ ├── view
│ │ ├── mxConnectionConstraint.js
│ │ ├── mxStyleRegistry.js
│ │ ├── mxTemporaryCellStates.js
│ │ └── mxCellStatePreview.js
│ ├── handler
│ │ └── mxCellTracker.js
│ ├── model
│ │ └── mxCellPath.js
│ └── editor
│ │ └── mxDefaultKeyHandler.js
├── images
│ ├── close.gif
│ ├── error.gif
│ ├── point.gif
│ ├── button.gif
│ ├── resize.gif
│ ├── submenu.gif
│ ├── warning.gif
│ ├── warning.png
│ ├── window.gif
│ ├── collapsed.gif
│ ├── expanded.gif
│ ├── maximize.gif
│ ├── minimize.gif
│ ├── normalize.gif
│ ├── separator.gif
│ ├── transparent.gif
│ └── window-title.gif
└── css
│ ├── explorer.css
│ └── common.css
├── config
├── card-shape.js
├── stencils
│ ├── index.js
│ ├── others.xml
│ └── general.xml
├── image-shape.js
└── general-shape.js
├── .babelrc
├── lib
└── index.js
├── .vscode
├── launch.json
└── settings.json
├── gulpfile.js
├── LICENSE
├── .eslintrc
├── webpack.config.js
├── package.json
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/demo/index.less:
--------------------------------------------------------------------------------
1 |
2 | .mxgraph-editor-container{
3 |
4 | }
5 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Editor from './editor';
2 |
3 | export default Editor;
4 |
--------------------------------------------------------------------------------
/resources/js/index.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/js/index.txt
--------------------------------------------------------------------------------
/resources/images/close.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/close.gif
--------------------------------------------------------------------------------
/resources/images/error.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/error.gif
--------------------------------------------------------------------------------
/resources/images/point.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/point.gif
--------------------------------------------------------------------------------
/resources/images/button.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/button.gif
--------------------------------------------------------------------------------
/resources/images/resize.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/resize.gif
--------------------------------------------------------------------------------
/resources/images/submenu.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/submenu.gif
--------------------------------------------------------------------------------
/resources/images/warning.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/warning.gif
--------------------------------------------------------------------------------
/resources/images/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/warning.png
--------------------------------------------------------------------------------
/resources/images/window.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/window.gif
--------------------------------------------------------------------------------
/resources/images/collapsed.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/collapsed.gif
--------------------------------------------------------------------------------
/resources/images/expanded.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/expanded.gif
--------------------------------------------------------------------------------
/resources/images/maximize.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/maximize.gif
--------------------------------------------------------------------------------
/resources/images/minimize.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/minimize.gif
--------------------------------------------------------------------------------
/resources/images/normalize.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/normalize.gif
--------------------------------------------------------------------------------
/resources/images/separator.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/separator.gif
--------------------------------------------------------------------------------
/resources/images/transparent.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/transparent.gif
--------------------------------------------------------------------------------
/resources/images/window-title.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/korbinzhao/mxgraph-editor/HEAD/resources/images/window-title.gif
--------------------------------------------------------------------------------
/config/card-shape.js:
--------------------------------------------------------------------------------
1 | export default [{
2 | name: 'primary equipment',
3 | key: 'zhushebei',
4 | logo: 'https://img.alicdn.com/tfs/TB1eD9LdgHqK1RjSZJnXXbNLpXa-144-128.png',
5 | width: 100,
6 | height: 80
7 | }];
8 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | mxgraph-editor demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "env", "react", "stage-0"
4 | ],
5 | "plugins": [
6 | ["import", {
7 | "libraryName": "antd",
8 | "libraryDirectory": "es",
9 | "style": "css"
10 | }]
11 | ]
12 |
13 | }
--------------------------------------------------------------------------------
/demo/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import MyEditor from './my-editor';
4 | import './index.less';
5 |
6 | const App = () => (
7 |
8 |
9 |
10 | );
11 |
12 |
13 | ReactDOM.render(, document.getElementById('app'));
14 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _editor = require('./editor');
8 |
9 | var _editor2 = _interopRequireDefault(_editor);
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 |
13 | exports.default = _editor2.default;
--------------------------------------------------------------------------------
/config/stencils/index.js:
--------------------------------------------------------------------------------
1 | import BASIC from './basic.xml';
2 | import BPMN from './bpmn.xml';
3 | import ARROWS from './arrows.xml';
4 | import FLOWCHART from './flowchart.xml';
5 | import OTHERS from './others.xml';
6 | import GENERAL from './general.xml';
7 |
8 | export default {
9 | BASIC,
10 | BPMN,
11 | ARROWS,
12 | FLOWCHART,
13 | OTHERS,
14 | GENERAL,
15 | };
16 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // 使用 IntelliSense 了解相关属性。
3 | // 悬停以查看现有属性的描述。
4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 |
8 | {
9 | "type": "node",
10 | "request": "launch",
11 | "name": "启动程序",
12 | "program": "${workspaceFolder}/nozomi/test/skeleton-test"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/config/image-shape.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | name: 'industry',
4 | key: 'gongye1',
5 | logo: 'https://img.alicdn.com/tfs/TB1NzGpt9rqK1RjSZK9XXXyypXa-80-80.svg',
6 | width: 80,
7 | height: 80
8 | },
9 | {
10 | name: 'can',
11 | key: 'youtong',
12 | logo: 'https://img.alicdn.com/tfs/TB188qwt3HqK1RjSZFgXXa7JXXa-80-80.svg',
13 | width: 80,
14 | height: 80
15 | }
16 | ];
17 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.tabSize": 2,
3 | "editor.formatOnPaste": false,
4 | "eslint.enable": true,
5 | "eslint.autoFixOnSave": true,
6 | "eslint.validate": [
7 | "javascript",
8 | "javascriptreact"
9 | ],
10 | "sasslint.enable": true,
11 | "emmet.includeLanguages": {
12 | "javascript": "javascriptreact"
13 | },
14 | "emmet.triggerExpansionOnTab": true,
15 | "editor.snippetSuggestions": "top",
16 | "git.ignoreLimitWarning": true,
17 | "files.associations": {
18 | "*.js": "javascriptreact"
19 | },
20 | }
--------------------------------------------------------------------------------
/resources/css/explorer.css:
--------------------------------------------------------------------------------
1 | div.mxTooltip {
2 | filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4,
3 | Color='#A2A2A2', Positive='true');
4 | }
5 | div.mxPopupMenu {
6 | filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4,
7 | Color='#C0C0C0', Positive='true');
8 | }
9 | div.mxWindow {
10 | _filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4,
11 | Color='#C0C0C0', Positive='true');
12 | }
13 | td.mxWindowTitle {
14 | _height: 23px;
15 | }
16 | .mxDisabled {
17 | filter:alpha(opacity=20) !important;
18 | }
19 |
--------------------------------------------------------------------------------
/demo/shape-config/card-shape.js:
--------------------------------------------------------------------------------
1 | export default [{
2 | name: 'primary equipment',
3 | key: 'zhushebei',
4 | logo: 'https://img.alicdn.com/tfs/TB1eD9LdgHqK1RjSZJnXXbNLpXa-144-128.png',
5 | width: 100,
6 | height: 80
7 | }, {
8 | name: 'auxiliary equipment',
9 | key: 'fujiashebei',
10 | logo: 'https://img.alicdn.com/tfs/TB1ejUeiAPoK1RjSZKbXXX1IXXa-36-32.png',
11 | width: 100,
12 | height: 80
13 | }, {
14 | name: 'product element',
15 | key: 'chanchuwu',
16 | logo: 'https://img.alicdn.com/tfs/TB1ht.aisbpK1RjSZFyXXX_qFXa-32-32.png',
17 | width: 100,
18 | height: 80
19 | }];
20 |
--------------------------------------------------------------------------------
/demo/my-editor.less:
--------------------------------------------------------------------------------
1 | a {
2 | color: #333;
3 | text-decoration: none;
4 |
5 | &:hover {
6 | color: #333;
7 | }
8 | }
9 |
10 | .editor-container {
11 | position: relative;
12 | width: 100%;
13 | height: 100%;
14 |
15 | .graph-inner-container {
16 | position: relative;
17 | width: 100%;
18 | height: 100%;
19 | overflow: scroll;
20 | }
21 |
22 | .graph-content {
23 | flex: 1;
24 | background-image: url('https://img.alicdn.com/tfs/TB1ZP2zj9zqK1RjSZPcXXbTepXa-150-150.png');
25 | align-items: center;
26 | justify-content: center;
27 | width: 100%;
28 | height: calc(100% - 40px);
29 | overflow: hidden;
30 |
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/resources/js/io/mxGraphCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | mxCodecRegistry.register(function()
6 | {
7 | /**
8 | * Class: mxGraphCodec
9 | *
10 | * Codec for s. This class is created and registered
11 | * dynamically at load time and used implicitely via
12 | * and the .
13 | *
14 | * Transient Fields:
15 | *
16 | * - graphListeners
17 | * - eventListeners
18 | * - view
19 | * - container
20 | * - cellRenderer
21 | * - editor
22 | * - selection
23 | */
24 | return new mxObjectCodec(new mxGraph(),
25 | ['graphListeners', 'eventListeners', 'view', 'container',
26 | 'cellRenderer', 'editor', 'selection']);
27 |
28 | }());
29 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const gulp = require('gulp');
2 | const less = require('gulp-less');
3 | const postcss = require('gulp-postcss');
4 | const sourcemaps = require('gulp-sourcemaps');
5 | const autoprefixer = require('autoprefixer');
6 | const replace = require('gulp-replace');
7 |
8 | gulp.task('less', () => gulp.src('src/*.less')
9 | .pipe(less())
10 | .pipe(gulp.dest('lib')));
11 |
12 | gulp.task('autoprefixer', () => gulp.src('src/*.css')
13 | .pipe(sourcemaps.init())
14 | .pipe(postcss([autoprefixer()]))
15 | .pipe(sourcemaps.write('.'))
16 | .pipe(gulp.dest('./lib')));
17 |
18 | gulp.task('replace', () => {
19 | gulp.src('lib/*.js')
20 | .pipe(replace(/\/(.+)\.less/, '/$1.css'))
21 | .pipe(replace(/\/(.+)\.styl/, '/$1.css'))
22 | .pipe(gulp.dest('lib'));
23 | });
24 |
25 | gulp.task('default', ['less', 'autoprefixer', 'replace']);
26 |
--------------------------------------------------------------------------------
/resources/js/util/mxImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxImage
7 | *
8 | * Encapsulates the URL, width and height of an image.
9 | *
10 | * Constructor: mxImage
11 | *
12 | * Constructs a new image.
13 | */
14 | function mxImage(src, width, height) {
15 | this.src = src;
16 | this.width = width;
17 | this.height = height;
18 | }
19 |
20 | /**
21 | * Variable: src
22 | *
23 | * String that specifies the URL of the image.
24 | */
25 | mxImage.prototype.src = null;
26 |
27 | /**
28 | * Variable: width
29 | *
30 | * Integer that specifies the width of the image.
31 | */
32 | mxImage.prototype.width = null;
33 |
34 | /**
35 | * Variable: height
36 | *
37 | * Integer that specifies the height of the image.
38 | */
39 | mxImage.prototype.height = null;
40 |
41 | window.mxImage = mxImage;
42 |
--------------------------------------------------------------------------------
/resources/js/shape/mxTriangle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxTriangle
7 | *
8 | * Implementation of the triangle shape.
9 | *
10 | * Constructor: mxTriangle
11 | *
12 | * Constructs a new triangle shape.
13 | */
14 | function mxTriangle()
15 | {
16 | mxActor.call(this);
17 | };
18 |
19 | /**
20 | * Extends mxActor.
21 | */
22 | mxUtils.extend(mxTriangle, mxActor);
23 |
24 | /**
25 | * Function: redrawPath
26 | *
27 | * Draws the path for this shape.
28 | */
29 | mxTriangle.prototype.redrawPath = function(c, x, y, w, h)
30 | {
31 | var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
32 | this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0.5 * h), new mxPoint(0, h)], this.isRounded, arcSize, true);
33 | };
34 |
35 | window.mxTriangle = mxTriangle;
36 |
--------------------------------------------------------------------------------
/resources/js/layout/hierarchical/stage/mxHierarchicalLayoutStage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxHierarchicalLayoutStage
7 | *
8 | * The specific layout interface for hierarchical layouts. It adds a
9 | * run method with a parameter for the hierarchical layout model
10 | * that is shared between the layout stages.
11 | *
12 | * Constructor: mxHierarchicalLayoutStage
13 | *
14 | * Constructs a new hierarchical layout stage.
15 | */
16 | function mxHierarchicalLayoutStage() { };
17 |
18 | /**
19 | * Function: execute
20 | *
21 | * Takes the graph detail and configuration information within the facade
22 | * and creates the resulting laid out graph within that facade for further
23 | * use.
24 | */
25 | mxHierarchicalLayoutStage.prototype.execute = function(parent) { };
26 |
27 | window.mxHierarchicalLayoutStage = mxHierarchicalLayoutStage;
28 |
--------------------------------------------------------------------------------
/resources/js/shape/mxHexagon.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxHexagon
7 | *
8 | * Implementation of the hexagon shape.
9 | *
10 | * Constructor: mxHexagon
11 | *
12 | * Constructs a new hexagon shape.
13 | */
14 | function mxHexagon()
15 | {
16 | mxActor.call(this);
17 | };
18 |
19 | /**
20 | * Extends mxActor.
21 | */
22 | mxUtils.extend(mxHexagon, mxActor);
23 |
24 | /**
25 | * Function: redrawPath
26 | *
27 | * Draws the path for this shape.
28 | */
29 | mxHexagon.prototype.redrawPath = function(c, x, y, w, h)
30 | {
31 | var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
32 | this.addPoints(c, [new mxPoint(0.25 * w, 0), new mxPoint(0.75 * w, 0), new mxPoint(w, 0.5 * h), new mxPoint(0.75 * w, h),
33 | new mxPoint(0.25 * w, h), new mxPoint(0, 0.5 * h)], this.isRounded, arcSize, true);
34 | };
35 |
36 | window.mxHexagon = mxHexagon;
37 |
--------------------------------------------------------------------------------
/resources/js/io/mxTerminalChangeCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | mxCodecRegistry.register(function()
6 | {
7 | /**
8 | * Class: mxTerminalChangeCodec
9 | *
10 | * Codec for s. This class is created and registered
11 | * dynamically at load time and used implicitely via and
12 | * the .
13 | *
14 | * Transient Fields:
15 | *
16 | * - model
17 | * - previous
18 | *
19 | * Reference Fields:
20 | *
21 | * - cell
22 | * - terminal
23 | */
24 | var codec = new mxObjectCodec(new mxTerminalChange(),
25 | ['model', 'previous'], ['cell', 'terminal']);
26 |
27 | /**
28 | * Function: afterDecode
29 | *
30 | * Restores the state by assigning the previous value.
31 | */
32 | codec.afterDecode = function(dec, node, obj)
33 | {
34 | obj.previous = obj.terminal;
35 |
36 | return obj;
37 | };
38 |
39 | // Returns the codec into the registry
40 | return codec;
41 |
42 | }());
43 |
--------------------------------------------------------------------------------
/config/stencils/others.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT LICENSE
2 |
3 | Copyright (c) 2015-present Ant UED, https://xtech.antfin.com/
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/demo/shape-config/image-shape.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | name: 'industry',
4 | key: 'gongye1',
5 | logo: 'https://img.alicdn.com/tfs/TB1NzGpt9rqK1RjSZK9XXXyypXa-80-80.svg',
6 | width: 80,
7 | height: 80
8 | },
9 | {
10 | name: 'can',
11 | key: 'youtong',
12 | logo: 'https://img.alicdn.com/tfs/TB188qwt3HqK1RjSZFgXXa7JXXa-80-80.svg',
13 | width: 80,
14 | height: 80
15 | },
16 | {
17 | name: 'mechanical arm',
18 | key: 'jixiebi',
19 | logo: 'https://img.alicdn.com/tfs/TB1bGiAtZfpK1RjSZFOXXa6nFXa-80-80.svg',
20 | width: 80,
21 | height: 80
22 | },
23 | {
24 | name: 'plug',
25 | key: 'chatou',
26 | logo: 'https://img.alicdn.com/tfs/TB1oNqtt6TpK1RjSZKPXXa3UpXa-80-80.svg',
27 | width: 80,
28 | height: 80
29 | },
30 | {
31 | name: 'factory',
32 | key: 'gongchang',
33 | logo: 'https://img.alicdn.com/tfs/TB1_natt3DqK1RjSZSyXXaxEVXa-80-80.svg',
34 | width: 80,
35 | height: 80
36 | },
37 | {
38 | name: 'boiler',
39 | key: 'guolu',
40 | logo: 'https://img.alicdn.com/tfs/TB1gU1tt3DqK1RjSZSyXXaxEVXa-80-80.svg',
41 | width: 80,
42 | height: 80
43 | }
44 |
45 | ];
46 |
--------------------------------------------------------------------------------
/demo/toolbar.less:
--------------------------------------------------------------------------------
1 | .toolbar {
2 | // position: fixed;
3 | padding: 4px 20px 4px 10px;
4 | background-color: #fff;
5 | width: 100%;
6 | height: 40px;
7 | display: flex;
8 | border-bottom: 1px solid #E4E8EA;
9 | color: #666;
10 | font-size: 12px;
11 |
12 | .toolbar-btn {
13 | font-size: 12px;
14 | border: none;
15 | box-shadow: none;
16 | height: 32px;
17 | min-width: 75px;
18 | padding: 4px 10px;
19 | box-sizing: border-box;
20 | cursor: pointer;
21 | display: flex;
22 | justify-content: center;
23 | align-items: center;
24 | -webkit-touch-callout: none;
25 | -webkit-user-select: none;
26 | -khtml-user-select: none;
27 | -moz-user-select: none;
28 | -ms-user-select: none;
29 | user-select: none;
30 |
31 | &.active {
32 | background-color: #fff;
33 | border: 1px solid #DEE0EA;
34 | border-radius: 5px;
35 | color: #666666;
36 | }
37 |
38 | &:hover {
39 | background-color: #fff;
40 | border: 1px solid #DEE0EA;
41 | border-radius: 5px;
42 | color: #666666;
43 | }
44 | }
45 |
46 | .icon {
47 | margin-right: 8px;
48 | font-size: 18px;
49 | width: 18px;
50 | height: 18px;
51 | }
52 | }
--------------------------------------------------------------------------------
/config/stencils/general.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/resources/js/util/mxPoint.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxPoint
7 | *
8 | * Implements a 2-dimensional vector with double precision coordinates.
9 | *
10 | * Constructor: mxPoint
11 | *
12 | * Constructs a new point for the optional x and y coordinates. If no
13 | * coordinates are given, then the default values for and are used.
14 | */
15 | function mxPoint(x, y)
16 | {
17 | this.x = (x != null) ? x : 0;
18 | this.y = (y != null) ? y : 0;
19 | };
20 |
21 | /**
22 | * Variable: x
23 | *
24 | * Holds the x-coordinate of the point. Default is 0.
25 | */
26 | mxPoint.prototype.x = null;
27 |
28 | /**
29 | * Variable: y
30 | *
31 | * Holds the y-coordinate of the point. Default is 0.
32 | */
33 | mxPoint.prototype.y = null;
34 |
35 | /**
36 | * Function: equals
37 | *
38 | * Returns true if the given object equals this point.
39 | */
40 | mxPoint.prototype.equals = function(obj)
41 | {
42 | return obj != null && obj.x == this.x && obj.y == this.y;
43 | };
44 |
45 | /**
46 | * Function: clone
47 | *
48 | * Returns a clone of this .
49 | */
50 | mxPoint.prototype.clone = function()
51 | {
52 | // Handles subclasses as well
53 | return mxUtils.clone(this);
54 | };
55 |
56 | window.mxPoint = mxPoint;
--------------------------------------------------------------------------------
/resources/js/shape/mxStencilRegistry.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | *
5 | * Code to add stencils.
6 | *
7 | * (code)
8 | * var req = mxUtils.load('test/stencils.xml');
9 | * var root = req.getDocumentElement();
10 | * var shape = root.firstChild;
11 | *
12 | * while (shape != null)
13 | * {
14 | * if (shape.nodeType == mxConstants.NODETYPE_ELEMENT)
15 | * {
16 | * mxStencilRegistry.addStencil(shape.getAttribute('name'), new mxStencil(shape));
17 | * }
18 | *
19 | * shape = shape.nextSibling;
20 | * }
21 | * (end)
22 | */
23 | var mxStencilRegistry =
24 | {
25 | /**
26 | * Class: mxStencilRegistry
27 | *
28 | * A singleton class that provides a registry for stencils and the methods
29 | * for painting those stencils onto a canvas or into a DOM.
30 | */
31 | stencils: {},
32 |
33 | /**
34 | * Function: addStencil
35 | *
36 | * Adds the given .
37 | */
38 | addStencil: function(name, stencil)
39 | {
40 | mxStencilRegistry.stencils[name] = stencil;
41 | },
42 |
43 | /**
44 | * Function: getStencil
45 | *
46 | * Returns the for the given name.
47 | */
48 | getStencil: function(name)
49 | {
50 | return mxStencilRegistry.stencils[name];
51 | }
52 |
53 | };
54 |
55 | window.mxStencilRegistry = mxStencilRegistry;
56 |
--------------------------------------------------------------------------------
/resources/js/shape/mxLine.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxLine
7 | *
8 | * Extends to implement a horizontal line shape.
9 | * This shape is registered under in
10 | * .
11 | *
12 | * Constructor: mxLine
13 | *
14 | * Constructs a new line shape.
15 | *
16 | * Parameters:
17 | *
18 | * bounds - that defines the bounds. This is stored in
19 | * .
20 | * stroke - String that defines the stroke color. Default is 'black'. This is
21 | * stored in .
22 | * strokewidth - Optional integer that defines the stroke width. Default is
23 | * 1. This is stored in .
24 | */
25 | function mxLine(bounds, stroke, strokewidth)
26 | {
27 | mxShape.call(this);
28 | this.bounds = bounds;
29 | this.stroke = stroke;
30 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
31 | };
32 |
33 | /**
34 | * Extends mxShape.
35 | */
36 | mxUtils.extend(mxLine, mxShape);
37 |
38 | /**
39 | * Function: paintVertexShape
40 | *
41 | * Redirects to redrawPath for subclasses to work.
42 | */
43 | mxLine.prototype.paintVertexShape = function(c, x, y, w, h)
44 | {
45 | var mid = y + h / 2;
46 |
47 | c.begin();
48 | c.moveTo(x, mid);
49 | c.lineTo(x + w, mid);
50 | c.stroke();
51 | };
52 |
53 | window.mxLine = mxLine;
54 |
--------------------------------------------------------------------------------
/resources/js/shape/mxEllipse.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxEllipse
7 | *
8 | * Extends to implement an ellipse shape.
9 | * This shape is registered under
10 | * in .
11 | *
12 | * Constructor: mxEllipse
13 | *
14 | * Constructs a new ellipse shape.
15 | *
16 | * Parameters:
17 | *
18 | * bounds - that defines the bounds. This is stored in
19 | * .
20 | * fill - String that defines the fill color. This is stored in .
21 | * stroke - String that defines the stroke color. This is stored in .
22 | * strokewidth - Optional integer that defines the stroke width. Default is
23 | * 1. This is stored in .
24 | */
25 | function mxEllipse(bounds, fill, stroke, strokewidth)
26 | {
27 | mxShape.call(this);
28 | this.bounds = bounds;
29 | this.fill = fill;
30 | this.stroke = stroke;
31 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
32 | };
33 |
34 | /**
35 | * Extends mxShape.
36 | */
37 | mxUtils.extend(mxEllipse, mxShape);
38 |
39 | /**
40 | * Function: paintVertexShape
41 | *
42 | * Paints the ellipse shape.
43 | */
44 | mxEllipse.prototype.paintVertexShape = function(c, x, y, w, h)
45 | {
46 | c.ellipse(x, y, w, h);
47 | c.fillAndStroke();
48 | };
49 |
50 | window.mxEllipse = mxEllipse;
51 |
--------------------------------------------------------------------------------
/resources/js/io/mxDefaultPopupMenuCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | mxCodecRegistry.register(function()
6 | {
7 | /**
8 | * Class: mxDefaultPopupMenuCodec
9 | *
10 | * Custom codec for configuring s. This class is created
11 | * and registered dynamically at load time and used implicitely via
12 | * and the . This codec only reads configuration
13 | * data for existing popup menus, it does not encode or create menus. Note
14 | * that this codec only passes the configuration node to the popup menu,
15 | * which uses the config to dynamically create menus. See
16 | * .
17 | */
18 | var codec = new mxObjectCodec(new mxDefaultPopupMenu());
19 |
20 | /**
21 | * Function: encode
22 | *
23 | * Returns null.
24 | */
25 | codec.encode = function(enc, obj)
26 | {
27 | return null;
28 | };
29 |
30 | /**
31 | * Function: decode
32 | *
33 | * Uses the given node as the config for .
34 | */
35 | codec.decode = function(dec, node, into)
36 | {
37 | var inc = node.getElementsByTagName('include')[0];
38 |
39 | if (inc != null)
40 | {
41 | this.processInclude(dec, inc, into);
42 | }
43 | else if (into != null)
44 | {
45 | into.config = node;
46 | }
47 |
48 | return into;
49 | };
50 |
51 | // Returns the codec into the registry
52 | return codec;
53 |
54 | }());
55 |
--------------------------------------------------------------------------------
/resources/js/view/mxConnectionConstraint.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxConnectionConstraint
7 | *
8 | * Defines an object that contains the constraints about how to connect one
9 | * side of an edge to its terminal.
10 | *
11 | * Constructor: mxConnectionConstraint
12 | *
13 | * Constructs a new connection constraint for the given point and boolean
14 | * arguments.
15 | *
16 | * Parameters:
17 | *
18 | * point - Optional that specifies the fixed location of the point
19 | * in relative coordinates. Default is null.
20 | * perimeter - Optional boolean that specifies if the fixed point should be
21 | * projected onto the perimeter of the terminal. Default is true.
22 | */
23 | function mxConnectionConstraint(point, perimeter, name)
24 | {
25 | this.point = point;
26 | this.perimeter = (perimeter != null) ? perimeter : true;
27 | this.name = name;
28 | };
29 |
30 | /**
31 | * Variable: point
32 | *
33 | * that specifies the fixed location of the connection point.
34 | */
35 | mxConnectionConstraint.prototype.point = null;
36 |
37 | /**
38 | * Variable: perimeter
39 | *
40 | * Boolean that specifies if the point should be projected onto the perimeter
41 | * of the terminal.
42 | */
43 | mxConnectionConstraint.prototype.perimeter = null;
44 |
45 | /**
46 | * Variable: name
47 | *
48 | * Optional string that specifies the name of the constraint.
49 | */
50 | mxConnectionConstraint.prototype.name = null;
51 |
52 | window.mxConnectionConstraint = mxConnectionConstraint;
--------------------------------------------------------------------------------
/resources/js/shape/mxRhombus.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxRhombus
7 | *
8 | * Extends to implement a rhombus (aka diamond) shape.
9 | * This shape is registered under
10 | * in .
11 | *
12 | * Constructor: mxRhombus
13 | *
14 | * Constructs a new rhombus shape.
15 | *
16 | * Parameters:
17 | *
18 | * bounds - that defines the bounds. This is stored in
19 | * .
20 | * fill - String that defines the fill color. This is stored in .
21 | * stroke - String that defines the stroke color. This is stored in .
22 | * strokewidth - Optional integer that defines the stroke width. Default is
23 | * 1. This is stored in .
24 | */
25 | function mxRhombus(bounds, fill, stroke, strokewidth)
26 | {
27 | mxShape.call(this);
28 | this.bounds = bounds;
29 | this.fill = fill;
30 | this.stroke = stroke;
31 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
32 | };
33 |
34 | /**
35 | * Extends mxShape.
36 | */
37 | mxUtils.extend(mxRhombus, mxShape);
38 |
39 | /**
40 | * Function: paintVertexShape
41 | *
42 | * Generic painting implementation.
43 | */
44 | mxRhombus.prototype.paintVertexShape = function(c, x, y, w, h)
45 | {
46 | var hw = w / 2;
47 | var hh = h / 2;
48 |
49 | var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
50 | c.begin();
51 | this.addPoints(c, [new mxPoint(x + hw, y), new mxPoint(x + w, y + hh), new mxPoint(x + hw, y + h),
52 | new mxPoint(x, y + hh)], this.isRounded, arcSize, true);
53 | c.fillAndStroke();
54 | };
55 |
56 | window.mxRhombus = mxRhombus;
57 |
--------------------------------------------------------------------------------
/resources/js/shape/mxCloud.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxCloud
7 | *
8 | * Extends to implement a cloud shape.
9 | *
10 | * This shape is registered under in
11 | * .
12 | *
13 | * Constructor: mxCloud
14 | *
15 | * Constructs a new cloud shape.
16 | *
17 | * Parameters:
18 | *
19 | * bounds - that defines the bounds. This is stored in
20 | * .
21 | * fill - String that defines the fill color. This is stored in .
22 | * stroke - String that defines the stroke color. This is stored in .
23 | * strokewidth - Optional integer that defines the stroke width. Default is
24 | * 1. This is stored in .
25 | */
26 | function mxCloud(bounds, fill, stroke, strokewidth)
27 | {
28 | mxActor.call(this);
29 | this.bounds = bounds;
30 | this.fill = fill;
31 | this.stroke = stroke;
32 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
33 | };
34 |
35 | /**
36 | * Extends mxActor.
37 | */
38 | mxUtils.extend(mxCloud, mxActor);
39 |
40 | /**
41 | * Function: redrawPath
42 | *
43 | * Draws the path for this shape.
44 | */
45 | mxCloud.prototype.redrawPath = function(c, x, y, w, h)
46 | {
47 | c.moveTo(0.25 * w, 0.25 * h);
48 | c.curveTo(0.05 * w, 0.25 * h, 0, 0.5 * h, 0.16 * w, 0.55 * h);
49 | c.curveTo(0, 0.66 * h, 0.18 * w, 0.9 * h, 0.31 * w, 0.8 * h);
50 | c.curveTo(0.4 * w, h, 0.7 * w, h, 0.8 * w, 0.8 * h);
51 | c.curveTo(w, 0.8 * h, w, 0.6 * h, 0.875 * w, 0.5 * h);
52 | c.curveTo(w, 0.3 * h, 0.8 * w, 0.1 * h, 0.625 * w, 0.2 * h);
53 | c.curveTo(0.5 * w, 0.05 * h, 0.3 * w, 0.05 * h, 0.25 * w, 0.25 * h);
54 | c.close();
55 | };
56 |
57 | window.mxCloud = mxCloud;
58 |
--------------------------------------------------------------------------------
/resources/js/util/mxObjectIdentity.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | var mxObjectIdentity =
6 | {
7 | /**
8 | * Class: mxObjectIdentity
9 | *
10 | * Identity for JavaScript objects and functions. This is implemented using
11 | * a simple incrementing counter which is stored in each object under
12 | * .
13 | *
14 | * The identity for an object does not change during its lifecycle.
15 | *
16 | * Variable: FIELD_NAME
17 | *
18 | * Name of the field to be used to store the object ID. Default is
19 | * mxObjectId.
20 | */
21 | FIELD_NAME: 'mxObjectId',
22 |
23 | /**
24 | * Variable: counter
25 | *
26 | * Current counter.
27 | */
28 | counter: 0,
29 |
30 | /**
31 | * Function: get
32 | *
33 | * Returns the ID for the given object or function or null if no object
34 | * is specified.
35 | */
36 | get: function(obj)
37 | {
38 | if (obj != null)
39 | {
40 | if (obj[mxObjectIdentity.FIELD_NAME] == null)
41 | {
42 | if (typeof obj === 'object')
43 | {
44 | var ctor = mxUtils.getFunctionName(obj.constructor);
45 | obj[mxObjectIdentity.FIELD_NAME] = ctor + '#' + mxObjectIdentity.counter++;
46 | }
47 | else if (typeof obj === 'function')
48 | {
49 | obj[mxObjectIdentity.FIELD_NAME] = 'Function#' + mxObjectIdentity.counter++;
50 | }
51 | }
52 |
53 | return obj[mxObjectIdentity.FIELD_NAME];
54 | }
55 |
56 | return null;
57 | },
58 |
59 | /**
60 | * Function: clear
61 | *
62 | * Deletes the ID from the given object or function.
63 | */
64 | clear: function(obj)
65 | {
66 | if (typeof(obj) === 'object' || typeof obj === 'function')
67 | {
68 | delete obj[mxObjectIdentity.FIELD_NAME];
69 | }
70 | }
71 |
72 | };
73 |
74 | window.mxObjectIdentity = mxObjectIdentity;
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": "airbnb",
4 | "plugins": [
5 | "react",
6 | "jsx-a11y",
7 | "import"
8 | ],
9 | "rules": {
10 | "react/jsx-filename-extension": [2, {
11 | "extensions": [".js", ".jsx"]
12 | }],
13 | "react/forbid-prop-types": 0,
14 | "no-unused-expressions": 0,
15 | "func-names": 0,
16 | "class-methods-use-this": 0,
17 | "destructuring": false,
18 | "no-param-reassign": [1, { "props": false } ],
19 | "linebreak-style": 0,
20 | "react/sort-comp": [1, {
21 | "order": [
22 | "static-methods",
23 | "lifecycle",
24 | "everything-else",
25 | "/^on.+$/",
26 | "render"
27 | ]
28 | }],
29 | "max-len": 0,
30 | "jsx-a11y/click-events-have-key-events": 0,
31 | "jsx-a11y/no-static-element-interactions": 0,
32 | "import/no-unresolved": 0,
33 | "react/jsx-one-expression-per-line": 0,
34 | "react/jsx-closing-tag-location": 0,
35 | "no-nested-ternary": 0,
36 | "array-callback-return": 0,
37 | "consistent-return": 0,
38 | "react/no-array-index-key": 0,
39 | "camelcase": 0,
40 | "no-underscore-dangle": 0,
41 | "no-trailing-spaces": 0,
42 | "comma-dangle": 0,
43 | "no-tabs": 0,
44 | "import/extensions": 0,
45 | "prefer-rest-params": 0,
46 | "react/no-multi-comp": 0,
47 | "react/prop-types": 0,
48 | "jsx-a11y/no-noninteractive-element-interactions": 0,
49 | "jsx-a11y/no-noninteractive-tabindex": 0,
50 | "no-script-url": 0,
51 | "jsx-a11y/anchor-is-valid": 0
52 | },
53 | "settings": {
54 | "import/resolver": {}
55 | },
56 | "globals": {
57 | "document": true,
58 | "window": true
59 | },
60 | "env": {
61 | "es6": true,
62 | "node": true,
63 | "jest": true
64 | },
65 | "ecmaFeatures": {
66 | "destructuring": false
67 | }
68 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebPackPlugin = require('html-webpack-plugin');
2 | const postcssImport = require('postcss-import');
3 | const postcssCssnext = require('postcss-cssnext');
4 | const cssnano = require('cssnano');
5 |
6 | module.exports = {
7 | resolve: {
8 | extensions: ['.js', '.jsx', '.json']
9 | },
10 | entry: {
11 | demo: './demo/index.jsx',
12 | index: './src/index.js'
13 | },
14 | module: {
15 | rules: [{
16 | test: /\.js$|\.jsx$/,
17 | exclude: /node_modules/,
18 | use: {
19 | loader: 'babel-loader'
20 | }
21 | },
22 | {
23 | test: /\.html$/,
24 | use: [{
25 | loader: 'html-loader',
26 | options: {
27 | minimize: true
28 | }
29 | }]
30 | },
31 | {
32 | test: /\.less$/,
33 | exclude: '/node_modules',
34 | use: [{
35 | loader: 'style-loader'
36 | },
37 | {
38 | loader: 'css-loader',
39 | options: {
40 | importLoaders: 1
41 | }
42 | },
43 | {
44 | loader: 'postcss-loader',
45 | options: {
46 | ident: 'postcss',
47 | plugins: loader => [
48 | postcssImport({
49 | root: loader.resourcePath
50 | }),
51 | postcssCssnext(),
52 | cssnano()
53 | ]
54 | }
55 | },
56 | {
57 | loader: 'less-loader',
58 | options: {
59 | importLoaders: 1
60 | }
61 | }
62 | ]
63 | },
64 | {
65 | test: /\.css$/,
66 | loader: 'style-loader!css-loader'
67 | },
68 | {
69 | test: /\.xml$/,
70 | loader: 'raw-loader'
71 | }
72 | ]
73 | },
74 | plugins: [
75 | new HtmlWebPackPlugin({
76 | template: './demo/index.html',
77 | filename: './index.html',
78 | chunks: ['demo']
79 | })
80 | ]
81 | };
82 |
--------------------------------------------------------------------------------
/resources/js/io/mxRootChangeCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | mxCodecRegistry.register(function()
6 | {
7 | /**
8 | * Class: mxRootChangeCodec
9 | *
10 | * Codec for s. This class is created and registered
11 | * dynamically at load time and used implicitely via and
12 | * the .
13 | *
14 | * Transient Fields:
15 | *
16 | * - model
17 | * - previous
18 | * - root
19 | */
20 | var codec = new mxObjectCodec(new mxRootChange(),
21 | ['model', 'previous', 'root']);
22 |
23 | /**
24 | * Function: onEncode
25 | *
26 | * Encodes the child recursively.
27 | */
28 | codec.afterEncode = function(enc, obj, node)
29 | {
30 | enc.encodeCell(obj.root, node);
31 |
32 | return node;
33 | };
34 |
35 | /**
36 | * Function: beforeDecode
37 | *
38 | * Decodes the optional children as cells
39 | * using the respective decoder.
40 | */
41 | codec.beforeDecode = function(dec, node, obj)
42 | {
43 | if (node.firstChild != null &&
44 | node.firstChild.nodeType == mxConstants.NODETYPE_ELEMENT)
45 | {
46 | // Makes sure the original node isn't modified
47 | node = node.cloneNode(true);
48 |
49 | var tmp = node.firstChild;
50 | obj.root = dec.decodeCell(tmp, false);
51 |
52 | var tmp2 = tmp.nextSibling;
53 | tmp.parentNode.removeChild(tmp);
54 | tmp = tmp2;
55 |
56 | while (tmp != null)
57 | {
58 | tmp2 = tmp.nextSibling;
59 | dec.decodeCell(tmp);
60 | tmp.parentNode.removeChild(tmp);
61 | tmp = tmp2;
62 | }
63 | }
64 |
65 | return node;
66 | };
67 |
68 | /**
69 | * Function: afterDecode
70 | *
71 | * Restores the state by assigning the previous value.
72 | */
73 | codec.afterDecode = function(dec, node, obj)
74 | {
75 | obj.previous = obj.root;
76 |
77 | return obj;
78 | };
79 |
80 | // Returns the codec into the registry
81 | return codec;
82 |
83 | }());
84 |
--------------------------------------------------------------------------------
/resources/js/io/mxModelCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | mxCodecRegistry.register(function()
6 | {
7 | /**
8 | * Class: mxModelCodec
9 | *
10 | * Codec for s. This class is created and registered
11 | * dynamically at load time and used implicitely via
12 | * and the .
13 | */
14 | var codec = new mxObjectCodec(new mxGraphModel());
15 |
16 | /**
17 | * Function: encodeObject
18 | *
19 | * Encodes the given by writing a (flat) XML sequence of
20 | * cell nodes as produced by the . The sequence is
21 | * wrapped-up in a node with the name root.
22 | */
23 | codec.encodeObject = function(enc, obj, node)
24 | {
25 | var rootNode = enc.document.createElement('root');
26 | enc.encodeCell(obj.getRoot(), rootNode);
27 | node.appendChild(rootNode);
28 | };
29 |
30 | /**
31 | * Function: decodeChild
32 | *
33 | * Overrides decode child to handle special child nodes.
34 | */
35 | codec.decodeChild = function(dec, child, obj)
36 | {
37 | if (child.nodeName == 'root')
38 | {
39 | this.decodeRoot(dec, child, obj);
40 | }
41 | else
42 | {
43 | mxObjectCodec.prototype.decodeChild.apply(this, arguments);
44 | }
45 | };
46 |
47 | /**
48 | * Function: decodeRoot
49 | *
50 | * Reads the cells into the graph model. All cells
51 | * are children of the root element in the node.
52 | */
53 | codec.decodeRoot = function(dec, root, model)
54 | {
55 | var rootCell = null;
56 | var tmp = root.firstChild;
57 |
58 | while (tmp != null)
59 | {
60 | var cell = dec.decodeCell(tmp);
61 |
62 | if (cell != null && cell.getParent() == null)
63 | {
64 | rootCell = cell;
65 | }
66 |
67 | tmp = tmp.nextSibling;
68 | }
69 |
70 | // Sets the root on the model if one has been decoded
71 | if (rootCell != null)
72 | {
73 | model.setRoot(rootCell);
74 | }
75 | };
76 |
77 | // Returns the codec into the registry
78 | return codec;
79 |
80 | }());
81 |
--------------------------------------------------------------------------------
/resources/js/io/mxGenericChangeCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxGenericChangeCodec
7 | *
8 | * Codec for s, s, s,
9 | * s and s. This class is created
10 | * and registered dynamically at load time and used implicitely
11 | * via and the .
12 | *
13 | * Transient Fields:
14 | *
15 | * - model
16 | * - previous
17 | *
18 | * Reference Fields:
19 | *
20 | * - cell
21 | *
22 | * Constructor: mxGenericChangeCodec
23 | *
24 | * Factory function that creates a for
25 | * the specified change and fieldname.
26 | *
27 | * Parameters:
28 | *
29 | * obj - An instance of the change object.
30 | * variable - The fieldname for the change data.
31 | */
32 | var mxGenericChangeCodec = function(obj, variable)
33 | {
34 | var codec = new mxObjectCodec(obj, ['model', 'previous'], ['cell']);
35 |
36 | /**
37 | * Function: afterDecode
38 | *
39 | * Restores the state by assigning the previous value.
40 | */
41 | codec.afterDecode = function(dec, node, obj)
42 | {
43 | // Allows forward references in sessions. This is a workaround
44 | // for the sequence of edits in mxGraph.moveCells and cellsAdded.
45 | if (mxUtils.isNode(obj.cell))
46 | {
47 | obj.cell = dec.decodeCell(obj.cell, false);
48 | }
49 |
50 | obj.previous = obj[variable];
51 |
52 | return obj;
53 | };
54 |
55 | return codec;
56 | };
57 |
58 | // Registers the codecs
59 | mxCodecRegistry.register(mxGenericChangeCodec(new mxValueChange(), 'value'));
60 | mxCodecRegistry.register(mxGenericChangeCodec(new mxStyleChange(), 'style'));
61 | mxCodecRegistry.register(mxGenericChangeCodec(new mxGeometryChange(), 'geometry'));
62 | mxCodecRegistry.register(mxGenericChangeCodec(new mxCollapseChange(), 'collapsed'));
63 | mxCodecRegistry.register(mxGenericChangeCodec(new mxVisibleChange(), 'visible'));
64 | mxCodecRegistry.register(mxGenericChangeCodec(new mxCellAttributeChange(), 'value'));
65 |
66 | window.mxGenericChangeCodec = mxGenericChangeCodec;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mxgraph-editor",
3 | "version": "1.0.3",
4 | "description": "mxgraph editor",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --mode development --open",
8 | "build": "webpack --mode production",
9 | "lib": "babel src --out-dir lib && gulp",
10 | "prepublish": "npm run lib"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git@github.com:korbinzhao/mxgraph-editor.git"
15 | },
16 | "keywords": ["mxgraph", "editor", "mxgraph editor"],
17 | "author": "korbinzhao",
18 | "bugs": {
19 | "url": "https://github.com/korbinzhao/mxgraph-editor/issues"
20 | },
21 | "license": "MIT",
22 | "homepage": "https://github.com/korbinzhao/mxgraph-editor",
23 | "devDependencies": {
24 | "autoprefixer": "^9.4.3",
25 | "babel-cli": "^6.26.0",
26 | "babel-core": "^6.26.0",
27 | "babel-eslint": "^10.0.1",
28 | "babel-loader": "^7.1.2",
29 | "babel-plugin-add-module-exports": "^1.0.0",
30 | "babel-plugin-import": "^1.11.0",
31 | "babel-preset-env": "^1.6.1",
32 | "babel-preset-react": "^6.24.1",
33 | "babel-preset-stage-0": "^6.24.1",
34 | "css-loader": "^1.0.0",
35 | "cssnano": "^4.1.0",
36 | "eslint": "^5.5.0",
37 | "eslint-config-airbnb": "^17.0.0",
38 | "eslint-plugin-import": "^2.13.0",
39 | "eslint-plugin-jsx-a11y": "^6.1.1",
40 | "eslint-plugin-react": "^7.10.0",
41 | "gulp": "^3.9.1",
42 | "gulp-less": "^4.0.1",
43 | "gulp-postcss": "^8.0.0",
44 | "gulp-replace": "^1.0.0",
45 | "gulp-sourcemaps": "^2.6.4",
46 | "html-loader": "^0.5.5",
47 | "html-webpack-plugin": "^3.0.4",
48 | "less": "^3.8.1",
49 | "less-loader": "^4.1.0",
50 | "path": "^0.12.7",
51 | "postcss": "^7.0.2",
52 | "postcss-cssnext": "^3.1.0",
53 | "postcss-import": "^12.0.0",
54 | "postcss-loader": "^3.0.0",
55 | "raw-loader": "^1.0.0",
56 | "style-loader": "^0.22.1",
57 | "webpack": "^4.16.3",
58 | "webpack-cli": "^3.1.1",
59 | "webpack-dev-server": "^3.1.5"
60 | },
61 | "dependencies": {
62 | "antd": "^3.8.2",
63 | "prop-types": "^15.6.2",
64 | "react": "^16.2.0",
65 | "react-dom": "^16.2.0",
66 | "uniqid": "^5.0.3"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/resources/js/util/mxAnimation.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | *
7 | * Class: mxAnimation
8 | *
9 | * Implements a basic animation in JavaScript.
10 | *
11 | * Constructor: mxAnimation
12 | *
13 | * Constructs an animation.
14 | *
15 | * Parameters:
16 | *
17 | * graph - Reference to the enclosing .
18 | */
19 | function mxAnimation(delay)
20 | {
21 | this.delay = (delay != null) ? delay : 20;
22 | };
23 |
24 | /**
25 | * Extends mxEventSource.
26 | */
27 | mxAnimation.prototype = new mxEventSource();
28 | mxAnimation.prototype.constructor = mxAnimation;
29 |
30 | /**
31 | * Variable: delay
32 | *
33 | * Specifies the delay between the animation steps. Defaul is 30ms.
34 | */
35 | mxAnimation.prototype.delay = null;
36 |
37 | /**
38 | * Variable: thread
39 | *
40 | * Reference to the thread while the animation is running.
41 | */
42 | mxAnimation.prototype.thread = null;
43 |
44 | /**
45 | * Function: isRunning
46 | *
47 | * Returns true if the animation is running.
48 | */
49 | mxAnimation.prototype.isRunning = function()
50 | {
51 | return this.thread != null;
52 | };
53 |
54 | /**
55 | * Function: startAnimation
56 | *
57 | * Starts the animation by repeatedly invoking updateAnimation.
58 | */
59 | mxAnimation.prototype.startAnimation = function()
60 | {
61 | if (this.thread == null)
62 | {
63 | this.thread = window.setInterval(mxUtils.bind(this, this.updateAnimation), this.delay);
64 | }
65 | };
66 |
67 | /**
68 | * Function: updateAnimation
69 | *
70 | * Hook for subclassers to implement the animation. Invoke stopAnimation
71 | * when finished, startAnimation to resume. This is called whenever the
72 | * timer fires and fires an mxEvent.EXECUTE event with no properties.
73 | */
74 | mxAnimation.prototype.updateAnimation = function()
75 | {
76 | this.fireEvent(new mxEventObject(mxEvent.EXECUTE));
77 | };
78 |
79 | /**
80 | * Function: stopAnimation
81 | *
82 | * Stops the animation by deleting the timer and fires an .
83 | */
84 | mxAnimation.prototype.stopAnimation = function()
85 | {
86 | if (this.thread != null)
87 | {
88 | window.clearInterval(this.thread);
89 | this.thread = null;
90 | this.fireEvent(new mxEventObject(mxEvent.DONE));
91 | }
92 | };
93 |
94 | window.mxAnimation = mxAnimation;
--------------------------------------------------------------------------------
/resources/js/view/mxStyleRegistry.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | var mxStyleRegistry =
6 | {
7 | /**
8 | * Class: mxStyleRegistry
9 | *
10 | * Singleton class that acts as a global converter from string to object values
11 | * in a style. This is currently only used to perimeters and edge styles.
12 | *
13 | * Variable: values
14 | *
15 | * Maps from strings to objects.
16 | */
17 | values: [],
18 |
19 | /**
20 | * Function: putValue
21 | *
22 | * Puts the given object into the registry under the given name.
23 | */
24 | putValue: function(name, obj)
25 | {
26 | mxStyleRegistry.values[name] = obj;
27 | },
28 |
29 | /**
30 | * Function: getValue
31 | *
32 | * Returns the value associated with the given name.
33 | */
34 | getValue: function(name)
35 | {
36 | return mxStyleRegistry.values[name];
37 | },
38 |
39 | /**
40 | * Function: getName
41 | *
42 | * Returns the name for the given value.
43 | */
44 | getName: function(value)
45 | {
46 | for (var key in mxStyleRegistry.values)
47 | {
48 | if (mxStyleRegistry.values[key] == value)
49 | {
50 | return key;
51 | }
52 | }
53 |
54 | return null;
55 | }
56 |
57 | };
58 |
59 | mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ELBOW, mxEdgeStyle.ElbowConnector);
60 | mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ENTITY_RELATION, mxEdgeStyle.EntityRelation);
61 | mxStyleRegistry.putValue(mxConstants.EDGESTYLE_LOOP, mxEdgeStyle.Loop);
62 | mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SIDETOSIDE, mxEdgeStyle.SideToSide);
63 | mxStyleRegistry.putValue(mxConstants.EDGESTYLE_TOPTOBOTTOM, mxEdgeStyle.TopToBottom);
64 | mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ORTHOGONAL, mxEdgeStyle.OrthConnector);
65 | mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SEGMENT, mxEdgeStyle.SegmentConnector);
66 |
67 | mxStyleRegistry.putValue(mxConstants.PERIMETER_ELLIPSE, mxPerimeter.EllipsePerimeter);
68 | mxStyleRegistry.putValue(mxConstants.PERIMETER_RECTANGLE, mxPerimeter.RectanglePerimeter);
69 | mxStyleRegistry.putValue(mxConstants.PERIMETER_RHOMBUS, mxPerimeter.RhombusPerimeter);
70 | mxStyleRegistry.putValue(mxConstants.PERIMETER_TRIANGLE, mxPerimeter.TrianglePerimeter);
71 | mxStyleRegistry.putValue(mxConstants.PERIMETER_HEXAGON, mxPerimeter.HexagonPerimeter);
72 |
73 | window.mxStyleRegistry = mxStyleRegistry;
74 |
--------------------------------------------------------------------------------
/resources/js/io/mxDefaultKeyHandlerCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | mxCodecRegistry.register(function()
6 | {
7 | /**
8 | * Class: mxDefaultKeyHandlerCodec
9 | *
10 | * Custom codec for configuring s. This class is created
11 | * and registered dynamically at load time and used implicitely via
12 | * and the . This codec only reads configuration
13 | * data for existing key handlers, it does not encode or create key handlers.
14 | */
15 | var codec = new mxObjectCodec(new mxDefaultKeyHandler());
16 |
17 | /**
18 | * Function: encode
19 | *
20 | * Returns null.
21 | */
22 | codec.encode = function(enc, obj)
23 | {
24 | return null;
25 | };
26 |
27 | /**
28 | * Function: decode
29 | *
30 | * Reads a sequence of the following child nodes
31 | * and attributes:
32 | *
33 | * Child Nodes:
34 | *
35 | * add - Binds a keystroke to an actionname.
36 | *
37 | * Attributes:
38 | *
39 | * as - Keycode.
40 | * action - Actionname to execute in editor.
41 | * control - Optional boolean indicating if
42 | * the control key must be pressed.
43 | *
44 | * Example:
45 | *
46 | * (code)
47 | *
48 | *
49 | *
50 | *
51 | *
52 | * (end)
53 | *
54 | * The keycodes are for the x, c and v keys.
55 | *
56 | * See also: ,
57 | * http://www.js-examples.com/page/tutorials__key_codes.html
58 | */
59 | codec.decode = function(dec, node, into)
60 | {
61 | if (into != null)
62 | {
63 | var editor = into.editor;
64 | node = node.firstChild;
65 |
66 | while (node != null)
67 | {
68 | if (!this.processInclude(dec, node, into) &&
69 | node.nodeName == 'add')
70 | {
71 | var as = node.getAttribute('as');
72 | var action = node.getAttribute('action');
73 | var control = node.getAttribute('control');
74 |
75 | into.bindAction(as, action, control);
76 | }
77 |
78 | node = node.nextSibling;
79 | }
80 | }
81 |
82 | return into;
83 | };
84 |
85 | // Returns the codec into the registry
86 | return codec;
87 |
88 | }());
89 |
--------------------------------------------------------------------------------
/resources/js/shape/mxActor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxActor
7 | *
8 | * Extends to implement an actor shape. If a custom shape with one
9 | * filled area is needed, then this shape's should be overridden.
10 | *
11 | * Example:
12 | *
13 | * (code)
14 | * function SampleShape() { }
15 | *
16 | * SampleShape.prototype = new mxActor();
17 | * SampleShape.prototype.constructor = vsAseShape;
18 | *
19 | * mxCellRenderer.registerShape('sample', SampleShape);
20 | * SampleShape.prototype.redrawPath = function(path, x, y, w, h)
21 | * {
22 | * path.moveTo(0, 0);
23 | * path.lineTo(w, h);
24 | * // ...
25 | * path.close();
26 | * }
27 | * (end)
28 | *
29 | * This shape is registered under in
30 | * .
31 | *
32 | * Constructor: mxActor
33 | *
34 | * Constructs a new actor shape.
35 | *
36 | * Parameters:
37 | *
38 | * bounds - that defines the bounds. This is stored in
39 | * .
40 | * fill - String that defines the fill color. This is stored in .
41 | * stroke - String that defines the stroke color. This is stored in .
42 | * strokewidth - Optional integer that defines the stroke width. Default is
43 | * 1. This is stored in .
44 | */
45 | function mxActor(bounds, fill, stroke, strokewidth) {
46 | mxShape.call(this);
47 | this.bounds = bounds;
48 | this.fill = fill;
49 | this.stroke = stroke;
50 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
51 | }
52 |
53 | /**
54 | * Extends mxShape.
55 | */
56 | mxUtils.extend(mxActor, mxShape);
57 |
58 | /**
59 | * Function: paintVertexShape
60 | *
61 | * Redirects to redrawPath for subclasses to work.
62 | */
63 | mxActor.prototype.paintVertexShape = function (c, x, y, w, h) {
64 | c.translate(x, y);
65 | c.begin();
66 | this.redrawPath(c, x, y, w, h);
67 | c.fillAndStroke();
68 | };
69 |
70 | /**
71 | * Function: redrawPath
72 | *
73 | * Draws the path for this shape.
74 | */
75 | mxActor.prototype.redrawPath = function (c, x, y, w, h) {
76 | const width = w / 3;
77 | c.moveTo(0, h);
78 | c.curveTo(0, 3 * h / 5, 0, 2 * h / 5, w / 2, 2 * h / 5);
79 | c.curveTo(w / 2 - width, 2 * h / 5, w / 2 - width, 0, w / 2, 0);
80 | c.curveTo(w / 2 + width, 0, w / 2 + width, 2 * h / 5, w / 2, 2 * h / 5);
81 | c.curveTo(w, 2 * h / 5, w, 3 * h / 5, w, h);
82 | c.close();
83 | };
84 |
85 | window.mxActor = mxActor;
86 |
--------------------------------------------------------------------------------
/resources/js/util/mxEventObject.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxEventObject
7 | *
8 | * The mxEventObject is a wrapper for all properties of a single event.
9 | * Additionally, it also offers functions to consume the event and check if it
10 | * was consumed as follows:
11 | *
12 | * (code)
13 | * evt.consume();
14 | * INV: evt.isConsumed() == true
15 | * (end)
16 | *
17 | * Constructor: mxEventObject
18 | *
19 | * Constructs a new event object with the specified name. An optional
20 | * sequence of key, value pairs can be appended to define properties.
21 | *
22 | * Example:
23 | *
24 | * (code)
25 | * new mxEventObject("eventName", key1, val1, .., keyN, valN)
26 | * (end)
27 | */
28 | function mxEventObject(name)
29 | {
30 | this.name = name;
31 | this.properties = [];
32 |
33 | for (var i = 1; i < arguments.length; i += 2)
34 | {
35 | if (arguments[i + 1] != null)
36 | {
37 | this.properties[arguments[i]] = arguments[i + 1];
38 | }
39 | }
40 | };
41 |
42 | /**
43 | * Variable: name
44 | *
45 | * Holds the name.
46 | */
47 | mxEventObject.prototype.name = null;
48 |
49 | /**
50 | * Variable: properties
51 | *
52 | * Holds the properties as an associative array.
53 | */
54 | mxEventObject.prototype.properties = null;
55 |
56 | /**
57 | * Variable: consumed
58 | *
59 | * Holds the consumed state. Default is false.
60 | */
61 | mxEventObject.prototype.consumed = false;
62 |
63 | /**
64 | * Function: getName
65 | *
66 | * Returns .
67 | */
68 | mxEventObject.prototype.getName = function()
69 | {
70 | return this.name;
71 | };
72 |
73 | /**
74 | * Function: getProperties
75 | *
76 | * Returns .
77 | */
78 | mxEventObject.prototype.getProperties = function()
79 | {
80 | return this.properties;
81 | };
82 |
83 | /**
84 | * Function: getProperty
85 | *
86 | * Returns the property for the given key.
87 | */
88 | mxEventObject.prototype.getProperty = function(key)
89 | {
90 | return this.properties[key];
91 | };
92 |
93 | /**
94 | * Function: isConsumed
95 | *
96 | * Returns true if the event has been consumed.
97 | */
98 | mxEventObject.prototype.isConsumed = function()
99 | {
100 | return this.consumed;
101 | };
102 |
103 | /**
104 | * Function: consume
105 | *
106 | * Consumes the event.
107 | */
108 | mxEventObject.prototype.consume = function()
109 | {
110 | this.consumed = true;
111 | };
112 |
113 | window.mxEventObject = mxEventObject;
--------------------------------------------------------------------------------
/demo/sidebar.less:
--------------------------------------------------------------------------------
1 | @fontColor: #E4E8EA;
2 |
3 | .sidebar-container {
4 | width: 235px;
5 | height: 100%;
6 | min-height: 500px;
7 | background-color: #fff;
8 | border-right: 1px solid @fontColor;
9 | box-shadow: 0 0 4px 0 rgba(54, 71, 134, 0.1);
10 | overflow-y: scroll;
11 |
12 | .suanfa-name {
13 | padding-left: 6px;
14 | }
15 |
16 | .ant-collapse-content-box {
17 | padding: 6px !important;
18 | display: flex;
19 | flex-wrap: wrap;
20 | }
21 |
22 | .ant-collapse-item {
23 | border-bottom: none;
24 | }
25 |
26 | .custom-svg {
27 | width: 36px;
28 | height: 46px;
29 | display: block;
30 | position: relative;
31 | overflow: hidden;
32 | cursor: move;
33 | left: 2px;
34 | top: 2px;
35 | }
36 |
37 | }
38 |
39 | .custom-sidebar-node {
40 | overflow: hidden;
41 | width: 64px;
42 | height: 64px;
43 | padding: 1px;
44 | display: flex;
45 | flex-direction: column;
46 | align-items: center;
47 | justify-content: center;
48 | cursor: move;
49 | box-sizing: border-box;
50 | font-size: 12px;
51 | text-align: center;
52 | // float:left
53 | margin: 2px;
54 | cursor: move;
55 | text-decoration: none;
56 |
57 | .tooltip {
58 | display: flex;
59 | flex-direction: column;
60 | align-items: center;
61 | justify-content: center;
62 | }
63 |
64 | &:hover {
65 | background-color: #FBFBFB;
66 | border: 1px solid #DEE0EA;
67 | border-radius: 2px;
68 | }
69 |
70 | &:focus {
71 | text-decoration: none;
72 | }
73 |
74 | &.suanfa-node {
75 | width: 180px;
76 | height: 24px;
77 | flex-direction: row;
78 | justify-content: start;
79 | padding: 0 6px;
80 | }
81 |
82 | .sidebar-node-image {
83 | width: 31px;
84 | height: 31px;
85 | }
86 |
87 | .sidebar-node-label {
88 | padding-top: 6px;
89 | text-overflow: ellipsis;
90 | overflow: hidden;
91 | height: 14px;
92 | line-height: 14px;
93 | box-sizing: content-box;
94 | white-space: nowrap;
95 | width: 63px;
96 | }
97 |
98 | .svg-node {
99 | width: 36px;
100 | height: 36px;
101 | display: block;
102 | position: relative;
103 | overflow: hidden;
104 | cursor: move;
105 |
106 | .text-node {
107 | display: inline-block;
108 | font-size: 12px;
109 | font-family: Helvetica;
110 | color: #666;
111 | line-height: 1.2;
112 | vertical-align: top;
113 | width: 24px;
114 | white-space: normal;
115 | overflow-wrap: normal;
116 | text-align: center;
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/resources/js/util/mxDictionary.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxDictionary
7 | *
8 | * A wrapper class for an associative array with object keys. Note: This
9 | * implementation uses to turn object keys into strings.
10 | *
11 | * Constructor: mxEventSource
12 | *
13 | * Constructs a new dictionary which allows object to be used as keys.
14 | */
15 | function mxDictionary()
16 | {
17 | this.clear();
18 | };
19 |
20 | /**
21 | * Function: map
22 | *
23 | * Stores the (key, value) pairs in this dictionary.
24 | */
25 | mxDictionary.prototype.map = null;
26 |
27 | /**
28 | * Function: clear
29 | *
30 | * Clears the dictionary.
31 | */
32 | mxDictionary.prototype.clear = function()
33 | {
34 | this.map = {};
35 | };
36 |
37 | /**
38 | * Function: get
39 | *
40 | * Returns the value for the given key.
41 | */
42 | mxDictionary.prototype.get = function(key)
43 | {
44 | var id = mxObjectIdentity.get(key);
45 |
46 | return this.map[id];
47 | };
48 |
49 | /**
50 | * Function: put
51 | *
52 | * Stores the value under the given key and returns the previous
53 | * value for that key.
54 | */
55 | mxDictionary.prototype.put = function(key, value)
56 | {
57 | var id = mxObjectIdentity.get(key);
58 | var previous = this.map[id];
59 | this.map[id] = value;
60 |
61 | return previous;
62 | };
63 |
64 | /**
65 | * Function: remove
66 | *
67 | * Removes the value for the given key and returns the value that
68 | * has been removed.
69 | */
70 | mxDictionary.prototype.remove = function(key)
71 | {
72 | var id = mxObjectIdentity.get(key);
73 | var previous = this.map[id];
74 | delete this.map[id];
75 |
76 | return previous;
77 | };
78 |
79 | /**
80 | * Function: getKeys
81 | *
82 | * Returns all keys as an array.
83 | */
84 | mxDictionary.prototype.getKeys = function()
85 | {
86 | var result = [];
87 |
88 | for (var key in this.map)
89 | {
90 | result.push(key);
91 | }
92 |
93 | return result;
94 | };
95 |
96 | /**
97 | * Function: getValues
98 | *
99 | * Returns all values as an array.
100 | */
101 | mxDictionary.prototype.getValues = function()
102 | {
103 | var result = [];
104 |
105 | for (var key in this.map)
106 | {
107 | result.push(this.map[key]);
108 | }
109 |
110 | return result;
111 | };
112 |
113 | /**
114 | * Function: visit
115 | *
116 | * Visits all entries in the dictionary using the given function with the
117 | * following signature: function(key, value) where key is a string and
118 | * value is an object.
119 | *
120 | * Parameters:
121 | *
122 | * visitor - A function that takes the key and value as arguments.
123 | */
124 | mxDictionary.prototype.visit = function(visitor)
125 | {
126 | for (var key in this.map)
127 | {
128 | visitor(key, this.map[key]);
129 | }
130 | };
131 |
132 | window.mxDictionary = mxDictionary;
--------------------------------------------------------------------------------
/resources/js/layout/mxCompositeLayout.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxCompositeLayout
7 | *
8 | * Allows to compose multiple layouts into a single layout. The master layout
9 | * is the layout that handles move operations if another layout than the first
10 | * element in should be used. The layout is not executed as
11 | * the code assumes that it is part of .
12 | *
13 | * Example:
14 | * (code)
15 | * var first = new mxFastOrganicLayout(graph);
16 | * var second = new mxParallelEdgeLayout(graph);
17 | * var layout = new mxCompositeLayout(graph, [first, second], first);
18 | * layout.execute(graph.getDefaultParent());
19 | * (end)
20 | *
21 | * Constructor: mxCompositeLayout
22 | *
23 | * Constructs a new layout using the given layouts. The graph instance is
24 | * required for creating the transaction that contains all layouts.
25 | *
26 | * Arguments:
27 | *
28 | * graph - Reference to the enclosing .
29 | * layouts - Array of .
30 | * master - Optional layout that handles moves. If no layout is given then
31 | * the first layout of the above array is used to handle moves.
32 | */
33 | function mxCompositeLayout(graph, layouts, master)
34 | {
35 | mxGraphLayout.call(this, graph);
36 | this.layouts = layouts;
37 | this.master = master;
38 | };
39 |
40 | /**
41 | * Extends mxGraphLayout.
42 | */
43 | mxCompositeLayout.prototype = new mxGraphLayout();
44 | mxCompositeLayout.prototype.constructor = mxCompositeLayout;
45 |
46 | /**
47 | * Variable: layouts
48 | *
49 | * Holds the array of that this layout contains.
50 | */
51 | mxCompositeLayout.prototype.layouts = null;
52 |
53 | /**
54 | * Variable: layouts
55 | *
56 | * Reference to the that handles moves. If this is null
57 | * then the first layout in is used.
58 | */
59 | mxCompositeLayout.prototype.master = null;
60 |
61 | /**
62 | * Function: moveCell
63 | *
64 | * Implements by calling move on or the first
65 | * layout in .
66 | */
67 | mxCompositeLayout.prototype.moveCell = function(cell, x, y)
68 | {
69 | if (this.master != null)
70 | {
71 | this.master.move.apply(this.master, arguments);
72 | }
73 | else
74 | {
75 | this.layouts[0].move.apply(this.layouts[0], arguments);
76 | }
77 | };
78 |
79 | /**
80 | * Function: execute
81 | *
82 | * Implements by executing all in a
83 | * single transaction.
84 | */
85 | mxCompositeLayout.prototype.execute = function(parent)
86 | {
87 | var model = this.graph.getModel();
88 |
89 | model.beginUpdate();
90 | try
91 | {
92 | for (var i = 0; i < this.layouts.length; i++)
93 | {
94 | this.layouts[i].execute.apply(this.layouts[i], arguments);
95 | }
96 | }
97 | finally
98 | {
99 | model.endUpdate();
100 | }
101 | };
102 |
103 | window.mxCompositeLayout = mxCompositeLayout;
104 |
--------------------------------------------------------------------------------
/resources/js/shape/mxPolyline.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxPolyline
7 | *
8 | * Extends to implement a polyline (a line with multiple points).
9 | * This shape is registered under in
10 | * .
11 | *
12 | * Constructor: mxPolyline
13 | *
14 | * Constructs a new polyline shape.
15 | *
16 | * Parameters:
17 | *
18 | * points - Array of that define the points. This is stored in
19 | * .
20 | * stroke - String that defines the stroke color. Default is 'black'. This is
21 | * stored in .
22 | * strokewidth - Optional integer that defines the stroke width. Default is
23 | * 1. This is stored in .
24 | */
25 | function mxPolyline(points, stroke, strokewidth)
26 | {
27 | mxShape.call(this);
28 | this.points = points;
29 | this.stroke = stroke;
30 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
31 | };
32 |
33 | /**
34 | * Extends mxShape.
35 | */
36 | mxUtils.extend(mxPolyline, mxShape);
37 |
38 | /**
39 | * Function: getRotation
40 | *
41 | * Returns 0.
42 | */
43 | mxPolyline.prototype.getRotation = function()
44 | {
45 | return 0;
46 | };
47 |
48 | /**
49 | * Function: getShapeRotation
50 | *
51 | * Returns 0.
52 | */
53 | mxPolyline.prototype.getShapeRotation = function()
54 | {
55 | return 0;
56 | };
57 |
58 | /**
59 | * Function: isPaintBoundsInverted
60 | *
61 | * Returns false.
62 | */
63 | mxPolyline.prototype.isPaintBoundsInverted = function()
64 | {
65 | return false;
66 | };
67 |
68 | /**
69 | * Function: paintEdgeShape
70 | *
71 | * Paints the line shape.
72 | */
73 | mxPolyline.prototype.paintEdgeShape = function(c, pts)
74 | {
75 | if (this.style == null || this.style[mxConstants.STYLE_CURVED] != 1)
76 | {
77 | this.paintLine(c, pts, this.isRounded);
78 | }
79 | else
80 | {
81 | this.paintCurvedLine(c, pts);
82 | }
83 | };
84 |
85 | /**
86 | * Function: paintLine
87 | *
88 | * Paints the line shape.
89 | */
90 | mxPolyline.prototype.paintLine = function(c, pts, rounded)
91 | {
92 | var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
93 | c.begin();
94 | this.addPoints(c, pts, rounded, arcSize, false);
95 | c.stroke();
96 | };
97 |
98 | /**
99 | * Function: paintLine
100 | *
101 | * Paints the line shape.
102 | */
103 | mxPolyline.prototype.paintCurvedLine = function(c, pts)
104 | {
105 | c.begin();
106 |
107 | var pt = pts[0];
108 | var n = pts.length;
109 |
110 | c.moveTo(pt.x, pt.y);
111 |
112 | for (var i = 1; i < n - 2; i++)
113 | {
114 | var p0 = pts[i];
115 | var p1 = pts[i + 1];
116 | var ix = (p0.x + p1.x) / 2;
117 | var iy = (p0.y + p1.y) / 2;
118 |
119 | c.quadTo(p0.x, p0.y, ix, iy);
120 | }
121 |
122 | var p0 = pts[n - 2];
123 | var p1 = pts[n - 1];
124 |
125 | c.quadTo(p0.x, p0.y, p1.x, p1.y);
126 | c.stroke();
127 | };
128 |
129 | window.mxPolyline = mxPolyline;
130 |
--------------------------------------------------------------------------------
/resources/js/layout/hierarchical/stage/mxSwimlaneOrdering.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxSwimlaneOrdering
7 | *
8 | * An implementation of the first stage of the Sugiyama layout. Straightforward
9 | * longest path calculation of layer assignment
10 | *
11 | * Constructor: mxSwimlaneOrdering
12 | *
13 | * Creates a cycle remover for the given internal model.
14 | */
15 | function mxSwimlaneOrdering(layout)
16 | {
17 | this.layout = layout;
18 | };
19 |
20 | /**
21 | * Extends mxHierarchicalLayoutStage.
22 | */
23 | mxSwimlaneOrdering.prototype = new mxHierarchicalLayoutStage();
24 | mxSwimlaneOrdering.prototype.constructor = mxSwimlaneOrdering;
25 |
26 | /**
27 | * Variable: layout
28 | *
29 | * Reference to the enclosing .
30 | */
31 | mxSwimlaneOrdering.prototype.layout = null;
32 |
33 | /**
34 | * Function: execute
35 | *
36 | * Takes the graph detail and configuration information within the facade
37 | * and creates the resulting laid out graph within that facade for further
38 | * use.
39 | */
40 | mxSwimlaneOrdering.prototype.execute = function(parent)
41 | {
42 | var model = this.layout.getModel();
43 | var seenNodes = new Object();
44 | var unseenNodes = mxUtils.clone(model.vertexMapper, null, true);
45 |
46 | // Perform a dfs through the internal model. If a cycle is found,
47 | // reverse it.
48 | var rootsArray = null;
49 |
50 | if (model.roots != null)
51 | {
52 | var modelRoots = model.roots;
53 | rootsArray = [];
54 |
55 | for (var i = 0; i < modelRoots.length; i++)
56 | {
57 | var nodeId = mxCellPath.create(modelRoots[i]);
58 | rootsArray[i] = model.vertexMapper.get(modelRoots[i]);
59 | }
60 | }
61 |
62 | model.visit(function(parent, node, connectingEdge, layer, seen)
63 | {
64 | // Check if the cell is in it's own ancestor list, if so
65 | // invert the connecting edge and reverse the target/source
66 | // relationship to that edge in the parent and the cell
67 | // Ancestor hashes only line up within a swimlane
68 | var isAncestor = parent != null && parent.swimlaneIndex == node.swimlaneIndex && node.isAncestor(parent);
69 |
70 | // If the source->target swimlane indices go from higher to
71 | // lower, the edge is reverse
72 | var reversedOverSwimlane = parent != null && connectingEdge != null &&
73 | parent.swimlaneIndex < node.swimlaneIndex && connectingEdge.source == node;
74 |
75 | if (isAncestor)
76 | {
77 | connectingEdge.invert();
78 | mxUtils.remove(connectingEdge, parent.connectsAsSource);
79 | node.connectsAsSource.push(connectingEdge);
80 | parent.connectsAsTarget.push(connectingEdge);
81 | mxUtils.remove(connectingEdge, node.connectsAsTarget);
82 | }
83 | else if (reversedOverSwimlane)
84 | {
85 | connectingEdge.invert();
86 | mxUtils.remove(connectingEdge, parent.connectsAsTarget);
87 | node.connectsAsTarget.push(connectingEdge);
88 | parent.connectsAsSource.push(connectingEdge);
89 | mxUtils.remove(connectingEdge, node.connectsAsSource);
90 | }
91 |
92 | var cellId = mxCellPath.create(node.cell);
93 | seenNodes[cellId] = node;
94 | delete unseenNodes[cellId];
95 | }, rootsArray, true, null);
96 | };
97 |
98 | window.mxSwimlaneOrdering = mxSwimlaneOrdering;
99 |
--------------------------------------------------------------------------------
/resources/js/shape/mxCylinder.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxCylinder
7 | *
8 | * Extends to implement an cylinder shape. If a
9 | * custom shape with one filled area and an overlay path is
10 | * needed, then this shape's should be overridden.
11 | * This shape is registered under
12 | * in .
13 | *
14 | * Constructor: mxCylinder
15 | *
16 | * Constructs a new cylinder shape.
17 | *
18 | * Parameters:
19 | *
20 | * bounds - that defines the bounds. This is stored in
21 | * .
22 | * fill - String that defines the fill color. This is stored in .
23 | * stroke - String that defines the stroke color. This is stored in .
24 | * strokewidth - Optional integer that defines the stroke width. Default is
25 | * 1. This is stored in .
26 | */
27 | function mxCylinder(bounds, fill, stroke, strokewidth)
28 | {
29 | mxShape.call(this);
30 | this.bounds = bounds;
31 | this.fill = fill;
32 | this.stroke = stroke;
33 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
34 | };
35 |
36 | /**
37 | * Extends mxShape.
38 | */
39 | mxUtils.extend(mxCylinder, mxShape);
40 |
41 | /**
42 | * Variable: maxHeight
43 | *
44 | * Defines the maximum height of the top and bottom part
45 | * of the cylinder shape.
46 | */
47 | mxCylinder.prototype.maxHeight = 40;
48 |
49 | /**
50 | * Variable: svgStrokeTolerance
51 | *
52 | * Sets stroke tolerance to 0 for SVG.
53 | */
54 | mxCylinder.prototype.svgStrokeTolerance = 0;
55 |
56 | /**
57 | * Function: paintVertexShape
58 | *
59 | * Redirects to redrawPath for subclasses to work.
60 | */
61 | mxCylinder.prototype.paintVertexShape = function(c, x, y, w, h)
62 | {
63 | c.translate(x, y);
64 | c.begin();
65 | this.redrawPath(c, x, y, w, h, false);
66 | c.fillAndStroke();
67 |
68 | if (!this.outline || this.style == null || mxUtils.getValue(
69 | this.style, mxConstants.STYLE_BACKGROUND_OUTLINE, 0) == 0)
70 | {
71 | c.setShadow(false);
72 | c.begin();
73 | this.redrawPath(c, x, y, w, h, true);
74 | c.stroke();
75 | }
76 | };
77 |
78 | /**
79 | * Function: redrawPath
80 | *
81 | * Draws the path for this shape.
82 | */
83 | mxCylinder.prototype.getCylinderSize = function(x, y, w, h)
84 | {
85 | return Math.min(this.maxHeight, Math.round(h / 5));
86 | };
87 |
88 | /**
89 | * Function: redrawPath
90 | *
91 | * Draws the path for this shape.
92 | */
93 | mxCylinder.prototype.redrawPath = function(c, x, y, w, h, isForeground)
94 | {
95 | var dy = this.getCylinderSize(x, y, w, h);
96 |
97 | if ((isForeground && this.fill != null) || (!isForeground && this.fill == null))
98 | {
99 | c.moveTo(0, dy);
100 | c.curveTo(0, 2 * dy, w, 2 * dy, w, dy);
101 |
102 | // Needs separate shapes for correct hit-detection
103 | if (!isForeground)
104 | {
105 | c.stroke();
106 | c.begin();
107 | }
108 | }
109 |
110 | if (!isForeground)
111 | {
112 | c.moveTo(0, dy);
113 | c.curveTo(0, -dy / 3, w, -dy / 3, w, dy);
114 | c.lineTo(w, h - dy);
115 | c.curveTo(w, h + dy / 3, 0, h + dy / 3, 0, h - dy);
116 | c.close();
117 | }
118 | };
119 |
120 | window.mxCylinder = mxCylinder;
121 |
--------------------------------------------------------------------------------
/resources/js/io/mxCodecRegistry.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | var mxCodecRegistry =
6 | {
7 | /**
8 | * Class: mxCodecRegistry
9 | *
10 | * Singleton class that acts as a global registry for codecs.
11 | *
12 | * Adding an :
13 | *
14 | * 1. Define a default codec with a new instance of the
15 | * object to be handled.
16 | *
17 | * (code)
18 | * var codec = new mxObjectCodec(new mxGraphModel());
19 | * (end)
20 | *
21 | * 2. Define the functions required for encoding and decoding
22 | * objects.
23 | *
24 | * (code)
25 | * codec.encode = function(enc, obj) { ... }
26 | * codec.decode = function(dec, node, into) { ... }
27 | * (end)
28 | *
29 | * 3. Register the codec in the .
30 | *
31 | * (code)
32 | * mxCodecRegistry.register(codec);
33 | * (end)
34 | *
35 | * may be used to either create a new
36 | * instance of an object or to configure an existing instance,
37 | * in which case the into argument points to the existing
38 | * object. In this case, we say the codec "configures" the
39 | * object.
40 | *
41 | * Variable: codecs
42 | *
43 | * Maps from constructor names to codecs.
44 | */
45 | codecs: [],
46 |
47 | /**
48 | * Variable: aliases
49 | *
50 | * Maps from classnames to codecnames.
51 | */
52 | aliases: [],
53 |
54 | /**
55 | * Function: register
56 | *
57 | * Registers a new codec and associates the name of the template
58 | * constructor in the codec with the codec object.
59 | *
60 | * Parameters:
61 | *
62 | * codec - to be registered.
63 | */
64 | register: function(codec)
65 | {
66 | if (codec != null)
67 | {
68 | var name = codec.getName();
69 | mxCodecRegistry.codecs[name] = codec;
70 |
71 | var classname = mxUtils.getFunctionName(codec.template.constructor);
72 |
73 | if (classname != name)
74 | {
75 | mxCodecRegistry.addAlias(classname, name);
76 | }
77 | }
78 |
79 | return codec;
80 | },
81 |
82 | /**
83 | * Function: addAlias
84 | *
85 | * Adds an alias for mapping a classname to a codecname.
86 | */
87 | addAlias: function(classname, codecname)
88 | {
89 | mxCodecRegistry.aliases[classname] = codecname;
90 | },
91 |
92 | /**
93 | * Function: getCodec
94 | *
95 | * Returns a codec that handles objects that are constructed
96 | * using the given constructor.
97 | *
98 | * Parameters:
99 | *
100 | * ctor - JavaScript constructor function.
101 | */
102 | getCodec: function(ctor)
103 | {
104 | var codec = null;
105 |
106 | if (ctor != null)
107 | {
108 | var name = mxUtils.getFunctionName(ctor);
109 | var tmp = mxCodecRegistry.aliases[name];
110 |
111 | if (tmp != null)
112 | {
113 | name = tmp;
114 | }
115 |
116 | codec = mxCodecRegistry.codecs[name];
117 |
118 | // Registers a new default codec for the given constructor
119 | // if no codec has been previously defined.
120 | if (codec == null)
121 | {
122 | try
123 | {
124 | codec = new mxObjectCodec(new ctor());
125 | mxCodecRegistry.register(codec);
126 | }
127 | catch (e)
128 | {
129 | // ignore
130 | }
131 | }
132 | }
133 |
134 | return codec;
135 | }
136 |
137 | };
138 |
139 | window.mxCodecRegistry = mxCodecRegistry;
140 |
--------------------------------------------------------------------------------
/resources/js/shape/mxDoubleEllipse.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxDoubleEllipse
7 | *
8 | * Extends to implement a double ellipse shape. This shape is
9 | * registered under in .
10 | * Use the following override to only fill the inner ellipse in this shape:
11 | *
12 | * (code)
13 | * mxDoubleEllipse.prototype.paintVertexShape = function(c, x, y, w, h)
14 | * {
15 | * c.ellipse(x, y, w, h);
16 | * c.stroke();
17 | *
18 | * var inset = mxUtils.getValue(this.style, mxConstants.STYLE_MARGIN, Math.min(3 + this.strokewidth, Math.min(w / 5, h / 5)));
19 | * x += inset;
20 | * y += inset;
21 | * w -= 2 * inset;
22 | * h -= 2 * inset;
23 | *
24 | * if (w > 0 && h > 0)
25 | * {
26 | * c.ellipse(x, y, w, h);
27 | * }
28 | *
29 | * c.fillAndStroke();
30 | * };
31 | * (end)
32 | *
33 | * Constructor: mxDoubleEllipse
34 | *
35 | * Constructs a new ellipse shape.
36 | *
37 | * Parameters:
38 | *
39 | * bounds - that defines the bounds. This is stored in
40 | * .
41 | * fill - String that defines the fill color. This is stored in .
42 | * stroke - String that defines the stroke color. This is stored in .
43 | * strokewidth - Optional integer that defines the stroke width. Default is
44 | * 1. This is stored in .
45 | */
46 | function mxDoubleEllipse(bounds, fill, stroke, strokewidth)
47 | {
48 | mxShape.call(this);
49 | this.bounds = bounds;
50 | this.fill = fill;
51 | this.stroke = stroke;
52 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
53 | };
54 |
55 | /**
56 | * Extends mxShape.
57 | */
58 | mxUtils.extend(mxDoubleEllipse, mxShape);
59 |
60 | /**
61 | * Variable: vmlScale
62 | *
63 | * Scale for improving the precision of VML rendering. Default is 10.
64 | */
65 | mxDoubleEllipse.prototype.vmlScale = 10;
66 |
67 | /**
68 | * Function: paintBackground
69 | *
70 | * Paints the background.
71 | */
72 | mxDoubleEllipse.prototype.paintBackground = function(c, x, y, w, h)
73 | {
74 | c.ellipse(x, y, w, h);
75 | c.fillAndStroke();
76 | };
77 |
78 | /**
79 | * Function: paintForeground
80 | *
81 | * Paints the foreground.
82 | */
83 | mxDoubleEllipse.prototype.paintForeground = function(c, x, y, w, h)
84 | {
85 | if (!this.outline)
86 | {
87 | var margin = mxUtils.getValue(this.style, mxConstants.STYLE_MARGIN, Math.min(3 + this.strokewidth, Math.min(w / 5, h / 5)));
88 | x += margin;
89 | y += margin;
90 | w -= 2 * margin;
91 | h -= 2 * margin;
92 |
93 | // FIXME: Rounding issues in IE8 standards mode (not in 1.x)
94 | if (w > 0 && h > 0)
95 | {
96 | c.ellipse(x, y, w, h);
97 | }
98 |
99 | c.stroke();
100 | }
101 | };
102 |
103 | /**
104 | * Function: getLabelBounds
105 | *
106 | * Returns the bounds for the label.
107 | */
108 | mxDoubleEllipse.prototype.getLabelBounds = function(rect)
109 | {
110 | var margin = (mxUtils.getValue(this.style, mxConstants.STYLE_MARGIN, Math.min(3 + this.strokewidth,
111 | Math.min(rect.width / 5 / this.scale, rect.height / 5 / this.scale)))) * this.scale;
112 |
113 | return new mxRectangle(rect.x + margin, rect.y + margin, rect.width - 2 * margin, rect.height - 2 * margin);
114 | };
115 |
116 | window.mxDoubleEllipse = mxDoubleEllipse;
117 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mxgraph-editor
2 | A mxGraph editor support 3 types of shapes, svg/image/card.
3 |
4 | 
5 |
6 | # development
7 | ```
8 | npm install
9 |
10 | npm start
11 | ```
12 |
13 | # install
14 | ```
15 | npm install --save mxgraph-editor
16 | ```
17 |
18 | # demo
19 |
20 | See the detail in ./demo .
21 |
22 | ## start the demo
23 | ```
24 | // start the demo
25 | npm start
26 | ```
27 |
28 | ## code
29 |
30 | ```
31 | import Sidebar from './sidebar';
32 | import Toolbar from './toolbar';
33 |
34 | import IMAGE_SHAPES from './shape-config/image-shape';
35 | import CARD_SHAPES from './shape-config/card-shape';
36 | import SVG_SHAPES from './shape-config/svg-shape.xml';
37 |
38 | import Editor from 'mxgraph-editor';
39 |
40 | const editor = new Editor({
41 | container: '.graph-content',
42 | clickFunc: this.clickFunc,
43 | doubleClickFunc: this.doubleClickFunc,
44 | autoSaveFunc: this.autoSaveFunc,
45 | cellCreatedFunc: this.cellCreatedFunc,
46 | deleteFunc: this.deleteFunc,
47 | valueChangeFunc: this.valueChangeFunc,
48 | IMAGE_SHAPES,
49 | CARD_SHAPES,
50 | SVG_SHAPES
51 | });
52 |
53 | render() {
54 | return (
55 |
56 |
57 |
58 |
59 |
60 |
61 |
68 |
69 |
70 |
71 | );
72 | }
73 |
74 |
75 | ```
76 |
77 | # api
78 |
79 | |property| description| type| default|
80 | |---|---|---|---|
81 | |SVG_SHAPES|SVG shapes config|Array|[]|
82 | |CARD_SHAPES|card shapes config|Array|[]|
83 | |IMAGE_SHAPES|image shapes config|Array|[]|
84 | |container|container dom selector|selector|
85 | |clickFunc|click event callback|function(cell)|
86 | |doubleClickFunc|double click event callback|function(cell)||
87 | |autoSaveFunc|auto save callback|function(xml)|
88 | |cellCreatedFunc|cell created callback|function(cell)||
89 | |deleteFunc|cell delete callback|function(e)||
90 | |valueChangeFunc|cell value change callback|function(value)||
91 | |initSidebar|init the sidebar|function(elements)||
92 | |initCustomPort|the custom port, 10x10px|function((picture))||
93 | |zoom|zoom|function(type),input params:in(zoom in)、out(zoom out)、actual(zoom actual)||
94 | |updateStyle|update style|function(cell, key, value),input params:cell,key (the key of style),value (the value of style)||
95 | |groupCells|group cells|function(groupId, labelName),input params:groupId(group id),name (group label)||
96 | |ungroupCells|ungroup cells|function(cells)|
97 | |getCellsSelected|get all cells selected|function()||
98 | |getGraphXml|get the xml of graph|function()||
99 | |createVertex|create vertex|function(shapeLabel, x, y, width, height, shapeStyle)|
100 | |insertEdge|insert edge|function(vertex1, vertex2)||
101 | |getCellById|get cell by id|function(id)||
102 | |getAllCells|get all cells|function()|
103 | |refresh|refresh the graph|function()||
104 | |clearSelection|clear the selection in the graph|function()||
105 | |startPanning|start panning|function()||
106 | |stopPanning|stop panning|function()||
107 |
108 |
109 |
--------------------------------------------------------------------------------
/resources/js/util/mxUrlConverter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | *
7 | * Class: mxUrlConverter
8 | *
9 | * Converts relative and absolute URLs to absolute URLs with protocol and domain.
10 | */
11 | var mxUrlConverter = function()
12 | {
13 | // Empty constructor
14 | };
15 |
16 | /**
17 | * Variable: enabled
18 | *
19 | * Specifies if the converter is enabled. Default is true.
20 | */
21 | mxUrlConverter.prototype.enabled = true;
22 |
23 | /**
24 | * Variable: baseUrl
25 | *
26 | * Specifies the base URL to be used as a prefix for relative URLs.
27 | */
28 | mxUrlConverter.prototype.baseUrl = null;
29 |
30 | /**
31 | * Variable: baseDomain
32 | *
33 | * Specifies the base domain to be used as a prefix for absolute URLs.
34 | */
35 | mxUrlConverter.prototype.baseDomain = null;
36 |
37 | /**
38 | * Function: updateBaseUrl
39 | *
40 | * Private helper function to update the base URL.
41 | */
42 | mxUrlConverter.prototype.updateBaseUrl = function()
43 | {
44 | this.baseDomain = location.protocol + '//' + location.host;
45 | this.baseUrl = this.baseDomain + location.pathname;
46 | var tmp = this.baseUrl.lastIndexOf('/');
47 |
48 | // Strips filename etc
49 | if (tmp > 0)
50 | {
51 | this.baseUrl = this.baseUrl.substring(0, tmp + 1);
52 | }
53 | };
54 |
55 | /**
56 | * Function: isEnabled
57 | *
58 | * Returns .
59 | */
60 | mxUrlConverter.prototype.isEnabled = function()
61 | {
62 | return this.enabled;
63 | };
64 |
65 | /**
66 | * Function: setEnabled
67 | *
68 | * Sets .
69 | */
70 | mxUrlConverter.prototype.setEnabled = function(value)
71 | {
72 | this.enabled = value;
73 | };
74 |
75 | /**
76 | * Function: getBaseUrl
77 | *
78 | * Returns .
79 | */
80 | mxUrlConverter.prototype.getBaseUrl = function()
81 | {
82 | return this.baseUrl;
83 | };
84 |
85 | /**
86 | * Function: setBaseUrl
87 | *
88 | * Sets .
89 | */
90 | mxUrlConverter.prototype.setBaseUrl = function(value)
91 | {
92 | this.baseUrl = value;
93 | };
94 |
95 | /**
96 | * Function: getBaseDomain
97 | *
98 | * Returns .
99 | */
100 | mxUrlConverter.prototype.getBaseDomain = function()
101 | {
102 | return this.baseDomain;
103 | },
104 |
105 | /**
106 | * Function: setBaseDomain
107 | *
108 | * Sets .
109 | */
110 | mxUrlConverter.prototype.setBaseDomain = function(value)
111 | {
112 | this.baseDomain = value;
113 | },
114 |
115 | /**
116 | * Function: isRelativeUrl
117 | *
118 | * Returns true if the given URL is relative.
119 | */
120 | mxUrlConverter.prototype.isRelativeUrl = function(url)
121 | {
122 | return url.substring(0, 2) != '//' && url.substring(0, 7) != 'http://' &&
123 | url.substring(0, 8) != 'https://' && url.substring(0, 10) != 'data:image' &&
124 | url.substring(0, 7) != 'file://';
125 | };
126 |
127 | /**
128 | * Function: convert
129 | *
130 | * Converts the given URL to an absolute URL with protol and domain.
131 | * Relative URLs are first converted to absolute URLs.
132 | */
133 | mxUrlConverter.prototype.convert = function(url)
134 | {
135 | if (this.isEnabled() && this.isRelativeUrl(url))
136 | {
137 | if (this.getBaseUrl() == null)
138 | {
139 | this.updateBaseUrl();
140 | }
141 |
142 | if (url.charAt(0) == '/')
143 | {
144 | url = this.getBaseDomain() + url;
145 | }
146 | else
147 | {
148 | url = this.getBaseUrl() + url;
149 | }
150 | }
151 |
152 | return url;
153 | };
154 |
155 | window.mxUrlConverter = mxUrlConverter;
--------------------------------------------------------------------------------
/resources/js/view/mxTemporaryCellStates.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2017, JGraph Ltd
3 | * Copyright (c) 2006-2017, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxTemporaryCellStates
7 | *
8 | * Creates a temporary set of cell states.
9 | */
10 | function mxTemporaryCellStates(view, scale, cells, isCellVisibleFn, getLinkForCellState)
11 | {
12 | scale = (scale != null) ? scale : 1;
13 | this.view = view;
14 |
15 | // Stores the previous state
16 | this.oldValidateCellState = view.validateCellState;
17 | this.oldBounds = view.getGraphBounds();
18 | this.oldStates = view.getStates();
19 | this.oldScale = view.getScale();
20 | this.oldDoRedrawShape = view.graph.cellRenderer.doRedrawShape;
21 |
22 | var self = this;
23 |
24 | // Overrides doRedrawShape and paint shape to add links on shapes
25 | if (getLinkForCellState != null)
26 | {
27 | view.graph.cellRenderer.doRedrawShape = function(state)
28 | {
29 | var oldPaint = state.shape.paint;
30 |
31 | state.shape.paint = function(c)
32 | {
33 | var link = getLinkForCellState(state);
34 |
35 | if (link != null)
36 | {
37 | c.setLink(link);
38 | }
39 |
40 | oldPaint.apply(this, arguments);
41 |
42 | if (link != null)
43 | {
44 | c.setLink(null);
45 | }
46 | };
47 |
48 | self.oldDoRedrawShape.apply(view.graph.cellRenderer, arguments);
49 | state.shape.paint = oldPaint;
50 | };
51 | }
52 |
53 | // Overrides validateCellState to ignore invisible cells
54 | view.validateCellState = function(cell, resurse)
55 | {
56 | if (cell == null || isCellVisibleFn == null || isCellVisibleFn(cell))
57 | {
58 | return self.oldValidateCellState.apply(view, arguments);
59 | }
60 |
61 | return null;
62 | };
63 |
64 | // Creates space for new states
65 | view.setStates(new mxDictionary());
66 | view.setScale(scale);
67 |
68 | if (cells != null)
69 | {
70 | view.resetValidationState();
71 | var bbox = null;
72 |
73 | // Validates the vertices and edges without adding them to
74 | // the model so that the original cells are not modified
75 | for (var i = 0; i < cells.length; i++)
76 | {
77 | var bounds = view.getBoundingBox(view.validateCellState(view.validateCell(cells[i])));
78 |
79 | if (bbox == null)
80 | {
81 | bbox = bounds;
82 | }
83 | else
84 | {
85 | bbox.add(bounds);
86 | }
87 | }
88 |
89 | view.setGraphBounds(bbox || new mxRectangle());
90 | }
91 | };
92 |
93 | /**
94 | * Variable: view
95 | *
96 | * Holds the width of the rectangle. Default is 0.
97 | */
98 | mxTemporaryCellStates.prototype.view = null;
99 |
100 | /**
101 | * Variable: oldStates
102 | *
103 | * Holds the height of the rectangle. Default is 0.
104 | */
105 | mxTemporaryCellStates.prototype.oldStates = null;
106 |
107 | /**
108 | * Variable: oldBounds
109 | *
110 | * Holds the height of the rectangle. Default is 0.
111 | */
112 | mxTemporaryCellStates.prototype.oldBounds = null;
113 |
114 | /**
115 | * Variable: oldScale
116 | *
117 | * Holds the height of the rectangle. Default is 0.
118 | */
119 | mxTemporaryCellStates.prototype.oldScale = null;
120 |
121 | /**
122 | * Function: destroy
123 | *
124 | * Returns the top, left corner as a new .
125 | */
126 | mxTemporaryCellStates.prototype.destroy = function()
127 | {
128 | this.view.setScale(this.oldScale);
129 | this.view.setStates(this.oldStates);
130 | this.view.setGraphBounds(this.oldBounds);
131 | this.view.validateCellState = this.oldValidateCellState;
132 | this.view.graph.cellRenderer.doRedrawShape = this.oldDoRedrawShape;
133 | };
134 |
135 | window.mxTemporaryCellStates = mxTemporaryCellStates;
136 |
--------------------------------------------------------------------------------
/resources/js/handler/mxCellTracker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxCellTracker
7 | *
8 | * Event handler that highlights cells. Inherits from .
9 | *
10 | * Example:
11 | *
12 | * (code)
13 | * new mxCellTracker(graph, '#00FF00');
14 | * (end)
15 | *
16 | * For detecting dragEnter, dragOver and dragLeave on cells, the following
17 | * code can be used:
18 | *
19 | * (code)
20 | * graph.addMouseListener(
21 | * {
22 | * cell: null,
23 | * mouseDown: function(sender, me) { },
24 | * mouseMove: function(sender, me)
25 | * {
26 | * var tmp = me.getCell();
27 | *
28 | * if (tmp != this.cell)
29 | * {
30 | * if (this.cell != null)
31 | * {
32 | * this.dragLeave(me.getEvent(), this.cell);
33 | * }
34 | *
35 | * this.cell = tmp;
36 | *
37 | * if (this.cell != null)
38 | * {
39 | * this.dragEnter(me.getEvent(), this.cell);
40 | * }
41 | * }
42 | *
43 | * if (this.cell != null)
44 | * {
45 | * this.dragOver(me.getEvent(), this.cell);
46 | * }
47 | * },
48 | * mouseUp: function(sender, me) { },
49 | * dragEnter: function(evt, cell)
50 | * {
51 | * mxLog.debug('dragEnter', cell.value);
52 | * },
53 | * dragOver: function(evt, cell)
54 | * {
55 | * mxLog.debug('dragOver', cell.value);
56 | * },
57 | * dragLeave: function(evt, cell)
58 | * {
59 | * mxLog.debug('dragLeave', cell.value);
60 | * }
61 | * });
62 | * (end)
63 | *
64 | * Constructor: mxCellTracker
65 | *
66 | * Constructs an event handler that highlights cells.
67 | *
68 | * Parameters:
69 | *
70 | * graph - Reference to the enclosing .
71 | * color - Color of the highlight. Default is blue.
72 | * funct - Optional JavaScript function that is used to override
73 | * .
74 | */
75 | function mxCellTracker(graph, color, funct) {
76 | mxCellMarker.call(this, graph, color);
77 |
78 | this.graph.addMouseListener(this);
79 |
80 | if (funct != null) {
81 | this.getCell = funct;
82 | }
83 |
84 | // Automatic deallocation of memory
85 | if (mxClient.IS_IE) {
86 | mxEvent.addListener(window, 'unload', mxUtils.bind(this, function () {
87 | this.destroy();
88 | }));
89 | }
90 | }
91 |
92 | /**
93 | * Extends mxCellMarker.
94 | */
95 | mxUtils.extend(mxCellTracker, mxCellMarker);
96 |
97 | /**
98 | * Function: mouseDown
99 | *
100 | * Ignores the event. The event is not consumed.
101 | */
102 | mxCellTracker.prototype.mouseDown = function (sender, me) {
103 | };
104 |
105 | /**
106 | * Function: mouseMove
107 | *
108 | * Handles the event by highlighting the cell under the mousepointer if it
109 | * is over the hotspot region of the cell.
110 | */
111 | mxCellTracker.prototype.mouseMove = function (sender, me) {
112 | if (this.isEnabled()) {
113 | this.process(me);
114 | }
115 | };
116 |
117 | /**
118 | * Function: mouseUp
119 | *
120 | * Handles the event by reseting the highlight.
121 | */
122 | mxCellTracker.prototype.mouseUp = function (sender, me) {};
123 |
124 | /**
125 | * Function: destroy
126 | *
127 | * Destroys the object and all its resources and DOM nodes. This doesn't
128 | * normally need to be called. It is called automatically when the window
129 | * unloads.
130 | */
131 | mxCellTracker.prototype.destroy = function () {
132 | if (!this.destroyed) {
133 | this.destroyed = true;
134 |
135 | this.graph.removeMouseListener(this);
136 | mxCellMarker.prototype.destroy.apply(this);
137 | }
138 | };
139 |
140 | window.mxCellTracker = mxCellTracker;
141 |
--------------------------------------------------------------------------------
/resources/js/layout/hierarchical/stage/mxMinimumCycleRemover.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxMinimumCycleRemover
7 | *
8 | * An implementation of the first stage of the Sugiyama layout. Straightforward
9 | * longest path calculation of layer assignment
10 | *
11 | * Constructor: mxMinimumCycleRemover
12 | *
13 | * Creates a cycle remover for the given internal model.
14 | */
15 | function mxMinimumCycleRemover(layout)
16 | {
17 | this.layout = layout;
18 | };
19 |
20 | /**
21 | * Extends mxHierarchicalLayoutStage.
22 | */
23 | mxMinimumCycleRemover.prototype = new mxHierarchicalLayoutStage();
24 | mxMinimumCycleRemover.prototype.constructor = mxMinimumCycleRemover;
25 |
26 | /**
27 | * Variable: layout
28 | *
29 | * Reference to the enclosing .
30 | */
31 | mxMinimumCycleRemover.prototype.layout = null;
32 |
33 | /**
34 | * Function: execute
35 | *
36 | * Takes the graph detail and configuration information within the facade
37 | * and creates the resulting laid out graph within that facade for further
38 | * use.
39 | */
40 | mxMinimumCycleRemover.prototype.execute = function(parent)
41 | {
42 | var model = this.layout.getModel();
43 | var seenNodes = new Object();
44 | var unseenNodesArray = model.vertexMapper.getValues();
45 | var unseenNodes = new Object();
46 |
47 | for (var i = 0; i < unseenNodesArray.length; i++)
48 | {
49 | unseenNodes[unseenNodesArray[i].id] = unseenNodesArray[i];
50 | }
51 |
52 | // Perform a dfs through the internal model. If a cycle is found,
53 | // reverse it.
54 | var rootsArray = null;
55 |
56 | if (model.roots != null)
57 | {
58 | var modelRoots = model.roots;
59 | rootsArray = [];
60 |
61 | for (var i = 0; i < modelRoots.length; i++)
62 | {
63 | rootsArray[i] = model.vertexMapper.get(modelRoots[i]);
64 | }
65 | }
66 |
67 | model.visit(function(parent, node, connectingEdge, layer, seen)
68 | {
69 | // Check if the cell is in it's own ancestor list, if so
70 | // invert the connecting edge and reverse the target/source
71 | // relationship to that edge in the parent and the cell
72 | if (node.isAncestor(parent))
73 | {
74 | connectingEdge.invert();
75 | mxUtils.remove(connectingEdge, parent.connectsAsSource);
76 | parent.connectsAsTarget.push(connectingEdge);
77 | mxUtils.remove(connectingEdge, node.connectsAsTarget);
78 | node.connectsAsSource.push(connectingEdge);
79 | }
80 |
81 | seenNodes[node.id] = node;
82 | delete unseenNodes[node.id];
83 | }, rootsArray, true, null);
84 |
85 | // If there are any nodes that should be nodes that the dfs can miss
86 | // these need to be processed with the dfs and the roots assigned
87 | // correctly to form a correct internal model
88 | var seenNodesCopy = mxUtils.clone(seenNodes, null, true);
89 |
90 | // Pick a random cell and dfs from it
91 | model.visit(function(parent, node, connectingEdge, layer, seen)
92 | {
93 | // Check if the cell is in it's own ancestor list, if so
94 | // invert the connecting edge and reverse the target/source
95 | // relationship to that edge in the parent and the cell
96 | if (node.isAncestor(parent))
97 | {
98 | connectingEdge.invert();
99 | mxUtils.remove(connectingEdge, parent.connectsAsSource);
100 | node.connectsAsSource.push(connectingEdge);
101 | parent.connectsAsTarget.push(connectingEdge);
102 | mxUtils.remove(connectingEdge, node.connectsAsTarget);
103 | }
104 |
105 | seenNodes[node.id] = node;
106 | delete unseenNodes[node.id];
107 | }, unseenNodes, true, seenNodesCopy);
108 | };
109 |
110 | window.mxMinimumCycleRemover = mxMinimumCycleRemover;
111 |
--------------------------------------------------------------------------------
/resources/js/shape/mxRectangleShape.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxRectangleShape
7 | *
8 | * Extends to implement a rectangle shape.
9 | * This shape is registered under
10 | * in .
11 | *
12 | * Constructor: mxRectangleShape
13 | *
14 | * Constructs a new rectangle shape.
15 | *
16 | * Parameters:
17 | *
18 | * bounds - that defines the bounds. This is stored in
19 | * .
20 | * fill - String that defines the fill color. This is stored in .
21 | * stroke - String that defines the stroke color. This is stored in .
22 | * strokewidth - Optional integer that defines the stroke width. Default is
23 | * 1. This is stored in .
24 | */
25 | function mxRectangleShape(bounds, fill, stroke, strokewidth)
26 | {
27 | mxShape.call(this);
28 | this.bounds = bounds;
29 | this.fill = fill;
30 | this.stroke = stroke;
31 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
32 | };
33 |
34 | /**
35 | * Extends mxShape.
36 | */
37 | mxUtils.extend(mxRectangleShape, mxShape);
38 |
39 | /**
40 | * Function: isHtmlAllowed
41 | *
42 | * Returns true for non-rounded, non-rotated shapes with no glass gradient.
43 | */
44 | mxRectangleShape.prototype.isHtmlAllowed = function()
45 | {
46 | var events = true;
47 |
48 | if (this.style != null)
49 | {
50 | events = mxUtils.getValue(this.style, mxConstants.STYLE_POINTER_EVENTS, '1') == '1';
51 | }
52 |
53 | return !this.isRounded && !this.glass && this.rotation == 0 && (events ||
54 | (this.fill != null && this.fill != mxConstants.NONE));
55 | };
56 |
57 | /**
58 | * Function: paintBackground
59 | *
60 | * Generic background painting implementation.
61 | */
62 | mxRectangleShape.prototype.paintBackground = function(c, x, y, w, h)
63 | {
64 | var events = true;
65 |
66 | if (this.style != null)
67 | {
68 | events = mxUtils.getValue(this.style, mxConstants.STYLE_POINTER_EVENTS, '1') == '1';
69 | }
70 |
71 | if (events || (this.fill != null && this.fill != mxConstants.NONE) ||
72 | (this.stroke != null && this.stroke != mxConstants.NONE))
73 | {
74 | if (!events && (this.fill == null || this.fill == mxConstants.NONE))
75 | {
76 | c.pointerEvents = false;
77 | }
78 |
79 | if (this.isRounded)
80 | {
81 | var r = 0;
82 |
83 | if (mxUtils.getValue(this.style, mxConstants.STYLE_ABSOLUTE_ARCSIZE, 0) == '1')
84 | {
85 | r = Math.min(w / 2, Math.min(h / 2, mxUtils.getValue(this.style,
86 | mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2));
87 | }
88 | else
89 | {
90 | var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE,
91 | mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100;
92 | r = Math.min(w * f, h * f);
93 | }
94 |
95 | c.roundrect(x, y, w, h, r, r);
96 | }
97 | else
98 | {
99 | c.rect(x, y, w, h);
100 | }
101 |
102 | c.fillAndStroke();
103 | }
104 | };
105 |
106 | /**
107 | * Function: isRoundable
108 | *
109 | * Adds roundable support.
110 | */
111 | mxRectangleShape.prototype.isRoundable = function(c, x, y, w, h)
112 | {
113 | return true;
114 | };
115 |
116 | /**
117 | * Function: paintForeground
118 | *
119 | * Generic background painting implementation.
120 | */
121 | mxRectangleShape.prototype.paintForeground = function(c, x, y, w, h)
122 | {
123 | if (this.glass && !this.outline && this.fill != null && this.fill != mxConstants.NONE)
124 | {
125 | this.paintGlassEffect(c, x, y, w, h, this.getArcSize(w + this.strokewidth, h + this.strokewidth));
126 | }
127 | };
128 |
129 | window.mxRectangleShape = mxRectangleShape;
130 |
--------------------------------------------------------------------------------
/resources/js/model/mxCellPath.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | var mxCellPath =
6 | {
7 |
8 | /**
9 | * Class: mxCellPath
10 | *
11 | * Implements a mechanism for temporary cell Ids.
12 | *
13 | * Variable: PATH_SEPARATOR
14 | *
15 | * Defines the separator between the path components. Default is ".".
16 | */
17 | PATH_SEPARATOR: '.',
18 |
19 | /**
20 | * Function: create
21 | *
22 | * Creates the cell path for the given cell. The cell path is a
23 | * concatenation of the indices of all ancestors on the (finite) path to
24 | * the root, eg. "0.0.0.1".
25 | *
26 | * Parameters:
27 | *
28 | * cell - Cell whose path should be returned.
29 | */
30 | create: function(cell)
31 | {
32 | var result = '';
33 |
34 | if (cell != null)
35 | {
36 | var parent = cell.getParent();
37 |
38 | while (parent != null)
39 | {
40 | var index = parent.getIndex(cell);
41 | result = index + mxCellPath.PATH_SEPARATOR + result;
42 |
43 | cell = parent;
44 | parent = cell.getParent();
45 | }
46 | }
47 |
48 | // Removes trailing separator
49 | var n = result.length;
50 |
51 | if (n > 1)
52 | {
53 | result = result.substring(0, n - 1);
54 | }
55 |
56 | return result;
57 | },
58 |
59 | /**
60 | * Function: getParentPath
61 | *
62 | * Returns the path for the parent of the cell represented by the given
63 | * path. Returns null if the given path has no parent.
64 | *
65 | * Parameters:
66 | *
67 | * path - Path whose parent path should be returned.
68 | */
69 | getParentPath: function(path)
70 | {
71 | if (path != null)
72 | {
73 | var index = path.lastIndexOf(mxCellPath.PATH_SEPARATOR);
74 |
75 | if (index >= 0)
76 | {
77 | return path.substring(0, index);
78 | }
79 | else if (path.length > 0)
80 | {
81 | return '';
82 | }
83 | }
84 |
85 | return null;
86 | },
87 |
88 | /**
89 | * Function: resolve
90 | *
91 | * Returns the cell for the specified cell path using the given root as the
92 | * root of the path.
93 | *
94 | * Parameters:
95 | *
96 | * root - Root cell of the path to be resolved.
97 | * path - String that defines the path.
98 | */
99 | resolve: function(root, path)
100 | {
101 | var parent = root;
102 |
103 | if (path != null)
104 | {
105 | var tokens = path.split(mxCellPath.PATH_SEPARATOR);
106 |
107 | for (var i=0; i p2[i]) ? 1 : -1);
135 | }
136 | else
137 | {
138 | var t1 = parseInt(p1[i]);
139 | var t2 = parseInt(p2[i]);
140 |
141 | comp = (t1 == t2) ? 0 : ((t1 > t2) ? 1 : -1);
142 | }
143 |
144 | break;
145 | }
146 | }
147 |
148 | // Compares path length if both paths are equal to this point
149 | if (comp == 0)
150 | {
151 | var t1 = p1.length;
152 | var t2 = p2.length;
153 |
154 | if (t1 != t2)
155 | {
156 | comp = (t1 > t2) ? 1 : -1;
157 | }
158 | }
159 |
160 | return comp;
161 | }
162 |
163 | };
164 |
165 | window.mxCellPath = mxCellPath;
166 |
--------------------------------------------------------------------------------
/resources/js/shape/mxArrow.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxArrow
7 | *
8 | * Extends to implement an arrow shape. (The shape
9 | * is used to represent edges, not vertices.)
10 | * This shape is registered under
11 | * in .
12 | *
13 | * Constructor: mxArrow
14 | *
15 | * Constructs a new arrow shape.
16 | *
17 | * Parameters:
18 | *
19 | * points - Array of that define the points. This is stored in
20 | * .
21 | * fill - String that defines the fill color. This is stored in .
22 | * stroke - String that defines the stroke color. This is stored in .
23 | * strokewidth - Optional integer that defines the stroke width. Default is
24 | * 1. This is stored in .
25 | * arrowWidth - Optional integer that defines the arrow width. Default is
26 | * . This is stored in .
27 | * spacing - Optional integer that defines the spacing between the arrow shape
28 | * and its endpoints. Default is . This is stored in
29 | * .
30 | * endSize - Optional integer that defines the size of the arrowhead. Default
31 | * is . This is stored in .
32 | */
33 | function mxArrow(points, fill, stroke, strokewidth, arrowWidth, spacing, endSize)
34 | {
35 | mxShape.call(this);
36 | this.points = points;
37 | this.fill = fill;
38 | this.stroke = stroke;
39 | this.strokewidth = (strokewidth != null) ? strokewidth : 1;
40 | this.arrowWidth = (arrowWidth != null) ? arrowWidth : mxConstants.ARROW_WIDTH;
41 | this.spacing = (spacing != null) ? spacing : mxConstants.ARROW_SPACING;
42 | this.endSize = (endSize != null) ? endSize : mxConstants.ARROW_SIZE;
43 | };
44 |
45 | /**
46 | * Extends mxShape.
47 | */
48 | mxUtils.extend(mxArrow, mxShape);
49 |
50 | /**
51 | * Function: augmentBoundingBox
52 | *
53 | * Augments the bounding box with the edge width and markers.
54 | */
55 | mxArrow.prototype.augmentBoundingBox = function(bbox)
56 | {
57 | mxShape.prototype.augmentBoundingBox.apply(this, arguments);
58 |
59 | var w = Math.max(this.arrowWidth, this.endSize);
60 | bbox.grow((w / 2 + this.strokewidth) * this.scale);
61 | };
62 |
63 | /**
64 | * Function: paintEdgeShape
65 | *
66 | * Paints the line shape.
67 | */
68 | mxArrow.prototype.paintEdgeShape = function(c, pts)
69 | {
70 | // Geometry of arrow
71 | var spacing = mxConstants.ARROW_SPACING;
72 | var width = mxConstants.ARROW_WIDTH;
73 | var arrow = mxConstants.ARROW_SIZE;
74 |
75 | // Base vector (between end points)
76 | var p0 = pts[0];
77 | var pe = pts[pts.length - 1];
78 | var dx = pe.x - p0.x;
79 | var dy = pe.y - p0.y;
80 | var dist = Math.sqrt(dx * dx + dy * dy);
81 | var length = dist - 2 * spacing - arrow;
82 |
83 | // Computes the norm and the inverse norm
84 | var nx = dx / dist;
85 | var ny = dy / dist;
86 | var basex = length * nx;
87 | var basey = length * ny;
88 | var floorx = width * ny/3;
89 | var floory = -width * nx/3;
90 |
91 | // Computes points
92 | var p0x = p0.x - floorx / 2 + spacing * nx;
93 | var p0y = p0.y - floory / 2 + spacing * ny;
94 | var p1x = p0x + floorx;
95 | var p1y = p0y + floory;
96 | var p2x = p1x + basex;
97 | var p2y = p1y + basey;
98 | var p3x = p2x + floorx;
99 | var p3y = p2y + floory;
100 | // p4 not necessary
101 | var p5x = p3x - 3 * floorx;
102 | var p5y = p3y - 3 * floory;
103 |
104 | c.begin();
105 | c.moveTo(p0x, p0y);
106 | c.lineTo(p1x, p1y);
107 | c.lineTo(p2x, p2y);
108 | c.lineTo(p3x, p3y);
109 | c.lineTo(pe.x - spacing * nx, pe.y - spacing * ny);
110 | c.lineTo(p5x, p5y);
111 | c.lineTo(p5x + floorx, p5y + floory);
112 | c.close();
113 |
114 | c.fillAndStroke();
115 | };
116 |
117 | window.mxArrow = mxArrow;
118 |
--------------------------------------------------------------------------------
/resources/js/util/mxImageBundle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxImageBundle
7 | *
8 | * Maps from keys to base64 encoded images or file locations. All values must
9 | * be URLs or use the format data:image/format followed by a comma and the base64
10 | * encoded image data, eg. "data:image/gif,XYZ", where XYZ is the base64 encoded
11 | * image data.
12 | *
13 | * To add a new image bundle to an existing graph, the following code is used:
14 | *
15 | * (code)
16 | * var bundle = new mxImageBundle(alt);
17 | * bundle.putImage('myImage', 'data:image/gif,R0lGODlhEAAQAMIGAAAAAICAAICAgP' +
18 | * '//AOzp2O3r2////////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgAHACwAAAAA' +
19 | * 'EAAQAAADTXi63AowynnAMDfjPUDlnAAJhmeBFxAEloliKltWmiYCQvfVr6lBPB1ggxN1hi' +
20 | * 'laSSASFQpIV5HJBDyHpqK2ejVRm2AAgZCdmCGO9CIBADs=', fallback);
21 | * bundle.putImage('mySvgImage', 'data:image/svg+xml,' + encodeURIComponent(
22 | * ''), fallback);
26 | * graph.addImageBundle(bundle);
27 | * (end);
28 | *
29 | * Alt is an optional boolean (default is false) that specifies if the value
30 | * or the fallback should be returned in .
31 | *
32 | * The image can then be referenced in any cell style using image=myImage.
33 | * If you are using mxOutline, you should use the same image bundles in the
34 | * graph that renders the outline.
35 | *
36 | * The keys for images are resolved in and
37 | * turned into a data URI if the returned value has a short data URI format
38 | * as specified above.
39 | *
40 | * A typical value for the fallback is a MTHML link as defined in RFC 2557.
41 | * Note that this format requires a file to be dynamically created on the
42 | * server-side, or the page that contains the graph to be modified to contain
43 | * the resources, this can be done by adding a comment that contains the
44 | * resource in the HEAD section of the page after the title tag.
45 | *
46 | * This type of fallback mechanism should be used in IE6 and IE7. IE8 does
47 | * support data URIs, but the maximum size is limited to 32 KB, which means
48 | * all data URIs should be limited to 32 KB.
49 | */
50 | function mxImageBundle(alt)
51 | {
52 | this.images = [];
53 | this.alt = (alt != null) ? alt : false;
54 | };
55 |
56 | /**
57 | * Variable: images
58 | *
59 | * Maps from keys to images.
60 | */
61 | mxImageBundle.prototype.images = null;
62 |
63 | /**
64 | * Variable: alt
65 | *
66 | * Specifies if the fallback representation should be returned.
67 | */
68 | mxImageBundle.prototype.images = null;
69 |
70 | /**
71 | * Function: putImage
72 | *
73 | * Adds the specified entry to the map. The entry is an object with a value and
74 | * fallback property as specified in the arguments.
75 | */
76 | mxImageBundle.prototype.putImage = function(key, value, fallback)
77 | {
78 | this.images[key] = {value: value, fallback: fallback};
79 | };
80 |
81 | /**
82 | * Function: getImage
83 | *
84 | * Returns the value for the given key. This returns the value
85 | * or fallback, depending on . The fallback is returned if
86 | * is true, the value is returned otherwise.
87 | */
88 | mxImageBundle.prototype.getImage = function(key)
89 | {
90 | var result = null;
91 |
92 | if (key != null)
93 | {
94 | var img = this.images[key];
95 |
96 | if (img != null)
97 | {
98 | result = (this.alt) ? img.fallback : img.value;
99 | }
100 | }
101 |
102 | return result;
103 | };
104 |
105 | window.mxImageBundle = mxImageBundle;
--------------------------------------------------------------------------------
/resources/js/editor/mxDefaultKeyHandler.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxDefaultKeyHandler
7 | *
8 | * Binds keycodes to actionnames in an editor. This aggregates an internal
9 | * and extends the implementation of to not
10 | * only cancel the editing, but also hide the properties dialog and fire an
11 | * event via . An instance of this class is created
12 | * by and stored in .
13 | *
14 | * Example:
15 | *
16 | * Bind the delete key to the delete action in an existing editor.
17 | *
18 | * (code)
19 | * var keyHandler = new mxDefaultKeyHandler(editor);
20 | * keyHandler.bindAction(46, 'delete');
21 | * (end)
22 | *
23 | * Codec:
24 | *
25 | * This class uses the to read configuration
26 | * data into an existing instance. See for a
27 | * description of the configuration format.
28 | *
29 | * Keycodes:
30 | *
31 | * See .
32 | *
33 | * An event is fired via the editor if the escape key is
34 | * pressed.
35 | *
36 | * Constructor: mxDefaultKeyHandler
37 | *
38 | * Constructs a new default key handler for the in the
39 | * given . (The editor may be null if a prototypical instance for
40 | * a is created.)
41 | *
42 | * Parameters:
43 | *
44 | * editor - Reference to the enclosing .
45 | */
46 | function mxDefaultKeyHandler(editor)
47 | {
48 | if (editor != null)
49 | {
50 | this.editor = editor;
51 | this.handler = new mxKeyHandler(editor.graph);
52 |
53 | // Extends the escape function of the internal key
54 | // handle to hide the properties dialog and fire
55 | // the escape event via the editor instance
56 | var old = this.handler.escape;
57 |
58 | this.handler.escape = function(evt)
59 | {
60 | old.apply(this, arguments);
61 | editor.hideProperties();
62 | editor.fireEvent(new mxEventObject(mxEvent.ESCAPE, 'event', evt));
63 | };
64 | }
65 | };
66 |
67 | /**
68 | * Variable: editor
69 | *
70 | * Reference to the enclosing .
71 | */
72 | mxDefaultKeyHandler.prototype.editor = null;
73 |
74 | /**
75 | * Variable: handler
76 | *
77 | * Holds the for key event handling.
78 | */
79 | mxDefaultKeyHandler.prototype.handler = null;
80 |
81 | /**
82 | * Function: bindAction
83 | *
84 | * Binds the specified keycode to the given action in . The
85 | * optional control flag specifies if the control key must be pressed
86 | * to trigger the action.
87 | *
88 | * Parameters:
89 | *
90 | * code - Integer that specifies the keycode.
91 | * action - Name of the action to execute in .
92 | * control - Optional boolean that specifies if control must be pressed.
93 | * Default is false.
94 | */
95 | mxDefaultKeyHandler.prototype.bindAction = function (code, action, control)
96 | {
97 | var keyHandler = mxUtils.bind(this, function()
98 | {
99 | this.editor.execute(action);
100 | });
101 |
102 | // Binds the function to control-down keycode
103 | if (control)
104 | {
105 | this.handler.bindControlKey(code, keyHandler);
106 | }
107 |
108 | // Binds the function to the normal keycode
109 | else
110 | {
111 | this.handler.bindKey(code, keyHandler);
112 | }
113 | };
114 |
115 | /**
116 | * Function: destroy
117 | *
118 | * Destroys the associated with this object. This does normally
119 | * not need to be called, the is destroyed automatically when the
120 | * window unloads (in IE) by .
121 | */
122 | mxDefaultKeyHandler.prototype.destroy = function ()
123 | {
124 | this.handler.destroy();
125 | this.handler = null;
126 | };
127 |
128 | window.mxDefaultKeyHandler = mxDefaultKeyHandler;
129 |
--------------------------------------------------------------------------------
/resources/js/util/mxDivResizer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxDivResizer
7 | *
8 | * Maintains the size of a div element in Internet Explorer. This is a
9 | * workaround for the right and bottom style being ignored in IE.
10 | *
11 | * If you need a div to cover the scrollwidth and -height of a document,
12 | * then you can use this class as follows:
13 | *
14 | * (code)
15 | * var resizer = new mxDivResizer(background);
16 | * resizer.getDocumentHeight = function()
17 | * {
18 | * return document.body.scrollHeight;
19 | * }
20 | * resizer.getDocumentWidth = function()
21 | * {
22 | * return document.body.scrollWidth;
23 | * }
24 | * resizer.resize();
25 | * (end)
26 | *
27 | * Constructor: mxDivResizer
28 | *
29 | * Constructs an object that maintains the size of a div
30 | * element when the window is being resized. This is only
31 | * required for Internet Explorer as it ignores the respective
32 | * stylesheet information for DIV elements.
33 | *
34 | * Parameters:
35 | *
36 | * div - Reference to the DOM node whose size should be maintained.
37 | * container - Optional Container that contains the div. Default is the
38 | * window.
39 | */
40 | function mxDivResizer(div, container)
41 | {
42 | if (div.nodeName.toLowerCase() == 'div')
43 | {
44 | if (container == null)
45 | {
46 | container = window;
47 | }
48 |
49 | this.div = div;
50 | var style = mxUtils.getCurrentStyle(div);
51 |
52 | if (style != null)
53 | {
54 | this.resizeWidth = style.width == 'auto';
55 | this.resizeHeight = style.height == 'auto';
56 | }
57 |
58 | mxEvent.addListener(container, 'resize',
59 | mxUtils.bind(this, function(evt)
60 | {
61 | if (!this.handlingResize)
62 | {
63 | this.handlingResize = true;
64 | this.resize();
65 | this.handlingResize = false;
66 | }
67 | })
68 | );
69 |
70 | this.resize();
71 | }
72 | };
73 |
74 | /**
75 | * Function: resizeWidth
76 | *
77 | * Boolean specifying if the width should be updated.
78 | */
79 | mxDivResizer.prototype.resizeWidth = true;
80 |
81 | /**
82 | * Function: resizeHeight
83 | *
84 | * Boolean specifying if the height should be updated.
85 | */
86 | mxDivResizer.prototype.resizeHeight = true;
87 |
88 | /**
89 | * Function: handlingResize
90 | *
91 | * Boolean specifying if the width should be updated.
92 | */
93 | mxDivResizer.prototype.handlingResize = false;
94 |
95 | /**
96 | * Function: resize
97 | *
98 | * Updates the style of the DIV after the window has been resized.
99 | */
100 | mxDivResizer.prototype.resize = function()
101 | {
102 | var w = this.getDocumentWidth();
103 | var h = this.getDocumentHeight();
104 |
105 | var l = parseInt(this.div.style.left);
106 | var r = parseInt(this.div.style.right);
107 | var t = parseInt(this.div.style.top);
108 | var b = parseInt(this.div.style.bottom);
109 |
110 | if (this.resizeWidth &&
111 | !isNaN(l) &&
112 | !isNaN(r) &&
113 | l >= 0 &&
114 | r >= 0 &&
115 | w - r - l > 0)
116 | {
117 | this.div.style.width = (w - r - l)+'px';
118 | }
119 |
120 | if (this.resizeHeight &&
121 | !isNaN(t) &&
122 | !isNaN(b) &&
123 | t >= 0 &&
124 | b >= 0 &&
125 | h - t - b > 0)
126 | {
127 | this.div.style.height = (h - t - b)+'px';
128 | }
129 | };
130 |
131 | /**
132 | * Function: getDocumentWidth
133 | *
134 | * Hook for subclassers to return the width of the document (without
135 | * scrollbars).
136 | */
137 | mxDivResizer.prototype.getDocumentWidth = function()
138 | {
139 | return document.body.clientWidth;
140 | };
141 |
142 | /**
143 | * Function: getDocumentHeight
144 | *
145 | * Hook for subclassers to return the height of the document (without
146 | * scrollbars).
147 | */
148 | mxDivResizer.prototype.getDocumentHeight = function()
149 | {
150 | return document.body.clientHeight;
151 | };
152 |
153 | window.mxDivResizer = mxDivResizer;
--------------------------------------------------------------------------------
/resources/js/layout/mxEdgeLabelLayout.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxEdgeLabelLayout
7 | *
8 | * Extends to implement an edge label layout. This layout
9 | * makes use of cell states, which means the graph must be validated in
10 | * a graph view (so that the label bounds are available) before this layout
11 | * can be executed.
12 | *
13 | * Example:
14 | *
15 | * (code)
16 | * var layout = new mxEdgeLabelLayout(graph);
17 | * layout.execute(graph.getDefaultParent());
18 | * (end)
19 | *
20 | * Constructor: mxEdgeLabelLayout
21 | *
22 | * Constructs a new edge label layout.
23 | *
24 | * Arguments:
25 | *
26 | * graph - that contains the cells.
27 | */
28 | function mxEdgeLabelLayout(graph, radius)
29 | {
30 | mxGraphLayout.call(this, graph);
31 | };
32 |
33 | /**
34 | * Extends mxGraphLayout.
35 | */
36 | mxEdgeLabelLayout.prototype = new mxGraphLayout();
37 | mxEdgeLabelLayout.prototype.constructor = mxEdgeLabelLayout;
38 |
39 | /**
40 | * Function: execute
41 | *
42 | * Implements .
43 | */
44 | mxEdgeLabelLayout.prototype.execute = function(parent)
45 | {
46 | var view = this.graph.view;
47 | var model = this.graph.getModel();
48 |
49 | // Gets all vertices and edges inside the parent
50 | var edges = [];
51 | var vertices = [];
52 | var childCount = model.getChildCount(parent);
53 |
54 | for (var i = 0; i < childCount; i++)
55 | {
56 | var cell = model.getChildAt(parent, i);
57 | var state = view.getState(cell);
58 |
59 | if (state != null)
60 | {
61 | if (!this.isVertexIgnored(cell))
62 | {
63 | vertices.push(state);
64 | }
65 | else if (!this.isEdgeIgnored(cell))
66 | {
67 | edges.push(state);
68 | }
69 | }
70 | }
71 |
72 | this.placeLabels(vertices, edges);
73 | };
74 |
75 | /**
76 | * Function: placeLabels
77 | *
78 | * Places the labels of the given edges.
79 | */
80 | mxEdgeLabelLayout.prototype.placeLabels = function(v, e)
81 | {
82 | var model = this.graph.getModel();
83 |
84 | // Moves the vertices to build a circle. Makes sure the
85 | // radius is large enough for the vertices to not
86 | // overlap
87 | model.beginUpdate();
88 | try
89 | {
90 | for (var i = 0; i < e.length; i++)
91 | {
92 | var edge = e[i];
93 |
94 | if (edge != null && edge.text != null &&
95 | edge.text.boundingBox != null)
96 | {
97 | for (var j = 0; j < v.length; j++)
98 | {
99 | var vertex = v[j];
100 |
101 | if (vertex != null)
102 | {
103 | this.avoid(edge, vertex);
104 | }
105 | }
106 | }
107 | }
108 | }
109 | finally
110 | {
111 | model.endUpdate();
112 | }
113 | };
114 |
115 | /**
116 | * Function: avoid
117 | *
118 | * Places the labels of the given edges.
119 | */
120 | mxEdgeLabelLayout.prototype.avoid = function(edge, vertex)
121 | {
122 | var model = this.graph.getModel();
123 | var labRect = edge.text.boundingBox;
124 |
125 | if (mxUtils.intersects(labRect, vertex))
126 | {
127 | var dy1 = -labRect.y - labRect.height + vertex.y;
128 | var dy2 = -labRect.y + vertex.y + vertex.height;
129 |
130 | var dy = (Math.abs(dy1) < Math.abs(dy2)) ? dy1 : dy2;
131 |
132 | var dx1 = -labRect.x - labRect.width + vertex.x;
133 | var dx2 = -labRect.x + vertex.x + vertex.width;
134 |
135 | var dx = (Math.abs(dx1) < Math.abs(dx2)) ? dx1 : dx2;
136 |
137 | if (Math.abs(dx) < Math.abs(dy))
138 | {
139 | dy = 0;
140 | }
141 | else
142 | {
143 | dx = 0;
144 | }
145 |
146 | var g = model.getGeometry(edge.cell);
147 |
148 | if (g != null)
149 | {
150 | g = g.clone();
151 |
152 | if (g.offset != null)
153 | {
154 | g.offset.x += dx;
155 | g.offset.y += dy;
156 | }
157 | else
158 | {
159 | g.offset = new mxPoint(dx, dy);
160 | }
161 |
162 | model.setGeometry(edge.cell, g);
163 | }
164 | }
165 | };
166 |
167 | window.mxEdgeLabelLayout = mxEdgeLabelLayout;
168 |
--------------------------------------------------------------------------------
/config/general-shape.js:
--------------------------------------------------------------------------------
1 | export default {
2 | Rectangle: {
3 | type: 'vertex',
4 | style: 'rounded=0;whiteSpace=wrap;html=1;',
5 | },
6 | 'Rounded Rectangle': {
7 | type: 'vertex',
8 | style: 'rounded=1;whiteSpace=wrap;html=1;',
9 | },
10 | Text: {
11 | type: 'vertex',
12 | style: 'text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;',
13 | },
14 | Eclipse: {
15 | type: 'vertex',
16 | style: 'shape=ellipse;whiteSpace=wrap;html=1;',
17 | },
18 | Square: {
19 | type: 'vertex',
20 | style: 'whiteSpace=wrap;html=1;aspect=fixed;',
21 | },
22 | Circle: {
23 | type: 'vertex',
24 | style: 'shape=ellipse;whiteSpace=wrap;html=1;aspect=fixed;',
25 | },
26 | Process: {
27 | type: 'vertex',
28 | style: 'shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;',
29 | },
30 | Diamond: {
31 | type: 'vertex',
32 | style: 'shape=rhombus;whiteSpace=wrap;html=1;',
33 | },
34 | Parallelogram: {
35 | type: 'vertex',
36 | style: 'shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;',
37 | },
38 | Triangle: {
39 | type: 'vertex',
40 | style: 'shape=triangle;whiteSpace=wrap;html=1;',
41 | },
42 | Cylinder: {
43 | type: 'vertex',
44 | style: 'shape=cylinder;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;',
45 | },
46 | Cloud: {
47 | type: 'vertex',
48 | style: 'shape=ellipse;shape=cloud;whiteSpace=wrap;html=1;',
49 | },
50 | Document: {
51 | type: 'vertex',
52 | style: 'shape=document;whiteSpace=wrap;html=1;boundedLbl=1;',
53 | },
54 | 'Internal Storage': {
55 | type: 'vertex',
56 | style: 'shape=internalStorage;whiteSpace=wrap;html=1;backgroundOutline=1;',
57 | },
58 | Cube: {
59 | type: 'vertex',
60 | style: 'shape=cube;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;',
61 | },
62 | Step: {
63 | type: 'vertex',
64 | style: 'shape=step;perimeter=stepPerimeter;whiteSpace=wrap;html=1;fixedSize=1;',
65 | },
66 | Trapezoid: {
67 | type: 'vertex',
68 | style: 'shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;',
69 | },
70 | Tape: {
71 | type: 'vertex',
72 | style: 'shape=tape;whiteSpace=wrap;html=1;',
73 | },
74 | Note: {
75 | type: 'vertex',
76 | style: 'shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;',
77 | },
78 | Card: {
79 | type: 'vertex',
80 | style: 'shape=card;whiteSpace=wrap;html=1;',
81 | },
82 | Callout: {
83 | type: 'vertex',
84 | style: 'shape=callout;whiteSpace=wrap;html=1;perimeter=calloutPerimeter;',
85 | },
86 | Actor: {
87 | type: 'vertex',
88 | style: 'shape=umlActor;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;html=1;outlineConnect=0;',
89 | },
90 | Hexagon: {
91 | type: 'vertex',
92 | style: 'shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;',
93 | },
94 | Curve: {
95 | type: 'edge',
96 | style: 'edgeStyle=elbowEdgeStyle;curved=1;endArrow=classic;html=1;',
97 | },
98 | 'Bidirectional Arrow': {
99 | type: 'edge',
100 | style: 'edgeStyle=loopEdgeStyle;shape=flexArrow;endArrow=classic;startArrow=classic;html=1;fillColor=#ffffff;',
101 | },
102 | Arrow: {
103 | type: 'edge',
104 | style: 'edgeStyle=loopEdgeStyle;shape=flexArrow;endArrow=classic;html=1;fillColor=#ffffff;',
105 | },
106 | Link: {
107 | type: 'edge',
108 | style: 'edgeStyle=loopEdgeStyle;shape=link;html=1;',
109 | },
110 | 'Dashed Line': {
111 | type: 'edge',
112 | style: 'edgeStyle=loopEdgeStyle;endArrow=none;dashed=1;html=1;',
113 | },
114 | Line: {
115 | type: 'edge',
116 | style: 'edgeStyle=loopEdgeStyle;endArrow=none;html=1;',
117 | },
118 | 'Bidirectional Connector': {
119 | type: 'edge',
120 | style: 'edgeStyle=loopEdgeStyle;endArrow=classic;html=1;',
121 | },
122 | 'Directional Connector': {
123 | type: 'edge',
124 | style: 'edgeStyle=loopEdgeStyle;endArrow=classic;html=1;',
125 | },
126 | };
127 |
--------------------------------------------------------------------------------
/demo/my-editor.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { message, Layout } from 'antd';
3 |
4 | import Sidebar from './sidebar';
5 | import Toolbar from './toolbar';
6 | import Editor from '../src/editor';
7 |
8 | import IMAGE_SHAPES from './shape-config/image-shape';
9 | import CARD_SHAPES from './shape-config/card-shape';
10 | import SVG_SHAPES from './shape-config/svg-shape.xml';
11 |
12 | import './my-editor.less';
13 |
14 | const { Sider, Content } = Layout;
15 |
16 | class MyEditor extends React.Component {
17 | constructor(props) {
18 | super(props);
19 |
20 | this.state = {
21 | editor: null
22 | };
23 |
24 | this.graphContainerClickCount = 0;
25 | }
26 |
27 | componentDidMount() {
28 | this.mounted = true;
29 |
30 | const editor = new Editor({
31 | container: '.graph-content',
32 | clickFunc: this.clickFunc,
33 | doubleClickFunc: this.doubleClickFunc,
34 | autoSaveFunc: this.autoSaveFunc,
35 | cellCreatedFunc: this.cellCreatedFunc,
36 | deleteFunc: this.deleteFunc,
37 | undoFunc: this.undoFunc,
38 | copyFunc: this.copyFunc,
39 | valueChangeFunc: this.valueChangeFunc,
40 | IMAGE_SHAPES,
41 | CARD_SHAPES,
42 | SVG_SHAPES
43 | });
44 |
45 | this.editor = editor;
46 |
47 | window.editor = editor;
48 |
49 | editor.initCustomPort('https://gw.alicdn.com/tfs/TB1PqwZzzDpK1RjSZFrXXa78VXa-200-200.png');
50 |
51 | const xml = window.localStorage.getItem('autosaveXml');
52 |
53 | this.editor.renderGraphFromXml(xml);
54 |
55 | this.setState({ editor });
56 | }
57 |
58 | componentWillUnmount() {
59 | this.mounted = false;
60 |
61 | // remove event listeners when component will unmount
62 | this.editor.removeEventListeners();
63 | }
64 |
65 |
66 | /**
67 | * double click event callback
68 | */
69 | doubleClickFunc = (cell) => {
70 | console.log('double click', cell);
71 | };
72 |
73 | cellCreatedFunc = (currentCell) => {
74 | const allCells = this.editor.getAllCells();
75 |
76 | let sameShapeNameCount = 0;
77 | const { shapeName } = currentCell;
78 |
79 | allCells
80 | && Object.keys(allCells).forEach((index) => {
81 | if (allCells[index].shapeName === shapeName) {
82 | sameShapeNameCount += 1;
83 | }
84 | });
85 |
86 | const labelName = currentCell.value;
87 |
88 | this.editor.renameCell(`${labelName}${sameShapeNameCount}`, currentCell);
89 | };
90 |
91 | deleteFunc = (cells) => {
92 | console.log('cells deleted: ', cells);
93 | };
94 |
95 | /**
96 | * value change callback
97 | * @param {*} cell cell
98 | * @param {*} newValue new value
99 | */
100 | valueChangeFunc = (cell, newValue) => {
101 | console.log(`new value: ${newValue}`);
102 | };
103 |
104 | autoSaveFunc = (xml) => {
105 | window.autosaveXml = xml;
106 |
107 | const oParser = new DOMParser (); // eslint-disable-line
108 | const oDOM = oParser.parseFromString(xml, 'application/xml');
109 |
110 | window.autoSaveXmlDom = oDOM;
111 |
112 | window.localStorage.setItem('autosaveXml', xml);
113 | };
114 |
115 | clickFunc = (cell) => {
116 | console.log('click', cell);
117 | };
118 |
119 | undoFunc = (histories) => {
120 | console.log('undo', histories);
121 | }
122 |
123 | copyFunc = (cells) => {
124 | console.log('copy', cells);
125 | }
126 |
127 | updateDiagramData = (data) => {
128 | console.log(`update diagram: ${data}`);
129 |
130 | message.info('diagram save success');
131 | }
132 |
133 | render() {
134 | const { editor } = this.state;
135 |
136 | return (
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | {editor ? (
145 |
149 | ) : null}
150 |
151 |
152 |
153 |
154 |
155 | );
156 | }
157 | }
158 |
159 | export default MyEditor;
160 |
--------------------------------------------------------------------------------
/resources/css/common.css:
--------------------------------------------------------------------------------
1 | div.mxRubberband {
2 | position: absolute;
3 | overflow: hidden;
4 | border-style: solid;
5 | border-width: 1px;
6 | border-color: #0000FF;
7 | background: #0077FF;
8 | }
9 |
10 | .mxCellEditor {
11 | background: url(data:image/gif;base64,R0lGODlhMAAwAIAAAP///wAAACH5BAEAAAAALAAAAAAwADAAAAIxhI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8egpAAA7);
12 | /* _background: url('../images/transparent.gif'); */
13 | border-color: transparent;
14 | border-style: solid;
15 | display: inline-block;
16 | position: absolute;
17 | overflow: visible;
18 | word-wrap: normal;
19 | border-width: 0;
20 | min-width: 1px;
21 | resize: none;
22 | padding: 0px;
23 | margin: 0px;
24 | }
25 |
26 | .mxPlainTextEditor * {
27 | padding: 0px;
28 | margin: 0px;
29 | }
30 |
31 | div.mxWindow {
32 | -webkit-box-shadow: 3px 3px 12px #C0C0C0;
33 | -moz-box-shadow: 3px 3px 12px #C0C0C0;
34 | box-shadow: 3px 3px 12px #C0C0C0;
35 | /* background: url('../images/window.gif'); */
36 | border: 1px solid #c3c3c3;
37 | position: absolute;
38 | overflow: hidden;
39 | z-index: 1;
40 | }
41 |
42 | table.mxWindow {
43 | border-collapse: collapse;
44 | table-layout: fixed;
45 | font-family: Arial;
46 | font-size: 8pt;
47 | }
48 |
49 | td.mxWindowTitle {
50 | /* background: url('../images/window-title.gif') repeat-x; */
51 | text-overflow: ellipsis;
52 | white-space: nowrap;
53 | text-align: center;
54 | font-weight: bold;
55 | overflow: hidden;
56 | height: 13px;
57 | padding: 2px;
58 | padding-top: 4px;
59 | padding-bottom: 6px;
60 | color: black;
61 | }
62 |
63 | td.mxWindowPane {
64 | vertical-align: top;
65 | padding: 0px;
66 | }
67 |
68 | div.mxWindowPane {
69 | overflow: hidden;
70 | position: relative;
71 | }
72 |
73 | td.mxWindowPane td {
74 | font-family: Arial;
75 | font-size: 8pt;
76 | }
77 |
78 | td.mxWindowPane input,
79 | td.mxWindowPane select,
80 | td.mxWindowPane textarea,
81 | td.mxWindowPane radio {
82 | border-color: #8C8C8C;
83 | border-style: solid;
84 | border-width: 1px;
85 | font-family: Arial;
86 | font-size: 8pt;
87 | padding: 1px;
88 | }
89 |
90 | td.mxWindowPane button {
91 | /* background: url('../images/button.gif') repeat-x; */
92 | font-family: Arial;
93 | font-size: 8pt;
94 | padding: 2px;
95 | float: left;
96 | }
97 |
98 | img.mxToolbarItem {
99 | margin-right: 6px;
100 | margin-bottom: 6px;
101 | border-width: 1px;
102 | }
103 |
104 | select.mxToolbarCombo {
105 | vertical-align: top;
106 | border-style: inset;
107 | border-width: 2px;
108 | }
109 |
110 | div.mxToolbarComboContainer {
111 | padding: 2px;
112 | }
113 |
114 | img.mxToolbarMode {
115 | margin: 2px;
116 | margin-right: 4px;
117 | margin-bottom: 4px;
118 | border-width: 0px;
119 | }
120 |
121 | img.mxToolbarModeSelected {
122 | margin: 0px;
123 | margin-right: 2px;
124 | margin-bottom: 2px;
125 | border-width: 2px;
126 | border-style: inset;
127 | }
128 |
129 | div.mxTooltip {
130 | -webkit-box-shadow: 3px 3px 12px #C0C0C0;
131 | -moz-box-shadow: 3px 3px 12px #C0C0C0;
132 | box-shadow: 3px 3px 12px #C0C0C0;
133 | background: #FFFFCC;
134 | border-style: solid;
135 | border-width: 1px;
136 | border-color: black;
137 | font-family: Arial;
138 | font-size: 8pt;
139 | position: absolute;
140 | cursor: default;
141 | padding: 4px;
142 | color: black;
143 | }
144 |
145 | div.mxPopupMenu {
146 | -webkit-box-shadow: 3px 3px 12px #C0C0C0;
147 | -moz-box-shadow: 3px 3px 12px #C0C0C0;
148 | box-shadow: 3px 3px 12px #C0C0C0;
149 | /* background: url('../images/window.gif'); */
150 | position: absolute;
151 | border-style: solid;
152 | border-width: 1px;
153 | border-color: black;
154 | }
155 |
156 | table.mxPopupMenu {
157 | border-collapse: collapse;
158 | margin-top: 1px;
159 | margin-bottom: 1px;
160 | }
161 |
162 | tr.mxPopupMenuItem {
163 | color: black;
164 | cursor: pointer;
165 | }
166 |
167 | tr.mxPopupMenuItemHover {
168 | background-color: #000066;
169 | color: #FFFFFF;
170 | cursor: pointer;
171 | }
172 |
173 | td.mxPopupMenuItem {
174 | padding: 2px 30px 2px 10px;
175 | white-space: nowrap;
176 | font-family: Arial;
177 | font-size: 8pt;
178 | }
179 |
180 | td.mxPopupMenuIcon {
181 | background-color: #D0D0D0;
182 | padding: 2px 4px 2px 4px;
183 | }
184 |
185 | .mxDisabled {
186 | opacity: 0.2 !important;
187 | cursor: default !important;
188 | }
--------------------------------------------------------------------------------
/resources/js/io/mxChildChangeCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | mxCodecRegistry.register(function()
6 | {
7 | /**
8 | * Class: mxChildChangeCodec
9 | *
10 | * Codec for s. This class is created and registered
11 | * dynamically at load time and used implicitely via and
12 | * the .
13 | *
14 | * Transient Fields:
15 | *
16 | * - model
17 | * - previous
18 | * - previousIndex
19 | * - child
20 | *
21 | * Reference Fields:
22 | *
23 | * - parent
24 | */
25 | var codec = new mxObjectCodec(new mxChildChange(),
26 | ['model', 'child', 'previousIndex'],
27 | ['parent', 'previous']);
28 |
29 | /**
30 | * Function: isReference
31 | *
32 | * Returns true for the child attribute if the child
33 | * cell had a previous parent or if we're reading the
34 | * child as an attribute rather than a child node, in
35 | * which case it's always a reference.
36 | */
37 | codec.isReference = function(obj, attr, value, isWrite)
38 | {
39 | if (attr == 'child' && (obj.previous != null || !isWrite))
40 | {
41 | return true;
42 | }
43 |
44 | return mxUtils.indexOf(this.idrefs, attr) >= 0;
45 | };
46 |
47 | /**
48 | * Function: afterEncode
49 | *
50 | * Encodes the child recusively and adds the result
51 | * to the given node.
52 | */
53 | codec.afterEncode = function(enc, obj, node)
54 | {
55 | if (this.isReference(obj, 'child', obj.child, true))
56 | {
57 | // Encodes as reference (id)
58 | node.setAttribute('child', enc.getId(obj.child));
59 | }
60 | else
61 | {
62 | // At this point, the encoder is no longer able to know which cells
63 | // are new, so we have to encode the complete cell hierarchy and
64 | // ignore the ones that are already there at decoding time. Note:
65 | // This can only be resolved by moving the notify event into the
66 | // execute of the edit.
67 | enc.encodeCell(obj.child, node);
68 | }
69 |
70 | return node;
71 | };
72 |
73 | /**
74 | * Function: beforeDecode
75 | *
76 | * Decodes the any child nodes as using the respective
77 | * codec from the registry.
78 | */
79 | codec.beforeDecode = function(dec, node, obj)
80 | {
81 | if (node.firstChild != null &&
82 | node.firstChild.nodeType == mxConstants.NODETYPE_ELEMENT)
83 | {
84 | // Makes sure the original node isn't modified
85 | node = node.cloneNode(true);
86 |
87 | var tmp = node.firstChild;
88 | obj.child = dec.decodeCell(tmp, false);
89 |
90 | var tmp2 = tmp.nextSibling;
91 | tmp.parentNode.removeChild(tmp);
92 | tmp = tmp2;
93 |
94 | while (tmp != null)
95 | {
96 | tmp2 = tmp.nextSibling;
97 |
98 | if (tmp.nodeType == mxConstants.NODETYPE_ELEMENT)
99 | {
100 | // Ignores all existing cells because those do not need to
101 | // be re-inserted into the model. Since the encoded version
102 | // of these cells contains the new parent, this would leave
103 | // to an inconsistent state on the model (ie. a parent
104 | // change without a call to parentForCellChanged).
105 | var id = tmp.getAttribute('id');
106 |
107 | if (dec.lookup(id) == null)
108 | {
109 | dec.decodeCell(tmp);
110 | }
111 | }
112 |
113 | tmp.parentNode.removeChild(tmp);
114 | tmp = tmp2;
115 | }
116 | }
117 | else
118 | {
119 | var childRef = node.getAttribute('child');
120 | obj.child = dec.getObject(childRef);
121 | }
122 |
123 | return node;
124 | };
125 |
126 | /**
127 | * Function: afterDecode
128 | *
129 | * Restores object state in the child change.
130 | */
131 | codec.afterDecode = function(dec, node, obj)
132 | {
133 | // Cells are encoded here after a complete transaction so the previous
134 | // parent must be restored on the cell for the case where the cell was
135 | // added. This is needed for the local model to identify the cell as a
136 | // new cell and register the ID.
137 | if (obj.child != null)
138 | {
139 | if (obj.child.parent != null && obj.previous != null &&
140 | obj.child.parent != obj.previous)
141 | {
142 |
143 | obj.previous = obj.child.parent;
144 | }
145 |
146 | obj.child.parent = obj.previous;
147 | obj.previous = obj.parent;
148 | obj.previousIndex = obj.index;
149 | }
150 |
151 | return obj;
152 | };
153 |
154 | // Returns the codec into the registry
155 | return codec;
156 |
157 | }());
158 |
--------------------------------------------------------------------------------
/resources/js/util/mxRectangle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxRectangle
7 | *
8 | * Extends to implement a 2-dimensional rectangle with double
9 | * precision coordinates.
10 | *
11 | * Constructor: mxRectangle
12 | *
13 | * Constructs a new rectangle for the optional parameters. If no parameters
14 | * are given then the respective default values are used.
15 | */
16 | function mxRectangle(x, y, width, height)
17 | {
18 | mxPoint.call(this, x, y);
19 |
20 | this.width = (width != null) ? width : 0;
21 | this.height = (height != null) ? height : 0;
22 | };
23 |
24 | /**
25 | * Extends mxPoint.
26 | */
27 | mxRectangle.prototype = new mxPoint();
28 | mxRectangle.prototype.constructor = mxRectangle;
29 |
30 | /**
31 | * Variable: width
32 | *
33 | * Holds the width of the rectangle. Default is 0.
34 | */
35 | mxRectangle.prototype.width = null;
36 |
37 | /**
38 | * Variable: height
39 | *
40 | * Holds the height of the rectangle. Default is 0.
41 | */
42 | mxRectangle.prototype.height = null;
43 |
44 | /**
45 | * Function: setRect
46 | *
47 | * Sets this rectangle to the specified values
48 | */
49 | mxRectangle.prototype.setRect = function(x, y, w, h)
50 | {
51 | this.x = x;
52 | this.y = y;
53 | this.width = w;
54 | this.height = h;
55 | };
56 |
57 | /**
58 | * Function: getCenterX
59 | *
60 | * Returns the x-coordinate of the center point.
61 | */
62 | mxRectangle.prototype.getCenterX = function ()
63 | {
64 | return this.x + this.width/2;
65 | };
66 |
67 | /**
68 | * Function: getCenterY
69 | *
70 | * Returns the y-coordinate of the center point.
71 | */
72 | mxRectangle.prototype.getCenterY = function ()
73 | {
74 | return this.y + this.height/2;
75 | };
76 |
77 | /**
78 | * Function: add
79 | *
80 | * Adds the given rectangle to this rectangle.
81 | */
82 | mxRectangle.prototype.add = function(rect)
83 | {
84 | if (rect != null)
85 | {
86 | var minX = Math.min(this.x, rect.x);
87 | var minY = Math.min(this.y, rect.y);
88 | var maxX = Math.max(this.x + this.width, rect.x + rect.width);
89 | var maxY = Math.max(this.y + this.height, rect.y + rect.height);
90 |
91 | this.x = minX;
92 | this.y = minY;
93 | this.width = maxX - minX;
94 | this.height = maxY - minY;
95 | }
96 | };
97 |
98 | /**
99 | * Function: intersect
100 | *
101 | * Changes this rectangle to where it overlaps with the given rectangle.
102 | */
103 | mxRectangle.prototype.intersect = function(rect)
104 | {
105 | if (rect != null)
106 | {
107 | var r1 = this.x + this.width;
108 | var r2 = rect.x + rect.width;
109 |
110 | var b1 = this.y + this.height;
111 | var b2 = rect.y + rect.height;
112 |
113 | this.x = Math.max(this.x, rect.x);
114 | this.y = Math.max(this.y, rect.y);
115 | this.width = Math.min(r1, r2) - this.x;
116 | this.height = Math.min(b1, b2) - this.y;
117 | }
118 | };
119 |
120 | /**
121 | * Function: grow
122 | *
123 | * Grows the rectangle by the given amount, that is, this method subtracts
124 | * the given amount from the x- and y-coordinates and adds twice the amount
125 | * to the width and height.
126 | */
127 | mxRectangle.prototype.grow = function(amount)
128 | {
129 | this.x -= amount;
130 | this.y -= amount;
131 | this.width += 2 * amount;
132 | this.height += 2 * amount;
133 | };
134 |
135 | /**
136 | * Function: getPoint
137 | *
138 | * Returns the top, left corner as a new .
139 | */
140 | mxRectangle.prototype.getPoint = function()
141 | {
142 | return new mxPoint(this.x, this.y);
143 | };
144 |
145 | /**
146 | * Function: rotate90
147 | *
148 | * Rotates this rectangle by 90 degree around its center point.
149 | */
150 | mxRectangle.prototype.rotate90 = function()
151 | {
152 | var t = (this.width - this.height) / 2;
153 | this.x += t;
154 | this.y -= t;
155 | var tmp = this.width;
156 | this.width = this.height;
157 | this.height = tmp;
158 | };
159 |
160 | /**
161 | * Function: equals
162 | *
163 | * Returns true if the given object equals this rectangle.
164 | */
165 | mxRectangle.prototype.equals = function(obj)
166 | {
167 | return obj != null && obj.x == this.x && obj.y == this.y &&
168 | obj.width == this.width && obj.height == this.height;
169 | };
170 |
171 | /**
172 | * Function: fromRectangle
173 | *
174 | * Returns a new which is a copy of the given rectangle.
175 | */
176 | mxRectangle.fromRectangle = function(rect)
177 | {
178 | return new mxRectangle(rect.x, rect.y, rect.width, rect.height);
179 | };
180 |
181 | window.mxRectangle = mxRectangle;
--------------------------------------------------------------------------------
/resources/js/util/mxImageExport.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxImageExport
7 | *
8 | * Creates a new image export instance to be used with an export canvas. Here
9 | * is an example that uses this class to create an image via a backend using
10 | * .
11 | *
12 | * (code)
13 | * var xmlDoc = mxUtils.createXmlDocument();
14 | * var root = xmlDoc.createElement('output');
15 | * xmlDoc.appendChild(root);
16 | *
17 | * var xmlCanvas = new mxXmlCanvas2D(root);
18 | * var imgExport = new mxImageExport();
19 | * imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas);
20 | *
21 | * var bounds = graph.getGraphBounds();
22 | * var w = Math.ceil(bounds.x + bounds.width);
23 | * var h = Math.ceil(bounds.y + bounds.height);
24 | *
25 | * var xml = mxUtils.getXml(root);
26 | * new mxXmlRequest('export', 'format=png&w=' + w +
27 | * '&h=' + h + '&bg=#F9F7ED&xml=' + encodeURIComponent(xml))
28 | * .simulate(document, '_blank');
29 | * (end)
30 | *
31 | * Constructor: mxImageExport
32 | *
33 | * Constructs a new image export.
34 | */
35 | function mxImageExport() { };
36 |
37 | /**
38 | * Variable: includeOverlays
39 | *
40 | * Specifies if overlays should be included in the export. Default is false.
41 | */
42 | mxImageExport.prototype.includeOverlays = false;
43 |
44 | /**
45 | * Function: drawState
46 | *
47 | * Draws the given state and all its descendants to the given canvas.
48 | */
49 | mxImageExport.prototype.drawState = function(state, canvas)
50 | {
51 | if (state != null)
52 | {
53 | this.visitStatesRecursive(state, canvas, mxUtils.bind(this, function()
54 | {
55 | this.drawCellState.apply(this, arguments);
56 | }));
57 |
58 | // Paints the overlays
59 | if (this.includeOverlays)
60 | {
61 | this.visitStatesRecursive(state, canvas, mxUtils.bind(this, function()
62 | {
63 | this.drawOverlays.apply(this, arguments);
64 | }));
65 | }
66 | }
67 | };
68 |
69 | /**
70 | * Function: drawState
71 | *
72 | * Draws the given state and all its descendants to the given canvas.
73 | */
74 | mxImageExport.prototype.visitStatesRecursive = function(state, canvas, visitor)
75 | {
76 | if (state != null)
77 | {
78 | visitor(state, canvas);
79 |
80 | var graph = state.view.graph;
81 | var childCount = graph.model.getChildCount(state.cell);
82 |
83 | for (var i = 0; i < childCount; i++)
84 | {
85 | var childState = graph.view.getState(graph.model.getChildAt(state.cell, i));
86 | this.visitStatesRecursive(childState, canvas, visitor);
87 | }
88 | }
89 | };
90 |
91 | /**
92 | * Function: getLinkForCellState
93 | *
94 | * Returns the link for the given cell state and canvas. This returns null.
95 | */
96 | mxImageExport.prototype.getLinkForCellState = function(state, canvas)
97 | {
98 | return null;
99 | };
100 |
101 | /**
102 | * Function: drawCellState
103 | *
104 | * Draws the given state to the given canvas.
105 | */
106 | mxImageExport.prototype.drawCellState = function(state, canvas)
107 | {
108 | // Experimental feature
109 | var link = this.getLinkForCellState(state, canvas);
110 |
111 | if (link != null)
112 | {
113 | canvas.setLink(link);
114 | }
115 |
116 | // Paints the shape and text
117 | this.drawShape(state, canvas);
118 | this.drawText(state, canvas);
119 |
120 | if (link != null)
121 | {
122 | canvas.setLink(null);
123 | }
124 | };
125 |
126 | /**
127 | * Function: drawShape
128 | *
129 | * Draws the shape of the given state.
130 | */
131 | mxImageExport.prototype.drawShape = function(state, canvas)
132 | {
133 | if (state.shape instanceof mxShape && state.shape.checkBounds())
134 | {
135 | canvas.save();
136 | state.shape.paint(canvas);
137 | canvas.restore();
138 | }
139 | };
140 |
141 | /**
142 | * Function: drawText
143 | *
144 | * Draws the text of the given state.
145 | */
146 | mxImageExport.prototype.drawText = function(state, canvas)
147 | {
148 | if (state.text != null && state.text.checkBounds())
149 | {
150 | canvas.save();
151 | state.text.paint(canvas);
152 | canvas.restore();
153 | }
154 | };
155 |
156 | /**
157 | * Function: drawOverlays
158 | *
159 | * Draws the overlays for the given state. This is called if
160 | * is true.
161 | */
162 | mxImageExport.prototype.drawOverlays = function(state, canvas)
163 | {
164 | if (state.overlays != null)
165 | {
166 | state.overlays.visit(function(id, shape)
167 | {
168 | if (shape instanceof mxShape)
169 | {
170 | shape.paint(canvas);
171 | }
172 | });
173 | }
174 | };
175 |
176 | window.mxImageExport = mxImageExport;
--------------------------------------------------------------------------------
/resources/js/util/mxEventSource.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxEventSource
7 | *
8 | * Base class for objects that dispatch named events. To create a subclass that
9 | * inherits from mxEventSource, the following code is used.
10 | *
11 | * (code)
12 | * function MyClass() { };
13 | *
14 | * MyClass.prototype = new mxEventSource();
15 | * MyClass.prototype.constructor = MyClass;
16 | * (end)
17 | *
18 | * Known Subclasses:
19 | *
20 | * , , , , ,
21 | * ,
22 | *
23 | * Constructor: mxEventSource
24 | *
25 | * Constructs a new event source.
26 | */
27 | function mxEventSource(eventSource)
28 | {
29 | this.setEventSource(eventSource);
30 | };
31 |
32 | /**
33 | * Variable: eventListeners
34 | *
35 | * Holds the event names and associated listeners in an array. The array
36 | * contains the event name followed by the respective listener for each
37 | * registered listener.
38 | */
39 | mxEventSource.prototype.eventListeners = null;
40 |
41 | /**
42 | * Variable: eventsEnabled
43 | *
44 | * Specifies if events can be fired. Default is true.
45 | */
46 | mxEventSource.prototype.eventsEnabled = true;
47 |
48 | /**
49 | * Variable: eventSource
50 | *
51 | * Optional source for events. Default is null.
52 | */
53 | mxEventSource.prototype.eventSource = null;
54 |
55 | /**
56 | * Function: isEventsEnabled
57 | *
58 | * Returns .
59 | */
60 | mxEventSource.prototype.isEventsEnabled = function()
61 | {
62 | return this.eventsEnabled;
63 | };
64 |
65 | /**
66 | * Function: setEventsEnabled
67 | *
68 | * Sets .
69 | */
70 | mxEventSource.prototype.setEventsEnabled = function(value)
71 | {
72 | this.eventsEnabled = value;
73 | };
74 |
75 | /**
76 | * Function: getEventSource
77 | *
78 | * Returns .
79 | */
80 | mxEventSource.prototype.getEventSource = function()
81 | {
82 | return this.eventSource;
83 | };
84 |
85 | /**
86 | * Function: setEventSource
87 | *
88 | * Sets .
89 | */
90 | mxEventSource.prototype.setEventSource = function(value)
91 | {
92 | this.eventSource = value;
93 | };
94 |
95 | /**
96 | * Function: addListener
97 | *
98 | * Binds the specified function to the given event name. If no event name
99 | * is given, then the listener is registered for all events.
100 | *
101 | * The parameters of the listener are the sender and an .
102 | */
103 | mxEventSource.prototype.addListener = function(name, funct)
104 | {
105 | if (this.eventListeners == null)
106 | {
107 | this.eventListeners = [];
108 | }
109 |
110 | this.eventListeners.push(name);
111 | this.eventListeners.push(funct);
112 | };
113 |
114 | /**
115 | * Function: removeListener
116 | *
117 | * Removes all occurrences of the given listener from .
118 | */
119 | mxEventSource.prototype.removeListener = function(funct)
120 | {
121 | if (this.eventListeners != null)
122 | {
123 | var i = 0;
124 |
125 | while (i < this.eventListeners.length)
126 | {
127 | if (this.eventListeners[i+1] == funct)
128 | {
129 | this.eventListeners.splice(i, 2);
130 | }
131 | else
132 | {
133 | i += 2;
134 | }
135 | }
136 | }
137 | };
138 |
139 | /**
140 | * Function: fireEvent
141 | *
142 | * Dispatches the given event to the listeners which are registered for
143 | * the event. The sender argument is optional. The current execution scope
144 | * ("this") is used for the listener invocation (see ).
145 | *
146 | * Example:
147 | *
148 | * (code)
149 | * fireEvent(new mxEventObject("eventName", key1, val1, .., keyN, valN))
150 | * (end)
151 | *
152 | * Parameters:
153 | *
154 | * evt - that represents the event.
155 | * sender - Optional sender to be passed to the listener. Default value is
156 | * the return value of .
157 | */
158 | mxEventSource.prototype.fireEvent = function(evt, sender)
159 | {
160 | if (this.eventListeners != null && this.isEventsEnabled())
161 | {
162 | if (evt == null)
163 | {
164 | evt = new mxEventObject();
165 | }
166 |
167 | if (sender == null)
168 | {
169 | sender = this.getEventSource();
170 | }
171 |
172 | if (sender == null)
173 | {
174 | sender = this;
175 | }
176 |
177 | var args = [sender, evt];
178 |
179 | for (var i = 0; i < this.eventListeners.length; i += 2)
180 | {
181 | var listen = this.eventListeners[i];
182 |
183 | if (listen == null || listen == evt.getName())
184 | {
185 | this.eventListeners[i+1].apply(this, args);
186 | }
187 | }
188 | }
189 | };
190 |
191 | window.mxEventSource = mxEventSource;
--------------------------------------------------------------------------------
/resources/js/layout/hierarchical/model/mxGraphHierarchyEdge.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxGraphHierarchyEdge
7 | *
8 | * An abstraction of a hierarchical edge for the hierarchy layout
9 | *
10 | * Constructor: mxGraphHierarchyEdge
11 | *
12 | * Constructs a hierarchy edge
13 | *
14 | * Arguments:
15 | *
16 | * edges - a list of real graph edges this abstraction represents
17 | */
18 | function mxGraphHierarchyEdge(edges)
19 | {
20 | mxGraphAbstractHierarchyCell.apply(this, arguments);
21 | this.edges = edges;
22 | this.ids = [];
23 |
24 | for (var i = 0; i < edges.length; i++)
25 | {
26 | this.ids.push(mxObjectIdentity.get(edges[i]));
27 | }
28 | };
29 |
30 | /**
31 | * Extends mxGraphAbstractHierarchyCell.
32 | */
33 | mxGraphHierarchyEdge.prototype = new mxGraphAbstractHierarchyCell();
34 | mxGraphHierarchyEdge.prototype.constructor = mxGraphHierarchyEdge;
35 |
36 | /**
37 | * Variable: edges
38 | *
39 | * The graph edge(s) this object represents. Parallel edges are all grouped
40 | * together within one hierarchy edge.
41 | */
42 | mxGraphHierarchyEdge.prototype.edges = null;
43 |
44 | /**
45 | * Variable: ids
46 | *
47 | * The object identities of the wrapped cells
48 | */
49 | mxGraphHierarchyEdge.prototype.ids = null;
50 |
51 | /**
52 | * Variable: source
53 | *
54 | * The node this edge is sourced at
55 | */
56 | mxGraphHierarchyEdge.prototype.source = null;
57 |
58 | /**
59 | * Variable: target
60 | *
61 | * The node this edge targets
62 | */
63 | mxGraphHierarchyEdge.prototype.target = null;
64 |
65 | /**
66 | * Variable: isReversed
67 | *
68 | * Whether or not the direction of this edge has been reversed
69 | * internally to create a DAG for the hierarchical layout
70 | */
71 | mxGraphHierarchyEdge.prototype.isReversed = false;
72 |
73 | /**
74 | * Function: invert
75 | *
76 | * Inverts the direction of this internal edge(s)
77 | */
78 | mxGraphHierarchyEdge.prototype.invert = function(layer)
79 | {
80 | var temp = this.source;
81 | this.source = this.target;
82 | this.target = temp;
83 | this.isReversed = !this.isReversed;
84 | };
85 |
86 | /**
87 | * Function: getNextLayerConnectedCells
88 | *
89 | * Returns the cells this cell connects to on the next layer up
90 | */
91 | mxGraphHierarchyEdge.prototype.getNextLayerConnectedCells = function(layer)
92 | {
93 | if (this.nextLayerConnectedCells == null)
94 | {
95 | this.nextLayerConnectedCells = [];
96 |
97 | for (var i = 0; i < this.temp.length; i++)
98 | {
99 | this.nextLayerConnectedCells[i] = [];
100 |
101 | if (i == this.temp.length - 1)
102 | {
103 | this.nextLayerConnectedCells[i].push(this.source);
104 | }
105 | else
106 | {
107 | this.nextLayerConnectedCells[i].push(this);
108 | }
109 | }
110 | }
111 |
112 | return this.nextLayerConnectedCells[layer - this.minRank - 1];
113 | };
114 |
115 | /**
116 | * Function: getPreviousLayerConnectedCells
117 | *
118 | * Returns the cells this cell connects to on the next layer down
119 | */
120 | mxGraphHierarchyEdge.prototype.getPreviousLayerConnectedCells = function(layer)
121 | {
122 | if (this.previousLayerConnectedCells == null)
123 | {
124 | this.previousLayerConnectedCells = [];
125 |
126 | for (var i = 0; i < this.temp.length; i++)
127 | {
128 | this.previousLayerConnectedCells[i] = [];
129 |
130 | if (i == 0)
131 | {
132 | this.previousLayerConnectedCells[i].push(this.target);
133 | }
134 | else
135 | {
136 | this.previousLayerConnectedCells[i].push(this);
137 | }
138 | }
139 | }
140 |
141 | return this.previousLayerConnectedCells[layer - this.minRank - 1];
142 | };
143 |
144 | /**
145 | * Function: isEdge
146 | *
147 | * Returns true.
148 | */
149 | mxGraphHierarchyEdge.prototype.isEdge = function()
150 | {
151 | return true;
152 | };
153 |
154 | /**
155 | * Function: getGeneralPurposeVariable
156 | *
157 | * Gets the value of temp for the specified layer
158 | */
159 | mxGraphHierarchyEdge.prototype.getGeneralPurposeVariable = function(layer)
160 | {
161 | return this.temp[layer - this.minRank - 1];
162 | };
163 |
164 | /**
165 | * Function: setGeneralPurposeVariable
166 | *
167 | * Set the value of temp for the specified layer
168 | */
169 | mxGraphHierarchyEdge.prototype.setGeneralPurposeVariable = function(layer, value)
170 | {
171 | this.temp[layer - this.minRank - 1] = value;
172 | };
173 |
174 | /**
175 | * Function: getCoreCell
176 | *
177 | * Gets the first core edge associated with this wrapper
178 | */
179 | mxGraphHierarchyEdge.prototype.getCoreCell = function()
180 | {
181 | if (this.edges != null && this.edges.length > 0)
182 | {
183 | return this.edges[0];
184 | }
185 |
186 | return null;
187 | };
188 |
189 | window.mxGraphHierarchyEdge = mxGraphHierarchyEdge;
--------------------------------------------------------------------------------
/resources/js/shape/mxConnector.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxConnector
7 | *
8 | * Extends to implement a connector shape. The connector
9 | * shape allows for arrow heads on either side.
10 | *
11 | * This shape is registered under in
12 | * .
13 | *
14 | * Constructor: mxConnector
15 | *
16 | * Constructs a new connector shape.
17 | *
18 | * Parameters:
19 | *
20 | * points - Array of that define the points. This is stored in
21 | * .
22 | * stroke - String that defines the stroke color. This is stored in .
23 | * Default is 'black'.
24 | * strokewidth - Optional integer that defines the stroke width. Default is
25 | * 1. This is stored in .
26 | */
27 | function mxConnector(points, stroke, strokewidth)
28 | {
29 | mxPolyline.call(this, points, stroke, strokewidth);
30 | };
31 |
32 | /**
33 | * Extends mxPolyline.
34 | */
35 | mxUtils.extend(mxConnector, mxPolyline);
36 |
37 | /**
38 | * Function: updateBoundingBox
39 | *
40 | * Updates the for this shape using and
41 | * and stores the result in .
42 | */
43 | mxConnector.prototype.updateBoundingBox = function()
44 | {
45 | this.useSvgBoundingBox = this.style != null && this.style[mxConstants.STYLE_CURVED] == 1;
46 | mxShape.prototype.updateBoundingBox.apply(this, arguments);
47 | };
48 |
49 | /**
50 | * Function: paintEdgeShape
51 | *
52 | * Paints the line shape.
53 | */
54 | mxConnector.prototype.paintEdgeShape = function(c, pts)
55 | {
56 | // The indirection via functions for markers is needed in
57 | // order to apply the offsets before painting the line and
58 | // paint the markers after painting the line.
59 | var sourceMarker = this.createMarker(c, pts, true);
60 | var targetMarker = this.createMarker(c, pts, false);
61 |
62 | mxPolyline.prototype.paintEdgeShape.apply(this, arguments);
63 |
64 | // Disables shadows, dashed styles and fixes fill color for markers
65 | c.setFillColor(this.stroke);
66 | c.setShadow(false);
67 | c.setDashed(false);
68 |
69 | if (sourceMarker != null)
70 | {
71 | sourceMarker();
72 | }
73 |
74 | if (targetMarker != null)
75 | {
76 | targetMarker();
77 | }
78 | };
79 |
80 | /**
81 | * Function: createMarker
82 | *
83 | * Prepares the marker by adding offsets in pts and returning a function to
84 | * paint the marker.
85 | */
86 | mxConnector.prototype.createMarker = function(c, pts, source)
87 | {
88 | var result = null;
89 | var n = pts.length;
90 | var type = mxUtils.getValue(this.style, (source) ? mxConstants.STYLE_STARTARROW : mxConstants.STYLE_ENDARROW);
91 | var p0 = (source) ? pts[1] : pts[n - 2];
92 | var pe = (source) ? pts[0] : pts[n - 1];
93 |
94 | if (type != null && p0 != null && pe != null)
95 | {
96 | var count = 1;
97 |
98 | // Uses next non-overlapping point
99 | while (count < n - 1 && Math.round(p0.x - pe.x) == 0 && Math.round(p0.y - pe.y) == 0)
100 | {
101 | p0 = (source) ? pts[1 + count] : pts[n - 2 - count];
102 | count++;
103 | }
104 |
105 | // Computes the norm and the inverse norm
106 | var dx = pe.x - p0.x;
107 | var dy = pe.y - p0.y;
108 |
109 | var dist = Math.max(1, Math.sqrt(dx * dx + dy * dy));
110 |
111 | var unitX = dx / dist;
112 | var unitY = dy / dist;
113 |
114 | var size = mxUtils.getNumber(this.style, (source) ? mxConstants.STYLE_STARTSIZE : mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE);
115 |
116 | // Allow for stroke width in the end point used and the
117 | // orthogonal vectors describing the direction of the marker
118 | var filled = this.style[(source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL] != 0;
119 |
120 | result = mxMarker.createMarker(c, this, type, pe, unitX, unitY, size, source, this.strokewidth, filled);
121 | }
122 |
123 | return result;
124 | };
125 |
126 | /**
127 | * Function: augmentBoundingBox
128 | *
129 | * Augments the bounding box with the strokewidth and shadow offsets.
130 | */
131 | mxConnector.prototype.augmentBoundingBox = function(bbox)
132 | {
133 | mxShape.prototype.augmentBoundingBox.apply(this, arguments);
134 |
135 | // Adds marker sizes
136 | var size = 0;
137 |
138 | if (mxUtils.getValue(this.style, mxConstants.STYLE_STARTARROW, mxConstants.NONE) != mxConstants.NONE)
139 | {
140 | size = mxUtils.getNumber(this.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE) + 1;
141 | }
142 |
143 | if (mxUtils.getValue(this.style, mxConstants.STYLE_ENDARROW, mxConstants.NONE) != mxConstants.NONE)
144 | {
145 | size = Math.max(size, mxUtils.getNumber(this.style, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE)) + 1;
146 | }
147 |
148 | bbox.grow(size * this.scale);
149 | };
150 |
151 | window.mxConnector = mxConnector;
152 |
--------------------------------------------------------------------------------
/resources/js/util/mxForm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxForm
7 | *
8 | * A simple class for creating HTML forms.
9 | *
10 | * Constructor: mxForm
11 | *
12 | * Creates a HTML table using the specified classname.
13 | */
14 | function mxForm(className)
15 | {
16 | this.table = document.createElement('table');
17 | this.table.className = className;
18 | this.body = document.createElement('tbody');
19 |
20 | this.table.appendChild(this.body);
21 | };
22 |
23 | /**
24 | * Variable: table
25 | *
26 | * Holds the DOM node that represents the table.
27 | */
28 | mxForm.prototype.table = null;
29 |
30 | /**
31 | * Variable: body
32 | *
33 | * Holds the DOM node that represents the tbody (table body). New rows
34 | * can be added to this object using DOM API.
35 | */
36 | mxForm.prototype.body = false;
37 |
38 | /**
39 | * Function: getTable
40 | *
41 | * Returns the table that contains this form.
42 | */
43 | mxForm.prototype.getTable = function()
44 | {
45 | return this.table;
46 | };
47 |
48 | /**
49 | * Function: addButtons
50 | *
51 | * Helper method to add an OK and Cancel button using the respective
52 | * functions.
53 | */
54 | mxForm.prototype.addButtons = function(okFunct, cancelFunct)
55 | {
56 | var tr = document.createElement('tr');
57 | var td = document.createElement('td');
58 | tr.appendChild(td);
59 | td = document.createElement('td');
60 |
61 | // Adds the ok button
62 | var button = document.createElement('button');
63 | mxUtils.write(button, mxResources.get('ok') || 'OK');
64 | td.appendChild(button);
65 |
66 | mxEvent.addListener(button, 'click', function()
67 | {
68 | okFunct();
69 | });
70 |
71 | // Adds the cancel button
72 | button = document.createElement('button');
73 | mxUtils.write(button, mxResources.get('cancel') || 'Cancel');
74 | td.appendChild(button);
75 |
76 | mxEvent.addListener(button, 'click', function()
77 | {
78 | cancelFunct();
79 | });
80 |
81 | tr.appendChild(td);
82 | this.body.appendChild(tr);
83 | };
84 |
85 | /**
86 | * Function: addText
87 | *
88 | * Adds an input for the given name, type and value and returns it.
89 | */
90 | mxForm.prototype.addText = function(name, value, type)
91 | {
92 | var input = document.createElement('input');
93 |
94 | input.setAttribute('type', type || 'text');
95 | input.value = value;
96 |
97 | return this.addField(name, input);
98 | };
99 |
100 | /**
101 | * Function: addCheckbox
102 | *
103 | * Adds a checkbox for the given name and value and returns the textfield.
104 | */
105 | mxForm.prototype.addCheckbox = function(name, value)
106 | {
107 | var input = document.createElement('input');
108 |
109 | input.setAttribute('type', 'checkbox');
110 | this.addField(name, input);
111 |
112 | // IE can only change the checked value if the input is inside the DOM
113 | if (value)
114 | {
115 | input.checked = true;
116 | }
117 |
118 | return input;
119 | };
120 |
121 | /**
122 | * Function: addTextarea
123 | *
124 | * Adds a textarea for the given name and value and returns the textarea.
125 | */
126 | mxForm.prototype.addTextarea = function(name, value, rows)
127 | {
128 | var input = document.createElement('textarea');
129 |
130 | if (mxClient.IS_NS)
131 | {
132 | rows--;
133 | }
134 |
135 | input.setAttribute('rows', rows || 2);
136 | input.value = value;
137 |
138 | return this.addField(name, input);
139 | };
140 |
141 | /**
142 | * Function: addCombo
143 | *
144 | * Adds a combo for the given name and returns the combo.
145 | */
146 | mxForm.prototype.addCombo = function(name, isMultiSelect, size)
147 | {
148 | var select = document.createElement('select');
149 |
150 | if (size != null)
151 | {
152 | select.setAttribute('size', size);
153 | }
154 |
155 | if (isMultiSelect)
156 | {
157 | select.setAttribute('multiple', 'true');
158 | }
159 |
160 | return this.addField(name, select);
161 | };
162 |
163 | /**
164 | * Function: addOption
165 | *
166 | * Adds an option for the given label to the specified combo.
167 | */
168 | mxForm.prototype.addOption = function(combo, label, value, isSelected)
169 | {
170 | var option = document.createElement('option');
171 |
172 | mxUtils.writeln(option, label);
173 | option.setAttribute('value', value);
174 |
175 | if (isSelected)
176 | {
177 | option.setAttribute('selected', isSelected);
178 | }
179 |
180 | combo.appendChild(option);
181 | };
182 |
183 | /**
184 | * Function: addField
185 | *
186 | * Adds a new row with the name and the input field in two columns and
187 | * returns the given input.
188 | */
189 | mxForm.prototype.addField = function(name, input)
190 | {
191 | var tr = document.createElement('tr');
192 | var td = document.createElement('td');
193 | mxUtils.write(td, name);
194 | tr.appendChild(td);
195 |
196 | td = document.createElement('td');
197 | td.appendChild(input);
198 | tr.appendChild(td);
199 | this.body.appendChild(tr);
200 |
201 | return input;
202 | };
203 |
204 | window.mxForm = mxForm;
--------------------------------------------------------------------------------
/resources/js/layout/hierarchical/model/mxGraphAbstractHierarchyCell.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxGraphAbstractHierarchyCell
7 | *
8 | * An abstraction of an internal hierarchy node or edge
9 | *
10 | * Constructor: mxGraphAbstractHierarchyCell
11 | *
12 | * Constructs a new hierarchical layout algorithm.
13 | *
14 | * Arguments:
15 | *
16 | * graph - Reference to the enclosing .
17 | * deterministic - Optional boolean that specifies if this layout should be
18 | * deterministic. Default is true.
19 | */
20 | function mxGraphAbstractHierarchyCell()
21 | {
22 | this.x = [];
23 | this.y = [];
24 | this.temp = [];
25 | };
26 |
27 | /**
28 | * Variable: maxRank
29 | *
30 | * The maximum rank this cell occupies. Default is -1.
31 | */
32 | mxGraphAbstractHierarchyCell.prototype.maxRank = -1;
33 |
34 | /**
35 | * Variable: minRank
36 | *
37 | * The minimum rank this cell occupies. Default is -1.
38 | */
39 | mxGraphAbstractHierarchyCell.prototype.minRank = -1;
40 |
41 | /**
42 | * Variable: x
43 | *
44 | * The x position of this cell for each layer it occupies
45 | */
46 | mxGraphAbstractHierarchyCell.prototype.x = null;
47 |
48 | /**
49 | * Variable: y
50 | *
51 | * The y position of this cell for each layer it occupies
52 | */
53 | mxGraphAbstractHierarchyCell.prototype.y = null;
54 |
55 | /**
56 | * Variable: width
57 | *
58 | * The width of this cell
59 | */
60 | mxGraphAbstractHierarchyCell.prototype.width = 0;
61 |
62 | /**
63 | * Variable: height
64 | *
65 | * The height of this cell
66 | */
67 | mxGraphAbstractHierarchyCell.prototype.height = 0;
68 |
69 | /**
70 | * Variable: nextLayerConnectedCells
71 | *
72 | * A cached version of the cells this cell connects to on the next layer up
73 | */
74 | mxGraphAbstractHierarchyCell.prototype.nextLayerConnectedCells = null;
75 |
76 | /**
77 | * Variable: previousLayerConnectedCells
78 | *
79 | * A cached version of the cells this cell connects to on the next layer down
80 | */
81 | mxGraphAbstractHierarchyCell.prototype.previousLayerConnectedCells = null;
82 |
83 | /**
84 | * Variable: temp
85 | *
86 | * Temporary variable for general use. Generally, try to avoid
87 | * carrying information between stages. Currently, the longest
88 | * path layering sets temp to the rank position in fixRanks()
89 | * and the crossing reduction uses this. This meant temp couldn't
90 | * be used for hashing the nodes in the model dfs and so hashCode
91 | * was created
92 | */
93 | mxGraphAbstractHierarchyCell.prototype.temp = null;
94 |
95 | /**
96 | * Function: getNextLayerConnectedCells
97 | *
98 | * Returns the cells this cell connects to on the next layer up
99 | */
100 | mxGraphAbstractHierarchyCell.prototype.getNextLayerConnectedCells = function(layer)
101 | {
102 | return null;
103 | };
104 |
105 | /**
106 | * Function: getPreviousLayerConnectedCells
107 | *
108 | * Returns the cells this cell connects to on the next layer down
109 | */
110 | mxGraphAbstractHierarchyCell.prototype.getPreviousLayerConnectedCells = function(layer)
111 | {
112 | return null;
113 | };
114 |
115 | /**
116 | * Function: isEdge
117 | *
118 | * Returns whether or not this cell is an edge
119 | */
120 | mxGraphAbstractHierarchyCell.prototype.isEdge = function()
121 | {
122 | return false;
123 | };
124 |
125 | /**
126 | * Function: isVertex
127 | *
128 | * Returns whether or not this cell is a node
129 | */
130 | mxGraphAbstractHierarchyCell.prototype.isVertex = function()
131 | {
132 | return false;
133 | };
134 |
135 | /**
136 | * Function: getGeneralPurposeVariable
137 | *
138 | * Gets the value of temp for the specified layer
139 | */
140 | mxGraphAbstractHierarchyCell.prototype.getGeneralPurposeVariable = function(layer)
141 | {
142 | return null;
143 | };
144 |
145 | /**
146 | * Function: setGeneralPurposeVariable
147 | *
148 | * Set the value of temp for the specified layer
149 | */
150 | mxGraphAbstractHierarchyCell.prototype.setGeneralPurposeVariable = function(layer, value)
151 | {
152 | return null;
153 | };
154 |
155 | /**
156 | * Function: setX
157 | *
158 | * Set the value of x for the specified layer
159 | */
160 | mxGraphAbstractHierarchyCell.prototype.setX = function(layer, value)
161 | {
162 | if (this.isVertex())
163 | {
164 | this.x[0] = value;
165 | }
166 | else if (this.isEdge())
167 | {
168 | this.x[layer - this.minRank - 1] = value;
169 | }
170 | };
171 |
172 | /**
173 | * Function: getX
174 | *
175 | * Gets the value of x on the specified layer
176 | */
177 | mxGraphAbstractHierarchyCell.prototype.getX = function(layer)
178 | {
179 | if (this.isVertex())
180 | {
181 | return this.x[0];
182 | }
183 | else if (this.isEdge())
184 | {
185 | return this.x[layer - this.minRank - 1];
186 | }
187 |
188 | return 0.0;
189 | };
190 |
191 | /**
192 | * Function: setY
193 | *
194 | * Set the value of y for the specified layer
195 | */
196 | mxGraphAbstractHierarchyCell.prototype.setY = function(layer, value)
197 | {
198 | if (this.isVertex())
199 | {
200 | this.y[0] = value;
201 | }
202 | else if (this.isEdge())
203 | {
204 | this.y[layer -this. minRank - 1] = value;
205 | }
206 | };
207 |
208 | window.mxGraphAbstractHierarchyCell = mxGraphAbstractHierarchyCell;
--------------------------------------------------------------------------------
/resources/js/view/mxCellStatePreview.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | *
7 | * Class: mxCellStatePreview
8 | *
9 | * Implements a live preview for moving cells.
10 | *
11 | * Constructor: mxCellStatePreview
12 | *
13 | * Constructs a move preview for the given graph.
14 | *
15 | * Parameters:
16 | *
17 | * graph - Reference to the enclosing .
18 | */
19 | function mxCellStatePreview(graph)
20 | {
21 | this.deltas = new mxDictionary();
22 | this.graph = graph;
23 | };
24 |
25 | /**
26 | * Variable: graph
27 | *
28 | * Reference to the enclosing .
29 | */
30 | mxCellStatePreview.prototype.graph = null;
31 |
32 | /**
33 | * Variable: deltas
34 | *
35 | * Reference to the enclosing .
36 | */
37 | mxCellStatePreview.prototype.deltas = null;
38 |
39 | /**
40 | * Variable: count
41 | *
42 | * Contains the number of entries in the map.
43 | */
44 | mxCellStatePreview.prototype.count = 0;
45 |
46 | /**
47 | * Function: isEmpty
48 | *
49 | * Returns true if this contains no entries.
50 | */
51 | mxCellStatePreview.prototype.isEmpty = function()
52 | {
53 | return this.count == 0;
54 | };
55 |
56 | /**
57 | * Function: moveState
58 | */
59 | mxCellStatePreview.prototype.moveState = function(state, dx, dy, add, includeEdges)
60 | {
61 | add = (add != null) ? add : true;
62 | includeEdges = (includeEdges != null) ? includeEdges : true;
63 |
64 | var delta = this.deltas.get(state.cell);
65 |
66 | if (delta == null)
67 | {
68 | // Note: Deltas stores the point and the state since the key is a string.
69 | delta = {point: new mxPoint(dx, dy), state: state};
70 | this.deltas.put(state.cell, delta);
71 | this.count++;
72 | }
73 | else if (add)
74 | {
75 | delta.point.x += dx;
76 | delta.point.y += dy;
77 | }
78 | else
79 | {
80 | delta.point.x = dx;
81 | delta.point.y = dy;
82 | }
83 |
84 | if (includeEdges)
85 | {
86 | this.addEdges(state);
87 | }
88 |
89 | return delta.point;
90 | };
91 |
92 | /**
93 | * Function: show
94 | */
95 | mxCellStatePreview.prototype.show = function(visitor)
96 | {
97 | this.deltas.visit(mxUtils.bind(this, function(key, delta)
98 | {
99 | this.translateState(delta.state, delta.point.x, delta.point.y);
100 | }));
101 |
102 | this.deltas.visit(mxUtils.bind(this, function(key, delta)
103 | {
104 | this.revalidateState(delta.state, delta.point.x, delta.point.y, visitor);
105 | }));
106 | };
107 |
108 | /**
109 | * Function: translateState
110 | */
111 | mxCellStatePreview.prototype.translateState = function(state, dx, dy)
112 | {
113 | if (state != null)
114 | {
115 | var model = this.graph.getModel();
116 |
117 | if (model.isVertex(state.cell))
118 | {
119 | state.view.updateCellState(state);
120 | var geo = model.getGeometry(state.cell);
121 |
122 | // Moves selection cells and non-relative vertices in
123 | // the first phase so that edge terminal points will
124 | // be updated in the second phase
125 | if ((dx != 0 || dy != 0) && geo != null && (!geo.relative || this.deltas.get(state.cell) != null))
126 | {
127 | state.x += dx;
128 | state.y += dy;
129 | }
130 | }
131 |
132 | var childCount = model.getChildCount(state.cell);
133 |
134 | for (var i = 0; i < childCount; i++)
135 | {
136 | this.translateState(state.view.getState(model.getChildAt(state.cell, i)), dx, dy);
137 | }
138 | }
139 | };
140 |
141 | /**
142 | * Function: revalidateState
143 | */
144 | mxCellStatePreview.prototype.revalidateState = function(state, dx, dy, visitor)
145 | {
146 | if (state != null)
147 | {
148 | var model = this.graph.getModel();
149 |
150 | // Updates the edge terminal points and restores the
151 | // (relative) positions of any (relative) children
152 | if (model.isEdge(state.cell))
153 | {
154 | state.view.updateCellState(state);
155 | }
156 |
157 | var geo = this.graph.getCellGeometry(state.cell);
158 | var pState = state.view.getState(model.getParent(state.cell));
159 |
160 | // Moves selection vertices which are relative
161 | if ((dx != 0 || dy != 0) && geo != null && geo.relative &&
162 | model.isVertex(state.cell) && (pState == null ||
163 | model.isVertex(pState.cell) || this.deltas.get(state.cell) != null))
164 | {
165 | state.x += dx;
166 | state.y += dy;
167 | }
168 |
169 | this.graph.cellRenderer.redraw(state);
170 |
171 | // Invokes the visitor on the given state
172 | if (visitor != null)
173 | {
174 | visitor(state);
175 | }
176 |
177 | var childCount = model.getChildCount(state.cell);
178 |
179 | for (var i = 0; i < childCount; i++)
180 | {
181 | this.revalidateState(this.graph.view.getState(model.getChildAt(state.cell, i)), dx, dy, visitor);
182 | }
183 | }
184 | };
185 |
186 | /**
187 | * Function: addEdges
188 | */
189 | mxCellStatePreview.prototype.addEdges = function(state)
190 | {
191 | var model = this.graph.getModel();
192 | var edgeCount = model.getEdgeCount(state.cell);
193 |
194 | for (var i = 0; i < edgeCount; i++)
195 | {
196 | var s = state.view.getState(model.getEdgeAt(state.cell, i));
197 |
198 | if (s != null)
199 | {
200 | this.moveState(s, 0, 0);
201 | }
202 | }
203 | };
204 |
205 | window.mxCellStatePreview = mxCellStatePreview;
--------------------------------------------------------------------------------
/resources/js/layout/mxCircleLayout.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxCircleLayout
7 | *
8 | * Extends to implement a circluar layout for a given radius.
9 | * The vertices do not need to be connected for this layout to work and all
10 | * connections between vertices are not taken into account.
11 | *
12 | * Example:
13 | *
14 | * (code)
15 | * var layout = new mxCircleLayout(graph);
16 | * layout.execute(graph.getDefaultParent());
17 | * (end)
18 | *
19 | * Constructor: mxCircleLayout
20 | *
21 | * Constructs a new circular layout for the specified radius.
22 | *
23 | * Arguments:
24 | *
25 | * graph - that contains the cells.
26 | * radius - Optional radius as an int. Default is 100.
27 | */
28 | function mxCircleLayout(graph, radius)
29 | {
30 | mxGraphLayout.call(this, graph);
31 | this.radius = (radius != null) ? radius : 100;
32 | };
33 |
34 | /**
35 | * Extends mxGraphLayout.
36 | */
37 | mxCircleLayout.prototype = new mxGraphLayout();
38 | mxCircleLayout.prototype.constructor = mxCircleLayout;
39 |
40 | /**
41 | * Variable: radius
42 | *
43 | * Integer specifying the size of the radius. Default is 100.
44 | */
45 | mxCircleLayout.prototype.radius = null;
46 |
47 | /**
48 | * Variable: moveCircle
49 | *
50 | * Boolean specifying if the circle should be moved to the top,
51 | * left corner specified by and . Default is false.
52 | */
53 | mxCircleLayout.prototype.moveCircle = false;
54 |
55 | /**
56 | * Variable: x0
57 | *
58 | * Integer specifying the left coordinate of the circle.
59 | * Default is 0.
60 | */
61 | mxCircleLayout.prototype.x0 = 0;
62 |
63 | /**
64 | * Variable: y0
65 | *
66 | * Integer specifying the top coordinate of the circle.
67 | * Default is 0.
68 | */
69 | mxCircleLayout.prototype.y0 = 0;
70 |
71 | /**
72 | * Variable: resetEdges
73 | *
74 | * Specifies if all edge points of traversed edges should be removed.
75 | * Default is true.
76 | */
77 | mxCircleLayout.prototype.resetEdges = true;
78 |
79 | /**
80 | * Variable: disableEdgeStyle
81 | *
82 | * Specifies if the STYLE_NOEDGESTYLE flag should be set on edges that are
83 | * modified by the result. Default is true.
84 | */
85 | mxCircleLayout.prototype.disableEdgeStyle = true;
86 |
87 | /**
88 | * Function: execute
89 | *
90 | * Implements .
91 | */
92 | mxCircleLayout.prototype.execute = function(parent)
93 | {
94 | var model = this.graph.getModel();
95 |
96 | // Moves the vertices to build a circle. Makes sure the
97 | // radius is large enough for the vertices to not
98 | // overlap
99 | model.beginUpdate();
100 | try
101 | {
102 | // Gets all vertices inside the parent and finds
103 | // the maximum dimension of the largest vertex
104 | var max = 0;
105 | var top = null;
106 | var left = null;
107 | var vertices = [];
108 | var childCount = model.getChildCount(parent);
109 |
110 | for (var i = 0; i < childCount; i++)
111 | {
112 | var cell = model.getChildAt(parent, i);
113 |
114 | if (!this.isVertexIgnored(cell))
115 | {
116 | vertices.push(cell);
117 | var bounds = this.getVertexBounds(cell);
118 |
119 | if (top == null)
120 | {
121 | top = bounds.y;
122 | }
123 | else
124 | {
125 | top = Math.min(top, bounds.y);
126 | }
127 |
128 | if (left == null)
129 | {
130 | left = bounds.x;
131 | }
132 | else
133 | {
134 | left = Math.min(left, bounds.x);
135 | }
136 |
137 | max = Math.max(max, Math.max(bounds.width, bounds.height));
138 | }
139 | else if (!this.isEdgeIgnored(cell))
140 | {
141 | // Resets the points on the traversed edge
142 | if (this.resetEdges)
143 | {
144 | this.graph.resetEdge(cell);
145 | }
146 |
147 | if (this.disableEdgeStyle)
148 | {
149 | this.setEdgeStyleEnabled(cell, false);
150 | }
151 | }
152 | }
153 |
154 | var r = this.getRadius(vertices.length, max);
155 |
156 | // Moves the circle to the specified origin
157 | if (this.moveCircle)
158 | {
159 | left = this.x0;
160 | top = this.y0;
161 | }
162 |
163 | this.circle(vertices, r, left, top);
164 | }
165 | finally
166 | {
167 | model.endUpdate();
168 | }
169 | };
170 |
171 | /**
172 | * Function: getRadius
173 | *
174 | * Returns the radius to be used for the given vertex count. Max is the maximum
175 | * width or height of all vertices in the layout.
176 | */
177 | mxCircleLayout.prototype.getRadius = function(count, max)
178 | {
179 | return Math.max(count * max / Math.PI, this.radius);
180 | };
181 |
182 | /**
183 | * Function: circle
184 | *
185 | * Executes the circular layout for the specified array
186 | * of vertices and the given radius. This is called from
187 | * .
188 | */
189 | mxCircleLayout.prototype.circle = function(vertices, r, left, top)
190 | {
191 | var vertexCount = vertices.length;
192 | var phi = 2 * Math.PI / vertexCount;
193 |
194 | for (var i = 0; i < vertexCount; i++)
195 | {
196 | if (this.isVertexMovable(vertices[i]))
197 | {
198 | this.setVertexLocation(vertices[i],
199 | Math.round(left + r + r * Math.sin(i * phi)),
200 | Math.round(top + r + r * Math.cos(i * phi)));
201 | }
202 | }
203 | };
204 |
205 | window.mxCircleLayout = mxCircleLayout;
--------------------------------------------------------------------------------
/resources/js/io/mxCellCodec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | mxCodecRegistry.register(function () {
6 | /**
7 | * Class: mxCellCodec
8 | *
9 | * Codec for s. This class is created and registered
10 | * dynamically at load time and used implicitely via
11 | * and the .
12 | *
13 | * Transient Fields:
14 | *
15 | * - children
16 | * - edges
17 | * - overlays
18 | * - mxTransient
19 | *
20 | * Reference Fields:
21 | *
22 | * - parent
23 | * - source
24 | * - target
25 | *
26 | * Transient fields can be added using the following code:
27 | *
28 | * mxCodecRegistry.getCodec(mxCell).exclude.push('name_of_field');
29 | *
30 | * To subclass , replace the template and add an alias as
31 | * follows.
32 | *
33 | * (code)
34 | * function CustomCell(value, geometry, style)
35 | * {
36 | * mxCell.apply(this, arguments);
37 | * }
38 | *
39 | * mxUtils.extend(CustomCell, mxCell);
40 | *
41 | * mxCodecRegistry.getCodec(mxCell).template = new CustomCell();
42 | * mxCodecRegistry.addAlias('CustomCell', 'mxCell');
43 | * (end)
44 | */
45 | const codec = new mxObjectCodec(new mxCell(),
46 | ['children', 'edges', 'overlays', 'mxTransient'],
47 | ['parent', 'source', 'target']);
48 |
49 | /**
50 | * Function: isCellCodec
51 | *
52 | * Returns true since this is a cell codec.
53 | */
54 | codec.isCellCodec = function () {
55 | return true;
56 | };
57 |
58 | /**
59 | * Overidden to disable conversion of value to number.
60 | */
61 | codec.isNumericAttribute = function (dec, attr, obj) {
62 | return attr.nodeName !== 'value' && mxObjectCodec.prototype.isNumericAttribute.apply(this, arguments);
63 | };
64 |
65 | /**
66 | * Function: isExcluded
67 | *
68 | * Excludes user objects that are XML nodes.
69 | */
70 | codec.isExcluded = function (obj, attr, value, isWrite) {
71 | return mxObjectCodec.prototype.isExcluded.apply(this, arguments)
72 | || (isWrite && attr == 'value'
73 | && value.nodeType == mxConstants.NODETYPE_ELEMENT);
74 | };
75 |
76 | /**
77 | * Function: afterEncode
78 | *
79 | * Encodes an and wraps the XML up inside the
80 | * XML of the user object (inversion).
81 | */
82 | codec.afterEncode = function (enc, obj, node) {
83 | if (obj.value != null && obj.value.nodeType == mxConstants.NODETYPE_ELEMENT) {
84 | // Wraps the graphical annotation up in the user object (inversion)
85 | // by putting the result of the default encoding into a clone of the
86 | // user object (node type 1) and returning this cloned user object.
87 | const tmp = node;
88 | node = mxUtils.importNode(enc.document, obj.value, true);
89 | node.appendChild(tmp);
90 |
91 | // Moves the id attribute to the outermost XML node, namely the
92 | // node which denotes the object boundaries in the file.
93 | const id = tmp.getAttribute('id');
94 | node.setAttribute('id', id);
95 | tmp.removeAttribute('id');
96 | }
97 |
98 | return node;
99 | };
100 |
101 | /**
102 | * Function: beforeDecode
103 | *
104 | * Decodes an and uses the enclosing XML node as
105 | * the user object for the cell (inversion).
106 | */
107 | codec.beforeDecode = function (dec, node, obj) {
108 | let inner = node.cloneNode(true);
109 | const classname = this.getName();
110 |
111 | if (node.nodeName != classname) {
112 | // Passes the inner graphical annotation node to the
113 | // object codec for further processing of the cell.
114 | const tmp = node.getElementsByTagName(classname)[0];
115 |
116 | if (tmp != null && tmp.parentNode == node) {
117 | mxUtils.removeWhitespace(tmp, true);
118 | mxUtils.removeWhitespace(tmp, false);
119 | tmp.parentNode.removeChild(tmp);
120 | inner = tmp;
121 | } else {
122 | inner = null;
123 | }
124 |
125 | // Creates the user object out of the XML node
126 | obj.value = node.cloneNode(true);
127 | const id = obj.value.getAttribute('id');
128 |
129 | if (id != null) {
130 | obj.setId(id);
131 | obj.value.removeAttribute('id');
132 | }
133 | } else {
134 | // Uses ID from XML file as ID for cell in model
135 | obj.setId(node.getAttribute('id'));
136 | }
137 |
138 | // Preprocesses and removes all Id-references in order to use the
139 | // correct encoder (this) for the known references to cells (all).
140 | if (inner != null) {
141 | for (let i = 0; i < this.idrefs.length; i++) {
142 | const attr = this.idrefs[i];
143 | const ref = inner.getAttribute(attr);
144 |
145 | if (ref != null) {
146 | inner.removeAttribute(attr);
147 | let object = dec.objects[ref] || dec.lookup(ref);
148 |
149 | if (object == null) {
150 | // Needs to decode forward reference
151 | const element = dec.getElementById(ref);
152 |
153 | if (element != null) {
154 | const decoder = mxCodecRegistry.codecs[element.nodeName] || this;
155 | object = decoder.decode(dec, element);
156 | }
157 | }
158 |
159 | obj[attr] = object;
160 | }
161 | }
162 | }
163 |
164 | return inner;
165 | };
166 |
167 | // Returns the codec into the registry
168 | return codec;
169 | }());
170 |
--------------------------------------------------------------------------------
/resources/js/util/mxEffects.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | var mxEffects =
6 | {
7 |
8 | /**
9 | * Class: mxEffects
10 | *
11 | * Provides animation effects.
12 | */
13 |
14 | /**
15 | * Function: animateChanges
16 | *
17 | * Asynchronous animated move operation. See also: .
18 | *
19 | * Example:
20 | *
21 | * (code)
22 | * graph.model.addListener(mxEvent.CHANGE, function(sender, evt)
23 | * {
24 | * var changes = evt.getProperty('edit').changes;
25 | *
26 | * if (changes.length < 10)
27 | * {
28 | * mxEffects.animateChanges(graph, changes);
29 | * }
30 | * });
31 | * (end)
32 | *
33 | * Parameters:
34 | *
35 | * graph - that received the changes.
36 | * changes - Array of changes to be animated.
37 | * done - Optional function argument that is invoked after the
38 | * last step of the animation.
39 | */
40 | animateChanges: function(graph, changes, done)
41 | {
42 | var maxStep = 10;
43 | var step = 0;
44 |
45 | var animate = function()
46 | {
47 | var isRequired = false;
48 |
49 | for (var i = 0; i < changes.length; i++)
50 | {
51 | var change = changes[i];
52 |
53 | if (change instanceof mxGeometryChange ||
54 | change instanceof mxTerminalChange ||
55 | change instanceof mxValueChange ||
56 | change instanceof mxChildChange ||
57 | change instanceof mxStyleChange)
58 | {
59 | var state = graph.getView().getState(change.cell || change.child, false);
60 |
61 | if (state != null)
62 | {
63 | isRequired = true;
64 |
65 | if (change.constructor != mxGeometryChange || graph.model.isEdge(change.cell))
66 | {
67 | mxUtils.setOpacity(state.shape.node, 100 * step / maxStep);
68 | }
69 | else
70 | {
71 | var scale = graph.getView().scale;
72 |
73 | var dx = (change.geometry.x - change.previous.x) * scale;
74 | var dy = (change.geometry.y - change.previous.y) * scale;
75 |
76 | var sx = (change.geometry.width - change.previous.width) * scale;
77 | var sy = (change.geometry.height - change.previous.height) * scale;
78 |
79 | if (step == 0)
80 | {
81 | state.x -= dx;
82 | state.y -= dy;
83 | state.width -= sx;
84 | state.height -= sy;
85 | }
86 | else
87 | {
88 | state.x += dx / maxStep;
89 | state.y += dy / maxStep;
90 | state.width += sx / maxStep;
91 | state.height += sy / maxStep;
92 | }
93 |
94 | graph.cellRenderer.redraw(state);
95 |
96 | // Fades all connected edges and children
97 | mxEffects.cascadeOpacity(graph, change.cell, 100 * step / maxStep);
98 | }
99 | }
100 | }
101 | }
102 |
103 | if (step < maxStep && isRequired)
104 | {
105 | step++;
106 | window.setTimeout(animate, delay);
107 | }
108 | else if (done != null)
109 | {
110 | done();
111 | }
112 | };
113 |
114 | var delay = 30;
115 | animate();
116 | },
117 |
118 | /**
119 | * Function: cascadeOpacity
120 | *
121 | * Sets the opacity on the given cell and its descendants.
122 | *
123 | * Parameters:
124 | *
125 | * graph - that contains the cells.
126 | * cell - to set the opacity for.
127 | * opacity - New value for the opacity in %.
128 | */
129 | cascadeOpacity: function(graph, cell, opacity)
130 | {
131 | // Fades all children
132 | var childCount = graph.model.getChildCount(cell);
133 |
134 | for (var i=0; i 0)
185 | {
186 | window.setTimeout(f, delay);
187 | }
188 | else
189 | {
190 | node.style.visibility = 'hidden';
191 |
192 | if (remove && node.parentNode)
193 | {
194 | node.parentNode.removeChild(node);
195 | }
196 | }
197 | };
198 | window.setTimeout(f, delay);
199 | }
200 | else
201 | {
202 | node.style.visibility = 'hidden';
203 |
204 | if (remove && node.parentNode)
205 | {
206 | node.parentNode.removeChild(node);
207 | }
208 | }
209 | }
210 |
211 | };
212 |
213 | window.mxEffects = mxEffects;
--------------------------------------------------------------------------------
/resources/js/util/mxAutoSaveManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxAutoSaveManager
7 | *
8 | * Manager for automatically saving diagrams. The hook must be
9 | * implemented.
10 | *
11 | * Example:
12 | *
13 | * (code)
14 | * var mgr = new mxAutoSaveManager(editor.graph);
15 | * mgr.save = function()
16 | * {
17 | * mxLog.show();
18 | * mxLog.debug('save');
19 | * };
20 | * (end)
21 | *
22 | * Constructor: mxAutoSaveManager
23 | *
24 | * Constructs a new automatic layout for the given graph.
25 | *
26 | * Arguments:
27 | *
28 | * graph - Reference to the enclosing graph.
29 | */
30 | function mxAutoSaveManager(graph)
31 | {
32 | // Notifies the manager of a change
33 | this.changeHandler = mxUtils.bind(this, function(sender, evt)
34 | {
35 | if (this.isEnabled())
36 | {
37 | this.graphModelChanged(evt.getProperty('edit').changes);
38 | }
39 | });
40 |
41 | this.setGraph(graph);
42 | };
43 |
44 | /**
45 | * Extends mxEventSource.
46 | */
47 | mxAutoSaveManager.prototype = new mxEventSource();
48 | mxAutoSaveManager.prototype.constructor = mxAutoSaveManager;
49 |
50 | /**
51 | * Variable: graph
52 | *
53 | * Reference to the enclosing .
54 | */
55 | mxAutoSaveManager.prototype.graph = null;
56 |
57 | /**
58 | * Variable: autoSaveDelay
59 | *
60 | * Minimum amount of seconds between two consecutive autosaves. Eg. a
61 | * value of 1 (s) means the graph is not stored more than once per second.
62 | * Default is 10.
63 | */
64 | mxAutoSaveManager.prototype.autoSaveDelay = 10;
65 |
66 | /**
67 | * Variable: autoSaveThrottle
68 | *
69 | * Minimum amount of seconds between two consecutive autosaves triggered by
70 | * more than changes within a timespan of less than
71 | * seconds. Eg. a value of 1 (s) means the graph is not
72 | * stored more than once per second even if there are more than
73 | * changes within that timespan. Default is 2.
74 | */
75 | mxAutoSaveManager.prototype.autoSaveThrottle = 2;
76 |
77 | /**
78 | * Variable: autoSaveThreshold
79 | *
80 | * Minimum amount of ignored changes before an autosave. Eg. a value of 2
81 | * means after 2 change of the graph model the autosave will trigger if the
82 | * condition below is true. Default is 5.
83 | */
84 | mxAutoSaveManager.prototype.autoSaveThreshold = 5;
85 |
86 | /**
87 | * Variable: ignoredChanges
88 | *
89 | * Counter for ignored changes in autosave.
90 | */
91 | mxAutoSaveManager.prototype.ignoredChanges = 0;
92 |
93 | /**
94 | * Variable: lastSnapshot
95 | *
96 | * Used for autosaving. See .
97 | */
98 | mxAutoSaveManager.prototype.lastSnapshot = 0;
99 |
100 | /**
101 | * Variable: enabled
102 | *
103 | * Specifies if event handling is enabled. Default is true.
104 | */
105 | mxAutoSaveManager.prototype.enabled = true;
106 |
107 | /**
108 | * Variable: changeHandler
109 | *
110 | * Holds the function that handles graph model changes.
111 | */
112 | mxAutoSaveManager.prototype.changeHandler = null;
113 |
114 | /**
115 | * Function: isEnabled
116 | *
117 | * Returns true if events are handled. This implementation
118 | * returns .
119 | */
120 | mxAutoSaveManager.prototype.isEnabled = function()
121 | {
122 | return this.enabled;
123 | };
124 |
125 | /**
126 | * Function: setEnabled
127 | *
128 | * Enables or disables event handling. This implementation
129 | * updates .
130 | *
131 | * Parameters:
132 | *
133 | * enabled - Boolean that specifies the new enabled state.
134 | */
135 | mxAutoSaveManager.prototype.setEnabled = function(value)
136 | {
137 | this.enabled = value;
138 | };
139 |
140 | /**
141 | * Function: setGraph
142 | *
143 | * Sets the graph that the layouts operate on.
144 | */
145 | mxAutoSaveManager.prototype.setGraph = function(graph)
146 | {
147 | if (this.graph != null)
148 | {
149 | this.graph.getModel().removeListener(this.changeHandler);
150 | }
151 |
152 | this.graph = graph;
153 |
154 | if (this.graph != null)
155 | {
156 | this.graph.getModel().addListener(mxEvent.CHANGE, this.changeHandler);
157 | }
158 | };
159 |
160 | /**
161 | * Function: save
162 | *
163 | * Empty hook that is called if the graph should be saved.
164 | */
165 | mxAutoSaveManager.prototype.save = function()
166 | {
167 | // empty
168 | };
169 |
170 | /**
171 | * Function: graphModelChanged
172 | *
173 | * Invoked when the graph model has changed.
174 | */
175 | mxAutoSaveManager.prototype.graphModelChanged = function(changes)
176 | {
177 | var now = new Date().getTime();
178 | var dt = (now - this.lastSnapshot) / 1000;
179 |
180 | if (dt > this.autoSaveDelay ||
181 | (this.ignoredChanges >= this.autoSaveThreshold &&
182 | dt > this.autoSaveThrottle))
183 | {
184 | this.save();
185 | this.reset();
186 | }
187 | else
188 | {
189 | // Increments the number of ignored changes
190 | this.ignoredChanges++;
191 | }
192 | };
193 |
194 | /**
195 | * Function: reset
196 | *
197 | * Resets all counters.
198 | */
199 | mxAutoSaveManager.prototype.reset = function()
200 | {
201 | this.lastSnapshot = new Date().getTime();
202 | this.ignoredChanges = 0;
203 | };
204 |
205 | /**
206 | * Function: destroy
207 | *
208 | * Removes all handlers from the and deletes the reference to it.
209 | */
210 | mxAutoSaveManager.prototype.destroy = function()
211 | {
212 | this.setGraph(null);
213 | };
214 |
215 | window.mxAutoSaveManager = mxAutoSaveManager;
--------------------------------------------------------------------------------
/resources/js/util/mxUndoableEdit.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2006-2015, JGraph Ltd
3 | * Copyright (c) 2006-2015, Gaudenz Alder
4 | */
5 | /**
6 | * Class: mxUndoableEdit
7 | *
8 | * Implements a composite undoable edit. Here is an example for a custom change
9 | * which gets executed via the model:
10 | *
11 | * (code)
12 | * function CustomChange(model, name)
13 | * {
14 | * this.model = model;
15 | * this.name = name;
16 | * this.previous = name;
17 | * };
18 | *
19 | * CustomChange.prototype.execute = function()
20 | * {
21 | * var tmp = this.model.name;
22 | * this.model.name = this.previous;
23 | * this.previous = tmp;
24 | * };
25 | *
26 | * var name = prompt('Enter name');
27 | * graph.model.execute(new CustomChange(graph.model, name));
28 | * (end)
29 | *
30 | * Event: mxEvent.EXECUTED
31 | *
32 | * Fires between START_EDIT and END_EDIT after an atomic change was executed.
33 | * The