summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoradhitya2016-04-12 07:02:39 +0000
committeradhitya2016-04-12 07:02:39 +0000
commitdd83478e3fcaac98de690aa59e6288ad41a1c351 (patch)
tree38653bdf0ae95053f66777c4ac3fe5be5d8fbd33 /src
parent92f3207b50a1caca07df5c5b238212af3358905b (diff)
downloadxcos-on-web-dd83478e3fcaac98de690aa59e6288ad41a1c351.tar.gz
xcos-on-web-dd83478e3fcaac98de690aa59e6288ad41a1c351.tar.bz2
xcos-on-web-dd83478e3fcaac98de690aa59e6288ad41a1c351.zip
Keyboard shortcuts work properly
Diffstat (limited to 'src')
-rw-r--r--src/css/common.css152
-rw-r--r--src/css/explorer.css15
-rw-r--r--src/images/button.gifbin137 -> 0 bytes
-rw-r--r--src/images/close.gifbin70 -> 0 bytes
-rw-r--r--src/images/collapsed.gifbin877 -> 0 bytes
-rw-r--r--src/images/error.gifbin907 -> 0 bytes
-rw-r--r--src/images/expanded.gifbin878 -> 0 bytes
-rw-r--r--src/images/maximize.gifbin843 -> 0 bytes
-rw-r--r--src/images/minimize.gifbin64 -> 0 bytes
-rw-r--r--src/images/normalize.gifbin845 -> 0 bytes
-rw-r--r--src/images/point.gifbin55 -> 0 bytes
-rw-r--r--src/images/resize.gifbin74 -> 0 bytes
-rw-r--r--src/images/separator.gifbin146 -> 0 bytes
-rw-r--r--src/images/submenu.gifbin56 -> 0 bytes
-rw-r--r--src/images/transparent.gifbin90 -> 0 bytes
-rw-r--r--src/images/warning.gifbin276 -> 0 bytes
-rw-r--r--src/images/warning.pngbin425 -> 0 bytes
-rw-r--r--src/images/window-title.gifbin275 -> 0 bytes
-rw-r--r--src/images/window.gifbin75 -> 0 bytes
-rw-r--r--src/js/editor/mxDefaultKeyHandler.js126
-rw-r--r--src/js/editor/mxDefaultPopupMenu.js300
-rw-r--r--src/js/editor/mxDefaultToolbar.js567
-rw-r--r--src/js/editor/mxEditor.js3220
-rw-r--r--src/js/handler/mxCellHighlight.js271
-rw-r--r--src/js/handler/mxCellMarker.js419
-rw-r--r--src/js/handler/mxCellTracker.js149
-rw-r--r--src/js/handler/mxConnectionHandler.js1969
-rw-r--r--src/js/handler/mxConstraintHandler.js308
-rw-r--r--src/js/handler/mxEdgeHandler.js1529
-rw-r--r--src/js/handler/mxEdgeSegmentHandler.js284
-rw-r--r--src/js/handler/mxElbowEdgeHandler.js248
-rw-r--r--src/js/handler/mxGraphHandler.js916
-rw-r--r--src/js/handler/mxKeyHandler.js402
-rw-r--r--src/js/handler/mxPanningHandler.js390
-rw-r--r--src/js/handler/mxRubberband.js348
-rw-r--r--src/js/handler/mxSelectionCellsHandler.js260
-rw-r--r--src/js/handler/mxTooltipHandler.js317
-rw-r--r--src/js/handler/mxVertexHandler.js753
-rw-r--r--src/js/index.txt316
-rw-r--r--src/js/io/mxCellCodec.js170
-rw-r--r--src/js/io/mxChildChangeCodec.js149
-rw-r--r--src/js/io/mxCodec.js531
-rw-r--r--src/js/io/mxCodecRegistry.js137
-rw-r--r--src/js/io/mxDefaultKeyHandlerCodec.js88
-rw-r--r--src/js/io/mxDefaultPopupMenuCodec.js54
-rw-r--r--src/js/io/mxDefaultToolbarCodec.js301
-rw-r--r--src/js/io/mxEditorCodec.js246
-rw-r--r--src/js/io/mxGenericChangeCodec.js64
-rw-r--r--src/js/io/mxGraphCodec.js28
-rw-r--r--src/js/io/mxGraphViewCodec.js197
-rw-r--r--src/js/io/mxModelCodec.js80
-rw-r--r--src/js/io/mxObjectCodec.js983
-rw-r--r--src/js/io/mxRootChangeCodec.js83
-rw-r--r--src/js/io/mxStylesheetCodec.js210
-rw-r--r--src/js/io/mxTerminalChangeCodec.js42
-rw-r--r--src/js/layout/hierarchical/model/mxGraphAbstractHierarchyCell.js206
-rw-r--r--src/js/layout/hierarchical/model/mxGraphHierarchyEdge.js174
-rw-r--r--src/js/layout/hierarchical/model/mxGraphHierarchyModel.js685
-rw-r--r--src/js/layout/hierarchical/model/mxGraphHierarchyNode.js210
-rw-r--r--src/js/layout/hierarchical/mxHierarchicalLayout.js623
-rw-r--r--src/js/layout/hierarchical/stage/mxCoordinateAssignment.js1836
-rw-r--r--src/js/layout/hierarchical/stage/mxHierarchicalLayoutStage.js25
-rw-r--r--src/js/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js674
-rw-r--r--src/js/layout/hierarchical/stage/mxMinimumCycleRemover.js131
-rw-r--r--src/js/layout/mxCircleLayout.js203
-rw-r--r--src/js/layout/mxCompactTreeLayout.js995
-rw-r--r--src/js/layout/mxCompositeLayout.js101
-rw-r--r--src/js/layout/mxEdgeLabelLayout.js165
-rw-r--r--src/js/layout/mxFastOrganicLayout.js591
-rw-r--r--src/js/layout/mxGraphLayout.js503
-rw-r--r--src/js/layout/mxParallelEdgeLayout.js198
-rw-r--r--src/js/layout/mxPartitionLayout.js240
-rw-r--r--src/js/layout/mxStackLayout.js381
-rw-r--r--src/js/model/mxCell.js806
-rw-r--r--src/js/model/mxCellPath.js163
-rw-r--r--src/js/model/mxGeometry.js277
-rw-r--r--src/js/model/mxGraphModel.js2622
-rw-r--r--src/js/mxClient.js643
-rw-r--r--src/js/shape/mxActor.js183
-rw-r--r--src/js/shape/mxArrow.js226
-rw-r--r--src/js/shape/mxCloud.js56
-rw-r--r--src/js/shape/mxConnector.js446
-rw-r--r--src/js/shape/mxCylinder.js319
-rw-r--r--src/js/shape/mxDoubleEllipse.js203
-rw-r--r--src/js/shape/mxEllipse.js132
-rw-r--r--src/js/shape/mxHexagon.js37
-rw-r--r--src/js/shape/mxImageShape.js405
-rw-r--r--src/js/shape/mxLabel.js427
-rw-r--r--src/js/shape/mxLine.js217
-rw-r--r--src/js/shape/mxMarker.js267
-rw-r--r--src/js/shape/mxPolyline.js146
-rw-r--r--src/js/shape/mxRectangleShape.js61
-rw-r--r--src/js/shape/mxRhombus.js172
-rw-r--r--src/js/shape/mxShape.js2045
-rw-r--r--src/js/shape/mxStencil.js1585
-rw-r--r--src/js/shape/mxStencilRegistry.js53
-rw-r--r--src/js/shape/mxStencilShape.js209
-rw-r--r--src/js/shape/mxSwimlane.js553
-rw-r--r--src/js/shape/mxText.js1811
-rw-r--r--src/js/shape/mxTriangle.js34
-rw-r--r--src/js/util/mxAnimation.js82
-rw-r--r--src/js/util/mxAutoSaveManager.js213
-rw-r--r--src/js/util/mxClipboard.js144
-rw-r--r--src/js/util/mxConstants.js1911
-rw-r--r--src/js/util/mxDictionary.js130
-rw-r--r--src/js/util/mxDivResizer.js151
-rw-r--r--src/js/util/mxDragSource.js594
-rw-r--r--src/js/util/mxEffects.js214
-rw-r--r--src/js/util/mxEvent.js1175
-rw-r--r--src/js/util/mxEventObject.js111
-rw-r--r--src/js/util/mxEventSource.js191
-rw-r--r--src/js/util/mxForm.js202
-rw-r--r--src/js/util/mxGuide.js364
-rw-r--r--src/js/util/mxImage.js40
-rw-r--r--src/js/util/mxImageBundle.js98
-rw-r--r--src/js/util/mxImageExport.js1412
-rw-r--r--src/js/util/mxLog.js410
-rw-r--r--src/js/util/mxMorphing.js239
-rw-r--r--src/js/util/mxMouseEvent.js241
-rw-r--r--src/js/util/mxObjectIdentity.js59
-rw-r--r--src/js/util/mxPanningManager.js262
-rw-r--r--src/js/util/mxPath.js314
-rw-r--r--src/js/util/mxPoint.js55
-rw-r--r--src/js/util/mxPopupMenu.js574
-rw-r--r--src/js/util/mxRectangle.js134
-rw-r--r--src/js/util/mxResources.js366
-rw-r--r--src/js/util/mxSession.js674
-rw-r--r--src/js/util/mxSvgCanvas2D.js1234
-rw-r--r--src/js/util/mxToolbar.js528
-rw-r--r--src/js/util/mxUndoManager.js229
-rw-r--r--src/js/util/mxUndoableEdit.js168
-rw-r--r--src/js/util/mxUrlConverter.js141
-rw-r--r--src/js/util/mxUtils.js3920
-rw-r--r--src/js/util/mxWindow.js1065
-rw-r--r--src/js/util/mxXmlCanvas2D.js715
-rw-r--r--src/js/util/mxXmlRequest.js425
-rw-r--r--src/js/view/mxCellEditor.js522
-rw-r--r--src/js/view/mxCellOverlay.js233
-rw-r--r--src/js/view/mxCellRenderer.js1480
-rw-r--r--src/js/view/mxCellState.js375
-rw-r--r--src/js/view/mxCellStatePreview.js223
-rw-r--r--src/js/view/mxConnectionConstraint.js42
-rw-r--r--src/js/view/mxEdgeStyle.js1302
-rw-r--r--src/js/view/mxGraph.js11176
-rw-r--r--src/js/view/mxGraphSelectionModel.js435
-rw-r--r--src/js/view/mxGraphView.js2545
-rw-r--r--src/js/view/mxLayoutManager.js375
-rw-r--r--src/js/view/mxMultiplicity.js257
-rw-r--r--src/js/view/mxOutline.js649
-rw-r--r--src/js/view/mxPerimeter.js484
-rw-r--r--src/js/view/mxPrintPreview.js801
-rw-r--r--src/js/view/mxSpaceManager.js460
-rw-r--r--src/js/view/mxStyleRegistry.js70
-rw-r--r--src/js/view/mxStylesheet.js266
-rw-r--r--src/js/view/mxSwimlaneManager.js449
-rw-r--r--src/js/view/mxTemporaryCellStates.js105
-rw-r--r--src/js/xcos/core/details.js204
-rw-r--r--src/resources/editor.properties5
-rw-r--r--src/resources/graph.properties11
159 files changed, 0 insertions, 79915 deletions
diff --git a/src/css/common.css b/src/css/common.css
deleted file mode 100644
index 5eb0b45..0000000
--- a/src/css/common.css
+++ /dev/null
@@ -1,152 +0,0 @@
-div.mxRubberband {
- position: absolute;
- overflow: hidden;
- border-style: solid;
- border-width: 1px;
- border-color: #0000FF;
- background: #0077FF;
-}
-textarea.mxCellEditor {
- background: url('../images/transparent.gif');
- border-style: solid;
- border-color: black;
- border-width: 0;
- overflow: auto;
-}
-div.mxWindow {
- -webkit-box-shadow: 3px 3px 12px #C0C0C0;
- -moz-box-shadow: 3px 3px 12px #C0C0C0;
- box-shadow: 3px 3px 12px #C0C0C0;
- background: url('../images/window.gif');
- border-style: outset;
- border-width: 1px;
- position: absolute;
- overflow: hidden;
- z-index: 1;
-}
-table.mxWindow {
- border-collapse: collapse;
- table-layout: fixed;
- font-family: Arial;
- font-size: 8pt;
-}
-td.mxWindowTitle {
- background: url('../images/window-title.gif') repeat-x;
- text-overflow: ellipsis;
- white-space: nowrap;
- text-align: center;
- font-weight: bold;
- overflow: hidden;
- height: 13px;
- padding: 2px;
- padding-top: 4px;
- padding-bottom: 6px;
- color: black;
-}
-td.mxWindowPane {
- vertical-align: top;
- padding: 0px;
-}
-div.mxWindowPane {
- overflow: hidden;
-}
-td.mxWindowPane td {
- font-family: Arial;
- font-size: 8pt;
-}
-td.mxWindowPane input, td.mxWindowPane select, td.mxWindowPane textarea, td.mxWindowPane radio {
- border-color: #8C8C8C;
- border-style: solid;
- border-width: 1px;
- font-family: Arial;
- font-size: 8pt;
- padding: 1px;
-}
-td.mxWindowPane button {
- background: url('../images/button.gif') repeat-x;
- font-family: Arial;
- font-size: 8pt;
- padding: 2px;
- float: left;
-}
-img.mxToolbarItem {
- margin-right: 6px;
- margin-bottom: 6px;
- border-width: 1px;
-}
-select.mxToolbarCombo {
- vertical-align: top;
- border-style: inset;
- border-width: 2px;
-}
-div.mxToolbarComboContainer {
- padding: 2px;
-}
-img.mxToolbarMode {
- margin: 2px;
- margin-right: 4px;
- margin-bottom: 4px;
- border-width: 0px;
-}
-img.mxToolbarModeSelected {
- margin: 0px;
- margin-right: 2px;
- margin-bottom: 2px;
- border-width: 2px;
- border-style: inset;
-}
-div.mxTooltip {
- -webkit-box-shadow: 3px 3px 12px #C0C0C0;
- -moz-box-shadow: 3px 3px 12px #C0C0C0;
- box-shadow: 3px 3px 12px #C0C0C0;
- background: #FFFFCC;
- border-style: solid;
- border-width: 1px;
- border-color: black;
- font-family: Arial;
- font-size: 8pt;
- position: absolute;
- cursor: default;
- padding: 4px;
- color: black;
-}
-div.mxPopupMenu {
- -webkit-box-shadow: 3px 3px 12px #C0C0C0;
- -moz-box-shadow: 3px 3px 12px #C0C0C0;
- box-shadow: 3px 3px 12px #C0C0C0;
- background: url('../images/window.gif');
- position: absolute;
- border-style: solid;
- border-width: 1px;
- border-color: black;
- cursor: default;
-}
-table.mxPopupMenu {
- border-collapse: collapse;
- margin-top: 1px;
- margin-bottom: 1px;
-}
-tr.mxPopupMenuItem {
- color: black;
- cursor: default;
-}
-td.mxPopupMenuItem.disabled {
- opacity: 0.2;
-}
-td.mxPopupMenuItem.disabled {
- _filter:alpha(opacity=20) !important;
-}
-tr.mxPopupMenuItemHover {
- background-color: #000066;
- color: #FFFFFF;
-}
-td.mxPopupMenuItem {
- padding: 2px 30px 2px 10px;
- white-space: nowrap;
- font-family: Arial;
- font-size: 8pt;
-}
-td.mxPopupMenuIcon {
- background-color: #D0D0D0;
- padding: 2px 4px 2px 4px;
-}
diff --git a/src/css/explorer.css b/src/css/explorer.css
deleted file mode 100644
index dfbbd21..0000000
--- a/src/css/explorer.css
+++ /dev/null
@@ -1,15 +0,0 @@
-div.mxTooltip {
- filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4,
- Color='#A2A2A2', Positive='true')
-}
-div.mxPopupMenu {
- filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4,
- Color='#C0C0C0', Positive='true')
-}
-div.mxWindow {
- filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4,
- Color='#C0C0C0', Positive='true')
-}
-td.mxWindowTitle {
- _height: 23px;
-}
diff --git a/src/images/button.gif b/src/images/button.gif
deleted file mode 100644
index ad55cab..0000000
--- a/src/images/button.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/close.gif b/src/images/close.gif
deleted file mode 100644
index 1069e94..0000000
--- a/src/images/close.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/collapsed.gif b/src/images/collapsed.gif
deleted file mode 100644
index 0276444..0000000
--- a/src/images/collapsed.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/error.gif b/src/images/error.gif
deleted file mode 100644
index 14e1aee..0000000
--- a/src/images/error.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/expanded.gif b/src/images/expanded.gif
deleted file mode 100644
index 3767b0b..0000000
--- a/src/images/expanded.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/maximize.gif b/src/images/maximize.gif
deleted file mode 100644
index e27cf3e..0000000
--- a/src/images/maximize.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/minimize.gif b/src/images/minimize.gif
deleted file mode 100644
index 1e95e7c..0000000
--- a/src/images/minimize.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/normalize.gif b/src/images/normalize.gif
deleted file mode 100644
index 34a8d30..0000000
--- a/src/images/normalize.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/point.gif b/src/images/point.gif
deleted file mode 100644
index 9074c39..0000000
--- a/src/images/point.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/resize.gif b/src/images/resize.gif
deleted file mode 100644
index ff558db..0000000
--- a/src/images/resize.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/separator.gif b/src/images/separator.gif
deleted file mode 100644
index 5c1b895..0000000
--- a/src/images/separator.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/submenu.gif b/src/images/submenu.gif
deleted file mode 100644
index ffe7617..0000000
--- a/src/images/submenu.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/transparent.gif b/src/images/transparent.gif
deleted file mode 100644
index 76040f2..0000000
--- a/src/images/transparent.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/warning.gif b/src/images/warning.gif
deleted file mode 100644
index 705235f..0000000
--- a/src/images/warning.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/warning.png b/src/images/warning.png
deleted file mode 100644
index 2f78789..0000000
--- a/src/images/warning.png
+++ /dev/null
Binary files differ
diff --git a/src/images/window-title.gif b/src/images/window-title.gif
deleted file mode 100644
index 231def8..0000000
--- a/src/images/window-title.gif
+++ /dev/null
Binary files differ
diff --git a/src/images/window.gif b/src/images/window.gif
deleted file mode 100644
index 6631c4f..0000000
--- a/src/images/window.gif
+++ /dev/null
Binary files differ
diff --git a/src/js/editor/mxDefaultKeyHandler.js b/src/js/editor/mxDefaultKeyHandler.js
deleted file mode 100644
index 3814e5e..0000000
--- a/src/js/editor/mxDefaultKeyHandler.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * $Id: mxDefaultKeyHandler.js,v 1.26 2010-01-02 09:45:15 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxDefaultKeyHandler
- *
- * Binds keycodes to actionnames in an editor. This aggregates an internal
- * <handler> and extends the implementation of <mxKeyHandler.escape> to not
- * only cancel the editing, but also hide the properties dialog and fire an
- * <mxEditor.escape> event via <editor>. An instance of this class is created
- * by <mxEditor> and stored in <mxEditor.keyHandler>.
- *
- * Example:
- *
- * Bind the delete key to the delete action in an existing editor.
- *
- * (code)
- * var keyHandler = new mxDefaultKeyHandler(editor);
- * keyHandler.bindAction(46, 'delete');
- * (end)
- *
- * Codec:
- *
- * This class uses the <mxDefaultKeyHandlerCodec> to read configuration
- * data into an existing instance. See <mxDefaultKeyHandlerCodec> for a
- * description of the configuration format.
- *
- * Keycodes:
- *
- * See <mxKeyHandler>.
- *
- * An <mxEvent.ESCAPE> event is fired via the editor if the escape key is
- * pressed.
- *
- * Constructor: mxDefaultKeyHandler
- *
- * Constructs a new default key handler for the <mxEditor.graph> in the
- * given <mxEditor>. (The editor may be null if a prototypical instance for
- * a <mxDefaultKeyHandlerCodec> is created.)
- *
- * Parameters:
- *
- * editor - Reference to the enclosing <mxEditor>.
- */
-function mxDefaultKeyHandler(editor)
-{
- if (editor != null)
- {
- this.editor = editor;
- this.handler = new mxKeyHandler(editor.graph);
-
- // Extends the escape function of the internal key
- // handle to hide the properties dialog and fire
- // the escape event via the editor instance
- var old = this.handler.escape;
-
- this.handler.escape = function(evt)
- {
- old.apply(this, arguments);
- editor.hideProperties();
- editor.fireEvent(new mxEventObject(mxEvent.ESCAPE, 'event', evt));
- };
- }
-};
-
-/**
- * Variable: editor
- *
- * Reference to the enclosing <mxEditor>.
- */
-mxDefaultKeyHandler.prototype.editor = null;
-
-/**
- * Variable: handler
- *
- * Holds the <mxKeyHandler> for key event handling.
- */
-mxDefaultKeyHandler.prototype.handler = null;
-
-/**
- * Function: bindAction
- *
- * Binds the specified keycode to the given action in <editor>. The
- * optional control flag specifies if the control key must be pressed
- * to trigger the action.
- *
- * Parameters:
- *
- * code - Integer that specifies the keycode.
- * action - Name of the action to execute in <editor>.
- * control - Optional boolean that specifies if control must be pressed.
- * Default is false.
- */
-mxDefaultKeyHandler.prototype.bindAction = function (code, action, control)
-{
- var keyHandler = mxUtils.bind(this, function()
- {
- this.editor.execute(action);
- });
-
- // Binds the function to control-down keycode
- if (control)
- {
- this.handler.bindControlKey(code, keyHandler);
- }
-
- // Binds the function to the normal keycode
- else
- {
- this.handler.bindKey(code, keyHandler);
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the <handler> associated with this object. This does normally
- * not need to be called, the <handler> is destroyed automatically when the
- * window unloads (in IE) by <mxEditor>.
- */
-mxDefaultKeyHandler.prototype.destroy = function ()
-{
- this.handler.destroy();
- this.handler = null;
-};
diff --git a/src/js/editor/mxDefaultPopupMenu.js b/src/js/editor/mxDefaultPopupMenu.js
deleted file mode 100644
index 01c65b5..0000000
--- a/src/js/editor/mxDefaultPopupMenu.js
+++ /dev/null
@@ -1,300 +0,0 @@
-/**
- * $Id: mxDefaultPopupMenu.js,v 1.29 2012-07-03 06:30:25 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxDefaultPopupMenu
- *
- * Creates popupmenus for mouse events. This object holds an XML node
- * which is a description of the popup menu to be created. In
- * <createMenu>, the configuration is applied to the context and
- * the resulting menu items are added to the menu dynamically. See
- * <createMenu> for a description of the configuration format.
- *
- * This class does not create the DOM nodes required for the popup menu, it
- * only parses an XML description to invoke the respective methods on an
- * <mxPopupMenu> each time the menu is displayed.
- *
- * Codec:
- *
- * This class uses the <mxDefaultPopupMenuCodec> to read configuration
- * data into an existing instance, however, the actual parsing is done
- * by this class during program execution, so the format is described
- * below.
- *
- * Constructor: mxDefaultPopupMenu
- *
- * Constructs a new popupmenu-factory based on given configuration.
- *
- * Paramaters:
- *
- * config - XML node that contains the configuration data.
- */
-function mxDefaultPopupMenu(config)
-{
- this.config = config;
-};
-
-/**
- * Variable: imageBasePath
- *
- * Base path for all icon attributes in the config. Default is null.
- */
-mxDefaultPopupMenu.prototype.imageBasePath = null;
-
-/**
- * Variable: config
- *
- * XML node used as the description of new menu items. This node is
- * used in <createMenu> to dynamically create the menu items if their
- * respective conditions evaluate to true for the given arguments.
- */
-mxDefaultPopupMenu.prototype.config = null;
-
-/**
- * Function: createMenu
- *
- * This function is called from <mxEditor> to add items to the
- * given menu based on <config>. The config is a sequence of
- * the following nodes and attributes.
- *
- * Child Nodes:
- *
- * add - Adds a new menu item. See below for attributes.
- * separator - Adds a separator. No attributes.
- * condition - Adds a custom condition. Name attribute.
- *
- * The add-node may have a child node that defines a function to be invoked
- * before the action is executed (or instead of an action to be executed).
- *
- * Attributes:
- *
- * as - Resource key for the label (needs entry in property file).
- * action - Name of the action to execute in enclosing editor.
- * icon - Optional icon (relative/absolute URL).
- * iconCls - Optional CSS class for the icon.
- * if - Optional name of condition that must be true(see below).
- * name - Name of custom condition. Only for condition nodes.
- *
- * Conditions:
- *
- * nocell - No cell under the mouse.
- * ncells - More than one cell selected.
- * notRoot - Drilling position is other than home.
- * cell - Cell under the mouse.
- * notEmpty - Exactly one cell with children under mouse.
- * expandable - Exactly one expandable cell under mouse.
- * collapsable - Exactly one collapsable cell under mouse.
- * validRoot - Exactly one cell which is a possible root under mouse.
- * swimlane - Exactly one cell which is a swimlane under mouse.
- *
- * Example:
- *
- * To add a new item for a given action to the popupmenu:
- *
- * (code)
- * <mxDefaultPopupMenu as="popupHandler">
- * <add as="delete" action="delete" icon="images/delete.gif" if="cell"/>
- * </mxDefaultPopupMenu>
- * (end)
- *
- * To add a new item for a custom function:
- *
- * (code)
- * <mxDefaultPopupMenu as="popupHandler">
- * <add as="action1"><![CDATA[
- * function (editor, cell, evt)
- * {
- * editor.execute('action1', cell, 'myArg');
- * }
- * ]]></add>
- * </mxDefaultPopupMenu>
- * (end)
- *
- * The above example invokes action1 with an additional third argument via
- * the editor instance. The third argument is passed to the function that
- * defines action1. If the add-node has no action-attribute, then only the
- * function defined in the text content is executed, otherwise first the
- * function and then the action defined in the action-attribute is
- * executed. The function in the text content has 3 arguments, namely the
- * <mxEditor> instance, the <mxCell> instance under the mouse, and the
- * native mouse event.
- *
- * Custom Conditions:
- *
- * To add a new condition for popupmenu items:
- *
- * (code)
- * <condition name="condition1"><![CDATA[
- * function (editor, cell, evt)
- * {
- * return cell != null;
- * }
- * ]]></condition>
- * (end)
- *
- * The new condition can then be used in any item as follows:
- *
- * (code)
- * <add as="action1" action="action1" icon="action1.gif" if="condition1"/>
- * (end)
- *
- * The order in which the items and conditions appear is not significant as
- * all connditions are evaluated before any items are created.
- *
- * Parameters:
- *
- * editor - Enclosing <mxEditor> instance.
- * menu - <mxPopupMenu> that is used for adding items and separators.
- * cell - Optional <mxCell> which is under the mousepointer.
- * evt - Optional mouse event which triggered the menu.
- */
-mxDefaultPopupMenu.prototype.createMenu = function(editor, menu, cell, evt)
-{
- if (this.config != null)
- {
- var conditions = this.createConditions(editor, cell, evt);
- var item = this.config.firstChild;
-
- this.addItems(editor, menu, cell, evt, conditions, item, null);
- }
-};
-
-/**
- * Function: addItems
- *
- * Recursively adds the given items and all of its children into the given menu.
- *
- * Parameters:
- *
- * editor - Enclosing <mxEditor> instance.
- * menu - <mxPopupMenu> that is used for adding items and separators.
- * cell - Optional <mxCell> which is under the mousepointer.
- * evt - Optional mouse event which triggered the menu.
- * conditions - Array of names boolean conditions.
- * item - XML node that represents the current menu item.
- * parent - DOM node that represents the parent menu item.
- */
-mxDefaultPopupMenu.prototype.addItems = function(editor, menu, cell, evt, conditions, item, parent)
-{
- var addSeparator = false;
-
- while (item != null)
- {
- if (item.nodeName == 'add')
- {
- var condition = item.getAttribute('if');
-
- if (condition == null || conditions[condition])
- {
- var as = item.getAttribute('as');
- as = mxResources.get(as) || as;
- var funct = mxUtils.eval(mxUtils.getTextContent(item));
- var action = item.getAttribute('action');
- var icon = item.getAttribute('icon');
- var iconCls = item.getAttribute('iconCls');
-
- if (addSeparator)
- {
- menu.addSeparator(parent);
- addSeparator = false;
- }
-
- if (icon != null && this.imageBasePath)
- {
- icon = this.imageBasePath + icon;
- }
-
- var row = this.addAction(menu, editor, as, icon, funct, action, cell, parent, iconCls);
- this.addItems(editor, menu, cell, evt, conditions, item.firstChild, row);
- }
- }
- else if (item.nodeName == 'separator')
- {
- addSeparator = true;
- }
-
- item = item.nextSibling;
- }
-};
-
-/**
- * Function: addAction
- *
- * Helper method to bind an action to a new menu item.
- *
- * Parameters:
- *
- * menu - <mxPopupMenu> that is used for adding items and separators.
- * editor - Enclosing <mxEditor> instance.
- * lab - String that represents the label of the menu item.
- * icon - Optional URL that represents the icon of the menu item.
- * action - Optional name of the action to execute in the given editor.
- * funct - Optional function to execute before the optional action. The
- * function takes an <mxEditor>, the <mxCell> under the mouse and the
- * mouse event that triggered the call.
- * cell - Optional <mxCell> to use as an argument for the action.
- * parent - DOM node that represents the parent menu item.
- * iconCls - Optional CSS class for the menu icon.
- */
-mxDefaultPopupMenu.prototype.addAction = function(menu, editor, lab, icon, funct, action, cell, parent, iconCls)
-{
- var clickHandler = function(evt)
- {
- if (typeof(funct) == 'function')
- {
- funct.call(editor, editor, cell, evt);
- }
-
- if (action != null)
- {
- editor.execute(action, cell, evt);
- }
- };
-
- return menu.addItem(lab, icon, clickHandler, parent, iconCls);
-};
-
-/**
- * Function: createConditions
- *
- * Evaluates the default conditions for the given context.
- */
-mxDefaultPopupMenu.prototype.createConditions = function(editor, cell, evt)
-{
- // Creates array with conditions
- var model = editor.graph.getModel();
- var childCount = model.getChildCount(cell);
-
- // Adds some frequently used conditions
- var conditions = [];
- conditions['nocell'] = cell == null;
- conditions['ncells'] = editor.graph.getSelectionCount() > 1;
- conditions['notRoot'] = model.getRoot() !=
- model.getParent(editor.graph.getDefaultParent());
- conditions['cell'] = cell != null;
-
- var isCell = cell != null && editor.graph.getSelectionCount() == 1;
- conditions['nonEmpty'] = isCell && childCount > 0;
- conditions['expandable'] = isCell && editor.graph.isCellFoldable(cell, false);
- conditions['collapsable'] = isCell && editor.graph.isCellFoldable(cell, true);
- conditions['validRoot'] = isCell && editor.graph.isValidRoot(cell);
- conditions['emptyValidRoot'] = conditions['validRoot'] && childCount == 0;
- conditions['swimlane'] = isCell && editor.graph.isSwimlane(cell);
-
- // Evaluates dynamic conditions from config file
- var condNodes = this.config.getElementsByTagName('condition');
-
- for (var i=0; i<condNodes.length; i++)
- {
- var funct = mxUtils.eval(mxUtils.getTextContent(condNodes[i]));
- var name = condNodes[i].getAttribute('name');
-
- if (name != null && typeof(funct) == 'function')
- {
- conditions[name] = funct(editor, cell, evt);
- }
- }
-
- return conditions;
-};
diff --git a/src/js/editor/mxDefaultToolbar.js b/src/js/editor/mxDefaultToolbar.js
deleted file mode 100644
index 3f8f901..0000000
--- a/src/js/editor/mxDefaultToolbar.js
+++ /dev/null
@@ -1,567 +0,0 @@
-/**
- * $Id: mxDefaultToolbar.js,v 1.67 2012-04-11 07:00:52 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxDefaultToolbar
- *
- * Toolbar for the editor. This modifies the state of the graph
- * or inserts new cells upon mouse clicks.
- *
- * Example:
- *
- * Create a toolbar with a button to copy the selection into the clipboard,
- * and a combo box with one action to paste the selection from the clipboard
- * into the graph.
- *
- * (code)
- * var toolbar = new mxDefaultToolbar(container, editor);
- * toolbar.addItem('Copy', null, 'copy');
- *
- * var combo = toolbar.addActionCombo('More actions...');
- * toolbar.addActionOption(combo, 'Paste', 'paste');
- * (end)
- *
- * Codec:
- *
- * This class uses the <mxDefaultToolbarCodec> to read configuration
- * data into an existing instance. See <mxDefaultToolbarCodec> for a
- * description of the configuration format.
- *
- * Constructor: mxDefaultToolbar
- *
- * Constructs a new toolbar for the given container and editor. The
- * container and editor may be null if a prototypical instance for a
- * <mxDefaultKeyHandlerCodec> is created.
- *
- * Parameters:
- *
- * container - DOM node that contains the toolbar.
- * editor - Reference to the enclosing <mxEditor>.
- */
-function mxDefaultToolbar(container, editor)
-{
- this.editor = editor;
-
- if (container != null &&
- editor != null)
- {
- this.init(container);
- }
-};
-
-/**
- * Variable: editor
- *
- * Reference to the enclosing <mxEditor>.
- */
-mxDefaultToolbar.prototype.editor = null;
-
-/**
- * Variable: toolbar
- *
- * Holds the internal <mxToolbar>.
- */
-mxDefaultToolbar.prototype.toolbar = null;
-
-/**
- * Variable: resetHandler
- *
- * Reference to the function used to reset the <toolbar>.
- */
-mxDefaultToolbar.prototype.resetHandler = null;
-
-/**
- * Variable: spacing
- *
- * Defines the spacing between existing and new vertices in
- * gridSize units when a new vertex is dropped on an existing
- * cell. Default is 4 (40 pixels).
- */
-mxDefaultToolbar.prototype.spacing = 4;
-
-/**
- * Variable: connectOnDrop
- *
- * Specifies if elements should be connected if new cells are dropped onto
- * connectable elements. Default is false.
- */
-mxDefaultToolbar.prototype.connectOnDrop = false;
-
-/**
- * Variable: init
- *
- * Constructs the <toolbar> for the given container and installs a listener
- * that updates the <mxEditor.insertFunction> on <editor> if an item is
- * selected in the toolbar. This assumes that <editor> is not null.
- *
- * Parameters:
- *
- * container - DOM node that contains the toolbar.
- */
-mxDefaultToolbar.prototype.init = function(container)
-{
- if (container != null)
- {
- this.toolbar = new mxToolbar(container);
-
- // Installs the insert function in the editor if an item is
- // selected in the toolbar
- this.toolbar.addListener(mxEvent.SELECT,
- mxUtils.bind(this, function(sender, evt)
- {
- var funct = evt.getProperty('function');
-
- if (funct != null)
- {
- this.editor.insertFunction = mxUtils.bind(this, function()
- {
- funct.apply(this, arguments);
- this.toolbar.resetMode();
- });
- }
- else
- {
- this.editor.insertFunction = null;
- }
- })
- );
-
- // Resets the selected tool after a doubleclick or escape keystroke
- this.resetHandler = mxUtils.bind(this, function()
- {
- if (this.toolbar != null)
- {
- this.toolbar.resetMode(true);
- }
- });
-
- this.editor.graph.addListener(mxEvent.DOUBLE_CLICK, this.resetHandler);
- this.editor.addListener(mxEvent.ESCAPE, this.resetHandler);
- }
-};
-
-/**
- * Function: addItem
- *
- * Adds a new item that executes the given action in <editor>. The title,
- * icon and pressedIcon are used to display the toolbar item.
- *
- * Parameters:
- *
- * title - String that represents the title (tooltip) for the item.
- * icon - URL of the icon to be used for displaying the item.
- * action - Name of the action to execute when the item is clicked.
- * pressed - Optional URL of the icon for the pressed state.
- */
-mxDefaultToolbar.prototype.addItem = function(title, icon, action, pressed)
-{
- var clickHandler = mxUtils.bind(this, function()
- {
- if (action != null && action.length > 0)
- {
- this.editor.execute(action);
- }
- });
-
- return this.toolbar.addItem(title, icon, clickHandler, pressed);
-};
-
-/**
- * Function: addSeparator
- *
- * Adds a vertical separator using the optional icon.
- *
- * Parameters:
- *
- * icon - Optional URL of the icon that represents the vertical separator.
- * Default is <mxClient.imageBasePath> + '/separator.gif'.
- */
-mxDefaultToolbar.prototype.addSeparator = function(icon)
-{
- icon = icon || mxClient.imageBasePath + '/separator.gif';
- this.toolbar.addSeparator(icon);
-};
-
-/**
- * Function: addCombo
- *
- * Helper method to invoke <mxToolbar.addCombo> on <toolbar> and return the
- * resulting DOM node.
- */
-mxDefaultToolbar.prototype.addCombo = function()
-{
- return this.toolbar.addCombo();
-};
-
-/**
- * Function: addActionCombo
- *
- * Helper method to invoke <mxToolbar.addActionCombo> on <toolbar> using
- * the given title and return the resulting DOM node.
- *
- * Parameters:
- *
- * title - String that represents the title of the combo.
- */
-mxDefaultToolbar.prototype.addActionCombo = function(title)
-{
- return this.toolbar.addActionCombo(title);
-};
-
-/**
- * Function: addActionOption
- *
- * Binds the given action to a option with the specified label in the
- * given combo. Combo is an object returned from an earlier call to
- * <addCombo> or <addActionCombo>.
- *
- * Parameters:
- *
- * combo - DOM node that represents the combo box.
- * title - String that represents the title of the combo.
- * action - Name of the action to execute in <editor>.
- */
-mxDefaultToolbar.prototype.addActionOption = function(combo, title, action)
-{
- var clickHandler = mxUtils.bind(this, function()
- {
- this.editor.execute(action);
- });
-
- this.addOption(combo, title, clickHandler);
-};
-
-/**
- * Function: addOption
- *
- * Helper method to invoke <mxToolbar.addOption> on <toolbar> and return
- * the resulting DOM node that represents the option.
- *
- * Parameters:
- *
- * combo - DOM node that represents the combo box.
- * title - String that represents the title of the combo.
- * value - Object that represents the value of the option.
- */
-mxDefaultToolbar.prototype.addOption = function(combo, title, value)
-{
- return this.toolbar.addOption(combo, title, value);
-};
-
-/**
- * Function: addMode
- *
- * Creates an item for selecting the given mode in the <editor>'s graph.
- * Supported modenames are select, connect and pan.
- *
- * Parameters:
- *
- * title - String that represents the title of the item.
- * icon - URL of the icon that represents the item.
- * mode - String that represents the mode name to be used in
- * <mxEditor.setMode>.
- * pressed - Optional URL of the icon that represents the pressed state.
- * funct - Optional JavaScript function that takes the <mxEditor> as the
- * first and only argument that is executed after the mode has been
- * selected.
- */
-mxDefaultToolbar.prototype.addMode = function(title, icon, mode, pressed, funct)
-{
- var clickHandler = mxUtils.bind(this, function()
- {
- this.editor.setMode(mode);
-
- if (funct != null)
- {
- funct(this.editor);
- }
- });
-
- return this.toolbar.addSwitchMode(title, icon, clickHandler, pressed);
-};
-
-/**
- * Function: addPrototype
- *
- * Creates an item for inserting a clone of the specified prototype cell into
- * the <editor>'s graph. The ptype may either be a cell or a function that
- * returns a cell.
- *
- * Parameters:
- *
- * title - String that represents the title of the item.
- * icon - URL of the icon that represents the item.
- * ptype - Function or object that represents the prototype cell. If ptype
- * is a function then it is invoked with no arguments to create new
- * instances.
- * pressed - Optional URL of the icon that represents the pressed state.
- * insert - Optional JavaScript function that handles an insert of the new
- * cell. This function takes the <mxEditor>, new cell to be inserted, mouse
- * event and optional <mxCell> under the mouse pointer as arguments.
- * toggle - Optional boolean that specifies if the item can be toggled.
- * Default is true.
- */
-mxDefaultToolbar.prototype.addPrototype = function(title, icon, ptype, pressed, insert, toggle)
-{
- // Creates a wrapper function that is in charge of constructing
- // the new cell instance to be inserted into the graph
- var factory = function()
- {
- if (typeof(ptype) == 'function')
- {
- return ptype();
- }
- else if (ptype != null)
- {
- return ptype.clone();
- }
-
- return null;
- };
-
- // Defines the function for a click event on the graph
- // after this item has been selected in the toolbar
- var clickHandler = mxUtils.bind(this, function(evt, cell)
- {
- if (typeof(insert) == 'function')
- {
- insert(this.editor, factory(), evt, cell);
- }
- else
- {
- this.drop(factory(), evt, cell);
- }
-
- this.toolbar.resetMode();
- mxEvent.consume(evt);
- });
-
- var img = this.toolbar.addMode(title, icon, clickHandler, pressed, null, toggle);
-
- // Creates a wrapper function that calls the click handler without
- // the graph argument
- var dropHandler = function(graph, evt, cell)
- {
- clickHandler(evt, cell);
- };
-
- this.installDropHandler(img, dropHandler);
-
- return img;
-};
-
-/**
- * Function: drop
- *
- * Handles a drop from a toolbar item to the graph. The given vertex
- * represents the new cell to be inserted. This invokes <insert> or
- * <connect> depending on the given target cell.
- *
- * Parameters:
- *
- * vertex - <mxCell> to be inserted.
- * evt - Mouse event that represents the drop.
- * target - Optional <mxCell> that represents the drop target.
- */
-mxDefaultToolbar.prototype.drop = function(vertex, evt, target)
-{
- var graph = this.editor.graph;
- var model = graph.getModel();
-
- if (target == null ||
- model.isEdge(target) ||
- !this.connectOnDrop ||
- !graph.isCellConnectable(target))
- {
- while (target != null &&
- !graph.isValidDropTarget(target, [vertex], evt))
- {
- target = model.getParent(target);
- }
-
- this.insert(vertex, evt, target);
- }
- else
- {
- this.connect(vertex, evt, target);
- }
-};
-
-/**
- * Function: insert
- *
- * Handles a drop by inserting the given vertex into the given parent cell
- * or the default parent if no parent is specified.
- *
- * Parameters:
- *
- * vertex - <mxCell> to be inserted.
- * evt - Mouse event that represents the drop.
- * parent - Optional <mxCell> that represents the parent.
- */
-mxDefaultToolbar.prototype.insert = function(vertex, evt, target)
-{
- var graph = this.editor.graph;
-
- if (graph.canImportCell(vertex))
- {
- var x = mxEvent.getClientX(evt);
- var y = mxEvent.getClientY(evt);
- var pt = mxUtils.convertPoint(graph.container, x, y);
-
- // Splits the target edge or inserts into target group
- if (graph.isSplitEnabled() &&
- graph.isSplitTarget(target, [vertex], evt))
- {
- return graph.splitEdge(target, [vertex], null, pt.x, pt.y);
- }
- else
- {
- return this.editor.addVertex(target, vertex, pt.x, pt.y);
- }
- }
-
- return null;
-};
-
-/**
- * Function: connect
- *
- * Handles a drop by connecting the given vertex to the given source cell.
- *
- * vertex - <mxCell> to be inserted.
- * evt - Mouse event that represents the drop.
- * source - Optional <mxCell> that represents the source terminal.
- */
-mxDefaultToolbar.prototype.connect = function(vertex, evt, source)
-{
- var graph = this.editor.graph;
- var model = graph.getModel();
-
- if (source != null &&
- graph.isCellConnectable(vertex) &&
- graph.isEdgeValid(null, source, vertex))
- {
- var edge = null;
-
- model.beginUpdate();
- try
- {
- var geo = model.getGeometry(source);
- var g = model.getGeometry(vertex).clone();
-
- // Moves the vertex away from the drop target that will
- // be used as the source for the new connection
- g.x = geo.x + (geo.width - g.width) / 2;
- g.y = geo.y + (geo.height - g.height) / 2;
-
- var step = this.spacing * graph.gridSize;
- var dist = model.getDirectedEdgeCount(source, true) * 20;
-
- if (this.editor.horizontalFlow)
- {
- g.x += (g.width + geo.width) / 2 + step + dist;
- }
- else
- {
- g.y += (g.height + geo.height) / 2 + step + dist;
- }
-
- vertex.setGeometry(g);
-
- // Fires two add-events with the code below - should be fixed
- // to only fire one add event for both inserts
- var parent = model.getParent(source);
- graph.addCell(vertex, parent);
- graph.constrainChild(vertex);
-
- // Creates the edge using the editor instance and calls
- // the second function that fires an add event
- edge = this.editor.createEdge(source, vertex);
-
- if (model.getGeometry(edge) == null)
- {
- var edgeGeometry = new mxGeometry();
- edgeGeometry.relative = true;
-
- model.setGeometry(edge, edgeGeometry);
- }
-
- graph.addEdge(edge, parent, source, vertex);
- }
- finally
- {
- model.endUpdate();
- }
-
- graph.setSelectionCells([vertex, edge]);
- graph.scrollCellToVisible(vertex);
- }
-};
-
-/**
- * Function: installDropHandler
- *
- * Makes the given img draggable using the given function for handling a
- * drop event.
- *
- * Parameters:
- *
- * img - DOM node that represents the image.
- * dropHandler - Function that handles a drop of the image.
- */
-mxDefaultToolbar.prototype.installDropHandler = function (img, dropHandler)
-{
- var sprite = document.createElement('img');
- sprite.setAttribute('src', img.getAttribute('src'));
-
- // Handles delayed loading of the images
- var loader = mxUtils.bind(this, function(evt)
- {
- // Preview uses the image node with double size. Later this can be
- // changed to use a separate preview and guides, but for this the
- // dropHandler must use the additional x- and y-arguments and the
- // dragsource which makeDraggable returns much be configured to
- // use guides via mxDragSource.isGuidesEnabled.
- sprite.style.width = (2 * img.offsetWidth) + 'px';
- sprite.style.height = (2 * img.offsetHeight) + 'px';
-
- mxUtils.makeDraggable(img, this.editor.graph, dropHandler,
- sprite);
- mxEvent.removeListener(sprite, 'load', loader);
- });
-
- if (mxClient.IS_IE)
- {
- loader();
- }
- else
- {
- mxEvent.addListener(sprite, 'load', loader);
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the <toolbar> associated with this object and removes all
- * installed listeners. This does normally not need to be called, the
- * <toolbar> is destroyed automatically when the window unloads (in IE) by
- * <mxEditor>.
- */
-mxDefaultToolbar.prototype.destroy = function ()
-{
- if (this.resetHandler != null)
- {
- this.editor.graph.removeListener('dblclick', this.resetHandler);
- this.editor.removeListener('escape', this.resetHandler);
- this.resetHandler = null;
- }
-
- if (this.toolbar != null)
- {
- this.toolbar.destroy();
- this.toolbar = null;
- }
-};
diff --git a/src/js/editor/mxEditor.js b/src/js/editor/mxEditor.js
deleted file mode 100644
index 9c57a9c..0000000
--- a/src/js/editor/mxEditor.js
+++ /dev/null
@@ -1,3220 +0,0 @@
-/**
- * $Id: mxEditor.js,v 1.231 2012-12-03 18:02:25 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxEditor
- *
- * Extends <mxEventSource> to implement a application wrapper for a graph that
- * adds <actions>, I/O using <mxCodec>, auto-layout using <mxLayoutManager>,
- * command history using <undoManager>, and standard dialogs and widgets, eg.
- * properties, help, outline, toolbar, and popupmenu. It also adds <templates>
- * to be used as cells in toolbars, auto-validation using the <validation>
- * flag, attribute cycling using <cycleAttributeValues>, higher-level events
- * such as <root>, and backend integration using <urlPost>, <urlImage>,
- * <urlInit>, <urlNotify> and <urlPoll>.
- *
- * Actions:
- *
- * Actions are functions stored in the <actions> array under their names. The
- * functions take the <mxEditor> as the first, and an optional <mxCell> as the
- * second argument and are invoked using <execute>. Any additional arguments
- * passed to execute are passed on to the action as-is.
- *
- * A list of built-in actions is available in the <addActions> description.
- *
- * Read/write Diagrams:
- *
- * To read a diagram from an XML string, for example from a textfield within the
- * page, the following code is used:
- *
- * (code)
- * var doc = mxUtils.parseXML(xmlString);
- * var node = doc.documentElement;
- * editor.readGraphModel(node);
- * (end)
- *
- * For reading a diagram from a remote location, use the <open> method.
- *
- * To save diagrams in XML on a server, you can set the <urlPost> variable.
- * This variable will be used in <getUrlPost> to construct a URL for the post
- * request that is issued in the <save> method. The post request contains the
- * XML representation of the diagram as returned by <writeGraphModel> in the
- * xml parameter.
- *
- * On the server side, the post request is processed using standard
- * technologies such as Java Servlets, CGI, .NET or ASP.
- *
- * Here are some examples of processing a post request in various languages.
- *
- * - Java: URLDecoder.decode(request.getParameter("xml"), "UTF-8").replace("\n", "&#xa;")
- *
- * Note that the linefeeds should only be replaced if the XML is
- * processed in Java, for example when creating an image, but not
- * if the XML is passed back to the client-side.
- *
- * - .NET: HttpUtility.UrlDecode(context.Request.Params["xml"])
- * - PHP: urldecode($_POST["xml"])
- *
- * Creating images:
- *
- * A backend (Java, PHP or C#) is required for creating images. The
- * distribution contains an example for each backend (ImageHandler.java,
- * ImageHandler.cs and graph.php). More information about using a backend
- * to create images can be found in the readme.html files. Note that the
- * preview is implemented using VML/SVG in the browser and does not require
- * a backend. The backend is only required to creates images (bitmaps).
- *
- * Special characters:
- *
- * Note There are five characters that should always appear in XML content as
- * escapes, so that they do not interact with the syntax of the markup. These
- * are part of the language for all documents based on XML and for HTML.
- *
- * - &lt; (<)
- * - &gt; (>)
- * - &amp; (&)
- * - &quot; (")
- * - &apos; (')
- *
- * Although it is part of the XML language, &apos; is not defined in HTML.
- * For this reason the XHTML specification recommends instead the use of
- * &#39; if text may be passed to a HTML user agent.
- *
- * If you are having problems with special characters on the server-side then
- * you may want to try the <escapePostData> flag.
- *
- * For converting decimal escape sequences inside strings, a user has provided
- * us with the following function:
- *
- * (code)
- * function html2js(text)
- * {
- * var entitySearch = /&#[0-9]+;/;
- * var entity;
- *
- * while (entity = entitySearch.exec(text))
- * {
- * var charCode = entity[0].substring(2, entity[0].length -1);
- * text = text.substring(0, entity.index)
- * + String.fromCharCode(charCode)
- * + text.substring(entity.index + entity[0].length);
- * }
- *
- * return text;
- * }
- * (end)
- *
- * Otherwise try using hex escape sequences and the built-in unescape function
- * for converting such strings.
- *
- * Local Files:
- *
- * For saving and opening local files, no standardized method exists that
- * works across all browsers. The recommended way of dealing with local files
- * is to create a backend that streams the XML data back to the browser (echo)
- * as an attachment so that a Save-dialog is displayed on the client-side and
- * the file can be saved to the local disk.
- *
- * For example, in PHP the code that does this looks as follows.
- *
- * (code)
- * $xml = stripslashes($_POST["xml"]);
- * header("Content-Disposition: attachment; filename=\"diagram.xml\"");
- * echo($xml);
- * (end)
- *
- * To open a local file, the file should be uploaded via a form in the browser
- * and then opened from the server in the editor.
- *
- * Cell Properties:
- *
- * The properties displayed in the properties dialog are the attributes and
- * values of the cell's user object, which is an XML node. The XML node is
- * defined in the templates section of the config file.
- *
- * The templates are stored in <mxEditor.templates> and contain cells which
- * are cloned at insertion time to create new vertices by use of drag and
- * drop from the toolbar. Each entry in the toolbar for adding a new vertex
- * must refer to an existing template.
- *
- * In the following example, the task node is a business object and only the
- * mxCell node and its mxGeometry child contain graph information:
- *
- * (code)
- * <Task label="Task" description="">
- * <mxCell vertex="true">
- * <mxGeometry as="geometry" width="72" height="32"/>
- * </mxCell>
- * </Task>
- * (end)
- *
- * The idea is that the XML representation is inverse from the in-memory
- * representation: The outer XML node is the user object and the inner node is
- * the cell. This means the user object of the cell is the Task node with no
- * children for the above example:
- *
- * (code)
- * <Task label="Task" description=""/>
- * (end)
- *
- * The Task node can have any tag name, attributes and child nodes. The
- * <mxCodec> will use the XML hierarchy as the user object, while removing the
- * "known annotations", such as the mxCell node. At save-time the cell data
- * will be "merged" back into the user object. The user object is only modified
- * via the properties dialog during the lifecycle of the cell.
- *
- * In the default implementation of <createProperties>, the user object's
- * attributes are put into a form for editing. Attributes are changed using
- * the <mxCellAttributeChange> action in the model. The dialog can be replaced
- * by overriding the <createProperties> hook or by replacing the showProperties
- * action in <actions>. Alternatively, the entry in the config file's popupmenu
- * section can be modified to invoke a different action.
- *
- * If you want to displey the properties dialog on a doubleclick, you can set
- * <mxEditor.dblClickAction> to showProperties as follows:
- *
- * (code)
- * editor.dblClickAction = 'showProperties';
- * (end)
- *
- * Popupmenu and Toolbar:
- *
- * The toolbar and popupmenu are typically configured using the respective
- * sections in the config file, that is, the popupmenu is defined as follows:
- *
- * (code)
- * <mxEditor>
- * <mxDefaultPopupMenu as="popupHandler">
- * <add as="cut" action="cut" icon="images/cut.gif"/>
- * ...
- * (end)
- *
- * New entries can be added to the toolbar by inserting an add-node into the
- * above configuration. Existing entries may be removed and changed by
- * modifying or removing the respective entries in the configuration.
- * The configuration is read by the <mxDefaultPopupMenuCodec>, the format of the
- * configuration is explained in <mxDefaultPopupMenu.decode>.
- *
- * The toolbar is defined in the mxDefaultToolbar section. Items can be added
- * and removed in this section.
- *
- * (code)
- * <mxEditor>
- * <mxDefaultToolbar>
- * <add as="save" action="save" icon="images/save.gif"/>
- * <add as="Swimlane" template="swimlane" icon="images/swimlane.gif"/>
- * ...
- * (end)
- *
- * The format of the configuration is described in
- * <mxDefaultToolbarCodec.decode>.
- *
- * Ids:
- *
- * For the IDs, there is an implicit behaviour in <mxCodec>: It moves the Id
- * from the cell to the user object at encoding time and vice versa at decoding
- * time. For example, if the Task node from above has an id attribute, then
- * the <mxCell.id> of the corresponding cell will have this value. If there
- * is no Id collision in the model, then the cell may be retrieved using this
- * Id with the <mxGraphModel.getCell> function. If there is a collision, a new
- * Id will be created for the cell using <mxGraphModel.createId>. At encoding
- * time, this new Id will replace the value previously stored under the id
- * attribute in the Task node.
- *
- * See <mxEditorCodec>, <mxDefaultToolbarCodec> and <mxDefaultPopupMenuCodec>
- * for information about configuring the editor and user interface.
- *
- * Programmatically inserting cells:
- *
- * For inserting a new cell, say, by clicking a button in the document,
- * the following code can be used. This requires an reference to the editor.
- *
- * (code)
- * var userObject = new Object();
- * var parent = editor.graph.getDefaultParent();
- * var model = editor.graph.model;
- * model.beginUpdate();
- * try
- * {
- * editor.graph.insertVertex(parent, null, userObject, 20, 20, 80, 30);
- * }
- * finally
- * {
- * model.endUpdate();
- * }
- * (end)
- *
- * If a template cell from the config file should be inserted, then a clone
- * of the template can be created as follows. The clone is then inserted using
- * the add function instead of addVertex.
- *
- * (code)
- * var template = editor.templates['task'];
- * var clone = editor.graph.model.cloneCell(template);
- * (end)
- *
- * Resources:
- *
- * resources/editor - Language resources for mxEditor
- *
- * Callback: onInit
- *
- * Called from within the constructor. In the callback,
- * "this" refers to the editor instance.
- *
- * Cookie: mxgraph=seen
- *
- * Set when the editor is started. Never expires. Use
- * <resetFirstTime> to reset this cookie. This cookie
- * only exists if <onInit> is implemented.
- *
- * Event: mxEvent.OPEN
- *
- * Fires after a file was opened in <open>. The <code>filename</code> property
- * contains the filename that was used. The same value is also available in
- * <filename>.
- *
- * Event: mxEvent.SAVE
- *
- * Fires after the current file was saved in <save>. The <code>url</code>
- * property contains the URL that was used for saving.
- *
- * Event: mxEvent.POST
- *
- * Fires if a successful response was received in <postDiagram>. The
- * <code>request</code> property contains the <mxXmlRequest>, the
- * <code>url</code> and <code>data</code> properties contain the URL and the
- * data that were used in the post request.
- *
- * Event: mxEvent.ROOT
- *
- * Fires when the current root has changed, or when the title of the current
- * root has changed. This event has no properties.
- *
- * Event: mxEvent.SESSION
- *
- * Fires when anything in the session has changed. The <code>session</code>
- * property contains the respective <mxSession>.
- *
- * Event: mxEvent.BEFORE_ADD_VERTEX
- *
- * Fires before a vertex is added in <addVertex>. The <code>vertex</code>
- * property contains the new vertex and the <code>parent</code> property
- * contains its parent.
- *
- * Event: mxEvent.ADD_VERTEX
- *
- * Fires between begin- and endUpdate in <addVertex>. The <code>vertex</code>
- * property contains the vertex that is being inserted.
- *
- * Event: mxEvent.AFTER_ADD_VERTEX
- *
- * Fires after a vertex was inserted and selected in <addVertex>. The
- * <code>vertex</code> property contains the new vertex.
- *
- * Example:
- *
- * For starting an in-place edit after a new vertex has been added to the
- * graph, the following code can be used.
- *
- * (code)
- * editor.addListener(mxEvent.AFTER_ADD_VERTEX, function(sender, evt)
- * {
- * var vertex = evt.getProperty('vertex');
- *
- * if (editor.graph.isCellEditable(vertex))
- * {
- * editor.graph.startEditingAtCell(vertex);
- * }
- * });
- * (end)
- *
- * Event: mxEvent.ESCAPE
- *
- * Fires when the escape key is pressed. The <code>event</code> property
- * contains the key event.
- *
- * Constructor: mxEditor
- *
- * Constructs a new editor. This function invokes the <onInit> callback
- * upon completion.
- *
- * Example:
- *
- * (code)
- * var config = mxUtils.load('config/diagrameditor.xml').getDocumentElement();
- * var editor = new mxEditor(config);
- * (end)
- *
- * Parameters:
- *
- * config - Optional XML node that contains the configuration.
- */
-function mxEditor(config)
-{
- this.actions = [];
- this.addActions();
-
- // Executes the following only if a document has been instanciated.
- // That is, don't execute when the editorcodec is setup.
- if (document.body != null)
- {
- // Defines instance fields
- this.cycleAttributeValues = [];
- this.popupHandler = new mxDefaultPopupMenu();
- this.undoManager = new mxUndoManager();
-
- // Creates the graph and toolbar without the containers
- this.graph = this.createGraph();
- this.toolbar = this.createToolbar();
-
- // Creates the global keyhandler (requires graph instance)
- this.keyHandler = new mxDefaultKeyHandler(this);
-
- // Configures the editor using the URI
- // which was passed to the ctor
- this.configure(config);
-
- // Assigns the swimlaneIndicatorColorAttribute on the graph
- this.graph.swimlaneIndicatorColorAttribute = this.cycleAttributeName;
-
- // Initializes the session if the urlInit
- // member field of this editor is set.
- if (!mxClient.IS_LOCAL && this.urlInit != null)
- {
- this.session = this.createSession();
- }
-
- // Checks ifthe <onInit> hook has been set
- if (this.onInit != null)
- {
- // Invokes the <onInit> hook
- this.onInit();
- }
-
- // Automatic deallocation of memory
- if (mxClient.IS_IE)
- {
- mxEvent.addListener(window, 'unload', mxUtils.bind(this, function()
- {
- this.destroy();
- }));
- }
- }
-};
-
-/**
- * Installs the required language resources at class
- * loading time.
- */
-if (mxLoadResources)
-{
- mxResources.add(mxClient.basePath+'/resources/editor');
-}
-
-/**
- * Extends mxEventSource.
- */
-mxEditor.prototype = new mxEventSource();
-mxEditor.prototype.constructor = mxEditor;
-
-/**
- * Group: Controls and Handlers
- */
-
-/**
- * Variable: askZoomResource
- *
- * Specifies the resource key for the zoom dialog. If the resource for this
- * key does not exist then the value is used as the error message. Default
- * is 'askZoom'.
- */
-mxEditor.prototype.askZoomResource = (mxClient.language != 'none') ? 'askZoom' : '';
-
-/**
- * Variable: lastSavedResource
- *
- * Specifies the resource key for the last saved info. If the resource for
- * this key does not exist then the value is used as the error message.
- * Default is 'lastSaved'.
- */
-mxEditor.prototype.lastSavedResource = (mxClient.language != 'none') ? 'lastSaved' : '';
-
-/**
- * Variable: currentFileResource
- *
- * Specifies the resource key for the current file info. If the resource for
- * this key does not exist then the value is used as the error message.
- * Default is 'lastSaved'.
- */
-mxEditor.prototype.currentFileResource = (mxClient.language != 'none') ? 'currentFile' : '';
-
-/**
- * Variable: propertiesResource
- *
- * Specifies the resource key for the properties window title. If the
- * resource for this key does not exist then the value is used as the
- * error message. Default is 'properties'.
- */
-mxEditor.prototype.propertiesResource = (mxClient.language != 'none') ? 'properties' : '';
-
-/**
- * Variable: tasksResource
- *
- * Specifies the resource key for the tasks window title. If the
- * resource for this key does not exist then the value is used as the
- * error message. Default is 'tasks'.
- */
-mxEditor.prototype.tasksResource = (mxClient.language != 'none') ? 'tasks' : '';
-
-/**
- * Variable: helpResource
- *
- * Specifies the resource key for the help window title. If the
- * resource for this key does not exist then the value is used as the
- * error message. Default is 'help'.
- */
-mxEditor.prototype.helpResource = (mxClient.language != 'none') ? 'help' : '';
-
-/**
- * Variable: outlineResource
- *
- * Specifies the resource key for the outline window title. If the
- * resource for this key does not exist then the value is used as the
- * error message. Default is 'outline'.
- */
-mxEditor.prototype.outlineResource = (mxClient.language != 'none') ? 'outline' : '';
-
-/**
- * Variable: outline
- *
- * Reference to the <mxWindow> that contains the outline. The <mxOutline>
- * is stored in outline.outline.
- */
-mxEditor.prototype.outline = null;
-
-/**
- * Variable: graph
- *
- * Holds a <mxGraph> for displaying the diagram. The graph
- * is created in <setGraphContainer>.
- */
-mxEditor.prototype.graph = null;
-
-/**
- * Variable: graphRenderHint
- *
- * Holds the render hint used for creating the
- * graph in <setGraphContainer>. See <mxGraph>.
- * Default is null.
- */
-mxEditor.prototype.graphRenderHint = null;
-
-/**
- * Variable: toolbar
- *
- * Holds a <mxDefaultToolbar> for displaying the toolbar. The
- * toolbar is created in <setToolbarContainer>.
- */
-mxEditor.prototype.toolbar = null;
-
-/**
- * Variable: session
- *
- * Holds a <mxSession> instance associated with this editor.
- */
-mxEditor.prototype.session = null;
-
-/**
- * Variable: status
- *
- * DOM container that holds the statusbar. Default is null.
- * Use <setStatusContainer> to set this value.
- */
-mxEditor.prototype.status = null;
-
-/**
- * Variable: popupHandler
- *
- * Holds a <mxDefaultPopupMenu> for displaying
- * popupmenus.
- */
-mxEditor.prototype.popupHandler = null;
-
-/**
- * Variable: undoManager
- *
- * Holds an <mxUndoManager> for the command history.
- */
-mxEditor.prototype.undoManager = null;
-
-/**
- * Variable: keyHandler
- *
- * Holds a <mxDefaultKeyHandler> for handling keyboard events.
- * The handler is created in <setGraphContainer>.
- */
-mxEditor.prototype.keyHandler = null;
-
-/**
- * Group: Actions and Options
- */
-
-/**
- * Variable: actions
- *
- * Maps from actionnames to actions, which are functions taking
- * the editor and the cell as arguments. Use <addAction>
- * to add or replace an action and <execute> to execute an action
- * by name, passing the cell to be operated upon as the second
- * argument.
- */
-mxEditor.prototype.actions = null;
-
-/**
- * Variable: dblClickAction
- *
- * Specifies the name of the action to be executed
- * when a cell is double clicked. Default is edit.
- *
- * To handle a singleclick, use the following code.
- *
- * (code)
- * editor.graph.addListener(mxEvent.CLICK, function(sender, evt)
- * {
- * var e = evt.getProperty('event');
- * var cell = evt.getProperty('cell');
- *
- * if (cell != null && !e.isConsumed())
- * {
- * // Do something useful with cell...
- * e.consume();
- * }
- * });
- * (end)
- */
-mxEditor.prototype.dblClickAction = 'edit';
-
-/**
- * Variable: swimlaneRequired
- *
- * Specifies if new cells must be inserted
- * into an existing swimlane. Otherwise, cells
- * that are not swimlanes can be inserted as
- * top-level cells. Default is false.
- */
-mxEditor.prototype.swimlaneRequired = false;
-
-/**
- * Variable: disableContextMenu
- *
- * Specifies if the context menu should be disabled in the graph container.
- * Default is true.
- */
-mxEditor.prototype.disableContextMenu = true;
-
-/**
- * Group: Templates
- */
-
-/**
- * Variable: insertFunction
- *
- * Specifies the function to be used for inserting new
- * cells into the graph. This is assigned from the
- * <mxDefaultToolbar> if a vertex-tool is clicked.
- */
-mxEditor.prototype.insertFunction = null;
-
-/**
- * Variable: forcedInserting
- *
- * Specifies if a new cell should be inserted on a single
- * click even using <insertFunction> if there is a cell
- * under the mousepointer, otherwise the cell under the
- * mousepointer is selected. Default is false.
- */
-mxEditor.prototype.forcedInserting = false;
-
-/**
- * Variable: templates
- *
- * Maps from names to protoype cells to be used
- * in the toolbar for inserting new cells into
- * the diagram.
- */
-mxEditor.prototype.templates = null;
-
-/**
- * Variable: defaultEdge
- *
- * Prototype edge cell that is used for creating
- * new edges.
- */
-mxEditor.prototype.defaultEdge = null;
-
-/**
- * Variable: defaultEdgeStyle
- *
- * Specifies the edge style to be returned in <getEdgeStyle>.
- * Default is null.
- */
-mxEditor.prototype.defaultEdgeStyle = null;
-
-/**
- * Variable: defaultGroup
- *
- * Prototype group cell that is used for creating
- * new groups.
- */
-mxEditor.prototype.defaultGroup = null;
-
-/**
- * Variable: graphRenderHint
- *
- * Default size for the border of new groups. If null,
- * then then <mxGraph.gridSize> is used. Default is
- * null.
- */
-mxEditor.prototype.groupBorderSize = null;
-
-/**
- * Group: Backend Integration
- */
-
-/**
- * Variable: filename
- *
- * Contains the URL of the last opened file as a string.
- * Default is null.
- */
-mxEditor.prototype.filename = null;
-
-/**
- * Variable: lineFeed
- *
- * Character to be used for encoding linefeeds in <save>. Default is '&#xa;'.
- */
-mxEditor.prototype.linefeed = '&#xa;';
-
-/**
- * Variable: postParameterName
- *
- * Specifies if the name of the post parameter that contains the diagram
- * data in a post request to the server. Default is xml.
- */
-mxEditor.prototype.postParameterName = 'xml';
-
-/**
- * Variable: escapePostData
- *
- * Specifies if the data in the post request for saving a diagram
- * should be converted using encodeURIComponent. Default is true.
- */
-mxEditor.prototype.escapePostData = true;
-
-/**
- * Variable: urlPost
- *
- * Specifies the URL to be used for posting the diagram
- * to a backend in <save>.
- */
-mxEditor.prototype.urlPost = null;
-
-/**
- * Variable: urlImage
- *
- * Specifies the URL to be used for creating a bitmap of
- * the graph in the image action.
- */
-mxEditor.prototype.urlImage = null;
-
-/**
- * Variable: urlInit
- *
- * Specifies the URL to be used for initializing the session.
- */
-mxEditor.prototype.urlInit = null;
-
-/**
- * Variable: urlNotify
- *
- * Specifies the URL to be used for notifying the backend
- * in the session.
- */
-mxEditor.prototype.urlNotify = null;
-
-/**
- * Variable: urlPoll
- *
- * Specifies the URL to be used for polling in the session.
- */
-mxEditor.prototype.urlPoll = null;
-
-/**
- * Group: Autolayout
- */
-
-/**
- * Variable: horizontalFlow
- *
- * Specifies the direction of the flow
- * in the diagram. This is used in the
- * layout algorithms. Default is false,
- * ie. vertical flow.
- */
-mxEditor.prototype.horizontalFlow = false;
-
-/**
- * Variable: layoutDiagram
- *
- * Specifies if the top-level elements in the
- * diagram should be layed out using a vertical
- * or horizontal stack depending on the setting
- * of <horizontalFlow>. The spacing between the
- * swimlanes is specified by <swimlaneSpacing>.
- * Default is false.
- *
- * If the top-level elements are swimlanes, then
- * the intra-swimlane layout is activated by
- * the <layoutSwimlanes> switch.
- */
-mxEditor.prototype.layoutDiagram = false;
-
-/**
- * Variable: swimlaneSpacing
- *
- * Specifies the spacing between swimlanes if
- * automatic layout is turned on in
- * <layoutDiagram>. Default is 0.
- */
-mxEditor.prototype.swimlaneSpacing = 0;
-
-/**
- * Variable: maintainSwimlanes
- *
- * Specifies if the swimlanes should be kept at the same
- * width or height depending on the setting of
- * <horizontalFlow>. Default is false.
- *
- * For horizontal flows, all swimlanes
- * have the same height and for vertical flows, all swimlanes
- * have the same width. Furthermore, the swimlanes are
- * automatically "stacked" if <layoutDiagram> is true.
- */
-mxEditor.prototype.maintainSwimlanes = false;
-
-/**
- * Variable: layoutSwimlanes
- *
- * Specifies if the children of swimlanes should
- * be layed out, either vertically or horizontally
- * depending on <horizontalFlow>.
- * Default is false.
- */
-mxEditor.prototype.layoutSwimlanes = false;
-
-/**
- * Group: Attribute Cycling
- */
-
-/**
- * Variable: cycleAttributeValues
- *
- * Specifies the attribute values to be cycled when
- * inserting new swimlanes. Default is an empty
- * array.
- */
-mxEditor.prototype.cycleAttributeValues = null;
-
-/**
- * Variable: cycleAttributeIndex
- *
- * Index of the last consumed attribute index. If a new
- * swimlane is inserted, then the <cycleAttributeValues>
- * at this index will be used as the value for
- * <cycleAttributeName>. Default is 0.
- */
-mxEditor.prototype.cycleAttributeIndex = 0;
-
-/**
- * Variable: cycleAttributeName
- *
- * Name of the attribute to be assigned a <cycleAttributeValues>
- * when inserting new swimlanes. Default is fillColor.
- */
-mxEditor.prototype.cycleAttributeName = 'fillColor';
-
-/**
- * Group: Windows
- */
-
-/**
- * Variable: tasks
- *
- * Holds the <mxWindow> created in <showTasks>.
- */
-mxEditor.prototype.tasks = null;
-
-/**
- * Variable: tasksWindowImage
- *
- * Icon for the tasks window.
- */
-mxEditor.prototype.tasksWindowImage = null;
-
-/**
- * Variable: tasksTop
- *
- * Specifies the top coordinate of the tasks window in pixels.
- * Default is 20.
- */
-mxEditor.prototype.tasksTop = 20;
-
-/**
- * Variable: help
- *
- * Holds the <mxWindow> created in <showHelp>.
- */
-mxEditor.prototype.help = null;
-
-/**
- * Variable: helpWindowImage
- *
- * Icon for the help window.
- */
-mxEditor.prototype.helpWindowImage = null;
-
-/**
- * Variable: urlHelp
- *
- * Specifies the URL to be used for the contents of the
- * Online Help window. This is usually specified in the
- * resources file under urlHelp for language-specific
- * online help support.
- */
-mxEditor.prototype.urlHelp = null;
-
-/**
- * Variable: helpWidth
- *
- * Specifies the width of the help window in pixels.
- * Default is 300.
- */
-mxEditor.prototype.helpWidth = 300;
-
-/**
- * Variable: helpWidth
- *
- * Specifies the width of the help window in pixels.
- * Default is 260.
- */
-mxEditor.prototype.helpHeight = 260;
-
-/**
- * Variable: propertiesWidth
- *
- * Specifies the width of the properties window in pixels.
- * Default is 240.
- */
-mxEditor.prototype.propertiesWidth = 240;
-
-/**
- * Variable: propertiesHeight
- *
- * Specifies the height of the properties window in pixels.
- * If no height is specified then the window will be automatically
- * sized to fit its contents. Default is null.
- */
-mxEditor.prototype.propertiesHeight = null;
-
-/**
- * Variable: movePropertiesDialog
- *
- * Specifies if the properties dialog should be automatically
- * moved near the cell it is displayed for, otherwise the
- * dialog is not moved. This value is only taken into
- * account if the dialog is already visible. Default is false.
- */
-mxEditor.prototype.movePropertiesDialog = false;
-
-/**
- * Variable: validating
- *
- * Specifies if <mxGraph.validateGraph> should automatically be invoked after
- * each change. Default is false.
- */
-mxEditor.prototype.validating = false;
-
-/**
- * Variable: modified
- *
- * True if the graph has been modified since it was last saved.
- */
-mxEditor.prototype.modified = false;
-
-/**
- * Function: isModified
- *
- * Returns <modified>.
- */
-mxEditor.prototype.isModified = function ()
-{
- return this.modified;
-};
-
-/**
- * Function: setModified
- *
- * Sets <modified> to the specified boolean value.
- */
-mxEditor.prototype.setModified = function (value)
-{
- this.modified = value;
-};
-
-/**
- * Function: addActions
- *
- * Adds the built-in actions to the editor instance.
- *
- * save - Saves the graph using <urlPost>.
- * print - Shows the graph in a new print preview window.
- * show - Shows the graph in a new window.
- * exportImage - Shows the graph as a bitmap image using <getUrlImage>.
- * refresh - Refreshes the graph's display.
- * cut - Copies the current selection into the clipboard
- * and removes it from the graph.
- * copy - Copies the current selection into the clipboard.
- * paste - Pastes the clipboard into the graph.
- * delete - Removes the current selection from the graph.
- * group - Puts the current selection into a new group.
- * ungroup - Removes the selected groups and selects the children.
- * undo - Undoes the last change on the graph model.
- * redo - Redoes the last change on the graph model.
- * zoom - Sets the zoom via a dialog.
- * zoomIn - Zooms into the graph.
- * zoomOut - Zooms out of the graph
- * actualSize - Resets the scale and translation on the graph.
- * fit - Changes the scale so that the graph fits into the window.
- * showProperties - Shows the properties dialog.
- * selectAll - Selects all cells.
- * selectNone - Clears the selection.
- * selectVertices - Selects all vertices.
- * selectEdges = Selects all edges.
- * edit - Starts editing the current selection cell.
- * enterGroup - Drills down into the current selection cell.
- * exitGroup - Moves up in the drilling hierachy
- * home - Moves to the topmost parent in the drilling hierarchy
- * selectPrevious - Selects the previous cell.
- * selectNext - Selects the next cell.
- * selectParent - Selects the parent of the selection cell.
- * selectChild - Selects the first child of the selection cell.
- * collapse - Collapses the currently selected cells.
- * expand - Expands the currently selected cells.
- * bold - Toggle bold text style.
- * italic - Toggle italic text style.
- * underline - Toggle underline text style.
- * shadow - Toggle shadow text style.
- * alignCellsLeft - Aligns the selection cells at the left.
- * alignCellsCenter - Aligns the selection cells in the center.
- * alignCellsRight - Aligns the selection cells at the right.
- * alignCellsTop - Aligns the selection cells at the top.
- * alignCellsMiddle - Aligns the selection cells in the middle.
- * alignCellsBottom - Aligns the selection cells at the bottom.
- * alignFontLeft - Sets the horizontal text alignment to left.
- * alignFontCenter - Sets the horizontal text alignment to center.
- * alignFontRight - Sets the horizontal text alignment to right.
- * alignFontTop - Sets the vertical text alignment to top.
- * alignFontMiddle - Sets the vertical text alignment to middle.
- * alignFontBottom - Sets the vertical text alignment to bottom.
- * toggleTasks - Shows or hides the tasks window.
- * toggleHelp - Shows or hides the help window.
- * toggleOutline - Shows or hides the outline window.
- * toggleConsole - Shows or hides the console window.
- */
-mxEditor.prototype.addActions = function ()
-{
- this.addAction('save', function(editor)
- {
- editor.save();
- });
-
- this.addAction('print', function(editor)
- {
- var preview = new mxPrintPreview(editor.graph, 1);
- preview.open();
- });
-
- this.addAction('show', function(editor)
- {
- mxUtils.show(editor.graph, null, 10, 10);
- });
-
- this.addAction('exportImage', function(editor)
- {
- var url = editor.getUrlImage();
-
- if (url == null || mxClient.IS_LOCAL)
- {
- editor.execute('show');
- }
- else
- {
- var node = mxUtils.getViewXml(editor.graph, 1);
- var xml = mxUtils.getXml(node, '\n');
-
- mxUtils.submit(url, editor.postParameterName + '=' +
- encodeURIComponent(xml), document, '_blank');
- }
- });
-
- this.addAction('refresh', function(editor)
- {
- editor.graph.refresh();
- });
-
- this.addAction('cut', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- mxClipboard.cut(editor.graph);
- }
- });
-
- this.addAction('copy', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- mxClipboard.copy(editor.graph);
- }
- });
-
- this.addAction('paste', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- mxClipboard.paste(editor.graph);
- }
- });
-
- this.addAction('delete', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.removeCells();
- }
- });
-
- this.addAction('group', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.setSelectionCell(editor.groupCells());
- }
- });
-
- this.addAction('ungroup', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.setSelectionCells(editor.graph.ungroupCells());
- }
- });
-
- this.addAction('removeFromParent', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.removeCellsFromParent();
- }
- });
-
- this.addAction('undo', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.undo();
- }
- });
-
- this.addAction('redo', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.redo();
- }
- });
-
- this.addAction('zoomIn', function(editor)
- {
- editor.graph.zoomIn();
- });
-
- this.addAction('zoomOut', function(editor)
- {
- editor.graph.zoomOut();
- });
-
- this.addAction('actualSize', function(editor)
- {
- editor.graph.zoomActual();
- });
-
- this.addAction('fit', function(editor)
- {
- editor.graph.fit();
- });
-
- this.addAction('showProperties', function(editor, cell)
- {
- editor.showProperties(cell);
- });
-
- this.addAction('selectAll', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.selectAll();
- }
- });
-
- this.addAction('selectNone', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.clearSelection();
- }
- });
-
- this.addAction('selectVertices', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.selectVertices();
- }
- });
-
- this.addAction('selectEdges', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.selectEdges();
- }
- });
-
- this.addAction('edit', function(editor, cell)
- {
- if (editor.graph.isEnabled() &&
- editor.graph.isCellEditable(cell))
- {
- editor.graph.startEditingAtCell(cell);
- }
- });
-
- this.addAction('toBack', function(editor, cell)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.orderCells(true);
- }
- });
-
- this.addAction('toFront', function(editor, cell)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.orderCells(false);
- }
- });
-
- this.addAction('enterGroup', function(editor, cell)
- {
- editor.graph.enterGroup(cell);
- });
-
- this.addAction('exitGroup', function(editor)
- {
- editor.graph.exitGroup();
- });
-
- this.addAction('home', function(editor)
- {
- editor.graph.home();
- });
-
- this.addAction('selectPrevious', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.selectPreviousCell();
- }
- });
-
- this.addAction('selectNext', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.selectNextCell();
- }
- });
-
- this.addAction('selectParent', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.selectParentCell();
- }
- });
-
- this.addAction('selectChild', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.selectChildCell();
- }
- });
-
- this.addAction('collapse', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.foldCells(true);
- }
- });
-
- this.addAction('collapseAll', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- var cells = editor.graph.getChildVertices();
- editor.graph.foldCells(true, false, cells);
- }
- });
-
- this.addAction('expand', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.foldCells(false);
- }
- });
-
- this.addAction('expandAll', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- var cells = editor.graph.getChildVertices();
- editor.graph.foldCells(false, false, cells);
- }
- });
-
- this.addAction('bold', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.toggleCellStyleFlags(
- mxConstants.STYLE_FONTSTYLE,
- mxConstants.FONT_BOLD);
- }
- });
-
- this.addAction('italic', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.toggleCellStyleFlags(
- mxConstants.STYLE_FONTSTYLE,
- mxConstants.FONT_ITALIC);
- }
- });
-
- this.addAction('underline', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.toggleCellStyleFlags(
- mxConstants.STYLE_FONTSTYLE,
- mxConstants.FONT_UNDERLINE);
- }
- });
-
- this.addAction('shadow', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.toggleCellStyleFlags(
- mxConstants.STYLE_FONTSTYLE,
- mxConstants.FONT_SHADOW);
- }
- });
-
- this.addAction('alignCellsLeft', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.alignCells(mxConstants.ALIGN_LEFT);
- }
- });
-
- this.addAction('alignCellsCenter', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.alignCells(mxConstants.ALIGN_CENTER);
- }
- });
-
- this.addAction('alignCellsRight', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.alignCells(mxConstants.ALIGN_RIGHT);
- }
- });
-
- this.addAction('alignCellsTop', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.alignCells(mxConstants.ALIGN_TOP);
- }
- });
-
- this.addAction('alignCellsMiddle', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.alignCells(mxConstants.ALIGN_MIDDLE);
- }
- });
-
- this.addAction('alignCellsBottom', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.alignCells(mxConstants.ALIGN_BOTTOM);
- }
- });
-
- this.addAction('alignFontLeft', function(editor)
- {
-
- editor.graph.setCellStyles(
- mxConstants.STYLE_ALIGN,
- mxConstants.ALIGN_LEFT);
- });
-
- this.addAction('alignFontCenter', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.setCellStyles(
- mxConstants.STYLE_ALIGN,
- mxConstants.ALIGN_CENTER);
- }
- });
-
- this.addAction('alignFontRight', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.setCellStyles(
- mxConstants.STYLE_ALIGN,
- mxConstants.ALIGN_RIGHT);
- }
- });
-
- this.addAction('alignFontTop', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.setCellStyles(
- mxConstants.STYLE_VERTICAL_ALIGN,
- mxConstants.ALIGN_TOP);
- }
- });
-
- this.addAction('alignFontMiddle', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.setCellStyles(
- mxConstants.STYLE_VERTICAL_ALIGN,
- mxConstants.ALIGN_MIDDLE);
- }
- });
-
- this.addAction('alignFontBottom', function(editor)
- {
- if (editor.graph.isEnabled())
- {
- editor.graph.setCellStyles(
- mxConstants.STYLE_VERTICAL_ALIGN,
- mxConstants.ALIGN_BOTTOM);
- }
- });
-
- this.addAction('zoom', function(editor)
- {
- var current = editor.graph.getView().scale*100;
- var scale = parseFloat(mxUtils.prompt(
- mxResources.get(editor.askZoomResource) ||
- editor.askZoomResource,
- current))/100;
-
- if (!isNaN(scale))
- {
- editor.graph.getView().setScale(scale);
- }
- });
-
- this.addAction('toggleTasks', function(editor)
- {
- if (editor.tasks != null)
- {
- editor.tasks.setVisible(!editor.tasks.isVisible());
- }
- else
- {
- editor.showTasks();
- }
- });
-
- this.addAction('toggleHelp', function(editor)
- {
- if (editor.help != null)
- {
- editor.help.setVisible(!editor.help.isVisible());
- }
- else
- {
- editor.showHelp();
- }
- });
-
- this.addAction('toggleOutline', function(editor)
- {
- if (editor.outline == null)
- {
- editor.showOutline();
- }
- else
- {
- editor.outline.setVisible(!editor.outline.isVisible());
- }
- });
-
- this.addAction('toggleConsole', function(editor)
- {
- mxLog.setVisible(!mxLog.isVisible());
- });
-};
-
-/**
- * Function: createSession
- *
- * Creates and returns and <mxSession> using <urlInit>, <urlPoll> and <urlNotify>.
- */
-mxEditor.prototype.createSession = function ()
-{
- // Routes any change events from the session
- // through the editor and dispatches them as
- // a session event.
- var sessionChanged = mxUtils.bind(this, function(session)
- {
- this.fireEvent(new mxEventObject(mxEvent.SESSION, 'session', session));
- });
-
- return this.connect(this.urlInit, this.urlPoll,
- this.urlNotify, sessionChanged);
-};
-
-/**
- * Function: configure
- *
- * Configures the editor using the specified node. To load the
- * configuration from a given URL the following code can be used to obtain
- * the XML node.
- *
- * (code)
- * var node = mxUtils.load(url).getDocumentElement();
- * (end)
- *
- * Parameters:
- *
- * node - XML node that contains the configuration.
- */
-mxEditor.prototype.configure = function (node)
-{
- if (node != null)
- {
- // Creates a decoder for the XML data
- // and uses it to configure the editor
- var dec = new mxCodec(node.ownerDocument);
- dec.decode(node, this);
-
- // Resets the counters, modified state and
- // command history
- this.resetHistory();
- }
-};
-
-/**
- * Function: resetFirstTime
- *
- * Resets the cookie that is used to remember if the editor has already
- * been used.
- */
-mxEditor.prototype.resetFirstTime = function ()
-{
- document.cookie =
- 'mxgraph=seen; expires=Fri, 27 Jul 2001 02:47:11 UTC; path=/';
-};
-
-/**
- * Function: resetHistory
- *
- * Resets the command history, modified state and counters.
- */
-mxEditor.prototype.resetHistory = function ()
-{
- this.lastSnapshot = new Date().getTime();
- this.undoManager.clear();
- this.ignoredChanges = 0;
- this.setModified(false);
-};
-
-/**
- * Function: addAction
- *
- * Binds the specified actionname to the specified function.
- *
- * Parameters:
- *
- * actionname - String that specifies the name of the action
- * to be added.
- * funct - Function that implements the new action. The first
- * argument of the function is the editor it is used
- * with, the second argument is the cell it operates
- * upon.
- *
- * Example:
- * (code)
- * editor.addAction('test', function(editor, cell)
- * {
- * mxUtils.alert("test "+cell);
- * });
- * (end)
- */
-mxEditor.prototype.addAction = function (actionname, funct)
-{
- this.actions[actionname] = funct;
-};
-
-/**
- * Function: execute
- *
- * Executes the function with the given name in <actions> passing the
- * editor instance and given cell as the first and second argument. All
- * additional arguments are passed to the action as well. This method
- * contains a try-catch block and displays an error message if an action
- * causes an exception. The exception is re-thrown after the error
- * message was displayed.
- *
- * Example:
- *
- * (code)
- * editor.execute("showProperties", cell);
- * (end)
- */
-mxEditor.prototype.execute = function (actionname, cell, evt)
-{
- var action = this.actions[actionname];
-
- if (action != null)
- {
- try
- {
- // Creates the array of arguments by replacing the actionname
- // with the editor instance in the args of this function
- var args = arguments;
- args[0] = this;
-
- // Invokes the function on the editor using the args
- action.apply(this, args);
- }
- catch (e)
- {
- mxUtils.error('Cannot execute ' + actionname +
- ': ' + e.message, 280, true);
-
- throw e;
- }
- }
- else
- {
- mxUtils.error('Cannot find action '+actionname, 280, true);
- }
-};
-
-/**
- * Function: addTemplate
- *
- * Adds the specified template under the given name in <templates>.
- */
-mxEditor.prototype.addTemplate = function (name, template)
-{
- this.templates[name] = template;
-};
-
-/**
- * Function: getTemplate
- *
- * Returns the template for the given name.
- */
-mxEditor.prototype.getTemplate = function (name)
-{
- return this.templates[name];
-};
-
-/**
- * Function: createGraph
- *
- * Creates the <graph> for the editor. The graph is created with no
- * container and is initialized from <setGraphContainer>.
- */
-mxEditor.prototype.createGraph = function ()
-{
- var graph = new mxGraph(null, null, this.graphRenderHint);
-
- // Enables rubberband, tooltips, panning
- graph.setTooltips(true);
- graph.setPanning(true);
-
- // Overrides the dblclick method on the graph to
- // invoke the dblClickAction for a cell and reset
- // the selection tool in the toolbar
- this.installDblClickHandler(graph);
-
- // Installs the command history
- this.installUndoHandler(graph);
-
- // Installs the handlers for the root event
- this.installDrillHandler(graph);
-
- // Installs the handler for validation
- this.installChangeHandler(graph);
-
- // Installs the handler for calling the
- // insert function and consume the
- // event if an insert function is defined
- this.installInsertHandler(graph);
-
- // Redirects the function for creating the
- // popupmenu items
- graph.panningHandler.factoryMethod =
- mxUtils.bind(this, function(menu, cell, evt)
- {
- return this.createPopupMenu(menu, cell, evt);
- });
-
- // Redirects the function for creating
- // new connections in the diagram
- graph.connectionHandler.factoryMethod =
- mxUtils.bind(this, function(source, target)
- {
- return this.createEdge(source, target);
- });
-
- // Maintains swimlanes and installs autolayout
- this.createSwimlaneManager(graph);
- this.createLayoutManager(graph);
-
- return graph;
-};
-
-/**
- * Function: createSwimlaneManager
- *
- * Sets the graph's container using <mxGraph.init>.
- */
-mxEditor.prototype.createSwimlaneManager = function (graph)
-{
- var swimlaneMgr = new mxSwimlaneManager(graph, false);
-
- swimlaneMgr.isHorizontal = mxUtils.bind(this, function()
- {
- return this.horizontalFlow;
- });
-
- swimlaneMgr.isEnabled = mxUtils.bind(this, function()
- {
- return this.maintainSwimlanes;
- });
-
- return swimlaneMgr;
-};
-
-/**
- * Function: createLayoutManager
- *
- * Creates a layout manager for the swimlane and diagram layouts, that
- * is, the locally defined inter- and intraswimlane layouts.
- */
-mxEditor.prototype.createLayoutManager = function (graph)
-{
- var layoutMgr = new mxLayoutManager(graph);
-
- var self = this; // closure
- layoutMgr.getLayout = function(cell)
- {
- var layout = null;
- var model = self.graph.getModel();
-
- if (model.getParent(cell) != null)
- {
- // Executes the swimlane layout if a child of
- // a swimlane has been changed. The layout is
- // lazy created in createSwimlaneLayout.
- if (self.layoutSwimlanes &&
- graph.isSwimlane(cell))
- {
- if (self.swimlaneLayout == null)
- {
- self.swimlaneLayout = self.createSwimlaneLayout();
- }
-
- layout = self.swimlaneLayout;
- }
-
- // Executes the diagram layout if the modified
- // cell is a top-level cell. The layout is
- // lazy created in createDiagramLayout.
- else if (self.layoutDiagram &&
- (graph.isValidRoot(cell) ||
- model.getParent(model.getParent(cell)) == null))
- {
- if (self.diagramLayout == null)
- {
- self.diagramLayout = self.createDiagramLayout();
- }
-
- layout = self.diagramLayout;
- }
- }
-
- return layout;
- };
-
- return layoutMgr;
-};
-
-/**
- * Function: setGraphContainer
- *
- * Sets the graph's container using <mxGraph.init>.
- */
-mxEditor.prototype.setGraphContainer = function (container)
-{
- if (this.graph.container == null)
- {
- // Creates the graph instance inside the given container and render hint
- //this.graph = new mxGraph(container, null, this.graphRenderHint);
- this.graph.init(container);
-
- // Install rubberband selection as the last
- // action handler in the chain
- this.rubberband = new mxRubberband(this.graph);
-
- // Disables the context menu
- if (this.disableContextMenu)
- {
- mxEvent.disableContextMenu(container);
- }
-
- // Workaround for stylesheet directives in IE
- if (mxClient.IS_QUIRKS)
- {
- new mxDivResizer(container);
- }
- }
-};
-
-/**
- * Function: installDblClickHandler
- *
- * Overrides <mxGraph.dblClick> to invoke <dblClickAction>
- * on a cell and reset the selection tool in the toolbar.
- */
-mxEditor.prototype.installDblClickHandler = function (graph)
-{
- // Installs a listener for double click events
- graph.addListener(mxEvent.DOUBLE_CLICK,
- mxUtils.bind(this, function(sender, evt)
- {
- var cell = evt.getProperty('cell');
-
- if (cell != null &&
- graph.isEnabled() &&
- this.dblClickAction != null)
- {
- this.execute(this.dblClickAction, cell);
- evt.consume();
- }
- })
- );
-};
-
-/**
- * Function: installUndoHandler
- *
- * Adds the <undoManager> to the graph model and the view.
- */
-mxEditor.prototype.installUndoHandler = function (graph)
-{
- var listener = mxUtils.bind(this, function(sender, evt)
- {
- var edit = evt.getProperty('edit');
- this.undoManager.undoableEditHappened(edit);
- });
-
- graph.getModel().addListener(mxEvent.UNDO, listener);
- graph.getView().addListener(mxEvent.UNDO, listener);
-
- // Keeps the selection state in sync
- var undoHandler = function(sender, evt)
- {
- var changes = evt.getProperty('edit').changes;
- graph.setSelectionCells(graph.getSelectionCellsForChanges(changes));
- };
-
- this.undoManager.addListener(mxEvent.UNDO, undoHandler);
- this.undoManager.addListener(mxEvent.REDO, undoHandler);
-};
-
-/**
- * Function: installDrillHandler
- *
- * Installs listeners for dispatching the <root> event.
- */
-mxEditor.prototype.installDrillHandler = function (graph)
-{
- var listener = mxUtils.bind(this, function(sender)
- {
- this.fireEvent(new mxEventObject(mxEvent.ROOT));
- });
-
- graph.getView().addListener(mxEvent.DOWN, listener);
- graph.getView().addListener(mxEvent.UP, listener);
-};
-
-/**
- * Function: installChangeHandler
- *
- * Installs the listeners required to automatically validate
- * the graph. On each change of the root, this implementation
- * fires a <root> event.
- */
-mxEditor.prototype.installChangeHandler = function (graph)
-{
- var listener = mxUtils.bind(this, function(sender, evt)
- {
- // Updates the modified state
- this.setModified(true);
-
- // Automatically validates the graph
- // after each change
- if (this.validating == true)
- {
- graph.validateGraph();
- }
-
- // Checks if the root has been changed
- var changes = evt.getProperty('edit').changes;
-
- for (var i = 0; i < changes.length; i++)
- {
- var change = changes[i];
-
- if (change instanceof mxRootChange ||
- (change instanceof mxValueChange &&
- change.cell == this.graph.model.root) ||
- (change instanceof mxCellAttributeChange &&
- change.cell == this.graph.model.root))
- {
- this.fireEvent(new mxEventObject(mxEvent.ROOT));
- break;
- }
- }
- });
-
- graph.getModel().addListener(mxEvent.CHANGE, listener);
-};
-
-/**
- * Function: installInsertHandler
- *
- * Installs the handler for invoking <insertFunction> if
- * one is defined.
- */
-mxEditor.prototype.installInsertHandler = function (graph)
-{
- var self = this; // closure
- var insertHandler =
- {
- mouseDown: function(sender, me)
- {
- if (self.insertFunction != null &&
- !me.isPopupTrigger() &&
- (self.forcedInserting ||
- me.getState() == null))
- {
- self.graph.clearSelection();
- self.insertFunction(me.getEvent(), me.getCell());
-
- // Consumes the rest of the events
- // for this gesture (down, move, up)
- this.isActive = true;
- me.consume();
- }
- },
-
- mouseMove: function(sender, me)
- {
- if (this.isActive)
- {
- me.consume();
- }
- },
-
- mouseUp: function(sender, me)
- {
- if (this.isActive)
- {
- this.isActive = false;
- me.consume();
- }
- }
- };
-
- graph.addMouseListener(insertHandler);
-};
-
-/**
- * Function: createDiagramLayout
- *
- * Creates the layout instance used to layout the
- * swimlanes in the diagram.
- */
-mxEditor.prototype.createDiagramLayout = function ()
-{
- var gs = this.graph.gridSize;
- var layout = new mxStackLayout(this.graph, !this.horizontalFlow,
- this.swimlaneSpacing, 2*gs, 2*gs);
-
- // Overrides isIgnored to only take into account swimlanes
- layout.isVertexIgnored = function(cell)
- {
- return !layout.graph.isSwimlane(cell);
- };
-
- return layout;
-};
-
-/**
- * Function: createSwimlaneLayout
- *
- * Creates the layout instance used to layout the
- * children of each swimlane.
- */
-mxEditor.prototype.createSwimlaneLayout = function ()
-{
- return new mxCompactTreeLayout(this.graph, this.horizontalFlow);
-};
-
-/**
- * Function: createToolbar
- *
- * Creates the <toolbar> with no container.
- */
-mxEditor.prototype.createToolbar = function ()
-{
- return new mxDefaultToolbar(null, this);
-};
-
-/**
- * Function: setToolbarContainer
- *
- * Initializes the toolbar for the given container.
- */
-mxEditor.prototype.setToolbarContainer = function (container)
-{
- this.toolbar.init(container);
-
- // Workaround for stylesheet directives in IE
- if (mxClient.IS_QUIRKS)
- {
- new mxDivResizer(container);
- }
-};
-
-/**
- * Function: setStatusContainer
- *
- * Creates the <status> using the specified container.
- *
- * This implementation adds listeners in the editor to
- * display the last saved time and the current filename
- * in the status bar.
- *
- * Parameters:
- *
- * container - DOM node that will contain the statusbar.
- */
-mxEditor.prototype.setStatusContainer = function (container)
-{
- if (this.status == null)
- {
- this.status = container;
-
- // Prints the last saved time in the status bar
- // when files are saved
- this.addListener(mxEvent.SAVE, mxUtils.bind(this, function()
- {
- var tstamp = new Date().toLocaleString();
- this.setStatus((mxResources.get(this.lastSavedResource) ||
- this.lastSavedResource)+': '+tstamp);
- }));
-
- // Updates the statusbar to display the filename
- // when new files are opened
- this.addListener(mxEvent.OPEN, mxUtils.bind(this, function()
- {
- this.setStatus((mxResources.get(this.currentFileResource) ||
- this.currentFileResource)+': '+this.filename);
- }));
-
- // Workaround for stylesheet directives in IE
- if (mxClient.IS_QUIRKS)
- {
- new mxDivResizer(container);
- }
- }
-};
-
-/**
- * Function: setStatus
- *
- * Display the specified message in the status bar.
- *
- * Parameters:
- *
- * message - String the specified the message to
- * be displayed.
- */
-mxEditor.prototype.setStatus = function (message)
-{
- if (this.status != null && message != null)
- {
- this.status.innerHTML = message;
- }
-};
-
-/**
- * Function: setTitleContainer
- *
- * Creates a listener to update the inner HTML of the
- * specified DOM node with the value of <getTitle>.
- *
- * Parameters:
- *
- * container - DOM node that will contain the title.
- */
-mxEditor.prototype.setTitleContainer = function (container)
-{
- this.addListener(mxEvent.ROOT, mxUtils.bind(this, function(sender)
- {
- container.innerHTML = this.getTitle();
- }));
-
- // Workaround for stylesheet directives in IE
- if (mxClient.IS_QUIRKS)
- {
- new mxDivResizer(container);
- }
-};
-
-/**
- * Function: treeLayout
- *
- * Executes a vertical or horizontal compact tree layout
- * using the specified cell as an argument. The cell may
- * either be a group or the root of a tree.
- *
- * Parameters:
- *
- * cell - <mxCell> to use in the compact tree layout.
- * horizontal - Optional boolean to specify the tree's
- * orientation. Default is true.
- */
-mxEditor.prototype.treeLayout = function (cell, horizontal)
-{
- if (cell != null)
- {
- var layout = new mxCompactTreeLayout(this.graph, horizontal);
- layout.execute(cell);
- }
-};
-
-/**
- * Function: getTitle
- *
- * Returns the string value for the current root of the
- * diagram.
- */
-mxEditor.prototype.getTitle = function ()
-{
- var title = '';
- var graph = this.graph;
- var cell = graph.getCurrentRoot();
-
- while (cell != null &&
- graph.getModel().getParent(
- graph.getModel().getParent(cell)) != null)
- {
- // Append each label of a valid root
- if (graph.isValidRoot(cell))
- {
- title = ' > ' +
- graph.convertValueToString(cell) + title;
- }
-
- cell = graph.getModel().getParent(cell);
- }
-
- var prefix = this.getRootTitle();
-
- return prefix + title;
-};
-
-/**
- * Function: getRootTitle
- *
- * Returns the string value of the root cell in
- * <mxGraph.model>.
- */
-mxEditor.prototype.getRootTitle = function ()
-{
- var root = this.graph.getModel().getRoot();
- return this.graph.convertValueToString(root);
-};
-
-/**
- * Function: undo
- *
- * Undo the last change in <graph>.
- */
-mxEditor.prototype.undo = function ()
-{
- this.undoManager.undo();
-};
-
-/**
- * Function: redo
- *
- * Redo the last change in <graph>.
- */
-mxEditor.prototype.redo = function ()
-{
- this.undoManager.redo();
-};
-
-/**
- * Function: groupCells
- *
- * Invokes <createGroup> to create a new group cell and the invokes
- * <mxGraph.groupCells>, using the grid size of the graph as the spacing
- * in the group's content area.
- */
-mxEditor.prototype.groupCells = function ()
-{
- var border = (this.groupBorderSize != null) ?
- this.groupBorderSize :
- this.graph.gridSize;
- return this.graph.groupCells(this.createGroup(), border);
-};
-
-/**
- * Function: createGroup
- *
- * Creates and returns a clone of <defaultGroup> to be used
- * as a new group cell in <group>.
- */
-mxEditor.prototype.createGroup = function ()
-{
- var model = this.graph.getModel();
-
- return model.cloneCell(this.defaultGroup);
-};
-
-/**
- * Function: open
- *
- * Opens the specified file synchronously and parses it using
- * <readGraphModel>. It updates <filename> and fires an <open>-event after
- * the file has been opened. Exceptions should be handled as follows:
- *
- * (code)
- * try
- * {
- * editor.open(filename);
- * }
- * catch (e)
- * {
- * mxUtils.error('Cannot open ' + filename +
- * ': ' + e.message, 280, true);
- * }
- * (end)
- *
- * Parameters:
- *
- * filename - URL of the file to be opened.
- */
-mxEditor.prototype.open = function (filename)
-{
- if (filename != null)
- {
- var xml = mxUtils.load(filename).getXml();
- this.readGraphModel(xml.documentElement);
- this.filename = filename;
-
- this.fireEvent(new mxEventObject(mxEvent.OPEN, 'filename', filename));
- }
-};
-
-/**
- * Function: readGraphModel
- *
- * Reads the specified XML node into the existing graph model and resets
- * the command history and modified state.
- */
-mxEditor.prototype.readGraphModel = function (node)
-{
- var dec = new mxCodec(node.ownerDocument);
- dec.decode(node, this.graph.getModel());
- this.resetHistory();
-};
-
-/**
- * Function: save
- *
- * Posts the string returned by <writeGraphModel> to the given URL or the
- * URL returned by <getUrlPost>. The actual posting is carried out by
- * <postDiagram>. If the URL is null then the resulting XML will be
- * displayed using <mxUtils.popup>. Exceptions should be handled as
- * follows:
- *
- * (code)
- * try
- * {
- * editor.save();
- * }
- * catch (e)
- * {
- * mxUtils.error('Cannot save : ' + e.message, 280, true);
- * }
- * (end)
- */
-mxEditor.prototype.save = function (url, linefeed)
-{
- // Gets the URL to post the data to
- url = url || this.getUrlPost();
-
- // Posts the data if the URL is not empty
- if (url != null && url.length > 0)
- {
- var data = this.writeGraphModel(linefeed);
- this.postDiagram(url, data);
-
- // Resets the modified flag
- this.setModified(false);
- }
-
- // Dispatches a save event
- this.fireEvent(new mxEventObject(mxEvent.SAVE, 'url', url));
-};
-
-/**
- * Function: postDiagram
- *
- * Hook for subclassers to override the posting of a diagram
- * represented by the given node to the given URL. This fires
- * an asynchronous <post> event if the diagram has been posted.
- *
- * Example:
- *
- * To replace the diagram with the diagram in the response, use the
- * following code.
- *
- * (code)
- * editor.addListener(mxEvent.POST, function(sender, evt)
- * {
- * // Process response (replace diagram)
- * var req = evt.getProperty('request');
- * var root = req.getDocumentElement();
- * editor.graph.readGraphModel(root)
- * });
- * (end)
- */
-mxEditor.prototype.postDiagram = function (url, data)
-{
- if (this.escapePostData)
- {
- data = encodeURIComponent(data);
- }
-
- mxUtils.post(url, this.postParameterName+'='+data,
- mxUtils.bind(this, function(req)
- {
- this.fireEvent(new mxEventObject(mxEvent.POST,
- 'request', req, 'url', url, 'data', data));
- })
- );
-};
-
-/**
- * Function: writeGraphModel
- *
- * Hook to create the string representation of the diagram. The default
- * implementation uses an <mxCodec> to encode the graph model as
- * follows:
- *
- * (code)
- * var enc = new mxCodec();
- * var node = enc.encode(this.graph.getModel());
- * return mxUtils.getXml(node, this.linefeed);
- * (end)
- *
- * Parameters:
- *
- * linefeed - Optional character to be used as the linefeed. Default is
- * <linefeed>.
- */
-mxEditor.prototype.writeGraphModel = function (linefeed)
-{
- linefeed = (linefeed != null) ? linefeed : this.linefeed;
- var enc = new mxCodec();
- var node = enc.encode(this.graph.getModel());
-
- return mxUtils.getXml(node, linefeed);
-};
-
-/**
- * Function: getUrlPost
- *
- * Returns the URL to post the diagram to. This is used
- * in <save>. The default implementation returns <urlPost>,
- * adding <code>?draft=true</code>.
- */
-mxEditor.prototype.getUrlPost = function ()
-{
- return this.urlPost;
-};
-
-/**
- * Function: getUrlImage
- *
- * Returns the URL to create the image with. This is typically
- * the URL of a backend which accepts an XML representation
- * of a graph view to create an image. The function is used
- * in the image action to create an image. This implementation
- * returns <urlImage>.
- */
-mxEditor.prototype.getUrlImage = function ()
-{
- return this.urlImage;
-};
-
-/**
- * Function: connect
- *
- * Creates and returns a session for the specified parameters, installing
- * the onChange function as a change listener for the session.
- */
-mxEditor.prototype.connect = function (urlInit, urlPoll, urlNotify, onChange)
-{
- var session = null;
-
- if (!mxClient.IS_LOCAL)
- {
- session = new mxSession(this.graph.getModel(),
- urlInit, urlPoll, urlNotify);
-
- // Resets the undo history if the session was initialized which is the
- // case if the message carries a namespace to be used for new IDs.
- session.addListener(mxEvent.RECEIVE,
- mxUtils.bind(this, function(sender, evt)
- {
- var node = evt.getProperty('node');
-
- if (node.getAttribute('namespace') != null)
- {
- this.resetHistory();
- }
- })
- );
-
- // Installs the listener for all events
- // that signal a change of the session
- session.addListener(mxEvent.DISCONNECT, onChange);
- session.addListener(mxEvent.CONNECT, onChange);
- session.addListener(mxEvent.NOTIFY, onChange);
- session.addListener(mxEvent.GET, onChange);
- session.start();
- }
-
- return session;
-};
-
-/**
- * Function: swapStyles
- *
- * Swaps the styles for the given names in the graph's
- * stylesheet and refreshes the graph.
- */
-mxEditor.prototype.swapStyles = function (first, second)
-{
- var style = this.graph.getStylesheet().styles[second];
- this.graph.getView().getStylesheet().putCellStyle(
- second, this.graph.getStylesheet().styles[first]);
- this.graph.getStylesheet().putCellStyle(first, style);
- this.graph.refresh();
-};
-
-/**
- * Function: showProperties
- *
- * Creates and shows the properties dialog for the given
- * cell. The content area of the dialog is created using
- * <createProperties>.
- */
-mxEditor.prototype.showProperties = function (cell)
-{
- cell = cell || this.graph.getSelectionCell();
-
- // Uses the root node for the properties dialog
- // if not cell was passed in and no cell is
- // selected
- if (cell == null)
- {
- cell = this.graph.getCurrentRoot();
-
- if (cell == null)
- {
- cell = this.graph.getModel().getRoot();
- }
- }
-
- if (cell != null)
- {
- // Makes sure there is no in-place editor in the
- // graph and computes the location of the dialog
- this.graph.stopEditing(true);
-
- var offset = mxUtils.getOffset(this.graph.container);
- var x = offset.x+10;
- var y = offset.y;
-
- // Avoids moving the dialog if it is alredy open
- if (this.properties != null && !this.movePropertiesDialog)
- {
- x = this.properties.getX();
- y = this.properties.getY();
- }
-
- // Places the dialog near the cell for which it
- // displays the properties
- else
- {
- var bounds = this.graph.getCellBounds(cell);
-
- if (bounds != null)
- {
- x += bounds.x+Math.min(200, bounds.width);
- y += bounds.y;
- }
- }
-
- // Hides the existing properties dialog and creates a new one with the
- // contents created in the hook method
- this.hideProperties();
- var node = this.createProperties(cell);
-
- if (node != null)
- {
- // Displays the contents in a window and stores a reference to the
- // window for later hiding of the window
- this.properties = new mxWindow(mxResources.get(this.propertiesResource) ||
- this.propertiesResource, node, x, y, this.propertiesWidth, this.propertiesHeight, false);
- this.properties.setVisible(true);
- }
- }
-};
-
-/**
- * Function: isPropertiesVisible
- *
- * Returns true if the properties dialog is currently visible.
- */
-mxEditor.prototype.isPropertiesVisible = function ()
-{
- return this.properties != null;
-};
-
-/**
- * Function: createProperties
- *
- * Creates and returns the DOM node that represents the contents
- * of the properties dialog for the given cell. This implementation
- * works for user objects that are XML nodes and display all the
- * node attributes in a form.
- */
-mxEditor.prototype.createProperties = function (cell)
-{
- var model = this.graph.getModel();
- var value = model.getValue(cell);
-
- if (mxUtils.isNode(value))
- {
- // Creates a form for the user object inside
- // the cell
- var form = new mxForm('properties');
-
- // Adds a readonly field for the cell id
- var id = form.addText('ID', cell.getId());
- id.setAttribute('readonly', 'true');
-
- var geo = null;
- var yField = null;
- var xField = null;
- var widthField = null;
- var heightField = null;
-
- // Adds fields for the location and size
- if (model.isVertex(cell))
- {
- geo = model.getGeometry(cell);
-
- if (geo != null)
- {
- yField = form.addText('top', geo.y);
- xField = form.addText('left', geo.x);
- widthField = form.addText('width', geo.width);
- heightField = form.addText('height', geo.height);
- }
- }
-
- // Adds a field for the cell style
- var tmp = model.getStyle(cell);
- var style = form.addText('Style', tmp || '');
-
- // Creates textareas for each attribute of the
- // user object within the cell
- var attrs = value.attributes;
- var texts = [];
-
- for (var i = 0; i < attrs.length; i++)
- {
- // Creates a textarea with more lines for
- // the cell label
- var val = attrs[i].nodeValue;
- texts[i] = form.addTextarea(attrs[i].nodeName, val,
- (attrs[i].nodeName == 'label') ? 4 : 2);
- }
-
- // Adds an OK and Cancel button to the dialog
- // contents and implements the respective
- // actions below
-
- // Defines the function to be executed when the
- // OK button is pressed in the dialog
- var okFunction = mxUtils.bind(this, function()
- {
- // Hides the dialog
- this.hideProperties();
-
- // Supports undo for the changes on the underlying
- // XML structure / XML node attribute changes.
- model.beginUpdate();
- try
- {
- if (geo != null)
- {
- geo = geo.clone();
-
- geo.x = parseFloat(xField.value);
- geo.y = parseFloat(yField.value);
- geo.width = parseFloat(widthField.value);
- geo.height = parseFloat(heightField.value);
-
- model.setGeometry(cell, geo);
- }
-
- // Applies the style
- if (style.value.length > 0)
- {
- model.setStyle(cell, style.value);
- }
- else
- {
- model.setStyle(cell, null);
- }
-
- // Creates an undoable change for each
- // attribute and executes it using the
- // model, which will also make the change
- // part of the current transaction
- for (var i=0; i<attrs.length; i++)
- {
- var edit = new mxCellAttributeChange(
- cell, attrs[i].nodeName,
- texts[i].value);
- model.execute(edit);
- }
-
- // Checks if the graph wants cells to
- // be automatically sized and updates
- // the size as an undoable step if
- // the feature is enabled
- if (this.graph.isAutoSizeCell(cell))
- {
- this.graph.updateCellSize(cell);
- }
- }
- finally
- {
- model.endUpdate();
- }
- });
-
- // Defines the function to be executed when the
- // Cancel button is pressed in the dialog
- var cancelFunction = mxUtils.bind(this, function()
- {
- // Hides the dialog
- this.hideProperties();
- });
-
- form.addButtons(okFunction, cancelFunction);
-
- return form.table;
- }
-
- return null;
-};
-
-/**
- * Function: hideProperties
- *
- * Hides the properties dialog.
- */
-mxEditor.prototype.hideProperties = function ()
-{
- if (this.properties != null)
- {
- this.properties.destroy();
- this.properties = null;
- }
-};
-
-/**
- * Function: showTasks
- *
- * Shows the tasks window. The tasks window is created using <createTasks>. The
- * default width of the window is 200 pixels, the y-coordinate of the location
- * can be specifies in <tasksTop> and the x-coordinate is right aligned with a
- * 20 pixel offset from the right border. To change the location of the tasks
- * window, the following code can be used:
- *
- * (code)
- * var oldShowTasks = mxEditor.prototype.showTasks;
- * mxEditor.prototype.showTasks = function()
- * {
- * oldShowTasks.apply(this, arguments); // "supercall"
- *
- * if (this.tasks != null)
- * {
- * this.tasks.setLocation(10, 10);
- * }
- * };
- * (end)
- */
-mxEditor.prototype.showTasks = function ()
-{
- if (this.tasks == null)
- {
- var div = document.createElement('div');
- div.style.padding = '4px';
- div.style.paddingLeft = '20px';
- var w = document.body.clientWidth;
- var wnd = new mxWindow(
- mxResources.get(this.tasksResource) ||
- this.tasksResource,
- div, w - 220, this.tasksTop, 200);
- wnd.setClosable(true);
- wnd.destroyOnClose = false;
-
- // Installs a function to update the contents
- // of the tasks window on every change of the
- // model, selection or root.
- var funct = mxUtils.bind(this, function(sender)
- {
- mxEvent.release(div);
- div.innerHTML = '';
- this.createTasks(div);
- });
-
- this.graph.getModel().addListener(mxEvent.CHANGE, funct);
- this.graph.getSelectionModel().addListener(mxEvent.CHANGE, funct);
- this.graph.addListener(mxEvent.ROOT, funct);
-
- // Assigns the icon to the tasks window
- if (this.tasksWindowImage != null)
- {
- wnd.setImage(this.tasksWindowImage);
- }
-
- this.tasks = wnd;
- this.createTasks(div);
- }
-
- this.tasks.setVisible(true);
-};
-
-/**
- * Function: refreshTasks
- *
- * Updates the contents of the tasks window using <createTasks>.
- */
-mxEditor.prototype.refreshTasks = function (div)
-{
- if (this.tasks != null)
- {
- var div = this.tasks.content;
- mxEvent.release(div);
- div.innerHTML = '';
- this.createTasks(div);
- }
-};
-
-/**
- * Function: createTasks
- *
- * Updates the contents of the given DOM node to
- * display the tasks associated with the current
- * editor state. This is invoked whenever there
- * is a possible change of state in the editor.
- * Default implementation is empty.
- */
-mxEditor.prototype.createTasks = function (div)
-{
- // override
-};
-
-/**
- * Function: showHelp
- *
- * Shows the help window. If the help window does not exist
- * then it is created using an iframe pointing to the resource
- * for the <code>urlHelp</code> key or <urlHelp> if the resource
- * is undefined.
- */
-mxEditor.prototype.showHelp = function (tasks)
-{
- if (this.help == null)
- {
- var frame = document.createElement('iframe');
- frame.setAttribute('src', mxResources.get('urlHelp') || this.urlHelp);
- frame.setAttribute('height', '100%');
- frame.setAttribute('width', '100%');
- frame.setAttribute('frameBorder', '0');
- frame.style.backgroundColor = 'white';
-
- var w = document.body.clientWidth;
- var h = (document.body.clientHeight || document.documentElement.clientHeight);
-
- var wnd = new mxWindow(mxResources.get(this.helpResource) || this.helpResource,
- frame, (w-this.helpWidth)/2, (h-this.helpHeight)/3, this.helpWidth, this.helpHeight);
- wnd.setMaximizable(true);
- wnd.setClosable(true);
- wnd.destroyOnClose = false;
- wnd.setResizable(true);
-
- // Assigns the icon to the help window
- if (this.helpWindowImage != null)
- {
- wnd.setImage(this.helpWindowImage);
- }
-
- // Workaround for ignored iframe height 100% in FF
- if (mxClient.IS_NS)
- {
- var handler = function(sender)
- {
- var h = wnd.div.offsetHeight;
- frame.setAttribute('height', (h-26)+'px');
- };
-
- wnd.addListener(mxEvent.RESIZE_END, handler);
- wnd.addListener(mxEvent.MAXIMIZE, handler);
- wnd.addListener(mxEvent.NORMALIZE, handler);
- wnd.addListener(mxEvent.SHOW, handler);
- }
-
- this.help = wnd;
- }
-
- this.help.setVisible(true);
-};
-
-/**
- * Function: showOutline
- *
- * Shows the outline window. If the window does not exist, then it is
- * created using an <mxOutline>.
- */
-mxEditor.prototype.showOutline = function ()
-{
- var create = this.outline == null;
-
- if (create)
- {
- var div = document.createElement('div');
- div.style.overflow = 'hidden';
- div.style.width = '100%';
- div.style.height = '100%';
- div.style.background = 'white';
- div.style.cursor = 'move';
-
- var wnd = new mxWindow(
- mxResources.get(this.outlineResource) ||
- this.outlineResource,
- div, 600, 480, 200, 200, false);
-
- // Creates the outline in the specified div
- // and links it to the existing graph
- var outline = new mxOutline(this.graph, div);
- wnd.setClosable(true);
- wnd.setResizable(true);
- wnd.destroyOnClose = false;
-
- wnd.addListener(mxEvent.RESIZE_END, function()
- {
- outline.update();
- });
-
- this.outline = wnd;
- this.outline.outline = outline;
- }
-
- // Finally shows the outline
- this.outline.setVisible(true);
- this.outline.outline.update(true);
-};
-
-/**
- * Function: setMode
- *
- * Puts the graph into the specified mode. The following modenames are
- * supported:
- *
- * select - Selects using the left mouse button, new connections
- * are disabled.
- * connect - Selects using the left mouse button or creates new
- * connections if mouse over cell hotspot. See <mxConnectionHandler>.
- * pan - Pans using the left mouse button, new connections are disabled.
- */
-mxEditor.prototype.setMode = function(modename)
-{
- if (modename == 'select')
- {
- this.graph.panningHandler.useLeftButtonForPanning = false;
- this.graph.setConnectable(false);
- }
- else if (modename == 'connect')
- {
- this.graph.panningHandler.useLeftButtonForPanning = false;
- this.graph.setConnectable(true);
- }
- else if (modename == 'pan')
- {
- this.graph.panningHandler.useLeftButtonForPanning = true;
- this.graph.setConnectable(false);
- }
-};
-
-/**
- * Function: createPopupMenu
- *
- * Uses <popupHandler> to create the menu in the graph's
- * panning handler. The redirection is setup in
- * <setToolbarContainer>.
- */
-mxEditor.prototype.createPopupMenu = function (menu, cell, evt)
-{
- this.popupHandler.createMenu(this, menu, cell, evt);
-};
-
-/**
- * Function: createEdge
- *
- * Uses <defaultEdge> as the prototype for creating new edges
- * in the connection handler of the graph. The style of the
- * edge will be overridden with the value returned by
- * <getEdgeStyle>.
- */
-mxEditor.prototype.createEdge = function (source, target)
-{
- // Clones the defaultedge prototype
- var e = null;
-
- if (this.defaultEdge != null)
- {
- var model = this.graph.getModel();
- e = model.cloneCell(this.defaultEdge);
- }
- else
- {
- e = new mxCell('');
- e.setEdge(true);
-
- var geo = new mxGeometry();
- geo.relative = true;
- e.setGeometry(geo);
- }
-
- // Overrides the edge style
- var style = this.getEdgeStyle();
-
- if (style != null)
- {
- e.setStyle(style);
- }
-
- return e;
-};
-
-/**
- * Function: getEdgeStyle
- *
- * Returns a string identifying the style of new edges.
- * The function is used in <createEdge> when new edges
- * are created in the graph.
- */
-mxEditor.prototype.getEdgeStyle = function ()
-{
- return this.defaultEdgeStyle;
-};
-
-/**
- * Function: consumeCycleAttribute
- *
- * Returns the next attribute in <cycleAttributeValues>
- * or null, if not attribute should be used in the
- * specified cell.
- */
-mxEditor.prototype.consumeCycleAttribute = function (cell)
-{
- return (this.cycleAttributeValues != null &&
- this.cycleAttributeValues.length > 0 &&
- this.graph.isSwimlane(cell)) ?
- this.cycleAttributeValues[this.cycleAttributeIndex++ %
- this.cycleAttributeValues.length] : null;
-};
-
-/**
- * Function: cycleAttribute
- *
- * Uses the returned value from <consumeCycleAttribute>
- * as the value for the <cycleAttributeName> key in
- * the given cell's style.
- */
-mxEditor.prototype.cycleAttribute = function (cell)
-{
- if (this.cycleAttributeName != null)
- {
- var value = this.consumeCycleAttribute(cell);
-
- if (value != null)
- {
- cell.setStyle(cell.getStyle()+';'+
- this.cycleAttributeName+'='+value);
- }
- }
-};
-
-/**
- * Function: addVertex
- *
- * Adds the given vertex as a child of parent at the specified
- * x and y coordinate and fires an <addVertex> event.
- */
-mxEditor.prototype.addVertex = function (parent, vertex, x, y)
-{
- var model = this.graph.getModel();
-
- while (parent != null && !this.graph.isValidDropTarget(parent))
- {
- parent = model.getParent(parent);
- }
-
- parent = (parent != null) ? parent : this.graph.getSwimlaneAt(x, y);
- var scale = this.graph.getView().scale;
-
- var geo = model.getGeometry(vertex);
- var pgeo = model.getGeometry(parent);
-
- if (this.graph.isSwimlane(vertex) &&
- !this.graph.swimlaneNesting)
- {
- parent = null;
- }
- else if (parent == null && this.swimlaneRequired)
- {
- return null;
- }
- else if (parent != null && pgeo != null)
- {
- // Keeps vertex inside parent
- var state = this.graph.getView().getState(parent);
-
- if (state != null)
- {
- x -= state.origin.x * scale;
- y -= state.origin.y * scale;
-
- if (this.graph.isConstrainedMoving)
- {
- var width = geo.width;
- var height = geo.height;
- var tmp = state.x+state.width;
-
- if (x+width > tmp)
- {
- x -= x+width - tmp;
- }
-
- tmp = state.y+state.height;
-
- if (y+height > tmp)
- {
- y -= y+height - tmp;
- }
- }
- }
- else if (pgeo != null)
- {
- x -= pgeo.x*scale;
- y -= pgeo.y*scale;
- }
- }
-
- geo = geo.clone();
- geo.x = this.graph.snap(x / scale -
- this.graph.getView().translate.x -
- this.graph.gridSize/2);
- geo.y = this.graph.snap(y / scale -
- this.graph.getView().translate.y -
- this.graph.gridSize/2);
- vertex.setGeometry(geo);
-
- if (parent == null)
- {
- parent = this.graph.getDefaultParent();
- }
-
- this.cycleAttribute(vertex);
- this.fireEvent(new mxEventObject(mxEvent.BEFORE_ADD_VERTEX,
- 'vertex', vertex, 'parent', parent));
-
- model.beginUpdate();
- try
- {
- vertex = this.graph.addCell(vertex, parent);
-
- if (vertex != null)
- {
- this.graph.constrainChild(vertex);
-
- this.fireEvent(new mxEventObject(mxEvent.ADD_VERTEX, 'vertex', vertex));
- }
- }
- finally
- {
- model.endUpdate();
- }
-
- if (vertex != null)
- {
- this.graph.setSelectionCell(vertex);
- this.graph.scrollCellToVisible(vertex);
- this.fireEvent(new mxEventObject(mxEvent.AFTER_ADD_VERTEX, 'vertex', vertex));
- }
-
- return vertex;
-};
-
-/**
- * Function: destroy
- *
- * Removes the editor and all its associated resources. This does not
- * normally need to be called, it is called automatically when the window
- * unloads.
- */
-mxEditor.prototype.destroy = function ()
-{
- if (!this.destroyed)
- {
- this.destroyed = true;
-
- if (this.tasks != null)
- {
- this.tasks.destroy();
- }
-
- if (this.outline != null)
- {
- this.outline.destroy();
- }
-
- if (this.properties != null)
- {
- this.properties.destroy();
- }
-
- if (this.keyHandler != null)
- {
- this.keyHandler.destroy();
- }
-
- if (this.rubberband != null)
- {
- this.rubberband.destroy();
- }
-
- if (this.toolbar != null)
- {
- this.toolbar.destroy();
- }
-
- if (this.graph != null)
- {
- this.graph.destroy();
- }
-
- this.status = null;
- this.templates = null;
- }
-};
diff --git a/src/js/handler/mxCellHighlight.js b/src/js/handler/mxCellHighlight.js
deleted file mode 100644
index f967f00..0000000
--- a/src/js/handler/mxCellHighlight.js
+++ /dev/null
@@ -1,271 +0,0 @@
-/**
- * $Id: mxCellHighlight.js,v 1.25 2012-09-27 14:43:40 boris Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCellHighlight
- *
- * A helper class to highlight cells. Here is an example for a given cell.
- *
- * (code)
- * var highlight = new mxCellHighlight(graph, '#ff0000', 2);
- * highlight.highlight(graph.view.getState(cell)));
- * (end)
- *
- * Constructor: mxCellHighlight
- *
- * Constructs a cell highlight.
- */
-function mxCellHighlight(graph, highlightColor, strokeWidth)
-{
- if (graph != null)
- {
- this.graph = graph;
- this.highlightColor = (highlightColor != null) ? highlightColor : mxConstants.DEFAULT_VALID_COLOR;
- this.strokeWidth = (strokeWidth != null) ? strokeWidth : mxConstants.HIGHLIGHT_STROKEWIDTH;
-
- // Updates the marker if the graph changes
- this.repaintHandler = mxUtils.bind(this, function()
- {
- this.repaint();
- });
-
- this.graph.getView().addListener(mxEvent.SCALE, this.repaintHandler);
- this.graph.getView().addListener(mxEvent.TRANSLATE, this.repaintHandler);
- this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, this.repaintHandler);
- this.graph.getModel().addListener(mxEvent.CHANGE, this.repaintHandler);
-
- // Hides the marker if the current root changes
- this.resetHandler = mxUtils.bind(this, function()
- {
- this.hide();
- });
-
- this.graph.getView().addListener(mxEvent.DOWN, this.resetHandler);
- this.graph.getView().addListener(mxEvent.UP, this.resetHandler);
- }
-};
-
-/**
- * Variable: keepOnTop
- *
- * Specifies if the highlights should appear on top of everything
- * else in the overlay pane. Default is false.
- */
-mxCellHighlight.prototype.keepOnTop = false;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxCellHighlight.prototype.graph = true;
-
-/**
- * Variable: state
- *
- * Reference to the <mxCellState>.
- */
-mxCellHighlight.prototype.state = null;
-
-/**
- * Variable: spacing
- *
- * Specifies the spacing between the highlight for vertices and the vertex.
- * Default is 2.
- */
-mxCellHighlight.prototype.spacing = 2;
-
-/**
- * Variable: resetHandler
- *
- * Holds the handler that automatically invokes reset if the highlight
- * should be hidden.
- */
-mxCellHighlight.prototype.resetHandler = null;
-
-/**
- * Function: setHighlightColor
- *
- * Sets the color of the rectangle used to highlight drop targets.
- *
- * Parameters:
- *
- * color - String that represents the new highlight color.
- */
-mxCellHighlight.prototype.setHighlightColor = function(color)
-{
- this.highlightColor = color;
-
- if (this.shape != null)
- {
- if (this.shape.dialect == mxConstants.DIALECT_SVG)
- {
- this.shape.innerNode.setAttribute('stroke', color);
- }
- else if (this.shape.dialect == mxConstants.DIALECT_VML)
- {
- this.shape.node.strokecolor = color;
- }
- }
-};
-
-/**
- * Function: drawHighlight
- *
- * Creates and returns the highlight shape for the given state.
- */
-mxCellHighlight.prototype.drawHighlight = function()
-{
- this.shape = this.createShape();
- this.repaint();
-
- if (!this.keepOnTop && this.shape.node.parentNode.firstChild != this.shape.node)
- {
- this.shape.node.parentNode.insertBefore(this.shape.node, this.shape.node.parentNode.firstChild);
- }
-
- // Workaround to force a repaint in AppleWebKit
- if (this.graph.model.isEdge(this.state.cell))
- {
- mxUtils.repaintGraph(this.graph, this.shape.points[0]);
- }
-};
-
-/**
- * Function: createShape
- *
- * Creates and returns the highlight shape for the given state.
- */
-mxCellHighlight.prototype.createShape = function()
-{
- var shape = null;
-
- if (this.graph.model.isEdge(this.state.cell))
- {
- shape = new mxPolyline(this.state.absolutePoints,
- this.highlightColor, this.strokeWidth);
- }
- else
- {
- shape = new mxRectangleShape( new mxRectangle(),
- null, this.highlightColor, this.strokeWidth);
- }
-
- shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- shape.init(this.graph.getView().getOverlayPane());
- mxEvent.redirectMouseEvents(shape.node, this.graph, this.state);
-
- return shape;
-};
-
-
-/**
- * Function: repaint
- *
- * Updates the highlight after a change of the model or view.
- */
-mxCellHighlight.prototype.repaint = function()
-{
- if (this.state != null && this.shape != null)
- {
- if (this.graph.model.isEdge(this.state.cell))
- {
- this.shape.points = this.state.absolutePoints;
- }
- else
- {
- this.shape.bounds = new mxRectangle(this.state.x - this.spacing, this.state.y - this.spacing,
- this.state.width + 2 * this.spacing, this.state.height + 2 * this.spacing);
- }
-
- // Uses cursor from shape in highlight
- if (this.state.shape != null)
- {
- this.shape.setCursor(this.state.shape.getCursor());
- }
-
- var alpha = (!this.graph.model.isEdge(this.state.cell)) ? Number(this.state.style[mxConstants.STYLE_ROTATION] || '0') : 0;
-
- // Event-transparency
- if (this.shape.dialect == mxConstants.DIALECT_SVG)
- {
- this.shape.node.setAttribute('style', 'pointer-events:none;');
-
- if (alpha != 0)
- {
- var cx = this.state.getCenterX();
- var cy = this.state.getCenterY();
- var transform = 'rotate(' + alpha + ' ' + cx + ' ' + cy + ')';
-
- this.shape.node.setAttribute('transform', transform);
- }
- }
- else
- {
- this.shape.node.style.background = '';
-
- if (alpha != 0)
- {
- this.shape.node.rotation = alpha;
- }
- }
-
- this.shape.redraw();
- }
-};
-
-/**
- * Function: hide
- *
- * Resets the state of the cell marker.
- */
-mxCellHighlight.prototype.hide = function()
-{
- this.highlight(null);
-};
-
-/**
- * Function: mark
- *
- * Marks the <markedState> and fires a <mark> event.
- */
-mxCellHighlight.prototype.highlight = function(state)
-{
- if (this.state != state)
- {
- if (this.shape != null)
- {
- this.shape.destroy();
- this.shape = null;
- }
-
- this.state = state;
-
- if (this.state != null)
- {
- this.drawHighlight();
- }
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes.
- */
-mxCellHighlight.prototype.destroy = function()
-{
- this.graph.getView().removeListener(this.repaintHandler);
- this.graph.getModel().removeListener(this.repaintHandler);
-
- this.graph.getView().removeListener(this.resetHandler);
- this.graph.getModel().removeListener(this.resetHandler);
-
- if (this.shape != null)
- {
- this.shape.destroy();
- this.shape = null;
- }
-};
diff --git a/src/js/handler/mxCellMarker.js b/src/js/handler/mxCellMarker.js
deleted file mode 100644
index b336278..0000000
--- a/src/js/handler/mxCellMarker.js
+++ /dev/null
@@ -1,419 +0,0 @@
-/**
- * $Id: mxCellMarker.js,v 1.30 2011-07-15 12:57:50 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCellMarker
- *
- * A helper class to process mouse locations and highlight cells.
- *
- * Helper class to highlight cells. To add a cell marker to an existing graph
- * for highlighting all cells, the following code is used:
- *
- * (code)
- * var marker = new mxCellMarker(graph);
- * graph.addMouseListener({
- * mouseDown: function() {},
- * mouseMove: function(sender, me)
- * {
- * marker.process(me);
- * },
- * mouseUp: function() {}
- * });
- * (end)
- *
- * Event: mxEvent.MARK
- *
- * Fires after a cell has been marked or unmarked. The <code>state</code>
- * property contains the marked <mxCellState> or null if no state is marked.
- *
- * Constructor: mxCellMarker
- *
- * Constructs a new cell marker.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * validColor - Optional marker color for valid states. Default is
- * <mxConstants.DEFAULT_VALID_COLOR>.
- * invalidColor - Optional marker color for invalid states. Default is
- * <mxConstants.DEFAULT_INVALID_COLOR>.
- * hotspot - Portion of the width and hight where a state intersects a
- * given coordinate pair. A value of 0 means always highlight. Default is
- * <mxConstants.DEFAULT_HOTSPOT>.
- */
-function mxCellMarker(graph, validColor, invalidColor, hotspot)
-{
- if (graph != null)
- {
- this.graph = graph;
- this.validColor = (validColor != null) ? validColor : mxConstants.DEFAULT_VALID_COLOR;
- this.invalidColor = (validColor != null) ? invalidColor : mxConstants.DEFAULT_INVALID_COLOR;
- this.hotspot = (hotspot != null) ? hotspot : mxConstants.DEFAULT_HOTSPOT;
-
- this.highlight = new mxCellHighlight(graph);
- }
-};
-
-/**
- * Extends mxEventSource.
- */
-mxCellMarker.prototype = new mxEventSource();
-mxCellMarker.prototype.constructor = mxCellMarker;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxCellMarker.prototype.graph = null;
-
-/**
- * Variable: enabled
- *
- * Specifies if the marker is enabled. Default is true.
- */
-mxCellMarker.prototype.enabled = true;
-
-/**
- * Variable: hotspot
- *
- * Specifies the portion of the width and height that should trigger
- * a highlight. The area around the center of the cell to be marked is used
- * as the hotspot. Possible values are between 0 and 1. Default is
- * mxConstants.DEFAULT_HOTSPOT.
- */
-mxCellMarker.prototype.hotspot = mxConstants.DEFAULT_HOTSPOT;
-
-/**
- * Variable: hotspotEnabled
- *
- * Specifies if the hotspot is enabled. Default is false.
- */
-mxCellMarker.prototype.hotspotEnabled = false;
-
-/**
- * Variable: validColor
- *
- * Holds the valid marker color.
- */
-mxCellMarker.prototype.validColor = null;
-
-/**
- * Variable: invalidColor
- *
- * Holds the invalid marker color.
- */
-mxCellMarker.prototype.invalidColor = null;
-
-/**
- * Variable: currentColor
- *
- * Holds the current marker color.
- */
-mxCellMarker.prototype.currentColor = null;
-
-/**
- * Variable: validState
- *
- * Holds the marked <mxCellState> if it is valid.
- */
-mxCellMarker.prototype.validState = null;
-
-/**
- * Variable: markedState
- *
- * Holds the marked <mxCellState>.
- */
-mxCellMarker.prototype.markedState = null;
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxCellMarker.prototype.setEnabled = function(enabled)
-{
- this.enabled = enabled;
-};
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxCellMarker.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setHotspot
- *
- * Sets the <hotspot>.
- */
-mxCellMarker.prototype.setHotspot = function(hotspot)
-{
- this.hotspot = hotspot;
-};
-
-/**
- * Function: getHotspot
- *
- * Returns the <hotspot>.
- */
-mxCellMarker.prototype.getHotspot = function()
-{
- return this.hotspot;
-};
-
-/**
- * Function: setHotspotEnabled
- *
- * Specifies whether the hotspot should be used in <intersects>.
- */
-mxCellMarker.prototype.setHotspotEnabled = function(enabled)
-{
- this.hotspotEnabled = enabled;
-};
-
-/**
- * Function: isHotspotEnabled
- *
- * Returns true if hotspot is used in <intersects>.
- */
-mxCellMarker.prototype.isHotspotEnabled = function()
-{
- return this.hotspotEnabled;
-};
-
-/**
- * Function: hasValidState
- *
- * Returns true if <validState> is not null.
- */
-mxCellMarker.prototype.hasValidState = function()
-{
- return this.validState != null;
-};
-
-/**
- * Function: getValidState
- *
- * Returns the <validState>.
- */
-mxCellMarker.prototype.getValidState = function()
-{
- return this.validState;
-};
-
-/**
- * Function: getMarkedState
- *
- * Returns the <markedState>.
- */
-mxCellMarker.prototype.getMarkedState = function()
-{
- return this.markedState;
-};
-
-/**
- * Function: reset
- *
- * Resets the state of the cell marker.
- */
-mxCellMarker.prototype.reset = function()
-{
- this.validState = null;
-
- if (this.markedState != null)
- {
- this.markedState = null;
- this.unmark();
- }
-};
-
-/**
- * Function: process
- *
- * Processes the given event and cell and marks the state returned by
- * <getState> with the color returned by <getMarkerColor>. If the
- * markerColor is not null, then the state is stored in <markedState>. If
- * <isValidState> returns true, then the state is stored in <validState>
- * regardless of the marker color. The state is returned regardless of the
- * marker color and valid state.
- */
-mxCellMarker.prototype.process = function(me)
-{
- var state = null;
-
- if (this.isEnabled())
- {
- state = this.getState(me);
- var isValid = (state != null) ? this.isValidState(state) : false;
- var color = this.getMarkerColor(me.getEvent(), state, isValid);
-
- if (isValid)
- {
- this.validState = state;
- }
- else
- {
- this.validState = null;
- }
-
- if (state != this.markedState || color != this.currentColor)
- {
- this.currentColor = color;
-
- if (state != null && this.currentColor != null)
- {
- this.markedState = state;
- this.mark();
- }
- else if (this.markedState != null)
- {
- this.markedState = null;
- this.unmark();
- }
- }
- }
-
- return state;
-};
-
-/**
- * Function: markCell
- *
- * Marks the given cell using the given color, or <validColor> if no color is specified.
- */
-mxCellMarker.prototype.markCell = function(cell, color)
-{
- var state = this.graph.getView().getState(cell);
-
- if (state != null)
- {
- this.currentColor = (color != null) ? color : this.validColor;
- this.markedState = state;
- this.mark();
- }
-};
-
-/**
- * Function: mark
- *
- * Marks the <markedState> and fires a <mark> event.
- */
-mxCellMarker.prototype.mark = function()
-{
- this.highlight.setHighlightColor(this.currentColor);
- this.highlight.highlight(this.markedState);
- this.fireEvent(new mxEventObject(mxEvent.MARK, 'state', this.markedState));
-};
-
-/**
- * Function: unmark
- *
- * Hides the marker and fires a <mark> event.
- */
-mxCellMarker.prototype.unmark = function()
-{
- this.mark();
-};
-
-/**
- * Function: isValidState
- *
- * Returns true if the given <mxCellState> is a valid state. If this
- * returns true, then the state is stored in <validState>. The return value
- * of this method is used as the argument for <getMarkerColor>.
- */
-mxCellMarker.prototype.isValidState = function(state)
-{
- return true;
-};
-
-/**
- * Function: getMarkerColor
- *
- * Returns the valid- or invalidColor depending on the value of isValid.
- * The given <mxCellState> is ignored by this implementation.
- */
-mxCellMarker.prototype.getMarkerColor = function(evt, state, isValid)
-{
- return (isValid) ? this.validColor : this.invalidColor;
-};
-
-/**
- * Function: getState
- *
- * Uses <getCell>, <getStateToMark> and <intersects> to return the
- * <mxCellState> for the given <mxMouseEvent>.
- */
-mxCellMarker.prototype.getState = function(me)
-{
- var view = this.graph.getView();
- cell = this.getCell(me);
- var state = this.getStateToMark(view.getState(cell));
-
- return (state != null && this.intersects(state, me)) ? state : null;
-};
-
-/**
- * Function: getCell
- *
- * Returns the <mxCell> for the given event and cell. This returns the
- * given cell.
- */
-mxCellMarker.prototype.getCell = function(me)
-{
- return me.getCell();
-};
-
-/**
- * Function: getStateToMark
- *
- * Returns the <mxCellState> to be marked for the given <mxCellState> under
- * the mouse. This returns the given state.
- */
-mxCellMarker.prototype.getStateToMark = function(state)
-{
- return state;
-};
-
-/**
- * Function: intersects
- *
- * Returns true if the given coordinate pair intersects the given state.
- * This returns true if the <hotspot> is 0 or the coordinates are inside
- * the hotspot for the given cell state.
- */
-mxCellMarker.prototype.intersects = function(state, me)
-{
- if (this.hotspotEnabled)
- {
- return mxUtils.intersectsHotspot(state, me.getGraphX(), me.getGraphY(),
- this.hotspot, mxConstants.MIN_HOTSPOT_SIZE,
- mxConstants.MAX_HOTSPOT_SIZE);
- }
-
- return true;
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes.
- */
-mxCellMarker.prototype.destroy = function()
-{
- this.graph.getView().removeListener(this.resetHandler);
- this.graph.getModel().removeListener(this.resetHandler);
- this.highlight.destroy();
-};
diff --git a/src/js/handler/mxCellTracker.js b/src/js/handler/mxCellTracker.js
deleted file mode 100644
index 5adcd6a..0000000
--- a/src/js/handler/mxCellTracker.js
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * $Id: mxCellTracker.js,v 1.9 2011-08-28 09:49:46 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCellTracker
- *
- * Event handler that highlights cells. Inherits from <mxCellMarker>.
- *
- * Example:
- *
- * (code)
- * new mxCellTracker(graph, '#00FF00');
- * (end)
- *
- * For detecting dragEnter, dragOver and dragLeave on cells, the following
- * code can be used:
- *
- * (code)
- * graph.addMouseListener(
- * {
- * cell: null,
- * mouseDown: function(sender, me) { },
- * mouseMove: function(sender, me)
- * {
- * var tmp = me.getCell();
- *
- * if (tmp != this.cell)
- * {
- * if (this.cell != null)
- * {
- * this.dragLeave(me.getEvent(), this.cell);
- * }
- *
- * this.cell = tmp;
- *
- * if (this.cell != null)
- * {
- * this.dragEnter(me.getEvent(), this.cell);
- * }
- * }
- *
- * if (this.cell != null)
- * {
- * this.dragOver(me.getEvent(), this.cell);
- * }
- * },
- * mouseUp: function(sender, me) { },
- * dragEnter: function(evt, cell)
- * {
- * mxLog.debug('dragEnter', cell.value);
- * },
- * dragOver: function(evt, cell)
- * {
- * mxLog.debug('dragOver', cell.value);
- * },
- * dragLeave: function(evt, cell)
- * {
- * mxLog.debug('dragLeave', cell.value);
- * }
- * });
- * (end)
- *
- * Constructor: mxCellTracker
- *
- * Constructs an event handler that highlights cells.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * color - Color of the highlight. Default is blue.
- * funct - Optional JavaScript function that is used to override
- * <mxCellMarker.getCell>.
- */
-function mxCellTracker(graph, color, funct)
-{
- mxCellMarker.call(this, graph, color);
-
- this.graph.addMouseListener(this);
-
- if (funct != null)
- {
- this.getCell = funct;
- }
-
- // Automatic deallocation of memory
- if (mxClient.IS_IE)
- {
- mxEvent.addListener(window, 'unload', mxUtils.bind(this, function()
- {
- this.destroy();
- }));
- }
-};
-
-/**
- * Extends mxCellMarker.
- */
-mxCellTracker.prototype = new mxCellMarker();
-mxCellTracker.prototype.constructor = mxCellTracker;
-
-/**
- * Function: mouseDown
- *
- * Ignores the event. The event is not consumed.
- */
-mxCellTracker.prototype.mouseDown = function(sender, me) { };
-
-/**
- * Function: mouseMove
- *
- * Handles the event by highlighting the cell under the mousepointer if it
- * is over the hotspot region of the cell.
- */
-mxCellTracker.prototype.mouseMove = function(sender, me)
-{
- if (this.isEnabled())
- {
- this.process(me);
- }
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event by reseting the highlight.
- */
-mxCellTracker.prototype.mouseUp = function(sender, me)
-{
- this.reset();
-};
-
-/**
- * Function: destroy
- *
- * Destroys the object and all its resources and DOM nodes. This doesn't
- * normally need to be called. It is called automatically when the window
- * unloads.
- */
-mxCellTracker.prototype.destroy = function()
-{
- if (!this.destroyed)
- {
- this.destroyed = true;
-
- this.graph.removeMouseListener(this);
- mxCellMarker.prototype.destroy.apply(this);
- }
-};
diff --git a/src/js/handler/mxConnectionHandler.js b/src/js/handler/mxConnectionHandler.js
deleted file mode 100644
index 07daaf8..0000000
--- a/src/js/handler/mxConnectionHandler.js
+++ /dev/null
@@ -1,1969 +0,0 @@
-/**
- * $Id: mxConnectionHandler.js,v 1.216 2012-12-07 15:17:37 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxConnectionHandler
- *
- * Graph event handler that creates new connections. Uses <mxTerminalMarker>
- * for finding and highlighting the source and target vertices and
- * <factoryMethod> to create the edge instance. This handler is built-into
- * <mxGraph.connectionHandler> and enabled using <mxGraph.setConnectable>.
- *
- * Example:
- *
- * (code)
- * new mxConnectionHandler(graph, function(source, target, style)
- * {
- * edge = new mxCell('', new mxGeometry());
- * edge.setEdge(true);
- * edge.setStyle(style);
- * edge.geometry.relative = true;
- * return edge;
- * });
- * (end)
- *
- * Here is an alternative solution that just sets a specific user object for
- * new edges by overriding <insertEdge>.
- *
- * (code)
- * mxConnectionHandlerInsertEdge = mxConnectionHandler.prototype.insertEdge;
- * mxConnectionHandler.prototype.insertEdge = function(parent, id, value, source, target, style)
- * {
- * value = 'Test';
- *
- * return mxConnectionHandlerInsertEdge.apply(this, arguments);
- * };
- * (end)
- *
- * Using images to trigger connections:
- *
- * This handler uses mxTerminalMarker to find the source and target cell for
- * the new connection and creates a new edge using <connect>. The new edge is
- * created using <createEdge> which in turn uses <factoryMethod> or creates a
- * new default edge.
- *
- * The handler uses a "highlight-paradigm" for indicating if a cell is being
- * used as a source or target terminal, as seen in MS Visio and other products.
- * In order to allow both, moving and connecting cells at the same time,
- * <mxConstants.DEFAULT_HOTSPOT> is used in the handler to determine the hotspot
- * of a cell, that is, the region of the cell which is used to trigger a new
- * connection. The constant is a value between 0 and 1 that specifies the
- * amount of the width and height around the center to be used for the hotspot
- * of a cell and its default value is 0.5. In addition,
- * <mxConstants.MIN_HOTSPOT_SIZE> defines the minimum number of pixels for the
- * width and height of the hotspot.
- *
- * This solution, while standards compliant, may be somewhat confusing because
- * there is no visual indicator for the hotspot and the highlight is seen to
- * switch on and off while the mouse is being moved in and out. Furthermore,
- * this paradigm does not allow to create different connections depending on
- * the highlighted hotspot as there is only one hotspot per cell and it
- * normally does not allow cells to be moved and connected at the same time as
- * there is no clear indication of the connectable area of the cell.
- *
- * To come across these issues, the handle has an additional <createIcons> hook
- * with a default implementation that allows to create one icon to be used to
- * trigger new connections. If this icon is specified, then new connections can
- * only be created if the image is clicked while the cell is being highlighted.
- * The <createIcons> hook may be overridden to create more than one
- * <mxImageShape> for creating new connections, but the default implementation
- * supports one image and is used as follows:
- *
- * In order to display the "connect image" whenever the mouse is over the cell,
- * an DEFAULT_HOTSPOT of 1 should be used:
- *
- * (code)
- * mxConstants.DEFAULT_HOTSPOT = 1;
- * (end)
- *
- * In order to avoid confusion with the highlighting, the highlight color
- * should not be used with a connect image:
- *
- * (code)
- * mxConstants.HIGHLIGHT_COLOR = null;
- * (end)
- *
- * To install the image, the connectImage field of the mxConnectionHandler must
- * be assigned a new <mxImage> instance:
- *
- * (code)
- * mxConnectionHandler.prototype.connectImage = new mxImage('images/green-dot.gif', 14, 14);
- * (end)
- *
- * This will use the green-dot.gif with a width and height of 14 pixels as the
- * image to trigger new connections. In createIcons the icon field of the
- * handler will be set in order to remember the icon that has been clicked for
- * creating the new connection. This field will be available under selectedIcon
- * in the connect method, which may be overridden to take the icon that
- * triggered the new connection into account. This is useful if more than one
- * icon may be used to create a connection.
- *
- * Group: Events
- *
- * Event: mxEvent.START
- *
- * Fires when a new connection is being created by the user. The <code>state</code>
- * property contains the state of the source cell.
- *
- * Event: mxEvent.CONNECT
- *
- * Fires between begin- and endUpdate in <connect>. The <code>cell</code>
- * property contains the inserted edge, the <code>event</code> and <code>target</code>
- * properties contain the respective arguments that were passed to <connect> (where
- * target corresponds to the dropTarget argument).
- *
- * Note that the target is the cell under the mouse where the mouse button was released.
- * Depending on the logic in the handler, this doesn't necessarily have to be the target
- * of the inserted edge. To print the source, target or any optional ports IDs that the
- * edge is connected to, the following code can be used. To get more details about the
- * actual connection point, <mxGraph.getConnectionConstraint> can be used. To resolve
- * the port IDs, use <mxGraphModel.getCell>.
- *
- * (code)
- * graph.connectionHandler.addListener(mxEvent.CONNECT, function(sender, evt)
- * {
- * var edge = evt.getProperty('cell');
- * var source = graph.getModel().getTerminal(edge, true);
- * var target = graph.getModel().getTerminal(edge, false);
- *
- * var style = graph.getCellStyle(edge);
- * var sourcePortId = style[mxConstants.STYLE_SOURCE_PORT];
- * var targetPortId = style[mxConstants.STYLE_TARGET_PORT];
- *
- * mxLog.show();
- * mxLog.debug('connect', edge, source.id, target.id, sourcePortId, targetPortId);
- * });
- * (end)
- *
- * Event: mxEvent.RESET
- *
- * Fires when the <reset> method is invoked.
- *
- * Constructor: mxConnectionHandler
- *
- * Constructs an event handler that connects vertices using the specified
- * factory method to create the new edges. Modify
- * <mxConstants.ACTIVE_REGION> to setup the region on a cell which triggers
- * the creation of a new connection or use connect icons as explained
- * above.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * factoryMethod - Optional function to create the edge. The function takes
- * the source and target <mxCell> as the first and second argument and an
- * optional cell style from the preview as the third argument. It returns
- * the <mxCell> that represents the new edge.
- */
-function mxConnectionHandler(graph, factoryMethod)
-{
- if (graph != null)
- {
- this.graph = graph;
- this.factoryMethod = factoryMethod;
- this.init();
- }
-};
-
-/**
- * Extends mxEventSource.
- */
-mxConnectionHandler.prototype = new mxEventSource();
-mxConnectionHandler.prototype.constructor = mxConnectionHandler;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxConnectionHandler.prototype.graph = null;
-
-/**
- * Variable: factoryMethod
- *
- * Function that is used for creating new edges. The function takes the
- * source and target <mxCell> as the first and second argument and returns
- * a new <mxCell> that represents the edge. This is used in <createEdge>.
- */
-mxConnectionHandler.prototype.factoryMethod = true;
-
-/**
- * Variable: moveIconFront
- *
- * Specifies if icons should be displayed inside the graph container instead
- * of the overlay pane. This is used for HTML labels on vertices which hide
- * the connect icon. This has precendence over <moveIconBack> when set
- * to true. Default is false.
- */
-mxConnectionHandler.prototype.moveIconFront = false;
-
-/**
- * Variable: moveIconBack
- *
- * Specifies if icons should be moved to the back of the overlay pane. This can
- * be set to true if the icons of the connection handler conflict with other
- * handles, such as the vertex label move handle. Default is false.
- */
-mxConnectionHandler.prototype.moveIconBack = false;
-
-/**
- * Variable: connectImage
- *
- * <mxImage> that is used to trigger the creation of a new connection. This
- * is used in <createIcons>. Default is null.
- */
-mxConnectionHandler.prototype.connectImage = null;
-
-/**
- * Variable: targetConnectImage
- *
- * Specifies if the connect icon should be centered on the target state
- * while connections are being previewed. Default is false.
- */
-mxConnectionHandler.prototype.targetConnectImage = false;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxConnectionHandler.prototype.enabled = true;
-
-/**
- * Variable: select
- *
- * Specifies if new edges should be selected. Default is true.
- */
-mxConnectionHandler.prototype.select = true;
-
-/**
- * Variable: createTarget
- *
- * Specifies if <createTargetVertex> should be called if no target was under the
- * mouse for the new connection. Setting this to true means the connection
- * will be drawn as valid if no target is under the mouse, and
- * <createTargetVertex> will be called before the connection is created between
- * the source cell and the newly created vertex in <createTargetVertex>, which
- * can be overridden to create a new target. Default is false.
- */
-mxConnectionHandler.prototype.createTarget = false;
-
-/**
- * Variable: marker
- *
- * Holds the <mxTerminalMarker> used for finding source and target cells.
- */
-mxConnectionHandler.prototype.marker = null;
-
-/**
- * Variable: constraintHandler
- *
- * Holds the <mxConstraintHandler> used for drawing and highlighting
- * constraints.
- */
-mxConnectionHandler.prototype.constraintHandler = null;
-
-/**
- * Variable: error
- *
- * Holds the current validation error while connections are being created.
- */
-mxConnectionHandler.prototype.error = null;
-
-/**
- * Variable: waypointsEnabled
- *
- * Specifies if single clicks should add waypoints on the new edge. Default is
- * false.
- */
-mxConnectionHandler.prototype.waypointsEnabled = false;
-
-/**
- * Variable: tapAndHoldEnabled
- *
- * Specifies if tap and hold should be used for starting connections on touch-based
- * devices. Default is true.
- */
-mxConnectionHandler.prototype.tapAndHoldEnabled = true;
-
-/**
- * Variable: tapAndHoldDelay
- *
- * Specifies the time for a tap and hold. Default is 500 ms.
- */
-mxConnectionHandler.prototype.tapAndHoldDelay = 500;
-
-/**
- * Variable: tapAndHoldInProgress
- *
- * True if the timer for tap and hold events is running.
- */
-mxConnectionHandler.prototype.tapAndHoldInProgress = false;
-
-/**
- * Variable: tapAndHoldValid
- *
- * True as long as the timer is running and the touch events
- * stay within the given <tapAndHoldTolerance>.
- */
-mxConnectionHandler.prototype.tapAndHoldValid = false;
-
-/**
- * Variable: tapAndHoldTolerance
- *
- * Specifies the tolerance for a tap and hold. Default is 4 pixels.
- */
-mxConnectionHandler.prototype.tapAndHoldTolerance = 4;
-
-/**
- * Variable: initialTouchX
- *
- * Holds the x-coordinate of the intial touch event for tap and hold.
- */
-mxConnectionHandler.prototype.initialTouchX = 0;
-
-/**
- * Variable: initialTouchY
- *
- * Holds the y-coordinate of the intial touch event for tap and hold.
- */
-mxConnectionHandler.prototype.initialTouchY = 0;
-
-/**
- * Variable: ignoreMouseDown
- *
- * Specifies if the connection handler should ignore the state of the mouse
- * button when highlighting the source. Default is false, that is, the
- * handler only highlights the source if no button is being pressed.
- */
-mxConnectionHandler.prototype.ignoreMouseDown = false;
-
-/**
- * Variable: first
- *
- * Holds the <mxPoint> where the mouseDown took place while the handler is
- * active.
- */
-mxConnectionHandler.prototype.first = null;
-
-/**
- * Variable: connectIconOffset
- *
- * Holds the offset for connect icons during connection preview.
- * Default is mxPoint(0, <mxConstants.TOOLTIP_VERTICAL_OFFSET>).
- * Note that placing the icon under the mouse pointer with an
- * offset of (0,0) will affect hit detection.
- */
-mxConnectionHandler.prototype.connectIconOffset = new mxPoint(0, mxConstants.TOOLTIP_VERTICAL_OFFSET);
-
-/**
- * Variable: edgeState
- *
- * Optional <mxCellState> that represents the preview edge while the
- * handler is active. This is created in <createEdgeState>.
- */
-mxConnectionHandler.prototype.edgeState = null;
-
-/**
- * Variable: changeHandler
- *
- * Holds the change event listener for later removal.
- */
-mxConnectionHandler.prototype.changeHandler = null;
-
-/**
- * Variable: drillHandler
- *
- * Holds the drill event listener for later removal.
- */
-mxConnectionHandler.prototype.drillHandler = null;
-
-/**
- * Variable: mouseDownCounter
- *
- * Counts the number of mouseDown events since the start. The initial mouse
- * down event counts as 1.
- */
-mxConnectionHandler.prototype.mouseDownCounter = 0;
-
-/**
- * Variable: movePreviewAway
- *
- * Switch to enable moving the preview away from the mousepointer. This is required in browsers
- * where the preview cannot be made transparent to events and if the built-in hit detection on
- * the HTML elements in the page should be used. Default is the value of <mxClient.IS_VML>.
- */
-mxConnectionHandler.prototype.movePreviewAway = mxClient.IS_VML;
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxConnectionHandler.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxConnectionHandler.prototype.setEnabled = function(enabled)
-{
- this.enabled = enabled;
-};
-
-/**
- * Function: isCreateTarget
- *
- * Returns <createTarget>.
- */
-mxConnectionHandler.prototype.isCreateTarget = function()
-{
- return this.createTarget;
-};
-
-/**
- * Function: setCreateTarget
- *
- * Sets <createTarget>.
- */
-mxConnectionHandler.prototype.setCreateTarget = function(value)
-{
- this.createTarget = value;
-};
-
-/**
- * Function: createShape
- *
- * Creates the preview shape for new connections.
- */
-mxConnectionHandler.prototype.createShape = function()
-{
- // Creates the edge preview
- var shape = new mxPolyline([], mxConstants.INVALID_COLOR);
- shape.isDashed = true;
- shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- shape.init(this.graph.getView().getOverlayPane());
-
- // Event-transparency
- if (this.graph.dialect == mxConstants.DIALECT_SVG)
- {
- // Sets event transparency on the internal shapes that represent
- // the actual dashed line on the screen
- shape.pipe.setAttribute('style', 'pointer-events:none;');
- shape.innerNode.setAttribute('style', 'pointer-events:none;');
- }
- else
- {
- // Workaround no event transparency for preview in IE
- // FIXME: 3,3 pixel offset for custom hit detection in IE
- var getState = mxUtils.bind(this, function(evt)
- {
- var pt = mxUtils.convertPoint(this.graph.container, mxEvent.getClientX(evt), mxEvent.getClientY(evt));
-
- return this.graph.view.getState(this.graph.getCellAt(pt.x, pt.y));
- });
-
- // Redirects events on the shape to the graph
- mxEvent.redirectMouseEvents(shape.node, this.graph, getState);
- }
-
- return shape;
-};
-
-/**
- * Function: init
- *
- * Initializes the shapes required for this connection handler. This should
- * be invoked if <mxGraph.container> is assigned after the connection
- * handler has been created.
- */
-mxConnectionHandler.prototype.init = function()
-{
- this.graph.addMouseListener(this);
- this.marker = this.createMarker();
- this.constraintHandler = new mxConstraintHandler(this.graph);
-
- // Redraws the icons if the graph changes
- this.changeHandler = mxUtils.bind(this, function(sender)
- {
- if (this.iconState != null)
- {
- this.iconState = this.graph.getView().getState(this.iconState.cell);
- }
-
- if (this.iconState != null)
- {
- this.redrawIcons(this.icons, this.iconState);
- }
- else
- {
- this.destroyIcons(this.icons);
- this.previous = null;
- }
-
- this.constraintHandler.reset();
- });
-
- this.graph.getModel().addListener(mxEvent.CHANGE, this.changeHandler);
- this.graph.getView().addListener(mxEvent.SCALE, this.changeHandler);
- this.graph.getView().addListener(mxEvent.TRANSLATE, this.changeHandler);
- this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, this.changeHandler);
-
- // Removes the icon if we step into/up or start editing
- this.drillHandler = mxUtils.bind(this, function(sender)
- {
- this.destroyIcons(this.icons);
- });
-
- this.graph.addListener(mxEvent.START_EDITING, this.drillHandler);
- this.graph.getView().addListener(mxEvent.DOWN, this.drillHandler);
- this.graph.getView().addListener(mxEvent.UP, this.drillHandler);
-};
-
-/**
- * Function: isConnectableCell
- *
- * Returns true if the given cell is connectable. This is a hook to
- * disable floating connections. This implementation returns true.
- */
-mxConnectionHandler.prototype.isConnectableCell = function(cell)
-{
- return true;
-};
-
-/**
- * Function: createMarker
- *
- * Creates and returns the <mxCellMarker> used in <marker>.
- */
-mxConnectionHandler.prototype.createMarker = function()
-{
- var marker = new mxCellMarker(this.graph);
- marker.hotspotEnabled = true;
-
- // Overrides to return cell at location only if valid (so that
- // there is no highlight for invalid cells)
- marker.getCell = mxUtils.bind(this, function(evt, cell)
- {
- var cell = mxCellMarker.prototype.getCell.apply(marker, arguments);
- this.error = null;
-
- if (!this.isConnectableCell(cell))
- {
- return null;
- }
-
- if (cell != null)
- {
- if (this.isConnecting())
- {
- if (this.previous != null)
- {
- this.error = this.validateConnection(this.previous.cell, cell);
-
- if (this.error != null && this.error.length == 0)
- {
- cell = null;
-
- // Enables create target inside groups
- if (this.isCreateTarget())
- {
- this.error = null;
- }
- }
- }
- }
- else if (!this.isValidSource(cell))
- {
- cell = null;
- }
- }
- else if (this.isConnecting() && !this.isCreateTarget() &&
- !this.graph.allowDanglingEdges)
- {
- this.error = '';
- }
-
- return cell;
- });
-
- // Sets the highlight color according to validateConnection
- marker.isValidState = mxUtils.bind(this, function(state)
- {
- if (this.isConnecting())
- {
- return this.error == null;
- }
- else
- {
- return mxCellMarker.prototype.isValidState.apply(marker, arguments);
- }
- });
-
- // Overrides to use marker color only in highlight mode or for
- // target selection
- marker.getMarkerColor = mxUtils.bind(this, function(evt, state, isValid)
- {
- return (this.connectImage == null || this.isConnecting()) ?
- mxCellMarker.prototype.getMarkerColor.apply(marker, arguments) :
- null;
- });
-
- // Overrides to use hotspot only for source selection otherwise
- // intersects always returns true when over a cell
- marker.intersects = mxUtils.bind(this, function(state, evt)
- {
- if (this.connectImage != null || this.isConnecting())
- {
- return true;
- }
-
- return mxCellMarker.prototype.intersects.apply(marker, arguments);
- });
-
- return marker;
-};
-
-/**
- * Function: start
- *
- * Starts a new connection for the given state and coordinates.
- */
-mxConnectionHandler.prototype.start = function(state, x, y, edgeState)
-{
- this.previous = state;
- this.first = new mxPoint(x, y);
- this.edgeState = (edgeState != null) ? edgeState : this.createEdgeState(null);
-
- // Marks the source state
- this.marker.currentColor = this.marker.validColor;
- this.marker.markedState = state;
- this.marker.mark();
-
- this.fireEvent(new mxEventObject(mxEvent.START, 'state', this.previous));
-};
-
-/**
- * Function: isConnecting
- *
- * Returns true if the source terminal has been clicked and a new
- * connection is currently being previewed.
- */
-mxConnectionHandler.prototype.isConnecting = function()
-{
- return this.first != null && this.shape != null;
-};
-
-/**
- * Function: isValidSource
- *
- * Returns <mxGraph.isValidSource> for the given source terminal.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the source terminal.
- */
-mxConnectionHandler.prototype.isValidSource = function(cell)
-{
- return this.graph.isValidSource(cell);
-};
-
-/**
- * Function: isValidTarget
- *
- * Returns true. The call to <mxGraph.isValidTarget> is implicit by calling
- * <mxGraph.getEdgeValidationError> in <validateConnection>. This is an
- * additional hook for disabling certain targets in this specific handler.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the target terminal.
- */
-mxConnectionHandler.prototype.isValidTarget = function(cell)
-{
- return true;
-};
-
-/**
- * Function: validateConnection
- *
- * Returns the error message or an empty string if the connection for the
- * given source target pair is not valid. Otherwise it returns null. This
- * implementation uses <mxGraph.getEdgeValidationError>.
- *
- * Parameters:
- *
- * source - <mxCell> that represents the source terminal.
- * target - <mxCell> that represents the target terminal.
- */
-mxConnectionHandler.prototype.validateConnection = function(source, target)
-{
- if (!this.isValidTarget(target))
- {
- return '';
- }
-
- return this.graph.getEdgeValidationError(null, source, target);
-};
-
-/**
- * Function: getConnectImage
- *
- * Hook to return the <mxImage> used for the connection icon of the given
- * <mxCellState>. This implementation returns <connectImage>.
- *
- * Parameters:
- *
- * state - <mxCellState> whose connect image should be returned.
- */
-mxConnectionHandler.prototype.getConnectImage = function(state)
-{
- return this.connectImage;
-};
-
-/**
- * Function: isMoveIconToFrontForState
- *
- * Returns true if the state has a HTML label in the graph's container, otherwise
- * it returns <moveIconFront>.
- *
- * Parameters:
- *
- * state - <mxCellState> whose connect icons should be returned.
- */
-mxConnectionHandler.prototype.isMoveIconToFrontForState = function(state)
-{
- if (state.text != null && state.text.node.parentNode == this.graph.container)
- {
- return true;
- }
-
- return this.moveIconFront;
-};
-
-/**
- * Function: createIcons
- *
- * Creates the array <mxImageShapes> that represent the connect icons for
- * the given <mxCellState>.
- *
- * Parameters:
- *
- * state - <mxCellState> whose connect icons should be returned.
- */
-mxConnectionHandler.prototype.createIcons = function(state)
-{
- var image = this.getConnectImage(state);
-
- if (image != null && state != null)
- {
- this.iconState = state;
- var icons = [];
-
- // Cannot use HTML for the connect icons because the icon receives all
- // mouse move events in IE, must use VML and SVG instead even if the
- // connect-icon appears behind the selection border and the selection
- // border consumes the events before the icon gets a chance
- var bounds = new mxRectangle(0, 0, image.width, image.height);
- var icon = new mxImageShape(bounds, image.src, null, null, 0);
- icon.preserveImageAspect = false;
-
- if (this.isMoveIconToFrontForState(state))
- {
- icon.dialect = mxConstants.DIALECT_STRICTHTML;
- icon.init(this.graph.container);
- }
- else
- {
- icon.dialect = (this.graph.dialect == mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_SVG :
- mxConstants.DIALECT_VML;
- icon.init(this.graph.getView().getOverlayPane());
-
- // Move the icon back in the overlay pane
- if (this.moveIconBack && icon.node.previousSibling != null)
- {
- icon.node.parentNode.insertBefore(icon.node, icon.node.parentNode.firstChild);
- }
- }
-
- icon.node.style.cursor = mxConstants.CURSOR_CONNECT;
-
- // Events transparency
- var getState = mxUtils.bind(this, function()
- {
- return (this.currentState != null) ? this.currentState : state;
- });
-
- // Updates the local icon before firing the mouse down event.
- var mouseDown = mxUtils.bind(this, function(evt)
- {
- if (!mxEvent.isConsumed(evt))
- {
- this.icon = icon;
- this.graph.fireMouseEvent(mxEvent.MOUSE_DOWN,
- new mxMouseEvent(evt, getState()));
- }
- });
-
- mxEvent.redirectMouseEvents(icon.node, this.graph, getState, mouseDown);
-
- icons.push(icon);
- this.redrawIcons(icons, this.iconState);
-
- return icons;
- }
-
- return null;
-};
-
-/**
- * Function: redrawIcons
- *
- * Redraws the given array of <mxImageShapes>.
- *
- * Parameters:
- *
- * icons - Optional array of <mxImageShapes> to be redrawn.
- */
-mxConnectionHandler.prototype.redrawIcons = function(icons, state)
-{
- if (icons != null && icons[0] != null && state != null)
- {
- var pos = this.getIconPosition(icons[0], state);
- icons[0].bounds.x = pos.x;
- icons[0].bounds.y = pos.y;
- icons[0].redraw();
- }
-};
-
-/**
- * Function: redrawIcons
- *
- * Redraws the given array of <mxImageShapes>.
- *
- * Parameters:
- *
- * icons - Optional array of <mxImageShapes> to be redrawn.
- */
-mxConnectionHandler.prototype.getIconPosition = function(icon, state)
-{
- var scale = this.graph.getView().scale;
- var cx = state.getCenterX();
- var cy = state.getCenterY();
-
- if (this.graph.isSwimlane(state.cell))
- {
- var size = this.graph.getStartSize(state.cell);
-
- cx = (size.width != 0) ? state.x + size.width * scale / 2 : cx;
- cy = (size.height != 0) ? state.y + size.height * scale / 2 : cy;
- }
-
- return new mxPoint(cx - icon.bounds.width / 2,
- cy - icon.bounds.height / 2);
-};
-
-/**
- * Function: destroyIcons
- *
- * Destroys the given array of <mxImageShapes>.
- *
- * Parameters:
- *
- * icons - Optional array of <mxImageShapes> to be destroyed.
- */
-mxConnectionHandler.prototype.destroyIcons = function(icons)
-{
- if (icons != null)
- {
- this.iconState = null;
-
- for (var i = 0; i < icons.length; i++)
- {
- icons[i].destroy();
- }
- }
-};
-
-/**
- * Function: isStartEvent
- *
- * Returns true if the given mouse down event should start this handler. The
- * This implementation returns true if the event does not force marquee
- * selection, and the currentConstraint and currentFocus of the
- * <constraintHandler> are not null, or <previous> and <error> are not null and
- * <icons> is null or <icons> and <icon> are not null.
- */
-mxConnectionHandler.prototype.isStartEvent = function(me)
-{
- return !this.graph.isForceMarqueeEvent(me.getEvent()) &&
- ((this.constraintHandler.currentFocus != null &&
- this.constraintHandler.currentConstraint != null) ||
- (this.previous != null && this.error == null &&
- (this.icons == null || (this.icons != null && this.icon != null))));
-};
-
-/**
- * Function: mouseDown
- *
- * Handles the event by initiating a new connection.
- */
-mxConnectionHandler.prototype.mouseDown = function(sender, me)
-{
- this.mouseDownCounter++;
-
- if (this.isEnabled() && this.graph.isEnabled() && !me.isConsumed() &&
- !this.isConnecting() && this.isStartEvent(me))
- {
- if (this.constraintHandler.currentConstraint != null &&
- this.constraintHandler.currentFocus != null &&
- this.constraintHandler.currentPoint != null)
- {
- this.sourceConstraint = this.constraintHandler.currentConstraint;
- this.previous = this.constraintHandler.currentFocus;
- this.first = this.constraintHandler.currentPoint.clone();
- }
- else
- {
- // Stores the location of the initial mousedown
- this.first = new mxPoint(me.getGraphX(), me.getGraphY());
- }
-
- this.edgeState = this.createEdgeState(me);
- this.mouseDownCounter = 1;
-
- if (this.waypointsEnabled && this.shape == null)
- {
- this.waypoints = null;
- this.shape = this.createShape();
- }
-
- // Stores the starting point in the geometry of the preview
- if (this.previous == null && this.edgeState != null)
- {
- var pt = this.graph.getPointForEvent(me.getEvent());
- this.edgeState.cell.geometry.setTerminalPoint(pt, true);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.START, 'state', this.previous));
-
- me.consume();
- }
- // Handles connecting via tap and hold
- else if (mxClient.IS_TOUCH && this.tapAndHoldEnabled && !this.tapAndHoldInProgress &&
- this.isEnabled() && this.graph.isEnabled() && !this.isConnecting())
- {
- this.tapAndHoldInProgress = true;
- this.initialTouchX = me.getX();
- this.initialTouchY = me.getY();
- var state = this.graph.view.getState(this.marker.getCell(me));
-
- var handler = function()
- {
- if (this.tapAndHoldValid)
- {
- this.tapAndHold(me, state);
- }
-
- this.tapAndHoldInProgress = false;
- this.tapAndHoldValid = false;
- };
-
- if (this.tapAndHoldThread)
- {
- window.clearTimeout(this.tapAndHoldThread);
- }
-
- this.tapAndHoldThread = window.setTimeout(mxUtils.bind(this, handler), this.tapAndHoldDelay);
- this.tapAndHoldValid = true;
- }
-
- this.selectedIcon = this.icon;
- this.icon = null;
-};
-
-/**
- * Function: tapAndHold
- *
- * Handles the <mxMouseEvent> by highlighting the <mxCellState>.
- *
- * Parameters:
- *
- * me - <mxMouseEvent> that represents the touch event.
- * state - Optional <mxCellState> that is associated with the event.
- */
-mxConnectionHandler.prototype.tapAndHold = function(me, state)
-{
- if (state != null)
- {
- this.marker.currentColor = this.marker.validColor;
- this.marker.markedState = state;
- this.marker.mark();
-
- this.first = new mxPoint(me.getGraphX(), me.getGraphY());
- this.edgeState = this.createEdgeState(me);
- this.previous = state;
- this.fireEvent(new mxEventObject(mxEvent.START, 'state', this.previous));
- }
-};
-
-/**
- * Function: isImmediateConnectSource
- *
- * Returns true if a tap on the given source state should immediately start
- * connecting. This implementation returns true if the state is not movable
- * in the graph.
- */
-mxConnectionHandler.prototype.isImmediateConnectSource = function(state)
-{
- return !this.graph.isCellMovable(state.cell);
-};
-
-/**
- * Function: createEdgeState
- *
- * Hook to return an <mxCellState> which may be used during the preview.
- * This implementation returns null.
- *
- * Use the following code to create a preview for an existing edge style:
- *
- * [code]
- * graph.connectionHandler.createEdgeState = function(me)
- * {
- * var edge = graph.createEdge(null, null, null, null, null, 'edgeStyle=elbowEdgeStyle');
- *
- * return new mxCellState(this.graph.view, edge, this.graph.getCellStyle(edge));
- * };
- * [/code]
- */
-mxConnectionHandler.prototype.createEdgeState = function(me)
-{
- return null;
-};
-
-/**
- * Function: updateCurrentState
- *
- * Updates the current state for a given mouse move event by using
- * the <marker>.
- */
-mxConnectionHandler.prototype.updateCurrentState = function(me)
-{
- var state = this.marker.process(me);
- this.constraintHandler.update(me, this.first == null);
- this.currentState = state;
-};
-
-/**
- * Function: convertWaypoint
- *
- * Converts the given point from screen coordinates to model coordinates.
- */
-mxConnectionHandler.prototype.convertWaypoint = function(point)
-{
- var scale = this.graph.getView().getScale();
- var tr = this.graph.getView().getTranslate();
-
- point.x = point.x / scale - tr.x;
- point.y = point.y / scale - tr.y;
-};
-
-/**
- * Function: mouseMove
- *
- * Handles the event by updating the preview edge or by highlighting
- * a possible source or target terminal.
- */
-mxConnectionHandler.prototype.mouseMove = function(sender, me)
-{
- if (this.tapAndHoldValid)
- {
- this.tapAndHoldValid =
- Math.abs(this.initialTouchX - me.getX()) < this.tapAndHoldTolerance &&
- Math.abs(this.initialTouchY - me.getY()) < this.tapAndHoldTolerance;
- }
-
- if (!me.isConsumed() && (this.ignoreMouseDown || this.first != null || !this.graph.isMouseDown))
- {
- // Handles special case when handler is disabled during highlight
- if (!this.isEnabled() && this.currentState != null)
- {
- this.destroyIcons(this.icons);
- this.currentState = null;
- }
-
- if (this.first != null || (this.isEnabled() && this.graph.isEnabled()))
- {
- this.updateCurrentState(me);
- }
-
- if (this.first != null)
- {
- var view = this.graph.getView();
- var scale = view.scale;
- var point = new mxPoint(this.graph.snap(me.getGraphX() / scale) * scale,
- this.graph.snap(me.getGraphY() / scale) * scale);
- var constraint = null;
- var current = point;
-
- // Uses the current point from the constraint handler if available
- if (this.constraintHandler.currentConstraint != null &&
- this.constraintHandler.currentFocus != null &&
- this.constraintHandler.currentPoint != null)
- {
- constraint = this.constraintHandler.currentConstraint;
- current = this.constraintHandler.currentPoint.clone();
- }
-
- var pt2 = this.first;
-
- // Moves the connect icon with the mouse
- if (this.selectedIcon != null)
- {
- var w = this.selectedIcon.bounds.width;
- var h = this.selectedIcon.bounds.height;
-
- if (this.currentState != null && this.targetConnectImage)
- {
- var pos = this.getIconPosition(this.selectedIcon, this.currentState);
- this.selectedIcon.bounds.x = pos.x;
- this.selectedIcon.bounds.y = pos.y;
- }
- else
- {
- var bounds = new mxRectangle(me.getGraphX() + this.connectIconOffset.x,
- me.getGraphY() + this.connectIconOffset.y, w, h);
- this.selectedIcon.bounds = bounds;
- }
-
- this.selectedIcon.redraw();
- }
-
- // Uses edge state to compute the terminal points
- if (this.edgeState != null)
- {
- this.edgeState.absolutePoints = [null, (this.currentState != null) ? null : current];
- this.graph.view.updateFixedTerminalPoint(this.edgeState, this.previous, true, this.sourceConstraint);
-
- if (this.currentState != null)
- {
- if (constraint == null)
- {
- constraint = this.graph.getConnectionConstraint(this.edgeState, this.previous, false);
- }
-
- this.edgeState.setAbsoluteTerminalPoint(null, false);
- this.graph.view.updateFixedTerminalPoint(this.edgeState, this.currentState, false, constraint);
- }
-
- // Scales and translates the waypoints to the model
- var realPoints = null;
-
- if (this.waypoints != null)
- {
- realPoints = [];
-
- for (var i = 0; i < this.waypoints.length; i++)
- {
- var pt = this.waypoints[i].clone();
- this.convertWaypoint(pt);
- realPoints[i] = pt;
- }
- }
-
- this.graph.view.updatePoints(this.edgeState, realPoints, this.previous, this.currentState);
- this.graph.view.updateFloatingTerminalPoints(this.edgeState, this.previous, this.currentState);
- current = this.edgeState.absolutePoints[this.edgeState.absolutePoints.length - 1];
- pt2 = this.edgeState.absolutePoints[0];
- }
- else
- {
- if (this.currentState != null)
- {
- if (this.constraintHandler.currentConstraint == null)
- {
- var tmp = this.getTargetPerimeterPoint(this.currentState, me);
-
- if (tmp != null)
- {
- current = tmp;
- }
- }
- }
-
- // Computes the source perimeter point
- if (this.sourceConstraint == null && this.previous != null)
- {
- var next = (this.waypoints != null && this.waypoints.length > 0) ?
- this.waypoints[0] : current;
- var tmp = this.getSourcePerimeterPoint(this.previous, next, me);
-
- if (tmp != null)
- {
- pt2 = tmp;
- }
- }
- }
-
- // Makes sure the cell under the mousepointer can be detected
- // by moving the preview shape away from the mouse. This
- // makes sure the preview shape does not prevent the detection
- // of the cell under the mousepointer even for slow gestures.
- if (this.currentState == null && this.movePreviewAway)
- {
- var tmp = pt2;
-
- if (this.edgeState != null && this.edgeState.absolutePoints.length > 2)
- {
- var tmp2 = this.edgeState.absolutePoints[this.edgeState.absolutePoints.length - 2];
-
- if (tmp2 != null)
- {
- tmp = tmp2;
- }
- }
-
- var dx = current.x - tmp.x;
- var dy = current.y - tmp.y;
-
- var len = Math.sqrt(dx * dx + dy * dy);
-
- if (len == 0)
- {
- return;
- }
-
- current.x -= dx * 4 / len;
- current.y -= dy * 4 / len;
- }
-
- // Creates the preview shape (lazy)
- if (this.shape == null)
- {
- var dx = Math.abs(point.x - this.first.x);
- var dy = Math.abs(point.y - this.first.y);
-
- if (dx > this.graph.tolerance || dy > this.graph.tolerance)
- {
- this.shape = this.createShape();
-
- // Revalidates current connection
- this.updateCurrentState(me);
- }
- }
-
- // Updates the points in the preview edge
- if (this.shape != null)
- {
- if (this.edgeState != null)
- {
- this.shape.points = this.edgeState.absolutePoints;
- }
- else
- {
- var pts = [pt2];
-
- if (this.waypoints != null)
- {
- pts = pts.concat(this.waypoints);
- }
-
- pts.push(current);
- this.shape.points = pts;
- }
-
- this.drawPreview();
- }
-
- mxEvent.consume(me.getEvent());
- me.consume();
- }
- else if(!this.isEnabled() || !this.graph.isEnabled())
- {
- this.constraintHandler.reset();
- }
- else if (this.previous != this.currentState && this.edgeState == null)
- {
- this.destroyIcons(this.icons);
- this.icons = null;
-
- // Sets the cursor on the current shape
- if (this.currentState != null && this.error == null)
- {
- this.icons = this.createIcons(this.currentState);
-
- if (this.icons == null)
- {
- this.currentState.setCursor(mxConstants.CURSOR_CONNECT);
- me.consume();
- }
- }
-
- this.previous = this.currentState;
- }
- else if (this.previous == this.currentState && this.currentState != null && this.icons == null &&
- !this.graph.isMouseDown)
- {
- // Makes sure that no cursors are changed
- me.consume();
- }
-
- if (this.constraintHandler.currentConstraint != null)
- {
- this.marker.reset();
- }
-
- if (!this.graph.isMouseDown && this.currentState != null && this.icons != null)
- {
- var hitsIcon = false;
- var target = me.getSource();
-
- for (var i = 0; i < this.icons.length && !hitsIcon; i++)
- {
- hitsIcon = target == this.icons[i].node || target.parentNode == this.icons[i].node;
- }
-
- if (!hitsIcon)
- {
- this.updateIcons(this.currentState, this.icons, me);
- }
- }
- }
- else
- {
- this.constraintHandler.reset();
- }
-};
-
-/**
- * Function: getTargetPerimeterPoint
- *
- * Returns the perimeter point for the given target state.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the target cell state.
- * me - <mxMouseEvent> that represents the mouse move.
- */
-mxConnectionHandler.prototype.getTargetPerimeterPoint = function(state, me)
-{
- var result = null;
- var view = state.view;
- var targetPerimeter = view.getPerimeterFunction(state);
-
- if (targetPerimeter != null)
- {
- var next = (this.waypoints != null && this.waypoints.length > 0) ?
- this.waypoints[this.waypoints.length - 1] :
- new mxPoint(this.previous.getCenterX(), this.previous.getCenterY());
- var tmp = targetPerimeter(view.getPerimeterBounds(state),
- this.edgeState, next, false);
-
- if (tmp != null)
- {
- result = tmp;
- }
- }
- else
- {
- result = new mxPoint(state.getCenterX(), state.getCenterY());
- }
-
- return result;
-};
-
-/**
- * Function: getSourcePerimeterPoint
- *
- * Hook to update the icon position(s) based on a mouseOver event. This is
- * an empty implementation.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the target cell state.
- * next - <mxPoint> that represents the next point along the previewed edge.
- * me - <mxMouseEvent> that represents the mouse move.
- */
-mxConnectionHandler.prototype.getSourcePerimeterPoint = function(state, next, me)
-{
- var result = null;
- var view = state.view;
- var sourcePerimeter = view.getPerimeterFunction(state);
-
- if (sourcePerimeter != null)
- {
- var tmp = sourcePerimeter(view.getPerimeterBounds(state), state, next, false);
-
- if (tmp != null)
- {
- result = tmp;
- }
- }
- else
- {
- result = new mxPoint(state.getCenterX(), state.getCenterY());
- }
-
- return result;
-};
-
-
-/**
- * Function: updateIcons
- *
- * Hook to update the icon position(s) based on a mouseOver event. This is
- * an empty implementation.
- *
- * Parameters:
- *
- * state - <mxCellState> under the mouse.
- * icons - Array of currently displayed icons.
- * me - <mxMouseEvent> that contains the mouse event.
- */
-mxConnectionHandler.prototype.updateIcons = function(state, icons, me)
-{
- // empty
-};
-
-/**
- * Function: isStopEvent
- *
- * Returns true if the given mouse up event should stop this handler. The
- * connection will be created if <error> is null. Note that this is only
- * called if <waypointsEnabled> is true. This implemtation returns true
- * if there is a cell state in the given event.
- */
-mxConnectionHandler.prototype.isStopEvent = function(me)
-{
- return me.getState() != null;
-};
-
-/**
- * Function: addWaypoint
- *
- * Adds the waypoint for the given event to <waypoints>.
- */
-mxConnectionHandler.prototype.addWaypointForEvent = function(me)
-{
- var point = mxUtils.convertPoint(this.graph.container, me.getX(), me.getY());
- var dx = Math.abs(point.x - this.first.x);
- var dy = Math.abs(point.y - this.first.y);
- var addPoint = this.waypoints != null || (this.mouseDownCounter > 1 &&
- (dx > this.graph.tolerance || dy > this.graph.tolerance));
-
- if (addPoint)
- {
- if (this.waypoints == null)
- {
- this.waypoints = [];
- }
-
- var scale = this.graph.view.scale;
- var point = new mxPoint(this.graph.snap(me.getGraphX() / scale) * scale,
- this.graph.snap(me.getGraphY() / scale) * scale);
- this.waypoints.push(point);
- }
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event by inserting the new connection.
- */
-mxConnectionHandler.prototype.mouseUp = function(sender, me)
-{
- if (!me.isConsumed() && this.isConnecting())
- {
- if (this.waypointsEnabled && !this.isStopEvent(me))
- {
- this.addWaypointForEvent(me);
- me.consume();
-
- return;
- }
-
- // Inserts the edge if no validation error exists
- if (this.error == null)
- {
- var source = (this.previous != null) ? this.previous.cell : null;
- var target = null;
-
- if (this.constraintHandler.currentConstraint != null &&
- this.constraintHandler.currentFocus != null)
- {
- target = this.constraintHandler.currentFocus.cell;
- }
-
- if (target == null && this.marker.hasValidState())
- {
- target = this.marker.validState.cell;
- }
-
- this.connect(source, target, me.getEvent(), me.getCell());
- }
- else
- {
- // Selects the source terminal for self-references
- if (this.previous != null && this.marker.validState != null &&
- this.previous.cell == this.marker.validState.cell)
- {
- this.graph.selectCellForEvent(this.marker.source, evt);
- }
-
- // Displays the error message if it is not an empty string,
- // for empty error messages, the event is silently dropped
- if (this.error.length > 0)
- {
- this.graph.validationAlert(this.error);
- }
- }
-
- // Redraws the connect icons and resets the handler state
- this.destroyIcons(this.icons);
- me.consume();
- }
-
- if (this.first != null)
- {
- this.reset();
- }
-
- this.tapAndHoldInProgress = false;
- this.tapAndHoldValid = false;
-};
-
-/**
- * Function: reset
- *
- * Resets the state of this handler.
- */
-mxConnectionHandler.prototype.reset = function()
-{
- if (this.shape != null)
- {
- this.shape.destroy();
- this.shape = null;
- }
-
- this.destroyIcons(this.icons);
- this.icons = null;
- this.marker.reset();
- this.constraintHandler.reset();
- this.selectedIcon = null;
- this.edgeState = null;
- this.previous = null;
- this.error = null;
- this.sourceConstraint = null;
- this.mouseDownCounter = 0;
- this.first = null;
- this.icon = null;
-
- this.fireEvent(new mxEventObject(mxEvent.RESET));
-};
-
-/**
- * Function: drawPreview
- *
- * Redraws the preview edge using the color and width returned by
- * <getEdgeColor> and <getEdgeWidth>.
- */
-mxConnectionHandler.prototype.drawPreview = function()
-{
- var valid = this.error == null;
- var color = this.getEdgeColor(valid);
-
- if (this.shape.dialect == mxConstants.DIALECT_SVG)
- {
- this.shape.innerNode.setAttribute('stroke', color);
- }
- else
- {
- this.shape.node.strokecolor = color;
- }
-
- this.shape.strokewidth = this.getEdgeWidth(valid);
- this.shape.redraw();
-
- // Workaround to force a repaint in AppleWebKit
- mxUtils.repaintGraph(this.graph, this.shape.points[1]);
-};
-
-/**
- * Function: getEdgeColor
- *
- * Returns the color used to draw the preview edge. This returns green if
- * there is no edge validation error and red otherwise.
- *
- * Parameters:
- *
- * valid - Boolean indicating if the color for a valid edge should be
- * returned.
- */
-mxConnectionHandler.prototype.getEdgeColor = function(valid)
-{
- return (valid) ? mxConstants.VALID_COLOR : mxConstants.INVALID_COLOR;
-};
-
-/**
- * Function: getEdgeWidth
- *
- * Returns the width used to draw the preview edge. This returns 3 if
- * there is no edge validation error and 1 otherwise.
- *
- * Parameters:
- *
- * valid - Boolean indicating if the width for a valid edge should be
- * returned.
- */
-mxConnectionHandler.prototype.getEdgeWidth = function(valid)
-{
- return (valid) ? 3 : 1;
-};
-
-/**
- * Function: connect
- *
- * Connects the given source and target using a new edge. This
- * implementation uses <createEdge> to create the edge.
- *
- * Parameters:
- *
- * source - <mxCell> that represents the source terminal.
- * target - <mxCell> that represents the target terminal.
- * evt - Mousedown event of the connect gesture.
- * dropTarget - <mxCell> that represents the cell under the mouse when it was
- * released.
- */
-mxConnectionHandler.prototype.connect = function(source, target, evt, dropTarget)
-{
- if (target != null || this.isCreateTarget() || this.graph.allowDanglingEdges)
- {
- // Uses the common parent of source and target or
- // the default parent to insert the edge
- var model = this.graph.getModel();
- var edge = null;
-
- model.beginUpdate();
- try
- {
- if (source != null && target == null && this.isCreateTarget())
- {
- target = this.createTargetVertex(evt, source);
-
- if (target != null)
- {
- dropTarget = this.graph.getDropTarget([target], evt, dropTarget);
-
- // Disables edges as drop targets if the target cell was created
- // FIXME: Should not shift if vertex was aligned (same in Java)
- if (dropTarget == null || !this.graph.getModel().isEdge(dropTarget))
- {
- var pstate = this.graph.getView().getState(dropTarget);
-
- if (pstate != null)
- {
- var tmp = model.getGeometry(target);
- tmp.x -= pstate.origin.x;
- tmp.y -= pstate.origin.y;
- }
- }
- else
- {
- dropTarget = this.graph.getDefaultParent();
- }
-
- this.graph.addCell(target, dropTarget);
- }
- }
-
- var parent = this.graph.getDefaultParent();
-
- if (source != null && target != null &&
- model.getParent(source) == model.getParent(target) &&
- model.getParent(model.getParent(source)) != model.getRoot())
- {
- parent = model.getParent(source);
-
- if ((source.geometry != null && source.geometry.relative) &&
- (target.geometry != null && target.geometry.relative))
- {
- parent = model.getParent(parent);
- }
- }
-
- // Uses the value of the preview edge state for inserting
- // the new edge into the graph
- var value = null;
- var style = null;
-
- if (this.edgeState != null)
- {
- value = this.edgeState.cell.value;
- style = this.edgeState.cell.style;
- }
-
- edge = this.insertEdge(parent, null, value, source, target, style);
-
- if (edge != null)
- {
- // Updates the connection constraints
- this.graph.setConnectionConstraint(edge, source, true, this.sourceConstraint);
- this.graph.setConnectionConstraint(edge, target, false, this.constraintHandler.currentConstraint);
-
- // Uses geometry of the preview edge state
- if (this.edgeState != null)
- {
- model.setGeometry(edge, this.edgeState.cell.geometry);
- }
-
- // Makes sure the edge has a non-null, relative geometry
- var geo = model.getGeometry(edge);
-
- if (geo == null)
- {
- geo = new mxGeometry();
- geo.relative = true;
-
- model.setGeometry(edge, geo);
- }
-
- // Uses scaled waypoints in geometry
- if (this.waypoints != null && this.waypoints.length > 0)
- {
- var s = this.graph.view.scale;
- var tr = this.graph.view.translate;
- geo.points = [];
-
- for (var i = 0; i < this.waypoints.length; i++)
- {
- var pt = this.waypoints[i];
- geo.points.push(new mxPoint(pt.x / s - tr.x, pt.y / s - tr.y));
- }
- }
-
- if (target == null)
- {
- var pt = this.graph.getPointForEvent(evt, false);
- pt.x -= this.graph.panDx / this.graph.view.scale;
- pt.y -= this.graph.panDy / this.graph.view.scale;
- geo.setTerminalPoint(pt, false);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.CONNECT,
- 'cell', edge, 'event', evt, 'target', dropTarget));
- }
- }
- catch (e)
- {
- mxLog.show();
- mxLog.debug(e.message);
- }
- finally
- {
- model.endUpdate();
- }
-
- if (this.select)
- {
- this.selectCells(edge, target);
- }
- }
-};
-
-/**
- * Function: selectCells
- *
- * Selects the given edge after adding a new connection. The target argument
- * contains the target vertex if one has been inserted.
- */
-mxConnectionHandler.prototype.selectCells = function(edge, target)
-{
- this.graph.setSelectionCell(edge);
-};
-
-/**
- * Function: insertEdge
- *
- * Creates, inserts and returns the new edge for the given parameters. This
- * implementation does only use <createEdge> if <factoryMethod> is defined,
- * otherwise <mxGraph.insertEdge> will be used.
- */
-mxConnectionHandler.prototype.insertEdge = function(parent, id, value, source, target, style)
-{
- if (this.factoryMethod == null)
- {
- return this.graph.insertEdge(parent, id, value, source, target, style);
- }
- else
- {
- var edge = this.createEdge(value, source, target, style);
- edge = this.graph.addEdge(edge, parent, source, target);
-
- return edge;
- }
-};
-
-/**
- * Function: createTargetVertex
- *
- * Hook method for creating new vertices on the fly if no target was
- * under the mouse. This is only called if <createTarget> is true and
- * returns null.
- *
- * Parameters:
- *
- * evt - Mousedown event of the connect gesture.
- * source - <mxCell> that represents the source terminal.
- */
-mxConnectionHandler.prototype.createTargetVertex = function(evt, source)
-{
- // Uses the first non-relative source
- var geo = this.graph.getCellGeometry(source);
-
- while (geo != null && geo.relative)
- {
- source = this.graph.getModel().getParent(source);
- geo = this.graph.getCellGeometry(source);
- }
-
- var clone = this.graph.cloneCells([source])[0];
- var geo = this.graph.getModel().getGeometry(clone);
-
- if (geo != null)
- {
- var point = this.graph.getPointForEvent(evt);
- geo.x = this.graph.snap(point.x - geo.width / 2) - this.graph.panDx / this.graph.view.scale;
- geo.y = this.graph.snap(point.y - geo.height / 2) - this.graph.panDy / this.graph.view.scale;
-
- // Aligns with source if within certain tolerance
- if (this.first != null)
- {
- var sourceState = this.graph.view.getState(source);
-
- if (sourceState != null)
- {
- var tol = this.getAlignmentTolerance();
-
- if (Math.abs(this.graph.snap(this.first.x) -
- this.graph.snap(point.x)) <= tol)
- {
- geo.x = sourceState.x;
- }
- else if (Math.abs(this.graph.snap(this.first.y) -
- this.graph.snap(point.y)) <= tol)
- {
- geo.y = sourceState.y;
- }
- }
- }
- }
-
- return clone;
-};
-
-/**
- * Function: getAlignmentTolerance
- *
- * Returns the tolerance for aligning new targets to sources.
- */
-mxConnectionHandler.prototype.getAlignmentTolerance = function()
-{
- return (this.graph.isGridEnabled()) ?
- this.graph.gridSize : this.graph.tolerance;
-};
-
-/**
- * Function: createEdge
- *
- * Creates and returns a new edge using <factoryMethod> if one exists. If
- * no factory method is defined, then a new default edge is returned. The
- * source and target arguments are informal, the actual connection is
- * setup later by the caller of this function.
- *
- * Parameters:
- *
- * value - Value to be used for creating the edge.
- * source - <mxCell> that represents the source terminal.
- * target - <mxCell> that represents the target terminal.
- * style - Optional style from the preview edge.
- */
-mxConnectionHandler.prototype.createEdge = function(value, source, target, style)
-{
- var edge = null;
-
- // Creates a new edge using the factoryMethod
- if (this.factoryMethod != null)
- {
- edge = this.factoryMethod(source, target, style);
- }
-
- if (edge == null)
- {
- edge = new mxCell(value || '');
- edge.setEdge(true);
- edge.setStyle(style);
-
- var geo = new mxGeometry();
- geo.relative = true;
- edge.setGeometry(geo);
- }
-
- return edge;
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes. This should be
- * called on all instances. It is called automatically for the built-in
- * instance created for each <mxGraph>.
- */
-mxConnectionHandler.prototype.destroy = function()
-{
- this.graph.removeMouseListener(this);
-
- if (this.shape != null)
- {
- this.shape.destroy();
- this.shape = null;
- }
-
- if (this.marker != null)
- {
- this.marker.destroy();
- this.marker = null;
- }
-
- if (this.constraintHandler != null)
- {
- this.constraintHandler.destroy();
- this.constraintHandler = null;
- }
-
- if (this.changeHandler != null)
- {
- this.graph.getModel().removeListener(this.changeHandler);
- this.graph.getView().removeListener(this.changeHandler);
- this.changeHandler = null;
- }
-
- if (this.drillHandler != null)
- {
- this.graph.removeListener(this.drillHandler);
- this.graph.getView().removeListener(this.drillHandler);
- this.drillHandler = null;
- }
-};
diff --git a/src/js/handler/mxConstraintHandler.js b/src/js/handler/mxConstraintHandler.js
deleted file mode 100644
index 39b3ab6..0000000
--- a/src/js/handler/mxConstraintHandler.js
+++ /dev/null
@@ -1,308 +0,0 @@
-/**
- * $Id: mxConstraintHandler.js,v 1.15 2012-11-01 16:13:41 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxConstraintHandler
- *
- * Handles constraints on connection targets. This class is in charge of
- * showing fixed points when the mouse is over a vertex and handles constraints
- * to establish new connections.
- *
- * Constructor: mxConstraintHandler
- *
- * Constructs an new constraint handler.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * factoryMethod - Optional function to create the edge. The function takes
- * the source and target <mxCell> as the first and second argument and
- * returns the <mxCell> that represents the new edge.
- */
-function mxConstraintHandler(graph)
-{
- this.graph = graph;
-};
-
-/**
- * Variable: pointImage
- *
- * <mxImage> to be used as the image for fixed connection points.
- */
-mxConstraintHandler.prototype.pointImage = new mxImage(mxClient.imageBasePath + '/point.gif', 5, 5);
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxConstraintHandler.prototype.graph = null;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxConstraintHandler.prototype.enabled = true;
-
-/**
- * Variable: highlightColor
- *
- * Specifies the color for the highlight. Default is <mxConstants.DEFAULT_VALID_COLOR>.
- */
-mxConstraintHandler.prototype.highlightColor = mxConstants.DEFAULT_VALID_COLOR;
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxConstraintHandler.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxConstraintHandler.prototype.setEnabled = function(enabled)
-{
- this.enabled = enabled;
-};
-
-/**
- * Function: reset
- *
- * Resets the state of this handler.
- */
-mxConstraintHandler.prototype.reset = function()
-{
- if (this.focusIcons != null)
- {
- for (var i = 0; i < this.focusIcons.length; i++)
- {
- this.focusIcons[i].destroy();
- }
-
- this.focusIcons = null;
- }
-
- if (this.focusHighlight != null)
- {
- this.focusHighlight.destroy();
- this.focusHighlight = null;
- }
-
- this.currentConstraint = null;
- this.currentFocusArea = null;
- this.currentPoint = null;
- this.currentFocus = null;
- this.focusPoints = null;
-};
-
-/**
- * Function: getTolerance
- *
- * Returns the tolerance to be used for intersecting connection points.
- */
-mxConstraintHandler.prototype.getTolerance = function()
-{
- return this.graph.getTolerance();
-};
-
-/**
- * Function: getImageForConstraint
- *
- * Returns the tolerance to be used for intersecting connection points.
- */
-mxConstraintHandler.prototype.getImageForConstraint = function(state, constraint, point)
-{
- return this.pointImage;
-};
-
-/**
- * Function: isEventIgnored
- *
- * Returns true if the given <mxMouseEvent> should be ignored in <update>. This
- * implementation always returns false.
- */
-mxConstraintHandler.prototype.isEventIgnored = function(me, source)
-{
- return false;
-};
-
-/**
- * Function: update
- *
- * Updates the state of this handler based on the given <mxMouseEvent>.
- * Source is a boolean indicating if the cell is a source or target.
- */
-mxConstraintHandler.prototype.update = function(me, source)
-{
- if (this.isEnabled() && !this.isEventIgnored(me))
- {
- var tol = this.getTolerance();
- var mouse = new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol);
- var connectable = (me.getCell() != null) ? this.graph.isCellConnectable(me.getCell()) : false;
-
- if ((this.currentFocusArea == null || (!mxUtils.intersects(this.currentFocusArea, mouse) ||
- (me.getState() != null && this.currentFocus != null && connectable))))
- {
- this.currentFocusArea = null;
-
- if (me.getState() != this.currentFocus)
- {
- this.currentFocus = null;
- this.constraints = (me.getState() != null && connectable) ?
- this.graph.getAllConnectionConstraints(me.getState(), source) : null;
-
- // Only uses cells which have constraints
- if (this.constraints != null)
- {
- this.currentFocus = me.getState();
- this.currentFocusArea = new mxRectangle(me.getState().x, me.getState().y, me.getState().width, me.getState().height);
-
- if (this.focusIcons != null)
- {
- for (var i = 0; i < this.focusIcons.length; i++)
- {
- this.focusIcons[i].destroy();
- }
-
- this.focusIcons = null;
- this.focusPoints = null;
- }
-
- this.focusIcons = [];
- this.focusPoints = [];
-
- for (var i = 0; i < this.constraints.length; i++)
- {
- var cp = this.graph.getConnectionPoint(me.getState(), this.constraints[i]);
- var img = this.getImageForConstraint(me.getState(), this.constraints[i], cp);
-
- var src = img.src;
- var bounds = new mxRectangle(cp.x - img.width / 2,
- cp.y - img.height / 2, img.width, img.height);
- var icon = new mxImageShape(bounds, src);
- icon.dialect = (this.graph.dialect == mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_SVG :
- mxConstants.DIALECT_VML;
- icon.init(this.graph.getView().getOverlayPane());
-
- // Move the icon behind all other overlays
- if (icon.node.previousSibling != null)
- {
- icon.node.parentNode.insertBefore(icon.node, icon.node.parentNode.firstChild);
- }
-
- var getState = mxUtils.bind(this, function()
- {
- return (this.currentFocus != null) ? this.currentFocus : me.getState();
- });
-
- icon.redraw();
-
- mxEvent.redirectMouseEvents(icon.node, this.graph, getState);
- this.currentFocusArea.add(icon.bounds);
- this.focusIcons.push(icon);
- this.focusPoints.push(cp);
- }
-
- this.currentFocusArea.grow(tol);
- }
- else if (this.focusIcons != null)
- {
- if (this.focusHighlight != null)
- {
- this.focusHighlight.destroy();
- this.focusHighlight = null;
- }
-
- for (var i = 0; i < this.focusIcons.length; i++)
- {
- this.focusIcons[i].destroy();
- }
-
- this.focusIcons = null;
- this.focusPoints = null;
- }
- }
- }
-
- this.currentConstraint = null;
- this.currentPoint = null;
-
- if (this.focusIcons != null && this.constraints != null &&
- (me.getState() == null || this.currentFocus == me.getState()))
- {
- for (var i = 0; i < this.focusIcons.length; i++)
- {
- if (mxUtils.intersects(this.focusIcons[i].bounds, mouse))
- {
- this.currentConstraint = this.constraints[i];
- this.currentPoint = this.focusPoints[i];
-
- var tmp = this.focusIcons[i].bounds.clone();
- tmp.grow((mxClient.IS_IE) ? 3 : 2);
-
- if (mxClient.IS_IE)
- {
- tmp.width -= 1;
- tmp.height -= 1;
- }
-
- if (this.focusHighlight == null)
- {
- var hl = new mxRectangleShape(tmp, null, this.highlightColor, 3);
- hl.dialect = (this.graph.dialect == mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_SVG :
- mxConstants.DIALECT_VML;
- hl.init(this.graph.getView().getOverlayPane());
- this.focusHighlight = hl;
-
- var getState = mxUtils.bind(this, function()
- {
- return (this.currentFocus != null) ? this.currentFocus : me.getState();
- });
-
- mxEvent.redirectMouseEvents(hl.node, this.graph, getState/*, mouseDown*/);
- }
- else
- {
- this.focusHighlight.bounds = tmp;
- this.focusHighlight.redraw();
- }
-
- break;
- }
- }
- }
-
- if (this.currentConstraint == null &&
- this.focusHighlight != null)
- {
- this.focusHighlight.destroy();
- this.focusHighlight = null;
- }
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroy this handler.
- */
-mxConstraintHandler.prototype.destroy = function()
-{
- this.reset();
-}; \ No newline at end of file
diff --git a/src/js/handler/mxEdgeHandler.js b/src/js/handler/mxEdgeHandler.js
deleted file mode 100644
index 2028342..0000000
--- a/src/js/handler/mxEdgeHandler.js
+++ /dev/null
@@ -1,1529 +0,0 @@
-/**
- * $Id: mxEdgeHandler.js,v 1.178 2012-09-12 09:16:23 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxEdgeHandler
- *
- * Graph event handler that reconnects edges and modifies control points and
- * the edge label location. Uses <mxTerminalMarker> for finding and
- * highlighting new source and target vertices. This handler is automatically
- * created in <mxGraph.createHandler> for each selected edge.
- *
- * To enable adding/removing control points, the following code can be used:
- *
- * (code)
- * mxEdgeHandler.prototype.addEnabled = true;
- * mxEdgeHandler.prototype.removeEnabled = true;
- * (end)
- *
- * Note: This experimental feature is not recommended for production use.
- *
- * Constructor: mxEdgeHandler
- *
- * Constructs an edge handler for the specified <mxCellState>.
- *
- * Parameters:
- *
- * state - <mxCellState> of the cell to be handled.
- */
-function mxEdgeHandler(state)
-{
- if (state != null)
- {
- this.state = state;
- this.init();
- }
-};
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxEdgeHandler.prototype.graph = null;
-
-/**
- * Variable: state
- *
- * Reference to the <mxCellState> being modified.
- */
-mxEdgeHandler.prototype.state = null;
-
-/**
- * Variable: marker
- *
- * Holds the <mxTerminalMarker> which is used for highlighting terminals.
- */
-mxEdgeHandler.prototype.marker = null;
-
-/**
- * Variable: constraintHandler
- *
- * Holds the <mxConstraintHandler> used for drawing and highlighting
- * constraints.
- */
-mxEdgeHandler.prototype.constraintHandler = null;
-
-/**
- * Variable: error
- *
- * Holds the current validation error while a connection is being changed.
- */
-mxEdgeHandler.prototype.error = null;
-
-/**
- * Variable: shape
- *
- * Holds the <mxShape> that represents the preview edge.
- */
-mxEdgeHandler.prototype.shape = null;
-
-/**
- * Variable: bends
- *
- * Holds the <mxShapes> that represent the points.
- */
-mxEdgeHandler.prototype.bends = null;
-
-/**
- * Variable: labelShape
- *
- * Holds the <mxShape> that represents the label position.
- */
-mxEdgeHandler.prototype.labelShape = null;
-
-/**
- * Variable: cloneEnabled
- *
- * Specifies if cloning by control-drag is enabled. Default is true.
- */
-mxEdgeHandler.prototype.cloneEnabled = true;
-
-/**
- * Variable: addEnabled
- *
- * Specifies if adding bends by shift-click is enabled. Default is false.
- * Note: This experimental feature is not recommended for production use.
- */
-mxEdgeHandler.prototype.addEnabled = false;
-
-/**
- * Variable: removeEnabled
- *
- * Specifies if removing bends by shift-click is enabled. Default is false.
- * Note: This experimental feature is not recommended for production use.
- */
-mxEdgeHandler.prototype.removeEnabled = false;
-
-/**
- * Variable: preferHtml
- *
- * Specifies if bends should be added to the graph container. This is updated
- * in <init> based on whether the edge or one of its terminals has an HTML
- * label in the container.
- */
-mxEdgeHandler.prototype.preferHtml = false;
-
-/**
- * Variable: allowHandleBoundsCheck
- *
- * Specifies if the bounds of handles should be used for hit-detection in IE
- * Default is true.
- */
-mxEdgeHandler.prototype.allowHandleBoundsCheck = true;
-
-/**
- * Variable: snapToTerminals
- *
- * Specifies if waypoints should snap to the routing centers of terminals.
- * Default is false.
- */
-mxEdgeHandler.prototype.snapToTerminals = false;
-
-/**
- * Variable: crisp
- *
- * Specifies if the edge handles should be rendered in crisp mode. Default is
- * true.
- */
-mxEdgeHandler.prototype.crisp = true;
-
-/**
- * Variable: handleImage
- *
- * Optional <mxImage> to be used as handles. Default is null.
- */
-mxEdgeHandler.prototype.handleImage = null;
-
-/**
- * Variable: tolerance
- *
- * Optional tolerance for hit-detection in <getHandleForEvent>. Default is 0.
- */
-mxEdgeHandler.prototype.tolerance = 0;
-
-/**
- * Function: init
- *
- * Initializes the shapes required for this edge handler.
- */
-mxEdgeHandler.prototype.init = function()
-{
- this.graph = this.state.view.graph;
- this.marker = this.createMarker();
- this.constraintHandler = new mxConstraintHandler(this.graph);
-
- // Clones the original points from the cell
- // and makes sure at least one point exists
- this.points = [];
-
- // Uses the absolute points of the state
- // for the initial configuration and preview
- this.abspoints = this.getSelectionPoints(this.state);
- this.shape = this.createSelectionShape(this.abspoints);
- this.shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- this.shape.init(this.graph.getView().getOverlayPane());
- this.shape.node.style.cursor = mxConstants.CURSOR_MOVABLE_EDGE;
-
- // Event handling
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- mxEvent.addListener(this.shape.node, 'dblclick',
- mxUtils.bind(this, function(evt)
- {
- this.graph.dblClick(evt, this.state.cell);
- })
- );
- mxEvent.addListener(this.shape.node, md,
- mxUtils.bind(this, function(evt)
- {
- if (this.addEnabled && this.isAddPointEvent(evt))
- {
- this.addPoint(this.state, evt);
- }
- else
- {
- this.graph.fireMouseEvent(mxEvent.MOUSE_DOWN,
- new mxMouseEvent(evt, this.state));
- }
- })
- );
- mxEvent.addListener(this.shape.node, mm,
- mxUtils.bind(this, function(evt)
- {
- var cell = this.state.cell;
-
- // Finds the cell under the mouse if the edge is being connected
- // in which case the edge is never highlighted as it cannot
- // be its own source or target terminal (transparent preview)
- if (this.index != null)
- {
- var pt = mxUtils.convertPoint(this.graph.container,
- mxEvent.getClientX(evt), mxEvent.getClientY(evt));
- cell = this.graph.getCellAt(pt.x, pt.y);
-
- // Swimlane content area is transparent in this case
- if (this.graph.isSwimlane(cell) && this.graph.hitsSwimlaneContent(cell, pt.x, pt.y))
- {
- cell = null;
- }
- }
-
- this.graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
- new mxMouseEvent(evt, this.graph.getView().getState(cell)));
- })
- );
- mxEvent.addListener(this.shape.node, mu,
- mxUtils.bind(this, function(evt)
- {
- this.graph.fireMouseEvent(mxEvent.MOUSE_UP,
- new mxMouseEvent(evt, this.state));
- })
- );
-
- // Updates preferHtml
- this.preferHtml = this.state.text != null &&
- this.state.text.node.parentNode == this.graph.container;
-
- if (!this.preferHtml)
- {
- // Checks source terminal
- var sourceState = this.state.getVisibleTerminalState(true);
-
- if (sourceState != null)
- {
- this.preferHtml = sourceState.text != null &&
- sourceState.text.node.parentNode == this.graph.container;
- }
-
- if (!this.preferHtml)
- {
- // Checks target terminal
- var targetState = this.state.getVisibleTerminalState(false);
-
- if (targetState != null)
- {
- this.preferHtml = targetState.text != null &&
- targetState.text.node.parentNode == this.graph.container;
- }
- }
- }
-
- // Creates bends for the non-routed absolute points
- // or bends that don't correspond to points
- if (this.graph.getSelectionCount() < mxGraphHandler.prototype.maxCells ||
- mxGraphHandler.prototype.maxCells <= 0)
- {
- this.bends = this.createBends();
- }
-
- // Adds a rectangular handle for the label position
- this.label = new mxPoint(this.state.absoluteOffset.x, this.state.absoluteOffset.y);
- this.labelShape = new mxRectangleShape(new mxRectangle(),
- mxConstants.LABEL_HANDLE_FILLCOLOR,
- mxConstants.HANDLE_STROKECOLOR);
- this.initBend(this.labelShape);
- this.labelShape.node.style.cursor = mxConstants.CURSOR_LABEL_HANDLE;
- mxEvent.redirectMouseEvents(this.labelShape.node, this.graph, this.state);
-
- this.redraw();
-};
-
-/**
- * Function: isAddPointEvent
- *
- * Returns true if the given event is a trigger to add a new point. This
- * implementation returns true if shift is pressed.
- */
-mxEdgeHandler.prototype.isAddPointEvent = function(evt)
-{
- return mxEvent.isShiftDown(evt);
-};
-
-/**
- * Function: isRemovePointEvent
- *
- * Returns true if the given event is a trigger to remove a point. This
- * implementation returns true if shift is pressed.
- */
-mxEdgeHandler.prototype.isRemovePointEvent = function(evt)
-{
- return mxEvent.isShiftDown(evt);
-};
-
-/**
- * Function: getSelectionPoints
- *
- * Returns the list of points that defines the selection stroke.
- */
-mxEdgeHandler.prototype.getSelectionPoints = function(state)
-{
- return state.absolutePoints;
-};
-
-/**
- * Function: createSelectionShape
- *
- * Creates the shape used to draw the selection border.
- */
-mxEdgeHandler.prototype.createSelectionShape = function(points)
-{
- var shape = new mxPolyline(points, this.getSelectionColor());
- shape.strokewidth = this.getSelectionStrokeWidth();
- shape.isDashed = this.isSelectionDashed();
-
- return shape;
-};
-
-/**
- * Function: getSelectionColor
- *
- * Returns <mxConstants.EDGE_SELECTION_COLOR>.
- */
-mxEdgeHandler.prototype.getSelectionColor = function()
-{
- return mxConstants.EDGE_SELECTION_COLOR;
-};
-
-/**
- * Function: getSelectionStrokeWidth
- *
- * Returns <mxConstants.EDGE_SELECTION_STROKEWIDTH>.
- */
-mxEdgeHandler.prototype.getSelectionStrokeWidth = function()
-{
- return mxConstants.EDGE_SELECTION_STROKEWIDTH;
-};
-
-/**
- * Function: isSelectionDashed
- *
- * Returns <mxConstants.EDGE_SELECTION_DASHED>.
- */
-mxEdgeHandler.prototype.isSelectionDashed = function()
-{
- return mxConstants.EDGE_SELECTION_DASHED;
-};
-
-/**
- * Function: isConnectableCell
- *
- * Returns true if the given cell is connectable. This is a hook to
- * disable floating connections. This implementation returns true.
- */
-mxEdgeHandler.prototype.isConnectableCell = function(cell)
-{
- return true;
-};
-
-/**
- * Function: createMarker
- *
- * Creates and returns the <mxCellMarker> used in <marker>.
- */
-mxEdgeHandler.prototype.createMarker = function()
-{
- var marker = new mxCellMarker(this.graph);
- var self = this; // closure
-
- // Only returns edges if they are connectable and never returns
- // the edge that is currently being modified
- marker.getCell = function(me)
- {
- var cell = mxCellMarker.prototype.getCell.apply(this, arguments);
-
- if (!self.isConnectableCell(cell))
- {
- return null;
- }
-
- var model = self.graph.getModel();
-
- if (cell == self.state.cell || (cell != null &&
- !self.graph.connectableEdges && model.isEdge(cell)))
- {
- cell = null;
- }
-
- return cell;
- };
-
- // Sets the highlight color according to validateConnection
- marker.isValidState = function(state)
- {
- var model = self.graph.getModel();
- var other = self.graph.view.getTerminalPort(state,
- self.graph.view.getState(model.getTerminal(self.state.cell,
- !self.isSource)), !self.isSource);
- var otherCell = (other != null) ? other.cell : null;
- var source = (self.isSource) ? state.cell : otherCell;
- var target = (self.isSource) ? otherCell : state.cell;
-
- // Updates the error message of the handler
- self.error = self.validateConnection(source, target);
-
- return self.error == null;
- };
-
- return marker;
-};
-
-/**
- * Function: validateConnection
- *
- * Returns the error message or an empty string if the connection for the
- * given source, target pair is not valid. Otherwise it returns null. This
- * implementation uses <mxGraph.getEdgeValidationError>.
- *
- * Parameters:
- *
- * source - <mxCell> that represents the source terminal.
- * target - <mxCell> that represents the target terminal.
- */
-mxEdgeHandler.prototype.validateConnection = function(source, target)
-{
- return this.graph.getEdgeValidationError(this.state.cell, source, target);
-};
-
-/**
- * Function: createBends
- *
- * Creates and returns the bends used for modifying the edge. This is
- * typically an array of <mxRectangleShapes>.
- */
- mxEdgeHandler.prototype.createBends = function()
- {
- var cell = this.state.cell;
- var bends = [];
-
- for (var i = 0; i < this.abspoints.length; i++)
- {
- if (this.isHandleVisible(i))
- {
- var source = i == 0;
- var target = i == this.abspoints.length - 1;
- var terminal = source || target;
-
- if (terminal || this.graph.isCellBendable(cell))
- {
- var bend = this.createHandleShape(i);
- this.initBend(bend);
-
- if (mxClient.IS_TOUCH)
- {
- bend.node.setAttribute('pointer-events', 'none');
- }
-
- if (this.isHandleEnabled(i))
- {
- if (mxClient.IS_TOUCH)
- {
- var getState = mxUtils.bind(this, function(evt)
- {
- var pt = mxUtils.convertPoint(this.graph.container, mxEvent.getClientX(evt), mxEvent.getClientY(evt));
-
- return this.graph.view.getState(this.graph.getCellAt(pt.x, pt.y));
- });
-
- mxEvent.redirectMouseEvents(bend.node, this.graph, getState);
- }
- else
- {
- bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE;
- mxEvent.redirectMouseEvents(bend.node, this.graph, this.state);
- }
- }
-
- bends.push(bend);
-
- if (!terminal)
- {
- this.points.push(new mxPoint(0,0));
- bend.node.style.visibility = 'hidden';
- }
- }
- }
- }
-
- return bends;
-};
-/**
- * Function: isHandleEnabled
- *
- * Creates the shape used to display the given bend.
- */
-mxEdgeHandler.prototype.isHandleEnabled = function(index)
-{
- return true;
-};
-
-/**
- * Function: isHandleVisible
- *
- * Returns true if the handle at the given index is visible.
- */
-mxEdgeHandler.prototype.isHandleVisible = function(index)
-{
- return true;
-};
-
-/**
- * Function: createHandleShape
- *
- * Creates the shape used to display the given bend. Note that the index may be
- * null for special cases, such as when called from
- * <mxElbowEdgeHandler.createVirtualBend>.
- */
-mxEdgeHandler.prototype.createHandleShape = function(index)
-{
- if (this.handleImage != null)
- {
- return new mxImageShape(new mxRectangle(0, 0, this.handleImage.width, this.handleImage.height), this.handleImage.src);
- }
- else
- {
- var s = mxConstants.HANDLE_SIZE;
-
- if (this.preferHtml)
- {
- s -= 1;
- }
-
- return new mxRectangleShape(new mxRectangle(0, 0, s, s), mxConstants.HANDLE_FILLCOLOR, mxConstants.HANDLE_STROKECOLOR);
- }
-};
-
-/**
- * Function: initBend
- *
- * Helper method to initialize the given bend.
- *
- * Parameters:
- *
- * bend - <mxShape> that represents the bend to be initialized.
- */
-mxEdgeHandler.prototype.initBend = function(bend)
-{
- bend.crisp = this.crisp;
-
- if (this.preferHtml)
- {
- bend.dialect = mxConstants.DIALECT_STRICTHTML;
- bend.init(this.graph.container);
- }
- else
- {
- bend.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- bend.init(this.graph.getView().getOverlayPane());
- }
-};
-
-/**
- * Function: getHandleForEvent
- *
- * Returns the index of the handle for the given event.
- */
-mxEdgeHandler.prototype.getHandleForEvent = function(me)
-{
- // Finds the handle that triggered the event
- if (this.bends != null)
- {
- // Connection highlight may consume events before they reach sizer handle
- var tol = this.tolerance;
- var hit = (this.allowHandleBoundsCheck && (mxClient.IS_IE || tol > 0)) ?
- new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol) : null;
-
- for (var i = 0; i < this.bends.length; i++)
- {
- if (me.isSource(this.bends[i]) || (hit != null &&
- this.bends[i].node.style.visibility != 'hidden' &&
- mxUtils.intersects(this.bends[i].bounds, hit)))
- {
- return i;
- }
- }
- }
-
- if (me.isSource(this.labelShape) || me.isSource(this.state.text))
- {
- // Workaround for SELECT element not working in Webkit
- if ((!mxClient.IS_SF && !mxClient.IS_GC) || me.getSource().nodeName != 'SELECT')
- {
- return mxEvent.LABEL_HANDLE;
- }
- }
-
- return null;
-};
-
-/**
- * Function: mouseDown
- *
- * Handles the event by checking if a special element of the handler
- * was clicked, in which case the index parameter is non-null. The
- * indices may be one of <LABEL_HANDLE> or the number of the respective
- * control point. The source and target points are used for reconnecting
- * the edge.
- */
-mxEdgeHandler.prototype.mouseDown = function(sender, me)
-{
- var handle = null;
-
- // Handles the case where the state in the event points to another
- // cell if the cell has a HTML label which sits on top of the handles
- // NOTE: Commented out. This should not be required as all HTML labels
- // are in order an do not appear behind the handles.
- //if (mxClient.IS_SVG || me.getState() == this.state)
- {
- handle = this.getHandleForEvent(me);
- }
-
- if (handle != null && !me.isConsumed() && this.graph.isEnabled() &&
- !this.graph.isForceMarqueeEvent(me.getEvent()))
- {
- if (this.removeEnabled && this.isRemovePointEvent(me.getEvent()))
- {
- this.removePoint(this.state, handle);
- }
- else if (handle != mxEvent.LABEL_HANDLE || this.graph.isLabelMovable(me.getCell()))
- {
- this.start(me.getX(), me.getY(), handle);
- }
-
- me.consume();
- }
-};
-
-/**
- * Function: start
- *
- * Starts the handling of the mouse gesture.
- */
-mxEdgeHandler.prototype.start = function(x, y, index)
-{
- this.startX = x;
- this.startY = y;
-
- this.isSource = (this.bends == null) ? false : index == 0;
- this.isTarget = (this.bends == null) ? false : index == this.bends.length - 1;
- this.isLabel = index == mxEvent.LABEL_HANDLE;
-
- if (this.isSource || this.isTarget)
- {
- var cell = this.state.cell;
- var terminal = this.graph.model.getTerminal(cell, this.isSource);
-
- if ((terminal == null && this.graph.isTerminalPointMovable(cell, this.isSource)) ||
- (terminal != null && this.graph.isCellDisconnectable(cell, terminal, this.isSource)))
- {
- this.index = index;
- }
- }
- else
- {
- this.index = index;
- }
-};
-
-/**
- * Function: clonePreviewState
- *
- * Returns a clone of the current preview state for the given point and terminal.
- */
-mxEdgeHandler.prototype.clonePreviewState = function(point, terminal)
-{
- return this.state.clone();
-};
-
-/**
- * Function: getSnapToTerminalTolerance
- *
- * Returns the tolerance for the guides. Default value is
- * gridSize * scale / 2.
- */
-mxEdgeHandler.prototype.getSnapToTerminalTolerance = function()
-{
- return this.graph.gridSize * this.graph.view.scale / 2;
-};
-
-/**
- * Function: getPointForEvent
- *
- * Returns the point for the given event.
- */
-mxEdgeHandler.prototype.getPointForEvent = function(me)
-{
- var point = new mxPoint(me.getGraphX(), me.getGraphY());
-
- var tt = this.getSnapToTerminalTolerance();
- var view = this.graph.getView();
- var overrideX = false;
- var overrideY = false;
-
- if (this.snapToTerminals && tt > 0)
- {
- function snapToPoint(pt)
- {
- if (pt != null)
- {
- var x = pt.x;
-
- if (Math.abs(point.x - x) < tt)
- {
- point.x = x;
- overrideX = true;
- }
-
- var y = pt.y;
-
- if (Math.abs(point.y - y) < tt)
- {
- point.y = y;
- overrideY = true;
- }
- }
- }
-
- // Temporary function
- function snapToTerminal(terminal)
- {
- if (terminal != null)
- {
- snapToPoint.call(this, new mxPoint(view.getRoutingCenterX(terminal),
- view.getRoutingCenterY(terminal)));
- }
- };
-
- snapToTerminal.call(this, this.state.getVisibleTerminalState(true));
- snapToTerminal.call(this, this.state.getVisibleTerminalState(false));
-
- if (this.abspoints != null)
- {
- for (var i = 0; i < this.abspoints; i++)
- {
- if (i != this.index)
- {
- snapToPoint.call(this, this.abspoints[i]);
- }
- }
- }
- }
-
- if (this.graph.isGridEnabledEvent(me.getEvent()))
- {
- var scale = view.scale;
- var tr = view.translate;
-
- if (!overrideX)
- {
- point.x = (this.graph.snap(point.x / scale - tr.x) + tr.x) * scale;
- }
-
- if (!overrideY)
- {
- point.y = (this.graph.snap(point.y / scale - tr.y) + tr.y) * scale;
- }
- }
-
- return point;
-};
-
-/**
- * Function: getPreviewTerminalState
- *
- * Updates the given preview state taking into account the state of the constraint handler.
- */
-mxEdgeHandler.prototype.getPreviewTerminalState = function(me)
-{
- this.constraintHandler.update(me, this.isSource);
- this.marker.process(me);
- var currentState = this.marker.getValidState();
- var result = null;
-
- if (this.constraintHandler.currentFocus != null &&
- this.constraintHandler.currentConstraint != null)
- {
- this.marker.reset();
- }
-
- if (currentState != null)
- {
- result = currentState;
- }
- else if (this.constraintHandler.currentConstraint != null &&
- this.constraintHandler.currentFocus != null)
- {
- result = this.constraintHandler.currentFocus;
- }
-
- return result;
-};
-
-/**
- * Function: getPreviewPoints
- *
- * Updates the given preview state taking into account the state of the constraint handler.
- */
-mxEdgeHandler.prototype.getPreviewPoints = function(point)
-{
- var geometry = this.graph.getCellGeometry(this.state.cell);
- var points = (geometry.points != null) ? geometry.points.slice() : null;
-
- if (!this.isSource && !this.isTarget)
- {
- this.convertPoint(point, false);
-
- if (points == null)
- {
- points = [point];
- }
- else
- {
- points[this.index - 1] = point;
- }
- }
- else if (this.graph.resetEdgesOnConnect)
- {
- points = null;
- }
-
- return points;
-};
-
-/**
- * Function: updatePreviewState
- *
- * Updates the given preview state taking into account the state of the constraint handler.
- */
-mxEdgeHandler.prototype.updatePreviewState = function(edge, point, terminalState)
-{
- // Computes the points for the edge style and terminals
- var sourceState = (this.isSource) ? terminalState : this.state.getVisibleTerminalState(true);
- var targetState = (this.isTarget) ? terminalState : this.state.getVisibleTerminalState(false);
-
- var sourceConstraint = this.graph.getConnectionConstraint(edge, sourceState, true);
- var targetConstraint = this.graph.getConnectionConstraint(edge, targetState, false);
-
- var constraint = this.constraintHandler.currentConstraint;
-
- if (constraint == null)
- {
- constraint = new mxConnectionConstraint();
- }
-
- if (this.isSource)
- {
- sourceConstraint = constraint;
- }
- else if (this.isTarget)
- {
- targetConstraint = constraint;
- }
-
- if (!this.isSource || sourceState != null)
- {
- edge.view.updateFixedTerminalPoint(edge, sourceState, true, sourceConstraint);
- }
-
- if (!this.isTarget || targetState != null)
- {
- edge.view.updateFixedTerminalPoint(edge, targetState, false, targetConstraint);
- }
-
- if ((this.isSource || this.isTarget) && terminalState == null)
- {
- edge.setAbsoluteTerminalPoint(point, this.isSource);
-
- if (this.marker.getMarkedState() == null)
- {
- this.error = (this.graph.allowDanglingEdges) ? null : '';
- }
- }
-
- edge.view.updatePoints(edge, this.points, sourceState, targetState);
- edge.view.updateFloatingTerminalPoints(edge, sourceState, targetState);
-};
-
-/**
- * Function: mouseMove
- *
- * Handles the event by updating the preview.
- */
-mxEdgeHandler.prototype.mouseMove = function(sender, me)
-{
- if (this.index != null && this.marker != null)
- {
- var point = this.getPointForEvent(me);
-
- if (this.isLabel)
- {
- this.label.x = point.x;
- this.label.y = point.y;
- }
- else
- {
- this.points = this.getPreviewPoints(point);
- var terminalState = (this.isSource || this.isTarget) ? this.getPreviewTerminalState(me) : null;
- var clone = this.clonePreviewState(point, (terminalState != null) ? terminalState.cell : null);
- this.updatePreviewState(clone, point, terminalState);
-
- // Sets the color of the preview to valid or invalid, updates the
- // points of the preview and redraws
- var color = (this.error == null) ? this.marker.validColor :
- this.marker.invalidColor;
- this.setPreviewColor(color);
- this.abspoints = clone.absolutePoints;
- this.active = true;
- }
-
- this.drawPreview();
- mxEvent.consume(me.getEvent());
- me.consume();
- }
- // Workaround for disabling the connect highlight when over handle
- else if (mxClient.IS_IE && this.getHandleForEvent(me) != null)
- {
- me.consume(false);
- }
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event to applying the previewed changes on the edge by
- * using <moveLabel>, <connect> or <changePoints>.
- */
-mxEdgeHandler.prototype.mouseUp = function(sender, me)
-{
- if (this.index != null && this.marker != null)
- {
- var edge = this.state.cell;
-
- // Ignores event if mouse has not been moved
- if (me.getX() != this.startX || me.getY() != this.startY)
- {
- // Displays the reason for not carriying out the change
- // if there is an error message with non-zero length
- if (this.error != null)
- {
- if (this.error.length > 0)
- {
- this.graph.validationAlert(this.error);
- }
- }
- else if (this.isLabel)
- {
- this.moveLabel(this.state, this.label.x, this.label.y);
- }
- else if (this.isSource || this.isTarget)
- {
- var terminal = null;
-
- if (this.constraintHandler.currentConstraint != null &&
- this.constraintHandler.currentFocus != null)
- {
- terminal = this.constraintHandler.currentFocus.cell;
- }
-
- if (terminal == null && this.marker.hasValidState())
- {
- terminal = this.marker.validState.cell;
- }
-
- if (terminal != null)
- {
- edge = this.connect(edge, terminal, this.isSource,
- this.graph.isCloneEvent(me.getEvent()) && this.cloneEnabled &&
- this.graph.isCellsCloneable(), me);
- }
- else if (this.graph.isAllowDanglingEdges())
- {
- var pt = this.abspoints[(this.isSource) ? 0 : this.abspoints.length - 1];
- pt.x = pt.x / this.graph.view.scale - this.graph.view.translate.x;
- pt.y = pt.y / this.graph.view.scale - this.graph.view.translate.y;
-
- var pstate = this.graph.getView().getState(
- this.graph.getModel().getParent(edge));
-
- if (pstate != null)
- {
- pt.x -= pstate.origin.x;
- pt.y -= pstate.origin.y;
- }
-
- pt.x -= this.graph.panDx / this.graph.view.scale;
- pt.y -= this.graph.panDy / this.graph.view.scale;
-
- // Destroys and rectreates this handler
- this.changeTerminalPoint(edge, pt, this.isSource);
- }
- }
- else if (this.active)
- {
- this.changePoints(edge, this.points);
- }
- else
- {
- this.graph.getView().invalidate(this.state.cell);
- this.graph.getView().revalidate(this.state.cell);
- }
- }
-
- // Resets the preview color the state of the handler if this
- // handler has not been recreated
- if (this.marker != null)
- {
- this.reset();
-
- // Updates the selection if the edge has been cloned
- if (edge != this.state.cell)
- {
- this.graph.setSelectionCell(edge);
- }
- }
-
- me.consume();
- }
-};
-
-/**
- * Function: reset
- *
- * Resets the state of this handler.
- */
-mxEdgeHandler.prototype.reset = function()
-{
- this.error = null;
- this.index = null;
- this.label = null;
- this.points = null;
- this.active = false;
- this.isLabel = false;
- this.isSource = false;
- this.isTarget = false;
- this.marker.reset();
- this.constraintHandler.reset();
- this.setPreviewColor(mxConstants.EDGE_SELECTION_COLOR);
- this.redraw();
-};
-
-/**
- * Function: setPreviewColor
- *
- * Sets the color of the preview to the given value.
- */
-mxEdgeHandler.prototype.setPreviewColor = function(color)
-{
- if (this.shape != null && this.shape.node != null)
- {
- if (this.shape.dialect == mxConstants.DIALECT_SVG)
- {
- this.shape.innerNode.setAttribute('stroke', color);
- }
- else
- {
- this.shape.node.strokecolor = color;
- }
- }
-};
-
-/**
- * Function: convertPoint
- *
- * Converts the given point in-place from screen to unscaled, untranslated
- * graph coordinates and applies the grid. Returns the given, modified
- * point instance.
- *
- * Parameters:
- *
- * point - <mxPoint> to be converted.
- * gridEnabled - Boolean that specifies if the grid should be applied.
- */
-mxEdgeHandler.prototype.convertPoint = function(point, gridEnabled)
-{
- var scale = this.graph.getView().getScale();
- var tr = this.graph.getView().getTranslate();
-
- if (gridEnabled)
- {
- point.x = this.graph.snap(point.x);
- point.y = this.graph.snap(point.y);
- }
-
- point.x = Math.round(point.x / scale - tr.x);
- point.y = Math.round(point.y / scale - tr.y);
-
- var pstate = this.graph.getView().getState(
- this.graph.getModel().getParent(this.state.cell));
-
- if (pstate != null)
- {
- point.x -= pstate.origin.x;
- point.y -= pstate.origin.y;
- }
-
- return point;
-};
-
-/**
- * Function: moveLabel
- *
- * Changes the coordinates for the label of the given edge.
- *
- * Parameters:
- *
- * edge - <mxCell> that represents the edge.
- * x - Integer that specifies the x-coordinate of the new location.
- * y - Integer that specifies the y-coordinate of the new location.
- */
-mxEdgeHandler.prototype.moveLabel = function(edgeState, x, y)
-{
- var model = this.graph.getModel();
- var geometry = model.getGeometry(edgeState.cell);
-
- if (geometry != null)
- {
- geometry = geometry.clone();
-
- // Resets the relative location stored inside the geometry
- var pt = this.graph.getView().getRelativePoint(edgeState, x, y);
- geometry.x = pt.x;
- geometry.y = pt.y;
-
- // Resets the offset inside the geometry to find the offset
- // from the resulting point
- var scale = this.graph.getView().scale;
- geometry.offset = new mxPoint(0, 0);
- var pt = this.graph.view.getPoint(edgeState, geometry);
- geometry.offset = new mxPoint((x - pt.x) / scale, (y - pt.y) / scale);
-
- model.setGeometry(edgeState.cell, geometry);
- }
-};
-
-/**
- * Function: connect
- *
- * Changes the terminal or terminal point of the given edge in the graph
- * model.
- *
- * Parameters:
- *
- * edge - <mxCell> that represents the edge to be reconnected.
- * terminal - <mxCell> that represents the new terminal.
- * isSource - Boolean indicating if the new terminal is the source or
- * target terminal.
- * isClone - Boolean indicating if the new connection should be a clone of
- * the old edge.
- * me - <mxMouseEvent> that contains the mouse up event.
- */
-mxEdgeHandler.prototype.connect = function(edge, terminal, isSource, isClone, me)
-{
- var model = this.graph.getModel();
- var parent = model.getParent(edge);
-
- model.beginUpdate();
- try
- {
- // Clones and adds the cell
- if (isClone)
- {
- var clone = edge.clone();
- model.add(parent, clone, model.getChildCount(parent));
-
- var other = model.getTerminal(edge, !isSource);
- this.graph.connectCell(clone, other, !isSource);
-
- edge = clone;
- }
-
- var constraint = this.constraintHandler.currentConstraint;
-
- if (constraint == null)
- {
- constraint = new mxConnectionConstraint();
- }
-
- this.graph.connectCell(edge, terminal, isSource, constraint);
- }
- finally
- {
- model.endUpdate();
- }
-
- return edge;
-};
-
-/**
- * Function: changeTerminalPoint
- *
- * Changes the terminal point of the given edge.
- */
-mxEdgeHandler.prototype.changeTerminalPoint = function(edge, point, isSource)
-{
- var model = this.graph.getModel();
- var geo = model.getGeometry(edge);
-
- if (geo != null)
- {
- model.beginUpdate();
- try
- {
- geo = geo.clone();
- geo.setTerminalPoint(point, isSource);
- model.setGeometry(edge, geo);
- this.graph.connectCell(edge, null, isSource, new mxConnectionConstraint());
- }
- finally
- {
- model.endUpdate();
- }
- }
-};
-
-/**
- * Function: changePoints
- *
- * Changes the control points of the given edge in the graph model.
- */
-mxEdgeHandler.prototype.changePoints = function(edge, points)
-{
- var model = this.graph.getModel();
- var geo = model.getGeometry(edge);
-
- if (geo != null)
- {
- geo = geo.clone();
- geo.points = points;
-
- model.setGeometry(edge, geo);
- }
-};
-
-/**
- * Function: addPoint
- *
- * Adds a control point for the given state and event.
- */
-mxEdgeHandler.prototype.addPoint = function(state, evt)
-{
- var geo = this.graph.getCellGeometry(state.cell);
-
- if (geo != null)
- {
- geo = geo.clone();
- var pt = mxUtils.convertPoint(this.graph.container, mxEvent.getClientX(evt),
- mxEvent.getClientY(evt));
- var index = mxUtils.findNearestSegment(state, pt.x, pt.y);
- var gridEnabled = this.graph.isGridEnabledEvent(evt);
- this.convertPoint(pt, gridEnabled);
-
- if (geo.points == null)
- {
- geo.points = [pt];
- }
- else
- {
- geo.points.splice(index, 0, pt);
- }
-
- this.graph.getModel().setGeometry(state.cell, geo);
- this.destroy();
- this.init();
- mxEvent.consume(evt);
- }
-};
-
-/**
- * Function: removePoint
- *
- * Removes the control point at the given index from the given state.
- */
-mxEdgeHandler.prototype.removePoint = function(state, index)
-{
- if (index > 0 && index < this.abspoints.length - 1)
- {
- var geo = this.graph.getCellGeometry(this.state.cell);
-
- if (geo != null &&
- geo.points != null)
- {
- geo = geo.clone();
- geo.points.splice(index - 1, 1);
- this.graph.getModel().setGeometry(state.cell, geo);
- this.destroy();
- this.init();
- }
- }
-};
-
-/**
- * Function: getHandleFillColor
- *
- * Returns the fillcolor for the handle at the given index.
- */
-mxEdgeHandler.prototype.getHandleFillColor = function(index)
-{
- var isSource = index == 0;
- var cell = this.state.cell;
- var terminal = this.graph.getModel().getTerminal(cell, isSource);
- var color = mxConstants.HANDLE_FILLCOLOR;
-
- if ((terminal != null && !this.graph.isCellDisconnectable(cell, terminal, isSource)) ||
- (terminal == null && !this.graph.isTerminalPointMovable(cell, isSource)))
- {
- color = mxConstants.LOCKED_HANDLE_FILLCOLOR;
- }
- else if (terminal != null && this.graph.isCellDisconnectable(cell, terminal, isSource))
- {
- color = mxConstants.CONNECT_HANDLE_FILLCOLOR;
- }
-
- return color;
-};
-
-/**
- * Function: redraw
- *
- * Redraws the preview, and the bends- and label control points.
- */
-mxEdgeHandler.prototype.redraw = function()
-{
- this.abspoints = this.state.absolutePoints.slice();
- var cell = this.state.cell;
-
- // Updates the handle for the label position
- var s = mxConstants.LABEL_HANDLE_SIZE;
-
- this.label = new mxPoint(this.state.absoluteOffset.x, this.state.absoluteOffset.y);
- this.labelShape.bounds = new mxRectangle(this.label.x - s / 2,
- this.label.y - s / 2, s, s);
- this.labelShape.redraw();
-
- // Shows or hides the label handle depending on the label
- var lab = this.graph.getLabel(cell);
-
- if (lab != null && lab.length > 0 && this.graph.isLabelMovable(cell))
- {
- this.labelShape.node.style.visibility = 'visible';
- }
- else
- {
- this.labelShape.node.style.visibility = 'hidden';
- }
-
- if (this.bends != null && this.bends.length > 0)
- {
- var n = this.abspoints.length - 1;
-
- var p0 = this.abspoints[0];
- var x0 = this.abspoints[0].x;
- var y0 = this.abspoints[0].y;
-
- var b = this.bends[0].bounds;
- this.bends[0].bounds = new mxRectangle(x0 - b.width / 2, y0 - b.height / 2, b.width, b.height);
- this.bends[0].fill = this.getHandleFillColor(0);
- this.bends[0].reconfigure();
- this.bends[0].redraw();
-
- var pe = this.abspoints[n];
- var xn = this.abspoints[n].x;
- var yn = this.abspoints[n].y;
-
- var bn = this.bends.length - 1;
- b = this.bends[bn].bounds;
- this.bends[bn].bounds = new mxRectangle(xn - b.width / 2, yn - b.height / 2, b.width, b.height);
- this.bends[bn].fill = this.getHandleFillColor(bn);
- this.bends[bn].reconfigure();
- this.bends[bn].redraw();
-
- this.redrawInnerBends(p0, pe);
- }
-
- this.drawPreview();
-};
-
-/**
- * Function: redrawInnerBends
- *
- * Updates and redraws the inner bends.
- *
- * Parameters:
- *
- * p0 - <mxPoint> that represents the location of the first point.
- * pe - <mxPoint> that represents the location of the last point.
- */
-mxEdgeHandler.prototype.redrawInnerBends = function(p0, pe)
-{
- var g = this.graph.getModel().getGeometry(this.state.cell);
- var pts = g.points;
-
- if (pts != null)
- {
- if (this.points == null)
- {
- this.points = [];
- }
-
- for (var i = 1; i < this.bends.length-1; i++)
- {
- if (this.bends[i] != null)
- {
- if (this.abspoints[i] != null)
- {
- var x = this.abspoints[i].x;
- var y = this.abspoints[i].y;
-
- var b = this.bends[i].bounds;
- this.bends[i].node.style.visibility = 'visible';
- this.bends[i].bounds = new mxRectangle(x - b.width / 2, y - b.height / 2, b.width, b.height);
- this.bends[i].redraw();
-
- this.points[i - 1] = pts[i - 1];
- }
- else
- {
- this.bends[i].destroy();
- this.bends[i] = null;
- }
- }
- }
- }
-};
-
-/**
- * Function: drawPreview
- *
- * Redraws the preview.
- */
-mxEdgeHandler.prototype.drawPreview = function()
-{
- if (this.isLabel)
- {
- var s = mxConstants.LABEL_HANDLE_SIZE;
-
- var bounds = new mxRectangle(this.label.x - s / 2, this.label.y - s / 2, s, s);
- this.labelShape.bounds = bounds;
- this.labelShape.redraw();
- }
- else
- {
- this.shape.points = this.abspoints;
- this.shape.redraw();
- }
-
- // Workaround to force a repaint in AppleWebKit
- mxUtils.repaintGraph(this.graph, this.shape.points[this.shape.points.length - 1]);
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes. This does
- * normally not need to be called as handlers are destroyed automatically
- * when the corresponding cell is deselected.
- */
-mxEdgeHandler.prototype.destroy = function()
-{
- if (this.marker != null)
- {
- this.marker.destroy();
- this.marker = null;
- }
-
- if (this.shape != null)
- {
- this.shape.destroy();
- this.shape = null;
- }
-
- if (this.labelShape != null)
- {
- this.labelShape.destroy();
- this.labelShape = null;
- }
-
- if (this.constraintHandler != null)
- {
- this.constraintHandler.destroy();
- this.constraintHandler = null;
- }
-
- // Destroy the control points for the bends
- if (this.bends != null)
- {
- for (var i = 0; i < this.bends.length; i++)
- {
- if (this.bends[i] != null)
- {
- this.bends[i].destroy();
- this.bends[i] = null;
- }
- }
- }
-};
diff --git a/src/js/handler/mxEdgeSegmentHandler.js b/src/js/handler/mxEdgeSegmentHandler.js
deleted file mode 100644
index e14fde0..0000000
--- a/src/js/handler/mxEdgeSegmentHandler.js
+++ /dev/null
@@ -1,284 +0,0 @@
-/**
- * $Id: mxEdgeSegmentHandler.js,v 1.14 2012-12-17 13:22:49 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-function mxEdgeSegmentHandler(state)
-{
- if (state != null)
- {
- this.state = state;
- this.init();
- }
-};
-
-/**
- * Extends mxEdgeHandler.
- */
-mxEdgeSegmentHandler.prototype = new mxElbowEdgeHandler();
-mxEdgeSegmentHandler.prototype.constructor = mxEdgeSegmentHandler;
-
-/**
- * Function: getPreviewPoints
- *
- * Updates the given preview state taking into account the state of the constraint handler.
- */
-mxEdgeSegmentHandler.prototype.getPreviewPoints = function(point)
-{
- if (this.isSource || this.isTarget)
- {
- return mxElbowEdgeHandler.prototype.getPreviewPoints.apply(this, arguments);
- }
- else
- {
- this.convertPoint(point, false);
- var pts = this.state.absolutePoints;
- var last = pts[0].clone();
- this.convertPoint(last, false);
- var result = [];
-
- for (var i = 1; i < pts.length; i++)
- {
- var pt = pts[i].clone();
- this.convertPoint(pt, false);
-
- if (i == this.index)
- {
- if (last.x == pt.x)
- {
- last.x = point.x;
- pt.x = point.x;
- }
- else
- {
- last.y = point.y;
- pt.y = point.y;
- }
- }
-
- if (i < pts.length - 1)
- {
- result.push(pt);
- }
-
- last = pt;
- }
-
- if (result.length == 1)
- {
- var view = this.state.view;
- var source = this.state.getVisibleTerminalState(true);
- var target = this.state.getVisibleTerminalState(false);
-
- if (target != null & source != null)
- {
- var dx = this.state.origin.x;
- var dy = this.state.origin.y;
-
- if (mxUtils.contains(target, result[0].x + dx, result[0].y + dy))
- {
- if (pts[1].y == pts[2].y)
- {
- result[0].y = view.getRoutingCenterY(source) - dy;
- }
- else
- {
- result[0].x = view.getRoutingCenterX(source) - dx;
- }
- }
- else if (mxUtils.contains(source, result[0].x + dx, result[0].y + dy))
- {
- if (pts[1].y == pts[0].y)
- {
- result[0].y = view.getRoutingCenterY(target) - dy;
- }
- else
- {
- result[0].x = view.getRoutingCenterX(target) - dx;
- }
- }
- }
- }
- else if (result.length == 0)
- {
- result = [point];
- }
-
- return result;
- }
-};
-
-/**
- * Function: createBends
- *
- * Adds custom bends for the center of each segment.
- */
-mxEdgeSegmentHandler.prototype.createBends = function()
-{
- var bends = [];
-
- // Source
- var bend = this.createHandleShape(0);
-
- this.initBend(bend);
- bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE;
- mxEvent.redirectMouseEvents(bend.node, this.graph, this.state);
- bends.push(bend);
-
- if (mxClient.IS_TOUCH)
- {
- bend.node.setAttribute('pointer-events', 'none');
- }
-
- var pts = this.state.absolutePoints;
-
- // Waypoints (segment handles)
- if (this.graph.isCellBendable(this.state.cell))
- {
- if (this.points == null)
- {
- this.points = [];
- }
-
- for (var i = 0; i < pts.length - 1; i++)
- {
- var bend = this.createVirtualBend();
- bends.push(bend);
- var horizontal = pts[i].x - pts[i + 1].x == 0;
- bend.node.style.cursor = (horizontal) ? 'col-resize' : 'row-resize';
- this.points.push(new mxPoint(0,0));
-
- if (mxClient.IS_TOUCH)
- {
- bend.node.setAttribute('pointer-events', 'none');
- }
- }
- }
-
- // Target
- var bend = this.createHandleShape(pts.length);
-
- this.initBend(bend);
- bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE;
- mxEvent.redirectMouseEvents(bend.node, this.graph, this.state);
- bends.push(bend);
-
- if (mxClient.IS_TOUCH)
- {
- bend.node.setAttribute('pointer-events', 'none');
- }
-
- return bends;
-};
-
-
-/**
- * Function: redrawInnerBends
- *
- * Updates the position of the custom bends.
- */
-mxEdgeSegmentHandler.prototype.redrawInnerBends = function(p0, pe)
-{
- if (this.graph.isCellBendable(this.state.cell))
- {
- var s = mxConstants.HANDLE_SIZE;
- var pts = this.state.absolutePoints;
-
- if (pts != null && pts.length > 1)
- {
- for (var i = 0; i < this.state.absolutePoints.length - 1; i++)
- {
- if (this.bends[i + 1] != null)
- {
- var p0 = pts[i];
- var pe = pts[i + 1];
- var pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2);
- this.bends[i+1].bounds = new mxRectangle(pt.x - s / 2, pt.y - s / 2, s, s);
- this.bends[i+1].reconfigure();
- this.bends[i+1].redraw();
- }
- }
- }
- }
-};
-
-/**
- * Function: connect
- *
- * Calls <refresh> after <mxEdgeHandler.connect>.
- */
-mxEdgeSegmentHandler.prototype.connect = function(edge, terminal, isSource, isClone, me)
-{
- mxEdgeHandler.prototype.connect.apply(this, arguments);
- this.refresh();
-};
-
-/**
- * Function: changeTerminalPoint
- *
- * Calls <refresh> after <mxEdgeHandler.changeTerminalPoint>.
- */
-mxEdgeSegmentHandler.prototype.changeTerminalPoint = function(edge, point, isSource)
-{
- mxEdgeHandler.prototype.changeTerminalPoint.apply(this, arguments);
- this.refresh();
-};
-
-/**
- * Function: changePoints
- *
- * Changes the points of the given edge to reflect the current state of the handler.
- */
-mxEdgeSegmentHandler.prototype.changePoints = function(edge, points)
-{
- points = [];
- var pts = this.abspoints;
-
- if (pts.length > 1)
- {
- var pt0 = pts[0];
- var pt1 = pts[1];
-
- for (var i = 2; i < pts.length; i++)
- {
- var pt2 = pts[i];
-
- if ((Math.round(pt0.x) != Math.round(pt1.x) ||
- Math.round(pt1.x) != Math.round(pt2.x)) &&
- (Math.round(pt0.y) != Math.round(pt1.y) ||
- Math.round(pt1.y) != Math.round(pt2.y)))
- {
- pt0 = pt1;
- pt1 = pt1.clone();
- this.convertPoint(pt1, false);
- points.push(pt1);
- }
-
- pt1 = pt2;
- }
- }
-
- mxElbowEdgeHandler.prototype.changePoints.apply(this, arguments);
- this.refresh();
-};
-
-/**
- * Function: refresh
- *
- * Refreshes the bends of this handler.
- */
-mxEdgeSegmentHandler.prototype.refresh = function()
-{
- if (this.bends != null)
- {
- for (var i = 0; i < this.bends.length; i++)
- {
- if (this.bends[i] != null)
- {
- this.bends[i].destroy();
- this.bends[i] = null;
- }
- }
-
- this.bends = this.createBends();
- }
-};
diff --git a/src/js/handler/mxElbowEdgeHandler.js b/src/js/handler/mxElbowEdgeHandler.js
deleted file mode 100644
index 85fbb06..0000000
--- a/src/js/handler/mxElbowEdgeHandler.js
+++ /dev/null
@@ -1,248 +0,0 @@
-/**
- * $Id: mxElbowEdgeHandler.js,v 1.43 2012-01-06 13:06:01 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxElbowEdgeHandler
- *
- * Graph event handler that reconnects edges and modifies control points and
- * the edge label location. Uses <mxTerminalMarker> for finding and
- * highlighting new source and target vertices. This handler is automatically
- * created in <mxGraph.createHandler>. It extends <mxEdgeHandler>.
- *
- * Constructor: mxEdgeHandler
- *
- * Constructs an edge handler for the specified <mxCellState>.
- *
- * Parameters:
- *
- * state - <mxCellState> of the cell to be modified.
- */
-function mxElbowEdgeHandler(state)
-{
- if (state != null)
- {
- this.state = state;
- this.init();
- }
-};
-
-/**
- * Extends mxEdgeHandler.
- */
-mxElbowEdgeHandler.prototype = new mxEdgeHandler();
-mxElbowEdgeHandler.prototype.constructor = mxElbowEdgeHandler;
-
-/**
- * Specifies if a double click on the middle handle should call
- * <mxGraph.flipEdge>. Default is true.
- */
-mxElbowEdgeHandler.prototype.flipEnabled = true;
-
-/**
- * Variable: doubleClickOrientationResource
- *
- * Specifies the resource key for the tooltip to be displayed on the single
- * control point for routed edges. If the resource for this key does not
- * exist then the value is used as the error message. Default is
- * 'doubleClickOrientation'.
- */
-mxElbowEdgeHandler.prototype.doubleClickOrientationResource =
- (mxClient.language != 'none') ? 'doubleClickOrientation' : '';
-
-/**
- * Function: createBends
- *
- * Overrides <mxEdgeHandler.createBends> to create custom bends.
- */
- mxElbowEdgeHandler.prototype.createBends = function()
- {
- var bends = [];
-
- // Source
- var bend = this.createHandleShape(0);
-
- this.initBend(bend);
- bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE;
- mxEvent.redirectMouseEvents(bend.node, this.graph, this.state);
- bends.push(bend);
-
- if (mxClient.IS_TOUCH)
- {
- bend.node.setAttribute('pointer-events', 'none');
- }
-
- // Virtual
- bends.push(this.createVirtualBend());
- this.points.push(new mxPoint(0,0));
-
- // Target
- bend = this.createHandleShape(2);
-
- this.initBend(bend);
- bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE;
- mxEvent.redirectMouseEvents(bend.node, this.graph, this.state);
- bends.push(bend);
-
- if (mxClient.IS_TOUCH)
- {
- bend.node.setAttribute('pointer-events', 'none');
- }
-
- return bends;
- };
-
-/**
- * Function: createVirtualBend
- *
- * Creates a virtual bend that supports double clicking and calls
- * <mxGraph.flipEdge>.
- */
-mxElbowEdgeHandler.prototype.createVirtualBend = function()
-{
- var bend = this.createHandleShape();
- this.initBend(bend);
-
- var crs = this.getCursorForBend();
- bend.node.style.cursor = crs;
-
- // Double-click changes edge style
- var dblClick = mxUtils.bind(this, function(evt)
- {
- if (!mxEvent.isConsumed(evt) &&
- this.flipEnabled)
- {
- this.graph.flipEdge(this.state.cell, evt);
- mxEvent.consume(evt);
- }
- });
-
- mxEvent.redirectMouseEvents(bend.node, this.graph, this.state,
- null, null, null, dblClick);
-
- if (!this.graph.isCellBendable(this.state.cell))
- {
- bend.node.style.visibility = 'hidden';
- }
-
- return bend;
-};
-
-/**
- * Function: getCursorForBend
- *
- * Returns the cursor to be used for the bend.
- */
-mxElbowEdgeHandler.prototype.getCursorForBend = function()
-{
- return (this.state.style[mxConstants.STYLE_EDGE] == mxEdgeStyle.TopToBottom ||
- this.state.style[mxConstants.STYLE_EDGE] == mxConstants.EDGESTYLE_TOPTOBOTTOM ||
- ((this.state.style[mxConstants.STYLE_EDGE] == mxEdgeStyle.ElbowConnector ||
- this.state.style[mxConstants.STYLE_EDGE] == mxConstants.EDGESTYLE_ELBOW)&&
- this.state.style[mxConstants.STYLE_ELBOW] == mxConstants.ELBOW_VERTICAL)) ?
- 'row-resize' : 'col-resize';
-};
-
-/**
- * Function: getTooltipForNode
- *
- * Returns the tooltip for the given node.
- */
-mxElbowEdgeHandler.prototype.getTooltipForNode = function(node)
-{
- var tip = null;
-
- if (this.bends != null &&
- this.bends[1] != null &&
- (node == this.bends[1].node ||
- node.parentNode == this.bends[1].node))
- {
- tip = this.doubleClickOrientationResource;
- tip = mxResources.get(tip) || tip; // translate
- }
-
- return tip;
-};
-
-/**
- * Function: convertPoint
- *
- * Converts the given point in-place from screen to unscaled, untranslated
- * graph coordinates and applies the grid.
- *
- * Parameters:
- *
- * point - <mxPoint> to be converted.
- * gridEnabled - Boolean that specifies if the grid should be applied.
- */
-mxElbowEdgeHandler.prototype.convertPoint = function(point, gridEnabled)
-{
- var scale = this.graph.getView().getScale();
- var tr = this.graph.getView().getTranslate();
- var origin = this.state.origin;
-
- if (gridEnabled)
- {
- point.x = this.graph.snap(point.x);
- point.y = this.graph.snap(point.y);
- }
-
- point.x = Math.round(point.x / scale - tr.x - origin.x);
- point.y = Math.round(point.y / scale - tr.y - origin.y);
-};
-
-/**
- * Function: redrawInnerBends
- *
- * Updates and redraws the inner bends.
- *
- * Parameters:
- *
- * p0 - <mxPoint> that represents the location of the first point.
- * pe - <mxPoint> that represents the location of the last point.
- */
-mxElbowEdgeHandler.prototype.redrawInnerBends = function(p0, pe)
-{
- var g = this.graph.getModel().getGeometry(this.state.cell);
- var pts = g.points;
-
- var pt = (pts != null) ? pts[0] : null;
-
- if (pt == null)
- {
- pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2);
- }
- else
- {
- pt = new mxPoint(this.graph.getView().scale*(pt.x +
- this.graph.getView().translate.x + this.state.origin.x),
- this.graph.getView().scale*(pt.y + this.graph.getView().translate.y +
- this.state.origin.y));
- }
-
- // Makes handle slightly bigger if the yellow label handle
- // exists and intersects this green handle
- var b = this.bends[1].bounds;
- var w = b.width;
- var h = b.height;
-
- if (this.handleImage == null)
- {
- w = mxConstants.HANDLE_SIZE;
- h = mxConstants.HANDLE_SIZE;
- }
-
- var bounds = new mxRectangle(pt.x - w / 2, pt.y - h / 2, w, h);
-
- if (this.handleImage == null && this.labelShape.node.style.visibility != 'hidden' &&
- mxUtils.intersects(bounds, this.labelShape.bounds))
- {
- w += 3;
- h += 3;
- bounds = new mxRectangle(pt.x - w / 2, pt.y - h / 2, w, h);
- }
-
- this.bends[1].bounds = bounds;
- this.bends[1].reconfigure();
- this.bends[1].redraw();
-};
diff --git a/src/js/handler/mxGraphHandler.js b/src/js/handler/mxGraphHandler.js
deleted file mode 100644
index 57e27a1..0000000
--- a/src/js/handler/mxGraphHandler.js
+++ /dev/null
@@ -1,916 +0,0 @@
-/**
- * $Id: mxGraphHandler.js,v 1.129 2012-04-13 12:53:30 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraphHandler
- *
- * Graph event handler that handles selection. Individual cells are handled
- * separately using <mxVertexHandler> or one of the edge handlers. These
- * handlers are created using <mxGraph.createHandler> in
- * <mxGraphSelectionModel.cellAdded>.
- *
- * To avoid the container to scroll a moved cell into view, set
- * <scrollAfterMove> to false.
- *
- * Constructor: mxGraphHandler
- *
- * Constructs an event handler that creates handles for the
- * selection cells.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- */
-function mxGraphHandler(graph)
-{
- this.graph = graph;
- this.graph.addMouseListener(this);
-
- // Repaints the handler after autoscroll
- this.panHandler = mxUtils.bind(this, function()
- {
- this.updatePreviewShape();
- });
-
- this.graph.addListener(mxEvent.PAN, this.panHandler);
-};
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxGraphHandler.prototype.graph = null;
-
-/**
- * Variable: maxCells
- *
- * Defines the maximum number of cells to paint subhandles
- * for. Default is 50 for Firefox and 20 for IE. Set this
- * to 0 if you want an unlimited number of handles to be
- * displayed. This is only recommended if the number of
- * cells in the graph is limited to a small number, eg.
- * 500.
- */
-mxGraphHandler.prototype.maxCells = (mxClient.IS_IE) ? 20 : 50;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxGraphHandler.prototype.enabled = true;
-
-/**
- * Variable: highlightEnabled
- *
- * Specifies if drop targets under the mouse should be enabled. Default is
- * true.
- */
-mxGraphHandler.prototype.highlightEnabled = true;
-
-/**
- * Variable: cloneEnabled
- *
- * Specifies if cloning by control-drag is enabled. Default is true.
- */
-mxGraphHandler.prototype.cloneEnabled = true;
-
-/**
- * Variable: moveEnabled
- *
- * Specifies if moving is enabled. Default is true.
- */
-mxGraphHandler.prototype.moveEnabled = true;
-
-/**
- * Variable: guidesEnabled
- *
- * Specifies if other cells should be used for snapping the right, center or
- * left side of the current selection. Default is false.
- */
-mxGraphHandler.prototype.guidesEnabled = false;
-
-/**
- * Variable: guide
- *
- * Holds the <mxGuide> instance that is used for alignment.
- */
-mxGraphHandler.prototype.guide = null;
-
-/**
- * Variable: currentDx
- *
- * Stores the x-coordinate of the current mouse move.
- */
-mxGraphHandler.prototype.currentDx = null;
-
-/**
- * Variable: currentDy
- *
- * Stores the y-coordinate of the current mouse move.
- */
-mxGraphHandler.prototype.currentDy = null;
-
-/**
- * Variable: updateCursor
- *
- * Specifies if a move cursor should be shown if the mouse is ove a movable
- * cell. Default is true.
- */
-mxGraphHandler.prototype.updateCursor = true;
-
-/**
- * Variable: selectEnabled
- *
- * Specifies if selecting is enabled. Default is true.
- */
-mxGraphHandler.prototype.selectEnabled = true;
-
-/**
- * Variable: removeCellsFromParent
- *
- * Specifies if cells may be moved out of their parents. Default is true.
- */
-mxGraphHandler.prototype.removeCellsFromParent = true;
-
-/**
- * Variable: connectOnDrop
- *
- * Specifies if drop events are interpreted as new connections if no other
- * drop action is defined. Default is false.
- */
-mxGraphHandler.prototype.connectOnDrop = false;
-
-/**
- * Variable: scrollOnMove
- *
- * Specifies if the view should be scrolled so that a moved cell is
- * visible. Default is true.
- */
-mxGraphHandler.prototype.scrollOnMove = true;
-
-/**
- * Variable: minimumSize
- *
- * Specifies the minimum number of pixels for the width and height of a
- * selection border. Default is 6.
- */
-mxGraphHandler.prototype.minimumSize = 6;
-
-/**
- * Variable: previewColor
- *
- * Specifies the color of the preview shape. Default is black.
- */
-mxGraphHandler.prototype.previewColor = 'black';
-
-/**
- * Variable: htmlPreview
- *
- * Specifies if the graph container should be used for preview. If this is used
- * then drop target detection relies entirely on <mxGraph.getCellAt> because
- * the HTML preview does not "let events through". Default is false.
- */
-mxGraphHandler.prototype.htmlPreview = false;
-
-/**
- * Variable: shape
- *
- * Reference to the <mxShape> that represents the preview.
- */
-mxGraphHandler.prototype.shape = null;
-
-/**
- * Variable: scaleGrid
- *
- * Specifies if the grid should be scaled. Default is false.
- */
-mxGraphHandler.prototype.scaleGrid = false;
-
-/**
- * Variable: crisp
- *
- * Specifies if the move preview should be rendered in crisp mode if applicable.
- * Default is true.
- */
-mxGraphHandler.prototype.crisp = true;
-
-/**
- * Function: isEnabled
- *
- * Returns <enabled>.
- */
-mxGraphHandler.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Sets <enabled>.
- */
-mxGraphHandler.prototype.setEnabled = function(value)
-{
- this.enabled = value;
-};
-
-/**
- * Function: isCloneEnabled
- *
- * Returns <cloneEnabled>.
- */
-mxGraphHandler.prototype.isCloneEnabled = function()
-{
- return this.cloneEnabled;
-};
-
-/**
- * Function: setCloneEnabled
- *
- * Sets <cloneEnabled>.
- *
- * Parameters:
- *
- * value - Boolean that specifies the new clone enabled state.
- */
-mxGraphHandler.prototype.setCloneEnabled = function(value)
-{
- this.cloneEnabled = value;
-};
-
-/**
- * Function: isMoveEnabled
- *
- * Returns <moveEnabled>.
- */
-mxGraphHandler.prototype.isMoveEnabled = function()
-{
- return this.moveEnabled;
-};
-
-/**
- * Function: setMoveEnabled
- *
- * Sets <moveEnabled>.
- */
-mxGraphHandler.prototype.setMoveEnabled = function(value)
-{
- this.moveEnabled = value;
-};
-
-/**
- * Function: isSelectEnabled
- *
- * Returns <selectEnabled>.
- */
-mxGraphHandler.prototype.isSelectEnabled = function()
-{
- return this.selectEnabled;
-};
-
-/**
- * Function: setSelectEnabled
- *
- * Sets <selectEnabled>.
- */
-mxGraphHandler.prototype.setSelectEnabled = function(value)
-{
- this.selectEnabled = value;
-};
-
-/**
- * Function: isRemoveCellsFromParent
- *
- * Returns <removeCellsFromParent>.
- */
-mxGraphHandler.prototype.isRemoveCellsFromParent = function()
-{
- return this.removeCellsFromParent;
-};
-
-/**
- * Function: setRemoveCellsFromParent
- *
- * Sets <removeCellsFromParent>.
- */
-mxGraphHandler.prototype.setRemoveCellsFromParent = function(value)
-{
- this.removeCellsFromParent = value;
-};
-
-/**
- * Function: getInitialCellForEvent
- *
- * Hook to return initial cell for the given event.
- */
-mxGraphHandler.prototype.getInitialCellForEvent = function(me)
-{
- return me.getCell();
-};
-
-/**
- * Function: isDelayedSelection
- *
- * Hook to return true for delayed selections.
- */
-mxGraphHandler.prototype.isDelayedSelection = function(cell)
-{
- return this.graph.isCellSelected(cell);
-};
-
-/**
- * Function: mouseDown
- *
- * Handles the event by selecing the given cell and creating a handle for
- * it. By consuming the event all subsequent events of the gesture are
- * redirected to this handler.
- */
-mxGraphHandler.prototype.mouseDown = function(sender, me)
-{
- if (!me.isConsumed() && this.isEnabled() && this.graph.isEnabled() &&
- !this.graph.isForceMarqueeEvent(me.getEvent()) && me.getState() != null)
- {
- var cell = this.getInitialCellForEvent(me);
- this.cell = null;
- this.delayedSelection = this.isDelayedSelection(cell);
-
- if (this.isSelectEnabled() && !this.delayedSelection)
- {
- this.graph.selectCellForEvent(cell, me.getEvent());
- }
-
- if (this.isMoveEnabled())
- {
- var model = this.graph.model;
- var geo = model.getGeometry(cell);
-
- if (this.graph.isCellMovable(cell) && ((!model.isEdge(cell) || this.graph.getSelectionCount() > 1 ||
- (geo.points != null && geo.points.length > 0) || model.getTerminal(cell, true) == null ||
- model.getTerminal(cell, false) == null) || this.graph.allowDanglingEdges ||
- (this.graph.isCloneEvent(me.getEvent()) && this.graph.isCellsCloneable())))
- {
- this.start(cell, me.getX(), me.getY());
- }
-
- this.cellWasClicked = true;
-
- // Workaround for SELECT element not working in Webkit, this blocks moving
- // of the cell if the select element is clicked in Safari which is needed
- // because Safari doesn't seem to route the subsequent mouseUp event via
- // this handler which leads to an inconsistent state (no reset called).
- // Same for cellWasClicked which will block clearing the selection when
- // clicking the background after clicking on the SELECT element in Safari.
- if ((!mxClient.IS_SF && !mxClient.IS_GC) || me.getSource().nodeName != 'SELECT')
- {
- me.consume();
- }
- else if (mxClient.IS_SF && me.getSource().nodeName == 'SELECT')
- {
- this.cellWasClicked = false;
- this.first = null;
- }
- }
- }
-};
-
-/**
- * Function: getGuideStates
- *
- * Creates an array of cell states which should be used as guides.
- */
-mxGraphHandler.prototype.getGuideStates = function()
-{
- var parent = this.graph.getDefaultParent();
- var model = this.graph.getModel();
-
- var filter = mxUtils.bind(this, function(cell)
- {
- return this.graph.view.getState(cell) != null &&
- model.isVertex(cell) &&
- model.getGeometry(cell) != null &&
- !model.getGeometry(cell).relative;
- });
-
- return this.graph.view.getCellStates(model.filterDescendants(filter, parent));
-};
-
-/**
- * Function: getCells
- *
- * Returns the cells to be modified by this handler. This implementation
- * returns all selection cells that are movable, or the given initial cell if
- * the given cell is not selected and movable. This handles the case of moving
- * unselectable or unselected cells.
- *
- * Parameters:
- *
- * initialCell - <mxCell> that triggered this handler.
- */
-mxGraphHandler.prototype.getCells = function(initialCell)
-{
- if (!this.delayedSelection && this.graph.isCellMovable(initialCell))
- {
- return [initialCell];
- }
- else
- {
- return this.graph.getMovableCells(this.graph.getSelectionCells());
- }
-};
-
-/**
- * Function: getPreviewBounds
- *
- * Returns the <mxRectangle> used as the preview bounds for
- * moving the given cells.
- */
-mxGraphHandler.prototype.getPreviewBounds = function(cells)
-{
- var bounds = this.graph.getView().getBounds(cells);
-
- if (bounds != null)
- {
- if (bounds.width < this.minimumSize)
- {
- var dx = this.minimumSize - bounds.width;
- bounds.x -= dx / 2;
- bounds.width = this.minimumSize;
- }
-
- if (bounds.height < this.minimumSize)
- {
- var dy = this.minimumSize - bounds.height;
- bounds.y -= dy / 2;
- bounds.height = this.minimumSize;
- }
- }
-
- return bounds;
-};
-
-/**
- * Function: createPreviewShape
- *
- * Creates the shape used to draw the preview for the given bounds.
- */
-mxGraphHandler.prototype.createPreviewShape = function(bounds)
-{
- var shape = new mxRectangleShape(bounds, null, this.previewColor);
- shape.isDashed = true;
- shape.crisp = this.crisp;
-
- if (this.htmlPreview)
- {
- shape.dialect = mxConstants.DIALECT_STRICTHTML;
- shape.init(this.graph.container);
- }
- else
- {
- // Makes sure to use either VML or SVG shapes in order to implement
- // event-transparency on the background area of the rectangle since
- // HTML shapes do not let mouseevents through even when transparent
- shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- shape.init(this.graph.getView().getOverlayPane());
-
- // Event-transparency
- if (shape.dialect == mxConstants.DIALECT_SVG)
- {
- shape.node.setAttribute('style', 'pointer-events:none;');
- }
- else
- {
- shape.node.style.background = '';
- }
- }
-
- return shape;
-};
-
-/**
- * Function: start
- *
- * Starts the handling of the mouse gesture.
- */
-mxGraphHandler.prototype.start = function(cell, x, y)
-{
- this.cell = cell;
- this.first = mxUtils.convertPoint(this.graph.container, x, y);
- this.cells = this.getCells(this.cell);
- this.bounds = this.getPreviewBounds(this.cells);
-
- if (this.guidesEnabled)
- {
- this.guide = new mxGuide(this.graph, this.getGuideStates());
- }
-};
-
-/**
- * Function: useGuidesForEvent
- *
- * Returns true if the guides should be used for the given <mxMouseEvent>.
- * This implementation returns <mxGuide.isEnabledForEvent>.
- */
-mxGraphHandler.prototype.useGuidesForEvent = function(me)
-{
- return (this.guide != null) ? this.guide.isEnabledForEvent(me.getEvent()) : true;
-};
-
-
-/**
- * Function: snap
- *
- * Snaps the given vector to the grid and returns the given mxPoint instance.
- */
-mxGraphHandler.prototype.snap = function(vector)
-{
- var scale = (this.scaleGrid) ? this.graph.view.scale : 1;
-
- vector.x = this.graph.snap(vector.x / scale) * scale;
- vector.y = this.graph.snap(vector.y / scale) * scale;
-
- return vector;
-};
-
-/**
- * Function: mouseMove
- *
- * Handles the event by highlighting possible drop targets and updating the
- * preview.
- */
-mxGraphHandler.prototype.mouseMove = function(sender, me)
-{
- var graph = this.graph;
-
- if (!me.isConsumed() && graph.isMouseDown && this.cell != null &&
- this.first != null && this.bounds != null)
- {
- var point = mxUtils.convertPoint(graph.container, me.getX(), me.getY());
- var dx = point.x - this.first.x;
- var dy = point.y - this.first.y;
- var tol = graph.tolerance;
-
- if (this.shape!= null || Math.abs(dx) > tol || Math.abs(dy) > tol)
- {
- // Highlight is used for highlighting drop targets
- if (this.highlight == null)
- {
- this.highlight = new mxCellHighlight(this.graph,
- mxConstants.DROP_TARGET_COLOR, 3);
- }
-
- if (this.shape == null)
- {
- this.shape = this.createPreviewShape(this.bounds);
- }
-
- var gridEnabled = graph.isGridEnabledEvent(me.getEvent());
- var hideGuide = true;
-
- if (this.guide != null && this.useGuidesForEvent(me))
- {
- var delta = this.guide.move(this.bounds, new mxPoint(dx, dy), gridEnabled);
- hideGuide = false;
- dx = delta.x;
- dy = delta.y;
- }
- else if (gridEnabled)
- {
- var trx = graph.getView().translate;
- var scale = graph.getView().scale;
-
- var tx = this.bounds.x - (graph.snap(this.bounds.x / scale - trx.x) + trx.x) * scale;
- var ty = this.bounds.y - (graph.snap(this.bounds.y / scale - trx.y) + trx.y) * scale;
- var v = this.snap(new mxPoint(dx, dy));
-
- dx = v.x - tx;
- dy = v.y - ty;
- }
-
- if (this.guide != null && hideGuide)
- {
- this.guide.hide();
- }
-
- // Constrained movement if shift key is pressed
- if (graph.isConstrainedEvent(me.getEvent()))
- {
- if (Math.abs(dx) > Math.abs(dy))
- {
- dy = 0;
- }
- else
- {
- dx = 0;
- }
- }
-
- this.currentDx = dx;
- this.currentDy = dy;
- this.updatePreviewShape();
-
- var target = null;
- var cell = me.getCell();
-
- if (graph.isDropEnabled() && this.highlightEnabled)
- {
- // Contains a call to getCellAt to find the cell under the mouse
- target = graph.getDropTarget(this.cells, me.getEvent(), cell);
- }
-
- // Checks if parent is dropped into child
- var parent = target;
- var model = graph.getModel();
-
- while (parent != null && parent != this.cells[0])
- {
- parent = model.getParent(parent);
- }
-
- var clone = graph.isCloneEvent(me.getEvent()) && graph.isCellsCloneable() && this.isCloneEnabled();
- var state = graph.getView().getState(target);
- var highlight = false;
-
- if (state != null && parent == null && (model.getParent(this.cell) != target || clone))
- {
- if (this.target != target)
- {
- this.target = target;
- this.setHighlightColor(mxConstants.DROP_TARGET_COLOR);
- }
-
- highlight = true;
- }
- else
- {
- this.target = null;
-
- if (this.connectOnDrop && cell != null && this.cells.length == 1 &&
- graph.getModel().isVertex(cell) && graph.isCellConnectable(cell))
- {
- state = graph.getView().getState(cell);
-
- if (state != null)
- {
- var error = graph.getEdgeValidationError(null, this.cell, cell);
- var color = (error == null) ?
- mxConstants.VALID_COLOR :
- mxConstants.INVALID_CONNECT_TARGET_COLOR;
- this.setHighlightColor(color);
- highlight = true;
- }
- }
- }
-
- if (state != null && highlight)
- {
- this.highlight.highlight(state);
- }
- else
- {
- this.highlight.hide();
- }
- }
-
- me.consume();
-
- // Cancels the bubbling of events to the container so
- // that the droptarget is not reset due to an mouseMove
- // fired on the container with no associated state.
- mxEvent.consume(me.getEvent());
- }
- else if ((this.isMoveEnabled() || this.isCloneEnabled()) && this.updateCursor &&
- !me.isConsumed() && me.getState() != null && !graph.isMouseDown)
- {
- var cursor = graph.getCursorForCell(me.getCell());
-
- if (cursor == null && graph.isEnabled() && graph.isCellMovable(me.getCell()))
- {
- if (graph.getModel().isEdge(me.getCell()))
- {
- cursor = mxConstants.CURSOR_MOVABLE_EDGE;
- }
- else
- {
- cursor = mxConstants.CURSOR_MOVABLE_VERTEX;
- }
- }
-
- me.getState().setCursor(cursor);
- me.consume();
- }
-};
-
-/**
- * Function: updatePreviewShape
- *
- * Updates the bounds of the preview shape.
- */
-mxGraphHandler.prototype.updatePreviewShape = function()
-{
- if (this.shape != null)
- {
- this.shape.bounds = new mxRectangle(this.bounds.x + this.currentDx - this.graph.panDx,
- this.bounds.y + this.currentDy - this.graph.panDy, this.bounds.width, this.bounds.height);
- this.shape.redraw();
- }
-};
-
-/**
- * Function: setHighlightColor
- *
- * Sets the color of the rectangle used to highlight drop targets.
- *
- * Parameters:
- *
- * color - String that represents the new highlight color.
- */
-mxGraphHandler.prototype.setHighlightColor = function(color)
-{
- if (this.highlight != null)
- {
- this.highlight.setHighlightColor(color);
- }
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event by applying the changes to the selection cells.
- */
-mxGraphHandler.prototype.mouseUp = function(sender, me)
-{
- if (!me.isConsumed())
- {
- var graph = this.graph;
-
- if (this.cell != null && this.first != null && this.shape != null &&
- this.currentDx != null && this.currentDy != null)
- {
- var scale = graph.getView().scale;
- var clone = graph.isCloneEvent(me.getEvent()) && graph.isCellsCloneable() && this.isCloneEnabled();
- var dx = this.currentDx / scale;
- var dy = this.currentDy / scale;
-
- var cell = me.getCell();
-
- if (this.connectOnDrop && this.target == null && cell != null && graph.getModel().isVertex(cell) &&
- graph.isCellConnectable(cell) && graph.isEdgeValid(null, this.cell, cell))
- {
- graph.connectionHandler.connect(this.cell, cell, me.getEvent());
- }
- else
- {
- var target = this.target;
-
- if (graph.isSplitEnabled() && graph.isSplitTarget(target, this.cells, me.getEvent()))
- {
- graph.splitEdge(target, this.cells, null, dx, dy);
- }
- else
- {
- this.moveCells(this.cells, dx, dy, clone, this.target, me.getEvent());
- }
- }
- }
- else if (this.isSelectEnabled() && this.delayedSelection && this.cell != null)
- {
- this.selectDelayed(me);
- }
- }
-
- // Consumes the event if a cell was initially clicked
- if (this.cellWasClicked)
- {
- me.consume();
- }
-
- this.reset();
-};
-
-/**
- * Function: selectDelayed
- *
- * Implements the delayed selection for the given mouse event.
- */
-mxGraphHandler.prototype.selectDelayed = function(me)
-{
- this.graph.selectCellForEvent(this.cell, me.getEvent());
-};
-
-/**
- * Function: reset
- *
- * Resets the state of this handler.
- */
-mxGraphHandler.prototype.reset = function()
-{
- this.destroyShapes();
- this.cellWasClicked = false;
- this.delayedSelection = false;
- this.currentDx = null;
- this.currentDy = null;
- this.guides = null;
- this.first = null;
- this.cell = null;
- this.target = null;
-};
-
-/**
- * Function: shouldRemoveCellsFromParent
- *
- * Returns true if the given cells should be removed from the parent for the specified
- * mousereleased event.
- */
-mxGraphHandler.prototype.shouldRemoveCellsFromParent = function(parent, cells, evt)
-{
- if (this.graph.getModel().isVertex(parent))
- {
- var pState = this.graph.getView().getState(parent);
- var pt = mxUtils.convertPoint(this.graph.container,
- mxEvent.getClientX(evt), mxEvent.getClientY(evt));
-
- return pState != null && !mxUtils.contains(pState, pt.x, pt.y);
- }
-
- return false;
-};
-
-/**
- * Function: moveCells
- *
- * Moves the given cells by the specified amount.
- */
-mxGraphHandler.prototype.moveCells = function(cells, dx, dy, clone, target, evt)
-{
- if (clone)
- {
- cells = this.graph.getCloneableCells(cells);
- }
-
- // Removes cells from parent
- if (target == null && this.isRemoveCellsFromParent() &&
- this.shouldRemoveCellsFromParent(this.graph.getModel().getParent(this.cell), cells, evt))
- {
- target = this.graph.getDefaultParent();
- }
-
- // Passes all selected cells in order to correctly clone or move into
- // the target cell. The method checks for each cell if its movable.
- cells = this.graph.moveCells(cells, dx - this.graph.panDx / this.graph.view.scale,
- dy - this.graph.panDy / this.graph.view.scale, clone, target, evt);
-
- if (this.isSelectEnabled() && this.scrollOnMove)
- {
- this.graph.scrollCellToVisible(cells[0]);
- }
-
- // Selects the new cells if cells have been cloned
- if (clone)
- {
- this.graph.setSelectionCells(cells);
- }
-};
-
-/**
- * Function: destroyShapes
- *
- * Destroy the preview and highlight shapes.
- */
-mxGraphHandler.prototype.destroyShapes = function()
-{
- // Destroys the preview dashed rectangle
- if (this.shape != null)
- {
- this.shape.destroy();
- this.shape = null;
- }
-
- if (this.guide != null)
- {
- this.guide.destroy();
- this.guide = null;
- }
-
- // Destroys the drop target highlight
- if (this.highlight != null)
- {
- this.highlight.destroy();
- this.highlight = null;
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes.
- */
-mxGraphHandler.prototype.destroy = function()
-{
- this.graph.removeMouseListener(this);
- this.graph.removeListener(this.panHandler);
- this.destroyShapes();
-};
diff --git a/src/js/handler/mxKeyHandler.js b/src/js/handler/mxKeyHandler.js
deleted file mode 100644
index cc07e51..0000000
--- a/src/js/handler/mxKeyHandler.js
+++ /dev/null
@@ -1,402 +0,0 @@
-/**
- * $Id: mxKeyHandler.js,v 1.48 2012-03-30 08:30:41 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxKeyHandler
- *
- * Event handler that listens to keystroke events. This is not a singleton,
- * however, it is normally only required once if the target is the document
- * element (default).
- *
- * This handler installs a key event listener in the topmost DOM node and
- * processes all events that originate from descandants of <mxGraph.container>
- * or from the topmost DOM node. The latter means that all unhandled keystrokes
- * are handled by this object regardless of the focused state of the <graph>.
- *
- * Example:
- *
- * The following example creates a key handler that listens to the delete key
- * (46) and deletes the selection cells if the graph is enabled.
- *
- * (code)
- * var keyHandler = new mxKeyHandler(graph);
- * keyHandler.bindKey(46, function(evt)
- * {
- * if (graph.isEnabled())
- * {
- * graph.removeCells();
- * }
- * });
- * (end)
- *
- * Keycodes:
- *
- * See http://tinyurl.com/yp8jgl or http://tinyurl.com/229yqw for a list of
- * keycodes or install a key event listener into the document element and print
- * the key codes of the respective events to the console.
- *
- * To support the Command key and the Control key on the Mac, the following
- * code can be used.
- *
- * (code)
- * keyHandler.getFunction = function(evt)
- * {
- * if (evt != null)
- * {
- * return (mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey)) ? this.controlKeys[evt.keyCode] : this.normalKeys[evt.keyCode];
- * }
- *
- * return null;
- * };
- * (end)
- *
- * Constructor: mxKeyHandler
- *
- * Constructs an event handler that executes functions bound to specific
- * keystrokes.
- *
- * Parameters:
- *
- * graph - Reference to the associated <mxGraph>.
- * target - Optional reference to the event target. If null, the document
- * element is used as the event target, that is, the object where the key
- * event listener is installed.
- */
-function mxKeyHandler(graph, target)
-{
- if (graph != null)
- {
- this.graph = graph;
- this.target = target || document.documentElement;
-
- // Creates the arrays to map from keycodes to functions
- this.normalKeys = [];
- this.shiftKeys = [];
- this.controlKeys = [];
- this.controlShiftKeys = [];
-
- // Installs the keystroke listener in the target
- mxEvent.addListener(this.target, "keydown",
- mxUtils.bind(this, function(evt)
- {
- this.keyDown(evt);
- })
- );
-
- // Automatically deallocates memory in IE
- if (mxClient.IS_IE)
- {
- mxEvent.addListener(window, 'unload',
- mxUtils.bind(this, function()
- {
- this.destroy();
- })
- );
- }
- }
-};
-
-/**
- * Variable: graph
- *
- * Reference to the <mxGraph> associated with this handler.
- */
-mxKeyHandler.prototype.graph = null;
-
-/**
- * Variable: target
- *
- * Reference to the target DOM, that is, the DOM node where the key event
- * listeners are installed.
- */
-mxKeyHandler.prototype.target = null;
-
-/**
- * Variable: normalKeys
- *
- * Maps from keycodes to functions for non-pressed control keys.
- */
-mxKeyHandler.prototype.normalKeys = null;
-
-/**
- * Variable: shiftKeys
- *
- * Maps from keycodes to functions for pressed shift keys.
- */
-mxKeyHandler.prototype.shiftKeys = null;
-
-/**
- * Variable: controlKeys
- *
- * Maps from keycodes to functions for pressed control keys.
- */
-mxKeyHandler.prototype.controlKeys = null;
-
-/**
- * Variable: controlShiftKeys
- *
- * Maps from keycodes to functions for pressed control and shift keys.
- */
-mxKeyHandler.prototype.controlShiftKeys = null;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxKeyHandler.prototype.enabled = true;
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation returns
- * <enabled>.
- */
-mxKeyHandler.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling by updating <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxKeyHandler.prototype.setEnabled = function(enabled)
-{
- this.enabled = enabled;
-};
-
-/**
- * Function: bindKey
- *
- * Binds the specified keycode to the given function. This binding is used
- * if the control key is not pressed.
- *
- * Parameters:
- *
- * code - Integer that specifies the keycode.
- * funct - JavaScript function that takes the key event as an argument.
- */
-mxKeyHandler.prototype.bindKey = function(code, funct)
-{
- this.normalKeys[code] = funct;
-};
-
-/**
- * Function: bindShiftKey
- *
- * Binds the specified keycode to the given function. This binding is used
- * if the shift key is pressed.
- *
- * Parameters:
- *
- * code - Integer that specifies the keycode.
- * funct - JavaScript function that takes the key event as an argument.
- */
-mxKeyHandler.prototype.bindShiftKey = function(code, funct)
-{
- this.shiftKeys[code] = funct;
-};
-
-/**
- * Function: bindControlKey
- *
- * Binds the specified keycode to the given function. This binding is used
- * if the control key is pressed.
- *
- * Parameters:
- *
- * code - Integer that specifies the keycode.
- * funct - JavaScript function that takes the key event as an argument.
- */
-mxKeyHandler.prototype.bindControlKey = function(code, funct)
-{
- this.controlKeys[code] = funct;
-};
-
-/**
- * Function: bindControlShiftKey
- *
- * Binds the specified keycode to the given function. This binding is used
- * if the control and shift key are pressed.
- *
- * Parameters:
- *
- * code - Integer that specifies the keycode.
- * funct - JavaScript function that takes the key event as an argument.
- */
-mxKeyHandler.prototype.bindControlShiftKey = function(code, funct)
-{
- this.controlShiftKeys[code] = funct;
-};
-
-/**
- * Function: isControlDown
- *
- * Returns true if the control key is pressed. This uses <mxEvent.isControlDown>.
- *
- * Parameters:
- *
- * evt - Key event whose control key pressed state should be returned.
- */
-mxKeyHandler.prototype.isControlDown = function(evt)
-{
- return mxEvent.isControlDown(evt);
-};
-
-/**
- * Function: getFunction
- *
- * Returns the function associated with the given key event or null if no
- * function is associated with the given event.
- *
- * Parameters:
- *
- * evt - Key event whose associated function should be returned.
- */
-mxKeyHandler.prototype.getFunction = function(evt)
-{
- if (evt != null)
- {
- if (this.isControlDown(evt))
- {
- if (mxEvent.isShiftDown(evt))
- {
- return this.controlShiftKeys[evt.keyCode];
- }
- else
- {
- return this.controlKeys[evt.keyCode];
- }
- }
- else
- {
- if (mxEvent.isShiftDown(evt))
- {
- return this.shiftKeys[evt.keyCode];
- }
- else
- {
- return this.normalKeys[evt.keyCode];
- }
- }
- }
-
- return null;
-};
-
-/**
- * Function: isGraphEvent
- *
- * Returns true if the event should be processed by this handler, that is,
- * if the event source is either the target, one of its direct children, a
- * descendant of the <mxGraph.container>, or the <mxGraph.cellEditor> of the
- * <graph>.
- *
- * Parameters:
- *
- * evt - Key event that represents the keystroke.
- */
-mxKeyHandler.prototype.isGraphEvent = function(evt)
-{
- var source = mxEvent.getSource(evt);
-
- // Accepts events from the target object or
- // in-place editing inside graph
- if ((source == this.target || source.parentNode == this.target) ||
- (this.graph.cellEditor != null && source == this.graph.cellEditor.textarea))
- {
- return true;
- }
-
- // Accepts events from inside the container
- var elt = source;
-
- while (elt != null)
- {
- if (elt == this.graph.container)
- {
- return true;
- }
-
- elt = elt.parentNode;
- }
-
- return false;
-};
-
-/**
- * Function: keyDown
- *
- * Handles the event by invoking the function bound to the respective
- * keystroke if <mxGraph.isEnabled>, <isEnabled> and <isGraphEvent> all
- * return true for the given event and <mxGraph.isEditing> returns false.
- * If the graph is editing only the <enter> and <escape> cases are handled
- * by calling the respective hooks.
- *
- * Parameters:
- *
- * evt - Key event that represents the keystroke.
- */
-mxKeyHandler.prototype.keyDown = function(evt)
-{
- if (this.graph.isEnabled() && !mxEvent.isConsumed(evt) &&
- this.isGraphEvent(evt) && this.isEnabled())
- {
- // Cancels the editing if escape is pressed
- if (evt.keyCode == 27 /* Escape */)
- {
- this.escape(evt);
- }
-
- // Invokes the function for the keystroke
- else if (!this.graph.isEditing())
- {
- var boundFunction = this.getFunction(evt);
-
- if (boundFunction != null)
- {
- boundFunction(evt);
- mxEvent.consume(evt);
- }
- }
- }
-};
-
-/**
- * Function: escape
- *
- * Hook to process ESCAPE keystrokes. This implementation invokes
- * <mxGraph.stopEditing> to cancel the current editing, connecting
- * and/or other ongoing modifications.
- *
- * Parameters:
- *
- * evt - Key event that represents the keystroke. Possible keycode in this
- * case is 27 (ESCAPE).
- */
-mxKeyHandler.prototype.escape = function(evt)
-{
- if (this.graph.isEscapeEnabled())
- {
- this.graph.escape(evt);
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its references into the DOM. This does
- * normally not need to be called, it is called automatically when the
- * window unloads (in IE).
- */
-mxKeyHandler.prototype.destroy = function()
-{
- this.target = null;
-};
diff --git a/src/js/handler/mxPanningHandler.js b/src/js/handler/mxPanningHandler.js
deleted file mode 100644
index b388144..0000000
--- a/src/js/handler/mxPanningHandler.js
+++ /dev/null
@@ -1,390 +0,0 @@
-/**
- * $Id: mxPanningHandler.js,v 1.79 2012-07-17 14:37:41 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxPanningHandler
- *
- * Event handler that pans and creates popupmenus. To use the left
- * mousebutton for panning without interfering with cell moving and
- * resizing, use <isUseLeftButton> and <isIgnoreCell>. For grid size
- * steps while panning, use <useGrid>. This handler is built-into
- * <mxGraph.panningHandler> and enabled using <mxGraph.setPanning>.
- *
- * Constructor: mxPanningHandler
- *
- * Constructs an event handler that creates a <mxPopupMenu>
- * and pans the graph.
- *
- * Event: mxEvent.PAN_START
- *
- * Fires when the panning handler changes its <active> state to true. The
- * <code>event</code> property contains the corresponding <mxMouseEvent>.
- *
- * Event: mxEvent.PAN
- *
- * Fires while handle is processing events. The <code>event</code> property contains
- * the corresponding <mxMouseEvent>.
- *
- * Event: mxEvent.PAN_END
- *
- * Fires when the panning handler changes its <active> state to false. The
- * <code>event</code> property contains the corresponding <mxMouseEvent>.
- */
-function mxPanningHandler(graph, factoryMethod)
-{
- if (graph != null)
- {
- this.graph = graph;
- this.factoryMethod = factoryMethod;
- this.graph.addMouseListener(this);
- this.init();
- }
-};
-
-/**
- * Extends mxPopupMenu.
- */
-mxPanningHandler.prototype = new mxPopupMenu();
-mxPanningHandler.prototype.constructor = mxPanningHandler;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxPanningHandler.prototype.graph = null;
-
-/**
- * Variable: usePopupTrigger
- *
- * Specifies if the <isPopupTrigger> should also be used for panning. To
- * avoid conflicts, the panning is only activated if the mouse was moved
- * more than <mxGraph.tolerance>, otherwise, a single click is assumed
- * and the popupmenu is displayed. Default is true.
- */
-mxPanningHandler.prototype.usePopupTrigger = true;
-
-/**
- * Variable: useLeftButtonForPanning
- *
- * Specifies if panning should be active for the left mouse button.
- * Setting this to true may conflict with <mxRubberband>. Default is false.
- */
-mxPanningHandler.prototype.useLeftButtonForPanning = false;
-
-/**
- * Variable: selectOnPopup
- *
- * Specifies if cells should be selected if a popupmenu is displayed for
- * them. Default is true.
- */
-mxPanningHandler.prototype.selectOnPopup = true;
-
-/**
- * Variable: clearSelectionOnBackground
- *
- * Specifies if cells should be deselected if a popupmenu is displayed for
- * the diagram background. Default is true.
- */
-mxPanningHandler.prototype.clearSelectionOnBackground = true;
-
-/**
- * Variable: ignoreCell
- *
- * Specifies if panning should be active even if there is a cell under the
- * mousepointer. Default is false.
- */
-mxPanningHandler.prototype.ignoreCell = false;
-
-/**
- * Variable: previewEnabled
- *
- * Specifies if the panning should be previewed. Default is true.
- */
-mxPanningHandler.prototype.previewEnabled = true;
-
-/**
- * Variable: useGrid
- *
- * Specifies if the panning steps should be aligned to the grid size.
- * Default is false.
- */
-mxPanningHandler.prototype.useGrid = false;
-
-/**
- * Variable: panningEnabled
- *
- * Specifies if panning should be enabled. Default is true.
- */
-mxPanningHandler.prototype.panningEnabled = true;
-
-/**
- * Function: isPanningEnabled
- *
- * Returns <panningEnabled>.
- */
-mxPanningHandler.prototype.isPanningEnabled = function()
-{
- return this.panningEnabled;
-};
-
-/**
- * Function: setPanningEnabled
- *
- * Sets <panningEnabled>.
- */
-mxPanningHandler.prototype.setPanningEnabled = function(value)
-{
- this.panningEnabled = value;
-};
-
-/**
- * Function: init
- *
- * Initializes the shapes required for this vertex handler.
- */
-mxPanningHandler.prototype.init = function()
-{
- // Supercall
- mxPopupMenu.prototype.init.apply(this);
-
- // Hides the tooltip if the mouse is over
- // the context menu
- mxEvent.addListener(this.div, (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove',
- mxUtils.bind(this, function(evt)
- {
- this.graph.tooltipHandler.hide();
- })
- );
-};
-
-/**
- * Function: isPanningTrigger
- *
- * Returns true if the given event is a panning trigger for the optional
- * given cell. This returns true if control-shift is pressed or if
- * <usePopupTrigger> is true and the event is a popup trigger.
- */
-mxPanningHandler.prototype.isPanningTrigger = function(me)
-{
- var evt = me.getEvent();
-
- return (this.useLeftButtonForPanning && (this.ignoreCell || me.getState() == null) &&
- mxEvent.isLeftMouseButton(evt)) || (mxEvent.isControlDown(evt) &&
- mxEvent.isShiftDown(evt)) || (this.usePopupTrigger &&
- mxEvent.isPopupTrigger(evt));
-};
-
-/**
- * Function: mouseDown
- *
- * Handles the event by initiating the panning. By consuming the event all
- * subsequent events of the gesture are redirected to this handler.
- */
-mxPanningHandler.prototype.mouseDown = function(sender, me)
-{
- if (!me.isConsumed() && this.isEnabled())
- {
- // Hides the popupmenu if is is being displayed
- this.hideMenu();
-
- this.dx0 = -this.graph.container.scrollLeft;
- this.dy0 = -this.graph.container.scrollTop;
-
- // Checks the event triggers to panning and popupmenu
- this.popupTrigger = this.isPopupTrigger(me);
- this.panningTrigger = this.isPanningEnabled() &&
- this.isPanningTrigger(me);
-
- // Stores the location of the trigger event
- this.startX = me.getX();
- this.startY = me.getY();
-
- // Displays popup menu on Mac after the mouse was released
- if (this.panningTrigger)
- {
- this.consumePanningTrigger(me);
- }
- }
-};
-
-/**
- * Function: consumePanningTrigger
- *
- * Consumes the given <mxMouseEvent> if it was a panning trigger in
- * <mouseDown>. The default is to invoke <mxMouseEvent.consume>. Note that this
- * will block any further event processing. If you haven't disabled built-in
- * context menus and require immediate selection of the cell on mouseDown in
- * Safari and/or on the Mac, then use the following code:
- *
- * (code)
- * mxPanningHandler.prototype.consumePanningTrigger = function(me)
- * {
- * if (me.evt.preventDefault)
- * {
- * me.evt.preventDefault();
- * }
- *
- * // Stops event processing in IE
- * me.evt.returnValue = false;
- *
- * // Sets local consumed state
- * if (!mxClient.IS_SF && !mxClient.IS_MAC)
- * {
- * me.consumed = true;
- * }
- * };
- * (end)
- */
-mxPanningHandler.prototype.consumePanningTrigger = function(me)
-{
- me.consume();
-};
-
-/**
- * Function: mouseMove
- *
- * Handles the event by updating the panning on the graph.
- */
-mxPanningHandler.prototype.mouseMove = function(sender, me)
-{
- var dx = me.getX() - this.startX;
- var dy = me.getY() - this.startY;
-
- if (this.active)
- {
- if (this.previewEnabled)
- {
- // Applies the grid to the panning steps
- if (this.useGrid)
- {
- dx = this.graph.snap(dx);
- dy = this.graph.snap(dy);
- }
-
- this.graph.panGraph(dx + this.dx0, dy + this.dy0);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.PAN, 'event', me));
- me.consume();
- }
- else if (this.panningTrigger)
- {
- var tmp = this.active;
-
- // Panning is activated only if the mouse is moved
- // beyond the graph tolerance
- this.active = Math.abs(dx) > this.graph.tolerance ||
- Math.abs(dy) > this.graph.tolerance;
-
- if (!tmp && this.active)
- {
- this.fireEvent(new mxEventObject(mxEvent.PAN_START, 'event', me));
- }
- }
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event by setting the translation on the view or showing the
- * popupmenu.
- */
-mxPanningHandler.prototype.mouseUp = function(sender, me)
-{
- // Shows popup menu if mouse was not moved
- var dx = Math.abs(me.getX() - this.startX);
- var dy = Math.abs(me.getY() - this.startY);
-
- if (this.active)
- {
- if (!this.graph.useScrollbarsForPanning || !mxUtils.hasScrollbars(this.graph.container))
- {
- dx = me.getX() - this.startX;
- dy = me.getY() - this.startY;
-
- // Applies the grid to the panning steps
- if (this.useGrid)
- {
- dx = this.graph.snap(dx);
- dy = this.graph.snap(dy);
- }
-
- var scale = this.graph.getView().scale;
- var t = this.graph.getView().translate;
-
- this.graph.panGraph(0, 0);
- this.panGraph(t.x + dx / scale, t.y + dy / scale);
- }
-
- this.active = false;
- this.fireEvent(new mxEventObject(mxEvent.PAN_END, 'event', me));
- me.consume();
- }
- else if (this.popupTrigger)
- {
- if (dx < this.graph.tolerance && dy < this.graph.tolerance)
- {
- var cell = this.getCellForPopupEvent(me);
-
- // Selects the cell for which the context menu is being displayed
- if (this.graph.isEnabled() && this.selectOnPopup &&
- cell != null && !this.graph.isCellSelected(cell))
- {
- this.graph.setSelectionCell(cell);
- }
- else if (this.clearSelectionOnBackground && cell == null)
- {
- this.graph.clearSelection();
- }
-
- // Hides the tooltip if there is one
- this.graph.tooltipHandler.hide();
- var origin = mxUtils.getScrollOrigin();
- var point = new mxPoint(me.getX() + origin.x,
- me.getY() + origin.y);
-
- // Menu is shifted by 1 pixel so that the mouse up event
- // is routed via the underlying shape instead of the DIV
- this.popup(point.x + 1, point.y + 1, cell, me.getEvent());
- me.consume();
- }
- }
-
- this.panningTrigger = false;
- this.popupTrigger = false;
-};
-
-/**
- * Function: getCellForPopupEvent
- *
- * Hook to return the cell for the mouse up popup trigger handling.
- */
-mxPanningHandler.prototype.getCellForPopupEvent = function(me)
-{
- return me.getCell();
-};
-
-/**
- * Function: panGraph
- *
- * Pans <graph> by the given amount.
- */
-mxPanningHandler.prototype.panGraph = function(dx, dy)
-{
- this.graph.getView().setTranslate(dx, dy);
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes.
- */
-mxPanningHandler.prototype.destroy = function()
-{
- this.graph.removeMouseListener(this);
-
- // Supercall
- mxPopupMenu.prototype.destroy.apply(this);
-};
diff --git a/src/js/handler/mxRubberband.js b/src/js/handler/mxRubberband.js
deleted file mode 100644
index f9e7187..0000000
--- a/src/js/handler/mxRubberband.js
+++ /dev/null
@@ -1,348 +0,0 @@
-/**
- * $Id: mxRubberband.js,v 1.48 2012-04-13 12:53:30 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxRubberband
- *
- * Event handler that selects rectangular regions. This is not built-into
- * <mxGraph>. To enable rubberband selection in a graph, use the following code.
- *
- * Example:
- *
- * (code)
- * var rubberband = new mxRubberband(graph);
- * (end)
- *
- * Constructor: mxRubberband
- *
- * Constructs an event handler that selects rectangular regions in the graph
- * using rubberband selection.
- */
-function mxRubberband(graph)
-{
- if (graph != null)
- {
- this.graph = graph;
- this.graph.addMouseListener(this);
-
- // Repaints the marquee after autoscroll
- this.panHandler = mxUtils.bind(this, function()
- {
- this.repaint();
- });
-
- this.graph.addListener(mxEvent.PAN, this.panHandler);
-
- // Automatic deallocation of memory
- if (mxClient.IS_IE)
- {
- mxEvent.addListener(window, 'unload',
- mxUtils.bind(this, function()
- {
- this.destroy();
- })
- );
- }
- }
-};
-
-/**
- * Variable: defaultOpacity
- *
- * Specifies the default opacity to be used for the rubberband div. Default
- * is 20.
- */
-mxRubberband.prototype.defaultOpacity = 20;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxRubberband.prototype.enabled = true;
-
-/**
- * Variable: div
- *
- * Holds the DIV element which is currently visible.
- */
-mxRubberband.prototype.div = null;
-
-/**
- * Variable: sharedDiv
- *
- * Holds the DIV element which is used to display the rubberband.
- */
-mxRubberband.prototype.sharedDiv = null;
-
-/**
- * Variable: currentX
- *
- * Holds the value of the x argument in the last call to <update>.
- */
-mxRubberband.prototype.currentX = 0;
-
-/**
- * Variable: currentY
- *
- * Holds the value of the y argument in the last call to <update>.
- */
-mxRubberband.prototype.currentY = 0;
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation returns
- * <enabled>.
- */
-mxRubberband.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation updates
- * <enabled>.
- */
-mxRubberband.prototype.setEnabled = function(enabled)
-{
- this.enabled = enabled;
-};
-
-/**
- * Function: mouseDown
- *
- * Handles the event by initiating a rubberband selection. By consuming the
- * event all subsequent events of the gesture are redirected to this
- * handler.
- */
-mxRubberband.prototype.mouseDown = function(sender, me)
-{
- if (!me.isConsumed() && this.isEnabled() && this.graph.isEnabled() &&
- (this.graph.isForceMarqueeEvent(me.getEvent()) || me.getState() == null))
- {
- var offset = mxUtils.getOffset(this.graph.container);
- var origin = mxUtils.getScrollOrigin(this.graph.container);
- origin.x -= offset.x;
- origin.y -= offset.y;
- this.start(me.getX() + origin.x, me.getY() + origin.y);
-
- // Workaround for rubberband stopping if the mouse leaves the
- // graph container in Firefox.
- if (mxClient.IS_NS && !mxClient.IS_SF && !mxClient.IS_GC)
- {
- var container = this.graph.container;
-
- function createMouseEvent(evt)
- {
- var me = new mxMouseEvent(evt);
- var pt = mxUtils.convertPoint(container, me.getX(), me.getY());
-
- me.graphX = pt.x;
- me.graphY = pt.y;
-
- return me;
- };
-
- this.dragHandler = mxUtils.bind(this, function(evt)
- {
- this.mouseMove(this.graph, createMouseEvent(evt));
- });
-
- this.dropHandler = mxUtils.bind(this, function(evt)
- {
- this.mouseUp(this.graph, createMouseEvent(evt));
- });
-
- mxEvent.addListener(document, 'mousemove', this.dragHandler);
- mxEvent.addListener(document, 'mouseup', this.dropHandler);
- }
-
- // Does not prevent the default for this event so that the
- // event processing chain is still executed even if we start
- // rubberbanding. This is required eg. in ExtJs to hide the
- // current context menu. In mouseMove we'll make sure we're
- // not selecting anything while we're rubberbanding.
- me.consume(false);
- }
-};
-
-/**
- * Function: start
- *
- * Sets the start point for the rubberband selection.
- */
-mxRubberband.prototype.start = function(x, y)
-{
- this.first = new mxPoint(x, y);
-};
-
-/**
- * Function: mouseMove
- *
- * Handles the event by updating therubberband selection.
- */
-mxRubberband.prototype.mouseMove = function(sender, me)
-{
- if (!me.isConsumed() && this.first != null)
- {
- var origin = mxUtils.getScrollOrigin(this.graph.container);
- var offset = mxUtils.getOffset(this.graph.container);
- origin.x -= offset.x;
- origin.y -= offset.y;
- var x = me.getX() + origin.x;
- var y = me.getY() + origin.y;
- var dx = this.first.x - x;
- var dy = this.first.y - y;
- var tol = this.graph.tolerance;
-
- if (this.div != null || Math.abs(dx) > tol || Math.abs(dy) > tol)
- {
- if (this.div == null)
- {
- this.div = this.createShape();
- }
-
- // Clears selection while rubberbanding. This is required because
- // the event is not consumed in mouseDown.
- mxUtils.clearSelection();
-
- this.update(x, y);
- me.consume();
- }
- }
-};
-
-/**
- * Function: createShape
- *
- * Creates the rubberband selection shape.
- */
-mxRubberband.prototype.createShape = function()
-{
- if (this.sharedDiv == null)
- {
- this.sharedDiv = document.createElement('div');
- this.sharedDiv.className = 'mxRubberband';
- mxUtils.setOpacity(this.sharedDiv, this.defaultOpacity);
- }
-
- this.graph.container.appendChild(this.sharedDiv);
-
- return this.sharedDiv;
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event by selecting the region of the rubberband using
- * <mxGraph.selectRegion>.
- */
-mxRubberband.prototype.mouseUp = function(sender, me)
-{
- var execute = this.div != null;
- this.reset();
-
- if (execute)
- {
- var rect = new mxRectangle(this.x, this.y, this.width, this.height);
- this.graph.selectRegion(rect, me.getEvent());
- me.consume();
- }
-};
-
-/**
- * Function: reset
- *
- * Resets the state of the rubberband selection.
- */
-mxRubberband.prototype.reset = function()
-{
- if (this.div != null)
- {
- this.div.parentNode.removeChild(this.div);
- }
-
- if (this.dragHandler != null)
- {
- mxEvent.removeListener(document, 'mousemove', this.dragHandler);
- this.dragHandler = null;
- }
-
- if (this.dropHandler != null)
- {
- mxEvent.removeListener(document, 'mouseup', this.dropHandler);
- this.dropHandler = null;
- }
-
- this.currentX = 0;
- this.currentY = 0;
- this.first = null;
- this.div = null;
-};
-
-/**
- * Function: update
- *
- * Sets <currentX> and <currentY> and calls <repaint>.
- */
-mxRubberband.prototype.update = function(x, y)
-{
- this.currentX = x;
- this.currentY = y;
-
- this.repaint();
-};
-
-/**
- * Function: repaint
- *
- * Computes the bounding box and updates the style of the <div>.
- */
-mxRubberband.prototype.repaint = function()
-{
- if (this.div != null)
- {
- var x = this.currentX - this.graph.panDx;
- var y = this.currentY - this.graph.panDy;
-
- this.x = Math.min(this.first.x, x);
- this.y = Math.min(this.first.y, y);
- this.width = Math.max(this.first.x, x) - this.x;
- this.height = Math.max(this.first.y, y) - this.y;
-
- var dx = (mxClient.IS_VML) ? this.graph.panDx : 0;
- var dy = (mxClient.IS_VML) ? this.graph.panDy : 0;
-
- this.div.style.left = (this.x + dx) + 'px';
- this.div.style.top = (this.y + dy) + 'px';
- this.div.style.width = Math.max(1, this.width) + 'px';
- this.div.style.height = Math.max(1, this.height) + 'px';
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes. This does
- * normally not need to be called, it is called automatically when the
- * window unloads.
- */
-mxRubberband.prototype.destroy = function()
-{
- if (!this.destroyed)
- {
- this.destroyed = true;
- this.graph.removeMouseListener(this);
- this.graph.removeListener(this.panHandler);
- this.reset();
-
- if (this.sharedDiv != null)
- {
- this.sharedDiv = null;
- }
- }
-};
diff --git a/src/js/handler/mxSelectionCellsHandler.js b/src/js/handler/mxSelectionCellsHandler.js
deleted file mode 100644
index 800d718..0000000
--- a/src/js/handler/mxSelectionCellsHandler.js
+++ /dev/null
@@ -1,260 +0,0 @@
-/**
- * $Id: mxSelectionCellsHandler.js,v 1.5 2012-08-10 11:35:06 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxSelectionCellsHandler
- *
- * An event handler that manages cell handlers and invokes their mouse event
- * processing functions.
- *
- * Group: Events
- *
- * Event: mxEvent.ADD
- *
- * Fires if a cell has been added to the selection. The <code>state</code>
- * property contains the <mxCellState> that has been added.
- *
- * Event: mxEvent.REMOVE
- *
- * Fires if a cell has been remove from the selection. The <code>state</code>
- * property contains the <mxCellState> that has been removed.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- */
-function mxSelectionCellsHandler(graph)
-{
- this.graph = graph;
- this.handlers = new mxDictionary();
- this.graph.addMouseListener(this);
-
- this.refreshHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled())
- {
- this.refresh();
- }
- });
-
- this.graph.getSelectionModel().addListener(mxEvent.CHANGE, this.refreshHandler);
- this.graph.getModel().addListener(mxEvent.CHANGE, this.refreshHandler);
- this.graph.getView().addListener(mxEvent.SCALE, this.refreshHandler);
- this.graph.getView().addListener(mxEvent.TRANSLATE, this.refreshHandler);
- this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, this.refreshHandler);
- this.graph.getView().addListener(mxEvent.DOWN, this.refreshHandler);
- this.graph.getView().addListener(mxEvent.UP, this.refreshHandler);
-};
-
-/**
- * Extends mxEventSource.
- */
-mxSelectionCellsHandler.prototype = new mxEventSource();
-mxSelectionCellsHandler.prototype.constructor = mxSelectionCellsHandler;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxSelectionCellsHandler.prototype.graph = null;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxSelectionCellsHandler.prototype.enabled = true;
-
-/**
- * Variable: refreshHandler
- *
- * Keeps a reference to an event listener for later removal.
- */
-mxSelectionCellsHandler.prototype.refreshHandler = null;
-
-/**
- * Variable: maxHandlers
- *
- * Defines the maximum number of handlers to paint individually. Default is 100.
- */
-mxSelectionCellsHandler.prototype.maxHandlers = 100;
-
-/**
- * Variable: handlers
- *
- * <mxDictionary> that maps from cells to handlers.
- */
-mxSelectionCellsHandler.prototype.handlers = null;
-
-/**
- * Function: isEnabled
- *
- * Returns <enabled>.
- */
-mxSelectionCellsHandler.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Sets <enabled>.
- */
-mxSelectionCellsHandler.prototype.setEnabled = function(value)
-{
- this.enabled = value;
-};
-
-/**
- * Function: getHandler
- *
- * Returns the handler for the given cell.
- */
-mxSelectionCellsHandler.prototype.getHandler = function(cell)
-{
- return this.handlers.get(cell);
-};
-
-/**
- * Function: reset
- *
- * Resets all handlers.
- */
-mxSelectionCellsHandler.prototype.reset = function()
-{
- this.handlers.visit(function(key, handler)
- {
- handler.reset.apply(handler);
- });
-};
-
-/**
- * Function: refresh
- *
- * Reloads or updates all handlers.
- */
-mxSelectionCellsHandler.prototype.refresh = function()
-{
- // Removes all existing handlers
- var oldHandlers = this.handlers;
- this.handlers = new mxDictionary();
-
- // Creates handles for all selection cells
- var tmp = this.graph.getSelectionCells();
-
- for (var i = 0; i < tmp.length; i++)
- {
- var state = this.graph.view.getState(tmp[i]);
-
- if (state != null)
- {
- var handler = oldHandlers.remove(tmp[i]);
-
- if (handler != null)
- {
- if (handler.state != state)
- {
- handler.destroy();
- handler = null;
- }
- else
- {
- handler.redraw();
- }
- }
-
- if (handler == null)
- {
- handler = this.graph.createHandler(state);
- this.fireEvent(new mxEventObject(mxEvent.ADD, 'state', state));
- }
-
- if (handler != null)
- {
- this.handlers.put(tmp[i], handler);
- }
- }
- }
-
- // Destroys all unused handlers
- oldHandlers.visit(mxUtils.bind(this, function(key, handler)
- {
- this.fireEvent(new mxEventObject(mxEvent.REMOVE, 'state', handler.state));
- handler.destroy();
- }));
-};
-
-/**
- * Function: mouseDown
- *
- * Redirects the given event to the handlers.
- */
-mxSelectionCellsHandler.prototype.mouseDown = function(sender, me)
-{
- if (this.graph.isEnabled() && this.isEnabled())
- {
- var args = [sender, me];
-
- this.handlers.visit(function(key, handler)
- {
- handler.mouseDown.apply(handler, args);
- });
- }
-};
-
-/**
- * Function: mouseMove
- *
- * Redirects the given event to the handlers.
- */
-mxSelectionCellsHandler.prototype.mouseMove = function(sender, me)
-{
- if (this.graph.isEnabled() && this.isEnabled())
- {
- var args = [sender, me];
-
- this.handlers.visit(function(key, handler)
- {
- handler.mouseMove.apply(handler, args);
- });
- }
-};
-
-/**
- * Function: mouseUp
- *
- * Redirects the given event to the handlers.
- */
-mxSelectionCellsHandler.prototype.mouseUp = function(sender, me)
-{
- if (this.graph.isEnabled() && this.isEnabled())
- {
- var args = [sender, me];
-
- this.handlers.visit(function(key, handler)
- {
- handler.mouseUp.apply(handler, args);
- });
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes.
- */
-mxSelectionCellsHandler.prototype.destroy = function()
-{
- this.graph.removeMouseListener(this);
-
- if (this.refreshHandler != null)
- {
- this.graph.getSelectionModel().removeListener(this.refreshHandler);
- this.graph.getModel().removeListener(this.refreshHandler);
- this.graph.getView().removeListener(this.refreshHandler);
- this.refreshHandler = null;
- }
-};
diff --git a/src/js/handler/mxTooltipHandler.js b/src/js/handler/mxTooltipHandler.js
deleted file mode 100644
index 4e34a13..0000000
--- a/src/js/handler/mxTooltipHandler.js
+++ /dev/null
@@ -1,317 +0,0 @@
-/**
- * $Id: mxTooltipHandler.js,v 1.51 2011-03-31 10:11:17 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxTooltipHandler
- *
- * Graph event handler that displays tooltips. <mxGraph.getTooltip> is used to
- * get the tooltip for a cell or handle. This handler is built-into
- * <mxGraph.tooltipHandler> and enabled using <mxGraph.setTooltips>.
- *
- * Example:
- *
- * (code>
- * new mxTooltipHandler(graph);
- * (end)
- *
- * Constructor: mxTooltipHandler
- *
- * Constructs an event handler that displays tooltips with the specified
- * delay (in milliseconds). If no delay is specified then a default delay
- * of 500 ms (0.5 sec) is used.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * delay - Optional delay in milliseconds.
- */
-function mxTooltipHandler(graph, delay)
-{
- if (graph != null)
- {
- this.graph = graph;
- this.delay = delay || 500;
- this.graph.addMouseListener(this);
- }
-};
-
-/**
- * Variable: zIndex
- *
- * Specifies the zIndex for the tooltip and its shadow. Default is 10005.
- */
-mxTooltipHandler.prototype.zIndex = 10005;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxTooltipHandler.prototype.graph = null;
-
-/**
- * Variable: delay
- *
- * Delay to show the tooltip in milliseconds. Default is 500.
- */
-mxTooltipHandler.prototype.delay = null;
-
-/**
- * Variable: hideOnHover
- *
- * Specifies if the tooltip should be hidden if the mouse is moved over the
- * current cell. Default is false.
- */
-mxTooltipHandler.prototype.hideOnHover = false;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxTooltipHandler.prototype.enabled = true;
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxTooltipHandler.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- */
-mxTooltipHandler.prototype.setEnabled = function(enabled)
-{
- this.enabled = enabled;
-};
-
-/**
- * Function: isHideOnHover
- *
- * Returns <hideOnHover>.
- */
-mxTooltipHandler.prototype.isHideOnHover = function()
-{
- return this.hideOnHover;
-};
-
-/**
- * Function: setHideOnHover
- *
- * Sets <hideOnHover>.
- */
-mxTooltipHandler.prototype.setHideOnHover = function(value)
-{
- this.hideOnHover = value;
-};
-
-/**
- * Function: init
- *
- * Initializes the DOM nodes required for this tooltip handler.
- */
-mxTooltipHandler.prototype.init = function()
-{
- if (document.body != null)
- {
- this.div = document.createElement('div');
- this.div.className = 'mxTooltip';
- this.div.style.visibility = 'hidden';
- this.div.style.zIndex = this.zIndex;
-
- document.body.appendChild(this.div);
-
- mxEvent.addListener(this.div, 'mousedown',
- mxUtils.bind(this, function(evt)
- {
- this.hideTooltip();
- })
- );
- }
-};
-
-/**
- * Function: mouseDown
- *
- * Handles the event by initiating a rubberband selection. By consuming the
- * event all subsequent events of the gesture are redirected to this
- * handler.
- */
-mxTooltipHandler.prototype.mouseDown = function(sender, me)
-{
- this.reset(me, false);
- this.hideTooltip();
-};
-
-/**
- * Function: mouseMove
- *
- * Handles the event by updating the rubberband selection.
- */
-mxTooltipHandler.prototype.mouseMove = function(sender, me)
-{
- if (me.getX() != this.lastX || me.getY() != this.lastY)
- {
- this.reset(me, true);
-
- if (this.isHideOnHover() || me.getState() != this.state || (me.getSource() != this.node &&
- (!this.stateSource || (me.getState() != null && this.stateSource ==
- (me.isSource(me.getState().shape) || !me.isSource(me.getState().text))))))
- {
- this.hideTooltip();
- }
- }
-
- this.lastX = me.getX();
- this.lastY = me.getY();
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event by resetting the tooltip timer or hiding the existing
- * tooltip.
- */
-mxTooltipHandler.prototype.mouseUp = function(sender, me)
-{
- this.reset(me, true);
- this.hideTooltip();
-};
-
-
-/**
- * Function: resetTimer
- *
- * Resets the timer.
- */
-mxTooltipHandler.prototype.resetTimer = function()
-{
- if (this.thread != null)
- {
- window.clearTimeout(this.thread);
- this.thread = null;
- }
-};
-
-/**
- * Function: reset
- *
- * Resets and/or restarts the timer to trigger the display of the tooltip.
- */
-mxTooltipHandler.prototype.reset = function(me, restart)
-{
- this.resetTimer();
-
- if (restart && this.isEnabled() && me.getState() != null && (this.div == null ||
- this.div.style.visibility == 'hidden'))
- {
- var state = me.getState();
- var node = me.getSource();
- var x = me.getX();
- var y = me.getY();
- var stateSource = me.isSource(state.shape) || me.isSource(state.text);
-
- this.thread = window.setTimeout(mxUtils.bind(this, function()
- {
- if (!this.graph.isEditing() && !this.graph.panningHandler.isMenuShowing())
- {
- // Uses information from inside event cause using the event at
- // this (delayed) point in time is not possible in IE as it no
- // longer contains the required information (member not found)
- var tip = this.graph.getTooltip(state, node, x, y);
- this.show(tip, x, y);
- this.state = state;
- this.node = node;
- this.stateSource = stateSource;
- }
- }), this.delay);
- }
-};
-
-/**
- * Function: hide
- *
- * Hides the tooltip and resets the timer.
- */
-mxTooltipHandler.prototype.hide = function()
-{
- this.resetTimer();
- this.hideTooltip();
-};
-
-/**
- * Function: hideTooltip
- *
- * Hides the tooltip.
- */
-mxTooltipHandler.prototype.hideTooltip = function()
-{
- if (this.div != null)
- {
- this.div.style.visibility = 'hidden';
- }
-};
-
-/**
- * Function: show
- *
- * Shows the tooltip for the specified cell and optional index at the
- * specified location (with a vertical offset of 10 pixels).
- */
-mxTooltipHandler.prototype.show = function(tip, x, y)
-{
- if (tip != null && tip.length > 0)
- {
- // Initializes the DOM nodes if required
- if (this.div == null)
- {
- this.init();
- }
-
- var origin = mxUtils.getScrollOrigin();
-
- this.div.style.left = (x + origin.x) + 'px';
- this.div.style.top = (y + mxConstants.TOOLTIP_VERTICAL_OFFSET +
- origin.y) + 'px';
-
- if (!mxUtils.isNode(tip))
- {
- this.div.innerHTML = tip.replace(/\n/g, '<br>');
- }
- else
- {
- this.div.innerHTML = '';
- this.div.appendChild(tip);
- }
-
- this.div.style.visibility = '';
- mxUtils.fit(this.div);
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes.
- */
-mxTooltipHandler.prototype.destroy = function()
-{
- this.graph.removeMouseListener(this);
- mxEvent.release(this.div);
-
- if (this.div != null && this.div.parentNode != null)
- {
- this.div.parentNode.removeChild(this.div);
- }
-
- this.div = null;
-};
diff --git a/src/js/handler/mxVertexHandler.js b/src/js/handler/mxVertexHandler.js
deleted file mode 100644
index 0b12e27..0000000
--- a/src/js/handler/mxVertexHandler.js
+++ /dev/null
@@ -1,753 +0,0 @@
-/**
- * $Id: mxVertexHandler.js,v 1.107 2012-11-20 09:06:07 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxVertexHandler
- *
- * Event handler for resizing cells. This handler is automatically created in
- * <mxGraph.createHandler>.
- *
- * Constructor: mxVertexHandler
- *
- * Constructs an event handler that allows to resize vertices
- * and groups.
- *
- * Parameters:
- *
- * state - <mxCellState> of the cell to be resized.
- */
-function mxVertexHandler(state)
-{
- if (state != null)
- {
- this.state = state;
- this.init();
- }
-};
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxVertexHandler.prototype.graph = null;
-
-/**
- * Variable: state
- *
- * Reference to the <mxCellState> being modified.
- */
-mxVertexHandler.prototype.state = null;
-
-/**
- * Variable: singleSizer
- *
- * Specifies if only one sizer handle at the bottom, right corner should be
- * used. Default is false.
- */
-mxVertexHandler.prototype.singleSizer = false;
-
-/**
- * Variable: index
- *
- * Holds the index of the current handle.
- */
-mxVertexHandler.prototype.index = null;
-
-/**
- * Variable: allowHandleBoundsCheck
- *
- * Specifies if the bounds of handles should be used for hit-detection in IE
- * Default is true.
- */
-mxVertexHandler.prototype.allowHandleBoundsCheck = true;
-
-/**
- * Variable: crisp
- *
- * Specifies if the selection bounds and handles should be rendered in crisp
- * mode. Default is true.
- */
-mxVertexHandler.prototype.crisp = true;
-
-/**
- * Variable: handleImage
- *
- * Optional <mxImage> to be used as handles. Default is null.
- */
-mxVertexHandler.prototype.handleImage = null;
-
-/**
- * Variable: tolerance
- *
- * Optional tolerance for hit-detection in <getHandleForEvent>. Default is 0.
- */
-mxVertexHandler.prototype.tolerance = 0;
-
-/**
- * Function: init
- *
- * Initializes the shapes required for this vertex handler.
- */
-mxVertexHandler.prototype.init = function()
-{
- this.graph = this.state.view.graph;
- this.selectionBounds = this.getSelectionBounds(this.state);
- this.bounds = new mxRectangle(this.selectionBounds.x, this.selectionBounds.y,
- this.selectionBounds.width, this.selectionBounds.height);
- this.selectionBorder = this.createSelectionShape(this.bounds);
- this.selectionBorder.dialect =
- (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- this.selectionBorder.init(this.graph.getView().getOverlayPane());
-
- // Event-transparency
- if (this.selectionBorder.dialect == mxConstants.DIALECT_SVG)
- {
- this.selectionBorder.node.setAttribute('pointer-events', 'none');
- }
- else
- {
- this.selectionBorder.node.style.background = '';
- }
-
- if (this.graph.isCellMovable(this.state.cell))
- {
- this.selectionBorder.node.style.cursor = mxConstants.CURSOR_MOVABLE_VERTEX;
- }
-
- mxEvent.redirectMouseEvents(this.selectionBorder.node, this.graph, this.state);
-
- // Adds the sizer handles
- if (mxGraphHandler.prototype.maxCells <= 0 ||
- this.graph.getSelectionCount() < mxGraphHandler.prototype.maxCells)
- {
- var resizable = this.graph.isCellResizable(this.state.cell);
- this.sizers = [];
-
- if (resizable || (this.graph.isLabelMovable(this.state.cell) &&
- this.state.width >= 2 && this.state.height >= 2))
- {
- var i = 0;
-
- if (resizable)
- {
- if (!this.singleSizer)
- {
- this.sizers.push(this.createSizer('nw-resize', i++));
- this.sizers.push(this.createSizer('n-resize', i++));
- this.sizers.push(this.createSizer('ne-resize', i++));
- this.sizers.push(this.createSizer('w-resize', i++));
- this.sizers.push(this.createSizer('e-resize', i++));
- this.sizers.push(this.createSizer('sw-resize', i++));
- this.sizers.push(this.createSizer('s-resize', i++));
- }
-
- this.sizers.push(this.createSizer('se-resize', i++));
- }
-
- var geo = this.graph.model.getGeometry(this.state.cell);
-
- if (geo != null && !geo.relative && !this.graph.isSwimlane(this.state.cell) &&
- this.graph.isLabelMovable(this.state.cell))
- {
- // Marks this as the label handle for getHandleForEvent
- this.labelShape = this.createSizer(mxConstants.CURSOR_LABEL_HANDLE,
- mxEvent.LABEL_HANDLE, mxConstants.LABEL_HANDLE_SIZE,
- mxConstants.LABEL_HANDLE_FILLCOLOR);
- this.sizers.push(this.labelShape);
- }
- }
- else if (this.graph.isCellMovable(this.state.cell) && !this.graph.isCellResizable(this.state.cell) &&
- this.state.width < 2 && this.state.height < 2)
- {
- this.labelShape = this.createSizer(mxConstants.CURSOR_MOVABLE_VERTEX,
- null, null, mxConstants.LABEL_HANDLE_FILLCOLOR);
- this.sizers.push(this.labelShape);
- }
- }
-
- this.redraw();
-};
-
-/**
- * Function: getSelectionBounds
- *
- * Returns the mxRectangle that defines the bounds of the selection
- * border.
- */
-mxVertexHandler.prototype.getSelectionBounds = function(state)
-{
- return new mxRectangle(state.x, state.y, state.width, state.height);
-};
-
-/**
- * Function: createSelectionShape
- *
- * Creates the shape used to draw the selection border.
- */
-mxVertexHandler.prototype.createSelectionShape = function(bounds)
-{
- var shape = new mxRectangleShape(bounds, null, this.getSelectionColor());
- shape.strokewidth = this.getSelectionStrokeWidth();
- shape.isDashed = this.isSelectionDashed();
- shape.crisp = this.crisp;
-
- return shape;
-};
-
-/**
- * Function: getSelectionColor
- *
- * Returns <mxConstants.VERTEX_SELECTION_COLOR>.
- */
-mxVertexHandler.prototype.getSelectionColor = function()
-{
- return mxConstants.VERTEX_SELECTION_COLOR;
-};
-
-/**
- * Function: getSelectionStrokeWidth
- *
- * Returns <mxConstants.VERTEX_SELECTION_STROKEWIDTH>.
- */
-mxVertexHandler.prototype.getSelectionStrokeWidth = function()
-{
- return mxConstants.VERTEX_SELECTION_STROKEWIDTH;
-};
-
-/**
- * Function: isSelectionDashed
- *
- * Returns <mxConstants.VERTEX_SELECTION_DASHED>.
- */
-mxVertexHandler.prototype.isSelectionDashed = function()
-{
- return mxConstants.VERTEX_SELECTION_DASHED;
-};
-
-/**
- * Function: createSizer
- *
- * Creates a sizer handle for the specified cursor and index and returns
- * the new <mxRectangleShape> that represents the handle.
- */
-mxVertexHandler.prototype.createSizer = function(cursor, index, size, fillColor)
-{
- size = size || mxConstants.HANDLE_SIZE;
-
- var bounds = new mxRectangle(0, 0, size, size);
- var sizer = this.createSizerShape(bounds, index, fillColor);
-
- if (this.state.text != null && this.state.text.node.parentNode == this.graph.container)
- {
- sizer.bounds.height -= 1;
- sizer.bounds.width -= 1;
- sizer.dialect = mxConstants.DIALECT_STRICTHTML;
- sizer.init(this.graph.container);
- }
- else
- {
- sizer.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- sizer.init(this.graph.getView().getOverlayPane());
- }
-
- mxEvent.redirectMouseEvents(sizer.node, this.graph, this.state);
-
- if (this.graph.isEnabled())
- {
- sizer.node.style.cursor = cursor;
- }
-
- if (!this.isSizerVisible(index))
- {
- sizer.node.style.visibility = 'hidden';
- }
-
- return sizer;
-};
-
-/**
- * Function: isSizerVisible
- *
- * Returns true if the sizer for the given index is visible.
- * This returns true for all given indices.
- */
-mxVertexHandler.prototype.isSizerVisible = function(index)
-{
- return true;
-};
-
-/**
- * Function: createSizerShape
- *
- * Creates the shape used for the sizer handle for the specified bounds and
- * index.
- */
-mxVertexHandler.prototype.createSizerShape = function(bounds, index, fillColor)
-{
- if (this.handleImage != null)
- {
- bounds.width = this.handleImage.width;
- bounds.height = this.handleImage.height;
-
- return new mxImageShape(bounds, this.handleImage.src);
- }
- else
- {
- var shape = new mxRectangleShape(bounds,
- fillColor || mxConstants.HANDLE_FILLCOLOR,
- mxConstants.HANDLE_STROKECOLOR);
- shape.crisp = this.crisp;
-
- return shape;
- }
-};
-
-/**
- * Function: createBounds
- *
- * Helper method to create an <mxRectangle> around the given centerpoint
- * with a width and height of 2*s or 6, if no s is given.
- */
-mxVertexHandler.prototype.moveSizerTo = function(shape, x, y)
-{
- if (shape != null)
- {
- shape.bounds.x = x - shape.bounds.width / 2;
- shape.bounds.y = y - shape.bounds.height / 2;
- shape.redraw();
- }
-};
-
-/**
- * Function: getHandleForEvent
- *
- * Returns the index of the handle for the given event. This returns the index
- * of the sizer from where the event originated or <mxEvent.LABEL_INDEX>.
- */
-mxVertexHandler.prototype.getHandleForEvent = function(me)
-{
- if (me.isSource(this.labelShape))
- {
- return mxEvent.LABEL_HANDLE;
- }
-
- if (this.sizers != null)
- {
- // Connection highlight may consume events before they reach sizer handle
- var tol = this.tolerance;
- var hit = (this.allowHandleBoundsCheck && (mxClient.IS_IE || tol > 0)) ?
- new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol) : null;
-
- for (var i = 0; i < this.sizers.length; i++)
- {
- if (me.isSource(this.sizers[i]) || (hit != null &&
- this.sizers[i].node.style.visibility != 'hidden' &&
- mxUtils.intersects(this.sizers[i].bounds, hit)))
- {
- return i;
- }
- }
- }
-
- return null;
-};
-
-/**
- * Function: mouseDown
- *
- * Handles the event if a handle has been clicked. By consuming the
- * event all subsequent events of the gesture are redirected to this
- * handler.
- */
-mxVertexHandler.prototype.mouseDown = function(sender, me)
-{
- if (!me.isConsumed() && this.graph.isEnabled() && !this.graph.isForceMarqueeEvent(me.getEvent()) &&
- (this.tolerance > 0 || me.getState() == this.state))
- {
- var handle = this.getHandleForEvent(me);
-
- if (handle != null)
- {
- this.start(me.getX(), me.getY(), handle);
- me.consume();
- }
- }
-};
-
-/**
- * Function: start
- *
- * Starts the handling of the mouse gesture.
- */
-mxVertexHandler.prototype.start = function(x, y, index)
-{
- var pt = mxUtils.convertPoint(this.graph.container, x, y);
- this.startX = pt.x;
- this.startY = pt.y;
- this.index = index;
-
- // Creates a preview that can be on top of any HTML label
- this.selectionBorder.node.style.visibility = 'hidden';
- this.preview = this.createSelectionShape(this.bounds);
-
- if (this.state.text != null && this.state.text.node.parentNode == this.graph.container)
- {
- this.preview.dialect = mxConstants.DIALECT_STRICTHTML;
- this.preview.init(this.graph.container);
- }
- else
- {
- this.preview.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- this.preview.init(this.graph.view.getOverlayPane());
- }
-};
-
-/**
- * Function: mouseMove
- *
- * Handles the event by updating the preview.
- */
-mxVertexHandler.prototype.mouseMove = function(sender, me)
-{
- if (!me.isConsumed() && this.index != null)
- {
- var point = new mxPoint(me.getGraphX(), me.getGraphY());
- var gridEnabled = this.graph.isGridEnabledEvent(me.getEvent());
- var scale = this.graph.getView().scale;
-
- if (this.index == mxEvent.LABEL_HANDLE)
- {
- if (gridEnabled)
- {
- point.x = this.graph.snap(point.x / scale) * scale;
- point.y = this.graph.snap(point.y / scale) * scale;
- }
-
- this.moveSizerTo(this.sizers[this.sizers.length - 1], point.x, point.y);
- me.consume();
- }
- else if (this.index != null)
- {
- var dx = point.x - this.startX;
- var dy = point.y - this.startY;
- var tr = this.graph.view.translate;
- this.bounds = this.union(this.selectionBounds, dx, dy, this.index, gridEnabled, scale, tr);
- this.drawPreview();
- me.consume();
- }
- }
- // Workaround for disabling the connect highlight when over handle
- else if (this.getHandleForEvent(me) != null)
- {
- me.consume(false);
- }
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event by applying the changes to the geometry.
- */
-mxVertexHandler.prototype.mouseUp = function(sender, me)
-{
- if (!me.isConsumed() && this.index != null && this.state != null)
- {
- var point = new mxPoint(me.getGraphX(), me.getGraphY());
- var scale = this.graph.getView().scale;
-
- var gridEnabled = this.graph.isGridEnabledEvent(me.getEvent());
- var dx = (point.x - this.startX) / scale;
- var dy = (point.y - this.startY) / scale;
-
- this.resizeCell(this.state.cell, dx, dy, this.index, gridEnabled);
- this.reset();
- me.consume();
- }
-};
-
-/**
- * Function: reset
- *
- * Resets the state of this handler.
- */
-mxVertexHandler.prototype.reset = function()
-{
- this.index = null;
-
- if (this.preview != null)
- {
- this.preview.destroy();
- this.preview = null;
- }
-
- // Checks if handler has been destroyed
- if (this.selectionBorder != null)
- {
- this.selectionBounds = this.getSelectionBounds(this.state);
- this.selectionBorder.node.style.visibility = 'visible';
- this.bounds = new mxRectangle(this.selectionBounds.x, this.selectionBounds.y,
- this.selectionBounds.width, this.selectionBounds.height);
- this.drawPreview();
- }
-};
-
-/**
- * Function: resizeCell
- *
- * Uses the given vector to change the bounds of the given cell
- * in the graph using <mxGraph.resizeCell>.
- */
-mxVertexHandler.prototype.resizeCell = function(cell, dx, dy, index, gridEnabled)
-{
- var geo = this.graph.model.getGeometry(cell);
-
- if (index == mxEvent.LABEL_HANDLE)
- {
- var scale = this.graph.view.scale;
- dx = (this.labelShape.bounds.getCenterX() - this.startX) / scale;
- dy = (this.labelShape.bounds.getCenterY() - this.startY) / scale;
-
- geo = geo.clone();
-
- if (geo.offset == null)
- {
- geo.offset = new mxPoint(dx, dy);
- }
- else
- {
- geo.offset.x += dx;
- geo.offset.y += dy;
- }
-
- this.graph.model.setGeometry(cell, geo);
- }
- else
- {
- var bounds = this.union(geo, dx, dy, index, gridEnabled, 1, new mxPoint(0, 0));
- this.graph.resizeCell(cell, bounds);
- }
-};
-
-/**
- * Function: union
- *
- * Returns the union of the given bounds and location for the specified
- * handle index.
- *
- * To override this to limit the size of vertex via a minWidth/-Height style,
- * the following code can be used.
- *
- * (code)
- * var vertexHandlerUnion = mxVertexHandler.prototype.union;
- * mxVertexHandler.prototype.union = function(bounds, dx, dy, index, gridEnabled, scale, tr)
- * {
- * var result = vertexHandlerUnion.apply(this, arguments);
- *
- * result.width = Math.max(result.width, mxUtils.getNumber(this.state.style, 'minWidth', 0));
- * result.height = Math.max(result.height, mxUtils.getNumber(this.state.style, 'minHeight', 0));
- *
- * return result;
- * };
- * (end)
- *
- * The minWidth/-Height style can then be used as follows:
- *
- * (code)
- * graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30, 'minWidth=100;minHeight=100;');
- * (end)
- */
-mxVertexHandler.prototype.union = function(bounds, dx, dy, index, gridEnabled, scale, tr)
-{
- if (this.singleSizer)
- {
- var x = bounds.x + bounds.width + dx;
- var y = bounds.y + bounds.height + dy;
-
- if (gridEnabled)
- {
- x = this.graph.snap(x / scale) * scale;
- y = this.graph.snap(y / scale) * scale;
- }
-
- var rect = new mxRectangle(bounds.x, bounds.y, 0, 0);
- rect.add(new mxRectangle(x, y, 0, 0));
-
- return rect;
- }
- else
- {
- var left = bounds.x - tr.x * scale;
- var right = left + bounds.width;
- var top = bounds.y - tr.y * scale;
- var bottom = top + bounds.height;
-
- if (index > 4 /* Bottom Row */)
- {
- bottom = bottom + dy;
-
- if (gridEnabled)
- {
- bottom = this.graph.snap(bottom / scale) * scale;
- }
- }
- else if (index < 3 /* Top Row */)
- {
- top = top + dy;
-
- if (gridEnabled)
- {
- top = this.graph.snap(top / scale) * scale;
- }
- }
-
- if (index == 0 || index == 3 || index == 5 /* Left */)
- {
- left += dx;
-
- if (gridEnabled)
- {
- left = this.graph.snap(left / scale) * scale;
- }
- }
- else if (index == 2 || index == 4 || index == 7 /* Right */)
- {
- right += dx;
-
- if (gridEnabled)
- {
- right = this.graph.snap(right / scale) * scale;
- }
- }
-
- var width = right - left;
- var height = bottom - top;
-
- // Flips over left side
- if (width < 0)
- {
- left += width;
- width = Math.abs(width);
- }
-
- // Flips over top side
- if (height < 0)
- {
- top += height;
- height = Math.abs(height);
- }
-
- return new mxRectangle(left + tr.x * scale, top + tr.y * scale, width, height);
- }
-};
-
-/**
- * Function: redraw
- *
- * Redraws the handles and the preview.
- */
-mxVertexHandler.prototype.redraw = function()
-{
- this.selectionBounds = this.getSelectionBounds(this.state);
- this.bounds = new mxRectangle(this.selectionBounds.x, this.selectionBounds.y,
- this.selectionBounds.width, this.selectionBounds.height);
-
- if (this.sizers != null)
- {
- var s = this.state;
- var r = s.x + s.width;
- var b = s.y + s.height;
-
- if (this.singleSizer)
- {
- this.moveSizerTo(this.sizers[0], r, b);
- }
- else
- {
- var cx = s.x + s.width / 2;
- var cy = s.y + s.height / 2;
-
- if (this.sizers.length > 1)
- {
- this.moveSizerTo(this.sizers[0], s.x, s.y);
- this.moveSizerTo(this.sizers[1], cx, s.y);
- this.moveSizerTo(this.sizers[2], r, s.y);
- this.moveSizerTo(this.sizers[3], s.x, cy);
- this.moveSizerTo(this.sizers[4], r, cy);
- this.moveSizerTo(this.sizers[5], s.x, b);
- this.moveSizerTo(this.sizers[6], cx, b);
- this.moveSizerTo(this.sizers[7], r, b);
- this.moveSizerTo(this.sizers[8],
- cx + s.absoluteOffset.x,
- cy + s.absoluteOffset.y);
- }
- else if (this.state.width >= 2 && this.state.height >= 2)
- {
- this.moveSizerTo(this.sizers[0],
- cx + s.absoluteOffset.x,
- cy + s.absoluteOffset.y);
- }
- else
- {
- this.moveSizerTo(this.sizers[0], s.x, s.y);
- }
- }
- }
-
- this.drawPreview();
-};
-
-/**
- * Function: drawPreview
- *
- * Redraws the preview.
- */
-mxVertexHandler.prototype.drawPreview = function()
-{
- if (this.preview != null)
- {
- this.preview.bounds = this.bounds;
-
- if (this.preview.node.parentNode == this.graph.container)
- {
- this.preview.bounds.width = Math.max(0, this.preview.bounds.width - 1);
- this.preview.bounds.height = Math.max(0, this.preview.bounds.height - 1);
- }
-
- this.preview.redraw();
- }
-
- this.selectionBorder.bounds = this.bounds;
- this.selectionBorder.redraw();
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes.
- */
-mxVertexHandler.prototype.destroy = function()
-{
- if (this.preview != null)
- {
- this.preview.destroy();
- this.preview = null;
- }
-
- this.selectionBorder.destroy();
- this.selectionBorder = null;
- this.labelShape = null;
-
- if (this.sizers != null)
- {
- for (var i = 0; i < this.sizers.length; i++)
- {
- this.sizers[i].destroy();
- this.sizers[i] = null;
- }
- }
-};
diff --git a/src/js/index.txt b/src/js/index.txt
deleted file mode 100644
index f3631d6..0000000
--- a/src/js/index.txt
+++ /dev/null
@@ -1,316 +0,0 @@
-Document: API Specification
-
-Overview:
-
- This JavaScript library is divided into 8 packages. The top-level <mxClient>
- class includes (or dynamically imports) everything else. The current version
- is stored in <mxClient.VERSION>.
-
- The *editor* package provides the classes required to implement a diagram
- editor. The main class in this package is <mxEditor>.
-
- The *view* and *model* packages implement the graph component, represented
- by <mxGraph>. It refers to a <mxGraphModel> which contains <mxCell>s and
- caches the state of the cells in a <mxGraphView>. The cells are painted
- using a <mxCellRenderer> based on the appearance defined in <mxStylesheet>.
- Undo history is implemented in <mxUndoManager>. To display an icon on the
- graph, <mxCellOverlay> may be used. Validation rules are defined with
- <mxMultiplicity>.
-
- The *handler*, *layout* and *shape* packages contain event listeners,
- layout algorithms and shapes, respectively. The graph event listeners
- include <mxRubberband> for rubberband selection, <mxTooltipHandler>
- for tooltips and <mxGraphHandler> for basic cell modifications.
- <mxCompactTreeLayout> implements a tree layout algorithm, and the
- shape package provides various shapes, which are subclasses of
- <mxShape>.
-
- The *util* package provides utility classes including <mxClipboard> for
- copy-paste, <mxDatatransfer> for drag-and-drop, <mxConstants> for keys and
- values of stylesheets, <mxEvent> and <mxUtils> for cross-browser
- event-handling and general purpose functions, <mxResources> for
- internationalization and <mxLog> for console output.
-
- The *io* package implements a generic <mxObjectCodec> for turning
- JavaScript objects into XML. The main class is <mxCodec>.
- <mxCodecRegistry> is the global registry for custom codecs.
-
-Events:
-
- There are three different types of events, namely native DOM events,
- <mxEventObjects> which are fired in an <mxEventSource>, and <mxMouseEvents>
- which are fired in <mxGraph>.
-
- Some helper methods for handling native events are provided in <mxEvent>. It
- also takes care of resolving cycles between DOM nodes and JavaScript event
- handlers, which can lead to memory leaks in IE6.
-
- Most custom events in mxGraph are implemented using <mxEventSource>. Its
- listeners are functions that take a sender and <mxEventObject>. Additionally,
- the <mxGraph> class fires special <mxMouseEvents> which are handled using
- mouse listeners, which are objects that provide a mousedown, mousemove and
- mouseup method.
-
- Events in <mxEventSource> are fired using <mxEventSource.fireEvent>.
- Listeners are added and removed using <mxEventSource.addListener> and
- <mxEventSource.removeListener>. <mxMouseEvents> in <mxGraph> are fired using
- <mxGraph.fireMouseEvent>. Listeners are added and removed using
- <mxGraph.addMouseListener> and <mxGraph.removeMouseListener>, respectively.
-
-Key bindings:
-
- The following key bindings are defined for mouse events in the client across
- all browsers and platforms:
-
- - Control-Drag: Duplicates (clones) selected cells
- - Shift-Rightlick: Shows the context menu
- - Alt-Click: Forces rubberband (aka. marquee)
- - Control-Select: Toggles the selection state
- - Shift-Drag: Constrains the offset to one direction
- - Shift-Control-Drag: Panning (also Shift-Rightdrag)
-
-Configuration:
-
- The following global variables may be defined before the client is loaded to
- specify its language or base path, respectively.
-
- - mxBasePath: Specifies the path in <mxClient.basePath>.
- - mxImageBasePath: Specifies the path in <mxClient.imageBasePath>.
- - mxLanguage: Specifies the language for resources in <mxClient.language>.
- - mxDefaultLanguage: Specifies the default language in <mxClient.defaultLanguage>.
- - mxLoadResources: Specifies if any resources should be loaded. Default is true.
- - mxLoadStylesheets: Specifies if any stylesheets should be loaded. Default is true.
-
-Reserved Words:
-
- The mx prefix is used for all classes and objects in mxGraph. The mx prefix
- can be seen as the global namespace for all JavaScript code in mxGraph. The
- following fieldnames should not be used in objects.
-
- - *mxObjectId*: If the object is used with mxObjectIdentity
- - *as*: If the object is a field of another object
- - *id*: If the object is an idref in a codec
- - *mxListenerList*: Added to DOM nodes when used with <mxEvent>
- - *window._mxDynamicCode*: Temporarily used to load code in Safari and Chrome
- (see <mxClient.include>).
- - *_mxJavaScriptExpression*: Global variable that is temporarily used to
- evaluate code in Safari, Opera, Firefox 3 and IE (see <mxUtils.eval>).
-
-Files:
-
- The library contains these relative filenames. All filenames are relative
- to <mxClient.basePath>.
-
-Built-in Images:
-
- All images are loaded from the <mxClient.imageBasePath>,
- which you can change to reflect your environment. The image variables can
- also be changed individually.
-
- - mxGraph.prototype.collapsedImage
- - mxGraph.prototype.expandedImage
- - mxGraph.prototype.warningImage
- - mxWindow.prototype.closeImage
- - mxWindow.prototype.minimizeImage
- - mxWindow.prototype.normalizeImage
- - mxWindow.prototype.maximizeImage
- - mxWindow.prototype.resizeImage
- - mxPopupMenu.prototype.submenuImage
- - mxUtils.errorImage
- - mxConstraintHandler.prototype.pointImage
-
- The basename of the warning image (images/warning without extension) used in
- <mxGraph.setCellWarning> is defined in <mxGraph.warningImage>.
-
-Resources:
-
- The <mxEditor> and <mxGraph> classes add the following resources to
- <mxResources> at class loading time:
-
- - resources/editor*.properties
- - resources/graph*.properties
-
- By default, the library ships with English and German resource files.
-
-Images:
-
- Recommendations for using images. Use GIF images (256 color palette) in HTML
- elements (such as the toolbar and context menu), and PNG images (24 bit) for
- all images which appear inside the graph component.
-
- - For PNG images inside HTML elements, Internet Explorer will ignore any
- transparency information.
- - For GIF images inside the graph, Firefox on the Mac will display strange
- colors. Furthermore, only the first image for animated GIFs is displayed
- on the Mac.
-
- For faster image rendering during application runtime, images can be
- prefetched using the following code:
-
- (code)
- var image = new Image();
- image.src = url_to_image;
- (end)
-
-Deployment:
-
- The client is added to the page using the following script tag inside the
- head of a document:
-
- (code)
- <script type="text/javascript" src="js/mxClient.js"></script>
- (end)
-
- The deployment version of the mxClient.js file contains all required code
- in a single file. For deployment, the complete javascript/src directory is
- required.
-
-Source Code:
-
- If you are a source code customer and you wish to develop using the
- full source code, the commented source code is shipped in the
- javascript/devel/source.zip file. It contains one file for each class
- in mxGraph. To use the source code the source.zip file must be
- uncompressed and the mxClient.js URL in the HTML page must be changed
- to reference the uncompressed mxClient.js from the source.zip file.
-
-Compression:
-
- When using Apache2 with mod_deflate, you can use the following directive
- in src/js/.htaccess to speedup the loading of the JavaScript sources:
-
- (code)
- SetOutputFilter DEFLATE
- (end)
-
-Classes:
-
- There are two types of "classes" in mxGraph: classes and singletons (where
- only one instance exists). Singletons are mapped to global objects where the
- variable name equals the classname. For example mxConstants is an object with
- all the constants defined as object fields. Normal classes are mapped to a
- constructor function and a prototype which defines the instance fields and
- methods. For example, <mxEditor> is a function and mxEditor.prototype is the
- prototype for the object that the mxEditor function creates. The mx prefix is
- a convention that is used for all classes in the mxGraph package to avoid
- conflicts with other objects in the global namespace.
-
-Subclassing:
-
- For subclassing, the superclass must provide a constructor that is either
- parameterless or handles an invocation with no arguments. Furthermore, the
- special constructor field must be redefined after extending the prototype.
- For example, the superclass of mxEditor is <mxEventSource>. This is
- represented in JavaScript by first "inheriting" all fields and methods from
- the superclass by assigning the prototype to an instance of the superclass,
- eg. mxEditor.prototype = new mxEventSource() and redefining the constructor
- field using mxEditor.prototype.constructor = mxEditor. The latter rule is
- applied so that the type of an object can be retrieved via the name of it’s
- constructor using mxUtils.getFunctionName(obj.constructor).
-
-Constructor:
-
- For subclassing in mxGraph, the same scheme should be applied. For example,
- for subclassing the <mxGraph> class, first a constructor must be defined for
- the new class. The constructor calls the super constructor with any arguments
- that it may have using the call function on the mxGraph function object,
- passing along explitely each argument:
-
- (code)
- function MyGraph(container)
- {
- mxGraph.call(this, container);
- }
- (end)
-
- The prototype of MyGraph inherits from mxGraph as follows. As usual, the
- constructor is redefined after extending the superclass:
-
- (code)
- MyGraph.prototype = new mxGraph();
- MyGraph.prototype.constructor = MyGraph;
- (end)
-
- You may want to define the codec associated for the class after the above
- code. This code will be executed at class loading time and makes sure the
- same codec is used to encode instances of mxGraph and MyGraph.
-
- (code)
- var codec = mxCodecRegistry.getCodec(mxGraph);
- codec.template = new MyGraph();
- mxCodecRegistry.register(codec);
- (end)
-
-Functions:
-
- In the prototype for MyGraph, functions of mxGraph can then be extended as
- follows.
-
- (code)
- MyGraph.prototype.isCellSelectable = function(cell)
- {
- var selectable = mxGraph.prototype.isSelectable.apply(this, arguments);
-
- var geo = this.model.getGeometry(cell);
- return selectable && (geo == null || !geo.relative);
- }
- (end)
-
- The supercall in the first line is optional. It is done using the apply
- function on the isSelectable function object of the mxGraph prototype, using
- the special this and arguments variables as parameters. Calls to the
- superclass function are only possible if the function is not replaced in the
- superclass as follows, which is another way of “subclassing” in JavaScript.
-
- (code)
- mxGraph.prototype.isCellSelectable = function(cell)
- {
- var geo = this.model.getGeometry(cell);
- return selectable &&
- (geo == null ||
- !geo.relative);
- }
- (end)
-
- The above scheme is useful if a function definition needs to be replaced
- completely.
-
- In order to add new functions and fields to the subclass, the following code
- is used. The example below adds a new function to return the XML
- representation of the graph model:
-
- (code)
- MyGraph.prototype.getXml = function()
- {
- var enc = new mxCodec();
- return enc.encode(this.getModel());
- }
- (end)
-
-Variables:
-
- Likewise, a new field is declared and defined as follows.
-
- (code)
- MyGraph.prototype.myField = 'Hello, World!';
- (end)
-
- Note that the value assigned to myField is created only once, that is, all
- instances of MyGraph share the same value. If you require instance-specific
- values, then the field must be defined in the constructor instead.
-
- (code)
- function MyGraph(container)
- {
- mxGraph.call(this, container);
-
- this.myField = new Array();
- }
- (end)
-
- Finally, a new instance of MyGraph is created using the following code, where
- container is a DOM node that acts as a container for the graph view:
-
- (code)
- var graph = new MyGraph(container);
- (end)
diff --git a/src/js/io/mxCellCodec.js b/src/js/io/mxCellCodec.js
deleted file mode 100644
index cbcd651..0000000
--- a/src/js/io/mxCellCodec.js
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * $Id: mxCellCodec.js,v 1.22 2010-10-21 07:12:31 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxCellCodec
- *
- * Codec for <mxCell>s. This class is created and registered
- * dynamically at load time and used implicitely via <mxCodec>
- * and the <mxCodecRegistry>.
- *
- * Transient Fields:
- *
- * - children
- * - edges
- * - overlays
- * - mxTransient
- *
- * Reference Fields:
- *
- * - parent
- * - source
- * - target
- *
- * Transient fields can be added using the following code:
- *
- * mxCodecRegistry.getCodec(mxCell).exclude.push('name_of_field');
- */
- var codec = new mxObjectCodec(new mxCell(),
- ['children', 'edges', 'overlays', 'mxTransient'],
- ['parent', 'source', 'target']);
-
- /**
- * Function: isCellCodec
- *
- * Returns true since this is a cell codec.
- */
- codec.isCellCodec = function()
- {
- return true;
- };
-
- /**
- * Function: isExcluded
- *
- * Excludes user objects that are XML nodes.
- */
- codec.isExcluded = function(obj, attr, value, isWrite)
- {
- return mxObjectCodec.prototype.isExcluded.apply(this, arguments) ||
- (isWrite && attr == 'value' &&
- value.nodeType == mxConstants.NODETYPE_ELEMENT);
- };
-
- /**
- * Function: afterEncode
- *
- * Encodes an <mxCell> and wraps the XML up inside the
- * XML of the user object (inversion).
- */
- codec.afterEncode = function(enc, obj, node)
- {
- if (obj.value != null &&
- obj.value.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- // Wraps the graphical annotation up in the user object (inversion)
- // by putting the result of the default encoding into a clone of the
- // user object (node type 1) and returning this cloned user object.
- var tmp = node;
- node = (mxClient.IS_IE) ?
- obj.value.cloneNode(true) :
- enc.document.importNode(obj.value, true);
- node.appendChild(tmp);
-
- // Moves the id attribute to the outermost XML node, namely the
- // node which denotes the object boundaries in the file.
- var id = tmp.getAttribute('id');
- node.setAttribute('id', id);
- tmp.removeAttribute('id');
- }
-
- return node;
- };
-
- /**
- * Function: beforeDecode
- *
- * Decodes an <mxCell> and uses the enclosing XML node as
- * the user object for the cell (inversion).
- */
- codec.beforeDecode = function(dec, node, obj)
- {
- var inner = node;
- var classname = this.getName();
-
- if (node.nodeName != classname)
- {
- // Passes the inner graphical annotation node to the
- // object codec for further processing of the cell.
- var tmp = node.getElementsByTagName(classname)[0];
-
- if (tmp != null &&
- tmp.parentNode == node)
- {
- mxUtils.removeWhitespace(tmp, true);
- mxUtils.removeWhitespace(tmp, false);
- tmp.parentNode.removeChild(tmp);
- inner = tmp;
- }
- else
- {
- inner = null;
- }
-
- // Creates the user object out of the XML node
- obj.value = node.cloneNode(true);
- var id = obj.value.getAttribute('id');
-
- if (id != null)
- {
- obj.setId(id);
- obj.value.removeAttribute('id');
- }
- }
- else
- {
- // Uses ID from XML file as ID for cell in model
- obj.setId(node.getAttribute('id'));
- }
-
- // Preprocesses and removes all Id-references in order to use the
- // correct encoder (this) for the known references to cells (all).
- if (inner != null)
- {
- for (var i = 0; i < this.idrefs.length; i++)
- {
- var attr = this.idrefs[i];
- var ref = inner.getAttribute(attr);
-
- if (ref != null)
- {
- inner.removeAttribute(attr);
- var object = dec.objects[ref] || dec.lookup(ref);
-
- if (object == null)
- {
- // Needs to decode forward reference
- var element = dec.getElementById(ref);
-
- if (element != null)
- {
- var decoder = mxCodecRegistry.codecs[element.nodeName] || this;
- object = decoder.decode(dec, element);
- }
- }
-
- obj[attr] = object;
- }
- }
- }
-
- return inner;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxChildChangeCodec.js b/src/js/io/mxChildChangeCodec.js
deleted file mode 100644
index deeb57b..0000000
--- a/src/js/io/mxChildChangeCodec.js
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * $Id: mxChildChangeCodec.js,v 1.12 2010-09-15 14:38:52 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxChildChangeCodec
- *
- * Codec for <mxChildChange>s. This class is created and registered
- * dynamically at load time and used implicitely via <mxCodec> and
- * the <mxCodecRegistry>.
- *
- * Transient Fields:
- *
- * - model
- * - previous
- * - previousIndex
- * - child
- *
- * Reference Fields:
- *
- * - parent
- */
- var codec = new mxObjectCodec(new mxChildChange(),
- ['model', 'child', 'previousIndex'],
- ['parent', 'previous']);
-
- /**
- * Function: isReference
- *
- * Returns true for the child attribute if the child
- * cell had a previous parent or if we're reading the
- * child as an attribute rather than a child node, in
- * which case it's always a reference.
- */
- codec.isReference = function(obj, attr, value, isWrite)
- {
- if (attr == 'child' &&
- (obj.previous != null ||
- !isWrite))
- {
- return true;
- }
-
- return mxUtils.indexOf(this.idrefs, attr) >= 0;
- };
-
- /**
- * Function: afterEncode
- *
- * Encodes the child recusively and adds the result
- * to the given node.
- */
- codec.afterEncode = function(enc, obj, node)
- {
- if (this.isReference(obj, 'child', obj.child, true))
- {
- // Encodes as reference (id)
- node.setAttribute('child', enc.getId(obj.child));
- }
- else
- {
- // At this point, the encoder is no longer able to know which cells
- // are new, so we have to encode the complete cell hierarchy and
- // ignore the ones that are already there at decoding time. Note:
- // This can only be resolved by moving the notify event into the
- // execute of the edit.
- enc.encodeCell(obj.child, node);
- }
-
- return node;
- };
-
- /**
- * Function: beforeDecode
- *
- * Decodes the any child nodes as using the respective
- * codec from the registry.
- */
- codec.beforeDecode = function(dec, node, obj)
- {
- if (node.firstChild != null &&
- node.firstChild.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- // Makes sure the original node isn't modified
- node = node.cloneNode(true);
-
- var tmp = node.firstChild;
- obj.child = dec.decodeCell(tmp, false);
-
- var tmp2 = tmp.nextSibling;
- tmp.parentNode.removeChild(tmp);
- tmp = tmp2;
-
- while (tmp != null)
- {
- tmp2 = tmp.nextSibling;
-
- if (tmp.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- // Ignores all existing cells because those do not need to
- // be re-inserted into the model. Since the encoded version
- // of these cells contains the new parent, this would leave
- // to an inconsistent state on the model (ie. a parent
- // change without a call to parentForCellChanged).
- var id = tmp.getAttribute('id');
-
- if (dec.lookup(id) == null)
- {
- dec.decodeCell(tmp);
- }
- }
-
- tmp.parentNode.removeChild(tmp);
- tmp = tmp2;
- }
- }
- else
- {
- var childRef = node.getAttribute('child');
- obj.child = dec.getObject(childRef);
- }
-
- return node;
- };
-
- /**
- * Function: afterDecode
- *
- * Restores object state in the child change.
- */
- codec.afterDecode = function(dec, node, obj)
- {
- // Cells are encoded here after a complete transaction so the previous
- // parent must be restored on the cell for the case where the cell was
- // added. This is needed for the local model to identify the cell as a
- // new cell and register the ID.
- obj.child.parent = obj.previous;
- obj.previous = obj.parent;
- obj.previousIndex = obj.index;
-
- return obj;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxCodec.js b/src/js/io/mxCodec.js
deleted file mode 100644
index b8bfc6a..0000000
--- a/src/js/io/mxCodec.js
+++ /dev/null
@@ -1,531 +0,0 @@
-/**
- * $Id: mxCodec.js,v 1.48 2012-01-04 10:01:16 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCodec
- *
- * XML codec for JavaScript object graphs. See <mxObjectCodec> for a
- * description of the general encoding/decoding scheme. This class uses the
- * codecs registered in <mxCodecRegistry> for encoding/decoding each object.
- *
- * References:
- *
- * In order to resolve references, especially forward references, the mxCodec
- * constructor must be given the document that contains the referenced
- * elements.
- *
- * Examples:
- *
- * The following code is used to encode a graph model.
- *
- * (code)
- * var encoder = new mxCodec();
- * var result = encoder.encode(graph.getModel());
- * var xml = mxUtils.getXml(result);
- * (end)
- *
- * Example:
- *
- * Using the following code, the selection cells of a graph are encoded and the
- * output is displayed in a dialog box.
- *
- * (code)
- * var enc = new mxCodec();
- * var cells = graph.getSelectionCells();
- * mxUtils.alert(mxUtils.getPrettyXml(enc.encode(cells)));
- * (end)
- *
- * Newlines in the XML can be coverted to <br>, in which case a '<br>' argument
- * must be passed to <mxUtils.getXml> as the second argument.
- *
- * Example:
- *
- * Using the code below, an XML document is decodec into an existing model. The
- * document may be obtained using one of the functions in mxUtils for loading
- * an XML file, eg. <mxUtils.get>, or using <mxUtils.parseXml> for parsing an
- * XML string.
- *
- * (code)
- * var decoder = new mxCodec(doc)
- * decoder.decode(doc.documentElement, graph.getModel());
- * (end)
- *
- * Debugging:
- *
- * For debugging i/o you can use the following code to get the sequence of
- * encoded objects:
- *
- * (code)
- * var oldEncode = mxCodec.prototype.encode;
- * mxCodec.prototype.encode = function(obj)
- * {
- * mxLog.show();
- * mxLog.debug('mxCodec.encode: obj='+mxUtils.getFunctionName(obj.constructor));
- *
- * return oldEncode.apply(this, arguments);
- * };
- * (end)
- *
- * Constructor: mxCodec
- *
- * Constructs an XML encoder/decoder for the specified
- * owner document.
- *
- * Parameters:
- *
- * document - Optional XML document that contains the data.
- * If no document is specified then a new document is created
- * using <mxUtils.createXmlDocument>.
- */
-function mxCodec(document)
-{
- this.document = document || mxUtils.createXmlDocument();
- this.objects = [];
-};
-
-/**
- * Variable: document
- *
- * The owner document of the codec.
- */
-mxCodec.prototype.document = null;
-
-/**
- * Variable: objects
- *
- * Maps from IDs to objects.
- */
-mxCodec.prototype.objects = null;
-
-/**
- * Variable: encodeDefaults
- *
- * Specifies if default values should be encoded. Default is false.
- */
-mxCodec.prototype.encodeDefaults = false;
-
-
-/**
- * Function: putObject
- *
- * Assoiates the given object with the given ID and returns the given object.
- *
- * Parameters
- *
- * id - ID for the object to be associated with.
- * obj - Object to be associated with the ID.
- */
-mxCodec.prototype.putObject = function(id, obj)
-{
- this.objects[id] = obj;
-
- return obj;
-};
-
-/**
- * Function: getObject
- *
- * Returns the decoded object for the element with the specified ID in
- * <document>. If the object is not known then <lookup> is used to find an
- * object. If no object is found, then the element with the respective ID
- * from the document is parsed using <decode>.
- */
-mxCodec.prototype.getObject = function(id)
-{
- var obj = null;
-
- if (id != null)
- {
- obj = this.objects[id];
-
- if (obj == null)
- {
- obj = this.lookup(id);
-
- if (obj == null)
- {
- var node = this.getElementById(id);
-
- if (node != null)
- {
- obj = this.decode(node);
- }
- }
- }
- }
-
- return obj;
-};
-
-/**
- * Function: lookup
- *
- * Hook for subclassers to implement a custom lookup mechanism for cell IDs.
- * This implementation always returns null.
- *
- * Example:
- *
- * (code)
- * var codec = new mxCodec();
- * codec.lookup = function(id)
- * {
- * return model.getCell(id);
- * };
- * (end)
- *
- * Parameters:
- *
- * id - ID of the object to be returned.
- */
-mxCodec.prototype.lookup = function(id)
-{
- return null;
-};
-
-/**
- * Function: getElementById
- *
- * Returns the element with the given ID from <document>. The optional attr
- * argument specifies the name of the ID attribute. Default is "id". The
- * XPath expression used to find the element is //*[@attr='arg'] where attr is
- * the name of the ID attribute and arg is the given id.
- *
- * Parameters:
- *
- * id - String that contains the ID.
- * attr - Optional string for the attributename. Default is "id".
- */
-mxCodec.prototype.getElementById = function(id, attr)
-{
- attr = (attr != null) ? attr : 'id';
-
- return mxUtils.findNodeByAttribute(this.document.documentElement, attr, id);
-};
-
-/**
- * Function: getId
- *
- * Returns the ID of the specified object. This implementation
- * calls <reference> first and if that returns null handles
- * the object as an <mxCell> by returning their IDs using
- * <mxCell.getId>. If no ID exists for the given cell, then
- * an on-the-fly ID is generated using <mxCellPath.create>.
- *
- * Parameters:
- *
- * obj - Object to return the ID for.
- */
-mxCodec.prototype.getId = function(obj)
-{
- var id = null;
-
- if (obj != null)
- {
- id = this.reference(obj);
-
- if (id == null && obj instanceof mxCell)
- {
- id = obj.getId();
-
- if (id == null)
- {
- // Uses an on-the-fly Id
- id = mxCellPath.create(obj);
-
- if (id.length == 0)
- {
- id = 'root';
- }
- }
- }
- }
-
- return id;
-};
-
-/**
- * Function: reference
- *
- * Hook for subclassers to implement a custom method
- * for retrieving IDs from objects. This implementation
- * always returns null.
- *
- * Example:
- *
- * (code)
- * var codec = new mxCodec();
- * codec.reference = function(obj)
- * {
- * return obj.getCustomId();
- * };
- * (end)
- *
- * Parameters:
- *
- * obj - Object whose ID should be returned.
- */
-mxCodec.prototype.reference = function(obj)
-{
- return null;
-};
-
-/**
- * Function: encode
- *
- * Encodes the specified object and returns the resulting
- * XML node.
- *
- * Parameters:
- *
- * obj - Object to be encoded.
- */
-mxCodec.prototype.encode = function(obj)
-{
- var node = null;
-
- if (obj != null && obj.constructor != null)
- {
- var enc = mxCodecRegistry.getCodec(obj.constructor);
-
- if (enc != null)
- {
- node = enc.encode(this, obj);
- }
- else
- {
- if (mxUtils.isNode(obj))
- {
- node = (mxClient.IS_IE) ? obj.cloneNode(true) :
- this.document.importNode(obj, true);
- }
- else
- {
- mxLog.warn('mxCodec.encode: No codec for '+
- mxUtils.getFunctionName(obj.constructor));
- }
- }
- }
-
- return node;
-};
-
-/**
- * Function: decode
- *
- * Decodes the given XML node. The optional "into"
- * argument specifies an existing object to be
- * used. If no object is given, then a new instance
- * is created using the constructor from the codec.
- *
- * The function returns the passed in object or
- * the new instance if no object was given.
- *
- * Parameters:
- *
- * node - XML node to be decoded.
- * into - Optional object to be decodec into.
- */
-mxCodec.prototype.decode = function(node, into)
-{
- var obj = null;
-
- if (node != null && node.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- var ctor = null;
-
- try
- {
- ctor = eval(node.nodeName);
- }
- catch (err)
- {
- // ignore
- }
-
- try
- {
- var dec = mxCodecRegistry.getCodec(ctor);
-
- if (dec != null)
- {
- obj = dec.decode(this, node, into);
- }
- else
- {
- obj = node.cloneNode(true);
- obj.removeAttribute('as');
- }
- }
- catch (err)
- {
- mxLog.debug('Cannot decode '+node.nodeName+': '+err.message);
- }
- }
-
- return obj;
-};
-
-/**
- * Function: encodeCell
- *
- * Encoding of cell hierarchies is built-into the core, but
- * is a higher-level function that needs to be explicitely
- * used by the respective object encoders (eg. <mxModelCodec>,
- * <mxChildChangeCodec> and <mxRootChangeCodec>). This
- * implementation writes the given cell and its children as a
- * (flat) sequence into the given node. The children are not
- * encoded if the optional includeChildren is false. The
- * function is in charge of adding the result into the
- * given node and has no return value.
- *
- * Parameters:
- *
- * cell - <mxCell> to be encoded.
- * node - Parent XML node to add the encoded cell into.
- * includeChildren - Optional boolean indicating if the
- * function should include all descendents. Default is true.
- */
-mxCodec.prototype.encodeCell = function(cell, node, includeChildren)
-{
- node.appendChild(this.encode(cell));
-
- if (includeChildren == null || includeChildren)
- {
- var childCount = cell.getChildCount();
-
- for (var i = 0; i < childCount; i++)
- {
- this.encodeCell(cell.getChildAt(i), node);
- }
- }
-};
-
-/**
- * Function: isCellCodec
- *
- * Returns true if the given codec is a cell codec. This uses
- * <mxCellCodec.isCellCodec> to check if the codec is of the
- * given type.
- */
-mxCodec.prototype.isCellCodec = function(codec)
-{
- if (codec != null && typeof(codec.isCellCodec) == 'function')
- {
- return codec.isCellCodec();
- }
-
- return false;
-};
-
-/**
- * Function: decodeCell
- *
- * Decodes cells that have been encoded using inversion, ie.
- * where the user object is the enclosing node in the XML,
- * and restores the group and graph structure in the cells.
- * Returns a new <mxCell> instance that represents the
- * given node.
- *
- * Parameters:
- *
- * node - XML node that contains the cell data.
- * restoreStructures - Optional boolean indicating whether
- * the graph structure should be restored by calling insert
- * and insertEdge on the parent and terminals, respectively.
- * Default is true.
- */
-mxCodec.prototype.decodeCell = function(node, restoreStructures)
-{
- restoreStructures = (restoreStructures != null) ? restoreStructures : true;
- var cell = null;
-
- if (node != null && node.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- // Tries to find a codec for the given node name. If that does
- // not return a codec then the node is the user object (an XML node
- // that contains the mxCell, aka inversion).
- var decoder = mxCodecRegistry.getCodec(node.nodeName);
-
- // Tries to find the codec for the cell inside the user object.
- // This assumes all node names inside the user object are either
- // not registered or they correspond to a class for cells.
- if (!this.isCellCodec(decoder))
- {
- var child = node.firstChild;
-
- while (child != null && !this.isCellCodec(decoder))
- {
- decoder = mxCodecRegistry.getCodec(child.nodeName);
- child = child.nextSibling;
- }
- }
-
- if (!this.isCellCodec(decoder))
- {
- decoder = mxCodecRegistry.getCodec(mxCell);
- }
-
- cell = decoder.decode(this, node);
-
- if (restoreStructures)
- {
- this.insertIntoGraph(cell);
- }
- }
-
- return cell;
-};
-
-/**
- * Function: insertIntoGraph
- *
- * Inserts the given cell into its parent and terminal cells.
- */
-mxCodec.prototype.insertIntoGraph = function(cell)
-{
- var parent = cell.parent;
- var source = cell.getTerminal(true);
- var target = cell.getTerminal(false);
-
- // Fixes possible inconsistencies during insert into graph
- cell.setTerminal(null, false);
- cell.setTerminal(null, true);
- cell.parent = null;
-
- if (parent != null)
- {
- parent.insert(cell);
- }
-
- if (source != null)
- {
- source.insertEdge(cell, true);
- }
-
- if (target != null)
- {
- target.insertEdge(cell, false);
- }
-};
-
-/**
- * Function: setAttribute
- *
- * Sets the attribute on the specified node to value. This is a
- * helper method that makes sure the attribute and value arguments
- * are not null.
- *
- * Parameters:
- *
- * node - XML node to set the attribute for.
- * attributes - Attributename to be set.
- * value - New value of the attribute.
- */
-mxCodec.prototype.setAttribute = function(node, attribute, value)
-{
- if (attribute != null && value != null)
- {
- node.setAttribute(attribute, value);
- }
-};
diff --git a/src/js/io/mxCodecRegistry.js b/src/js/io/mxCodecRegistry.js
deleted file mode 100644
index a0a0f20..0000000
--- a/src/js/io/mxCodecRegistry.js
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * $Id: mxCodecRegistry.js,v 1.12 2010-04-30 13:18:21 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxCodecRegistry =
-{
- /**
- * Class: mxCodecRegistry
- *
- * Singleton class that acts as a global registry for codecs.
- *
- * Adding an <mxCodec>:
- *
- * 1. Define a default codec with a new instance of the
- * object to be handled.
- *
- * (code)
- * var codec = new mxObjectCodec(new mxGraphModel());
- * (end)
- *
- * 2. Define the functions required for encoding and decoding
- * objects.
- *
- * (code)
- * codec.encode = function(enc, obj) { ... }
- * codec.decode = function(dec, node, into) { ... }
- * (end)
- *
- * 3. Register the codec in the <mxCodecRegistry>.
- *
- * (code)
- * mxCodecRegistry.register(codec);
- * (end)
- *
- * <mxObjectCodec.decode> may be used to either create a new
- * instance of an object or to configure an existing instance,
- * in which case the into argument points to the existing
- * object. In this case, we say the codec "configures" the
- * object.
- *
- * Variable: codecs
- *
- * Maps from constructor names to codecs.
- */
- codecs: [],
-
- /**
- * Variable: aliases
- *
- * Maps from classnames to codecnames.
- */
- aliases: [],
-
- /**
- * Function: register
- *
- * Registers a new codec and associates the name of the template
- * constructor in the codec with the codec object.
- *
- * Parameters:
- *
- * codec - <mxObjectCodec> to be registered.
- */
- register: function(codec)
- {
- if (codec != null)
- {
- var name = codec.getName();
- mxCodecRegistry.codecs[name] = codec;
-
- var classname = mxUtils.getFunctionName(codec.template.constructor);
-
- if (classname != name)
- {
- mxCodecRegistry.addAlias(classname, name);
- }
- }
-
- return codec;
- },
-
- /**
- * Function: addAlias
- *
- * Adds an alias for mapping a classname to a codecname.
- */
- addAlias: function(classname, codecname)
- {
- mxCodecRegistry.aliases[classname] = codecname;
- },
-
- /**
- * Function: getCodec
- *
- * Returns a codec that handles objects that are constructed
- * using the given constructor.
- *
- * Parameters:
- *
- * ctor - JavaScript constructor function.
- */
- getCodec: function(ctor)
- {
- var codec = null;
-
- if (ctor != null)
- {
- var name = mxUtils.getFunctionName(ctor);
- var tmp = mxCodecRegistry.aliases[name];
-
- if (tmp != null)
- {
- name = tmp;
- }
-
- codec = mxCodecRegistry.codecs[name];
-
- // Registers a new default codec for the given constructor
- // if no codec has been previously defined.
- if (codec == null)
- {
- try
- {
- codec = new mxObjectCodec(new ctor());
- mxCodecRegistry.register(codec);
- }
- catch (e)
- {
- // ignore
- }
- }
- }
-
- return codec;
- }
-
-};
diff --git a/src/js/io/mxDefaultKeyHandlerCodec.js b/src/js/io/mxDefaultKeyHandlerCodec.js
deleted file mode 100644
index 628524a..0000000
--- a/src/js/io/mxDefaultKeyHandlerCodec.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * $Id: mxDefaultKeyHandlerCodec.js,v 1.5 2010-01-02 09:45:15 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxDefaultKeyHandlerCodec
- *
- * Custom codec for configuring <mxDefaultKeyHandler>s. This class is created
- * and registered dynamically at load time and used implicitely via
- * <mxCodec> and the <mxCodecRegistry>. This codec only reads configuration
- * data for existing key handlers, it does not encode or create key handlers.
- */
- var codec = new mxObjectCodec(new mxDefaultKeyHandler());
-
- /**
- * Function: encode
- *
- * Returns null.
- */
- codec.encode = function(enc, obj)
- {
- return null;
- };
-
- /**
- * Function: decode
- *
- * Reads a sequence of the following child nodes
- * and attributes:
- *
- * Child Nodes:
- *
- * add - Binds a keystroke to an actionname.
- *
- * Attributes:
- *
- * as - Keycode.
- * action - Actionname to execute in editor.
- * control - Optional boolean indicating if
- * the control key must be pressed.
- *
- * Example:
- *
- * (code)
- * <mxDefaultKeyHandler as="keyHandler">
- * <add as="88" control="true" action="cut"/>
- * <add as="67" control="true" action="copy"/>
- * <add as="86" control="true" action="paste"/>
- * </mxDefaultKeyHandler>
- * (end)
- *
- * The keycodes are for the x, c and v keys.
- *
- * See also: <mxDefaultKeyHandler.bindAction>,
- * http://www.js-examples.com/page/tutorials__key_codes.html
- */
- codec.decode = function(dec, node, into)
- {
- if (into != null)
- {
- var editor = into.editor;
- node = node.firstChild;
-
- while (node != null)
- {
- if (!this.processInclude(dec, node, into) &&
- node.nodeName == 'add')
- {
- var as = node.getAttribute('as');
- var action = node.getAttribute('action');
- var control = node.getAttribute('control');
-
- into.bindAction(as, action, control);
- }
-
- node = node.nextSibling;
- }
- }
-
- return into;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxDefaultPopupMenuCodec.js b/src/js/io/mxDefaultPopupMenuCodec.js
deleted file mode 100644
index 8d949ea..0000000
--- a/src/js/io/mxDefaultPopupMenuCodec.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * $Id: mxDefaultPopupMenuCodec.js,v 1.6 2010-01-02 09:45:15 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxDefaultPopupMenuCodec
- *
- * Custom codec for configuring <mxDefaultPopupMenu>s. This class is created
- * and registered dynamically at load time and used implicitely via
- * <mxCodec> and the <mxCodecRegistry>. This codec only reads configuration
- * data for existing popup menus, it does not encode or create menus. Note
- * that this codec only passes the configuration node to the popup menu,
- * which uses the config to dynamically create menus. See
- * <mxDefaultPopupMenu.createMenu>.
- */
- var codec = new mxObjectCodec(new mxDefaultPopupMenu());
-
- /**
- * Function: encode
- *
- * Returns null.
- */
- codec.encode = function(enc, obj)
- {
- return null;
- };
-
- /**
- * Function: decode
- *
- * Uses the given node as the config for <mxDefaultPopupMenu>.
- */
- codec.decode = function(dec, node, into)
- {
- var inc = node.getElementsByTagName('include')[0];
-
- if (inc != null)
- {
- this.processInclude(dec, inc, into);
- }
- else if (into != null)
- {
- into.config = node;
- }
-
- return into;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxDefaultToolbarCodec.js b/src/js/io/mxDefaultToolbarCodec.js
deleted file mode 100644
index 6698b9b..0000000
--- a/src/js/io/mxDefaultToolbarCodec.js
+++ /dev/null
@@ -1,301 +0,0 @@
-/**
- * $Id: mxDefaultToolbarCodec.js,v 1.22 2012-04-11 07:00:52 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxDefaultToolbarCodec
- *
- * Custom codec for configuring <mxDefaultToolbar>s. This class is created
- * and registered dynamically at load time and used implicitely via
- * <mxCodec> and the <mxCodecRegistry>. This codec only reads configuration
- * data for existing toolbars handlers, it does not encode or create toolbars.
- */
- var codec = new mxObjectCodec(new mxDefaultToolbar());
-
- /**
- * Function: encode
- *
- * Returns null.
- */
- codec.encode = function(enc, obj)
- {
- return null;
- };
-
- /**
- * Function: decode
- *
- * Reads a sequence of the following child nodes
- * and attributes:
- *
- * Child Nodes:
- *
- * add - Adds a new item to the toolbar. See below for attributes.
- * separator - Adds a vertical separator. No attributes.
- * hr - Adds a horizontal separator. No attributes.
- * br - Adds a linefeed. No attributes.
- *
- * Attributes:
- *
- * as - Resource key for the label.
- * action - Name of the action to execute in enclosing editor.
- * mode - Modename (see below).
- * template - Template name for cell insertion.
- * style - Optional style to override the template style.
- * icon - Icon (relative/absolute URL).
- * pressedIcon - Optional icon for pressed state (relative/absolute URL).
- * id - Optional ID to be used for the created DOM element.
- * toggle - Optional 0 or 1 to disable toggling of the element. Default is
- * 1 (true).
- *
- * The action, mode and template attributes are mutually exclusive. The
- * style can only be used with the template attribute. The add node may
- * contain another sequence of add nodes with as and action attributes
- * to create a combo box in the toolbar. If the icon is specified then
- * a list of the child node is expected to have its template attribute
- * set and the action is ignored instead.
- *
- * Nodes with a specified template may define a function to be used for
- * inserting the cloned template into the graph. Here is an example of such
- * a node:
- *
- * (code)
- * <add as="Swimlane" template="swimlane" icon="images/swimlane.gif"><![CDATA[
- * function (editor, cell, evt, targetCell)
- * {
- * var pt = mxUtils.convertPoint(
- * editor.graph.container, mxEvent.getClientX(evt),
- * mxEvent.getClientY(evt));
- * return editor.addVertex(targetCell, cell, pt.x, pt.y);
- * }
- * ]]></add>
- * (end)
- *
- * In the above function, editor is the enclosing <mxEditor> instance, cell
- * is the clone of the template, evt is the mouse event that represents the
- * drop and targetCell is the cell under the mousepointer where the drop
- * occurred. The targetCell is retrieved using <mxGraph.getCellAt>.
- *
- * Futhermore, nodes with the mode attribute may define a function to
- * be executed upon selection of the respective toolbar icon. In the
- * example below, the default edge style is set when this specific
- * connect-mode is activated:
- *
- * (code)
- * <add as="connect" mode="connect"><![CDATA[
- * function (editor)
- * {
- * if (editor.defaultEdge != null)
- * {
- * editor.defaultEdge.style = 'straightEdge';
- * }
- * }
- * ]]></add>
- * (end)
- *
- * Modes:
- *
- * select - Left mouse button used for rubberband- & cell-selection.
- * connect - Allows connecting vertices by inserting new edges.
- * pan - Disables selection and switches to panning on the left button.
- *
- * Example:
- *
- * To add items to the toolbar:
- *
- * (code)
- * <mxDefaultToolbar as="toolbar">
- * <add as="save" action="save" icon="images/save.gif"/>
- * <br/><hr/>
- * <add as="select" mode="select" icon="images/select.gif"/>
- * <add as="connect" mode="connect" icon="images/connect.gif"/>
- * </mxDefaultToolbar>
- * (end)
- */
- codec.decode = function(dec, node, into)
- {
- if (into != null)
- {
- var editor = into.editor;
- node = node.firstChild;
-
- while (node != null)
- {
- if (node.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- if (!this.processInclude(dec, node, into))
- {
- if (node.nodeName == 'separator')
- {
- into.addSeparator();
- }
- else if (node.nodeName == 'br')
- {
- into.toolbar.addBreak();
- }
- else if (node.nodeName == 'hr')
- {
- into.toolbar.addLine();
- }
- else if (node.nodeName == 'add')
- {
- var as = node.getAttribute('as');
- as = mxResources.get(as) || as;
- var icon = node.getAttribute('icon');
- var pressedIcon = node.getAttribute('pressedIcon');
- var action = node.getAttribute('action');
- var mode = node.getAttribute('mode');
- var template = node.getAttribute('template');
- var toggle = node.getAttribute('toggle') != '0';
- var text = mxUtils.getTextContent(node);
- var elt = null;
-
- if (action != null)
- {
- elt = into.addItem(as, icon, action, pressedIcon);
- }
- else if (mode != null)
- {
- var funct = mxUtils.eval(text);
- elt = into.addMode(as, icon, mode, pressedIcon, funct);
- }
- else if (template != null || (text != null && text.length > 0))
- {
- var cell = editor.templates[template];
- var style = node.getAttribute('style');
-
- if (cell != null && style != null)
- {
- cell = cell.clone();
- cell.setStyle(style);
- }
-
- var insertFunction = null;
-
- if (text != null && text.length > 0)
- {
- insertFunction = mxUtils.eval(text);
- }
-
- elt = into.addPrototype(as, icon, cell, pressedIcon, insertFunction, toggle);
- }
- else
- {
- var children = mxUtils.getChildNodes(node);
-
- if (children.length > 0)
- {
- if (icon == null)
- {
- var combo = into.addActionCombo(as);
-
- for (var i=0; i<children.length; i++)
- {
- var child = children[i];
-
- if (child.nodeName == 'separator')
- {
- into.addOption(combo, '---');
- }
- else if (child.nodeName == 'add')
- {
- var lab = child.getAttribute('as');
- var act = child.getAttribute('action');
- into.addActionOption(combo, lab, act);
- }
- }
- }
- else
- {
- var select = null;
- var create = function()
- {
- var template = editor.templates[select.value];
-
- if (template != null)
- {
- var clone = template.clone();
- var style = select.options[select.selectedIndex].cellStyle;
-
- if (style != null)
- {
- clone.setStyle(style);
- }
-
- return clone;
- }
- else
- {
- mxLog.warn('Template '+template+' not found');
- }
-
- return null;
- };
-
- var img = into.addPrototype(as, icon, create, null, null, toggle);
- select = into.addCombo();
-
- // Selects the toolbar icon if a selection change
- // is made in the corresponding combobox.
- mxEvent.addListener(select, 'change', function()
- {
- into.toolbar.selectMode(img, function(evt)
- {
- var pt = mxUtils.convertPoint(editor.graph.container,
- mxEvent.getClientX(evt), mxEvent.getClientY(evt));
-
- return editor.addVertex(null, funct(), pt.x, pt.y);
- });
-
- into.toolbar.noReset = false;
- });
-
- // Adds the entries to the combobox
- for (var i=0; i<children.length; i++)
- {
- var child = children[i];
-
- if (child.nodeName == 'separator')
- {
- into.addOption(select, '---');
- }
- else if (child.nodeName == 'add')
- {
- var lab = child.getAttribute('as');
- var tmp = child.getAttribute('template');
- var option = into.addOption(select, lab, tmp || template);
- option.cellStyle = child.getAttribute('style');
- }
- }
-
- }
- }
- }
-
- // Assigns an ID to the created element to access it later.
- if (elt != null)
- {
- var id = node.getAttribute('id');
-
- if (id != null && id.length > 0)
- {
- elt.setAttribute('id', id);
- }
- }
- }
- }
- }
-
- node = node.nextSibling;
- }
- }
-
- return into;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxEditorCodec.js b/src/js/io/mxEditorCodec.js
deleted file mode 100644
index f61bd95..0000000
--- a/src/js/io/mxEditorCodec.js
+++ /dev/null
@@ -1,246 +0,0 @@
-/**
- * $Id: mxEditorCodec.js,v 1.11 2010-01-04 11:18:26 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxEditorCodec
- *
- * Codec for <mxEditor>s. This class is created and registered
- * dynamically at load time and used implicitely via <mxCodec>
- * and the <mxCodecRegistry>.
- *
- * Transient Fields:
- *
- * - modified
- * - lastSnapshot
- * - ignoredChanges
- * - undoManager
- * - graphContainer
- * - toolbarContainer
- */
- var codec = new mxObjectCodec(new mxEditor(),
- ['modified', 'lastSnapshot', 'ignoredChanges',
- 'undoManager', 'graphContainer', 'toolbarContainer']);
-
- /**
- * Function: beforeDecode
- *
- * Decodes the ui-part of the configuration node by reading
- * a sequence of the following child nodes and attributes
- * and passes the control to the default decoding mechanism:
- *
- * Child Nodes:
- *
- * stylesheet - Adds a CSS stylesheet to the document.
- * resource - Adds the basename of a resource bundle.
- * add - Creates or configures a known UI element.
- *
- * These elements may appear in any order given that the
- * graph UI element is added before the toolbar element
- * (see Known Keys).
- *
- * Attributes:
- *
- * as - Key for the UI element (see below).
- * element - ID for the element in the document.
- * style - CSS style to be used for the element or window.
- * x - X coordinate for the new window.
- * y - Y coordinate for the new window.
- * width - Width for the new window.
- * height - Optional height for the new window.
- * name - Name of the stylesheet (absolute/relative URL).
- * basename - Basename of the resource bundle (see <mxResources>).
- *
- * The x, y, width and height attributes are used to create a new
- * <mxWindow> if the element attribute is not specified in an add
- * node. The name and basename are only used in the stylesheet and
- * resource nodes, respectively.
- *
- * Known Keys:
- *
- * graph - Main graph element (see <mxEditor.setGraphContainer>).
- * title - Title element (see <mxEditor.setTitleContainer>).
- * toolbar - Toolbar element (see <mxEditor.setToolbarContainer>).
- * status - Status bar element (see <mxEditor.setStatusContainer>).
- *
- * Example:
- *
- * (code)
- * <ui>
- * <stylesheet name="css/process.css"/>
- * <resource basename="resources/mxApplication"/>
- * <add as="graph" element="graph"
- * style="left:70px;right:20px;top:20px;bottom:40px"/>
- * <add as="status" element="status"/>
- * <add as="toolbar" x="10" y="20" width="54"/>
- * </ui>
- * (end)
- */
- codec.afterDecode = function(dec, node, obj)
- {
- // Assigns the specified templates for edges
- var defaultEdge = node.getAttribute('defaultEdge');
-
- if (defaultEdge != null)
- {
- node.removeAttribute('defaultEdge');
- obj.defaultEdge = obj.templates[defaultEdge];
- }
-
- // Assigns the specified templates for groups
- var defaultGroup = node.getAttribute('defaultGroup');
-
- if (defaultGroup != null)
- {
- node.removeAttribute('defaultGroup');
- obj.defaultGroup = obj.templates[defaultGroup];
- }
-
- return obj;
- };
-
- /**
- * Function: decodeChild
- *
- * Overrides decode child to handle special child nodes.
- */
- codec.decodeChild = function(dec, child, obj)
- {
- if (child.nodeName == 'Array')
- {
- var role = child.getAttribute('as');
-
- if (role == 'templates')
- {
- this.decodeTemplates(dec, child, obj);
- return;
- }
- }
- else if (child.nodeName == 'ui')
- {
- this.decodeUi(dec, child, obj);
- return;
- }
-
- mxObjectCodec.prototype.decodeChild.apply(this, arguments);
- };
-
- /**
- * Function: decodeTemplates
- *
- * Decodes the cells from the given node as templates.
- */
- codec.decodeUi = function(dec, node, editor)
- {
- var tmp = node.firstChild;
- while (tmp != null)
- {
- if (tmp.nodeName == 'add')
- {
- var as = tmp.getAttribute('as');
- var elt = tmp.getAttribute('element');
- var style = tmp.getAttribute('style');
- var element = null;
-
- if (elt != null)
- {
- element = document.getElementById(elt);
-
- if (element != null &&
- style != null)
- {
- element.style.cssText += ';'+style;
- }
- }
- else
- {
- var x = parseInt(tmp.getAttribute('x'));
- var y = parseInt(tmp.getAttribute('y'));
- var width = tmp.getAttribute('width');
- var height = tmp.getAttribute('height');
-
- // Creates a new window around the element
- element = document.createElement('div');
- element.style.cssText = style;
-
- var wnd = new mxWindow(mxResources.get(as) || as,
- element, x, y, width, height, false, true);
- wnd.setVisible(true);
- }
-
- // TODO: Make more generic
- if (as == 'graph')
- {
- editor.setGraphContainer(element);
- }
- else if (as == 'toolbar')
- {
- editor.setToolbarContainer(element);
- }
- else if (as == 'title')
- {
- editor.setTitleContainer(element);
- }
- else if (as == 'status')
- {
- editor.setStatusContainer(element);
- }
- else if (as == 'map')
- {
- editor.setMapContainer(element);
- }
- }
- else if (tmp.nodeName == 'resource')
- {
- mxResources.add(tmp.getAttribute('basename'));
- }
- else if (tmp.nodeName == 'stylesheet')
- {
- mxClient.link('stylesheet', tmp.getAttribute('name'));
- }
-
- tmp = tmp.nextSibling;
- }
- };
-
- /**
- * Function: decodeTemplates
- *
- * Decodes the cells from the given node as templates.
- */
- codec.decodeTemplates = function(dec, node, editor)
- {
- if (editor.templates == null)
- {
- editor.templates = [];
- }
-
- var children = mxUtils.getChildNodes(node);
- for (var j=0; j<children.length; j++)
- {
- var name = children[j].getAttribute('as');
- var child = children[j].firstChild;
-
- while (child != null && child.nodeType != 1)
- {
- child = child.nextSibling;
- }
-
- if (child != null)
- {
- // LATER: Only single cells means you need
- // to group multiple cells within another
- // cell. This should be changed to support
- // arrays of cells, or the wrapper must
- // be automatically handled in this class.
- editor.templates[name] = dec.decodeCell(child);
- }
- }
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxGenericChangeCodec.js b/src/js/io/mxGenericChangeCodec.js
deleted file mode 100644
index 8da7789..0000000
--- a/src/js/io/mxGenericChangeCodec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * $Id: mxGenericChangeCodec.js,v 1.11 2010-09-13 15:50:36 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGenericChangeCodec
- *
- * Codec for <mxValueChange>s, <mxStyleChange>s, <mxGeometryChange>s,
- * <mxCollapseChange>s and <mxVisibleChange>s. This class is created
- * and registered dynamically at load time and used implicitely
- * via <mxCodec> and the <mxCodecRegistry>.
- *
- * Transient Fields:
- *
- * - model
- * - previous
- *
- * Reference Fields:
- *
- * - cell
- *
- * Constructor: mxGenericChangeCodec
- *
- * Factory function that creates a <mxObjectCodec> for
- * the specified change and fieldname.
- *
- * Parameters:
- *
- * obj - An instance of the change object.
- * variable - The fieldname for the change data.
- */
-var mxGenericChangeCodec = function(obj, variable)
-{
- var codec = new mxObjectCodec(obj, ['model', 'previous'], ['cell']);
-
- /**
- * Function: afterDecode
- *
- * Restores the state by assigning the previous value.
- */
- codec.afterDecode = function(dec, node, obj)
- {
- // Allows forward references in sessions. This is a workaround
- // for the sequence of edits in mxGraph.moveCells and cellsAdded.
- if (mxUtils.isNode(obj.cell))
- {
- obj.cell = dec.decodeCell(obj.cell, false);
- }
-
- obj.previous = obj[variable];
-
- return obj;
- };
-
- return codec;
-};
-
-// Registers the codecs
-mxCodecRegistry.register(mxGenericChangeCodec(new mxValueChange(), 'value'));
-mxCodecRegistry.register(mxGenericChangeCodec(new mxStyleChange(), 'style'));
-mxCodecRegistry.register(mxGenericChangeCodec(new mxGeometryChange(), 'geometry'));
-mxCodecRegistry.register(mxGenericChangeCodec(new mxCollapseChange(), 'collapsed'));
-mxCodecRegistry.register(mxGenericChangeCodec(new mxVisibleChange(), 'visible'));
-mxCodecRegistry.register(mxGenericChangeCodec(new mxCellAttributeChange(), 'value'));
diff --git a/src/js/io/mxGraphCodec.js b/src/js/io/mxGraphCodec.js
deleted file mode 100644
index f052e13..0000000
--- a/src/js/io/mxGraphCodec.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * $Id: mxGraphCodec.js,v 1.8 2010-06-10 06:54:18 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxGraphCodec
- *
- * Codec for <mxGraph>s. This class is created and registered
- * dynamically at load time and used implicitely via <mxCodec>
- * and the <mxCodecRegistry>.
- *
- * Transient Fields:
- *
- * - graphListeners
- * - eventListeners
- * - view
- * - container
- * - cellRenderer
- * - editor
- * - selection
- */
- return new mxObjectCodec(new mxGraph(),
- ['graphListeners', 'eventListeners', 'view', 'container',
- 'cellRenderer', 'editor', 'selection']);
-
-}());
diff --git a/src/js/io/mxGraphViewCodec.js b/src/js/io/mxGraphViewCodec.js
deleted file mode 100644
index 110b212..0000000
--- a/src/js/io/mxGraphViewCodec.js
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
- * $Id: mxGraphViewCodec.js,v 1.18 2010-12-03 11:05:52 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxGraphViewCodec
- *
- * Custom encoder for <mxGraphView>s. This class is created
- * and registered dynamically at load time and used implicitely via
- * <mxCodec> and the <mxCodecRegistry>. This codec only writes views
- * into a XML format that can be used to create an image for
- * the graph, that is, it contains absolute coordinates with
- * computed perimeters, edge styles and cell styles.
- */
- var codec = new mxObjectCodec(new mxGraphView());
-
- /**
- * Function: encode
- *
- * Encodes the given <mxGraphView> using <encodeCell>
- * starting at the model's root. This returns the
- * top-level graph node of the recursive encoding.
- */
- codec.encode = function(enc, view)
- {
- return this.encodeCell(enc, view,
- view.graph.getModel().getRoot());
- };
-
- /**
- * Function: encodeCell
- *
- * Recursively encodes the specifed cell. Uses layer
- * as the default nodename. If the cell's parent is
- * null, then graph is used for the nodename. If
- * <mxGraphModel.isEdge> returns true for the cell,
- * then edge is used for the nodename, else if
- * <mxGraphModel.isVertex> returns true for the cell,
- * then vertex is used for the nodename.
- *
- * <mxGraph.getLabel> is used to create the label
- * attribute for the cell. For graph nodes and vertices
- * the bounds are encoded into x, y, width and height.
- * For edges the points are encoded into a points
- * attribute as a space-separated list of comma-separated
- * coordinate pairs (eg. x0,y0 x1,y1 ... xn,yn). All
- * values from the cell style are added as attribute
- * values to the node.
- */
- codec.encodeCell = function(enc, view, cell)
- {
- var model = view.graph.getModel();
- var state = view.getState(cell);
- var parent = model.getParent(cell);
-
- if (parent == null || state != null)
- {
- var childCount = model.getChildCount(cell);
- var geo = view.graph.getCellGeometry(cell);
- var name = null;
-
- if (parent == model.getRoot())
- {
- name = 'layer';
- }
- else if (parent == null)
- {
- name = 'graph';
- }
- else if (model.isEdge(cell))
- {
- name = 'edge';
- }
- else if (childCount > 0 && geo != null)
- {
- name = 'group';
- }
- else if (model.isVertex(cell))
- {
- name = 'vertex';
- }
-
- if (name != null)
- {
- var node = enc.document.createElement(name);
- var lab = view.graph.getLabel(cell);
-
- if (lab != null)
- {
- node.setAttribute('label', view.graph.getLabel(cell));
-
- if (view.graph.isHtmlLabel(cell))
- {
- node.setAttribute('html', true);
- }
- }
-
- if (parent == null)
- {
- var bounds = view.getGraphBounds();
-
- if (bounds != null)
- {
- node.setAttribute('x', Math.round(bounds.x));
- node.setAttribute('y', Math.round(bounds.y));
- node.setAttribute('width', Math.round(bounds.width));
- node.setAttribute('height', Math.round(bounds.height));
- }
-
- node.setAttribute('scale', view.scale);
- }
- else if (state != null && geo != null)
- {
- // Writes each key, value in the style pair to an attribute
- for (var i in state.style)
- {
- var value = state.style[i];
-
- // Tries to turn objects and functions into strings
- if (typeof(value) == 'function' &&
- typeof(value) == 'object')
- {
- value = mxStyleRegistry.getName(value);
- }
-
- if (value != null &&
- typeof(value) != 'function' &&
- typeof(value) != 'object')
- {
- node.setAttribute(i, value);
- }
- }
-
- var abs = state.absolutePoints;
-
- // Writes the list of points into one attribute
- if (abs != null && abs.length > 0)
- {
- var pts = Math.round(abs[0].x) + ',' + Math.round(abs[0].y);
-
- for (var i=1; i<abs.length; i++)
- {
- pts += ' ' + Math.round(abs[i].x) + ',' +
- Math.round(abs[i].y);
- }
-
- node.setAttribute('points', pts);
- }
-
- // Writes the bounds into 4 attributes
- else
- {
- node.setAttribute('x', Math.round(state.x));
- node.setAttribute('y', Math.round(state.y));
- node.setAttribute('width', Math.round(state.width));
- node.setAttribute('height', Math.round(state.height));
- }
-
- var offset = state.absoluteOffset;
-
- // Writes the offset into 2 attributes
- if (offset != null)
- {
- if (offset.x != 0)
- {
- node.setAttribute('dx', Math.round(offset.x));
- }
-
- if (offset.y != 0)
- {
- node.setAttribute('dy', Math.round(offset.y));
- }
- }
- }
-
- for (var i=0; i<childCount; i++)
- {
- var childNode = this.encodeCell(enc,
- view, model.getChildAt(cell, i));
-
- if (childNode != null)
- {
- node.appendChild(childNode);
- }
- }
- }
- }
-
- return node;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxModelCodec.js b/src/js/io/mxModelCodec.js
deleted file mode 100644
index 760a2b1..0000000
--- a/src/js/io/mxModelCodec.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * $Id: mxModelCodec.js,v 1.11 2010-11-23 08:46:41 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxModelCodec
- *
- * Codec for <mxGraphModel>s. This class is created and registered
- * dynamically at load time and used implicitely via <mxCodec>
- * and the <mxCodecRegistry>.
- */
- var codec = new mxObjectCodec(new mxGraphModel());
-
- /**
- * Function: encodeObject
- *
- * Encodes the given <mxGraphModel> by writing a (flat) XML sequence of
- * cell nodes as produced by the <mxCellCodec>. The sequence is
- * wrapped-up in a node with the name root.
- */
- codec.encodeObject = function(enc, obj, node)
- {
- var rootNode = enc.document.createElement('root');
- enc.encodeCell(obj.getRoot(), rootNode);
- node.appendChild(rootNode);
- };
-
- /**
- * Function: decodeChild
- *
- * Overrides decode child to handle special child nodes.
- */
- codec.decodeChild = function(dec, child, obj)
- {
- if (child.nodeName == 'root')
- {
- this.decodeRoot(dec, child, obj);
- }
- else
- {
- mxObjectCodec.prototype.decodeChild.apply(this, arguments);
- }
- };
-
- /**
- * Function: decodeRoot
- *
- * Reads the cells into the graph model. All cells
- * are children of the root element in the node.
- */
- codec.decodeRoot = function(dec, root, model)
- {
- var rootCell = null;
- var tmp = root.firstChild;
-
- while (tmp != null)
- {
- var cell = dec.decodeCell(tmp);
-
- if (cell != null && cell.getParent() == null)
- {
- rootCell = cell;
- }
-
- tmp = tmp.nextSibling;
- }
-
- // Sets the root on the model if one has been decoded
- if (rootCell != null)
- {
- model.setRoot(rootCell);
- }
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxObjectCodec.js b/src/js/io/mxObjectCodec.js
deleted file mode 100644
index 9d2473a..0000000
--- a/src/js/io/mxObjectCodec.js
+++ /dev/null
@@ -1,983 +0,0 @@
-/**
- * $Id: mxObjectCodec.js,v 1.49 2010-12-01 09:19:58 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxObjectCodec
- *
- * Generic codec for JavaScript objects that implements a mapping between
- * JavaScript objects and XML nodes that maps each field or element to an
- * attribute or child node, and vice versa.
- *
- * Atomic Values:
- *
- * Consider the following example.
- *
- * (code)
- * var obj = new Object();
- * obj.foo = "Foo";
- * obj.bar = "Bar";
- * (end)
- *
- * This object is encoded into an XML node using the following.
- *
- * (code)
- * var enc = new mxCodec();
- * var node = enc.encode(obj);
- * (end)
- *
- * The output of the encoding may be viewed using <mxLog> as follows.
- *
- * (code)
- * mxLog.show();
- * mxLog.debug(mxUtils.getPrettyXml(node));
- * (end)
- *
- * Finally, the result of the encoding looks as follows.
- *
- * (code)
- * <Object foo="Foo" bar="Bar"/>
- * (end)
- *
- * In the above output, the foo and bar fields have been mapped to attributes
- * with the same names, and the name of the constructor was used for the
- * nodename.
- *
- * Booleans:
- *
- * Since booleans are numbers in JavaScript, all boolean values are encoded
- * into 1 for true and 0 for false. The decoder also accepts the string true
- * and false for boolean values.
- *
- * Objects:
- *
- * The above scheme is applied to all atomic fields, that is, to all non-object
- * fields of an object. For object fields, a child node is created with a
- * special attribute that contains the fieldname. This special attribute is
- * called "as" and hence, as is a reserved word that should not be used for a
- * fieldname.
- *
- * Consider the following example where foo is an object and bar is an atomic
- * property of foo.
- *
- * (code)
- * var obj = {foo: {bar: "Bar"}};
- * (end)
- *
- * This will be mapped to the following XML structure by mxObjectCodec.
- *
- * (code)
- * <Object>
- * <Object bar="Bar" as="foo"/>
- * </Object>
- * (end)
- *
- * In the above output, the inner Object node contains the as-attribute that
- * specifies the fieldname in the enclosing object. That is, the field foo was
- * mapped to a child node with an as-attribute that has the value foo.
- *
- * Arrays:
- *
- * Arrays are special objects that are either associative, in which case each
- * key, value pair is treated like a field where the key is the fieldname, or
- * they are a sequence of atomic values and objects, which is mapped to a
- * sequence of child nodes. For object elements, the above scheme is applied
- * without the use of the special as-attribute for creating each child. For
- * atomic elements, a special add-node is created with the value stored in the
- * value-attribute.
- *
- * For example, the following array contains one atomic value and one object
- * with a field called bar. Furthermore it contains two associative entries
- * called bar with an atomic value, and foo with an object value.
- *
- * (code)
- * var obj = ["Bar", {bar: "Bar"}];
- * obj["bar"] = "Bar";
- * obj["foo"] = {bar: "Bar"};
- * (end)
- *
- * This array is represented by the following XML nodes.
- *
- * (code)
- * <Array bar="Bar">
- * <add value="Bar"/>
- * <Object bar="Bar"/>
- * <Object bar="Bar" as="foo"/>
- * </Array>
- * (end)
- *
- * The Array node name is the name of the constructor. The additional
- * as-attribute in the last child contains the key of the associative entry,
- * whereas the second last child is part of the array sequence and does not
- * have an as-attribute.
- *
- * References:
- *
- * Objects may be represented as child nodes or attributes with ID values,
- * which are used to lookup the object in a table within <mxCodec>. The
- * <isReference> function is in charge of deciding if a specific field should
- * be encoded as a reference or not. Its default implementation returns true if
- * the fieldname is in <idrefs>, an array of strings that is used to configure
- * the <mxObjectCodec>.
- *
- * Using this approach, the mapping does not guarantee that the referenced
- * object itself exists in the document. The fields that are encoded as
- * references must be carefully chosen to make sure all referenced objects
- * exist in the document, or may be resolved by some other means if necessary.
- *
- * For example, in the case of the graph model all cells are stored in a tree
- * whose root is referenced by the model's root field. A tree is a structure
- * that is well suited for an XML representation, however, the additional edges
- * in the graph model have a reference to a source and target cell, which are
- * also contained in the tree. To handle this case, the source and target cell
- * of an edge are treated as references, whereas the children are treated as
- * objects. Since all cells are contained in the tree and no edge references a
- * source or target outside the tree, this setup makes sure all referenced
- * objects are contained in the document.
- *
- * In the case of a tree structure we must further avoid infinite recursion by
- * ignoring the parent reference of each child. This is done by returning true
- * in <isExcluded>, whose default implementation uses the array of excluded
- * fieldnames passed to the mxObjectCodec constructor.
- *
- * References are only used for cells in mxGraph. For defining other
- * referencable object types, the codec must be able to work out the ID of an
- * object. This is done by implementing <mxCodec.reference>. For decoding a
- * reference, the XML node with the respective id-attribute is fetched from the
- * document, decoded, and stored in a lookup table for later reference. For
- * looking up external objects, <mxCodec.lookup> may be implemented.
- *
- * Expressions:
- *
- * For decoding JavaScript expressions, the add-node may be used with a text
- * content that contains the JavaScript expression. For example, the following
- * creates a field called foo in the enclosing object and assigns it the value
- * of <mxConstants.ALIGN_LEFT>.
- *
- * (code)
- * <Object>
- * <add as="foo">mxConstants.ALIGN_LEFT</add>
- * </Object>
- * (end)
- *
- * The resulting object has a field called foo with the value "left". Its XML
- * representation looks as follows.
- *
- * (code)
- * <Object foo="left"/>
- * (end)
- *
- * This means the expression is evaluated at decoding time and the result of
- * the evaluation is stored in the respective field. Valid expressions are all
- * JavaScript expressions, including function definitions, which are mapped to
- * functions on the resulting object.
- *
- * Constructor: mxObjectCodec
- *
- * Constructs a new codec for the specified template object.
- * The variables in the optional exclude array are ignored by
- * the codec. Variables in the optional idrefs array are
- * turned into references in the XML. The optional mapping
- * may be used to map from variable names to XML attributes.
- * The argument is created as follows:
- *
- * (code)
- * var mapping = new Object();
- * mapping['variableName'] = 'attribute-name';
- * (end)
- *
- * Parameters:
- *
- * template - Prototypical instance of the object to be
- * encoded/decoded.
- * exclude - Optional array of fieldnames to be ignored.
- * idrefs - Optional array of fieldnames to be converted to/from
- * references.
- * mapping - Optional mapping from field- to attributenames.
- */
-function mxObjectCodec(template, exclude, idrefs, mapping)
-{
- this.template = template;
-
- this.exclude = (exclude != null) ? exclude : [];
- this.idrefs = (idrefs != null) ? idrefs : [];
- this.mapping = (mapping != null) ? mapping : [];
-
- this.reverse = new Object();
-
- for (var i in this.mapping)
- {
- this.reverse[this.mapping[i]] = i;
- }
-};
-
-/**
- * Variable: template
- *
- * Holds the template object associated with this codec.
- */
-mxObjectCodec.prototype.template = null;
-
-/**
- * Variable: exclude
- *
- * Array containing the variable names that should be
- * ignored by the codec.
- */
-mxObjectCodec.prototype.exclude = null;
-
-/**
- * Variable: idrefs
- *
- * Array containing the variable names that should be
- * turned into or converted from references. See
- * <mxCodec.getId> and <mxCodec.getObject>.
- */
-mxObjectCodec.prototype.idrefs = null;
-
-/**
- * Variable: mapping
- *
- * Maps from from fieldnames to XML attribute names.
- */
-mxObjectCodec.prototype.mapping = null;
-
-/**
- * Variable: reverse
- *
- * Maps from from XML attribute names to fieldnames.
- */
-mxObjectCodec.prototype.reverse = null;
-
-/**
- * Function: getName
- *
- * Returns the name used for the nodenames and lookup of the codec when
- * classes are encoded and nodes are decoded. For classes to work with
- * this the codec registry automatically adds an alias for the classname
- * if that is different than what this returns. The default implementation
- * returns the classname of the template class.
- */
-mxObjectCodec.prototype.getName = function()
-{
- return mxUtils.getFunctionName(this.template.constructor);
-};
-
-/**
- * Function: cloneTemplate
- *
- * Returns a new instance of the template for this codec.
- */
-mxObjectCodec.prototype.cloneTemplate = function()
-{
- return new this.template.constructor();
-};
-
-/**
- * Function: getFieldName
- *
- * Returns the fieldname for the given attributename.
- * Looks up the value in the <reverse> mapping or returns
- * the input if there is no reverse mapping for the
- * given name.
- */
-mxObjectCodec.prototype.getFieldName = function(attributename)
-{
- if (attributename != null)
- {
- var mapped = this.reverse[attributename];
-
- if (mapped != null)
- {
- attributename = mapped;
- }
- }
-
- return attributename;
-};
-
-/**
- * Function: getAttributeName
- *
- * Returns the attributename for the given fieldname.
- * Looks up the value in the <mapping> or returns
- * the input if there is no mapping for the
- * given name.
- */
-mxObjectCodec.prototype.getAttributeName = function(fieldname)
-{
- if (fieldname != null)
- {
- var mapped = this.mapping[fieldname];
-
- if (mapped != null)
- {
- fieldname = mapped;
- }
- }
-
- return fieldname;
-};
-
-/**
- * Function: isExcluded
- *
- * Returns true if the given attribute is to be ignored by the codec. This
- * implementation returns true if the given fieldname is in <exclude> or
- * if the fieldname equals <mxObjectIdentity.FIELD_NAME>.
- *
- * Parameters:
- *
- * obj - Object instance that contains the field.
- * attr - Fieldname of the field.
- * value - Value of the field.
- * write - Boolean indicating if the field is being encoded or decoded.
- * Write is true if the field is being encoded, else it is being decoded.
- */
-mxObjectCodec.prototype.isExcluded = function(obj, attr, value, write)
-{
- return attr == mxObjectIdentity.FIELD_NAME ||
- mxUtils.indexOf(this.exclude, attr) >= 0;
-};
-
-/**
- * Function: isReference
- *
- * Returns true if the given fieldname is to be treated
- * as a textual reference (ID). This implementation returns
- * true if the given fieldname is in <idrefs>.
- *
- * Parameters:
- *
- * obj - Object instance that contains the field.
- * attr - Fieldname of the field.
- * value - Value of the field.
- * write - Boolean indicating if the field is being encoded or decoded.
- * Write is true if the field is being encoded, else it is being decoded.
- */
-mxObjectCodec.prototype.isReference = function(obj, attr, value, write)
-{
- return mxUtils.indexOf(this.idrefs, attr) >= 0;
-};
-
-/**
- * Function: encode
- *
- * Encodes the specified object and returns a node
- * representing then given object. Calls <beforeEncode>
- * after creating the node and <afterEncode> with the
- * resulting node after processing.
- *
- * Enc is a reference to the calling encoder. It is used
- * to encode complex objects and create references.
- *
- * This implementation encodes all variables of an
- * object according to the following rules:
- *
- * - If the variable name is in <exclude> then it is ignored.
- * - If the variable name is in <idrefs> then <mxCodec.getId>
- * is used to replace the object with its ID.
- * - The variable name is mapped using <mapping>.
- * - If obj is an array and the variable name is numeric
- * (ie. an index) then it is not encoded.
- * - If the value is an object, then the codec is used to
- * create a child node with the variable name encoded into
- * the "as" attribute.
- * - Else, if <encodeDefaults> is true or the value differs
- * from the template value, then ...
- * - ... if obj is not an array, then the value is mapped to
- * an attribute.
- * - ... else if obj is an array, the value is mapped to an
- * add child with a value attribute or a text child node,
- * if the value is a function.
- *
- * If no ID exists for a variable in <idrefs> or if an object
- * cannot be encoded, a warning is issued using <mxLog.warn>.
- *
- * Returns the resulting XML node that represents the given
- * object.
- *
- * Parameters:
- *
- * enc - <mxCodec> that controls the encoding process.
- * obj - Object to be encoded.
- */
-mxObjectCodec.prototype.encode = function(enc, obj)
-{
- var node = enc.document.createElement(this.getName());
-
- obj = this.beforeEncode(enc, obj, node);
- this.encodeObject(enc, obj, node);
-
- return this.afterEncode(enc, obj, node);
-};
-
-/**
- * Function: encodeObject
- *
- * Encodes the value of each member in then given obj into the given node using
- * <encodeValue>.
- *
- * Parameters:
- *
- * enc - <mxCodec> that controls the encoding process.
- * obj - Object to be encoded.
- * node - XML node that contains the encoded object.
- */
-mxObjectCodec.prototype.encodeObject = function(enc, obj, node)
-{
- enc.setAttribute(node, 'id', enc.getId(obj));
-
- for (var i in obj)
- {
- var name = i;
- var value = obj[name];
-
- if (value != null && !this.isExcluded(obj, name, value, true))
- {
- if (mxUtils.isNumeric(name))
- {
- name = null;
- }
-
- this.encodeValue(enc, obj, name, value, node);
- }
- }
-};
-
-/**
- * Function: encodeValue
- *
- * Converts the given value according to the mappings
- * and id-refs in this codec and uses <writeAttribute>
- * to write the attribute into the given node.
- *
- * Parameters:
- *
- * enc - <mxCodec> that controls the encoding process.
- * obj - Object whose property is going to be encoded.
- * name - XML node that contains the encoded object.
- * value - Value of the property to be encoded.
- * node - XML node that contains the encoded object.
- */
-mxObjectCodec.prototype.encodeValue = function(enc, obj,
- name, value, node)
-{
- if (value != null)
- {
- if (this.isReference(obj, name, value, true))
- {
- var tmp = enc.getId(value);
-
- if (tmp == null)
- {
- mxLog.warn('mxObjectCodec.encode: No ID for ' +
- this.getName() + '.' + name + '=' + value);
- return; // exit
- }
-
- value = tmp;
- }
-
- var defaultValue = this.template[name];
-
- // Checks if the value is a default value and
- // the name is correct
- if (name == null || enc.encodeDefaults ||
- defaultValue != value)
- {
- name = this.getAttributeName(name);
- this.writeAttribute(enc, obj, name, value, node);
- }
- }
-};
-
-/**
- * Function: writeAttribute
- *
- * Writes the given value into node using <writePrimitiveAttribute>
- * or <writeComplexAttribute> depending on the type of the value.
- */
-mxObjectCodec.prototype.writeAttribute = function(enc, obj,
- attr, value, node)
-{
- if (typeof(value) != 'object' /* primitive type */)
- {
- this.writePrimitiveAttribute(enc, obj, attr, value, node);
- }
- else /* complex type */
- {
- this.writeComplexAttribute(enc, obj, attr, value, node);
- }
-};
-
-/**
- * Function: writePrimitiveAttribute
- *
- * Writes the given value as an attribute of the given node.
- */
-mxObjectCodec.prototype.writePrimitiveAttribute = function(enc, obj,
- attr, value, node)
-{
- value = this.convertValueToXml(value);
-
- if (attr == null)
- {
- var child = enc.document.createElement('add');
-
- if (typeof(value) == 'function')
- {
- child.appendChild(
- enc.document.createTextNode(value));
- }
- else
- {
- enc.setAttribute(child, 'value', value);
- }
-
- node.appendChild(child);
- }
- else if (typeof(value) != 'function')
- {
- enc.setAttribute(node, attr, value);
- }
-};
-
-/**
- * Function: writeComplexAttribute
- *
- * Writes the given value as a child node of the given node.
- */
-mxObjectCodec.prototype.writeComplexAttribute = function(enc, obj,
- attr, value, node)
-{
- var child = enc.encode(value);
-
- if (child != null)
- {
- if (attr != null)
- {
- child.setAttribute('as', attr);
- }
-
- node.appendChild(child);
- }
- else
- {
- mxLog.warn('mxObjectCodec.encode: No node for ' +
- this.getName() + '.' + attr + ': ' + value);
- }
-};
-
-/**
- * Function: convertValueToXml
- *
- * Converts true to "1" and false to "0". All other values are ignored.
- */
-mxObjectCodec.prototype.convertValueToXml = function(value)
-{
- // Makes sure to encode boolean values as numeric values
- if (typeof(value.length) == 'undefined' &&
- (value == true ||
- value == false))
- {
- // Checks if the value is true (do not use the
- // value as is, because this would check if the
- // value is not null, so 0 would be true!
- value = (value == true) ? '1' : '0';
- }
- return value;
-};
-
-/**
- * Function: convertValueFromXml
- *
- * Converts booleans and numeric values to the respective types.
- */
-mxObjectCodec.prototype.convertValueFromXml = function(value)
-{
- if (mxUtils.isNumeric(value))
- {
- value = parseFloat(value);
- }
-
- return value;
-};
-
-/**
- * Function: beforeEncode
- *
- * Hook for subclassers to pre-process the object before
- * encoding. This returns the input object. The return
- * value of this function is used in <encode> to perform
- * the default encoding into the given node.
- *
- * Parameters:
- *
- * enc - <mxCodec> that controls the encoding process.
- * obj - Object to be encoded.
- * node - XML node to encode the object into.
- */
-mxObjectCodec.prototype.beforeEncode = function(enc, obj, node)
-{
- return obj;
-};
-
-/**
- * Function: afterEncode
- *
- * Hook for subclassers to post-process the node
- * for the given object after encoding and return the
- * post-processed node. This implementation returns
- * the input node. The return value of this method
- * is returned to the encoder from <encode>.
- *
- * Parameters:
- *
- * enc - <mxCodec> that controls the encoding process.
- * obj - Object to be encoded.
- * node - XML node that represents the default encoding.
- */
-mxObjectCodec.prototype.afterEncode = function(enc, obj, node)
-{
- return node;
-};
-
-/**
- * Function: decode
- *
- * Parses the given node into the object or returns a new object
- * representing the given node.
- *
- * Dec is a reference to the calling decoder. It is used to decode
- * complex objects and resolve references.
- *
- * If a node has an id attribute then the object cache is checked for the
- * object. If the object is not yet in the cache then it is constructed
- * using the constructor of <template> and cached in <mxCodec.objects>.
- *
- * This implementation decodes all attributes and childs of a node
- * according to the following rules:
- *
- * - If the variable name is in <exclude> or if the attribute name is "id"
- * or "as" then it is ignored.
- * - If the variable name is in <idrefs> then <mxCodec.getObject> is used
- * to replace the reference with an object.
- * - The variable name is mapped using a reverse <mapping>.
- * - If the value has a child node, then the codec is used to create a
- * child object with the variable name taken from the "as" attribute.
- * - If the object is an array and the variable name is empty then the
- * value or child object is appended to the array.
- * - If an add child has no value or the object is not an array then
- * the child text content is evaluated using <mxUtils.eval>.
- *
- * For add nodes where the object is not an array and the variable name
- * is defined, the default mechanism is used, allowing to override/add
- * methods as follows:
- *
- * (code)
- * <Object>
- * <add as="hello"><![CDATA[
- * function(arg1) {
- * mxUtils.alert('Hello '+arg1);
- * }
- * ]]></add>
- * </Object>
- * (end)
- *
- * If no object exists for an ID in <idrefs> a warning is issued
- * using <mxLog.warn>.
- *
- * Returns the resulting object that represents the given XML node
- * or the object given to the method as the into parameter.
- *
- * Parameters:
- *
- * dec - <mxCodec> that controls the decoding process.
- * node - XML node to be decoded.
- * into - Optional objec to encode the node into.
- */
-mxObjectCodec.prototype.decode = function(dec, node, into)
-{
- var id = node.getAttribute('id');
- var obj = dec.objects[id];
-
- if (obj == null)
- {
- obj = into || this.cloneTemplate();
-
- if (id != null)
- {
- dec.putObject(id, obj);
- }
- }
-
- node = this.beforeDecode(dec, node, obj);
- this.decodeNode(dec, node, obj);
-
- return this.afterDecode(dec, node, obj);
-};
-
-/**
- * Function: decodeNode
- *
- * Calls <decodeAttributes> and <decodeChildren> for the given node.
- */
-mxObjectCodec.prototype.decodeNode = function(dec, node, obj)
-{
- if (node != null)
- {
- this.decodeAttributes(dec, node, obj);
- this.decodeChildren(dec, node, obj);
- }
-};
-
-/**
- * Function: decodeAttributes
- *
- * Decodes all attributes of the given node using <decodeAttribute>.
- */
-mxObjectCodec.prototype.decodeAttributes = function(dec, node, obj)
-{
- var attrs = node.attributes;
-
- if (attrs != null)
- {
- for (var i = 0; i < attrs.length; i++)
- {
- this.decodeAttribute(dec, attrs[i], obj);
- }
- }
-};
-
-/**
- * Function: decodeAttribute
- *
- * Reads the given attribute into the specified object.
- */
-mxObjectCodec.prototype.decodeAttribute = function(dec, attr, obj)
-{
- var name = attr.nodeName;
-
- if (name != 'as' && name != 'id')
- {
- // Converts the string true and false to their boolean values.
- // This may require an additional check on the obj to see if
- // the existing field is a boolean value or uninitialized, in
- // which case we may want to convert true and false to a string.
- var value = this.convertValueFromXml(attr.nodeValue);
- var fieldname = this.getFieldName(name);
-
- if (this.isReference(obj, fieldname, value, false))
- {
- var tmp = dec.getObject(value);
-
- if (tmp == null)
- {
- mxLog.warn('mxObjectCodec.decode: No object for ' +
- this.getName() + '.' + name + '=' + value);
- return; // exit
- }
-
- value = tmp;
- }
-
- if (!this.isExcluded(obj, name, value, false))
- {
- //mxLog.debug(mxUtils.getFunctionName(obj.constructor)+'.'+name+'='+value);
- obj[name] = value;
- }
- }
-};
-
-/**
- * Function: decodeChildren
- *
- * Decodec all children of the given node using <decodeChild>.
- */
-mxObjectCodec.prototype.decodeChildren = function(dec, node, obj)
-{
- var child = node.firstChild;
-
- while (child != null)
- {
- var tmp = child.nextSibling;
-
- if (child.nodeType == mxConstants.NODETYPE_ELEMENT &&
- !this.processInclude(dec, child, obj))
- {
- this.decodeChild(dec, child, obj);
- }
-
- child = tmp;
- }
-};
-
-/**
- * Function: decodeChild
- *
- * Reads the specified child into the given object.
- */
-mxObjectCodec.prototype.decodeChild = function(dec, child, obj)
-{
- var fieldname = this.getFieldName(child.getAttribute('as'));
-
- if (fieldname == null ||
- !this.isExcluded(obj, fieldname, child, false))
- {
- var template = this.getFieldTemplate(obj, fieldname, child);
- var value = null;
-
- if (child.nodeName == 'add')
- {
- value = child.getAttribute('value');
-
- if (value == null)
- {
- value = mxUtils.eval(mxUtils.getTextContent(child));
- //mxLog.debug('Decoded '+fieldname+' '+mxUtils.getTextContent(child));
- }
- }
- else
- {
- value = dec.decode(child, template);
- // mxLog.debug('Decoded '+node.nodeName+'.'+fieldname+'='+
- // ((tmp != null) ? tmp.constructor.name : 'null'));
- }
-
- this.addObjectValue(obj, fieldname, value, template);
- }
-};
-
-/**
- * Function: getFieldTemplate
- *
- * Returns the template instance for the given field. This returns the
- * value of the field, null if the value is an array or an empty collection
- * if the value is a collection. The value is then used to populate the
- * field for a new instance. For strongly typed languages it may be
- * required to override this to return the correct collection instance
- * based on the encoded child.
- */
-mxObjectCodec.prototype.getFieldTemplate = function(obj, fieldname, child)
-{
- var template = obj[fieldname];
-
- // Non-empty arrays are replaced completely
- if (template instanceof Array && template.length > 0)
- {
- template = null;
- }
-
- return template;
-};
-
-/**
- * Function: addObjectValue
- *
- * Sets the decoded child node as a value of the given object. If the
- * object is a map, then the value is added with the given fieldname as a
- * key. If the fieldname is not empty, then setFieldValue is called or
- * else, if the object is a collection, the value is added to the
- * collection. For strongly typed languages it may be required to
- * override this with the correct code to add an entry to an object.
- */
-mxObjectCodec.prototype.addObjectValue = function(obj, fieldname, value, template)
-{
- if (value != null && value != template)
- {
- if (fieldname != null && fieldname.length > 0)
- {
- obj[fieldname] = value;
- }
- else
- {
- obj.push(value);
- }
- //mxLog.debug('Decoded '+mxUtils.getFunctionName(obj.constructor)+'.'+fieldname+': '+value);
- }
-};
-
-/**
- * Function: processInclude
- *
- * Returns true if the given node is an include directive and
- * executes the include by decoding the XML document. Returns
- * false if the given node is not an include directive.
- *
- * Parameters:
- *
- * dec - <mxCodec> that controls the encoding/decoding process.
- * node - XML node to be checked.
- * into - Optional object to pass-thru to the codec.
- */
-mxObjectCodec.prototype.processInclude = function(dec, node, into)
-{
- if (node.nodeName == 'include')
- {
- var name = node.getAttribute('name');
-
- if (name != null)
- {
- try
- {
- var xml = mxUtils.load(name).getDocumentElement();
-
- if (xml != null)
- {
- dec.decode(xml, into);
- }
- }
- catch (e)
- {
- // ignore
- }
- }
-
- return true;
- }
-
- return false;
-};
-
-/**
- * Function: beforeDecode
- *
- * Hook for subclassers to pre-process the node for
- * the specified object and return the node to be
- * used for further processing by <decode>.
- * The object is created based on the template in the
- * calling method and is never null. This implementation
- * returns the input node. The return value of this
- * function is used in <decode> to perform
- * the default decoding into the given object.
- *
- * Parameters:
- *
- * dec - <mxCodec> that controls the decoding process.
- * node - XML node to be decoded.
- * obj - Object to encode the node into.
- */
-mxObjectCodec.prototype.beforeDecode = function(dec, node, obj)
-{
- return node;
-};
-
-/**
- * Function: afterDecode
- *
- * Hook for subclassers to post-process the object after
- * decoding. This implementation returns the given object
- * without any changes. The return value of this method
- * is returned to the decoder from <decode>.
- *
- * Parameters:
- *
- * enc - <mxCodec> that controls the encoding process.
- * node - XML node to be decoded.
- * obj - Object that represents the default decoding.
- */
-mxObjectCodec.prototype.afterDecode = function(dec, node, obj)
-{
- return obj;
-};
diff --git a/src/js/io/mxRootChangeCodec.js b/src/js/io/mxRootChangeCodec.js
deleted file mode 100644
index fda613a..0000000
--- a/src/js/io/mxRootChangeCodec.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * $Id: mxRootChangeCodec.js,v 1.6 2010-09-15 14:38:51 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxRootChangeCodec
- *
- * Codec for <mxRootChange>s. This class is created and registered
- * dynamically at load time and used implicitely via <mxCodec> and
- * the <mxCodecRegistry>.
- *
- * Transient Fields:
- *
- * - model
- * - previous
- * - root
- */
- var codec = new mxObjectCodec(new mxRootChange(),
- ['model', 'previous', 'root']);
-
- /**
- * Function: onEncode
- *
- * Encodes the child recursively.
- */
- codec.afterEncode = function(enc, obj, node)
- {
- enc.encodeCell(obj.root, node);
-
- return node;
- };
-
- /**
- * Function: beforeDecode
- *
- * Decodes the optional children as cells
- * using the respective decoder.
- */
- codec.beforeDecode = function(dec, node, obj)
- {
- if (node.firstChild != null &&
- node.firstChild.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- // Makes sure the original node isn't modified
- node = node.cloneNode(true);
-
- var tmp = node.firstChild;
- obj.root = dec.decodeCell(tmp, false);
-
- var tmp2 = tmp.nextSibling;
- tmp.parentNode.removeChild(tmp);
- tmp = tmp2;
-
- while (tmp != null)
- {
- tmp2 = tmp.nextSibling;
- dec.decodeCell(tmp);
- tmp.parentNode.removeChild(tmp);
- tmp = tmp2;
- }
- }
-
- return node;
- };
-
- /**
- * Function: afterDecode
- *
- * Restores the state by assigning the previous value.
- */
- codec.afterDecode = function(dec, node, obj)
- {
- obj.previous = obj.root;
-
- return obj;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxStylesheetCodec.js b/src/js/io/mxStylesheetCodec.js
deleted file mode 100644
index 7636eb1..0000000
--- a/src/js/io/mxStylesheetCodec.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/**
- * $Id: mxStylesheetCodec.js,v 1.19 2011-06-13 08:18:42 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxStylesheetCodec
- *
- * Codec for <mxStylesheet>s. This class is created and registered
- * dynamically at load time and used implicitely via <mxCodec>
- * and the <mxCodecRegistry>.
- */
- var codec = new mxObjectCodec(new mxStylesheet());
-
- /**
- * Function: encode
- *
- * Encodes a stylesheet. See <decode> for a description of the
- * format.
- */
- codec.encode = function(enc, obj)
- {
- var node = enc.document.createElement(this.getName());
-
- for (var i in obj.styles)
- {
- var style = obj.styles[i];
- var styleNode = enc.document.createElement('add');
-
- if (i != null)
- {
- styleNode.setAttribute('as', i);
-
- for (var j in style)
- {
- var value = this.getStringValue(j, style[j]);
-
- if (value != null)
- {
- var entry = enc.document.createElement('add');
- entry.setAttribute('value', value);
- entry.setAttribute('as', j);
- styleNode.appendChild(entry);
- }
- }
-
- if (styleNode.childNodes.length > 0)
- {
- node.appendChild(styleNode);
- }
- }
- }
-
- return node;
- };
-
- /**
- * Function: getStringValue
- *
- * Returns the string for encoding the given value.
- */
- codec.getStringValue = function(key, value)
- {
- var type = typeof(value);
-
- if (type == 'function')
- {
- value = mxStyleRegistry.getName(style[j]);
- }
- else if (type == 'object')
- {
- value = null;
- }
-
- return value;
- };
-
- /**
- * Function: decode
- *
- * Reads a sequence of the following child nodes
- * and attributes:
- *
- * Child Nodes:
- *
- * add - Adds a new style.
- *
- * Attributes:
- *
- * as - Name of the style.
- * extend - Name of the style to inherit from.
- *
- * Each node contains another sequence of add and remove nodes with the following
- * attributes:
- *
- * as - Name of the style (see <mxConstants>).
- * value - Value for the style.
- *
- * Instead of the value-attribute, one can put Javascript expressions into
- * the node as follows:
- * <add as="perimeter">mxPerimeter.RectanglePerimeter</add>
- *
- * A remove node will remove the entry with the name given in the as-attribute
- * from the style.
- *
- * Example:
- *
- * (code)
- * <mxStylesheet as="stylesheet">
- * <add as="text">
- * <add as="fontSize" value="12"/>
- * </add>
- * <add as="defaultVertex" extend="text">
- * <add as="shape" value="rectangle"/>
- * </add>
- * </mxStylesheet>
- * (end)
- */
- codec.decode = function(dec, node, into)
- {
- var obj = into || new this.template.constructor();
- var id = node.getAttribute('id');
-
- if (id != null)
- {
- dec.objects[id] = obj;
- }
-
- node = node.firstChild;
-
- while (node != null)
- {
- if (!this.processInclude(dec, node, obj) &&
- node.nodeName == 'add')
- {
- var as = node.getAttribute('as');
-
- if (as != null)
- {
- var extend = node.getAttribute('extend');
- var style = (extend != null) ? mxUtils.clone(obj.styles[extend]) : null;
-
- if (style == null)
- {
- if (extend != null)
- {
- mxLog.warn('mxStylesheetCodec.decode: stylesheet ' +
- extend + ' not found to extend');
- }
-
- style = new Object();
- }
-
- var entry = node.firstChild;
-
- while (entry != null)
- {
- if (entry.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- var key = entry.getAttribute('as');
-
- if (entry.nodeName == 'add')
- {
- var text = mxUtils.getTextContent(entry);
- var value = null;
-
- if (text != null &&
- text.length > 0)
- {
- value = mxUtils.eval(text);
- }
- else
- {
- value = entry.getAttribute('value');
-
- if (mxUtils.isNumeric(value))
- {
- value = parseFloat(value);
- }
- }
-
- if (value != null)
- {
- style[key] = value;
- }
- }
- else if (entry.nodeName == 'remove')
- {
- delete style[key];
- }
- }
-
- entry = entry.nextSibling;
- }
-
- obj.putCellStyle(as, style);
- }
- }
-
- node = node.nextSibling;
- }
-
- return obj;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/io/mxTerminalChangeCodec.js b/src/js/io/mxTerminalChangeCodec.js
deleted file mode 100644
index a51d871..0000000
--- a/src/js/io/mxTerminalChangeCodec.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * $Id: mxTerminalChangeCodec.js,v 1.7 2010-09-13 15:58:36 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-mxCodecRegistry.register(function()
-{
- /**
- * Class: mxTerminalChangeCodec
- *
- * Codec for <mxTerminalChange>s. This class is created and registered
- * dynamically at load time and used implicitely via <mxCodec> and
- * the <mxCodecRegistry>.
- *
- * Transient Fields:
- *
- * - model
- * - previous
- *
- * Reference Fields:
- *
- * - cell
- * - terminal
- */
- var codec = new mxObjectCodec(new mxTerminalChange(),
- ['model', 'previous'], ['cell', 'terminal']);
-
- /**
- * Function: afterDecode
- *
- * Restores the state by assigning the previous value.
- */
- codec.afterDecode = function(dec, node, obj)
- {
- obj.previous = obj.terminal;
-
- return obj;
- };
-
- // Returns the codec into the registry
- return codec;
-
-}());
diff --git a/src/js/layout/hierarchical/model/mxGraphAbstractHierarchyCell.js b/src/js/layout/hierarchical/model/mxGraphAbstractHierarchyCell.js
deleted file mode 100644
index e2fe6a6..0000000
--- a/src/js/layout/hierarchical/model/mxGraphAbstractHierarchyCell.js
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * $Id: mxGraphAbstractHierarchyCell.js,v 1.12 2010-01-04 11:18:26 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraphAbstractHierarchyCell
- *
- * An abstraction of an internal hierarchy node or edge
- *
- * Constructor: mxGraphAbstractHierarchyCell
- *
- * Constructs a new hierarchical layout algorithm.
- *
- * Arguments:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * deterministic - Optional boolean that specifies if this layout should be
- * deterministic. Default is true.
- */
-function mxGraphAbstractHierarchyCell()
-{
- this.x = [];
- this.y = [];
- this.temp = [];
-};
-
-/**
- * Variable: maxRank
- *
- * The maximum rank this cell occupies. Default is -1.
- */
-mxGraphAbstractHierarchyCell.prototype.maxRank = -1;
-
-/**
- * Variable: minRank
- *
- * The minimum rank this cell occupies. Default is -1.
- */
-mxGraphAbstractHierarchyCell.prototype.minRank = -1;
-
-/**
- * Variable: x
- *
- * The x position of this cell for each layer it occupies
- */
-mxGraphAbstractHierarchyCell.prototype.x = null;
-
-/**
- * Variable: y
- *
- * The y position of this cell for each layer it occupies
- */
-mxGraphAbstractHierarchyCell.prototype.y = null;
-
-/**
- * Variable: width
- *
- * The width of this cell
- */
-mxGraphAbstractHierarchyCell.prototype.width = 0;
-
-/**
- * Variable: height
- *
- * The height of this cell
- */
-mxGraphAbstractHierarchyCell.prototype.height = 0;
-
-/**
- * Variable: nextLayerConnectedCells
- *
- * A cached version of the cells this cell connects to on the next layer up
- */
-mxGraphAbstractHierarchyCell.prototype.nextLayerConnectedCells = null;
-
-/**
- * Variable: previousLayerConnectedCells
- *
- * A cached version of the cells this cell connects to on the next layer down
- */
-mxGraphAbstractHierarchyCell.prototype.previousLayerConnectedCells = null;
-
-/**
- * Variable: temp
- *
- * Temporary variable for general use. Generally, try to avoid
- * carrying information between stages. Currently, the longest
- * path layering sets temp to the rank position in fixRanks()
- * and the crossing reduction uses this. This meant temp couldn't
- * be used for hashing the nodes in the model dfs and so hashCode
- * was created
- */
-mxGraphAbstractHierarchyCell.prototype.temp = null;
-
-/**
- * Function: getNextLayerConnectedCells
- *
- * Returns the cells this cell connects to on the next layer up
- */
-mxGraphAbstractHierarchyCell.prototype.getNextLayerConnectedCells = function(layer)
-{
- return null;
-};
-
-/**
- * Function: getPreviousLayerConnectedCells
- *
- * Returns the cells this cell connects to on the next layer down
- */
-mxGraphAbstractHierarchyCell.prototype.getPreviousLayerConnectedCells = function(layer)
-{
- return null;
-};
-
-/**
- * Function: isEdge
- *
- * Returns whether or not this cell is an edge
- */
-mxGraphAbstractHierarchyCell.prototype.isEdge = function()
-{
- return false;
-};
-
-/**
- * Function: isVertex
- *
- * Returns whether or not this cell is a node
- */
-mxGraphAbstractHierarchyCell.prototype.isVertex = function()
-{
- return false;
-};
-
-/**
- * Function: getGeneralPurposeVariable
- *
- * Gets the value of temp for the specified layer
- */
-mxGraphAbstractHierarchyCell.prototype.getGeneralPurposeVariable = function(layer)
-{
- return null;
-};
-
-/**
- * Function: setGeneralPurposeVariable
- *
- * Set the value of temp for the specified layer
- */
-mxGraphAbstractHierarchyCell.prototype.setGeneralPurposeVariable = function(layer, value)
-{
- return null;
-};
-
-/**
- * Function: setX
- *
- * Set the value of x for the specified layer
- */
-mxGraphAbstractHierarchyCell.prototype.setX = function(layer, value)
-{
- if (this.isVertex())
- {
- this.x[0] = value;
- }
- else if (this.isEdge())
- {
- this.x[layer - this.minRank - 1] = value;
- }
-};
-
-/**
- * Function: getX
- *
- * Gets the value of x on the specified layer
- */
-mxGraphAbstractHierarchyCell.prototype.getX = function(layer)
-{
- if (this.isVertex())
- {
- return this.x[0];
- }
- else if (this.isEdge())
- {
- return this.x[layer - this.minRank - 1];
- }
-
- return 0.0;
-};
-
-/**
- * Function: setY
- *
- * Set the value of y for the specified layer
- */
-mxGraphAbstractHierarchyCell.prototype.setY = function(layer, value)
-{
- if (this.isVertex())
- {
- this.y[0] = value;
- }
- else if (this.isEdge())
- {
- this.y[layer -this. minRank - 1] = value;
- }
-};
diff --git a/src/js/layout/hierarchical/model/mxGraphHierarchyEdge.js b/src/js/layout/hierarchical/model/mxGraphHierarchyEdge.js
deleted file mode 100644
index 8ba16dd..0000000
--- a/src/js/layout/hierarchical/model/mxGraphHierarchyEdge.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/**
- * $Id: mxGraphHierarchyEdge.js,v 1.15 2012-06-12 20:23:14 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraphHierarchyEdge
- *
- * An abstraction of a hierarchical edge for the hierarchy layout
- *
- * Constructor: mxGraphHierarchyEdge
- *
- * Constructs a hierarchy edge
- *
- * Arguments:
- *
- * edges - a list of real graph edges this abstraction represents
- */
-function mxGraphHierarchyEdge(edges)
-{
- mxGraphAbstractHierarchyCell.apply(this, arguments);
- this.edges = edges;
-};
-
-/**
- * Extends mxGraphAbstractHierarchyCell.
- */
-mxGraphHierarchyEdge.prototype = new mxGraphAbstractHierarchyCell();
-mxGraphHierarchyEdge.prototype.constructor = mxGraphHierarchyEdge;
-
-/**
- * Variable: edges
- *
- * The graph edge(s) this object represents. Parallel edges are all grouped
- * together within one hierarchy edge.
- */
-mxGraphHierarchyEdge.prototype.edges = null;
-
-/**
- * Variable: source
- *
- * The node this edge is sourced at
- */
-mxGraphHierarchyEdge.prototype.source = null;
-
-/**
- * Variable: target
- *
- * The node this edge targets
- */
-mxGraphHierarchyEdge.prototype.target = null;
-
-/**
- * Variable: isReversed
- *
- * Whether or not the direction of this edge has been reversed
- * internally to create a DAG for the hierarchical layout
- */
-mxGraphHierarchyEdge.prototype.isReversed = false;
-
-/**
- * Function: invert
- *
- * Inverts the direction of this internal edge(s)
- */
-mxGraphHierarchyEdge.prototype.invert = function(layer)
-{
- var temp = this.source;
- this.source = this.target;
- this.target = temp;
- this.isReversed = !this.isReversed;
-};
-
-/**
- * Function: getNextLayerConnectedCells
- *
- * Returns the cells this cell connects to on the next layer up
- */
-mxGraphHierarchyEdge.prototype.getNextLayerConnectedCells = function(layer)
-{
- if (this.nextLayerConnectedCells == null)
- {
- this.nextLayerConnectedCells = [];
-
- for (var i = 0; i < this.temp.length; i++)
- {
- this.nextLayerConnectedCells[i] = [];
-
- if (i == this.temp.length - 1)
- {
- this.nextLayerConnectedCells[i].push(this.source);
- }
- else
- {
- this.nextLayerConnectedCells[i].push(this);
- }
- }
- }
-
- return this.nextLayerConnectedCells[layer - this.minRank - 1];
-};
-
-/**
- * Function: getPreviousLayerConnectedCells
- *
- * Returns the cells this cell connects to on the next layer down
- */
-mxGraphHierarchyEdge.prototype.getPreviousLayerConnectedCells = function(layer)
-{
- if (this.previousLayerConnectedCells == null)
- {
- this.previousLayerConnectedCells = [];
-
- for (var i = 0; i < this.temp.length; i++)
- {
- this.previousLayerConnectedCells[i] = [];
-
- if (i == 0)
- {
- this.previousLayerConnectedCells[i].push(this.target);
- }
- else
- {
- this.previousLayerConnectedCells[i].push(this);
- }
- }
- }
-
- return this.previousLayerConnectedCells[layer - this.minRank - 1];
-};
-
-/**
- * Function: isEdge
- *
- * Returns true.
- */
-mxGraphHierarchyEdge.prototype.isEdge = function()
-{
- return true;
-};
-
-/**
- * Function: getGeneralPurposeVariable
- *
- * Gets the value of temp for the specified layer
- */
-mxGraphHierarchyEdge.prototype.getGeneralPurposeVariable = function(layer)
-{
- return this.temp[layer - this.minRank - 1];
-};
-
-/**
- * Function: setGeneralPurposeVariable
- *
- * Set the value of temp for the specified layer
- */
-mxGraphHierarchyEdge.prototype.setGeneralPurposeVariable = function(layer, value)
-{
- this.temp[layer - this.minRank - 1] = value;
-};
-
-/**
- * Function: getCoreCell
- *
- * Gets the first core edge associated with this wrapper
- */
-mxGraphHierarchyEdge.prototype.getCoreCell = function()
-{
- if (this.edges != null && this.edges.length > 0)
- {
- return this.edges[0];
- }
-
- return null;
-}; \ No newline at end of file
diff --git a/src/js/layout/hierarchical/model/mxGraphHierarchyModel.js b/src/js/layout/hierarchical/model/mxGraphHierarchyModel.js
deleted file mode 100644
index ca2ba30..0000000
--- a/src/js/layout/hierarchical/model/mxGraphHierarchyModel.js
+++ /dev/null
@@ -1,685 +0,0 @@
-/**
- * $Id: mxGraphHierarchyModel.js,v 1.33 2012-12-18 13:16:43 david Exp $
- * Copyright (c) 2006-2012, JGraph Ltd
- */
-/**
- * Class: mxGraphHierarchyModel
- *
- * Internal model of a hierarchical graph. This model stores nodes and edges
- * equivalent to the real graph nodes and edges, but also stores the rank of the
- * cells, the order within the ranks and the new candidate locations of cells.
- * The internal model also reverses edge direction were appropriate , ignores
- * self-loop and groups parallels together under one edge object.
- *
- * Constructor: mxGraphHierarchyModel
- *
- * Creates an internal ordered graph model using the vertices passed in. If
- * there are any, leftward edge need to be inverted in the internal model
- *
- * Arguments:
- *
- * graph - the facade describing the graph to be operated on
- * vertices - the vertices for this hierarchy
- * ordered - whether or not the vertices are already ordered
- * deterministic - whether or not this layout should be deterministic on each
- * tightenToSource - whether or not to tighten vertices towards the sources
- * scanRanksFromSinks - Whether rank assignment is from the sinks or sources.
- * usage
- */
-function mxGraphHierarchyModel(layout, vertices, roots, parent, tightenToSource)
-{
- var graph = layout.getGraph();
- this.tightenToSource = tightenToSource;
- this.roots = roots;
- this.parent = parent;
-
- // map of cells to internal cell needed for second run through
- // to setup the sink of edges correctly
- this.vertexMapper = new Object();
- this.edgeMapper = new Object();
- this.maxRank = 0;
- var internalVertices = [];
-
- if (vertices == null)
- {
- vertices = this.graph.getChildVertices(parent);
- }
-
- this.maxRank = this.SOURCESCANSTARTRANK;
- // map of cells to internal cell needed for second run through
- // to setup the sink of edges correctly. Guess size by number
- // of edges is roughly same as number of vertices.
- this.createInternalCells(layout, vertices, internalVertices);
-
- // Go through edges set their sink values. Also check the
- // ordering if and invert edges if necessary
- for (var i = 0; i < vertices.length; i++)
- {
- var edges = internalVertices[i].connectsAsSource;
-
- for (var j = 0; j < edges.length; j++)
- {
- var internalEdge = edges[j];
- var realEdges = internalEdge.edges;
-
- // Only need to process the first real edge, since
- // all the edges connect to the same other vertex
- if (realEdges != null && realEdges.length > 0)
- {
- var realEdge = realEdges[0];
- var targetCell = graph.getView().getVisibleTerminal(
- realEdge, false);
- var targetCellId = mxCellPath.create(targetCell);
- var internalTargetCell = this.vertexMapper[targetCellId];
-
- if (internalVertices[i] == internalTargetCell)
- {
- // The real edge is reversed relative to the internal edge
- targetCell = graph.getView().getVisibleTerminal(
- realEdge, true);
- targetCellId = mxCellPath.create(targetCell);
- internalTargetCell = this.vertexMapper[targetCellId];
- }
-
- if (internalTargetCell != null
- && internalVertices[i] != internalTargetCell)
- {
- internalEdge.target = internalTargetCell;
-
- if (internalTargetCell.connectsAsTarget.length == 0)
- {
- internalTargetCell.connectsAsTarget = [];
- }
-
- if (mxUtils.indexOf(internalTargetCell.connectsAsTarget, internalEdge) < 0)
- {
- internalTargetCell.connectsAsTarget.push(internalEdge);
- }
- }
- }
- }
-
- // Use the temp variable in the internal nodes to mark this
- // internal vertex as having been visited.
- internalVertices[i].temp[0] = 1;
- }
-};
-
-/**
- * Variable: maxRank
- *
- * Stores the largest rank number allocated
- */
-mxGraphHierarchyModel.prototype.maxRank = null;
-
-/**
- * Variable: vertexMapper
- *
- * Map from graph vertices to internal model nodes.
- */
-mxGraphHierarchyModel.prototype.vertexMapper = null;
-
-/**
- * Variable: edgeMapper
- *
- * Map from graph edges to internal model edges
- */
-mxGraphHierarchyModel.prototype.edgeMapper = null;
-
-/**
- * Variable: ranks
- *
- * Mapping from rank number to actual rank
- */
-mxGraphHierarchyModel.prototype.ranks = null;
-
-/**
- * Variable: roots
- *
- * Store of roots of this hierarchy model, these are real graph cells, not
- * internal cells
- */
-mxGraphHierarchyModel.prototype.roots = null;
-
-/**
- * Variable: parent
- *
- * The parent cell whose children are being laid out
- */
-mxGraphHierarchyModel.prototype.parent = null;
-
-/**
- * Variable: dfsCount
- *
- * Count of the number of times the ancestor dfs has been used.
- */
-mxGraphHierarchyModel.prototype.dfsCount = 0;
-
-/**
- * Variable: SOURCESCANSTARTRANK
- *
- * High value to start source layering scan rank value from.
- */
-mxGraphHierarchyModel.prototype.SOURCESCANSTARTRANK = 100000000;
-
-/**
- * Variable: tightenToSource
- *
- * Whether or not to tighten the assigned ranks of vertices up towards
- * the source cells.
- */
-mxGraphHierarchyModel.prototype.tightenToSource = false;
-
-/**
- * Function: createInternalCells
- *
- * Creates all edges in the internal model
- *
- * Parameters:
- *
- * layout - Reference to the <mxHierarchicalLayout> algorithm.
- * vertices - Array of <mxCells> that represent the vertices whom are to
- * have an internal representation created.
- * internalVertices - The array of <mxGraphHierarchyNodes> to have their
- * information filled in using the real vertices.
- */
-mxGraphHierarchyModel.prototype.createInternalCells = function(layout, vertices, internalVertices)
-{
- var graph = layout.getGraph();
-
- // Create internal edges
- for (var i = 0; i < vertices.length; i++)
- {
- internalVertices[i] = new mxGraphHierarchyNode(vertices[i]);
- var vertexId = mxCellPath.create(vertices[i]);
- this.vertexMapper[vertexId] = internalVertices[i];
-
- // If the layout is deterministic, order the cells
- //List outgoingCells = graph.getNeighbours(vertices[i], deterministic);
- var conns = layout.getEdges(vertices[i]);
- var outgoingCells = graph.getOpposites(conns, vertices[i]);
- internalVertices[i].connectsAsSource = [];
-
- // Create internal edges, but don't do any rank assignment yet
- // First use the information from the greedy cycle remover to
- // invert the leftward edges internally
- for (var j = 0; j < outgoingCells.length; j++)
- {
- var cell = outgoingCells[j];
-
- if (cell != vertices[i] && layout.graph.model.isVertex(cell) &&
- !layout.isVertexIgnored(cell))
- {
- // We process all edge between this source and its targets
- // If there are edges going both ways, we need to collect
- // them all into one internal edges to avoid looping problems
- // later. We assume this direction (source -> target) is the
- // natural direction if at least half the edges are going in
- // that direction.
-
- // The check below for edges[0] being in the vertex mapper is
- // in case we've processed this the other way around
- // (target -> source) and the number of edges in each direction
- // are the same. All the graph edges will have been assigned to
- // an internal edge going the other way, so we don't want to
- // process them again
- var undirectedEdges = graph.getEdgesBetween(vertices[i],
- cell, false);
- var directedEdges = graph.getEdgesBetween(vertices[i],
- cell, true);
- var edgeId = mxCellPath.create(undirectedEdges[0]);
-
- if (undirectedEdges != null &&
- undirectedEdges.length > 0 &&
- this.edgeMapper[edgeId] == null &&
- directedEdges.length * 2 >= undirectedEdges.length)
- {
- var internalEdge = new mxGraphHierarchyEdge(undirectedEdges);
-
- for (var k = 0; k < undirectedEdges.length; k++)
- {
- var edge = undirectedEdges[k];
- edgeId = mxCellPath.create(edge);
- this.edgeMapper[edgeId] = internalEdge;
-
- // Resets all point on the edge and disables the edge style
- // without deleting it from the cell style
- graph.resetEdge(edge);
-
- if (layout.disableEdgeStyle)
- {
- layout.setEdgeStyleEnabled(edge, false);
- layout.setOrthogonalEdge(edge,true);
- }
- }
-
- internalEdge.source = internalVertices[i];
-
- if (mxUtils.indexOf(internalVertices[i].connectsAsSource, internalEdge) < 0)
- {
- internalVertices[i].connectsAsSource.push(internalEdge);
- }
- }
- }
- }
-
- // Ensure temp variable is cleared from any previous use
- internalVertices[i].temp[0] = 0;
- }
-};
-
-/**
- * Function: initialRank
- *
- * Basic determination of minimum layer ranking by working from from sources
- * or sinks and working through each node in the relevant edge direction.
- * Starting at the sinks is basically a longest path layering algorithm.
-*/
-mxGraphHierarchyModel.prototype.initialRank = function()
-{
- var startNodes = [];
-
- if (this.roots != null)
- {
- for (var i = 0; i < this.roots.length; i++)
- {
- var vertexId = mxCellPath.create(this.roots[i]);
- var internalNode = this.vertexMapper[vertexId];
-
- if (internalNode != null)
- {
- startNodes.push(internalNode);
- }
- }
- }
-
- for (var key in this.vertexMapper)
- {
- var internalNode = this.vertexMapper[key];
-
- // Mark the node as not having had a layer assigned
- internalNode.temp[0] = -1;
- }
-
- var startNodesCopy = startNodes.slice();
-
- while (startNodes.length > 0)
- {
- var internalNode = startNodes[0];
- var layerDeterminingEdges;
- var edgesToBeMarked;
-
- layerDeterminingEdges = internalNode.connectsAsTarget;
- edgesToBeMarked = internalNode.connectsAsSource;
-
- // flag to keep track of whether or not all layer determining
- // edges have been scanned
- var allEdgesScanned = true;
-
- // Work out the layer of this node from the layer determining
- // edges. The minimum layer number of any node connected by one of
- // the layer determining edges variable
- var minimumLayer = this.SOURCESCANSTARTRANK;
-
- for (var i = 0; i < layerDeterminingEdges.length; i++)
- {
- var internalEdge = layerDeterminingEdges[i];
-
- if (internalEdge.temp[0] == 5270620)
- {
- // This edge has been scanned, get the layer of the
- // node on the other end
- var otherNode = internalEdge.source;
- minimumLayer = Math.min(minimumLayer, otherNode.temp[0] - 1);
- }
- else
- {
- allEdgesScanned = false;
-
- break;
- }
- }
-
- // If all edge have been scanned, assign the layer, mark all
- // edges in the other direction and remove from the nodes list
- if (allEdgesScanned)
- {
- internalNode.temp[0] = minimumLayer;
- this.maxRank = Math.min(this.maxRank, minimumLayer);
-
- if (edgesToBeMarked != null)
- {
- for (var i = 0; i < edgesToBeMarked.length; i++)
- {
- var internalEdge = edgesToBeMarked[i];
-
- // Assign unique stamp ( y/m/d/h )
- internalEdge.temp[0] = 5270620;
-
- // Add node on other end of edge to LinkedList of
- // nodes to be analysed
- var otherNode = internalEdge.target;
-
- // Only add node if it hasn't been assigned a layer
- if (otherNode.temp[0] == -1)
- {
- startNodes.push(otherNode);
-
- // Mark this other node as neither being
- // unassigned nor assigned so it isn't
- // added to this list again, but it's
- // layer isn't used in any calculation.
- otherNode.temp[0] = -2;
- }
- }
- }
-
- startNodes.shift();
- }
- else
- {
- // Not all the edges have been scanned, get to the back of
- // the class and put the dunces cap on
- var removedCell = startNodes.shift();
- startNodes.push(internalNode);
-
- if (removedCell == internalNode && startNodes.length == 1)
- {
- // This is an error condition, we can't get out of
- // this loop. It could happen for more than one node
- // but that's a lot harder to detect. Log the error
- // TODO make log comment
- break;
- }
- }
- }
-
- // Normalize the ranks down from their large starting value to place
- // at least 1 sink on layer 0
- for (var key in this.vertexMapper)
- {
- var internalNode = this.vertexMapper[key];
- // Mark the node as not having had a layer assigned
- internalNode.temp[0] -= this.maxRank;
- }
-
- // Tighten the rank 0 nodes as far as possible
- for ( var i = 0; i < startNodesCopy.length; i++)
- {
- var internalNode = startNodesCopy[i];
- var currentMaxLayer = 0;
- var layerDeterminingEdges = internalNode.connectsAsSource;
-
- for ( var j = 0; j < layerDeterminingEdges.length; j++)
- {
- var internalEdge = layerDeterminingEdges[j];
- var otherNode = internalEdge.target;
- internalNode.temp[0] = Math.max(currentMaxLayer,
- otherNode.temp[0] + 1);
- currentMaxLayer = internalNode.temp[0];
- }
- }
-
- // Reset the maxRank to that which would be expected for a from-sink
- // scan
- this.maxRank = this.SOURCESCANSTARTRANK - this.maxRank;
-};
-
-/**
- * Function: fixRanks
- *
- * Fixes the layer assignments to the values stored in the nodes. Also needs
- * to create dummy nodes for edges that cross layers.
- */
-mxGraphHierarchyModel.prototype.fixRanks = function()
-{
- var rankList = [];
- this.ranks = [];
-
- for (var i = 0; i < this.maxRank + 1; i++)
- {
- rankList[i] = [];
- this.ranks[i] = rankList[i];
- }
-
- // Perform a DFS to obtain an initial ordering for each rank.
- // Without doing this you would end up having to process
- // crossings for a standard tree.
- var rootsArray = null;
-
- if (this.roots != null)
- {
- var oldRootsArray = this.roots;
- rootsArray = [];
-
- for (var i = 0; i < oldRootsArray.length; i++)
- {
- var cell = oldRootsArray[i];
- var cellId = mxCellPath.create(cell);
- var internalNode = this.vertexMapper[cellId];
- rootsArray[i] = internalNode;
- }
- }
-
- this.visit(function(parent, node, edge, layer, seen)
- {
- if (seen == 0 && node.maxRank < 0 && node.minRank < 0)
- {
- rankList[node.temp[0]].push(node);
- node.maxRank = node.temp[0];
- node.minRank = node.temp[0];
-
- // Set temp[0] to the nodes position in the rank
- node.temp[0] = rankList[node.maxRank].length - 1;
- }
-
- if (parent != null && edge != null)
- {
- var parentToCellRankDifference = parent.maxRank - node.maxRank;
-
- if (parentToCellRankDifference > 1)
- {
- // There are ranks in between the parent and current cell
- edge.maxRank = parent.maxRank;
- edge.minRank = node.maxRank;
- edge.temp = [];
- edge.x = [];
- edge.y = [];
-
- for (var i = edge.minRank + 1; i < edge.maxRank; i++)
- {
- // The connecting edge must be added to the
- // appropriate ranks
- rankList[i].push(edge);
- edge.setGeneralPurposeVariable(i, rankList[i]
- .length - 1);
- }
- }
- }
- }, rootsArray, false, null);
-};
-
-/**
- * Function: visit
- *
- * A depth first search through the internal heirarchy model.
- *
- * Parameters:
- *
- * visitor - The visitor function pattern to be called for each node.
- * trackAncestors - Whether or not the search is to keep track all nodes
- * directly above this one in the search path.
- */
-mxGraphHierarchyModel.prototype.visit = function(visitor, dfsRoots, trackAncestors, seenNodes)
-{
- // Run dfs through on all roots
- if (dfsRoots != null)
- {
- for (var i = 0; i < dfsRoots.length; i++)
- {
- var internalNode = dfsRoots[i];
-
- if (internalNode != null)
- {
- if (seenNodes == null)
- {
- seenNodes = new Object();
- }
-
- if (trackAncestors)
- {
- // Set up hash code for root
- internalNode.hashCode = [];
- internalNode.hashCode[0] = this.dfsCount;
- internalNode.hashCode[1] = i;
- this.extendedDfs(null, internalNode, null, visitor, seenNodes,
- internalNode.hashCode, i, 0);
- }
- else
- {
- this.dfs(null, internalNode, null, visitor, seenNodes, 0);
- }
- }
- }
-
- this.dfsCount++;
- }
-};
-
-/**
- * Function: dfs
- *
- * Performs a depth first search on the internal hierarchy model
- *
- * Parameters:
- *
- * parent - the parent internal node of the current internal node
- * root - the current internal node
- * connectingEdge - the internal edge connecting the internal node and the parent
- * internal node, if any
- * visitor - the visitor pattern to be called for each node
- * seen - a set of all nodes seen by this dfs a set of all of the
- * ancestor node of the current node
- * layer - the layer on the dfs tree ( not the same as the model ranks )
- */
-mxGraphHierarchyModel.prototype.dfs = function(parent, root, connectingEdge, visitor, seen, layer)
-{
- if (root != null)
- {
- var rootId = mxCellPath.create(root.cell);
-
- if (seen[rootId] == null)
- {
- seen[rootId] = root;
- visitor(parent, root, connectingEdge, layer, 0);
-
- // Copy the connects as source list so that visitors
- // can change the original for edge direction inversions
- var outgoingEdges = root.connectsAsSource.slice();
-
- for (var i = 0; i< outgoingEdges.length; i++)
- {
- var internalEdge = outgoingEdges[i];
- var targetNode = internalEdge.target;
-
- // Root check is O(|roots|)
- this.dfs(root, targetNode, internalEdge, visitor, seen,
- layer + 1);
- }
- }
- else
- {
- // Use the int field to indicate this node has been seen
- visitor(parent, root, connectingEdge, layer, 1);
- }
- }
-};
-
-/**
- * Function: extendedDfs
- *
- * Performs a depth first search on the internal hierarchy model. This dfs
- * extends the default version by keeping track of cells ancestors, but it
- * should be only used when necessary because of it can be computationally
- * intensive for deep searches.
- *
- * Parameters:
- *
- * parent - the parent internal node of the current internal node
- * root - the current internal node
- * connectingEdge - the internal edge connecting the internal node and the parent
- * internal node, if any
- * visitor - the visitor pattern to be called for each node
- * seen - a set of all nodes seen by this dfs
- * ancestors - the parent hash code
- * childHash - the new hash code for this node
- * layer - the layer on the dfs tree ( not the same as the model ranks )
- */
-mxGraphHierarchyModel.prototype.extendedDfs = function(parent, root, connectingEdge, visitor, seen, ancestors, childHash, layer)
-{
- // Explanation of custom hash set. Previously, the ancestors variable
- // was passed through the dfs as a HashSet. The ancestors were copied
- // into a new HashSet and when the new child was processed it was also
- // added to the set. If the current node was in its ancestor list it
- // meant there is a cycle in the graph and this information is passed
- // to the visitor.visit() in the seen parameter. The HashSet clone was
- // very expensive on CPU so a custom hash was developed using primitive
- // types. temp[] couldn't be used so hashCode[] was added to each node.
- // Each new child adds another int to the array, copying the prefix
- // from its parent. Child of the same parent add different ints (the
- // limit is therefore 2^32 children per parent...). If a node has a
- // child with the hashCode already set then the child code is compared
- // to the same portion of the current nodes array. If they match there
- // is a loop.
- // Note that the basic mechanism would only allow for 1 use of this
- // functionality, so the root nodes have two ints. The second int is
- // incremented through each node root and the first is incremented
- // through each run of the dfs algorithm (therefore the dfs is not
- // thread safe). The hash code of each node is set if not already set,
- // or if the first int does not match that of the current run.
- if (root != null)
- {
- if (parent != null)
- {
- // Form this nodes hash code if necessary, that is, if the
- // hashCode variable has not been initialized or if the
- // start of the parent hash code does not equal the start of
- // this nodes hash code, indicating the code was set on a
- // previous run of this dfs.
- if (root.hashCode == null ||
- root.hashCode[0] != parent.hashCode[0])
- {
- var hashCodeLength = parent.hashCode.length + 1;
- root.hashCode = parent.hashCode.slice();
- root.hashCode[hashCodeLength - 1] = childHash;
- }
- }
-
- var rootId = mxCellPath.create(root.cell);
-
- if (seen[rootId] == null)
- {
- seen[rootId] = root;
- visitor(parent, root, connectingEdge, layer, 0);
-
- // Copy the connects as source list so that visitors
- // can change the original for edge direction inversions
- var outgoingEdges = root.connectsAsSource.slice();
-
- for (var i = 0; i < outgoingEdges.length; i++)
- {
- var internalEdge = outgoingEdges[i];
- var targetNode = internalEdge.target;
-
- // Root check is O(|roots|)
- this.extendedDfs(root, targetNode, internalEdge, visitor, seen,
- root.hashCode, i, layer + 1);
- }
- }
- else
- {
- // Use the int field to indicate this node has been seen
- visitor(parent, root, connectingEdge, layer, 1);
- }
- }
-};
diff --git a/src/js/layout/hierarchical/model/mxGraphHierarchyNode.js b/src/js/layout/hierarchical/model/mxGraphHierarchyNode.js
deleted file mode 100644
index d901d57..0000000
--- a/src/js/layout/hierarchical/model/mxGraphHierarchyNode.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/**
- * $Id: mxGraphHierarchyNode.js,v 1.13 2012-06-12 20:24:58 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraphHierarchyNode
- *
- * An abstraction of a hierarchical edge for the hierarchy layout
- *
- * Constructor: mxGraphHierarchyNode
- *
- * Constructs an internal node to represent the specified real graph cell
- *
- * Arguments:
- *
- * cell - the real graph cell this node represents
- */
-function mxGraphHierarchyNode(cell)
-{
- mxGraphAbstractHierarchyCell.apply(this, arguments);
- this.cell = cell;
-};
-
-/**
- * Extends mxGraphAbstractHierarchyCell.
- */
-mxGraphHierarchyNode.prototype = new mxGraphAbstractHierarchyCell();
-mxGraphHierarchyNode.prototype.constructor = mxGraphHierarchyNode;
-
-/**
- * Variable: cell
- *
- * The graph cell this object represents.
- */
-mxGraphHierarchyNode.prototype.cell = null;
-
-/**
- * Variable: connectsAsTarget
- *
- * Collection of hierarchy edges that have this node as a target
- */
-mxGraphHierarchyNode.prototype.connectsAsTarget = [];
-
-/**
- * Variable: connectsAsSource
- *
- * Collection of hierarchy edges that have this node as a source
- */
-mxGraphHierarchyNode.prototype.connectsAsSource = [];
-
-/**
- * Variable: hashCode
- *
- * Assigns a unique hashcode for each node. Used by the model dfs instead
- * of copying HashSets
- */
-mxGraphHierarchyNode.prototype.hashCode = false;
-
-/**
- * Function: getRankValue
- *
- * Returns the integer value of the layer that this node resides in
- */
-mxGraphHierarchyNode.prototype.getRankValue = function(layer)
-{
- return this.maxRank;
-};
-
-/**
- * Function: getNextLayerConnectedCells
- *
- * Returns the cells this cell connects to on the next layer up
- */
-mxGraphHierarchyNode.prototype.getNextLayerConnectedCells = function(layer)
-{
- if (this.nextLayerConnectedCells == null)
- {
- this.nextLayerConnectedCells = [];
- this.nextLayerConnectedCells[0] = [];
-
- for (var i = 0; i < this.connectsAsTarget.length; i++)
- {
- var edge = this.connectsAsTarget[i];
-
- if (edge.maxRank == -1 || edge.maxRank == layer + 1)
- {
- // Either edge is not in any rank or
- // no dummy nodes in edge, add node of other side of edge
- this.nextLayerConnectedCells[0].push(edge.source);
- }
- else
- {
- // Edge spans at least two layers, add edge
- this.nextLayerConnectedCells[0].push(edge);
- }
- }
- }
-
- return this.nextLayerConnectedCells[0];
-};
-
-/**
- * Function: getPreviousLayerConnectedCells
- *
- * Returns the cells this cell connects to on the next layer down
- */
-mxGraphHierarchyNode.prototype.getPreviousLayerConnectedCells = function(layer)
-{
- if (this.previousLayerConnectedCells == null)
- {
- this.previousLayerConnectedCells = [];
- this.previousLayerConnectedCells[0] = [];
-
- for (var i = 0; i < this.connectsAsSource.length; i++)
- {
- var edge = this.connectsAsSource[i];
-
- if (edge.minRank == -1 || edge.minRank == layer - 1)
- {
- // No dummy nodes in edge, add node of other side of edge
- this.previousLayerConnectedCells[0].push(edge.target);
- }
- else
- {
- // Edge spans at least two layers, add edge
- this.previousLayerConnectedCells[0].push(edge);
- }
- }
- }
-
- return this.previousLayerConnectedCells[0];
-};
-
-/**
- * Function: isVertex
- *
- * Returns true.
- */
-mxGraphHierarchyNode.prototype.isVertex = function()
-{
- return true;
-};
-
-/**
- * Function: getGeneralPurposeVariable
- *
- * Gets the value of temp for the specified layer
- */
-mxGraphHierarchyNode.prototype.getGeneralPurposeVariable = function(layer)
-{
- return this.temp[0];
-};
-
-/**
- * Function: setGeneralPurposeVariable
- *
- * Set the value of temp for the specified layer
- */
-mxGraphHierarchyNode.prototype.setGeneralPurposeVariable = function(layer, value)
-{
- this.temp[0] = value;
-};
-
-/**
- * Function: isAncestor
- */
-mxGraphHierarchyNode.prototype.isAncestor = function(otherNode)
-{
- // Firstly, the hash code of this node needs to be shorter than the
- // other node
- if (otherNode != null && this.hashCode != null && otherNode.hashCode != null
- && this.hashCode.length < otherNode.hashCode.length)
- {
- if (this.hashCode == otherNode.hashCode)
- {
- return true;
- }
-
- if (this.hashCode == null || this.hashCode == null)
- {
- return false;
- }
-
- // Secondly, this hash code must match the start of the other
- // node's hash code. Arrays.equals cannot be used here since
- // the arrays are different length, and we do not want to
- // perform another array copy.
- for (var i = 0; i < this.hashCode.length; i++)
- {
- if (this.hashCode[i] != otherNode.hashCode[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- return false;
-};
-
-/**
- * Function: getCoreCell
- *
- * Gets the core vertex associated with this wrapper
- */
-mxGraphHierarchyNode.prototype.getCoreCell = function()
-{
- return this.cell;
-}; \ No newline at end of file
diff --git a/src/js/layout/hierarchical/mxHierarchicalLayout.js b/src/js/layout/hierarchical/mxHierarchicalLayout.js
deleted file mode 100644
index 6ce0e05..0000000
--- a/src/js/layout/hierarchical/mxHierarchicalLayout.js
+++ /dev/null
@@ -1,623 +0,0 @@
-/**
- * $Id: mxHierarchicalLayout.js,v 1.30 2012-12-18 12:41:06 david Exp $
- * Copyright (c) 2005-2012, JGraph Ltd
- */
-/**
- * Class: mxHierarchicalLayout
- *
- * A hierarchical layout algorithm.
- *
- * Constructor: mxHierarchicalLayout
- *
- * Constructs a new hierarchical layout algorithm.
- *
- * Arguments:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * orientation - Optional constant that defines the orientation of this
- * layout.
- * deterministic - Optional boolean that specifies if this layout should be
- * deterministic. Default is true.
- */
-function mxHierarchicalLayout(graph, orientation, deterministic)
-{
- mxGraphLayout.call(this, graph);
- this.orientation = (orientation != null) ? orientation : mxConstants.DIRECTION_NORTH;
- this.deterministic = (deterministic != null) ? deterministic : true;
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxHierarchicalLayout.prototype = new mxGraphLayout();
-mxHierarchicalLayout.prototype.constructor = mxHierarchicalLayout;
-
-/**
- * Variable: roots
- *
- * Holds the array of <mxGraphLayouts> that this layout contains.
- */
-mxHierarchicalLayout.prototype.roots = null;
-
-/**
- * Variable: resizeParent
- *
- * Specifies if the parent should be resized after the layout so that it
- * contains all the child cells. Default is false. See also <parentBorder>.
- */
-mxHierarchicalLayout.prototype.resizeParent = false;
-
-/**
- * Variable: moveParent
- *
- * Specifies if the parent should be moved if <resizeParent> is enabled.
- * Default is false.
- */
-mxHierarchicalLayout.prototype.moveParent = false;
-
-/**
- * Variable: parentBorder
- *
- * The border to be added around the children if the parent is to be
- * resized using <resizeParent>. Default is 0.
- */
-mxHierarchicalLayout.prototype.parentBorder = 0;
-
-/**
- * Variable: intraCellSpacing
- *
- * The spacing buffer added between cells on the same layer. Default is 30.
- */
-mxHierarchicalLayout.prototype.intraCellSpacing = 30;
-
-/**
- * Variable: interRankCellSpacing
- *
- * The spacing buffer added between cell on adjacent layers. Default is 50.
- */
-mxHierarchicalLayout.prototype.interRankCellSpacing = 50;
-
-/**
- * Variable: interHierarchySpacing
- *
- * The spacing buffer between unconnected hierarchies. Default is 60.
- */
-mxHierarchicalLayout.prototype.interHierarchySpacing = 60;
-
-/**
- * Variable: parallelEdgeSpacing
- *
- * The distance between each parallel edge on each ranks for long edges
- */
-mxHierarchicalLayout.prototype.parallelEdgeSpacing = 10;
-
-/**
- * Variable: orientation
- *
- * The position of the root node(s) relative to the laid out graph in.
- * Default is <mxConstants.DIRECTION_NORTH>.
- */
-mxHierarchicalLayout.prototype.orientation = mxConstants.DIRECTION_NORTH;
-
-/**
- * Variable: fineTuning
- *
- * Whether or not to perform local optimisations and iterate multiple times
- * through the algorithm. Default is true.
- */
-mxHierarchicalLayout.prototype.fineTuning = true;
-
-/**
- *
- * Variable: tightenToSource
- *
- * Whether or not to tighten the assigned ranks of vertices up towards
- * the source cells.
- */
-mxHierarchicalLayout.prototype.tightenToSource = true;
-
-/**
- * Variable: disableEdgeStyle
- *
- * Specifies if the STYLE_NOEDGESTYLE flag should be set on edges that are
- * modified by the result. Default is true.
- */
-mxHierarchicalLayout.prototype.disableEdgeStyle = true;
-
-/**
- * Variable: promoteEdges
- *
- * Whether or not to promote edges that terminate on vertices with
- * different but common ancestry to appear connected to the highest
- * siblings in the ancestry chains
- */
-mxHierarchicalLayout.prototype.promoteEdges = true;
-
-/**
- * Variable: traverseAncestors
- *
- * Whether or not to navigate edges whose terminal vertices
- * have different parents but are in the same ancestry chain
- */
-mxHierarchicalLayout.prototype.traverseAncestors = true;
-
-/**
- * Variable: model
- *
- * The internal <mxGraphHierarchyModel> formed of the layout.
- */
-mxHierarchicalLayout.prototype.model = null;
-
-/**
- * Function: getModel
- *
- * Returns the internal <mxGraphHierarchyModel> for this layout algorithm.
- */
-mxHierarchicalLayout.prototype.getModel = function()
-{
- return this.model;
-};
-
-/**
- * Function: execute
- *
- * Executes the layout for the children of the specified parent.
- *
- * Parameters:
- *
- * parent - Parent <mxCell> that contains the children to be laid out.
- * roots - Optional starting roots of the layout.
- */
-mxHierarchicalLayout.prototype.execute = function(parent, roots)
-{
- this.parent = parent;
- var model = this.graph.model;
-
- // If the roots are set and the parent is set, only
- // use the roots that are some dependent of the that
- // parent.
- // If just the root are set, use them as-is
- // If just the parent is set use it's immediate
- // children as the initial set
-
- if (roots == null && parent == null)
- {
- // TODO indicate the problem
- return;
- }
-
- if (roots != null && parent != null)
- {
- var rootsCopy = [];
-
- for (var i = 0; i < roots.length; i++)
- {
-
- if (model.isAncestor(parent, roots[i]))
- {
- rootsCopy.push(roots[i]);
- }
- }
-
- this.roots = rootsCopy;
- }
- else
- {
- this.roots = roots;
- }
-
- model.beginUpdate();
- try
- {
- this.run(parent);
-
- if (this.resizeParent &&
- !this.graph.isCellCollapsed(parent))
- {
- this.graph.updateGroupBounds([parent],
- this.parentBorder, this.moveParent);
- }
- }
- finally
- {
- model.endUpdate();
- }
-};
-
-/**
- * Function: findRoots
- *
- * Returns all visible children in the given parent which do not have
- * incoming edges. If the result is empty then the children with the
- * maximum difference between incoming and outgoing edges are returned.
- * This takes into account edges that are being promoted to the given
- * root due to invisible children or collapsed cells.
- *
- * Parameters:
- *
- * parent - <mxCell> whose children should be checked.
- * vertices - array of vertices to limit search to
- */
-mxHierarchicalLayout.prototype.findRoots = function(parent, vertices)
-{
- var roots = [];
-
- if (parent != null && vertices != null)
- {
- var model = this.graph.model;
- var best = null;
- var maxDiff = -100000;
-
- for (var i in vertices)
- {
- var cell = vertices[i];
-
- if (model.isVertex(cell) && this.graph.isCellVisible(cell))
- {
- var conns = this.getEdges(cell);
- var fanOut = 0;
- var fanIn = 0;
-
- for (var k = 0; k < conns.length; k++)
- {
- var src = this.graph.view.getVisibleTerminal(conns[k], true);
-
- if (src == cell)
- {
- fanOut++;
- }
- else
- {
- fanIn++;
- }
- }
-
- if (fanIn == 0 && fanOut > 0)
- {
- roots.push(cell);
- }
-
- var diff = fanOut - fanIn;
-
- if (diff > maxDiff)
- {
- maxDiff = diff;
- best = cell;
- }
- }
- }
-
- if (roots.length == 0 && best != null)
- {
- roots.push(best);
- }
- }
-
- return roots;
-};
-
-/**
- * Function: getEdges
- *
- * Returns the connected edges for the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> whose edges should be returned.
- */
-mxHierarchicalLayout.prototype.getEdges = function(cell)
-{
- var model = this.graph.model;
- var edges = [];
- var isCollapsed = this.graph.isCellCollapsed(cell);
- var childCount = model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(cell, i);
-
- if (isCollapsed || !this.graph.isCellVisible(child))
- {
- edges = edges.concat(model.getEdges(child, true, true));
- }
- }
-
- edges = edges.concat(model.getEdges(cell, true, true));
- var result = [];
-
- for (var i = 0; i < edges.length; i++)
- {
- var state = this.graph.view.getState(edges[i]);
-
- var source = (state != null) ? state.getVisibleTerminal(true) : this.graph.view.getVisibleTerminal(edges[i], true);
- var target = (state != null) ? state.getVisibleTerminal(false) : this.graph.view.getVisibleTerminal(edges[i], false);
-
- if ((source == target) || ((source != target) && ((target == cell && (this.parent == null || this.graph.isValidAncestor(source, this.parent, this.traverseAncestors))) ||
- (source == cell && (this.parent == null ||
- this.graph.isValidAncestor(target, this.parent, this.traverseAncestors))))))
- {
- result.push(edges[i]);
- }
- }
-
- return result;
-};
-
-/**
- * Function: run
- *
- * The API method used to exercise the layout upon the graph description
- * and produce a separate description of the vertex position and edge
- * routing changes made. It runs each stage of the layout that has been
- * created.
- */
-mxHierarchicalLayout.prototype.run = function(parent)
-{
- // Separate out unconnected hierarchies
- var hierarchyVertices = [];
- var allVertexSet = [];
-
- if (this.roots == null && parent != null)
- {
- var filledVertexSet = this.filterDescendants(parent);
-
- this.roots = [];
- var filledVertexSetEmpty = true;
-
- // Poor man's isSetEmpty
- for (var key in filledVertexSet)
- {
- if (filledVertexSet[key] != null)
- {
- filledVertexSetEmpty = false;
- break;
- }
- }
-
- while (!filledVertexSetEmpty)
- {
- var candidateRoots = this.findRoots(parent, filledVertexSet);
-
- for (var i = 0; i < candidateRoots.length; i++)
- {
- var vertexSet = [];
- hierarchyVertices.push(vertexSet);
-
- this.traverse(candidateRoots[i], true, null, allVertexSet, vertexSet,
- hierarchyVertices, filledVertexSet);
- }
-
- for (var i = 0; i < candidateRoots.length; i++)
- {
- this.roots.push(candidateRoots[i]);
- }
-
- filledVertexSetEmpty = true;
-
- // Poor man's isSetEmpty
- for (var key in filledVertexSet)
- {
- if (filledVertexSet[key] != null)
- {
- filledVertexSetEmpty = false;
- break;
- }
- }
- }
- }
- else
- {
- // Find vertex set as directed traversal from roots
-
- for (var i = 0; i < roots.length; i++)
- {
- var vertexSet = [];
- hierarchyVertices.push(vertexSet);
-
- traverse(roots.get(i), true, null, allVertexSet, vertexSet,
- hierarchyVertices, null);
- }
- }
-
- // Iterate through the result removing parents who have children in this layout
-
- // Perform a layout for each seperate hierarchy
- // Track initial coordinate x-positioning
- var initialX = 0;
-
- for (var i = 0; i < hierarchyVertices.length; i++)
- {
- var vertexSet = hierarchyVertices[i];
- var tmp = [];
-
- for (var key in vertexSet)
- {
- tmp.push(vertexSet[key]);
- }
-
- this.model = new mxGraphHierarchyModel(this, tmp, this.roots,
- parent, this.tightenToSource);
-
- this.cycleStage(parent);
- this.layeringStage();
-
- this.crossingStage(parent);
- initialX = this.placementStage(initialX, parent);
- }
-};
-
-/**
- * Function: filterDescendants
- *
- * Creates an array of descendant cells
- */
-mxHierarchicalLayout.prototype.filterDescendants = function(cell)
-{
- var model = this.graph.model;
- var result = [];
-
- if (model.isVertex(cell) && cell != this.parent && this.graph.isCellVisible(cell))
- {
- result.push(cell);
- }
-
- if (this.traverseAncestors || cell == this.parent
- && this.graph.isCellVisible(cell))
- {
- var childCount = model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(cell, i);
- var children = this.filterDescendants(child);
-
- for (var j = 0; j < children.length; j++)
- {
- result[mxCellPath.create(children[j])] = children[j];
- }
- }
- }
-
- return result;
-};
-
-/**
- * Traverses the (directed) graph invoking the given function for each
- * visited vertex and edge. The function is invoked with the current vertex
- * and the incoming edge as a parameter. This implementation makes sure
- * each vertex is only visited once. The function may return false if the
- * traversal should stop at the given vertex.
- *
- * Parameters:
- *
- * vertex - <mxCell> that represents the vertex where the traversal starts.
- * directed - boolean indicating if edges should only be traversed
- * from source to target. Default is true.
- * edge - Optional <mxCell> that represents the incoming edge. This is
- * null for the first step of the traversal.
- * allVertices - Array of cell paths for the visited cells.
- */
-mxHierarchicalLayout.prototype.traverse = function(vertex, directed, edge, allVertices, currentComp,
- hierarchyVertices, filledVertexSet)
-{
- var view = this.graph.view;
- var model = this.graph.model;
-
- if (vertex != null && allVertices != null)
- {
- // Has this vertex been seen before in any traversal
- // And if the filled vertex set is populated, only
- // process vertices in that it contains
- var vertexID = mxCellPath.create(vertex);
-
- if ((allVertices[vertexID] == null)
- && (filledVertexSet == null ? true : filledVertexSet[vertexID] != null))
- {
- if (currentComp[vertexID] == null)
- {
- currentComp[vertexID] = vertex;
- }
- if (allVertices[vertexID] == null)
- {
- allVertices[vertexID] = vertex;
- }
-
- delete filledVertexSet[vertexID];
-
- var edgeCount = model.getEdgeCount(vertex);
-
- if (edgeCount > 0)
- {
- for (var i = 0; i < edgeCount; i++)
- {
- var e = model.getEdgeAt(vertex, i);
- var isSource = view.getVisibleTerminal(e, true) == vertex;
-
- if (!directed || isSource)
- {
- var next = view.getVisibleTerminal(e, !isSource);
- currentComp = this.traverse(next, directed, e, allVertices,
- currentComp, hierarchyVertices,
- filledVertexSet);
- }
- }
- }
- }
- else
- {
- if (currentComp[vertexID] == null)
- {
- // We've seen this vertex before, but not in the current component
- // This component and the one it's in need to be merged
-
- for (var i = 0; i < hierarchyVertices.length; i++)
- {
- var comp = hierarchyVertices[i];
-
- if (comp[vertexID] != null)
- {
- for (var key in currentComp)
- {
- comp[key] = currentComp[key];
- }
-
- // Remove the current component from the hierarchy set
- hierarchyVertices.pop();
- return comp;
- }
- }
- }
- }
- }
-
- return currentComp;
-};
-
-/**
- * Function: cycleStage
- *
- * Executes the cycle stage using mxMinimumCycleRemover.
- */
-mxHierarchicalLayout.prototype.cycleStage = function(parent)
-{
- var cycleStage = new mxMinimumCycleRemover(this);
- cycleStage.execute(parent);
-};
-
-/**
- * Function: layeringStage
- *
- * Implements first stage of a Sugiyama layout.
- */
-mxHierarchicalLayout.prototype.layeringStage = function()
-{
- this.model.initialRank();
- this.model.fixRanks();
-};
-
-/**
- * Function: crossingStage
- *
- * Executes the crossing stage using mxMedianHybridCrossingReduction.
- */
-mxHierarchicalLayout.prototype.crossingStage = function(parent)
-{
- var crossingStage = new mxMedianHybridCrossingReduction(this);
- crossingStage.execute(parent);
-};
-
-/**
- * Function: placementStage
- *
- * Executes the placement stage using mxCoordinateAssignment.
- */
-mxHierarchicalLayout.prototype.placementStage = function(initialX, parent)
-{
- var placementStage = new mxCoordinateAssignment(this, this.intraCellSpacing,
- this.interRankCellSpacing, this.orientation, initialX,
- this.parallelEdgeSpacing);
- placementStage.fineTuning = this.fineTuning;
- placementStage.execute(parent);
-
- return placementStage.limitX + this.interHierarchySpacing;
-};
diff --git a/src/js/layout/hierarchical/stage/mxCoordinateAssignment.js b/src/js/layout/hierarchical/stage/mxCoordinateAssignment.js
deleted file mode 100644
index 8b73ccf..0000000
--- a/src/js/layout/hierarchical/stage/mxCoordinateAssignment.js
+++ /dev/null
@@ -1,1836 +0,0 @@
-/**
- * $Id: mxCoordinateAssignment.js,v 1.29 2012-06-21 14:28:09 david Exp $
- * Copyright (c) 2005-2012, JGraph Ltd
- */
-/**
- * Class: mxCoordinateAssignment
- *
- * Sets the horizontal locations of node and edge dummy nodes on each layer.
- * Uses median down and up weighings as well as heuristics to straighten edges as
- * far as possible.
- *
- * Constructor: mxCoordinateAssignment
- *
- * Creates a coordinate assignment.
- *
- * Arguments:
- *
- * intraCellSpacing - the minimum buffer between cells on the same rank
- * interRankCellSpacing - the minimum distance between cells on adjacent ranks
- * orientation - the position of the root node(s) relative to the graph
- * initialX - the leftmost coordinate node placement starts at
- */
-function mxCoordinateAssignment(layout, intraCellSpacing, interRankCellSpacing,
- orientation, initialX, parallelEdgeSpacing)
-{
- this.layout = layout;
- this.intraCellSpacing = intraCellSpacing;
- this.interRankCellSpacing = interRankCellSpacing;
- this.orientation = orientation;
- this.initialX = initialX;
- this.parallelEdgeSpacing = parallelEdgeSpacing;
-};
-
-var mxHierarchicalEdgeStyle =
-{
- ORTHOGONAL: 1,
- POLYLINE: 2,
- STRAIGHT: 3
-};
-
-/**
- * Extends mxHierarchicalLayoutStage.
- */
-mxCoordinateAssignment.prototype = new mxHierarchicalLayoutStage();
-mxCoordinateAssignment.prototype.constructor = mxCoordinateAssignment;
-
-/**
- * Variable: layout
- *
- * Reference to the enclosing <mxHierarchicalLayout>.
- */
-mxCoordinateAssignment.prototype.layout = null;
-
-/**
- * Variable: intraCellSpacing
- *
- * The minimum buffer between cells on the same rank. Default is 30.
- */
-mxCoordinateAssignment.prototype.intraCellSpacing = 30;
-
-/**
- * Variable: interRankCellSpacing
- *
- * The minimum distance between cells on adjacent ranks. Default is 10.
- */
-mxCoordinateAssignment.prototype.interRankCellSpacing = 10;
-
-/**
- * Variable: parallelEdgeSpacing
- *
- * The distance between each parallel edge on each ranks for long edges.
- * Default is 10.
- */
-mxCoordinateAssignment.prototype.parallelEdgeSpacing = 10;
-
-/**
- * Variable: maxIterations
- *
- * The number of heuristic iterations to run. Default is 8.
- */
-mxCoordinateAssignment.prototype.maxIterations = 8;
-
-/**
- * Variable: prefHozEdgeSep
- *
- * The preferred horizontal distance between edges exiting a vertex
- */
-mxCoordinateAssignment.prototype.prefHozEdgeSep = 5;
-
-/**
- * Variable: prefVertEdgeOff
- *
- * The preferred vertical offset between edges exiting a vertex
- */
-mxCoordinateAssignment.prototype.prefVertEdgeOff = 2;
-
-/**
- * Variable: minEdgeJetty
- *
- * The minimum distance for an edge jetty from a vertex
- */
-mxCoordinateAssignment.prototype.minEdgeJetty = 12;
-
-/**
- * Variable: channelBuffer
- *
- * The size of the vertical buffer in the center of inter-rank channels
- * where edge control points should not be placed
- */
-mxCoordinateAssignment.prototype.channelBuffer = 4;
-
-/**
- * Variable: jettyPositions
- *
- * Map of internal edges and (x,y) pair of positions of the start and end jetty
- * for that edge where it connects to the source and target vertices.
- * Note this should technically be a WeakHashMap, but since JS does not
- * have an equivalent, housekeeping must be performed before using.
- * i.e. check all edges are still in the model and clear the values.
- * Note that the y co-ord is the offset of the jetty, not the
- * absolute point
- */
-mxCoordinateAssignment.prototype.jettyPositions = null;
-
-/**
- * Variable: orientation
- *
- * The position of the root ( start ) node(s) relative to the rest of the
- * laid out graph. Default is <mxConstants.DIRECTION_NORTH>.
- */
-mxCoordinateAssignment.prototype.orientation = mxConstants.DIRECTION_NORTH;
-
-/**
- * Variable: initialX
- *
- * The minimum x position node placement starts at
- */
-mxCoordinateAssignment.prototype.initialX = null;
-
-/**
- * Variable: limitX
- *
- * The maximum x value this positioning lays up to
- */
-mxCoordinateAssignment.prototype.limitX = null;
-
-/**
- * Variable: currentXDelta
- *
- * The sum of x-displacements for the current iteration
- */
-mxCoordinateAssignment.prototype.currentXDelta = null;
-
-/**
- * Variable: widestRank
- *
- * The rank that has the widest x position
- */
-mxCoordinateAssignment.prototype.widestRank = null;
-
-/**
- * Variable: rankTopY
- *
- * Internal cache of top-most values of Y for each rank
- */
-mxCoordinateAssignment.prototype.rankTopY = null;
-
-/**
- * Variable: rankBottomY
- *
- * Internal cache of bottom-most value of Y for each rank
- */
-mxCoordinateAssignment.prototype.rankBottomY = null;
-
-/**
- * Variable: widestRankValue
- *
- * The X-coordinate of the edge of the widest rank
- */
-mxCoordinateAssignment.prototype.widestRankValue = null;
-
-/**
- * Variable: rankWidths
- *
- * The width of all the ranks
- */
-mxCoordinateAssignment.prototype.rankWidths = null;
-
-/**
- * Variable: rankY
- *
- * The Y-coordinate of all the ranks
- */
-mxCoordinateAssignment.prototype.rankY = null;
-
-/**
- * Variable: fineTuning
- *
- * Whether or not to perform local optimisations and iterate multiple times
- * through the algorithm. Default is true.
- */
-mxCoordinateAssignment.prototype.fineTuning = true;
-
-/**
- * Variable: edgeStyle
- *
- * The style to apply between cell layers to edge segments
- */
-mxCoordinateAssignment.prototype.edgeStyle = mxHierarchicalEdgeStyle.POLYLINE;
-
-/**
- * Variable: nextLayerConnectedCache
- *
- * A store of connections to the layer above for speed
- */
-mxCoordinateAssignment.prototype.nextLayerConnectedCache = null;
-
-/**
- * Variable: previousLayerConnectedCache
- *
- * A store of connections to the layer below for speed
- */
-mxCoordinateAssignment.prototype.previousLayerConnectedCache = null;
-
-/**
- * Variable: groupPadding
- *
- * Padding added to resized parents
- */
-mxCoordinateAssignment.prototype.groupPadding = 10;
-
-/**
- * Utility method to display current positions
- */
-mxCoordinateAssignment.prototype.printStatus = function()
-{
- var model = this.layout.getModel();
- mxLog.show();
-
- mxLog.writeln('======Coord assignment debug=======');
-
- for (var j = 0; j < model.ranks.length; j++)
- {
- mxLog.write('Rank ', j, ' : ' );
- var rank = model.ranks[j];
-
- for (var k = 0; k < rank.length; k++)
- {
- var cell = rank[k];
-
- mxLog.write(cell.getGeneralPurposeVariable(j), ' ');
- }
- mxLog.writeln();
- }
-
- mxLog.writeln('====================================');
-};
-
-/**
- * Function: execute
- *
- * A basic horizontal coordinate assignment algorithm
- */
-mxCoordinateAssignment.prototype.execute = function(parent)
-{
- this.jettyPositions = [];
- var model = this.layout.getModel();
- this.currentXDelta = 0.0;
-
- this.initialCoords(this.layout.getGraph(), model);
-
-// this.printStatus();
-
- if (this.fineTuning)
- {
- this.minNode(model);
- }
-
- var bestXDelta = 100000000.0;
-
- if (this.fineTuning)
- {
- for (var i = 0; i < this.maxIterations; i++)
- {
-// this.printStatus();
-
- // Median Heuristic
- if (i != 0)
- {
- this.medianPos(i, model);
- this.minNode(model);
- }
-
- // if the total offset is less for the current positioning,
- // there are less heavily angled edges and so the current
- // positioning is used
- if (this.currentXDelta < bestXDelta)
- {
- for (var j = 0; j < model.ranks.length; j++)
- {
- var rank = model.ranks[j];
-
- for (var k = 0; k < rank.length; k++)
- {
- var cell = rank[k];
- cell.setX(j, cell.getGeneralPurposeVariable(j));
- }
- }
-
- bestXDelta = this.currentXDelta;
- }
- else
- {
- // Restore the best positions
- for (var j = 0; j < model.ranks.length; j++)
- {
- var rank = model.ranks[j];
-
- for (var k = 0; k < rank.length; k++)
- {
- var cell = rank[k];
- cell.setGeneralPurposeVariable(j, cell.getX(j));
- }
- }
- }
-
- this.minPath(this.layout.getGraph(), model);
-
- this.currentXDelta = 0;
- }
- }
-
- this.setCellLocations(this.layout.getGraph(), model);
-};
-
-/**
- * Function: minNode
- *
- * Performs one median positioning sweep in both directions
- */
-mxCoordinateAssignment.prototype.minNode = function(model)
-{
- // Queue all nodes
- var nodeList = [];
-
- // Need to be able to map from cell to cellWrapper
- var map = [];
- var rank = [];
-
- for (var i = 0; i <= model.maxRank; i++)
- {
- rank[i] = model.ranks[i];
-
- for (var j = 0; j < rank[i].length; j++)
- {
- // Use the weight to store the rank and visited to store whether
- // or not the cell is in the list
- var node = rank[i][j];
- var nodeWrapper = new WeightedCellSorter(node, i);
- nodeWrapper.rankIndex = j;
- nodeWrapper.visited = true;
- nodeList.push(nodeWrapper);
-
- var cellId = mxCellPath.create(node.getCoreCell());
- map[cellId] = nodeWrapper;
- }
- }
-
- // Set a limit of the maximum number of times we will access the queue
- // in case a loop appears
- var maxTries = nodeList.length * 10;
- var count = 0;
-
- // Don't move cell within this value of their median
- var tolerance = 1;
-
- while (nodeList.length > 0 && count <= maxTries)
- {
- var cellWrapper = nodeList.shift();
- var cell = cellWrapper.cell;
-
- var rankValue = cellWrapper.weightedValue;
- var rankIndex = parseInt(cellWrapper.rankIndex);
-
- var nextLayerConnectedCells = cell.getNextLayerConnectedCells(rankValue);
- var previousLayerConnectedCells = cell.getPreviousLayerConnectedCells(rankValue);
-
- var numNextLayerConnected = nextLayerConnectedCells.length;
- var numPreviousLayerConnected = previousLayerConnectedCells.length;
-
- var medianNextLevel = this.medianXValue(nextLayerConnectedCells,
- rankValue + 1);
- var medianPreviousLevel = this.medianXValue(previousLayerConnectedCells,
- rankValue - 1);
-
- var numConnectedNeighbours = numNextLayerConnected
- + numPreviousLayerConnected;
- var currentPosition = cell.getGeneralPurposeVariable(rankValue);
- var cellMedian = currentPosition;
-
- if (numConnectedNeighbours > 0)
- {
- cellMedian = (medianNextLevel * numNextLayerConnected + medianPreviousLevel
- * numPreviousLayerConnected)
- / numConnectedNeighbours;
- }
-
- // Flag storing whether or not position has changed
- var positionChanged = false;
-
- if (cellMedian < currentPosition - tolerance)
- {
- if (rankIndex == 0)
- {
- cell.setGeneralPurposeVariable(rankValue, cellMedian);
- positionChanged = true;
- }
- else
- {
- var leftCell = rank[rankValue][rankIndex - 1];
- var leftLimit = leftCell
- .getGeneralPurposeVariable(rankValue);
- leftLimit = leftLimit + leftCell.width / 2
- + this.intraCellSpacing + cell.width / 2;
-
- if (leftLimit < cellMedian)
- {
- cell.setGeneralPurposeVariable(rankValue, cellMedian);
- positionChanged = true;
- }
- else if (leftLimit < cell
- .getGeneralPurposeVariable(rankValue)
- - tolerance)
- {
- cell.setGeneralPurposeVariable(rankValue, leftLimit);
- positionChanged = true;
- }
- }
- }
- else if (cellMedian > currentPosition + tolerance)
- {
- var rankSize = rank[rankValue].length;
-
- if (rankIndex == rankSize - 1)
- {
- cell.setGeneralPurposeVariable(rankValue, cellMedian);
- positionChanged = true;
- }
- else
- {
- var rightCell = rank[rankValue][rankIndex + 1];
- var rightLimit = rightCell
- .getGeneralPurposeVariable(rankValue);
- rightLimit = rightLimit - rightCell.width / 2
- - this.intraCellSpacing - cell.width / 2;
-
- if (rightLimit > cellMedian)
- {
- cell.setGeneralPurposeVariable(rankValue, cellMedian);
- positionChanged = true;
- }
- else if (rightLimit > cell
- .getGeneralPurposeVariable(rankValue)
- + tolerance)
- {
- cell.setGeneralPurposeVariable(rankValue, rightLimit);
- positionChanged = true;
- }
- }
- }
-
- if (positionChanged)
- {
- // Add connected nodes to map and list
- for (var i = 0; i < nextLayerConnectedCells.length; i++)
- {
- var connectedCell = nextLayerConnectedCells[i];
- var connectedCellId = mxCellPath.create(connectedCell.getCoreCell());
- var connectedCellWrapper = map[connectedCellId];
-
- if (connectedCellWrapper != null)
- {
- if (connectedCellWrapper.visited == false)
- {
- connectedCellWrapper.visited = true;
- nodeList.push(connectedCellWrapper);
- }
- }
- }
-
- // Add connected nodes to map and list
- for (var i = 0; i < previousLayerConnectedCells.length; i++)
- {
- var connectedCell = previousLayerConnectedCells[i];
- var connectedCellId = mxCellPath.create(connectedCell.getCoreCell());
- var connectedCellWrapper = map[connectedCellId];
-
- if (connectedCellWrapper != null)
- {
- if (connectedCellWrapper.visited == false)
- {
- connectedCellWrapper.visited = true;
- nodeList.push(connectedCellWrapper);
- }
- }
- }
- }
-
- cellWrapper.visited = false;
- count++;
- }
-};
-
-/**
- * Function: medianPos
- *
- * Performs one median positioning sweep in one direction
- *
- * Parameters:
- *
- * i - the iteration of the whole process
- * model - an internal model of the hierarchical layout
- */
-mxCoordinateAssignment.prototype.medianPos = function(i, model)
-{
- // Reverse sweep direction each time through this method
- var downwardSweep = (i % 2 == 0);
-
- if (downwardSweep)
- {
- for (var j = model.maxRank; j > 0; j--)
- {
- this.rankMedianPosition(j - 1, model, j);
- }
- }
- else
- {
- for (var j = 0; j < model.maxRank - 1; j++)
- {
- this.rankMedianPosition(j + 1, model, j);
- }
- }
-};
-
-/**
- * Function: rankMedianPosition
- *
- * Performs median minimisation over one rank.
- *
- * Parameters:
- *
- * rankValue - the layer number of this rank
- * model - an internal model of the hierarchical layout
- * nextRankValue - the layer number whose connected cels are to be laid out
- * relative to
- */
-mxCoordinateAssignment.prototype.rankMedianPosition = function(rankValue, model, nextRankValue)
-{
- var rank = model.ranks[rankValue];
-
- // Form an array of the order in which the cell are to be processed
- // , the order is given by the weighted sum of the in or out edges,
- // depending on whether we're travelling up or down the hierarchy.
- var weightedValues = [];
- var cellMap = [];
-
- for (var i = 0; i < rank.length; i++)
- {
- var currentCell = rank[i];
- weightedValues[i] = new WeightedCellSorter();
- weightedValues[i].cell = currentCell;
- weightedValues[i].rankIndex = i;
- var currentCellId = mxCellPath.create(currentCell.getCoreCell());
- cellMap[currentCellId] = weightedValues[i];
- var nextLayerConnectedCells = null;
-
- if (nextRankValue < rankValue)
- {
- nextLayerConnectedCells = currentCell
- .getPreviousLayerConnectedCells(rankValue);
- }
- else
- {
- nextLayerConnectedCells = currentCell
- .getNextLayerConnectedCells(rankValue);
- }
-
- // Calculate the weighing based on this node type and those this
- // node is connected to on the next layer
- weightedValues[i].weightedValue = this.calculatedWeightedValue(
- currentCell, nextLayerConnectedCells);
- }
-
- weightedValues.sort(WeightedCellSorter.prototype.compare);
-
- // Set the new position of each node within the rank using
- // its temp variable
-
- for (var i = 0; i < weightedValues.length; i++)
- {
- var numConnectionsNextLevel = 0;
- var cell = weightedValues[i].cell;
- var nextLayerConnectedCells = null;
- var medianNextLevel = 0;
-
- if (nextRankValue < rankValue)
- {
- nextLayerConnectedCells = cell.getPreviousLayerConnectedCells(
- rankValue).slice();
- }
- else
- {
- nextLayerConnectedCells = cell.getNextLayerConnectedCells(
- rankValue).slice();
- }
-
- if (nextLayerConnectedCells != null)
- {
- numConnectionsNextLevel = nextLayerConnectedCells.length;
-
- if (numConnectionsNextLevel > 0)
- {
- medianNextLevel = this.medianXValue(nextLayerConnectedCells,
- nextRankValue);
- }
- else
- {
- // For case of no connections on the next level set the
- // median to be the current position and try to be
- // positioned there
- medianNextLevel = cell.getGeneralPurposeVariable(rankValue);
- }
- }
-
- var leftBuffer = 0.0;
- var leftLimit = -100000000.0;
-
- for (var j = weightedValues[i].rankIndex - 1; j >= 0;)
- {
- var rankId = mxCellPath.create(rank[j].getCoreCell());
- var weightedValue = cellMap[rankId];
-
- if (weightedValue != null)
- {
- var leftCell = weightedValue.cell;
-
- if (weightedValue.visited)
- {
- // The left limit is the right hand limit of that
- // cell plus any allowance for unallocated cells
- // in-between
- leftLimit = leftCell
- .getGeneralPurposeVariable(rankValue)
- + leftCell.width
- / 2.0
- + this.intraCellSpacing
- + leftBuffer + cell.width / 2.0;
- j = -1;
- }
- else
- {
- leftBuffer += leftCell.width + this.intraCellSpacing;
- j--;
- }
- }
- }
-
- var rightBuffer = 0.0;
- var rightLimit = 100000000.0;
-
- for (var j = weightedValues[i].rankIndex + 1; j < weightedValues.length;)
- {
- var rankId = mxCellPath.create(rank[j].getCoreCell());
- var weightedValue = cellMap[rankId];
-
- if (weightedValue != null)
- {
- var rightCell = weightedValue.cell;
-
- if (weightedValue.visited)
- {
- // The left limit is the right hand limit of that
- // cell plus any allowance for unallocated cells
- // in-between
- rightLimit = rightCell
- .getGeneralPurposeVariable(rankValue)
- - rightCell.width
- / 2.0
- - this.intraCellSpacing
- - rightBuffer - cell.width / 2.0;
- j = weightedValues.length;
- }
- else
- {
- rightBuffer += rightCell.width + this.intraCellSpacing;
- j++;
- }
- }
- }
-
- if (medianNextLevel >= leftLimit && medianNextLevel <= rightLimit)
- {
- cell.setGeneralPurposeVariable(rankValue, medianNextLevel);
- }
- else if (medianNextLevel < leftLimit)
- {
- // Couldn't place at median value, place as close to that
- // value as possible
- cell.setGeneralPurposeVariable(rankValue, leftLimit);
- this.currentXDelta += leftLimit - medianNextLevel;
- }
- else if (medianNextLevel > rightLimit)
- {
- // Couldn't place at median value, place as close to that
- // value as possible
- cell.setGeneralPurposeVariable(rankValue, rightLimit);
- this.currentXDelta += medianNextLevel - rightLimit;
- }
-
- weightedValues[i].visited = true;
- }
-};
-
-/**
- * Function: calculatedWeightedValue
- *
- * Calculates the priority the specified cell has based on the type of its
- * cell and the cells it is connected to on the next layer
- *
- * Parameters:
- *
- * currentCell - the cell whose weight is to be calculated
- * collection - the cells the specified cell is connected to
- */
-mxCoordinateAssignment.prototype.calculatedWeightedValue = function(currentCell, collection)
-{
- var totalWeight = 0;
-
- for (var i = 0; i < collection.length; i++)
- {
- var cell = collection[i];
-
- if (currentCell.isVertex() && cell.isVertex())
- {
- totalWeight++;
- }
- else if (currentCell.isEdge() && cell.isEdge())
- {
- totalWeight += 8;
- }
- else
- {
- totalWeight += 2;
- }
- }
-
- return totalWeight;
-};
-
-/**
- * Function: medianXValue
- *
- * Calculates the median position of the connected cell on the specified
- * rank
- *
- * Parameters:
- *
- * connectedCells - the cells the candidate connects to on this level
- * rankValue - the layer number of this rank
- */
-mxCoordinateAssignment.prototype.medianXValue = function(connectedCells, rankValue)
-{
- if (connectedCells.length == 0)
- {
- return 0;
- }
-
- var medianValues = [];
-
- for (var i = 0; i < connectedCells.length; i++)
- {
- medianValues[i] = connectedCells[i].getGeneralPurposeVariable(rankValue);
- }
-
- medianValues.sort(function(a,b){return a - b;});
-
- if (connectedCells.length % 2 == 1)
- {
- // For odd numbers of adjacent vertices return the median
- return medianValues[Math.floor(connectedCells.length / 2)];
- }
- else
- {
- var medianPoint = connectedCells.length / 2;
- var leftMedian = medianValues[medianPoint - 1];
- var rightMedian = medianValues[medianPoint];
-
- return ((leftMedian + rightMedian) / 2);
- }
-};
-
-/**
- * Function: initialCoords
- *
- * Sets up the layout in an initial positioning. The ranks are all centered
- * as much as possible along the middle vertex in each rank. The other cells
- * are then placed as close as possible on either side.
- *
- * Parameters:
- *
- * facade - the facade describing the input graph
- * model - an internal model of the hierarchical layout
- */
-mxCoordinateAssignment.prototype.initialCoords = function(facade, model)
-{
- this.calculateWidestRank(facade, model);
-
- // Sweep up and down from the widest rank
- for (var i = this.widestRank; i >= 0; i--)
- {
- if (i < model.maxRank)
- {
- this.rankCoordinates(i, facade, model);
- }
- }
-
- for (var i = this.widestRank+1; i <= model.maxRank; i++)
- {
- if (i > 0)
- {
- this.rankCoordinates(i, facade, model);
- }
- }
-};
-
-/**
- * Function: rankCoordinates
- *
- * Sets up the layout in an initial positioning. All the first cells in each
- * rank are moved to the left and the rest of the rank inserted as close
- * together as their size and buffering permits. This method works on just
- * the specified rank.
- *
- * Parameters:
- *
- * rankValue - the current rank being processed
- * graph - the facade describing the input graph
- * model - an internal model of the hierarchical layout
- */
-mxCoordinateAssignment.prototype.rankCoordinates = function(rankValue, graph, model)
-{
- var rank = model.ranks[rankValue];
- var maxY = 0.0;
- var localX = this.initialX + (this.widestRankValue - this.rankWidths[rankValue])
- / 2;
-
- // Store whether or not any of the cells' bounds were unavailable so
- // to only issue the warning once for all cells
- var boundsWarning = false;
-
- for (var i = 0; i < rank.length; i++)
- {
- var node = rank[i];
-
- if (node.isVertex())
- {
- var bounds = this.layout.getVertexBounds(node.cell);
-
- if (bounds != null)
- {
- if (this.orientation == mxConstants.DIRECTION_NORTH ||
- this.orientation == mxConstants.DIRECTION_SOUTH)
- {
- node.width = bounds.width;
- node.height = bounds.height;
- }
- else
- {
- node.width = bounds.height;
- node.height = bounds.width;
- }
- }
- else
- {
- boundsWarning = true;
- }
-
- maxY = Math.max(maxY, node.height);
- }
- else if (node.isEdge())
- {
- // The width is the number of additional parallel edges
- // time the parallel edge spacing
- var numEdges = 1;
-
- if (node.edges != null)
- {
- numEdges = node.edges.length;
- }
- else
- {
- mxLog.warn('edge.edges is null');
- }
-
- node.width = (numEdges - 1) * this.parallelEdgeSpacing;
- }
-
- // Set the initial x-value as being the best result so far
- localX += node.width / 2.0;
- node.setX(rankValue, localX);
- node.setGeneralPurposeVariable(rankValue, localX);
- localX += node.width / 2.0;
- localX += this.intraCellSpacing;
- }
-
- if (boundsWarning == true)
- {
- mxLog.warn('At least one cell has no bounds');
- }
-};
-
-/**
- * Function: calculateWidestRank
- *
- * Calculates the width rank in the hierarchy. Also set the y value of each
- * rank whilst performing the calculation
- *
- * Parameters:
- *
- * graph - the facade describing the input graph
- * model - an internal model of the hierarchical layout
- */
-mxCoordinateAssignment.prototype.calculateWidestRank = function(graph, model)
-{
- // Starting y co-ordinate
- var y = -this.interRankCellSpacing;
-
- // Track the widest cell on the last rank since the y
- // difference depends on it
- var lastRankMaxCellHeight = 0.0;
- this.rankWidths = [];
- this.rankY = [];
-
- for (var rankValue = model.maxRank; rankValue >= 0; rankValue--)
- {
- // Keep track of the widest cell on this rank
- var maxCellHeight = 0.0;
- var rank = model.ranks[rankValue];
- var localX = this.initialX;
-
- // Store whether or not any of the cells' bounds were unavailable so
- // to only issue the warning once for all cells
- var boundsWarning = false;
-
- for (var i = 0; i < rank.length; i++)
- {
- var node = rank[i];
-
- if (node.isVertex())
- {
- var bounds = this.layout.getVertexBounds(node.cell);
-
- if (bounds != null)
- {
- if (this.orientation == mxConstants.DIRECTION_NORTH ||
- this.orientation == mxConstants.DIRECTION_SOUTH)
- {
- node.width = bounds.width;
- node.height = bounds.height;
- }
- else
- {
- node.width = bounds.height;
- node.height = bounds.width;
- }
- }
- else
- {
- boundsWarning = true;
- }
-
- maxCellHeight = Math.max(maxCellHeight, node.height);
- }
- else if (node.isEdge())
- {
- // The width is the number of additional parallel edges
- // time the parallel edge spacing
- var numEdges = 1;
-
- if (node.edges != null)
- {
- numEdges = node.edges.length;
- }
- else
- {
- mxLog.warn('edge.edges is null');
- }
-
- node.width = (numEdges - 1) * this.parallelEdgeSpacing;
- }
-
- // Set the initial x-value as being the best result so far
- localX += node.width / 2.0;
- node.setX(rankValue, localX);
- node.setGeneralPurposeVariable(rankValue, localX);
- localX += node.width / 2.0;
- localX += this.intraCellSpacing;
-
- if (localX > this.widestRankValue)
- {
- this.widestRankValue = localX;
- this.widestRank = rankValue;
- }
-
- this.rankWidths[rankValue] = localX;
- }
-
- if (boundsWarning == true)
- {
- mxLog.warn('At least one cell has no bounds');
- }
-
- this.rankY[rankValue] = y;
- var distanceToNextRank = maxCellHeight / 2.0
- + lastRankMaxCellHeight / 2.0 + this.interRankCellSpacing;
- lastRankMaxCellHeight = maxCellHeight;
-
- if (this.orientation == mxConstants.DIRECTION_NORTH ||
- this.orientation == mxConstants.DIRECTION_WEST)
- {
- y += distanceToNextRank;
- }
- else
- {
- y -= distanceToNextRank;
- }
-
- for (var i = 0; i < rank.length; i++)
- {
- var cell = rank[i];
- cell.setY(rankValue, y);
- }
- }
-};
-
-/**
- * Function: minPath
- *
- * Straightens out chains of virtual nodes where possibleacade to those stored after this layout
- * processing step has completed.
- *
- * Parameters:
- *
- * graph - the facade describing the input graph
- * model - an internal model of the hierarchical layout
- */
-mxCoordinateAssignment.prototype.minPath = function(graph, model)
-{
- // Work down and up each edge with at least 2 control points
- // trying to straighten each one out. If the same number of
- // straight segments are formed in both directions, the
- // preferred direction used is the one where the final
- // control points have the least offset from the connectable
- // region of the terminating vertices
- var edges = model.edgeMapper;
-
- for (var key in edges)
- {
- var cell = edges[key];
-
- if (cell.maxRank - cell.minRank - 1 < 1)
- {
- continue;
- }
-
- // At least two virtual nodes in the edge
- // Check first whether the edge is already straight
- var referenceX = cell
- .getGeneralPurposeVariable(cell.minRank + 1);
- var edgeStraight = true;
- var refSegCount = 0;
-
- for (var i = cell.minRank + 2; i < cell.maxRank; i++)
- {
- var x = cell.getGeneralPurposeVariable(i);
-
- if (referenceX != x)
- {
- edgeStraight = false;
- referenceX = x;
- }
- else
- {
- refSegCount++;
- }
- }
-
- if (!edgeStraight)
- {
- var upSegCount = 0;
- var downSegCount = 0;
- var upXPositions = [];
- var downXPositions = [];
-
- var currentX = cell.getGeneralPurposeVariable(cell.minRank + 1);
-
- for (var i = cell.minRank + 1; i < cell.maxRank - 1; i++)
- {
- // Attempt to straight out the control point on the
- // next segment up with the current control point.
- var nextX = cell.getX(i + 1);
-
- if (currentX == nextX)
- {
- upXPositions[i - cell.minRank - 1] = currentX;
- upSegCount++;
- }
- else if (this.repositionValid(model, cell, i + 1, currentX))
- {
- upXPositions[i - cell.minRank - 1] = currentX;
- upSegCount++;
- // Leave currentX at same value
- }
- else
- {
- upXPositions[i - cell.minRank - 1] = nextX;
- currentX = nextX;
- }
- }
-
- currentX = cell.getX(i);
-
- for (var i = cell.maxRank - 1; i > cell.minRank + 1; i--)
- {
- // Attempt to straight out the control point on the
- // next segment down with the current control point.
- var nextX = cell.getX(i - 1);
-
- if (currentX == nextX)
- {
- downXPositions[i - cell.minRank - 2] = currentX;
- downSegCount++;
- }
- else if (this.repositionValid(model, cell, i - 1, currentX))
- {
- downXPositions[i - cell.minRank - 2] = currentX;
- downSegCount++;
- // Leave currentX at same value
- }
- else
- {
- downXPositions[i - cell.minRank - 2] = cell.getX(i-1);
- currentX = nextX;
- }
- }
-
- if (downSegCount > refSegCount || upSegCount > refSegCount)
- {
- if (downSegCount >= upSegCount)
- {
- // Apply down calculation values
- for (var i = cell.maxRank - 2; i > cell.minRank; i--)
- {
- cell.setX(i, downXPositions[i - cell.minRank - 1]);
- }
- }
- else if (upSegCount > downSegCount)
- {
- // Apply up calculation values
- for (var i = cell.minRank + 2; i < cell.maxRank; i++)
- {
- cell.setX(i, upXPositions[i - cell.minRank - 2]);
- }
- }
- else
- {
- // Neither direction provided a favourable result
- // But both calculations are better than the
- // existing solution, so apply the one with minimal
- // offset to attached vertices at either end.
- }
- }
- }
- }
-};
-
-/**
- * Function: repositionValid
- *
- * Determines whether or not a node may be moved to the specified x
- * position on the specified rank
- *
- * Parameters:
- *
- * model - the layout model
- * cell - the cell being analysed
- * rank - the layer of the cell
- * position - the x position being sought
- */
-mxCoordinateAssignment.prototype.repositionValid = function(model, cell, rank, position)
-{
- var rankArray = model.ranks[rank];
- var rankIndex = -1;
-
- for (var i = 0; i < rankArray.length; i++)
- {
- if (cell == rankArray[i])
- {
- rankIndex = i;
- break;
- }
- }
-
- if (rankIndex < 0)
- {
- return false;
- }
-
- var currentX = cell.getGeneralPurposeVariable(rank);
-
- if (position < currentX)
- {
- // Trying to move node to the left.
- if (rankIndex == 0)
- {
- // Left-most node, can move anywhere
- return true;
- }
-
- var leftCell = rankArray[rankIndex - 1];
- var leftLimit = leftCell.getGeneralPurposeVariable(rank);
- leftLimit = leftLimit + leftCell.width / 2
- + this.intraCellSpacing + cell.width / 2;
-
- if (leftLimit <= position)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- else if (position > currentX)
- {
- // Trying to move node to the right.
- if (rankIndex == rankArray.length - 1)
- {
- // Right-most node, can move anywhere
- return true;
- }
-
- var rightCell = rankArray[rankIndex + 1];
- var rightLimit = rightCell.getGeneralPurposeVariable(rank);
- rightLimit = rightLimit - rightCell.width / 2
- - this.intraCellSpacing - cell.width / 2;
-
- if (rightLimit >= position)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- return true;
-};
-
-/**
- * Function: setCellLocations
- *
- * Sets the cell locations in the facade to those stored after this layout
- * processing step has completed.
- *
- * Parameters:
- *
- * graph - the input graph
- * model - the layout model
- */
-mxCoordinateAssignment.prototype.setCellLocations = function(graph, model)
-{
- this.rankTopY = [];
- this.rankBottomY = [];
-
- for (var i = 0; i < model.ranks.length; i++)
- {
- this.rankTopY[i] = Number.MAX_VALUE;
- this.rankBottomY[i] = 0.0;
- }
-
- var parentsChanged = null;
-
- if (this.layout.resizeParent)
- {
- parentsChanged = new Object();
- }
-
- var edges = model.edgeMapper;
- var vertices = model.vertexMapper;
-
- // Process vertices all first, since they define the lower and
- // limits of each rank. Between these limits lie the channels
- // where the edges can be routed across the graph
-
- for (var key in vertices)
- {
- var vertex = vertices[key];
- this.setVertexLocation(vertex);
-
- if (this.layout.resizeParent)
- {
- var parent = graph.model.getParent(vertex.cell);
- var id = mxCellPath.create(parent);
-
- // Implements set semantic
- if (parentsChanged[id] == null)
- {
- parentsChanged[id] = parent;
- }
- }
- }
-
- if (this.layout.resizeParent && parentsChanged != null)
- {
- this.adjustParents(parentsChanged);
- }
-
- // Post process edge styles. Needs the vertex locations set for initial
- // values of the top and bottoms of each rank
- if (this.edgeStyle == mxHierarchicalEdgeStyle.ORTHOGONAL
- || this.edgeStyle == mxHierarchicalEdgeStyle.POLYLINE)
- {
- this.localEdgeProcessing(model);
- }
-
- for (var key in edges)
- {
- this.setEdgePosition(edges[key]);
- }
-};
-
-/**
- * Function: adjustParents
- *
- * Adjust parent cells whose child geometries have changed. The default
- * implementation adjusts the group to just fit around the children with
- * a padding.
- */
-mxCoordinateAssignment.prototype.adjustParents = function(parentsChanged)
-{
- var tmp = [];
-
- for (var id in parentsChanged)
- {
- tmp.push(parentsChanged[id]);
- }
-
- this.layout.arrangeGroups(mxUtils.sortCells(tmp, true), this.groupPadding);
-};
-
-/**
- * Function: localEdgeProcessing
- *
- * Separates the x position of edges as they connect to vertices
- *
- * Parameters:
- *
- * model - the layout model
- */
-mxCoordinateAssignment.prototype.localEdgeProcessing = function(model)
-{
- var edgeMapping = model.edgeMapper;
-
- // Iterate through each vertex, look at the edges connected in
- // both directions.
- for (var rankIndex = 0; rankIndex < model.ranks.length; rankIndex++)
- {
- var rank = model.ranks[rankIndex];
-
- for (var cellIndex = 0; cellIndex < rank.length; cellIndex++)
- {
- var cell = rank[cellIndex];
-
- if (cell.isVertex())
- {
- var currentCells = cell.getPreviousLayerConnectedCells(rankIndex);
-
- var currentRank = rankIndex - 1;
-
- // Two loops, last connected cells, and next
- for (var k = 0; k < 2; k++)
- {
- if (currentRank > -1
- && currentRank < model.ranks.length
- && currentCells != null
- && currentCells.length > 0)
- {
- var sortedCells = [];
-
- for (var j = 0; j < currentCells.length; j++)
- {
- var sorter = new WeightedCellSorter(
- currentCells[j], currentCells[j].getX(currentRank));
- sortedCells.push(sorter);
- }
-
- sortedCells.sort(WeightedCellSorter.prototype.compare);
-
- var leftLimit = cell.x[0] - cell.width / 2;
- var rightLimit = leftLimit + cell.width;
-
- // Connected edge count starts at 1 to allow for buffer
- // with edge of vertex
- var connectedEdgeCount = 0;
- var connectedEdgeGroupCount = 0;
- var connectedEdges = [];
- // Calculate width requirements for all connected edges
- for (var j = 0; j < sortedCells.length; j++)
- {
- var innerCell = sortedCells[j].cell;
- var connections;
-
- if (innerCell.isVertex())
- {
- // Get the connecting edge
- if (k == 0)
- {
- connections = cell.connectsAsSource;
-
- }
- else
- {
- connections = cell.connectsAsTarget;
- }
-
- for (var connIndex = 0; connIndex < connections.length; connIndex++)
- {
- if (connections[connIndex].source == innerCell
- || connections[connIndex].target == innerCell)
- {
- connectedEdgeCount += connections[connIndex].edges
- .length;
- connectedEdgeGroupCount++;
-
- connectedEdges.push(connections[connIndex]);
- }
- }
- }
- else
- {
- connectedEdgeCount += innerCell.edges.length;
- connectedEdgeGroupCount++;
- connectedEdges.push(innerCell);
- }
- }
-
- var requiredWidth = (connectedEdgeCount + 1)
- * this.prefHozEdgeSep;
-
- // Add a buffer on the edges of the vertex if the edge count allows
- if (cell.width > requiredWidth
- + (2 * this.prefHozEdgeSep))
- {
- leftLimit += this.prefHozEdgeSep;
- rightLimit -= this.prefHozEdgeSep;
- }
-
- var availableWidth = rightLimit - leftLimit;
- var edgeSpacing = availableWidth / connectedEdgeCount;
-
- var currentX = leftLimit + edgeSpacing / 2.0;
- var currentYOffset = this.minEdgeJetty - this.prefVertEdgeOff;
- var maxYOffset = 0;
-
- for (var j = 0; j < connectedEdges.length; j++)
- {
- var numActualEdges = connectedEdges[j].edges
- .length;
- var edgeId = mxCellPath.create(connectedEdges[j].edges[0]);
- var pos = this.jettyPositions[edgeId];
-
- if (pos == null)
- {
- pos = [];
- this.jettyPositions[edgeId] = pos;
- }
-
- if (j < connectedEdgeCount / 2)
- {
- currentYOffset += this.prefVertEdgeOff;
- }
- else if (j > connectedEdgeCount / 2)
- {
- currentYOffset -= this.prefVertEdgeOff;
- }
- // Ignore the case if equals, this means the second of 2
- // jettys with the same y (even number of edges)
-
- for (var m = 0; m < numActualEdges; m++)
- {
- pos[m * 4 + k * 2] = currentX;
- currentX += edgeSpacing;
- pos[m * 4 + k * 2 + 1] = currentYOffset;
- }
-
- maxYOffset = Math.max(maxYOffset,
- currentYOffset);
- }
- }
-
- currentCells = cell.getNextLayerConnectedCells(rankIndex);
-
- currentRank = rankIndex + 1;
- }
- }
- }
- }
-};
-
-/**
- * Function: setEdgePosition
- *
- * Fixes the control points
- */
-mxCoordinateAssignment.prototype.setEdgePosition = function(cell)
-{
- // For parallel edges we need to seperate out the points a
- // little
- var offsetX = 0;
- // Only set the edge control points once
-
- if (cell.temp[0] != 101207)
- {
- var maxRank = cell.maxRank;
- var minRank = cell.minRank;
-
- if (maxRank == minRank)
- {
- maxRank = cell.source.maxRank;
- minRank = cell.target.minRank;
- }
-
- var parallelEdgeCount = 0;
- var edgeId = mxCellPath.create(cell.edges[0]);
- var jettys = this.jettyPositions[edgeId];
-
- var source = cell.isReversed ? cell.target.cell : cell.source.cell;
-
- for (var i = 0; i < cell.edges.length; i++)
- {
- var realEdge = cell.edges[i];
- var realSource = this.layout.graph.view.getVisibleTerminal(realEdge, true);
-
- //List oldPoints = graph.getPoints(realEdge);
- var newPoints = [];
-
- // Single length reversed edges end up with the jettys in the wrong
- // places. Since single length edges only have jettys, not segment
- // control points, we just say the edge isn't reversed in this section
- var reversed = cell.isReversed;
-
- if (realSource != source)
- {
- // The real edges include all core model edges and these can go
- // in both directions. If the source of the hierarchical model edge
- // isn't the source of the specific real edge in this iteration
- // treat if as reversed
- reversed = !reversed;
- }
-
- // First jetty of edge
- if (jettys != null)
- {
- var arrayOffset = reversed ? 2 : 0;
- var y = reversed ? this.rankTopY[minRank] : this.rankBottomY[maxRank];
- var jetty = jettys[parallelEdgeCount * 4 + 1 + arrayOffset];
-
- if (reversed)
- {
- jetty = -jetty;
- }
-
- y += jetty;
- var x = jettys[parallelEdgeCount * 4 + arrayOffset];
-
- if (this.orientation == mxConstants.DIRECTION_NORTH
- || this.orientation == mxConstants.DIRECTION_SOUTH)
- {
- newPoints.push(new mxPoint(x, y));
- }
- else
- {
- newPoints.push(new mxPoint(y, x));
- }
- }
-
- // Declare variables to define loop through edge points and
- // change direction if edge is reversed
-
- var loopStart = cell.x.length - 1;
- var loopLimit = -1;
- var loopDelta = -1;
- var currentRank = cell.maxRank - 1;
-
- if (reversed)
- {
- loopStart = 0;
- loopLimit = cell.x.length;
- loopDelta = 1;
- currentRank = cell.minRank + 1;
- }
- // Reversed edges need the points inserted in
- // reverse order
- for (var j = loopStart; (cell.maxRank != cell.minRank) && j != loopLimit; j += loopDelta)
- {
- // The horizontal position in a vertical layout
- var positionX = cell.x[j] + offsetX;
-
- // Work out the vertical positions in a vertical layout
- // in the edge buffer channels above and below this rank
- var topChannelY = (this.rankTopY[currentRank] + this.rankBottomY[currentRank + 1]) / 2.0;
- var bottomChannelY = (this.rankTopY[currentRank - 1] + this.rankBottomY[currentRank]) / 2.0;
-
- if (reversed)
- {
- var tmp = topChannelY;
- topChannelY = bottomChannelY;
- bottomChannelY = tmp;
- }
-
- if (this.orientation == mxConstants.DIRECTION_NORTH ||
- this.orientation == mxConstants.DIRECTION_SOUTH)
- {
- newPoints.push(new mxPoint(positionX, topChannelY));
- newPoints.push(new mxPoint(positionX, bottomChannelY));
- }
- else
- {
- newPoints.push(new mxPoint(topChannelY, positionX));
- newPoints.push(new mxPoint(bottomChannelY, positionX));
- }
-
- this.limitX = Math.max(this.limitX, positionX);
- currentRank += loopDelta;
- }
-
- // Second jetty of edge
- if (jettys != null)
- {
- var arrayOffset = reversed ? 2 : 0;
- var rankY = reversed ? this.rankBottomY[maxRank] : this.rankTopY[minRank];
- var jetty = jettys[parallelEdgeCount * 4 + 3 - arrayOffset];
-
- if (reversed)
- {
- jetty = -jetty;
- }
- var y = rankY - jetty;
- var x = jettys[parallelEdgeCount * 4 + 2 - arrayOffset];
-
- if (this.orientation == mxConstants.DIRECTION_NORTH ||
- this.orientation == mxConstants.DIRECTION_SOUTH)
- {
- newPoints.push(new mxPoint(x, y));
- }
- else
- {
- newPoints.push(new mxPoint(y, x));
- }
- }
-
- if (cell.isReversed)
- {
- this.processReversedEdge(cell, realEdge);
- }
-
- this.layout.setEdgePoints(realEdge, newPoints);
-
- // Increase offset so next edge is drawn next to
- // this one
- if (offsetX == 0.0)
- {
- offsetX = this.parallelEdgeSpacing;
- }
- else if (offsetX > 0)
- {
- offsetX = -offsetX;
- }
- else
- {
- offsetX = -offsetX + this.parallelEdgeSpacing;
- }
-
- parallelEdgeCount++;
- }
-
- cell.temp[0] = 101207;
- }
-};
-
-
-/**
- * Function: setVertexLocation
- *
- * Fixes the position of the specified vertex.
- *
- * Parameters:
- *
- * cell - the vertex to position
- */
-mxCoordinateAssignment.prototype.setVertexLocation = function(cell)
-{
- var realCell = cell.cell;
- var positionX = cell.x[0] - cell.width / 2;
- var positionY = cell.y[0] - cell.height / 2;
-
- this.rankTopY[cell.minRank] = Math.min(this.rankTopY[cell.minRank], positionY);
- this.rankBottomY[cell.minRank] = Math.max(this.rankBottomY[cell.minRank],
- positionY + cell.height);
-
- if (this.orientation == mxConstants.DIRECTION_NORTH ||
- this.orientation == mxConstants.DIRECTION_SOUTH)
- {
- this.layout.setVertexLocation(realCell, positionX, positionY);
- }
- else
- {
- this.layout.setVertexLocation(realCell, positionY, positionX);
- }
-
- this.limitX = Math.max(this.limitX, positionX + cell.width);
-};
-
-/**
- * Function: processReversedEdge
- *
- * Hook to add additional processing
- *
- * Parameters:
- *
- * edge - the hierarchical model edge
- * realEdge - the real edge in the graph
- */
-mxCoordinateAssignment.prototype.processReversedEdge = function(graph, model)
-{
- // hook for subclassers
-};
-
-/**
- * Class: WeightedCellSorter
- *
- * A utility class used to track cells whilst sorting occurs on the weighted
- * sum of their connected edges. Does not violate (x.compareTo(y)==0) ==
- * (x.equals(y))
- *
- * Constructor: WeightedCellSorter
- *
- * Constructs a new weighted cell sorted for the given cell and weight.
- */
-function WeightedCellSorter(cell, weightedValue)
-{
- this.cell = cell;
- this.weightedValue = weightedValue;
-};
-
-/**
- * Variable: weightedValue
- *
- * The weighted value of the cell stored.
- */
-WeightedCellSorter.prototype.weightedValue = 0;
-
-/**
- * Variable: nudge
- *
- * Whether or not to flip equal weight values.
- */
-WeightedCellSorter.prototype.nudge = false;
-
-/**
- * Variable: visited
- *
- * Whether or not this cell has been visited in the current assignment.
- */
-WeightedCellSorter.prototype.visited = false;
-
-/**
- * Variable: rankIndex
- *
- * The index this cell is in the model rank.
- */
-WeightedCellSorter.prototype.rankIndex = null;
-
-/**
- * Variable: cell
- *
- * The cell whose median value is being calculated.
- */
-WeightedCellSorter.prototype.cell = null;
-
-/**
- * Function: compare
- *
- * Compares two WeightedCellSorters.
- */
-WeightedCellSorter.prototype.compare = function(a, b)
-{
- if (a != null && b != null)
- {
- if (b.weightedValue > a.weightedValue)
- {
- return -1;
- }
- else if (b.weightedValue < a.weightedValue)
- {
- return 1;
- }
- else
- {
- if (b.nudge)
- {
- return -1;
- }
- else
- {
- return 1;
- }
- }
- }
- else
- {
- return 0;
- }
-};
diff --git a/src/js/layout/hierarchical/stage/mxHierarchicalLayoutStage.js b/src/js/layout/hierarchical/stage/mxHierarchicalLayoutStage.js
deleted file mode 100644
index 2e635fc..0000000
--- a/src/js/layout/hierarchical/stage/mxHierarchicalLayoutStage.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * $Id: mxHierarchicalLayoutStage.js,v 1.8 2010-01-02 09:45:15 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxHierarchicalLayoutStage
- *
- * The specific layout interface for hierarchical layouts. It adds a
- * <code>run</code> method with a parameter for the hierarchical layout model
- * that is shared between the layout stages.
- *
- * Constructor: mxHierarchicalLayoutStage
- *
- * Constructs a new hierarchical layout stage.
- */
-function mxHierarchicalLayoutStage() { };
-
-/**
- * Function: execute
- *
- * Takes the graph detail and configuration information within the facade
- * and creates the resulting laid out graph within that facade for further
- * use.
- */
-mxHierarchicalLayoutStage.prototype.execute = function(parent) { };
diff --git a/src/js/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js b/src/js/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js
deleted file mode 100644
index 997890e..0000000
--- a/src/js/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js
+++ /dev/null
@@ -1,674 +0,0 @@
-/**
- * $Id: mxMedianHybridCrossingReduction.js,v 1.25 2012-06-07 11:16:41 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxMedianHybridCrossingReduction
- *
- * Sets the horizontal locations of node and edge dummy nodes on each layer.
- * Uses median down and up weighings as well heuristic to straighten edges as
- * far as possible.
- *
- * Constructor: mxMedianHybridCrossingReduction
- *
- * Creates a coordinate assignment.
- *
- * Arguments:
- *
- * intraCellSpacing - the minimum buffer between cells on the same rank
- * interRankCellSpacing - the minimum distance between cells on adjacent ranks
- * orientation - the position of the root node(s) relative to the graph
- * initialX - the leftmost coordinate node placement starts at
- */
-function mxMedianHybridCrossingReduction(layout)
-{
- this.layout = layout;
-};
-
-/**
- * Extends mxMedianHybridCrossingReduction.
- */
-mxMedianHybridCrossingReduction.prototype = new mxHierarchicalLayoutStage();
-mxMedianHybridCrossingReduction.prototype.constructor = mxMedianHybridCrossingReduction;
-
-/**
- * Variable: layout
- *
- * Reference to the enclosing <mxHierarchicalLayout>.
- */
-mxMedianHybridCrossingReduction.prototype.layout = null;
-
-/**
- * Variable: maxIterations
- *
- * The maximum number of iterations to perform whilst reducing edge
- * crossings. Default is 24.
- */
-mxMedianHybridCrossingReduction.prototype.maxIterations = 24;
-
-/**
- * Variable: nestedBestRanks
- *
- * Stores each rank as a collection of cells in the best order found for
- * each layer so far
- */
-mxMedianHybridCrossingReduction.prototype.nestedBestRanks = null;
-
-/**
- * Variable: currentBestCrossings
- *
- * The total number of crossings found in the best configuration so far
- */
-mxMedianHybridCrossingReduction.prototype.currentBestCrossings = 0;
-
-/**
- * Variable: iterationsWithoutImprovement
- *
- * The total number of crossings found in the best configuration so far
- */
-mxMedianHybridCrossingReduction.prototype.iterationsWithoutImprovement = 0;
-
-/**
- * Variable: maxNoImprovementIterations
- *
- * The total number of crossings found in the best configuration so far
- */
-mxMedianHybridCrossingReduction.prototype.maxNoImprovementIterations = 2;
-
-/**
- * Function: execute
- *
- * Performs a vertex ordering within ranks as described by Gansner et al
- * 1993
- */
-mxMedianHybridCrossingReduction.prototype.execute = function(parent)
-{
- var model = this.layout.getModel();
-
- // Stores initial ordering as being the best one found so far
- this.nestedBestRanks = [];
-
- for (var i = 0; i < model.ranks.length; i++)
- {
- this.nestedBestRanks[i] = model.ranks[i].slice();
- }
-
- var iterationsWithoutImprovement = 0;
- var currentBestCrossings = this.calculateCrossings(model);
-
- for (var i = 0; i < this.maxIterations &&
- iterationsWithoutImprovement < this.maxNoImprovementIterations; i++)
- {
- this.weightedMedian(i, model);
- this.transpose(i, model);
- var candidateCrossings = this.calculateCrossings(model);
-
- if (candidateCrossings < currentBestCrossings)
- {
- currentBestCrossings = candidateCrossings;
- iterationsWithoutImprovement = 0;
-
- // Store the current rankings as the best ones
- for (var j = 0; j < this.nestedBestRanks.length; j++)
- {
- var rank = model.ranks[j];
-
- for (var k = 0; k < rank.length; k++)
- {
- var cell = rank[k];
- this.nestedBestRanks[j][cell.getGeneralPurposeVariable(j)] = cell;
- }
- }
- }
- else
- {
- // Increase count of iterations where we haven't improved the
- // layout
- iterationsWithoutImprovement++;
-
- // Restore the best values to the cells
- for (var j = 0; j < this.nestedBestRanks.length; j++)
- {
- var rank = model.ranks[j];
-
- for (var k = 0; k < rank.length; k++)
- {
- var cell = rank[k];
- cell.setGeneralPurposeVariable(j, k);
- }
- }
- }
-
- if (currentBestCrossings == 0)
- {
- // Do nothing further
- break;
- }
- }
-
- // Store the best rankings but in the model
- var ranks = [];
- var rankList = [];
-
- for (var i = 0; i < model.maxRank + 1; i++)
- {
- rankList[i] = [];
- ranks[i] = rankList[i];
- }
-
- for (var i = 0; i < this.nestedBestRanks.length; i++)
- {
- for (var j = 0; j < this.nestedBestRanks[i].length; j++)
- {
- rankList[i].push(this.nestedBestRanks[i][j]);
- }
- }
-
- model.ranks = ranks;
-};
-
-
-/**
- * Function: calculateCrossings
- *
- * Calculates the total number of edge crossing in the current graph.
- * Returns the current number of edge crossings in the hierarchy graph
- * model in the current candidate layout
- *
- * Parameters:
- *
- * model - the internal model describing the hierarchy
- */
-mxMedianHybridCrossingReduction.prototype.calculateCrossings = function(model)
-{
- var numRanks = model.ranks.length;
- var totalCrossings = 0;
-
- for (var i = 1; i < numRanks; i++)
- {
- totalCrossings += this.calculateRankCrossing(i, model);
- }
-
- return totalCrossings;
-};
-
-/**
- * Function: calculateRankCrossing
- *
- * Calculates the number of edges crossings between the specified rank and
- * the rank below it. Returns the number of edges crossings with the rank
- * beneath
- *
- * Parameters:
- *
- * i - the topmost rank of the pair ( higher rank value )
- * model - the internal model describing the hierarchy
- */
-mxMedianHybridCrossingReduction.prototype.calculateRankCrossing = function(i, model)
-{
- var totalCrossings = 0;
- var rank = model.ranks[i];
- var previousRank = model.ranks[i - 1];
-
- // Create an array of connections between these two levels
- var currentRankSize = rank.length;
- var previousRankSize = previousRank.length;
- var connections = [];
-
- for (var j = 0; j < currentRankSize; j++)
- {
- connections[j] = [];
- }
-
- // Iterate over the top rank and fill in the connection information
- for (var j = 0; j < rank.length; j++)
- {
- var node = rank[j];
- var rankPosition = node.getGeneralPurposeVariable(i);
- var connectedCells = node.getPreviousLayerConnectedCells(i);
-
- for (var k = 0; k < connectedCells.length; k++)
- {
- var connectedNode = connectedCells[k];
- var otherCellRankPosition = connectedNode.getGeneralPurposeVariable(i - 1);
- connections[rankPosition][otherCellRankPosition] = 201207;
- }
- }
-
- // Iterate through the connection matrix, crossing edges are
- // indicated by other connected edges with a greater rank position
- // on one rank and lower position on the other
- for (var j = 0; j < currentRankSize; j++)
- {
- for (var k = 0; k < previousRankSize; k++)
- {
- if (connections[j][k] == 201207)
- {
- // Draw a grid of connections, crossings are top right
- // and lower left from this crossing pair
- for (var j2 = j + 1; j2 < currentRankSize; j2++)
- {
- for (var k2 = 0; k2 < k; k2++)
- {
- if (connections[j2][k2] == 201207)
- {
- totalCrossings++;
- }
- }
- }
-
- for (var j2 = 0; j2 < j; j2++)
- {
- for (var k2 = k + 1; k2 < previousRankSize; k2++)
- {
- if (connections[j2][k2] == 201207)
- {
- totalCrossings++;
- }
- }
- }
-
- }
- }
- }
-
- return totalCrossings / 2;
-};
-
-/**
- * Function: transpose
- *
- * Takes each possible adjacent cell pair on each rank and checks if
- * swapping them around reduces the number of crossing
- *
- * Parameters:
- *
- * mainLoopIteration - the iteration number of the main loop
- * model - the internal model describing the hierarchy
- */
-mxMedianHybridCrossingReduction.prototype.transpose = function(mainLoopIteration, model)
-{
- var improved = true;
-
- // Track the number of iterations in case of looping
- var count = 0;
- var maxCount = 10;
- while (improved && count++ < maxCount)
- {
- // On certain iterations allow allow swapping of cell pairs with
- // equal edge crossings switched or not switched. This help to
- // nudge a stuck layout into a lower crossing total.
- var nudge = mainLoopIteration % 2 == 1 && count % 2 == 1;
- improved = false;
-
- for (var i = 0; i < model.ranks.length; i++)
- {
- var rank = model.ranks[i];
- var orderedCells = [];
-
- for (var j = 0; j < rank.length; j++)
- {
- var cell = rank[j];
- var tempRank = cell.getGeneralPurposeVariable(i);
-
- // FIXME: Workaround to avoid negative tempRanks
- if (tempRank < 0)
- {
- tempRank = j;
- }
- orderedCells[tempRank] = cell;
- }
-
- var leftCellAboveConnections = null;
- var leftCellBelowConnections = null;
- var rightCellAboveConnections = null;
- var rightCellBelowConnections = null;
-
- var leftAbovePositions = null;
- var leftBelowPositions = null;
- var rightAbovePositions = null;
- var rightBelowPositions = null;
-
- var leftCell = null;
- var rightCell = null;
-
- for (var j = 0; j < (rank.length - 1); j++)
- {
- // For each intra-rank adjacent pair of cells
- // see if swapping them around would reduce the
- // number of edges crossing they cause in total
- // On every cell pair except the first on each rank, we
- // can save processing using the previous values for the
- // right cell on the new left cell
- if (j == 0)
- {
- leftCell = orderedCells[j];
- leftCellAboveConnections = leftCell
- .getNextLayerConnectedCells(i);
- leftCellBelowConnections = leftCell
- .getPreviousLayerConnectedCells(i);
- leftAbovePositions = [];
- leftBelowPositions = [];
-
- for (var k = 0; k < leftCellAboveConnections.length; k++)
- {
- leftAbovePositions[k] = leftCellAboveConnections[k].getGeneralPurposeVariable(i + 1);
- }
-
- for (var k = 0; k < leftCellBelowConnections.length; k++)
- {
- leftBelowPositions[k] = leftCellBelowConnections[k].getGeneralPurposeVariable(i - 1);
- }
- }
- else
- {
- leftCellAboveConnections = rightCellAboveConnections;
- leftCellBelowConnections = rightCellBelowConnections;
- leftAbovePositions = rightAbovePositions;
- leftBelowPositions = rightBelowPositions;
- leftCell = rightCell;
- }
-
- rightCell = orderedCells[j + 1];
- rightCellAboveConnections = rightCell
- .getNextLayerConnectedCells(i);
- rightCellBelowConnections = rightCell
- .getPreviousLayerConnectedCells(i);
-
- rightAbovePositions = [];
- rightBelowPositions = [];
-
- for (var k = 0; k < rightCellAboveConnections.length; k++)
- {
- rightAbovePositions[k] = rightCellAboveConnections[k].getGeneralPurposeVariable(i + 1);
- }
-
- for (var k = 0; k < rightCellBelowConnections.length; k++)
- {
- rightBelowPositions[k] = rightCellBelowConnections[k].getGeneralPurposeVariable(i - 1);
- }
-
- var totalCurrentCrossings = 0;
- var totalSwitchedCrossings = 0;
-
- for (var k = 0; k < leftAbovePositions.length; k++)
- {
- for (var ik = 0; ik < rightAbovePositions.length; ik++)
- {
- if (leftAbovePositions[k] > rightAbovePositions[ik])
- {
- totalCurrentCrossings++;
- }
-
- if (leftAbovePositions[k] < rightAbovePositions[ik])
- {
- totalSwitchedCrossings++;
- }
- }
- }
-
- for (var k = 0; k < leftBelowPositions.length; k++)
- {
- for (var ik = 0; ik < rightBelowPositions.length; ik++)
- {
- if (leftBelowPositions[k] > rightBelowPositions[ik])
- {
- totalCurrentCrossings++;
- }
-
- if (leftBelowPositions[k] < rightBelowPositions[ik])
- {
- totalSwitchedCrossings++;
- }
- }
- }
-
- if ((totalSwitchedCrossings < totalCurrentCrossings) ||
- (totalSwitchedCrossings == totalCurrentCrossings &&
- nudge))
- {
- var temp = leftCell.getGeneralPurposeVariable(i);
- leftCell.setGeneralPurposeVariable(i, rightCell
- .getGeneralPurposeVariable(i));
- rightCell.setGeneralPurposeVariable(i, temp);
-
- // With this pair exchanged we have to switch all of
- // values for the left cell to the right cell so the
- // next iteration for this rank uses it as the left
- // cell again
- rightCellAboveConnections = leftCellAboveConnections;
- rightCellBelowConnections = leftCellBelowConnections;
- rightAbovePositions = leftAbovePositions;
- rightBelowPositions = leftBelowPositions;
- rightCell = leftCell;
-
- if (!nudge)
- {
- // Don't count nudges as improvement or we'll end
- // up stuck in two combinations and not finishing
- // as early as we should
- improved = true;
- }
- }
- }
- }
- }
-};
-
-/**
- * Function: weightedMedian
- *
- * Sweeps up or down the layout attempting to minimise the median placement
- * of connected cells on adjacent ranks
- *
- * Parameters:
- *
- * iteration - the iteration number of the main loop
- * model - the internal model describing the hierarchy
- */
-mxMedianHybridCrossingReduction.prototype.weightedMedian = function(iteration, model)
-{
- // Reverse sweep direction each time through this method
- var downwardSweep = (iteration % 2 == 0);
- if (downwardSweep)
- {
- for (var j = model.maxRank - 1; j >= 0; j--)
- {
- this.medianRank(j, downwardSweep);
- }
- }
- else
- {
- for (var j = 1; j < model.maxRank; j++)
- {
- this.medianRank(j, downwardSweep);
- }
- }
-};
-
-/**
- * Function: medianRank
- *
- * Attempts to minimise the median placement of connected cells on this rank
- * and one of the adjacent ranks
- *
- * Parameters:
- *
- * rankValue - the layer number of this rank
- * downwardSweep - whether or not this is a downward sweep through the graph
- */
-mxMedianHybridCrossingReduction.prototype.medianRank = function(rankValue, downwardSweep)
-{
- var numCellsForRank = this.nestedBestRanks[rankValue].length;
- var medianValues = [];
- var reservedPositions = [];
-
- for (var i = 0; i < numCellsForRank; i++)
- {
- var cell = this.nestedBestRanks[rankValue][i];
- var sorterEntry = new MedianCellSorter();
- sorterEntry.cell = cell;
-
- // Flip whether or not equal medians are flipped on up and down
- // sweeps
- // TODO re-implement some kind of nudge
- // medianValues[i].nudge = !downwardSweep;
- var nextLevelConnectedCells;
-
- if (downwardSweep)
- {
- nextLevelConnectedCells = cell
- .getNextLayerConnectedCells(rankValue);
- }
- else
- {
- nextLevelConnectedCells = cell
- .getPreviousLayerConnectedCells(rankValue);
- }
-
- var nextRankValue;
-
- if (downwardSweep)
- {
- nextRankValue = rankValue + 1;
- }
- else
- {
- nextRankValue = rankValue - 1;
- }
-
- if (nextLevelConnectedCells != null
- && nextLevelConnectedCells.length != 0)
- {
- sorterEntry.medianValue = this.medianValue(
- nextLevelConnectedCells, nextRankValue);
- medianValues.push(sorterEntry);
- }
- else
- {
- // Nodes with no adjacent vertices are flagged in the reserved array
- // to indicate they should be left in their current position.
- reservedPositions[cell.getGeneralPurposeVariable(rankValue)] = true;
- }
- }
-
- medianValues.sort(MedianCellSorter.prototype.compare);
-
- // Set the new position of each node within the rank using
- // its temp variable
- for (var i = 0; i < numCellsForRank; i++)
- {
- if (reservedPositions[i] == null)
- {
- var cell = medianValues.shift().cell;
- cell.setGeneralPurposeVariable(rankValue, i);
- }
- }
-};
-
-/**
- * Function: medianValue
- *
- * Calculates the median rank order positioning for the specified cell using
- * the connected cells on the specified rank. Returns the median rank
- * ordering value of the connected cells
- *
- * Parameters:
- *
- * connectedCells - the cells on the specified rank connected to the
- * specified cell
- * rankValue - the rank that the connected cell lie upon
- */
-mxMedianHybridCrossingReduction.prototype.medianValue = function(connectedCells, rankValue)
-{
- var medianValues = [];
- var arrayCount = 0;
-
- for (var i = 0; i < connectedCells.length; i++)
- {
- var cell = connectedCells[i];
- medianValues[arrayCount++] = cell.getGeneralPurposeVariable(rankValue);
- }
-
- // Sort() sorts lexicographically by default (i.e. 11 before 9) so force
- // numerical order sort
- medianValues.sort(function(a,b){return a - b;});
-
- if (arrayCount % 2 == 1)
- {
- // For odd numbers of adjacent vertices return the median
- return medianValues[Math.floor(arrayCount / 2)];
- }
- else if (arrayCount == 2)
- {
- return ((medianValues[0] + medianValues[1]) / 2.0);
- }
- else
- {
- var medianPoint = arrayCount / 2;
- var leftMedian = medianValues[medianPoint - 1] - medianValues[0];
- var rightMedian = medianValues[arrayCount - 1]
- - medianValues[medianPoint];
-
- return (medianValues[medianPoint - 1] * rightMedian + medianValues[medianPoint]
- * leftMedian)
- / (leftMedian + rightMedian);
- }
-};
-
-/**
- * Class: MedianCellSorter
- *
- * A utility class used to track cells whilst sorting occurs on the median
- * values. Does not violate (x.compareTo(y)==0) == (x.equals(y))
- *
- * Constructor: MedianCellSorter
- *
- * Constructs a new median cell sorter.
- */
-function MedianCellSorter()
-{
- // empty
-};
-
-/**
- * Variable: medianValue
- *
- * The weighted value of the cell stored.
- */
-MedianCellSorter.prototype.medianValue = 0;
-
-/**
- * Variable: cell
- *
- * The cell whose median value is being calculated
- */
-MedianCellSorter.prototype.cell = false;
-
-/**
- * Function: compare
- *
- * Compares two MedianCellSorters.
- */
-MedianCellSorter.prototype.compare = function(a, b)
-{
- if (a != null && b != null)
- {
- if (b.medianValue > a.medianValue)
- {
- return -1;
- }
- else if (b.medianValue < a.medianValue)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- else
- {
- return 0;
- }
-};
diff --git a/src/js/layout/hierarchical/stage/mxMinimumCycleRemover.js b/src/js/layout/hierarchical/stage/mxMinimumCycleRemover.js
deleted file mode 100644
index 4f18f62..0000000
--- a/src/js/layout/hierarchical/stage/mxMinimumCycleRemover.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * $Id: mxMinimumCycleRemover.js,v 1.14 2010-01-04 11:18:26 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxMinimumCycleRemover
- *
- * An implementation of the first stage of the Sugiyama layout. Straightforward
- * longest path calculation of layer assignment
- *
- * Constructor: mxMinimumCycleRemover
- *
- * Creates a cycle remover for the given internal model.
- */
-function mxMinimumCycleRemover(layout)
-{
- this.layout = layout;
-};
-
-/**
- * Extends mxHierarchicalLayoutStage.
- */
-mxMinimumCycleRemover.prototype = new mxHierarchicalLayoutStage();
-mxMinimumCycleRemover.prototype.constructor = mxMinimumCycleRemover;
-
-/**
- * Variable: layout
- *
- * Reference to the enclosing <mxHierarchicalLayout>.
- */
-mxMinimumCycleRemover.prototype.layout = null;
-
-/**
- * Function: execute
- *
- * Takes the graph detail and configuration information within the facade
- * and creates the resulting laid out graph within that facade for further
- * use.
- */
-mxMinimumCycleRemover.prototype.execute = function(parent)
-{
- var model = this.layout.getModel();
- var seenNodes = new Object();
- var unseenNodes = mxUtils.clone(model.vertexMapper, null, true);
-
- // Perform a dfs through the internal model. If a cycle is found,
- // reverse it.
- var rootsArray = null;
-
- if (model.roots != null)
- {
- var modelRoots = model.roots;
- rootsArray = [];
-
- for (var i = 0; i < modelRoots.length; i++)
- {
- var nodeId = mxCellPath.create(modelRoots[i]);
- rootsArray[i] = model.vertexMapper[nodeId];
- }
- }
-
- model.visit(function(parent, node, connectingEdge, layer, seen)
- {
- // Check if the cell is in it's own ancestor list, if so
- // invert the connecting edge and reverse the target/source
- // relationship to that edge in the parent and the cell
- if (node.isAncestor(parent))
- {
- connectingEdge.invert();
- mxUtils.remove(connectingEdge, parent.connectsAsSource);
- parent.connectsAsTarget.push(connectingEdge);
- mxUtils.remove(connectingEdge, node.connectsAsTarget);
- node.connectsAsSource.push(connectingEdge);
- }
-
- var cellId = mxCellPath.create(node.cell);
- seenNodes[cellId] = node;
- delete unseenNodes[cellId];
- }, rootsArray, true, null);
-
- var possibleNewRoots = null;
-
- if (unseenNodes.lenth > 0)
- {
- possibleNewRoots = mxUtils.clone(unseenNodes, null, true);
- }
-
- // If there are any nodes that should be nodes that the dfs can miss
- // these need to be processed with the dfs and the roots assigned
- // correctly to form a correct internal model
- var seenNodesCopy = mxUtils.clone(seenNodes, null, true);
-
- // Pick a random cell and dfs from it
- model.visit(function(parent, node, connectingEdge, layer, seen)
- {
- // Check if the cell is in it's own ancestor list, if so
- // invert the connecting edge and reverse the target/source
- // relationship to that edge in the parent and the cell
- if (node.isAncestor(parent))
- {
- connectingEdge.invert();
- mxUtils.remove(connectingEdge, parent.connectsAsSource);
- node.connectsAsSource.push(connectingEdge);
- parent.connectsAsTarget.push(connectingEdge);
- mxUtils.remove(connectingEdge, node.connectsAsTarget);
- }
-
- var cellId = mxCellPath.create(node.cell);
- seenNodes[cellId] = node;
- delete unseenNodes[cellId];
- }, unseenNodes, true, seenNodesCopy);
-
- var graph = this.layout.getGraph();
-
- if (possibleNewRoots != null && possibleNewRoots.length > 0)
- {
- var roots = model.roots;
-
- for (var i = 0; i < possibleNewRoots.length; i++)
- {
- var node = possibleNewRoots[i];
- var realNode = node.cell;
- var numIncomingEdges = graph.getIncomingEdges(realNode).length;
-
- if (numIncomingEdges == 0)
- {
- roots.push(realNode);
- }
- }
- }
-};
diff --git a/src/js/layout/mxCircleLayout.js b/src/js/layout/mxCircleLayout.js
deleted file mode 100644
index e3e6ec1..0000000
--- a/src/js/layout/mxCircleLayout.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
- * $Id: mxCircleLayout.js,v 1.25 2012-08-22 17:26:12 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCircleLayout
- *
- * Extends <mxGraphLayout> to implement a circluar layout for a given radius.
- * The vertices do not need to be connected for this layout to work and all
- * connections between vertices are not taken into account.
- *
- * Example:
- *
- * (code)
- * var layout = new mxCircleLayout(graph);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxCircleLayout
- *
- * Constructs a new circular layout for the specified radius.
- *
- * Arguments:
- *
- * graph - <mxGraph> that contains the cells.
- * radius - Optional radius as an int. Default is 100.
- */
-function mxCircleLayout(graph, radius)
-{
- mxGraphLayout.call(this, graph);
- this.radius = (radius != null) ? radius : 100;
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxCircleLayout.prototype = new mxGraphLayout();
-mxCircleLayout.prototype.constructor = mxCircleLayout;
-
-/**
- * Variable: radius
- *
- * Integer specifying the size of the radius. Default is 100.
- */
-mxCircleLayout.prototype.radius = null;
-
-/**
- * Variable: moveCircle
- *
- * Boolean specifying if the circle should be moved to the top,
- * left corner specified by <x0> and <y0>. Default is false.
- */
-mxCircleLayout.prototype.moveCircle = false;
-
-/**
- * Variable: x0
- *
- * Integer specifying the left coordinate of the circle.
- * Default is 0.
- */
-mxCircleLayout.prototype.x0 = 0;
-
-/**
- * Variable: y0
- *
- * Integer specifying the top coordinate of the circle.
- * Default is 0.
- */
-mxCircleLayout.prototype.y0 = 0;
-
-/**
- * Variable: resetEdges
- *
- * Specifies if all edge points of traversed edges should be removed.
- * Default is true.
- */
-mxCircleLayout.prototype.resetEdges = true;
-
-/**
- * Variable: disableEdgeStyle
- *
- * Specifies if the STYLE_NOEDGESTYLE flag should be set on edges that are
- * modified by the result. Default is true.
- */
-mxCircleLayout.prototype.disableEdgeStyle = true;
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>.
- */
-mxCircleLayout.prototype.execute = function(parent)
-{
- var model = this.graph.getModel();
-
- // Moves the vertices to build a circle. Makes sure the
- // radius is large enough for the vertices to not
- // overlap
- model.beginUpdate();
- try
- {
- // Gets all vertices inside the parent and finds
- // the maximum dimension of the largest vertex
- var max = 0;
- var top = null;
- var left = null;
- var vertices = [];
- var childCount = model.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var cell = model.getChildAt(parent, i);
-
- if (!this.isVertexIgnored(cell))
- {
- vertices.push(cell);
- var bounds = this.getVertexBounds(cell);
-
- if (top == null)
- {
- top = bounds.y;
- }
- else
- {
- top = Math.min(top, bounds.y);
- }
-
- if (left == null)
- {
- left = bounds.x;
- }
- else
- {
- left = Math.min(left, bounds.x);
- }
-
- max = Math.max(max, Math.max(bounds.width, bounds.height));
- }
- else if (!this.isEdgeIgnored(cell))
- {
- // Resets the points on the traversed edge
- if (this.resetEdges)
- {
- this.graph.resetEdge(cell);
- }
-
- if (this.disableEdgeStyle)
- {
- this.setEdgeStyleEnabled(cell, false);
- }
- }
- }
-
- var r = this.getRadius(vertices.length, max);
-
- // Moves the circle to the specified origin
- if (this.moveCircle)
- {
- left = this.x0;
- top = this.y0;
- }
-
- this.circle(vertices, r, left, top);
- }
- finally
- {
- model.endUpdate();
- }
-};
-
-/**
- * Function: getRadius
- *
- * Returns the radius to be used for the given vertex count. Max is the maximum
- * width or height of all vertices in the layout.
- */
-mxCircleLayout.prototype.getRadius = function(count, max)
-{
- return Math.max(count * max / Math.PI, this.radius);
-};
-
-/**
- * Function: circle
- *
- * Executes the circular layout for the specified array
- * of vertices and the given radius. This is called from
- * <execute>.
- */
-mxCircleLayout.prototype.circle = function(vertices, r, left, top)
-{
- var vertexCount = vertices.length;
- var phi = 2 * Math.PI / vertexCount;
-
- for (var i = 0; i < vertexCount; i++)
- {
- if (this.isVertexMovable(vertices[i]))
- {
- this.setVertexLocation(vertices[i],
- left + r + r * Math.sin(i*phi),
- top + r + r * Math.cos(i*phi));
- }
- }
-};
diff --git a/src/js/layout/mxCompactTreeLayout.js b/src/js/layout/mxCompactTreeLayout.js
deleted file mode 100644
index db6324c..0000000
--- a/src/js/layout/mxCompactTreeLayout.js
+++ /dev/null
@@ -1,995 +0,0 @@
-/**
- * $Id: mxCompactTreeLayout.js,v 1.57 2012-05-24 13:09:34 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCompactTreeLayout
- *
- * Extends <mxGraphLayout> to implement a compact tree (Moen) algorithm. This
- * layout is suitable for graphs that have no cycles (trees). Vertices that are
- * not connected to the tree will be ignored by this layout.
- *
- * Example:
- *
- * (code)
- * var layout = new mxCompactTreeLayout(graph);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxCompactTreeLayout
- *
- * Constructs a new compact tree layout for the specified graph
- * and orientation.
- */
-function mxCompactTreeLayout(graph, horizontal, invert)
-{
- mxGraphLayout.call(this, graph);
- this.horizontal = (horizontal != null) ? horizontal : true;
- this.invert = (invert != null) ? invert : false;
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxCompactTreeLayout.prototype = new mxGraphLayout();
-mxCompactTreeLayout.prototype.constructor = mxCompactTreeLayout;
-
-/**
- * Variable: horizontal
- *
- * Specifies the orientation of the layout. Default is true.
- */
-mxCompactTreeLayout.prototype.horizontal = null;
-
-/**
- * Variable: invert
- *
- * Specifies if edge directions should be inverted. Default is false.
- */
-mxCompactTreeLayout.prototype.invert = null;
-
-/**
- * Variable: resizeParent
- *
- * If the parents should be resized to match the width/height of the
- * children. Default is true.
- */
-mxCompactTreeLayout.prototype.resizeParent = true;
-
-/**
- * Variable: groupPadding
- *
- * Padding added to resized parents
- */
-mxCompactTreeLayout.prototype.groupPadding = 10;
-
-/**
- * Variable: parentsChanged
- *
- * A set of the parents that need updating based on children
- * process as part of the layout
- */
-mxCompactTreeLayout.prototype.parentsChanged = null;
-
-/**
- * Variable: moveTree
- *
- * Specifies if the tree should be moved to the top, left corner
- * if it is inside a top-level layer. Default is false.
- */
-mxCompactTreeLayout.prototype.moveTree = false;
-
-/**
- * Variable: levelDistance
- *
- * Holds the levelDistance. Default is 10.
- */
-mxCompactTreeLayout.prototype.levelDistance = 10;
-
-/**
- * Variable: nodeDistance
- *
- * Holds the nodeDistance. Default is 20.
- */
-mxCompactTreeLayout.prototype.nodeDistance = 20;
-
-/**
- * Variable: resetEdges
- *
- * Specifies if all edge points of traversed edges should be removed.
- * Default is true.
- */
-mxCompactTreeLayout.prototype.resetEdges = true;
-
-/**
- * Variable: prefHozEdgeSep
- *
- * The preferred horizontal distance between edges exiting a vertex
- */
-mxCompactTreeLayout.prototype.prefHozEdgeSep = 5;
-
-/**
- * Variable: prefVertEdgeOff
- *
- * The preferred vertical offset between edges exiting a vertex
- */
-mxCompactTreeLayout.prototype.prefVertEdgeOff = 4;
-
-/**
- * Variable: minEdgeJetty
- *
- * The minimum distance for an edge jetty from a vertex
- */
-mxCompactTreeLayout.prototype.minEdgeJetty = 8;
-
-/**
- * Variable: channelBuffer
- *
- * The size of the vertical buffer in the center of inter-rank channels
- * where edge control points should not be placed
- */
-mxCompactTreeLayout.prototype.channelBuffer = 4;
-
-/**
- * Variable: edgeRouting
- *
- * Whether or not to apply the internal tree edge routing
- */
-mxCompactTreeLayout.prototype.edgeRouting = true;
-
-/**
- * Function: isVertexIgnored
- *
- * Returns a boolean indicating if the given <mxCell> should be ignored as a
- * vertex. This returns true if the cell has no connections.
- *
- * Parameters:
- *
- * vertex - <mxCell> whose ignored state should be returned.
- */
-mxCompactTreeLayout.prototype.isVertexIgnored = function(vertex)
-{
- return mxGraphLayout.prototype.isVertexIgnored.apply(this, arguments) ||
- this.graph.getConnections(vertex).length == 0;
-};
-
-/**
- * Function: isHorizontal
- *
- * Returns <horizontal>.
- */
-mxCompactTreeLayout.prototype.isHorizontal = function()
-{
- return this.horizontal;
-};
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>.
- *
- * If the parent has any connected edges, then it is used as the root of
- * the tree. Else, <mxGraph.findTreeRoots> will be used to find a suitable
- * root node within the set of children of the given parent.
- *
- * Parameters:
- *
- * parent - <mxCell> whose children should be laid out.
- * root - Optional <mxCell> that will be used as the root of the tree.
- */
-mxCompactTreeLayout.prototype.execute = function(parent, root)
-{
- this.parent = parent;
- var model = this.graph.getModel();
-
- if (root == null)
- {
- // Takes the parent as the root if it has outgoing edges
- if (this.graph.getEdges(parent, model.getParent(parent),
- this.invert, !this.invert, false).length > 0)
- {
- root = parent;
- }
-
- // Tries to find a suitable root in the parent's
- // children
- else
- {
- var roots = this.graph.findTreeRoots(parent, true, this.invert);
-
- if (roots.length > 0)
- {
- for (var i = 0; i < roots.length; i++)
- {
- if (!this.isVertexIgnored(roots[i]) &&
- this.graph.getEdges(roots[i], null,
- this.invert, !this.invert, false).length > 0)
- {
- root = roots[i];
- break;
- }
- }
- }
- }
- }
-
- if (root != null)
- {
- if (this.resizeParent)
- {
- this.parentsChanged = new Object();
- }
- else
- {
- this.parentsChanged = null;
- }
-
- model.beginUpdate();
-
- try
- {
- var node = this.dfs(root, parent);
-
- if (node != null)
- {
- this.layout(node);
- var x0 = this.graph.gridSize;
- var y0 = x0;
-
- if (!this.moveTree)
- {
- var g = this.getVertexBounds(root);
-
- if (g != null)
- {
- x0 = g.x;
- y0 = g.y;
- }
- }
-
- var bounds = null;
-
- if (this.isHorizontal())
- {
- bounds = this.horizontalLayout(node, x0, y0);
- }
- else
- {
- bounds = this.verticalLayout(node, null, x0, y0);
- }
-
- if (bounds != null)
- {
- var dx = 0;
- var dy = 0;
-
- if (bounds.x < 0)
- {
- dx = Math.abs(x0 - bounds.x);
- }
-
- if (bounds.y < 0)
- {
- dy = Math.abs(y0 - bounds.y);
- }
-
- if (dx != 0 || dy != 0)
- {
- this.moveNode(node, dx, dy);
- }
-
- if (this.resizeParent)
- {
- this.adjustParents();
- }
-
- if (this.edgeRouting)
- {
- // Iterate through all edges setting their positions
- this.localEdgeProcessing(node);
- }
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
-};
-
-/**
- * Function: moveNode
- *
- * Moves the specified node and all of its children by the given amount.
- */
-mxCompactTreeLayout.prototype.moveNode = function(node, dx, dy)
-{
- node.x += dx;
- node.y += dy;
- this.apply(node);
-
- var child = node.child;
-
- while (child != null)
- {
- this.moveNode(child, dx, dy);
- child = child.next;
- }
-};
-
-/**
- * Function: dfs
- *
- * Does a depth first search starting at the specified cell.
- * Makes sure the specified parent is never left by the
- * algorithm.
- */
-mxCompactTreeLayout.prototype.dfs = function(cell, parent, visited)
-{
- visited = (visited != null) ? visited : [];
-
- var id = mxCellPath.create(cell);
- var node = null;
-
- if (cell != null && visited[id] == null && !this.isVertexIgnored(cell))
- {
- visited[id] = cell;
- node = this.createNode(cell);
-
- var model = this.graph.getModel();
- var prev = null;
- var out = this.graph.getEdges(cell, parent, this.invert, !this.invert, false, true);
- var view = this.graph.getView();
-
- for (var i = 0; i < out.length; i++)
- {
- var edge = out[i];
-
- if (!this.isEdgeIgnored(edge))
- {
- // Resets the points on the traversed edge
- if (this.resetEdges)
- {
- this.setEdgePoints(edge, null);
- }
-
- if (this.edgeRouting)
- {
- this.setEdgeStyleEnabled(edge, false);
- this.setEdgePoints(edge, null);
- }
-
- // Checks if terminal in same swimlane
- var state = view.getState(edge);
- var target = (state != null) ? state.getVisibleTerminal(this.invert) : view.getVisibleTerminal(edge, this.invert);
- var tmp = this.dfs(target, parent, visited);
-
- if (tmp != null && model.getGeometry(target) != null)
- {
- if (prev == null)
- {
- node.child = tmp;
- }
- else
- {
- prev.next = tmp;
- }
-
- prev = tmp;
- }
- }
- }
- }
-
- return node;
-};
-
-/**
- * Function: layout
- *
- * Starts the actual compact tree layout algorithm
- * at the given node.
- */
-mxCompactTreeLayout.prototype.layout = function(node)
-{
- if (node != null)
- {
- var child = node.child;
-
- while (child != null)
- {
- this.layout(child);
- child = child.next;
- }
-
- if (node.child != null)
- {
- this.attachParent(node, this.join(node));
- }
- else
- {
- this.layoutLeaf(node);
- }
- }
-};
-
-/**
- * Function: horizontalLayout
- */
-mxCompactTreeLayout.prototype.horizontalLayout = function(node, x0, y0, bounds)
-{
- node.x += x0 + node.offsetX;
- node.y += y0 + node.offsetY;
- bounds = this.apply(node, bounds);
- var child = node.child;
-
- if (child != null)
- {
- bounds = this.horizontalLayout(child, node.x, node.y, bounds);
- var siblingOffset = node.y + child.offsetY;
- var s = child.next;
-
- while (s != null)
- {
- bounds = this.horizontalLayout(s, node.x + child.offsetX, siblingOffset, bounds);
- siblingOffset += s.offsetY;
- s = s.next;
- }
- }
-
- return bounds;
-};
-
-/**
- * Function: verticalLayout
- */
-mxCompactTreeLayout.prototype.verticalLayout = function(node, parent, x0, y0, bounds)
-{
- node.x += x0 + node.offsetY;
- node.y += y0 + node.offsetX;
- bounds = this.apply(node, bounds);
- var child = node.child;
-
- if (child != null)
- {
- bounds = this.verticalLayout(child, node, node.x, node.y, bounds);
- var siblingOffset = node.x + child.offsetY;
- var s = child.next;
-
- while (s != null)
- {
- bounds = this.verticalLayout(s, node, siblingOffset, node.y + child.offsetX, bounds);
- siblingOffset += s.offsetY;
- s = s.next;
- }
- }
-
- return bounds;
-};
-
-/**
- * Function: attachParent
- */
-mxCompactTreeLayout.prototype.attachParent = function(node, height)
-{
- var x = this.nodeDistance + this.levelDistance;
- var y2 = (height - node.width) / 2 - this.nodeDistance;
- var y1 = y2 + node.width + 2 * this.nodeDistance - height;
-
- node.child.offsetX = x + node.height;
- node.child.offsetY = y1;
-
- node.contour.upperHead = this.createLine(node.height, 0,
- this.createLine(x, y1, node.contour.upperHead));
- node.contour.lowerHead = this.createLine(node.height, 0,
- this.createLine(x, y2, node.contour.lowerHead));
-};
-
-/**
- * Function: layoutLeaf
- */
-mxCompactTreeLayout.prototype.layoutLeaf = function(node)
-{
- var dist = 2 * this.nodeDistance;
-
- node.contour.upperTail = this.createLine(
- node.height + dist, 0);
- node.contour.upperHead = node.contour.upperTail;
- node.contour.lowerTail = this.createLine(
- 0, -node.width - dist);
- node.contour.lowerHead = this.createLine(
- node.height + dist, 0, node.contour.lowerTail);
-};
-
-/**
- * Function: join
- */
-mxCompactTreeLayout.prototype.join = function(node)
-{
- var dist = 2 * this.nodeDistance;
-
- var child = node.child;
- node.contour = child.contour;
- var h = child.width + dist;
- var sum = h;
- child = child.next;
-
- while (child != null)
- {
- var d = this.merge(node.contour, child.contour);
- child.offsetY = d + h;
- child.offsetX = 0;
- h = child.width + dist;
- sum += d + h;
- child = child.next;
- }
-
- return sum;
-};
-
-/**
- * Function: merge
- */
-mxCompactTreeLayout.prototype.merge = function(p1, p2)
-{
- var x = 0;
- var y = 0;
- var total = 0;
-
- var upper = p1.lowerHead;
- var lower = p2.upperHead;
-
- while (lower != null && upper != null)
- {
- var d = this.offset(x, y, lower.dx, lower.dy,
- upper.dx, upper.dy);
- y += d;
- total += d;
-
- if (x + lower.dx <= upper.dx)
- {
- x += lower.dx;
- y += lower.dy;
- lower = lower.next;
- }
- else
- {
- x -= upper.dx;
- y -= upper.dy;
- upper = upper.next;
- }
- }
-
- if (lower != null)
- {
- var b = this.bridge(p1.upperTail, 0, 0, lower, x, y);
- p1.upperTail = (b.next != null) ? p2.upperTail : b;
- p1.lowerTail = p2.lowerTail;
- }
- else
- {
- var b = this.bridge(p2.lowerTail, x, y, upper, 0, 0);
-
- if (b.next == null)
- {
- p1.lowerTail = b;
- }
- }
-
- p1.lowerHead = p2.lowerHead;
-
- return total;
-};
-
-/**
- * Function: offset
- */
-mxCompactTreeLayout.prototype.offset = function(p1, p2, a1, a2, b1, b2)
-{
- var d = 0;
-
- if (b1 <= p1 || p1 + a1 <= 0)
- {
- return 0;
- }
-
- var t = b1 * a2 - a1 * b2;
-
- if (t > 0)
- {
- if (p1 < 0)
- {
- var s = p1 * a2;
- d = s / a1 - p2;
- }
- else if (p1 > 0)
- {
- var s = p1 * b2;
- d = s / b1 - p2;
- }
- else
- {
- d = -p2;
- }
- }
- else if (b1 < p1 + a1)
- {
- var s = (b1 - p1) * a2;
- d = b2 - (p2 + s / a1);
- }
- else if (b1 > p1 + a1)
- {
- var s = (a1 + p1) * b2;
- d = s / b1 - (p2 + a2);
- }
- else
- {
- d = b2 - (p2 + a2);
- }
-
- if (d > 0)
- {
- return d;
- }
- else
- {
- return 0;
- }
-};
-
-/**
- * Function: bridge
- */
-mxCompactTreeLayout.prototype.bridge = function(line1, x1, y1, line2, x2, y2)
-{
- var dx = x2 + line2.dx - x1;
- var dy = 0;
- var s = 0;
-
- if (line2.dx == 0)
- {
- dy = line2.dy;
- }
- else
- {
- s = dx * line2.dy;
- dy = s / line2.dx;
- }
-
- var r = this.createLine(dx, dy, line2.next);
- line1.next = this.createLine(0, y2 + line2.dy - dy - y1, r);
-
- return r;
-};
-
-/**
- * Function: createNode
- */
-mxCompactTreeLayout.prototype.createNode = function(cell)
-{
- var node = new Object();
- node.cell = cell;
- node.x = 0;
- node.y = 0;
- node.width = 0;
- node.height = 0;
-
- var geo = this.getVertexBounds(cell);
-
- if (geo != null)
- {
- if (this.isHorizontal())
- {
- node.width = geo.height;
- node.height = geo.width;
- }
- else
- {
- node.width = geo.width;
- node.height = geo.height;
- }
- }
-
- node.offsetX = 0;
- node.offsetY = 0;
- node.contour = new Object();
-
- return node;
-};
-
-/**
- * Function: apply
- */
-mxCompactTreeLayout.prototype.apply = function(node, bounds)
-{
- var model = this.graph.getModel();
- var cell = node.cell;
- var g = model.getGeometry(cell);
-
- if (cell != null && g != null)
- {
- if (this.isVertexMovable(cell))
- {
- g = this.setVertexLocation(cell, node.x, node.y);
-
- if (this.resizeParent)
- {
- var parent = model.getParent(cell);
- var id = mxCellPath.create(parent);
-
- // Implements set semantic
- if (this.parentsChanged[id] == null)
- {
- this.parentsChanged[id] = parent;
- }
- }
- }
-
- if (bounds == null)
- {
- bounds = new mxRectangle(g.x, g.y, g.width, g.height);
- }
- else
- {
- bounds = new mxRectangle(Math.min(bounds.x, g.x),
- Math.min(bounds.y, g.y),
- Math.max(bounds.x + bounds.width, g.x + g.width),
- Math.max(bounds.y + bounds.height, g.y + g.height));
- }
- }
-
- return bounds;
-};
-
-/**
- * Function: createLine
- */
-mxCompactTreeLayout.prototype.createLine = function(dx, dy, next)
-{
- var line = new Object();
- line.dx = dx;
- line.dy = dy;
- line.next = next;
-
- return line;
-};
-
-/**
- * Function: adjustParents
- *
- * Adjust parent cells whose child geometries have changed. The default
- * implementation adjusts the group to just fit around the children with
- * a padding.
- */
-mxCompactTreeLayout.prototype.adjustParents = function()
-{
- var tmp = [];
-
- for (var id in this.parentsChanged)
- {
- tmp.push(this.parentsChanged[id]);
- }
-
- this.arrangeGroups(mxUtils.sortCells(tmp, true), this.groupPadding);
-};
-
-/**
- * Function: localEdgeProcessing
- *
- * Moves the specified node and all of its children by the given amount.
- */
-mxCompactTreeLayout.prototype.localEdgeProcessing = function(node)
-{
- this.processNodeOutgoing(node);
- var child = node.child;
-
- while (child != null)
- {
- this.localEdgeProcessing(child);
- child = child.next;
- }
-};
-
-/**
- * Function: localEdgeProcessing
- *
- * Separates the x position of edges as they connect to vertices
- */
-mxCompactTreeLayout.prototype.processNodeOutgoing = function(node)
-{
- var child = node.child;
- var parentCell = node.cell;
-
- var childCount = 0;
- var sortedCells = [];
-
- while (child != null)
- {
- childCount++;
-
- var sortingCriterion = child.x;
-
- if (this.horizontal)
- {
- sortingCriterion = child.y;
- }
-
- sortedCells.push(new WeightedCellSorter(child, sortingCriterion));
- child = child.next;
- }
-
- sortedCells.sort(WeightedCellSorter.prototype.compare);
-
- var availableWidth = node.width;
-
- var requiredWidth = (childCount + 1) * this.prefHozEdgeSep;
-
- // Add a buffer on the edges of the vertex if the edge count allows
- if (availableWidth > requiredWidth + (2 * this.prefHozEdgeSep))
- {
- availableWidth -= 2 * this.prefHozEdgeSep;
- }
-
- var edgeSpacing = availableWidth / childCount;
-
- var currentXOffset = edgeSpacing / 2.0;
-
- if (availableWidth > requiredWidth + (2 * this.prefHozEdgeSep))
- {
- currentXOffset += this.prefHozEdgeSep;
- }
-
- var currentYOffset = this.minEdgeJetty - this.prefVertEdgeOff;
- var maxYOffset = 0;
-
- var parentBounds = this.getVertexBounds(parentCell);
- child = node.child;
-
- for (var j = 0; j < sortedCells.length; j++)
- {
- var childCell = sortedCells[j].cell.cell;
- var childBounds = this.getVertexBounds(childCell);
-
- var edges = this.graph.getEdgesBetween(parentCell,
- childCell, false);
-
- var newPoints = [];
- var x = 0;
- var y = 0;
-
- for (var i = 0; i < edges.length; i++)
- {
- if (this.horizontal)
- {
- // Use opposite co-ords, calculation was done for
- //
- x = parentBounds.x + parentBounds.width;
- y = parentBounds.y + currentXOffset;
- newPoints.push(new mxPoint(x, y));
- x = parentBounds.x + parentBounds.width
- + currentYOffset;
- newPoints.push(new mxPoint(x, y));
- y = childBounds.y + childBounds.height / 2.0;
- newPoints.push(new mxPoint(x, y));
- this.setEdgePoints(edges[i], newPoints);
- }
- else
- {
- x = parentBounds.x + currentXOffset;
- y = parentBounds.y + parentBounds.height;
- newPoints.push(new mxPoint(x, y));
- y = parentBounds.y + parentBounds.height
- + currentYOffset;
- newPoints.push(new mxPoint(x, y));
- x = childBounds.x + childBounds.width / 2.0;
- newPoints.push(new mxPoint(x, y));
- this.setEdgePoints(edges[i], newPoints);
- }
- }
-
- if (j < childCount / 2)
- {
- currentYOffset += this.prefVertEdgeOff;
- }
- else if (j > childCount / 2)
- {
- currentYOffset -= this.prefVertEdgeOff;
- }
- // Ignore the case if equals, this means the second of 2
- // jettys with the same y (even number of edges)
-
- // pos[k * 2] = currentX;
- currentXOffset += edgeSpacing;
- // pos[k * 2 + 1] = currentYOffset;
-
- maxYOffset = Math.max(maxYOffset, currentYOffset);
- }
-};
-
-/**
- * Class: WeightedCellSorter
- *
- * A utility class used to track cells whilst sorting occurs on the weighted
- * sum of their connected edges. Does not violate (x.compareTo(y)==0) ==
- * (x.equals(y))
- *
- * Constructor: WeightedCellSorter
- *
- * Constructs a new weighted cell sorted for the given cell and weight.
- */
-function WeightedCellSorter(cell, weightedValue)
-{
- this.cell = cell;
- this.weightedValue = weightedValue;
-};
-
-/**
- * Variable: weightedValue
- *
- * The weighted value of the cell stored.
- */
-WeightedCellSorter.prototype.weightedValue = 0;
-
-/**
- * Variable: nudge
- *
- * Whether or not to flip equal weight values.
- */
-WeightedCellSorter.prototype.nudge = false;
-
-/**
- * Variable: visited
- *
- * Whether or not this cell has been visited in the current assignment.
- */
-WeightedCellSorter.prototype.visited = false;
-
-/**
- * Variable: rankIndex
- *
- * The index this cell is in the model rank.
- */
-WeightedCellSorter.prototype.rankIndex = null;
-
-/**
- * Variable: cell
- *
- * The cell whose median value is being calculated.
- */
-WeightedCellSorter.prototype.cell = null;
-
-/**
- * Function: compare
- *
- * Compares two WeightedCellSorters.
- */
-WeightedCellSorter.prototype.compare = function(a, b)
-{
- if (a != null && b != null)
- {
- if (b.weightedValue > a.weightedValue)
- {
- return 1;
- }
- else if (b.weightedValue < a.weightedValue)
- {
- return -1;
- }
- else
- {
- if (b.nudge)
- {
- return 1;
- }
- else
- {
- return -1;
- }
- }
- }
- else
- {
- return 0;
- }
-}; \ No newline at end of file
diff --git a/src/js/layout/mxCompositeLayout.js b/src/js/layout/mxCompositeLayout.js
deleted file mode 100644
index 2ceb5f5..0000000
--- a/src/js/layout/mxCompositeLayout.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * $Id: mxCompositeLayout.js,v 1.11 2010-01-02 09:45:15 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCompositeLayout
- *
- * Allows to compose multiple layouts into a single layout. The master layout
- * is the layout that handles move operations if another layout than the first
- * element in <layouts> should be used. The <master> layout is not executed as
- * the code assumes that it is part of <layouts>.
- *
- * Example:
- * (code)
- * var first = new mxFastOrganicLayout(graph);
- * var second = new mxParallelEdgeLayout(graph);
- * var layout = new mxCompositeLayout(graph, [first, second], first);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxCompositeLayout
- *
- * Constructs a new layout using the given layouts. The graph instance is
- * required for creating the transaction that contains all layouts.
- *
- * Arguments:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * layouts - Array of <mxGraphLayouts>.
- * master - Optional layout that handles moves. If no layout is given then
- * the first layout of the above array is used to handle moves.
- */
-function mxCompositeLayout(graph, layouts, master)
-{
- mxGraphLayout.call(this, graph);
- this.layouts = layouts;
- this.master = master;
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxCompositeLayout.prototype = new mxGraphLayout();
-mxCompositeLayout.prototype.constructor = mxCompositeLayout;
-
-/**
- * Variable: layouts
- *
- * Holds the array of <mxGraphLayouts> that this layout contains.
- */
-mxCompositeLayout.prototype.layouts = null;
-
-/**
- * Variable: layouts
- *
- * Reference to the <mxGraphLayouts> that handles moves. If this is null
- * then the first layout in <layouts> is used.
- */
-mxCompositeLayout.prototype.master = null;
-
-/**
- * Function: moveCell
- *
- * Implements <mxGraphLayout.moveCell> by calling move on <master> or the first
- * layout in <layouts>.
- */
-mxCompositeLayout.prototype.moveCell = function(cell, x, y)
-{
- if (this.master != null)
- {
- this.master.move.apply(this.master, arguments);
- }
- else
- {
- this.layouts[0].move.apply(this.layouts[0], arguments);
- }
-};
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute> by executing all <layouts> in a
- * single transaction.
- */
-mxCompositeLayout.prototype.execute = function(parent)
-{
- var model = this.graph.getModel();
-
- model.beginUpdate();
- try
- {
- for (var i = 0; i < this.layouts.length; i++)
- {
- this.layouts[i].execute.apply(this.layouts[i], arguments);
- }
- }
- finally
- {
- model.endUpdate();
- }
-};
diff --git a/src/js/layout/mxEdgeLabelLayout.js b/src/js/layout/mxEdgeLabelLayout.js
deleted file mode 100644
index 2bfb3c2..0000000
--- a/src/js/layout/mxEdgeLabelLayout.js
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * $Id: mxEdgeLabelLayout.js,v 1.8 2010-01-04 11:18:25 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxEdgeLabelLayout
- *
- * Extends <mxGraphLayout> to implement an edge label layout. This layout
- * makes use of cell states, which means the graph must be validated in
- * a graph view (so that the label bounds are available) before this layout
- * can be executed.
- *
- * Example:
- *
- * (code)
- * var layout = new mxEdgeLabelLayout(graph);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxEdgeLabelLayout
- *
- * Constructs a new edge label layout.
- *
- * Arguments:
- *
- * graph - <mxGraph> that contains the cells.
- */
-function mxEdgeLabelLayout(graph, radius)
-{
- mxGraphLayout.call(this, graph);
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxEdgeLabelLayout.prototype = new mxGraphLayout();
-mxEdgeLabelLayout.prototype.constructor = mxEdgeLabelLayout;
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>.
- */
-mxEdgeLabelLayout.prototype.execute = function(parent)
-{
- var view = this.graph.view;
- var model = this.graph.getModel();
-
- // Gets all vertices and edges inside the parent
- var edges = [];
- var vertices = [];
- var childCount = model.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var cell = model.getChildAt(parent, i);
- var state = view.getState(cell);
-
- if (state != null)
- {
- if (!this.isVertexIgnored(cell))
- {
- vertices.push(state);
- }
- else if (!this.isEdgeIgnored(cell))
- {
- edges.push(state);
- }
- }
- }
-
- this.placeLabels(vertices, edges);
-};
-
-/**
- * Function: placeLabels
- *
- * Places the labels of the given edges.
- */
-mxEdgeLabelLayout.prototype.placeLabels = function(v, e)
-{
- var model = this.graph.getModel();
-
- // Moves the vertices to build a circle. Makes sure the
- // radius is large enough for the vertices to not
- // overlap
- model.beginUpdate();
- try
- {
- for (var i = 0; i < e.length; i++)
- {
- var edge = e[i];
-
- if (edge != null && edge.text != null &&
- edge.text.boundingBox != null)
- {
- for (var j = 0; j < v.length; j++)
- {
- var vertex = v[j];
-
- if (vertex != null)
- {
- this.avoid(edge, vertex);
- }
- }
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
-};
-
-/**
- * Function: avoid
- *
- * Places the labels of the given edges.
- */
-mxEdgeLabelLayout.prototype.avoid = function(edge, vertex)
-{
- var model = this.graph.getModel();
- var labRect = edge.text.boundingBox;
-
- if (mxUtils.intersects(labRect, vertex))
- {
- var dy1 = -labRect.y - labRect.height + vertex.y;
- var dy2 = -labRect.y + vertex.y + vertex.height;
-
- var dy = (Math.abs(dy1) < Math.abs(dy2)) ? dy1 : dy2;
-
- var dx1 = -labRect.x - labRect.width + vertex.x;
- var dx2 = -labRect.x + vertex.x + vertex.width;
-
- var dx = (Math.abs(dx1) < Math.abs(dx2)) ? dx1 : dx2;
-
- if (Math.abs(dx) < Math.abs(dy))
- {
- dy = 0;
- }
- else
- {
- dx = 0;
- }
-
- var g = model.getGeometry(edge.cell);
-
- if (g != null)
- {
- g = g.clone();
-
- if (g.offset != null)
- {
- g.offset.x += dx;
- g.offset.y += dy;
- }
- else
- {
- g.offset = new mxPoint(dx, dy);
- }
-
- model.setGeometry(edge.cell, g);
- }
- }
-};
diff --git a/src/js/layout/mxFastOrganicLayout.js b/src/js/layout/mxFastOrganicLayout.js
deleted file mode 100644
index d7d6b5d..0000000
--- a/src/js/layout/mxFastOrganicLayout.js
+++ /dev/null
@@ -1,591 +0,0 @@
-/**
- * $Id: mxFastOrganicLayout.js,v 1.37 2011-04-28 13:14:55 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxFastOrganicLayout
- *
- * Extends <mxGraphLayout> to implement a fast organic layout algorithm.
- * The vertices need to be connected for this layout to work, vertices
- * with no connections are ignored.
- *
- * Example:
- *
- * (code)
- * var layout = new mxFastOrganicLayout(graph);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxCompactTreeLayout
- *
- * Constructs a new fast organic layout for the specified graph.
- */
-function mxFastOrganicLayout(graph)
-{
- mxGraphLayout.call(this, graph);
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxFastOrganicLayout.prototype = new mxGraphLayout();
-mxFastOrganicLayout.prototype.constructor = mxFastOrganicLayout;
-
-/**
- * Variable: useInputOrigin
- *
- * Specifies if the top left corner of the input cells should be the origin
- * of the layout result. Default is true.
- */
-mxFastOrganicLayout.prototype.useInputOrigin = true;
-
-/**
- * Variable: resetEdges
- *
- * Specifies if all edge points of traversed edges should be removed.
- * Default is true.
- */
-mxFastOrganicLayout.prototype.resetEdges = true;
-
-/**
- * Variable: disableEdgeStyle
- *
- * Specifies if the STYLE_NOEDGESTYLE flag should be set on edges that are
- * modified by the result. Default is true.
- */
-mxFastOrganicLayout.prototype.disableEdgeStyle = true;
-
-/**
- * Variable: forceConstant
- *
- * The force constant by which the attractive forces are divided and the
- * replusive forces are multiple by the square of. The value equates to the
- * average radius there is of free space around each node. Default is 50.
- */
-mxFastOrganicLayout.prototype.forceConstant = 50;
-
-/**
- * Variable: forceConstantSquared
- *
- * Cache of <forceConstant>^2 for performance.
- */
-mxFastOrganicLayout.prototype.forceConstantSquared = 0;
-
-/**
- * Variable: minDistanceLimit
- *
- * Minimal distance limit. Default is 2. Prevents of
- * dividing by zero.
- */
-mxFastOrganicLayout.prototype.minDistanceLimit = 2;
-
-/**
- * Variable: minDistanceLimit
- *
- * Minimal distance limit. Default is 2. Prevents of
- * dividing by zero.
- */
-mxFastOrganicLayout.prototype.maxDistanceLimit = 500;
-
-/**
- * Variable: minDistanceLimitSquared
- *
- * Cached version of <minDistanceLimit> squared.
- */
-mxFastOrganicLayout.prototype.minDistanceLimitSquared = 4;
-
-/**
- * Variable: initialTemp
- *
- * Start value of temperature. Default is 200.
- */
-mxFastOrganicLayout.prototype.initialTemp = 200;
-
-/**
- * Variable: temperature
- *
- * Temperature to limit displacement at later stages of layout.
- */
-mxFastOrganicLayout.prototype.temperature = 0;
-
-/**
- * Variable: maxIterations
- *
- * Total number of iterations to run the layout though.
- */
-mxFastOrganicLayout.prototype.maxIterations = 0;
-
-/**
- * Variable: iteration
- *
- * Current iteration count.
- */
-mxFastOrganicLayout.prototype.iteration = 0;
-
-/**
- * Variable: vertexArray
- *
- * An array of all vertices to be laid out.
- */
-mxFastOrganicLayout.prototype.vertexArray;
-
-/**
- * Variable: dispX
- *
- * An array of locally stored X co-ordinate displacements for the vertices.
- */
-mxFastOrganicLayout.prototype.dispX;
-
-/**
- * Variable: dispY
- *
- * An array of locally stored Y co-ordinate displacements for the vertices.
- */
-mxFastOrganicLayout.prototype.dispY;
-
-/**
- * Variable: cellLocation
- *
- * An array of locally stored co-ordinate positions for the vertices.
- */
-mxFastOrganicLayout.prototype.cellLocation;
-
-/**
- * Variable: radius
- *
- * The approximate radius of each cell, nodes only.
- */
-mxFastOrganicLayout.prototype.radius;
-
-/**
- * Variable: radiusSquared
- *
- * The approximate radius squared of each cell, nodes only.
- */
-mxFastOrganicLayout.prototype.radiusSquared;
-
-/**
- * Variable: isMoveable
- *
- * Array of booleans representing the movable states of the vertices.
- */
-mxFastOrganicLayout.prototype.isMoveable;
-
-/**
- * Variable: neighbours
- *
- * Local copy of cell neighbours.
- */
-mxFastOrganicLayout.prototype.neighbours;
-
-/**
- * Variable: indices
- *
- * Hashtable from cells to local indices.
- */
-mxFastOrganicLayout.prototype.indices;
-
-/**
- * Variable: allowedToRun
- *
- * Boolean flag that specifies if the layout is allowed to run. If this is
- * set to false, then the layout exits in the following iteration.
- */
-mxFastOrganicLayout.prototype.allowedToRun = true;
-
-/**
- * Function: isVertexIgnored
- *
- * Returns a boolean indicating if the given <mxCell> should be ignored as a
- * vertex. This returns true if the cell has no connections.
- *
- * Parameters:
- *
- * vertex - <mxCell> whose ignored state should be returned.
- */
-mxFastOrganicLayout.prototype.isVertexIgnored = function(vertex)
-{
- return mxGraphLayout.prototype.isVertexIgnored.apply(this, arguments) ||
- this.graph.getConnections(vertex).length == 0;
-};
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>. This operates on all children of the
- * given parent where <isVertexIgnored> returns false.
- */
-mxFastOrganicLayout.prototype.execute = function(parent)
-{
- var model = this.graph.getModel();
- this.vertexArray = [];
- var cells = this.graph.getChildVertices(parent);
-
- for (var i = 0; i < cells.length; i++)
- {
- if (!this.isVertexIgnored(cells[i]))
- {
- this.vertexArray.push(cells[i]);
- }
- }
-
- var initialBounds = (this.useInputOrigin) ?
- this.graph.view.getBounds(this.vertexArray) :
- null;
- var n = this.vertexArray.length;
-
- this.indices = [];
- this.dispX = [];
- this.dispY = [];
- this.cellLocation = [];
- this.isMoveable = [];
- this.neighbours = [];
- this.radius = [];
- this.radiusSquared = [];
-
- if (this.forceConstant < 0.001)
- {
- this.forceConstant = 0.001;
- }
-
- this.forceConstantSquared = this.forceConstant * this.forceConstant;
-
- // Create a map of vertices first. This is required for the array of
- // arrays called neighbours which holds, for each vertex, a list of
- // ints which represents the neighbours cells to that vertex as
- // the indices into vertexArray
- for (var i = 0; i < this.vertexArray.length; i++)
- {
- var vertex = this.vertexArray[i];
- this.cellLocation[i] = [];
-
- // Set up the mapping from array indices to cells
- var id = mxCellPath.create(vertex);
- this.indices[id] = i;
- var bounds = this.getVertexBounds(vertex);
-
- // Set the X,Y value of the internal version of the cell to
- // the center point of the vertex for better positioning
- var width = bounds.width;
- var height = bounds.height;
-
- // Randomize (0, 0) locations
- var x = bounds.x;
- var y = bounds.y;
-
- this.cellLocation[i][0] = x + width / 2.0;
- this.cellLocation[i][1] = y + height / 2.0;
- this.radius[i] = Math.min(width, height);
- this.radiusSquared[i] = this.radius[i] * this.radius[i];
- }
-
- // Moves cell location back to top-left from center locations used in
- // algorithm, resetting the edge points is part of the transaction
- model.beginUpdate();
- try
- {
- for (var i = 0; i < n; i++)
- {
- this.dispX[i] = 0;
- this.dispY[i] = 0;
- this.isMoveable[i] = this.isVertexMovable(this.vertexArray[i]);
-
- // Get lists of neighbours to all vertices, translate the cells
- // obtained in indices into vertexArray and store as an array
- // against the orginial cell index
- var edges = this.graph.getConnections(this.vertexArray[i], parent);
- var cells = this.graph.getOpposites(edges, this.vertexArray[i]);
- this.neighbours[i] = [];
-
- for (var j = 0; j < cells.length; j++)
- {
- // Resets the points on the traversed edge
- if (this.resetEdges)
- {
- this.graph.resetEdge(edges[j]);
- }
-
- if (this.disableEdgeStyle)
- {
- this.setEdgeStyleEnabled(edges[j], false);
- }
-
- // Looks the cell up in the indices dictionary
- var id = mxCellPath.create(cells[j]);
- var index = this.indices[id];
-
- // Check the connected cell in part of the vertex list to be
- // acted on by this layout
- if (index != null)
- {
- this.neighbours[i][j] = index;
- }
-
- // Else if index of the other cell doesn't correspond to
- // any cell listed to be acted upon in this layout. Set
- // the index to the value of this vertex (a dummy self-loop)
- // so the attraction force of the edge is not calculated
- else
- {
- this.neighbours[i][j] = i;
- }
- }
- }
- this.temperature = this.initialTemp;
-
- // If max number of iterations has not been set, guess it
- if (this.maxIterations == 0)
- {
- this.maxIterations = 20 * Math.sqrt(n);
- }
-
- // Main iteration loop
- for (this.iteration = 0; this.iteration < this.maxIterations; this.iteration++)
- {
- if (!this.allowedToRun)
- {
- return;
- }
-
- // Calculate repulsive forces on all vertices
- this.calcRepulsion();
-
- // Calculate attractive forces through edges
- this.calcAttraction();
-
- this.calcPositions();
- this.reduceTemperature();
- }
-
- var minx = null;
- var miny = null;
-
- for (var i = 0; i < this.vertexArray.length; i++)
- {
- var vertex = this.vertexArray[i];
-
- if (this.isVertexMovable(vertex))
- {
- var bounds = this.getVertexBounds(vertex);
-
- if (bounds != null)
- {
- this.cellLocation[i][0] -= bounds.width / 2.0;
- this.cellLocation[i][1] -= bounds.height / 2.0;
-
- var x = this.graph.snap(this.cellLocation[i][0]);
- var y = this.graph.snap(this.cellLocation[i][1]);
-
- this.setVertexLocation(vertex, x, y);
-
- if (minx == null)
- {
- minx = x;
- }
- else
- {
- minx = Math.min(minx, x);
- }
-
- if (miny == null)
- {
- miny = y;
- }
- else
- {
- miny = Math.min(miny, y);
- }
- }
- }
- }
-
- // Modifies the cloned geometries in-place. Not needed
- // to clone the geometries again as we're in the same
- // undoable change.
- var dx = -(minx || 0) + 1;
- var dy = -(miny || 0) + 1;
-
- if (initialBounds != null)
- {
- dx += initialBounds.x;
- dy += initialBounds.y;
- }
-
- this.graph.moveCells(this.vertexArray, dx, dy);
- }
- finally
- {
- model.endUpdate();
- }
-};
-
-/**
- * Function: calcPositions
- *
- * Takes the displacements calculated for each cell and applies them to the
- * local cache of cell positions. Limits the displacement to the current
- * temperature.
- */
-mxFastOrganicLayout.prototype.calcPositions = function()
-{
- for (var index = 0; index < this.vertexArray.length; index++)
- {
- if (this.isMoveable[index])
- {
- // Get the distance of displacement for this node for this
- // iteration
- var deltaLength = Math.sqrt(this.dispX[index] * this.dispX[index] +
- this.dispY[index] * this.dispY[index]);
-
- if (deltaLength < 0.001)
- {
- deltaLength = 0.001;
- }
-
- // Scale down by the current temperature if less than the
- // displacement distance
- var newXDisp = this.dispX[index] / deltaLength
- * Math.min(deltaLength, this.temperature);
-
- var newYDisp = this.dispY[index] / deltaLength
- * Math.min(deltaLength, this.temperature);
-
- // reset displacements
- this.dispX[index] = 0;
- this.dispY[index] = 0;
-
- // Update the cached cell locations
- this.cellLocation[index][0] += newXDisp;
- this.cellLocation[index][1] += newYDisp;
- }
- }
-};
-
-/**
- * Function: calcAttraction
- *
- * Calculates the attractive forces between all laid out nodes linked by
- * edges
- */
-mxFastOrganicLayout.prototype.calcAttraction = function()
-{
- // Check the neighbours of each vertex and calculate the attractive
- // force of the edge connecting them
- for (var i = 0; i < this.vertexArray.length; i++)
- {
- for (var k = 0; k < this.neighbours[i].length; k++)
- {
- // Get the index of the othe cell in the vertex array
- var j = this.neighbours[i][k];
-
- // Do not proceed self-loops
- if (i != j &&
- this.isMoveable[i] &&
- this.isMoveable[j])
- {
- var xDelta = this.cellLocation[i][0] - this.cellLocation[j][0];
- var yDelta = this.cellLocation[i][1] - this.cellLocation[j][1];
-
- // The distance between the nodes
- var deltaLengthSquared = xDelta * xDelta + yDelta
- * yDelta - this.radiusSquared[i] - this.radiusSquared[j];
-
- if (deltaLengthSquared < this.minDistanceLimitSquared)
- {
- deltaLengthSquared = this.minDistanceLimitSquared;
- }
-
- var deltaLength = Math.sqrt(deltaLengthSquared);
- var force = (deltaLengthSquared) / this.forceConstant;
-
- var displacementX = (xDelta / deltaLength) * force;
- var displacementY = (yDelta / deltaLength) * force;
-
- this.dispX[i] -= displacementX;
- this.dispY[i] -= displacementY;
-
- this.dispX[j] += displacementX;
- this.dispY[j] += displacementY;
- }
- }
- }
-};
-
-/**
- * Function: calcRepulsion
- *
- * Calculates the repulsive forces between all laid out nodes
- */
-mxFastOrganicLayout.prototype.calcRepulsion = function()
-{
- var vertexCount = this.vertexArray.length;
-
- for (var i = 0; i < vertexCount; i++)
- {
- for (var j = i; j < vertexCount; j++)
- {
- // Exits if the layout is no longer allowed to run
- if (!this.allowedToRun)
- {
- return;
- }
-
- if (j != i &&
- this.isMoveable[i] &&
- this.isMoveable[j])
- {
- var xDelta = this.cellLocation[i][0] - this.cellLocation[j][0];
- var yDelta = this.cellLocation[i][1] - this.cellLocation[j][1];
-
- if (xDelta == 0)
- {
- xDelta = 0.01 + Math.random();
- }
-
- if (yDelta == 0)
- {
- yDelta = 0.01 + Math.random();
- }
-
- // Distance between nodes
- var deltaLength = Math.sqrt((xDelta * xDelta)
- + (yDelta * yDelta));
- var deltaLengthWithRadius = deltaLength - this.radius[i]
- - this.radius[j];
-
- if (deltaLengthWithRadius > this.maxDistanceLimit)
- {
- // Ignore vertices too far apart
- continue;
- }
-
- if (deltaLengthWithRadius < this.minDistanceLimit)
- {
- deltaLengthWithRadius = this.minDistanceLimit;
- }
-
- var force = this.forceConstantSquared / deltaLengthWithRadius;
-
- var displacementX = (xDelta / deltaLength) * force;
- var displacementY = (yDelta / deltaLength) * force;
-
- this.dispX[i] += displacementX;
- this.dispY[i] += displacementY;
-
- this.dispX[j] -= displacementX;
- this.dispY[j] -= displacementY;
- }
- }
- }
-};
-
-/**
- * Function: reduceTemperature
- *
- * Reduces the temperature of the layout from an initial setting in a linear
- * fashion to zero.
- */
-mxFastOrganicLayout.prototype.reduceTemperature = function()
-{
- this.temperature = this.initialTemp * (1.0 - this.iteration / this.maxIterations);
-};
diff --git a/src/js/layout/mxGraphLayout.js b/src/js/layout/mxGraphLayout.js
deleted file mode 100644
index c9f5f32..0000000
--- a/src/js/layout/mxGraphLayout.js
+++ /dev/null
@@ -1,503 +0,0 @@
-/**
- * $Id: mxGraphLayout.js,v 1.48 2012-08-21 17:22:21 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraphLayout
- *
- * Base class for all layout algorithms in mxGraph. Main public functions are
- * <move> for handling a moved cell within a layouted parent, and <execute> for
- * running the layout on a given parent cell.
- *
- * Known Subclasses:
- *
- * <mxCircleLayout>, <mxCompactTreeLayout>, <mxCompositeLayout>,
- * <mxFastOrganicLayout>, <mxParallelEdgeLayout>, <mxPartitionLayout>,
- * <mxStackLayout>
- *
- * Constructor: mxGraphLayout
- *
- * Constructs a new layout using the given layouts.
- *
- * Arguments:
- *
- * graph - Enclosing
- */
-function mxGraphLayout(graph)
-{
- this.graph = graph;
-};
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxGraphLayout.prototype.graph = null;
-
-/**
- * Variable: useBoundingBox
- *
- * Boolean indicating if the bounding box of the label should be used if
- * its available. Default is true.
- */
-mxGraphLayout.prototype.useBoundingBox = true;
-
-/**
- * Variable: parent
- *
- * The parent cell of the layout, if any
- */
-mxGraphLayout.prototype.parent = null;
-
-/**
- * Function: moveCell
- *
- * Notified when a cell is being moved in a parent that has automatic
- * layout to update the cell state (eg. index) so that the outcome of the
- * layout will position the vertex as close to the point (x, y) as
- * possible.
- *
- * Empty implementation.
- *
- * Parameters:
- *
- * cell - <mxCell> which has been moved.
- * x - X-coordinate of the new cell location.
- * y - Y-coordinate of the new cell location.
- */
-mxGraphLayout.prototype.moveCell = function(cell, x, y) { };
-
-/**
- * Function: execute
- *
- * Executes the layout algorithm for the children of the given parent.
- *
- * Parameters:
- *
- * parent - <mxCell> whose children should be layed out.
- */
-mxGraphLayout.prototype.execute = function(parent) { };
-
-/**
- * Function: getGraph
- *
- * Returns the graph that this layout operates on.
- */
-mxGraphLayout.prototype.getGraph = function()
-{
- return this.graph;
-};
-
-/**
- * Function: getConstraint
- *
- * Returns the constraint for the given key and cell. The optional edge and
- * source arguments are used to return inbound and outgoing routing-
- * constraints for the given edge and vertex. This implementation always
- * returns the value for the given key in the style of the given cell.
- *
- * Parameters:
- *
- * key - Key of the constraint to be returned.
- * cell - <mxCell> whose constraint should be returned.
- * edge - Optional <mxCell> that represents the connection whose constraint
- * should be returned. Default is null.
- * source - Optional boolean that specifies if the connection is incoming
- * or outgoing. Default is null.
- */
-mxGraphLayout.prototype.getConstraint = function(key, cell, edge, source)
-{
- var state = this.graph.view.getState(cell);
- var style = (state != null) ? state.style : this.graph.getCellStyle(cell);
-
- return (style != null) ? style[key] : null;
-};
-
-/**
- * Function: traverse
- *
- * Traverses the (directed) graph invoking the given function for each
- * visited vertex and edge. The function is invoked with the current vertex
- * and the incoming edge as a parameter. This implementation makes sure
- * each vertex is only visited once. The function may return false if the
- * traversal should stop at the given vertex.
- *
- * Example:
- *
- * (code)
- * mxLog.show();
- * var cell = graph.getSelectionCell();
- * graph.traverse(cell, false, function(vertex, edge)
- * {
- * mxLog.debug(graph.getLabel(vertex));
- * });
- * (end)
- *
- * Parameters:
- *
- * vertex - <mxCell> that represents the vertex where the traversal starts.
- * directed - Optional boolean indicating if edges should only be traversed
- * from source to target. Default is true.
- * func - Visitor function that takes the current vertex and the incoming
- * edge as arguments. The traversal stops if the function returns false.
- * edge - Optional <mxCell> that represents the incoming edge. This is
- * null for the first step of the traversal.
- * visited - Optional array of cell paths for the visited cells.
- */
-mxGraphLayout.traverse = function(vertex, directed, func, edge, visited)
-{
- if (func != null && vertex != null)
- {
- directed = (directed != null) ? directed : true;
- visited = visited || [];
- var id = mxCellPath.create(vertex);
-
- if (visited[id] == null)
- {
- visited[id] = vertex;
- var result = func(vertex, edge);
-
- if (result == null || result)
- {
- var edgeCount = this.graph.model.getEdgeCount(vertex);
-
- if (edgeCount > 0)
- {
- for (var i = 0; i < edgeCount; i++)
- {
- var e = this.graph.model.getEdgeAt(vertex, i);
- var isSource = this.graph.model.getTerminal(e, true) == vertex;
-
- if (!directed || isSource)
- {
- var next = this.graph.view.getVisibleTerminal(e, !isSource);
- this.traverse(next, directed, func, e, visited);
- }
- }
- }
- }
- }
- }
-};
-
-/**
- * Function: isVertexMovable
- *
- * Returns a boolean indicating if the given <mxCell> is movable or
- * bendable by the algorithm. This implementation returns true if the given
- * cell is movable in the graph.
- *
- * Parameters:
- *
- * cell - <mxCell> whose movable state should be returned.
- */
-mxGraphLayout.prototype.isVertexMovable = function(cell)
-{
- return this.graph.isCellMovable(cell);
-};
-
-/**
- * Function: isVertexIgnored
- *
- * Returns a boolean indicating if the given <mxCell> should be ignored by
- * the algorithm. This implementation returns false for all vertices.
- *
- * Parameters:
- *
- * vertex - <mxCell> whose ignored state should be returned.
- */
-mxGraphLayout.prototype.isVertexIgnored = function(vertex)
-{
- return !this.graph.getModel().isVertex(vertex) ||
- !this.graph.isCellVisible(vertex);
-};
-
-/**
- * Function: isEdgeIgnored
- *
- * Returns a boolean indicating if the given <mxCell> should be ignored by
- * the algorithm. This implementation returns false for all vertices.
- *
- * Parameters:
- *
- * cell - <mxCell> whose ignored state should be returned.
- */
-mxGraphLayout.prototype.isEdgeIgnored = function(edge)
-{
- var model = this.graph.getModel();
-
- return !model.isEdge(edge) ||
- !this.graph.isCellVisible(edge) ||
- model.getTerminal(edge, true) == null ||
- model.getTerminal(edge, false) == null;
-};
-
-/**
- * Function: setEdgeStyleEnabled
- *
- * Disables or enables the edge style of the given edge.
- */
-mxGraphLayout.prototype.setEdgeStyleEnabled = function(edge, value)
-{
- this.graph.setCellStyles(mxConstants.STYLE_NOEDGESTYLE,
- (value) ? '0' : '1', [edge]);
-};
-
-/**
- * Function: setOrthogonalEdge
- *
- * Disables or enables orthogonal end segments of the given edge.
- */
-mxGraphLayout.prototype.setOrthogonalEdge = function(edge, value)
-{
- this.graph.setCellStyles(mxConstants.STYLE_ORTHOGONAL,
- (value) ? '1' : '0', [edge]);
-};
-
-/**
- * Function: getParentOffset
- *
- * Determines the offset of the given parent to the parent
- * of the layout
- */
-mxGraphLayout.prototype.getParentOffset = function(parent)
-{
- var result = new mxPoint();
-
- if (parent != null && parent != this.parent)
- {
- var model = this.graph.getModel();
-
- if (model.isAncestor(this.parent, parent))
- {
- var parentGeo = model.getGeometry(parent);
-
- while (parent != this.parent)
- {
- result.x = result.x + parentGeo.x;
- result.y = result.y + parentGeo.y;
-
- parent = model.getParent(parent);;
- parentGeo = model.getGeometry(parent);
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: setEdgePoints
- *
- * Replaces the array of mxPoints in the geometry of the given edge
- * with the given array of mxPoints.
- */
-mxGraphLayout.prototype.setEdgePoints = function(edge, points)
-{
- if (edge != null)
- {
- var model = this.graph.model;
- var geometry = model.getGeometry(edge);
-
- if (geometry == null)
- {
- geometry = new mxGeometry();
- geometry.setRelative(true);
- }
- else
- {
- geometry = geometry.clone();
- }
-
- if (this.parent != null && points != null)
- {
- var parent = model.getParent(edge);
-
- var parentOffset = this.getParentOffset(parent);
-
- for (var i = 0; i < points.length; i++)
- {
- points[i].x = points[i].x - parentOffset.x;
- points[i].y = points[i].y - parentOffset.y;
- }
- }
-
- geometry.points = points;
- model.setGeometry(edge, geometry);
- }
-};
-
-/**
- * Function: setVertexLocation
- *
- * Sets the new position of the given cell taking into account the size of
- * the bounding box if <useBoundingBox> is true. The change is only carried
- * out if the new location is not equal to the existing location, otherwise
- * the geometry is not replaced with an updated instance. The new or old
- * bounds are returned (including overlapping labels).
- *
- * Parameters:
- *
- * cell - <mxCell> whose geometry is to be set.
- * x - Integer that defines the x-coordinate of the new location.
- * y - Integer that defines the y-coordinate of the new location.
- */
-mxGraphLayout.prototype.setVertexLocation = function(cell, x, y)
-{
- var model = this.graph.getModel();
- var geometry = model.getGeometry(cell);
- var result = null;
-
- if (geometry != null)
- {
- result = new mxRectangle(x, y, geometry.width, geometry.height);
-
- // Checks for oversize labels and shifts the result
- // TODO: Use mxUtils.getStringSize for label bounds
- if (this.useBoundingBox)
- {
- var state = this.graph.getView().getState(cell);
-
- if (state != null && state.text != null && state.text.boundingBox != null)
- {
- var scale = this.graph.getView().scale;
- var box = state.text.boundingBox;
-
- if (state.text.boundingBox.x < state.x)
- {
- x += (state.x - box.x) / scale;
- result.width = box.width;
- }
-
- if (state.text.boundingBox.y < state.y)
- {
- y += (state.y - box.y) / scale;
- result.height = box.height;
- }
- }
- }
-
- if (this.parent != null)
- {
- var parent = model.getParent(cell);
-
- if (parent != null && parent != this.parent)
- {
- var parentOffset = this.getParentOffset(parent);
-
- x = x - parentOffset.x;
- y = y - parentOffset.y;
- }
- }
-
- if (geometry.x != x || geometry.y != y)
- {
- geometry = geometry.clone();
- geometry.x = x;
- geometry.y = y;
-
- model.setGeometry(cell, geometry);
- }
- }
-
- return result;
-};
-
-/**
- * Function: getVertexBounds
- *
- * Returns an <mxRectangle> that defines the bounds of the given cell or
- * the bounding box if <useBoundingBox> is true.
- */
-mxGraphLayout.prototype.getVertexBounds = function(cell)
-{
- var geo = this.graph.getModel().getGeometry(cell);
-
- // Checks for oversize label bounding box and corrects
- // the return value accordingly
- // TODO: Use mxUtils.getStringSize for label bounds
- if (this.useBoundingBox)
- {
- var state = this.graph.getView().getState(cell);
-
- if (state != null && state.text != null && state.text.boundingBox != null)
- {
- var scale = this.graph.getView().scale;
- var tmp = state.text.boundingBox;
-
- var dx0 = Math.max(state.x - tmp.x, 0) / scale;
- var dy0 = Math.max(state.y - tmp.y, 0) / scale;
- var dx1 = Math.max((tmp.x + tmp.width) - (state.x + state.width), 0) / scale;
- var dy1 = Math.max((tmp.y + tmp.height) - (state.y + state.height), 0) / scale;
-
- geo = new mxRectangle(geo.x - dx0, geo.y - dy0,
- geo.width + dx0 + dx1, geo.height + dy0 + dy1);
- }
- }
-
- if (this.parent != null)
- {
- var parent = this.graph.getModel().getParent(cell);
- geo = geo.clone();
-
- if (parent != null && parent != this.parent)
- {
- var parentOffset = this.getParentOffset(parent);
- geo.x = geo.x + parentOffset.x;
- geo.y = geo.y + parentOffset.y;
- }
- }
-
- return new mxRectangle(geo.x, geo.y, geo.width, geo.height);
-};
-
-/**
- * Function: arrangeGroups
- *
- * Updates the bounds of the given groups to include all children. Call
- * this with the groups in parent to child order, top-most group first, eg.
- *
- * arrangeGroups(graph, mxUtils.sortCells(Arrays.asList(
- * new Object[] { v1, v3 }), true).toArray(), 10);
- */
-mxGraphLayout.prototype.arrangeGroups = function(groups, border)
-{
- this.graph.getModel().beginUpdate();
- try
- {
- for (var i = groups.length - 1; i >= 0; i--)
- {
- var group = groups[i];
- var children = this.graph.getChildVertices(group);
- var bounds = this.graph.getBoundingBoxFromGeometry(children);
- var geometry = this.graph.getCellGeometry(group);
- var left = 0;
- var top = 0;
-
- // Adds the size of the title area for swimlanes
- if (this.graph.isSwimlane(group))
- {
- var size = this.graph.getStartSize(group);
- left = size.width;
- top = size.height;
- }
-
- if (bounds != null && geometry != null)
- {
- geometry = geometry.clone();
- geometry.x = geometry.x + bounds.x - border - left;
- geometry.y = geometry.y + bounds.y - border - top;
- geometry.width = bounds.width + 2 * border + left;
- geometry.height = bounds.height + 2 * border + top;
- this.graph.getModel().setGeometry(group, geometry);
- this.graph.moveCells(children, border + left - bounds.x,
- border + top - bounds.y);
- }
- }
- }
- finally
- {
- this.graph.getModel().endUpdate();
- }
-};
diff --git a/src/js/layout/mxParallelEdgeLayout.js b/src/js/layout/mxParallelEdgeLayout.js
deleted file mode 100644
index e1ad57c..0000000
--- a/src/js/layout/mxParallelEdgeLayout.js
+++ /dev/null
@@ -1,198 +0,0 @@
-/**
- * $Id: mxParallelEdgeLayout.js,v 1.24 2012-03-27 15:03:34 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxParallelEdgeLayout
- *
- * Extends <mxGraphLayout> for arranging parallel edges. This layout works
- * on edges for all pairs of vertices where there is more than one edge
- * connecting the latter.
- *
- * Example:
- *
- * (code)
- * var layout = new mxParallelEdgeLayout(graph);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxCompactTreeLayout
- *
- * Constructs a new fast organic layout for the specified graph.
- */
-function mxParallelEdgeLayout(graph)
-{
- mxGraphLayout.call(this, graph);
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxParallelEdgeLayout.prototype = new mxGraphLayout();
-mxParallelEdgeLayout.prototype.constructor = mxParallelEdgeLayout;
-
-/**
- * Variable: spacing
- *
- * Defines the spacing between the parallels. Default is 20.
- */
-mxParallelEdgeLayout.prototype.spacing = 20;
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>.
- */
-mxParallelEdgeLayout.prototype.execute = function(parent)
-{
- var lookup = this.findParallels(parent);
-
- this.graph.model.beginUpdate();
- try
- {
- for (var i in lookup)
- {
- var parallels = lookup[i];
-
- if (parallels.length > 1)
- {
- this.layout(parallels);
- }
- }
- }
- finally
- {
- this.graph.model.endUpdate();
- }
-};
-
-/**
- * Function: findParallels
- *
- * Finds the parallel edges in the given parent.
- */
-mxParallelEdgeLayout.prototype.findParallels = function(parent)
-{
- var model = this.graph.getModel();
- var lookup = [];
- var childCount = model.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(parent, i);
-
- if (!this.isEdgeIgnored(child))
- {
- var id = this.getEdgeId(child);
-
- if (id != null)
- {
- if (lookup[id] == null)
- {
- lookup[id] = [];
- }
-
- lookup[id].push(child);
- }
- }
- }
-
- return lookup;
-};
-
-/**
- * Function: getEdgeId
- *
- * Returns a unique ID for the given edge. The id is independent of the
- * edge direction and is built using the visible terminal of the given
- * edge.
- */
-mxParallelEdgeLayout.prototype.getEdgeId = function(edge)
-{
- var view = this.graph.getView();
-
- var state = view.getState(edge);
-
- var src = (state != null) ? state.getVisibleTerminal(true) : view.getVisibleTerminal(edge, true);
- var trg = (state != null) ? state.getVisibleTerminal(false) : view.getVisibleTerminal(edge, false);
-
- if (src != null && trg != null)
- {
- src = mxCellPath.create(src);
- trg = mxCellPath.create(trg);
-
- return (src > trg) ? trg+'-'+src : src+'-'+trg;
- }
-
- return null;
-};
-
-/**
- * Function: layout
- *
- * Lays out the parallel edges in the given array.
- */
-mxParallelEdgeLayout.prototype.layout = function(parallels)
-{
- var edge = parallels[0];
- var model = this.graph.getModel();
-
- var src = model.getGeometry(model.getTerminal(edge, true));
- var trg = model.getGeometry(model.getTerminal(edge, false));
-
- // Routes multiple loops
- if (src == trg)
- {
- var x0 = src.x + src.width + this.spacing;
- var y0 = src.y + src.height / 2;
-
- for (var i = 0; i < parallels.length; i++)
- {
- this.route(parallels[i], x0, y0);
- x0 += this.spacing;
- }
- }
- else if (src != null && trg != null)
- {
- // Routes parallel edges
- var scx = src.x + src.width / 2;
- var scy = src.y + src.height / 2;
-
- var tcx = trg.x + trg.width / 2;
- var tcy = trg.y + trg.height / 2;
-
- var dx = tcx - scx;
- var dy = tcy - scy;
-
- var len = Math.sqrt(dx*dx+dy*dy);
-
- var x0 = scx + dx / 2;
- var y0 = scy + dy / 2;
-
- var nx = dy * this.spacing / len;
- var ny = dx * this.spacing / len;
-
- x0 += nx * (parallels.length - 1) / 2;
- y0 -= ny * (parallels.length - 1) / 2;
-
- for (var i = 0; i < parallels.length; i++)
- {
- this.route(parallels[i], x0, y0);
- x0 -= nx;
- y0 += ny;
- }
- }
-};
-
-/**
- * Function: route
- *
- * Routes the given edge via the given point.
- */
-mxParallelEdgeLayout.prototype.route = function(edge, x, y)
-{
- if (this.graph.isCellMovable(edge))
- {
- this.setEdgePoints(edge, [new mxPoint(x, y)]);
- }
-};
diff --git a/src/js/layout/mxPartitionLayout.js b/src/js/layout/mxPartitionLayout.js
deleted file mode 100644
index d3592f8..0000000
--- a/src/js/layout/mxPartitionLayout.js
+++ /dev/null
@@ -1,240 +0,0 @@
-/**
- * $Id: mxPartitionLayout.js,v 1.25 2010-01-04 11:18:25 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxPartitionLayout
- *
- * Extends <mxGraphLayout> for partitioning the parent cell vertically or
- * horizontally by filling the complete area with the child cells. A horizontal
- * layout partitions the height of the given parent whereas a a non-horizontal
- * layout partitions the width. If the parent is a layer (that is, a child of
- * the root node), then the current graph size is partitioned. The children do
- * not need to be connected for this layout to work.
- *
- * Example:
- *
- * (code)
- * var layout = new mxPartitionLayout(graph, true, 10, 20);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxPartitionLayout
- *
- * Constructs a new stack layout layout for the specified graph,
- * spacing, orientation and offset.
- */
-function mxPartitionLayout(graph, horizontal, spacing, border)
-{
- mxGraphLayout.call(this, graph);
- this.horizontal = (horizontal != null) ? horizontal : true;
- this.spacing = spacing || 0;
- this.border = border || 0;
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxPartitionLayout.prototype = new mxGraphLayout();
-mxPartitionLayout.prototype.constructor = mxPartitionLayout;
-
-/**
- * Variable: horizontal
- *
- * Boolean indicating the direction in which the space is partitioned.
- * Default is true.
- */
-mxPartitionLayout.prototype.horizontal = null;
-
-/**
- * Variable: spacing
- *
- * Integer that specifies the absolute spacing in pixels between the
- * children. Default is 0.
- */
-mxPartitionLayout.prototype.spacing = null;
-
-/**
- * Variable: border
- *
- * Integer that specifies the absolute inset in pixels for the parent that
- * contains the children. Default is 0.
- */
-mxPartitionLayout.prototype.border = null;
-
-/**
- * Variable: resizeVertices
- *
- * Boolean that specifies if vertices should be resized. Default is true.
- */
-mxPartitionLayout.prototype.resizeVertices = true;
-
-/**
- * Function: isHorizontal
- *
- * Returns <horizontal>.
- */
-mxPartitionLayout.prototype.isHorizontal = function()
-{
- return this.horizontal;
-};
-
-/**
- * Function: moveCell
- *
- * Implements <mxGraphLayout.moveCell>.
- */
-mxPartitionLayout.prototype.moveCell = function(cell, x, y)
-{
- var model = this.graph.getModel();
- var parent = model.getParent(cell);
-
- if (cell != null &&
- parent != null)
- {
- var i = 0;
- var last = 0;
- var childCount = model.getChildCount(parent);
-
- // Finds index of the closest swimlane
- // TODO: Take into account the orientation
- for (i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(parent, i);
- var bounds = this.getVertexBounds(child);
-
- if (bounds != null)
- {
- var tmp = bounds.x + bounds.width / 2;
-
- if (last < x && tmp > x)
- {
- break;
- }
-
- last = tmp;
- }
- }
-
- // Changes child order in parent
- var idx = parent.getIndex(cell);
- idx = Math.max(0, i - ((i > idx) ? 1 : 0));
-
- model.add(parent, cell, idx);
- }
-};
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>. All children where <isVertexIgnored>
- * returns false and <isVertexMovable> returns true are modified.
- */
-mxPartitionLayout.prototype.execute = function(parent)
-{
- var horizontal = this.isHorizontal();
- var model = this.graph.getModel();
- var pgeo = model.getGeometry(parent);
-
- // Handles special case where the parent is either a layer with no
- // geometry or the current root of the view in which case the size
- // of the graph's container will be used.
- if (this.graph.container != null &&
- ((pgeo == null &&
- model.isLayer(parent)) ||
- parent == this.graph.getView().currentRoot))
- {
- var width = this.graph.container.offsetWidth - 1;
- var height = this.graph.container.offsetHeight - 1;
- pgeo = new mxRectangle(0, 0, width, height);
- }
-
- if (pgeo != null)
- {
- var children = [];
- var childCount = model.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(parent, i);
-
- if (!this.isVertexIgnored(child) &&
- this.isVertexMovable(child))
- {
- children.push(child);
- }
- }
-
- var n = children.length;
-
- if (n > 0)
- {
- var x0 = this.border;
- var y0 = this.border;
- var other = (horizontal) ? pgeo.height : pgeo.width;
- other -= 2 * this.border;
-
- var size = (this.graph.isSwimlane(parent)) ?
- this.graph.getStartSize(parent) :
- new mxRectangle();
-
- other -= (horizontal) ? size.height : size.width;
- x0 = x0 + size.width;
- y0 = y0 + size.height;
-
- var tmp = this.border + (n - 1) * this.spacing;
- var value = (horizontal) ?
- ((pgeo.width - x0 - tmp) / n) :
- ((pgeo.height - y0 - tmp) / n);
-
- // Avoids negative values, that is values where the sum of the
- // spacing plus the border is larger then the available space
- if (value > 0)
- {
- model.beginUpdate();
- try
- {
- for (var i = 0; i < n; i++)
- {
- var child = children[i];
- var geo = model.getGeometry(child);
-
- if (geo != null)
- {
- geo = geo.clone();
- geo.x = x0;
- geo.y = y0;
-
- if (horizontal)
- {
- if (this.resizeVertices)
- {
- geo.width = value;
- geo.height = other;
- }
-
- x0 += value + this.spacing;
- }
- else
- {
- if (this.resizeVertices)
- {
- geo.height = value;
- geo.width = other;
- }
-
- y0 += value + this.spacing;
- }
-
- model.setGeometry(child, geo);
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
- }
- }
-};
diff --git a/src/js/layout/mxStackLayout.js b/src/js/layout/mxStackLayout.js
deleted file mode 100644
index 7f5cd47..0000000
--- a/src/js/layout/mxStackLayout.js
+++ /dev/null
@@ -1,381 +0,0 @@
-/**
- * $Id: mxStackLayout.js,v 1.47 2012-12-14 08:54:34 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxStackLayout
- *
- * Extends <mxGraphLayout> to create a horizontal or vertical stack of the
- * child vertices. The children do not need to be connected for this layout
- * to work.
- *
- * Example:
- *
- * (code)
- * var layout = new mxStackLayout(graph, true);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxStackLayout
- *
- * Constructs a new stack layout layout for the specified graph,
- * spacing, orientation and offset.
- */
-function mxStackLayout(graph, horizontal, spacing, x0, y0, border)
-{
- mxGraphLayout.call(this, graph);
- this.horizontal = (horizontal != null) ? horizontal : true;
- this.spacing = (spacing != null) ? spacing : 0;
- this.x0 = (x0 != null) ? x0 : 0;
- this.y0 = (y0 != null) ? y0 : 0;
- this.border = (border != null) ? border : 0;
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxStackLayout.prototype = new mxGraphLayout();
-mxStackLayout.prototype.constructor = mxStackLayout;
-
-/**
- * Variable: horizontal
- *
- * Specifies the orientation of the layout. Default is true.
- */
-mxStackLayout.prototype.horizontal = null;
-
-/**
- * Variable: spacing
- *
- * Specifies the spacing between the cells. Default is 0.
- */
-mxStackLayout.prototype.spacing = null;
-
-/**
- * Variable: x0
- *
- * Specifies the horizontal origin of the layout. Default is 0.
- */
-mxStackLayout.prototype.x0 = null;
-
-/**
- * Variable: y0
- *
- * Specifies the vertical origin of the layout. Default is 0.
- */
-mxStackLayout.prototype.y0 = null;
-
-/**
- * Variable: border
- *
- * Border to be added if fill is true. Default is 0.
- */
-mxStackLayout.prototype.border = 0;
-
-/**
- * Variable: keepFirstLocation
- *
- * Boolean indicating if the location of the first cell should be
- * kept, that is, it will not be moved to x0 or y0.
- */
-mxStackLayout.prototype.keepFirstLocation = false;
-
-/**
- * Variable: fill
- *
- * Boolean indicating if dimension should be changed to fill out the parent
- * cell. Default is false.
- */
-mxStackLayout.prototype.fill = false;
-
-/**
- * Variable: resizeParent
- *
- * If the parent should be resized to match the width/height of the
- * stack. Default is false.
- */
-mxStackLayout.prototype.resizeParent = false;
-
-/**
- * Variable: resizeLast
- *
- * If the last element should be resized to fill out the parent. Default is
- * false. If <resizeParent> is true then this is ignored.
- */
-mxStackLayout.prototype.resizeLast = false;
-
-/**
- * Variable: wrap
- *
- * Value at which a new column or row should be created. Default is null.
- */
-mxStackLayout.prototype.wrap = null;
-
-/**
- * Function: isHorizontal
- *
- * Returns <horizontal>.
- */
-mxStackLayout.prototype.isHorizontal = function()
-{
- return this.horizontal;
-};
-
-/**
- * Function: moveCell
- *
- * Implements <mxGraphLayout.moveCell>.
- */
-mxStackLayout.prototype.moveCell = function(cell, x, y)
-{
- var model = this.graph.getModel();
- var parent = model.getParent(cell);
- var horizontal = this.isHorizontal();
-
- if (cell != null && parent != null)
- {
- var i = 0;
- var last = 0;
- var childCount = model.getChildCount(parent);
- var value = (horizontal) ? x : y;
- var pstate = this.graph.getView().getState(parent);
-
- if (pstate != null)
- {
- value -= (horizontal) ? pstate.x : pstate.y;
- }
-
- for (i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(parent, i);
-
- if (child != cell)
- {
- var bounds = model.getGeometry(child);
-
- if (bounds != null)
- {
- var tmp = (horizontal) ?
- bounds.x + bounds.width / 2 :
- bounds.y + bounds.height / 2;
-
- if (last < value && tmp > value)
- {
- break;
- }
-
- last = tmp;
- }
- }
- }
-
- // Changes child order in parent
- var idx = parent.getIndex(cell);
- idx = Math.max(0, i - ((i > idx) ? 1 : 0));
-
- model.add(parent, cell, idx);
- }
-};
-
-/**
- * Function: getParentSize
- *
- * Returns the size for the parent container or the size of the graph
- * container if the parent is a layer or the root of the model.
- */
-mxStackLayout.prototype.getParentSize = function(parent)
-{
- var model = this.graph.getModel();
- var pgeo = model.getGeometry(parent);
-
- // Handles special case where the parent is either a layer with no
- // geometry or the current root of the view in which case the size
- // of the graph's container will be used.
- if (this.graph.container != null && ((pgeo == null &&
- model.isLayer(parent)) || parent == this.graph.getView().currentRoot))
- {
- var width = this.graph.container.offsetWidth - 1;
- var height = this.graph.container.offsetHeight - 1;
- pgeo = new mxRectangle(0, 0, width, height);
- }
-
- return pgeo;
-};
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>.
- *
- * Only children where <isVertexIgnored> returns false are taken into
- * account.
- */
-mxStackLayout.prototype.execute = function(parent)
-{
- if (parent != null)
- {
- var horizontal = this.isHorizontal();
- var model = this.graph.getModel();
- var pgeo = this.getParentSize(parent);
-
- var fillValue = 0;
-
- if (pgeo != null)
- {
- fillValue = (horizontal) ? pgeo.height : pgeo.width;
- }
-
- fillValue -= 2 * this.spacing + 2 * this.border;
- var x0 = this.x0 + this.border;
- var y0 = this.y0 + this.border;
-
- // Handles swimlane start size
- if (this.graph.isSwimlane(parent))
- {
- // Uses computed style to get latest
- var style = this.graph.getCellStyle(parent);
- var start = mxUtils.getValue(style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE);
- var horz = mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, true);
-
- if (horizontal == horz)
- {
- fillValue -= start;
- }
-
- if (horizontal)
- {
- y0 += start;
- }
- else
- {
- x0 += start;
- }
- }
-
- model.beginUpdate();
- try
- {
- var tmp = 0;
- var last = null;
- var childCount = model.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(parent, i);
-
- if (!this.isVertexIgnored(child) && this.isVertexMovable(child))
- {
- var geo = model.getGeometry(child);
-
- if (geo != null)
- {
- geo = geo.clone();
-
- if (this.wrap != null && last != null)
- {
- if ((horizontal && last.x + last.width +
- geo.width + 2 * this.spacing > this.wrap) ||
- (!horizontal && last.y + last.height +
- geo.height + 2 * this.spacing > this.wrap))
- {
- last = null;
-
- if (horizontal)
- {
- y0 += tmp + this.spacing;
- }
- else
- {
- x0 += tmp + this.spacing;
- }
-
- tmp = 0;
- }
- }
-
- tmp = Math.max(tmp, (horizontal) ? geo.height : geo.width);
-
- if (last != null)
- {
- if (horizontal)
- {
- geo.x = last.x + last.width + this.spacing;
- }
- else
- {
- geo.y = last.y + last.height + this.spacing;
- }
- }
- else if (!this.keepFirstLocation)
- {
- if (horizontal)
- {
- geo.x = x0;
- }
- else
- {
- geo.y = y0;
- }
- }
-
- if (horizontal)
- {
- geo.y = y0;
- }
- else
- {
- geo.x = x0;
- }
-
- if (this.fill && fillValue > 0)
- {
- if (horizontal)
- {
- geo.height = fillValue;
- }
- else
- {
- geo.width = fillValue;
- }
- }
-
- model.setGeometry(child, geo);
- last = geo;
- }
- }
- }
-
- if (this.resizeParent && pgeo != null && last != null &&
- !this.graph.isCellCollapsed(parent))
- {
- pgeo = pgeo.clone();
-
- if (horizontal)
- {
- pgeo.width = last.x + last.width + this.spacing;
- }
- else
- {
- pgeo.height = last.y + last.height + this.spacing;
- }
-
- model.setGeometry(parent, pgeo);
- }
- else if (this.resizeLast && pgeo != null && last != null)
- {
- if (horizontal)
- {
- last.width = pgeo.width - last.x - this.spacing;
- }
- else
- {
- last.height = pgeo.height - last.y - this.spacing;
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
-};
diff --git a/src/js/model/mxCell.js b/src/js/model/mxCell.js
deleted file mode 100644
index cb5eb9f..0000000
--- a/src/js/model/mxCell.js
+++ /dev/null
@@ -1,806 +0,0 @@
-/**
- * $Id: mxCell.js,v 1.36 2011-06-17 13:45:08 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCell
- *
- * Cells are the elements of the graph model. They represent the state
- * of the groups, vertices and edges in a graph.
- *
- * Custom attributes:
- *
- * For custom attributes we recommend using an XML node as the value of a cell.
- * The following code can be used to create a cell with an XML node as the
- * value:
- *
- * (code)
- * var doc = mxUtils.createXmlDocument();
- * var node = doc.createElement('MyNode')
- * node.setAttribute('label', 'MyLabel');
- * node.setAttribute('attribute1', 'value1');
- * graph.insertVertex(graph.getDefaultParent(), null, node, 40, 40, 80, 30);
- * (end)
- *
- * For the label to work, <mxGraph.convertValueToString> and
- * <mxGraph.cellLabelChanged> should be overridden as follows:
- *
- * (code)
- * graph.convertValueToString = function(cell)
- * {
- * if (mxUtils.isNode(cell.value))
- * {
- * return cell.getAttribute('label', '')
- * }
- * };
- *
- * var cellLabelChanged = graph.cellLabelChanged;
- * graph.cellLabelChanged = function(cell, newValue, autoSize)
- * {
- * if (mxUtils.isNode(cell.value))
- * {
- * // Clones the value for correct undo/redo
- * var elt = cell.value.cloneNode(true);
- * elt.setAttribute('label', newValue);
- * newValue = elt;
- * }
- *
- * cellLabelChanged.apply(this, arguments);
- * };
- * (end)
- *
- * Callback: onInit
- *
- * Called from within the constructor.
- *
- * Constructor: mxCell
- *
- * Constructs a new cell to be used in a graph model.
- * This method invokes <onInit> upon completion.
- *
- * Parameters:
- *
- * value - Optional object that represents the cell value.
- * geometry - Optional <mxGeometry> that specifies the geometry.
- * style - Optional formatted string that defines the style.
- */
-function mxCell(value, geometry, style)
-{
- this.value = value;
- this.setGeometry(geometry);
- this.setStyle(style);
-
- if (this.onInit != null)
- {
- this.onInit();
- }
-};
-
-/**
- * Variable: id
- *
- * Holds the Id. Default is null.
- */
-mxCell.prototype.id = null;
-
-/**
- * Variable: value
- *
- * Holds the user object. Default is null.
- */
-mxCell.prototype.value = null;
-
-/**
- * Variable: geometry
- *
- * Holds the <mxGeometry>. Default is null.
- */
-mxCell.prototype.geometry = null;
-
-/**
- * Variable: style
- *
- * Holds the style as a string of the form [(stylename|key=value);]. Default is
- * null.
- */
-mxCell.prototype.style = null;
-
-/**
- * Variable: vertex
- *
- * Specifies whether the cell is a vertex. Default is false.
- */
-mxCell.prototype.vertex = false;
-
-/**
- * Variable: edge
- *
- * Specifies whether the cell is an edge. Default is false.
- */
-mxCell.prototype.edge = false;
-
-/**
- * Variable: connectable
- *
- * Specifies whether the cell is connectable. Default is true.
- */
-mxCell.prototype.connectable = true;
-
-/**
- * Variable: visible
- *
- * Specifies whether the cell is visible. Default is true.
- */
-mxCell.prototype.visible = true;
-
-/**
- * Variable: collapsed
- *
- * Specifies whether the cell is collapsed. Default is false.
- */
-mxCell.prototype.collapsed = false;
-
-/**
- * Variable: parent
- *
- * Reference to the parent cell.
- */
-mxCell.prototype.parent = null;
-
-/**
- * Variable: source
- *
- * Reference to the source terminal.
- */
-mxCell.prototype.source = null;
-
-/**
- * Variable: target
- *
- * Reference to the target terminal.
- */
-mxCell.prototype.target = null;
-
-/**
- * Variable: children
- *
- * Holds the child cells.
- */
-mxCell.prototype.children = null;
-
-/**
- * Variable: edges
- *
- * Holds the edges.
- */
-mxCell.prototype.edges = null;
-
-/**
- * Variable: mxTransient
- *
- * List of members that should not be cloned inside <clone>. This field is
- * passed to <mxUtils.clone> and is not made persistent in <mxCellCodec>.
- * This is not a convention for all classes, it is only used in this class
- * to mark transient fields since transient modifiers are not supported by
- * the language.
- */
-mxCell.prototype.mxTransient = ['id', 'value', 'parent', 'source',
- 'target', 'children', 'edges'];
-
-/**
- * Function: getId
- *
- * Returns the Id of the cell as a string.
- */
-mxCell.prototype.getId = function()
-{
- return this.id;
-};
-
-/**
- * Function: setId
- *
- * Sets the Id of the cell to the given string.
- */
-mxCell.prototype.setId = function(id)
-{
- this.id = id;
-};
-
-/**
- * Function: getValue
- *
- * Returns the user object of the cell. The user
- * object is stored in <value>.
- */
-mxCell.prototype.getValue = function()
-{
- return this.value;
-};
-
-/**
- * Function: setValue
- *
- * Sets the user object of the cell. The user object
- * is stored in <value>.
- */
-mxCell.prototype.setValue = function(value)
-{
- this.value = value;
-};
-
-/**
- * Function: valueChanged
- *
- * Changes the user object after an in-place edit
- * and returns the previous value. This implementation
- * replaces the user object with the given value and
- * returns the old user object.
- */
-mxCell.prototype.valueChanged = function(newValue)
-{
- var previous = this.getValue();
- this.setValue(newValue);
-
- return previous;
-};
-
-/**
- * Function: getGeometry
- *
- * Returns the <mxGeometry> that describes the <geometry>.
- */
-mxCell.prototype.getGeometry = function()
-{
- return this.geometry;
-};
-
-/**
- * Function: setGeometry
- *
- * Sets the <mxGeometry> to be used as the <geometry>.
- */
-mxCell.prototype.setGeometry = function(geometry)
-{
- this.geometry = geometry;
-};
-
-/**
- * Function: getStyle
- *
- * Returns a string that describes the <style>.
- */
-mxCell.prototype.getStyle = function()
-{
- return this.style;
-};
-
-/**
- * Function: setStyle
- *
- * Sets the string to be used as the <style>.
- */
-mxCell.prototype.setStyle = function(style)
-{
- this.style = style;
-};
-
-/**
- * Function: isVertex
- *
- * Returns true if the cell is a vertex.
- */
-mxCell.prototype.isVertex = function()
-{
- return this.vertex;
-};
-
-/**
- * Function: setVertex
- *
- * Specifies if the cell is a vertex. This should only be assigned at
- * construction of the cell and not be changed during its lifecycle.
- *
- * Parameters:
- *
- * vertex - Boolean that specifies if the cell is a vertex.
- */
-mxCell.prototype.setVertex = function(vertex)
-{
- this.vertex = vertex;
-};
-
-/**
- * Function: isEdge
- *
- * Returns true if the cell is an edge.
- */
-mxCell.prototype.isEdge = function()
-{
- return this.edge;
-};
-
-/**
- * Function: setEdge
- *
- * Specifies if the cell is an edge. This should only be assigned at
- * construction of the cell and not be changed during its lifecycle.
- *
- * Parameters:
- *
- * edge - Boolean that specifies if the cell is an edge.
- */
-mxCell.prototype.setEdge = function(edge)
-{
- this.edge = edge;
-};
-
-/**
- * Function: isConnectable
- *
- * Returns true if the cell is connectable.
- */
-mxCell.prototype.isConnectable = function()
-{
- return this.connectable;
-};
-
-/**
- * Function: setConnectable
- *
- * Sets the connectable state.
- *
- * Parameters:
- *
- * connectable - Boolean that specifies the new connectable state.
- */
-mxCell.prototype.setConnectable = function(connectable)
-{
- this.connectable = connectable;
-};
-
-/**
- * Function: isVisible
- *
- * Returns true if the cell is visibile.
- */
-mxCell.prototype.isVisible = function()
-{
- return this.visible;
-};
-
-/**
- * Function: setVisible
- *
- * Specifies if the cell is visible.
- *
- * Parameters:
- *
- * visible - Boolean that specifies the new visible state.
- */
-mxCell.prototype.setVisible = function(visible)
-{
- this.visible = visible;
-};
-
-/**
- * Function: isCollapsed
- *
- * Returns true if the cell is collapsed.
- */
-mxCell.prototype.isCollapsed = function()
-{
- return this.collapsed;
-};
-
-/**
- * Function: setCollapsed
- *
- * Sets the collapsed state.
- *
- * Parameters:
- *
- * collapsed - Boolean that specifies the new collapsed state.
- */
-mxCell.prototype.setCollapsed = function(collapsed)
-{
- this.collapsed = collapsed;
-};
-
-/**
- * Function: getParent
- *
- * Returns the cell's parent.
- */
-mxCell.prototype.getParent = function()
-{
- return this.parent;
-};
-
-/**
- * Function: setParent
- *
- * Sets the parent cell.
- *
- * Parameters:
- *
- * parent - <mxCell> that represents the new parent.
- */
-mxCell.prototype.setParent = function(parent)
-{
- this.parent = parent;
-};
-
-/**
- * Function: getTerminal
- *
- * Returns the source or target terminal.
- *
- * Parameters:
- *
- * source - Boolean that specifies if the source terminal should be
- * returned.
- */
-mxCell.prototype.getTerminal = function(source)
-{
- return (source) ? this.source : this.target;
-};
-
-/**
- * Function: setTerminal
- *
- * Sets the source or target terminal and returns the new terminal.
- *
- * Parameters:
- *
- * terminal - <mxCell> that represents the new source or target terminal.
- * isSource - Boolean that specifies if the source or target terminal
- * should be set.
- */
-mxCell.prototype.setTerminal = function(terminal, isSource)
-{
- if (isSource)
- {
- this.source = terminal;
- }
- else
- {
- this.target = terminal;
- }
-
- return terminal;
-};
-
-/**
- * Function: getChildCount
- *
- * Returns the number of child cells.
- */
-mxCell.prototype.getChildCount = function()
-{
- return (this.children == null) ? 0 : this.children.length;
-};
-
-/**
- * Function: getIndex
- *
- * Returns the index of the specified child in the child array.
- *
- * Parameters:
- *
- * child - Child whose index should be returned.
- */
-mxCell.prototype.getIndex = function(child)
-{
- return mxUtils.indexOf(this.children, child);
-};
-
-/**
- * Function: getChildAt
- *
- * Returns the child at the specified index.
- *
- * Parameters:
- *
- * index - Integer that specifies the child to be returned.
- */
-mxCell.prototype.getChildAt = function(index)
-{
- return (this.children == null) ? null : this.children[index];
-};
-
-/**
- * Function: insert
- *
- * Inserts the specified child into the child array at the specified index
- * and updates the parent reference of the child. If not childIndex is
- * specified then the child is appended to the child array. Returns the
- * inserted child.
- *
- * Parameters:
- *
- * child - <mxCell> to be inserted or appended to the child array.
- * index - Optional integer that specifies the index at which the child
- * should be inserted into the child array.
- */
-mxCell.prototype.insert = function(child, index)
-{
- if (child != null)
- {
- if (index == null)
- {
- index = this.getChildCount();
-
- if (child.getParent() == this)
- {
- index--;
- }
- }
-
- child.removeFromParent();
- child.setParent(this);
-
- if (this.children == null)
- {
- this.children = [];
- this.children.push(child);
- }
- else
- {
- this.children.splice(index, 0, child);
- }
- }
-
- return child;
-};
-
-/**
- * Function: remove
- *
- * Removes the child at the specified index from the child array and
- * returns the child that was removed. Will remove the parent reference of
- * the child.
- *
- * Parameters:
- *
- * index - Integer that specifies the index of the child to be
- * removed.
- */
-mxCell.prototype.remove = function(index)
-{
- var child = null;
-
- if (this.children != null && index >= 0)
- {
- child = this.getChildAt(index);
-
- if (child != null)
- {
- this.children.splice(index, 1);
- child.setParent(null);
- }
- }
-
- return child;
-};
-
-/**
- * Function: removeFromParent
- *
- * Removes the cell from its parent.
- */
-mxCell.prototype.removeFromParent = function()
-{
- if (this.parent != null)
- {
- var index = this.parent.getIndex(this);
- this.parent.remove(index);
- }
-};
-
-/**
- * Function: getEdgeCount
- *
- * Returns the number of edges in the edge array.
- */
-mxCell.prototype.getEdgeCount = function()
-{
- return (this.edges == null) ? 0 : this.edges.length;
-};
-
-/**
- * Function: getEdgeIndex
- *
- * Returns the index of the specified edge in <edges>.
- *
- * Parameters:
- *
- * edge - <mxCell> whose index in <edges> should be returned.
- */
-mxCell.prototype.getEdgeIndex = function(edge)
-{
- return mxUtils.indexOf(this.edges, edge);
-};
-
-/**
- * Function: getEdgeAt
- *
- * Returns the edge at the specified index in <edges>.
- *
- * Parameters:
- *
- * index - Integer that specifies the index of the edge to be returned.
- */
-mxCell.prototype.getEdgeAt = function(index)
-{
- return (this.edges == null) ? null : this.edges[index];
-};
-
-/**
- * Function: insertEdge
- *
- * Inserts the specified edge into the edge array and returns the edge.
- * Will update the respective terminal reference of the edge.
- *
- * Parameters:
- *
- * edge - <mxCell> to be inserted into the edge array.
- * isOutgoing - Boolean that specifies if the edge is outgoing.
- */
-mxCell.prototype.insertEdge = function(edge, isOutgoing)
-{
- if (edge != null)
- {
- edge.removeFromTerminal(isOutgoing);
- edge.setTerminal(this, isOutgoing);
-
- if (this.edges == null ||
- edge.getTerminal(!isOutgoing) != this ||
- mxUtils.indexOf(this.edges, edge) < 0)
- {
- if (this.edges == null)
- {
- this.edges = [];
- }
-
- this.edges.push(edge);
- }
- }
-
- return edge;
-};
-
-/**
- * Function: removeEdge
- *
- * Removes the specified edge from the edge array and returns the edge.
- * Will remove the respective terminal reference from the edge.
- *
- * Parameters:
- *
- * edge - <mxCell> to be removed from the edge array.
- * isOutgoing - Boolean that specifies if the edge is outgoing.
- */
-mxCell.prototype.removeEdge = function(edge, isOutgoing)
-{
- if (edge != null)
- {
- if (edge.getTerminal(!isOutgoing) != this &&
- this.edges != null)
- {
- var index = this.getEdgeIndex(edge);
-
- if (index >= 0)
- {
- this.edges.splice(index, 1);
- }
- }
-
- edge.setTerminal(null, isOutgoing);
- }
-
- return edge;
-};
-
-/**
- * Function: removeFromTerminal
- *
- * Removes the edge from its source or target terminal.
- *
- * Parameters:
- *
- * isSource - Boolean that specifies if the edge should be removed from its
- * source or target terminal.
- */
-mxCell.prototype.removeFromTerminal = function(isSource)
-{
- var terminal = this.getTerminal(isSource);
-
- if (terminal != null)
- {
- terminal.removeEdge(this, isSource);
- }
-};
-
-/**
- * Function: getAttribute
- *
- * Returns the specified attribute from the user object if it is an XML
- * node.
- *
- * Parameters:
- *
- * name - Name of the attribute whose value should be returned.
- * defaultValue - Optional default value to use if the attribute has no
- * value.
- */
-mxCell.prototype.getAttribute = function(name, defaultValue)
-{
- var userObject = this.getValue();
-
- var val = (userObject != null &&
- userObject.nodeType == mxConstants.NODETYPE_ELEMENT) ?
- userObject.getAttribute(name) : null;
-
- return val || defaultValue;
-};
-
-/**
- * Function: setAttribute
- *
- * Sets the specified attribute on the user object if it is an XML node.
- *
- * Parameters:
- *
- * name - Name of the attribute whose value should be set.
- * value - New value of the attribute.
- */
-mxCell.prototype.setAttribute = function(name, value)
-{
- var userObject = this.getValue();
-
- if (userObject != null &&
- userObject.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- userObject.setAttribute(name, value);
- }
-};
-
-/**
- * Function: clone
- *
- * Returns a clone of the cell. Uses <cloneValue> to clone
- * the user object. All fields in <mxTransient> are ignored
- * during the cloning.
- */
-mxCell.prototype.clone = function()
-{
- var clone = mxUtils.clone(this, this.mxTransient);
- clone.setValue(this.cloneValue());
-
- return clone;
-};
-
-/**
- * Function: cloneValue
- *
- * Returns a clone of the cell's user object.
- */
-mxCell.prototype.cloneValue = function()
-{
- var value = this.getValue();
-
- if (value != null)
- {
- if (typeof(value.clone) == 'function')
- {
- value = value.clone();
- }
- else if (!isNaN(value.nodeType))
- {
- value = value.cloneNode(true);
- }
- }
-
- return value;
-};
diff --git a/src/js/model/mxCellPath.js b/src/js/model/mxCellPath.js
deleted file mode 100644
index 71a379e..0000000
--- a/src/js/model/mxCellPath.js
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- * $Id: mxCellPath.js,v 1.12 2010-01-02 09:45:15 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxCellPath =
-{
-
- /**
- * Class: mxCellPath
- *
- * Implements a mechanism for temporary cell Ids.
- *
- * Variable: PATH_SEPARATOR
- *
- * Defines the separator between the path components. Default is ".".
- */
- PATH_SEPARATOR: '.',
-
- /**
- * Function: create
- *
- * Creates the cell path for the given cell. The cell path is a
- * concatenation of the indices of all ancestors on the (finite) path to
- * the root, eg. "0.0.0.1".
- *
- * Parameters:
- *
- * cell - Cell whose path should be returned.
- */
- create: function(cell)
- {
- var result = '';
-
- if (cell != null)
- {
- var parent = cell.getParent();
-
- while (parent != null)
- {
- var index = parent.getIndex(cell);
- result = index + mxCellPath.PATH_SEPARATOR + result;
-
- cell = parent;
- parent = cell.getParent();
- }
- }
-
- // Removes trailing separator
- var n = result.length;
-
- if (n > 1)
- {
- result = result.substring(0, n - 1);
- }
-
- return result;
- },
-
- /**
- * Function: getParentPath
- *
- * Returns the path for the parent of the cell represented by the given
- * path. Returns null if the given path has no parent.
- *
- * Parameters:
- *
- * path - Path whose parent path should be returned.
- */
- getParentPath: function(path)
- {
- if (path != null)
- {
- var index = path.lastIndexOf(mxCellPath.PATH_SEPARATOR);
-
- if (index >= 0)
- {
- return path.substring(0, index);
- }
- else if (path.length > 0)
- {
- return '';
- }
- }
-
- return null;
- },
-
- /**
- * Function: resolve
- *
- * Returns the cell for the specified cell path using the given root as the
- * root of the path.
- *
- * Parameters:
- *
- * root - Root cell of the path to be resolved.
- * path - String that defines the path.
- */
- resolve: function(root, path)
- {
- var parent = root;
-
- if (path != null)
- {
- var tokens = path.split(mxCellPath.PATH_SEPARATOR);
-
- for (var i=0; i<tokens.length; i++)
- {
- parent = parent.getChildAt(parseInt(tokens[i]));
- }
- }
-
- return parent;
- },
-
- /**
- * Function: compare
- *
- * Compares the given cell paths and returns -1 if p1 is smaller, 0 if
- * p1 is equal and 1 if p1 is greater than p2.
- */
- compare: function(p1, p2)
- {
- var min = Math.min(p1.length, p2.length);
- var comp = 0;
-
- for (var i = 0; i < min; i++)
- {
- if (p1[i] != p2[i])
- {
- if (p1[i].length == 0 ||
- p2[i].length == 0)
- {
- comp = (p1[i] == p2[i]) ? 0 : ((p1[i] > p2[i]) ? 1 : -1);
- }
- else
- {
- var t1 = parseInt(p1[i]);
- var t2 = parseInt(p2[i]);
-
- comp = (t1 == t2) ? 0 : ((t1 > t2) ? 1 : -1);
- }
-
- break;
- }
- }
-
- // Compares path length if both paths are equal to this point
- if (comp == 0)
- {
- var t1 = p1.length;
- var t2 = p2.length;
-
- if (t1 != t2)
- {
- comp = (t1 > t2) ? 1 : -1;
- }
- }
-
- return comp;
- }
-
-};
diff --git a/src/js/model/mxGeometry.js b/src/js/model/mxGeometry.js
deleted file mode 100644
index 51a7d3b..0000000
--- a/src/js/model/mxGeometry.js
+++ /dev/null
@@ -1,277 +0,0 @@
-/**
- * $Id: mxGeometry.js,v 1.26 2010-01-02 09:45:15 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGeometry
- *
- * Extends <mxRectangle> to represent the geometry of a cell.
- *
- * For vertices, the geometry consists of the x- and y-location, and the width
- * and height. For edges, the geometry consists of the optional terminal- and
- * control points. The terminal points are only required if an edge is
- * unconnected, and are stored in the sourcePoint> and <targetPoint>
- * variables, respectively.
- *
- * Example:
- *
- * If an edge is unconnected, that is, it has no source or target terminal,
- * then a geometry with terminal points for a new edge can be defined as
- * follows.
- *
- * (code)
- * geometry.setTerminalPoint(new mxPoint(x1, y1), true);
- * geometry.points = [new mxPoint(x2, y2)];
- * geometry.setTerminalPoint(new mxPoint(x3, y3), false);
- * (end)
- *
- * Control points are used regardless of the connected state of an edge and may
- * be ignored or interpreted differently depending on the edge's <mxEdgeStyle>.
- *
- * To disable automatic reset of control points after a cell has been moved or
- * resized, the the <mxGraph.resizeEdgesOnMove> and
- * <mxGraph.resetEdgesOnResize> may be used.
- *
- * Edge Labels:
- *
- * Using the x- and y-coordinates of a cell's geometry, it is possible to
- * position the label on edges on a specific location on the actual edge shape
- * as it appears on the screen. The x-coordinate of an edge's geometry is used
- * to describe the distance from the center of the edge from -1 to 1 with 0
- * being the center of the edge and the default value. The y-coordinate of an
- * edge's geometry is used to describe the absolute, orthogonal distance in
- * pixels from that point. In addition, the <mxGeometry.offset> is used as an
- * absolute offset vector from the resulting point.
- *
- * This coordinate system is applied if <relative> is true, otherwise the
- * offset defines the absolute vector from the edge's center point to the
- * label.
- *
- * Ports:
- *
- * The term "port" refers to a relatively positioned, connectable child cell,
- * which is used to specify the connection between the parent and another cell
- * in the graph. Ports are typically modeled as vertices with relative
- * geometries.
- *
- * Offsets:
- *
- * The <offset> field is interpreted in 3 different ways, depending on the cell
- * and the geometry. For edges, the offset defines the absolute offset for the
- * edge label. For relative geometries, the offset defines the absolute offset
- * for the origin (top, left corner) of the vertex, otherwise the offset
- * defines the absolute offset for the label inside the vertex or group.
- *
- * Constructor: mxGeometry
- *
- * Constructs a new object to describe the size and location of a vertex or
- * the control points of an edge.
- */
-function mxGeometry(x, y, width, height)
-{
- mxRectangle.call(this, x, y, width, height);
-};
-
-/**
- * Extends mxRectangle.
- */
-mxGeometry.prototype = new mxRectangle();
-mxGeometry.prototype.constructor = mxGeometry;
-
-/**
- * Variable: TRANSLATE_CONTROL_POINTS
- *
- * Global switch to translate the points in translate. Default is true.
- */
-mxGeometry.prototype.TRANSLATE_CONTROL_POINTS = true;
-
-/**
- * Variable: alternateBounds
- *
- * Stores alternate values for x, y, width and height in a rectangle. See
- * <swap> to exchange the values. Default is null.
- */
-mxGeometry.prototype.alternateBounds = null;
-
-/**
- * Variable: sourcePoint
- *
- * Defines the source <mxPoint> of the edge. This is used if the
- * corresponding edge does not have a source vertex. Otherwise it is
- * ignored. Default is null.
- */
-mxGeometry.prototype.sourcePoint = null;
-
-/**
- * Variable: targetPoint
- *
- * Defines the target <mxPoint> of the edge. This is used if the
- * corresponding edge does not have a target vertex. Otherwise it is
- * ignored. Default is null.
- */
-mxGeometry.prototype.targetPoint = null;
-
-/**
- * Variable: points
- *
- * Array of <mxPoints> which specifies the control points along the edge.
- * These points are the intermediate points on the edge, for the endpoints
- * use <targetPoint> and <sourcePoint> or set the terminals of the edge to
- * a non-null value. Default is null.
- */
-mxGeometry.prototype.points = null;
-
-/**
- * Variable: offset
- *
- * For edges, this holds the offset (in pixels) from the position defined
- * by <x> and <y> on the edge. For relative geometries (for vertices), this
- * defines the absolute offset from the point defined by the relative
- * coordinates. For absolute geometries (for vertices), this defines the
- * offset for the label. Default is null.
- */
-mxGeometry.prototype.offset = null;
-
-/**
- * Variable: relative
- *
- * Specifies if the coordinates in the geometry are to be interpreted as
- * relative coordinates. For edges, this is used to define the location of
- * the edge label relative to the edge as rendered on the display. For
- * vertices, this specifies the relative location inside the bounds of the
- * parent cell.
- *
- * If this is false, then the coordinates are relative to the origin of the
- * parent cell or, for edges, the edge label position is relative to the
- * center of the edge as rendered on screen.
- *
- * Default is false.
- */
-mxGeometry.prototype.relative = false;
-
-/**
- * Function: swap
- *
- * Swaps the x, y, width and height with the values stored in
- * <alternateBounds> and puts the previous values into <alternateBounds> as
- * a rectangle. This operation is carried-out in-place, that is, using the
- * existing geometry instance. If this operation is called during a graph
- * model transactional change, then the geometry should be cloned before
- * calling this method and setting the geometry of the cell using
- * <mxGraphModel.setGeometry>.
- */
-mxGeometry.prototype.swap = function()
-{
- if (this.alternateBounds != null)
- {
- var old = new mxRectangle(
- this.x, this.y, this.width, this.height);
-
- this.x = this.alternateBounds.x;
- this.y = this.alternateBounds.y;
- this.width = this.alternateBounds.width;
- this.height = this.alternateBounds.height;
-
- this.alternateBounds = old;
- }
-};
-
-/**
- * Function: getTerminalPoint
- *
- * Returns the <mxPoint> representing the source or target point of this
- * edge. This is only used if the edge has no source or target vertex.
- *
- * Parameters:
- *
- * isSource - Boolean that specifies if the source or target point
- * should be returned.
- */
-mxGeometry.prototype.getTerminalPoint = function(isSource)
-{
- return (isSource) ? this.sourcePoint : this.targetPoint;
-};
-
-/**
- * Function: setTerminalPoint
- *
- * Sets the <sourcePoint> or <targetPoint> to the given <mxPoint> and
- * returns the new point.
- *
- * Parameters:
- *
- * point - Point to be used as the new source or target point.
- * isSource - Boolean that specifies if the source or target point
- * should be set.
- */
-mxGeometry.prototype.setTerminalPoint = function(point, isSource)
-{
- if (isSource)
- {
- this.sourcePoint = point;
- }
- else
- {
- this.targetPoint = point;
- }
-
- return point;
-};
-
-/**
- * Function: translate
- *
- * Translates the geometry by the specified amount. That is, <x> and <y>
- * of the geometry, the <sourcePoint>, <targetPoint> and all elements of
- * <points> are translated by the given amount. <x> and <y> are only
- * translated if <relative> is false. If <TRANSLATE_CONTROL_POINTS> is
- * false, then <points> are not modified by this function.
- *
- * Parameters:
- *
- * dx - Integer that specifies the x-coordinate of the translation.
- * dy - Integer that specifies the y-coordinate of the translation.
- */
-mxGeometry.prototype.translate = function(dx, dy)
-{
- var clone = this.clone();
-
- // Translates the geometry
- if (!this.relative)
- {
- this.x += dx;
- this.y += dy;
- }
-
- // Translates the source point
- if (this.sourcePoint != null)
- {
- this.sourcePoint.x += dx;
- this.sourcePoint.y += dy;
- }
-
- // Translates the target point
- if (this.targetPoint != null)
- {
- this.targetPoint.x += dx;
- this.targetPoint.y += dy;
- }
-
- // Translate the control points
- if (this.TRANSLATE_CONTROL_POINTS &&
- this.points != null)
- {
- var count = this.points.length;
-
- for (var i = 0; i < count; i++)
- {
- var pt = this.points[i];
-
- if (pt != null)
- {
- pt.x += dx;
- pt.y += dy;
- }
- }
- }
-};
diff --git a/src/js/model/mxGraphModel.js b/src/js/model/mxGraphModel.js
deleted file mode 100644
index c65c0e1..0000000
--- a/src/js/model/mxGraphModel.js
+++ /dev/null
@@ -1,2622 +0,0 @@
-/**
- * $Id: mxGraphModel.js,v 1.125 2012-04-16 10:48:43 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraphModel
- *
- * Extends <mxEventSource> to implement a graph model. The graph model acts as
- * a wrapper around the cells which are in charge of storing the actual graph
- * datastructure. The model acts as a transactional wrapper with event
- * notification for all changes, whereas the cells contain the atomic
- * operations for updating the actual datastructure.
- *
- * Layers:
- *
- * The cell hierarchy in the model must have a top-level root cell which
- * contains the layers (typically one default layer), which in turn contain the
- * top-level cells of the layers. This means each cell is contained in a layer.
- * If no layers are required, then all new cells should be added to the default
- * layer.
- *
- * Layers are useful for hiding and showing groups of cells, or for placing
- * groups of cells on top of other cells in the display. To identify a layer,
- * the <isLayer> function is used. It returns true if the parent of the given
- * cell is the root of the model.
- *
- * Encoding the model:
- *
- * To encode a graph model, use the following code:
- *
- * (code)
- * var enc = new mxCodec();
- * var node = enc.encode(graph.getModel());
- * (end)
- *
- * This will create an XML node that contains all the model information.
- *
- * Encoding and decoding changes:
- *
- * For the encoding of changes, a graph model listener is required that encodes
- * each change from the given array of changes.
- *
- * (code)
- * model.addListener(mxEvent.CHANGE, function(sender, evt)
- * {
- * var changes = evt.getProperty('edit').changes;
- * var nodes = [];
- * var codec = new mxCodec();
- *
- * for (var i = 0; i < changes.length; i++)
- * {
- * nodes.push(codec.encode(changes[i]));
- * }
- * // do something with the nodes
- * });
- * (end)
- *
- * For the decoding and execution of changes, the codec needs a lookup function
- * that allows it to resolve cell IDs as follows:
- *
- * (code)
- * var codec = new mxCodec();
- * codec.lookup = function(id)
- * {
- * return model.getCell(id);
- * }
- * (end)
- *
- * For each encoded change (represented by a node), the following code can be
- * used to carry out the decoding and create a change object.
- *
- * (code)
- * var changes = [];
- * var change = codec.decode(node);
- * change.model = model;
- * change.execute();
- * changes.push(change);
- * (end)
- *
- * The changes can then be dispatched using the model as follows.
- *
- * (code)
- * var edit = new mxUndoableEdit(model, false);
- * edit.changes = changes;
- *
- * edit.notify = function()
- * {
- * edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,
- * 'edit', edit, 'changes', edit.changes));
- * edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,
- * 'edit', edit, 'changes', edit.changes));
- * }
- *
- * model.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
- * model.fireEvent(new mxEventObject(mxEvent.CHANGE,
- * 'edit', edit, 'changes', changes));
- * (end)
- *
- * Event: mxEvent.CHANGE
- *
- * Fires when an undoable edit is dispatched. The <code>edit</code> property
- * contains the <mxUndoableEdit>. The <code>changes</code> property contains
- * the array of atomic changes inside the undoable edit. The changes property
- * is <strong>deprecated</strong>, please use edit.changes instead.
- *
- * Example:
- *
- * For finding newly inserted cells, the following code can be used:
- *
- * (code)
- * graph.model.addListener(mxEvent.CHANGE, function(sender, evt)
- * {
- * var changes = evt.getProperty('edit').changes;
- *
- * for (var i = 0; i < changes.length; i++)
- * {
- * var change = changes[i];
- *
- * if (change instanceof mxChildChange &&
- * change.change.previous == null)
- * {
- * graph.startEditingAtCell(change.child);
- * break;
- * }
- * }
- * });
- * (end)
- *
- *
- * Event: mxEvent.NOTIFY
- *
- * Same as <mxEvent.CHANGE>, this event can be used for classes that need to
- * implement a sync mechanism between this model and, say, a remote model. In
- * such a setup, only local changes should trigger a notify event and all
- * changes should trigger a change event.
- *
- * Event: mxEvent.EXECUTE
- *
- * Fires between begin- and endUpdate and after an atomic change was executed
- * in the model. The <code>change</code> property contains the atomic change
- * that was executed.
- *
- * Event: mxEvent.BEGIN_UPDATE
- *
- * Fires after the <updateLevel> was incremented in <beginUpdate>. This event
- * contains no properties.
- *
- * Event: mxEvent.END_UPDATE
- *
- * Fires after the <updateLevel> was decreased in <endUpdate> but before any
- * notification or change dispatching. The <code>edit</code> property contains
- * the <currentEdit>.
- *
- * Event: mxEvent.BEFORE_UNDO
- *
- * Fires before the change is dispatched after the update level has reached 0
- * in <endUpdate>. The <code>edit</code> property contains the <curreneEdit>.
- *
- * Event: mxEvent.UNDO
- *
- * Fires after the change was dispatched in <endUpdate>. The <code>edit</code>
- * property contains the <currentEdit>.
- *
- * Constructor: mxGraphModel
- *
- * Constructs a new graph model. If no root is specified then a new root
- * <mxCell> with a default layer is created.
- *
- * Parameters:
- *
- * root - <mxCell> that represents the root cell.
- */
-function mxGraphModel(root)
-{
- this.currentEdit = this.createUndoableEdit();
-
- if (root != null)
- {
- this.setRoot(root);
- }
- else
- {
- this.clear();
- }
-};
-
-/**
- * Extends mxEventSource.
- */
-mxGraphModel.prototype = new mxEventSource();
-mxGraphModel.prototype.constructor = mxGraphModel;
-
-/**
- * Variable: root
- *
- * Holds the root cell, which in turn contains the cells that represent the
- * layers of the diagram as child cells. That is, the actual elements of the
- * diagram are supposed to live in the third generation of cells and below.
- */
-mxGraphModel.prototype.root = null;
-
-/**
- * Variable: cells
- *
- * Maps from Ids to cells.
- */
-mxGraphModel.prototype.cells = null;
-
-/**
- * Variable: maintainEdgeParent
- *
- * Specifies if edges should automatically be moved into the nearest common
- * ancestor of their terminals. Default is true.
- */
-mxGraphModel.prototype.maintainEdgeParent = true;
-
-/**
- * Variable: createIds
- *
- * Specifies if the model should automatically create Ids for new cells.
- * Default is true.
- */
-mxGraphModel.prototype.createIds = true;
-
-/**
- * Variable: prefix
- *
- * Defines the prefix of new Ids. Default is an empty string.
- */
-mxGraphModel.prototype.prefix = '';
-
-/**
- * Variable: postfix
- *
- * Defines the postfix of new Ids. Default is an empty string.
- */
-mxGraphModel.prototype.postfix = '';
-
-/**
- * Variable: nextId
- *
- * Specifies the next Id to be created. Initial value is 0.
- */
-mxGraphModel.prototype.nextId = 0;
-
-/**
- * Variable: currentEdit
- *
- * Holds the changes for the current transaction. If the transaction is
- * closed then a new object is created for this variable using
- * <createUndoableEdit>.
- */
-mxGraphModel.prototype.currentEdit = null;
-
-/**
- * Variable: updateLevel
- *
- * Counter for the depth of nested transactions. Each call to <beginUpdate>
- * will increment this number and each call to <endUpdate> will decrement
- * it. When the counter reaches 0, the transaction is closed and the
- * respective events are fired. Initial value is 0.
- */
-mxGraphModel.prototype.updateLevel = 0;
-
-/**
- * Variable: endingUpdate
- *
- * True if the program flow is currently inside endUpdate.
- */
-mxGraphModel.prototype.endingUpdate = false;
-
-/**
- * Function: clear
- *
- * Sets a new root using <createRoot>.
- */
-mxGraphModel.prototype.clear = function()
-{
- this.setRoot(this.createRoot());
-};
-
-/**
- * Function: isCreateIds
- *
- * Returns <createIds>.
- */
-mxGraphModel.prototype.isCreateIds = function()
-{
- return this.createIds;
-};
-
-/**
- * Function: setCreateIds
- *
- * Sets <createIds>.
- */
-mxGraphModel.prototype.setCreateIds = function(value)
-{
- this.createIds = value;
-};
-
-/**
- * Function: createRoot
- *
- * Creates a new root cell with a default layer (child 0).
- */
-mxGraphModel.prototype.createRoot = function()
-{
- var cell = new mxCell();
- cell.insert(new mxCell());
-
- return cell;
-};
-
-/**
- * Function: getCell
- *
- * Returns the <mxCell> for the specified Id or null if no cell can be
- * found for the given Id.
- *
- * Parameters:
- *
- * id - A string representing the Id of the cell.
- */
-mxGraphModel.prototype.getCell = function(id)
-{
- return (this.cells != null) ? this.cells[id] : null;
-};
-
-/**
- * Function: filterCells
- *
- * Returns the cells from the given array where the fiven filter function
- * returns true.
- */
-mxGraphModel.prototype.filterCells = function(cells, filter)
-{
- var result = null;
-
- if (cells != null)
- {
- result = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- if (filter(cells[i]))
- {
- result.push(cells[i]);
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: getDescendants
- *
- * Returns all descendants of the given cell and the cell itself in an array.
- *
- * Parameters:
- *
- * parent - <mxCell> whose descendants should be returned.
- */
-mxGraphModel.prototype.getDescendants = function(parent)
-{
- return this.filterDescendants(null, parent);
-};
-
-/**
- * Function: filterDescendants
- *
- * Visits all cells recursively and applies the specified filter function
- * to each cell. If the function returns true then the cell is added
- * to the resulting array. The parent and result paramters are optional.
- * If parent is not specified then the recursion starts at <root>.
- *
- * Example:
- * The following example extracts all vertices from a given model:
- * (code)
- * var filter = function(cell)
- * {
- * return model.isVertex(cell);
- * }
- * var vertices = model.filterDescendants(filter);
- * (code)
- *
- * Parameters:
- *
- * filter - JavaScript function that takes an <mxCell> as an argument
- * and returns a boolean.
- * parent - Optional <mxCell> that is used as the root of the recursion.
- */
-mxGraphModel.prototype.filterDescendants = function(filter, parent)
-{
- // Creates a new array for storing the result
- var result = [];
-
- // Recursion starts at the root of the model
- parent = parent || this.getRoot();
-
- // Checks if the filter returns true for the cell
- // and adds it to the result array
- if (filter == null || filter(parent))
- {
- result.push(parent);
- }
-
- // Visits the children of the cell
- var childCount = this.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = this.getChildAt(parent, i);
- result = result.concat(this.filterDescendants(filter, child));
- }
-
- return result;
-};
-
-/**
- * Function: getRoot
- *
- * Returns the root of the model or the topmost parent of the given cell.
- *
- * Parameters:
- *
- * cell - Optional <mxCell> that specifies the child.
- */
-mxGraphModel.prototype.getRoot = function(cell)
-{
- var root = cell || this.root;
-
- if (cell != null)
- {
- while (cell != null)
- {
- root = cell;
- cell = this.getParent(cell);
- }
- }
-
- return root;
-};
-
-/**
- * Function: setRoot
- *
- * Sets the <root> of the model using <mxRootChange> and adds the change to
- * the current transaction. This resets all datastructures in the model and
- * is the preferred way of clearing an existing model. Returns the new
- * root.
- *
- * Example:
- *
- * (code)
- * var root = new mxCell();
- * root.insert(new mxCell());
- * model.setRoot(root);
- * (end)
- *
- * Parameters:
- *
- * root - <mxCell> that specifies the new root.
- */
-mxGraphModel.prototype.setRoot = function(root)
-{
- this.execute(new mxRootChange(this, root));
-
- return root;
-};
-
-/**
- * Function: rootChanged
- *
- * Inner callback to change the root of the model and update the internal
- * datastructures, such as <cells> and <nextId>. Returns the previous root.
- *
- * Parameters:
- *
- * root - <mxCell> that specifies the new root.
- */
-mxGraphModel.prototype.rootChanged = function(root)
-{
- var oldRoot = this.root;
- this.root = root;
-
- // Resets counters and datastructures
- this.nextId = 0;
- this.cells = null;
- this.cellAdded(root);
-
- return oldRoot;
-};
-
-/**
- * Function: isRoot
- *
- * Returns true if the given cell is the root of the model and a non-null
- * value.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the possible root.
- */
-mxGraphModel.prototype.isRoot = function(cell)
-{
- return cell != null && this.root == cell;
-};
-
-/**
- * Function: isLayer
- *
- * Returns true if <isRoot> returns true for the parent of the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the possible layer.
- */
-mxGraphModel.prototype.isLayer = function(cell)
-{
- return this.isRoot(this.getParent(cell));
-};
-
-/**
- * Function: isAncestor
- *
- * Returns true if the given parent is an ancestor of the given child.
- *
- * Parameters:
- *
- * parent - <mxCell> that specifies the parent.
- * child - <mxCell> that specifies the child.
- */
-mxGraphModel.prototype.isAncestor = function(parent, child)
-{
- while (child != null && child != parent)
- {
- child = this.getParent(child);
- }
-
- return child == parent;
-};
-
-/**
- * Function: contains
- *
- * Returns true if the model contains the given <mxCell>.
- *
- * Parameters:
- *
- * cell - <mxCell> that specifies the cell.
- */
-mxGraphModel.prototype.contains = function(cell)
-{
- return this.isAncestor(this.root, cell);
-};
-
-/**
- * Function: getParent
- *
- * Returns the parent of the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> whose parent should be returned.
- */
-mxGraphModel.prototype.getParent = function(cell)
-{
- return (cell != null) ? cell.getParent() : null;
-};
-
-/**
- * Function: add
- *
- * Adds the specified child to the parent at the given index using
- * <mxChildChange> and adds the change to the current transaction. If no
- * index is specified then the child is appended to the parent's array of
- * children. Returns the inserted child.
- *
- * Parameters:
- *
- * parent - <mxCell> that specifies the parent to contain the child.
- * child - <mxCell> that specifies the child to be inserted.
- * index - Optional integer that specifies the index of the child.
- */
-mxGraphModel.prototype.add = function(parent, child, index)
-{
- if (child != parent && parent != null && child != null)
- {
- // Appends the child if no index was specified
- if (index == null)
- {
- index = this.getChildCount(parent);
- }
-
- var parentChanged = parent != this.getParent(child);
- this.execute(new mxChildChange(this, parent, child, index));
-
- // Maintains the edges parents by moving the edges
- // into the nearest common ancestor of its
- // terminals
- if (this.maintainEdgeParent && parentChanged)
- {
- this.updateEdgeParents(child);
- }
- }
-
- return child;
-};
-
-/**
- * Function: cellAdded
- *
- * Inner callback to update <cells> when a cell has been added. This
- * implementation resolves collisions by creating new Ids. To change the
- * ID of a cell after it was inserted into the model, use the following
- * code:
- *
- * (code
- * delete model.cells[cell.getId()];
- * cell.setId(newId);
- * model.cells[cell.getId()] = cell;
- * (end)
- *
- * If the change of the ID should be part of the command history, then the
- * cell should be removed from the model and a clone with the new ID should
- * be reinserted into the model instead.
- *
- * Parameters:
- *
- * cell - <mxCell> that specifies the cell that has been added.
- */
-mxGraphModel.prototype.cellAdded = function(cell)
-{
- if (cell != null)
- {
- // Creates an Id for the cell if not Id exists
- if (cell.getId() == null && this.createIds)
- {
- cell.setId(this.createId(cell));
- }
-
- if (cell.getId() != null)
- {
- var collision = this.getCell(cell.getId());
-
- if (collision != cell)
- {
- // Creates new Id for the cell
- // as long as there is a collision
- while (collision != null)
- {
- cell.setId(this.createId(cell));
- collision = this.getCell(cell.getId());
- }
-
- // Lazily creates the cells dictionary
- if (this.cells == null)
- {
- this.cells = new Object();
- }
-
- this.cells[cell.getId()] = cell;
- }
- }
-
- // Makes sure IDs of deleted cells are not reused
- if (mxUtils.isNumeric(cell.getId()))
- {
- this.nextId = Math.max(this.nextId, cell.getId());
- }
-
- // Recursively processes child cells
- var childCount = this.getChildCount(cell);
-
- for (var i=0; i<childCount; i++)
- {
- this.cellAdded(this.getChildAt(cell, i));
- }
- }
-};
-
-/**
- * Function: createId
- *
- * Hook method to create an Id for the specified cell. This implementation
- * concatenates <prefix>, id and <postfix> to create the Id and increments
- * <nextId>. The cell is ignored by this implementation, but can be used in
- * overridden methods to prefix the Ids with eg. the cell type.
- *
- * Parameters:
- *
- * cell - <mxCell> to create the Id for.
- */
-mxGraphModel.prototype.createId = function(cell)
-{
- var id = this.nextId;
- this.nextId++;
-
- return this.prefix + id + this.postfix;
-};
-
-/**
- * Function: updateEdgeParents
- *
- * Updates the parent for all edges that are connected to cell or one of
- * its descendants using <updateEdgeParent>.
- */
-mxGraphModel.prototype.updateEdgeParents = function(cell, root)
-{
- // Gets the topmost node of the hierarchy
- root = root || this.getRoot(cell);
-
- // Updates edges on children first
- var childCount = this.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = this.getChildAt(cell, i);
- this.updateEdgeParents(child, root);
- }
-
- // Updates the parents of all connected edges
- var edgeCount = this.getEdgeCount(cell);
- var edges = [];
-
- for (var i = 0; i < edgeCount; i++)
- {
- edges.push(this.getEdgeAt(cell, i));
- }
-
- for (var i = 0; i < edges.length; i++)
- {
- var edge = edges[i];
-
- // Updates edge parent if edge and child have
- // a common root node (does not need to be the
- // model root node)
- if (this.isAncestor(root, edge))
- {
- this.updateEdgeParent(edge, root);
- }
- }
-};
-
-/**
- * Function: updateEdgeParent
- *
- * Inner callback to update the parent of the specified <mxCell> to the
- * nearest-common-ancestor of its two terminals.
- *
- * Parameters:
- *
- * edge - <mxCell> that specifies the edge.
- * root - <mxCell> that represents the current root of the model.
- */
-mxGraphModel.prototype.updateEdgeParent = function(edge, root)
-{
- var source = this.getTerminal(edge, true);
- var target = this.getTerminal(edge, false);
- var cell = null;
-
- // Uses the first non-relative descendants of the source terminal
- while (source != null && !this.isEdge(source) &&
- source.geometry != null && source.geometry.relative)
- {
- source = this.getParent(source);
- }
-
- // Uses the first non-relative descendants of the target terminal
- while (target != null && !this.isEdge(target) &&
- target.geometry != null && target.geometry.relative)
- {
- target = this.getParent(target);
- }
-
- if (this.isAncestor(root, source) && this.isAncestor(root, target))
- {
- if (source == target)
- {
- cell = this.getParent(source);
- }
- else
- {
- cell = this.getNearestCommonAncestor(source, target);
- }
-
- if (cell != null && (this.getParent(cell) != this.root ||
- this.isAncestor(cell, edge)) && this.getParent(edge) != cell)
- {
- var geo = this.getGeometry(edge);
-
- if (geo != null)
- {
- var origin1 = this.getOrigin(this.getParent(edge));
- var origin2 = this.getOrigin(cell);
-
- var dx = origin2.x - origin1.x;
- var dy = origin2.y - origin1.y;
-
- geo = geo.clone();
- geo.translate(-dx, -dy);
- this.setGeometry(edge, geo);
- }
-
- this.add(cell, edge, this.getChildCount(cell));
- }
- }
-};
-
-/**
- * Function: getOrigin
- *
- * Returns the absolute, accumulated origin for the children inside the
- * given parent as an <mxPoint>.
- */
-mxGraphModel.prototype.getOrigin = function(cell)
-{
- var result = null;
-
- if (cell != null)
- {
- result = this.getOrigin(this.getParent(cell));
-
- if (!this.isEdge(cell))
- {
- var geo = this.getGeometry(cell);
-
- if (geo != null)
- {
- result.x += geo.x;
- result.y += geo.y;
- }
- }
- }
- else
- {
- result = new mxPoint();
- }
-
- return result;
-};
-
-/**
- * Function: getNearestCommonAncestor
- *
- * Returns the nearest common ancestor for the specified cells.
- *
- * Parameters:
- *
- * cell1 - <mxCell> that specifies the first cell in the tree.
- * cell2 - <mxCell> that specifies the second cell in the tree.
- */
-mxGraphModel.prototype.getNearestCommonAncestor = function(cell1, cell2)
-{
- if (cell1 != null && cell2 != null)
- {
- // Creates the cell path for the second cell
- var path = mxCellPath.create(cell2);
-
- if (path != null && path.length > 0)
- {
- // Bubbles through the ancestors of the first
- // cell to find the nearest common ancestor.
- var cell = cell1;
- var current = mxCellPath.create(cell);
-
- // Inverts arguments
- if (path.length < current.length)
- {
- cell = cell2;
- var tmp = current;
- current = path;
- path = tmp;
- }
-
- while (cell != null)
- {
- var parent = this.getParent(cell);
-
- // Checks if the cell path is equal to the beginning of the given cell path
- if (path.indexOf(current + mxCellPath.PATH_SEPARATOR) == 0 && parent != null)
- {
- return cell;
- }
-
- current = mxCellPath.getParentPath(current);
- cell = parent;
- }
- }
- }
-
- return null;
-};
-
-/**
- * Function: remove
- *
- * Removes the specified cell from the model using <mxChildChange> and adds
- * the change to the current transaction. This operation will remove the
- * cell and all of its children from the model. Returns the removed cell.
- *
- * Parameters:
- *
- * cell - <mxCell> that should be removed.
- */
-mxGraphModel.prototype.remove = function(cell)
-{
- if (cell == this.root)
- {
- this.setRoot(null);
- }
- else if (this.getParent(cell) != null)
- {
- this.execute(new mxChildChange(this, null, cell));
- }
-
- return cell;
-};
-
-/**
- * Function: cellRemoved
- *
- * Inner callback to update <cells> when a cell has been removed.
- *
- * Parameters:
- *
- * cell - <mxCell> that specifies the cell that has been removed.
- */
-mxGraphModel.prototype.cellRemoved = function(cell)
-{
- if (cell != null && this.cells != null)
- {
- // Recursively processes child cells
- var childCount = this.getChildCount(cell);
-
- for (var i = childCount - 1; i >= 0; i--)
- {
- this.cellRemoved(this.getChildAt(cell, i));
- }
-
- // Removes the dictionary entry for the cell
- if (this.cells != null && cell.getId() != null)
- {
- delete this.cells[cell.getId()];
- }
- }
-};
-
-/**
- * Function: parentForCellChanged
- *
- * Inner callback to update the parent of a cell using <mxCell.insert>
- * on the parent and return the previous parent.
- *
- * Parameters:
- *
- * cell - <mxCell> to update the parent for.
- * parent - <mxCell> that specifies the new parent of the cell.
- * index - Optional integer that defines the index of the child
- * in the parent's child array.
- */
-mxGraphModel.prototype.parentForCellChanged = function(cell, parent, index)
-{
- var previous = this.getParent(cell);
-
- if (parent != null)
- {
- if (parent != previous || previous.getIndex(cell) != index)
- {
- parent.insert(cell, index);
- }
- }
- else if (previous != null)
- {
- var oldIndex = previous.getIndex(cell);
- previous.remove(oldIndex);
- }
-
- // Checks if the previous parent was already in the
- // model and avoids calling cellAdded if it was.
- if (!this.contains(previous) && parent != null)
- {
- this.cellAdded(cell);
- }
- else if (parent == null)
- {
- this.cellRemoved(cell);
- }
-
- return previous;
-};
-
-/**
- * Function: getChildCount
- *
- * Returns the number of children in the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> whose number of children should be returned.
- */
-mxGraphModel.prototype.getChildCount = function(cell)
-{
- return (cell != null) ? cell.getChildCount() : 0;
-};
-
-/**
- * Function: getChildAt
- *
- * Returns the child of the given <mxCell> at the given index.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the parent.
- * index - Integer that specifies the index of the child to be returned.
- */
-mxGraphModel.prototype.getChildAt = function(cell, index)
-{
- return (cell != null) ? cell.getChildAt(index) : null;
-};
-
-/**
- * Function: getChildren
- *
- * Returns all children of the given <mxCell> as an array of <mxCells>. The
- * return value should be only be read.
- *
- * Parameters:
- *
- * cell - <mxCell> the represents the parent.
- */
-mxGraphModel.prototype.getChildren = function(cell)
-{
- return (cell != null) ? cell.children : null;
-};
-
-/**
- * Function: getChildVertices
- *
- * Returns the child vertices of the given parent.
- *
- * Parameters:
- *
- * cell - <mxCell> whose child vertices should be returned.
- */
-mxGraphModel.prototype.getChildVertices = function(parent)
-{
- return this.getChildCells(parent, true, false);
-};
-
-/**
- * Function: getChildEdges
- *
- * Returns the child edges of the given parent.
- *
- * Parameters:
- *
- * cell - <mxCell> whose child edges should be returned.
- */
-mxGraphModel.prototype.getChildEdges = function(parent)
-{
- return this.getChildCells(parent, false, true);
-};
-
-/**
- * Function: getChildCells
- *
- * Returns the children of the given cell that are vertices and/or edges
- * depending on the arguments.
- *
- * Parameters:
- *
- * cell - <mxCell> the represents the parent.
- * vertices - Boolean indicating if child vertices should be returned.
- * Default is false.
- * edges - Boolean indicating if child edges should be returned.
- * Default is false.
- */
-mxGraphModel.prototype.getChildCells = function(parent, vertices, edges)
-{
- vertices = (vertices != null) ? vertices : false;
- edges = (edges != null) ? edges : false;
-
- var childCount = this.getChildCount(parent);
- var result = [];
-
- for (var i = 0; i < childCount; i++)
- {
- var child = this.getChildAt(parent, i);
-
- if ((!edges && !vertices) || (edges && this.isEdge(child)) ||
- (vertices && this.isVertex(child)))
- {
- result.push(child);
- }
- }
-
- return result;
-};
-
-/**
- * Function: getTerminal
- *
- * Returns the source or target <mxCell> of the given edge depending on the
- * value of the boolean parameter.
- *
- * Parameters:
- *
- * edge - <mxCell> that specifies the edge.
- * isSource - Boolean indicating which end of the edge should be returned.
- */
-mxGraphModel.prototype.getTerminal = function(edge, isSource)
-{
- return (edge != null) ? edge.getTerminal(isSource) : null;
-};
-
-/**
- * Function: setTerminal
- *
- * Sets the source or target terminal of the given <mxCell> using
- * <mxTerminalChange> and adds the change to the current transaction.
- * This implementation updates the parent of the edge using <updateEdgeParent>
- * if required.
- *
- * Parameters:
- *
- * edge - <mxCell> that specifies the edge.
- * terminal - <mxCell> that specifies the new terminal.
- * isSource - Boolean indicating if the terminal is the new source or
- * target terminal of the edge.
- */
-mxGraphModel.prototype.setTerminal = function(edge, terminal, isSource)
-{
- var terminalChanged = terminal != this.getTerminal(edge, isSource);
- this.execute(new mxTerminalChange(this, edge, terminal, isSource));
-
- if (this.maintainEdgeParent && terminalChanged)
- {
- this.updateEdgeParent(edge, this.getRoot());
- }
-
- return terminal;
-};
-
-/**
- * Function: setTerminals
- *
- * Sets the source and target <mxCell> of the given <mxCell> in a single
- * transaction using <setTerminal> for each end of the edge.
- *
- * Parameters:
- *
- * edge - <mxCell> that specifies the edge.
- * source - <mxCell> that specifies the new source terminal.
- * target - <mxCell> that specifies the new target terminal.
- */
-mxGraphModel.prototype.setTerminals = function(edge, source, target)
-{
- this.beginUpdate();
- try
- {
- this.setTerminal(edge, source, true);
- this.setTerminal(edge, target, false);
- }
- finally
- {
- this.endUpdate();
- }
-};
-
-/**
- * Function: terminalForCellChanged
- *
- * Inner helper function to update the terminal of the edge using
- * <mxCell.insertEdge> and return the previous terminal.
- *
- * Parameters:
- *
- * edge - <mxCell> that specifies the edge to be updated.
- * terminal - <mxCell> that specifies the new terminal.
- * isSource - Boolean indicating if the terminal is the new source or
- * target terminal of the edge.
- */
-mxGraphModel.prototype.terminalForCellChanged = function(edge, terminal, isSource)
-{
- var previous = this.getTerminal(edge, isSource);
-
- if (terminal != null)
- {
- terminal.insertEdge(edge, isSource);
- }
- else if (previous != null)
- {
- previous.removeEdge(edge, isSource);
- }
-
- return previous;
-};
-
-/**
- * Function: getEdgeCount
- *
- * Returns the number of distinct edges connected to the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the vertex.
- */
-mxGraphModel.prototype.getEdgeCount = function(cell)
-{
- return (cell != null) ? cell.getEdgeCount() : 0;
-};
-
-/**
- * Function: getEdgeAt
- *
- * Returns the edge of cell at the given index.
- *
- * Parameters:
- *
- * cell - <mxCell> that specifies the vertex.
- * index - Integer that specifies the index of the edge
- * to return.
- */
-mxGraphModel.prototype.getEdgeAt = function(cell, index)
-{
- return (cell != null) ? cell.getEdgeAt(index) : null;
-};
-
-/**
- * Function: getDirectedEdgeCount
- *
- * Returns the number of incoming or outgoing edges, ignoring the given
- * edge.
- *
- * Parameters:
- *
- * cell - <mxCell> whose edge count should be returned.
- * outgoing - Boolean that specifies if the number of outgoing or
- * incoming edges should be returned.
- * ignoredEdge - <mxCell> that represents an edge to be ignored.
- */
-mxGraphModel.prototype.getDirectedEdgeCount = function(cell, outgoing, ignoredEdge)
-{
- var count = 0;
- var edgeCount = this.getEdgeCount(cell);
-
- for (var i = 0; i < edgeCount; i++)
- {
- var edge = this.getEdgeAt(cell, i);
-
- if (edge != ignoredEdge && this.getTerminal(edge, outgoing) == cell)
- {
- count++;
- }
- }
-
- return count;
-};
-
-/**
- * Function: getConnections
- *
- * Returns all edges of the given cell without loops.
- *
- * Parameters:
- *
- * cell - <mxCell> whose edges should be returned.
- *
- */
-mxGraphModel.prototype.getConnections = function(cell)
-{
- return this.getEdges(cell, true, true, false);
-};
-
-/**
- * Function: getIncomingEdges
- *
- * Returns the incoming edges of the given cell without loops.
- *
- * Parameters:
- *
- * cell - <mxCell> whose incoming edges should be returned.
- *
- */
-mxGraphModel.prototype.getIncomingEdges = function(cell)
-{
- return this.getEdges(cell, true, false, false);
-};
-
-/**
- * Function: getOutgoingEdges
- *
- * Returns the outgoing edges of the given cell without loops.
- *
- * Parameters:
- *
- * cell - <mxCell> whose outgoing edges should be returned.
- *
- */
-mxGraphModel.prototype.getOutgoingEdges = function(cell)
-{
- return this.getEdges(cell, false, true, false);
-};
-
-/**
- * Function: getEdges
- *
- * Returns all distinct edges connected to this cell as a new array of
- * <mxCells>. If at least one of incoming or outgoing is true, then loops
- * are ignored, otherwise if both are false, then all edges connected to
- * the given cell are returned including loops.
- *
- * Parameters:
- *
- * cell - <mxCell> that specifies the cell.
- * incoming - Optional boolean that specifies if incoming edges should be
- * returned. Default is true.
- * outgoing - Optional boolean that specifies if outgoing edges should be
- * returned. Default is true.
- * includeLoops - Optional boolean that specifies if loops should be returned.
- * Default is true.
- */
-mxGraphModel.prototype.getEdges = function(cell, incoming, outgoing, includeLoops)
-{
- incoming = (incoming != null) ? incoming : true;
- outgoing = (outgoing != null) ? outgoing : true;
- includeLoops = (includeLoops != null) ? includeLoops : true;
-
- var edgeCount = this.getEdgeCount(cell);
- var result = [];
-
- for (var i = 0; i < edgeCount; i++)
- {
- var edge = this.getEdgeAt(cell, i);
- var source = this.getTerminal(edge, true);
- var target = this.getTerminal(edge, false);
-
- if ((includeLoops && source == target) || ((source != target) && ((incoming && target == cell) ||
- (outgoing && source == cell))))
- {
- result.push(edge);
- }
- }
-
- return result;
-};
-
-/**
- * Function: getEdgesBetween
- *
- * Returns all edges between the given source and target pair. If directed
- * is true, then only edges from the source to the target are returned,
- * otherwise, all edges between the two cells are returned.
- *
- * Parameters:
- *
- * source - <mxCell> that defines the source terminal of the edge to be
- * returned.
- * target - <mxCell> that defines the target terminal of the edge to be
- * returned.
- * directed - Optional boolean that specifies if the direction of the
- * edge should be taken into account. Default is false.
- */
-mxGraphModel.prototype.getEdgesBetween = function(source, target, directed)
-{
- directed = (directed != null) ? directed : false;
-
- var tmp1 = this.getEdgeCount(source);
- var tmp2 = this.getEdgeCount(target);
-
- // Assumes the source has less connected edges
- var terminal = source;
- var edgeCount = tmp1;
-
- // Uses the smaller array of connected edges
- // for searching the edge
- if (tmp2 < tmp1)
- {
- edgeCount = tmp2;
- terminal = target;
- }
-
- var result = [];
-
- // Checks if the edge is connected to the correct
- // cell and returns the first match
- for (var i = 0; i < edgeCount; i++)
- {
- var edge = this.getEdgeAt(terminal, i);
- var src = this.getTerminal(edge, true);
- var trg = this.getTerminal(edge, false);
- var directedMatch = (src == source) && (trg == target);
- var oppositeMatch = (trg == source) && (src == target);
-
- if (directedMatch || (!directed && oppositeMatch))
- {
- result.push(edge);
- }
- }
-
- return result;
-};
-
-/**
- * Function: getOpposites
- *
- * Returns all opposite vertices wrt terminal for the given edges, only
- * returning sources and/or targets as specified. The result is returned
- * as an array of <mxCells>.
- *
- * Parameters:
- *
- * edges - Array of <mxCells> that contain the edges to be examined.
- * terminal - <mxCell> that specifies the known end of the edges.
- * sources - Boolean that specifies if source terminals should be contained
- * in the result. Default is true.
- * targets - Boolean that specifies if target terminals should be contained
- * in the result. Default is true.
- */
-mxGraphModel.prototype.getOpposites = function(edges, terminal, sources, targets)
-{
- sources = (sources != null) ? sources : true;
- targets = (targets != null) ? targets : true;
-
- var terminals = [];
-
- if (edges != null)
- {
- for (var i = 0; i < edges.length; i++)
- {
- var source = this.getTerminal(edges[i], true);
- var target = this.getTerminal(edges[i], false);
-
- // Checks if the terminal is the source of
- // the edge and if the target should be
- // stored in the result
- if (source == terminal && target != null && target != terminal && targets)
- {
- terminals.push(target);
- }
-
- // Checks if the terminal is the taget of
- // the edge and if the source should be
- // stored in the result
- else if (target == terminal && source != null && source != terminal && sources)
- {
- terminals.push(source);
- }
- }
- }
-
- return terminals;
-};
-
-/**
- * Function: getTopmostCells
- *
- * Returns the topmost cells of the hierarchy in an array that contains no
- * descendants for each <mxCell> that it contains. Duplicates should be
- * removed in the cells array to improve performance.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> whose topmost ancestors should be returned.
- */
-mxGraphModel.prototype.getTopmostCells = function(cells)
-{
- var tmp = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- var cell = cells[i];
- var topmost = true;
- var parent = this.getParent(cell);
-
- while (parent != null)
- {
- if (mxUtils.indexOf(cells, parent) >= 0)
- {
- topmost = false;
- break;
- }
-
- parent = this.getParent(parent);
- }
-
- if (topmost)
- {
- tmp.push(cell);
- }
- }
-
- return tmp;
-};
-
-/**
- * Function: isVertex
- *
- * Returns true if the given cell is a vertex.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the possible vertex.
- */
-mxGraphModel.prototype.isVertex = function(cell)
-{
- return (cell != null) ? cell.isVertex() : false;
-};
-
-/**
- * Function: isEdge
- *
- * Returns true if the given cell is an edge.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the possible edge.
- */
-mxGraphModel.prototype.isEdge = function(cell)
-{
- return (cell != null) ? cell.isEdge() : false;
-};
-
-/**
- * Function: isConnectable
- *
- * Returns true if the given <mxCell> is connectable. If <edgesConnectable>
- * is false, then this function returns false for all edges else it returns
- * the return value of <mxCell.isConnectable>.
- *
- * Parameters:
- *
- * cell - <mxCell> whose connectable state should be returned.
- */
-mxGraphModel.prototype.isConnectable = function(cell)
-{
- return (cell != null) ? cell.isConnectable() : false;
-};
-
-/**
- * Function: getValue
- *
- * Returns the user object of the given <mxCell> using <mxCell.getValue>.
- *
- * Parameters:
- *
- * cell - <mxCell> whose user object should be returned.
- */
-mxGraphModel.prototype.getValue = function(cell)
-{
- return (cell != null) ? cell.getValue() : null;
-};
-
-/**
- * Function: setValue
- *
- * Sets the user object of then given <mxCell> using <mxValueChange>
- * and adds the change to the current transaction.
- *
- * Parameters:
- *
- * cell - <mxCell> whose user object should be changed.
- * value - Object that defines the new user object.
- */
-mxGraphModel.prototype.setValue = function(cell, value)
-{
- this.execute(new mxValueChange(this, cell, value));
-
- return value;
-};
-
-/**
- * Function: valueForCellChanged
- *
- * Inner callback to update the user object of the given <mxCell>
- * using <mxCell.valueChanged> and return the previous value,
- * that is, the return value of <mxCell.valueChanged>.
- *
- * To change a specific attribute in an XML node, the following code can be
- * used.
- *
- * (code)
- * graph.getModel().valueForCellChanged = function(cell, value)
- * {
- * var previous = cell.value.getAttribute('label');
- * cell.value.setAttribute('label', value);
- *
- * return previous;
- * };
- * (end)
- */
-mxGraphModel.prototype.valueForCellChanged = function(cell, value)
-{
- return cell.valueChanged(value);
-};
-
-/**
- * Function: getGeometry
- *
- * Returns the <mxGeometry> of the given <mxCell>.
- *
- * Parameters:
- *
- * cell - <mxCell> whose geometry should be returned.
- */
-mxGraphModel.prototype.getGeometry = function(cell, geometry)
-{
- return (cell != null) ? cell.getGeometry() : null;
-};
-
-/**
- * Function: setGeometry
- *
- * Sets the <mxGeometry> of the given <mxCell>. The actual update
- * of the cell is carried out in <geometryForCellChanged>. The
- * <mxGeometryChange> action is used to encapsulate the change.
- *
- * Parameters:
- *
- * cell - <mxCell> whose geometry should be changed.
- * geometry - <mxGeometry> that defines the new geometry.
- */
-mxGraphModel.prototype.setGeometry = function(cell, geometry)
-{
- if (geometry != this.getGeometry(cell))
- {
- this.execute(new mxGeometryChange(this, cell, geometry));
- }
-
- return geometry;
-};
-
-/**
- * Function: geometryForCellChanged
- *
- * Inner callback to update the <mxGeometry> of the given <mxCell> using
- * <mxCell.setGeometry> and return the previous <mxGeometry>.
- */
-mxGraphModel.prototype.geometryForCellChanged = function(cell, geometry)
-{
- var previous = this.getGeometry(cell);
- cell.setGeometry(geometry);
-
- return previous;
-};
-
-/**
- * Function: getStyle
- *
- * Returns the style of the given <mxCell>.
- *
- * Parameters:
- *
- * cell - <mxCell> whose style should be returned.
- */
-mxGraphModel.prototype.getStyle = function(cell)
-{
- return (cell != null) ? cell.getStyle() : null;
-};
-
-/**
- * Function: setStyle
- *
- * Sets the style of the given <mxCell> using <mxStyleChange> and
- * adds the change to the current transaction.
- *
- * Parameters:
- *
- * cell - <mxCell> whose style should be changed.
- * style - String of the form [stylename;|key=value;] to specify
- * the new cell style.
- */
-mxGraphModel.prototype.setStyle = function(cell, style)
-{
- if (style != this.getStyle(cell))
- {
- this.execute(new mxStyleChange(this, cell, style));
- }
-
- return style;
-};
-
-/**
- * Function: styleForCellChanged
- *
- * Inner callback to update the style of the given <mxCell>
- * using <mxCell.setStyle> and return the previous style.
- *
- * Parameters:
- *
- * cell - <mxCell> that specifies the cell to be updated.
- * style - String of the form [stylename;|key=value;] to specify
- * the new cell style.
- */
-mxGraphModel.prototype.styleForCellChanged = function(cell, style)
-{
- var previous = this.getStyle(cell);
- cell.setStyle(style);
-
- return previous;
-};
-
-/**
- * Function: isCollapsed
- *
- * Returns true if the given <mxCell> is collapsed.
- *
- * Parameters:
- *
- * cell - <mxCell> whose collapsed state should be returned.
- */
-mxGraphModel.prototype.isCollapsed = function(cell)
-{
- return (cell != null) ? cell.isCollapsed() : false;
-};
-
-/**
- * Function: setCollapsed
- *
- * Sets the collapsed state of the given <mxCell> using <mxCollapseChange>
- * and adds the change to the current transaction.
- *
- * Parameters:
- *
- * cell - <mxCell> whose collapsed state should be changed.
- * collapsed - Boolean that specifies the new collpased state.
- */
-mxGraphModel.prototype.setCollapsed = function(cell, collapsed)
-{
- if (collapsed != this.isCollapsed(cell))
- {
- this.execute(new mxCollapseChange(this, cell, collapsed));
- }
-
- return collapsed;
-};
-
-/**
- * Function: collapsedStateForCellChanged
- *
- * Inner callback to update the collapsed state of the
- * given <mxCell> using <mxCell.setCollapsed> and return
- * the previous collapsed state.
- *
- * Parameters:
- *
- * cell - <mxCell> that specifies the cell to be updated.
- * collapsed - Boolean that specifies the new collpased state.
- */
-mxGraphModel.prototype.collapsedStateForCellChanged = function(cell, collapsed)
-{
- var previous = this.isCollapsed(cell);
- cell.setCollapsed(collapsed);
-
- return previous;
-};
-
-/**
- * Function: isVisible
- *
- * Returns true if the given <mxCell> is visible.
- *
- * Parameters:
- *
- * cell - <mxCell> whose visible state should be returned.
- */
-mxGraphModel.prototype.isVisible = function(cell)
-{
- return (cell != null) ? cell.isVisible() : false;
-};
-
-/**
- * Function: setVisible
- *
- * Sets the visible state of the given <mxCell> using <mxVisibleChange> and
- * adds the change to the current transaction.
- *
- * Parameters:
- *
- * cell - <mxCell> whose visible state should be changed.
- * visible - Boolean that specifies the new visible state.
- */
-mxGraphModel.prototype.setVisible = function(cell, visible)
-{
- if (visible != this.isVisible(cell))
- {
- this.execute(new mxVisibleChange(this, cell, visible));
- }
-
- return visible;
-};
-
-/**
- * Function: visibleStateForCellChanged
- *
- * Inner callback to update the visible state of the
- * given <mxCell> using <mxCell.setCollapsed> and return
- * the previous visible state.
- *
- * Parameters:
- *
- * cell - <mxCell> that specifies the cell to be updated.
- * visible - Boolean that specifies the new visible state.
- */
-mxGraphModel.prototype.visibleStateForCellChanged = function(cell, visible)
-{
- var previous = this.isVisible(cell);
- cell.setVisible(visible);
-
- return previous;
-};
-
-/**
- * Function: execute
- *
- * Executes the given edit and fires events if required. The edit object
- * requires an execute function which is invoked. The edit is added to the
- * <currentEdit> between <beginUpdate> and <endUpdate> calls, so that
- * events will be fired if this execute is an individual transaction, that
- * is, if no previous <beginUpdate> calls have been made without calling
- * <endUpdate>. This implementation fires an <execute> event before
- * executing the given change.
- *
- * Parameters:
- *
- * change - Object that described the change.
- */
-mxGraphModel.prototype.execute = function(change)
-{
- change.execute();
- this.beginUpdate();
- this.currentEdit.add(change);
- this.fireEvent(new mxEventObject(mxEvent.EXECUTE, 'change', change));
- this.endUpdate();
-};
-
-/**
- * Function: beginUpdate
- *
- * Increments the <updateLevel> by one. The event notification
- * is queued until <updateLevel> reaches 0 by use of
- * <endUpdate>.
- *
- * All changes on <mxGraphModel> are transactional,
- * that is, they are executed in a single undoable change
- * on the model (without transaction isolation).
- * Therefore, if you want to combine any
- * number of changes into a single undoable change,
- * you should group any two or more API calls that
- * modify the graph model between <beginUpdate>
- * and <endUpdate> calls as shown here:
- *
- * (code)
- * var model = graph.getModel();
- * var parent = graph.getDefaultParent();
- * var index = model.getChildCount(parent);
- * model.beginUpdate();
- * try
- * {
- * model.add(parent, v1, index);
- * model.add(parent, v2, index+1);
- * }
- * finally
- * {
- * model.endUpdate();
- * }
- * (end)
- *
- * Of course there is a shortcut for appending a
- * sequence of cells into the default parent:
- *
- * (code)
- * graph.addCells([v1, v2]).
- * (end)
- */
-mxGraphModel.prototype.beginUpdate = function()
-{
- this.updateLevel++;
- this.fireEvent(new mxEventObject(mxEvent.BEGIN_UPDATE));
-};
-
-/**
- * Function: endUpdate
- *
- * Decrements the <updateLevel> by one and fires an <undo>
- * event if the <updateLevel> reaches 0. This function
- * indirectly fires a <change> event by invoking the notify
- * function on the <currentEdit> und then creates a new
- * <currentEdit> using <createUndoableEdit>.
- *
- * The <undo> event is fired only once per edit, whereas
- * the <change> event is fired whenever the notify
- * function is invoked, that is, on undo and redo of
- * the edit.
- */
-mxGraphModel.prototype.endUpdate = function()
-{
- this.updateLevel--;
-
- if (!this.endingUpdate)
- {
- this.endingUpdate = this.updateLevel == 0;
- this.fireEvent(new mxEventObject(mxEvent.END_UPDATE, 'edit', this.currentEdit));
-
- try
- {
- if (this.endingUpdate && !this.currentEdit.isEmpty())
- {
- this.fireEvent(new mxEventObject(mxEvent.BEFORE_UNDO, 'edit', this.currentEdit));
- var tmp = this.currentEdit;
- this.currentEdit = this.createUndoableEdit();
- tmp.notify();
- this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', tmp));
- }
- }
- finally
- {
- this.endingUpdate = false;
- }
- }
-};
-
-/**
- * Function: createUndoableEdit
- *
- * Creates a new <mxUndoableEdit> that implements the
- * notify function to fire a <change> and <notify> event
- * through the <mxUndoableEdit>'s source.
- */
-mxGraphModel.prototype.createUndoableEdit = function()
-{
- var edit = new mxUndoableEdit(this, true);
-
- edit.notify = function()
- {
- // LATER: Remove changes property (deprecated)
- edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,
- 'edit', edit, 'changes', edit.changes));
- edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,
- 'edit', edit, 'changes', edit.changes));
- };
-
- return edit;
-};
-
-/**
- * Function: mergeChildren
- *
- * Merges the children of the given cell into the given target cell inside
- * this model. All cells are cloned unless there is a corresponding cell in
- * the model with the same id, in which case the source cell is ignored and
- * all edges are connected to the corresponding cell in this model. Edges
- * are considered to have no identity and are always cloned unless the
- * cloneAllEdges flag is set to false, in which case edges with the same
- * id in the target model are reconnected to reflect the terminals of the
- * source edges.
- */
-mxGraphModel.prototype.mergeChildren = function(from, to, cloneAllEdges)
-{
- cloneAllEdges = (cloneAllEdges != null) ? cloneAllEdges : true;
-
- this.beginUpdate();
- try
- {
- var mapping = new Object();
- this.mergeChildrenImpl(from, to, cloneAllEdges, mapping);
-
- // Post-processes all edges in the mapping and
- // reconnects the terminals to the corresponding
- // cells in the target model
- for (var key in mapping)
- {
- var cell = mapping[key];
- var terminal = this.getTerminal(cell, true);
-
- if (terminal != null)
- {
- terminal = mapping[mxCellPath.create(terminal)];
- this.setTerminal(cell, terminal, true);
- }
-
- terminal = this.getTerminal(cell, false);
-
- if (terminal != null)
- {
- terminal = mapping[mxCellPath.create(terminal)];
- this.setTerminal(cell, terminal, false);
- }
- }
- }
- finally
- {
- this.endUpdate();
- }
-};
-
-/**
- * Function: mergeChildren
- *
- * Clones the children of the source cell into the given target cell in
- * this model and adds an entry to the mapping that maps from the source
- * cell to the target cell with the same id or the clone of the source cell
- * that was inserted into this model.
- */
-mxGraphModel.prototype.mergeChildrenImpl = function(from, to, cloneAllEdges, mapping)
-{
- this.beginUpdate();
- try
- {
- var childCount = from.getChildCount();
-
- for (var i = 0; i < childCount; i++)
- {
- var cell = from.getChildAt(i);
-
- if (typeof(cell.getId) == 'function')
- {
- var id = cell.getId();
- var target = (id != null && (!this.isEdge(cell) || !cloneAllEdges)) ?
- this.getCell(id) : null;
-
- // Clones and adds the child if no cell exists for the id
- if (target == null)
- {
- var clone = cell.clone();
- clone.setId(id);
-
- // Sets the terminals from the original cell to the clone
- // because the lookup uses strings not cells in JS
- clone.setTerminal(cell.getTerminal(true), true);
- clone.setTerminal(cell.getTerminal(false), false);
-
- // Do *NOT* use model.add as this will move the edge away
- // from the parent in updateEdgeParent if maintainEdgeParent
- // is enabled in the target model
- target = to.insert(clone);
- this.cellAdded(target);
- }
-
- // Stores the mapping for later reconnecting edges
- mapping[mxCellPath.create(cell)] = target;
-
- // Recurses
- this.mergeChildrenImpl(cell, target, cloneAllEdges, mapping);
- }
- }
- }
- finally
- {
- this.endUpdate();
- }
-};
-
-/**
- * Function: getParents
- *
- * Returns an array that represents the set (no duplicates) of all parents
- * for the given array of cells.
- *
- * Parameters:
- *
- * cells - Array of cells whose parents should be returned.
- */
-mxGraphModel.prototype.getParents = function(cells)
-{
- var parents = [];
-
- if (cells != null)
- {
- var hash = new Object();
-
- for (var i = 0; i < cells.length; i++)
- {
- var parent = this.getParent(cells[i]);
-
- if (parent != null)
- {
- var id = mxCellPath.create(parent);
-
- if (hash[id] == null)
- {
- hash[id] = parent;
- parents.push(parent);
- }
- }
- }
- }
-
- return parents;
-};
-
-//
-// Cell Cloning
-//
-
-/**
- * Function: cloneCell
- *
- * Returns a deep clone of the given <mxCell> (including
- * the children) which is created using <cloneCells>.
- *
- * Parameters:
- *
- * cell - <mxCell> to be cloned.
- */
-mxGraphModel.prototype.cloneCell = function(cell)
-{
- if (cell != null)
- {
- return this.cloneCells([cell], true)[0];
- }
-
- return null;
-};
-
-/**
- * Function: cloneCells
- *
- * Returns an array of clones for the given array of <mxCells>.
- * Depending on the value of includeChildren, a deep clone is created for
- * each cell. Connections are restored based if the corresponding
- * cell is contained in the passed in array.
- *
- * Parameters:
- *
- * cells - Array of <mxCell> to be cloned.
- * includeChildren - Boolean indicating if the cells should be cloned
- * with all descendants.
- */
-mxGraphModel.prototype.cloneCells = function(cells, includeChildren)
-{
- var mapping = new Object();
- var clones = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- if (cells[i] != null)
- {
- clones.push(this.cloneCellImpl(cells[i], mapping, includeChildren));
- }
- else
- {
- clones.push(null);
- }
- }
-
- for (var i = 0; i < clones.length; i++)
- {
- if (clones[i] != null)
- {
- this.restoreClone(clones[i], cells[i], mapping);
- }
- }
-
- return clones;
-};
-
-/**
- * Function: cloneCellImpl
- *
- * Inner helper method for cloning cells recursively.
- */
-mxGraphModel.prototype.cloneCellImpl = function(cell, mapping, includeChildren)
-{
- var clone = this.cellCloned(cell);
-
- // Stores the clone in the lookup under the
- // cell path for the original cell
- mapping[mxObjectIdentity.get(cell)] = clone;
-
- if (includeChildren)
- {
- var childCount = this.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var cloneChild = this.cloneCellImpl(
- this.getChildAt(cell, i), mapping, true);
- clone.insert(cloneChild);
- }
- }
-
- return clone;
-};
-
-/**
- * Function: cellCloned
- *
- * Hook for cloning the cell. This returns cell.clone() or
- * any possible exceptions.
- */
-mxGraphModel.prototype.cellCloned = function(cell)
-{
- return cell.clone();
-};
-
-/**
- * Function: restoreClone
- *
- * Inner helper method for restoring the connections in
- * a network of cloned cells.
- */
-mxGraphModel.prototype.restoreClone = function(clone, cell, mapping)
-{
- var source = this.getTerminal(cell, true);
-
- if (source != null)
- {
- var tmp = mapping[mxObjectIdentity.get(source)];
-
- if (tmp != null)
- {
- tmp.insertEdge(clone, true);
- }
- }
-
- var target = this.getTerminal(cell, false);
-
- if (target != null)
- {
- var tmp = mapping[mxObjectIdentity.get(target)];
-
- if (tmp != null)
- {
- tmp.insertEdge(clone, false);
- }
- }
-
- var childCount = this.getChildCount(clone);
-
- for (var i = 0; i < childCount; i++)
- {
- this.restoreClone(this.getChildAt(clone, i),
- this.getChildAt(cell, i), mapping);
- }
-};
-
-//
-// Atomic changes
-//
-
-/**
- * Class: mxRootChange
- *
- * Action to change the root in a model.
- *
- * Constructor: mxRootChange
- *
- * Constructs a change of the root in the
- * specified model.
- */
-function mxRootChange(model, root)
-{
- this.model = model;
- this.root = root;
- this.previous = root;
-};
-
-/**
- * Function: execute
- *
- * Carries out a change of the root using
- * <mxGraphModel.rootChanged>.
- */
-mxRootChange.prototype.execute = function()
-{
- this.root = this.previous;
- this.previous = this.model.rootChanged(this.previous);
-};
-
-/**
- * Class: mxChildChange
- *
- * Action to add or remove a child in a model.
- *
- * Constructor: mxChildChange
- *
- * Constructs a change of a child in the
- * specified model.
- */
-function mxChildChange(model, parent, child, index)
-{
- this.model = model;
- this.parent = parent;
- this.previous = parent;
- this.child = child;
- this.index = index;
- this.previousIndex = index;
-};
-
-/**
- * Function: execute
- *
- * Changes the parent of <child> using
- * <mxGraphModel.parentForCellChanged> and
- * removes or restores the cell's
- * connections.
- */
-mxChildChange.prototype.execute = function()
-{
- var tmp = this.model.getParent(this.child);
- var tmp2 = (tmp != null) ? tmp.getIndex(this.child) : 0;
-
- if (this.previous == null)
- {
- this.connect(this.child, false);
- }
-
- tmp = this.model.parentForCellChanged(
- this.child, this.previous, this.previousIndex);
-
- if (this.previous != null)
- {
- this.connect(this.child, true);
- }
-
- this.parent = this.previous;
- this.previous = tmp;
- this.index = this.previousIndex;
- this.previousIndex = tmp2;
-};
-
-/**
- * Function: disconnect
- *
- * Disconnects the given cell recursively from its
- * terminals and stores the previous terminal in the
- * cell's terminals.
- */
-mxChildChange.prototype.connect = function(cell, isConnect)
-{
- isConnect = (isConnect != null) ? isConnect : true;
-
- var source = cell.getTerminal(true);
- var target = cell.getTerminal(false);
-
- if (source != null)
- {
- if (isConnect)
- {
- this.model.terminalForCellChanged(cell, source, true);
- }
- else
- {
- this.model.terminalForCellChanged(cell, null, true);
- }
- }
-
- if (target != null)
- {
- if (isConnect)
- {
- this.model.terminalForCellChanged(cell, target, false);
- }
- else
- {
- this.model.terminalForCellChanged(cell, null, false);
- }
- }
-
- cell.setTerminal(source, true);
- cell.setTerminal(target, false);
-
- var childCount = this.model.getChildCount(cell);
-
- for (var i=0; i<childCount; i++)
- {
- this.connect(this.model.getChildAt(cell, i), isConnect);
- }
-};
-
-/**
- * Class: mxTerminalChange
- *
- * Action to change a terminal in a model.
- *
- * Constructor: mxTerminalChange
- *
- * Constructs a change of a terminal in the
- * specified model.
- */
-function mxTerminalChange(model, cell, terminal, source)
-{
- this.model = model;
- this.cell = cell;
- this.terminal = terminal;
- this.previous = terminal;
- this.source = source;
-};
-
-/**
- * Function: execute
- *
- * Changes the terminal of <cell> to <previous> using
- * <mxGraphModel.terminalForCellChanged>.
- */
-mxTerminalChange.prototype.execute = function()
-{
- this.terminal = this.previous;
- this.previous = this.model.terminalForCellChanged(
- this.cell, this.previous, this.source);
-};
-
-/**
- * Class: mxValueChange
- *
- * Action to change a user object in a model.
- *
- * Constructor: mxValueChange
- *
- * Constructs a change of a user object in the
- * specified model.
- */
-function mxValueChange(model, cell, value)
-{
- this.model = model;
- this.cell = cell;
- this.value = value;
- this.previous = value;
-};
-
-/**
- * Function: execute
- *
- * Changes the value of <cell> to <previous> using
- * <mxGraphModel.valueForCellChanged>.
- */
-mxValueChange.prototype.execute = function()
-{
- this.value = this.previous;
- this.previous = this.model.valueForCellChanged(
- this.cell, this.previous);
-};
-
-/**
- * Class: mxStyleChange
- *
- * Action to change a cell's style in a model.
- *
- * Constructor: mxStyleChange
- *
- * Constructs a change of a style in the
- * specified model.
- */
-function mxStyleChange(model, cell, style)
-{
- this.model = model;
- this.cell = cell;
- this.style = style;
- this.previous = style;
-};
-
-/**
- * Function: execute
- *
- * Changes the style of <cell> to <previous> using
- * <mxGraphModel.styleForCellChanged>.
- */
-mxStyleChange.prototype.execute = function()
-{
- this.style = this.previous;
- this.previous = this.model.styleForCellChanged(
- this.cell, this.previous);
-};
-
-/**
- * Class: mxGeometryChange
- *
- * Action to change a cell's geometry in a model.
- *
- * Constructor: mxGeometryChange
- *
- * Constructs a change of a geometry in the
- * specified model.
- */
-function mxGeometryChange(model, cell, geometry)
-{
- this.model = model;
- this.cell = cell;
- this.geometry = geometry;
- this.previous = geometry;
-};
-
-/**
- * Function: execute
- *
- * Changes the geometry of <cell> ro <previous> using
- * <mxGraphModel.geometryForCellChanged>.
- */
-mxGeometryChange.prototype.execute = function()
-{
- this.geometry = this.previous;
- this.previous = this.model.geometryForCellChanged(
- this.cell, this.previous);
-};
-
-/**
- * Class: mxCollapseChange
- *
- * Action to change a cell's collapsed state in a model.
- *
- * Constructor: mxCollapseChange
- *
- * Constructs a change of a collapsed state in the
- * specified model.
- */
-function mxCollapseChange(model, cell, collapsed)
-{
- this.model = model;
- this.cell = cell;
- this.collapsed = collapsed;
- this.previous = collapsed;
-};
-
-/**
- * Function: execute
- *
- * Changes the collapsed state of <cell> to <previous> using
- * <mxGraphModel.collapsedStateForCellChanged>.
- */
-mxCollapseChange.prototype.execute = function()
-{
- this.collapsed = this.previous;
- this.previous = this.model.collapsedStateForCellChanged(
- this.cell, this.previous);
-};
-
-/**
- * Class: mxVisibleChange
- *
- * Action to change a cell's visible state in a model.
- *
- * Constructor: mxVisibleChange
- *
- * Constructs a change of a visible state in the
- * specified model.
- */
-function mxVisibleChange(model, cell, visible)
-{
- this.model = model;
- this.cell = cell;
- this.visible = visible;
- this.previous = visible;
-};
-
-/**
- * Function: execute
- *
- * Changes the visible state of <cell> to <previous> using
- * <mxGraphModel.visibleStateForCellChanged>.
- */
-mxVisibleChange.prototype.execute = function()
-{
- this.visible = this.previous;
- this.previous = this.model.visibleStateForCellChanged(
- this.cell, this.previous);
-};
-
-/**
- * Class: mxCellAttributeChange
- *
- * Action to change the attribute of a cell's user object.
- * There is no method on the graph model that uses this
- * action. To use the action, you can use the code shown
- * in the example below.
- *
- * Example:
- *
- * To change the attributeName in the cell's user object
- * to attributeValue, use the following code:
- *
- * (code)
- * model.beginUpdate();
- * try
- * {
- * var edit = new mxCellAttributeChange(
- * cell, attributeName, attributeValue);
- * model.execute(edit);
- * }
- * finally
- * {
- * model.endUpdate();
- * }
- * (end)
- *
- * Constructor: mxCellAttributeChange
- *
- * Constructs a change of a attribute of the DOM node
- * stored as the value of the given <mxCell>.
- */
-function mxCellAttributeChange(cell, attribute, value)
-{
- this.cell = cell;
- this.attribute = attribute;
- this.value = value;
- this.previous = value;
-};
-
-/**
- * Function: execute
- *
- * Changes the attribute of the cell's user object by
- * using <mxCell.setAttribute>.
- */
-mxCellAttributeChange.prototype.execute = function()
-{
- var tmp = this.cell.getAttribute(this.attribute);
-
- if (this.previous == null)
- {
- this.cell.value.removeAttribute(this.attribute);
- }
- else
- {
- this.cell.setAttribute(this.attribute, this.previous);
- }
-
- this.previous = tmp;
-};
diff --git a/src/js/mxClient.js b/src/js/mxClient.js
deleted file mode 100644
index a23b5fc..0000000
--- a/src/js/mxClient.js
+++ /dev/null
@@ -1,643 +0,0 @@
-/**
- * $Id: mxClient.js,v 1.203 2012-07-19 15:19:07 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxClient =
-{
-
- /**
- * Class: mxClient
- *
- * Bootstrapping mechanism for the mxGraph thin client. The production version
- * of this file contains all code required to run the mxGraph thin client, as
- * well as global constants to identify the browser and operating system in
- * use. You may have to load chrome://global/content/contentAreaUtils.js in
- * your page to disable certain security restrictions in Mozilla.
- *
- * Variable: VERSION
- *
- * Contains the current version of the mxGraph library. The strings that
- * communicate versions of mxGraph use the following format.
- *
- * versionMajor.versionMinor.buildNumber.revisionNumber
- *
- * Current version is 1.10.4.1.
- */
- VERSION: '1.10.4.1',
-
- /**
- * Variable: IS_IE
- *
- * True if the current browser is Internet Explorer.
- */
- IS_IE: navigator.userAgent.indexOf('MSIE') >= 0,
-
- /**
- * Variable: IS_IE6
- *
- * True if the current browser is Internet Explorer 6.x.
- */
- IS_IE6: navigator.userAgent.indexOf('MSIE 6') >= 0,
-
- /**
- * Variable: IS_QUIRKS
- *
- * True if the current browser is Internet Explorer and it is in quirks mode.
- */
- IS_QUIRKS: navigator.userAgent.indexOf('MSIE') >= 0 && (document.documentMode == null || document.documentMode == 5),
-
- /**
- * Variable: IS_NS
- *
- * True if the current browser is Netscape (including Firefox).
- */
- IS_NS: navigator.userAgent.indexOf('Mozilla/') >= 0 &&
- navigator.userAgent.indexOf('MSIE') < 0,
-
- /**
- * Variable: IS_OP
- *
- * True if the current browser is Opera.
- */
- IS_OP: navigator.userAgent.indexOf('Opera/') >= 0,
-
- /**
- * Variable: IS_OT
- *
- * True if -o-transform is available as a CSS style. This is the case
- * for Opera browsers that use Presto/2.5 and later.
- */
- IS_OT: navigator.userAgent.indexOf('Presto/2.4.') < 0 &&
- navigator.userAgent.indexOf('Presto/2.3.') < 0 &&
- navigator.userAgent.indexOf('Presto/2.2.') < 0 &&
- navigator.userAgent.indexOf('Presto/2.1.') < 0 &&
- navigator.userAgent.indexOf('Presto/2.0.') < 0 &&
- navigator.userAgent.indexOf('Presto/1.') < 0,
-
- /**
- * Variable: IS_SF
- *
- * True if the current browser is Safari.
- */
- IS_SF: navigator.userAgent.indexOf('AppleWebKit/') >= 0 &&
- navigator.userAgent.indexOf('Chrome/') < 0,
-
- /**
- * Variable: IS_GC
- *
- * True if the current browser is Google Chrome.
- */
- IS_GC: navigator.userAgent.indexOf('Chrome/') >= 0,
-
- /**
- * Variable: IS_MT
- *
- * True if -moz-transform is available as a CSS style. This is the case
- * for all Firefox-based browsers newer than or equal 3, such as Camino,
- * Iceweasel, Seamonkey and Iceape.
- */
- IS_MT: (navigator.userAgent.indexOf('Firefox/') >= 0 &&
- navigator.userAgent.indexOf('Firefox/1.') < 0 &&
- navigator.userAgent.indexOf('Firefox/2.') < 0) ||
- (navigator.userAgent.indexOf('Iceweasel/') >= 0 &&
- navigator.userAgent.indexOf('Iceweasel/1.') < 0 &&
- navigator.userAgent.indexOf('Iceweasel/2.') < 0) ||
- (navigator.userAgent.indexOf('SeaMonkey/') >= 0 &&
- navigator.userAgent.indexOf('SeaMonkey/1.') < 0) ||
- (navigator.userAgent.indexOf('Iceape/') >= 0 &&
- navigator.userAgent.indexOf('Iceape/1.') < 0),
-
- /**
- * Variable: IS_SVG
- *
- * True if the browser supports SVG.
- */
- IS_SVG: navigator.userAgent.indexOf('Firefox/') >= 0 || // FF and Camino
- navigator.userAgent.indexOf('Iceweasel/') >= 0 || // Firefox on Debian
- navigator.userAgent.indexOf('Seamonkey/') >= 0 || // Firefox-based
- navigator.userAgent.indexOf('Iceape/') >= 0 || // Seamonkey on Debian
- navigator.userAgent.indexOf('Galeon/') >= 0 || // Gnome Browser (old)
- navigator.userAgent.indexOf('Epiphany/') >= 0 || // Gnome Browser (new)
- navigator.userAgent.indexOf('AppleWebKit/') >= 0 || // Safari/Google Chrome
- navigator.userAgent.indexOf('Gecko/') >= 0 || // Netscape/Gecko
- navigator.userAgent.indexOf('Opera/') >= 0,
-
-
- /**
- * Variable: NO_FO
- *
- * True if foreignObject support is not available. This is the case for
- * Opera and older SVG-based browsers. IE does not require this type
- * of tag.
- */
- NO_FO: navigator.userAgent.indexOf('Firefox/1.') >= 0 ||
- navigator.userAgent.indexOf('Iceweasel/1.') >= 0 ||
- navigator.userAgent.indexOf('Firefox/2.') >= 0 ||
- navigator.userAgent.indexOf('Iceweasel/2.') >= 0 ||
- navigator.userAgent.indexOf('SeaMonkey/1.') >= 0 ||
- navigator.userAgent.indexOf('Iceape/1.') >= 0 ||
- navigator.userAgent.indexOf('Camino/1.') >= 0 ||
- navigator.userAgent.indexOf('Epiphany/2.') >= 0 ||
- navigator.userAgent.indexOf('Opera/') >= 0 ||
- navigator.userAgent.indexOf('MSIE') >= 0 ||
- navigator.userAgent.indexOf('Mozilla/2.') >= 0, // Safari/Google Chrome
-
- /**
- * Variable: IS_VML
- *
- * True if the browser supports VML.
- */
- IS_VML: navigator.appName.toUpperCase() == 'MICROSOFT INTERNET EXPLORER',
-
- /**
- * Variable: IS_MAC
- *
- * True if the client is a Mac.
- */
- IS_MAC: navigator.userAgent.toUpperCase().indexOf('MACINTOSH') > 0,
-
- /**
- * Variable: IS_TOUCH
- *
- * True if this client uses a touch interface (no mouse). Currently this
- * detects IPads, IPods, IPhones and Android devices.
- */
- IS_TOUCH: navigator.userAgent.toUpperCase().indexOf('IPAD') > 0 ||
- navigator.userAgent.toUpperCase().indexOf('IPOD') > 0 ||
- navigator.userAgent.toUpperCase().indexOf('IPHONE') > 0 ||
- navigator.userAgent.toUpperCase().indexOf('ANDROID') > 0,
-
- /**
- * Variable: IS_LOCAL
- *
- * True if the documents location does not start with http:// or https://.
- */
- IS_LOCAL: document.location.href.indexOf('http://') < 0 &&
- document.location.href.indexOf('https://') < 0,
-
- /**
- * Function: isBrowserSupported
- *
- * Returns true if the current browser is supported, that is, if
- * <mxClient.IS_VML> or <mxClient.IS_SVG> is true.
- *
- * Example:
- *
- * (code)
- * if (!mxClient.isBrowserSupported())
- * {
- * mxUtils.error('Browser is not supported!', 200, false);
- * }
- * (end)
- */
- isBrowserSupported: function()
- {
- return mxClient.IS_VML || mxClient.IS_SVG;
- },
-
- /**
- * Function: link
- *
- * Adds a link node to the head of the document. Use this
- * to add a stylesheet to the page as follows:
- *
- * (code)
- * mxClient.link('stylesheet', filename);
- * (end)
- *
- * where filename is the (relative) URL of the stylesheet. The charset
- * is hardcoded to ISO-8859-1 and the type is text/css.
- *
- * Parameters:
- *
- * rel - String that represents the rel attribute of the link node.
- * href - String that represents the href attribute of the link node.
- * doc - Optional parent document of the link node.
- */
- link: function(rel, href, doc)
- {
- doc = doc || document;
-
- // Workaround for Operation Aborted in IE6 if base tag is used in head
- if (mxClient.IS_IE6)
- {
- doc.write('<link rel="'+rel+'" href="'+href+'" charset="ISO-8859-1" type="text/css"/>');
- }
- else
- {
- var link = doc.createElement('link');
-
- link.setAttribute('rel', rel);
- link.setAttribute('href', href);
- link.setAttribute('charset', 'ISO-8859-1');
- link.setAttribute('type', 'text/css');
-
- var head = doc.getElementsByTagName('head')[0];
- head.appendChild(link);
- }
- },
-
- /**
- * Function: include
- *
- * Dynamically adds a script node to the document header.
- *
- * In production environments, the includes are resolved in the mxClient.js
- * file to reduce the number of requests required for client startup. This
- * function should only be used in development environments, but not in
- * production systems.
- */
- include: function(src)
- {
- document.write('<script src="'+src+'"></script>');
- },
-
- /**
- * Function: dispose
- *
- * Frees up memory in IE by resolving cyclic dependencies between the DOM
- * and the JavaScript objects. This is always invoked in IE when the page
- * unloads.
- */
- dispose: function()
- {
- // Cleans all objects where listeners have been added
- for (var i = 0; i < mxEvent.objects.length; i++)
- {
- if (mxEvent.objects[i].mxListenerList != null)
- {
- mxEvent.removeAllListeners(mxEvent.objects[i]);
- }
- }
- }
-
-};
-
-/**
- * Variable: mxLoadResources
- *
- * Optional global config variable to toggle loading of the two resource files
- * in <mxGraph> and <mxEditor>. Default is true. NOTE: This is a global variable,
- * not a variable of mxClient.
- *
- * (code)
- * <script type="text/javascript">
- * var mxLoadResources = false;
- * </script>
- * <script type="text/javascript" src="/path/to/core/directory/js/mxClient.js"></script>
- * (end)
- */
-if (typeof(mxLoadResources) == 'undefined')
-{
- mxLoadResources = true;
-}
-
-/**
- * Variable: mxLoadStylesheets
- *
- * Optional global config variable to toggle loading of the CSS files when
- * the library is initialized. Default is true. NOTE: This is a global variable,
- * not a variable of mxClient.
- *
- * (code)
- * <script type="text/javascript">
- * var mxLoadStylesheets = false;
- * </script>
- * <script type="text/javascript" src="/path/to/core/directory/js/mxClient.js"></script>
- * (end)
- */
-if (typeof(mxLoadStylesheets) == 'undefined')
-{
- mxLoadStylesheets = true;
-}
-
-/**
- * Variable: basePath
- *
- * Basepath for all URLs in the core without trailing slash. Default is '.'.
- * Set mxBasePath prior to loading the mxClient library as follows to override
- * this setting:
- *
- * (code)
- * <script type="text/javascript">
- * mxBasePath = '/path/to/core/directory';
- * </script>
- * <script type="text/javascript" src="/path/to/core/directory/js/mxClient.js"></script>
- * (end)
- *
- * When using a relative path, the path is relative to the URL of the page that
- * contains the assignment. Trailing slashes are automatically removed.
- */
-if (typeof(mxBasePath) != 'undefined' && mxBasePath.length > 0)
-{
- // Adds a trailing slash if required
- if (mxBasePath.substring(mxBasePath.length - 1) == '/')
- {
- mxBasePath = mxBasePath.substring(0, mxBasePath.length - 1);
- }
-
- mxClient.basePath = mxBasePath;
-}
-else
-{
- mxClient.basePath = '.';
-}
-
-/**
- * Variable: imageBasePath
- *
- * Basepath for all images URLs in the core without trailing slash. Default is
- * <mxClient.basePath> + '/images'. Set mxImageBasePath prior to loading the
- * mxClient library as follows to override this setting:
- *
- * (code)
- * <script type="text/javascript">
- * mxImageBasePath = '/path/to/image/directory';
- * </script>
- * <script type="text/javascript" src="/path/to/core/directory/js/mxClient.js"></script>
- * (end)
- *
- * When using a relative path, the path is relative to the URL of the page that
- * contains the assignment. Trailing slashes are automatically removed.
- */
-if (typeof(mxImageBasePath) != 'undefined' && mxImageBasePath.length > 0)
-{
- // Adds a trailing slash if required
- if (mxImageBasePath.substring(mxImageBasePath.length - 1) == '/')
- {
- mxImageBasePath = mxImageBasePath.substring(0, mxImageBasePath.length - 1);
- }
-
- mxClient.imageBasePath = mxImageBasePath;
-}
-else
-{
- mxClient.imageBasePath = mxClient.basePath + '/images';
-}
-
-/**
- * Variable: language
- *
- * Defines the language of the client, eg. en for english, de for german etc.
- * The special value 'none' will disable all built-in internationalization and
- * resource loading. See <mxResources.getSpecialBundle> for handling identifiers
- * with and without a dash.
- *
- * Set mxLanguage prior to loading the mxClient library as follows to override
- * this setting:
- *
- * (code)
- * <script type="text/javascript">
- * mxLanguage = 'en';
- * </script>
- * <script type="text/javascript" src="js/mxClient.js"></script>
- * (end)
- *
- * If internationalization is disabled, then the following variables should be
- * overridden to reflect the current language of the system. These variables are
- * cleared when i18n is disabled.
- * <mxEditor.askZoomResource>, <mxEditor.lastSavedResource>,
- * <mxEditor.currentFileResource>, <mxEditor.propertiesResource>,
- * <mxEditor.tasksResource>, <mxEditor.helpResource>, <mxEditor.outlineResource>,
- * <mxElbowEdgeHandler.doubleClickOrientationResource>, <mxUtils.errorResource>,
- * <mxUtils.closeResource>, <mxGraphSelectionModel.doneResource>,
- * <mxGraphSelectionModel.updatingSelectionResource>, <mxGraphView.doneResource>,
- * <mxGraphView.updatingDocumentResource>, <mxCellRenderer.collapseExpandResource>,
- * <mxGraph.containsValidationErrorsResource> and
- * <mxGraph.alreadyConnectedResource>.
- */
-if (typeof(mxLanguage) != 'undefined')
-{
- mxClient.language = mxLanguage;
-}
-else
-{
- mxClient.language = (mxClient.IS_IE) ? navigator.userLanguage : navigator.language;
-}
-
-/**
- * Variable: defaultLanguage
- *
- * Defines the default language which is used in the common resource files. Any
- * resources for this language will only load the common resource file, but not
- * the language-specific resource file. Default is 'en'.
- *
- * Set mxDefaultLanguage prior to loading the mxClient library as follows to override
- * this setting:
- *
- * (code)
- * <script type="text/javascript">
- * mxDefaultLanguage = 'de';
- * </script>
- * <script type="text/javascript" src="js/mxClient.js"></script>
- * (end)
- */
-if (typeof(mxDefaultLanguage) != 'undefined')
-{
- mxClient.defaultLanguage = mxDefaultLanguage;
-}
-else
-{
- mxClient.defaultLanguage = 'en';
-}
-
-// Adds all required stylesheets and namespaces
-if (mxLoadStylesheets)
-{
- mxClient.link('stylesheet', mxClient.basePath + '/css/common.css');
-}
-
-/**
- * Variable: languages
- *
- * Defines the optional array of all supported language extensions. The default
- * language does not have to be part of this list. See
- * <mxResources.isLanguageSupported>.
- *
- * (code)
- * <script type="text/javascript">
- * mxLanguages = ['de', 'it', 'fr'];
- * </script>
- * <script type="text/javascript" src="js/mxClient.js"></script>
- * (end)
- *
- * This is used to avoid unnecessary requests to language files, ie. if a 404
- * will be returned.
- */
-if (typeof(mxLanguages) != 'undefined')
-{
- mxClient.languages = mxLanguages;
-}
-
-if (mxClient.IS_IE)
-{
- // IE9/10 standards mode uses SVG (VML is broken)
- if (document.documentMode >= 9)
- {
- mxClient.IS_VML = false;
- mxClient.IS_SVG = true;
- }
- else
- {
- // Enables support for IE8 standards mode. Note that this requires all attributes for VML
- // elements to be set using direct notation, ie. node.attr = value. The use of setAttribute
- // is not possible. See mxShape.init for more code to handle this specific document mode.
- if (document.documentMode == 8)
- {
- document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');
- document.namespaces.add('o', 'urn:schemas-microsoft-com:office:office', '#default#VML');
- }
- else
- {
- document.namespaces.add('v', 'urn:schemas-microsoft-com:vml');
- document.namespaces.add('o', 'urn:schemas-microsoft-com:office:office');
- }
-
- var ss = document.createStyleSheet();
- ss.cssText = 'v\\:*{behavior:url(#default#VML)}o\\:*{behavior:url(#default#VML)}';
-
- if (mxLoadStylesheets)
- {
- mxClient.link('stylesheet', mxClient.basePath + '/css/explorer.css');
- }
- }
-
- // Cleans up resources when the application terminates
- window.attachEvent('onunload', mxClient.dispose);
-}
-
-mxClient.include(mxClient.basePath+'/js/util/mxLog.js');
-mxClient.include(mxClient.basePath+'/js/util/mxObjectIdentity.js');
-mxClient.include(mxClient.basePath+'/js/util/mxDictionary.js');
-mxClient.include(mxClient.basePath+'/js/util/mxResources.js');
-mxClient.include(mxClient.basePath+'/js/util/mxPoint.js');
-mxClient.include(mxClient.basePath+'/js/util/mxRectangle.js');
-mxClient.include(mxClient.basePath+'/js/util/mxEffects.js');
-mxClient.include(mxClient.basePath+'/js/util/mxUtils.js');
-mxClient.include(mxClient.basePath+'/js/util/mxConstants.js');
-mxClient.include(mxClient.basePath+'/js/util/mxEventObject.js');
-mxClient.include(mxClient.basePath+'/js/util/mxMouseEvent.js');
-mxClient.include(mxClient.basePath+'/js/util/mxEventSource.js');
-mxClient.include(mxClient.basePath+'/js/util/mxEvent.js');
-mxClient.include(mxClient.basePath+'/js/util/mxXmlRequest.js');
-mxClient.include(mxClient.basePath+'/js/util/mxClipboard.js');
-mxClient.include(mxClient.basePath+'/js/util/mxWindow.js');
-mxClient.include(mxClient.basePath+'/js/util/mxForm.js');
-mxClient.include(mxClient.basePath+'/js/util/mxImage.js');
-mxClient.include(mxClient.basePath+'/js/util/mxDivResizer.js');
-mxClient.include(mxClient.basePath+'/js/util/mxDragSource.js');
-mxClient.include(mxClient.basePath+'/js/util/mxToolbar.js');
-mxClient.include(mxClient.basePath+'/js/util/mxSession.js');
-mxClient.include(mxClient.basePath+'/js/util/mxUndoableEdit.js');
-mxClient.include(mxClient.basePath+'/js/util/mxUndoManager.js');
-mxClient.include(mxClient.basePath+'/js/util/mxUrlConverter.js');
-mxClient.include(mxClient.basePath+'/js/util/mxPanningManager.js');
-mxClient.include(mxClient.basePath+'/js/util/mxPath.js');
-mxClient.include(mxClient.basePath+'/js/util/mxPopupMenu.js');
-mxClient.include(mxClient.basePath+'/js/util/mxAutoSaveManager.js');
-mxClient.include(mxClient.basePath+'/js/util/mxAnimation.js');
-mxClient.include(mxClient.basePath+'/js/util/mxMorphing.js');
-mxClient.include(mxClient.basePath+'/js/util/mxImageBundle.js');
-mxClient.include(mxClient.basePath+'/js/util/mxImageExport.js');
-mxClient.include(mxClient.basePath+'/js/util/mxXmlCanvas2D.js');
-mxClient.include(mxClient.basePath+'/js/util/mxSvgCanvas2D.js');
-mxClient.include(mxClient.basePath+'/js/util/mxGuide.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxShape.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxStencil.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxStencilRegistry.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxStencilShape.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxMarker.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxActor.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxCloud.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxRectangleShape.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxEllipse.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxDoubleEllipse.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxRhombus.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxPolyline.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxArrow.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxText.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxTriangle.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxHexagon.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxLine.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxImageShape.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxLabel.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxCylinder.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxConnector.js');
-mxClient.include(mxClient.basePath+'/js/shape/mxSwimlane.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxGraphLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxStackLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxPartitionLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxCompactTreeLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxFastOrganicLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxCircleLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxParallelEdgeLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxCompositeLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/mxEdgeLabelLayout.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxGraphAbstractHierarchyCell.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxGraphHierarchyNode.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxGraphHierarchyEdge.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/model/mxGraphHierarchyModel.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxHierarchicalLayoutStage.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxMinimumCycleRemover.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/stage/mxCoordinateAssignment.js');
-mxClient.include(mxClient.basePath+'/js/layout/hierarchical/mxHierarchicalLayout.js');
-mxClient.include(mxClient.basePath+'/js/model/mxGraphModel.js');
-mxClient.include(mxClient.basePath+'/js/model/mxCell.js');
-mxClient.include(mxClient.basePath+'/js/model/mxGeometry.js');
-mxClient.include(mxClient.basePath+'/js/model/mxCellPath.js');
-mxClient.include(mxClient.basePath+'/js/view/mxPerimeter.js');
-mxClient.include(mxClient.basePath+'/js/view/mxPrintPreview.js');
-mxClient.include(mxClient.basePath+'/js/view/mxStylesheet.js');
-mxClient.include(mxClient.basePath+'/js/view/mxCellState.js');
-mxClient.include(mxClient.basePath+'/js/view/mxGraphSelectionModel.js');
-mxClient.include(mxClient.basePath+'/js/view/mxCellEditor.js');
-mxClient.include(mxClient.basePath+'/js/view/mxCellRenderer.js');
-mxClient.include(mxClient.basePath+'/js/view/mxEdgeStyle.js');
-mxClient.include(mxClient.basePath+'/js/view/mxStyleRegistry.js');
-mxClient.include(mxClient.basePath+'/js/view/mxGraphView.js');
-mxClient.include(mxClient.basePath+'/js/view/mxGraph.js');
-mxClient.include(mxClient.basePath+'/js/view/mxCellOverlay.js');
-mxClient.include(mxClient.basePath+'/js/view/mxOutline.js');
-mxClient.include(mxClient.basePath+'/js/view/mxMultiplicity.js');
-mxClient.include(mxClient.basePath+'/js/view/mxLayoutManager.js');
-mxClient.include(mxClient.basePath+'/js/view/mxSpaceManager.js');
-mxClient.include(mxClient.basePath+'/js/view/mxSwimlaneManager.js');
-mxClient.include(mxClient.basePath+'/js/view/mxTemporaryCellStates.js');
-mxClient.include(mxClient.basePath+'/js/view/mxCellStatePreview.js');
-mxClient.include(mxClient.basePath+'/js/view/mxConnectionConstraint.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxGraphHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxPanningHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxCellMarker.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxSelectionCellsHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxConnectionHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxConstraintHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxRubberband.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxVertexHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxEdgeHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxElbowEdgeHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxEdgeSegmentHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxKeyHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxTooltipHandler.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxCellTracker.js');
-mxClient.include(mxClient.basePath+'/js/handler/mxCellHighlight.js');
-mxClient.include(mxClient.basePath+'/js/editor/mxDefaultKeyHandler.js');
-mxClient.include(mxClient.basePath+'/js/editor/mxDefaultPopupMenu.js');
-mxClient.include(mxClient.basePath+'/js/editor/mxDefaultToolbar.js');
-mxClient.include(mxClient.basePath+'/js/editor/mxEditor.js');
-mxClient.include(mxClient.basePath+'/js/io/mxCodecRegistry.js');
-mxClient.include(mxClient.basePath+'/js/io/mxCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxObjectCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxCellCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxModelCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxRootChangeCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxChildChangeCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxTerminalChangeCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxGenericChangeCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxGraphCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxGraphViewCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxStylesheetCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxDefaultKeyHandlerCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxDefaultToolbarCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxDefaultPopupMenuCodec.js');
-mxClient.include(mxClient.basePath+'/js/io/mxEditorCodec.js');
diff --git a/src/js/shape/mxActor.js b/src/js/shape/mxActor.js
deleted file mode 100644
index e6a0765..0000000
--- a/src/js/shape/mxActor.js
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * $Id: mxActor.js,v 1.35 2012-07-31 11:46:53 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxActor
- *
- * Extends <mxShape> to implement an actor shape. If a custom shape with one
- * filled area is needed, then this shape's <redrawPath> should be overridden.
- *
- * Example:
- *
- * (code)
- * function SampleShape() { }
- *
- * SampleShape.prototype = new mxActor();
- * SampleShape.prototype.constructor = vsAseShape;
- *
- * mxCellRenderer.prototype.defaultShapes['sample'] = SampleShape;
- * SampleShape.prototype.redrawPath = function(path, x, y, w, h)
- * {
- * path.moveTo(0, 0);
- * path.lineTo(w, h);
- * // ...
- * path.close();
- * }
- * (end)
- *
- * This shape is registered under <mxConstants.SHAPE_ACTOR> in
- * <mxCellRenderer>.
- *
- * Constructor: mxActor
- *
- * Constructs a new actor shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxActor(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxActor.prototype = new mxShape();
-mxActor.prototype.constructor = mxActor;
-
-/**
- * Variable: mixedModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw in VML in mixed Html mode.
- */
-mxActor.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw as VML in prefer Html mode.
- */
-mxActor.prototype.preferModeHtml = false;
-
-/**
- * Variable: vmlScale
- *
- * Renders VML with a scale of 2.
- */
-mxActor.prototype.vmlScale = 2;
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node(s) to represent this shape.
- */
-mxActor.prototype.createVml = function()
-{
- var node = document.createElement('v:shape');
- node.style.position = 'absolute';
- this.configureVmlShape(node);
-
- return node;
-};
-
-/**
- * Function: redrawVml
- *
- * Updates the VML node(s) to reflect the latest bounds and scale.
- */
-mxActor.prototype.redrawVml = function()
-{
- this.updateVmlShape(this.node);
- this.node.path = this.createPath();
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxActor.prototype.createSvg = function()
-{
- return this.createSvgGroup('path');
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxActor.prototype.redrawSvg = function()
-{
- var strokeWidth = Math.round(Math.max(1, this.strokewidth * this.scale));
- this.innerNode.setAttribute('stroke-width', strokeWidth);
- this.innerNode.setAttribute('stroke-linejoin', 'round');
-
- if (this.crisp && (this.rotation == null || this.rotation == 0))
- {
- this.innerNode.setAttribute('shape-rendering', 'crispEdges');
- }
- else
- {
- this.innerNode.removeAttribute('shape-rendering');
- }
-
- var d = this.createPath();
-
- if (d.length > 0)
- {
- this.innerNode.setAttribute('d', d);
-
- if (this.shadowNode != null)
- {
- this.shadowNode.setAttribute('transform', this.getSvgShadowTransform() +
- (this.innerNode.getAttribute('transform') || ''));
- this.shadowNode.setAttribute('stroke-width', strokeWidth);
- this.shadowNode.setAttribute('d', d);
- }
- }
- else
- {
- this.innerNode.removeAttribute('d');
-
- if (this.shadowNode != null)
- {
- this.shadowNode.removeAttribute('d');
- }
- }
-
- if (this.isDashed)
- {
- var phase = Math.max(1, Math.round(3 * this.scale * this.strokewidth));
- this.innerNode.setAttribute('stroke-dasharray', phase + ' ' + phase);
- }
-};
-
-/**
- * Function: redrawPath
- *
- * Draws the path for this shape. This method uses the <mxPath>
- * abstraction to paint the shape for VML and SVG.
- */
-mxActor.prototype.redrawPath = function(path, x, y, w, h)
-{
- var width = w/3;
- path.moveTo(0, h);
- path.curveTo(0, 3 * h / 5, 0, 2 * h / 5, w / 2, 2 * h / 5);
- path.curveTo(w / 2 - width, 2 * h / 5, w / 2 - width, 0, w / 2, 0);
- path.curveTo(w / 2 + width, 0, w / 2 + width, 2 * h / 5, w / 2, 2 * h / 5);
- path.curveTo(w, 2 * h / 5, w, 3 * h / 5, w, h);
- path.close();
-};
diff --git a/src/js/shape/mxArrow.js b/src/js/shape/mxArrow.js
deleted file mode 100644
index 93777d8..0000000
--- a/src/js/shape/mxArrow.js
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
- * $Id: mxArrow.js,v 1.31 2012-05-23 19:09:22 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxArrow
- *
- * Extends <mxShape> to implement an arrow shape. (The shape
- * is used to represent edges, not vertices.)
- * This shape is registered under <mxConstants.SHAPE_ARROW>
- * in <mxCellRenderer>.
- *
- * Constructor: mxArrow
- *
- * Constructs a new arrow shape.
- *
- * Parameters:
- *
- * points - Array of <mxPoints> that define the points. This is stored in
- * <mxShape.points>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- * arrowWidth - Optional integer that defines the arrow width. Default is
- * <mxConstants.ARROW_WIDTH>. This is stored in <arrowWidth>.
- * spacing - Optional integer that defines the spacing between the arrow shape
- * and its endpoints. Default is <mxConstants.ARROW_SPACING>. This is stored in
- * <spacing>.
- * endSize - Optional integer that defines the size of the arrowhead. Default
- * is <mxConstants.ARROW_SIZE>. This is stored in <endSize>.
- */
-function mxArrow(points, fill, stroke, strokewidth, arrowWidth, spacing, endSize)
-{
- this.points = points;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
- this.arrowWidth = (arrowWidth != null) ? arrowWidth : mxConstants.ARROW_WIDTH;
- this.spacing = (spacing != null) ? spacing : mxConstants.ARROW_SPACING;
- this.endSize = (endSize != null) ? endSize : mxConstants.ARROW_SIZE;
-};
-
-/**
- * Extends <mxActor>.
- */
-mxArrow.prototype = new mxActor();
-mxArrow.prototype.constructor = mxArrow;
-
-/**
- * Variable: addPipe
- *
- * Specifies if a SVG path should be created around any path to increase the
- * tolerance for mouse events. Default is false since this shape is filled.
- */
-mxArrow.prototype.addPipe = false;
-
-/**
- * Variable: enableFill
- *
- * Specifies if fill colors should be ignored. This must be set to true for
- * shapes that are stroked only. Default is true since this shape is filled.
- */
-mxArrow.prototype.enableFill = true;
-
-/**
- * Function: configureTransparentBackground
- *
- * Overidden to remove transparent background.
- */
-mxArrow.prototype.configureTransparentBackground = function(node)
-{
- // do nothing
-};
-
-/**
- * Function: updateBoundingBox
- *
- * Updates the <boundingBox> for this shape.
- */
-mxArrow.prototype.augmentBoundingBox = function(bbox)
-{
- // FIXME: Fix precision, share math and cache results with painting code
- bbox.grow(Math.max(this.arrowWidth / 2, this.endSize / 2) * this.scale);
-
- mxShape.prototype.augmentBoundingBox.apply(this, arguments);
-};
-
-/**
- * Function: createVml
- *
- * Extends <mxShape.createVml> to ignore fill if <enableFill> is false.
- */
-mxArrow.prototype.createVml = function()
-{
- if (!this.enableFill)
- {
- this.fill = null;
- }
-
- return mxActor.prototype.createVml.apply(this, arguments);
-};
-
-/**
- * Function: createSvg
- *
- * Extends <mxActor.createSvg> to ignore fill if <enableFill> is false and
- * create an event handling shape if <this.addPipe> is true.
- */
-mxArrow.prototype.createSvg = function()
-{
- if (!this.enableFill)
- {
- this.fill = null;
- }
-
- var g = mxActor.prototype.createSvg.apply(this, arguments);
-
- // Creates an invisible shape around the path for easier
- // selection with the mouse. Note: Firefox does not ignore
- // the value of the stroke attribute for pointer-events: stroke,
- // it does, however, ignore the visibility attribute.
- if (this.addPipe)
- {
- this.pipe = this.createSvgPipe();
- g.appendChild(this.pipe);
- }
-
- return g;
-};
-
-/**
- * Function: reconfigure
- *
- * Extends <mxActor.reconfigure> to ignore fill if <enableFill> is false.
- */
-mxArrow.prototype.reconfigure = function()
-{
- if (!this.enableFill)
- {
- this.fill = null;
- }
-
- mxActor.prototype.reconfigure.apply(this, arguments);
-};
-
-/**
- * Function: redrawSvg
- *
- * Extends <mxActor.redrawSvg> to update the event handling shape if one
- * exists.
- */
-mxArrow.prototype.redrawSvg = function()
-{
- mxActor.prototype.redrawSvg.apply(this, arguments);
-
- if (this.pipe != null)
- {
- var d = this.innerNode.getAttribute('d');
-
- if (d != null)
- {
- this.pipe.setAttribute('d', this.innerNode.getAttribute('d'));
- var strokeWidth = Math.round(this.strokewidth * this.scale);
- this.pipe.setAttribute('stroke-width', strokeWidth + mxShape.prototype.SVG_STROKE_TOLERANCE);
- }
- }
-};
-
-/**
- * Function: redrawPath
- *
- * Draws the path for this shape. This method uses the <mxPath>
- * abstraction to paint the shape for VML and SVG.
- */
-mxArrow.prototype.redrawPath = function(path, x, y, w, h)
-{
- // All points are offset
- path.translate.x -= x;
- path.translate.y -= y;
-
- // Geometry of arrow
- var spacing = this.spacing * this.scale;
- var width = this.arrowWidth * this.scale;
- var arrow = this.endSize * this.scale;
-
- // Base vector (between end points)
- var p0 = this.points[0];
- var pe = this.points[this.points.length - 1];
-
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
- var dist = Math.sqrt(dx * dx + dy * dy);
- var length = dist - 2 * spacing - arrow;
-
- // Computes the norm and the inverse norm
- var nx = dx / dist;
- var ny = dy / dist;
- var basex = length * nx;
- var basey = length * ny;
- var floorx = width * ny/3;
- var floory = -width * nx/3;
-
- // Computes points
- var p0x = p0.x - floorx / 2 + spacing * nx;
- var p0y = p0.y - floory / 2 + spacing * ny;
- var p1x = p0x + floorx;
- var p1y = p0y + floory;
- var p2x = p1x + basex;
- var p2y = p1y + basey;
- var p3x = p2x + floorx;
- var p3y = p2y + floory;
- // p4 not necessary
- var p5x = p3x - 3 * floorx;
- var p5y = p3y - 3 * floory;
-
- path.moveTo(p0x, p0y);
- path.lineTo(p1x, p1y);
- path.lineTo(p2x, p2y);
- path.lineTo(p3x, p3y);
- path.lineTo(pe.x - spacing * nx, pe.y - spacing * ny);
- path.lineTo(p5x, p5y);
- path.lineTo(p5x + floorx, p5y + floory);
- path.lineTo(p0x, p0y);
- path.close();
-};
diff --git a/src/js/shape/mxCloud.js b/src/js/shape/mxCloud.js
deleted file mode 100644
index 3893a1b..0000000
--- a/src/js/shape/mxCloud.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * $Id: mxCloud.js,v 1.12 2011-06-24 11:27:30 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCloud
- *
- * Extends <mxActor> to implement a cloud shape.
- *
- * This shape is registered under <mxConstants.SHAPE_CLOUD> in
- * <mxCellRenderer>.
- *
- * Constructor: mxCloud
- *
- * Constructs a new cloud shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxCloud(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxActor.
- */
-mxCloud.prototype = new mxActor();
-mxCloud.prototype.constructor = mxActor;
-
-/**
- * Function: redrawPath
- *
- * Draws the path for this shape. This method uses the <mxPath>
- * abstraction to paint the shape for VML and SVG.
- */
-mxCloud.prototype.redrawPath = function(path, x, y, w, h)
-{
- path.moveTo(0.25 * w, 0.25 * h);
- path.curveTo(0.05 * w, 0.25 * h, 0, 0.5 * h, 0.16 * w, 0.55 * h);
- path.curveTo(0, 0.66 * h, 0.18 * w, 0.9 * h, 0.31 * w, 0.8 * h);
- path.curveTo(0.4 * w, h, 0.7 * w, h, 0.8 * w, 0.8 * h);
- path.curveTo(w, 0.8 * h, w, 0.6 * h, 0.875 * w, 0.5 * h);
- path.curveTo(w, 0.3 * h, 0.8 * w, 0.1 * h, 0.625 * w, 0.2 * h);
- path.curveTo(0.5 * w, 0.05 * h, 0.3 * w, 0.05 * h, 0.25 * w, 0.25 * h);
- path.close();
-};
diff --git a/src/js/shape/mxConnector.js b/src/js/shape/mxConnector.js
deleted file mode 100644
index 092bf79..0000000
--- a/src/js/shape/mxConnector.js
+++ /dev/null
@@ -1,446 +0,0 @@
-/**
- * $Id: mxConnector.js,v 1.80 2012-05-24 12:00:45 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxConnector
- *
- * Extends <mxShape> to implement a connector shape. The connector
- * shape allows for arrow heads on either side.
- *
- * This shape is registered under <mxConstants.SHAPE_CONNECTOR> in
- * <mxCellRenderer>.
- *
- * Constructor: mxConnector
- *
- * Constructs a new connector shape.
- *
- * Parameters:
- *
- * points - Array of <mxPoints> that define the points. This is stored in
- * <mxShape.points>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * Default is 'black'.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxConnector(points, stroke, strokewidth)
-{
- this.points = points;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxConnector.prototype = new mxShape();
-mxConnector.prototype.constructor = mxConnector;
-
-/**
- * Variable: vmlNodes
- *
- * Adds local references to <mxShape.vmlNodes>.
- */
-mxConnector.prototype.vmlNodes = mxConnector.prototype.vmlNodes.concat([
- 'shapeNode', 'start', 'end', 'startStroke', 'endStroke', 'startFill', 'endFill']);
-
-/**
- * Variable: mixedModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw in VML in mixed Html mode.
- */
-mxConnector.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw as VML in prefer Html mode.
- */
-mxConnector.prototype.preferModeHtml = false;
-
-/**
- * Variable: allowCrispMarkers
- *
- * Specifies if <mxShape.crisp> should be allowed for markers. Default is false.
- */
-mxConnector.prototype.allowCrispMarkers = false;
-
-/**
- * Variable: addPipe
- *
- * Specifies if a SVG path should be created around any path to increase the
- * tolerance for mouse events. Default is false since this shape is filled.
- */
-mxConnector.prototype.addPipe = true;
-
-/**
- * Function: configureHtmlShape
- *
- * Overrides <mxShape.configureHtmlShape> to clear the border and background.
- */
-mxConnector.prototype.configureHtmlShape = function(node)
-{
- mxShape.prototype.configureHtmlShape.apply(this, arguments);
- node.style.borderStyle = '';
- node.style.background = '';
-};
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
-mxConnector.prototype.createVml = function()
-{
- var node = document.createElement('v:group');
- node.style.position = 'absolute';
- this.shapeNode = document.createElement('v:shape');
- this.updateVmlStrokeColor(this.shapeNode);
- this.updateVmlStrokeNode(this.shapeNode);
- node.appendChild(this.shapeNode);
- this.shapeNode.filled = 'false';
-
- if (this.isShadow)
- {
- this.createVmlShadow(this.shapeNode);
- }
-
- // Creates the start arrow as an additional child path
- if (this.startArrow != null)
- {
- this.start = document.createElement('v:shape');
- this.start.style.position = 'absolute';
-
- // Only required for opacity and joinstyle
- this.startStroke = document.createElement('v:stroke');
- this.startStroke.joinstyle = 'miter';
- this.start.appendChild(this.startStroke);
-
- this.startFill = document.createElement('v:fill');
- this.start.appendChild(this.startFill);
-
- node.appendChild(this.start);
- }
-
- // Creates the end arrows as an additional child path
- if (this.endArrow != null)
- {
- this.end = document.createElement('v:shape');
- this.end.style.position = 'absolute';
-
- // Only required for opacity and joinstyle
- this.endStroke = document.createElement('v:stroke');
- this.endStroke.joinstyle = 'miter';
- this.end.appendChild(this.endStroke);
-
- this.endFill = document.createElement('v:fill');
- this.end.appendChild(this.endFill);
-
- node.appendChild(this.end);
- }
-
- this.updateVmlMarkerOpacity();
-
- return node;
-};
-
-/**
- * Function: updateVmlMarkerOpacity
- *
- * Updates the opacity for the markers in VML.
- */
-mxConnector.prototype.updateVmlMarkerOpacity = function()
-{
- var op = (this.opacity != null) ? (this.opacity + '%') : '100%';
-
- if (this.start != null)
- {
- this.startFill.opacity = op;
- this.startStroke.opacity = op;
- }
-
- if (this.end != null)
- {
- this.endFill.opacity = op;
- this.endStroke.opacity = op;
- }
-};
-
-/**
- * Function: redrawVml
- *
- * Redraws this VML shape by invoking <updateVmlShape> on this.node.
- */
-mxConnector.prototype.reconfigure = function()
-{
- // Never fill a connector
- this.fill = null;
-
- if (mxUtils.isVml(this.node))
- {
- // Updates the style of the given shape
- // LATER: Check if this can be replaced with redrawVml and
- // updating the color, dash pattern and shadow.
- this.node.style.visibility = 'hidden';
- this.configureVmlShape(this.shapeNode);
- this.updateVmlMarkerOpacity();
- this.node.style.visibility = 'visible';
- }
- else
- {
- mxShape.prototype.reconfigure.apply(this, arguments);
- }
-};
-
-/**
- * Function: redrawVml
- *
- * Redraws this VML shape by invoking <updateVmlShape> on this.node.
- */
-mxConnector.prototype.redrawVml = function()
-{
- if (this.node != null && this.points != null && this.bounds != null &&
- !isNaN(this.bounds.x) && !isNaN(this.bounds.y) &&
- !isNaN(this.bounds.width) && !isNaN(this.bounds.height))
- {
- var w = Math.max(0, Math.round(this.bounds.width));
- var h = Math.max(0, Math.round(this.bounds.height));
- var cs = w + ',' + h;
- w += 'px';
- h += 'px';
-
- // Computes the marker paths before the main path is updated so
- // that offsets can be taken into account
- if (this.start != null)
- {
- this.start.style.width = w;
- this.start.style.height = h;
- this.start.coordsize = cs;
-
- var p0 = this.points[1];
- var pe = this.points[0];
-
- var size = mxUtils.getNumber(this.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE);
- this.startOffset = this.redrawMarker(this.start, this.startArrow, p0, pe, this.stroke, size);
- }
-
- if (this.end != null)
- {
- this.end.style.width = w;
- this.end.style.height = h;
- this.end.coordsize = cs;
-
- var n = this.points.length;
- var p0 = this.points[n - 2];
- var pe = this.points[n - 1];
-
- var size = mxUtils.getNumber(this.style, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE);
- this.endOffset = this.redrawMarker(this.end, this.endArrow, p0, pe, this.stroke, size);
- }
-
- this.updateVmlShape(this.node);
- this.updateVmlShape(this.shapeNode);
- this.shapeNode.filled = 'false';
-
- // Adds custom dash pattern
- if (this.isDashed)
- {
- var pat = mxUtils.getValue(this.style, 'dashStyle', null);
-
- if (pat != null)
- {
- this.strokeNode.dashstyle = pat;
- }
-
- if (this.shadowStrokeNode != null)
- {
- this.shadowStrokeNode.dashstyle = this.strokeNode.dashstyle;
- }
- }
- }
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node to represent this shape.
- */
-mxConnector.prototype.createSvg = function()
-{
- this.fill = null;
- var g = this.createSvgGroup('path');
-
- // Creates the start arrow as an additional child path
- if (this.startArrow != null)
- {
- this.start = document.createElementNS(mxConstants.NS_SVG, 'path');
- g.appendChild(this.start);
- }
-
- // Creates the end arrows as an additional child path
- if (this.endArrow != null)
- {
- this.end = document.createElementNS(mxConstants.NS_SVG, 'path');
- g.appendChild(this.end);
- }
-
- // Creates an invisible shape around the path for easier
- // selection with the mouse. Note: Firefox does not ignore
- // the value of the stroke attribute for pointer-events: stroke,
- // it does, however, ignore the visibility attribute.
- if (this.addPipe)
- {
- this.pipe = this.createSvgPipe();
- g.appendChild(this.pipe);
- }
-
- return g;
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxConnector.prototype.redrawSvg = function()
-{
- // Computes the markers first which modifies the coordinates of the
- // endpoints to not overlap with the painted marker then updates the actual
- // shape for the edge to take the modified endpoints into account.
- if (this.points != null && this.points[0] != null)
- {
- var color = this.innerNode.getAttribute('stroke');
-
- // Draws the start marker
- if (this.start != null)
- {
- var p0 = this.points[1];
- var pe = this.points[0];
-
- var size = mxUtils.getNumber(this.style, mxConstants.STYLE_STARTSIZE,
- mxConstants.DEFAULT_MARKERSIZE);
- this.startOffset = this.redrawMarker(this.start,
- this.startArrow, p0, pe, color, size);
-
- if (this.allowCrispMarkers && this.crisp)
- {
- this.start.setAttribute('shape-rendering', 'crispEdges');
- }
- else
- {
- this.start.removeAttribute('shape-rendering');
- }
- }
-
- // Draws the end marker
- if (this.end != null)
- {
- var n = this.points.length;
-
- var p0 = this.points[n - 2];
- var pe = this.points[n - 1];
-
- var size = mxUtils.getNumber(this.style, mxConstants.STYLE_ENDSIZE,
- mxConstants.DEFAULT_MARKERSIZE);
- this.endOffset = this.redrawMarker(this.end,
- this.endArrow, p0, pe, color, size);
-
- if (this.allowCrispMarkers && this.crisp)
- {
- this.end.setAttribute('shape-rendering', 'crispEdges');
- }
- else
- {
- this.end.removeAttribute('shape-rendering');
- }
- }
- }
-
- this.updateSvgShape(this.innerNode);
- var d = this.innerNode.getAttribute('d');
-
- if (d != null)
- {
- var strokeWidth = Math.round(this.strokewidth * this.scale);
-
- // Updates the tolerance of the invisible shape for event handling
- if (this.pipe != null)
- {
- this.pipe.setAttribute('d', this.innerNode.getAttribute('d'));
- this.pipe.setAttribute('stroke-width', strokeWidth + mxShape.prototype.SVG_STROKE_TOLERANCE);
- }
-
- // Updates the shadow
- if (this.shadowNode != null)
- {
- this.shadowNode.setAttribute('transform', this.getSvgShadowTransform());
- this.shadowNode.setAttribute('d', d);
- this.shadowNode.setAttribute('stroke-width', strokeWidth);
- }
- }
-
- // Adds custom dash pattern
- if (this.isDashed)
- {
- var pat = this.createDashPattern(this.scale * this.strokewidth);
-
- if (pat != null)
- {
- this.innerNode.setAttribute('stroke-dasharray', pat);
- }
- }
-
- // Updates the shadow
- if (this.shadowNode != null)
- {
- var pat = this.innerNode.getAttribute('stroke-dasharray');
-
- if (pat != null)
- {
- this.shadowNode.setAttribute('stroke-dasharray', pat);
- }
- }
-};
-
-/**
- * Function: createDashPattern
- *
- * Creates a dash pattern for the given factor.
- */
-mxConnector.prototype.createDashPattern = function(factor)
-{
- var value = mxUtils.getValue(this.style, 'dashPattern', null);
-
- if (value != null)
- {
- var tmp = value.split(' ');
- var pat = [];
-
- for (var i = 0; i < tmp.length; i++)
- {
- if (tmp[i].length > 0)
- {
- pat.push(Math.round(Number(tmp[i]) * factor));
- }
- }
-
- return pat.join(' ');
- }
-
- return null;
-};
-
-/**
- * Function: redrawMarker
- *
- * Updates the given SVG or VML marker.
- */
-mxConnector.prototype.redrawMarker = function(node, type, p0, pe, color, size)
-{
- return mxMarker.paintMarker(node, type, p0, pe, color, this.strokewidth,
- size, this.scale, this.bounds.x, this.bounds.y, this.start == node,
- this.style);
-};
diff --git a/src/js/shape/mxCylinder.js b/src/js/shape/mxCylinder.js
deleted file mode 100644
index 9a45760..0000000
--- a/src/js/shape/mxCylinder.js
+++ /dev/null
@@ -1,319 +0,0 @@
-/**
- * $Id: mxCylinder.js,v 1.38 2012-07-31 11:46:53 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCylinder
- *
- * Extends <mxShape> to implement an cylinder shape. If a
- * custom shape with one filled area and an overlay path is
- * needed, then this shape's <redrawPath> should be overridden.
- * This shape is registered under <mxConstants.SHAPE_CYLINDER>
- * in <mxCellRenderer>.
- *
- * Constructor: mxCylinder
- *
- * Constructs a new cylinder shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxCylinder(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxCylinder.prototype = new mxShape();
-mxCylinder.prototype.constructor = mxCylinder;
-
-/**
- * Variable: vmlNodes
- *
- * Adds local references to <mxShape.vmlNodes>.
- */
-mxCylinder.prototype.vmlNodes = mxCylinder.prototype.vmlNodes.concat(['background', 'foreground']);
-
-/**
- * Variable: mixedModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw in VML in mixed Html mode.
- */
-mxCylinder.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw as VML in prefer Html mode.
- */
-mxCylinder.prototype.preferModeHtml = false;
-
-/**
- * Variable: addPipe
- *
- * Specifies if a SVG path should be created around the background for better
- * hit detection. Default is false.
- */
-mxCylinder.prototype.addPipe = false;
-
-/**
- * Variable: strokedBackground
- *
- * Specifies if the background should be stroked. Default is true.
- */
-mxCylinder.prototype.strokedBackground = true;
-
-/**
- * Variable: maxHeight
- *
- * Defines the maximum height of the top and bottom part
- * of the cylinder shape.
- */
-mxCylinder.prototype.maxHeight = 40;
-
-/**
- * Variable: vmlScale
- *
- * Renders VML with a scale of 2.
- */
-mxCylinder.prototype.vmlScale = 2;
-
-/**
- * Function: create
- *
- * Overrides the method to make sure the <stroke> is never
- * null. If it is null is will be assigned the <fill> color.
- */
-mxCylinder.prototype.create = function(container)
-{
- if (this.stroke == null)
- {
- this.stroke = this.fill;
- }
-
- // Calls superclass implementation of create
- return mxShape.prototype.create.apply(this, arguments);
-};
-
-/**
- * Function: reconfigure
- *
- * Overrides the method to make sure the <stroke> is applied to the foreground.
- */
-mxCylinder.prototype.reconfigure = function()
-{
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- this.configureSvgShape(this.foreground);
- this.foreground.setAttribute('fill', 'none');
- }
- else if (mxUtils.isVml(this.node))
- {
- this.configureVmlShape(this.background);
- this.configureVmlShape(this.foreground);
- }
-
- mxShape.prototype.reconfigure.apply(this);
-};
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
-mxCylinder.prototype.createVml = function()
-{
- var node = document.createElement('v:group');
-
- // Draws the background
- this.background = document.createElement('v:shape');
- this.label = this.background;
- this.configureVmlShape(this.background);
- node.appendChild(this.background);
-
- // Ignores values that only apply to the background
- this.fill = null;
- this.isShadow = false;
- this.configureVmlShape(node);
-
- // Draws the foreground
- this.foreground = document.createElement('v:shape');
- this.configureVmlShape(this.foreground);
-
- // To match SVG defaults jointsyle miter, miterlimit 4
- this.fgStrokeNode = document.createElement('v:stroke');
- this.fgStrokeNode.joinstyle = 'miter';
- this.fgStrokeNode.miterlimit = 4;
- this.foreground.appendChild(this.fgStrokeNode);
-
- node.appendChild(this.foreground);
-
- return node;
-};
-
-/**
- * Function: redrawVml
- *
- * Updates the VML node(s) to reflect the latest bounds and scale.
- */
-mxCylinder.prototype.redrawVml = function()
-{
- this.updateVmlShape(this.node);
- this.updateVmlShape(this.background);
- this.updateVmlShape(this.foreground);
- this.background.path = this.createPath(false);
- this.foreground.path = this.createPath(true);
-
- this.fgStrokeNode.dashstyle = this.strokeNode.dashstyle;
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxCylinder.prototype.createSvg = function()
-{
- var g = this.createSvgGroup('path');
- this.foreground = document.createElementNS(mxConstants.NS_SVG, 'path');
-
- if (this.stroke != null && this.stroke != mxConstants.NONE)
- {
- this.foreground.setAttribute('stroke', this.stroke);
- }
- else
- {
- this.foreground.setAttribute('stroke', 'none');
- }
-
- this.foreground.setAttribute('fill', 'none');
- g.appendChild(this.foreground);
-
- if (this.addPipe)
- {
- this.pipe = this.createSvgPipe();
- g.appendChild(this.pipe);
- }
-
- return g;
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxCylinder.prototype.redrawSvg = function()
-{
- var strokeWidth = Math.round(Math.max(1, this.strokewidth * this.scale));
- this.innerNode.setAttribute('stroke-width', strokeWidth);
-
- if (this.crisp && (this.rotation == null || this.rotation == 0))
- {
- this.innerNode.setAttribute('shape-rendering', 'crispEdges');
- this.foreground.setAttribute('shape-rendering', 'crispEdges');
- }
- else
- {
- this.innerNode.removeAttribute('shape-rendering');
- this.foreground.removeAttribute('shape-rendering');
- }
-
- // Paints background
- var d = this.createPath(false);
-
- if (d.length > 0)
- {
- this.innerNode.setAttribute('d', d);
-
- // Updates event handling element
- if (this.pipe != null)
- {
- this.pipe.setAttribute('d', d);
- this.pipe.setAttribute('stroke-width', strokeWidth + mxShape.prototype.SVG_STROKE_TOLERANCE);
- this.pipe.setAttribute('transform', (this.innerNode.getAttribute('transform') || ''));
- }
- }
- else
- {
- this.innerNode.removeAttribute('d');
-
- // Updates event handling element
- if (this.pipe != null)
- {
- this.pipe.removeAttribute('d');
- }
- }
-
- // Stroked background
- if (!this.strokedBackground)
- {
- this.innerNode.setAttribute('stroke', 'none');
- }
-
- // Paints shadow
- if (this.shadowNode != null)
- {
- this.shadowNode.setAttribute('stroke-width', strokeWidth);
- this.shadowNode.setAttribute('d', d);
- this.shadowNode.setAttribute('transform', this.getSvgShadowTransform());
- }
-
- // Paints foreground
- d = this.createPath(true);
-
- if (d.length > 0)
- {
- this.foreground.setAttribute('stroke-width', strokeWidth);
- this.foreground.setAttribute('d', d);
- }
- else
- {
- this.foreground.removeAttribute('d');
- }
-
- if (this.isDashed)
- {
- var phase = Math.max(1, Math.round(3 * this.scale * this.strokewidth));
- this.innerNode.setAttribute('stroke-dasharray', phase + ' ' + phase);
- this.foreground.setAttribute('stroke-dasharray', phase + ' ' + phase);
- }
-};
-
-/**
- * Function: redrawPath
- *
- * Draws the path for this shape. This method uses the <mxPath>
- * abstraction to paint the shape for VML and SVG.
- */
-mxCylinder.prototype.redrawPath = function(path, x, y, w, h, isForeground)
-{
- var dy = Math.min(this.maxHeight, Math.round(h / 5));
-
- if (isForeground)
- {
- path.moveTo(0, dy);
- path.curveTo(0, 2 * dy, w, 2 * dy, w, dy);
- }
- else
- {
- path.moveTo(0, dy);
- path.curveTo(0, -dy / 3, w, -dy / 3, w, dy);
- path.lineTo(w, h - dy);
- path.curveTo(w, h + dy / 3, 0, h + dy / 3, 0, h - dy);
- path.close();
- }
-};
diff --git a/src/js/shape/mxDoubleEllipse.js b/src/js/shape/mxDoubleEllipse.js
deleted file mode 100644
index 7854851..0000000
--- a/src/js/shape/mxDoubleEllipse.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
- * $Id: mxDoubleEllipse.js,v 1.19 2012-05-21 18:27:17 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxDoubleEllipse
- *
- * Extends <mxShape> to implement a double ellipse shape.
- * This shape is registered under <mxConstants.SHAPE_DOUBLE_ELLIPSE>
- * in <mxCellRenderer>.
- *
- * Constructor: mxDoubleEllipse
- *
- * Constructs a new ellipse shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxDoubleEllipse(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxDoubleEllipse.prototype = new mxShape();
-mxDoubleEllipse.prototype.constructor = mxDoubleEllipse;
-
-/**
- * Variable: vmlNodes
- *
- * Adds local references to <mxShape.vmlNodes>.
- */
-mxDoubleEllipse.prototype.vmlNodes = mxDoubleEllipse.prototype.vmlNodes.concat(['background', 'foreground']);
-
-/**
- * Variable: mixedModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw in VML in mixed Html mode.
- */
-mxDoubleEllipse.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw as VML in prefer Html mode.
- */
-mxDoubleEllipse.prototype.preferModeHtml = false;
-
-/**
- * Variable: vmlScale
- *
- * Renders VML with a scale of 2.
- */
-mxDoubleEllipse.prototype.vmlScale = 2;
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
-mxDoubleEllipse.prototype.createVml = function()
-{
- var node = document.createElement('v:group');
-
- // Draws the background
- this.background = document.createElement('v:arc');
- this.background.startangle = '0';
- this.background.endangle = '360';
- this.configureVmlShape(this.background);
-
- node.appendChild(this.background);
-
- // Ignores values that only apply to the background
- this.label = this.background;
- this.isShadow = false;
- this.fill = null;
-
- // Draws the foreground
- this.foreground = document.createElement('v:oval');
- this.configureVmlShape(this.foreground);
-
- node.appendChild(this.foreground);
-
- this.stroke = null;
- this.configureVmlShape(node);
-
- return node;
-};
-
-/**
- * Function: redrawVml
- *
- * Updates the VML node(s) to reflect the latest bounds and scale.
- */
-mxDoubleEllipse.prototype.redrawVml = function()
-{
- this.updateVmlShape(this.node);
- this.updateVmlShape(this.background);
- this.updateVmlShape(this.foreground);
-
- var inset = Math.round((this.strokewidth + 3) * this.scale) * this.vmlScale;
- var w = Math.round(this.bounds.width * this.vmlScale);
- var h = Math.round(this.bounds.height * this.vmlScale);
-
- this.foreground.style.top = inset + 'px'; // relative
- this.foreground.style.left = inset + 'px'; // relative
- this.foreground.style.width = Math.max(0, w - 2 * inset) + 'px';
- this.foreground.style.height = Math.max(0, h - 2 * inset) + 'px';
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxDoubleEllipse.prototype.createSvg = function()
-{
- var g = this.createSvgGroup('ellipse');
- this.foreground = document.createElementNS(mxConstants.NS_SVG, 'ellipse');
-
- if (this.stroke != null)
- {
- this.foreground.setAttribute('stroke', this.stroke);
- }
- else
- {
- this.foreground.setAttribute('stroke', 'none');
- }
-
- this.foreground.setAttribute('fill', 'none');
- g.appendChild(this.foreground);
-
- return g;
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxDoubleEllipse.prototype.redrawSvg = function()
-{
- if (this.crisp)
- {
- this.innerNode.setAttribute('shape-rendering', 'crispEdges');
- this.foreground.setAttribute('shape-rendering', 'crispEdges');
- }
- else
- {
- this.innerNode.removeAttribute('shape-rendering');
- this.foreground.removeAttribute('shape-rendering');
- }
-
- this.updateSvgNode(this.innerNode);
- this.updateSvgNode(this.shadowNode);
- this.updateSvgNode(this.foreground, (this.strokewidth + 3) * this.scale);
-
- if (this.isDashed)
- {
- var phase = Math.max(1, Math.round(3 * this.scale * this.strokewidth));
- this.innerNode.setAttribute('stroke-dasharray', phase + ' ' + phase);
- }
-};
-
-/**
- * Function: updateSvgNode
- *
- * Updates the given node to reflect the new <bounds> and <scale>.
- */
-mxDoubleEllipse.prototype.updateSvgNode = function(node, inset)
-{
- inset = (inset != null) ? inset : 0;
-
- if (node != null)
- {
- var strokeWidth = Math.round(Math.max(1, this.strokewidth * this.scale));
- node.setAttribute('stroke-width', strokeWidth);
-
- node.setAttribute('cx', this.bounds.x + this.bounds.width / 2);
- node.setAttribute('cy', this.bounds.y + this.bounds.height / 2);
- node.setAttribute('rx', Math.max(0, this.bounds.width / 2 - inset));
- node.setAttribute('ry', Math.max(0, this.bounds.height / 2 - inset));
-
- // Updates the transform of the shadow
- if (this.shadowNode != null)
- {
- this.shadowNode.setAttribute('transform', this.getSvgShadowTransform());
- }
- }
-};
diff --git a/src/js/shape/mxEllipse.js b/src/js/shape/mxEllipse.js
deleted file mode 100644
index f3882cf..0000000
--- a/src/js/shape/mxEllipse.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * $Id: mxEllipse.js,v 1.20 2012-04-04 07:34:50 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxEllipse
- *
- * Extends <mxShape> to implement an ellipse shape.
- * This shape is registered under <mxConstants.SHAPE_ELLIPSE>
- * in <mxCellRenderer>.
- *
- * Constructor: mxEllipse
- *
- * Constructs a new ellipse shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxEllipse(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxEllipse.prototype = new mxShape();
-mxEllipse.prototype.constructor = mxEllipse;
-
-/**
- * Variable: mixedModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw in VML in mixed Html mode.
- */
-mxEllipse.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw as VML in prefer Html mode.
- */
-mxEllipse.prototype.preferModeHtml = false;
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
-mxEllipse.prototype.createVml = function()
-{
- // Uses an arc not an oval to make sure the
- // textbox fills out the outer bounds of the
- // circle, not just the inner rectangle
- var node = document.createElement('v:arc');
- node.startangle = '0';
- node.endangle = '360';
- this.configureVmlShape(node);
-
- return node;
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxEllipse.prototype.createSvg = function()
-{
- return this.createSvgGroup('ellipse');
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxEllipse.prototype.redrawSvg = function()
-{
- if (this.crisp)
- {
- this.innerNode.setAttribute('shape-rendering', 'crispEdges');
- }
- else
- {
- this.innerNode.removeAttribute('shape-rendering');
- }
-
- this.updateSvgNode(this.innerNode);
- this.updateSvgNode(this.shadowNode);
-};
-
-/**
- * Function: updateSvgNode
- *
- * Updates the given node to reflect the new <bounds> and <scale>.
- */
-mxEllipse.prototype.updateSvgNode = function(node)
-{
- if (node != null)
- {
- var strokeWidth = Math.round(Math.max(1, this.strokewidth * this.scale));
- node.setAttribute('stroke-width', strokeWidth);
-
- node.setAttribute('cx', this.bounds.x + this.bounds.width / 2);
- node.setAttribute('cy', this.bounds.y + this.bounds.height / 2);
- node.setAttribute('rx', this.bounds.width / 2);
- node.setAttribute('ry', this.bounds.height / 2);
-
- // Updates the shadow offset
- if (this.shadowNode != null)
- {
- this.shadowNode.setAttribute('transform', this.getSvgShadowTransform());
- }
-
- if (this.isDashed)
- {
- var phase = Math.max(1, Math.round(3 * this.scale * this.strokewidth));
- node.setAttribute('stroke-dasharray', phase + ' ' + phase);
- }
- }
-};
diff --git a/src/js/shape/mxHexagon.js b/src/js/shape/mxHexagon.js
deleted file mode 100644
index 7fa45a3..0000000
--- a/src/js/shape/mxHexagon.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * $Id: mxHexagon.js,v 1.8 2011-09-02 10:01:00 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxHexagon
- *
- * Implementation of the hexagon shape.
- *
- * Constructor: mxHexagon
- *
- * Constructs a new hexagon shape.
- */
-function mxHexagon() { };
-
-/**
- * Extends <mxActor>.
- */
-mxHexagon.prototype = new mxActor();
-mxHexagon.prototype.constructor = mxHexagon;
-
-/**
- * Function: redrawPath
- *
- * Draws the path for this shape. This method uses the <mxPath>
- * abstraction to paint the shape for VML and SVG.
- */
-mxHexagon.prototype.redrawPath = function(path, x, y, w, h)
-{
- path.moveTo(0.25 * w, 0);
- path.lineTo(0.75 * w, 0);
- path.lineTo(w, 0.5 * h);
- path.lineTo(0.75 * w, h);
- path.lineTo(0.25 * w, h);
- path.lineTo(0, 0.5 * h);
- path.close();
-};
diff --git a/src/js/shape/mxImageShape.js b/src/js/shape/mxImageShape.js
deleted file mode 100644
index 2f1eab0..0000000
--- a/src/js/shape/mxImageShape.js
+++ /dev/null
@@ -1,405 +0,0 @@
-/**
- * $Id: mxImageShape.js,v 1.67 2012-04-22 10:16:23 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxImageShape
- *
- * Extends <mxShape> to implement an image shape. This shape is registered
- * under <mxConstants.SHAPE_IMAGE> in <mxCellRenderer>.
- *
- * Constructor: mxImageShape
- *
- * Constructs a new image shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * image - String that specifies the URL of the image. This is stored in
- * <image>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 0. This is stored in <strokewidth>.
- */
-function mxImageShape(bounds, image, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.image = (image != null) ? image : '';
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
- this.isShadow = false;
-};
-
-/**
- * Extends mxShape.
- */
-mxImageShape.prototype = new mxShape();
-mxImageShape.prototype.constructor = mxImageShape;
-
-/**
- * Variable: crisp
- *
- * Disables crisp rendering via attributes. Image quality defines the rendering
- * quality. Default is false.
- */
-mxImageShape.prototype.crisp = false;
-
-/**
- * Variable: preserveImageAspect
- *
- * Switch to preserve image aspect. Default is true.
- */
-mxImageShape.prototype.preserveImageAspect = true;
-
-/**
- * Function: apply
- *
- * Overrides <mxShape.apply> to replace the fill and stroke colors with the
- * respective values from <mxConstants.STYLE_IMAGE_BACKGROUND> and
- * <mxConstants.STYLE_IMAGE_BORDER>.
- *
- * Applies the style of the given <mxCellState> to the shape. This
- * implementation assigns the following styles to local fields:
- *
- * - <mxConstants.STYLE_IMAGE_BACKGROUND> => fill
- * - <mxConstants.STYLE_IMAGE_BORDER> => stroke
- *
- * Parameters:
- *
- * state - <mxCellState> of the corresponding cell.
- */
-mxImageShape.prototype.apply = function(state)
-{
- mxShape.prototype.apply.apply(this, arguments);
-
- this.fill = null;
- this.stroke = null;
-
- if (this.style != null)
- {
- this.fill = mxUtils.getValue(this.style, mxConstants.STYLE_IMAGE_BACKGROUND);
- this.stroke = mxUtils.getValue(this.style, mxConstants.STYLE_IMAGE_BORDER);
- this.preserveImageAspect = mxUtils.getNumber(this.style, mxConstants.STYLE_IMAGE_ASPECT, 1) == 1;
- this.gradient = null;
- }
-};
-
-/**
- * Function: create
- *
- * Override to create HTML regardless of gradient and
- * rounded property.
- */
-mxImageShape.prototype.create = function()
-{
- var node = null;
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- // Workaround: To avoid control-click on images in Firefox to
- // open the image in a new window, this image needs to be placed
- // inside a group with a rectangle in the foreground which has a
- // fill property but no visibility and absorbs all events.
- // The image in turn must have all pointer-events disabled.
- node = this.createSvgGroup('rect');
- this.innerNode.setAttribute('visibility', 'hidden');
- this.innerNode.setAttribute('pointer-events', 'fill');
-
- this.imageNode = document.createElementNS(mxConstants.NS_SVG, 'image');
- this.imageNode.setAttributeNS(mxConstants.NS_XLINK, 'xlink:href', this.image);
- this.imageNode.setAttribute('style', 'pointer-events:none');
- this.configureSvgShape(this.imageNode);
-
- // Removes invalid attributes on the image node
- this.imageNode.removeAttribute('stroke');
- this.imageNode.removeAttribute('fill');
- node.insertBefore(this.imageNode, this.innerNode);
-
- // Inserts node for background and border color rendering
- if ((this.fill != null && this.fill != mxConstants.NONE) ||
- (this.stroke != null && this.stroke != mxConstants.NONE))
- {
- this.bg = document.createElementNS(mxConstants.NS_SVG, 'rect');
- node.insertBefore(this.bg, node.firstChild);
- }
-
- // Preserves image aspect as default
- if (!this.preserveImageAspect)
- {
- this.imageNode.setAttribute('preserveAspectRatio', 'none');
- }
- }
- else
- {
- // Uses VML image for all non-embedded images in IE to support better
- // image flipping quality and avoid workarounds for event redirection
- var flipH = mxUtils.getValue(this.style, mxConstants.STYLE_IMAGE_FLIPH, 0) == 1;
- var flipV = mxUtils.getValue(this.style, mxConstants.STYLE_IMAGE_FLIPV, 0) == 1;
- var img = this.image.toUpperCase();
-
- // Handles non-flipped embedded images in IE6
- if (mxClient.IS_IE && !flipH && !flipV && img.substring(0, 6) == 'MHTML:')
- {
- // LATER: Check if outer DIV is required or if aspect can be implemented
- // by adding an offset to the image loading or the background via CSS.
- this.imageNode = document.createElement('DIV');
- this.imageNode.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader ' +
- '(src=\'' + this.image + '\', sizingMethod=\'scale\')';
-
- node = document.createElement('DIV');
- this.configureHtmlShape(node);
- node.appendChild(this.imageNode);
- }
- // Handles all data URL images and HTML images for IE9 with no VML support (in SVG mode)
- else if (!mxClient.IS_IE || img.substring(0, 5) == 'DATA:' || document.documentMode >= 9)
- {
- this.imageNode = document.createElement('img');
- this.imageNode.setAttribute('src', this.image);
- this.imageNode.setAttribute('border', '0');
- this.imageNode.style.position = 'absolute';
- this.imageNode.style.width = '100%';
- this.imageNode.style.height = '100%';
-
- node = document.createElement('DIV');
- this.configureHtmlShape(node);
- node.appendChild(this.imageNode);
- }
- else
- {
- this.imageNode = document.createElement('v:image');
- this.imageNode.style.position = 'absolute';
- this.imageNode.src = this.image;
-
- // Needed to draw the background and border but known
- // to cause problems in print preview with https
- node = document.createElement('DIV');
- this.configureHtmlShape(node);
-
- // Workaround for cropped images in IE7/8
- node.style.overflow = 'visible';
- node.appendChild(this.imageNode);
- }
- }
-
- return node;
-};
-
-/**
- * Function: updateAspect
- *
- * Updates the aspect of the image for the given image width and height.
- */
-mxImageShape.prototype.updateAspect = function(w, h)
-{
- var s = Math.min(this.bounds.width / w, this.bounds.height / h);
- w = Math.max(0, Math.round(w * s));
- h = Math.max(0, Math.round(h * s));
- var x0 = Math.max(0, Math.round((this.bounds.width - w) / 2));
- var y0 = Math.max(0, Math.round((this.bounds.height - h) / 2));
- var st = this.imageNode.style;
-
- // Positions the child node relative to the parent node
- if (this.imageNode.parentNode == this.node)
- {
- // Workaround for duplicate offset in VML in IE8 is
- // to use parent padding instead of left and top
- this.node.style.paddingLeft = x0 + 'px';
- this.node.style.paddingTop = y0 + 'px';
- }
- else
- {
- st.left = (Math.round(this.bounds.x) + x0) + 'px';
- st.top = (Math.round(this.bounds.y) + y0) + 'px';
- }
-
- st.width = w + 'px';
- st.height = h + 'px';
-};
-
-/**
- * Function: scheduleUpdateAspect
- *
- * Schedules an asynchronous <updateAspect> using the current <image>.
- */
-mxImageShape.prototype.scheduleUpdateAspect = function()
-{
- var img = new Image();
-
- img.onload = mxUtils.bind(this, function()
- {
- mxImageShape.prototype.updateAspect.call(this, img.width, img.height);
- });
-
- img.src = this.image;
-};
-
-/**
- * Function: redraw
- *
- * Overrides <mxShape.redraw> to preserve the aspect ratio of images.
- */
-mxImageShape.prototype.redraw = function()
-{
- mxShape.prototype.redraw.apply(this, arguments);
-
- if (this.imageNode != null && this.bounds != null)
- {
- // Horizontal and vertical flipping
- var flipH = mxUtils.getValue(this.style, mxConstants.STYLE_IMAGE_FLIPH, 0) == 1;
- var flipV = mxUtils.getValue(this.style, mxConstants.STYLE_IMAGE_FLIPV, 0) == 1;
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- var sx = 1;
- var sy = 1;
- var dx = 0;
- var dy = 0;
-
- if (flipH)
- {
- sx = -1;
- dx = -this.bounds.width - 2 * this.bounds.x;
- }
-
- if (flipV)
- {
- sy = -1;
- dy = -this.bounds.height - 2 * this.bounds.y;
- }
-
- // Adds image tansformation to existing transforms
- var transform = (this.imageNode.getAttribute('transform') || '') +
- ' scale('+sx+' '+sy+')'+ ' translate('+dx+' '+dy+')';
- this.imageNode.setAttribute('transform', transform);
- }
- else
- {
- // Sets default size (no aspect)
- if (this.imageNode.nodeName != 'DIV')
- {
- this.imageNode.style.width = Math.max(0, Math.round(this.bounds.width)) + 'px';
- this.imageNode.style.height = Math.max(0, Math.round(this.bounds.height)) + 'px';
- }
-
- // Preserves image aspect
- if (this.preserveImageAspect)
- {
- this.scheduleUpdateAspect();
- }
-
- if (flipH || flipV)
- {
- if (mxUtils.isVml(this.imageNode))
- {
- if (flipH && flipV)
- {
- this.imageNode.style.rotation = '180';
- }
- else if (flipH)
- {
- this.imageNode.style.flip = 'x';
- }
- else
- {
- this.imageNode.style.flip = 'y';
- }
- }
- else
- {
- var filter = (this.imageNode.nodeName == 'DIV') ? 'progid:DXImageTransform.Microsoft.AlphaImageLoader ' +
- '(src=\'' + this.image + '\', sizingMethod=\'scale\')' : '';
-
- if (flipH && flipV)
- {
- filter += 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2)';
- }
- else if (flipH)
- {
- filter += 'progid:DXImageTransform.Microsoft.BasicImage(mirror=1)';
- }
- else
- {
- filter += 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)';
- }
-
- if (this.imageNode.style.filter != filter)
- {
- this.imageNode.style.filter = filter;
- }
- }
- }
- }
- }
-};
-
-/**
- * Function: configureTransparentBackground
- *
- * Workaround for security warning in IE if this is used in the overlay pane
- * of a diagram.
- */
-mxImageShape.prototype.configureTransparentBackground = function(node)
-{
- // do nothing
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxImageShape.prototype.redrawSvg = function()
-{
- this.updateSvgShape(this.innerNode);
- this.updateSvgShape(this.imageNode);
-
- if (this.bg != null)
- {
- this.updateSvgShape(this.bg);
-
- if (this.fill != null)
- {
- this.bg.setAttribute('fill', this.fill);
- }
- else
- {
- this.bg.setAttribute('fill', 'none');
- }
-
- if (this.stroke != null)
- {
- this.bg.setAttribute('stroke', this.stroke);
- }
- else
- {
- this.bg.setAttribute('stroke', 'none');
- }
-
- this.bg.setAttribute('shape-rendering', 'crispEdges');
- }
-};
-
-/**
- * Function: configureSvgShape
- *
- * Extends method to set opacity on images.
- */
-mxImageShape.prototype.configureSvgShape = function(node)
-{
- mxShape.prototype.configureSvgShape.apply(this, arguments);
-
- if (this.imageNode != null)
- {
- if (this.opacity != null)
- {
- this.imageNode.setAttribute('opacity', this.opacity / 100);
- }
- else
- {
- this.imageNode.removeAttribute('opacity');
- }
- }
-};
diff --git a/src/js/shape/mxLabel.js b/src/js/shape/mxLabel.js
deleted file mode 100644
index c31f3bf..0000000
--- a/src/js/shape/mxLabel.js
+++ /dev/null
@@ -1,427 +0,0 @@
-/**
- * $Id: mxLabel.js,v 1.40 2012-05-22 16:10:12 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxLabel
- *
- * Extends <mxShape> to implement an image shape with a label.
- * This shape is registered under <mxConstants.SHAPE_LABEL> in
- * <mxCellRenderer>.
- *
- * Constructor: mxLabel
- *
- * Constructs a new label shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxLabel(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxLabel.prototype = new mxShape();
-mxLabel.prototype.constructor = mxLabel;
-
-/**
- * Variable: vmlNodes
- *
- * Adds local references to <mxShape.vmlNodes>.
- */
-mxLabel.prototype.vmlNodes = mxLabel.prototype.vmlNodes.concat(['label', 'imageNode', 'indicatorImageNode', 'rectNode']);
-
-/**
- * Variable: imageSize
- *
- * Default width and height for the image. Default is
- * <mxConstants.DEFAULT_IMAGESIZE>.
- */
-mxLabel.prototype.imageSize = mxConstants.DEFAULT_IMAGESIZE;
-
-/**
- * Variable: spacing
- *
- * Default value for spacing. Default is 2.
- */
-mxLabel.prototype.spacing = 2;
-
-/**
- * Variable: indicatorSize
- *
- * Default width and height for the indicicator. Default is
- * 10.
- */
-mxLabel.prototype.indicatorSize = 10;
-
-/**
- * Variable: indicatorSpacing
- *
- * Default spacing between image and indicator. Default is 2.
- */
-mxLabel.prototype.indicatorSpacing = 2;
-
-/**
- * Variable: opaqueVmlImages
- *
- * Specifies if all VML images should be rendered without transparency, that
- * is, if the current opacity should be ignored for images. Default is false.
- */
-mxLabel.prototype.opaqueVmlImages = false;
-
-/**
- * Function: init
- *
- * Initializes the shape and adds it to the container. This function is
- * overridden so that the node is already in the DOM when the indicator
- * is added. This is required to access the ownerSVGelement of the
- * container in the init function of the indicator.
- */
-mxLabel.prototype.init = function(container)
-{
- mxShape.prototype.init.apply(this, arguments);
-
- // Creates the indicator shape after the node was added to the DOM
- if (this.indicatorColor != null && this.indicatorShape != null)
- {
- this.indicator = new this.indicatorShape();
- this.indicator.dialect = this.dialect;
- this.indicator.bounds = this.bounds;
- this.indicator.fill = this.indicatorColor;
- this.indicator.stroke = this.indicatorColor;
- this.indicator.gradient = this.indicatorGradientColor;
- this.indicator.direction = this.indicatorDirection;
- this.indicator.init(this.node);
- this.indicatorShape = null;
- }
-};
-
-/**
- * Function: reconfigure
- *
- * Reconfigures this shape. This will update the colors of the indicator
- * and reconfigure it if required.
- */
-mxLabel.prototype.reconfigure = function()
-{
- mxShape.prototype.reconfigure.apply(this);
-
- if (this.indicator != null)
- {
- this.indicator.fill = this.indicatorColor;
- this.indicator.stroke = this.indicatorColor;
- this.indicator.gradient = this.indicatorGradientColor;
- this.indicator.direction = this.indicatorDirection;
- this.indicator.reconfigure();
- }
-};
-
-/**
- * Function: createHtml
- *
- * Creates and returns the HTML node to represent this shape.
- */
-mxLabel.prototype.createHtml = function()
-{
- var name = 'DIV';
- var node = document.createElement(name);
- this.configureHtmlShape(node);
-
- // Adds a small subshape inside this shape
- if (this.indicatorImage != null)
- {
- this.indicatorImageNode = mxUtils.createImage(this.indicatorImage);
- this.indicatorImageNode.style.position = 'absolute';
- node.appendChild(this.indicatorImageNode);
- }
-
- // Adds an image node to the div
- if (this.image != null)
- {
- this.imageNode = mxUtils.createImage(this.image);
- this.stroke = null;
- this.configureHtmlShape(this.imageNode);
- mxUtils.setOpacity(this.imageNode, '100');
- node.appendChild(this.imageNode);
- }
-
- return node;
-};
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
-mxLabel.prototype.createVml = function()
-{
- var node = document.createElement('v:group');
-
- // Background
- var name = (this.isRounded) ? 'v:roundrect' : 'v:rect';
- this.rectNode = document.createElement(name);
- this.configureVmlShape(this.rectNode);
-
- // Disables the shadow and configures the enclosing group
- this.isShadow = false;
- this.configureVmlShape(node);
- node.coordorigin = '0,0';
- node.appendChild(this.rectNode);
-
- // Adds a small subshape inside this shape
- if (this.indicatorImage != null)
- {
- this.indicatorImageNode = this.createVmlImage(this.indicatorImage, (this.opaqueVmlImages) ? null : this.opacity);
- node.appendChild(this.indicatorImageNode);
- }
-
- // Adds an image node to the div
- if (this.image != null)
- {
- this.imageNode = this.createVmlImage(this.image, (this.opaqueVmlImages) ? null : this.opacity);
- node.appendChild(this.imageNode);
- }
-
- // Container for the label on top of everything
- this.label = document.createElement('v:rect');
- this.label.style.top = '0px'; // relative
- this.label.style.left = '0px'; // relative
- this.label.filled = 'false';
- this.label.stroked = 'false';
- node.appendChild(this.label);
-
- return node;
-};
-
-/**
- * Function: createVmlImage
- *
- * Creates an image node for the given image src and opacity to be used in VML.
- */
-mxLabel.prototype.createVmlImage = function(src, opacity)
-{
- var result = null;
-
- // Workaround for data URIs not supported in VML and for added
- // border around images if opacity is used (not needed in IE9,
- // but IMG node is probably better and faster anyway).
- if (src.substring(0, 5) == 'data:' || opacity != null)
- {
- result = document.createElement('img');
- mxUtils.setOpacity(result, opacity);
- result.setAttribute('border', '0');
- result.style.position = 'absolute';
- result.setAttribute('src', src);
- }
- else
- {
- result = document.createElement('v:image');
- result.src = src;
- }
-
- return result;
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node to represent this shape.
- */
-mxLabel.prototype.createSvg = function()
-{
- var g = this.createSvgGroup('rect');
-
- // Adds a small subshape to the svg group
- if (this.indicatorImage != null)
- {
- this.indicatorImageNode = document.createElementNS(mxConstants.NS_SVG, 'image');
- this.indicatorImageNode.setAttributeNS(mxConstants.NS_XLINK, 'href', this.indicatorImage);
- g.appendChild(this.indicatorImageNode);
-
- if (this.opacity != null)
- {
- this.indicatorImageNode.setAttribute('opacity', this.opacity / 100);
- }
- }
-
- // Adds an image to the svg group
- if (this.image != null)
- {
- this.imageNode = document.createElementNS(mxConstants.NS_SVG, 'image');
- this.imageNode.setAttributeNS(mxConstants.NS_XLINK, 'href', this.image);
-
- if (this.opacity != null)
- {
- this.imageNode.setAttribute('opacity', this.opacity / 100);
- }
-
- // Disables control-click and alt-click in Firefox
- this.imageNode.setAttribute('style', 'pointer-events:none');
- this.configureSvgShape(this.imageNode);
- g.appendChild(this.imageNode);
- }
-
- return g;
-};
-
-/**
- * Function: redraw
- *
- * Overrides redraw to define a unified implementation for redrawing
- * all supported dialects.
- */
-mxLabel.prototype.redraw = function()
-{
- this.updateBoundingBox();
- var isSvg = (this.dialect == mxConstants.DIALECT_SVG);
- var isVml = mxUtils.isVml(this.node);
-
- // Updates the bounds of the outermost shape
- if (isSvg)
- {
- this.updateSvgShape(this.innerNode);
-
- if (this.shadowNode != null)
- {
- this.updateSvgShape(this.shadowNode);
- }
-
- this.updateSvgGlassPane();
- }
- else if (isVml)
- {
- this.updateVmlShape(this.node);
- this.updateVmlShape(this.rectNode);
- this.label.style.width = this.node.style.width;
- this.label.style.height = this.node.style.height;
-
- this.updateVmlGlassPane();
- }
- else
- {
- this.updateHtmlShape(this.node);
- }
-
- // Updates the imagewidth and imageheight
- var imageWidth = 0;
- var imageHeight = 0;
-
- if (this.imageNode != null)
- {
- imageWidth = (this.style[mxConstants.STYLE_IMAGE_WIDTH] ||
- this.imageSize) * this.scale;
- imageHeight = (this.style[mxConstants.STYLE_IMAGE_HEIGHT] ||
- this.imageSize) * this.scale;
- }
-
- // Updates the subshape size and location
- var indicatorSpacing = 0;
- var indicatorWidth = 0;
- var indicatorHeight = 0;
-
- if (this.indicator != null || this.indicatorImageNode != null)
- {
- indicatorSpacing = (this.style[mxConstants.STYLE_INDICATOR_SPACING] ||
- this.indicatorSpacing) * this.scale;
- indicatorWidth = (this.style[mxConstants.STYLE_INDICATOR_WIDTH] ||
- this.indicatorSize) * this.scale;
- indicatorHeight = (this.style[mxConstants.STYLE_INDICATOR_HEIGHT] ||
- this.indicatorSize) * this.scale;
- }
-
- var align = this.style[mxConstants.STYLE_IMAGE_ALIGN];
- var valign = this.style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN];
-
- var inset = this.spacing * this.scale + 5;
- var width = Math.max(imageWidth, indicatorWidth);
- var height = imageHeight + indicatorSpacing + indicatorHeight;
-
- var x = (isSvg) ? this.bounds.x : 0;
-
- if (align == mxConstants.ALIGN_RIGHT)
- {
- x += this.bounds.width - width - inset;
- }
- else if (align == mxConstants.ALIGN_CENTER)
- {
- x += (this.bounds.width - width) / 2;
- }
- else // default is left
- {
- x += inset;
- }
-
- var y = (isSvg) ? this.bounds.y : 0;
-
- if (valign == mxConstants.ALIGN_BOTTOM)
- {
- y += this.bounds.height - height - inset;
- }
- else if (valign == mxConstants.ALIGN_TOP)
- {
- y += inset;
- }
- else // default is middle
- {
- y += (this.bounds.height - height) / 2;
- }
-
- // Updates the imagenode
- if (this.imageNode != null)
- {
- if (isSvg)
- {
- this.imageNode.setAttribute('x', (x + (width - imageWidth) / 2) + 'px');
- this.imageNode.setAttribute('y', y + 'px');
- this.imageNode.setAttribute('width', imageWidth + 'px');
- this.imageNode.setAttribute('height', imageHeight + 'px');
- }
- else
- {
- this.imageNode.style.left = (x + width - imageWidth) + 'px';
- this.imageNode.style.top = y + 'px';
- this.imageNode.style.width = imageWidth + 'px';
- this.imageNode.style.height = imageHeight + 'px';
- this.imageNode.stroked = 'false';
- }
- }
-
- // Updates the subshapenode (aka. indicator)
- if (this.indicator != null)
- {
- this.indicator.bounds = new mxRectangle(
- x + (width - indicatorWidth) / 2,
- y + imageHeight + indicatorSpacing,
- indicatorWidth, indicatorHeight);
- this.indicator.redraw();
- }
- else if (this.indicatorImageNode != null)
- {
- if (isSvg)
- {
- this.indicatorImageNode.setAttribute('x', (x + (width - indicatorWidth) / 2) + 'px');
- this.indicatorImageNode.setAttribute('y', (y + imageHeight + indicatorSpacing) + 'px');
- this.indicatorImageNode.setAttribute('width', indicatorWidth + 'px');
- this.indicatorImageNode.setAttribute('height', indicatorHeight + 'px');
- }
- else
- {
- this.indicatorImageNode.style.left = (x + (width - indicatorWidth) / 2) + 'px';
- this.indicatorImageNode.style.top = (y + imageHeight + indicatorSpacing) + 'px';
- this.indicatorImageNode.style.width = indicatorWidth + 'px';
- this.indicatorImageNode.style.height = indicatorHeight + 'px';
- }
- }
-};
diff --git a/src/js/shape/mxLine.js b/src/js/shape/mxLine.js
deleted file mode 100644
index 5ef3eb0..0000000
--- a/src/js/shape/mxLine.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * $Id: mxLine.js,v 1.36 2012-03-30 04:44:59 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxLine
- *
- * Extends <mxShape> to implement a horizontal line shape.
- * This shape is registered under <mxConstants.SHAPE_LINE> in
- * <mxCellRenderer>.
- *
- * Constructor: mxLine
- *
- * Constructs a new line shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * stroke - String that defines the stroke color. Default is 'black'. This is
- * stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxLine(bounds, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxLine.prototype = new mxShape();
-mxLine.prototype.constructor = mxLine;
-
-/**
- * Variable: vmlNodes
- *
- * Adds local references to <mxShape.vmlNodes>.
- */
-mxLine.prototype.vmlNodes = mxLine.prototype.vmlNodes.concat(['label', 'innerNode']);
-
-/**
- * Variable: mixedModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw in VML in mixed Html mode.
- */
-mxLine.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw as VML in prefer Html mode.
- */
-mxLine.prototype.preferModeHtml = false;
-
-/**
- * Function: clone
- *
- * Overrides the clone method to add special fields.
- */
-mxLine.prototype.clone = function()
-{
- var clone = new mxLine(this.bounds,
- this.stroke, this.strokewidth);
- clone.isDashed = this.isDashed;
-
- return clone;
-};
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
-mxLine.prototype.createVml = function()
-{
- var node = document.createElement('v:group');
- node.style.position = 'absolute';
-
- // Represents the text label container
- this.label = document.createElement('v:rect');
- this.label.style.position = 'absolute';
- this.label.stroked = 'false';
- this.label.filled = 'false';
- node.appendChild(this.label);
-
- // Represents the straight line shape
- this.innerNode = document.createElement('v:shape');
- this.configureVmlShape(this.innerNode);
- node.appendChild(this.innerNode);
-
- return node;
-};
-
-/**
- * Function: redrawVml
- *
- * Redraws this VML shape by invoking <updateVmlShape> on this.node.
- */
-mxLine.prototype.reconfigure = function()
-{
- if (mxUtils.isVml(this.node))
- {
- this.configureVmlShape(this.innerNode);
- }
- else
- {
- mxShape.prototype.reconfigure.apply(this, arguments);
- }
-};
-
-/**
- * Function: redrawVml
- *
- * Updates the VML node(s) to reflect the latest bounds and scale.
- */
-mxLine.prototype.redrawVml = function()
-{
- this.updateVmlShape(this.node);
- this.updateVmlShape(this.label);
-
- this.innerNode.coordsize = this.node.coordsize;
- this.innerNode.strokeweight = (this.strokewidth * this.scale) + 'px';
- this.innerNode.style.width = this.node.style.width;
- this.innerNode.style.height = this.node.style.height;
-
- var w = this.bounds.width;
- var h =this.bounds.height;
-
- if (this.direction == mxConstants.DIRECTION_NORTH ||
- this.direction == mxConstants.DIRECTION_SOUTH)
- {
- this.innerNode.path = 'm ' + Math.round(w / 2) + ' 0' +
- ' l ' + Math.round(w / 2) + ' ' + Math.round(h) + ' e';
- }
- else
- {
- this.innerNode.path = 'm 0 ' + Math.round(h / 2) +
- ' l ' + Math.round(w) + ' ' + Math.round(h / 2) + ' e';
- }
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxLine.prototype.createSvg = function()
-{
- var g = this.createSvgGroup('path');
-
- // Creates an invisible shape around the path for easier
- // selection with the mouse. Note: Firefox does not ignore
- // the value of the stroke attribute for pointer-events: stroke.
- // It does, however, ignore the visibility attribute.
- this.pipe = this.createSvgPipe();
- g.appendChild(this.pipe);
-
- return g;
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxLine.prototype.redrawSvg = function()
-{
- var strokeWidth = Math.round(Math.max(1, this.strokewidth * this.scale));
- this.innerNode.setAttribute('stroke-width', strokeWidth);
-
- if (this.bounds != null)
- {
- var x = this.bounds.x;
- var y = this.bounds.y;
- var w = this.bounds.width;
- var h = this.bounds.height;
-
- var d = null;
-
- if (this.direction == mxConstants.DIRECTION_NORTH || this.direction == mxConstants.DIRECTION_SOUTH)
- {
- d = 'M ' + Math.round(x + w / 2) + ' ' + Math.round(y) + ' L ' + Math.round(x + w / 2) + ' ' + Math.round(y + h);
- }
- else
- {
- d = 'M ' + Math.round(x) + ' ' + Math.round(y + h / 2) + ' L ' + Math.round(x + w) + ' ' + Math.round(y + h / 2);
- }
-
- this.innerNode.setAttribute('d', d);
- this.pipe.setAttribute('d', d);
- this.pipe.setAttribute('stroke-width', this.strokewidth + mxShape.prototype.SVG_STROKE_TOLERANCE);
-
- this.updateSvgTransform(this.innerNode, false);
- this.updateSvgTransform(this.pipe, false);
-
- if (this.crisp)
- {
- this.innerNode.setAttribute('shape-rendering', 'crispEdges');
- }
- else
- {
- this.innerNode.removeAttribute('shape-rendering');
- }
-
- if (this.isDashed)
- {
- var phase = Math.max(1, Math.round(3 * this.scale * this.strokewidth));
- this.innerNode.setAttribute('stroke-dasharray', phase + ' ' + phase);
- }
- }
-};
diff --git a/src/js/shape/mxMarker.js b/src/js/shape/mxMarker.js
deleted file mode 100644
index cfd6f66..0000000
--- a/src/js/shape/mxMarker.js
+++ /dev/null
@@ -1,267 +0,0 @@
-/**
- * $Id: mxMarker.js,v 1.19 2012-03-30 12:51:58 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxMarker =
-{
- /**
- * Class: mxMarker
- *
- * A static class that implements all markers for VML and SVG using a
- * registry. NOTE: The signatures in this class will change.
- *
- * Variable: markers
- *
- * Maps from markers names to functions to paint the markers.
- */
- markers: [],
-
- /**
- * Function: paintMarker
- *
- * Paints the given marker.
- */
- paintMarker: function(node, type, p0, pe, color, strokewidth, size, scale, x0, y0, source, style)
- {
- var marker = mxMarker.markers[type];
- var result = null;
-
- if (marker != null)
- {
- var isVml = mxUtils.isVml(node);
-
- // Computes the norm and the inverse norm
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
-
- if (isNaN(dx) || isNaN(dy))
- {
- return;
- }
-
- var dist = Math.max(1, Math.sqrt(dx * dx + dy * dy));
- var nx = dx * scale / dist;
- var ny = dy * scale / dist;
-
- pe = pe.clone();
-
- if (isVml)
- {
- pe.x -= x0;
- pe.y -= y0;
- }
-
- // Handles start-/endFill style
- var filled = true;
- var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL;
-
- if (style[key] == 0)
- {
- filled = false;
- }
-
- if (isVml)
- {
- // Opacity is updated in reconfigure, use nf in path for no fill
- node.strokecolor = color;
-
- if (filled)
- {
- node.fillcolor = color;
- }
- else
- {
- node.filled = 'false';
- }
- }
- else
- {
- node.setAttribute('stroke', color);
-
- var op = (style.opacity != null) ? style.opacity / 100 : 1;
- node.setAttribute('stroke-opacity', op);
-
- if (filled)
- {
- node.setAttribute('fill', color);
- node.setAttribute('fill-opacity', op);
- }
- else
- {
- node.setAttribute('fill', 'none');
- }
- }
-
- result = marker.call(this, node, type, pe, nx, ny, strokewidth, size, scale, isVml);
- }
-
- return result;
- }
-
-};
-
-(function()
-{
- /**
- * Drawing of the classic and block arrows.
- */
- var tmp = function(node, type, pe, nx, ny, strokewidth, size, scale, isVml)
- {
- // The angle of the forward facing arrow sides against the x axis is
- // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
- // only half the strokewidth is processed ).
- var endOffsetX = nx * strokewidth * 1.118;
- var endOffsetY = ny * strokewidth * 1.118;
- pe.x -= endOffsetX;
- pe.y -= endOffsetY;
-
- nx = nx * (size + strokewidth);
- ny = ny * (size + strokewidth);
-
- if (isVml)
- {
- node.path = 'm' + Math.round(pe.x) + ',' + Math.round(pe.y) +
- ' l' + Math.round(pe.x - nx - ny / 2) + ' ' + Math.round(pe.y - ny + nx / 2) +
- ((type != mxConstants.ARROW_CLASSIC) ? '' :
- ' ' + Math.round(pe.x - nx * 3 / 4) + ' ' + Math.round(pe.y - ny * 3 / 4)) +
- ' ' + Math.round(pe.x + ny / 2 - nx) + ' ' + Math.round(pe.y - ny - nx / 2) +
- ' x e';
- node.setAttribute('strokeweight', (strokewidth * scale) + 'px');
- }
- else
- {
- node.setAttribute('d', 'M ' + pe.x + ' ' + pe.y +
- ' L ' + (pe.x - nx - ny / 2) + ' ' + (pe.y - ny + nx / 2) +
- ((type != mxConstants.ARROW_CLASSIC) ? '' :
- ' L ' + (pe.x - nx * 3 / 4) + ' ' + (pe.y - ny * 3 / 4)) +
- ' L ' + (pe.x + ny / 2 - nx) + ' ' + (pe.y - ny - nx / 2) +
- ' z');
- node.setAttribute('stroke-width', strokewidth * scale);
- }
-
- var f = (type != mxConstants.ARROW_CLASSIC) ? 1 : 3 / 4;
- return new mxPoint(-nx * f - endOffsetX, -ny * f - endOffsetY);
- };
-
- mxMarker.markers[mxConstants.ARROW_CLASSIC] = tmp;
- mxMarker.markers[mxConstants.ARROW_BLOCK] = tmp;
-}());
-
-mxMarker.markers[mxConstants.ARROW_OPEN] = function(node, type, pe, nx, ny, strokewidth, size, scale, isVml)
-{
- // The angle of the forward facing arrow sides against the x axis is
- // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
- // only half the strokewidth is processed ).
- var endOffsetX = nx * strokewidth * 1.118;
- var endOffsetY = ny * strokewidth * 1.118;
- pe.x -= endOffsetX;
- pe.y -= endOffsetY;
-
- nx = nx * (size + strokewidth);
- ny = ny * (size + strokewidth);
-
- if (isVml)
- {
- node.path = 'm' + Math.round(pe.x - nx - ny / 2) + ' ' + Math.round(pe.y - ny + nx / 2) +
- ' l' + Math.round(pe.x) + ' ' + Math.round(pe.y) +
- ' ' + Math.round(pe.x + ny / 2 - nx) + ' ' + Math.round(pe.y - ny - nx / 2) +
- ' e nf';
- node.setAttribute('strokeweight', (strokewidth * scale) + 'px');
- }
- else
- {
- node.setAttribute('d', 'M ' + (pe.x - nx - ny / 2) + ' ' + (pe.y - ny + nx / 2) +
- ' L ' + (pe.x) + ' ' + (pe.y) +
- ' L ' + (pe.x + ny / 2 - nx) + ' ' + (pe.y - ny - nx / 2));
- node.setAttribute('stroke-width', strokewidth * scale);
- node.setAttribute('fill', 'none');
- }
-
- return new mxPoint(-endOffsetX * 2, -endOffsetY * 2);
-};
-
-mxMarker.markers[mxConstants.ARROW_OVAL] = function(node, type, pe, nx, ny, strokewidth, size, scale, isVml)
-{
- nx *= size;
- ny *= size;
-
- nx *= 0.5 + strokewidth / 2;
- ny *= 0.5 + strokewidth / 2;
-
- var absSize = size * scale;
- var radius = absSize / 2;
-
- if (isVml)
- {
- node.path = 'm' + Math.round(pe.x + radius) + ' ' + Math.round(pe.y) +
- ' at ' + Math.round(pe.x - radius) + ' ' + Math.round(pe.y - radius) +
- ' ' + Math.round(pe.x + radius) + ' ' + Math.round(pe.y + radius) +
- ' ' + Math.round(pe.x + radius) + ' ' + Math.round(pe.y) +
- ' ' + Math.round(pe.x + radius) + ' ' + Math.round(pe.y) +
- ' x e';
-
- node.setAttribute('strokeweight', (strokewidth * scale) + 'px');
- }
- else
- {
- node.setAttribute('d', 'M ' + (pe.x - radius) + ' ' + (pe.y) +
- ' a ' + (radius) + ' ' + (radius) +
- ' 0 1,1 ' + (absSize) + ' 0' +
- ' a ' + (radius) + ' ' + (radius) +
- ' 0 1,1 ' + (-absSize) + ' 0 z');
- node.setAttribute('stroke-width', strokewidth * scale);
- }
-
- return new mxPoint(-nx / (2 + strokewidth), -ny / (2 + strokewidth));
-};
-
-(function()
- {
- /**
- * Drawing of the diamond and thin diamond markers
- */
- var tmp_diamond = function(node, type, pe, nx, ny, strokewidth, size, scale, isVml)
- {
- // The angle of the forward facing arrow sides against the x axis is
- // 45 degrees, 1/sin(45) = 1.4142 / 2 = 0.7071 ( / 2 allows for
- // only half the strokewidth is processed ). Or 0.9862 for thin diamond.
- // Note these values and the tk variable below are dependent, update
- // both together (saves trig hard coding it).
- var swFactor = (type == mxConstants.ARROW_DIAMOND) ? 0.7071 : 0.9862;
- var endOffsetX = nx * strokewidth * swFactor;
- var endOffsetY = ny * strokewidth * swFactor;
-
- nx = nx * (size + strokewidth);
- ny = ny * (size + strokewidth);
-
- pe.x -= endOffsetX + nx / 2;
- pe.y -= endOffsetY + ny / 2;
-
- // thickness factor for diamond
- var tk = ((type == mxConstants.ARROW_DIAMOND) ? 2 : 3.4);
-
- if (isVml)
- {
- node.path = 'm' + Math.round(pe.x + nx / 2) + ' ' + Math.round(pe.y + ny / 2) +
- ' l' + Math.round(pe.x - ny / tk) + ' ' + Math.round(pe.y + nx / tk) +
- ' ' + Math.round(pe.x - nx / 2) + ' ' + Math.round(pe.y - ny / 2) +
- ' ' + Math.round(pe.x + ny / tk) + ' ' + Math.round(pe.y - nx / tk) +
- ' x e';
- node.setAttribute('strokeweight', (strokewidth * scale) + 'px');
- }
- else
- {
- node.setAttribute('d', 'M ' + (pe.x + nx / 2) + ' ' + (pe.y + ny / 2) +
- ' L ' + (pe.x - ny / tk) + ' ' + (pe.y + nx / tk) +
- ' L ' + (pe.x - nx / 2) + ' ' + (pe.y - ny / 2) +
- ' L ' + (pe.x + ny / tk) + ' ' + (pe.y - nx / tk) +
- ' z');
- node.setAttribute('stroke-width', strokewidth * scale);
- }
-
- return new mxPoint(-endOffsetX - nx, -endOffsetY - ny);
- };
-
- mxMarker.markers[mxConstants.ARROW_DIAMOND] = tmp_diamond;
- mxMarker.markers[mxConstants.ARROW_DIAMOND_THIN] = tmp_diamond;
- }());
diff --git a/src/js/shape/mxPolyline.js b/src/js/shape/mxPolyline.js
deleted file mode 100644
index 2d64323..0000000
--- a/src/js/shape/mxPolyline.js
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- * $Id: mxPolyline.js,v 1.31 2012-05-24 12:00:45 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxPolyline
- *
- * Extends <mxShape> to implement a polyline (a line with multiple points).
- * This shape is registered under <mxConstants.SHAPE_POLYLINE> in
- * <mxCellRenderer>.
- *
- * Constructor: mxPolyline
- *
- * Constructs a new polyline shape.
- *
- * Parameters:
- *
- * points - Array of <mxPoints> that define the points. This is stored in
- * <mxShape.points>.
- * stroke - String that defines the stroke color. Default is 'black'. This is
- * stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxPolyline(points, stroke, strokewidth)
-{
- this.points = points;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxPolyline.prototype = new mxShape();
-mxPolyline.prototype.constructor = mxPolyline;
-
-/**
- * Variable: addPipe
- *
- * Specifies if a SVG path should be created around any path to increase the
- * tolerance for mouse events. Default is false since this shape is filled.
- */
-mxPolyline.prototype.addPipe = true;
-
-/**
- * Function: create
- *
- * Override to create HTML regardless of gradient and
- * rounded property.
- */
-mxPolyline.prototype.create = function()
-{
- var node = null;
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- node = this.createSvg();
- }
- else if (this.dialect == mxConstants.DIALECT_STRICTHTML ||
- (this.dialect == mxConstants.DIALECT_PREFERHTML &&
- this.points != null && this.points.length > 0))
- {
- node = document.createElement('DIV');
- this.configureHtmlShape(node);
- node.style.borderStyle = '';
- node.style.background = '';
- }
- else
- {
- node = document.createElement('v:shape');
- this.configureVmlShape(node);
- var strokeNode = document.createElement('v:stroke');
-
- if (this.opacity != null)
- {
- strokeNode.opacity = this.opacity + '%';
- }
-
- node.appendChild(strokeNode);
- }
-
- return node;
-};
-
-/**
- * Function: redrawVml
- *
- * Overrides the method to update the bounds if they have not been
- * assigned.
- */
-mxPolyline.prototype.redrawVml = function()
-{
- // Updates the bounds based on the points
- if (this.points != null && this.points.length > 0 && this.points[0] != null)
- {
- this.bounds = new mxRectangle(this.points[0].x,this.points[0].y, 0, 0);
-
- for (var i = 1; i < this.points.length; i++)
- {
- this.bounds.add(new mxRectangle(this.points[i].x,this.points[i].y, 0, 0));
- }
- }
-
- mxShape.prototype.redrawVml.apply(this, arguments);
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxPolyline.prototype.createSvg = function()
-{
- var g = this.createSvgGroup('path');
-
- // Creates an invisible shape around the path for easier
- // selection with the mouse. Note: Firefox does not ignore
- // the value of the stroke attribute for pointer-events: stroke,
- // it does, however, ignore the visibility attribute.
- if (this.addPipe)
- {
- this.pipe = this.createSvgPipe();
- g.appendChild(this.pipe);
- }
-
- return g;
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxPolyline.prototype.redrawSvg = function()
-{
- this.updateSvgShape(this.innerNode);
- var d = this.innerNode.getAttribute('d');
-
- if (d != null && this.pipe != null)
- {
- this.pipe.setAttribute('d', d);
- var strokeWidth = Math.round(Math.max(1, this.strokewidth * this.scale));
- this.pipe.setAttribute('stroke-width', strokeWidth + mxShape.prototype.SVG_STROKE_TOLERANCE);
- }
-};
diff --git a/src/js/shape/mxRectangleShape.js b/src/js/shape/mxRectangleShape.js
deleted file mode 100644
index 26688c3..0000000
--- a/src/js/shape/mxRectangleShape.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * $Id: mxRectangleShape.js,v 1.17 2012-09-26 07:51:29 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxRectangleShape
- *
- * Extends <mxShape> to implement a rectangle shape.
- * This shape is registered under <mxConstants.SHAPE_RECTANGLE>
- * in <mxCellRenderer>.
- *
- * Constructor: mxRectangleShape
- *
- * Constructs a new rectangle shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxRectangleShape(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxRectangleShape.prototype = new mxShape();
-mxRectangleShape.prototype.constructor = mxRectangleShape;
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
-mxRectangleShape.prototype.createVml = function()
-{
- var name = (this.isRounded) ? 'v:roundrect' : 'v:rect';
- var node = document.createElement(name);
- this.configureVmlShape(node);
-
- return node;
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node to represent this shape.
- */
-mxRectangleShape.prototype.createSvg = function()
-{
- return this.createSvgGroup('rect');
-};
diff --git a/src/js/shape/mxRhombus.js b/src/js/shape/mxRhombus.js
deleted file mode 100644
index 37e35ec..0000000
--- a/src/js/shape/mxRhombus.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * $Id: mxRhombus.js,v 1.25 2012-04-04 07:34:50 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxRhombus
- *
- * Extends <mxShape> to implement a rhombus (aka diamond) shape.
- * This shape is registered under <mxConstants.SHAPE_RHOMBUS>
- * in <mxCellRenderer>.
- *
- * Constructor: mxRhombus
- *
- * Constructs a new rhombus shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxRhombus(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxRhombus.prototype = new mxShape();
-mxRhombus.prototype.constructor = mxRhombus;
-
-/**
- * Variable: mixedModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw in VML in mixed Html mode.
- */
-mxRhombus.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw as VML in prefer Html mode.
- */
-mxRhombus.prototype.preferModeHtml = false;
-
-/**
- * Function: createHtml
- *
- * Creates and returns the HTML node to represent this shape.
- */
-mxRhombus.prototype.createHtml = function()
-{
- var node = document.createElement('DIV');
- this.configureHtmlShape(node);
-
- return node;
-};
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node(s) to represent this shape.
- */
-mxRhombus.prototype.createVml = function()
-{
- var node = document.createElement('v:shape');
- this.configureVmlShape(node);
-
- return node;
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxRhombus.prototype.createSvg = function()
-{
- return this.createSvgGroup('path');
-};
-
-// TODO: When used as an indicator, this.node.points is null
-// so we use a path object for building general diamonds.
-//mxRhombus.prototype.redraw = function() {
-// this.node.setAttribute('strokeweight', (this.strokewidth * this.scale) + 'px');
-// var x = this.bounds.x;
-// var y = this.bounds.y;
-// var w = this.bounds.width;
-// var h = this.bounds.height;
-// this.node.points.value = (x+w/2)+','+y+' '+(x+w)+','+(y+h/2)+
-// ' '+(x+w/2)+','+(y+h)+' '+x+','+(y+h/2)+' '+
-// (x+w/2)+','+y;
-//}
-
-/**
- * Function: redrawVml
- *
- * Updates the VML node(s) to reflect the latest bounds and scale.
- */
-mxRhombus.prototype.redrawVml = function()
-{
- this.updateVmlShape(this.node);
- var x = 0;
- var y = 0;
- var w = Math.round(this.bounds.width);
- var h = Math.round(this.bounds.height);
-
- this.node.path = 'm ' + Math.round(x + w / 2) + ' ' + y +
- ' l ' + (x + w) + ' ' + Math.round(y + h / 2) +
- ' l ' + Math.round(x + w / 2) + ' ' + (y + h) +
- ' l ' + x + ' ' + Math.round(y + h / 2) + ' x e';
-};
-
-/**
- * Function: redrawHtml
- *
- * Updates the HTML node(s) to reflect the latest bounds and scale.
- */
-mxRhombus.prototype.redrawHtml = function()
-{
- this.updateHtmlShape(this.node);
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxRhombus.prototype.redrawSvg = function()
-{
- this.updateSvgNode(this.innerNode);
-
- if (this.shadowNode != null)
- {
- this.updateSvgNode(this.shadowNode);
- }
-};
-
-/**
- * Function: createSvgSpan
- *
- * Updates the path for the given SVG node.
- */
-mxRhombus.prototype.updateSvgNode = function(node)
-{
- var strokeWidth = Math.round(Math.max(1, this.strokewidth * this.scale));
- node.setAttribute('stroke-width', strokeWidth);
- var x = this.bounds.x;
- var y = this.bounds.y;
- var w = this.bounds.width;
- var h = this.bounds.height;
- var d = 'M ' + Math.round(x + w / 2) + ' ' + Math.round(y) + ' L ' + Math.round(x + w) + ' ' + Math.round(y + h / 2) +
- ' L ' + Math.round(x + w / 2) + ' ' + Math.round(y + h) + ' L ' + Math.round(x) + ' ' + Math.round(y + h / 2) +
- ' Z ';
- node.setAttribute('d', d);
- this.updateSvgTransform(node, node == this.shadowNode);
-
- if (this.isDashed)
- {
- var phase = Math.max(1, Math.round(3 * this.scale * this.strokewidth));
- node.setAttribute('stroke-dasharray', phase + ' ' + phase);
- }
-};
diff --git a/src/js/shape/mxShape.js b/src/js/shape/mxShape.js
deleted file mode 100644
index 44ba3e7..0000000
--- a/src/js/shape/mxShape.js
+++ /dev/null
@@ -1,2045 +0,0 @@
-/**
- * $Id: mxShape.js,v 1.173 2012-07-31 11:46:53 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxShape
- *
- * Base class for all shapes. A shape in mxGraph is a
- * separate implementation for SVG, VML and HTML. Which
- * implementation to use is controlled by the <dialect>
- * property which is assigned from within the <mxCellRenderer>
- * when the shape is created. The dialect must be assigned
- * for a shape, and it does normally depend on the browser and
- * the confiuration of the graph (see <mxGraph> rendering hint).
- *
- * For each supported shape in SVG and VML, a corresponding
- * shape exists in mxGraph, namely for text, image, rectangle,
- * rhombus, ellipse and polyline. The other shapes are a
- * combination of these shapes (eg. label and swimlane)
- * or they consist of one or more (filled) path objects
- * (eg. actor and cylinder). The HTML implementation is
- * optional but may be required for a HTML-only view of
- * the graph.
- *
- * Custom Shapes:
- *
- * To extend from this class, the basic code looks as follows.
- * In the special case where the custom shape consists only of
- * one filled region or one filled region and an additional stroke
- * the <mxActor> and <mxCylinder> should be subclassed,
- * respectively. These implement <redrawPath> in order to create
- * the path expression for VML and SVG via a unified API (see
- * <mxPath>). <mxCylinder.redrawPath> has an additional boolean
- * argument to draw the foreground and background separately.
- *
- * (code)
- * function CustomShape() { }
- *
- * CustomShape.prototype = new mxShape();
- * CustomShape.prototype.constructor = CustomShape;
- * (end)
- *
- * To register a custom shape in an existing graph instance,
- * one must register the shape under a new name in the graph's
- * cell renderer as follows:
- *
- * (code)
- * graph.cellRenderer.registerShape('customShape', CustomShape);
- * (end)
- *
- * The second argument is the name of the constructor.
- *
- * In order to use the shape you can refer to the given name above
- * in a stylesheet. For example, to change the shape for the default
- * vertex style, the following code is used:
- *
- * (code)
- * var style = graph.getStylesheet().getDefaultVertexStyle();
- * style[mxConstants.STYLE_SHAPE] = 'customShape';
- * (end)
- *
- * Constructor: mxShape
- *
- * Constructs a new shape.
- */
-function mxShape() { };
-
-/**
- * Variable: SVG_STROKE_TOLERANCE
- *
- * Event-tolerance for SVG strokes (in px). Default is 8.
- */
-mxShape.prototype.SVG_STROKE_TOLERANCE = 8;
-
-/**
- * Variable: scale
- *
- * Holds the scale in which the shape is being painted.
- */
-mxShape.prototype.scale = 1;
-
-/**
- * Variable: dialect
- *
- * Holds the dialect in which the shape is to be painted.
- * This can be one of the DIALECT constants in <mxConstants>.
- */
-mxShape.prototype.dialect = null;
-
-/**
- * Variable: crisp
- *
- * Special attribute for SVG rendering to set the shape-rendering attribute to
- * crispEdges in the output. This is ignored in IE. Default is false. To
- * disable antialias in IE, the explorer.css file can be changed as follows:
- *
- * [code]
- * v\:* {
- * behavior: url(#default#VML);
- * antialias: false;
- * }
- * [/code]
- */
-mxShape.prototype.crisp = false;
-
-/**
- * Variable: roundedCrispSvg
- *
- * Specifies if crisp rendering should be enabled for rounded shapes.
- * Default is true.
- */
-mxShape.prototype.roundedCrispSvg = true;
-
-/**
- * Variable: mixedModeHtml
- *
- * Specifies if <createHtml> should be used in mixed Html mode.
- * Default is true.
- */
-mxShape.prototype.mixedModeHtml = true;
-
-/**
- * Variable: preferModeHtml
- *
- * Specifies if <createHtml> should be used in prefer Html mode.
- * Default is true.
- */
-mxShape.prototype.preferModeHtml = true;
-
-/**
- * Variable: bounds
- *
- * Holds the <mxRectangle> that specifies the bounds of this shape.
- */
-mxShape.prototype.bounds = null;
-
-/**
- * Variable: points
- *
- * Holds the array of <mxPoints> that specify the points of this shape.
- */
-mxShape.prototype.points = null;
-
-/**
- * Variable: node
- *
- * Holds the outermost DOM node that represents this shape.
- */
-mxShape.prototype.node = null;
-
-/**
- * Variable: label
- *
- * Reference to the DOM node that should contain the label. This is null
- * if the label should be placed inside <node> or <innerNode>.
- */
-mxShape.prototype.label = null;
-
-/**
- * Variable: innerNode
- *
- * Holds the DOM node that graphically represents this shape. This may be
- * null if the outermost DOM <node> represents this shape.
- */
-mxShape.prototype.innerNode = null;
-
-/**
- * Variable: style
- *
- * Holds the style of the cell state that corresponds to this shape. This may
- * be null if the shape is used directly, without a cell state.
- */
-mxShape.prototype.style = null;
-
-/**
- * Variable: startOffset
- *
- * Specifies the offset in pixels from the first point in <points> and
- * the actual start of the shape.
- */
-mxShape.prototype.startOffset = null;
-
-/**
- * Variable: endOffset
- *
- * Specifies the offset in pixels from the last point in <points> and
- * the actual start of the shape.
- */
-mxShape.prototype.endOffset = null;
-
-/**
- * Variable: boundingBox
- *
- * Contains the bounding box of the shape, that is, the smallest rectangle
- * that includes all pixels of the shape.
- */
-mxShape.prototype.boundingBox = null;
-
-/**
- * Variable: vmlNodes
- *
- * Array if VML node names to fix in IE8 standards mode.
- */
-mxShape.prototype.vmlNodes = ['node', 'strokeNode', 'fillNode', 'shadowNode'];
-
-/**
- * Variable: vmlScale
- *
- * Internal scaling for VML using coordsize for better precision.
- */
-mxShape.prototype.vmlScale = 1;
-
-/**
- * Variable: strokewidth
- *
- * Holds the current strokewidth. Default is 1.
- */
-mxShape.prototype.strokewidth = 1;
-
-/**
- * Function: setCursor
- *
- * Sets the cursor on the given shape.
- *
- * Parameters:
- *
- * cursor - The cursor to be used.
- */
-mxShape.prototype.setCursor = function(cursor)
-{
- if (cursor == null)
- {
- cursor = '';
- }
-
- this.cursor = cursor;
-
- if (this.innerNode != null)
- {
- this.innerNode.style.cursor = cursor;
- }
-
- if (this.node != null)
- {
- this.node.style.cursor = cursor;
- }
-
- if (this.pipe != null)
- {
- this.pipe.style.cursor = cursor;
- }
-};
-
-/**
- * Function: getCursor
- *
- * Returns the current cursor.
- */
-mxShape.prototype.getCursor = function()
-{
- return this.cursor;
-};
-
-/**
- * Function: init
- *
- * Initializes the shape by creaing the DOM node using <create>
- * and adding it into the given container.
- *
- * Parameters:
- *
- * container - DOM node that will contain the shape.
- */
-mxShape.prototype.init = function(container)
-{
- if (this.node == null)
- {
- this.node = this.create(container);
-
- if (container != null)
- {
- container.appendChild(this.node);
-
- // Workaround for broken VML in IE8 standards mode. This gives an ID to
- // each element that is referenced from this instance. After adding the
- // DOM to the document, the outerHTML is overwritten to fix the VML
- // rendering and the references are restored.
- if (document.documentMode == 8 && mxUtils.isVml(this.node))
- {
- this.reparseVml();
- }
- }
- }
-
- // Gradients are inserted late when the owner SVG element is known
- if (this.insertGradientNode != null)
- {
- this.insertGradient(this.insertGradientNode);
- this.insertGradientNode = null;
- }
-};
-
-/**
- * Function: reparseVml
- *
- * Forces a parsing of the outerHTML of this node and restores all references specified in <vmlNodes>.
- * This is a workaround for the VML rendering bug in IE8 standards mode.
- */
-mxShape.prototype.reparseVml = function()
-{
- // Assigns temporary IDs to VML nodes so that references can be restored when
- // inserted into the DOM as a string
- for (var i = 0; i < this.vmlNodes.length; i++)
- {
- if (this[this.vmlNodes[i]] != null)
- {
- this[this.vmlNodes[i]].setAttribute('id', 'mxTemporaryReference-' + this.vmlNodes[i]);
- }
- }
-
- this.node.outerHTML = this.node.outerHTML;
-
- // Restores references to the actual DOM nodes
- for (var i = 0; i < this.vmlNodes.length; i++)
- {
- if (this[this.vmlNodes[i]] != null)
- {
- this[this.vmlNodes[i]] = this.node.ownerDocument.getElementById('mxTemporaryReference-' + this.vmlNodes[i]);
- this[this.vmlNodes[i]].removeAttribute('id');
- }
- }
-};
-
-/**
- * Function: insertGradient
- *
- * Inserts the given gradient node.
- */
-mxShape.prototype.insertGradient = function(node)
-{
- // Gradients are inserted late when the owner SVG element is known
- if (node != null)
- {
- // Checks if the given gradient already exists inside the SVG element
- // that also contains the node that represents this shape. If the gradient
- // with the same ID exists in another SVG element, then this will add
- // a copy of the gradient with a different ID to the SVG element and update
- // the reference accordingly. This is required in Firefox because if the
- // referenced fill element is removed from the DOM the shape appears black.
- var count = 0;
- var id = node.getAttribute('id');
- var gradient = document.getElementById(id);
-
- while (gradient != null && gradient.ownerSVGElement != this.node.ownerSVGElement)
- {
- count++;
- id = node.getAttribute('id') + '-' + count;
- gradient = document.getElementById(id);
- }
-
- // According to specification, gradients should be put in a defs
- // section in the first child of the owner SVG element. However,
- // it turns out that gradients only work when added as follows.
- if (gradient == null)
- {
- node.setAttribute('id', id);
- this.node.ownerSVGElement.appendChild(node);
- gradient = node;
- }
-
- if (gradient != null)
- {
- var ref = 'url(#' + id + ')';
- var tmp = (this.innerNode != null) ? this.innerNode : this.node;
-
- if (tmp != null && tmp.getAttribute('fill') != ref)
- {
- tmp.setAttribute('fill', ref);
- }
- }
- }
-};
-
-/**
- * Function: isMixedModeHtml
- *
- * Used to determine if a shape can be rendered using <createHtml> in mixed
- * mode Html without compromising the display accuracy. The default
- * implementation will check if the shape is not rounded or rotated and has
- * no gradient, and will use a DIV if that is the case. It will also check
- * if <mxShape.mixedModeHtml> is true, which is the default settings.
- * Subclassers can either override <mixedModeHtml> or this function if the
- * result depends on dynamic values. The graph's dialect is available via
- * <dialect>.
- */
-mxShape.prototype.isMixedModeHtml = function()
-{
- return this.mixedModeHtml && !this.isRounded && !this.isShadow && this.gradient == null &&
- mxUtils.getValue(this.style, mxConstants.STYLE_GLASS, 0) == 0 &&
- mxUtils.getValue(this.style, mxConstants.STYLE_ROTATION, 0) == 0;
-};
-
-/**
- * Function: create
- *
- * Creates and returns the DOM node(s) for the shape in
- * the given container. This implementation invokes
- * <createSvg>, <createHtml> or <createVml> depending
- * on the <dialect> and style settings.
- *
- * Parameters:
- *
- * container - DOM node that will contain the shape.
- */
-mxShape.prototype.create = function(container)
-{
- var node = null;
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- node = this.createSvg();
- }
- else if (this.dialect == mxConstants.DIALECT_STRICTHTML ||
- (this.preferModeHtml && this.dialect == mxConstants.DIALECT_PREFERHTML) ||
- (this.isMixedModeHtml() && this.dialect == mxConstants.DIALECT_MIXEDHTML))
- {
- node = this.createHtml();
- }
- else
- {
- node = this.createVml();
- }
-
- return node;
-};
-
-/**
- * Function: createHtml
- *
- * Creates and returns the HTML DOM node(s) to represent
- * this shape. This implementation falls back to <createVml>
- * so that the HTML creation is optional.
- */
-mxShape.prototype.createHtml = function()
-{
- var node = document.createElement('DIV');
- this.configureHtmlShape(node);
-
- return node;
-};
-
-/**
- * Function: destroy
- *
- * Destroys the shape by removing it from the DOM and releasing the DOM
- * node associated with the shape using <mxEvent.release>.
- */
-mxShape.prototype.destroy = function()
-{
- if (this.node != null)
- {
- mxEvent.release(this.node);
-
- if (this.node.parentNode != null)
- {
- this.node.parentNode.removeChild(this.node);
- }
-
- if (this.node.glassOverlay)
- {
- this.node.glassOverlay.parentNode.removeChild(this.node.glassOverlay);
- this.node.glassOverlay = null;
- }
-
- this.node = null;
- }
-};
-
-/**
- * Function: apply
- *
- * Applies the style of the given <mxCellState> to the shape. This
- * implementation assigns the following styles to local fields:
- *
- * - <mxConstants.STYLE_FILLCOLOR> => fill
- * - <mxConstants.STYLE_GRADIENTCOLOR> => gradient
- * - <mxConstants.STYLE_GRADIENT_DIRECTION> => gradientDirection
- * - <mxConstants.STYLE_OPACITY> => opacity
- * - <mxConstants.STYLE_STROKECOLOR> => stroke
- * - <mxConstants.STYLE_STROKEWIDTH> => strokewidth
- * - <mxConstants.STYLE_SHADOW> => isShadow
- * - <mxConstants.STYLE_DASHED> => isDashed
- * - <mxConstants.STYLE_SPACING> => spacing
- * - <mxConstants.STYLE_STARTSIZE> => startSize
- * - <mxConstants.STYLE_ENDSIZE> => endSize
- * - <mxConstants.STYLE_ROUNDED> => isRounded
- * - <mxConstants.STYLE_STARTARROW> => startArrow
- * - <mxConstants.STYLE_ENDARROW> => endArrow
- * - <mxConstants.STYLE_ROTATION> => rotation
- * - <mxConstants.STYLE_DIRECTION> => direction
- *
- * This keeps a reference to the <style>. If you need to keep a reference to
- * the cell, you can override this method and store a local reference to
- * state.cell or the <mxCellState> itself.
- *
- * Parameters:
- *
- * state - <mxCellState> of the corresponding cell.
- */
-mxShape.prototype.apply = function(state)
-{
- var style = state.style;
- this.style = style;
-
- if (style != null)
- {
- this.fill = mxUtils.getValue(style, mxConstants.STYLE_FILLCOLOR, this.fill);
- this.gradient = mxUtils.getValue(style, mxConstants.STYLE_GRADIENTCOLOR, this.gradient);
- this.gradientDirection = mxUtils.getValue(style, mxConstants.STYLE_GRADIENT_DIRECTION, this.gradientDirection);
- this.opacity = mxUtils.getValue(style, mxConstants.STYLE_OPACITY, this.opacity);
- this.stroke = mxUtils.getValue(style, mxConstants.STYLE_STROKECOLOR, this.stroke);
- this.strokewidth = mxUtils.getNumber(style, mxConstants.STYLE_STROKEWIDTH, this.strokewidth);
- this.isShadow = mxUtils.getValue(style, mxConstants.STYLE_SHADOW, this.isShadow);
- this.isDashed = mxUtils.getValue(style, mxConstants.STYLE_DASHED, this.isDashed);
- this.spacing = mxUtils.getValue(style, mxConstants.STYLE_SPACING, this.spacing);
- this.startSize = mxUtils.getNumber(style, mxConstants.STYLE_STARTSIZE, this.startSize);
- this.endSize = mxUtils.getNumber(style, mxConstants.STYLE_ENDSIZE, this.endSize);
- this.isRounded = mxUtils.getValue(style, mxConstants.STYLE_ROUNDED, this.isRounded);
- this.startArrow = mxUtils.getValue(style, mxConstants.STYLE_STARTARROW, this.startArrow);
- this.endArrow = mxUtils.getValue(style, mxConstants.STYLE_ENDARROW, this.endArrow);
- this.rotation = mxUtils.getValue(style, mxConstants.STYLE_ROTATION, this.rotation);
- this.direction = mxUtils.getValue(style, mxConstants.STYLE_DIRECTION, this.direction);
-
- if (this.fill == 'none')
- {
- this.fill = null;
- }
-
- if (this.gradient == 'none')
- {
- this.gradient = null;
- }
-
- if (this.stroke == 'none')
- {
- this.stroke = null;
- }
- }
-};
-
-/**
- * Function: createSvgGroup
- *
- * Creates a SVG group element and adds the given shape as a child of the
- * element. The child is stored in <innerNode> for later access.
- */
-mxShape.prototype.createSvgGroup = function(shape)
-{
- var g = document.createElementNS(mxConstants.NS_SVG, 'g');
-
- // Creates the shape inside an svg group
- this.innerNode = document.createElementNS(mxConstants.NS_SVG, shape);
- this.configureSvgShape(this.innerNode);
-
- // Avoids anti-aliasing for non-rounded rectangles with a
- // strokewidth of 1 or more pixels
- if (shape == 'rect' && this.strokewidth * this.scale >= 1 && !this.isRounded)
- {
- this.innerNode.setAttribute('shape-rendering', 'optimizeSpeed');
- }
-
- // Creates the shadow
- this.shadowNode = this.createSvgShadow(this.innerNode);
-
- if (this.shadowNode != null)
- {
- g.appendChild(this.shadowNode);
- }
-
- // Appends the main shape after the shadow
- g.appendChild(this.innerNode);
-
- return g;
-};
-
-/**
- * Function: createSvgShadow
- *
- * Creates a clone of the given node and configures the node's color
- * to use <mxConstants.SHADOWCOLOR>.
- */
-mxShape.prototype.createSvgShadow = function(node)
-{
- if (this.isShadow)
- {
- var shadow = node.cloneNode(true);
- shadow.setAttribute('opacity', mxConstants.SHADOW_OPACITY);
-
- if (this.fill != null && this.fill != mxConstants.NONE)
- {
- shadow.setAttribute('fill', mxConstants.SHADOWCOLOR);
- }
-
- if (this.stroke != null && this.stroke != mxConstants.NONE)
- {
- shadow.setAttribute('stroke', mxConstants.SHADOWCOLOR);
- }
-
- return shadow;
- }
-
- return null;
-};
-
-/**
- * Function: configureHtmlShape
- *
- * Configures the specified HTML node by applying the current color,
- * bounds, shadow, opacity etc.
- */
-mxShape.prototype.configureHtmlShape = function(node)
-{
- if (mxUtils.isVml(node))
- {
- this.configureVmlShape(node);
- }
- else
- {
- node.style.position = 'absolute';
- node.style.overflow = 'hidden';
- var color = this.stroke;
-
- if (color != null && color != mxConstants.NONE)
- {
- node.style.borderColor = color;
-
- if (this.isDashed)
- {
- node.style.borderStyle = 'dashed';
- }
- else if (this.strokewidth > 0)
- {
- node.style.borderStyle = 'solid';
- }
-
- node.style.borderWidth = Math.ceil(this.strokewidth * this.scale) + 'px';
- }
- else
- {
- node.style.borderWidth = '0px';
- }
-
- color = this.fill;
- node.style.background = '';
-
- if (color != null && color != mxConstants.NONE)
- {
- node.style.backgroundColor = color;
- }
- else if (this.points == null)
- {
- this.configureTransparentBackground(node);
- }
-
- if (this.opacity != null)
- {
- mxUtils.setOpacity(node, this.opacity);
- }
- }
-};
-
-/**
- * Function: updateVmlFill
- *
- * Updates the given VML fill node.
- */
-mxShape.prototype.updateVmlFill = function(node, c1, c2, dir, alpha)
-{
- node.color = c1;
-
- if (alpha != null && alpha != 100)
- {
- node.opacity = alpha + '%';
-
- if (c2 != null)
- {
- // LATER: Set namespaced attribute without using setAttribute
- // which is required for updating the value in IE8 standards.
- node.setAttribute('o:opacity2', alpha + '%');
- }
- }
-
- if (c2 != null)
- {
- node.type = 'gradient';
- node.color2 = c2;
- var angle = '180';
-
- if (this.gradientDirection == mxConstants.DIRECTION_EAST)
- {
- angle = '270';
- }
- else if (this.gradientDirection == mxConstants.DIRECTION_WEST)
- {
- angle = '90';
- }
- else if (this.gradientDirection == mxConstants.DIRECTION_NORTH)
- {
- angle = '0';
- }
-
- node.angle = angle;
- }
-};
-
-/**
- * Function: updateVmlStrokeNode
- *
- * Creates the stroke node for VML.
- */
-mxShape.prototype.updateVmlStrokeNode = function(parent)
-{
- // Stroke node is always needed to specify defaults that match SVG output
- if (this.strokeNode == null)
- {
- this.strokeNode = document.createElement('v:stroke');
-
- // To math SVG defaults jointsyle miter and miterlimit 4
- this.strokeNode.joinstyle = 'miter';
- this.strokeNode.miterlimit = 4;
-
- parent.appendChild(this.strokeNode);
- }
-
- if (this.opacity != null)
- {
- this.strokeNode.opacity = this.opacity + '%';
- }
-
- this.updateVmlDashStyle();
-};
-
-/**
- * Function: updateVmlStrokeColor
- *
- * Updates the VML stroke color for the given node.
- */
-mxShape.prototype.updateVmlStrokeColor = function(node)
-{
- var color = this.stroke;
-
- if (color != null && color != mxConstants.NONE)
- {
- node.stroked = 'true';
- node.strokecolor = color;
- }
- else
- {
- node.stroked = 'false';
- }
-};
-
-/**
- * Function: configureVmlShape
- *
- * Configures the specified VML node by applying the current color,
- * bounds, shadow, opacity etc.
- */
-mxShape.prototype.configureVmlShape = function(node)
-{
- node.style.position = 'absolute';
- this.updateVmlStrokeColor(node);
- node.style.background = '';
- var color = this.fill;
-
- if (color != null && color != mxConstants.NONE)
- {
- if (this.fillNode == null)
- {
- this.fillNode = document.createElement('v:fill');
- node.appendChild(this.fillNode);
- }
-
- this.updateVmlFill(this.fillNode, color, this.gradient, this.gradientDirection, this.opacity);
- }
- else
- {
- node.filled = 'false';
-
- if (this.points == null)
- {
- this.configureTransparentBackground(node);
- }
- }
-
- this.updateVmlStrokeNode(node);
-
- if (this.isShadow)
- {
- this.createVmlShadow(node);
- }
-
- // Fixes possible hang in IE when arcsize is set on non-rects
- if (node.nodeName == 'roundrect')
- {
- // Workaround for occasional "member not found" error
- try
- {
- var f = mxConstants.RECTANGLE_ROUNDING_FACTOR * 100;
-
- if (this.style != null)
- {
- f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, f);
- }
-
- node.setAttribute('arcsize', String(f) + '%');
- }
- catch (e)
- {
- // ignore
- }
- }
-};
-
-/**
- * Function: createVmlShadow
- *
- * Creates the VML shadow node.
- */
-mxShape.prototype.createVmlShadow = function(node)
-{
- // Adds a shadow only once per shape
- if (this.shadowNode == null)
- {
- this.shadowNode = document.createElement('v:shadow');
- this.shadowNode.on = 'true';
- this.shadowNode.color = mxConstants.SHADOWCOLOR;
- this.shadowNode.opacity = (mxConstants.SHADOW_OPACITY * 100) + '%';
-
- this.shadowStrokeNode = document.createElement('v:stroke');
- this.shadowNode.appendChild(this.shadowStrokeNode);
-
- node.appendChild(this.shadowNode);
- }
-};
-
-/**
- * Function: configureTransparentBackground
- *
- * Hook to make the background of a shape transparent. This hook was added as
- * a workaround for the "display non secure items" warning dialog in IE which
- * appears if the background:url(transparent.gif) is used in the overlay pane
- * of a diagram. Since only mxImageShapes currently exist in the overlay pane
- * this function is only overridden in mxImageShape.
- */
-mxShape.prototype.configureTransparentBackground = function(node)
-{
- node.style.background = 'url(\'' + mxClient.imageBasePath + '/transparent.gif\')';
-};
-
-/**
- * Function: configureSvgShape
- *
- * Configures the specified SVG node by applying the current color,
- * bounds, shadow, opacity etc.
- */
-mxShape.prototype.configureSvgShape = function(node)
-{
- var color = this.stroke;
-
- if (color != null && color != mxConstants.NONE)
- {
- node.setAttribute('stroke', color);
- }
- else
- {
- node.setAttribute('stroke', 'none');
- }
-
- color = this.fill;
-
- if (color != null && color != mxConstants.NONE)
- {
- // Fetches a reference to a shared gradient
- if (this.gradient != null)
- {
- var id = this.getGradientId(color, this.gradient);
-
- if (this.gradientNode != null && this.gradientNode.getAttribute('id') != id)
- {
- this.gradientNode = null;
- node.setAttribute('fill', '');
- }
-
- if (this.gradientNode == null)
- {
- this.gradientNode = this.createSvgGradient(id,
- color, this.gradient, node);
- node.setAttribute('fill', 'url(#'+id+')');
- }
- }
- else
- {
- // TODO: Remove gradient from document if no longer shared
- this.gradientNode = null;
- node.setAttribute('fill', color);
- }
- }
- else
- {
- node.setAttribute('fill', 'none');
- }
-
- if (this.opacity != null)
- {
- // Improves opacity performance in Firefox
- node.setAttribute('fill-opacity', this.opacity / 100);
- node.setAttribute('stroke-opacity', this.opacity / 100);
- }
-};
-
-/**
- * Function: getGradientId
- *
- * Creates a unique ID for the gradient of this shape.
- */
-mxShape.prototype.getGradientId = function(start, end)
-{
- // Removes illegal characters from gradient ID
- if (start.charAt(0) == '#')
- {
- start = start.substring(1);
- }
-
- if (end.charAt(0) == '#')
- {
- end = end.substring(1);
- }
-
- // Workaround for gradient IDs not working in Safari 5 / Chrome 6
- // if they contain uppercase characters
- start = start.toLowerCase();
- end = end.toLowerCase();
-
- var dir = null;
-
- if (this.gradientDirection == null ||
- this.gradientDirection == mxConstants.DIRECTION_SOUTH)
- {
- dir = 'south';
- }
- else if (this.gradientDirection == mxConstants.DIRECTION_EAST)
- {
- dir = 'east';
- }
- else
- {
- var tmp = start;
- start = end;
- end = tmp;
-
- if (this.gradientDirection == mxConstants.DIRECTION_NORTH)
- {
- dir = 'south';
- }
- else if (this.gradientDirection == mxConstants.DIRECTION_WEST)
- {
- dir = 'east';
- }
- }
-
- return 'mx-gradient-'+start+'-'+end+'-'+dir;
-};
-
-/**
- * Function: createSvgPipe
- *
- * Creates an invisible path which is used to increase the hit detection for
- * edges in SVG.
- */
-mxShape.prototype.createSvgPipe = function(id, start, end, node)
-{
- var pipe = document.createElementNS(mxConstants.NS_SVG, 'path');
- pipe.setAttribute('pointer-events', 'stroke');
- pipe.setAttribute('fill', 'none');
- pipe.setAttribute('visibility', 'hidden');
- // Workaround for Opera ignoring the visiblity attribute above while
- // other browsers need a stroke color to perform the hit-detection but
- // do not ignore the visibility attribute. Side-effect is that Opera's
- // hit detection for horizontal/vertical edges seems to ignore the pipe.
- pipe.setAttribute('stroke', (mxClient.IS_OP) ? 'none' : 'white');
-
- return pipe;
-};
-
-/**
- * Function: createSvgGradient
- *
- * Creates a gradient object for SVG using the specified startcolor,
- * endcolor and opacity.
- */
-mxShape.prototype.createSvgGradient = function(id, start, end, node)
-{
- var gradient = this.insertGradientNode;
-
- if (gradient == null)
- {
- gradient = document.createElementNS(mxConstants.NS_SVG, 'linearGradient');
- gradient.setAttribute('id', id);
- gradient.setAttribute('x1', '0%');
- gradient.setAttribute('y1', '0%');
- gradient.setAttribute('x2', '0%');
- gradient.setAttribute('y2', '0%');
-
- if (this.gradientDirection == null ||
- this.gradientDirection == mxConstants.DIRECTION_SOUTH)
- {
- gradient.setAttribute('y2', '100%');
- }
- else if (this.gradientDirection == mxConstants.DIRECTION_EAST)
- {
- gradient.setAttribute('x2', '100%');
- }
- else if (this.gradientDirection == mxConstants.DIRECTION_NORTH)
- {
- gradient.setAttribute('y1', '100%');
- }
- else if (this.gradientDirection == mxConstants.DIRECTION_WEST)
- {
- gradient.setAttribute('x1', '100%');
- }
-
- var stop = document.createElementNS(mxConstants.NS_SVG, 'stop');
- stop.setAttribute('offset', '0%');
- stop.setAttribute('style', 'stop-color:'+start);
- gradient.appendChild(stop);
-
- stop = document.createElementNS(mxConstants.NS_SVG, 'stop');
- stop.setAttribute('offset', '100%');
- stop.setAttribute('style', 'stop-color:'+end);
- gradient.appendChild(stop);
- }
-
- // Inserted later when the owner SVG element is known
- this.insertGradientNode = gradient;
-
- return gradient;
-};
-
-/**
- * Function: createPoints
- *
- * Creates a path expression using the specified commands for this.points.
- * If <isRounded> is true, then the path contains curves for the corners.
- */
-mxShape.prototype.createPoints = function(moveCmd, lineCmd, curveCmd, isRelative)
-{
- var offsetX = (isRelative) ? this.bounds.x : 0;
- var offsetY = (isRelative) ? this.bounds.y : 0;
-
- // Workaround for crisp shape-rendering in IE9
- var crisp = (this.crisp && this.dialect == mxConstants.DIALECT_SVG && mxClient.IS_IE) ? 0.5 : 0;
-
- if (isNaN(this.points[0].x) || isNaN(this.points[0].y))
- {
- return null;
- }
-
- var size = mxConstants.LINE_ARCSIZE * this.scale;
- var p0 = this.points[0];
-
- if (this.startOffset != null)
- {
- p0 = p0.clone();
- p0.x += this.startOffset.x;
- p0.y += this.startOffset.y;
- }
-
- var points = moveCmd + ' ' + (Math.round(p0.x - offsetX) + crisp) + ' ' +
- (Math.round(p0.y - offsetY) + crisp) + ' ';
-
- for (var i = 1; i < this.points.length; i++)
- {
- p0 = this.points[i - 1];
- var pt = this.points[i];
-
- if (isNaN(pt.x) || isNaN(pt.y))
- {
- return null;
- }
-
- if (i == this.points.length - 1 && this.endOffset != null)
- {
- pt = pt.clone();
- pt.x += this.endOffset.x;
- pt.y += this.endOffset.y;
- }
-
- var dx = p0.x - pt.x;
- var dy = p0.y - pt.y;
-
- if ((this.isRounded && i < this.points.length - 1) &&
- (dx != 0 || dy != 0) && this.scale > 0.3)
- {
- // Draws a line from the last point to the current point with a spacing
- // of size off the current point into direction of the last point
- var dist = Math.sqrt(dx * dx + dy * dy);
- var nx1 = dx * Math.min(size, dist / 2) / dist;
- var ny1 = dy * Math.min(size, dist / 2) / dist;
- points += lineCmd + ' ' + (Math.round(pt.x + nx1 - offsetX) + crisp) + ' ' +
- (Math.round(pt.y + ny1 - offsetY) + crisp) + ' ';
-
- // Draws a curve from the last point to the current point with a spacing
- // of size off the current point into direction of the next point
- var pe = this.points[i+1];
- dx = pe.x - pt.x;
- dy = pe.y - pt.y;
-
- dist = Math.max(1, Math.sqrt(dx * dx + dy * dy));
-
- if (dist != 0)
- {
- var nx2 = dx * Math.min(size, dist / 2) / dist;
- var ny2 = dy * Math.min(size, dist / 2) / dist;
-
- points += curveCmd + ' ' + Math.round(pt.x - offsetX) + ' '+
- Math.round(pt.y - offsetY) + ' ' + Math.round(pt.x - offsetX) + ',' +
- Math.round(pt.y - offsetY) + ' ' + (Math.round(pt.x + nx2 - offsetX) + crisp) + ' ' +
- (Math.round(pt.y + ny2 - offsetY) + crisp) + ' ';
- }
- }
- else
- {
- points += lineCmd + ' ' + (Math.round(pt.x - offsetX) + crisp) + ' ' + (Math.round(pt.y - offsetY) + crisp) + ' ';
- }
- }
-
- return points;
-};
-
-/**
- * Function: updateHtmlShape
- *
- * Updates the bounds or points of the specified HTML node and
- * updates the inner children to reflect the changes.
- */
-mxShape.prototype.updateHtmlShape = function(node)
-{
- if (node != null)
- {
- if (mxUtils.isVml(node))
- {
- this.updateVmlShape(node);
- }
- else
- {
- var sw = Math.ceil(this.strokewidth * this.scale);
- node.style.borderWidth = Math.max(1, sw) + 'px';
-
- if (this.bounds != null && !isNaN(this.bounds.x) && !isNaN(this.bounds.y) &&
- !isNaN(this.bounds.width) && !isNaN(this.bounds.height))
- {
- node.style.left = Math.round(this.bounds.x - sw / 2) + 'px';
- node.style.top = Math.round(this.bounds.y - sw / 2) + 'px';
-
- if (document.compatMode == 'CSS1Compat')
- {
- sw = -sw;
- }
-
- node.style.width = Math.round(Math.max(0, this.bounds.width + sw)) + 'px';
- node.style.height = Math.round(Math.max(0, this.bounds.height + sw)) + 'px';
-
- if (this.bounds.width == 0 || this.bounds.height == 0)
- {
- node.style.visibility = 'hidden';
- }
- else
- {
- node.style.visibility = 'visible';
- }
- }
- }
-
- if (this.points != null && this.bounds != null && !mxUtils.isVml(node))
- {
- if (this.divContainer == null)
- {
- this.divContainer = node;
- }
-
- while (this.divContainer.firstChild != null)
- {
- mxEvent.release(this.divContainer.firstChild);
- this.divContainer.removeChild(this.divContainer.firstChild);
- }
-
- node.style.borderStyle = '';
- node.style.background = '';
-
- if (this.points.length == 2)
- {
- var p0 = this.points[0];
- var pe = this.points[1];
-
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
-
- if (dx == 0 || dy == 0)
- {
- node.style.borderStyle = 'solid';
- }
- else
- {
- node.style.width = Math.round(this.bounds.width + 1) + 'px';
- node.style.height = Math.round(this.bounds.height + 1) + 'px';
-
- var length = Math.sqrt(dx * dx + dy * dy);
- var dotCount = 1 + (length / (8 * this.scale));
-
- var nx = dx / dotCount;
- var ny = dy / dotCount;
- var x = p0.x - this.bounds.x;
- var y = p0.y - this.bounds.y;
-
- for (var i = 0; i < dotCount; i++)
- {
- var tmp = document.createElement('DIV');
-
- tmp.style.position = 'absolute';
- tmp.style.overflow = 'hidden';
-
- tmp.style.left = Math.round(x) + 'px';
- tmp.style.top = Math.round(y) + 'px';
- tmp.style.width = Math.max(1, 2 * this.scale) + 'px';
- tmp.style.height = Math.max(1, 2 * this.scale) + 'px';
-
- tmp.style.backgroundColor = this.stroke;
- this.divContainer.appendChild(tmp);
-
- x += nx;
- y += ny;
- }
- }
- }
- else if (this.points.length == 3)
- {
- var mid = this.points[1];
-
- var n = '0';
- var s = '1';
- var w = '0';
- var e = '1';
-
- if (mid.x == this.bounds.x)
- {
- e = '0';
- w = '1';
- }
-
- if (mid.y == this.bounds.y)
- {
- n = '1';
- s = '0';
- }
-
- node.style.borderStyle = 'solid';
- node.style.borderWidth = n + ' ' + e + ' ' + s + ' ' + w + 'px';
- }
- else
- {
- node.style.width = Math.round(this.bounds.width + 1) + 'px';
- node.style.height = Math.round(this.bounds.height + 1) + 'px';
- var last = this.points[0];
-
- for (var i = 1; i < this.points.length; i++)
- {
- var next = this.points[i];
-
- // TODO: Use one div for multiple lines
- var tmp = document.createElement('DIV');
-
- tmp.style.position = 'absolute';
- tmp.style.overflow = 'hidden';
-
- tmp.style.borderColor = this.stroke;
- tmp.style.borderStyle = 'solid';
- tmp.style.borderWidth = '1 0 0 1px';
-
- var x = Math.min(next.x, last.x) - this.bounds.x;
- var y = Math.min(next.y, last.y) - this.bounds.y;
- var w = Math.max(1, Math.abs(next.x - last.x));
- var h = Math.max(1, Math.abs(next.y - last.y));
-
- tmp.style.left = x + 'px';
- tmp.style.top = y + 'px';
- tmp.style.width = w + 'px';
- tmp.style.height = h + 'px';
-
- this.divContainer.appendChild(tmp);
- last = next;
- }
- }
- }
- }
-};
-
-/**
- * Function: updateVmlDashStyle
- *
- * Updates the dashstyle in the stroke node.
- */
-mxShape.prototype.updateVmlDashStyle = function()
-{
- if (this.isDashed)
- {
- if (this.strokeNode.dashstyle != 'dash')
- {
- this.strokeNode.dashstyle = 'dash';
- }
- }
- else if (this.strokeNode.dashstyle != 'solid')
- {
- this.strokeNode.dashstyle = 'solid';
- }
-};
-
-/**
- * Function: updateVmlShape
- *
- * Updates the bounds or points of the specified VML node and
- * updates the inner children to reflect the changes.
- */
-mxShape.prototype.updateVmlShape = function(node)
-{
- node.strokeweight = (this.strokewidth * this.scale) + 'px';
-
- // Dash pattern needs updating as it depends on strokeweight in VML
- if (this.strokeNode != null)
- {
- this.updateVmlDashStyle();
- }
-
- // Updates the offset of the shadow
- if (this.shadowNode != null)
- {
- var dx = Math.round(mxConstants.SHADOW_OFFSET_X * this.scale);
- var dy = Math.round(mxConstants.SHADOW_OFFSET_Y * this.scale);
- this.shadowNode.offset = dx + 'px,' + dy + 'px';
- }
-
- if (this.bounds != null && !isNaN(this.bounds.x) && !isNaN(this.bounds.y) &&
- !isNaN(this.bounds.width) && !isNaN(this.bounds.height))
- {
- var f = 1;
-
- var w = Math.max(0, Math.round(this.bounds.width));
- var h = Math.max(0, Math.round(this.bounds.height));
-
- // Groups and shapes need a coordsize
- if (this.points != null || node.nodeName == 'shape' || node.nodeName == 'group')
- {
- var tmp = (node.parentNode.nodeName == 'group') ? 1 : this.vmlScale;
- node.coordsize = (w * tmp) + ',' + (h * tmp);
- }
- else if (node.parentNode.nodeName == 'group')
- {
- f = this.vmlScale;
- }
-
- // Only top-level nodes are non-relative and rotated
- if (node.parentNode != this.node)
- {
- node.style.left = Math.round(this.bounds.x * f) + 'px';
- node.style.top = Math.round(this.bounds.y * f) + 'px';
-
- if (this.points == null)
- {
- if (this.rotation != null && this.rotation != 0)
- {
- node.style.rotation = this.rotation;
- }
- else if (node.style.rotation != null)
- {
- node.style.rotation = '';
- }
- }
- }
-
- node.style.width = (w * f) + 'px';
- node.style.height = (h * f) + 'px';
- }
-
- if (this.points != null && node.nodeName != 'group')
- {
- if (node.nodeName == 'polyline' && node.points != null)
- {
- var points = '';
-
- for (var i = 0; i < this.points.length; i++)
- {
- points += this.points[i].x + ',' + this.points[i].y + ' ';
- }
-
- node.points.value = points;
-
- node.style.left = null;
- node.style.top = null;
- node.style.width = null;
- node.style.height = null;
- }
- else if (this.bounds != null)
- {
- var points = this.createPoints('m', 'l', 'c', true);
-
- // Smooth style for VML (experimental)
- if (this.style != null && this.style[mxConstants.STYLE_SMOOTH])
- {
- var pts = this.points;
- var n = pts.length;
-
- if (n > 3)
- {
- var x0 = this.bounds.x;
- var y0 = this.bounds.y;
- points = 'm ' + Math.round(pts[0].x - x0) + ' ' + Math.round(pts[0].y - y0) + ' qb';
-
- for (var i = 1; i < n - 1; i++)
- {
- points += ' ' + Math.round(pts[i].x - x0) + ' ' + Math.round(pts[i].y - y0);
- }
-
- points += ' nf l ' + Math.round(pts[n - 1].x - x0) + ' ' + Math.round(pts[n - 1].y - y0);
- }
- }
-
- node.path = points + ' e';
- }
- }
-};
-
-/**
- * Function: updateSvgBounds
- *
- * Updates the bounds of the given node using <bounds>.
- */
-mxShape.prototype.updateSvgBounds = function(node)
-{
- var w = this.bounds.width;
- var h = this.bounds.height;
-
- if (this.isRounded && !(this.crisp && mxClient.IS_IE))
- {
- node.setAttribute('x', this.bounds.x);
- node.setAttribute('y', this.bounds.y);
- node.setAttribute('width', w);
- node.setAttribute('height', h);
- }
- else
- {
- // Workaround for crisp shape-rendering in IE9
- var dd = (this.crisp && mxClient.IS_IE) ? 0.5 : 0;
- node.setAttribute('x', Math.round(this.bounds.x) + dd);
- node.setAttribute('y', Math.round(this.bounds.y) + dd);
-
- w = Math.round(w);
- h = Math.round(h);
-
- node.setAttribute('width', w);
- node.setAttribute('height', h);
- }
-
- if (this.isRounded)
- {
- var f = mxConstants.RECTANGLE_ROUNDING_FACTOR * 100;
-
- if (this.style != null)
- {
- f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, f) / 100;
- }
-
- var r = Math.min(w * f, h * f);
- node.setAttribute('rx', r);
- node.setAttribute('ry', r);
- }
-
- this.updateSvgTransform(node, node == this.shadowNode);
-};
-
-/**
- * Function: updateSvgPath
- *
- * Updates the path of the given node using <points>.
- */
-mxShape.prototype.updateSvgPath = function(node)
-{
- var d = this.createPoints('M', 'L', 'C', false);
-
- if (d != null)
- {
- node.setAttribute('d', d);
-
- // Smooth style for SVG (experimental)
- if (this.style != null && this.style[mxConstants.STYLE_SMOOTH])
- {
- var pts = this.points;
- var n = pts.length;
-
- if (n > 3)
- {
- var points = 'M '+pts[0].x+' '+pts[0].y+' ';
- points += ' Q '+pts[1].x + ' ' + pts[1].y + ' ' +
- ' '+pts[2].x + ' ' + pts[2].y;
-
- for (var i = 3; i < n; i++)
- {
- points += ' T ' + pts[i].x + ' ' + pts[i].y;
- }
-
- node.setAttribute('d', points);
- }
- }
-
- node.removeAttribute('x');
- node.removeAttribute('y');
- node.removeAttribute('width');
- node.removeAttribute('height');
- }
-};
-
-/**
- * Function: updateSvgScale
- *
- * Updates the properties of the given node that depend on the scale and checks
- * the crisp rendering attribute.
- */
-mxShape.prototype.updateSvgScale = function(node)
-{
- node.setAttribute('stroke-width', Math.round(Math.max(1, this.strokewidth * this.scale)));
-
- if (this.isDashed)
- {
- var phase = Math.max(1, Math.round(3 * this.scale * this.strokewidth));
- node.setAttribute('stroke-dasharray', phase + ' ' + phase);
- }
-
- if (this.crisp && (this.roundedCrispSvg || this.isRounded != true) &&
- (this.rotation == null || this.rotation == 0))
- {
- node.setAttribute('shape-rendering', 'crispEdges');
- }
- else
- {
- node.removeAttribute('shape-rendering');
- }
-};
-
-/**
- * Function: updateSvgShape
- *
- * Updates the bounds or points of the specified SVG node and
- * updates the inner children to reflect the changes.
- */
-mxShape.prototype.updateSvgShape = function(node)
-{
- if (this.points != null && this.points[0] != null)
- {
- this.updateSvgPath(node);
- }
- else if (this.bounds != null)
- {
- this.updateSvgBounds(node);
- }
-
- this.updateSvgScale(node);
-};
-
-/**
- * Function: getSvgShadowTransform
- *
- * Returns the current transformation for SVG shadows.
- */
-mxShape.prototype.getSvgShadowTransform = function(node, shadow)
-{
- var dx = mxConstants.SHADOW_OFFSET_X * this.scale;
- var dy = mxConstants.SHADOW_OFFSET_Y * this.scale;
-
- return 'translate(' + dx + ' ' + dy + ')';
-};
-
-/**
- * Function: updateSvgTransform
- *
- * Updates the tranform of the given node.
- */
-mxShape.prototype.updateSvgTransform = function(node, shadow)
-{
- var st = (shadow) ? this.getSvgShadowTransform() : '';
-
- if (this.rotation != null && this.rotation != 0)
- {
- var cx = this.bounds.x + this.bounds.width / 2;
- var cy = this.bounds.y + this.bounds.height / 2;
- node.setAttribute('transform', 'rotate(' + this.rotation + ',' + cx + ',' + cy + ') ' + st);
- }
- else
- {
- if (shadow)
- {
- node.setAttribute('transform', st);
- }
- else
- {
- node.removeAttribute('transform');
- }
- }
-};
-
-/**
- * Function: reconfigure
- *
- * Reconfigures this shape. This will update the colors etc in
- * addition to the bounds or points.
- */
-mxShape.prototype.reconfigure = function()
-{
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- if (this.innerNode != null)
- {
- this.configureSvgShape(this.innerNode);
- }
- else
- {
- this.configureSvgShape(this.node);
- }
-
- if (this.insertGradientNode != null)
- {
- this.insertGradient(this.insertGradientNode);
- this.insertGradientNode = null;
- }
- }
- else if (mxUtils.isVml(this.node))
- {
- this.node.style.visibility = 'hidden';
- this.configureVmlShape(this.node);
- this.node.style.visibility = 'visible';
- }
- else
- {
- this.node.style.visibility = 'hidden';
- this.configureHtmlShape(this.node);
- this.node.style.visibility = 'visible';
- }
-};
-
-/**
- * Function: redraw
- *
- * Invokes <redrawSvg>, <redrawVml> or <redrawHtml> depending on the
- * dialect of the shape.
- */
-mxShape.prototype.redraw = function()
-{
- this.updateBoundingBox();
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- this.redrawSvg();
- }
- else if (mxUtils.isVml(this.node))
- {
- this.node.style.visibility = 'hidden';
- this.redrawVml();
- this.node.style.visibility = 'visible';
- }
- else
- {
- this.redrawHtml();
- }
-};
-
-/**
- * Function: updateBoundingBox
- *
- * Updates the <boundingBox> for this shape using <createBoundingBox> and
- * <augmentBoundingBox> and stores the result in <boundingBox>.
- */
-mxShape.prototype.updateBoundingBox = function()
-{
- if (this.bounds != null)
- {
- var bbox = this.createBoundingBox();
- this.augmentBoundingBox(bbox);
-
- var rot = Number(mxUtils.getValue(this.style, mxConstants.STYLE_ROTATION, 0));
-
- if (rot != 0)
- {
- bbox = mxUtils.getBoundingBox(bbox, rot);
- }
-
- bbox.x = Math.floor(bbox.x);
- bbox.y = Math.floor(bbox.y);
- // TODO: Fix rounding errors
- bbox.width = Math.ceil(bbox.width);
- bbox.height = Math.ceil(bbox.height);
-
- this.boundingBox = bbox;
- }
-};
-
-/**
- * Function: createBoundingBox
- *
- * Returns a new rectangle that represents the bounding box of the bare shape
- * with no shadows or strokewidths.
- */
-mxShape.prototype.createBoundingBox = function()
-{
- return this.bounds.clone();
-};
-
-/**
- * Function: augmentBoundingBox
- *
- * Augments the bounding box with the strokewidth and shadow offsets.
- */
-mxShape.prototype.augmentBoundingBox = function(bbox)
-{
- if (this.isShadow)
- {
- bbox.width += Math.ceil(mxConstants.SHADOW_OFFSET_X * this.scale);
- bbox.height += Math.ceil(mxConstants.SHADOW_OFFSET_Y * this.scale);
- }
-
- // Adds strokeWidth
- var sw = Math.ceil(this.strokewidth * this.scale);
- bbox.grow(Math.ceil(sw / 2));
-};
-
-/**
- * Function: redrawSvg
- *
- * Redraws this SVG shape by invoking <updateSvgShape> on this.node,
- * this.innerNode and this.shadowNode.
- */
-mxShape.prototype.redrawSvg = function()
-{
- if (this.innerNode != null)
- {
- this.updateSvgShape(this.innerNode);
-
- if (this.shadowNode != null)
- {
- this.updateSvgShape(this.shadowNode);
- }
- }
- else
- {
- this.updateSvgShape(this.node);
-
- // Updates the transform of the shadow
- if (this.shadowNode != null)
- {
- this.shadowNode.setAttribute('transform', this.getSvgShadowTransform());
- }
- }
-
- this.updateSvgGlassPane();
-};
-
-/**
- * Function: updateVmlGlassPane
- *
- * Draws the glass overlay if mxConstants.STYLE_GLASS is 1.
- */
-mxShape.prototype.updateVmlGlassPane = function()
-{
- // Currently only used in mxLabel. Most shapes would have to be changed to use
- // a group node in VML which might affect performance for glass-less cells.
- if (this.bounds != null && this.node.nodeName == 'group' && this.style != null &&
- mxUtils.getValue(this.style, mxConstants.STYLE_GLASS, 0) == 1)
- {
- // Glass overlay
- if (this.node.glassOverlay == null)
- {
- // Creates glass overlay
- this.node.glassOverlay = document.createElement('v:shape');
- this.node.glassOverlay.setAttribute('filled', 'true');
- this.node.glassOverlay.setAttribute('fillcolor', 'white');
- this.node.glassOverlay.setAttribute('stroked', 'false');
-
- var fillNode = document.createElement('v:fill');
- fillNode.setAttribute('type', 'gradient');
- fillNode.setAttribute('color', 'white');
- fillNode.setAttribute('color2', 'white');
- fillNode.setAttribute('opacity', '90%');
- fillNode.setAttribute('o:opacity2', '15%');
- fillNode.setAttribute('angle', '180');
-
- this.node.glassOverlay.appendChild(fillNode);
- this.node.appendChild(this.node.glassOverlay);
- }
-
- var size = 0.4;
-
- // TODO: Mask with rectangle or rounded rectangle of label
- var b = this.bounds;
- var sw = Math.ceil(this.strokewidth * this.scale / 2 + 1);
- var d = 'm ' + (-sw) + ' ' + (-sw) + ' l ' + (-sw) + ' ' + Math.round(b.height * size) +
- ' c ' + Math.round(b.width * 0.3) + ' ' + Math.round(b.height * 0.6) +
- ' ' + Math.round(b.width * 0.7) + ' ' + Math.round(b.height * 0.6) +
- ' ' + Math.round(b.width + sw) + ' ' + Math.round(b.height * size) +
- ' l '+Math.round(b.width + sw)+' ' + (-sw) + ' x e';
- this.node.glassOverlay.style.position = 'absolute';
- this.node.glassOverlay.style.width = b.width + 'px';
- this.node.glassOverlay.style.height = b.height + 'px';
- this.node.glassOverlay.setAttribute('coordsize',
- Math.round(this.bounds.width) + ',' +
- Math.round(this.bounds.height));
- this.node.glassOverlay.setAttribute('path', d);
- }
- else if (this.node.glassOverlay != null)
- {
- this.node.glassOverlay.parentNode.removeChild(this.node.glassOverlay);
- this.node.glassOverlay = null;
- }
-};
-
-/**
- * Function: updateSvgGlassPane
- *
- * Draws the glass overlay if mxConstants.STYLE_GLASS is 1.
- */
-mxShape.prototype.updateSvgGlassPane = function()
-{
- if (this.node.nodeName == 'g' && this.style != null &&
- mxUtils.getValue(this.style, mxConstants.STYLE_GLASS, 0) == 1)
- {
- // Glass overlay
- if (this.node.glassOverlay == null)
- {
- // Glass overlay gradient
- if (this.node.ownerSVGElement.glassGradient == null)
- {
- // Creates glass overlay gradient
- var glassGradient = document.createElementNS(mxConstants.NS_SVG, 'linearGradient');
- glassGradient.setAttribute('x1', '0%');
- glassGradient.setAttribute('y1', '0%');
- glassGradient.setAttribute('x2', '0%');
- glassGradient.setAttribute('y2', '100%');
-
- var stop1 = document.createElementNS(mxConstants.NS_SVG, 'stop');
- stop1.setAttribute('offset', '0%');
- stop1.setAttribute('style', 'stop-color:#ffffff;stop-opacity:0.9');
- glassGradient.appendChild(stop1);
-
- var stop2 = document.createElementNS(mxConstants.NS_SVG, 'stop');
- stop2.setAttribute('offset', '100%');
- stop2.setAttribute('style', 'stop-color:#ffffff;stop-opacity:0.1');
- glassGradient.appendChild(stop2);
-
- // Finds a unique ID for the gradient
- var prefix = 'mx-glass-gradient-';
- var counter = 0;
-
- while (document.getElementById(prefix+counter) != null)
- {
- counter++;
- }
-
- glassGradient.setAttribute('id', prefix+counter);
- this.node.ownerSVGElement.appendChild(glassGradient);
- this.node.ownerSVGElement.glassGradient = glassGradient;
- }
-
- // Creates glass overlay
- this.node.glassOverlay = document.createElementNS(mxConstants.NS_SVG, 'path');
- // LATER: Not sure what the behaviour is for mutiple SVG elements in page.
- // Probably its possible that this points to an element in another SVG
- // node which when removed will result in an undefined background.
- var id = this.node.ownerSVGElement.glassGradient.getAttribute('id');
- this.node.glassOverlay.setAttribute('style', 'fill:url(#'+id+');');
- this.node.appendChild(this.node.glassOverlay);
- }
-
- var size = 0.4;
-
- // TODO: Mask with rectangle or rounded rectangle of label
- var b = this.bounds;
- var sw = Math.ceil(this.strokewidth * this.scale / 2);
- var d = 'm ' + (b.x - sw) + ',' + (b.y - sw) +
- ' L ' + (b.x - sw) + ',' + (b.y + b.height * size) +
- ' Q '+ (b.x + b.width * 0.5) + ',' + (b.y + b.height * 0.7) + ' '+
- (b.x + b.width + sw) + ',' + (b.y + b.height * size) +
- ' L ' + (b.x + b.width + sw) + ',' + (b.y - sw) + ' z';
- this.node.glassOverlay.setAttribute('d', d);
- }
- else if (this.node.glassOverlay != null)
- {
- this.node.glassOverlay.parentNode.removeChild(this.node.glassOverlay);
- this.node.glassOverlay = null;
- }
-};
-
-/**
- * Function: redrawVml
- *
- * Redraws this VML shape by invoking <updateVmlShape> on this.node.
- */
-mxShape.prototype.redrawVml = function()
-{
- this.node.style.visibility = 'hidden';
- this.updateVmlShape(this.node);
- this.updateVmlGlassPane();
- this.node.style.visibility = 'visible';
-};
-
-/**
- * Function: redrawHtml
- *
- * Redraws this HTML shape by invoking <updateHtmlShape> on this.node.
- */
-mxShape.prototype.redrawHtml = function()
-{
- this.updateHtmlShape(this.node);
-};
-
-/**
- * Function: getRotation
- *
- * Returns the current rotation including direction.
- */
-mxShape.prototype.getRotation = function()
-{
- var rot = this.rotation || 0;
-
- // Default direction is east (ignored if rotation exists)
- if (this.direction != null)
- {
- if (this.direction == 'north')
- {
- rot += 270;
- }
- else if (this.direction == 'west')
- {
- rot += 180;
- }
- else if (this.direction == 'south')
- {
- rot += 90;
- }
- }
-
- return rot;
-};
-
-/**
- * Function: createPath
- *
- * Creates an <mxPath> for the specified format and origin. The path object is
- * then passed to <redrawPath> and <mxPath.getPath> is returned.
- */
-mxShape.prototype.createPath = function(arg)
-{
- var x = this.bounds.x;
- var y = this.bounds.y;
- var w = this.bounds.width;
- var h = this.bounds.height;
- var dx = 0;
- var dy = 0;
-
- // Inverts bounds for stencils which are rotated 90 or 270 degrees
- if (this.direction == 'north' || this.direction == 'south')
- {
- dx = (w - h) / 2;
- dy = (h - w) / 2;
- x += dx;
- y += dy;
- var tmp = w;
- w = h;
- h = tmp;
- }
-
- var rotation = this.getRotation();
- var path = null;
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- path = new mxPath('svg');
- path.setTranslate(x, y);
-
- // Adds rotation as a separate transform
- if (rotation != 0)
- {
- var cx = this.bounds.getCenterX();
- var cy = this.bounds.getCenterY();
- var transform = 'rotate(' + rotation + ' ' + cx + ' ' + cy + ')';
-
- if (this.innerNode != null)
- {
- this.innerNode.setAttribute('transform', transform);
- }
-
- if (this.foreground != null)
- {
- this.foreground.setAttribute('transform', transform);
- }
-
- // Shadow needs different transform so that it ends up on the correct side
- if (this.shadowNode != null)
- {
- this.shadowNode.setAttribute('transform', this.getSvgShadowTransform() + ' ' + transform);
- }
- }
- }
- else
- {
- path = new mxPath('vml');
- path.setTranslate(dx, -dx);
- path.scale = this.vmlScale;
-
- if (rotation != 0)
- {
- this.node.style.rotation = rotation;
- }
- }
-
- this.redrawPath(path, x, y, w, h, arg);
-
- return path.getPath();
-};
-
-/**
- * Function: redrawPath
- *
- * Draws the path for this shape. This implementation is empty. See
- * <mxActor> and <mxCylinder> for implementations.
- */
-mxShape.prototype.redrawPath = function(path, x, y, w, h)
-{
- // do nothing
-};
diff --git a/src/js/shape/mxStencil.js b/src/js/shape/mxStencil.js
deleted file mode 100644
index d0e1a63..0000000
--- a/src/js/shape/mxStencil.js
+++ /dev/null
@@ -1,1585 +0,0 @@
-/**
- * $Id: mxStencil.js,v 1.91 2012-07-16 10:22:44 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxStencil
- *
- * Implements a generic shape which is based on a XML node as a description.
- * The node contains a background and a foreground node, which contain the
- * definition to render the respective part of the shape. Note that the
- * fill, stroke or fillstroke of the background is be the first statement
- * of the foreground. This is because the content of the background node
- * maybe used to not only render the shape itself, but also its shadow and
- * other elements which do not require a fill, stroke or fillstroke.
- *
- * The shape uses a coordinate system with a width of 100 and a height of
- * 100 by default. This can be changed by setting the w and h attribute of
- * the shape element. The aspect attribute can be set to "variable" (default)
- * or "fixed". If fixed is used, then the aspect which is defined via the w
- * and h attribute is kept constant while the shape is scaled.
- *
- * The possible contents of the background and foreground elements are rect,
- * ellipse, roundrect, text, image, include-shape or paths. A path element
- * contains move, line, curve, quad, arc and close elements. The rect, ellipse
- * and roundrect elements may be thought of as special path elements. All these
- * path elements must be followed by either fill, stroke or fillstroke (note
- * that text, image and include-shape or not path elements).
- *
- * The background element can be empty or contain at most one path element. It
- * should not contain a text, image or include-shape element. If the background
- * element is empty, then no shadow or glass effect will be rendered. If the
- * background element is non-empty, then the corresponding fill, stroke or
- * fillstroke should be the first element in the subsequent foreground element.
- *
- * The format of the XML is "a simplified HTML 5 Canvas". Each command changes
- * the "current" state, so eg. a linecap, linejoin will be used for all
- * subsequent line drawing, unless a save/restore appears, which saves/restores
- * a state in a stack.
- *
- * The connections section contains the fixed connection points for a stencil.
- * The perimeter attribute of the constraint element should have a value of 0
- * or 1 (default), where 1 (true) specifies that the given point should be
- * projected into the perimeter of the given shape.
- *
- * The x- and y-coordinates are typically between 0 and 1 and define the
- * location of the connection point relative to the width and height of the
- * shape.
- *
- * The dashpattern directive sets the current dashpattern. The format for the
- * pattern attribute is a space-separated sequence of numbers, eg. 5 5 5 5,
- * that specifies the lengths of alternating dashes and spaces in dashed lines.
- * The dashpattern should be used together with the dashed directive to
- * enabled/disable the dashpattern. The default dashpattern is 3 3.
- *
- * The strokewidth attribute defines a fixed strokewidth for the shape. It
- * can contain a numeric value or the keyword "inherit", which means that the
- * strokeWidth from the cell's style will be used and muliplied with the shape's
- * scale. If numeric values are used, those are multiplied with the minimum
- * scale used to render the stencil inside the shape's bounds.
- *
- * Constructor: mxStencilShape
- *
- * Constructs a new generic shape by setting <desc> to the given XML node and
- * invoking <parseDescription> and <parseConstraints>.
- *
- * Parameters:
- *
- * desc - XML node that contains the stencil description.
- */
-function mxStencil(desc)
-{
- this.desc = desc;
- this.parseDescription();
- this.parseConstraints();
-};
-
-/**
- * Variable: desc
- *
- * Holds the XML node with the stencil description.
- */
-mxStencil.prototype.desc = null;
-
-/**
- * Variable: constraints
- *
- * Holds an array of <mxConnectionConstraints> as defined in the shape.
- */
-mxStencil.prototype.constraints = null;
-
-/**
- * Variable: aspect
- *
- * Holds the aspect of the shape. Default is 'auto'.
- */
-mxStencil.prototype.aspect = null;
-
-/**
- * Variable: w0
- *
- * Holds the width of the shape. Default is 100.
- */
-mxStencil.prototype.w0 = null;
-
-/**
- * Variable: h0
- *
- * Holds the height of the shape. Default is 100.
- */
-mxStencil.prototype.h0 = null;
-
-/**
- * Variable: bgNodes
- *
- * Holds the XML node with the stencil description.
- */
-mxStencil.prototype.bgNode = null;
-
-/**
- * Variable: fgNodes
- *
- * Holds the XML node with the stencil description.
- */
-mxStencil.prototype.fgNode = null;
-
-/**
- * Variable: strokewidth
- *
- * Holds the strokewidth direction from the description.
- */
-mxStencil.prototype.strokewidth = null;
-
-/**
- * Function: parseDescription
- *
- * Reads <w0>, <h0>, <aspect>, <bgNodes> and <fgNodes> from <desc>.
- */
-mxStencil.prototype.parseDescription = function()
-{
- // LATER: Preprocess nodes for faster painting
- this.fgNode = this.desc.getElementsByTagName('foreground')[0];
- this.bgNode = this.desc.getElementsByTagName('background')[0];
- this.w0 = Number(this.desc.getAttribute('w') || 100);
- this.h0 = Number(this.desc.getAttribute('h') || 100);
-
- // Possible values for aspect are: variable and fixed where
- // variable means fill the available space and fixed means
- // use w0 and h0 to compute the aspect.
- var aspect = this.desc.getAttribute('aspect');
- this.aspect = (aspect != null) ? aspect : 'variable';
-
- // Possible values for strokewidth are all numbers and "inherit"
- // where the inherit means take the value from the style (ie. the
- // user-defined stroke-width). Note that the strokewidth is scaled
- // by the minimum scaling that is used to draw the shape (sx, sy).
- var sw = this.desc.getAttribute('strokewidth');
- this.strokewidth = (sw != null) ? sw : '1';
-};
-
-/**
- * Function: parseConstraints
- *
- * Reads the constraints from <desc> into <constraints> using
- * <parseConstraint>.
- */
-mxStencil.prototype.parseConstraints = function()
-{
- var conns = this.desc.getElementsByTagName('connections')[0];
-
- if (conns != null)
- {
- var tmp = mxUtils.getChildNodes(conns);
-
- if (tmp != null && tmp.length > 0)
- {
- this.constraints = [];
-
- for (var i = 0; i < tmp.length; i++)
- {
- this.constraints.push(this.parseConstraint(tmp[i]));
- }
- }
- }
-};
-
-/**
- * Function: parseConstraint
- *
- * Parses the given XML node and returns its <mxConnectionConstraint>.
- */
-mxStencil.prototype.parseConstraint = function(node)
-{
- var x = Number(node.getAttribute('x'));
- var y = Number(node.getAttribute('y'));
- var perimeter = node.getAttribute('perimeter') == '1';
-
- return new mxConnectionConstraint(new mxPoint(x, y), perimeter);
-};
-
-/**
- * Function: evaluateAttribute
- *
- * Gets the attribute for the given name from the given node. If the attribute
- * does not exist then the text content of the node is evaluated and if it is
- * a function it is invoked with <state> as the only argument and the return
- * value is used as the attribute value to be returned.
- */
-mxStencil.prototype.evaluateAttribute = function(node, attribute, state)
-{
- var result = node.getAttribute(attribute);
-
- if (result == null)
- {
- var text = mxUtils.getTextContent(node);
-
- if (text != null)
- {
- var funct = mxUtils.eval(text);
-
- if (typeof(funct) == 'function')
- {
- result = funct(state);
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: renderDom
- *
- * Updates the SVG or VML shape.
- */
-mxStencil.prototype.renderDom = function(shape, bounds, parentNode, state)
-{
- var vml = shape.dialect != mxConstants.DIALECT_SVG;
- var vmlScale = (document.documentMode == 8) ? 1 : shape.vmlScale;
- var rotation = shape.rotation || 0;
- var inverse = false;
-
- // New styles for shape flipping the stencil
- var flipH = shape.style[mxConstants.STYLE_STENCIL_FLIPH];
- var flipV = shape.style[mxConstants.STYLE_STENCIL_FLIPV];
-
- if (flipH ? !flipV : flipV)
- {
- rotation *= -1;
- }
-
- // Default direction is east (ignored if rotation exists)
- if (shape.direction != null)
- {
- if (shape.direction == 'north')
- {
- rotation += 270;
- }
- else if (shape.direction == 'west')
- {
- rotation += 180;
- }
- else if (shape.direction == 'south')
- {
- rotation += 90;
- }
-
- inverse = (shape.direction == 'north' || shape.direction == 'south');
- }
-
- if (flipH && flipV)
- {
- rotation += 180;
- flipH = false;
- flipV = false;
- }
-
- // SVG transform should be applied on all child shapes
- var svgTransform = '';
-
- // Implements direction style and vertical/horizontal flip
- // via container transformation.
- if (vml)
- {
- if (flipH)
- {
- parentNode.style.flip = 'x';
- }
- else if (flipV)
- {
- parentNode.style.flip = 'y';
- }
-
- if (rotation != 0)
- {
- parentNode.style.rotation = rotation;
- }
- }
- else
- {
- if (flipH || flipV)
- {
- var sx = 1;
- var sy = 1;
- var dx = 0;
- var dy = 0;
-
- if (flipH)
- {
- sx = -1;
- dx = -bounds.width - 2 * bounds.x;
- }
-
- if (flipV)
- {
- sy = -1;
- dy = -bounds.height - 2 * bounds.y;
- }
-
- svgTransform = 'scale(' + sx + ' ' + sy + ') translate(' + dx + ' ' + dy + ')';
- }
-
- // Adds rotation as a separate transform
- if (rotation != 0)
- {
- var cx = bounds.getCenterX();
- var cy = bounds.getCenterY();
- svgTransform += ' rotate(' + rotation + ' ' + cx + ' ' + cy + ')';
- }
- }
-
- var background = (state == null);
-
- if (this.bgNode != null || this.fgNode != null)
- {
- var x0 = (vml && state == null) ? 0 : bounds.x;
- var y0 = (vml && state == null) ? 0 : bounds.y;
- var sx = bounds.width / this.w0;
- var sy = bounds.height / this.h0;
-
- // Stores current location inside path
- this.lastMoveX = 0;
- this.lastMoveY = 0;
-
- if (inverse)
- {
- sy = bounds.width / this.h0;
- sx = bounds.height / this.w0;
-
- var delta = (bounds.width - bounds.height) / 2;
-
- x0 += delta;
- y0 -= delta;
- }
-
- if (this.aspect == 'fixed')
- {
- sy = Math.min(sx, sy);
- sx = sy;
-
- // Centers the shape inside the available space
- if (inverse)
- {
- x0 += (bounds.height - this.w0 * sx) / 2;
- y0 += (bounds.width - this.h0 * sy) / 2;
- }
- else
- {
- x0 += (bounds.width - this.w0 * sx) / 2;
- y0 += (bounds.height - this.h0 * sy) / 2;
- }
- }
-
- // Workaround to improve VML rendering precision.
- if (vml)
- {
- sx *= vmlScale;
- sy *= vmlScale;
- x0 *= vmlScale;
- y0 *= vmlScale;
- }
-
- var minScale = Math.min(sx, sy);
-
- // Stack of states for save/restore ops
- var stack = [];
-
- var currentState = (state != null) ? state :
- {
- fillColorAssigned: false,
- fill: shape.fill,
- stroke: shape.stroke,
- strokeWidth: (this.strokewidth == 'inherit') ?
- Number(shape.strokewidth) * shape.scale :
- Number(this.strokewidth) * minScale / ((vml) ? vmlScale : 1),
- dashed: shape.isDashed,
- dashpattern: [3, 3],
- alpha: shape.opacity,
- linejoin: 'miter',
- fontColor: '#000000',
- fontSize: mxConstants.DEFAULT_FONTSIZE,
- fontFamily: mxConstants.DEFAULT_FONTFAMILY,
- fontStyle: 0
- };
-
- var currentPath = null;
- var currentPoints = null;
-
- var configurePath = function(path, state)
- {
- var sw = Math.max(1, state.strokeWidth);
-
- if (vml)
- {
- path.strokeweight = Math.round(sw) + 'px';
-
- if (state.fill != null)
- {
- // Gradient in foregrounds not supported because special gradients
- // with bounds must be created for each element in graphics-canvases
- var gradient = (!state.fillColorAssigned) ? shape.gradient : null;
- var fill = document.createElement('v:fill');
- shape.updateVmlFill(fill, state.fill, gradient, shape.gradientDirection, state.alpha);
- path.appendChild(fill);
- }
- else
- {
- path.filled = 'false';
- }
-
- if (state.stroke != null)
- {
- path.stroked = 'true';
- path.strokecolor = state.stroke;
- }
- else
- {
- path.stroked = 'false';
- }
-
- path.style.position = 'absolute';
- }
- else
- {
- path.setAttribute('stroke-width', sw);
-
- if (state.fill != null && state.fillColorAssigned)
- {
- path.setAttribute('fill', state.fill);
- }
-
- if (state.stroke != null)
- {
- path.setAttribute('stroke', state.stroke);
- }
- }
- };
-
- var addToPath = function(s)
- {
- if (currentPath != null && currentPoints != null)
- {
- currentPoints.push(s);
- }
- };
-
- var round = function(value)
- {
- return (vml) ? Math.round(value) : value;
- };
-
- // Will be moved to a hook later for example to set text values
- var renderNode = function(node)
- {
- var name = node.nodeName;
-
- var fillOp = name == 'fill';
- var strokeOp = name == 'stroke';
- var fillStrokeOp = name == 'fillstroke';
-
- if (name == 'save')
- {
- stack.push(currentState);
- currentState = mxUtils.clone(currentState);
- }
- else if (name == 'restore')
- {
- currentState = stack.pop();
- }
- else if (name == 'path')
- {
- currentPoints = [];
-
- if (vml)
- {
- currentPath = document.createElement('v:shape');
- configurePath.call(this, currentPath, currentState);
- var w = Math.round(bounds.width) * vmlScale;
- var h = Math.round(bounds.height) * vmlScale;
- currentPath.style.width = w + 'px';
- currentPath.style.height = h + 'px';
- currentPath.coordsize = w + ',' + h;
- }
- else
- {
- currentPath = document.createElementNS(mxConstants.NS_SVG, 'path');
- configurePath.call(this, currentPath, currentState);
-
- if (svgTransform.length > 0)
- {
- currentPath.setAttribute('transform', svgTransform);
- }
-
- if (node.getAttribute('crisp') == '1')
- {
- currentPath.setAttribute('shape-rendering', 'crispEdges');
- }
- }
-
- // Renders the elements inside the given path
- var childNode = node.firstChild;
-
- while (childNode != null)
- {
- if (childNode.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- renderNode.call(this, childNode);
- }
-
- childNode = childNode.nextSibling;
- }
-
- // Ends the current path
- if (vml)
- {
- addToPath('e');
- currentPath.path = currentPoints.join('');
- }
- else
- {
- currentPath.setAttribute('d', currentPoints.join(''));
- }
- }
- else if (name == 'move')
- {
- var op = (vml) ? 'm' : 'M';
- this.lastMoveX = round(x0 + Number(node.getAttribute('x')) * sx);
- this.lastMoveY = round(y0 + Number(node.getAttribute('y')) * sy);
- addToPath(op + ' ' + this.lastMoveX + ' ' + this.lastMoveY);
- }
- else if (name == 'line')
- {
- var op = (vml) ? 'l' : 'L';
- this.lastMoveX = round(x0 + Number(node.getAttribute('x')) * sx);
- this.lastMoveY = round(y0 + Number(node.getAttribute('y')) * sy);
- addToPath(op + ' ' + this.lastMoveX + ' ' + this.lastMoveY);
- }
- else if (name == 'quad')
- {
- if (vml)
- {
- var cpx0 = this.lastMoveX;
- var cpy0 = this.lastMoveY;
- var qpx1 = x0 + Number(node.getAttribute('x1')) * sx;
- var qpy1 = y0 + Number(node.getAttribute('y1')) * sy;
- var cpx3 = x0 + Number(node.getAttribute('x2')) * sx;
- var cpy3 = y0 + Number(node.getAttribute('y2')) * sy;
-
- var cpx1 = cpx0 + 2/3 * (qpx1 - cpx0);
- var cpy1 = cpy0 + 2/3 * (qpy1 - cpy0);
-
- var cpx2 = cpx3 + 2/3 * (qpx1 - cpx3);
- var cpy2 = cpy3 + 2/3 * (qpy1 - cpy3);
-
- addToPath('c ' + Math.round(cpx1) + ' ' + Math.round(cpy1) + ' ' +
- Math.round(cpx2) + ' ' + Math.round(cpy2) + ' ' +
- Math.round(cpx3) + ' ' + Math.round(cpy3));
-
- this.lastMoveX = cpx3;
- this.lastMoveY = cpy3;
- }
- else
- {
- this.lastMoveX = x0 + Number(node.getAttribute('x2')) * sx;
- this.lastMoveY = y0 + Number(node.getAttribute('y2')) * sy;
-
- addToPath('Q ' + (x0 + Number(node.getAttribute('x1')) * sx) + ' ' +
- (y0 + Number(node.getAttribute('y1')) * sy) + ' ' +
- this.lastMoveX + ' ' + this.lastMoveY);
- }
- }
- else if (name == 'curve')
- {
- var op = (vml) ? 'c' : 'C';
- this.lastMoveX = round(x0 + Number(node.getAttribute('x3')) * sx);
- this.lastMoveY = round(y0 + Number(node.getAttribute('y3')) * sy);
-
- addToPath(op + ' ' + round(x0 + Number(node.getAttribute('x1')) * sx) + ' ' +
- round(y0 + Number(node.getAttribute('y1')) * sy) + ' ' +
- round(x0 + Number(node.getAttribute('x2')) * sx) + ' ' +
- round(y0 + Number(node.getAttribute('y2')) * sy) + ' ' +
- this.lastMoveX + ' ' + this.lastMoveY);
- }
- else if (name == 'close')
- {
- addToPath((vml) ? 'x' : 'Z');
- }
- else if (name == 'rect' || name == 'roundrect')
- {
- var rounded = name == 'roundrect';
- var x = round(x0 + Number(node.getAttribute('x')) * sx);
- var y = round(y0 + Number(node.getAttribute('y')) * sy);
- var w = round(Number(node.getAttribute('w')) * sx);
- var h = round(Number(node.getAttribute('h')) * sy);
-
- var arcsize = node.getAttribute('arcsize');
-
- if (arcsize == 0)
- {
- arcsize = mxConstants.RECTANGLE_ROUNDING_FACTOR * 100;
- }
-
- if (vml)
- {
- // LATER: Use HTML for non-rounded, gradientless rectangles
- currentPath = document.createElement((rounded) ? 'v:roundrect' : 'v:rect');
- currentPath.style.left = x + 'px';
- currentPath.style.top = y + 'px';
- currentPath.style.width = w + 'px';
- currentPath.style.height = h + 'px';
-
- if (rounded)
- {
- currentPath.setAttribute('arcsize', String(arcsize) + '%');
- }
- }
- else
- {
- currentPath = document.createElementNS(mxConstants.NS_SVG, 'rect');
- currentPath.setAttribute('x', x);
- currentPath.setAttribute('y', y);
- currentPath.setAttribute('width', w);
- currentPath.setAttribute('height', h);
-
- if (rounded)
- {
- var factor = Number(arcsize) / 100;
- var r = Math.min(w * factor, h * factor);
- currentPath.setAttribute('rx', r);
- currentPath.setAttribute('ry', r);
- }
-
- if (svgTransform.length > 0)
- {
- currentPath.setAttribute('transform', svgTransform);
- }
-
- if (node.getAttribute('crisp') == '1')
- {
- currentPath.setAttribute('shape-rendering', 'crispEdges');
- }
- }
-
- configurePath.call(this, currentPath, currentState);
- }
- else if (name == 'ellipse')
- {
- var x = round(x0 + Number(node.getAttribute('x')) * sx);
- var y = round(y0 + Number(node.getAttribute('y')) * sy);
- var w = round(Number(node.getAttribute('w')) * sx);
- var h = round(Number(node.getAttribute('h')) * sy);
-
- if (vml)
- {
- currentPath = document.createElement('v:arc');
- currentPath.startangle = '0';
- currentPath.endangle = '360';
- currentPath.style.left = x + 'px';
- currentPath.style.top = y + 'px';
- currentPath.style.width = w + 'px';
- currentPath.style.height = h + 'px';
- }
- else
- {
- currentPath = document.createElementNS(mxConstants.NS_SVG, 'ellipse');
- currentPath.setAttribute('cx', x + w / 2);
- currentPath.setAttribute('cy', y + h / 2);
- currentPath.setAttribute('rx', w / 2);
- currentPath.setAttribute('ry', h / 2);
-
- if (svgTransform.length > 0)
- {
- currentPath.setAttribute('transform', svgTransform);
- }
- }
-
- configurePath.call(this, currentPath, currentState);
- }
- else if (name == 'arc')
- {
- var r1 = Number(node.getAttribute('rx')) * sx;
- var r2 = Number(node.getAttribute('ry')) * sy;
- var angle = Number(node.getAttribute('x-axis-rotation'));
- var largeArcFlag = Number(node.getAttribute('large-arc-flag'));
- var sweepFlag = Number(node.getAttribute('sweep-flag'));
- var x = x0 + Number(node.getAttribute('x')) * sx;
- var y = y0 + Number(node.getAttribute('y')) * sy;
-
- if (vml)
- {
- var curves = mxUtils.arcToCurves(this.lastMoveX, this.lastMoveY, r1, r2, angle, largeArcFlag, sweepFlag, x, y);
-
- for (var i = 0; i < curves.length; i += 6)
- {
- addToPath('c' + ' ' + Math.round(curves[i]) + ' ' + Math.round(curves[i + 1]) + ' ' +
- Math.round(curves[i + 2]) + ' ' + Math.round(curves[i + 3]) + ' ' +
- Math.round(curves[i + 4]) + ' ' + Math.round(curves[i + 5]));
-
- this.lastMoveX = curves[i + 4];
- this.lastMoveY = curves[i + 5];
- }
- }
- else
- {
- addToPath('A ' + r1 + ',' + r2 + ' ' + angle + ' ' + largeArcFlag + ',' + sweepFlag + ' ' + x + ',' + y);
- this.lastMoveX = x0 + x;
- this.lastMoveY = y0 + y;
- }
- }
- else if (name == 'image')
- {
- var src = this.evaluateAttribute(node, 'src', shape.state);
-
- if (src != null)
- {
- var x = round(x0 + Number(node.getAttribute('x')) * sx);
- var y = round(y0 + Number(node.getAttribute('y')) * sy);
- var w = round(Number(node.getAttribute('w')) * sx);
- var h = round(Number(node.getAttribute('h')) * sy);
-
- // TODO: _Not_ providing an aspect in the shapes format has the advantage
- // of not needing a callback to adjust the image in VML. Since the shape
- // developer can specify the aspect via width and height this should OK.
- //var aspect = node.getAttribute('aspect') != '0';
- var aspect = false;
- var flipH = node.getAttribute('flipH') == '1';
- var flipV = node.getAttribute('flipV') == '1';
-
- if (vml)
- {
- currentPath = document.createElement('v:image');
- currentPath.style.filter = 'alpha(opacity=' + currentState.alpha + ')';
- currentPath.style.left = x + 'px';
- currentPath.style.top = y + 'px';
- currentPath.style.width = w + 'px';
- currentPath.style.height = h + 'px';
- currentPath.src = src;
-
- if (flipH && flipV)
- {
- currentPath.style.rotation = '180';
- }
- else if (flipH)
- {
- currentPath.style.flip = 'x';
- }
- else if (flipV)
- {
- currentPath.style.flip = 'y';
- }
- }
- else
- {
- currentPath = document.createElementNS(mxConstants.NS_SVG, 'image');
- currentPath.setAttributeNS(mxConstants.NS_XLINK, 'xlink:href', src);
- currentPath.setAttribute('opacity', currentState.alpha / 100);
- currentPath.setAttribute('x', x);
- currentPath.setAttribute('y', y);
- currentPath.setAttribute('width', w);
- currentPath.setAttribute('height', h);
-
- if (!aspect)
- {
- currentPath.setAttribute('preserveAspectRatio', 'none');
- }
-
- if (flipH || flipV)
- {
- var scx = 1;
- var scy = 1;
- var dx = 0;
- var dy = 0;
-
- if (flipH)
- {
- scx = -1;
- dx = -w - 2 * x;
- }
-
- if (flipV)
- {
- scy = -1;
- dy = -h - 2 * y;
- }
-
- currentPath.setAttribute('transform', svgTransform + 'scale(' + scx + ' ' + scy + ')' +
- ' translate('+dx+' '+dy+') ');
- }
- else
- {
- currentPath.setAttribute('transform', svgTransform);
- }
- }
-
- parentNode.appendChild(currentPath);
- }
- }
- else if (name == 'include-shape')
- {
- var stencil = mxStencilRegistry.getStencil(node.getAttribute('name'));
-
- if (stencil != null)
- {
- var x = x0 + Number(node.getAttribute('x')) * sx;
- var y = y0 + Number(node.getAttribute('y')) * sy;
- var w = Number(node.getAttribute('w')) * sx;
- var h = Number(node.getAttribute('h')) * sy;
-
- stencil.renderDom(shape, new mxRectangle(x, y, w, h), parentNode, currentState);
- }
- }
- // Additional labels are currently disabled. Needs fixing of VML
- // text positon, SVG text rotation and ignored baseline in FF
- else if (name == 'text')
- {
- var str = this.evaluateAttribute(node, 'str', shape.state);
-
- if (str != null)
- {
- var x = round(x0 + Number(node.getAttribute('x')) * sx);
- var y = round(y0 + Number(node.getAttribute('y')) * sy);
- var align = node.getAttribute('align') || 'left';
- var valign = node.getAttribute('valign') || 'top';
-
- if (vml)
- {
- // Renders a single line of text with full rotation support
- currentPath = document.createElement('v:shape');
- currentPath.style.position = 'absolute';
- currentPath.style.width = '1px';
- currentPath.style.height = '1px';
- currentPath.style.left = x + 'px';
- currentPath.style.top = y + 'px';
-
- var fill = document.createElement('v:fill');
- fill.color = currentState.fontColor;
- fill.on = 'true';
- currentPath.appendChild(fill);
-
- var stroke = document.createElement('v:stroke');
- stroke.on = 'false';
- currentPath.appendChild(stroke);
-
- var path = document.createElement('v:path');
- path.textpathok = 'true';
- path.v = 'm ' + x + ' ' + y + ' l ' + (x + 1) + ' ' + y;
-
- currentPath.appendChild(path);
-
- var tp = document.createElement('v:textpath');
- tp.style.cssText = 'v-text-align:' + align;
- tp.style.fontSize = Math.round(currentState.fontSize / vmlScale) + 'px';
-
- // FIXME: Font-family seems to be ignored for textpath
- tp.style.fontFamily = currentState.fontFamily;
- tp.string = str;
- tp.on = 'true';
-
- // Bold
- if ((currentState.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD)
- {
- tp.style.fontWeight = 'bold';
- }
-
- // Italic
- if ((currentState.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC)
- {
- tp.style.fontStyle = 'italic';
- }
-
- // FIXME: Text decoration not supported in textpath
- if ((currentState.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE)
- {
- tp.style.textDecoration = 'underline';
- }
-
- // LATER: Find vertical center for div via CSS if possible
- if (valign == 'top')
- {
- currentPath.style.top = (y + currentState.fontSize / 2) + 'px';
- }
- else if (valign == 'bottom')
- {
- currentPath.style.top = (y - currentState.fontSize / 3) + 'px';
- }
-
- currentPath.appendChild(tp);
- }
- else
- {
- currentPath = document.createElementNS(mxConstants.NS_SVG, 'text');
- currentPath.setAttribute('fill', currentState.fontColor);
- currentPath.setAttribute('font-family', currentState.fontFamily);
- currentPath.setAttribute('font-size', currentState.fontSize);
- currentPath.setAttribute('stroke', 'none');
- currentPath.setAttribute('x', x);
- currentPath.appendChild(document.createTextNode(str));
-
- // Bold
- if ((currentState.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD)
- {
- currentPath.setAttribute('font-weight', 'bold');
- }
-
- // Italic
- if ((currentState.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC)
- {
- currentPath.setAttribute('font-style', 'italic');
- }
-
- // Underline
- if ((currentState.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE)
- {
- currentPath.setAttribute('text-decoration', uline);
- }
-
- // Horizontal alignment
- if (align == 'left')
- {
- align = 'start';
- }
- else if (align == 'center')
- {
- align = 'middle';
- }
- else if (align == 'right')
- {
- align = 'end';
- }
-
- currentPath.setAttribute('text-anchor', align);
-
- // Vertical alignment
- // Uses dy because FF ignores alignment-baseline
- if (valign == 'top')
- {
- currentPath.setAttribute('y', y + currentState.fontSize / 5);
- currentPath.setAttribute('dy', '1ex');
- }
- else if (valign == 'middle')
- {
- currentPath.setAttribute('y', y + currentState.fontSize / 8);
- currentPath.setAttribute('dy', '0.5ex');
- }
- else
- {
- currentPath.setAttribute('y', y);
- }
-
- if (svgTransform.length > 0)
- {
- currentPath.setAttribute('transform', svgTransform);
- }
- }
-
- parentNode.appendChild(currentPath);
- }
- }
- else if (fillOp || strokeOp || fillStrokeOp)
- {
- if (currentPath != null)
- {
- var pattern = null;
-
- if (currentState.dashed)
- {
- var f = (vml) ? minScale : Number(currentPath.getAttribute('stroke-width'));
- var pat = [];
-
- for (var i = 0; i < currentState.dashpattern.length; i++)
- {
- pat.push(Math.max(1, Math.round(Number(currentState.dashpattern[i]) * f)));
- }
-
- pattern = pat.join(' ');
- }
-
- if (strokeOp || fillStrokeOp)
- {
- if (vml)
- {
- var stroke = document.createElement('v:stroke');
- stroke.endcap = currentState.linecap || 'flat';
- stroke.joinstyle = currentState.linejoin || 'miter';
- stroke.miterlimit = currentState.miterlimit || '10';
- currentPath.appendChild(stroke);
-
- // TODO: Dashpattern support in VML is limited, we should
- // map this to VML or allow for a separate VML dashstyle.
- if (pattern != null)
- {
- stroke.dashstyle = pattern;
- }
- }
- else
- {
- if (currentState.linejoin != null)
- {
- currentPath.setAttribute('stroke-linejoin', currentState.linejoin);
- }
-
- if (currentState.linecap != null)
- {
- // flat is called butt in SVG
- var value = currentState.linecap;
-
- if (value == 'flat')
- {
- value = 'butt';
- }
-
- currentPath.setAttribute('stroke-linecap', value);
- }
-
- if (currentState.miterlimit != null)
- {
- currentPath.setAttribute('stroke-miterlimit', currentState.miterlimit);
- }
-
- // Handles dash pattern
- if (pattern != null)
- {
- currentPath.setAttribute('stroke-dasharray', pattern);
- }
- }
- }
-
- // Adds the shadow
- if (background && shape.isShadow)
- {
- var dx = mxConstants.SHADOW_OFFSET_X * shape.scale;
- var dy = mxConstants.SHADOW_OFFSET_Y * shape.scale;
-
- // Adds the shadow
- if (vml)
- {
- var shadow = document.createElement('v:shadow');
- shadow.setAttribute('on', 'true');
- shadow.setAttribute('color', mxConstants.SHADOWCOLOR);
- shadow.setAttribute('offset', Math.round(dx) + 'px,' + Math.round(dy) + 'px');
- shadow.setAttribute('opacity', (mxConstants.SHADOW_OPACITY * 100) + '%');
-
- var stroke = document.createElement('v:stroke');
- stroke.endcap = currentState.linecap || 'flat';
- stroke.joinstyle = currentState.linejoin || 'miter';
- stroke.miterlimit = currentState.miterlimit || '10';
-
- if (pattern != null)
- {
- stroke.dashstyle = pattern;
- }
-
- shadow.appendChild(stroke);
- currentPath.appendChild(shadow);
- }
- else
- {
- var shadow = currentPath.cloneNode(true);
- shadow.setAttribute('stroke', mxConstants.SHADOWCOLOR);
-
- if (currentState.fill != null && (fillOp || fillStrokeOp))
- {
- shadow.setAttribute('fill', mxConstants.SHADOWCOLOR);
- }
- else
- {
- shadow.setAttribute('fill', 'none');
- }
-
- shadow.setAttribute('transform', 'translate(' + dx + ' ' + dy + ') ' +
- (shadow.getAttribute('transform') || ''));
- shadow.setAttribute('opacity', mxConstants.SHADOW_OPACITY);
- parentNode.appendChild(shadow);
- }
- }
-
- if (fillOp)
- {
- if (vml)
- {
- currentPath.stroked = 'false';
- }
- else
- {
- currentPath.setAttribute('stroke', 'none');
- }
- }
- else if (strokeOp)
- {
- if (vml)
- {
- currentPath.filled = 'false';
- }
- else
- {
- currentPath.setAttribute('fill', 'none');
- }
- }
-
- parentNode.appendChild(currentPath);
- }
-
- // Background was painted
- if (background)
- {
- background = false;
- }
- }
- else if (name == 'linecap')
- {
- currentState.linecap = node.getAttribute('cap');
- }
- else if (name == 'linejoin')
- {
- currentState.linejoin = node.getAttribute('join');
- }
- else if (name == 'miterlimit')
- {
- currentState.miterlimit = node.getAttribute('limit');
- }
- else if (name == 'dashed')
- {
- currentState.dashed = node.getAttribute('dashed') == '1';
- }
- else if (name == 'dashpattern')
- {
- var value = node.getAttribute('pattern');
-
- if (value != null && value.length > 0)
- {
- currentState.dashpattern = value.split(' ');
- }
- }
- else if (name == 'strokewidth')
- {
- currentState.strokeWidth = node.getAttribute('width') * minScale;
-
- if (vml)
- {
- currentState.strokeWidth /= vmlScale;
- }
- }
- else if (name == 'strokecolor')
- {
- currentState.stroke = node.getAttribute('color');
- }
- else if (name == 'fillcolor')
- {
- currentState.fill = node.getAttribute('color');
- currentState.fillColorAssigned = true;
- }
- else if (name == 'alpha')
- {
- currentState.alpha = Number(node.getAttribute('alpha'));
- }
- else if (name == 'fontcolor')
- {
- currentState.fontColor = node.getAttribute('color');
- }
- else if (name == 'fontsize')
- {
- currentState.fontSize = Number(node.getAttribute('size')) * minScale;
- }
- else if (name == 'fontfamily')
- {
- currentState.fontFamily = node.getAttribute('family');
- }
- else if (name == 'fontstyle')
- {
- currentState.fontStyle = Number(node.getAttribute('style'));
- }
- };
-
- // Adds a transparent rectangle in the background for hit-detection in SVG
- if (!vml)
- {
- var rect = document.createElementNS(mxConstants.NS_SVG, 'rect');
- rect.setAttribute('x', bounds.x);
- rect.setAttribute('y', bounds.y);
- rect.setAttribute('width', bounds.width);
- rect.setAttribute('height', bounds.height);
- rect.setAttribute('fill', 'none');
- rect.setAttribute('stroke', 'none');
- parentNode.appendChild(rect);
- }
-
- // Background switches to false after fill/stroke of the background
- if (this.bgNode != null)
- {
- var tmp = this.bgNode.firstChild;
-
- while (tmp != null)
- {
- if (tmp.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- renderNode.call(this, tmp);
- }
-
- tmp = tmp.nextSibling;
- }
- }
- else
- {
- background = false;
- }
-
- if (this.fgNode != null)
- {
- var tmp = this.fgNode.firstChild;
-
- while (tmp != null)
- {
- if (tmp.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- renderNode.call(this, tmp);
- }
-
- tmp = tmp.nextSibling;
- }
- }
- }
-};
-
-/**
- * Function: drawShape
- *
- * Draws this stencil inside the given bounds.
- */
-mxStencil.prototype.drawShape = function(canvas, state, bounds, background)
-{
- // TODO: Unify with renderDom, check performance of pluggable shape,
- // internal structure (array of special structs?), relative and absolute
- // coordinates (eg. note shape, process vs star, actor etc.), text rendering
- // and non-proportional scaling, how to implement pluggable edge shapes
- // (start, segment, end blocks), pluggable markers, how to implement
- // swimlanes (title area) with this API, add icon, horizontal/vertical
- // label, indicator for all shapes, rotation
- var node = (background) ? this.bgNode : this.fgNode;
-
- if (node != null)
- {
- var direction = mxUtils.getValue(state.style, mxConstants.STYLE_DIRECTION, null);
- var aspect = this.computeAspect(state, bounds, direction);
- var minScale = Math.min(aspect.width, aspect.height);
- var sw = (this.strokewidth == 'inherit') ?
- Number(mxUtils.getNumber(state.style, mxConstants.STYLE_STROKEWIDTH, 1)) * state.view.scale :
- Number(this.strokewidth) * minScale;
- this.lastMoveX = 0;
- this.lastMoveY = 0;
- canvas.setStrokeWidth(sw);
-
- var tmp = node.firstChild;
-
- while (tmp != null)
- {
- if (tmp.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- this.drawNode(canvas, state, tmp, aspect);
- }
-
- tmp = tmp.nextSibling;
- }
-
- return true;
- }
-
- return false;
-};
-
-/**
- * Function: computeAspect
- *
- * Returns a rectangle that contains the offset in x and y and the horizontal
- * and vertical scale in width and height used to draw this shape inside the
- * given <mxRectangle>.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the shape should be drawn.
- * bounds - <mxRectangle> that should contain the stencil.
- * direction - Optional direction of the shape to be darwn.
- */
-mxStencil.prototype.computeAspect = function(state, bounds, direction)
-{
- var x0 = bounds.x;
- var y0 = bounds.y;
- var sx = bounds.width / this.w0;
- var sy = bounds.height / this.h0;
-
- var inverse = (direction == 'north' || direction == 'south');
-
- if (inverse)
- {
- sy = bounds.width / this.h0;
- sx = bounds.height / this.w0;
-
- var delta = (bounds.width - bounds.height) / 2;
-
- x0 += delta;
- y0 -= delta;
- }
-
- if (this.aspect == 'fixed')
- {
- sy = Math.min(sx, sy);
- sx = sy;
-
- // Centers the shape inside the available space
- if (inverse)
- {
- x0 += (bounds.height - this.w0 * sx) / 2;
- y0 += (bounds.width - this.h0 * sy) / 2;
- }
- else
- {
- x0 += (bounds.width - this.w0 * sx) / 2;
- y0 += (bounds.height - this.h0 * sy) / 2;
- }
- }
-
- return new mxRectangle(x0, y0, sx, sy);
-};
-
-/**
- * Function: drawNode
- *
- * Draws this stencil inside the given bounds.
- */
-mxStencil.prototype.drawNode = function(canvas, state, node, aspect)
-{
- var name = node.nodeName;
- var x0 = aspect.x;
- var y0 = aspect.y;
- var sx = aspect.width;
- var sy = aspect.height;
- var minScale = Math.min(sx, sy);
-
- // LATER: Move to lookup table
- if (name == 'save')
- {
- canvas.save();
- }
- else if (name == 'restore')
- {
- canvas.restore();
- }
- else if (name == 'path')
- {
- canvas.begin();
-
- // Renders the elements inside the given path
- var childNode = node.firstChild;
-
- while (childNode != null)
- {
- if (childNode.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- this.drawNode(canvas, state, childNode, aspect);
- }
-
- childNode = childNode.nextSibling;
- }
- }
- else if (name == 'close')
- {
- canvas.close();
- }
- else if (name == 'move')
- {
- this.lastMoveX = x0 + Number(node.getAttribute('x')) * sx;
- this.lastMoveY = y0 + Number(node.getAttribute('y')) * sy;
- canvas.moveTo(this.lastMoveX, this.lastMoveY);
- }
- else if (name == 'line')
- {
- this.lastMoveX = x0 + Number(node.getAttribute('x')) * sx;
- this.lastMoveY = y0 + Number(node.getAttribute('y')) * sy;
- canvas.lineTo(this.lastMoveX, this.lastMoveY);
- }
- else if (name == 'quad')
- {
- this.lastMoveX = x0 + Number(node.getAttribute('x2')) * sx;
- this.lastMoveY = y0 + Number(node.getAttribute('y2')) * sy;
- canvas.quadTo(x0 + Number(node.getAttribute('x1')) * sx,
- y0 + Number(node.getAttribute('y1')) * sy,
- this.lastMoveX, this.lastMoveY);
- }
- else if (name == 'curve')
- {
- this.lastMoveX = x0 + Number(node.getAttribute('x3')) * sx;
- this.lastMoveY = y0 + Number(node.getAttribute('y3')) * sy;
- canvas.curveTo(x0 + Number(node.getAttribute('x1')) * sx,
- y0 + Number(node.getAttribute('y1')) * sy,
- x0 + Number(node.getAttribute('x2')) * sx,
- y0 + Number(node.getAttribute('y2')) * sy,
- this.lastMoveX, this.lastMoveY);
- }
- else if (name == 'arc')
- {
- // Arc from stencil is turned into curves in image output
- var r1 = Number(node.getAttribute('rx')) * sx;
- var r2 = Number(node.getAttribute('ry')) * sy;
- var angle = Number(node.getAttribute('x-axis-rotation'));
- var largeArcFlag = Number(node.getAttribute('large-arc-flag'));
- var sweepFlag = Number(node.getAttribute('sweep-flag'));
- var x = x0 + Number(node.getAttribute('x')) * sx;
- var y = y0 + Number(node.getAttribute('y')) * sy;
-
- var curves = mxUtils.arcToCurves(this.lastMoveX, this.lastMoveY, r1, r2, angle, largeArcFlag, sweepFlag, x, y);
-
- for (var i = 0; i < curves.length; i += 6)
- {
- canvas.curveTo(curves[i], curves[i + 1], curves[i + 2],
- curves[i + 3], curves[i + 4], curves[i + 5]);
-
- this.lastMoveX = curves[i + 4];
- this.lastMoveY = curves[i + 5];
- }
- }
- else if (name == 'rect')
- {
- canvas.rect(x0 + Number(node.getAttribute('x')) * sx,
- y0 + Number(node.getAttribute('y')) * sy,
- Number(node.getAttribute('w')) * sx,
- Number(node.getAttribute('h')) * sy);
- }
- else if (name == 'roundrect')
- {
- var arcsize = node.getAttribute('arcsize');
-
- if (arcsize == 0)
- {
- arcsize = mxConstants.RECTANGLE_ROUNDING_FACTOR * 100;
- }
-
- var w = Number(node.getAttribute('w')) * sx;
- var h = Number(node.getAttribute('h')) * sy;
- var factor = Number(arcsize) / 100;
- var r = Math.min(w * factor, h * factor);
-
- canvas.roundrect(x0 + Number(node.getAttribute('x')) * sx,
- y0 + Number(node.getAttribute('y')) * sy,
- w, h, r, r);
- }
- else if (name == 'ellipse')
- {
- canvas.ellipse(x0 + Number(node.getAttribute('x')) * sx,
- y0 + Number(node.getAttribute('y')) * sy,
- Number(node.getAttribute('w')) * sx,
- Number(node.getAttribute('h')) * sy);
- }
- else if (name == 'image')
- {
- var src = this.evaluateAttribute(node, 'src', state);
-
- canvas.image(x0 + Number(node.getAttribute('x')) * sx,
- y0 + Number(node.getAttribute('y')) * sy,
- Number(node.getAttribute('w')) * sx,
- Number(node.getAttribute('h')) * sy,
- src, false, node.getAttribute('flipH') == '1',
- node.getAttribute('flipV') == '1');
- }
- else if (name == 'text')
- {
- var str = this.evaluateAttribute(node, 'str', state);
-
- canvas.text(x0 + Number(node.getAttribute('x')) * sx,
- y0 + Number(node.getAttribute('y')) * sy,
- 0, 0, str, node.getAttribute('align'),
- node.getAttribute('valign'),
- node.getAttribute('vertical'));
- }
- else if (name == 'include-shape')
- {
- var stencil = mxStencilRegistry.getStencil(node.getAttribute('name'));
-
- if (stencil != null)
- {
- var x = x0 + Number(node.getAttribute('x')) * sx;
- var y = y0 + Number(node.getAttribute('y')) * sy;
- var w = Number(node.getAttribute('w')) * sx;
- var h = Number(node.getAttribute('h')) * sy;
-
- var tmp = new mxRectangle(x, y, w, h);
- stencil.drawShape(canvas, state, tmp, true);
- stencil.drawShape(canvas, state, tmp, false);
- }
- }
- else if (name == 'fillstroke')
- {
- canvas.fillAndStroke();
- }
- else if (name == 'fill')
- {
- canvas.fill();
- }
- else if (name == 'stroke')
- {
- canvas.stroke();
- }
- else if (name == 'strokewidth')
- {
- canvas.setStrokeWidth(Number(node.getAttribute('width')) * minScale);
- }
- else if (name == 'dashed')
- {
- canvas.setDashed(node.getAttribute('dashed') == '1');
- }
- else if (name == 'dashpattern')
- {
- var value = node.getAttribute('pattern');
-
- if (value != null)
- {
- var tmp = value.split(' ');
- var pat = [];
-
- for (var i = 0; i < tmp.length; i++)
- {
- if (tmp[i].length > 0)
- {
- pat.push(Number(tmp[i]) * minScale);
- }
- }
-
- value = pat.join(' ');
- canvas.setDashPattern(value);
- }
- }
- else if (name == 'strokecolor')
- {
- canvas.setStrokeColor(node.getAttribute('color'));
- }
- else if (name == 'linecap')
- {
- canvas.setLineCap(node.getAttribute('cap'));
- }
- else if (name == 'linejoin')
- {
- canvas.setLineJoin(node.getAttribute('join'));
- }
- else if (name == 'miterlimit')
- {
- canvas.setMiterLimit(Number(node.getAttribute('limit')));
- }
- else if (name == 'fillcolor')
- {
- canvas.setFillColor(node.getAttribute('color'));
- }
- else if (name == 'fontcolor')
- {
- canvas.setFontColor(node.getAttribute('color'));
- }
- else if (name == 'fontstyle')
- {
- canvas.setFontStyle(node.getAttribute('style'));
- }
- else if (name == 'fontfamily')
- {
- canvas.setFontFamily(node.getAttribute('family'));
- }
- else if (name == 'fontsize')
- {
- canvas.setFontSize(Number(node.getAttribute('size')) * minScale);
- }
-};
diff --git a/src/js/shape/mxStencilRegistry.js b/src/js/shape/mxStencilRegistry.js
deleted file mode 100644
index 7621573..0000000
--- a/src/js/shape/mxStencilRegistry.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * $Id: mxStencilRegistry.js,v 1.2 2011-07-15 12:57:50 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- *
- * Code to add stencils.
- *
- * (code)
- * var req = mxUtils.load('test/stencils.xml');
- * var root = req.getDocumentElement();
- * var shape = root.firstChild;
- *
- * while (shape != null)
- * {
- * if (shape.nodeType == mxConstants.NODETYPE_ELEMENT)
- * {
- * mxStencilRegistry.addStencil(shape.getAttribute('name'), new mxStencil(shape));
- * }
- *
- * shape = shape.nextSibling;
- * }
- * (end)
- */
-var mxStencilRegistry =
-{
- /**
- * Class: mxStencilRegistry
- *
- * A singleton class that provides a registry for stencils and the methods
- * for painting those stencils onto a canvas or into a DOM.
- */
- stencils: [],
-
- /**
- * Function: addStencil
- *
- * Adds the given <mxStencil>.
- */
- addStencil: function(name, stencil)
- {
- mxStencilRegistry.stencils[name] = stencil;
- },
-
- /**
- * Function: getStencil
- *
- * Returns the <mxStencil> for the given name.
- */
- getStencil: function(name)
- {
- return mxStencilRegistry.stencils[name];
- }
-
-};
diff --git a/src/js/shape/mxStencilShape.js b/src/js/shape/mxStencilShape.js
deleted file mode 100644
index 9c95f8b..0000000
--- a/src/js/shape/mxStencilShape.js
+++ /dev/null
@@ -1,209 +0,0 @@
-/**
- * $Id: mxStencilShape.js,v 1.10 2012-07-16 10:22:44 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxStencilShape
- *
- * Implements a shape based on a <mxStencil>.
- *
- * Constructor: mxStencilShape
- *
- * Constructs a new generic shape.
- */
-function mxStencilShape(stencil)
-{
- this.stencil = stencil;
-};
-
-/**
- * Extends mxShape.
- */
-mxStencilShape.prototype = new mxShape();
-mxStencilShape.prototype.constructor = mxStencilShape;
-
-/**
- * Variable: mixedModeHtml
- *
- * Always prefers VML in mixed mode for stencil shapes. Default is false.
- */
-mxStencilShape.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Always prefers VML in prefer HTML mode for stencil shapes. Default is false.
- */
-mxStencilShape.prototype.preferModeHtml = false;
-
-/**
- * Variable: stencil
- *
- * Holds the <mxStencil> that defines the shape.
- */
-mxStencilShape.prototype.stencil = null;
-
-/**
- * Variable: state
- *
- * Holds the <mxCellState> associated with this shape.
- */
-mxStencilShape.prototype.state = null;
-
-/**
- * Variable: vmlScale
- *
- * Renders VML with a scale of 4.
- */
-mxStencilShape.prototype.vmlScale = 4;
-
-/**
- * Function: apply
- *
- * Extends <mxShape> apply to keep a reference to the <mxCellState>.
- *
- * Parameters:
- *
- * state - <mxCellState> of the corresponding cell.
- */
-mxStencilShape.prototype.apply = function(state)
-{
- this.state = state;
- mxShape.prototype.apply.apply(this, arguments);
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxStencilShape.prototype.createSvg = function()
-{
- var node = document.createElementNS(mxConstants.NS_SVG, 'g');
- this.configureSvgShape(node);
-
- return node;
-};
-
-/**
- * Function: configureHtmlShape
- *
- * Overrides method to set the overflow style to visible.
- */
-mxStencilShape.prototype.configureHtmlShape = function(node)
-{
- mxShape.prototype.configureHtmlShape.apply(this, arguments);
-
- if (!mxUtils.isVml(node))
- {
- node.style.overflow = 'visible';
- }
-};
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
-mxStencilShape.prototype.createVml = function()
-{
- var name = (document.documentMode == 8) ? 'div' : 'v:group';
- var node = document.createElement(name);
- this.configureTransparentBackground(node);
- node.style.position = 'absolute';
-
- return node;
-};
-
-/**
- * Function: configureVmlShape
- *
- * Configures the specified VML node by applying the current color,
- * bounds, shadow, opacity etc.
- */
-mxStencilShape.prototype.configureVmlShape = function(node)
-{
- // do nothing
-};
-
-/**
- * Function: redraw
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxStencilShape.prototype.redraw = function()
-{
- this.updateBoundingBox();
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- this.redrawShape();
- }
- else
- {
- this.node.style.visibility = 'hidden';
- this.redrawShape();
- this.node.style.visibility = 'visible';
- }
-};
-
-/**
- * Function: redrawShape
- *
- * Updates the SVG or VML shape.
- */
-mxStencilShape.prototype.redrawShape = function()
-{
- // LATER: Update existing DOM nodes to improve repaint performance
- if (this.dialect != mxConstants.DIALECT_SVG)
- {
- this.node.style.left = Math.round(this.bounds.x) + 'px';
- this.node.style.top = Math.round(this.bounds.y) + 'px';
- var w = Math.round(this.bounds.width);
- var h = Math.round(this.bounds.height);
- this.node.style.width = w + 'px';
- this.node.style.height = h + 'px';
-
- var node = this.node;
-
- // Workaround for VML rendering bug in IE8 standards mode where all VML must be
- // parsed via assigning the innerHTML of the parent HTML node to keep all event
- // handlers referencing node and support rotation via v:group parent element.
- if (this.node.nodeName == 'DIV')
- {
- node = document.createElement('v:group');
- node.style.position = 'absolute';
- node.style.left = '0px';
- node.style.top = '0px';
- node.style.width = w + 'px';
- node.style.height = h + 'px';
- }
- else
- {
- node.innerHTML = '';
- }
-
- if (mxUtils.isVml(node))
- {
- var s = (document.documentMode != 8) ? this.vmlScale : 1;
- node.coordsize = (w * s) + ',' + (h * s);
- }
-
- this.stencil.renderDom(this, this.bounds, node);
-
- if(this.node != node)
- {
- // Forces parsing in IE8 standards mode
- this.node.innerHTML = node.outerHTML;
- }
- }
- else
- {
- while (this.node.firstChild != null)
- {
- this.node.removeChild(this.node.firstChild);
- }
-
- this.stencil.renderDom(this, this.bounds, this.node);
- }
-};
diff --git a/src/js/shape/mxSwimlane.js b/src/js/shape/mxSwimlane.js
deleted file mode 100644
index 22720fd..0000000
--- a/src/js/shape/mxSwimlane.js
+++ /dev/null
@@ -1,553 +0,0 @@
-/**
- * $Id: mxSwimlane.js,v 1.43 2011-11-04 13:54:50 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxSwimlane
- *
- * Extends <mxShape> to implement a swimlane shape.
- * This shape is registered under <mxConstants.SHAPE_SWIMLANE>
- * in <mxCellRenderer>.
- *
- * Constructor: mxSwimlane
- *
- * Constructs a new swimlane shape.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * fill - String that defines the fill color. This is stored in <fill>.
- * stroke - String that defines the stroke color. This is stored in <stroke>.
- * strokewidth - Optional integer that defines the stroke width. Default is
- * 1. This is stored in <strokewidth>.
- */
-function mxSwimlane(bounds, fill, stroke, strokewidth)
-{
- this.bounds = bounds;
- this.fill = fill;
- this.stroke = stroke;
- this.strokewidth = (strokewidth != null) ? strokewidth : 1;
-};
-
-/**
- * Extends mxShape.
- */
-mxSwimlane.prototype = new mxShape();
-mxSwimlane.prototype.constructor = mxSwimlane;
-
-/**
- * Variable: vmlNodes
- *
- * Adds local references to <mxShape.vmlNodes>.
- */
-mxSwimlane.prototype.vmlNodes = mxSwimlane.prototype.vmlNodes.concat(['label', 'content', 'imageNode', 'separator']);
-
-/**
- * Variable: imageSize
- *
- * Default imagewidth and imageheight if an image but no imagewidth
- * and imageheight are defined in the style. Value is 16.
- */
-mxSwimlane.prototype.imageSize = 16;
-
-/**
- * Variable: mixedModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw in VML in mixed Html mode. This is for better
- * handling of event-transparency of the content area.
- */
-mxSwimlane.prototype.mixedModeHtml = false;
-
-/**
- * Variable: preferModeHtml
- *
- * Overrides the parent value with false, meaning it will
- * draw as VML in prefer Html mode. This is for better
- * handling of event-transparency of the content area.
- */
-mxRhombus.prototype.preferModeHtml = false;
-
-/**
- * Function: createHtml
- *
- * Creates and returns the HTML node to represent this shape.
- */
-mxSwimlane.prototype.createHtml = function()
-{
- var node = document.createElement('DIV');
- this.configureHtmlShape(node);
- node.style.background = '';
- node.style.backgroundColor = '';
- node.style.borderStyle = 'none';
-
- // Adds a node that will contain the text label
- this.label = document.createElement('DIV');
- this.configureHtmlShape(this.label);
- node.appendChild(this.label);
-
- // Adds a node for the content area of the swimlane
- this.content = document.createElement('DIV');
- this.configureHtmlShape(this.content);
- this.content.style.backgroundColor = '';
-
- // Sets border styles depending on orientation
- if (mxUtils.getValue(this.style, mxConstants.STYLE_HORIZONTAL, true))
- {
- this.content.style.borderTopStyle = 'none';
- }
- else
- {
- this.content.style.borderLeftStyle = 'none';
- }
-
- this.content.style.cursor = 'default';
- node.appendChild(this.content);
-
- // Adds a node for the separator
- var color = this.style[mxConstants.STYLE_SEPARATORCOLOR];
-
- if (color != null)
- {
- this.separator = document.createElement('DIV');
- this.separator.style.borderColor = color;
- this.separator.style.borderLeftStyle = 'dashed';
- node.appendChild(this.separator);
- }
-
- // Adds a node for the image
- if (this.image != null)
- {
- this.imageNode = mxUtils.createImage(this.image);
- this.configureHtmlShape(this.imageNode);
- this.imageNode.style.borderStyle = 'none';
- node.appendChild(this.imageNode);
- }
-
- return node;
-};
-
-/**
- * Function: reconfigure
- *
- * Overrides to avoid filled content area in HTML and updates the shadow
- * in SVG.
- */
-mxSwimlane.prototype.reconfigure = function(node)
-{
- mxShape.prototype.reconfigure.apply(this, arguments);
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- if (this.shadowNode != null)
- {
- this.updateSvgShape(this.shadowNode);
-
- if (mxUtils.getValue(this.style, mxConstants.STYLE_HORIZONTAL, true))
- {
- this.shadowNode.setAttribute('height', this.startSize*this.scale);
- }
- else
- {
- this.shadowNode.setAttribute('width', this.startSize*this.scale);
- }
- }
- }
- else if (!mxUtils.isVml(this.node))
- {
- this.node.style.background = '';
- this.node.style.backgroundColor = '';
- }
-};
-
-/**
- * Function: redrawHtml
- *
- * Updates the HTML node(s) to reflect the latest bounds and scale.
- */
-mxSwimlane.prototype.redrawHtml = function()
-{
- this.updateHtmlShape(this.node);
- this.node.style.background = '';
- this.node.style.backgroundColor = '';
- this.startSize = parseInt(mxUtils.getValue(this.style,
- mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE));
- this.updateHtmlShape(this.label);
- this.label.style.top = '0px';
- this.label.style.left = '0px';
-
- if (mxUtils.getValue(this.style, mxConstants.STYLE_HORIZONTAL, true))
- {
- this.startSize = Math.min(this.startSize, this.bounds.height);
- this.label.style.height = (this.startSize * this.scale)+'px'; // relative
- this.updateHtmlShape(this.content);
- this.content.style.background = '';
- this.content.style.backgroundColor = '';
-
- var h = this.startSize*this.scale;
-
- this.content.style.top = h+'px';
- this.content.style.left = '0px';
- this.content.style.height = Math.max(1, this.bounds.height - h)+'px';
-
- if (this.separator != null)
- {
- this.separator.style.left = Math.round(this.bounds.width)+'px';
- this.separator.style.top = Math.round(this.startSize*this.scale)+'px';
- this.separator.style.width = '1px';
- this.separator.style.height = Math.round(this.bounds.height)+'px';
- this.separator.style.borderWidth = Math.round(this.scale)+'px';
- }
-
- if (this.imageNode != null)
- {
- this.imageNode.style.left = (this.bounds.width-this.imageSize-4)+'px';
- this.imageNode.style.top = '0px';
- // TODO: Use imageWidth and height from style if available
- this.imageNode.style.width = Math.round(this.imageSize*this.scale)+'px';
- this.imageNode.style.height = Math.round(this.imageSize*this.scale)+'px';
- }
- }
- else
- {
- this.startSize = Math.min(this.startSize, this.bounds.width);
- this.label.style.width = (this.startSize * this.scale)+'px'; // relative
- this.updateHtmlShape(this.content);
- this.content.style.background = '';
- this.content.style.backgroundColor = '';
-
- var w = this.startSize*this.scale;
-
- this.content.style.top = '0px';
- this.content.style.left = w+'px';
- this.content.style.width = Math.max(0, this.bounds.width - w)+'px';
-
- if (this.separator != null)
- {
- this.separator.style.left = Math.round(this.startSize*this.scale)+'px';
- this.separator.style.top = Math.round(this.bounds.height)+'px';
- this.separator.style.width = Math.round(this.bounds.width)+'px';
- this.separator.style.height = '1px';
- }
-
- if (this.imageNode != null)
- {
- this.imageNode.style.left = (this.bounds.width-this.imageSize-4)+'px';
- this.imageNode.style.top = '0px';
- this.imageNode.style.width = this.imageSize*this.scale+'px';
- this.imageNode.style.height = this.imageSize*this.scale+'px';
- }
- }
-};
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node(s) to represent this shape.
- */
-mxSwimlane.prototype.createVml = function()
-{
- var node = document.createElement('v:group');
- var name = (this.isRounded) ? 'v:roundrect' : 'v:rect';
- this.label = document.createElement(name);
-
- // First configure the label with all settings
- this.configureVmlShape(this.label);
-
- if (this.isRounded)
- {
- this.label.setAttribute('arcsize', '20%');
- }
-
- // Disables stuff and configures the rest
- this.isShadow = false;
- this.configureVmlShape(node);
- node.coordorigin = '0,0';
- node.appendChild(this.label);
-
- this.content = document.createElement(name);
-
- var tmp = this.fill;
- this.fill = null;
-
- this.configureVmlShape(this.content);
- node.style.background = '';
-
- if (this.isRounded)
- {
- this.content.setAttribute('arcsize', '4%');
- }
-
- this.fill = tmp;
- this.content.style.borderBottom = '0px';
-
- node.appendChild(this.content);
-
- var color = this.style[mxConstants.STYLE_SEPARATORCOLOR];
-
- if (color != null)
- {
- this.separator = document.createElement('v:shape');
- this.separator.style.position = 'absolute';
- this.separator.strokecolor = color;
-
- var strokeNode = document.createElement('v:stroke');
- strokeNode.dashstyle = '2 2';
- this.separator.appendChild(strokeNode);
-
- node.appendChild(this.separator);
- }
-
- if (this.image != null)
- {
- this.imageNode = document.createElement('v:image');
- this.imageNode.src = this.image;
- this.configureVmlShape(this.imageNode);
- this.imageNode.stroked = 'false';
-
- node.appendChild(this.imageNode);
- }
-
- return node;
-};
-
-/**
- * Function: redrawVml
- *
- * Updates the VML node(s) to reflect the latest bounds and scale.
- */
-mxSwimlane.prototype.redrawVml = function()
-{
- var x = Math.round(this.bounds.x);
- var y = Math.round(this.bounds.y);
- var w = Math.round(this.bounds.width);
- var h = Math.round(this.bounds.height);
-
- this.updateVmlShape(this.node);
- this.node.coordsize = w + ',' + h;
-
- this.updateVmlShape(this.label);
- this.label.style.top = '0px';
- this.label.style.left = '0px';
- this.label.style.rotation = null;
-
- this.startSize = parseInt(mxUtils.getValue(this.style,
- mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE));
- var start = Math.round(this.startSize * this.scale);
-
- if (this.separator != null)
- {
- this.separator.coordsize = w + ',' + h;
- this.separator.style.left = x + 'px';
- this.separator.style.top = y + 'px';
- this.separator.style.width = w + 'px';
- this.separator.style.height = h + 'px';
- }
-
- if (mxUtils.getValue(this.style, mxConstants.STYLE_HORIZONTAL, true))
- {
- start = Math.min(start, this.bounds.height);
- this.label.style.height = start + 'px'; // relative
- this.updateVmlShape(this.content);
- this.content.style.background = '';
- this.content.style.top = start + 'px';
- this.content.style.left = '0px';
- this.content.style.height = Math.max(0, h - start)+'px';
-
- if (this.separator != null)
- {
- var d = 'm ' + (w - x) + ' ' + (start - y) +
- ' l ' + (w - x) + ' ' + (h - y) + ' e';
- this.separator.path = d;
- }
-
- if (this.imageNode != null)
- {
- var img = Math.round(this.imageSize*this.scale);
-
- this.imageNode.style.left = (w-img-4)+'px';
- this.imageNode.style.top = '0px';
- this.imageNode.style.width = img + 'px';
- this.imageNode.style.height = img + 'px';
- }
- }
- else
- {
- start = Math.min(start, this.bounds.width);
- this.label.style.width = start + 'px'; // relative
- this.updateVmlShape(this.content);
- this.content.style.background = '';
- this.content.style.top = '0px';
- this.content.style.left = start + 'px';
- this.content.style.width = Math.max(0, w - start) + 'px';
-
- if (this.separator != null)
- {
- var d = 'm ' + (start - x) + ' ' + (h - y) +
- ' l ' + (w - x) + ' ' + (h - y) + ' e';
- this.separator.path = d;
- }
-
- if (this.imageNode != null)
- {
- var img = Math.round(this.imageSize * this.scale);
-
- this.imageNode.style.left = (w - img - 4)+'px';
- this.imageNode.style.top = '0px';
- this.imageNode.style.width = img + 'px';
- this.imageNode.style.height = img + 'px';
- }
- }
-
- this.content.style.rotation = null;
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxSwimlane.prototype.createSvg = function()
-{
- var node = this.createSvgGroup('rect');
-
- if (this.isRounded)
- {
- this.innerNode.setAttribute('rx', 10);
- this.innerNode.setAttribute('ry', 10);
- }
-
- this.content = document.createElementNS(mxConstants.NS_SVG, 'path');
- this.configureSvgShape(this.content);
- this.content.setAttribute('fill', 'none');
-
- if (this.isRounded)
- {
- this.content.setAttribute('rx', 10);
- this.content.setAttribute('ry', 10);
- }
-
- node.appendChild(this.content);
- var color = this.style[mxConstants.STYLE_SEPARATORCOLOR];
-
- if (color != null)
- {
- this.separator = document.createElementNS(mxConstants.NS_SVG, 'line');
-
- this.separator.setAttribute('stroke', color);
- this.separator.setAttribute('fill', 'none');
- this.separator.setAttribute('stroke-dasharray', '2, 2');
-
- node.appendChild(this.separator);
- }
-
- if (this.image != null)
- {
- this.imageNode = document.createElementNS(mxConstants.NS_SVG, 'image');
-
- this.imageNode.setAttributeNS(mxConstants.NS_XLINK, 'href', this.image);
- this.configureSvgShape(this.imageNode);
-
- node.appendChild(this.imageNode);
- }
-
- return node;
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxSwimlane.prototype.redrawSvg = function()
-{
- var tmp = this.isRounded;
- this.isRounded = false;
-
- this.updateSvgShape(this.innerNode);
- this.updateSvgShape(this.content);
- var horizontal = mxUtils.getValue(this.style, mxConstants.STYLE_HORIZONTAL, true);
- this.startSize = parseInt(mxUtils.getValue(this.style,
- mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE));
- var ss = this.startSize * this.scale;
-
- // Updates the size of the shadow node
- if (this.shadowNode != null)
- {
- this.updateSvgShape(this.shadowNode);
-
- if (horizontal)
- {
- this.shadowNode.setAttribute('height', ss);
- }
- else
- {
- this.shadowNode.setAttribute('width', ss);
- }
- }
-
- this.isRounded = tmp;
-
- this.content.removeAttribute('x');
- this.content.removeAttribute('y');
- this.content.removeAttribute('width');
- this.content.removeAttribute('height');
-
- var crisp = (this.crisp && mxClient.IS_IE) ? 0.5 : 0;
- var x = Math.round(this.bounds.x) + crisp;
- var y = Math.round(this.bounds.y) + crisp;
- var w = Math.round(this.bounds.width);
- var h = Math.round(this.bounds.height);
-
- if (horizontal)
- {
- ss = Math.min(ss, h);
- this.innerNode.setAttribute('height', ss);
- var points = 'M ' + x + ' ' + (y + ss) +
- ' l 0 ' + (h - ss) + ' l ' + w + ' 0' +
- ' l 0 ' + (ss - h);
- this.content.setAttribute('d', points);
-
- if (this.separator != null)
- {
- this.separator.setAttribute('x1', x + w);
- this.separator.setAttribute('y1', y + ss);
- this.separator.setAttribute('x2', x + w);
- this.separator.setAttribute('y2', y + h);
- }
-
- if (this.imageNode != null)
- {
- this.imageNode.setAttribute('x', x + w - this.imageSize - 4);
- this.imageNode.setAttribute('y', y);
- this.imageNode.setAttribute('width', this.imageSize * this.scale + 'px');
- this.imageNode.setAttribute('height', this.imageSize * this.scale + 'px');
- }
- }
- else
- {
- ss = Math.min(ss, w);
- this.innerNode.setAttribute('width', ss);
- var points = 'M ' + (x + ss) + ' ' + y +
- ' l ' + (w - ss) + ' 0' + ' l 0 ' + h +
- ' l ' + (ss - w) + ' 0';
- this.content.setAttribute('d', points);
-
- if (this.separator != null)
- {
- this.separator.setAttribute('x1', x + ss);
- this.separator.setAttribute('y1', y + h);
- this.separator.setAttribute('x2', x + w);
- this.separator.setAttribute('y2', y + h);
- }
-
- if (this.imageNode != null)
- {
- this.imageNode.setAttribute('x', x + w - this.imageSize - 4);
- this.imageNode.setAttribute('y', y);
- this.imageNode.setAttribute('width', this.imageSize * this.scale + 'px');
- this.imageNode.setAttribute('height', this.imageSize * this.scale + 'px');
- }
- }
-};
diff --git a/src/js/shape/mxText.js b/src/js/shape/mxText.js
deleted file mode 100644
index de44b59..0000000
--- a/src/js/shape/mxText.js
+++ /dev/null
@@ -1,1811 +0,0 @@
-/**
- * $Id: mxText.js,v 1.174 2012-09-27 10:20:30 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxText
- *
- * Extends <mxShape> to implement a text shape. To change vertical text from
- * bottom to top to top to bottom, the following code can be used:
- *
- * (code)
- * mxText.prototype.ieVerticalFilter = 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)';
- * mxText.prototype.verticalTextDegree = 90;
- *
- * mxText.prototype.getVerticalOffset = function(offset)
- * {
- * return new mxPoint(-offset.y, offset.x);
- * };
- * (end)
- *
- * Constructor: mxText
- *
- * Constructs a new text shape.
- *
- * Parameters:
- *
- * value - String that represents the text to be displayed. This is stored in
- * <value>.
- * bounds - <mxRectangle> that defines the bounds. This is stored in
- * <mxShape.bounds>.
- * align - Specifies the horizontal alignment. Default is ''. This is stored in
- * <align>.
- * valign - Specifies the vertical alignment. Default is ''. This is stored in
- * <valign>.
- * color - String that specifies the text color. Default is 'black'. This is
- * stored in <color>.
- * family - String that specifies the font family. Default is
- * <mxConstants.DEFAULT_FONTFAMILY>. This is stored in <family>.
- * size - Integer that specifies the font size. Default is
- * <mxConstants.DEFAULT_FONTSIZE>. This is stored in <size>.
- * fontStyle - Specifies the font style. Default is 0. This is stored in
- * <fontStyle>.
- * spacing - Integer that specifies the global spacing. Default is 2. This is
- * stored in <spacing>.
- * spacingTop - Integer that specifies the top spacing. Default is 0. The
- * sum of the spacing and this is stored in <spacingTop>.
- * spacingRight - Integer that specifies the right spacing. Default is 0. The
- * sum of the spacing and this is stored in <spacingRight>.
- * spacingBottom - Integer that specifies the bottom spacing. Default is 0.The
- * sum of the spacing and this is stored in <spacingBottom>.
- * spacingLeft - Integer that specifies the left spacing. Default is 0. The
- * sum of the spacing and this is stored in <spacingLeft>.
- * horizontal - Boolean that specifies if the label is horizontal. Default is
- * true. This is stored in <horizontal>.
- * background - String that specifies the background color. Default is null.
- * This is stored in <background>.
- * border - String that specifies the label border color. Default is null.
- * This is stored in <border>.
- * wrap - Specifies if word-wrapping should be enabled. Default is false.
- * This is stored in <wrap>.
- * clipped - Specifies if the label should be clipped. Default is false.
- * This is stored in <clipped>.
- * overflow - Value of the overflow style. Default is 'visible'.
- */
-function mxText(value, bounds, align, valign, color,
- family, size, fontStyle, spacing, spacingTop, spacingRight,
- spacingBottom, spacingLeft, horizontal, background, border,
- wrap, clipped, overflow, labelPadding)
-{
- this.value = value;
- this.bounds = bounds;
- this.color = (color != null) ? color : 'black';
- this.align = (align != null) ? align : '';
- this.valign = (valign != null) ? valign : '';
- this.family = (family != null) ? family : mxConstants.DEFAULT_FONTFAMILY;
- this.size = (size != null) ? size : mxConstants.DEFAULT_FONTSIZE;
- this.fontStyle = (fontStyle != null) ? fontStyle : 0;
- this.spacing = parseInt(spacing || 2);
- this.spacingTop = this.spacing + parseInt(spacingTop || 0);
- this.spacingRight = this.spacing + parseInt(spacingRight || 0);
- this.spacingBottom = this.spacing + parseInt(spacingBottom || 0);
- this.spacingLeft = this.spacing + parseInt(spacingLeft || 0);
- this.horizontal = (horizontal != null) ? horizontal : true;
- this.background = background;
- this.border = border;
- this.wrap = (wrap != null) ? wrap : false;
- this.clipped = (clipped != null) ? clipped : false;
- this.overflow = (overflow != null) ? overflow : 'visible';
- this.labelPadding = (labelPadding != null) ? labelPadding : 0;
-};
-
-/**
- * Extends mxShape.
- */
-mxText.prototype = new mxShape();
-mxText.prototype.constructor = mxText;
-
-/**
- * Variable: replaceLinefeeds
- *
- * Specifies if linefeeds in HTML labels should be replaced with BR tags.
- * Default is true. This is also used in <mxImageExport> to export the label.
- */
-mxText.prototype.replaceLinefeeds = true;
-
-/**
- * Variable: ieVerticalFilter
- *
- * Holds the filter definition for vertical text in IE. Default is
- * progid:DXImageTransform.Microsoft.BasicImage(rotation=3).
- */
-mxText.prototype.ieVerticalFilter = 'progid:DXImageTransform.Microsoft.BasicImage(rotation=3)';
-
-/**
- * Variable: verticalTextDegree
- *
- * Specifies the degree to be used for vertical text. Default is -90.
- */
-mxText.prototype.verticalTextDegree = -90;
-
-/**
- * Variable: forceIgnoreStringSize
- *
- * Specifies if the string size should always be ignored. Default is false.
- * This can be used to improve rendering speed in slow browsers. This can be
- * used if all labels are smaller than the vertex width. String sizes are
- * ignored by default for labels which are left aligned with no background and
- * border or if the overflow is set to fill.
- */
-mxText.prototype.forceIgnoreStringSize = false;
-
-/**
- * Function: isStyleSet
- *
- * Returns true if the given font style (bold, italic etc)
- * is true in this shape's fontStyle.
- *
- * Parameters:
- *
- * style - Fontstyle constant from <mxConstants>.
- */
-mxText.prototype.isStyleSet = function(style)
-{
- return (this.fontStyle & style) == style;
-};
-
-/**
- * Function: create
- *
- * Override to create HTML regardless of gradient and
- * rounded property.
- */
-mxText.prototype.create = function(container)
-{
- var node = null;
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- node = this.createSvg();
- }
- else if (this.dialect == mxConstants.DIALECT_STRICTHTML ||
- this.dialect == mxConstants.DIALECT_PREFERHTML ||
- !mxUtils.isVml(container))
- {
- if (mxClient.IS_SVG && !mxClient.NO_FO)
- {
- node = this.createForeignObject();
- }
- else
- {
- node = this.createHtml();
- }
- }
- else
- {
- node = this.createVml();
- }
-
- return node;
-};
-
-/**
- * Function: updateBoundingBox
- *
- * Overrides method to do nothing.
- */
-mxText.prototype.updateBoundingBox = function()
-{
- // do nothing
-};
-
-/**
- * Function: createForeignObject
- *
- * Creates and returns the foreignObject node to represent this shape.
- */
-mxText.prototype.createForeignObject = function()
-{
- var node = document.createElementNS(mxConstants.NS_SVG, 'g');
-
- var fo = document.createElementNS(mxConstants.NS_SVG, 'foreignObject');
- fo.setAttribute('pointer-events', 'fill');
-
- // Ignored in FF
- if (this.overflow == 'hidden')
- {
- fo.style.overflow = 'hidden';
- }
- else
- {
- // Fill and default are visible
- fo.style.overflow = 'visible';
- }
-
- var body = document.createElement('div');
- body.style.margin = '0px';
- body.style.height = '100%';
-
- fo.appendChild(body);
- node.appendChild(fo);
-
- return node;
-};
-
-/**
- * Function: createHtml
- *
- * Creates and returns the HTML node to represent this shape.
- */
-mxText.prototype.createHtml = function()
-{
- var table = this.createHtmlTable();
- table.style.position = 'absolute';
-
- return table;
-};
-
-/**
- * Function: createVml
- *
- * Creates and returns the VML node(s) to represent this shape.
- */
-mxText.prototype.createVml = function()
-{
- return document.createElement('v:textbox');
-};
-
-/**
- * Function: redrawHtml
- *
- * Updates the HTML node(s) to reflect the latest bounds and scale.
- */
-mxText.prototype.redrawHtml = function()
-{
- this.redrawVml();
-};
-
-/**
- * Function: getOffset
- *
- * Returns the description of the space between the <bounds> size and the label
- * size as an <mxPoint>.
- */
-mxText.prototype.getOffset = function(outerWidth, outerHeight, actualWidth, actualHeight, horizontal)
-{
- horizontal = (horizontal != null) ? horizontal : this.horizontal;
-
- var tmpalign = (horizontal) ? this.align : this.valign;
- var tmpvalign = (horizontal) ? this.valign : this.align;
- var dx = actualWidth - outerWidth;
- var dy = actualHeight - outerHeight;
-
- if (tmpalign == mxConstants.ALIGN_CENTER || tmpalign == mxConstants.ALIGN_MIDDLE)
- {
- dx = Math.round(dx / 2);
- }
- else if (tmpalign == mxConstants.ALIGN_LEFT || tmpalign === mxConstants.ALIGN_TOP)
- {
- dx = (horizontal) ? 0 : (actualWidth - actualHeight) / 2;
- }
- else if (!horizontal) // BOTTOM
- {
- dx = (actualWidth + actualHeight) / 2 - outerWidth;
- }
-
- if (tmpvalign == mxConstants.ALIGN_MIDDLE || tmpvalign == mxConstants.ALIGN_CENTER)
- {
- dy = Math.round(dy / 2);
- }
- else if (tmpvalign == mxConstants.ALIGN_TOP || tmpvalign == mxConstants.ALIGN_LEFT)
- {
- dy = (horizontal) ? 0 : (actualHeight + actualWidth) / 2 - outerHeight;
- }
- else if (!horizontal) // RIGHT
- {
- dy = (actualHeight - actualWidth) / 2;
- }
-
- return new mxPoint(dx, dy);
-};
-
-/**
- * Function: getSpacing
- *
- * Returns the spacing as an <mxPoint>.
- */
-mxText.prototype.getSpacing = function(horizontal)
-{
- horizontal = (horizontal != null) ? horizontal : this.horizontal;
-
- var dx = 0;
- var dy = 0;
-
- if (this.align == mxConstants.ALIGN_CENTER)
- {
- dx = (this.spacingLeft - this.spacingRight) / 2;
- }
- else if (this.align == mxConstants.ALIGN_RIGHT)
- {
- dx = -this.spacingRight;
- }
- else
- {
- dx = this.spacingLeft;
- }
-
- if (this.valign == mxConstants.ALIGN_MIDDLE)
- {
- dy = (this.spacingTop - this.spacingBottom) / 2;
- }
- else if (this.valign == mxConstants.ALIGN_BOTTOM)
- {
- dy = -this.spacingBottom;
- }
- else
- {
- dy = this.spacingTop;
- }
-
- return (horizontal) ? new mxPoint(dx, dy) : new mxPoint(dy, dx);
-};
-
-/**
- * Function: createHtmlTable
- *
- * Creates and returns a HTML table with a table body and a single row with a
- * single cell.
- */
-mxText.prototype.createHtmlTable = function()
-{
- var table = document.createElement('table');
- table.style.borderCollapse = 'collapse';
- var tbody = document.createElement('tbody');
- var tr = document.createElement('tr');
- var td = document.createElement('td');
-
- // Workaround for ignored table height in IE9 standards mode
- if (document.documentMode >= 9)
- {
- // FIXME: Ignored in print preview for IE9 standards mode
- td.style.height = '100%';
- }
-
- tr.appendChild(td);
- tbody.appendChild(tr);
- table.appendChild(tbody);
-
- return table;
-};
-
-/**
- * Function: updateTableStyle
- *
- * Updates the style of the given HTML table and the value
- * within the table.
- */
-mxText.prototype.updateHtmlTable = function(table, scale)
-{
- scale = (scale != null) ? scale : 1;
- var td = table.firstChild.firstChild.firstChild;
-
- // Reset of width required to measure actual width after word wrap
- if (this.wrap)
- {
- table.style.width = '';
- }
-
- // Updates the value
- if (mxUtils.isNode(this.value))
- {
- if (td.firstChild != this.value)
- {
- if (td.firstChild != null)
- {
- td.removeChild(td.firstChild);
- }
-
- td.appendChild(this.value);
- }
- }
- else
- {
- if (this.lastValue != this.value)
- {
- td.innerHTML = (this.replaceLinefeeds) ? this.value.replace(/\n/g, '<br/>') : this.value;
- this.lastValue = this.value;
- }
- }
-
- // Font style
- var fontSize = Math.round(this.size * scale);
-
- if (fontSize <= 0)
- {
- table.style.visibility = 'hidden';
- }
- else
- {
- // Do not use visible here as it will clone
- // all labels while panning in IE
- table.style.visibility = '';
- }
-
- table.style.fontSize = fontSize + 'px';
- table.style.color = this.color;
- table.style.fontFamily = this.family;
-
- // Bold
- if (this.isStyleSet(mxConstants.FONT_BOLD))
- {
- table.style.fontWeight = 'bold';
- }
- else
- {
- table.style.fontWeight = 'normal';
- }
-
- // Italic
- if (this.isStyleSet(mxConstants.FONT_ITALIC))
- {
- table.style.fontStyle = 'italic';
- }
- else
- {
- table.style.fontStyle = '';
- }
-
- // Underline
- if (this.isStyleSet(mxConstants.FONT_UNDERLINE))
- {
- table.style.textDecoration = 'underline';
- }
- else
- {
- table.style.textDecoration = '';
- }
-
- // Font shadow (only available in IE)
- if (mxClient.IS_IE)
- {
- if (this.isStyleSet(mxConstants.FONT_SHADOW))
- {
- td.style.filter = 'Shadow(Color=#666666,'+'Direction=135,Strength=%)';
- }
- else
- {
- td.style.removeAttribute('filter');
- }
- }
-
- // Horizontal and vertical alignment
- td.style.textAlign =
- (this.align == mxConstants.ALIGN_RIGHT) ? 'right' :
- ((this.align == mxConstants.ALIGN_CENTER) ? 'center' :
- 'left');
- td.style.verticalAlign =
- (this.valign == mxConstants.ALIGN_BOTTOM) ? 'bottom' :
- ((this.valign == mxConstants.ALIGN_MIDDLE) ? 'middle' :
- 'top');
-
- // Background style (Must use TD not TABLE for Firefox when rotated)
- if (this.value.length > 0 && this.background != null)
- {
- td.style.background = this.background;
- }
- else
- {
- td.style.background = '';
- }
-
- td.style.padding = this.labelPadding + 'px';
-
- if (this.value.length > 0 && this.border != null)
- {
- table.style.borderColor = this.border;
- table.style.borderWidth = '1px';
- table.style.borderStyle = 'solid';
- }
- else
- {
- table.style.borderStyle = 'none';
- }
-};
-
-/**
- * Function: getTableSize
- *
- * Returns the actual size of the table.
- */
-mxText.prototype.getTableSize = function(table)
-{
- return new mxRectangle(0, 0, table.offsetWidth, table.offsetHeight);
-};
-
-/**
- * Function: updateTableWidth
- *
- * Updates the width of the given HTML table.
- */
-mxText.prototype.updateTableWidth = function(table)
-{
- var td = table.firstChild.firstChild.firstChild;
-
- // Word-wrap for vertices (not edges) and only if not
- // just getting the bounding box in SVG
- if (this.wrap && this.bounds.width > 0 && this.dialect != mxConstants.DIALECT_SVG)
- {
- // Makes sure the label is not wrapped when measuring full length
- td.style.whiteSpace = 'nowrap';
- var size = this.getTableSize(table);
- var space = Math.min(size.width, ((this.horizontal || mxUtils.isVml(this.node)) ?
- this.bounds.width : this.bounds.height) / this.scale);
-
- // Opera needs the new width to be scaled
- if (mxClient.IS_OP)
- {
- space *= this.scale;
- }
-
- table.style.width = Math.round(space) + 'px';
- td.style.whiteSpace = 'normal';
- }
- else
- {
- table.style.width = '';
- }
-
- if (!this.wrap)
- {
- td.style.whiteSpace = 'nowrap';
- }
- else
- {
- td.style.whiteSpace = 'normal';
- }
-};
-
-/**
- * Function: redrawVml
- *
- * Updates the VML node(s) to reflect the latest bounds and scale.
- */
-mxText.prototype.redrawVml = function()
-{
- if (this.node.nodeName == 'g')
- {
- this.redrawForeignObject();
- }
- else if (mxUtils.isVml(this.node))
- {
- this.redrawTextbox();
- }
- else
- {
- this.redrawHtmlTable();
- }
-};
-
-/**
- * Function: redrawTextbox
- *
- * Redraws the textbox for this text. This is only used in IE in exact
- * rendering mode.
- */
-mxText.prototype.redrawTextbox = function()
-{
- // Gets VML textbox
- var textbox = this.node;
-
- // Creates HTML container on the fly
- if (textbox.firstChild == null)
- {
- textbox.appendChild(this.createHtmlTable());
- }
-
- // Updates the table style and value
- var table = textbox.firstChild;
- this.updateHtmlTable(table);
- this.updateTableWidth(table);
-
- // Opacity
- if (this.opacity != null)
- {
- mxUtils.setOpacity(table, this.opacity);
- }
-
- table.style.filter = '';
- textbox.inset = '0px,0px,0px,0px';
-
- if (this.overflow != 'fill')
- {
- // Only tables can be used to work out the actual size of the markup
- var size = this.getTableSize(table);
- var w = size.width * this.scale;
- var h = size.height * this.scale;
- var offset = this.getOffset(this.bounds.width, this.bounds.height, w, h);
-
- // Rotates the label (IE only)
- if (!this.horizontal)
- {
- table.style.filter = this.ieVerticalFilter;
- }
-
- // Adds horizontal/vertical spacing
- var spacing = this.getSpacing();
- var x = this.bounds.x - offset.x + spacing.x * this.scale;
- var y = this.bounds.y - offset.y + spacing.y * this.scale;
-
- // Textboxes are always relative to their parent shape's top, left corner so
- // we use the inset for absolute positioning as they allow negative values
- // except for edges where the bounds are used to find the shape center
- var x0 = this.bounds.x;
- var y0 = this.bounds.y;
- var ow = this.bounds.width;
- var oh = this.bounds.height;
-
- // Insets are given as left, top, right, bottom
- if (this.horizontal)
- {
- var tx = Math.round(x - x0);
- var ty = Math.round(y - y0);
-
- var r = Math.min(0, Math.round(x0 + ow - x - w - 1));
- var b = Math.min(0, Math.round(y0 + oh - y - h - 1));
- textbox.inset = tx + 'px,' + ty + 'px,' + r + 'px,' + b + 'px';
- }
- else
- {
- var t = 0;
- var l = 0;
- var r = 0;
- var b = 0;
-
- if (this.align == mxConstants.ALIGN_CENTER)
- {
- t = (oh - w) / 2;
- b = t;
- }
- else if (this.align == mxConstants.ALIGN_LEFT)
- {
- t = oh - w;
- }
- else
- {
- b = oh - w;
- }
-
- if (this.valign == mxConstants.ALIGN_MIDDLE)
- {
- l = (ow - h) / 2;
- r = l;
- }
- else if (this.valign == mxConstants.ALIGN_BOTTOM)
- {
- l = ow - h;
- }
- else
- {
- r = ow - h;
- }
-
- textbox.inset = l + 'px,' + t + 'px,' + r + 'px,' + b + 'px';
- }
-
- textbox.style.zoom = this.scale;
-
- // Clipping
- if (this.clipped && this.bounds.width > 0 && this.bounds.height > 0)
- {
- this.boundingBox = this.bounds.clone();
- var dx = Math.round(x0 - x);
- var dy = Math.round(y0 - y);
-
- textbox.style.clip = 'rect(' + (dy / this.scale) + ' ' +
- ((dx + this.bounds.width) / this.scale) + ' ' +
- ((dy + this.bounds.height) / this.scale) + ' ' +
- (dx / this.scale) + ')';
- }
- else
- {
- this.boundingBox = new mxRectangle(x, y, w, h);
- }
- }
- else
- {
- this.boundingBox = this.bounds.clone();
- }
-};
-
-/**
- * Function: redrawHtmlTable
- *
- * Redraws the HTML table. This is used for HTML labels in all modes except
- * exact in IE and if NO_FO is false for the browser.
- */
-mxText.prototype.redrawHtmlTable = function()
-{
- if (isNaN(this.bounds.x) || isNaN(this.bounds.y) ||
- isNaN(this.bounds.width) || isNaN(this.bounds.height))
- {
- return;
- }
-
- // Gets table
- var table = this.node;
- var td = table.firstChild.firstChild.firstChild;
-
- // Un-rotates for computing the actual size
- // TODO: Check if the result can be tweaked instead in getActualSize
- // and only do this if actual rotation did change
- var oldBrowser = false;
- var fallbackScale = 1;
-
- if (mxClient.IS_IE)
- {
- table.style.removeAttribute('filter');
- }
- else if (mxClient.IS_SF || mxClient.IS_GC)
- {
- table.style.WebkitTransform = '';
- }
- else if (mxClient.IS_MT)
- {
- table.style.MozTransform = '';
- td.style.MozTransform = '';
- }
- else
- {
- if (mxClient.IS_OT)
- {
- table.style.OTransform = '';
- }
-
- fallbackScale = this.scale;
- oldBrowser = true;
- }
-
- // Resets the current zoom for text measuring
- td.style.zoom = '';
-
- // Updates the table style and value
- this.updateHtmlTable(table, fallbackScale);
- this.updateTableWidth(table);
-
- // Opacity
- if (this.opacity != null)
- {
- mxUtils.setOpacity(table, this.opacity);
- }
-
- // Resets the bounds for computing the actual size
- table.style.left = '';
- table.style.top = '';
- table.style.height = '';
-
- // Workaround for multiple zoom even if CSS style is reset here
- var currentZoom = parseFloat(td.style.zoom) || 1;
-
- // Only tables can be used to work out the actual size of the markup
- // NOTE: offsetWidth and offsetHeight are very slow in quirks and IE 8 standards mode
- var w = this.bounds.width;
- var h = this.bounds.height;
-
- var ignoreStringSize = this.forceIgnoreStringSize || this.overflow == 'fill' ||
- (this.align == mxConstants.ALIGN_LEFT && this.background == null && this.border == null);
-
- if (!ignoreStringSize)
- {
- var size = this.getTableSize(table);
- w = size.width / currentZoom;
- h = size.height / currentZoom;
- }
-
- var offset = this.getOffset(this.bounds.width / this.scale,
- this.bounds.height / this.scale, w, h,
- oldBrowser || this.horizontal);
-
- // Adds horizontal/vertical spacing
- var spacing = this.getSpacing(oldBrowser || this.horizontal);
- var x = this.bounds.x / this.scale - offset.x + spacing.x;
- var y = this.bounds.y / this.scale - offset.y + spacing.y;
-
- // Updates the table bounds and stores the scale to be used for
- // defining the table width and height, as well as an offset
- var s = this.scale;
- var s2 = 1;
- var shiftX = 0;
- var shiftY = 0;
-
- // Rotates the label and adds offset
- if (!this.horizontal)
- {
- if (mxClient.IS_IE && mxClient.IS_SVG)
- {
- table.style.msTransform = 'rotate(' + this.verticalTextDegree + 'deg)';
- }
- else if (mxClient.IS_IE)
- {
- table.style.filter = this.ieVerticalFilter;
- shiftX = (w - h) / 2;
- shiftY = -shiftX;
- }
- else if (mxClient.IS_SF || mxClient.IS_GC)
- {
- table.style.WebkitTransform = 'rotate(' + this.verticalTextDegree + 'deg)';
- }
- else if (mxClient.IS_OT)
- {
- table.style.OTransform = 'rotate(' + this.verticalTextDegree + 'deg)';
- }
- else if (mxClient.IS_MT)
- {
- // Firefox paints background and border only if background is on TD
- // and border is on TABLE and both are rotated, just the TD with a
- // rotation of zero (don't remove the 0-rotate CSS style)
- table.style.MozTransform = 'rotate(' + this.verticalTextDegree + 'deg)';
- td.style.MozTransform = 'rotate(0deg)';
-
- s2 = 1 / this.scale;
- s = 1;
- }
- }
-
- // Sets the zoom
- var correction = true;
-
- if (mxClient.IS_MT || oldBrowser)
- {
- if (mxClient.IS_MT)
- {
- table.style.MozTransform += ' scale(' + this.scale + ')';
- s2 = 1 / this.scale;
- }
- else if (mxClient.IS_OT)
- {
- td.style.OTransform = 'scale(' + this.scale + ')';
- table.style.borderWidth = Math.round(this.scale * parseInt(table.style.borderWidth)) + 'px';
- }
- }
- else if (!oldBrowser)
- {
- // Workaround for unsupported zoom CSS in IE9 standards mode
- if (document.documentMode >= 9)
- {
- td.style.msTransform = 'scale(' + this.scale + ')';
- }
- // Uses transform in Webkit for better HTML scaling
- else if (mxClient.IS_SF || mxClient.IS_GC)
- {
- td.style.WebkitTransform = 'scale(' + this.scale + ')';
- }
- else
- {
- td.style.zoom = this.scale;
-
- // Fixes scaling of border width
- if (table.style.borderWidth != '' && document.documentMode != 8)
- {
- table.style.borderWidth = Math.round(this.scale * parseInt(table.style.borderWidth)) + 'px';
- }
-
- // Workaround for wrong scale in IE8 standards mode
- if (document.documentMode == 8 || !mxClient.IS_IE)
- {
- s = 1;
- }
-
- correction = false;
- }
- }
-
- if (correction)
- {
- // Workaround for scaled TD position
- shiftX = (this.scale - 1) * w / (2 * this.scale);
- shiftY = (this.scale - 1) * h / (2 * this.scale);
- s = 1;
- }
-
- if (this.overflow != 'fill')
- {
- var rect = new mxRectangle(Math.round((x + shiftX) * this.scale),
- Math.round((y + shiftY) * this.scale), Math.round(w * s), Math.round(h * s));
- table.style.left = rect.x + 'px';
- table.style.top = rect.y + 'px';
- table.style.width = rect.width + 'px';
- table.style.height = rect.height + 'px';
-
- // Workaround for wrong scale in border and background rendering for table and td in IE8/9 standards mode
- if ((this.background != null || this.border != null) && document.documentMode >= 8)
- {
- var html = (this.replaceLinefeeds) ? this.value.replace(/\n/g, '<br/>') : this.value;
- td.innerHTML = '<div style="padding:' + this.labelPadding + 'px;background:' + td.style.background + ';border:' + table.style.border + '">' + html + '</div>';
- td.style.padding = '0px';
- td.style.background = '';
- table.style.border = '';
- }
-
- // Clipping
- if (this.clipped && this.bounds.width > 0 && this.bounds.height > 0)
- {
- this.boundingBox = this.bounds.clone();
-
- // Clipping without rotation or for older browsers
- if (this.horizontal || (oldBrowser && !mxClient.IS_OT))
- {
- var dx = Math.max(0, offset.x * s);
- var dy = Math.max(0, offset.y * s);
-
- // TODO: Fix clipping for Opera
- table.style.clip = 'rect(' + (dy) + 'px ' + (dx + this.bounds.width * s2) +
- 'px ' + (dy + this.bounds.height * s2) + 'px ' + (dx) + 'px)';
- }
- else
- {
- // Workaround for IE clip using top, right, bottom, left (un-rotated)
- if (mxClient.IS_IE)
- {
- var uw = this.bounds.width;
- var uh = this.bounds.height;
- var dx = 0;
- var dy = 0;
-
- if (this.align == mxConstants.ALIGN_LEFT)
- {
- dx = Math.max(0, w - uh / this.scale) * this.scale;
- }
- else if (this.align == mxConstants.ALIGN_CENTER)
- {
- dx = Math.max(0, w - uh / this.scale) * this.scale / 2;
- }
-
- if (this.valign == mxConstants.ALIGN_BOTTOM)
- {
- dy = Math.max(0, h - uw / this.scale) * this.scale;
- }
- else if (this.valign == mxConstants.ALIGN_MIDDLE)
- {
- dy = Math.max(0, h - uw / this.scale) * this.scale / 2;
- }
-
- table.style.clip = 'rect(' + (dx) + 'px ' + (dy + uw - 1) +
- 'px ' + (dx + uh - 1) + 'px ' + (dy) + 'px)';
- }
- else
- {
- var uw = this.bounds.width / this.scale;
- var uh = this.bounds.height / this.scale;
-
- if (mxClient.IS_OT)
- {
- uw = this.bounds.width;
- uh = this.bounds.height;
- }
-
- var dx = 0;
- var dy = 0;
-
- if (this.align == mxConstants.ALIGN_RIGHT)
- {
- dx = Math.max(0, w - uh);
- }
- else if (this.align == mxConstants.ALIGN_CENTER)
- {
- dx = Math.max(0, w - uh) / 2;
- }
-
- if (this.valign == mxConstants.ALIGN_BOTTOM)
- {
- dy = Math.max(0, h - uw);
- }
- else if (this.valign == mxConstants.ALIGN_MIDDLE)
- {
- dy = Math.max(0, h - uw) / 2;
- }
-
- if (mxClient.IS_GC || mxClient.IS_SF)
- {
- dx *= this.scale;
- dy *= this.scale;
- uw *= this.scale;
- uh *= this.scale;
- }
-
- table.style.clip = 'rect(' + (dy) + ' ' + (dx + uh) +
- ' ' + (dy + uw) + ' ' + (dx) + ')';
- }
- }
- }
- else
- {
- this.boundingBox = rect;
- }
- }
- else
- {
- this.boundingBox = this.bounds.clone();
-
- if (document.documentMode >= 9 || mxClient.IS_SVG)
- {
- table.style.left = Math.round(this.bounds.x + this.scale / 2 + shiftX) + 'px';
- table.style.top = Math.round(this.bounds.y + this.scale / 2 + shiftY) + 'px';
- table.style.width = Math.round((this.bounds.width - this.scale) / this.scale) + 'px';
- table.style.height = Math.round((this.bounds.height - this.scale) / this.scale) + 'px';
- }
- else
- {
- s = (document.documentMode == 8) ? this.scale : 1;
- table.style.left = Math.round(this.bounds.x + this.scale / 2) + 'px';
- table.style.top = Math.round(this.bounds.y + this.scale / 2) + 'px';
- table.style.width = Math.round((this.bounds.width - this.scale) / s) + 'px';
- table.style.height = Math.round((this.bounds.height - this.scale) / s) + 'px';
- }
- }
-};
-
-/**
- * Function: getVerticalOffset
- *
- * Returns the factors for the offset to be added to the text vertical
- * text rotation. This implementation returns (offset.y, -offset.x).
- */
-mxText.prototype.getVerticalOffset = function(offset)
-{
- return new mxPoint(offset.y, -offset.x);
-};
-
-/**
- * Function: redrawForeignObject
- *
- * Redraws the foreign object for this text.
- */
-mxText.prototype.redrawForeignObject = function()
-{
- // Gets SVG group with foreignObject
- var group = this.node;
- var fo = group.firstChild;
-
- // Searches the table which appears behind the background
- while (fo == this.backgroundNode)
- {
- fo = fo.nextSibling;
- }
-
- var body = fo.firstChild;
-
- // Creates HTML container on the fly
- if (body.firstChild == null)
- {
- body.appendChild(this.createHtmlTable());
- }
-
- // Updates the table style and value
- var table = body.firstChild;
- this.updateHtmlTable(table);
-
- // Workaround for bug in Google Chrome where the text is moved to origin if opacity
- // is set on the table, so we set the opacity on the foreignObject instead.
- if (this.opacity != null)
- {
- fo.setAttribute('opacity', this.opacity / 100);
- }
-
- // Workaround for table background not appearing above the shape that is
- // behind the label in Safari. To solve this, we add a background rect that
- // paints the background instead.
- if (mxClient.IS_SF)
- {
- table.style.borderStyle = 'none';
- table.firstChild.firstChild.firstChild.style.background = '';
-
- if (this.backgroundNode == null && (this.background != null || this.border != null))
- {
- this.backgroundNode = document.createElementNS(mxConstants.NS_SVG, 'rect');
- group.insertBefore(this.backgroundNode, group.firstChild);
- }
- else if (this.backgroundNode != null && this.background == null && this.border == null)
- {
- this.backgroundNode.parentNode.removeChild(this.backgroundNode);
- this.backgroundNode = null;
- }
-
- if (this.backgroundNode != null)
- {
- if (this.background != null)
- {
- this.backgroundNode.setAttribute('fill', this.background);
- }
- else
- {
- this.backgroundNode.setAttribute('fill', 'none');
- }
-
- if (this.border != null)
- {
- this.backgroundNode.setAttribute('stroke', this.border);
- }
- else
- {
- this.backgroundNode.setAttribute('stroke', 'none');
- }
- }
- }
-
- var tr = '';
-
- if (this.overflow != 'fill')
- {
- // Resets the bounds for computing the actual size
- fo.removeAttribute('width');
- fo.removeAttribute('height');
- fo.style.width = '';
- fo.style.height = '';
- fo.style.clip = '';
-
- // Workaround for size of table not updated if inside foreignObject
- if (this.wrap || (!mxClient.IS_GC && !mxClient.IS_SF))
- {
- document.body.appendChild(table);
- }
-
- this.updateTableWidth(table);
-
- // Only tables can be used to work out the actual size of the markup
- var size = this.getTableSize(table);
- var w = size.width;
- var h = size.height;
-
- if (table.parentNode != body)
- {
- body.appendChild(table);
- }
-
- // Adds horizontal/vertical spacing
- var spacing = this.getSpacing();
-
- var x = this.bounds.x / this.scale + spacing.x;
- var y = this.bounds.y / this.scale + spacing.y;
- var uw = this.bounds.width / this.scale;
- var uh = this.bounds.height / this.scale;
- var offset = this.getOffset(uw, uh, w, h);
-
- // Rotates the label and adds offset
- if (this.horizontal)
- {
- x -= offset.x;
- y -= offset.y;
-
- tr = 'scale(' + this.scale + ')';
- }
- else
- {
- var x0 = x + w / 2;
- var y0 = y + h / 2;
-
- tr = 'scale(' + this.scale + ') rotate(' + this.verticalTextDegree + ' ' + x0 + ' ' + y0 + ')';
-
- var tmp = this.getVerticalOffset(offset);
- x += tmp.x;
- y += tmp.y;
- }
-
- // Must use translate instead of x- and y-attribute on FO for iOS
- tr += ' translate(' + x + ' ' + y + ')';
-
- // Updates the bounds of the background node in Webkit
- if (this.backgroundNode != null)
- {
- this.backgroundNode.setAttribute('width', w);
- this.backgroundNode.setAttribute('height', h);
- }
-
- // Updates the foreignObject size
- fo.setAttribute('width', w);
- fo.setAttribute('height', h);
-
- // Clipping
- // TODO: Fix/check clipping for foreignObjects in Chrome 5.0 - if clipPath
- // is used in the group then things can no longer be moved around
- if (this.clipped && this.bounds.width > 0 && this.bounds.height > 0)
- {
- this.boundingBox = this.bounds.clone();
- var dx = Math.max(0, offset.x);
- var dy = Math.max(0, offset.y);
-
- if (this.horizontal)
- {
- fo.style.clip = 'rect(' + dy + 'px,' + (dx + uw) +
- 'px,' + (dy + uh) + 'px,' + (dx) + 'px)';
- }
- else
- {
- var dx = 0;
- var dy = 0;
-
- if (this.align == mxConstants.ALIGN_RIGHT)
- {
- dx = Math.max(0, w - uh);
- }
- else if (this.align == mxConstants.ALIGN_CENTER)
- {
- dx = Math.max(0, w - uh) / 2;
- }
-
- if (this.valign == mxConstants.ALIGN_BOTTOM)
- {
- dy = Math.max(0, h - uw);
- }
- else if (this.valign == mxConstants.ALIGN_MIDDLE)
- {
- dy = Math.max(0, h - uw) / 2;
- }
-
- fo.style.clip = 'rect(' + (dy) + 'px,' + (dx + uh) +
- 'px,' + (dy + uw) + 'px,' + (dx) + 'px)';
- }
-
- // Clipping for the background node in Chrome
- if (this.backgroundNode != null)
- {
- x = this.bounds.x / this.scale;
- y = this.bounds.y / this.scale;
-
- if (!this.horizontal)
- {
- x += (h + w) / 2 - uh;
- y += (h - w) / 2;
-
- var tmp = uw;
- uw = uh;
- uh = tmp;
- }
-
- // No clipping in Chome available due to bug
- if (!mxClient.IS_GC)
- {
- var clip = this.getSvgClip(this.node.ownerSVGElement, x, y, uw, uh);
-
- if (clip != this.clip)
- {
- this.releaseSvgClip();
- this.clip = clip;
- clip.refCount++;
- }
-
- this.backgroundNode.setAttribute('clip-path', 'url(#' + clip.getAttribute('id') + ')');
- }
- }
- }
- else
- {
- // Removes clipping from background and cleans up the clip
- this.releaseSvgClip();
-
- if (this.backgroundNode != null)
- {
- this.backgroundNode.removeAttribute('clip-path');
- }
-
- if (this.horizontal)
- {
- this.boundingBox = new mxRectangle(x * this.scale, y * this.scale, w * this.scale, h * this.scale);
- }
- else
- {
- this.boundingBox = new mxRectangle(x * this.scale, y * this.scale, h * this.scale, w * this.scale);
- }
- }
- }
- else
- {
- this.boundingBox = this.bounds.clone();
-
- var s = this.scale;
- var w = this.bounds.width / s;
- var h = this.bounds.height / s;
-
- // Updates the foreignObject and table bounds
- fo.setAttribute('width', w);
- fo.setAttribute('height', h);
- table.style.width = w + 'px';
- table.style.height = h + 'px';
-
- // Updates the bounds of the background node in Webkit
- if (this.backgroundNode != null)
- {
- this.backgroundNode.setAttribute('width', table.clientWidth);
- this.backgroundNode.setAttribute('height', table.offsetHeight);
- }
-
- // Must use translate instead of x- and y-attribute on FO for iOS
- tr = 'scale(' + s + ') translate(' + (this.bounds.x / s) +
- ' ' + (this.bounds.y / s) + ')';
-
- if (!this.wrap)
- {
- var td = table.firstChild.firstChild.firstChild;
- td.style.whiteSpace = 'nowrap';
- }
- }
-
- group.setAttribute('transform', tr);
-};
-
-/**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
-mxText.prototype.createSvg = function()
-{
- // Creates a group so that shapes inside are rendered properly, if this is
- // a text node then the background rectangle is not rendered in Webkit.
- var node = document.createElementNS(mxConstants.NS_SVG, 'g');
-
- var uline = this.isStyleSet(mxConstants.FONT_UNDERLINE) ? 'underline' : 'none';
- var weight = this.isStyleSet(mxConstants.FONT_BOLD) ? 'bold' : 'normal';
- var s = this.isStyleSet(mxConstants.FONT_ITALIC) ? 'italic' : null;
-
- // Underline is not implemented in FF, see
- // https://bugzilla.mozilla.org/show_bug.cgi?id=317196
- node.setAttribute('text-decoration', uline);
- node.setAttribute('font-family', this.family);
- node.setAttribute('font-weight', weight);
- node.setAttribute('font-size', Math.round(this.size * this.scale) + 'px');
- node.setAttribute('fill', this.color);
- var align = (this.align == mxConstants.ALIGN_RIGHT) ? 'end' :
- (this.align == mxConstants.ALIGN_CENTER) ? 'middle' :
- 'start';
- node.setAttribute('text-anchor', align);
-
- if (s != null)
- {
- node.setAttribute('font-style', s);
- }
-
- // Adds a rectangle for the background color
- if (this.background != null || this.border != null)
- {
- this.backgroundNode = document.createElementNS(mxConstants.NS_SVG, 'rect');
- this.backgroundNode.setAttribute('shape-rendering', 'crispEdges');
-
- if (this.background != null)
- {
- this.backgroundNode.setAttribute('fill', this.background);
- }
- else
- {
- this.backgroundNode.setAttribute('fill', 'none');
- }
-
- if (this.border != null)
- {
- this.backgroundNode.setAttribute('stroke', this.border);
- }
- else
- {
- this.backgroundNode.setAttribute('stroke', 'none');
- }
- }
-
- this.updateSvgValue(node);
-
- return node;
-};
-
-/**
- * Updates the text represented by the SVG DOM nodes.
- */
-mxText.prototype.updateSvgValue = function(node)
-{
- if (this.currentValue != this.value)
- {
- // Removes all existing children
- while (node.firstChild != null)
- {
- node.removeChild(node.firstChild);
- }
-
- if (this.value != null)
- {
- // Adds tspan elements for the lines
- var uline = this.isStyleSet(mxConstants.FONT_UNDERLINE) ? 'underline' : 'none';
- var lines = this.value.split('\n');
-
- // Workaround for empty lines breaking the return value of getBBox
- // for the enclosing g element so we avoid adding empty lines
- // but still count them as a linefeed
- this.textNodes = new Array(lines.length);
-
- for (var i = 0; i < lines.length; i++)
- {
- if (!this.isEmptyString(lines[i]))
- {
- var tspan = this.createSvgSpan(lines[i]);
- node.appendChild(tspan);
- this.textNodes[i] = tspan;
-
- // Requires either 'inherit' in Webkit or explicit setting
- // to work in Webkit and IE9 standards mode. Both, inherit
- // and underline do not work in FF. This is a known bug in
- // FF (see above).
- tspan.setAttribute('text-decoration', uline);
- }
- else
- {
- this.textNodes[i] = null;
- }
- }
- }
-
- this.currentValue = this.value;
- }
-};
-
-/**
- * Function: redrawSvg
- *
- * Updates the SVG node(s) to reflect the latest bounds and scale.
- */
-mxText.prototype.redrawSvg = function()
-{
- if (this.node.nodeName == 'foreignObject')
- {
- this.redrawHtml();
-
- return;
- }
-
- var fontSize = Math.round(this.size * this.scale);
-
- if (fontSize <= 0)
- {
- this.node.setAttribute('visibility', 'hidden');
- }
- else
- {
- this.node.removeAttribute('visibility');
- }
-
- this.updateSvgValue(this.node);
- this.node.setAttribute('font-size', fontSize + 'px');
-
- if (this.opacity != null)
- {
- // Improves opacity performance in Firefox
- this.node.setAttribute('fill-opacity', this.opacity/100);
- this.node.setAttribute('stroke-opacity', this.opacity/100);
- }
-
- // Workaround to avoid the use of getBBox to find the size
- // of the label. A temporary HTML table is created instead.
- var previous = this.value;
- var table = this.createHtmlTable();
-
- // Makes sure the table is updated and replaces all HTML entities
- this.lastValue = null;
- this.value = mxUtils.htmlEntities(this.value, false);
- this.updateHtmlTable(table);
-
- // Adds the table to the DOM to find the actual size
- document.body.appendChild(table);
- var w = table.offsetWidth * this.scale;
- var h = table.offsetHeight * this.scale;
-
- // Cleans up the DOM and restores the original value
- table.parentNode.removeChild(table);
- this.value = previous;
-
- // Sets the bounding box for the unclipped case so that
- // the full background can be painted using it, the initial
- // value for dx and the +4 in the width below are for
- // error correction of the HTML and SVG text width
- var dx = 2 * this.scale;
-
- if (this.align == mxConstants.ALIGN_CENTER)
- {
- dx += w / 2;
- }
- else if (this.align == mxConstants.ALIGN_RIGHT)
- {
- dx += w;
- }
-
- var dy = Math.round(fontSize * 1.3);
- var childCount = this.node.childNodes.length;
- var lineCount = (this.textNodes != null) ? this.textNodes.length : 0;
-
- if (this.backgroundNode != null)
- {
- childCount--;
- }
-
- var x = this.bounds.x;
- var y = this.bounds.y;
-
- x += (this.align == mxConstants.ALIGN_RIGHT) ?
- ((this.horizontal) ? this.bounds.width : this.bounds.height)-
- this.spacingRight * this.scale :
- (this.align == mxConstants.ALIGN_CENTER) ?
- this.spacingLeft * this.scale +
- (((this.horizontal) ? this.bounds.width : this.bounds.height) -
- this.spacingLeft * this.scale - this.spacingRight * this.scale) / 2 :
- this.spacingLeft * this.scale + 1;
-
- // Makes sure the alignment is like in VML and HTML
- y += (this.valign == mxConstants.ALIGN_BOTTOM) ?
- ((this.horizontal) ? this.bounds.height : this.bounds.width) -
- (lineCount - 1) * dy - this.spacingBottom * this.scale - 4 :
- (this.valign == mxConstants.ALIGN_MIDDLE) ?
- (this.spacingTop * this.scale +
- ((this.horizontal) ? this.bounds.height : this.bounds.width) -
- this.spacingBottom * this.scale -
- (lineCount - 1.5) * dy) / 2 :
- this.spacingTop * this.scale + dy;
-
- if (this.overflow == 'fill')
- {
- if (this.align == mxConstants.ALIGN_CENTER)
- {
- x = Math.max(this.bounds.x + w / 2, x);
- }
-
- y = Math.max(this.bounds.y + fontSize, y);
-
- this.boundingBox = new mxRectangle(x - dx, y - dy,
- w + 4 * this.scale, h + 1 * this.scale);
- this.boundingBox.x = Math.min(this.bounds.x, this.boundingBox.x);
- this.boundingBox.y = Math.min(this.bounds.y, this.boundingBox.y);
- this.boundingBox.width = Math.max(this.bounds.width, this.boundingBox.width);
- this.boundingBox.height = Math.max(this.bounds.height, this.boundingBox.height);
- }
- else
- {
- this.boundingBox = new mxRectangle(x - dx, y - dy,
- w + 4 * this.scale, h + 1 * this.scale);
- }
-
- if (!this.horizontal)
- {
- var cx = this.bounds.x + this.bounds.width / 2;
- var cy = this.bounds.y + this.bounds.height / 2;
-
- var offsetX = (this.bounds.width - this.bounds.height) / 2;
- var offsetY = (this.bounds.height - this.bounds.width) / 2;
-
- this.node.setAttribute('transform',
- 'rotate(' + this.verticalTextDegree + ' ' + cx + ' ' + cy + ') ' +
- 'translate(' + (-offsetY) + ' ' + (-offsetX) + ')');
- }
-
- // TODO: Font-shadow
- this.redrawSvgTextNodes(x, y, dy);
-
- /*
- * FIXME: Bounding box is not rotated. This seems to be a problem for
- * all vertical text boxes. Workaround is in mxImageExport.
- if (!this.horizontal)
- {
- var b = this.bounds.y + this.bounds.height;
- var cx = this.boundingBox.getCenterX() - this.bounds.x;
- var cy = this.boundingBox.getCenterY() - this.bounds.y;
-
- var y = b - cx - this.bounds.height / 2;
- this.boundingBox.x = this.bounds.x + cy - this.boundingBox.width / 2;
- this.boundingBox.y = y;
- }
- */
-
- // Updates the bounds of the background node if one exists
- if (this.value.length > 0 && this.backgroundNode != null && this.node.firstChild != null)
- {
- if (this.node.firstChild != this.backgroundNode)
- {
- this.node.insertBefore(this.backgroundNode, this.node.firstChild);
- }
-
- // FIXME: For larger font sizes the linespacing between HTML and SVG
- // seems to be different and hence the bounding box isn't accurate.
- // Also in Firefox the background box is slighly offset.
- this.backgroundNode.setAttribute('x', this.boundingBox.x + this.scale / 2 + 1 * this.scale);
- this.backgroundNode.setAttribute('y', this.boundingBox.y + this.scale / 2 + 2 * this.scale - this.labelPadding);
- this.backgroundNode.setAttribute('width', this.boundingBox.width - this.scale - 2 * this.scale);
- this.backgroundNode.setAttribute('height', this.boundingBox.height - this.scale);
-
- var strokeWidth = Math.round(Math.max(1, this.scale));
- this.backgroundNode.setAttribute('stroke-width', strokeWidth);
- }
-
- // Adds clipping and updates the bounding box
- if (this.clipped && this.bounds.width > 0 && this.bounds.height > 0)
- {
- this.boundingBox = this.bounds.clone();
-
- if (!this.horizontal)
- {
- this.boundingBox.width = this.bounds.height;
- this.boundingBox.height = this.bounds.width;
- }
-
- x = this.bounds.x;
- y = this.bounds.y;
-
- if (this.horizontal)
- {
- w = this.bounds.width;
- h = this.bounds.height;
- }
- else
- {
- w = this.bounds.height;
- h = this.bounds.width;
- }
-
- var clip = this.getSvgClip(this.node.ownerSVGElement, x, y, w, h);
-
- if (clip != this.clip)
- {
- this.releaseSvgClip();
- this.clip = clip;
- clip.refCount++;
- }
-
- this.node.setAttribute('clip-path', 'url(#' + clip.getAttribute('id') + ')');
- }
- else
- {
- this.releaseSvgClip();
- this.node.removeAttribute('clip-path');
- }
-};
-
-/**
- * Function: redrawSvgTextNodes
- *
- * Hook to update the position of the SVG text nodes.
- */
-mxText.prototype.redrawSvgTextNodes = function(x, y, dy)
-{
- if (this.textNodes != null)
- {
- var currentY = y;
-
- for (var i = 0; i < this.textNodes.length; i++)
- {
- var node = this.textNodes[i];
-
- if (node != null)
- {
- node.setAttribute('x', x);
- node.setAttribute('y', currentY);
-
- // Triggers an update in Firefox 1.5.0.x (don't add a semicolon!)
- node.setAttribute('style', 'pointer-events: all');
- }
-
- currentY += dy;
- }
- }
-};
-
-/**
- * Function: releaseSvgClip
- *
- * Releases the given SVG clip removing it from the DOM if required.
- */
-mxText.prototype.releaseSvgClip = function()
-{
- if (this.clip != null)
- {
- this.clip.refCount--;
-
- if (this.clip.refCount == 0)
- {
- this.clip.parentNode.removeChild(this.clip);
- }
-
- this.clip = null;
- }
-};
-
-/**
- * Function: getSvgClip
- *
- * Returns a new or existing SVG clip path which is a descendant of the given
- * SVG node with a unique ID.
- */
-mxText.prototype.getSvgClip = function(svg, x, y, w, h)
-{
- x = Math.round(x);
- y = Math.round(y);
- w = Math.round(w);
- h = Math.round(h);
-
- var id = 'mx-clip-' + x + '-' + y + '-' + w + '-' + h;
-
- // Quick access
- if (this.clip != null && this.clip.ident == id)
- {
- return this.clip;
- }
-
- var counter = 0;
- var tmp = id + '-' + counter;
- var clip = document.getElementById(tmp);
-
- // Tries to find an existing clip in the given SVG
- while (clip != null)
- {
- if (clip.ownerSVGElement == svg)
- {
- return clip;
- }
-
- counter++;
- tmp = id + '-' + counter;
- clip = document.getElementById(tmp);
- }
-
- // Creates a new clip node and adds it to the DOM
- if (clip != null)
- {
- clip = clip.cloneNode(true);
- counter++;
- }
- else
- {
- clip = document.createElementNS(mxConstants.NS_SVG, 'clipPath');
-
- var rect = document.createElementNS(mxConstants.NS_SVG, 'rect');
- rect.setAttribute('x', x);
- rect.setAttribute('y', y);
- rect.setAttribute('width', w);
- rect.setAttribute('height', h);
-
- clip.appendChild(rect);
- }
-
- clip.setAttribute('id', id + '-' + counter);
- clip.ident = id; // For quick access above
- svg.appendChild(clip);
- clip.refCount = 0;
-
- return clip;
-};
-
-/**
- * Function: isEmptyString
- *
- * Returns true if the given string is empty or
- * contains only whitespace.
- */
-mxText.prototype.isEmptyString = function(text)
-{
- return text.replace(/ /g, '').length == 0;
-};
-
-/**
- * Function: createSvgSpan
- *
- * Creats an SVG tspan node for the given text.
- */
-mxText.prototype.createSvgSpan = function(text)
-{
- // Creates a text node since there is no enclosing text element but
- // rather a group, which is required to render the background rectangle
- // in Webkit. This can be changed to tspan if the enclosing node is
- // a text but this leads to an hidden background in Webkit.
- var node = document.createElementNS(mxConstants.NS_SVG, 'text');
- // Needed to preserve multiple white spaces, but ignored in IE9 plus white-space:pre
- // is ignored in HTML output for VML, so better to not use this for SVG labels
- // node.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve')
- // Alternative idea is to replace all spaces with &nbsp; to fix HTML in IE, but
- // IE9/10 with SVG will still ignore the xml:space preserve tag as discussed here:
- // http://stackoverflow.com/questions/8086292/significant-whitespace-in-svg-embedded-in-html
- // Could replace spaces with &nbsp; in text but HTML tags must be scaped first.
- mxUtils.write(node, text);
-
- return node;
-};
-
-/**
- * Function: destroy
- *
- * Extends destroy to remove any allocated SVG clips.
- */
-mxText.prototype.destroy = function()
-{
- this.releaseSvgClip();
- mxShape.prototype.destroy.apply(this, arguments);
-};
diff --git a/src/js/shape/mxTriangle.js b/src/js/shape/mxTriangle.js
deleted file mode 100644
index 3a48db2..0000000
--- a/src/js/shape/mxTriangle.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * $Id: mxTriangle.js,v 1.10 2011-09-02 10:01:00 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxTriangle
- *
- * Implementation of the triangle shape.
- *
- * Constructor: mxTriangle
- *
- * Constructs a new triangle shape.
- */
-function mxTriangle() { };
-
-/**
- * Extends <mxActor>.
- */
-mxTriangle.prototype = new mxActor();
-mxTriangle.prototype.constructor = mxTriangle;
-
-/**
- * Function: redrawPath
- *
- * Draws the path for this shape. This method uses the <mxPath>
- * abstraction to paint the shape for VML and SVG.
- */
-mxTriangle.prototype.redrawPath = function(path, x, y, w, h)
-{
- path.moveTo(0, 0);
- path.lineTo(w, 0.5 * h);
- path.lineTo(0, h);
- path.close();
-};
diff --git a/src/js/util/mxAnimation.js b/src/js/util/mxAnimation.js
deleted file mode 100644
index 80901ef..0000000
--- a/src/js/util/mxAnimation.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * $Id: mxAnimation.js,v 1.2 2010-03-19 12:53:29 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- *
- * Class: mxAnimation
- *
- * Implements a basic animation in JavaScript.
- *
- * Constructor: mxAnimation
- *
- * Constructs an animation.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- */
-function mxAnimation(delay)
-{
- this.delay = (delay != null) ? delay : 20;
-};
-
-/**
- * Extends mxEventSource.
- */
-mxAnimation.prototype = new mxEventSource();
-mxAnimation.prototype.constructor = mxAnimation;
-
-/**
- * Variable: delay
- *
- * Specifies the delay between the animation steps. Defaul is 30ms.
- */
-mxAnimation.prototype.delay = null;
-
-/**
- * Variable: thread
- *
- * Reference to the thread while the animation is running.
- */
-mxAnimation.prototype.thread = null;
-
-/**
- * Function: startAnimation
- *
- * Starts the animation by repeatedly invoking updateAnimation.
- */
-mxAnimation.prototype.startAnimation = function()
-{
- if (this.thread == null)
- {
- this.thread = window.setInterval(mxUtils.bind(this, this.updateAnimation), this.delay);
- }
-};
-
-/**
- * Function: updateAnimation
- *
- * Hook for subclassers to implement the animation. Invoke stopAnimation
- * when finished, startAnimation to resume. This is called whenever the
- * timer fires and fires an mxEvent.EXECUTE event with no properties.
- */
-mxAnimation.prototype.updateAnimation = function()
-{
- this.fireEvent(new mxEventObject(mxEvent.EXECUTE));
-};
-
-/**
- * Function: stopAnimation
- *
- * Stops the animation by deleting the timer and fires an <mxEvent.DONE>.
- */
-mxAnimation.prototype.stopAnimation = function()
-{
- if (this.thread != null)
- {
- window.clearInterval(this.thread);
- this.thread = null;
- this.fireEvent(new mxEventObject(mxEvent.DONE));
- }
-};
diff --git a/src/js/util/mxAutoSaveManager.js b/src/js/util/mxAutoSaveManager.js
deleted file mode 100644
index 85c23dc..0000000
--- a/src/js/util/mxAutoSaveManager.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * $Id: mxAutoSaveManager.js,v 1.9 2010-09-16 09:10:21 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxAutoSaveManager
- *
- * Manager for automatically saving diagrams. The <save> hook must be
- * implemented.
- *
- * Example:
- *
- * (code)
- * var mgr = new mxAutoSaveManager(editor.graph);
- * mgr.save = function()
- * {
- * mxLog.show();
- * mxLog.debug('save');
- * };
- * (end)
- *
- * Constructor: mxAutoSaveManager
- *
- * Constructs a new automatic layout for the given graph.
- *
- * Arguments:
- *
- * graph - Reference to the enclosing graph.
- */
-function mxAutoSaveManager(graph)
-{
- // Notifies the manager of a change
- this.changeHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled())
- {
- this.graphModelChanged(evt.getProperty('edit').changes);
- }
- });
-
- this.setGraph(graph);
-};
-
-/**
- * Extends mxEventSource.
- */
-mxAutoSaveManager.prototype = new mxEventSource();
-mxAutoSaveManager.prototype.constructor = mxAutoSaveManager;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxAutoSaveManager.prototype.graph = null;
-
-/**
- * Variable: autoSaveDelay
- *
- * Minimum amount of seconds between two consecutive autosaves. Eg. a
- * value of 1 (s) means the graph is not stored more than once per second.
- * Default is 10.
- */
-mxAutoSaveManager.prototype.autoSaveDelay = 10;
-
-/**
- * Variable: autoSaveThrottle
- *
- * Minimum amount of seconds between two consecutive autosaves triggered by
- * more than <autoSaveThreshhold> changes within a timespan of less than
- * <autoSaveDelay> seconds. Eg. a value of 1 (s) means the graph is not
- * stored more than once per second even if there are more than
- * <autoSaveThreshold> changes within that timespan. Default is 2.
- */
-mxAutoSaveManager.prototype.autoSaveThrottle = 2;
-
-/**
- * Variable: autoSaveThreshold
- *
- * Minimum amount of ignored changes before an autosave. Eg. a value of 2
- * means after 2 change of the graph model the autosave will trigger if the
- * condition below is true. Default is 5.
- */
-mxAutoSaveManager.prototype.autoSaveThreshold = 5;
-
-/**
- * Variable: ignoredChanges
- *
- * Counter for ignored changes in autosave.
- */
-mxAutoSaveManager.prototype.ignoredChanges = 0;
-
-/**
- * Variable: lastSnapshot
- *
- * Used for autosaving. See <autosave>.
- */
-mxAutoSaveManager.prototype.lastSnapshot = 0;
-
-/**
- * Variable: enabled
- *
- * Specifies if event handling is enabled. Default is true.
- */
-mxAutoSaveManager.prototype.enabled = true;
-
-/**
- * Variable: changeHandler
- *
- * Holds the function that handles graph model changes.
- */
-mxAutoSaveManager.prototype.changeHandler = null;
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxAutoSaveManager.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxAutoSaveManager.prototype.setEnabled = function(value)
-{
- this.enabled = value;
-};
-
-/**
- * Function: setGraph
- *
- * Sets the graph that the layouts operate on.
- */
-mxAutoSaveManager.prototype.setGraph = function(graph)
-{
- if (this.graph != null)
- {
- this.graph.getModel().removeListener(this.changeHandler);
- }
-
- this.graph = graph;
-
- if (this.graph != null)
- {
- this.graph.getModel().addListener(mxEvent.CHANGE, this.changeHandler);
- }
-};
-
-/**
- * Function: save
- *
- * Empty hook that is called if the graph should be saved.
- */
-mxAutoSaveManager.prototype.save = function()
-{
- // empty
-};
-
-/**
- * Function: graphModelChanged
- *
- * Invoked when the graph model has changed.
- */
-mxAutoSaveManager.prototype.graphModelChanged = function(changes)
-{
- var now = new Date().getTime();
- var dt = (now - this.lastSnapshot) / 1000;
-
- if (dt > this.autoSaveDelay ||
- (this.ignoredChanges >= this.autoSaveThreshold &&
- dt > this.autoSaveThrottle))
- {
- this.save();
- this.reset();
- }
- else
- {
- // Increments the number of ignored changes
- this.ignoredChanges++;
- }
-};
-
-/**
- * Function: reset
- *
- * Resets all counters.
- */
-mxAutoSaveManager.prototype.reset = function()
-{
- this.lastSnapshot = new Date().getTime();
- this.ignoredChanges = 0;
-};
-
-/**
- * Function: destroy
- *
- * Removes all handlers from the <graph> and deletes the reference to it.
- */
-mxAutoSaveManager.prototype.destroy = function()
-{
- this.setGraph(null);
-};
diff --git a/src/js/util/mxClipboard.js b/src/js/util/mxClipboard.js
deleted file mode 100644
index e9fec6b..0000000
--- a/src/js/util/mxClipboard.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- * $Id: mxClipboard.js,v 1.29 2010-01-02 09:45:14 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxClipboard =
-{
- /**
- * Class: mxClipboard
- *
- * Singleton that implements a clipboard for graph cells.
- *
- * Example:
- *
- * (code)
- * mxClipboard.copy(graph);
- * mxClipboard.paste(graph2);
- * (end)
- *
- * This copies the selection cells from the graph to the
- * clipboard and pastes them into graph2.
- *
- * For fine-grained control of the clipboard data the <mxGraph.canExportCell>
- * and <mxGraph.canImportCell> functions can be overridden.
- *
- * Variable: STEPSIZE
- *
- * Defines the step size to offset the cells
- * after each paste operation. Default is 10.
- */
- STEPSIZE: 10,
-
- /**
- * Variable: insertCount
- *
- * Counts the number of times the clipboard data has been inserted.
- */
- insertCount: 1,
-
- /**
- * Variable: cells
- *
- * Holds the array of <mxCells> currently in the clipboard.
- */
- cells: null,
-
- /**
- * Function: isEmpty
- *
- * Returns true if the clipboard currently has not data stored.
- */
- isEmpty: function()
- {
- return mxClipboard.cells == null;
- },
-
- /**
- * Function: cut
- *
- * Cuts the given array of <mxCells> from the specified graph.
- * If cells is null then the selection cells of the graph will
- * be used. Returns the cells that have been cut from the graph.
- *
- * Parameters:
- *
- * graph - <mxGraph> that contains the cells to be cut.
- * cells - Optional array of <mxCells> to be cut.
- */
- cut: function(graph, cells)
- {
- cells = mxClipboard.copy(graph, cells);
- mxClipboard.insertCount = 0;
- mxClipboard.removeCells(graph, cells);
-
- return cells;
- },
-
- /**
- * Function: removeCells
- *
- * Hook to remove the given cells from the given graph after
- * a cut operation.
- *
- * Parameters:
- *
- * graph - <mxGraph> that contains the cells to be cut.
- * cells - Array of <mxCells> to be cut.
- */
- removeCells: function(graph, cells)
- {
- graph.removeCells(cells);
- },
-
- /**
- * Function: copy
- *
- * Copies the given array of <mxCells> from the specified
- * graph to <cells>.Returns the original array of cells that has
- * been cloned.
- *
- * Parameters:
- *
- * graph - <mxGraph> that contains the cells to be copied.
- * cells - Optional array of <mxCells> to be copied.
- */
- copy: function(graph, cells)
- {
- cells = cells || graph.getSelectionCells();
- var result = graph.getExportableCells(cells);
- mxClipboard.insertCount = 1;
- mxClipboard.cells = graph.cloneCells(result);
-
- return result;
- },
-
- /**
- * Function: paste
- *
- * Pastes the <cells> into the specified graph restoring
- * the relation to <parents>, if possible. If the parents
- * are no longer in the graph or invisible then the
- * cells are added to the graph's default or into the
- * swimlane under the cell's new location if one exists.
- * The cells are added to the graph using <mxGraph.importCells>.
- *
- * Parameters:
- *
- * graph - <mxGraph> to paste the <cells> into.
- */
- paste: function(graph)
- {
- if (mxClipboard.cells != null)
- {
- var cells = graph.getImportableCells(mxClipboard.cells);
- var delta = mxClipboard.insertCount * mxClipboard.STEPSIZE;
- var parent = graph.getDefaultParent();
- cells = graph.importCells(cells, delta, delta, parent);
-
- // Increments the counter and selects the inserted cells
- mxClipboard.insertCount++;
- graph.setSelectionCells(cells);
- }
- }
-
-};
diff --git a/src/js/util/mxConstants.js b/src/js/util/mxConstants.js
deleted file mode 100644
index 8d11dc1..0000000
--- a/src/js/util/mxConstants.js
+++ /dev/null
@@ -1,1911 +0,0 @@
-/**
- * $Id: mxConstants.js,v 1.127 2012-11-20 09:06:07 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
- var mxConstants =
- {
- /**
- * Class: mxConstants
- *
- * Defines various global constants.
- *
- * Variable: DEFAULT_HOTSPOT
- *
- * Defines the portion of the cell which is to be used as a connectable
- * region. Default is 0.3. Possible values are 0 < x <= 1.
- */
- DEFAULT_HOTSPOT: 0.3,
-
- /**
- * Variable: MIN_HOTSPOT_SIZE
- *
- * Defines the minimum size in pixels of the portion of the cell which is
- * to be used as a connectable region. Default is 8.
- */
- MIN_HOTSPOT_SIZE: 8,
-
- /**
- * Variable: MAX_HOTSPOT_SIZE
- *
- * Defines the maximum size in pixels of the portion of the cell which is
- * to be used as a connectable region. Use 0 for no maximum. Default is 0.
- */
- MAX_HOTSPOT_SIZE: 0,
-
- /**
- * Variable: RENDERING_HINT_EXACT
- *
- * Defines the exact rendering hint.
- */
- RENDERING_HINT_EXACT: 'exact',
-
- /**
- * Variable: RENDERING_HINT_FASTER
- *
- * Defines the faster rendering hint.
- */
- RENDERING_HINT_FASTER: 'faster',
-
- /**
- * Variable: RENDERING_HINT_FASTEST
- *
- * Defines the fastest rendering hint.
- */
- RENDERING_HINT_FASTEST: 'fastest',
-
- /**
- * Variable: DIALECT_SVG
- *
- * Defines the SVG display dialect name.
- */
- DIALECT_SVG: 'svg',
-
- /**
- * Variable: DIALECT_VML
- *
- * Defines the VML display dialect name.
- */
- DIALECT_VML: 'vml',
-
- /**
- * Variable: DIALECT_MIXEDHTML
- *
- * Defines the mixed HTML display dialect name.
- */
- DIALECT_MIXEDHTML: 'mixedHtml',
-
- /**
- * Variable: DIALECT_PREFERHTML
- *
- * Defines the preferred HTML display dialect name.
- */
- DIALECT_PREFERHTML: 'preferHtml',
-
- /**
- * Variable: DIALECT_STRICTHTML
- *
- * Defines the strict HTML display dialect.
- */
- DIALECT_STRICTHTML: 'strictHtml',
-
- /**
- * Variable: NS_SVG
- *
- * Defines the SVG namespace.
- */
- NS_SVG: 'http://www.w3.org/2000/svg',
-
- /**
- * Variable: NS_XHTML
- *
- * Defines the XHTML namespace.
- */
- NS_XHTML: 'http://www.w3.org/1999/xhtml',
-
- /**
- * Variable: NS_XLINK
- *
- * Defines the XLink namespace.
- */
- NS_XLINK: 'http://www.w3.org/1999/xlink',
-
- /**
- * Variable: SHADOWCOLOR
- *
- * Defines the color to be used to draw shadows in shapes and windows.
- * Default is gray.
- */
- SHADOWCOLOR: 'gray',
-
- /**
- * Variable: SHADOW_OFFSET_X
- *
- * Specifies the x-offset of the shadow. Default is 2.
- */
- SHADOW_OFFSET_X: 2,
-
- /**
- * Variable: SHADOW_OFFSET_Y
- *
- * Specifies the y-offset of the shadow. Default is 3.
- */
- SHADOW_OFFSET_Y: 3,
-
- /**
- * Variable: SHADOW_OPACITY
- *
- * Defines the opacity for shadows. Default is 1.
- */
- SHADOW_OPACITY: 1,
-
- /**
- * Variable: NODETYPE_ELEMENT
- *
- * DOM node of type ELEMENT.
- */
- NODETYPE_ELEMENT: 1,
-
- /**
- * Variable: NODETYPE_ATTRIBUTE
- *
- * DOM node of type ATTRIBUTE.
- */
- NODETYPE_ATTRIBUTE: 2,
-
- /**
- * Variable: NODETYPE_TEXT
- *
- * DOM node of type TEXT.
- */
- NODETYPE_TEXT: 3,
-
- /**
- * Variable: NODETYPE_CDATA
- *
- * DOM node of type CDATA.
- */
- NODETYPE_CDATA: 4,
-
- /**
- * Variable: NODETYPE_ENTITY_REFERENCE
- *
- * DOM node of type ENTITY_REFERENCE.
- */
- NODETYPE_ENTITY_REFERENCE: 5,
-
- /**
- * Variable: NODETYPE_ENTITY
- *
- * DOM node of type ENTITY.
- */
- NODETYPE_ENTITY: 6,
-
- /**
- * Variable: NODETYPE_PROCESSING_INSTRUCTION
- *
- * DOM node of type PROCESSING_INSTRUCTION.
- */
- NODETYPE_PROCESSING_INSTRUCTION: 7,
-
- /**
- * Variable: NODETYPE_COMMENT
- *
- * DOM node of type COMMENT.
- */
- NODETYPE_COMMENT: 8,
-
- /**
- * Variable: NODETYPE_DOCUMENT
- *
- * DOM node of type DOCUMENT.
- */
- NODETYPE_DOCUMENT: 9,
-
- /**
- * Variable: NODETYPE_DOCUMENTTYPE
- *
- * DOM node of type DOCUMENTTYPE.
- */
- NODETYPE_DOCUMENTTYPE: 10,
-
- /**
- * Variable: NODETYPE_DOCUMENT_FRAGMENT
- *
- * DOM node of type DOCUMENT_FRAGMENT.
- */
- NODETYPE_DOCUMENT_FRAGMENT: 11,
-
- /**
- * Variable: NODETYPE_NOTATION
- *
- * DOM node of type NOTATION.
- */
- NODETYPE_NOTATION: 12,
-
- /**
- * Variable: TOOLTIP_VERTICAL_OFFSET
- *
- * Defines the vertical offset for the tooltip.
- * Default is 16.
- */
- TOOLTIP_VERTICAL_OFFSET: 16,
-
- /**
- * Variable: DEFAULT_VALID_COLOR
- *
- * Specifies the default valid colorr. Default is #0000FF.
- */
- DEFAULT_VALID_COLOR: '#00FF00',
-
- /**
- * Variable: DEFAULT_INVALID_COLOR
- *
- * Specifies the default invalid color. Default is #FF0000.
- */
- DEFAULT_INVALID_COLOR: '#FF0000',
-
- /**
- * Variable: HIGHLIGHT_STROKEWIDTH
- *
- * Defines the strokewidth to be used for the highlights.
- * Default is 3.
- */
- HIGHLIGHT_STROKEWIDTH: 3,
-
- /**
- * Variable: CURSOR_MOVABLE_VERTEX
- *
- * Defines the cursor for a movable vertex. Default is 'move'.
- */
- CURSOR_MOVABLE_VERTEX: 'move',
-
- /**
- * Variable: CURSOR_MOVABLE_EDGE
- *
- * Defines the cursor for a movable edge. Default is 'move'.
- */
- CURSOR_MOVABLE_EDGE: 'move',
-
- /**
- * Variable: CURSOR_LABEL_HANDLE
- *
- * Defines the cursor for a movable label. Default is 'default'.
- */
- CURSOR_LABEL_HANDLE: 'default',
-
- /**
- * Variable: CURSOR_BEND_HANDLE
- *
- * Defines the cursor for a movable bend. Default is 'pointer'.
- */
- CURSOR_BEND_HANDLE: 'pointer',
-
- /**
- * Variable: CURSOR_CONNECT
- *
- * Defines the cursor for a connectable state. Default is 'pointer'.
- */
- CURSOR_CONNECT: 'pointer',
-
- /**
- * Variable: HIGHLIGHT_COLOR
- *
- * Defines the color to be used for the cell highlighting.
- * Use 'none' for no color. Default is #00FF00.
- */
- HIGHLIGHT_COLOR: '#00FF00',
-
- /**
- * Variable: TARGET_HIGHLIGHT_COLOR
- *
- * Defines the color to be used for highlighting a target cell for a new
- * or changed connection. Note that this may be either a source or
- * target terminal in the graph. Use 'none' for no color.
- * Default is #0000FF.
- */
- CONNECT_TARGET_COLOR: '#0000FF',
-
- /**
- * Variable: INVALID_CONNECT_TARGET_COLOR
- *
- * Defines the color to be used for highlighting a invalid target cells
- * for a new or changed connections. Note that this may be either a source
- * or target terminal in the graph. Use 'none' for no color. Default is
- * #FF0000.
- */
- INVALID_CONNECT_TARGET_COLOR: '#FF0000',
-
- /**
- * Variable: DROP_TARGET_COLOR
- *
- * Defines the color to be used for the highlighting target parent cells
- * (for drag and drop). Use 'none' for no color. Default is #0000FF.
- */
- DROP_TARGET_COLOR: '#0000FF',
-
- /**
- * Variable: VALID_COLOR
- *
- * Defines the color to be used for the coloring valid connection
- * previews. Use 'none' for no color. Default is #FF0000.
- */
- VALID_COLOR: '#00FF00',
-
- /**
- * Variable: INVALID_COLOR
- *
- * Defines the color to be used for the coloring invalid connection
- * previews. Use 'none' for no color. Default is #FF0000.
- */
- INVALID_COLOR: '#FF0000',
-
- /**
- * Variable: EDGE_SELECTION_COLOR
- *
- * Defines the color to be used for the selection border of edges. Use
- * 'none' for no color. Default is #00FF00.
- */
- EDGE_SELECTION_COLOR: '#00FF00',
-
- /**
- * Variable: VERTEX_SELECTION_COLOR
- *
- * Defines the color to be used for the selection border of vertices. Use
- * 'none' for no color. Default is #00FF00.
- */
- VERTEX_SELECTION_COLOR: '#00FF00',
-
- /**
- * Variable: VERTEX_SELECTION_STROKEWIDTH
- *
- * Defines the strokewidth to be used for vertex selections.
- * Default is 1.
- */
- VERTEX_SELECTION_STROKEWIDTH: 1,
-
- /**
- * Variable: EDGE_SELECTION_STROKEWIDTH
- *
- * Defines the strokewidth to be used for edge selections.
- * Default is 1.
- */
- EDGE_SELECTION_STROKEWIDTH: 1,
-
- /**
- * Variable: SELECTION_DASHED
- *
- * Defines the dashed state to be used for the vertex selection
- * border. Default is true.
- */
- VERTEX_SELECTION_DASHED: true,
-
- /**
- * Variable: SELECTION_DASHED
- *
- * Defines the dashed state to be used for the edge selection
- * border. Default is true.
- */
- EDGE_SELECTION_DASHED: true,
-
- /**
- * Variable: GUIDE_COLOR
- *
- * Defines the color to be used for the guidelines in mxGraphHandler.
- * Default is #FF0000.
- */
- GUIDE_COLOR: '#FF0000',
-
- /**
- * Variable: GUIDE_STROKEWIDTH
- *
- * Defines the strokewidth to be used for the guidelines in mxGraphHandler.
- * Default is 1.
- */
- GUIDE_STROKEWIDTH: 1,
-
- /**
- * Variable: OUTLINE_COLOR
- *
- * Defines the color to be used for the outline rectangle
- * border. Use 'none' for no color. Default is #0099FF.
- */
- OUTLINE_COLOR: '#0099FF',
-
- /**
- * Variable: OUTLINE_STROKEWIDTH
- *
- * Defines the strokewidth to be used for the outline rectangle
- * stroke width. Default is 3.
- */
- OUTLINE_STROKEWIDTH: (mxClient.IS_IE) ? 2 : 3,
-
- /**
- * Variable: HANDLE_SIZE
- *
- * Defines the default size for handles. Default is 7.
- */
- HANDLE_SIZE: 7,
-
- /**
- * Variable: LABEL_HANDLE_SIZE
- *
- * Defines the default size for label handles. Default is 4.
- */
- LABEL_HANDLE_SIZE: 4,
-
- /**
- * Variable: HANDLE_FILLCOLOR
- *
- * Defines the color to be used for the handle fill color. Use 'none' for
- * no color. Default is #00FF00 (green).
- */
- HANDLE_FILLCOLOR: '#00FF00',
-
- /**
- * Variable: HANDLE_STROKECOLOR
- *
- * Defines the color to be used for the handle stroke color. Use 'none' for
- * no color. Default is black.
- */
- HANDLE_STROKECOLOR: 'black',
-
- /**
- * Variable: LABEL_HANDLE_FILLCOLOR
- *
- * Defines the color to be used for the label handle fill color. Use 'none'
- * for no color. Default is yellow.
- */
- LABEL_HANDLE_FILLCOLOR: 'yellow',
-
- /**
- * Variable: CONNECT_HANDLE_FILLCOLOR
- *
- * Defines the color to be used for the connect handle fill color. Use
- * 'none' for no color. Default is #0000FF (blue).
- */
- CONNECT_HANDLE_FILLCOLOR: '#0000FF',
-
- /**
- * Variable: LOCKED_HANDLE_FILLCOLOR
- *
- * Defines the color to be used for the locked handle fill color. Use
- * 'none' for no color. Default is #FF0000 (red).
- */
- LOCKED_HANDLE_FILLCOLOR: '#FF0000',
-
- /**
- * Variable: OUTLINE_HANDLE_FILLCOLOR
- *
- * Defines the color to be used for the outline sizer fill color. Use
- * 'none' for no color. Default is #00FFFF.
- */
- OUTLINE_HANDLE_FILLCOLOR: '#00FFFF',
-
- /**
- * Variable: OUTLINE_HANDLE_STROKECOLOR
- *
- * Defines the color to be used for the outline sizer stroke color. Use
- * 'none' for no color. Default is #0033FF.
- */
- OUTLINE_HANDLE_STROKECOLOR: '#0033FF',
-
- /**
- * Variable: DEFAULT_FONTFAMILY
- *
- * Defines the default family for all fonts in points. Default is
- * Arial,Helvetica.
- */
- DEFAULT_FONTFAMILY: 'Arial,Helvetica',
-
- /**
- * Variable: DEFAULT_FONTSIZE
- *
- * Defines the default size for all fonts in points. Default is 11.
- */
- DEFAULT_FONTSIZE: 11,
-
- /**
- * Variable: DEFAULT_STARTSIZE
- *
- * Defines the default start size for swimlanes. Default is 40.
- */
- DEFAULT_STARTSIZE: 40,
-
- /**
- * Variable: DEFAULT_MARKERSIZE
- *
- * Defines the default size for all markers. Default is 6.
- */
- DEFAULT_MARKERSIZE: 6,
-
- /**
- * Variable: DEFAULT_IMAGESIZE
- *
- * Defines the default width and height for images used in the
- * label shape. Default is 24.
- */
- DEFAULT_IMAGESIZE: 24,
-
- /**
- * Variable: ENTITY_SEGMENT
- *
- * Defines the length of the horizontal segment of an Entity Relation.
- * This can be overridden using <mxConstants.STYLE_SEGMENT> style.
- * Default is 30.
- */
- ENTITY_SEGMENT: 30,
-
- /**
- * Variable: RECTANGLE_ROUNDING_FACTOR
- *
- * Defines the rounding factor for rounded rectangles in percent between
- * 0 and 1. Values should be smaller than 0.5. Default is 0.15.
- */
- RECTANGLE_ROUNDING_FACTOR: 0.15,
-
- /**
- * Variable: LINE_ARCSIZE
- *
- * Defines the size of the arcs for rounded edges. Default is 20.
- */
- LINE_ARCSIZE: 20,
-
- /**
- * Variable: ARROW_SPACING
- *
- * Defines the spacing between the arrow shape and its terminals. Default
- * is 10.
- */
- ARROW_SPACING: 10,
-
- /**
- * Variable: ARROW_WIDTH
- *
- * Defines the width of the arrow shape. Default is 30.
- */
- ARROW_WIDTH: 30,
-
- /**
- * Variable: ARROW_SIZE
- *
- * Defines the size of the arrowhead in the arrow shape. Default is 30.
- */
- ARROW_SIZE: 30,
-
- /**
- * Variable: PAGE_FORMAT_A4_PORTRAIT
- *
- * Defines the rectangle for the A4 portrait page format. The dimensions
- * of this page format are 826x1169 pixels.
- */
- PAGE_FORMAT_A4_PORTRAIT: new mxRectangle(0, 0, 826, 1169),
-
- /**
- * Variable: PAGE_FORMAT_A4_PORTRAIT
- *
- * Defines the rectangle for the A4 portrait page format. The dimensions
- * of this page format are 826x1169 pixels.
- */
- PAGE_FORMAT_A4_LANDSCAPE: new mxRectangle(0, 0, 1169, 826),
-
- /**
- * Variable: PAGE_FORMAT_LETTER_PORTRAIT
- *
- * Defines the rectangle for the Letter portrait page format. The
- * dimensions of this page format are 850x1100 pixels.
- */
- PAGE_FORMAT_LETTER_PORTRAIT: new mxRectangle(0, 0, 850, 1100),
-
- /**
- * Variable: PAGE_FORMAT_LETTER_PORTRAIT
- *
- * Defines the rectangle for the Letter portrait page format. The dimensions
- * of this page format are 850x1100 pixels.
- */
- PAGE_FORMAT_LETTER_LANDSCAPE: new mxRectangle(0, 0, 1100, 850),
-
- /**
- * Variable: NONE
- *
- * Defines the value for none. Default is "none".
- */
- NONE: 'none',
-
- /**
- * Variable: STYLE_PERIMETER
- *
- * Defines the key for the perimeter style. This is a function that defines
- * the perimeter around a particular shape. Possible values are the
- * functions defined in <mxPerimeter>. Alternatively, the constants in this
- * class that start with <code>PERIMETER_</code> may be used to access
- * perimeter styles in <mxStyleRegistry>.
- */
- STYLE_PERIMETER: 'perimeter',
-
- /**
- * Variable: STYLE_SOURCE_PORT
- *
- * Defines the ID of the cell that should be used for computing the
- * perimeter point of the source for an edge. This allows for graphically
- * connecting to a cell while keeping the actual terminal of the edge.
- */
- STYLE_SOURCE_PORT: 'sourcePort',
-
- /**
- * Variable: STYLE_TARGET_PORT
- *
- * Defines the ID of the cell that should be used for computing the
- * perimeter point of the target for an edge. This allows for graphically
- * connecting to a cell while keeping the actual terminal of the edge.
- */
- STYLE_TARGET_PORT: 'targetPort',
-
- /**
- * Variable: STYLE_PORT_CONSTRAINT
- *
- * Defines the direction(s) that edges are allowed to connect to cells in.
- * Possible values are <code>DIRECTION_NORTH, DIRECTION_SOUTH,
- * DIRECTION_EAST</code> and <code>DIRECTION_WEST</code>.
- */
- STYLE_PORT_CONSTRAINT: 'portConstraint',
-
- /**
- * Variable: STYLE_OPACITY
- *
- * Defines the key for the opacity style. The type of the value is
- * numeric and the possible range is 0-100.
- */
- STYLE_OPACITY: 'opacity',
-
- /**
- * Variable: STYLE_TEXT_OPACITY
- *
- * Defines the key for the text opacity style. The type of the value is
- * numeric and the possible range is 0-100.
- */
- STYLE_TEXT_OPACITY: 'textOpacity',
-
- /**
- * Variable: STYLE_OVERFLOW
- *
- * Defines the key for the overflow style. Possible values are 'visible',
- * 'hidden' and 'fill'. The default value is 'visible'. This value
- * specifies how overlapping vertex labels are handled. A value of
- * 'visible' will show the complete label. A value of 'hidden' will clip
- * the label so that it does not overlap the vertex bounds. A value of
- * 'fill' will use the vertex bounds for the label. See
- * <mxGraph.isLabelClipped>.
- */
- STYLE_OVERFLOW: 'overflow',
-
- /**
- * Variable: STYLE_ORTHOGONAL
- *
- * Defines if the connection points on either end of the edge should be
- * computed so that the edge is vertical or horizontal if possible and
- * if the point is not at a fixed location. Default is false. This is
- * used in <mxGraph.isOrthogonal>, which also returns true if the edgeStyle
- * of the edge is an elbow or entity.
- */
- STYLE_ORTHOGONAL: 'orthogonal',
-
- /**
- * Variable: STYLE_EXIT_X
- *
- * Defines the key for the horizontal relative coordinate connection point
- * of an edge with its source terminal.
- */
- STYLE_EXIT_X: 'exitX',
-
- /**
- * Variable: STYLE_EXIT_Y
- *
- * Defines the key for the vertical relative coordinate connection point
- * of an edge with its source terminal.
- */
- STYLE_EXIT_Y: 'exitY',
-
- /**
- * Variable: STYLE_EXIT_PERIMETER
- *
- * Defines if the perimeter should be used to find the exact entry point
- * along the perimeter of the source. Possible values are 0 (false) and
- * 1 (true). Default is 1 (true).
- */
- STYLE_EXIT_PERIMETER: 'exitPerimeter',
-
- /**
- * Variable: STYLE_ENTRY_X
- *
- * Defines the key for the horizontal relative coordinate connection point
- * of an edge with its target terminal.
- */
- STYLE_ENTRY_X: 'entryX',
-
- /**
- * Variable: STYLE_ENTRY_Y
- *
- * Defines the key for the vertical relative coordinate connection point
- * of an edge with its target terminal.
- */
- STYLE_ENTRY_Y: 'entryY',
-
- /**
- * Variable: STYLE_ENTRY_PERIMETER
- *
- * Defines if the perimeter should be used to find the exact entry point
- * along the perimeter of the target. Possible values are 0 (false) and
- * 1 (true). Default is 1 (true).
- */
- STYLE_ENTRY_PERIMETER: 'entryPerimeter',
-
- /**
- * Variable: STYLE_WHITE_SPACE
- *
- * Defines the key for the white-space style. Possible values are 'nowrap'
- * and 'wrap'. The default value is 'nowrap'. This value specifies how
- * white-space inside a HTML vertex label should be handled. A value of
- * 'nowrap' means the text will never wrap to the next line until a
- * linefeed is encountered. A value of 'wrap' means text will wrap when
- * necessary. This style is only used for HTML labels.
- * See <mxGraph.isWrapping>.
- */
- STYLE_WHITE_SPACE: 'whiteSpace',
-
- /**
- * Variable: STYLE_ROTATION
- *
- * Defines the key for the rotation style. The type of the value is
- * numeric and the possible range is 0-360.
- */
- STYLE_ROTATION: 'rotation',
-
- /**
- * Variable: STYLE_FILLCOLOR
- *
- * Defines the key for the fill color. Possible values are all HTML color
- * names or HEX codes, as well as special keywords such as 'swimlane,
- * 'inherit' or 'indicated' to use the color code of a related cell or the
- * indicator shape.
- */
- STYLE_FILLCOLOR: 'fillColor',
-
- /**
- * Variable: STYLE_GRADIENTCOLOR
- *
- * Defines the key for the gradient color. Possible values are all HTML color
- * names or HEX codes, as well as special keywords such as 'swimlane,
- * 'inherit' or 'indicated' to use the color code of a related cell or the
- * indicator shape. This is ignored if no fill color is defined.
- */
- STYLE_GRADIENTCOLOR: 'gradientColor',
-
- /**
- * Variable: STYLE_GRADIENT_DIRECTION
- *
- * Defines the key for the gradient direction. Possible values are
- * <DIRECTION_EAST>, <DIRECTION_WEST>, <DIRECTION_NORTH> and
- * <DIRECTION_SOUTH>. Default is <DIRECTION_SOUTH>. Generally, and by
- * default in mxGraph, gradient painting is done from the value of
- * <STYLE_FILLCOLOR> to the value of <STYLE_GRADIENTCOLOR>. Taking the
- * example of <DIRECTION_NORTH>, this means <STYLE_FILLCOLOR> color at the
- * bottom of paint pattern and <STYLE_GRADIENTCOLOR> at top, with a
- * gradient in-between.
- */
- STYLE_GRADIENT_DIRECTION: 'gradientDirection',
-
- /**
- * Variable: STYLE_STROKECOLOR
- *
- * Defines the key for the strokeColor style. Possible values are all HTML
- * color names or HEX codes, as well as special keywords such as 'swimlane,
- * 'inherit', 'indicated' to use the color code of a related cell or the
- * indicator shape or 'none' for no color.
- */
- STYLE_STROKECOLOR: 'strokeColor',
-
- /**
- * Variable: STYLE_SEPARATORCOLOR
- *
- * Defines the key for the separatorColor style. Possible values are all
- * HTML color names or HEX codes. This style is only used for
- * <SHAPE_SWIMLANE> shapes.
- */
- STYLE_SEPARATORCOLOR: 'separatorColor',
-
- /**
- * Variable: STYLE_STROKEWIDTH
- *
- * Defines the key for the strokeWidth style. The type of the value is
- * numeric and the possible range is any non-negative value larger or equal
- * to 1. The value defines the stroke width in pixels. Note: To hide a
- * stroke use strokeColor none.
- */
- STYLE_STROKEWIDTH: 'strokeWidth',
-
- /**
- * Variable: STYLE_ALIGN
- *
- * Defines the key for the align style. Possible values are <ALIGN_LEFT>,
- * <ALIGN_CENTER> and <ALIGN_RIGHT>. This value defines how the lines of
- * the label are horizontally aligned. <ALIGN_LEFT> mean label text lines
- * are aligned to left of the label bounds, <ALIGN_RIGHT> to the right of
- * the label bounds and <ALIGN_CENTER> means the center of the text lines
- * are aligned in the center of the label bounds. Note this value doesn't
- * affect the positioning of the overall label bounds relative to the
- * vertex, to move the label bounds horizontally, use
- * <STYLE_LABEL_POSITION>.
- */
- STYLE_ALIGN: 'align',
-
- /**
- * Variable: STYLE_VERTICAL_ALIGN
- *
- * Defines the key for the verticalAlign style. Possible values are
- * <ALIGN_TOP>, <ALIGN_MIDDLE> and <ALIGN_BOTTOM>. This value defines how
- * the lines of the label are vertically aligned. <ALIGN_TOP> means the
- * topmost label text line is aligned against the top of the label bounds,
- * <ALIGN_BOTTOM> means the bottom-most label text line is aligned against
- * the bottom of the label bounds and <ALIGN_MIDDLE> means there is equal
- * spacing between the topmost text label line and the top of the label
- * bounds and the bottom-most text label line and the bottom of the label
- * bounds. Note this value doesn't affect the positioning of the overall
- * label bounds relative to the vertex, to move the label bounds
- * vertically, use <STYLE_VERTICAL_LABEL_POSITION>.
- */
- STYLE_VERTICAL_ALIGN: 'verticalAlign',
-
- /**
- * Variable: STYLE_LABEL_POSITION
- *
- * Defines the key for the horizontal label position of vertices. Possible
- * values are <ALIGN_LEFT>, <ALIGN_CENTER> and <ALIGN_RIGHT>. Default is
- * <ALIGN_CENTER>. The label align defines the position of the label
- * relative to the cell. <ALIGN_LEFT> means the entire label bounds is
- * placed completely just to the left of the vertex, <ALIGN_RIGHT> means
- * adjust to the right and <ALIGN_CENTER> means the label bounds are
- * vertically aligned with the bounds of the vertex. Note this value
- * doesn't affect the positioning of label within the label bounds, to move
- * the label horizontally within the label bounds, use <STYLE_ALIGN>.
- */
- STYLE_LABEL_POSITION: 'labelPosition',
-
- /**
- * Variable: STYLE_VERTICAL_LABEL_POSITION
- *
- * Defines the key for the vertical label position of vertices. Possible
- * values are <ALIGN_TOP>, <ALIGN_BOTTOM> and <ALIGN_MIDDLE>. Default is
- * <ALIGN_MIDDLE>. The label align defines the position of the label
- * relative to the cell. <ALIGN_TOP> means the entire label bounds is
- * placed completely just on the top of the vertex, <ALIGN_BOTTOM> means
- * adjust on the bottom and <ALIGN_MIDDLE> means the label bounds are
- * horizontally aligned with the bounds of the vertex. Note this value
- * doesn't affect the positioning of label within the label bounds, to move
- * the label vertically within the label bounds, use
- * <STYLE_VERTICAL_ALIGN>.
- */
- STYLE_VERTICAL_LABEL_POSITION: 'verticalLabelPosition',
-
- /**
- * Variable: STYLE_IMAGE_ASPECT
- *
- * Defines the key for the image aspect style. Possible values are 0 (do
- * not preserve aspect) or 1 (keep aspect). This is only used in
- * <mxImageShape>. Default is 1.
- */
- STYLE_IMAGE_ASPECT: 'imageAspect',
-
- /**
- * Variable: STYLE_IMAGE_ALIGN
- *
- * Defines the key for the align style. Possible values are <ALIGN_LEFT>,
- * <ALIGN_CENTER> and <ALIGN_RIGHT>. The value defines how any image in the
- * vertex label is aligned horizontally within the label bounds of a
- * <SHAPE_LABEL> shape.
- */
- STYLE_IMAGE_ALIGN: 'imageAlign',
-
- /**
- * Variable: STYLE_IMAGE_VERTICAL_ALIGN
- *
- * Defines the key for the verticalAlign style. Possible values are
- * <ALIGN_TOP>, <ALIGN_MIDDLE> and <ALIGN_BOTTOM>. The value defines how
- * any image in the vertex label is aligned vertically within the label
- * bounds of a <SHAPE_LABEL> shape.
- */
- STYLE_IMAGE_VERTICAL_ALIGN: 'imageVerticalAlign',
-
- /**
- * Variable: STYLE_GLASS
- *
- * Defines the key for the glass style. Possible values are 0 (disabled) and
- * 1(enabled). The default value is 0. This is used in <mxLabel>.
- */
- STYLE_GLASS: 'glass',
-
- /**
- * Variable: STYLE_IMAGE
- *
- * Defines the key for the image style. Possible values are any image URL,
- * the type of the value is String. This is the path to the image to image
- * that is to be displayed within the label of a vertex. Data URLs should
- * use the following format: data:image/png,xyz where xyz is the base64
- * encoded data (without the "base64"-prefix). Note that Data URLs are only
- * supported in modern browsers.
- */
- STYLE_IMAGE: 'image',
-
- /**
- * Variable: STYLE_IMAGE_WIDTH
- *
- * Defines the key for the imageWidth style. The type of this value is
- * int, the value is the image width in pixels and must be greater than 0.
- */
- STYLE_IMAGE_WIDTH: 'imageWidth',
-
- /**
- * Variable: STYLE_IMAGE_HEIGHT
- *
- * Defines the key for the imageHeight style. The type of this value is
- * int, the value is the image height in pixels and must be greater than 0.
- */
- STYLE_IMAGE_HEIGHT: 'imageHeight',
-
- /**
- * Variable: STYLE_IMAGE_BACKGROUND
- *
- * Defines the key for the image background color. This style is only used
- * in <mxImageShape>. Possible values are all HTML color names or HEX
- * codes.
- */
- STYLE_IMAGE_BACKGROUND: 'imageBackground',
-
- /**
- * Variable: STYLE_IMAGE_BORDER
- *
- * Defines the key for the image border color. This style is only used in
- * <mxImageShape>. Possible values are all HTML color names or HEX codes.
- */
- STYLE_IMAGE_BORDER: 'imageBorder',
-
- /**
- * Variable: STYLE_IMAGE_FLIPH
- *
- * Defines the key for the horizontal image flip. This style is only used
- * in <mxImageShape>. Possible values are 0 and 1. Default is 0.
- */
- STYLE_IMAGE_FLIPH: 'imageFlipH',
-
- /**
- * Variable: STYLE_IMAGE_FLIPV
- *
- * Defines the key for the vertical image flip. This style is only used
- * in <mxImageShape>. Possible values are 0 and 1. Default is 0.
- */
- STYLE_IMAGE_FLIPV: 'imageFlipV',
-
- /**
- * Variable: STYLE_STENCIL_FLIPH
- *
- * Defines the key for the horizontal stencil flip. This style is only used
- * for <mxStencilShape>. Possible values are 0 and 1. Default is 0.
- */
- STYLE_STENCIL_FLIPH: 'stencilFlipH',
-
- /**
- * Variable: STYLE_STENCIL_FLIPV
- *
- * Defines the key for the vertical stencil flip. This style is only used
- * for <mxStencilShape>. Possible values are 0 and 1. Default is 0.
- */
- STYLE_STENCIL_FLIPV: 'stencilFlipV',
-
- /**
- * Variable: STYLE_NOLABEL
- *
- * Defines the key for the noLabel style. If this is
- * true then no label is visible for a given cell.
- * Possible values are true or false (1 or 0).
- * Default is false.
- */
- STYLE_NOLABEL: 'noLabel',
-
- /**
- * Variable: STYLE_NOEDGESTYLE
- *
- * Defines the key for the noEdgeStyle style. If this is
- * true then no edge style is applied for a given edge.
- * Possible values are true or false (1 or 0).
- * Default is false.
- */
- STYLE_NOEDGESTYLE: 'noEdgeStyle',
-
- /**
- * Variable: STYLE_LABEL_BACKGROUNDCOLOR
- *
- * Defines the key for the label background color. Possible values are all
- * HTML color names or HEX codes.
- */
- STYLE_LABEL_BACKGROUNDCOLOR: 'labelBackgroundColor',
-
- /**
- * Variable: STYLE_LABEL_BORDERCOLOR
- *
- * Defines the key for the label border color. Possible values are all
- * HTML color names or HEX codes.
- */
- STYLE_LABEL_BORDERCOLOR: 'labelBorderColor',
-
- /**
- * Variable: STYLE_LABEL_PADDING
- *
- * Defines the key for the label padding, ie. the space between the label
- * border and the label.
- */
- STYLE_LABEL_PADDING: 'labelPadding',
-
- /**
- * Variable: STYLE_INDICATOR_SHAPE
- *
- * Defines the key for the indicator shape used within an <mxLabel>.
- * Possible values are all SHAPE_* constants or the names of any new
- * shapes. The indicatorShape has precedence over the indicatorImage.
- */
- STYLE_INDICATOR_SHAPE: 'indicatorShape',
-
- /**
- * Variable: STYLE_INDICATOR_IMAGE
- *
- * Defines the key for the indicator image used within an <mxLabel>.
- * Possible values are all image URLs. The indicatorShape has
- * precedence over the indicatorImage.
- */
- STYLE_INDICATOR_IMAGE: 'indicatorImage',
-
- /**
- * Variable: STYLE_INDICATOR_COLOR
- *
- * Defines the key for the indicatorColor style. Possible values are all
- * HTML color names or HEX codes, as well as the special 'swimlane' keyword
- * to refer to the color of the parent swimlane if one exists.
- */
- STYLE_INDICATOR_COLOR: 'indicatorColor',
-
- /**
- * Variable: STYLE_INDICATOR_STROKECOLOR
- *
- * Defines the key for the indicator stroke color in <mxLabel>.
- * Possible values are all color codes.
- */
- STYLE_INDICATOR_STROKECOLOR: 'indicatorStrokeColor',
-
- /**
- * Variable: STYLE_INDICATOR_GRADIENTCOLOR
- *
- * Defines the key for the indicatorGradientColor style. Possible values
- * are all HTML color names or HEX codes. This style is only supported in
- * <SHAPE_LABEL> shapes.
- */
- STYLE_INDICATOR_GRADIENTCOLOR: 'indicatorGradientColor',
-
- /**
- * Variable: STYLE_INDICATOR_SPACING
- *
- * The defines the key for the spacing between the label and the
- * indicator in <mxLabel>. Possible values are in pixels.
- */
- STYLE_INDICATOR_SPACING: 'indicatorSpacing',
-
- /**
- * Variable: STYLE_INDICATOR_WIDTH
- *
- * Defines the key for the indicator width.
- * Possible values start at 0 (in pixels).
- */
- STYLE_INDICATOR_WIDTH: 'indicatorWidth',
-
- /**
- * Variable: STYLE_INDICATOR_HEIGHT
- *
- * Defines the key for the indicator height.
- * Possible values start at 0 (in pixels).
- */
- STYLE_INDICATOR_HEIGHT: 'indicatorHeight',
-
- /**
- * Variable: STYLE_INDICATOR_DIRECTION
- *
- * Defines the key for the indicatorDirection style. The direction style is
- * used to specify the direction of certain shapes (eg. <mxTriangle>).
- * Possible values are <DIRECTION_EAST> (default), <DIRECTION_WEST>,
- * <DIRECTION_NORTH> and <DIRECTION_SOUTH>.
- */
- STYLE_INDICATOR_DIRECTION: 'indicatorDirection',
-
- /**
- * Variable: STYLE_SHADOW
- *
- * Defines the key for the shadow style. The type of the value is Boolean.
- */
- STYLE_SHADOW: 'shadow',
-
- /**
- * Variable: STYLE_SEGMENT
- *
- * Defines the key for the segment style. The type of this value is
- * float and the value represents the size of the horizontal
- * segment of the entity relation style. Default is ENTITY_SEGMENT.
- */
- STYLE_SEGMENT: 'segment',
-
- /**
- * Variable: STYLE_ENDARROW
- *
- * Defines the key for the end arrow marker.
- * Possible values are all constants with an ARROW-prefix.
- * This is only used in <mxConnector>.
- *
- * Example:
- * (code)
- * style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
- * (end)
- */
- STYLE_ENDARROW: 'endArrow',
-
- /**
- * Variable: STYLE_STARTARROW
- *
- * Defines the key for the start arrow marker.
- * Possible values are all constants with an ARROW-prefix.
- * This is only used in <mxConnector>.
- * See <STYLE_ENDARROW>.
- */
- STYLE_STARTARROW: 'startArrow',
-
- /**
- * Variable: STYLE_ENDSIZE
- *
- * Defines the key for the endSize style. The type of this value is numeric
- * and the value represents the size of the end marker in pixels.
- */
- STYLE_ENDSIZE: 'endSize',
-
- /**
- * Variable: STYLE_STARTSIZE
- *
- * Defines the key for the startSize style. The type of this value is
- * numeric and the value represents the size of the start marker or the
- * size of the swimlane title region depending on the shape it is used for.
- */
- STYLE_STARTSIZE: 'startSize',
-
- /**
- * Variable: STYLE_ENDFILL
- *
- * Defines the key for the endFill style. Use 0 for no fill or 1
- * (default) for fill. (This style is only exported via <mxImageExport>.)
- */
- STYLE_ENDFILL: 'endFill',
-
- /**
- * Variable: STYLE_STARTFILL
- *
- * Defines the key for the startFill style. Use 0 for no fill or 1
- * (default) for fill. (This style is only exported via <mxImageExport>.)
- */
- STYLE_STARTFILL: 'startFill',
-
- /**
- * Variable: STYLE_DASHED
- *
- * Defines the key for the dashed style. Use 0 (default) for non-dashed or 1
- * for dashed.
- */
- STYLE_DASHED: 'dashed',
-
- /**
- * Defines the key for the dashed pattern style in SVG and image exports.
- * The type of this value is a space separated list of numbers that specify
- * a custom-defined dash pattern. Dash styles are defined in terms of the
- * length of the dash (the drawn part of the stroke) and the length of the
- * space between the dashes. The lengths are relative to the line width: a
- * length of "1" is equal to the line width. VML ignores this style and
- * uses dashStyle instead as defined in the VML specification. This style
- * is only used in the <mxConnector> shape.
- */
- STYLE_DASH_PATTERN: 'dashPattern',
-
- /**
- * Variable: STYLE_ROUNDED
- *
- * Defines the key for the rounded style. The type of this value is
- * Boolean. For edges this determines whether or not joins between edges
- * segments are smoothed to a rounded finish. For vertices that have the
- * rectangle shape, this determines whether or not the rectangle is
- * rounded.
- */
- STYLE_ROUNDED: 'rounded',
-
- /**
- * Variable: STYLE_ARCSIZE
- *
- * Defines the rounding factor for a rounded rectangle in percent (without
- * the percent sign). Possible values are between 0 and 100. If this value
- * is not specified then RECTANGLE_ROUNDING_FACTOR * 100 is used.
- * (This style is only exported via <mxImageExport>.)
- */
- STYLE_ARCSIZE: 'arcSize',
-
- /**
- * Variable: STYLE_SMOOTH
- *
- * An experimental style for edges. This style is currently not available
- * in the backends and is implemented differently for VML and SVG. The use
- * of this style is currently only recommended for VML.
- */
- STYLE_SMOOTH: 'smooth',
-
- /**
- * Variable: STYLE_SOURCE_PERIMETER_SPACING
- *
- * Defines the key for the source perimeter spacing. The type of this value
- * is numeric. This is the distance between the source connection point of
- * an edge and the perimeter of the source vertex in pixels. This style
- * only applies to edges.
- */
- STYLE_SOURCE_PERIMETER_SPACING: 'sourcePerimeterSpacing',
-
- /**
- * Variable: STYLE_TARGET_PERIMETER_SPACING
- *
- * Defines the key for the target perimeter spacing. The type of this value
- * is numeric. This is the distance between the target connection point of
- * an edge and the perimeter of the target vertex in pixels. This style
- * only applies to edges.
- */
- STYLE_TARGET_PERIMETER_SPACING: 'targetPerimeterSpacing',
-
- /**
- * Variable: STYLE_PERIMETER_SPACING
- *
- * Defines the key for the perimeter spacing. This is the distance between
- * the connection point and the perimeter in pixels. When used in a vertex
- * style, this applies to all incoming edges to floating ports (edges that
- * terminate on the perimeter of the vertex). When used in an edge style,
- * this spacing applies to the source and target separately, if they
- * terminate in floating ports (on the perimeter of the vertex).
- */
- STYLE_PERIMETER_SPACING: 'perimeterSpacing',
-
- /**
- * Variable: STYLE_SPACING
- *
- * Defines the key for the spacing. The value represents the spacing, in
- * pixels, added to each side of a label in a vertex (style applies to
- * vertices only).
- */
- STYLE_SPACING: 'spacing',
-
- /**
- * Variable: STYLE_SPACING_TOP
- *
- * Defines the key for the spacingTop style. The value represents the
- * spacing, in pixels, added to the top side of a label in a vertex (style
- * applies to vertices only).
- */
- STYLE_SPACING_TOP: 'spacingTop',
-
- /**
- * Variable: STYLE_SPACING_LEFT
- *
- * Defines the key for the spacingLeft style. The value represents the
- * spacing, in pixels, added to the left side of a label in a vertex (style
- * applies to vertices only).
- */
- STYLE_SPACING_LEFT: 'spacingLeft',
-
- /**
- * Variable: STYLE_SPACING_BOTTOM
- *
- * Defines the key for the spacingBottom style The value represents the
- * spacing, in pixels, added to the bottom side of a label in a vertex
- * (style applies to vertices only).
- */
- STYLE_SPACING_BOTTOM: 'spacingBottom',
-
- /**
- * Variable: STYLE_SPACING_RIGHT
- *
- * Defines the key for the spacingRight style The value represents the
- * spacing, in pixels, added to the right side of a label in a vertex (style
- * applies to vertices only).
- */
- STYLE_SPACING_RIGHT: 'spacingRight',
-
- /**
- * Variable: STYLE_HORIZONTAL
- *
- * Defines the key for the horizontal style. Possible values are
- * true or false. This value only applies to vertices. If the <STYLE_SHAPE>
- * is <code>SHAPE_SWIMLANE</code> a value of false indicates that the
- * swimlane should be drawn vertically, true indicates to draw it
- * horizontally. If the shape style does not indicate that this vertex is a
- * swimlane, this value affects only whether the label is drawn
- * horizontally or vertically.
- */
- STYLE_HORIZONTAL: 'horizontal',
-
- /**
- * Variable: STYLE_DIRECTION
- *
- * Defines the key for the direction style. The direction style is used
- * to specify the direction of certain shapes (eg. <mxTriangle>).
- * Possible values are <DIRECTION_EAST> (default), <DIRECTION_WEST>,
- * <DIRECTION_NORTH> and <DIRECTION_SOUTH>.
- */
- STYLE_DIRECTION: 'direction',
-
- /**
- * Variable: STYLE_ELBOW
- *
- * Defines the key for the elbow style. Possible values are
- * <ELBOW_HORIZONTAL> and <ELBOW_VERTICAL>. Default is <ELBOW_HORIZONTAL>.
- * This defines how the three segment orthogonal edge style leaves its
- * terminal vertices. The vertical style leaves the terminal vertices at
- * the top and bottom sides.
- */
- STYLE_ELBOW: 'elbow',
-
- /**
- * Variable: STYLE_FONTCOLOR
- *
- * Defines the key for the fontColor style. Possible values are all HTML
- * color names or HEX codes.
- */
- STYLE_FONTCOLOR: 'fontColor',
-
- /**
- * Variable: STYLE_FONTFAMILY
- *
- * Defines the key for the fontFamily style. Possible values are names such
- * as Arial; Dialog; Verdana; Times New Roman. The value is of type String.
- */
- STYLE_FONTFAMILY: 'fontFamily',
-
- /**
- * Variable: STYLE_FONTSIZE
- *
- * Defines the key for the fontSize style (in points). The type of the value
- * is int.
- */
- STYLE_FONTSIZE: 'fontSize',
-
- /**
- * Variable: STYLE_FONTSTYLE
- *
- * Defines the key for the fontStyle style. Values may be any logical AND
- * (sum) of <FONT_BOLD>, <FONT_ITALIC>, <FONT_UNDERLINE> and <FONT_SHADOW>.
- * The type of the value is int.
- */
- STYLE_FONTSTYLE: 'fontStyle',
-
- /**
- * Variable: STYLE_AUTOSIZE
- *
- * Defines the key for the autosize style. This specifies if a cell should be
- * resized automatically if the value has changed. Possible values are 0 or 1.
- * Default is 0. See <mxGraph.isAutoSizeCell>. This is normally combined with
- * <STYLE_RESIZABLE> to disable manual sizing.
- */
- STYLE_AUTOSIZE: 'autosize',
-
- /**
- * Variable: STYLE_FOLDABLE
- *
- * Defines the key for the foldable style. This specifies if a cell is foldable
- * using a folding icon. Possible values are 0 or 1. Default is 1. See
- * <mxGraph.isCellFoldable>.
- */
- STYLE_FOLDABLE: 'foldable',
-
- /**
- * Variable: STYLE_EDITABLE
- *
- * Defines the key for the editable style. This specifies if the value of
- * a cell can be edited using the in-place editor. Possible values are 0 or
- * 1. Default is 1. See <mxGraph.isCellEditable>.
- */
- STYLE_EDITABLE: 'editable',
-
- /**
- * Variable: STYLE_BENDABLE
- *
- * Defines the key for the bendable style. This specifies if the control
- * points of an edge can be moved. Possible values are 0 or 1. Default is
- * 1. See <mxGraph.isCellBendable>.
- */
- STYLE_BENDABLE: 'bendable',
-
- /**
- * Variable: STYLE_MOVABLE
- *
- * Defines the key for the movable style. This specifies if a cell can
- * be moved. Possible values are 0 or 1. Default is 1. See
- * <mxGraph.isCellMovable>.
- */
- STYLE_MOVABLE: 'movable',
-
- /**
- * Variable: STYLE_RESIZABLE
- *
- * Defines the key for the resizable style. This specifies if a cell can
- * be resized. Possible values are 0 or 1. Default is 1. See
- * <mxGraph.isCellResizable>.
- */
- STYLE_RESIZABLE: 'resizable',
-
- /**
- * Variable: STYLE_CLONEABLE
- *
- * Defines the key for the cloneable style. This specifies if a cell can
- * be cloned. Possible values are 0 or 1. Default is 1. See
- * <mxGraph.isCellCloneable>.
- */
- STYLE_CLONEABLE: 'cloneable',
-
- /**
- * Variable: STYLE_DELETABLE
- *
- * Defines the key for the deletable style. This specifies if a cell can be
- * deleted. Possible values are 0 or 1. Default is 1. See
- * <mxGraph.isCellDeletable>.
- */
- STYLE_DELETABLE: 'deletable',
-
- /**
- * Variable: STYLE_SHAPE
- *
- * Defines the key for the shape. Possible values are all constants
- * with a SHAPE-prefix or any newly defined shape names.
- */
- STYLE_SHAPE: 'shape',
-
- /**
- * Variable: STYLE_EDGE
- *
- * Defines the key for the edge style. Possible values are the functions
- * defined in <mxEdgeStyle>.
- */
- STYLE_EDGE: 'edgeStyle',
-
- /**
- * Variable: STYLE_LOOP
- *
- * Defines the key for the loop style. Possible values are the functions
- * defined in <mxEdgeStyle>.
- */
- STYLE_LOOP: 'loopStyle',
-
- /**
- * Variable: STYLE_ROUTING_CENTER_X
- *
- * Defines the key for the horizontal routing center. Possible values are
- * between -0.5 and 0.5. This is the relative offset from the center used
- * for connecting edges. The type of this value is numeric.
- */
- STYLE_ROUTING_CENTER_X: 'routingCenterX',
-
- /**
- * Variable: STYLE_ROUTING_CENTER_Y
- *
- * Defines the key for the vertical routing center. Possible values are
- * between -0.5 and 0.5. This is the relative offset from the center used
- * for connecting edges. The type of this value is numeric.
- */
- STYLE_ROUTING_CENTER_Y: 'routingCenterY',
-
- /**
- * Variable: FONT_BOLD
- *
- * Constant for bold fonts. Default is 1.
- */
- FONT_BOLD: 1,
-
- /**
- * Variable: FONT_ITALIC
- *
- * Constant for italic fonts. Default is 2.
- */
- FONT_ITALIC: 2,
-
- /**
- * Variable: FONT_UNDERLINE
- *
- * Constant for underlined fonts. Default is 4.
- */
- FONT_UNDERLINE: 4,
-
- /**
- * Variable: FONT_SHADOW
- *
- * Constant for fonts with a shadow. Default is 8.
- */
- FONT_SHADOW: 8,
-
- /**
- * Variable: SHAPE_RECTANGLE
- *
- * Name under which <mxRectangleShape> is registered
- * in <mxCellRenderer>. Default is rectangle.
- */
- SHAPE_RECTANGLE: 'rectangle',
-
- /**
- * Variable: SHAPE_ELLIPSE
- *
- * Name under which <mxEllipse> is registered
- * in <mxCellRenderer>. Default is ellipse.
- */
- SHAPE_ELLIPSE: 'ellipse',
-
- /**
- * Variable: SHAPE_DOUBLE_ELLIPSE
- *
- * Name under which <mxDoubleEllipse> is registered
- * in <mxCellRenderer>. Default is doubleEllipse.
- */
- SHAPE_DOUBLE_ELLIPSE: 'doubleEllipse',
-
- /**
- * Variable: SHAPE_RHOMBUS
- *
- * Name under which <mxRhombus> is registered
- * in <mxCellRenderer>. Default is rhombus.
- */
- SHAPE_RHOMBUS: 'rhombus',
-
- /**
- * Variable: SHAPE_LINE
- *
- * Name under which <mxLine> is registered
- * in <mxCellRenderer>. Default is line.
- */
- SHAPE_LINE: 'line',
-
- /**
- * Variable: SHAPE_IMAGE
- *
- * Name under which <mxImageShape> is registered
- * in <mxCellRenderer>. Default is image.
- */
- SHAPE_IMAGE: 'image',
-
- /**
- * Variable: SHAPE_ARROW
- *
- * Name under which <mxArrow> is registered
- * in <mxCellRenderer>. Default is arrow.
- */
- SHAPE_ARROW: 'arrow',
-
- /**
- * Variable: SHAPE_LABEL
- *
- * Name under which <mxLabel> is registered
- * in <mxCellRenderer>. Default is label.
- */
- SHAPE_LABEL: 'label',
-
- /**
- * Variable: SHAPE_CYLINDER
- *
- * Name under which <mxCylinder> is registered
- * in <mxCellRenderer>. Default is cylinder.
- */
- SHAPE_CYLINDER: 'cylinder',
-
- /**
- * Variable: SHAPE_SWIMLANE
- *
- * Name under which <mxSwimlane> is registered
- * in <mxCellRenderer>. Default is swimlane.
- */
- SHAPE_SWIMLANE: 'swimlane',
-
- /**
- * Variable: SHAPE_CONNECTOR
- *
- * Name under which <mxConnector> is registered
- * in <mxCellRenderer>. Default is connector.
- */
- SHAPE_CONNECTOR: 'connector',
-
- /**
- * Variable: SHAPE_ACTOR
- *
- * Name under which <mxActor> is registered
- * in <mxCellRenderer>. Default is actor.
- */
- SHAPE_ACTOR: 'actor',
-
- /**
- * Variable: SHAPE_CLOUD
- *
- * Name under which <mxCloud> is registered
- * in <mxCellRenderer>. Default is cloud.
- */
- SHAPE_CLOUD: 'cloud',
-
- /**
- * Variable: SHAPE_TRIANGLE
- *
- * Name under which <mxTriangle> is registered
- * in <mxCellRenderer>. Default is triangle.
- */
- SHAPE_TRIANGLE: 'triangle',
-
- /**
- * Variable: SHAPE_HEXAGON
- *
- * Name under which <mxHexagon> is registered
- * in <mxCellRenderer>. Default is hexagon.
- */
- SHAPE_HEXAGON: 'hexagon',
-
- /**
- * Variable: ARROW_CLASSIC
- *
- * Constant for classic arrow markers.
- */
- ARROW_CLASSIC: 'classic',
-
- /**
- * Variable: ARROW_BLOCK
- *
- * Constant for block arrow markers.
- */
- ARROW_BLOCK: 'block',
-
- /**
- * Variable: ARROW_OPEN
- *
- * Constant for open arrow markers.
- */
- ARROW_OPEN: 'open',
-
- /**
- * Variable: ARROW_OVAL
- *
- * Constant for oval arrow markers.
- */
- ARROW_OVAL: 'oval',
-
- /**
- * Variable: ARROW_DIAMOND
- *
- * Constant for diamond arrow markers.
- */
- ARROW_DIAMOND: 'diamond',
-
- /**
- * Variable: ARROW_DIAMOND
- *
- * Constant for diamond arrow markers.
- */
- ARROW_DIAMOND_THIN: 'diamondThin',
-
- /**
- * Variable: ALIGN_LEFT
- *
- * Constant for left horizontal alignment. Default is left.
- */
- ALIGN_LEFT: 'left',
-
- /**
- * Variable: ALIGN_CENTER
- *
- * Constant for center horizontal alignment. Default is center.
- */
- ALIGN_CENTER: 'center',
-
- /**
- * Variable: ALIGN_RIGHT
- *
- * Constant for right horizontal alignment. Default is right.
- */
- ALIGN_RIGHT: 'right',
-
- /**
- * Variable: ALIGN_TOP
- *
- * Constant for top vertical alignment. Default is top.
- */
- ALIGN_TOP: 'top',
-
- /**
- * Variable: ALIGN_MIDDLE
- *
- * Constant for middle vertical alignment. Default is middle.
- */
- ALIGN_MIDDLE: 'middle',
-
- /**
- * Variable: ALIGN_BOTTOM
- *
- * Constant for bottom vertical alignment. Default is bottom.
- */
- ALIGN_BOTTOM: 'bottom',
-
- /**
- * Variable: DIRECTION_NORTH
- *
- * Constant for direction north. Default is north.
- */
- DIRECTION_NORTH: 'north',
-
- /**
- * Variable: DIRECTION_SOUTH
- *
- * Constant for direction south. Default is south.
- */
- DIRECTION_SOUTH: 'south',
-
- /**
- * Variable: DIRECTION_EAST
- *
- * Constant for direction east. Default is east.
- */
- DIRECTION_EAST: 'east',
-
- /**
- * Variable: DIRECTION_WEST
- *
- * Constant for direction west. Default is west.
- */
- DIRECTION_WEST: 'west',
-
- /**
- * Variable: DIRECTION_MASK_NONE
- *
- * Constant for no direction.
- */
- DIRECTION_MASK_NONE: 0,
-
- /**
- * Variable: DIRECTION_MASK_WEST
- *
- * Bitwise mask for west direction.
- */
- DIRECTION_MASK_WEST: 1,
-
- /**
- * Variable: DIRECTION_MASK_NORTH
- *
- * Bitwise mask for north direction.
- */
- DIRECTION_MASK_NORTH: 2,
-
- /**
- * Variable: DIRECTION_MASK_SOUTH
- *
- * Bitwise mask for south direction.
- */
- DIRECTION_MASK_SOUTH: 4,
-
- /**
- * Variable: DIRECTION_MASK_EAST
- *
- * Bitwise mask for east direction.
- */
- DIRECTION_MASK_EAST: 8,
-
- /**
- * Variable: DIRECTION_MASK_ALL
- *
- * Bitwise mask for all directions.
- */
- DIRECTION_MASK_ALL: 15,
-
- /**
- * Variable: ELBOW_VERTICAL
- *
- * Constant for elbow vertical. Default is horizontal.
- */
- ELBOW_VERTICAL: 'vertical',
-
- /**
- * Variable: ELBOW_HORIZONTAL
- *
- * Constant for elbow horizontal. Default is horizontal.
- */
- ELBOW_HORIZONTAL: 'horizontal',
-
- /**
- * Variable: EDGESTYLE_ELBOW
- *
- * Name of the elbow edge style. Can be used as a string value
- * for the STYLE_EDGE style.
- */
- EDGESTYLE_ELBOW: 'elbowEdgeStyle',
-
- /**
- * Variable: EDGESTYLE_ENTITY_RELATION
- *
- * Name of the entity relation edge style. Can be used as a string value
- * for the STYLE_EDGE style.
- */
- EDGESTYLE_ENTITY_RELATION: 'entityRelationEdgeStyle',
-
- /**
- * Variable: EDGESTYLE_LOOP
- *
- * Name of the loop edge style. Can be used as a string value
- * for the STYLE_EDGE style.
- */
- EDGESTYLE_LOOP: 'loopEdgeStyle',
-
- /**
- * Variable: EDGESTYLE_SIDETOSIDE
- *
- * Name of the side to side edge style. Can be used as a string value
- * for the STYLE_EDGE style.
- */
- EDGESTYLE_SIDETOSIDE: 'sideToSideEdgeStyle',
-
- /**
- * Variable: EDGESTYLE_TOPTOBOTTOM
- *
- * Name of the top to bottom edge style. Can be used as a string value
- * for the STYLE_EDGE style.
- */
- EDGESTYLE_TOPTOBOTTOM: 'topToBottomEdgeStyle',
-
- /**
- * Variable: EDGESTYLE_ORTHOGONAL
- *
- * Name of the generic orthogonal edge style. Can be used as a string value
- * for the STYLE_EDGE style.
- */
- EDGESTYLE_ORTHOGONAL: 'orthogonalEdgeStyle',
-
- /**
- * Variable: EDGESTYLE_SEGMENT
- *
- * Name of the generic segment edge style. Can be used as a string value
- * for the STYLE_EDGE style.
- */
- EDGESTYLE_SEGMENT: 'segmentEdgeStyle',
-
- /**
- * Variable: PERIMETER_ELLIPSE
- *
- * Name of the ellipse perimeter. Can be used as a string value
- * for the STYLE_PERIMETER style.
- */
- PERIMETER_ELLIPSE: 'ellipsePerimeter',
-
- /**
- * Variable: PERIMETER_RECTANGLE
- *
- * Name of the rectangle perimeter. Can be used as a string value
- * for the STYLE_PERIMETER style.
- */
- PERIMETER_RECTANGLE: 'rectanglePerimeter',
-
- /**
- * Variable: PERIMETER_RHOMBUS
- *
- * Name of the rhombus perimeter. Can be used as a string value
- * for the STYLE_PERIMETER style.
- */
- PERIMETER_RHOMBUS: 'rhombusPerimeter',
-
- /**
- * Variable: PERIMETER_TRIANGLE
- *
- * Name of the triangle perimeter. Can be used as a string value
- * for the STYLE_PERIMETER style.
- */
- PERIMETER_TRIANGLE: 'trianglePerimeter'
-
-};
diff --git a/src/js/util/mxDictionary.js b/src/js/util/mxDictionary.js
deleted file mode 100644
index a2e503a..0000000
--- a/src/js/util/mxDictionary.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * $Id: mxDictionary.js,v 1.12 2012-04-26 08:08:54 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxDictionary
- *
- * A wrapper class for an associative array with object keys. Note: This
- * implementation uses <mxObjectIdentitiy> to turn object keys into strings.
- *
- * Constructor: mxEventSource
- *
- * Constructs a new dictionary which allows object to be used as keys.
- */
-function mxDictionary()
-{
- this.clear();
-};
-
-/**
- * Function: map
- *
- * Stores the (key, value) pairs in this dictionary.
- */
-mxDictionary.prototype.map = null;
-
-/**
- * Function: clear
- *
- * Clears the dictionary.
- */
-mxDictionary.prototype.clear = function()
-{
- this.map = {};
-};
-
-/**
- * Function: get
- *
- * Returns the value for the given key.
- */
-mxDictionary.prototype.get = function(key)
-{
- var id = mxObjectIdentity.get(key);
-
- return this.map[id];
-};
-
-/**
- * Function: put
- *
- * Stores the value under the given key and returns the previous
- * value for that key.
- */
-mxDictionary.prototype.put = function(key, value)
-{
- var id = mxObjectIdentity.get(key);
- var previous = this.map[id];
- this.map[id] = value;
-
- return previous;
-};
-
-/**
- * Function: remove
- *
- * Removes the value for the given key and returns the value that
- * has been removed.
- */
-mxDictionary.prototype.remove = function(key)
-{
- var id = mxObjectIdentity.get(key);
- var previous = this.map[id];
- delete this.map[id];
-
- return previous;
-};
-
-/**
- * Function: getKeys
- *
- * Returns all keys as an array.
- */
-mxDictionary.prototype.getKeys = function()
-{
- var result = [];
-
- for (var key in this.map)
- {
- result.push(key);
- }
-
- return result;
-};
-
-/**
- * Function: getValues
- *
- * Returns all values as an array.
- */
-mxDictionary.prototype.getValues = function()
-{
- var result = [];
-
- for (var key in this.map)
- {
- result.push(this.map[key]);
- }
-
- return result;
-};
-
-/**
- * Function: visit
- *
- * Visits all entries in the dictionary using the given function with the
- * following signature: function(key, value) where key is a string and
- * value is an object.
- *
- * Parameters:
- *
- * visitor - A function that takes the key and value as arguments.
- */
-mxDictionary.prototype.visit = function(visitor)
-{
- for (var key in this.map)
- {
- visitor(key, this.map[key]);
- }
-};
diff --git a/src/js/util/mxDivResizer.js b/src/js/util/mxDivResizer.js
deleted file mode 100644
index 2a2e4eb..0000000
--- a/src/js/util/mxDivResizer.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * $Id: mxDivResizer.js,v 1.22 2010-01-02 09:45:14 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxDivResizer
- *
- * Maintains the size of a div element in Internet Explorer. This is a
- * workaround for the right and bottom style being ignored in IE.
- *
- * If you need a div to cover the scrollwidth and -height of a document,
- * then you can use this class as follows:
- *
- * (code)
- * var resizer = new mxDivResizer(background);
- * resizer.getDocumentHeight = function()
- * {
- * return document.body.scrollHeight;
- * }
- * resizer.getDocumentWidth = function()
- * {
- * return document.body.scrollWidth;
- * }
- * resizer.resize();
- * (end)
- *
- * Constructor: mxDivResizer
- *
- * Constructs an object that maintains the size of a div
- * element when the window is being resized. This is only
- * required for Internet Explorer as it ignores the respective
- * stylesheet information for DIV elements.
- *
- * Parameters:
- *
- * div - Reference to the DOM node whose size should be maintained.
- * container - Optional Container that contains the div. Default is the
- * window.
- */
-function mxDivResizer(div, container)
-{
- if (div.nodeName.toLowerCase() == 'div')
- {
- if (container == null)
- {
- container = window;
- }
-
- this.div = div;
- var style = mxUtils.getCurrentStyle(div);
-
- if (style != null)
- {
- this.resizeWidth = style.width == 'auto';
- this.resizeHeight = style.height == 'auto';
- }
-
- mxEvent.addListener(container, 'resize',
- mxUtils.bind(this, function(evt)
- {
- if (!this.handlingResize)
- {
- this.handlingResize = true;
- this.resize();
- this.handlingResize = false;
- }
- })
- );
-
- this.resize();
- }
-};
-
-/**
- * Function: resizeWidth
- *
- * Boolean specifying if the width should be updated.
- */
-mxDivResizer.prototype.resizeWidth = true;
-
-/**
- * Function: resizeHeight
- *
- * Boolean specifying if the height should be updated.
- */
-mxDivResizer.prototype.resizeHeight = true;
-
-/**
- * Function: handlingResize
- *
- * Boolean specifying if the width should be updated.
- */
-mxDivResizer.prototype.handlingResize = false;
-
-/**
- * Function: resize
- *
- * Updates the style of the DIV after the window has been resized.
- */
-mxDivResizer.prototype.resize = function()
-{
- var w = this.getDocumentWidth();
- var h = this.getDocumentHeight();
-
- var l = parseInt(this.div.style.left);
- var r = parseInt(this.div.style.right);
- var t = parseInt(this.div.style.top);
- var b = parseInt(this.div.style.bottom);
-
- if (this.resizeWidth &&
- !isNaN(l) &&
- !isNaN(r) &&
- l >= 0 &&
- r >= 0 &&
- w - r - l > 0)
- {
- this.div.style.width = (w - r - l)+'px';
- }
-
- if (this.resizeHeight &&
- !isNaN(t) &&
- !isNaN(b) &&
- t >= 0 &&
- b >= 0 &&
- h - t - b > 0)
- {
- this.div.style.height = (h - t - b)+'px';
- }
-};
-
-/**
- * Function: getDocumentWidth
- *
- * Hook for subclassers to return the width of the document (without
- * scrollbars).
- */
-mxDivResizer.prototype.getDocumentWidth = function()
-{
- return document.body.clientWidth;
-};
-
-/**
- * Function: getDocumentHeight
- *
- * Hook for subclassers to return the height of the document (without
- * scrollbars).
- */
-mxDivResizer.prototype.getDocumentHeight = function()
-{
- return document.body.clientHeight;
-};
diff --git a/src/js/util/mxDragSource.js b/src/js/util/mxDragSource.js
deleted file mode 100644
index d0cafdf..0000000
--- a/src/js/util/mxDragSource.js
+++ /dev/null
@@ -1,594 +0,0 @@
-/**
- * $Id: mxDragSource.js,v 1.14 2012-12-05 21:43:16 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxDragSource
- *
- * Wrapper to create a drag source from a DOM element so that the element can
- * be dragged over a graph and dropped into the graph as a new cell.
- *
- * TODO: Problem is that in the dropHandler the current preview location is
- * not available, so the preview and the dropHandler must match.
- *
- * Constructor: mxDragSource
- *
- * Constructs a new drag source for the given element.
- */
-function mxDragSource(element, dropHandler)
-{
- this.element = element;
- this.dropHandler = dropHandler;
-
- // Handles a drag gesture on the element
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- mxEvent.addListener(element, md, mxUtils.bind(this, this.mouseDown));
-};
-
-/**
- * Variable: element
- *
- * Reference to the DOM node which was made draggable.
- */
-mxDragSource.prototype.element = null;
-
-/**
- * Variable: dropHandler
- *
- * Holds the DOM node that is used to represent the drag preview. If this is
- * null then the source element will be cloned and used for the drag preview.
- */
-mxDragSource.prototype.dropHandler = null;
-
-/**
- * Variable: dragOffset
- *
- * <mxPoint> that specifies the offset of the <dragElement>. Default is null.
- */
-mxDragSource.prototype.dragOffset = null;
-
-/**
- * Variable: dragElement
- *
- * Holds the DOM node that is used to represent the drag preview. If this is
- * null then the source element will be cloned and used for the drag preview.
- */
-mxDragSource.prototype.dragElement = null;
-
-/**
- * Variable: previewElement
- *
- * Optional <mxRectangle> that specifies the unscaled size of the preview.
- */
-mxDragSource.prototype.previewElement = null;
-
-/**
- * Variable: enabled
- *
- * Specifies if this drag source is enabled. Default is true.
- */
-mxDragSource.prototype.enabled = true;
-
-/**
- * Variable: currentGraph
- *
- * Reference to the <mxGraph> that is the current drop target.
- */
-mxDragSource.prototype.currentGraph = null;
-
-/**
- * Variable: currentDropTarget
- *
- * Holds the current drop target under the mouse.
- */
-mxDragSource.prototype.currentDropTarget = null;
-
-/**
- * Variable: currentPoint
- *
- * Holds the current drop location.
- */
-mxDragSource.prototype.currentPoint = null;
-
-/**
- * Variable: currentGuide
- *
- * Holds an <mxGuide> for the <currentGraph> if <dragPreview> is not null.
- */
-mxDragSource.prototype.currentGuide = null;
-
-/**
- * Variable: currentGuide
- *
- * Holds an <mxGuide> for the <currentGraph> if <dragPreview> is not null.
- */
-mxDragSource.prototype.currentHighlight = null;
-
-/**
- * Variable: autoscroll
- *
- * Specifies if the graph should scroll automatically. Default is true.
- */
-mxDragSource.prototype.autoscroll = true;
-
-/**
- * Variable: guidesEnabled
- *
- * Specifies if <mxGuide> should be enabled. Default is true.
- */
-mxDragSource.prototype.guidesEnabled = true;
-
-/**
- * Variable: gridEnabled
- *
- * Specifies if the grid should be allowed. Default is true.
- */
-mxDragSource.prototype.gridEnabled = true;
-
-/**
- * Variable: highlightDropTargets
- *
- * Specifies if drop targets should be highlighted. Default is true.
- */
-mxDragSource.prototype.highlightDropTargets = true;
-
-/**
- * Variable: dragElementZIndex
- *
- * ZIndex for the drag element. Default is 100.
- */
-mxDragSource.prototype.dragElementZIndex = 100;
-
-/**
- * Variable: dragElementOpacity
- *
- * Opacity of the drag element in %. Default is 70.
- */
-mxDragSource.prototype.dragElementOpacity = 70;
-
-/**
- * Function: isEnabled
- *
- * Returns <enabled>.
- */
-mxDragSource.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Sets <enabled>.
- */
-mxDragSource.prototype.setEnabled = function(value)
-{
- this.enabled = value;
-};
-
-/**
- * Function: isGuidesEnabled
- *
- * Returns <guidesEnabled>.
- */
-mxDragSource.prototype.isGuidesEnabled = function()
-{
- return this.guidesEnabled;
-};
-
-/**
- * Function: setGuidesEnabled
- *
- * Sets <guidesEnabled>.
- */
-mxDragSource.prototype.setGuidesEnabled = function(value)
-{
- this.guidesEnabled = value;
-};
-
-/**
- * Function: isGridEnabled
- *
- * Returns <gridEnabled>.
- */
-mxDragSource.prototype.isGridEnabled = function()
-{
- return this.gridEnabled;
-};
-
-/**
- * Function: setGridEnabled
- *
- * Sets <gridEnabled>.
- */
-mxDragSource.prototype.setGridEnabled = function(value)
-{
- this.gridEnabled = value;
-};
-
-/**
- * Function: getGraphForEvent
- *
- * Returns the graph for the given mouse event. This implementation returns
- * null.
- */
-mxDragSource.prototype.getGraphForEvent = function(evt)
-{
- return null;
-};
-
-/**
- * Function: getDropTarget
- *
- * Returns the drop target for the given graph and coordinates. This
- * implementation uses <mxGraph.getCellAt>.
- */
-mxDragSource.prototype.getDropTarget = function(graph, x, y)
-{
- return graph.getCellAt(x, y);
-};
-
-/**
- * Function: createDragElement
- *
- * Creates and returns a clone of the <dragElementPrototype> or the <element>
- * if the former is not defined.
- */
-mxDragSource.prototype.createDragElement = function(evt)
-{
- return this.element.cloneNode(true);
-};
-
-/**
- * Function: createPreviewElement
- *
- * Creates and returns an element which can be used as a preview in the given
- * graph.
- */
-mxDragSource.prototype.createPreviewElement = function(graph)
-{
- return null;
-};
-
-/**
- * Function: mouseDown
- *
- * Returns the drop target for the given graph and coordinates. This
- * implementation uses <mxGraph.getCellAt>.
- */
-mxDragSource.prototype.mouseDown = function(evt)
-{
- if (this.enabled && !mxEvent.isConsumed(evt) && this.mouseMoveHandler == null)
- {
- this.startDrag(evt);
-
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- this.mouseMoveHandler = mxUtils.bind(this, this.mouseMove);
- mxEvent.addListener(document, mm, this.mouseMoveHandler);
- this.mouseUpHandler = mxUtils.bind(this, this.mouseUp);
- mxEvent.addListener(document, mu, this.mouseUpHandler);
-
- // Prevents default action (native DnD for images in FF 10)
- // but does not stop event propagation
- mxEvent.consume(evt, true, false);
- }
-};
-
-/**
- * Function: startDrag
- *
- * Creates the <dragElement> using <createDragElement>.
- */
-mxDragSource.prototype.startDrag = function(evt)
-{
- this.dragElement = this.createDragElement(evt);
- this.dragElement.style.position = 'absolute';
- this.dragElement.style.zIndex = this.dragElementZIndex;
- mxUtils.setOpacity(this.dragElement, this.dragElementOpacity);
-};
-
-
-/**
- * Function: stopDrag
- *
- * Removes and destroys the <dragElement>.
- */
-mxDragSource.prototype.stopDrag = function(evt)
-{
- if (this.dragElement != null)
- {
- if (this.dragElement.parentNode != null)
- {
- this.dragElement.parentNode.removeChild(this.dragElement);
- }
-
- this.dragElement = null;
- }
-};
-
-/**
- * Function: graphContainsEvent
- *
- * Returns true if the given graph contains the given event.
- */
-mxDragSource.prototype.graphContainsEvent = function(graph, evt)
-{
- var x = mxEvent.getClientX(evt);
- var y = mxEvent.getClientY(evt);
- var offset = mxUtils.getOffset(graph.container);
- var origin = mxUtils.getScrollOrigin();
-
- // Checks if event is inside the bounds of the graph container
- return x >= offset.x - origin.x && y >= offset.y - origin.y &&
- x <= offset.x - origin.x + graph.container.offsetWidth &&
- y <= offset.y - origin.y + graph.container.offsetHeight;
-};
-
-/**
- * Function: mouseMove
- *
- * Gets the graph for the given event using <getGraphForEvent>, updates the
- * <currentGraph>, calling <dragEnter> and <dragExit> on the new and old graph,
- * respectively, and invokes <dragOver> if <currentGraph> is not null.
- */
-mxDragSource.prototype.mouseMove = function(evt)
-{
- var graph = this.getGraphForEvent(evt);
-
- // Checks if event is inside the bounds of the graph container
- if (graph != null && !this.graphContainsEvent(graph, evt))
- {
- graph = null;
- }
-
- if (graph != this.currentGraph)
- {
- if (this.currentGraph != null)
- {
- this.dragExit(this.currentGraph);
- }
-
- this.currentGraph = graph;
-
- if (this.currentGraph != null)
- {
- this.dragEnter(this.currentGraph);
- }
- }
-
- if (this.currentGraph != null)
- {
- this.dragOver(this.currentGraph, evt);
- }
-
- if (this.dragElement != null && (this.previewElement == null || this.previewElement.style.visibility != 'visible'))
- {
- var x = mxEvent.getClientX(evt);
- var y = mxEvent.getClientY(evt);
-
- if (this.dragElement.parentNode == null)
- {
- document.body.appendChild(this.dragElement);
- }
-
- this.dragElement.style.visibility = 'visible';
-
- if (this.dragOffset != null)
- {
- x += this.dragOffset.x;
- y += this.dragOffset.y;
- }
-
- x += document.body.scrollLeft || document.documentElement.scrollLeft;
- y += document.body.scrollTop || document.documentElement.scrollTop;
- this.dragElement.style.left = x + 'px';
- this.dragElement.style.top = y + 'px';
- }
- else if (this.dragElement != null)
- {
- this.dragElement.style.visibility = 'hidden';
- }
-
- mxEvent.consume(evt);
-};
-
-/**
- * Function: mouseUp
- *
- * Processes the mouse up event and invokes <drop>, <dragExit> and <stopDrag>
- * as required.
- */
-mxDragSource.prototype.mouseUp = function(evt)
-{
- if (this.currentGraph != null)
- {
- if (this.currentPoint != null && (this.previewElement == null ||
- this.previewElement.style.visibility != 'hidden'))
- {
- var scale = this.currentGraph.view.scale;
- var tr = this.currentGraph.view.translate;
- var x = this.currentPoint.x / scale - tr.x;
- var y = this.currentPoint.y / scale - tr.y;
-
- this.drop(this.currentGraph, evt, this.currentDropTarget, x, y);
- }
-
- this.dragExit(this.currentGraph);
- }
-
- this.stopDrag(evt);
-
- this.currentGraph = null;
-
- if (this.mouseMoveHandler != null)
- {
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- mxEvent.removeListener(document, mm, this.mouseMoveHandler);
- this.mouseMoveHandler = null;
- }
-
- if (this.mouseUpHandler != null)
- {
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
- mxEvent.removeListener(document, mu, this.mouseUpHandler);
- this.mouseUpHandler = null;
- }
-
- mxEvent.consume(evt);
-};
-
-/**
- * Function: dragEnter
- *
- * Actives the given graph as a drop target.
- */
-mxDragSource.prototype.dragEnter = function(graph)
-{
- graph.isMouseDown = true;
- this.previewElement = this.createPreviewElement(graph);
-
- // Guide is only needed if preview element is used
- if (this.isGuidesEnabled() && this.previewElement != null)
- {
- this.currentGuide = new mxGuide(graph, graph.graphHandler.getGuideStates());
- }
-
- if (this.highlightDropTargets)
- {
- this.currentHighlight = new mxCellHighlight(graph, mxConstants.DROP_TARGET_COLOR);
- }
-};
-
-/**
- * Function: dragExit
- *
- * Deactivates the given graph as a drop target.
- */
-mxDragSource.prototype.dragExit = function(graph)
-{
- this.currentDropTarget = null;
- this.currentPoint = null;
- graph.isMouseDown = false;
-
- if (this.previewElement != null)
- {
- if (this.previewElement.parentNode != null)
- {
- this.previewElement.parentNode.removeChild(this.previewElement);
- }
-
- this.previewElement = null;
- }
-
- if (this.currentGuide != null)
- {
- this.currentGuide.destroy();
- this.currentGuide = null;
- }
-
- if (this.currentHighlight != null)
- {
- this.currentHighlight.destroy();
- this.currentHighlight = null;
- }
-};
-
-/**
- * Function: dragOver
- *
- * Implements autoscroll, updates the <currentPoint>, highlights any drop
- * targets and updates the preview.
- */
-mxDragSource.prototype.dragOver = function(graph, evt)
-{
- var offset = mxUtils.getOffset(graph.container);
- var origin = mxUtils.getScrollOrigin(graph.container);
- var x = mxEvent.getClientX(evt) - offset.x + origin.x;
- var y = mxEvent.getClientY(evt) - offset.y + origin.y;
-
- if (graph.autoScroll && (this.autoscroll == null || this.autoscroll))
- {
- graph.scrollPointToVisible(x, y, graph.autoExtend);
- }
-
- // Highlights the drop target under the mouse
- if (this.currentHighlight != null && graph.isDropEnabled())
- {
- this.currentDropTarget = this.getDropTarget(graph, x, y);
- var state = graph.getView().getState(this.currentDropTarget);
- this.currentHighlight.highlight(state);
- }
-
- // Updates the location of the preview
- if (this.previewElement != null)
- {
- if (this.previewElement.parentNode == null)
- {
- graph.container.appendChild(this.previewElement);
-
- this.previewElement.style.zIndex = '3';
- this.previewElement.style.position = 'absolute';
- }
-
- var gridEnabled = this.isGridEnabled() && graph.isGridEnabledEvent(evt);
- var hideGuide = true;
-
- // Grid and guides
- if (this.currentGuide != null && this.currentGuide.isEnabledForEvent(evt))
- {
- // LATER: HTML preview appears smaller than SVG preview
- var w = parseInt(this.previewElement.style.width);
- var h = parseInt(this.previewElement.style.height);
- var bounds = new mxRectangle(0, 0, w, h);
- var delta = new mxPoint(x, y);
- delta = this.currentGuide.move(bounds, delta, gridEnabled);
- hideGuide = false;
- x = delta.x;
- y = delta.y;
- }
- else if (gridEnabled)
- {
- var scale = graph.view.scale;
- var tr = graph.view.translate;
- var off = graph.gridSize / 2;
- x = (graph.snap(x / scale - tr.x - off) + tr.x) * scale;
- y = (graph.snap(y / scale - tr.y - off) + tr.y) * scale;
- }
-
- if (this.currentGuide != null && hideGuide)
- {
- this.currentGuide.hide();
- }
-
- if (this.previewOffset != null)
- {
- x += this.previewOffset.x;
- y += this.previewOffset.y;
- }
-
- this.previewElement.style.left = Math.round(x) + 'px';
- this.previewElement.style.top = Math.round(y) + 'px';
- this.previewElement.style.visibility = 'visible';
- }
-
- this.currentPoint = new mxPoint(x, y);
-};
-
-/**
- * Function: drop
- *
- * Returns the drop target for the given graph and coordinates. This
- * implementation uses <mxGraph.getCellAt>.
- */
-mxDragSource.prototype.drop = function(graph, evt, dropTarget, x, y)
-{
- this.dropHandler(graph, evt, dropTarget, x, y);
-
- // Had to move this to after the insert because it will
- // affect the scrollbars of the window in IE to try and
- // make the complete container visible.
- // LATER: Should be made optional.
- graph.container.focus();
-};
diff --git a/src/js/util/mxEffects.js b/src/js/util/mxEffects.js
deleted file mode 100644
index 89d6a71..0000000
--- a/src/js/util/mxEffects.js
+++ /dev/null
@@ -1,214 +0,0 @@
-/**
- * $Id: mxEffects.js,v 1.6 2012-01-04 10:01:16 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxEffects =
-{
-
- /**
- * Class: mxEffects
- *
- * Provides animation effects.
- */
-
- /**
- * Function: animateChanges
- *
- * Asynchronous animated move operation. See also: <mxMorphing>.
- *
- * Example:
- *
- * (code)
- * graph.model.addListener(mxEvent.CHANGE, function(sender, evt)
- * {
- * var changes = evt.getProperty('edit').changes;
- *
- * if (changes.length < 10)
- * {
- * mxEffects.animateChanges(graph, changes);
- * }
- * });
- * (end)
- *
- * Parameters:
- *
- * graph - <mxGraph> that received the changes.
- * changes - Array of changes to be animated.
- * done - Optional function argument that is invoked after the
- * last step of the animation.
- */
- animateChanges: function(graph, changes, done)
- {
- var maxStep = 10;
- var step = 0;
-
- var animate = function()
- {
- var isRequired = false;
-
- for (var i = 0; i < changes.length; i++)
- {
- var change = changes[i];
-
- if (change instanceof mxGeometryChange ||
- change instanceof mxTerminalChange ||
- change instanceof mxValueChange ||
- change instanceof mxChildChange ||
- change instanceof mxStyleChange)
- {
- var state = graph.getView().getState(change.cell || change.child, false);
-
- if (state != null)
- {
- isRequired = true;
-
- if (change.constructor != mxGeometryChange || graph.model.isEdge(change.cell))
- {
- mxUtils.setOpacity(state.shape.node, 100 * step / maxStep);
- }
- else
- {
- var scale = graph.getView().scale;
-
- var dx = (change.geometry.x - change.previous.x) * scale;
- var dy = (change.geometry.y - change.previous.y) * scale;
-
- var sx = (change.geometry.width - change.previous.width) * scale;
- var sy = (change.geometry.height - change.previous.height) * scale;
-
- if (step == 0)
- {
- state.x -= dx;
- state.y -= dy;
- state.width -= sx;
- state.height -= sy;
- }
- else
- {
- state.x += dx / maxStep;
- state.y += dy / maxStep;
- state.width += sx / maxStep;
- state.height += sy / maxStep;
- }
-
- graph.cellRenderer.redraw(state);
-
- // Fades all connected edges and children
- mxEffects.cascadeOpacity(graph, change.cell, 100 * step / maxStep);
- }
- }
- }
- }
-
- // Workaround to force a repaint in AppleWebKit
- mxUtils.repaintGraph(graph, new mxPoint(1, 1));
-
- if (step < maxStep && isRequired)
- {
- step++;
- window.setTimeout(animate, delay);
- }
- else if (done != null)
- {
- done();
- }
- };
-
- var delay = 30;
- animate();
- },
-
- /**
- * Function: cascadeOpacity
- *
- * Sets the opacity on the given cell and its descendants.
- *
- * Parameters:
- *
- * graph - <mxGraph> that contains the cells.
- * cell - <mxCell> to set the opacity for.
- * opacity - New value for the opacity in %.
- */
- cascadeOpacity: function(graph, cell, opacity)
- {
- // Fades all children
- var childCount = graph.model.getChildCount(cell);
-
- for (var i=0; i<childCount; i++)
- {
- var child = graph.model.getChildAt(cell, i);
- var childState = graph.getView().getState(child);
-
- if (childState != null)
- {
- mxUtils.setOpacity(childState.shape.node, opacity);
- mxEffects.cascadeOpacity(graph, child, opacity);
- }
- }
-
- // Fades all connected edges
- var edges = graph.model.getEdges(cell);
-
- if (edges != null)
- {
- for (var i=0; i<edges.length; i++)
- {
- var edgeState = graph.getView().getState(edges[i]);
-
- if (edgeState != null)
- {
- mxUtils.setOpacity(edgeState.shape.node, opacity);
- }
- }
- }
- },
-
- /**
- * Function: fadeOut
- *
- * Asynchronous fade-out operation.
- */
- fadeOut: function(node, from, remove, step, delay, isEnabled)
- {
- step = step || 40;
- delay = delay || 30;
-
- var opacity = from || 100;
-
- mxUtils.setOpacity(node, opacity);
-
- if (isEnabled || isEnabled == null)
- {
- var f = function()
- {
- opacity = Math.max(opacity-step, 0);
- mxUtils.setOpacity(node, opacity);
-
- if (opacity > 0)
- {
- window.setTimeout(f, delay);
- }
- else
- {
- node.style.visibility = 'hidden';
-
- if (remove && node.parentNode)
- {
- node.parentNode.removeChild(node);
- }
- }
- };
- window.setTimeout(f, delay);
- }
- else
- {
- node.style.visibility = 'hidden';
-
- if (remove && node.parentNode)
- {
- node.parentNode.removeChild(node);
- }
- }
- }
-
-};
diff --git a/src/js/util/mxEvent.js b/src/js/util/mxEvent.js
deleted file mode 100644
index f831631..0000000
--- a/src/js/util/mxEvent.js
+++ /dev/null
@@ -1,1175 +0,0 @@
-/**
- * $Id: mxEvent.js,v 1.76 2012-12-07 07:39:03 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxEvent =
-{
-
- /**
- * Class: mxEvent
- *
- * Cross-browser DOM event support. For internal event handling,
- * <mxEventSource> and the graph event dispatch loop in <mxGraph> are used.
- *
- * Memory Leaks:
- *
- * Use this class for adding and removing listeners to/from DOM nodes. The
- * <removeAllListeners> function is provided to remove all listeners that
- * have been added using <addListener>. The function should be invoked when
- * the last reference is removed in the JavaScript code, typically when the
- * referenced DOM node is removed from the DOM, and helps to reduce memory
- * leaks in IE6.
- *
- * Variable: objects
- *
- * Contains all objects where any listener was added using <addListener>.
- * This is used to reduce memory leaks in IE, see <mxClient.dispose>.
- */
- objects: [],
-
- /**
- * Function: addListener
- *
- * Binds the function to the specified event on the given element. Use
- * <mxUtils.bind> in order to bind the "this" keyword inside the function
- * to a given execution scope.
- */
- addListener: function()
- {
- var updateListenerList = function(element, eventName, funct)
- {
- if (element.mxListenerList == null)
- {
- element.mxListenerList = [];
- mxEvent.objects.push(element);
- }
-
- var entry = {name: eventName, f: funct};
- element.mxListenerList.push(entry);
- };
-
- if (window.addEventListener)
- {
- return function(element, eventName, funct)
- {
- element.addEventListener(eventName, funct, false);
- updateListenerList(element, eventName, funct);
- };
- }
- else
- {
- return function(element, eventName, funct)
- {
- element.attachEvent('on' + eventName, funct);
- updateListenerList(element, eventName, funct);
- };
- }
- }(),
-
- /**
- * Function: removeListener
- *
- * Removes the specified listener from the given element.
- */
- removeListener: function()
- {
- var updateListener = function(element, eventName, funct)
- {
- if (element.mxListenerList != null)
- {
- var listenerCount = element.mxListenerList.length;
-
- for (var i=0; i<listenerCount; i++)
- {
- var entry = element.mxListenerList[i];
-
- if (entry.f == funct)
- {
- element.mxListenerList.splice(i, 1);
- break;
- }
- }
-
- if (element.mxListenerList.length == 0)
- {
- element.mxListenerList = null;
- }
- }
- };
-
- if (window.removeEventListener)
- {
- return function(element, eventName, funct)
- {
- element.removeEventListener(eventName, funct, false);
- updateListener(element, eventName, funct);
- };
- }
- else
- {
- return function(element, eventName, funct)
- {
- element.detachEvent('on' + eventName, funct);
- updateListener(element, eventName, funct);
- };
- }
- }(),
-
- /**
- * Function: removeAllListeners
- *
- * Removes all listeners from the given element.
- */
- removeAllListeners: function(element)
- {
- var list = element.mxListenerList;
-
- if (list != null)
- {
- while (list.length > 0)
- {
- var entry = list[0];
- mxEvent.removeListener(element, entry.name, entry.f);
- }
- }
- },
-
- /**
- * Function: redirectMouseEvents
- *
- * Redirects the mouse events from the given DOM node to the graph dispatch
- * loop using the event and given state as event arguments. State can
- * either be an instance of <mxCellState> or a function that returns an
- * <mxCellState>. The down, move, up and dblClick arguments are optional
- * functions that take the trigger event as arguments and replace the
- * default behaviour.
- */
- redirectMouseEvents: function(node, graph, state, down, move, up, dblClick)
- {
- var getState = function(evt)
- {
- return (typeof(state) == 'function') ? state(evt) : state;
- };
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- mxEvent.addListener(node, md, function (evt)
- {
- if (down != null)
- {
- down(evt);
- }
- else if (!mxEvent.isConsumed(evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_DOWN,
- new mxMouseEvent(evt, getState(evt)));
- }
- });
-
- mxEvent.addListener(node, mm, function (evt)
- {
- if (move != null)
- {
- move(evt);
- }
- else if (!mxEvent.isConsumed(evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
- new mxMouseEvent(evt, getState(evt)));
- }
- });
-
- mxEvent.addListener(node, mu, function (evt)
- {
- if (up != null)
- {
- up(evt);
- }
- else if (!mxEvent.isConsumed(evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_UP,
- new mxMouseEvent(evt, getState(evt)));
- }
- });
-
- mxEvent.addListener(node, 'dblclick', function (evt)
- {
- if (dblClick != null)
- {
- dblClick(evt);
- }
- else if (!mxEvent.isConsumed(evt))
- {
- var tmp = getState(evt);
- graph.dblClick(evt, (tmp != null) ? tmp.cell : null);
- }
- });
- },
-
- /**
- * Function: release
- *
- * Removes the known listeners from the given DOM node and its descendants.
- *
- * Parameters:
- *
- * element - DOM node to remove the listeners from.
- */
- release: function(element)
- {
- if (element != null)
- {
- mxEvent.removeAllListeners(element);
-
- var children = element.childNodes;
-
- if (children != null)
- {
- var childCount = children.length;
-
- for (var i = 0; i < childCount; i += 1)
- {
- mxEvent.release(children[i]);
- }
- }
- }
- },
-
- /**
- * Function: addMouseWheelListener
- *
- * Installs the given function as a handler for mouse wheel events. The
- * function has two arguments: the mouse event and a boolean that specifies
- * if the wheel was moved up or down.
- *
- * This has been tested with IE 6 and 7, Firefox (all versions), Opera and
- * Safari. It does currently not work on Safari for Mac.
- *
- * Example:
- *
- * (code)
- * mxEvent.addMouseWheelListener(function (evt, up)
- * {
- * mxLog.show();
- * mxLog.debug('mouseWheel: up='+up);
- * });
- *(end)
- *
- * Parameters:
- *
- * funct - Handler function that takes the event argument and a boolean up
- * argument for the mousewheel direction.
- */
- addMouseWheelListener: function(funct)
- {
- if (funct != null)
- {
- var wheelHandler = function(evt)
- {
- // IE does not give an event object but the
- // global event object is the mousewheel event
- // at this point in time.
- if (evt == null)
- {
- evt = window.event;
- }
-
- var delta = 0;
-
- if (mxClient.IS_NS && !mxClient.IS_SF && !mxClient.IS_GC)
- {
- delta = -evt.detail/2;
- }
- else
- {
- delta = evt.wheelDelta/120;
- }
-
- // Handles the event using the given function
- if (delta != 0)
- {
- funct(evt, delta > 0);
- }
- };
-
- // Webkit has NS event API, but IE event name and details
- if (mxClient.IS_NS)
- {
- var eventName = (mxClient.IS_SF || mxClient.IS_GC) ?
- 'mousewheel' : 'DOMMouseScroll';
- mxEvent.addListener(window, eventName, wheelHandler);
- }
- else
- {
- // TODO: Does not work with Safari and Chrome but it should be
- // working as tested in etc/markup/wheel.html
- mxEvent.addListener(document, 'mousewheel', wheelHandler);
- }
- }
- },
-
- /**
- * Function: disableContextMenu
- *
- * Disables the context menu for the given element.
- */
- disableContextMenu: function()
- {
- if (mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9))
- {
- return function(element)
- {
- mxEvent.addListener(element, 'contextmenu', function()
- {
- return false;
- });
- };
- }
- else
- {
- return function(element)
- {
- element.setAttribute('oncontextmenu', 'return false;');
- };
- }
- }(),
-
- /**
- * Function: getSource
- *
- * Returns the event's target or srcElement depending on the browser.
- */
- getSource: function(evt)
- {
- return (evt.srcElement != null) ? evt.srcElement : evt.target;
- },
-
- /**
- * Function: isConsumed
- *
- * Returns true if the event has been consumed using <consume>.
- */
- isConsumed: function(evt)
- {
- return evt.isConsumed != null && evt.isConsumed;
- },
-
- /**
- * Function: isLeftMouseButton
- *
- * Returns true if the left mouse button is pressed for the given event.
- * To check if a button is pressed during a mouseMove you should use the
- * <mxGraph.isMouseDown> property.
- */
- isLeftMouseButton: function(evt)
- {
- return evt.button == ((mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9)) ? 1 : 0);
- },
-
- /**
- * Function: isRightMouseButton
- *
- * Returns true if the right mouse button was pressed. Note that this
- * button might not be available on some systems. For handling a popup
- * trigger <isPopupTrigger> should be used.
- */
- isRightMouseButton: function(evt)
- {
- return evt.button == 2;
- },
-
- /**
- * Function: isPopupTrigger
- *
- * Returns true if the event is a popup trigger. This implementation
- * returns true if the right mouse button or shift was pressed.
- */
- isPopupTrigger: function(evt)
- {
- return mxEvent.isRightMouseButton(evt) ||
- (mxEvent.isShiftDown(evt) &&
- !mxEvent.isControlDown(evt));
- },
-
- /**
- * Function: isShiftDown
- *
- * Returns true if the shift key is pressed for the given event.
- */
- isShiftDown: function(evt)
- {
- return (evt != null) ? evt.shiftKey : false;
- },
-
- /**
- * Function: isAltDown
- *
- * Returns true if the alt key is pressed for the given event.
- */
- isAltDown: function(evt)
- {
- return (evt != null) ? evt.altKey : false;
- },
-
- /**
- * Function: isControlDown
- *
- * Returns true if the control key is pressed for the given event.
- */
- isControlDown: function(evt)
- {
- return (evt != null) ? evt.ctrlKey : false;
- },
-
- /**
- * Function: isMetaDown
- *
- * Returns true if the meta key is pressed for the given event.
- */
- isMetaDown: function(evt)
- {
- return (evt != null) ? evt.metaKey : false;
- },
-
- /**
- * Function: getMainEvent
- *
- * Returns the touch or mouse event that contains the mouse coordinates.
- */
- getMainEvent: function(e)
- {
- if ((e.type == 'touchstart' || e.type == 'touchmove') &&
- e.touches != null && e.touches[0] != null)
- {
- e = e.touches[0];
- }
- else if (e.type == 'touchend' && e.changedTouches != null &&
- e.changedTouches[0] != null)
- {
- e = e.changedTouches[0];
- }
-
- return e;
- },
-
- /**
- * Function: getClientX
- *
- * Returns true if the meta key is pressed for the given event.
- */
- getClientX: function(e)
- {
- return mxEvent.getMainEvent(e).clientX;
- },
-
- /**
- * Function: getClientY
- *
- * Returns true if the meta key is pressed for the given event.
- */
- getClientY: function(e)
- {
- return mxEvent.getMainEvent(e).clientY;
- },
-
- /**
- * Function: consume
- *
- * Consumes the given event.
- *
- * Parameters:
- *
- * evt - Native event to be consumed.
- * preventDefault - Optional boolean to prevent the default for the event.
- * Default is true.
- * stopPropagation - Option boolean to stop event propagation. Default is
- * true.
- */
- consume: function(evt, preventDefault, stopPropagation)
- {
- preventDefault = (preventDefault != null) ? preventDefault : true;
- stopPropagation = (stopPropagation != null) ? stopPropagation : true;
-
- if (preventDefault)
- {
- if (evt.preventDefault)
- {
- if (stopPropagation)
- {
- evt.stopPropagation();
- }
-
- evt.preventDefault();
- }
- else if (stopPropagation)
- {
- evt.cancelBubble = true;
- }
- }
-
- // Opera
- evt.isConsumed = true;
-
- // Other browsers
- evt.returnValue = false;
- },
-
- //
- // Special handles in mouse events
- //
-
- /**
- * Variable: LABEL_HANDLE
- *
- * Index for the label handle in an mxMouseEvent. This should be a negative
- * value that does not interfere with any possible handle indices. Default
- * is -1.
- */
- LABEL_HANDLE: -1,
-
- /**
- * Variable: ROTATION_HANDLE
- *
- * Index for the rotation handle in an mxMouseEvent. This should be a
- * negative value that does not interfere with any possible handle indices.
- * Default is -2.
- */
- ROTATION_HANDLE: -2,
-
- //
- // Event names
- //
-
- /**
- * Variable: MOUSE_DOWN
- *
- * Specifies the event name for mouseDown.
- */
- MOUSE_DOWN: 'mouseDown',
-
- /**
- * Variable: MOUSE_MOVE
- *
- * Specifies the event name for mouseMove.
- */
- MOUSE_MOVE: 'mouseMove',
-
- /**
- * Variable: MOUSE_UP
- *
- * Specifies the event name for mouseUp.
- */
- MOUSE_UP: 'mouseUp',
-
- /**
- * Variable: ACTIVATE
- *
- * Specifies the event name for activate.
- */
- ACTIVATE: 'activate',
-
- /**
- * Variable: RESIZE_START
- *
- * Specifies the event name for resizeStart.
- */
- RESIZE_START: 'resizeStart',
-
- /**
- * Variable: RESIZE
- *
- * Specifies the event name for resize.
- */
- RESIZE: 'resize',
-
- /**
- * Variable: RESIZE_END
- *
- * Specifies the event name for resizeEnd.
- */
- RESIZE_END: 'resizeEnd',
-
- /**
- * Variable: MOVE_START
- *
- * Specifies the event name for moveStart.
- */
- MOVE_START: 'moveStart',
-
- /**
- * Variable: MOVE
- *
- * Specifies the event name for move.
- */
- MOVE: 'move',
-
- /**
- * Variable: MOVE_END
- *
- * Specifies the event name for moveEnd.
- */
- MOVE_END: 'moveEnd',
-
- /**
- * Variable: PAN_START
- *
- * Specifies the event name for panStart.
- */
- PAN_START: 'panStart',
-
- /**
- * Variable: PAN
- *
- * Specifies the event name for pan.
- */
- PAN: 'pan',
-
- /**
- * Variable: PAN_END
- *
- * Specifies the event name for panEnd.
- */
- PAN_END: 'panEnd',
-
- /**
- * Variable: MINIMIZE
- *
- * Specifies the event name for minimize.
- */
- MINIMIZE: 'minimize',
-
- /**
- * Variable: NORMALIZE
- *
- * Specifies the event name for normalize.
- */
- NORMALIZE: 'normalize',
-
- /**
- * Variable: MAXIMIZE
- *
- * Specifies the event name for maximize.
- */
- MAXIMIZE: 'maximize',
-
- /**
- * Variable: HIDE
- *
- * Specifies the event name for hide.
- */
- HIDE: 'hide',
-
- /**
- * Variable: SHOW
- *
- * Specifies the event name for show.
- */
- SHOW: 'show',
-
- /**
- * Variable: CLOSE
- *
- * Specifies the event name for close.
- */
- CLOSE: 'close',
-
- /**
- * Variable: DESTROY
- *
- * Specifies the event name for destroy.
- */
- DESTROY: 'destroy',
-
- /**
- * Variable: REFRESH
- *
- * Specifies the event name for refresh.
- */
- REFRESH: 'refresh',
-
- /**
- * Variable: SIZE
- *
- * Specifies the event name for size.
- */
- SIZE: 'size',
-
- /**
- * Variable: SELECT
- *
- * Specifies the event name for select.
- */
- SELECT: 'select',
-
- /**
- * Variable: FIRED
- *
- * Specifies the event name for fired.
- */
- FIRED: 'fired',
-
- /**
- * Variable: GET
- *
- * Specifies the event name for get.
- */
- GET: 'get',
-
- /**
- * Variable: RECEIVE
- *
- * Specifies the event name for receive.
- */
- RECEIVE: 'receive',
-
- /**
- * Variable: CONNECT
- *
- * Specifies the event name for connect.
- */
- CONNECT: 'connect',
-
- /**
- * Variable: DISCONNECT
- *
- * Specifies the event name for disconnect.
- */
- DISCONNECT: 'disconnect',
-
- /**
- * Variable: SUSPEND
- *
- * Specifies the event name for suspend.
- */
- SUSPEND: 'suspend',
-
- /**
- * Variable: RESUME
- *
- * Specifies the event name for suspend.
- */
- RESUME: 'resume',
-
- /**
- * Variable: MARK
- *
- * Specifies the event name for mark.
- */
- MARK: 'mark',
-
- /**
- * Variable: SESSION
- *
- * Specifies the event name for session.
- */
- SESSION: 'session',
-
- /**
- * Variable: ROOT
- *
- * Specifies the event name for root.
- */
- ROOT: 'root',
-
- /**
- * Variable: POST
- *
- * Specifies the event name for post.
- */
- POST: 'post',
-
- /**
- * Variable: OPEN
- *
- * Specifies the event name for open.
- */
- OPEN: 'open',
-
- /**
- * Variable: SAVE
- *
- * Specifies the event name for open.
- */
- SAVE: 'save',
-
- /**
- * Variable: BEFORE_ADD_VERTEX
- *
- * Specifies the event name for beforeAddVertex.
- */
- BEFORE_ADD_VERTEX: 'beforeAddVertex',
-
- /**
- * Variable: ADD_VERTEX
- *
- * Specifies the event name for addVertex.
- */
- ADD_VERTEX: 'addVertex',
-
- /**
- * Variable: AFTER_ADD_VERTEX
- *
- * Specifies the event name for afterAddVertex.
- */
- AFTER_ADD_VERTEX: 'afterAddVertex',
-
- /**
- * Variable: DONE
- *
- * Specifies the event name for done.
- */
- DONE: 'done',
-
- /**
- * Variable: EXECUTE
- *
- * Specifies the event name for execute.
- */
- EXECUTE: 'execute',
-
- /**
- * Variable: BEGIN_UPDATE
- *
- * Specifies the event name for beginUpdate.
- */
- BEGIN_UPDATE: 'beginUpdate',
-
- /**
- * Variable: END_UPDATE
- *
- * Specifies the event name for endUpdate.
- */
- END_UPDATE: 'endUpdate',
-
- /**
- * Variable: BEFORE_UNDO
- *
- * Specifies the event name for beforeUndo.
- */
- BEFORE_UNDO: 'beforeUndo',
-
- /**
- * Variable: UNDO
- *
- * Specifies the event name for undo.
- */
- UNDO: 'undo',
-
- /**
- * Variable: REDO
- *
- * Specifies the event name for redo.
- */
- REDO: 'redo',
-
- /**
- * Variable: CHANGE
- *
- * Specifies the event name for change.
- */
- CHANGE: 'change',
-
- /**
- * Variable: NOTIFY
- *
- * Specifies the event name for notify.
- */
- NOTIFY: 'notify',
-
- /**
- * Variable: LAYOUT_CELLS
- *
- * Specifies the event name for layoutCells.
- */
- LAYOUT_CELLS: 'layoutCells',
-
- /**
- * Variable: CLICK
- *
- * Specifies the event name for click.
- */
- CLICK: 'click',
-
- /**
- * Variable: SCALE
- *
- * Specifies the event name for scale.
- */
- SCALE: 'scale',
-
- /**
- * Variable: TRANSLATE
- *
- * Specifies the event name for translate.
- */
- TRANSLATE: 'translate',
-
- /**
- * Variable: SCALE_AND_TRANSLATE
- *
- * Specifies the event name for scaleAndTranslate.
- */
- SCALE_AND_TRANSLATE: 'scaleAndTranslate',
-
- /**
- * Variable: UP
- *
- * Specifies the event name for up.
- */
- UP: 'up',
-
- /**
- * Variable: DOWN
- *
- * Specifies the event name for down.
- */
- DOWN: 'down',
-
- /**
- * Variable: ADD
- *
- * Specifies the event name for add.
- */
- ADD: 'add',
-
- /**
- * Variable: REMOVE
- *
- * Specifies the event name for remove.
- */
- REMOVE: 'remove',
-
- /**
- * Variable: CLEAR
- *
- * Specifies the event name for clear.
- */
- CLEAR: 'clear',
-
- /**
- * Variable: ADD_CELLS
- *
- * Specifies the event name for addCells.
- */
- ADD_CELLS: 'addCells',
-
- /**
- * Variable: CELLS_ADDED
- *
- * Specifies the event name for cellsAdded.
- */
- CELLS_ADDED: 'cellsAdded',
-
- /**
- * Variable: MOVE_CELLS
- *
- * Specifies the event name for moveCells.
- */
- MOVE_CELLS: 'moveCells',
-
- /**
- * Variable: CELLS_MOVED
- *
- * Specifies the event name for cellsMoved.
- */
- CELLS_MOVED: 'cellsMoved',
-
- /**
- * Variable: RESIZE_CELLS
- *
- * Specifies the event name for resizeCells.
- */
- RESIZE_CELLS: 'resizeCells',
-
- /**
- * Variable: CELLS_RESIZED
- *
- * Specifies the event name for cellsResized.
- */
- CELLS_RESIZED: 'cellsResized',
-
- /**
- * Variable: TOGGLE_CELLS
- *
- * Specifies the event name for toggleCells.
- */
- TOGGLE_CELLS: 'toggleCells',
-
- /**
- * Variable: CELLS_TOGGLED
- *
- * Specifies the event name for cellsToggled.
- */
- CELLS_TOGGLED: 'cellsToggled',
-
- /**
- * Variable: ORDER_CELLS
- *
- * Specifies the event name for orderCells.
- */
- ORDER_CELLS: 'orderCells',
-
- /**
- * Variable: CELLS_ORDERED
- *
- * Specifies the event name for cellsOrdered.
- */
- CELLS_ORDERED: 'cellsOrdered',
-
- /**
- * Variable: REMOVE_CELLS
- *
- * Specifies the event name for removeCells.
- */
- REMOVE_CELLS: 'removeCells',
-
- /**
- * Variable: CELLS_REMOVED
- *
- * Specifies the event name for cellsRemoved.
- */
- CELLS_REMOVED: 'cellsRemoved',
-
- /**
- * Variable: GROUP_CELLS
- *
- * Specifies the event name for groupCells.
- */
- GROUP_CELLS: 'groupCells',
-
- /**
- * Variable: UNGROUP_CELLS
- *
- * Specifies the event name for ungroupCells.
- */
- UNGROUP_CELLS: 'ungroupCells',
-
- /**
- * Variable: REMOVE_CELLS_FROM_PARENT
- *
- * Specifies the event name for removeCellsFromParent.
- */
- REMOVE_CELLS_FROM_PARENT: 'removeCellsFromParent',
-
- /**
- * Variable: FOLD_CELLS
- *
- * Specifies the event name for foldCells.
- */
- FOLD_CELLS: 'foldCells',
-
- /**
- * Variable: CELLS_FOLDED
- *
- * Specifies the event name for cellsFolded.
- */
- CELLS_FOLDED: 'cellsFolded',
-
- /**
- * Variable: ALIGN_CELLS
- *
- * Specifies the event name for alignCells.
- */
- ALIGN_CELLS: 'alignCells',
-
- /**
- * Variable: LABEL_CHANGED
- *
- * Specifies the event name for labelChanged.
- */
- LABEL_CHANGED: 'labelChanged',
-
- /**
- * Variable: CONNECT_CELL
- *
- * Specifies the event name for connectCell.
- */
- CONNECT_CELL: 'connectCell',
-
- /**
- * Variable: CELL_CONNECTED
- *
- * Specifies the event name for cellConnected.
- */
- CELL_CONNECTED: 'cellConnected',
-
- /**
- * Variable: SPLIT_EDGE
- *
- * Specifies the event name for splitEdge.
- */
- SPLIT_EDGE: 'splitEdge',
-
- /**
- * Variable: FLIP_EDGE
- *
- * Specifies the event name for flipEdge.
- */
- FLIP_EDGE: 'flipEdge',
-
- /**
- * Variable: START_EDITING
- *
- * Specifies the event name for startEditing.
- */
- START_EDITING: 'startEditing',
-
- /**
- * Variable: ADD_OVERLAY
- *
- * Specifies the event name for addOverlay.
- */
- ADD_OVERLAY: 'addOverlay',
-
- /**
- * Variable: REMOVE_OVERLAY
- *
- * Specifies the event name for removeOverlay.
- */
- REMOVE_OVERLAY: 'removeOverlay',
-
- /**
- * Variable: UPDATE_CELL_SIZE
- *
- * Specifies the event name for updateCellSize.
- */
- UPDATE_CELL_SIZE: 'updateCellSize',
-
- /**
- * Variable: ESCAPE
- *
- * Specifies the event name for escape.
- */
- ESCAPE: 'escape',
-
- /**
- * Variable: CLICK
- *
- * Specifies the event name for click.
- */
- CLICK: 'click',
-
- /**
- * Variable: DOUBLE_CLICK
- *
- * Specifies the event name for doubleClick.
- */
- DOUBLE_CLICK: 'doubleClick',
-
- /**
- * Variable: START
- *
- * Specifies the event name for start.
- */
- START: 'start',
-
- /**
- * Variable: RESET
- *
- * Specifies the event name for reset.
- */
- RESET: 'reset'
-
-};
diff --git a/src/js/util/mxEventObject.js b/src/js/util/mxEventObject.js
deleted file mode 100644
index cb08a55..0000000
--- a/src/js/util/mxEventObject.js
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * $Id: mxEventObject.js,v 1.11 2011-09-09 10:29:05 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxEventObject
- *
- * The mxEventObject is a wrapper for all properties of a single event.
- * Additionally, it also offers functions to consume the event and check if it
- * was consumed as follows:
- *
- * (code)
- * evt.consume();
- * INV: evt.isConsumed() == true
- * (end)
- *
- * Constructor: mxEventObject
- *
- * Constructs a new event object with the specified name. An optional
- * sequence of key, value pairs can be appended to define properties.
- *
- * Example:
- *
- * (code)
- * new mxEventObject("eventName", key1, val1, .., keyN, valN)
- * (end)
- */
-function mxEventObject(name)
-{
- this.name = name;
- this.properties = [];
-
- for (var i = 1; i < arguments.length; i += 2)
- {
- if (arguments[i + 1] != null)
- {
- this.properties[arguments[i]] = arguments[i + 1];
- }
- }
-};
-
-/**
- * Variable: name
- *
- * Holds the name.
- */
-mxEventObject.prototype.name = null;
-
-/**
- * Variable: properties
- *
- * Holds the properties as an associative array.
- */
-mxEventObject.prototype.properties = null;
-
-/**
- * Variable: consumed
- *
- * Holds the consumed state. Default is false.
- */
-mxEventObject.prototype.consumed = false;
-
-/**
- * Function: getName
- *
- * Returns <name>.
- */
-mxEventObject.prototype.getName = function()
-{
- return this.name;
-};
-
-/**
- * Function: getProperties
- *
- * Returns <properties>.
- */
-mxEventObject.prototype.getProperties = function()
-{
- return this.properties;
-};
-
-/**
- * Function: getProperty
- *
- * Returns the property for the given key.
- */
-mxEventObject.prototype.getProperty = function(key)
-{
- return this.properties[key];
-};
-
-/**
- * Function: isConsumed
- *
- * Returns true if the event has been consumed.
- */
-mxEventObject.prototype.isConsumed = function()
-{
- return this.consumed;
-};
-
-/**
- * Function: consume
- *
- * Consumes the event.
- */
-mxEventObject.prototype.consume = function()
-{
- this.consumed = true;
-};
diff --git a/src/js/util/mxEventSource.js b/src/js/util/mxEventSource.js
deleted file mode 100644
index 595f560..0000000
--- a/src/js/util/mxEventSource.js
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- * $Id: mxEventSource.js,v 1.25 2012-04-16 10:54:20 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxEventSource
- *
- * Base class for objects that dispatch named events. To create a subclass that
- * inherits from mxEventSource, the following code is used.
- *
- * (code)
- * function MyClass() { };
- *
- * MyClass.prototype = new mxEventSource();
- * MyClass.prototype.constructor = MyClass;
- * (end)
- *
- * Known Subclasses:
- *
- * <mxGraphModel>, <mxGraph>, <mxGraphView>, <mxEditor>, <mxCellOverlay>,
- * <mxToolbar>, <mxWindow>
- *
- * Constructor: mxEventSource
- *
- * Constructs a new event source.
- */
-function mxEventSource(eventSource)
-{
- this.setEventSource(eventSource);
-};
-
-/**
- * Variable: eventListeners
- *
- * Holds the event names and associated listeners in an array. The array
- * contains the event name followed by the respective listener for each
- * registered listener.
- */
-mxEventSource.prototype.eventListeners = null;
-
-/**
- * Variable: eventsEnabled
- *
- * Specifies if events can be fired. Default is true.
- */
-mxEventSource.prototype.eventsEnabled = true;
-
-/**
- * Variable: eventSource
- *
- * Optional source for events. Default is null.
- */
-mxEventSource.prototype.eventSource = null;
-
-/**
- * Function: isEventsEnabled
- *
- * Returns <eventsEnabled>.
- */
-mxEventSource.prototype.isEventsEnabled = function()
-{
- return this.eventsEnabled;
-};
-
-/**
- * Function: setEventsEnabled
- *
- * Sets <eventsEnabled>.
- */
-mxEventSource.prototype.setEventsEnabled = function(value)
-{
- this.eventsEnabled = value;
-};
-
-/**
- * Function: getEventSource
- *
- * Returns <eventSource>.
- */
-mxEventSource.prototype.getEventSource = function()
-{
- return this.eventSource;
-};
-
-/**
- * Function: setEventSource
- *
- * Sets <eventSource>.
- */
-mxEventSource.prototype.setEventSource = function(value)
-{
- this.eventSource = value;
-};
-
-/**
- * Function: addListener
- *
- * Binds the specified function to the given event name. If no event name
- * is given, then the listener is registered for all events.
- *
- * The parameters of the listener are the sender and an <mxEventObject>.
- */
-mxEventSource.prototype.addListener = function(name, funct)
-{
- if (this.eventListeners == null)
- {
- this.eventListeners = [];
- }
-
- this.eventListeners.push(name);
- this.eventListeners.push(funct);
-};
-
-/**
- * Function: removeListener
- *
- * Removes all occurrences of the given listener from <eventListeners>.
- */
-mxEventSource.prototype.removeListener = function(funct)
-{
- if (this.eventListeners != null)
- {
- var i = 0;
-
- while (i < this.eventListeners.length)
- {
- if (this.eventListeners[i+1] == funct)
- {
- this.eventListeners.splice(i, 2);
- }
- else
- {
- i += 2;
- }
- }
- }
-};
-
-/**
- * Function: fireEvent
- *
- * Dispatches the given event to the listeners which are registered for
- * the event. The sender argument is optional. The current execution scope
- * ("this") is used for the listener invocation (see <mxUtils.bind>).
- *
- * Example:
- *
- * (code)
- * fireEvent(new mxEventObject("eventName", key1, val1, .., keyN, valN))
- * (end)
- *
- * Parameters:
- *
- * evt - <mxEventObject> that represents the event.
- * sender - Optional sender to be passed to the listener. Default value is
- * the return value of <getEventSource>.
- */
-mxEventSource.prototype.fireEvent = function(evt, sender)
-{
- if (this.eventListeners != null &&
- this.isEventsEnabled())
- {
- if (evt == null)
- {
- evt = new mxEventObject();
- }
-
- if (sender == null)
- {
- sender = this.getEventSource();
- }
-
- if (sender == null)
- {
- sender = this;
- }
-
- var args = [sender, evt];
-
- for (var i = 0; i < this.eventListeners.length; i += 2)
- {
- var listen = this.eventListeners[i];
-
- if (listen == null ||
- listen == evt.getName())
- {
- this.eventListeners[i+1].apply(this, args);
- }
- }
- }
-};
diff --git a/src/js/util/mxForm.js b/src/js/util/mxForm.js
deleted file mode 100644
index bcee299..0000000
--- a/src/js/util/mxForm.js
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * $Id: mxForm.js,v 1.16 2010-10-08 04:21:45 david Exp $
- * Copyright (c) 2006-2010, Gaudenz Alder, David Benson
- */
-/**
- * Class: mxForm
- *
- * A simple class for creating HTML forms.
- *
- * Constructor: mxForm
- *
- * Creates a HTML table using the specified classname.
- */
-function mxForm(className)
-{
- this.table = document.createElement('table');
- this.table.className = className;
- this.body = document.createElement('tbody');
-
- this.table.appendChild(this.body);
-};
-
-/**
- * Variable: table
- *
- * Holds the DOM node that represents the table.
- */
-mxForm.prototype.table = null;
-
-/**
- * Variable: body
- *
- * Holds the DOM node that represents the tbody (table body). New rows
- * can be added to this object using DOM API.
- */
-mxForm.prototype.body = false;
-
-/**
- * Function: getTable
- *
- * Returns the table that contains this form.
- */
-mxForm.prototype.getTable = function()
-{
- return this.table;
-};
-
-/**
- * Function: addButtons
- *
- * Helper method to add an OK and Cancel button using the respective
- * functions.
- */
-mxForm.prototype.addButtons = function(okFunct, cancelFunct)
-{
- var tr = document.createElement('tr');
- var td = document.createElement('td');
- tr.appendChild(td);
- td = document.createElement('td');
-
- // Adds the ok button
- var button = document.createElement('button');
- mxUtils.write(button, mxResources.get('ok') || 'OK');
- td.appendChild(button);
-
- mxEvent.addListener(button, 'click', function()
- {
- okFunct();
- });
-
- // Adds the cancel button
- button = document.createElement('button');
- mxUtils.write(button, mxResources.get('cancel') || 'Cancel');
- td.appendChild(button);
-
- mxEvent.addListener(button, 'click', function()
- {
- cancelFunct();
- });
-
- tr.appendChild(td);
- this.body.appendChild(tr);
-};
-
-/**
- * Function: addText
- *
- * Adds a textfield for the given name and value and returns the textfield.
- */
-mxForm.prototype.addText = function(name, value)
-{
- var input = document.createElement('input');
-
- input.setAttribute('type', 'text');
- input.value = value;
-
- return this.addField(name, input);
-};
-
-/**
- * Function: addCheckbox
- *
- * Adds a checkbox for the given name and value and returns the textfield.
- */
-mxForm.prototype.addCheckbox = function(name, value)
-{
- var input = document.createElement('input');
-
- input.setAttribute('type', 'checkbox');
- this.addField(name, input);
-
- // IE can only change the checked value if the input is inside the DOM
- if (value)
- {
- input.checked = true;
- }
-
- return input;
-};
-
-/**
- * Function: addTextarea
- *
- * Adds a textarea for the given name and value and returns the textarea.
- */
-mxForm.prototype.addTextarea = function(name, value, rows)
-{
- var input = document.createElement('textarea');
-
- if (mxClient.IS_NS)
- {
- rows--;
- }
-
- input.setAttribute('rows', rows || 2);
- input.value = value;
-
- return this.addField(name, input);
-};
-
-/**
- * Function: addCombo
- *
- * Adds a combo for the given name and returns the combo.
- */
-mxForm.prototype.addCombo = function(name, isMultiSelect, size)
-{
- var select = document.createElement('select');
-
- if (size != null)
- {
- select.setAttribute('size', size);
- }
-
- if (isMultiSelect)
- {
- select.setAttribute('multiple', 'true');
- }
-
- return this.addField(name, select);
-};
-
-/**
- * Function: addOption
- *
- * Adds an option for the given label to the specified combo.
- */
-mxForm.prototype.addOption = function(combo, label, value, isSelected)
-{
- var option = document.createElement('option');
-
- mxUtils.writeln(option, label);
- option.setAttribute('value', value);
-
- if (isSelected)
- {
- option.setAttribute('selected', isSelected);
- }
-
- combo.appendChild(option);
-};
-
-/**
- * Function: addField
- *
- * Adds a new row with the name and the input field in two columns and
- * returns the given input.
- */
-mxForm.prototype.addField = function(name, input)
-{
- var tr = document.createElement('tr');
- var td = document.createElement('td');
- mxUtils.write(td, name);
- tr.appendChild(td);
-
- td = document.createElement('td');
- td.appendChild(input);
- tr.appendChild(td);
- this.body.appendChild(tr);
-
- return input;
-};
diff --git a/src/js/util/mxGuide.js b/src/js/util/mxGuide.js
deleted file mode 100644
index ab5c26d..0000000
--- a/src/js/util/mxGuide.js
+++ /dev/null
@@ -1,364 +0,0 @@
-/**
- * $Id: mxGuide.js,v 1.7 2012-04-13 12:53:30 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGuide
- *
- * Implements the alignment of selection cells to other cells in the graph.
- *
- * Constructor: mxGuide
- *
- * Constructs a new guide object.
- */
-function mxGuide(graph, states)
-{
- this.graph = graph;
- this.setStates(states);
-};
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph> instance.
- */
-mxGuide.prototype.graph = null;
-
-/**
- * Variable: states
- *
- * Contains the <mxCellStates> that are used for alignment.
- */
-mxGuide.prototype.states = null;
-
-/**
- * Variable: horizontal
- *
- * Specifies if horizontal guides are enabled. Default is true.
- */
-mxGuide.prototype.horizontal = true;
-
-/**
- * Variable: vertical
- *
- * Specifies if vertical guides are enabled. Default is true.
- */
-mxGuide.prototype.vertical = true;
-
-/**
- * Variable: vertical
- *
- * Holds the <mxShape> for the horizontal guide.
- */
-mxGuide.prototype.guideX = null;
-
-/**
- * Variable: vertical
- *
- * Holds the <mxShape> for the vertical guide.
- */
-mxGuide.prototype.guideY = null;
-
-/**
- * Variable: crisp
- *
- * Specifies if theguide should be rendered in crisp mode if applicable.
- * Default is true.
- */
-mxGuide.prototype.crisp = true;
-
-/**
- * Function: setStates
- *
- * Sets the <mxCellStates> that should be used for alignment.
- */
-mxGuide.prototype.setStates = function(states)
-{
- this.states = states;
-};
-
-/**
- * Function: isEnabledForEvent
- *
- * Returns true if the guide should be enabled for the given native event. This
- * implementation always returns true.
- */
-mxGuide.prototype.isEnabledForEvent = function(evt)
-{
- return true;
-};
-
-/**
- * Function: getGuideTolerance
- *
- * Returns the tolerance for the guides. Default value is
- * gridSize * scale / 2.
- */
-mxGuide.prototype.getGuideTolerance = function()
-{
- return this.graph.gridSize * this.graph.view.scale / 2;
-};
-
-/**
- * Function: createGuideShape
- *
- * Returns the mxShape to be used for painting the respective guide. This
- * implementation returns a new, dashed and crisp <mxPolyline> using
- * <mxConstants.GUIDE_COLOR> and <mxConstants.GUIDE_STROKEWIDTH> as the format.
- *
- * Parameters:
- *
- * horizontal - Boolean that specifies which guide should be created.
- */
-mxGuide.prototype.createGuideShape = function(horizontal)
-{
- var guide = new mxPolyline([], mxConstants.GUIDE_COLOR, mxConstants.GUIDE_STROKEWIDTH);
- guide.crisp = this.crisp;
- guide.isDashed = true;
-
- return guide;
-};
-
-/**
- * Function: move
- *
- * Moves the <bounds> by the given <mxPoint> and returnt the snapped point.
- */
-mxGuide.prototype.move = function(bounds, delta, gridEnabled)
-{
- if (this.states != null && (this.horizontal || this.vertical) && bounds != null && delta != null)
- {
- var trx = this.graph.getView().translate;
- var scale = this.graph.getView().scale;
- var dx = delta.x;
- var dy = delta.y;
-
- var overrideX = false;
- var overrideY = false;
-
- var tt = this.getGuideTolerance();
- var ttX = tt;
- var ttY = tt;
-
- var b = bounds.clone();
- b.x += delta.x;
- b.y += delta.y;
-
- var left = b.x;
- var right = b.x + b.width;
- var center = b.getCenterX();
- var top = b.y;
- var bottom = b.y + b.height;
- var middle = b.getCenterY();
-
- // Snaps the left, center and right to the given x-coordinate
- function snapX(x)
- {
- x += this.graph.panDx;
- var override = false;
-
- if (Math.abs(x - center) < ttX)
- {
- dx = x - bounds.getCenterX();
- ttX = Math.abs(x - center);
- override = true;
- }
- else if (Math.abs(x - left) < ttX)
- {
- dx = x - bounds.x;
- ttX = Math.abs(x - left);
- override = true;
- }
- else if (Math.abs(x - right) < ttX)
- {
- dx = x - bounds.x - bounds.width;
- ttX = Math.abs(x - right);
- override = true;
- }
-
- if (override)
- {
- if (this.guideX == null)
- {
- this.guideX = this.createGuideShape(true);
-
- // Makes sure to use either VML or SVG shapes in order to implement
- // event-transparency on the background area of the rectangle since
- // HTML shapes do not let mouseevents through even when transparent
- this.guideX.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- this.guideX.init(this.graph.getView().getOverlayPane());
-
- if (this.graph.dialect == mxConstants.DIALECT_SVG)
- {
- this.guideX.node.setAttribute('pointer-events', 'none');
- this.guideX.pipe.setAttribute('pointer-events', 'none');
- }
- }
-
- var c = this.graph.container;
- x -= this.graph.panDx;
- this.guideX.points = [new mxPoint(x, -this.graph.panDy), new mxPoint(x, c.scrollHeight - 3 - this.graph.panDy)];
- }
-
- overrideX = overrideX || override;
- };
-
- // Snaps the top, middle or bottom to the given y-coordinate
- function snapY(y)
- {
- y += this.graph.panDy;
- var override = false;
-
- if (Math.abs(y - middle) < ttY)
- {
- dy = y - bounds.getCenterY();
- ttY = Math.abs(y - middle);
- override = true;
- }
- else if (Math.abs(y - top) < ttY)
- {
- dy = y - bounds.y;
- ttY = Math.abs(y - top);
- override = true;
- }
- else if (Math.abs(y - bottom) < ttY)
- {
- dy = y - bounds.y - bounds.height;
- ttY = Math.abs(y - bottom);
- override = true;
- }
-
- if (override)
- {
- if (this.guideY == null)
- {
- this.guideY = this.createGuideShape(false);
-
- // Makes sure to use either VML or SVG shapes in order to implement
- // event-transparency on the background area of the rectangle since
- // HTML shapes do not let mouseevents through even when transparent
- this.guideY.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- this.guideY.init(this.graph.getView().getOverlayPane());
-
- if (this.graph.dialect == mxConstants.DIALECT_SVG)
- {
- this.guideY.node.setAttribute('pointer-events', 'none');
- this.guideY.pipe.setAttribute('pointer-events', 'none');
- }
- }
-
- var c = this.graph.container;
- y -= this.graph.panDy;
- this.guideY.points = [new mxPoint(-this.graph.panDx, y), new mxPoint(c.scrollWidth - 3 - this.graph.panDx, y)];
- }
-
- overrideY = overrideY || override;
- };
-
- for (var i = 0; i < this.states.length; i++)
- {
- var state = this.states[i];
-
- if (state != null)
- {
- // Align x
- if (this.horizontal)
- {
- snapX.call(this, state.getCenterX());
- snapX.call(this, state.x);
- snapX.call(this, state.x + state.width);
- }
-
- // Align y
- if (this.vertical)
- {
- snapY.call(this, state.getCenterY());
- snapY.call(this, state.y);
- snapY.call(this, state.y + state.height);
- }
- }
- }
-
- if (!overrideX && this.guideX != null)
- {
- this.guideX.node.style.visibility = 'hidden';
- }
- else if (this.guideX != null)
- {
- this.guideX.node.style.visibility = 'visible';
- this.guideX.redraw();
- }
-
- if (!overrideY && this.guideY != null)
- {
- this.guideY.node.style.visibility = 'hidden';
- }
- else if (this.guideY != null)
- {
- this.guideY.node.style.visibility = 'visible';
- this.guideY.redraw();
- }
-
- // Moves cells that are off-grid back to the grid on move
- if (gridEnabled)
- {
- if (!overrideX)
- {
- var tx = bounds.x - (this.graph.snap(bounds.x /
- scale - trx.x) + trx.x) * scale;
- dx = this.graph.snap(dx / scale) * scale - tx;
- }
-
- if (!overrideY)
- {
- var ty = bounds.y - (this.graph.snap(bounds.y /
- scale - trx.y) + trx.y) * scale;
- dy = this.graph.snap(dy / scale) * scale - ty;
- }
- }
-
- delta = new mxPoint(dx, dy);
- }
-
- return delta;
-};
-
-/**
- * Function: hide
- *
- * Hides all current guides.
- */
-mxGuide.prototype.hide = function()
-{
- if (this.guideX != null)
- {
- this.guideX.node.style.visibility = 'hidden';
- }
-
- if (this.guideY != null)
- {
- this.guideY.node.style.visibility = 'hidden';
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys all resources that this object uses.
- */
-mxGuide.prototype.destroy = function()
-{
- if (this.guideX != null)
- {
- this.guideX.destroy();
- this.guideX = null;
- }
-
- if (this.guideY != null)
- {
- this.guideY.destroy();
- this.guideY = null;
- }
-};
diff --git a/src/js/util/mxImage.js b/src/js/util/mxImage.js
deleted file mode 100644
index 39d1a09..0000000
--- a/src/js/util/mxImage.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * $Id: mxImage.js,v 1.7 2010-01-02 09:45:14 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxImage
- *
- * Encapsulates the URL, width and height of an image.
- *
- * Constructor: mxImage
- *
- * Constructs a new image.
- */
-function mxImage(src, width, height)
-{
- this.src = src;
- this.width = width;
- this.height = height;
-};
-
-/**
- * Variable: src
- *
- * String that specifies the URL of the image.
- */
-mxImage.prototype.src = null;
-
-/**
- * Variable: width
- *
- * Integer that specifies the width of the image.
- */
-mxImage.prototype.width = null;
-
-/**
- * Variable: height
- *
- * Integer that specifies the height of the image.
- */
-mxImage.prototype.height = null;
diff --git a/src/js/util/mxImageBundle.js b/src/js/util/mxImageBundle.js
deleted file mode 100644
index dc4c2cf..0000000
--- a/src/js/util/mxImageBundle.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * $Id: mxImageBundle.js,v 1.3 2011-01-20 19:08:11 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxImageBundle
- *
- * Maps from keys to base64 encoded images or file locations. All values must
- * be URLs or use the format data:image/format followed by a comma and the base64
- * encoded image data, eg. "data:image/gif,XYZ", where XYZ is the base64 encoded
- * image data.
- *
- * To add a new image bundle to an existing graph, the following code is used:
- *
- * (code)
- * var bundle = new mxImageBundle(alt);
- * bundle.putImage('myImage', 'data:image/gif,R0lGODlhEAAQAMIGAAAAAICAAICAgP' +
- * '//AOzp2O3r2////////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgAHACwAAAAA' +
- * 'EAAQAAADTXi63AowynnAMDfjPUDlnAAJhmeBFxAEloliKltWmiYCQvfVr6lBPB1ggxN1hi' +
- * 'laSSASFQpIV5HJBDyHpqK2ejVRm2AAgZCdmCGO9CIBADs=', fallback);
- * graph.addImageBundle(bundle);
- * (end);
- *
- * Alt is an optional boolean (default is false) that specifies if the value
- * or the fallback should be returned in <getImage>.
- *
- * The image can then be referenced in any cell style using image=myImage.
- * If you are using mxOutline, you should use the same image bundles in the
- * graph that renders the outline.
- *
- * The keys for images are resolved in <mxGraph.postProcessCellStyle> and
- * turned into a data URI if the returned value has a short data URI format
- * as specified above.
- *
- * A typical value for the fallback is a MTHML link as defined in RFC 2557.
- * Note that this format requires a file to be dynamically created on the
- * server-side, or the page that contains the graph to be modified to contain
- * the resources, this can be done by adding a comment that contains the
- * resource in the HEAD section of the page after the title tag.
- *
- * This type of fallback mechanism should be used in IE6 and IE7. IE8 does
- * support data URIs, but the maximum size is limited to 32 KB, which means
- * all data URIs should be limited to 32 KB.
- */
-function mxImageBundle(alt)
-{
- this.images = [];
- this.alt = (alt != null) ? alt : false;
-};
-
-/**
- * Variable: images
- *
- * Maps from keys to images.
- */
-mxImageBundle.prototype.images = null;
-
-/**
- * Variable: alt
- *
- * Specifies if the fallback representation should be returned.
- */
-mxImageBundle.prototype.images = null;
-
-/**
- * Function: putImage
- *
- * Adds the specified entry to the map. The entry is an object with a value and
- * fallback property as specified in the arguments.
- */
-mxImageBundle.prototype.putImage = function(key, value, fallback)
-{
- this.images[key] = {value: value, fallback: fallback};
-};
-
-/**
- * Function: getImage
- *
- * Returns the value for the given key. This returns the value
- * or fallback, depending on <alt>. The fallback is returned if
- * <alt> is true, the value is returned otherwise.
- */
-mxImageBundle.prototype.getImage = function(key)
-{
- var result = null;
-
- if (key != null)
- {
- var img = this.images[key];
-
- if (img != null)
- {
- result = (this.alt) ? img.fallback : img.value;
- }
- }
-
- return result;
-};
diff --git a/src/js/util/mxImageExport.js b/src/js/util/mxImageExport.js
deleted file mode 100644
index dcbcf9a..0000000
--- a/src/js/util/mxImageExport.js
+++ /dev/null
@@ -1,1412 +0,0 @@
-/**
- * $Id: mxImageExport.js,v 1.47 2012-09-24 14:54:32 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxImageExport
- *
- * Creates a new image export instance to be used with an export canvas. Here
- * is an example that uses this class to create an image via a backend using
- * <mxXmlExportCanvas>.
- *
- * (code)
- * var xmlDoc = mxUtils.createXmlDocument();
- * var root = xmlDoc.createElement('output');
- * xmlDoc.appendChild(root);
- *
- * var xmlCanvas = new mxXmlCanvas2D(root);
- * var imgExport = new mxImageExport();
- * imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas);
- *
- * var bounds = graph.getGraphBounds();
- * var w = Math.ceil(bounds.x + bounds.width);
- * var h = Math.ceil(bounds.y + bounds.height);
- *
- * var xml = mxUtils.getXml(root);
- * new mxXmlRequest('export', 'format=png&w=' + w +
- * '&h=' + h + '&bg=#F9F7ED&xml=' + encodeURIComponent(xml))
- * .simulate(document, '_blank');
- * (end)
- *
- * In order to export images for a graph whose container is not visible or not
- * part of the DOM, the following workaround can be used to compute the size of
- * the labels.
- *
- * (code)
- * mxText.prototype.getTableSize = function(table)
- * {
- * var oldParent = table.parentNode;
- *
- * document.body.appendChild(table);
- * var size = new mxRectangle(0, 0, table.offsetWidth, table.offsetHeight);
- * oldParent.appendChild(table);
- *
- * return size;
- * };
- * (end)
- *
- * Constructor: mxImageExport
- *
- * Constructs a new image export.
- */
-function mxImageExport()
-{
- this.initShapes();
- this.initMarkers();
-};
-
-/**
- * Variable: includeOverlays
- *
- * Specifies if overlays should be included in the export. Default is false.
- */
-mxImageExport.prototype.includeOverlays = false;
-
-/**
- * Variable: glassSize
- *
- * Reference to the thread while the animation is running.
- */
-mxImageExport.prototype.glassSize = 0.4;
-
-/**
- * Variable: shapes
- *
- * Holds implementations for the built-in shapes.
- */
-mxImageExport.prototype.shapes = null;
-
-/**
- * Variable: markers
- *
- * Holds implementations for the built-in markers.
- */
-mxImageExport.prototype.markers = null;
-
-/**
- * Function: drawState
- *
- * Draws the given state and all its descendants to the given canvas.
- */
-mxImageExport.prototype.drawState = function(state, canvas)
-{
- if (state != null)
- {
- if (state.shape != null)
- {
- var shape = (state.shape.stencil != null) ?
- state.shape.stencil :
- this.shapes[state.style[mxConstants.STYLE_SHAPE]];
-
- if (shape == null)
- {
- // Checks if there is a custom shape
- if (typeof(state.shape.redrawPath) == 'function')
- {
- shape = this.createShape(state, canvas);
- }
- // Uses a rectangle for all vertices where no shape can be found
- else if (state.view.graph.getModel().isVertex(state.cell))
- {
- shape = this.shapes['rectangle'];
- }
- }
-
- if (shape != null)
- {
- this.drawShape(state, canvas, shape);
-
- if (this.includeOverlays)
- {
- this.drawOverlays(state, canvas);
- }
- }
- }
-
- var graph = state.view.graph;
- var childCount = graph.model.getChildCount(state.cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var childState = graph.view.getState(graph.model.getChildAt(state.cell, i));
- this.drawState(childState, canvas);
- }
- }
-};
-
-/**
- * Function: createShape
- *
- * Creates a shape wrapper for the custom shape in the given cell state and
- * links its output to the given canvas.
- */
-mxImageExport.prototype.createShape = function(state, canvas)
-{
- return {
- drawShape: function(canvas, state, bounds, background)
- {
- var path =
- {
- translate: new mxPoint(bounds.x, bounds.y),
- moveTo: function(x, y)
- {
- canvas.moveTo(this.translate.x + x, this.translate.y + y);
- },
- lineTo: function(x, y)
- {
- canvas.lineTo(this.translate.x + x, this.translate.y + y);
- },
- quadTo: function(x1, y1, x, y)
- {
- canvas.quadTo(this.translate.x + x1, this.translate.y + y1, this.translate.x + x, this.translate.y + y);
- },
- curveTo: function(x1, y1, x2, y2, x, y)
- {
- canvas.curveTo(this.translate.x + x1, this.translate.y + y1, this.translate.x + x2, this.translate.y + y2, this.translate.x + x, this.translate.y + y);
- },
- end: function()
- {
- // do nothing
- },
- close: function()
- {
- canvas.close();
- }
- };
-
- if (!background)
- {
- canvas.fillAndStroke();
- }
-
- // LATER: Remove empty path if shape does not implement foreground, add shadow/clipping
- canvas.begin();
- state.shape.redrawPath.call(state.shape, path, bounds.x, bounds.y, bounds.width, bounds.height, !background);
-
- if (!background)
- {
- canvas.fillAndStroke();
- }
-
- return true;
- }
- };
-};
-
-/**
- * Function: drawOverlays
- *
- * Draws the overlays for the given state. This is called if <includeOverlays>
- * is true.
- */
-mxImageExport.prototype.drawOverlays = function(state, canvas)
-{
- if (state.overlays != null)
- {
- state.overlays.visit(function(id, shape)
- {
- var bounds = shape.bounds;
-
- if (bounds != null)
- {
- canvas.image(bounds.x, bounds.y, bounds.width, bounds.height, shape.image);
- }
- });
- }
-};
-
-/**
- * Function: drawShape
- *
- * Draws the given state to the given canvas.
- */
-mxImageExport.prototype.drawShape = function(state, canvas, shape)
-{
- var rotation = mxUtils.getNumber(state.style, mxConstants.STYLE_ROTATION, 0);
- var direction = mxUtils.getValue(state.style, mxConstants.STYLE_DIRECTION, null);
-
- // New styles for shape flipping the stencil
- var flipH = state.style[mxConstants.STYLE_STENCIL_FLIPH];
- var flipV = state.style[mxConstants.STYLE_STENCIL_FLIPV];
-
- if (flipH ? !flipV : flipV)
- {
- rotation *= -1;
- }
-
- // Default direction is east (ignored if rotation exists)
- if (direction != null)
- {
- if (direction == 'north')
- {
- rotation += 270;
- }
- else if (direction == 'west')
- {
- rotation += 180;
- }
- else if (direction == 'south')
- {
- rotation += 90;
- }
- }
-
- if (flipH && flipV)
- {
- rotation += 180;
- flipH = false;
- flipV = false;
- }
-
- // Saves the global state for each cell
- canvas.save();
-
- // Adds rotation and horizontal/vertical flipping
- // FIXME: Rotation and stencil flip only supported for stencil shapes
- rotation = rotation % 360;
-
- if (rotation != 0 || flipH || flipV)
- {
- canvas.rotate(rotation, flipH, flipV, state.getCenterX(), state.getCenterY());
- }
-
- // Note: Overwritten in mxStencil.paintShape (can depend on aspect)
- var scale = state.view.scale;
- var sw = mxUtils.getNumber(state.style, mxConstants.STYLE_STROKEWIDTH, 1) * scale;
- canvas.setStrokeWidth(sw);
-
- var sw2 = sw / 2;
- var bg = this.getBackgroundBounds(state);
-
- // Stencils will rotate the bounds as required
- if (state.shape.stencil == null && (direction == 'south' || direction == 'north'))
- {
- var dx = (bg.width - bg.height) / 2;
- bg.x += dx;
- bg.y += -dx;
- var tmp = bg.width;
- bg.width = bg.height;
- bg.height = tmp;
- }
-
- var bb = new mxRectangle(bg.x - sw2, bg.y - sw2, bg.width + sw, bg.height + sw);
- var alpha = mxUtils.getValue(state.style, mxConstants.STYLE_OPACITY, 100) / 100;
-
- var shp = state.style[mxConstants.STYLE_SHAPE];
- var imageShape = shp == mxConstants.SHAPE_IMAGE;
- var gradientColor = (imageShape) ? null : mxUtils.getValue(state.style, mxConstants.STYLE_GRADIENTCOLOR);
-
- // Converts colors with special keyword none to null
- if (gradientColor == mxConstants.NONE)
- {
- gradientColor = null;
- }
-
- var fcKey = (imageShape) ? mxConstants.STYLE_IMAGE_BACKGROUND : mxConstants.STYLE_FILLCOLOR;
- var fillColor = mxUtils.getValue(state.style, fcKey, null);
-
- if (fillColor == mxConstants.NONE)
- {
- fillColor = null;
- }
-
- var scKey = (imageShape) ? mxConstants.STYLE_IMAGE_BORDER : mxConstants.STYLE_STROKECOLOR;
- var strokeColor = mxUtils.getValue(state.style, scKey, null);
-
- if (strokeColor == mxConstants.NONE)
- {
- strokeColor = null;
- }
-
- var glass = (fillColor != null && (shp == mxConstants.SHAPE_LABEL || shp == mxConstants.SHAPE_RECTANGLE));
-
- // Draws the shadow if the fillColor is not transparent
- if (mxUtils.getValue(state.style, mxConstants.STYLE_SHADOW, false))
- {
- this.drawShadow(canvas, state, shape, rotation, flipH, flipV, bg, alpha, fillColor != null);
- }
-
- canvas.setAlpha(alpha);
-
- // Sets the dashed state
- if (mxUtils.getValue(state.style, mxConstants.STYLE_DASHED, '0') == '1')
- {
- canvas.setDashed(true);
-
- // Supports custom dash patterns
- var dash = state.style['dashPattern'];
-
- if (dash != null)
- {
- canvas.setDashPattern(dash);
- }
- }
-
- // Draws background and foreground
- if (strokeColor != null || fillColor != null)
- {
- if (strokeColor != null)
- {
- canvas.setStrokeColor(strokeColor);
- }
-
- if (fillColor != null)
- {
- if (gradientColor != null && gradientColor != 'transparent')
- {
- canvas.setGradient(fillColor, gradientColor, bg.x, bg.y, bg.width, bg.height, direction);
- }
- else
- {
- canvas.setFillColor(fillColor);
- }
- }
-
- // Draws background and foreground of shape
- glass = shape.drawShape(canvas, state, bg, true, false) && glass;
- shape.drawShape(canvas, state, bg, false, false);
- }
-
- // Draws the glass effect
- // Requires background in generic shape for clipping
- if (glass && mxUtils.getValue(state.style, mxConstants.STYLE_GLASS, 0) == 1)
- {
- this.drawGlass(state, canvas, bb, shape, this.glassSize);
- }
-
- // Draws the image (currently disabled for everything but image and label shapes)
- if (imageShape || shp == mxConstants.SHAPE_LABEL)
- {
- var src = state.view.graph.getImage(state);
-
- if (src != null)
- {
- var imgBounds = this.getImageBounds(state);
-
- if (imgBounds != null)
- {
- this.drawImage(state, canvas, imgBounds, src);
- }
- }
- }
-
- // Restores canvas state
- canvas.restore();
-
- // Draws the label (label has separate rotation)
- var txt = state.text;
-
- // Does not use mxCellRenderer.getLabelValue to avoid conversion of HTML entities for VML
- var label = state.view.graph.getLabel(state.cell);
-
- if (txt != null && label != null && label.length > 0)
- {
- canvas.save();
- canvas.setAlpha(mxUtils.getValue(state.style, mxConstants.STYLE_TEXT_OPACITY, 100) / 100);
- var bounds = new mxRectangle(txt.boundingBox.x, txt.boundingBox.y, txt.boundingBox.width, txt.boundingBox.height);
- var vert = mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 0;
-
- // Vertical error offset
- bounds.y += 2;
-
- if (vert)
- {
- if (txt.dialect != mxConstants.DIALECT_SVG)
- {
- var cx = bounds.x + bounds.width / 2;
- var cy = bounds.y + bounds.height / 2;
- var tmp = bounds.width;
- bounds.width = bounds.height;
- bounds.height = tmp;
- bounds.x = cx - bounds.width / 2;
- bounds.y = cy - bounds.height / 2;
- }
- else if (txt.dialect == mxConstants.DIALECT_SVG)
- {
- // Workarounds for different label bounding boxes (mostly ignoring rotation).
- // LATER: Fix in mxText so that the bounding box is consistent and rotated.
- // TODO: Check non-center/middle-aligned vertical labels in VML for IE8.
- var b = state.y + state.height;
- var cx = bounds.getCenterX() - state.x;
- var cy = bounds.getCenterY() - state.y;
-
- var y = b - cx - bounds.height / 2;
- bounds.x = state.x + cy - bounds.width / 2;
- bounds.y = y;
- //bounds.x -= state.height / 2 - state.width / 2;
- //bounds.y -= state.width / 2 - state.height / 2;
- }
- }
-
- this.drawLabelBackground(state, canvas, bounds, vert);
- this.drawLabel(state, canvas, bounds, vert, label);
- canvas.restore();
- }
-};
-
-/**
- * Function: drawGlass
- *
- * Draws the given state to the given canvas.
- */
-mxImageExport.prototype.drawShadow = function(canvas, state, shape, rotation, flipH, flipV, bounds, alpha, filled)
-{
- // Requires background in generic shape for shadow, looks like only one
- // fillAndStroke is allowed per current path, try working around that
- // Computes rotated shadow offset
- var rad = rotation * Math.PI / 180;
- var cos = Math.cos(-rad);
- var sin = Math.sin(-rad);
- var offset = mxUtils.getRotatedPoint(new mxPoint(mxConstants.SHADOW_OFFSET_X, mxConstants.SHADOW_OFFSET_Y), cos, sin);
-
- if (flipH)
- {
- offset.x *= -1;
- }
-
- if (flipV)
- {
- offset.y *= -1;
- }
-
- // TODO: Use save/restore instead of negative offset to restore (requires fix for HTML canvas)
- canvas.translate(offset.x, offset.y);
-
- // Returns true if a shadow has been painted (path has been created)
- if (shape.drawShape(canvas, state, bounds, true, true))
- {
- canvas.setAlpha(mxConstants.SHADOW_OPACITY * alpha);
- canvas.shadow(mxConstants.SHADOWCOLOR, filled);
- }
-
- canvas.translate(-offset.x, -offset.y);
-};
-
-/**
- * Function: drawGlass
- *
- * Draws the given state to the given canvas.
- */
-mxImageExport.prototype.drawGlass = function(state, canvas, bounds, shape, size)
-{
- // LATER: Clipping region should include stroke
- if (shape.drawShape(canvas, state, bounds, true, false))
- {
- canvas.save();
- canvas.clip();
- canvas.setGlassGradient(bounds.x, bounds.y, bounds.width, bounds.height);
-
- canvas.begin();
- canvas.moveTo(bounds.x, bounds.y);
- canvas.lineTo(bounds.x, (bounds.y + bounds.height * size));
- canvas.quadTo((bounds.x + bounds.width * 0.5),
- (bounds.y + bounds.height * 0.7), bounds.x + bounds.width,
- (bounds.y + bounds.height * size));
- canvas.lineTo(bounds.x + bounds.width, bounds.y);
- canvas.close();
-
- canvas.fill();
- canvas.restore();
- }
-};
-
-/**
- * Function: drawImage
- *
- * Draws the given state to the given canvas.
- */
-mxImageExport.prototype.drawImage = function(state, canvas, bounds, image)
-{
- var aspect = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_ASPECT, 1) == 1;
- var flipH = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_FLIPH, 0) == 1;
- var flipV = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_FLIPV, 0) == 1;
-
- canvas.image(bounds.x, bounds.y, bounds.width, bounds.height, image, aspect, flipH, flipV);
-};
-
-/**
- * Function: drawLabelBackground
- *
- * Draws background for the label of the given state to the given canvas.
- */
-mxImageExport.prototype.drawLabelBackground = function(state, canvas, bounds, vert)
-{
- var stroke = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_BORDERCOLOR);
- var fill = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_BACKGROUNDCOLOR);
-
- if (stroke == mxConstants.NONE)
- {
- stroke = null;
- }
-
- if (fill == mxConstants.NONE)
- {
- fill = null;
- }
-
- if (stroke != null || fill != null)
- {
- var x = bounds.x;
- var y = bounds.y - mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_PADDING, 0);
- var w = bounds.width;
- var h = bounds.height;
-
- if (vert)
- {
- x += (w - h) / 2;
- y += (h - w) / 2;
- var tmp = w;
- w = h;
- h = tmp;
- }
-
- if (fill != null)
- {
- canvas.setFillColor(fill);
- }
-
- if (stroke != null)
- {
- canvas.setStrokeColor(stroke);
- canvas.setStrokeWidth(1);
- canvas.setDashed(false);
- }
-
- canvas.rect(x, y, w, h);
-
- if (fill != null && stroke != null)
- {
- canvas.fillAndStroke();
- }
- else if (fill != null)
- {
- canvas.fill();
- }
- else if (stroke != null)
- {
- canvas.stroke();
- }
- }
-};
-
-/**
- * Function: drawLabel
- *
- * Draws the given state to the given canvas.
- */
-mxImageExport.prototype.drawLabel = function(state, canvas, bounds, vert, str)
-{
- var scale = state.view.scale;
-
- // Applies color
- canvas.setFontColor(mxUtils.getValue(state.style, mxConstants.STYLE_FONTCOLOR, '#000000'));
-
- // Applies font settings
- canvas.setFontFamily(mxUtils.getValue(state.style, mxConstants.STYLE_FONTFAMILY,
- mxConstants.DEFAULT_FONTFAMILY));
- canvas.setFontStyle(mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0));
- canvas.setFontSize(mxUtils.getValue(state.style, mxConstants.STYLE_FONTSIZE,
- mxConstants.DEFAULT_FONTSIZE) * scale);
-
- var align = mxUtils.getValue(state.style, mxConstants.STYLE_ALIGN, mxConstants.ALIGN_LEFT);
-
- // Uses null alignment for default values (valign default is 'top' which is fine)
- if (align == 'left')
- {
- align = null;
- }
-
- var y = bounds.y - mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_PADDING, 0);
- var wrap = state.view.graph.isWrapping(state.cell);
- var html = state.view.graph.isHtmlLabel(state.cell);
-
- // Replaces linefeeds in HTML markup to match the display output
- if (html && mxText.prototype.replaceLinefeeds)
- {
- str = str.replace(/\n/g, '<br/>');
- }
-
- canvas.text(bounds.x, y, bounds.width, bounds.height, str, align, null, vert, wrap, (html) ? 'html' : '');
-};
-
-/**
- * Function: getBackgroundBounds
- *
- * Draws the given state to the given canvas.
- */
-mxImageExport.prototype.getBackgroundBounds = function(state)
-{
- if (state.style[mxConstants.STYLE_SHAPE] == mxConstants.SHAPE_SWIMLANE)
- {
- var scale = state.view.scale;
- var start = mxUtils.getValue(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE) * scale;
- var w = state.width;
- var h = state.height;
-
- if (mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, true))
- {
- h = start;
- }
- else
- {
- w = start;
- }
-
- return new mxRectangle(state.x, state.y, Math.min(state.width, w), Math.min(state.height, h));
- }
- else
- {
- return new mxRectangle(state.x, state.y, state.width, state.height);
- }
-};
-
-/**
- * Function: getImageBounds
- *
- * Draws the given state to the given canvas.
- */
-mxImageExport.prototype.getImageBounds = function(state)
-{
- var bounds = new mxRectangle(state.x, state.y, state.width, state.height);
- var style = state.style;
-
- if (mxUtils.getValue(style, mxConstants.STYLE_SHAPE) != mxConstants.SHAPE_IMAGE)
- {
- var imgAlign = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_ALIGN, mxConstants.ALIGN_LEFT);
- var imgValign = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE);
- var imgWidth = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_WIDTH, mxConstants.DEFAULT_IMAGESIZE);
- var imgHeight = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_HEIGHT, mxConstants.DEFAULT_IMAGESIZE);
- var spacing = mxUtils.getValue(style, mxConstants.STYLE_SPACING, 2);
-
- if (imgAlign == mxConstants.ALIGN_CENTER)
- {
- bounds.x += (bounds.width - imgWidth) / 2;
- }
- else if (imgAlign == mxConstants.ALIGN_RIGHT)
- {
- bounds.x += bounds.width - imgWidth - spacing - 2;
- }
- else
- // LEFT
- {
- bounds.x += spacing + 4;
- }
-
- if (imgValign == mxConstants.ALIGN_TOP)
- {
- bounds.y += spacing;
- }
- else if (imgValign == mxConstants.ALIGN_BOTTOM)
- {
- bounds.y += bounds.height - imgHeight - spacing;
- }
- else
- // MIDDLE
- {
- bounds.y += (bounds.height - imgHeight) / 2;
- }
-
- bounds.width = imgWidth;
- bounds.height = imgHeight;
- }
-
- return bounds;
-};
-
-/**
- * Function: drawMarker
- *
- * Initializes the built-in shapes.
- */
-mxImageExport.prototype.drawMarker = function(canvas, state, source)
-{
- var offset = null;
-
- // Computes the norm and the inverse norm
- var pts = state.absolutePoints;
- var n = pts.length;
-
- var p0 = (source) ? pts[1] : pts[n - 2];
- var pe = (source) ? pts[0] : pts[n - 1];
-
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
-
- var dist = Math.max(1, Math.sqrt(dx * dx + dy * dy));
-
- var unitX = dx / dist;
- var unitY = dy / dist;
-
- var size = mxUtils.getValue(state.style, (source) ?
- mxConstants.STYLE_STARTSIZE :
- mxConstants.STYLE_ENDSIZE,
- mxConstants.DEFAULT_MARKERSIZE);
-
- // Allow for stroke width in the end point used and the
- // orthogonal vectors describing the direction of the marker
- // TODO: Should get strokewidth from canvas (same for strokecolor)
- var sw = mxUtils.getValue(state.style, mxConstants.STYLE_STROKEWIDTH, 1);
-
- pe = pe.clone();
-
- var type = mxUtils.getValue(state.style, (source) ?
- mxConstants.STYLE_STARTARROW :
- mxConstants.STYLE_ENDARROW);
- var f = this.markers[type];
-
- if (f != null)
- {
- offset = f(canvas, state, type, pe, unitX, unitY, size, source, sw);
- }
-
- return offset;
-};
-
-/**
- * Function: initShapes
- *
- * Initializes the built-in shapes.
- */
-mxImageExport.prototype.initShapes = function()
-{
- this.shapes = [];
-
- // Implements the rectangle and rounded rectangle shape
- this.shapes['rectangle'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- // Paints the shape
- if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false))
- {
- var f = mxUtils.getValue(state.style, mxConstants.STYLE_ARCSIZE, mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100;
- var r = Math.min(bounds.width * f, bounds.height * f);
- canvas.roundrect(bounds.x, bounds.y, bounds.width, bounds.height, r, r);
- }
- else
- {
- canvas.rect(bounds.x, bounds.y, bounds.width, bounds.height);
- }
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- }
- }
- };
-
- // Implements the swimlane shape
- this.shapes['swimlane'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false))
- {
- var r = Math.min(bounds.width * mxConstants.RECTANGLE_ROUNDING_FACTOR,
- bounds.height * mxConstants.RECTANGLE_ROUNDING_FACTOR);
- canvas.roundrect(bounds.x, bounds.y, bounds.width, bounds.height, r, r);
- }
- else
- {
- canvas.rect(bounds.x, bounds.y, bounds.width, bounds.height);
- }
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- canvas.begin();
-
- var x = state.x;
- var y = state.y;
- var w = state.width;
- var h = state.height;
-
- if (mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 0)
- {
- x += bounds.width;
- w -= bounds.width;
-
- canvas.moveTo(x, y);
- canvas.lineTo(x + w, y);
- canvas.lineTo(x + w, y + h);
- canvas.lineTo(x, y + h);
- }
- else
- {
- y += bounds.height;
- h -= bounds.height;
-
- canvas.moveTo(x, y);
- canvas.lineTo(x, y + h);
- canvas.lineTo(x + w, y + h);
- canvas.lineTo(x + w, y);
- }
-
- canvas.stroke();
- }
- }
- };
-
- this.shapes['image'] = this.shapes['rectangle'];
- this.shapes['label'] = this.shapes['rectangle'];
-
- var imageExport = this;
-
- this.shapes['connector'] =
- {
- translatePoint: function(points, index, offset)
- {
- if (offset != null)
- {
- var pt = points[index].clone();
- pt.x += offset.x;
- pt.y += offset.y;
- points[index] = pt;
- }
- },
-
- drawShape: function(canvas, state, bounds, background, shadow)
- {
- if (background)
- {
- var rounded = mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false);
- var arcSize = mxConstants.LINE_ARCSIZE / 2;
-
- // Does not draw the markers in the shadow to match the display
- canvas.setFillColor((shadow) ? mxConstants.NONE : mxUtils.getValue(state.style, mxConstants.STYLE_STROKECOLOR, "#000000"));
- canvas.setDashed(false);
- var pts = state.absolutePoints.slice();
- this.translatePoint(pts, 0, imageExport.drawMarker(canvas, state, true));
- this.translatePoint(pts, pts.length - 1, imageExport.drawMarker(canvas, state, false));
- canvas.setDashed(mxUtils.getValue(state.style, mxConstants.STYLE_DASHED, '0') == '1');
-
- var pt = pts[0];
- var pe = pts[pts.length - 1];
- canvas.begin();
- canvas.moveTo(pt.x, pt.y);
-
- // Draws the line segments
- for (var i = 1; i < pts.length - 1; i++)
- {
- var tmp = pts[i];
- var dx = pt.x - tmp.x;
- var dy = pt.y - tmp.y;
-
- if ((rounded && i < pts.length - 1) && (dx != 0 || dy != 0))
- {
- // Draws a line from the last point to the current
- // point with a spacing of size off the current point
- // into direction of the last point
- var dist = Math.sqrt(dx * dx + dy * dy);
- var nx1 = dx * Math.min(arcSize, dist / 2) / dist;
- var ny1 = dy * Math.min(arcSize, dist / 2) / dist;
-
- var x1 = tmp.x + nx1;
- var y1 = tmp.y + ny1;
- canvas.lineTo(x1, y1);
-
- // Draws a curve from the last point to the current
- // point with a spacing of size off the current point
- // into direction of the next point
- var next = pts[i + 1];
- dx = next.x - tmp.x;
- dy = next.y - tmp.y;
-
- dist = Math.max(1, Math.sqrt(dx * dx + dy * dy));
- var nx2 = dx * Math.min(arcSize, dist / 2) / dist;
- var ny2 = dy * Math.min(arcSize, dist / 2) / dist;
-
- var x2 = tmp.x + nx2;
- var y2 = tmp.y + ny2;
-
- canvas.curveTo(tmp.x, tmp.y, tmp.x, tmp.y, x2, y2);
- tmp = new mxPoint(x2, y2);
- }
- else
- {
- canvas.lineTo(tmp.x, tmp.y);
- }
-
- pt = tmp;
- }
-
- canvas.lineTo(pe.x, pe.y);
- canvas.stroke();
-
- return true;
- }
- else
- {
- // no foreground
- }
- }
- };
-
- this.shapes['arrow'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- // Geometry of arrow
- var spacing = mxConstants.ARROW_SPACING;
- var width = mxConstants.ARROW_WIDTH;
- var arrow = mxConstants.ARROW_SIZE;
-
- // Base vector (between end points)
- var pts = state.absolutePoints;
- var p0 = pts[0];
- var pe = pts[pts.length - 1];
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
- var dist = Math.sqrt(dx * dx + dy * dy);
- var length = dist - 2 * spacing - arrow;
-
- // Computes the norm and the inverse norm
- var nx = dx / dist;
- var ny = dy / dist;
- var basex = length * nx;
- var basey = length * ny;
- var floorx = width * ny/3;
- var floory = -width * nx/3;
-
- // Computes points
- var p0x = p0.x - floorx / 2 + spacing * nx;
- var p0y = p0.y - floory / 2 + spacing * ny;
- var p1x = p0x + floorx;
- var p1y = p0y + floory;
- var p2x = p1x + basex;
- var p2y = p1y + basey;
- var p3x = p2x + floorx;
- var p3y = p2y + floory;
- // p4 not necessary
- var p5x = p3x - 3 * floorx;
- var p5y = p3y - 3 * floory;
-
- canvas.begin();
- canvas.moveTo(p0x, p0y);
- canvas.lineTo(p1x, p1y);
- canvas.lineTo(p2x, p2y);
- canvas.lineTo(p3x, p3y);
- canvas.lineTo(pe.x - spacing * nx, pe.y - spacing * ny);
- canvas.lineTo(p5x, p5y);
- canvas.lineTo(p5x + floorx, p5y + floory);
- canvas.close();
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- }
- }
- };
-
- this.shapes['cylinder'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- return false;
- }
- else
- {
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
- var dy = Math.min(mxCylinder.prototype.maxHeight, Math.floor(h / 5));
-
- canvas.begin();
- canvas.moveTo(x, y + dy);
- canvas.curveTo(x, y - dy / 3, x + w, y - dy / 3, x + w, y + dy);
- canvas.lineTo(x + w, y + h - dy);
- canvas.curveTo(x + w, y + h + dy / 3, x, y + h + dy / 3, x, y + h - dy);
- canvas.close();
- canvas.fillAndStroke();
-
- canvas.begin();
- canvas.moveTo(x, y + dy);
- canvas.curveTo(x, y + 2 * dy, x + w, y + 2 * dy, x + w, y + dy);
- canvas.stroke();
- }
- }
- };
-
- this.shapes['line'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- return false;
- }
- else
- {
- canvas.begin();
-
- var mid = state.getCenterY();
- canvas.moveTo(bounds.x, mid);
- canvas.lineTo(bounds.x + bounds.width, mid);
-
- canvas.stroke();
- }
- }
- };
-
- this.shapes['ellipse'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- canvas.ellipse(bounds.x, bounds.y, bounds.width, bounds.height);
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- }
- }
- };
-
- this.shapes['doubleEllipse'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
-
- if (background)
- {
- canvas.ellipse(x, y, w, h);
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
-
- var inset = Math.min(4, Math.min(w / 5, h / 5));
- x += inset;
- y += inset;
- w -= 2 * inset;
- h -= 2 * inset;
-
- if (w > 0 && h > 0)
- {
- canvas.ellipse(x, y, w, h);
- }
-
- canvas.stroke();
- }
- }
- };
-
- this.shapes['triangle'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
- canvas.begin();
- canvas.moveTo(x, y);
- canvas.lineTo(x + w, y + h / 2);
- canvas.lineTo(x, y + h);
- canvas.close();
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- }
- }
- };
-
- this.shapes['rhombus'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
- var hw = w / 2;
- var hh = h / 2;
-
- canvas.begin();
- canvas.moveTo(x + hw, y);
- canvas.lineTo(x + w, y + hh);
- canvas.lineTo(x + hw, y + h);
- canvas.lineTo(x, y + hh);
- canvas.close();
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- }
- }
-
- };
-
- this.shapes['hexagon'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
-
- canvas.begin();
- canvas.moveTo(x + 0.25 * w, y);
- canvas.lineTo(x + 0.75 * w, y);
- canvas.lineTo(x + w, y + 0.5 * h);
- canvas.lineTo(x + 0.75 * w, y + h);
- canvas.lineTo(x + 0.25 * w, y + h);
- canvas.lineTo(x, y + 0.5 * h);
- canvas.close();
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- }
- }
- };
-
- this.shapes['actor'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
- var width = w * 2 / 6;
-
- canvas.begin();
- canvas.moveTo(x, y + h);
- canvas.curveTo(x, y + 3 * h / 5, x, y + 2 * h / 5, x + w / 2, y + 2 * h
- / 5);
- canvas.curveTo(x + w / 2 - width, y + 2 * h / 5, x + w / 2 - width, y, x
- + w / 2, y);
- canvas.curveTo(x + w / 2 + width, y, x + w / 2 + width, y + 2 * h / 5, x
- + w / 2, y + 2 * h / 5);
- canvas.curveTo(x + w, y + 2 * h / 5, x + w, y + 3 * h / 5, x + w, y + h);
- canvas.close();
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- }
- }
- };
-
- this.shapes['cloud'] =
- {
- drawShape: function(canvas, state, bounds, background)
- {
- if (background)
- {
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
-
- canvas.begin();
- canvas.moveTo(x + 0.25 * w, y + 0.25 * h);
- canvas.curveTo(x + 0.05 * w, y + 0.25 * h, x,
- y + 0.5 * h, x + 0.16 * w, y + 0.55 * h);
- canvas.curveTo(x, y + 0.66 * h, x + 0.18 * w,
- y + 0.9 * h, x + 0.31 * w, y + 0.8 * h);
- canvas.curveTo(x + 0.4 * w, y + h, x + 0.7 * w,
- y + h, x + 0.8 * w, y + 0.8 * h);
- canvas.curveTo(x + w, y + 0.8 * h, x + w,
- y + 0.6 * h, x + 0.875 * w, y + 0.5 * h);
- canvas.curveTo(x + w, y + 0.3 * h, x + 0.8 * w,
- y + 0.1 * h, x + 0.625 * w, y + 0.2 * h);
- canvas.curveTo(x + 0.5 * w, y + 0.05 * h,
- x + 0.3 * w, y + 0.05 * h,
- x + 0.25 * w, y + 0.25 * h);
- canvas.close();
-
- return true;
- }
- else
- {
- canvas.fillAndStroke();
- }
- }
- };
-
-};
-
-/**
- * Function: initMarkers
- *
- * Initializes the built-in markers.
- */
-mxImageExport.prototype.initMarkers = function()
-{
- this.markers = [];
-
- var tmp = function(canvas, state, type, pe, unitX, unitY, size, source, sw)
- {
- // The angle of the forward facing arrow sides against the x axis is
- // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
- // only half the strokewidth is processed ).
- var endOffsetX = unitX * sw * 1.118;
- var endOffsetY = unitY * sw * 1.118;
-
- pe.x -= endOffsetX;
- pe.y -= endOffsetY;
-
- unitX = unitX * (size + sw);
- unitY = unitY * (size + sw);
-
- canvas.begin();
- canvas.moveTo(pe.x, pe.y);
- canvas.lineTo(pe.x - unitX - unitY / 2, pe.y - unitY + unitX / 2);
-
- if (type == mxConstants.ARROW_CLASSIC)
- {
- canvas.lineTo(pe.x - unitX * 3 / 4, pe.y - unitY * 3 / 4);
- }
-
- canvas.lineTo(pe.x + unitY / 2 - unitX, pe.y - unitY - unitX / 2);
- canvas.close();
-
- var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL;
-
- if (state.style[key] == 0)
- {
- canvas.stroke();
- }
- else
- {
- canvas.fillAndStroke();
- }
-
- var f = (type != mxConstants.ARROW_CLASSIC) ? 1 : 3 / 4;
- return new mxPoint(-unitX * f - endOffsetX, -unitY * f - endOffsetY);
- };
-
- this.markers['classic'] = tmp;
- this.markers['block'] = tmp;
-
- this.markers['open'] = function(canvas, state, type, pe, unitX, unitY, size, source, sw)
- {
- // The angle of the forward facing arrow sides against the x axis is
- // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
- // only half the strokewidth is processed ).
- var endOffsetX = unitX * sw * 1.118;
- var endOffsetY = unitY * sw * 1.118;
-
- pe.x -= endOffsetX;
- pe.y -= endOffsetY;
-
- unitX = unitX * (size + sw);
- unitY = unitY * (size + sw);
-
- canvas.begin();
- canvas.moveTo(pe.x - unitX - unitY / 2, pe.y - unitY + unitX / 2);
- canvas.lineTo(pe.x, pe.y);
- canvas.lineTo(pe.x + unitY / 2 - unitX, pe.y - unitY - unitX / 2);
- canvas.stroke();
-
- return new mxPoint(-endOffsetX * 2, -endOffsetY * 2);
- };
-
- this.markers['oval'] = function(canvas, state, type, pe, unitX, unitY, size, source, sw)
- {
- var a = size / 2;
-
- canvas.ellipse(pe.x - a, pe.y - a, size, size);
-
- var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL;
-
- if (state.style[key] == 0)
- {
- canvas.stroke();
- }
- else
- {
- canvas.fillAndStroke();
- }
-
- return new mxPoint(-unitX / 2, -unitY / 2);
- };
-
- var tmp_diamond = function(canvas, state, type, pe, unitX, unitY, size, source, sw)
- {
- // The angle of the forward facing arrow sides against the x axis is
- // 45 degrees, 1/sin(45) = 1.4142 / 2 = 0.7071 ( / 2 allows for
- // only half the strokewidth is processed ). Or 0.9862 for thin diamond.
- // Note these values and the tk variable below are dependent, update
- // both together (saves trig hard coding it).
- var swFactor = (type == mxConstants.ARROW_DIAMOND) ? 0.7071 : 0.9862;
- var endOffsetX = unitX * sw * swFactor;
- var endOffsetY = unitY * sw * swFactor;
-
- unitX = unitX * (size + sw);
- unitY = unitY * (size + sw);
-
- pe.x -= endOffsetX;
- pe.y -= endOffsetY;
-
- // thickness factor for diamond
- var tk = ((type == mxConstants.ARROW_DIAMOND) ? 2 : 3.4);
-
- canvas.begin();
- canvas.moveTo(pe.x, pe.y);
- canvas.lineTo(pe.x - unitX / 2 - unitY / tk, pe.y + unitX / tk - unitY / 2);
- canvas.lineTo(pe.x - unitX, pe.y - unitY);
- canvas.lineTo(pe.x - unitX / 2 + unitY / tk, pe.y - unitY / 2 - unitX / tk);
- canvas.close();
-
- var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL;
-
- if (state.style[key] == 0)
- {
- canvas.stroke();
- }
- else
- {
- canvas.fillAndStroke();
- }
-
- return new mxPoint(-endOffsetX - unitX, -endOffsetY - unitY);
- };
-
- this.markers['diamond'] = tmp_diamond;
- this.markers['diamondThin'] = tmp_diamond;
-};
diff --git a/src/js/util/mxLog.js b/src/js/util/mxLog.js
deleted file mode 100644
index c556e22..0000000
--- a/src/js/util/mxLog.js
+++ /dev/null
@@ -1,410 +0,0 @@
-/**
- * $Id: mxLog.js,v 1.32 2012-11-12 09:40:59 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxLog =
-{
- /**
- * Class: mxLog
- *
- * A singleton class that implements a simple console.
- *
- * Variable: consoleName
- *
- * Specifies the name of the console window. Default is 'Console'.
- */
- consoleName: 'Console',
-
- /**
- * Variable: TRACE
- *
- * Specified if the output for <enter> and <leave> should be visible in the
- * console. Default is false.
- */
- TRACE: false,
-
- /**
- * Variable: DEBUG
- *
- * Specifies if the output for <debug> should be visible in the console.
- * Default is true.
- */
- DEBUG: true,
-
- /**
- * Variable: WARN
- *
- * Specifies if the output for <warn> should be visible in the console.
- * Default is true.
- */
- WARN: true,
-
- /**
- * Variable: buffer
- *
- * Buffer for pre-initialized content.
- */
- buffer: '',
-
- /**
- * Function: init
- *
- * Initializes the DOM node for the console. This requires document.body to
- * point to a non-null value. This is called from within <setVisible> if the
- * log has not yet been initialized.
- */
- init: function()
- {
- if (mxLog.window == null && document.body != null)
- {
- var title = mxLog.consoleName + ' - mxGraph ' + mxClient.VERSION;
-
- // Creates a table that maintains the layout
- var table = document.createElement('table');
- table.setAttribute('width', '100%');
- table.setAttribute('height', '100%');
-
- var tbody = document.createElement('tbody');
- var tr = document.createElement('tr');
- var td = document.createElement('td');
- td.style.verticalAlign = 'top';
-
- // Adds the actual console as a textarea
- mxLog.textarea = document.createElement('textarea');
- mxLog.textarea.setAttribute('readOnly', 'true');
- mxLog.textarea.style.height = '100%';
- mxLog.textarea.style.resize = 'none';
- mxLog.textarea.value = mxLog.buffer;
-
- // Workaround for wrong width in standards mode
- if (mxClient.IS_NS && document.compatMode != 'BackCompat')
- {
- mxLog.textarea.style.width = '99%';
- }
- else
- {
- mxLog.textarea.style.width = '100%';
- }
-
- td.appendChild(mxLog.textarea);
- tr.appendChild(td);
- tbody.appendChild(tr);
-
- // Creates the container div
- tr = document.createElement('tr');
- mxLog.td = document.createElement('td');
- mxLog.td.style.verticalAlign = 'top';
- mxLog.td.setAttribute('height', '30px');
-
- tr.appendChild(mxLog.td);
- tbody.appendChild(tr);
- table.appendChild(tbody);
-
- // Adds various debugging buttons
- mxLog.addButton('Info', function (evt)
- {
- mxLog.info();
- });
-
- mxLog.addButton('DOM', function (evt)
- {
- var content = mxUtils.getInnerHtml(document.body);
- mxLog.debug(content);
- });
-
- mxLog.addButton('Trace', function (evt)
- {
- mxLog.TRACE = !mxLog.TRACE;
-
- if (mxLog.TRACE)
- {
- mxLog.debug('Tracing enabled');
- }
- else
- {
- mxLog.debug('Tracing disabled');
- }
- });
-
- mxLog.addButton('Copy', function (evt)
- {
- try
- {
- mxUtils.copy(mxLog.textarea.value);
- }
- catch (err)
- {
- mxUtils.alert(err);
- }
- });
-
- mxLog.addButton('Show', function (evt)
- {
- try
- {
- mxUtils.popup(mxLog.textarea.value);
- }
- catch (err)
- {
- mxUtils.alert(err);
- }
- });
-
- mxLog.addButton('Clear', function (evt)
- {
- mxLog.textarea.value = '';
- });
-
- // Cross-browser code to get window size
- var h = 0;
- var w = 0;
-
- if (typeof(window.innerWidth) === 'number')
- {
- h = window.innerHeight;
- w = window.innerWidth;
- }
- else
- {
- h = (document.documentElement.clientHeight || document.body.clientHeight);
- w = document.body.clientWidth;
- }
-
- mxLog.window = new mxWindow(title, table, Math.max(0, w-320), Math.max(0, h-210), 300, 160);
- mxLog.window.setMaximizable(true);
- mxLog.window.setScrollable(false);
- mxLog.window.setResizable(true);
- mxLog.window.setClosable(true);
- mxLog.window.destroyOnClose = false;
-
- // Workaround for ignored textarea height in various setups
- if ((mxClient.IS_NS || mxClient.IS_IE) && !mxClient.IS_GC &&
- !mxClient.IS_SF && document.compatMode != 'BackCompat')
- {
- var elt = mxLog.window.getElement();
-
- var resizeHandler = function(sender, evt)
- {
- mxLog.textarea.style.height = Math.max(0, elt.offsetHeight - 70)+'px';
- };
-
- mxLog.window.addListener(mxEvent.RESIZE_END, resizeHandler);
- mxLog.window.addListener(mxEvent.MAXIMIZE, resizeHandler);
- mxLog.window.addListener(mxEvent.NORMALIZE, resizeHandler);
-
- mxLog.textarea.style.height = '92px';
- }
- }
- },
-
- /**
- * Function: info
- *
- * Writes the current navigator information to the console.
- */
- info: function()
- {
- mxLog.writeln(mxUtils.toString(navigator));
- },
-
- /**
- * Function: addButton
- *
- * Adds a button to the console using the given label and function.
- */
- addButton: function(lab, funct)
- {
- var button = document.createElement('button');
- mxUtils.write(button, lab);
- mxEvent.addListener(button, 'click', funct);
- mxLog.td.appendChild(button);
- },
-
- /**
- * Function: isVisible
- *
- * Returns true if the console is visible.
- */
- isVisible: function()
- {
- if (mxLog.window != null)
- {
- return mxLog.window.isVisible();
- }
- return false;
- },
-
-
- /**
- * Function: show
- *
- * Shows the console.
- */
- show: function()
- {
- mxLog.setVisible(true);
- },
-
- /**
- * Function: setVisible
- *
- * Shows or hides the console.
- */
- setVisible: function(visible)
- {
- if (mxLog.window == null)
- {
- mxLog.init();
- }
-
- if (mxLog.window != null)
- {
- mxLog.window.setVisible(visible);
- }
- },
-
- /**
- * Function: enter
- *
- * Writes the specified string to the console
- * if <TRACE> is true and returns the current
- * time in milliseconds.
- *
- * Example:
- *
- * (code)
- * mxLog.show();
- * var t0 = mxLog.enter('Hello');
- * // Do something
- * mxLog.leave('World!', t0);
- * (end)
- */
- enter: function(string)
- {
- if (mxLog.TRACE)
- {
- mxLog.writeln('Entering '+string);
-
- return new Date().getTime();
- }
- },
-
- /**
- * Function: leave
- *
- * Writes the specified string to the console
- * if <TRACE> is true and computes the difference
- * between the current time and t0 in milliseconds.
- * See <enter> for an example.
- */
- leave: function(string, t0)
- {
- if (mxLog.TRACE)
- {
- var dt = (t0 != 0) ? ' ('+(new Date().getTime() - t0)+' ms)' : '';
- mxLog.writeln('Leaving '+string+dt);
- }
- },
-
- /**
- * Function: debug
- *
- * Adds all arguments to the console if <DEBUG> is enabled.
- *
- * Example:
- *
- * (code)
- * mxLog.show();
- * mxLog.debug('Hello, World!');
- * (end)
- */
- debug: function()
- {
- if (mxLog.DEBUG)
- {
- mxLog.writeln.apply(this, arguments);
- }
- },
-
- /**
- * Function: warn
- *
- * Adds all arguments to the console if <WARN> is enabled.
- *
- * Example:
- *
- * (code)
- * mxLog.show();
- * mxLog.warn('Hello, World!');
- * (end)
- */
- warn: function()
- {
- if (mxLog.WARN)
- {
- mxLog.writeln.apply(this, arguments);
- }
- },
-
- /**
- * Function: write
- *
- * Adds the specified strings to the console.
- */
- write: function()
- {
- var string = '';
-
- for (var i = 0; i < arguments.length; i++)
- {
- string += arguments[i];
-
- if (i < arguments.length - 1)
- {
- string += ' ';
- }
- }
-
- if (mxLog.textarea != null)
- {
- mxLog.textarea.value = mxLog.textarea.value + string;
-
- // Workaround for no update in Presto 2.5.22 (Opera 10.5)
- if (navigator.userAgent.indexOf('Presto/2.5') >= 0)
- {
- mxLog.textarea.style.visibility = 'hidden';
- mxLog.textarea.style.visibility = 'visible';
- }
-
- mxLog.textarea.scrollTop = mxLog.textarea.scrollHeight;
- }
- else
- {
- mxLog.buffer += string;
- }
- },
-
- /**
- * Function: writeln
- *
- * Adds the specified strings to the console, appending a linefeed at the
- * end of each string.
- */
- writeln: function()
- {
- var string = '';
-
- for (var i = 0; i < arguments.length; i++)
- {
- string += arguments[i];
-
- if (i < arguments.length - 1)
- {
- string += ' ';
- }
- }
-
- mxLog.write(string + '\n');
- }
-
-};
diff --git a/src/js/util/mxMorphing.js b/src/js/util/mxMorphing.js
deleted file mode 100644
index 442143d..0000000
--- a/src/js/util/mxMorphing.js
+++ /dev/null
@@ -1,239 +0,0 @@
-/**
- * $Id: mxMorphing.js,v 1.4 2010-06-03 13:37:07 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- *
- * Class: mxMorphing
- *
- * Implements animation for morphing cells. Here is an example of
- * using this class for animating the result of a layout algorithm:
- *
- * (code)
- * graph.getModel().beginUpdate();
- * try
- * {
- * var circleLayout = new mxCircleLayout(graph);
- * circleLayout.execute(graph.getDefaultParent());
- * }
- * finally
- * {
- * var morph = new mxMorphing(graph);
- * morph.addListener(mxEvent.DONE, function()
- * {
- * graph.getModel().endUpdate();
- * });
- *
- * morph.startAnimation();
- * }
- * (end)
- *
- * Constructor: mxMorphing
- *
- * Constructs an animation.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- * steps - Optional number of steps in the morphing animation. Default is 6.
- * ease - Optional easing constant for the animation. Default is 1.5.
- * delay - Optional delay between the animation steps. Passed to <mxAnimation>.
- */
-function mxMorphing(graph, steps, ease, delay)
-{
- mxAnimation.call(this, delay);
- this.graph = graph;
- this.steps = (steps != null) ? steps : 6;
- this.ease = (ease != null) ? ease : 1.5;
-};
-
-/**
- * Extends mxEventSource.
- */
-mxMorphing.prototype = new mxAnimation();
-mxMorphing.prototype.constructor = mxMorphing;
-
-/**
- * Variable: graph
- *
- * Specifies the delay between the animation steps. Defaul is 30ms.
- */
-mxMorphing.prototype.graph = null;
-
-/**
- * Variable: steps
- *
- * Specifies the maximum number of steps for the morphing.
- */
-mxMorphing.prototype.steps = null;
-
-/**
- * Variable: step
- *
- * Contains the current step.
- */
-mxMorphing.prototype.step = 0;
-
-/**
- * Variable: ease
- *
- * Ease-off for movement towards the given vector. Larger values are
- * slower and smoother. Default is 4.
- */
-mxMorphing.prototype.ease = null;
-
-/**
- * Variable: cells
- *
- * Optional array of cells to be animated. If this is not specified
- * then all cells are checked and animated if they have been moved
- * in the current transaction.
- */
-mxMorphing.prototype.cells = null;
-
-/**
- * Function: updateAnimation
- *
- * Animation step.
- */
-mxMorphing.prototype.updateAnimation = function()
-{
- var move = new mxCellStatePreview(this.graph);
-
- if (this.cells != null)
- {
- // Animates the given cells individually without recursion
- for (var i = 0; i < this.cells.length; i++)
- {
- this.animateCell(cells[i], move, false);
- }
- }
- else
- {
- // Animates all changed cells by using recursion to find
- // the changed cells but not for the animation itself
- this.animateCell(this.graph.getModel().getRoot(), move, true);
- }
-
- this.show(move);
-
- if (move.isEmpty() ||
- this.step++ >= this.steps)
- {
- this.stopAnimation();
- }
-};
-
-/**
- * Function: show
- *
- * Shows the changes in the given <mxCellStatePreview>.
- */
-mxMorphing.prototype.show = function(move)
-{
- move.show();
-};
-
-/**
- * Function: animateCell
- *
- * Animates the given cell state using <mxCellStatePreview.moveState>.
- */
-mxMorphing.prototype.animateCell = function(cell, move, recurse)
-{
- var state = this.graph.getView().getState(cell);
- var delta = null;
-
- if (state != null)
- {
- // Moves the animated state from where it will be after the model
- // change by subtracting the given delta vector from that location
- delta = this.getDelta(state);
-
- if (this.graph.getModel().isVertex(cell) &&
- (delta.x != 0 || delta.y != 0))
- {
- var translate = this.graph.view.getTranslate();
- var scale = this.graph.view.getScale();
-
- delta.x += translate.x * scale;
- delta.y += translate.y * scale;
-
- move.moveState(state, -delta.x / this.ease, -delta.y / this.ease);
- }
- }
-
- if (recurse && !this.stopRecursion(state, delta))
- {
- var childCount = this.graph.getModel().getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- this.animateCell(this.graph.getModel().getChildAt(cell, i), move, recurse);
- }
- }
-};
-
-/**
- * Function: stopRecursion
- *
- * Returns true if the animation should not recursively find more
- * deltas for children if the given parent state has been animated.
- */
-mxMorphing.prototype.stopRecursion = function(state, delta)
-{
- return delta != null && (delta.x != 0 || delta.y != 0);
-};
-
-/**
- * Function: getDelta
- *
- * Returns the vector between the current rendered state and the future
- * location of the state after the display will be updated.
- */
-mxMorphing.prototype.getDelta = function(state)
-{
- var origin = this.getOriginForCell(state.cell);
- var translate = this.graph.getView().getTranslate();
- var scale = this.graph.getView().getScale();
- var current = new mxPoint(
- state.x / scale - translate.x,
- state.y / scale - translate.y);
-
- return new mxPoint(
- (origin.x - current.x) * scale,
- (origin.y - current.y) * scale);
-};
-
-/**
- * Function: getOriginForCell
- *
- * Returns the top, left corner of the given cell. TODO: Improve performance
- * by using caching inside this method as the result per cell never changes
- * during the lifecycle of this object.
- */
-mxMorphing.prototype.getOriginForCell = function(cell)
-{
- var result = null;
-
- if (cell != null)
- {
- result = this.getOriginForCell(this.graph.getModel().getParent(cell));
- var geo = this.graph.getCellGeometry(cell);
-
- // TODO: Handle offset, relative geometries etc
- if (geo != null)
- {
- result.x += geo.x;
- result.y += geo.y;
- }
- }
-
- if (result == null)
- {
- var t = this.graph.view.getTranslate();
- result = new mxPoint(-t.x, -t.y);
- }
-
- return result;
-};
diff --git a/src/js/util/mxMouseEvent.js b/src/js/util/mxMouseEvent.js
deleted file mode 100644
index e161d3a..0000000
--- a/src/js/util/mxMouseEvent.js
+++ /dev/null
@@ -1,241 +0,0 @@
-/**
- * $Id: mxMouseEvent.js,v 1.20 2011-03-02 17:24:39 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxMouseEvent
- *
- * Base class for all mouse events in mxGraph. A listener for this event should
- * implement the following methods:
- *
- * (code)
- * graph.addMouseListener(
- * {
- * mouseDown: function(sender, evt)
- * {
- * mxLog.debug('mouseDown');
- * },
- * mouseMove: function(sender, evt)
- * {
- * mxLog.debug('mouseMove');
- * },
- * mouseUp: function(sender, evt)
- * {
- * mxLog.debug('mouseUp');
- * }
- * });
- * (end)
- *
- * Constructor: mxMouseEvent
- *
- * Constructs a new event object for the given arguments.
- *
- * Parameters:
- *
- * evt - Native mouse event.
- * state - Optional <mxCellState> under the mouse.
- *
- */
-function mxMouseEvent(evt, state)
-{
- this.evt = evt;
- this.state = state;
-};
-
-/**
- * Variable: consumed
- *
- * Holds the consumed state of this event.
- */
-mxMouseEvent.prototype.consumed = false;
-
-/**
- * Variable: evt
- *
- * Holds the inner event object.
- */
-mxMouseEvent.prototype.evt = null;
-
-/**
- * Variable: graphX
- *
- * Holds the x-coordinate of the event in the graph. This value is set in
- * <mxGraph.fireMouseEvent>.
- */
-mxMouseEvent.prototype.graphX = null;
-
-/**
- * Variable: graphY
- *
- * Holds the y-coordinate of the event in the graph. This value is set in
- * <mxGraph.fireMouseEvent>.
- */
-mxMouseEvent.prototype.graphY = null;
-
-/**
- * Variable: state
- *
- * Holds the optional <mxCellState> associated with this event.
- */
-mxMouseEvent.prototype.state = null;
-
-/**
- * Function: getEvent
- *
- * Returns <evt>.
- */
-mxMouseEvent.prototype.getEvent = function()
-{
- return this.evt;
-};
-
-/**
- * Function: getSource
- *
- * Returns the target DOM element using <mxEvent.getSource> for <evt>.
- */
-mxMouseEvent.prototype.getSource = function()
-{
- return mxEvent.getSource(this.evt);
-};
-
-/**
- * Function: isSource
- *
- * Returns true if the given <mxShape> is the source of <evt>.
- */
-mxMouseEvent.prototype.isSource = function(shape)
-{
- if (shape != null)
- {
- var source = this.getSource();
-
- while (source != null)
- {
- if (source == shape.node)
- {
- return true;
- }
-
- source = source.parentNode;
- }
- }
-
- return false;
-};
-
-/**
- * Function: getX
- *
- * Returns <evt.clientX>.
- */
-mxMouseEvent.prototype.getX = function()
-{
- return mxEvent.getClientX(this.getEvent());
-};
-
-/**
- * Function: getY
- *
- * Returns <evt.clientY>.
- */
-mxMouseEvent.prototype.getY = function()
-{
- return mxEvent.getClientY(this.getEvent());
-};
-
-/**
- * Function: getGraphX
- *
- * Returns <graphX>.
- */
-mxMouseEvent.prototype.getGraphX = function()
-{
- return this.graphX;
-};
-
-/**
- * Function: getGraphY
- *
- * Returns <graphY>.
- */
-mxMouseEvent.prototype.getGraphY = function()
-{
- return this.graphY;
-};
-
-/**
- * Function: getState
- *
- * Returns <state>.
- */
-mxMouseEvent.prototype.getState = function()
-{
- return this.state;
-};
-
-/**
- * Function: getCell
- *
- * Returns the <mxCell> in <state> is not null.
- */
-mxMouseEvent.prototype.getCell = function()
-{
- var state = this.getState();
-
- if (state != null)
- {
- return state.cell;
- }
-
- return null;
-};
-
-/**
- * Function: isPopupTrigger
- *
- * Returns true if the event is a popup trigger.
- */
-mxMouseEvent.prototype.isPopupTrigger = function()
-{
- return mxEvent.isPopupTrigger(this.getEvent());
-};
-
-/**
- * Function: isConsumed
- *
- * Returns <consumed>.
- */
-mxMouseEvent.prototype.isConsumed = function()
-{
- return this.consumed;
-};
-
-/**
- * Function: consume
- *
- * Sets <consumed> to true and invokes preventDefault on the native event
- * if such a method is defined. This is used mainly to avoid the cursor from
- * being changed to a text cursor in Webkit. You can use the preventDefault
- * flag to disable this functionality.
- *
- * Parameters:
- *
- * preventDefault - Specifies if the native event should be canceled. Default
- * is true.
- */
-mxMouseEvent.prototype.consume = function(preventDefault)
-{
- preventDefault = (preventDefault != null) ? preventDefault : true;
-
- if (preventDefault && this.evt.preventDefault)
- {
- this.evt.preventDefault();
- }
-
- // Workaround for images being dragged in IE
- this.evt.returnValue = false;
-
- // Sets local consumed state
- this.consumed = true;
-};
diff --git a/src/js/util/mxObjectIdentity.js b/src/js/util/mxObjectIdentity.js
deleted file mode 100644
index 778a4ea..0000000
--- a/src/js/util/mxObjectIdentity.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * $Id: mxObjectIdentity.js,v 1.8 2010-01-02 09:45:14 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxObjectIdentity =
-{
- /**
- * Class: mxObjectIdentity
- *
- * Identity for JavaScript objects. This is implemented using a simple
- * incremeting counter which is stored in each object under <ID_NAME>.
- *
- * The identity for an object does not change during its lifecycle.
- *
- * Variable: FIELD_NAME
- *
- * Name of the field to be used to store the object ID. Default is
- * '_mxObjectId'.
- */
- FIELD_NAME: 'mxObjectId',
-
- /**
- * Variable: counter
- *
- * Current counter for objects.
- */
- counter: 0,
-
- /**
- * Function: get
- *
- * Returns the object id for the given object.
- */
- get: function(obj)
- {
- if (typeof(obj) == 'object' &&
- obj[mxObjectIdentity.FIELD_NAME] == null)
- {
- var ctor = mxUtils.getFunctionName(obj.constructor);
- obj[mxObjectIdentity.FIELD_NAME] = ctor+'#'+mxObjectIdentity.counter++;
- }
-
- return obj[mxObjectIdentity.FIELD_NAME];
- },
-
- /**
- * Function: clear
- *
- * Removes the object id from the given object.
- */
- clear: function(obj)
- {
- if (typeof(obj) == 'object')
- {
- delete obj[mxObjectIdentity.FIELD_NAME];
- }
- }
-
-};
diff --git a/src/js/util/mxPanningManager.js b/src/js/util/mxPanningManager.js
deleted file mode 100644
index 9f9f349..0000000
--- a/src/js/util/mxPanningManager.js
+++ /dev/null
@@ -1,262 +0,0 @@
-/**
- * $Id: mxPanningManager.js,v 1.7 2012-06-13 06:46:37 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxPanningManager
- *
- * Implements a handler for panning.
- */
-function mxPanningManager(graph)
-{
- this.thread = null;
- this.active = false;
- this.tdx = 0;
- this.tdy = 0;
- this.t0x = 0;
- this.t0y = 0;
- this.dx = 0;
- this.dy = 0;
- this.scrollbars = false;
- this.scrollLeft = 0;
- this.scrollTop = 0;
-
- this.mouseListener =
- {
- mouseDown: function(sender, me) { },
- mouseMove: function(sender, me) { },
- mouseUp: mxUtils.bind(this, function(sender, me)
- {
- if (this.active)
- {
- this.stop();
- }
- })
- };
-
- graph.addMouseListener(this.mouseListener);
-
- // Stops scrolling on every mouseup anywhere in the document
- mxEvent.addListener(document, 'mouseup', mxUtils.bind(this, function()
- {
- if (this.active)
- {
- this.stop();
- }
- }));
-
- var createThread = mxUtils.bind(this, function()
- {
- this.scrollbars = mxUtils.hasScrollbars(graph.container);
- this.scrollLeft = graph.container.scrollLeft;
- this.scrollTop = graph.container.scrollTop;
-
- return window.setInterval(mxUtils.bind(this, function()
- {
- this.tdx -= this.dx;
- this.tdy -= this.dy;
-
- if (this.scrollbars)
- {
- var left = -graph.container.scrollLeft - Math.ceil(this.dx);
- var top = -graph.container.scrollTop - Math.ceil(this.dy);
- graph.panGraph(left, top);
- graph.panDx = this.scrollLeft - graph.container.scrollLeft;
- graph.panDy = this.scrollTop - graph.container.scrollTop;
- graph.fireEvent(new mxEventObject(mxEvent.PAN));
- // TODO: Implement graph.autoExtend
- }
- else
- {
- graph.panGraph(this.getDx(), this.getDy());
- }
- }), this.delay);
- });
-
- this.isActive = function()
- {
- return active;
- };
-
- this.getDx = function()
- {
- return Math.round(this.tdx);
- };
-
- this.getDy = function()
- {
- return Math.round(this.tdy);
- };
-
- this.start = function()
- {
- this.t0x = graph.view.translate.x;
- this.t0y = graph.view.translate.y;
- this.active = true;
- };
-
- this.panTo = function(x, y, w, h)
- {
- if (!this.active)
- {
- this.start();
- }
-
- this.scrollLeft = graph.container.scrollLeft;
- this.scrollTop = graph.container.scrollTop;
-
- w = (w != null) ? w : 0;
- h = (h != null) ? h : 0;
-
- var c = graph.container;
- this.dx = x + w - c.scrollLeft - c.clientWidth;
-
- if (this.dx < 0 && Math.abs(this.dx) < this.border)
- {
- this.dx = this.border + this.dx;
- }
- else if (this.handleMouseOut)
- {
- this.dx = Math.max(this.dx, 0);
- }
- else
- {
- this.dx = 0;
- }
-
- if (this.dx == 0)
- {
- this.dx = x - c.scrollLeft;
-
- if (this.dx > 0 && this.dx < this.border)
- {
- this.dx = this.dx - this.border;
- }
- else if (this.handleMouseOut)
- {
- this.dx = Math.min(0, this.dx);
- }
- else
- {
- this.dx = 0;
- }
- }
-
- this.dy = y + h - c.scrollTop - c.clientHeight;
-
- if (this.dy < 0 && Math.abs(this.dy) < this.border)
- {
- this.dy = this.border + this.dy;
- }
- else if (this.handleMouseOut)
- {
- this.dy = Math.max(this.dy, 0);
- }
- else
- {
- this.dy = 0;
- }
-
- if (this.dy == 0)
- {
- this.dy = y - c.scrollTop;
-
- if (this.dy > 0 && this.dy < this.border)
- {
- this.dy = this.dy - this.border;
- }
- else if (this.handleMouseOut)
- {
- this.dy = Math.min(0, this.dy);
- }
- else
- {
- this.dy = 0;
- }
- }
-
- if (this.dx != 0 || this.dy != 0)
- {
- this.dx *= this.damper;
- this.dy *= this.damper;
-
- if (this.thread == null)
- {
- this.thread = createThread();
- }
- }
- else if (this.thread != null)
- {
- window.clearInterval(this.thread);
- this.thread = null;
- }
- };
-
- this.stop = function()
- {
- if (this.active)
- {
- this.active = false;
-
- if (this.thread != null)
- {
- window.clearInterval(this.thread);
- this.thread = null;
- }
-
- this.tdx = 0;
- this.tdy = 0;
-
- if (!this.scrollbars)
- {
- var px = graph.panDx;
- var py = graph.panDy;
-
- if (px != 0 || py != 0)
- {
- graph.panGraph(0, 0);
- graph.view.setTranslate(this.t0x + px / graph.view.scale, this.t0y + py / graph.view.scale);
- }
- }
- else
- {
- graph.panDx = 0;
- graph.panDy = 0;
- graph.fireEvent(new mxEventObject(mxEvent.PAN));
- }
- }
- };
-
- this.destroy = function()
- {
- graph.removeMouseListener(this.mouseListener);
- };
-};
-
-/**
- * Variable: damper
- *
- * Damper value for the panning. Default is 1/6.
- */
-mxPanningManager.prototype.damper = 1/6;
-
-/**
- * Variable: delay
- *
- * Delay in milliseconds for the panning. Default is 10.
- */
-mxPanningManager.prototype.delay = 10;
-
-/**
- * Variable: handleMouseOut
- *
- * Specifies if mouse events outside of the component should be handled. Default is true.
- */
-mxPanningManager.prototype.handleMouseOut = true;
-
-/**
- * Variable: border
- *
- * Border to handle automatic panning inside the component. Default is 0 (disabled).
- */
-mxPanningManager.prototype.border = 0;
diff --git a/src/js/util/mxPath.js b/src/js/util/mxPath.js
deleted file mode 100644
index 57efe74..0000000
--- a/src/js/util/mxPath.js
+++ /dev/null
@@ -1,314 +0,0 @@
-/**
- * $Id: mxPath.js,v 1.24 2012-06-13 17:31:32 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxPath
- *
- * An abstraction for creating VML and SVG paths. See <mxActor> for using this
- * object inside an <mxShape> for painting cells.
- *
- * Constructor: mxPath
- *
- * Constructs a path for the given format, which is one of svg or vml.
- *
- * Parameters:
- *
- * format - String specifying the <format>. May be one of vml or svg
- * (default).
- */
-function mxPath(format)
-{
- this.format = format;
- this.path = [];
- this.translate = new mxPoint(0, 0);
-};
-
-/**
- * Variable: format
- *
- * Defines the format for the output of this path. Possible values are
- * svg and vml.
- */
-mxPath.prototype.format = null;
-
-/**
- * Variable: translate
- *
- * <mxPoint> that specifies the translation of the complete path.
- */
-mxPath.prototype.translate = null;
-
-/**
- * Variable: scale
- *
- * Number that specifies the translation of the path.
- */
-mxPath.prototype.scale = 1;
-
-/**
- * Variable: path
- *
- * Contains the textual representation of the path as an array.
- */
-mxPath.prototype.path = null;
-
-/**
- * Function: isVml
- *
- * Returns true if <format> is vml.
- */
-mxPath.prototype.isVml = function()
-{
- return this.format == 'vml';
-};
-
-/**
- * Function: getPath
- *
- * Returns string that represents the path in <format>.
- */
-mxPath.prototype.getPath = function()
-{
- return this.path.join('');
-};
-
-/**
- * Function: setTranslate
- *
- * Set the global translation of this path, that is, the origin of the
- * coordinate system.
- *
- * Parameters:
- *
- * x - X-coordinate of the new origin.
- * y - Y-coordinate of the new origin.
- */
-mxPath.prototype.setTranslate = function(x, y)
-{
- this.translate = new mxPoint(x, y);
-};
-
-/**
- * Function: moveTo
- *
- * Moves the cursor to (x, y).
- *
- * Parameters:
- *
- * x - X-coordinate of the new cursor location.
- * y - Y-coordinate of the new cursor location.
- */
-mxPath.prototype.moveTo = function(x, y)
-{
- x += this.translate.x;
- y += this.translate.y;
-
- x *= this.scale;
- y *= this.scale;
-
- if (this.isVml())
- {
- this.path.push('m ', Math.round(x), ' ', Math.round(y), ' ');
- }
- else
- {
- this.path.push('M ', x, ' ', y, ' ');
- }
-};
-
-/**
- * Function: lineTo
- *
- * Draws a straight line from the current poin to (x, y).
- *
- * Parameters:
- *
- * x - X-coordinate of the endpoint.
- * y - Y-coordinate of the endpoint.
- */
-mxPath.prototype.lineTo = function(x, y)
-{
- x += this.translate.x;
- y += this.translate.y;
-
- x *= this.scale;
- y *= this.scale;
-
- if (this.isVml())
- {
- this.path.push('l ', Math.round(x), ' ', Math.round(y), ' ');
- }
- else
- {
- this.path.push('L ', x, ' ', y, ' ');
- }
-};
-
-/**
- * Function: quadTo
- *
- * Draws a quadratic Bézier curve from the current point to (x, y) using
- * (x1, y1) as the control point.
- *
- * Parameters:
- *
- * x1 - X-coordinate of the control point.
- * y1 - Y-coordinate of the control point.
- * x - X-coordinate of the endpoint.
- * y - Y-coordinate of the endpoint.
- */
-mxPath.prototype.quadTo = function(x1, y1, x, y)
-{
- x1 += this.translate.x;
- y1 += this.translate.y;
-
- x1 *= this.scale;
- y1 *= this.scale;
-
- x += this.translate.x;
- y += this.translate.y;
-
- x *= this.scale;
- y *= this.scale;
-
- if (this.isVml())
- {
- this.path.push('c ', Math.round(x1), ' ', Math.round(y1), ' ', Math.round(x), ' ',
- Math.round(y), ' ', Math.round(x), ' ', Math.round(y), ' ');
- }
- else
- {
- this.path.push('Q ', x1, ' ', y1, ' ', x, ' ', y, ' ');
- }
-};
-
-/**
- * Function: curveTo
- *
- * Draws a cubic Bézier curve from the current point to (x, y) using
- * (x1, y1) as the control point at the beginning of the curve and (x2, y2)
- * as the control point at the end of the curve.
- *
- * Parameters:
- *
- * x1 - X-coordinate of the first control point.
- * y1 - Y-coordinate of the first control point.
- * x2 - X-coordinate of the second control point.
- * y2 - Y-coordinate of the second control point.
- * x - X-coordinate of the endpoint.
- * y - Y-coordinate of the endpoint.
- */
-mxPath.prototype.curveTo = function(x1, y1, x2, y2, x, y)
-{
- x1 += this.translate.x;
- y1 += this.translate.y;
-
- x1 *= this.scale;
- y1 *= this.scale;
-
- x2 += this.translate.x;
- y2 += this.translate.y;
-
- x2 *= this.scale;
- y2 *= this.scale;
-
- x += this.translate.x;
- y += this.translate.y;
-
- x *= this.scale;
- y *= this.scale;
-
- if (this.isVml())
- {
- this.path.push('c ', Math.round(x1), ' ', Math.round(y1), ' ', Math.round(x2),
- ' ', Math.round(y2), ' ', Math.round(x), ' ', Math.round(y), ' ');
- }
- else
- {
- this.path.push('C ', x1, ' ', y1, ' ', x2,
- ' ', y2, ' ', x, ' ', y, ' ');
- }
-};
-
-/**
- * Function: ellipse
- *
- * Adds the given ellipse. Some implementations may require the path to be
- * closed after this operation.
- */
-mxPath.prototype.ellipse = function(x, y, w, h)
-{
- x += this.translate.x;
- y += this.translate.y;
- x *= this.scale;
- y *= this.scale;
-
- if (this.isVml())
- {
- this.path.push('at ', Math.round(x), ' ', Math.round(y), ' ', Math.round(x + w), ' ', Math.round(y + h), ' ',
- Math.round(x), ' ', Math.round(y + h / 2), ' ', Math.round(x), ' ', Math.round(y + h / 2));
- }
- else
- {
- var startX = x;
- var startY = y + h/2;
- var endX = x + w;
- var endY = y + h/2;
- var r1 = w/2;
- var r2 = h/2;
- this.path.push('M ', startX, ' ', startY, ' ');
- this.path.push('A ', r1, ' ', r2, ' 0 1 0 ', endX, ' ', endY, ' ');
- this.path.push('A ', r1, ' ', r2, ' 0 1 0 ', startX, ' ', startY);
- }
-};
-
-/**
- * Function: addPath
- *
- * Adds the given path.
- */
-mxPath.prototype.addPath = function(path)
-{
- this.path = this.path.concat(path.path);
-};
-
-/**
- * Function: write
- *
- * Writes directly into the path. This bypasses all conversions.
- */
-mxPath.prototype.write = function(string)
-{
- this.path.push(string, ' ');
-};
-
-/**
- * Function: end
- *
- * Ends the path.
- */
-mxPath.prototype.end = function()
-{
- if (this.format == 'vml')
- {
- this.path.push('e');
- }
-};
-
-/**
- * Function: close
- *
- * Closes the path.
- */
-mxPath.prototype.close = function()
-{
- if (this.format == 'vml')
- {
- this.path.push('x e');
- }
- else
- {
- this.path.push('Z');
- }
-};
diff --git a/src/js/util/mxPoint.js b/src/js/util/mxPoint.js
deleted file mode 100644
index e029a29..0000000
--- a/src/js/util/mxPoint.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * $Id: mxPoint.js,v 1.12 2010-01-02 09:45:14 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxPoint
- *
- * Implements a 2-dimensional vector with double precision coordinates.
- *
- * Constructor: mxPoint
- *
- * Constructs a new point for the optional x and y coordinates. If no
- * coordinates are given, then the default values for <x> and <y> are used.
- */
-function mxPoint(x, y)
-{
- this.x = (x != null) ? x : 0;
- this.y = (y != null) ? y : 0;
-};
-
-/**
- * Variable: x
- *
- * Holds the x-coordinate of the point. Default is 0.
- */
-mxPoint.prototype.x = null;
-
-/**
- * Variable: y
- *
- * Holds the y-coordinate of the point. Default is 0.
- */
-mxPoint.prototype.y = null;
-
-/**
- * Function: equals
- *
- * Returns true if the given object equals this rectangle.
- */
-mxPoint.prototype.equals = function(obj)
-{
- return obj.x == this.x &&
- obj.y == this.y;
-};
-
-/**
- * Function: clone
- *
- * Returns a clone of this <mxPoint>.
- */
-mxPoint.prototype.clone = function()
-{
- // Handles subclasses as well
- return mxUtils.clone(this);
-};
diff --git a/src/js/util/mxPopupMenu.js b/src/js/util/mxPopupMenu.js
deleted file mode 100644
index b188cb6..0000000
--- a/src/js/util/mxPopupMenu.js
+++ /dev/null
@@ -1,574 +0,0 @@
-/**
- * $Id: mxPopupMenu.js,v 1.37 2012-04-22 10:16:23 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxPopupMenu
- *
- * Event handler that pans and creates popupmenus. To use the left
- * mousebutton for panning without interfering with cell moving and
- * resizing, use <isUseLeftButton> and <isIgnoreCell>. For grid size
- * steps while panning, use <useGrid>. This handler is built-into
- * <mxGraph.panningHandler> and enabled using <mxGraph.setPanning>.
- *
- * Constructor: mxPopupMenu
- *
- * Constructs an event handler that creates a popupmenu. The
- * event handler is not installed anywhere in this ctor.
- *
- * Event: mxEvent.SHOW
- *
- * Fires after the menu has been shown in <popup>.
- */
-function mxPopupMenu(factoryMethod)
-{
- this.factoryMethod = factoryMethod;
-
- if (factoryMethod != null)
- {
- this.init();
- }
-};
-
-/**
- * Extends mxEventSource.
- */
-mxPopupMenu.prototype = new mxEventSource();
-mxPopupMenu.prototype.constructor = mxPopupMenu;
-
-/**
- * Variable: submenuImage
- *
- * URL of the image to be used for the submenu icon.
- */
-mxPopupMenu.prototype.submenuImage = mxClient.imageBasePath + '/submenu.gif';
-
-/**
- * Variable: zIndex
- *
- * Specifies the zIndex for the popupmenu and its shadow. Default is 1006.
- */
-mxPopupMenu.prototype.zIndex = 10006;
-
-/**
- * Variable: factoryMethod
- *
- * Function that is used to create the popup menu. The function takes the
- * current panning handler, the <mxCell> under the mouse and the mouse
- * event that triggered the call as arguments.
- */
-mxPopupMenu.prototype.factoryMethod = null;
-
-/**
- * Variable: useLeftButtonForPopup
- *
- * Specifies if popupmenus should be activated by clicking the left mouse
- * button. Default is false.
- */
-mxPopupMenu.prototype.useLeftButtonForPopup = false;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxPopupMenu.prototype.enabled = true;
-
-/**
- * Variable: itemCount
- *
- * Contains the number of times <addItem> has been called for a new menu.
- */
-mxPopupMenu.prototype.itemCount = 0;
-
-/**
- * Variable: autoExpand
- *
- * Specifies if submenus should be expanded on mouseover. Default is false.
- */
-mxPopupMenu.prototype.autoExpand = false;
-
-/**
- * Variable: smartSeparators
- *
- * Specifies if separators should only be added if a menu item follows them.
- * Default is false.
- */
-mxPopupMenu.prototype.smartSeparators = false;
-
-/**
- * Variable: labels
- *
- * Specifies if any labels should be visible. Default is true.
- */
-mxPopupMenu.prototype.labels = true;
-
-/**
- * Function: init
- *
- * Initializes the shapes required for this vertex handler.
- */
-mxPopupMenu.prototype.init = function()
-{
- // Adds the inner table
- this.table = document.createElement('table');
- this.table.className = 'mxPopupMenu';
-
- this.tbody = document.createElement('tbody');
- this.table.appendChild(this.tbody);
-
- // Adds the outer div
- this.div = document.createElement('div');
- this.div.className = 'mxPopupMenu';
- this.div.style.display = 'inline';
- this.div.style.zIndex = this.zIndex;
- this.div.appendChild(this.table);
-
- // Disables the context menu on the outer div
- mxEvent.disableContextMenu(this.div);
-};
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxPopupMenu.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- */
-mxPopupMenu.prototype.setEnabled = function(enabled)
-{
- this.enabled = enabled;
-};
-
-/**
- * Function: isPopupTrigger
- *
- * Returns true if the given event is a popupmenu trigger for the optional
- * given cell.
- *
- * Parameters:
- *
- * me - <mxMouseEvent> that represents the mouse event.
- */
-mxPopupMenu.prototype.isPopupTrigger = function(me)
-{
- return me.isPopupTrigger() || (this.useLeftButtonForPopup &&
- mxEvent.isLeftMouseButton(me.getEvent()));
-};
-
-/**
- * Function: addItem
- *
- * Adds the given item to the given parent item. If no parent item is specified
- * then the item is added to the top-level menu. The return value may be used
- * as the parent argument, ie. as a submenu item. The return value is the table
- * row that represents the item.
- *
- * Paramters:
- *
- * title - String that represents the title of the menu item.
- * image - Optional URL for the image icon.
- * funct - Function associated that takes a mouseup or touchend event.
- * parent - Optional item returned by <addItem>.
- * iconCls - Optional string that represents the CSS class for the image icon.
- * IconsCls is ignored if image is given.
- * enabled - Optional boolean indicating if the item is enabled. Default is true.
- */
-mxPopupMenu.prototype.addItem = function(title, image, funct, parent, iconCls, enabled)
-{
- parent = parent || this;
- this.itemCount++;
-
- // Smart separators only added if element contains items
- if (parent.willAddSeparator)
- {
- if (parent.containsItems)
- {
- this.addSeparator(parent, true);
- }
-
- parent.willAddSeparator = false;
- }
-
- parent.containsItems = true;
- var tr = document.createElement('tr');
- tr.className = 'mxPopupMenuItem';
- var col1 = document.createElement('td');
- col1.className = 'mxPopupMenuIcon';
-
- // Adds the given image into the first column
- if (image != null)
- {
- var img = document.createElement('img');
- img.src = image;
- col1.appendChild(img);
- }
- else if (iconCls != null)
- {
- var div = document.createElement('div');
- div.className = iconCls;
- col1.appendChild(div);
- }
-
- tr.appendChild(col1);
-
- if (this.labels)
- {
- var col2 = document.createElement('td');
- col2.className = 'mxPopupMenuItem' +
- ((enabled != null && !enabled) ? ' disabled' : '');
- mxUtils.write(col2, title);
- col2.align = 'left';
- tr.appendChild(col2);
-
- var col3 = document.createElement('td');
- col3.className = 'mxPopupMenuItem' +
- ((enabled != null && !enabled) ? ' disabled' : '');
- col3.style.paddingRight = '6px';
- col3.style.textAlign = 'right';
-
- tr.appendChild(col3);
-
- if (parent.div == null)
- {
- this.createSubmenu(parent);
- }
- }
-
- parent.tbody.appendChild(tr);
-
- if (enabled == null || enabled)
- {
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- // Consumes the event on mouse down
- mxEvent.addListener(tr, md, mxUtils.bind(this, function(evt)
- {
- this.eventReceiver = tr;
-
- if (parent.activeRow != tr && parent.activeRow != parent)
- {
- if (parent.activeRow != null &&
- parent.activeRow.div.parentNode != null)
- {
- this.hideSubmenu(parent);
- }
-
- if (tr.div != null)
- {
- this.showSubmenu(parent, tr);
- parent.activeRow = tr;
- }
- }
-
- mxEvent.consume(evt);
- }));
-
- mxEvent.addListener(tr, mm, mxUtils.bind(this, function(evt)
- {
- if (parent.activeRow != tr && parent.activeRow != parent)
- {
- if (parent.activeRow != null &&
- parent.activeRow.div.parentNode != null)
- {
- this.hideSubmenu(parent);
- }
-
- if (this.autoExpand && tr.div != null)
- {
- this.showSubmenu(parent, tr);
- parent.activeRow = tr;
- }
- }
-
- // Sets hover style because TR in IE doesn't have hover
- tr.className = 'mxPopupMenuItemHover';
- }));
-
- mxEvent.addListener(tr, mu, mxUtils.bind(this, function(evt)
- {
- // EventReceiver avoids clicks on a submenu item
- // which has just been shown in the mousedown
- if (this.eventReceiver == tr)
- {
- if (parent.activeRow != tr)
- {
- this.hideMenu();
- }
-
- if (funct != null)
- {
- funct(evt);
- }
- }
-
- this.eventReceiver = null;
- mxEvent.consume(evt);
- }));
-
- // Resets hover style because TR in IE doesn't have hover
- mxEvent.addListener(tr, 'mouseout',
- mxUtils.bind(this, function(evt)
- {
- tr.className = 'mxPopupMenuItem';
- })
- );
- }
-
- return tr;
-};
-
-/**
- * Function: createSubmenu
- *
- * Creates the nodes required to add submenu items inside the given parent
- * item. This is called in <addItem> if a parent item is used for the first
- * time. This adds various DOM nodes and a <submenuImage> to the parent.
- *
- * Parameters:
- *
- * parent - An item returned by <addItem>.
- */
-mxPopupMenu.prototype.createSubmenu = function(parent)
-{
- parent.table = document.createElement('table');
- parent.table.className = 'mxPopupMenu';
-
- parent.tbody = document.createElement('tbody');
- parent.table.appendChild(parent.tbody);
-
- parent.div = document.createElement('div');
- parent.div.className = 'mxPopupMenu';
-
- parent.div.style.position = 'absolute';
- parent.div.style.display = 'inline';
- parent.div.style.zIndex = this.zIndex;
-
- parent.div.appendChild(parent.table);
-
- var img = document.createElement('img');
- img.setAttribute('src', this.submenuImage);
-
- // Last column of the submenu item in the parent menu
- td = parent.firstChild.nextSibling.nextSibling;
- td.appendChild(img);
-};
-
-/**
- * Function: showSubmenu
- *
- * Shows the submenu inside the given parent row.
- */
-mxPopupMenu.prototype.showSubmenu = function(parent, row)
-{
- if (row.div != null)
- {
- row.div.style.left = (parent.div.offsetLeft +
- row.offsetLeft+row.offsetWidth - 1) + 'px';
- row.div.style.top = (parent.div.offsetTop+row.offsetTop) + 'px';
- document.body.appendChild(row.div);
-
- // Moves the submenu to the left side if there is no space
- var left = parseInt(row.div.offsetLeft);
- var width = parseInt(row.div.offsetWidth);
-
- var b = document.body;
- var d = document.documentElement;
-
- var right = (b.scrollLeft || d.scrollLeft) + (b.clientWidth || d.clientWidth);
-
- if (left + width > right)
- {
- row.div.style.left = (parent.div.offsetLeft - width +
- ((mxClient.IS_IE) ? 6 : -6)) + 'px';
- }
-
- mxUtils.fit(row.div);
- }
-};
-
-/**
- * Function: addSeparator
- *
- * Adds a horizontal separator in the given parent item or the top-level menu
- * if no parent is specified.
- *
- * Parameters:
- *
- * parent - Optional item returned by <addItem>.
- * force - Optional boolean to ignore <smartSeparators>. Default is false.
- */
-mxPopupMenu.prototype.addSeparator = function(parent, force)
-{
- parent = parent || this;
-
- if (this.smartSeparators && !force)
- {
- parent.willAddSeparator = true;
- }
- else if (parent.tbody != null)
- {
- parent.willAddSeparator = false;
- var tr = document.createElement('tr');
-
- var col1 = document.createElement('td');
- col1.className = 'mxPopupMenuIcon';
- col1.style.padding = '0 0 0 0px';
-
- tr.appendChild(col1);
-
- var col2 = document.createElement('td');
- col2.style.padding = '0 0 0 0px';
- col2.setAttribute('colSpan', '2');
-
- var hr = document.createElement('hr');
- hr.setAttribute('size', '1');
- col2.appendChild(hr);
-
- tr.appendChild(col2);
-
- parent.tbody.appendChild(tr);
- }
-};
-
-/**
- * Function: popup
- *
- * Shows the popup menu for the given event and cell.
- *
- * Example:
- *
- * (code)
- * graph.panningHandler.popup = function(x, y, cell, evt)
- * {
- * mxUtils.alert('Hello, World!');
- * }
- * (end)
- */
-mxPopupMenu.prototype.popup = function(x, y, cell, evt)
-{
- if (this.div != null && this.tbody != null && this.factoryMethod != null)
- {
- this.div.style.left = x + 'px';
- this.div.style.top = y + 'px';
-
- // Removes all child nodes from the existing menu
- while (this.tbody.firstChild != null)
- {
- mxEvent.release(this.tbody.firstChild);
- this.tbody.removeChild(this.tbody.firstChild);
- }
-
- this.itemCount = 0;
- this.factoryMethod(this, cell, evt);
-
- if (this.itemCount > 0)
- {
- this.showMenu();
- this.fireEvent(new mxEventObject(mxEvent.SHOW));
- }
- }
-};
-
-/**
- * Function: isMenuShowing
- *
- * Returns true if the menu is showing.
- */
-mxPopupMenu.prototype.isMenuShowing = function()
-{
- return this.div != null && this.div.parentNode == document.body;
-};
-
-/**
- * Function: showMenu
- *
- * Shows the menu.
- */
-mxPopupMenu.prototype.showMenu = function()
-{
- // Disables filter-based shadow in IE9 standards mode
- if (document.documentMode >= 9)
- {
- this.div.style.filter = 'none';
- }
-
- // Fits the div inside the viewport
- document.body.appendChild(this.div);
- mxUtils.fit(this.div);
-};
-
-/**
- * Function: hideMenu
- *
- * Removes the menu and all submenus.
- */
-mxPopupMenu.prototype.hideMenu = function()
-{
- if (this.div != null)
- {
- if (this.div.parentNode != null)
- {
- this.div.parentNode.removeChild(this.div);
- }
-
- this.hideSubmenu(this);
- this.containsItems = false;
- }
-};
-
-/**
- * Function: hideSubmenu
- *
- * Removes all submenus inside the given parent.
- *
- * Parameters:
- *
- * parent - An item returned by <addItem>.
- */
-mxPopupMenu.prototype.hideSubmenu = function(parent)
-{
- if (parent.activeRow != null)
- {
- this.hideSubmenu(parent.activeRow);
-
- if (parent.activeRow.div.parentNode != null)
- {
- parent.activeRow.div.parentNode.removeChild(parent.activeRow.div);
- }
-
- parent.activeRow = null;
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes.
- */
-mxPopupMenu.prototype.destroy = function()
-{
- if (this.div != null)
- {
- mxEvent.release(this.div);
-
- if (this.div.parentNode != null)
- {
- this.div.parentNode.removeChild(this.div);
- }
-
- this.div = null;
- }
-};
diff --git a/src/js/util/mxRectangle.js b/src/js/util/mxRectangle.js
deleted file mode 100644
index 035abf5..0000000
--- a/src/js/util/mxRectangle.js
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * $Id: mxRectangle.js,v 1.17 2010-12-08 12:46:03 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxRectangle
- *
- * Extends <mxPoint> to implement a 2-dimensional rectangle with double
- * precision coordinates.
- *
- * Constructor: mxRectangle
- *
- * Constructs a new rectangle for the optional parameters. If no parameters
- * are given then the respective default values are used.
- */
-function mxRectangle(x, y, width, height)
-{
- mxPoint.call(this, x, y);
-
- this.width = (width != null) ? width : 0;
- this.height = (height != null) ? height : 0;
-};
-
-/**
- * Extends mxPoint.
- */
-mxRectangle.prototype = new mxPoint();
-mxRectangle.prototype.constructor = mxRectangle;
-
-/**
- * Variable: width
- *
- * Holds the width of the rectangle. Default is 0.
- */
-mxRectangle.prototype.width = null;
-
-/**
- * Variable: height
- *
- * Holds the height of the rectangle. Default is 0.
- */
-mxRectangle.prototype.height = null;
-
-/**
- * Function: setRect
- *
- * Sets this rectangle to the specified values
- */
-mxRectangle.prototype.setRect = function(x, y, w, h)
-{
- this.x = x;
- this.y = y;
- this.width = w;
- this.height = h;
-};
-
-/**
- * Function: getCenterX
- *
- * Returns the x-coordinate of the center point.
- */
-mxRectangle.prototype.getCenterX = function ()
-{
- return this.x + this.width/2;
-};
-
-/**
- * Function: getCenterY
- *
- * Returns the y-coordinate of the center point.
- */
-mxRectangle.prototype.getCenterY = function ()
-{
- return this.y + this.height/2;
-};
-
-/**
- * Function: add
- *
- * Adds the given rectangle to this rectangle.
- */
-mxRectangle.prototype.add = function(rect)
-{
- if (rect != null)
- {
- var minX = Math.min(this.x, rect.x);
- var minY = Math.min(this.y, rect.y);
- var maxX = Math.max(this.x + this.width, rect.x + rect.width);
- var maxY = Math.max(this.y + this.height, rect.y + rect.height);
-
- this.x = minX;
- this.y = minY;
- this.width = maxX - minX;
- this.height = maxY - minY;
- }
-};
-
-/**
- * Function: grow
- *
- * Grows the rectangle by the given amount, that is, this method subtracts
- * the given amount from the x- and y-coordinates and adds twice the amount
- * to the width and height.
- */
-mxRectangle.prototype.grow = function(amount)
-{
- this.x -= amount;
- this.y -= amount;
- this.width += 2 * amount;
- this.height += 2 * amount;
-};
-
-/**
- * Function: getPoint
- *
- * Returns the top, left corner as a new <mxPoint>.
- */
-mxRectangle.prototype.getPoint = function()
-{
- return new mxPoint(this.x, this.y);
-};
-
-/**
- * Function: equals
- *
- * Returns true if the given object equals this rectangle.
- */
-mxRectangle.prototype.equals = function(obj)
-{
- return obj.x == this.x &&
- obj.y == this.y &&
- obj.width == this.width &&
- obj.height == this.height;
-};
diff --git a/src/js/util/mxResources.js b/src/js/util/mxResources.js
deleted file mode 100644
index 0969ebe..0000000
--- a/src/js/util/mxResources.js
+++ /dev/null
@@ -1,366 +0,0 @@
-/**
- * $Id: mxResources.js,v 1.32 2012-10-26 13:36:50 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxResources =
-{
- /**
- * Class: mxResources
- *
- * Implements internationalization. You can provide any number of
- * resource files on the server using the following format for the
- * filename: name[-en].properties. The en stands for any lowercase
- * 2-character language shortcut (eg. de for german, fr for french).
- *
- * If the optional language extension is omitted, then the file is used as a
- * default resource which is loaded in all cases. If a properties file for a
- * specific language exists, then it is used to override the settings in the
- * default resource. All entries in the file are of the form key=value. The
- * values may then be accessed in code via <get>. Lines without
- * equal signs in the properties files are ignored.
- *
- * Resource files may either be added programmatically using
- * <add> or via a resource tag in the UI section of the
- * editor configuration file, eg:
- *
- * (code)
- * <mxEditor>
- * <ui>
- * <resource basename="examples/resources/mxWorkflow"/>
- * (end)
- *
- * The above element will load examples/resources/mxWorkflow.properties as well
- * as the language specific file for the current language, if it exists.
- *
- * Values may contain placeholders of the form {1}...{n} where each placeholder
- * is replaced with the value of the corresponding array element in the params
- * argument passed to <mxResources.get>. The placeholder {1} maps to the first
- * element in the array (at index 0).
- *
- * See <mxClient.language> for more information on specifying the default
- * language or disabling all loading of resources.
- *
- * Lines that start with a # sign will be ignored.
- *
- * Special characters
- *
- * To use unicode characters, use the standard notation (eg. \u8fd1) or %u as a
- * prefix (eg. %u20AC will display a Euro sign). For normal hex encoded strings,
- * use % as a prefix, eg. %F6 will display a � (&ouml;).
- *
- * See <resourcesEncoded> to disable this. If you disable this, make sure that
- * your files are UTF-8 encoded.
- *
- * Variable: resources
- *
- * Associative array that maps from keys to values.
- */
- resources: [],
-
- /**
- * Variable: extension
- *
- * Specifies the extension used for language files. Default is '.properties'.
- */
- extension: '.properties',
-
- /**
- * Variable: resourcesEncoded
- *
- * Specifies whether or not values in resource files are encoded with \u or
- * percentage. Default is true.
- */
- resourcesEncoded: true,
-
- /**
- * Variable: loadDefaultBundle
- *
- * Specifies if the default file for a given basename should be loaded.
- * Default is true.
- */
- loadDefaultBundle: true,
-
- /**
- * Variable: loadDefaultBundle
- *
- * Specifies if the specific language file file for a given basename should
- * be loaded. Default is true.
- */
- loadSpecialBundle: true,
-
- /**
- * Function: isBundleSupported
- *
- * Hook for subclassers to disable support for a given language. This
- * implementation always returns true.
- *
- * Parameters:
- *
- * basename - The basename for which the file should be loaded.
- * lan - The current language.
- */
- isLanguageSupported: function(lan)
- {
- if (mxClient.languages != null)
- {
- return mxUtils.indexOf(mxClient.languages, lan) >= 0;
- }
-
- return true;
- },
-
- /**
- * Function: getDefaultBundle
- *
- * Hook for subclassers to return the URL for the special bundle. This
- * implementation returns basename + <extension> or null if
- * <loadDefaultBundle> is false.
- *
- * Parameters:
- *
- * basename - The basename for which the file should be loaded.
- * lan - The current language.
- */
- getDefaultBundle: function(basename, lan)
- {
- if (mxResources.loadDefaultBundle || !mxResources.isLanguageSupported(lan))
- {
- return basename + mxResources.extension;
- }
- else
- {
- return null;
- }
- },
-
- /**
- * Function: getSpecialBundle
- *
- * Hook for subclassers to return the URL for the special bundle. This
- * implementation returns basename + '_' + lan + <extension> or null if
- * <loadSpecialBundle> is false or lan equals <mxClient.defaultLanguage>.
- *
- * If <mxResources.languages> is not null and <mxClient.language> contains
- * a dash, then this method checks if <isLanguageSupported> returns true
- * for the full language (including the dash). If that returns false the
- * first part of the language (up to the dash) will be tried as an extension.
- *
- * If <mxResources.language> is null then the first part of the language is
- * used to maintain backwards compatibility.
- *
- * Parameters:
- *
- * basename - The basename for which the file should be loaded.
- * lan - The language for which the file should be loaded.
- */
- getSpecialBundle: function(basename, lan)
- {
- if (mxClient.languages == null || !this.isLanguageSupported(lan))
- {
- var dash = lan.indexOf('-');
-
- if (dash > 0)
- {
- lan = lan.substring(0, dash);
- }
- }
-
- if (mxResources.loadSpecialBundle && mxResources.isLanguageSupported(lan) && lan != mxClient.defaultLanguage)
- {
- return basename + '_' + lan + mxResources.extension;
- }
- else
- {
- return null;
- }
- },
-
- /**
- * Function: add
- *
- * Adds the default and current language properties
- * file for the specified basename. Existing keys
- * are overridden as new files are added.
- *
- * Example:
- *
- * At application startup, additional resources may be
- * added using the following code:
- *
- * (code)
- * mxResources.add('resources/editor');
- * (end)
- */
- add: function(basename, lan)
- {
- lan = (lan != null) ? lan : mxClient.language.toLowerCase();
-
- if (lan != mxConstants.NONE)
- {
- // Loads the common language file (no extension)
- var defaultBundle = mxResources.getDefaultBundle(basename, lan);
-
- if (defaultBundle != null)
- {
- try
- {
- var req = mxUtils.load(defaultBundle);
-
- if (req.isReady())
- {
- mxResources.parse(req.getText());
- }
- }
- catch (e)
- {
- // ignore
- }
- }
-
- // Overlays the language specific file (_lan-extension)
- var specialBundle = mxResources.getSpecialBundle(basename, lan);
-
- if (specialBundle != null)
- {
- try
- {
- var req = mxUtils.load(specialBundle);
-
- if (req.isReady())
- {
- mxResources.parse(req.getText());
- }
- }
- catch (e)
- {
- // ignore
- }
- }
- }
- },
-
- /**
- * Function: parse
- *
- * Parses the key, value pairs in the specified
- * text and stores them as local resources.
- */
- parse: function(text)
- {
- if (text != null)
- {
- var lines = text.split('\n');
-
- for (var i = 0; i < lines.length; i++)
- {
- if (lines[i].charAt(0) != '#')
- {
- var index = lines[i].indexOf('=');
-
- if (index > 0)
- {
- var key = lines[i].substring(0, index);
- var idx = lines[i].length;
-
- if (lines[i].charCodeAt(idx - 1) == 13)
- {
- idx--;
- }
-
- var value = lines[i].substring(index + 1, idx);
-
- if (this.resourcesEncoded)
- {
- value = value.replace(/\\(?=u[a-fA-F\d]{4})/g,"%");
- mxResources.resources[key] = unescape(value);
- }
- else
- {
- mxResources.resources[key] = value;
- }
- }
- }
- }
- }
- },
-
- /**
- * Function: get
- *
- * Returns the value for the specified resource key.
- *
- * Example:
- * To read the value for 'welomeMessage', use the following:
- * (code)
- * var result = mxResources.get('welcomeMessage') || '';
- * (end)
- *
- * This would require an entry of the following form in
- * one of the English language resource files:
- * (code)
- * welcomeMessage=Welcome to mxGraph!
- * (end)
- *
- * The part behind the || is the string value to be used if the given
- * resource is not available.
- *
- * Parameters:
- *
- * key - String that represents the key of the resource to be returned.
- * params - Array of the values for the placeholders of the form {1}...{n}
- * to be replaced with in the resulting string.
- * defaultValue - Optional string that specifies the default return value.
- */
- get: function(key, params, defaultValue)
- {
- var value = mxResources.resources[key];
-
- // Applies the default value if no resource was found
- if (value == null)
- {
- value = defaultValue;
- }
-
- // Replaces the placeholders with the values in the array
- if (value != null &&
- params != null)
- {
- var result = [];
- var index = null;
-
- for (var i = 0; i < value.length; i++)
- {
- var c = value.charAt(i);
-
- if (c == '{')
- {
- index = '';
- }
- else if (index != null && c == '}')
- {
- index = parseInt(index)-1;
-
- if (index >= 0 && index < params.length)
- {
- result.push(params[index]);
- }
-
- index = null;
- }
- else if (index != null)
- {
- index += c;
- }
- else
- {
- result.push(c);
- }
- }
-
- value = result.join('');
- }
-
- return value;
- }
-
-};
diff --git a/src/js/util/mxSession.js b/src/js/util/mxSession.js
deleted file mode 100644
index 4c2a70c..0000000
--- a/src/js/util/mxSession.js
+++ /dev/null
@@ -1,674 +0,0 @@
-/**
- * $Id: mxSession.js,v 1.46 2012-08-22 15:30:49 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxSession
- *
- * Session for sharing an <mxGraphModel> with other parties
- * via a backend that acts as a multicaster for all changes.
- *
- * Diagram Sharing:
- *
- * The diagram sharing is a mechanism where each atomic change of the model is
- * encoded into XML using <mxCodec> and then transmitted to the server by the
- * <mxSession> object. On the server, the XML data is dispatched to each
- * listener on the same diagram (except the sender), and the XML is decoded
- * back into atomic changes on the client side, which are then executed on the
- * model and stored in the command history.
- *
- * The <mxSession.significantRemoteChanges> specifies how these changes are
- * treated with respect to undo: The default value (true) will undo the last
- * change regardless of whether it was a remote or a local change. If the
- * switch is false, then an undo will go back until the last local change,
- * silently undoing all remote changes up to that point. Note that these
- * changes will be added as new remote changes to the history of the other
- * clients.
- *
- * Event: mxEvent.CONNECT
- *
- * Fires after the session has been started, that is, after the response to the
- * initial request was received and the session goes into polling mode. This
- * event has no properties.
- *
- * Event: mxEvent.SUSPEND
- *
- * Fires after <suspend> was called an the session was not already in suspended
- * state. This event has no properties.
- *
- * Event: mxEvent.RESUME
- *
- * Fires after the session was resumed in <resume>. This event has no
- * properties.
- *
- * Event: mxEvent.DISCONNECT
- *
- * Fires after the session was stopped in <stop>. The <code>reason</code>
- * property contains the optional exception that was passed to the stop method.
- *
- * Event: mxEvent.NOTIFY
- *
- * Fires after a notification was sent in <notify>. The <code>url</code>
- * property contains the URL and the <code>xml</code> property contains the XML
- * data of the request.
- *
- * Event: mxEvent.GET
- *
- * Fires after a response was received in <get>. The <code>url</code> property
- * contains the URL and the <code>request</code> is the <mxXmlRequest> that
- * contains the response.
- *
- * Event: mxEvent.FIRED
- *
- * Fires after an array of edits has been executed on the model. The
- * <code>changes</code> property contains the array of changes.
- *
- * Event: mxEvent.RECEIVE
- *
- * Fires after an XML node was received in <receive>. The <code>node</code>
- * property contains the node that was received.
- *
- * Constructor: mxSession
- *
- * Constructs a new session using the given <mxGraphModel> and URLs to
- * communicate with the backend.
- *
- * Parameters:
- *
- * model - <mxGraphModel> that contains the data.
- * urlInit - URL to be used for initializing the session.
- * urlPoll - URL to be used for polling the backend.
- * urlNotify - URL to be used for sending changes to the backend.
- */
-function mxSession(model, urlInit, urlPoll, urlNotify)
-{
- this.model = model;
- this.urlInit = urlInit;
- this.urlPoll = urlPoll;
- this.urlNotify = urlNotify;
-
- // Resolves cells by id using the model
- if (model != null)
- {
- this.codec = new mxCodec();
-
- this.codec.lookup = function(id)
- {
- return model.getCell(id);
- };
- }
-
- // Adds the listener for notifying the backend of any
- // changes in the model
- model.addListener(mxEvent.NOTIFY, mxUtils.bind(this, function(sender, evt)
- {
- var edit = evt.getProperty('edit');
-
- if (edit != null && this.debug || (this.connected && !this.suspended))
- {
- this.notify('<edit>'+this.encodeChanges(edit.changes, edit.undone)+'</edit>');
- }
- }));
-};
-
-/**
- * Extends mxEventSource.
- */
-mxSession.prototype = new mxEventSource();
-mxSession.prototype.constructor = mxSession;
-
-/**
- * Variable: model
- *
- * Reference to the enclosing <mxGraphModel>.
- */
-mxSession.prototype.model = null;
-
-/**
- * Variable: urlInit
- *
- * URL to initialize the session.
- */
-mxSession.prototype.urlInit = null;
-
-/**
- * Variable: urlPoll
- *
- * URL for polling the backend.
- */
-mxSession.prototype.urlPoll = null;
-
-/**
- * Variable: urlNotify
- *
- * URL to send changes to the backend.
- */
-mxSession.prototype.urlNotify = null;
-
-/**
- * Variable: codec
- *
- * Reference to the <mxCodec> used to encoding and decoding changes.
- */
-mxSession.prototype.codec = null;
-
-/**
- * Variable: linefeed
- *
- * Used for encoding linefeeds. Default is '&#xa;'.
- */
-mxSession.prototype.linefeed = '&#xa;';
-
-/**
- * Variable: escapePostData
- *
- * Specifies if the data in the post request sent in <notify>
- * should be converted using encodeURIComponent. Default is true.
- */
-mxSession.prototype.escapePostData = true;
-
-/**
- * Variable: significantRemoteChanges
- *
- * Whether remote changes should be significant in the
- * local command history. Default is true.
- */
-mxSession.prototype.significantRemoteChanges = true;
-
-/**
- * Variable: sent
- *
- * Total number of sent bytes.
- */
-mxSession.prototype.sent = 0;
-
-/**
- * Variable: received
- *
- * Total number of received bytes.
- */
-mxSession.prototype.received = 0;
-
-/**
- * Variable: debug
- *
- * Specifies if the session should run in debug mode. In this mode, no
- * connection is established. The data is written to the console instead.
- * Default is false.
- */
-mxSession.prototype.debug = false;
-
-/**
- * Variable: connected
- */
-mxSession.prototype.connected = false;
-
-/**
- * Variable: send
- */
-mxSession.prototype.suspended = false;
-
-/**
- * Variable: polling
- */
-mxSession.prototype.polling = false;
-
-/**
- * Function: start
- */
-mxSession.prototype.start = function()
-{
- if (this.debug)
- {
- this.connected = true;
- this.fireEvent(new mxEventObject(mxEvent.CONNECT));
- }
- else if (!this.connected)
- {
- this.get(this.urlInit, mxUtils.bind(this, function(req)
- {
- this.connected = true;
- this.fireEvent(new mxEventObject(mxEvent.CONNECT));
- this.poll();
- }));
- }
-};
-
-/**
- * Function: suspend
- *
- * Suspends the polling. Use <resume> to reactive the session. Fires a
- * suspend event.
- */
-mxSession.prototype.suspend = function()
-{
- if (this.connected && !this.suspended)
- {
- this.suspended = true;
- this.fireEvent(new mxEventObject(mxEvent.SUSPEND));
- }
-};
-
-/**
- * Function: resume
- *
- * Resumes the session if it has been suspended. Fires a resume-event
- * before starting the polling.
- */
-mxSession.prototype.resume = function(type, attr, value)
-{
- if (this.connected &&
- this.suspended)
- {
- this.suspended = false;
- this.fireEvent(new mxEventObject(mxEvent.RESUME));
-
- if (!this.polling)
- {
- this.poll();
- }
- }
-};
-
-/**
- * Function: stop
- *
- * Stops the session and fires a disconnect event. The given reason is
- * passed to the disconnect event listener as the second argument.
- */
-mxSession.prototype.stop = function(reason)
-{
- if (this.connected)
- {
- this.connected = false;
- }
-
- this.fireEvent(new mxEventObject(mxEvent.DISCONNECT,
- 'reason', reason));
-};
-
-/**
- * Function: poll
- *
- * Sends an asynchronous GET request to <urlPoll>.
- */
-mxSession.prototype.poll = function()
-{
- if (this.connected &&
- !this.suspended &&
- this.urlPoll != null)
- {
- this.polling = true;
-
- this.get(this.urlPoll, mxUtils.bind(this, function()
- {
- this.poll();
- }));
- }
- else
- {
- this.polling = false;
- }
-};
-
-/**
- * Function: notify
- *
- * Sends out the specified XML to <urlNotify> and fires a <notify> event.
- */
-mxSession.prototype.notify = function(xml, onLoad, onError)
-{
- if (xml != null &&
- xml.length > 0)
- {
- if (this.urlNotify != null)
- {
- if (this.debug)
- {
- mxLog.show();
- mxLog.debug('mxSession.notify: '+this.urlNotify+' xml='+xml);
- }
- else
- {
- xml = '<message><delta>'+xml+'</delta></message>';
-
- if (this.escapePostData)
- {
- xml = encodeURIComponent(xml);
- }
-
- mxUtils.post(this.urlNotify, 'xml='+xml, onLoad, onError);
- }
- }
-
- this.sent += xml.length;
- this.fireEvent(new mxEventObject(mxEvent.NOTIFY,
- 'url', this.urlNotify, 'xml', xml));
- }
-};
-
-/**
- * Function: get
- *
- * Sends an asynchronous get request to the given URL, fires a <get> event
- * and invokes the given onLoad function when a response is received.
- */
-mxSession.prototype.get = function(url, onLoad, onError)
-{
- // Response after browser refresh has no global scope
- // defined. This response is ignored and the session
- // stops implicitely.
- if (typeof(mxUtils) != 'undefined')
- {
- var onErrorWrapper = mxUtils.bind(this, function(ex)
- {
- if (onError != null)
- {
- onError(ex);
- }
- else
- {
- this.stop(ex);
- }
- });
-
- // Handles a successful response for
- // the above request.
- mxUtils.get(url, mxUtils.bind(this, function(req)
- {
- if (typeof(mxUtils) != 'undefined')
- {
- if (req.isReady() && req.getStatus() != 404)
- {
- this.received += req.getText().length;
- this.fireEvent(new mxEventObject(mxEvent.GET, 'url', url, 'request', req));
-
- if (this.isValidResponse(req))
- {
- if (req.getText().length > 0)
- {
- var node = req.getDocumentElement();
-
- if (node == null)
- {
- onErrorWrapper('Invalid response: '+req.getText());
- }
- else
- {
- this.receive(node);
- }
- }
-
- if (onLoad != null)
- {
- onLoad(req);
- }
- }
- }
- else
- {
- onErrorWrapper('Response not ready');
- }
- }
- }),
- // Handles a transmission error for the
- // above request
- function(req)
- {
- onErrorWrapper('Transmission error');
- });
- }
-};
-
-/**
- * Function: isValidResponse
- *
- * Returns true if the response data in the given <mxXmlRequest> is valid.
- */
-mxSession.prototype.isValidResponse = function(req)
-{
- // TODO: Find condition to check if response
- // contains valid XML (not eg. the PHP code).
- return req.getText().indexOf('<?php') < 0;
-};
-
-/**
- * Function: encodeChanges
- *
- * Returns the XML representation for the given array of changes.
- */
-mxSession.prototype.encodeChanges = function(changes, invert)
-{
- // TODO: Use array for string concatenation
- var xml = '';
- var step = (invert) ? -1 : 1;
- var i0 = (invert) ? changes.length - 1 : 0;
-
- for (var i = i0; i >= 0 && i < changes.length; i += step)
- {
- // Newlines must be kept, they will be converted
- // to &#xa; when the server sends data to the
- // client
- var node = this.codec.encode(changes[i]);
- xml += mxUtils.getXml(node, this.linefeed);
- }
-
- return xml;
-};
-
-/**
- * Function: receive
- *
- * Processes the given node by applying the changes to the model. If the nodename
- * is state, then the namespace is used as a prefix for creating Ids in the model,
- * and the child nodes are visited recursively. If the nodename is delta, then the
- * changes encoded in the child nodes are applied to the model. Each call to the
- * receive function fires a <receive> event with the given node as the second argument
- * after processing. If changes are processed, then the function additionally fires
- * a <mxEvent.FIRED> event before the <mxEvent.RECEIVE> event.
- */
-mxSession.prototype.receive = function(node)
-{
- if (node != null && node.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- // Uses the namespace in the model
- var ns = node.getAttribute('namespace');
-
- if (ns != null)
- {
- this.model.prefix = ns + '-';
- }
-
- var child = node.firstChild;
-
- while (child != null)
- {
- var name = child.nodeName.toLowerCase();
-
- if (name == 'state')
- {
- this.processState(child);
- }
- else if (name == 'delta')
- {
- this.processDelta(child);
- }
-
- child = child.nextSibling;
- }
-
- // Fires receive event
- this.fireEvent(new mxEventObject(mxEvent.RECEIVE, 'node', node));
- }
-};
-
-/**
- * Function: processState
- *
- * Processes the given state node which contains the current state of the
- * remote model.
- */
-mxSession.prototype.processState = function(node)
-{
- var dec = new mxCodec(node.ownerDocument);
- dec.decode(node.firstChild, this.model);
-};
-
-/**
- * Function: processDelta
- *
- * Processes the given delta node which contains a sequence of edits which in
- * turn map to one transaction on the remote model each.
- */
-mxSession.prototype.processDelta = function(node)
-{
- var edit = node.firstChild;
-
- while (edit != null)
- {
- if (edit.nodeName == 'edit')
- {
- this.processEdit(edit);
- }
-
- edit = edit.nextSibling;
- }
-};
-
-/**
- * Function: processEdit
- *
- * Processes the given edit by executing its changes and firing the required
- * events via the model.
- */
-mxSession.prototype.processEdit = function(node)
-{
- var changes = this.decodeChanges(node);
-
- if (changes.length > 0)
- {
- var edit = this.createUndoableEdit(changes);
-
- // No notify event here to avoid the edit from being encoded and transmitted
- // LATER: Remove changes property (deprecated)
- this.model.fireEvent(new mxEventObject(mxEvent.CHANGE,
- 'edit', edit, 'changes', changes));
- this.model.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
- this.fireEvent(new mxEventObject(mxEvent.FIRED, 'edit', edit));
- }
-};
-
-/**
- * Function: createUndoableEdit
- *
- * Creates a new <mxUndoableEdit> that implements the notify function to fire a
- * <change> and <notify> event via the model.
- */
-mxSession.prototype.createUndoableEdit = function(changes)
-{
- var edit = new mxUndoableEdit(this.model, this.significantRemoteChanges);
- edit.changes = changes;
-
- edit.notify = function()
- {
- // LATER: Remove changes property (deprecated)
- edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,
- 'edit', edit, 'changes', edit.changes));
- edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,
- 'edit', edit, 'changes', edit.changes));
- };
-
- return edit;
-};
-
-/**
- * Function: decodeChanges
- *
- * Decodes and executes the changes represented by the children in the
- * given node. Returns an array that contains all changes.
- */
-mxSession.prototype.decodeChanges = function(node)
-{
- // Updates the document in the existing codec
- this.codec.document = node.ownerDocument;
-
- // Parses and executes the changes on the model
- var changes = [];
- node = node.firstChild;
-
- while (node != null)
- {
- var change = this.decodeChange(node);
-
- if (change != null)
- {
- changes.push(change);
- }
-
- node = node.nextSibling;
- }
-
- return changes;
-};
-
-/**
- * Function: decodeChange
- *
- * Decodes, executes and returns the change object represented by the given
- * XML node.
- */
-mxSession.prototype.decodeChange = function(node)
-{
- var change = null;
-
- if (node.nodeType == mxConstants.NODETYPE_ELEMENT)
- {
- if (node.nodeName == 'mxRootChange')
- {
- // Handles the special case were no ids should be
- // resolved in the existing model. This change will
- // replace all registered ids and cells from the
- // model and insert a new cell hierarchy instead.
- var tmp = new mxCodec(node.ownerDocument);
- change = tmp.decode(node);
- }
- else
- {
- change = this.codec.decode(node);
- }
-
- if (change != null)
- {
- change.model = this.model;
- change.execute();
-
- // Workaround for references not being resolved if cells have
- // been removed from the model prior to being referenced. This
- // adds removed cells in the codec object lookup table.
- if (node.nodeName == 'mxChildChange' && change.parent == null)
- {
- this.cellRemoved(change.child);
- }
- }
- }
-
- return change;
-};
-
-/**
- * Function: cellRemoved
- *
- * Adds removed cells to the codec object lookup for references to the removed
- * cells after this point in time.
- */
-mxSession.prototype.cellRemoved = function(cell, codec)
-{
- this.codec.putObject(cell.getId(), cell);
-
- var childCount = this.model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- this.cellRemoved(this.model.getChildAt(cell, i));
- }
-};
diff --git a/src/js/util/mxSvgCanvas2D.js b/src/js/util/mxSvgCanvas2D.js
deleted file mode 100644
index 4af0642..0000000
--- a/src/js/util/mxSvgCanvas2D.js
+++ /dev/null
@@ -1,1234 +0,0 @@
-/**
- * $Id: mxSvgCanvas2D.js,v 1.18 2012-11-23 15:13:19 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- *
- * Class: mxSvgCanvas2D
- *
- * Implements a canvas to be used with <mxImageExport>. This canvas writes all
- * calls as SVG output to the given SVG root node.
- *
- * (code)
- * var svgDoc = mxUtils.createXmlDocument();
- * var root = (svgDoc.createElementNS != null) ?
- * svgDoc.createElementNS(mxConstants.NS_SVG, 'svg') : svgDoc.createElement('svg');
- *
- * if (svgDoc.createElementNS == null)
- * {
- * root.setAttribute('xmlns', mxConstants.NS_SVG);
- * }
- *
- * var bounds = graph.getGraphBounds();
- * root.setAttribute('width', (bounds.x + bounds.width + 4) + 'px');
- * root.setAttribute('height', (bounds.y + bounds.height + 4) + 'px');
- * root.setAttribute('version', '1.1');
- *
- * svgDoc.appendChild(root);
- *
- * var svgCanvas = new mxSvgCanvas2D(root);
- * (end)
- *
- * Constructor: mxSvgCanvas2D
- *
- * Constructs an SVG canvas.
- *
- * Parameters:
- *
- * root - SVG container for the output.
- * styleEnabled - Optional boolean that specifies if a style section should be
- * added. The style section sets the default font-size, font-family and
- * stroke-miterlimit globally. Default is false.
- */
-var mxSvgCanvas2D = function(root, styleEnabled)
-{
- styleEnabled = (styleEnabled != null) ? styleEnabled : false;
-
- /**
- * Variable: converter
- *
- * Holds the <mxUrlConverter> to convert image URLs.
- */
- var converter = new mxUrlConverter();
-
- /**
- * Variable: autoAntiAlias
- *
- * Specifies if anti aliasing should be disabled for rectangles
- * and orthogonal paths. Default is true.
- */
- var autoAntiAlias = true;
-
- /**
- * Variable: textEnabled
- *
- * Specifies if text output should be enabled. Default is true.
- */
- var textEnabled = true;
-
- /**
- * Variable: foEnabled
- *
- * Specifies if use of foreignObject for HTML markup is allowed. Default is true.
- */
- var foEnabled = true;
-
- // Private helper function to create SVG elements
- var create = function(tagName, namespace)
- {
- var doc = root.ownerDocument || document;
-
- if (doc.createElementNS != null)
- {
- return doc.createElementNS(namespace || mxConstants.NS_SVG, tagName);
- }
- else
- {
- var elt = doc.createElement(tagName);
-
- if (namespace != null)
- {
- elt.setAttribute('xmlns', namespace);
- }
-
- return elt;
- }
- };
-
- // Defs section contains optional style and gradients
- var defs = create('defs');
-
- // Creates defs section with optional global style
- if (styleEnabled)
- {
- var style = create('style');
- style.setAttribute('type', 'text/css');
- mxUtils.write(style, 'svg{font-family:' + mxConstants.DEFAULT_FONTFAMILY +
- ';font-size:' + mxConstants.DEFAULT_FONTSIZE +
- ';fill:none;stroke-miterlimit:10}');
-
- if (autoAntiAlias)
- {
- mxUtils.write(style, 'rect{shape-rendering:crispEdges}');
- }
-
- // Appends style to defs and defs to SVG container
- defs.appendChild(style);
- }
-
- root.appendChild(defs);
-
- // Defines the current state
- var currentState =
- {
- dx: 0,
- dy: 0,
- scale: 1,
- transform: '',
- fill: null,
- gradient: null,
- stroke: null,
- strokeWidth: 1,
- dashed: false,
- dashpattern: '3 3',
- alpha: 1,
- linecap: 'flat',
- linejoin: 'miter',
- miterlimit: 10,
- fontColor: '#000000',
- fontSize: mxConstants.DEFAULT_FONTSIZE,
- fontFamily: mxConstants.DEFAULT_FONTFAMILY,
- fontStyle: 0
- };
-
- // Local variables
- var currentPathIsOrthogonal = true;
- var glassGradient = null;
- var currentNode = null;
- var currentPath = null;
- var lastPoint = null;
- var gradients = [];
- var refCount = 0;
- var stack = [];
-
- // Other private helper methods
- var createGradientId = function(start, end, direction)
- {
- // Removes illegal characters from gradient ID
- if (start.charAt(0) == '#')
- {
- start = start.substring(1);
- }
-
- if (end.charAt(0) == '#')
- {
- end = end.substring(1);
- }
-
- // Workaround for gradient IDs not working in Safari 5 / Chrome 6
- // if they contain uppercase characters
- start = start.toLowerCase();
- end = end.toLowerCase();
-
- // Wrong gradient directions possible?
- var dir = null;
-
- if (direction == null || direction == mxConstants.DIRECTION_SOUTH)
- {
- dir = 's';
- }
- else if (direction == mxConstants.DIRECTION_EAST)
- {
- dir = 'e';
- }
- else
- {
- var tmp = start;
- start = end;
- end = tmp;
-
- if (direction == mxConstants.DIRECTION_NORTH)
- {
- dir = 's';
- }
- else if (direction == mxConstants.DIRECTION_WEST)
- {
- dir = 'e';
- }
- }
-
- return start+'-'+end+'-'+dir;
- };
-
- var createHtmlBody = function(str, align, valign)
- {
- var style = 'margin:0px;font-size:' + Math.floor(currentState.fontSize) + 'px;' +
- 'font-family:' + currentState.fontFamily + ';color:' + currentState.fontColor+ ';';
-
- if ((currentState.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD)
- {
- style += 'font-weight:bold;';
- }
-
- if ((currentState.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC)
- {
- style += 'font-style:italic;';
- }
-
- if ((currentState.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE)
- {
- style += 'font-decoration:underline;';
- }
-
- if (align == mxConstants.ALIGN_CENTER)
- {
- style += 'text-align:center;';
- }
- else if (align == mxConstants.ALIGN_RIGHT)
- {
- style += 'text-align:right;';
- }
-
- // Converts HTML entities to unicode
- var t = document.createElement('div');
- t.innerHTML = str;
- str = t.innerHTML.replace(/&nbsp;/g, '&#160;');
-
- // LATER: Add vertical align support via table, adds xmlns to workaround empty NS in IE9 standards
- var node = mxUtils.parseXml('<div xmlns="http://www.w3.org/1999/xhtml" style="' +
- style + '">' + str + '</div>').documentElement;
-
- return node;
- };
-
- var getSvgGradient = function(start, end, direction)
- {
- var id = createGradientId(start, end, direction);
- var gradient = gradients[id];
-
- if (gradient == null)
- {
- gradient = create('linearGradient');
- gradient.setAttribute('id', ++refCount);
- gradient.setAttribute('x1', '0%');
- gradient.setAttribute('y1', '0%');
- gradient.setAttribute('x2', '0%');
- gradient.setAttribute('y2', '0%');
-
- if (direction == null || direction == mxConstants.DIRECTION_SOUTH)
- {
- gradient.setAttribute('y2', '100%');
- }
- else if (direction == mxConstants.DIRECTION_EAST)
- {
- gradient.setAttribute('x2', '100%');
- }
- else if (direction == mxConstants.DIRECTION_NORTH)
- {
- gradient.setAttribute('y1', '100%');
- }
- else if (direction == mxConstants.DIRECTION_WEST)
- {
- gradient.setAttribute('x1', '100%');
- }
-
- var stop = create('stop');
- stop.setAttribute('offset', '0%');
- stop.setAttribute('style', 'stop-color:'+start);
- gradient.appendChild(stop);
-
- stop = create('stop');
- stop.setAttribute('offset', '100%');
- stop.setAttribute('style', 'stop-color:'+end);
- gradient.appendChild(stop);
-
- defs.appendChild(gradient);
- gradients[id] = gradient;
- }
-
- return gradient.getAttribute('id');
- };
-
- var appendNode = function(node, state, filled, stroked)
- {
- if (node != null)
- {
- if (state.clip != null)
- {
- node.setAttribute('clip-path', 'url(#' + state.clip + ')');
- state.clip = null;
- }
-
- if (currentPath != null)
- {
- node.setAttribute('d', currentPath.join(' '));
- currentPath = null;
-
- if (autoAntiAlias && currentPathIsOrthogonal)
- {
- node.setAttribute('shape-rendering', 'crispEdges');
- state.strokeWidth = Math.max(1, state.strokeWidth);
- }
- }
-
- if (state.alpha < 1)
- {
- // LATER: Check if using fill/stroke-opacity here is faster
- node.setAttribute('opacity', state.alpha);
- //node.setAttribute('fill-opacity', state.alpha);
- //node.setAttribute('stroke-opacity', state.alpha);
- }
-
- if (filled && (state.fill != null || state.gradient != null))
- {
- if (state.gradient != null)
- {
- node.setAttribute('fill', 'url(#' + state.gradient + ')');
- }
- else
- {
- node.setAttribute('fill', state.fill.toLowerCase());
- }
- }
- else if (!styleEnabled)
- {
- node.setAttribute('fill', 'none');
- }
-
- if (stroked && state.stroke != null)
- {
- node.setAttribute('stroke', state.stroke.toLowerCase());
-
- // Sets the stroke properties (1 is default is SVG)
- if (state.strokeWidth != 1)
- {
- if (node.nodeName == 'rect' && autoAntiAlias)
- {
- state.strokeWidth = Math.max(1, state.strokeWidth);
- }
-
- node.setAttribute('stroke-width', state.strokeWidth);
- }
-
- if (node.nodeName == 'path')
- {
- // Linejoin miter is default in SVG
- if (state.linejoin != null && state.linejoin != 'miter')
- {
- node.setAttribute('stroke-linejoin', state.linejoin);
- }
-
- if (state.linecap != null)
- {
- // flat is called butt in SVG
- var value = state.linecap;
-
- if (value == 'flat')
- {
- value = 'butt';
- }
-
- // Linecap butt is default in SVG
- if (value != 'butt')
- {
- node.setAttribute('stroke-linecap', value);
- }
- }
-
- // Miterlimit 10 is default in our document
- if (state.miterlimit != null && (!styleEnabled || state.miterlimit != 10))
- {
- node.setAttribute('stroke-miterlimit', state.miterlimit);
- }
- }
-
- if (state.dashed)
- {
- var dash = state.dashpattern.split(' ');
-
- if (dash.length > 0)
- {
- var pat = [];
-
- for (var i = 0; i < dash.length; i++)
- {
- pat[i] = Number(dash[i]) * currentState.strokeWidth;
- }
-
-
- node.setAttribute('stroke-dasharray', pat.join(' '));
- }
- }
- }
-
- if (state.transform.length > 0)
- {
- node.setAttribute('transform', state.transform);
- }
-
- root.appendChild(node);
- }
- };
-
- // Private helper function to format a number
- var f2 = function(x)
- {
- return Math.round(parseFloat(x) * 100) / 100;
- };
-
- // Returns public interface
- return {
-
- /**
- * Function: getConverter
- *
- * Returns <converter>.
- */
- getConverter: function()
- {
- return converter;
- },
-
- /**
- * Function: isAutoAntiAlias
- *
- * Returns <autoAntiAlias>.
- */
- isAutoAntiAlias: function()
- {
- return autoAntiAlias;
- },
-
- /**
- * Function: setAutoAntiAlias
- *
- * Sets <autoAntiAlias>.
- */
- setAutoAntiAlias: function(value)
- {
- autoAntiAlias = value;
- },
-
- /**
- * Function: isTextEnabled
- *
- * Returns <textEnabled>.
- */
- isTextEnabled: function()
- {
- return textEnabled;
- },
-
- /**
- * Function: setTextEnabled
- *
- * Sets <textEnabled>.
- */
- setTextEnabled: function(value)
- {
- textEnabled = value;
- },
-
- /**
- * Function: isFoEnabled
- *
- * Returns <foEnabled>.
- */
- isFoEnabled: function()
- {
- return foEnabled;
- },
-
- /**
- * Function: setFoEnabled
- *
- * Sets <foEnabled>.
- */
- setFoEnabled: function(value)
- {
- foEnabled = value;
- },
-
- /**
- * Function: save
- *
- * Saves the state of the graphics object.
- */
- save: function()
- {
- stack.push(currentState);
- currentState = mxUtils.clone(currentState);
- },
-
- /**
- * Function: restore
- *
- * Restores the state of the graphics object.
- */
- restore: function()
- {
- currentState = stack.pop();
- },
-
- /**
- * Function: scale
- *
- * Scales the current graphics object.
- */
- scale: function(value)
- {
- currentState.scale *= value;
- currentState.strokeWidth *= value;
- },
-
- /**
- * Function: translate
- *
- * Translates the current graphics object.
- */
- translate: function(dx, dy)
- {
- currentState.dx += dx;
- currentState.dy += dy;
- },
-
- /**
- * Function: rotate
- *
- * Rotates and/or flips the current graphics object.
- */
- rotate: function(theta, flipH, flipV, cx, cy)
- {
- cx += currentState.dx;
- cy += currentState.dy;
-
- cx *= currentState.scale;
- cy *= currentState.scale;
-
- // This implementation uses custom scale/translate and built-in rotation
- // Rotation state is part of the AffineTransform in state.transform
- if (flipH ^ flipV)
- {
- var tx = (flipH) ? cx : 0;
- var sx = (flipH) ? -1 : 1;
-
- var ty = (flipV) ? cy : 0;
- var sy = (flipV) ? -1 : 1;
-
- currentState.transform += 'translate(' + f2(tx) + ',' + f2(ty) + ')';
- currentState.transform += 'scale(' + f2(sx) + ',' + f2(sy) + ')';
- currentState.transform += 'translate(' + f2(-tx) + ' ' + f2(-ty) + ')';
- }
-
- currentState.transform += 'rotate(' + f2(theta) + ',' + f2(cx) + ',' + f2(cy) + ')';
- },
-
- /**
- * Function: setStrokeWidth
- *
- * Sets the stroke width.
- */
- setStrokeWidth: function(value)
- {
- currentState.strokeWidth = value * currentState.scale;
- },
-
- /**
- * Function: setStrokeColor
- *
- * Sets the stroke color.
- */
- setStrokeColor: function(value)
- {
- currentState.stroke = value;
- },
-
- /**
- * Function: setDashed
- *
- * Sets the dashed state to true or false.
- */
- setDashed: function(value)
- {
- currentState.dashed = value;
- },
-
- /**
- * Function: setDashPattern
- *
- * Sets the dashed pattern to the given space separated list of numbers.
- */
- setDashPattern: function(value)
- {
- currentState.dashpattern = value;
- },
-
- /**
- * Function: setLineCap
- *
- * Sets the linecap.
- */
- setLineCap: function(value)
- {
- currentState.linecap = value;
- },
-
- /**
- * Function: setLineJoin
- *
- * Sets the linejoin.
- */
- setLineJoin: function(value)
- {
- currentState.linejoin = value;
- },
-
- /**
- * Function: setMiterLimit
- *
- * Sets the miterlimit.
- */
- setMiterLimit: function(value)
- {
- currentState.miterlimit = value;
- },
-
- /**
- * Function: setFontSize
- *
- * Sets the fontsize.
- */
- setFontSize: function(value)
- {
- currentState.fontSize = value;
- },
-
- /**
- * Function: setFontColor
- *
- * Sets the fontcolor.
- */
- setFontColor: function(value)
- {
- currentState.fontColor = value;
- },
-
- /**
- * Function: setFontFamily
- *
- * Sets the fontfamily.
- */
- setFontFamily: function(value)
- {
- currentState.fontFamily = value;
- },
-
- /**
- * Function: setFontStyle
- *
- * Sets the fontstyle.
- */
- setFontStyle: function(value)
- {
- currentState.fontStyle = value;
- },
-
- /**
- * Function: setAlpha
- *
- * Sets the current alpha.
- */
- setAlpha: function(alpha)
- {
- currentState.alpha = alpha;
- },
-
- /**
- * Function: setFillColor
- *
- * Sets the fillcolor.
- */
- setFillColor: function(value)
- {
- currentState.fill = value;
- currentState.gradient = null;
- },
-
- /**
- * Function: setGradient
- *
- * Sets the gradient color.
- */
- setGradient: function(color1, color2, x, y, w, h, direction)
- {
- if (color1 != null && color2 != null)
- {
- currentState.gradient = getSvgGradient(color1, color2, direction);
- currentState.fill = color1;
- }
- },
-
- /**
- * Function: setGlassGradient
- *
- * Sets the glass gradient.
- */
- setGlassGradient: function(x, y, w, h)
- {
- // Creates glass overlay gradient
- if (glassGradient == null)
- {
- glassGradient = create('linearGradient');
- glassGradient.setAttribute('id', '0');
- glassGradient.setAttribute('x1', '0%');
- glassGradient.setAttribute('y1', '0%');
- glassGradient.setAttribute('x2', '0%');
- glassGradient.setAttribute('y2', '100%');
-
- var stop1 = create('stop');
- stop1.setAttribute('offset', '0%');
- stop1.setAttribute('style', 'stop-color:#ffffff;stop-opacity:0.9');
- glassGradient.appendChild(stop1);
-
- var stop2 = create('stop');
- stop2.setAttribute('offset', '100%');
- stop2.setAttribute('style', 'stop-color:#ffffff;stop-opacity:0.1');
- glassGradient.appendChild(stop2);
-
- // Makes it the first entry of all gradients in defs
- if (defs.firstChild.nextSibling != null)
- {
- defs.insertBefore(glassGradient, defs.firstChild.nextSibling);
- }
- else
- {
- defs.appendChild(glassGradient);
- }
- }
-
- // Glass gradient has hardcoded ID (see above)
- currentState.gradient = '0';
- },
-
- /**
- * Function: rect
- *
- * Sets the current path to a rectangle.
- */
- rect: function(x, y, w, h)
- {
- x += currentState.dx;
- y += currentState.dy;
-
- currentNode = create('rect');
- currentNode.setAttribute('x', f2(x * currentState.scale));
- currentNode.setAttribute('y', f2(y * currentState.scale));
- currentNode.setAttribute('width', f2(w * currentState.scale));
- currentNode.setAttribute('height', f2(h * currentState.scale));
-
- if (!styleEnabled && autoAntiAlias)
- {
- currentNode.setAttribute('shape-rendering', 'crispEdges');
- }
- },
-
- /**
- * Function: roundrect
- *
- * Sets the current path to a rounded rectangle.
- */
- roundrect: function(x, y, w, h, dx, dy)
- {
- x += currentState.dx;
- y += currentState.dy;
-
- currentNode = create('rect');
- currentNode.setAttribute('x', f2(x * currentState.scale));
- currentNode.setAttribute('y', f2(y * currentState.scale));
- currentNode.setAttribute('width', f2(w * currentState.scale));
- currentNode.setAttribute('height', f2(h * currentState.scale));
-
- if (dx > 0)
- {
- currentNode.setAttribute('rx', f2(dx * currentState.scale));
- }
-
- if (dy > 0)
- {
- currentNode.setAttribute('ry', f2(dy * currentState.scale));
- }
-
- if (!styleEnabled && autoAntiAlias)
- {
- currentNode.setAttribute('shape-rendering', 'crispEdges');
- }
- },
-
- /**
- * Function: ellipse
- *
- * Sets the current path to an ellipse.
- */
- ellipse: function(x, y, w, h)
- {
- x += currentState.dx;
- y += currentState.dy;
-
- currentNode = create('ellipse');
- currentNode.setAttribute('cx', f2((x + w / 2) * currentState.scale));
- currentNode.setAttribute('cy', f2((y + h / 2) * currentState.scale));
- currentNode.setAttribute('rx', f2(w / 2 * currentState.scale));
- currentNode.setAttribute('ry', f2(h / 2 * currentState.scale));
- },
-
- /**
- * Function: image
- *
- * Paints an image.
- */
- image: function(x, y, w, h, src, aspect, flipH, flipV)
- {
- src = converter.convert(src);
-
- // TODO: Add option for embedded images as base64. Current
- // known issues are binary loading of cross-domain images.
- aspect = (aspect != null) ? aspect : true;
- flipH = (flipH != null) ? flipH : false;
- flipV = (flipV != null) ? flipV : false;
- x += currentState.dx;
- y += currentState.dy;
-
- var node = create('image');
- node.setAttribute('x', f2(x * currentState.scale));
- node.setAttribute('y', f2(y * currentState.scale));
- node.setAttribute('width', f2(w * currentState.scale));
- node.setAttribute('height', f2(h * currentState.scale));
-
- if (mxClient.IS_VML)
- {
- node.setAttribute('xlink:href', src);
- }
- else
- {
- node.setAttributeNS(mxConstants.NS_XLINK, 'xlink:href', src);
- }
-
- if (!aspect)
- {
- node.setAttribute('preserveAspectRatio', 'none');
- }
-
- if (currentState.alpha < 1)
- {
- node.setAttribute('opacity', currentState.alpha);
- }
-
-
- var tr = currentState.transform;
-
- if (flipH || flipV)
- {
- var sx = 1;
- var sy = 1;
- var dx = 0;
- var dy = 0;
-
- if (flipH)
- {
- sx = -1;
- dx = -w - 2 * x;
- }
-
- if (flipV)
- {
- sy = -1;
- dy = -h - 2 * y;
- }
-
- // Adds image tansformation to existing transforms
- tr += 'scale(' + sx + ',' + sy + ')translate(' + dx + ',' + dy + ')';
- }
-
- if (tr.length > 0)
- {
- node.setAttribute('transform', tr);
- }
-
- root.appendChild(node);
- },
-
- /**
- * Function: text
- *
- * Paints the given text. Possible values for format are empty string for
- * plain text and html for HTML markup.
- */
- text: function(x, y, w, h, str, align, valign, vertical, wrap, format)
- {
- if (textEnabled)
- {
- x += currentState.dx;
- y += currentState.dy;
-
- if (foEnabled && format == 'html')
- {
- var node = create('g');
- node.setAttribute('transform', currentState.transform + 'scale(' + currentState.scale + ',' + currentState.scale + ')');
-
- if (currentState.alpha < 1)
- {
- node.setAttribute('opacity', currentState.alpha);
- }
-
- var fo = create('foreignObject');
- fo.setAttribute('x', Math.round(x));
- fo.setAttribute('y', Math.round(y));
- fo.setAttribute('width', Math.round(w));
- fo.setAttribute('height', Math.round(h));
- fo.appendChild(createHtmlBody(str, align, valign));
- node.appendChild(fo);
- root.appendChild(node);
- }
- else
- {
- var size = Math.floor(currentState.fontSize);
- var node = create('g');
- var tr = currentState.transform;
-
- if (vertical)
- {
- var cx = x + w / 2;
- var cy = y + h / 2;
- tr += 'rotate(-90,' + f2(cx * currentState.scale) + ',' + f2(cy * currentState.scale) + ')';
- }
-
- if (tr.length > 0)
- {
- node.setAttribute('transform', tr);
- }
-
- if (currentState.alpha < 1)
- {
- node.setAttribute('opacity', currentState.alpha);
- }
-
- // Default is left
- var anchor = (align == mxConstants.ALIGN_RIGHT) ? 'end' :
- (align == mxConstants.ALIGN_CENTER) ? 'middle' :
- 'start';
-
- if (anchor == 'end')
- {
- x += Math.max(0, w - 2);
- }
- else if (anchor == 'middle')
- {
- x += w / 2;
- }
- else
- {
- x += (w > 0) ? 2 : 0;
- }
-
- if ((currentState.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD)
- {
- node.setAttribute('font-weight', 'bold');
- }
-
- if ((currentState.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC)
- {
- node.setAttribute('font-style', 'italic');
- }
-
- if ((currentState.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE)
- {
- node.setAttribute('text-decoration', 'underline');
- }
-
- // Text-anchor start is default in SVG
- if (anchor != 'start')
- {
- node.setAttribute('text-anchor', anchor);
- }
-
- if (!styleEnabled || size != mxConstants.DEFAULT_FONTSIZE)
- {
- node.setAttribute('font-size', Math.floor(size * currentState.scale) + 'px');
- }
-
- if (!styleEnabled || currentState.fontFamily != mxConstants.DEFAULT_FONTFAMILY)
- {
- node.setAttribute('font-family', currentState.fontFamily);
- }
-
- node.setAttribute('fill', currentState.fontColor);
-
- var lines = str.split('\n');
-
- var lineHeight = size * 1.25;
- var textHeight = (h > 0) ? size + (lines.length - 1) * lineHeight : lines.length * lineHeight - 1;
- var dy = h - textHeight;
-
- // Top is default
- if (valign == null || valign == mxConstants.ALIGN_TOP)
- {
- y = Math.max(y - 3 * currentState.scale, y + dy / 2 + ((h > 0) ? lineHeight / 2 - 8 : 0));
- }
- else if (valign == mxConstants.ALIGN_MIDDLE)
- {
- y = y + dy / 2;
- }
- else if (valign == mxConstants.ALIGN_BOTTOM)
- {
- y = Math.min(y, y + dy + 2 * currentState.scale);
- }
-
- y += size;
-
- for (var i = 0; i < lines.length; i++)
- {
- var text = create('text');
- text.setAttribute('x', f2(x * currentState.scale));
- text.setAttribute('y', f2(y * currentState.scale));
-
- mxUtils.write(text, lines[i]);
- node.appendChild(text);
- y += size * 1.3;
- }
-
- root.appendChild(node);
- }
- }
- },
-
- /**
- * Function: begin
- *
- * Starts a new path.
- */
- begin: function()
- {
- currentNode = create('path');
- currentPath = [];
- lastPoint = null;
- currentPathIsOrthogonal = true;
- },
-
- /**
- * Function: moveTo
- *
- * Moves the current path the given coordinates.
- */
- moveTo: function(x, y)
- {
- if (currentPath != null)
- {
- x += currentState.dx;
- y += currentState.dy;
- currentPath.push('M ' + f2(x * currentState.scale) + ' ' + f2(y * currentState.scale));
-
- if (autoAntiAlias)
- {
- lastPoint = new mxPoint(x, y);
- }
- }
- },
-
- /**
- * Function: lineTo
- *
- * Adds a line to the current path.
- */
- lineTo: function(x, y)
- {
- if (currentPath != null)
- {
- x += currentState.dx;
- y += currentState.dy;
- currentPath.push('L ' + f2(x * currentState.scale) + ' ' + f2(y * currentState.scale));
-
- if (autoAntiAlias)
- {
- if (lastPoint != null && currentPathIsOrthogonal && x != lastPoint.x && y != lastPoint.y)
- {
- currentPathIsOrthogonal = false;
- }
-
- lastPoint = new mxPoint(x, y);
- }
- }
- },
-
- /**
- * Function: quadTo
- *
- * Adds a quadratic curve to the current path.
- */
- quadTo: function(x1, y1, x2, y2)
- {
- if (currentPath != null)
- {
- x1 += currentState.dx;
- y1 += currentState.dy;
- x2 += currentState.dx;
- y2 += currentState.dy;
- currentPath.push('Q ' + f2(x1 * currentState.scale) + ' ' + f2(y1 * currentState.scale) +
- ' ' + f2(x2 * currentState.scale) + ' ' + f2(y2 * currentState.scale));
- currentPathIsOrthogonal = false;
- }
- },
-
- /**
- * Function: curveTo
- *
- * Adds a bezier curve to the current path.
- */
- curveTo: function(x1, y1, x2, y2, x3, y3)
- {
- if (currentPath != null)
- {
- x1 += currentState.dx;
- y1 += currentState.dy;
- x2 += currentState.dx;
- y2 += currentState.dy;
- x3 += currentState.dx;
- y3 += currentState.dy;
- currentPath.push('C ' + f2(x1 * currentState.scale) + ' ' + f2(y1 * currentState.scale) +
- ' ' + f2(x2 * currentState.scale) + ' ' + f2(y2 * currentState.scale) +' ' +
- f2(x3 * currentState.scale) + ' ' + f2(y3 * currentState.scale));
- currentPathIsOrthogonal = false;
- }
- },
-
- /**
- * Function: close
- *
- * Closes the current path.
- */
- close: function()
- {
- if (currentPath != null)
- {
- currentPath.push('Z');
- }
- },
-
- /**
- * Function: stroke
- *
- * Paints the outline of the current path.
- */
- stroke: function()
- {
- appendNode(currentNode, currentState, false, true);
- },
-
- /**
- * Function: fill
- *
- * Fills the current path.
- */
- fill: function()
- {
- appendNode(currentNode, currentState, true, false);
- },
-
- /**
- * Function: fillstroke
- *
- * Fills and paints the outline of the current path.
- */
- fillAndStroke: function()
- {
- appendNode(currentNode, currentState, true, true);
- },
-
- /**
- * Function: shadow
- *
- * Paints the current path as a shadow of the given color.
- */
- shadow: function(value, filled)
- {
- this.save();
- this.setStrokeColor(value);
-
- if (filled)
- {
- this.setFillColor(value);
- this.fillAndStroke();
- }
- else
- {
- this.stroke();
- }
-
- this.restore();
- },
-
- /**
- * Function: clip
- *
- * Uses the current path for clipping.
- */
- clip: function()
- {
- if (currentNode != null)
- {
- if (currentPath != null)
- {
- currentNode.setAttribute('d', currentPath.join(' '));
- currentPath = null;
- }
-
- var id = ++refCount;
- var clip = create('clipPath');
- clip.setAttribute('id', id);
- clip.appendChild(currentNode);
- defs.appendChild(clip);
- currentState.clip = id;
- }
- }
- };
-
-}; \ No newline at end of file
diff --git a/src/js/util/mxToolbar.js b/src/js/util/mxToolbar.js
deleted file mode 100644
index 754e6b3..0000000
--- a/src/js/util/mxToolbar.js
+++ /dev/null
@@ -1,528 +0,0 @@
-/**
- * $Id: mxToolbar.js,v 1.36 2012-06-22 11:17:13 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxToolbar
- *
- * Creates a toolbar inside a given DOM node. The toolbar may contain icons,
- * buttons and combo boxes.
- *
- * Event: mxEvent.SELECT
- *
- * Fires when an item was selected in the toolbar. The <code>function</code>
- * property contains the function that was selected in <selectMode>.
- *
- * Constructor: mxToolbar
- *
- * Constructs a toolbar in the specified container.
- *
- * Parameters:
- *
- * container - DOM node that contains the toolbar.
- */
-function mxToolbar(container)
-{
- this.container = container;
-};
-
-/**
- * Extends mxEventSource.
- */
-mxToolbar.prototype = new mxEventSource();
-mxToolbar.prototype.constructor = mxToolbar;
-
-/**
- * Variable: container
- *
- * Reference to the DOM nodes that contains the toolbar.
- */
-mxToolbar.prototype.container = null;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxToolbar.prototype.enabled = true;
-
-/**
- * Variable: noReset
- *
- * Specifies if <resetMode> requires a forced flag of true for resetting
- * the current mode in the toolbar. Default is false. This is set to true
- * if the toolbar item is double clicked to avoid a reset after a single
- * use of the item.
- */
-mxToolbar.prototype.noReset = false;
-
-/**
- * Variable: updateDefaultMode
- *
- * Boolean indicating if the default mode should be the last selected
- * switch mode or the first inserted switch mode. Default is true, that
- * is the last selected switch mode is the default mode. The default mode
- * is the mode to be selected after a reset of the toolbar. If this is
- * false, then the default mode is the first inserted mode item regardless
- * of what was last selected. Otherwise, the selected item after a reset is
- * the previously selected item.
- */
-mxToolbar.prototype.updateDefaultMode = true;
-
-/**
- * Function: addItem
- *
- * Adds the given function as an image with the specified title and icon
- * and returns the new image node.
- *
- * Parameters:
- *
- * title - Optional string that is used as the tooltip.
- * icon - Optional URL of the image to be used. If no URL is given, then a
- * button is created.
- * funct - Function to execute on a mouse click.
- * pressedIcon - Optional URL of the pressed image. Default is a gray
- * background.
- * style - Optional style classname. Default is mxToolbarItem.
- * factoryMethod - Optional factory method for popup menu, eg.
- * function(menu, evt, cell) { menu.addItem('Hello, World!'); }
- */
-mxToolbar.prototype.addItem = function(title, icon, funct, pressedIcon, style, factoryMethod)
-{
- var img = document.createElement((icon != null) ? 'img' : 'button');
- var initialClassName = style || ((factoryMethod != null) ?
- 'mxToolbarMode' : 'mxToolbarItem');
- img.className = initialClassName;
- img.setAttribute('src', icon);
-
- if (title != null)
- {
- if (icon != null)
- {
- img.setAttribute('title', title);
- }
- else
- {
- mxUtils.write(img, title);
- }
- }
-
- this.container.appendChild(img);
-
- // Invokes the function on a click on the toolbar item
- if (funct != null)
- {
- mxEvent.addListener(img, (mxClient.IS_TOUCH) ? 'touchend' : 'click', funct);
- }
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- // Highlights the toolbar item with a gray background
- // while it is being clicked with the mouse
- mxEvent.addListener(img, md, mxUtils.bind(this, function(evt)
- {
- if (pressedIcon != null)
- {
- img.setAttribute('src', pressedIcon);
- }
- else
- {
- img.style.backgroundColor = 'gray';
- }
-
- // Popup Menu
- if (factoryMethod != null)
- {
- if (this.menu == null)
- {
- this.menu = new mxPopupMenu();
- this.menu.init();
- }
-
- var last = this.currentImg;
-
- if (this.menu.isMenuShowing())
- {
- this.menu.hideMenu();
- }
-
- if (last != img)
- {
- // Redirects factory method to local factory method
- this.currentImg = img;
- this.menu.factoryMethod = factoryMethod;
-
- var point = new mxPoint(
- img.offsetLeft,
- img.offsetTop + img.offsetHeight);
- this.menu.popup(point.x, point.y, null, evt);
-
- // Sets and overrides to restore classname
- if (this.menu.isMenuShowing())
- {
- img.className = initialClassName + 'Selected';
-
- this.menu.hideMenu = function()
- {
- mxPopupMenu.prototype.hideMenu.apply(this);
- img.className = initialClassName;
- this.currentImg = null;
- };
- }
- }
- }
- }));
-
- var mouseHandler = mxUtils.bind(this, function(evt)
- {
- if (pressedIcon != null)
- {
- img.setAttribute('src', icon);
- }
- else
- {
- img.style.backgroundColor = '';
- }
- });
-
- mxEvent.addListener(img, mu, mouseHandler);
- mxEvent.addListener(img, 'mouseout', mouseHandler);
-
- return img;
-};
-
-/**
- * Function: addCombo
- *
- * Adds and returns a new SELECT element using the given style. The element
- * is placed inside a DIV with the mxToolbarComboContainer style classname.
- *
- * Parameters:
- *
- * style - Optional style classname. Default is mxToolbarCombo.
- */
-mxToolbar.prototype.addCombo = function(style)
-{
- var div = document.createElement('div');
- div.style.display = 'inline';
- div.className = 'mxToolbarComboContainer';
-
- var select = document.createElement('select');
- select.className = style || 'mxToolbarCombo';
- div.appendChild(select);
-
- this.container.appendChild(div);
-
- return select;
-};
-
-/**
- * Function: addCombo
- *
- * Adds and returns a new SELECT element using the given title as the
- * default element. The selection is reset to this element after each
- * change.
- *
- * Parameters:
- *
- * title - String that specifies the title of the default element.
- * style - Optional style classname. Default is mxToolbarCombo.
- */
-mxToolbar.prototype.addActionCombo = function(title, style)
-{
- var select = document.createElement('select');
- select.className = style || 'mxToolbarCombo';
-
- this.addOption(select, title, null);
-
- mxEvent.addListener(select, 'change', function(evt)
- {
- var value = select.options[select.selectedIndex];
- select.selectedIndex = 0;
- if (value.funct != null)
- {
- value.funct(evt);
- }
- });
-
- this.container.appendChild(select);
-
- return select;
-};
-
-/**
- * Function: addOption
- *
- * Adds and returns a new OPTION element inside the given SELECT element.
- * If the given value is a function then it is stored in the option's funct
- * field.
- *
- * Parameters:
- *
- * combo - SELECT element that will contain the new entry.
- * title - String that specifies the title of the option.
- * value - Specifies the value associated with this option.
- */
-mxToolbar.prototype.addOption = function(combo, title, value)
-{
- var option = document.createElement('option');
- mxUtils.writeln(option, title);
-
- if (typeof(value) == 'function')
- {
- option.funct = value;
- }
- else
- {
- option.setAttribute('value', value);
- }
-
- combo.appendChild(option);
-
- return option;
-};
-
-/**
- * Function: addSwitchMode
- *
- * Adds a new selectable item to the toolbar. Only one switch mode item may
- * be selected at a time. The currently selected item is the default item
- * after a reset of the toolbar.
- */
-mxToolbar.prototype.addSwitchMode = function(title, icon, funct, pressedIcon, style)
-{
- var img = document.createElement('img');
- img.initialClassName = style || 'mxToolbarMode';
- img.className = img.initialClassName;
- img.setAttribute('src', icon);
- img.altIcon = pressedIcon;
-
- if (title != null)
- {
- img.setAttribute('title', title);
- }
-
- mxEvent.addListener(img, 'click', mxUtils.bind(this, function(evt)
- {
- var tmp = this.selectedMode.altIcon;
-
- if (tmp != null)
- {
- this.selectedMode.altIcon = this.selectedMode.getAttribute('src');
- this.selectedMode.setAttribute('src', tmp);
- }
- else
- {
- this.selectedMode.className = this.selectedMode.initialClassName;
- }
-
- if (this.updateDefaultMode)
- {
- this.defaultMode = img;
- }
-
- this.selectedMode = img;
-
- var tmp = img.altIcon;
-
- if (tmp != null)
- {
- img.altIcon = img.getAttribute('src');
- img.setAttribute('src', tmp);
- }
- else
- {
- img.className = img.initialClassName+'Selected';
- }
-
- this.fireEvent(new mxEventObject(mxEvent.SELECT));
- funct();
- }));
-
- this.container.appendChild(img);
-
- if (this.defaultMode == null)
- {
- this.defaultMode = img;
-
- // Function should fire only once so
- // do not pass it with the select event
- this.selectMode(img);
- funct();
- }
-
- return img;
-};
-
-/**
- * Function: addMode
- *
- * Adds a new item to the toolbar. The selection is typically reset after
- * the item has been consumed, for example by adding a new vertex to the
- * graph. The reset is not carried out if the item is double clicked.
- *
- * The function argument uses the following signature: funct(evt, cell) where
- * evt is the native mouse event and cell is the cell under the mouse.
- */
-mxToolbar.prototype.addMode = function(title, icon, funct, pressedIcon, style, toggle)
-{
- toggle = (toggle != null) ? toggle : true;
- var img = document.createElement((icon != null) ? 'img' : 'button');
-
- img.initialClassName = style || 'mxToolbarMode';
- img.className = img.initialClassName;
- img.setAttribute('src', icon);
- img.altIcon = pressedIcon;
-
- if (title != null)
- {
- img.setAttribute('title', title);
- }
-
- if (this.enabled && toggle)
- {
- mxEvent.addListener(img, 'click', mxUtils.bind(this, function(evt)
- {
- this.selectMode(img, funct);
- this.noReset = false;
- }));
- mxEvent.addListener(img, 'dblclick',
- mxUtils.bind(this, function(evt)
- {
- this.selectMode(img, funct);
- this.noReset = true;
- })
- );
-
- if (this.defaultMode == null)
- {
- this.defaultMode = img;
- this.defaultFunction = funct;
- this.selectMode(img, funct);
- }
- }
-
- this.container.appendChild(img);
-
- return img;
-};
-
-/**
- * Function: selectMode
- *
- * Resets the state of the previously selected mode and displays the given
- * DOM node as selected. This function fires a select event with the given
- * function as a parameter.
- */
-mxToolbar.prototype.selectMode = function(domNode, funct)
-{
- if (this.selectedMode != domNode)
- {
- if (this.selectedMode != null)
- {
- var tmp = this.selectedMode.altIcon;
-
- if (tmp != null)
- {
- this.selectedMode.altIcon = this.selectedMode.getAttribute('src');
- this.selectedMode.setAttribute('src', tmp);
- }
- else
- {
- this.selectedMode.className = this.selectedMode.initialClassName;
- }
- }
-
- this.selectedMode = domNode;
- var tmp = this.selectedMode.altIcon;
-
- if (tmp != null)
- {
- this.selectedMode.altIcon = this.selectedMode.getAttribute('src');
- this.selectedMode.setAttribute('src', tmp);
- }
- else
- {
- this.selectedMode.className = this.selectedMode.initialClassName+'Selected';
- }
-
- this.fireEvent(new mxEventObject(mxEvent.SELECT, "function", funct));
- }
-};
-
-/**
- * Function: resetMode
- *
- * Selects the default mode and resets the state of the previously selected
- * mode.
- */
-mxToolbar.prototype.resetMode = function(forced)
-{
- if ((forced || !this.noReset) &&
- this.selectedMode != this.defaultMode)
- {
- // The last selected switch mode will be activated
- // so the function was already executed and is
- // no longer required here
- this.selectMode(this.defaultMode, this.defaultFunction);
- }
-};
-
-/**
- * Function: addSeparator
- *
- * Adds the specifies image as a separator.
- *
- * Parameters:
- *
- * icon - URL of the separator icon.
- */
-mxToolbar.prototype.addSeparator = function(icon)
-{
- return this.addItem(null, icon, null);
-};
-
-/**
- * Function: addBreak
- *
- * Adds a break to the container.
- */
-mxToolbar.prototype.addBreak = function()
-{
- mxUtils.br(this.container);
-};
-
-/**
- * Function: addLine
- *
- * Adds a horizontal line to the container.
- */
-mxToolbar.prototype.addLine = function()
-{
- var hr = document.createElement('hr');
-
- hr.style.marginRight = '6px';
- hr.setAttribute('size', '1');
-
- this.container.appendChild(hr);
-};
-
-/**
- * Function: destroy
- *
- * Removes the toolbar and all its associated resources.
- */
-mxToolbar.prototype.destroy = function ()
-{
- mxEvent.release(this.container);
- this.container = null;
- this.defaultMode = null;
- this.defaultFunction = null;
- this.selectedMode = null;
-
- if (this.menu != null)
- {
- this.menu.destroy();
- }
-};
diff --git a/src/js/util/mxUndoManager.js b/src/js/util/mxUndoManager.js
deleted file mode 100644
index 2cb93cb..0000000
--- a/src/js/util/mxUndoManager.js
+++ /dev/null
@@ -1,229 +0,0 @@
-/**
- * $Id: mxUndoManager.js,v 1.30 2011-10-05 06:39:19 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxUndoManager
- *
- * Implements a command history. When changing the graph model, an
- * <mxUndoableChange> object is created at the start of the transaction (when
- * model.beginUpdate is called). All atomic changes are then added to this
- * object until the last model.endUpdate call, at which point the
- * <mxUndoableEdit> is dispatched in an event, and added to the history inside
- * <mxUndoManager>. This is done by an event listener in
- * <mxEditor.installUndoHandler>.
- *
- * Each atomic change of the model is represented by an object (eg.
- * <mxRootChange>, <mxChildChange>, <mxTerminalChange> etc) which contains the
- * complete undo information. The <mxUndoManager> also listens to the
- * <mxGraphView> and stores it's changes to the current root as insignificant
- * undoable changes, so that drilling (step into, step up) is undone.
- *
- * This means when you execute an atomic change on the model, then change the
- * current root on the view and click undo, the change of the root will be
- * undone together with the change of the model so that the display represents
- * the state at which the model was changed. However, these changes are not
- * transmitted for sharing as they do not represent a state change.
- *
- * Example:
- *
- * When adding an undo manager to a graph, make sure to add it
- * to the model and the view as well to maintain a consistent
- * display across multiple undo/redo steps.
- *
- * (code)
- * var undoManager = new mxUndoManager();
- * var listener = function(sender, evt)
- * {
- * undoManager.undoableEditHappened(evt.getProperty('edit'));
- * };
- * graph.getModel().addListener(mxEvent.UNDO, listener);
- * graph.getView().addListener(mxEvent.UNDO, listener);
- * (end)
- *
- * The code creates a function that informs the undoManager
- * of an undoable edit and binds it to the undo event of
- * <mxGraphModel> and <mxGraphView> using
- * <mxEventSource.addListener>.
- *
- * Event: mxEvent.CLEAR
- *
- * Fires after <clear> was invoked. This event has no properties.
- *
- * Event: mxEvent.UNDO
- *
- * Fires afer a significant edit was undone in <undo>. The <code>edit</code>
- * property contains the <mxUndoableEdit> that was undone.
- *
- * Event: mxEvent.REDO
- *
- * Fires afer a significant edit was redone in <redo>. The <code>edit</code>
- * property contains the <mxUndoableEdit> that was redone.
- *
- * Event: mxEvent.ADD
- *
- * Fires after an undoable edit was added to the history. The <code>edit</code>
- * property contains the <mxUndoableEdit> that was added.
- *
- * Constructor: mxUndoManager
- *
- * Constructs a new undo manager with the given history size. If no history
- * size is given, then a default size of 100 steps is used.
- */
-function mxUndoManager(size)
-{
- this.size = (size != null) ? size : 100;
- this.clear();
-};
-
-/**
- * Extends mxEventSource.
- */
-mxUndoManager.prototype = new mxEventSource();
-mxUndoManager.prototype.constructor = mxUndoManager;
-
-/**
- * Variable: size
- *
- * Maximum command history size. 0 means unlimited history. Default is
- * 100.
- */
-mxUndoManager.prototype.size = null;
-
-/**
- * Variable: history
- *
- * Array that contains the steps of the command history.
- */
-mxUndoManager.prototype.history = null;
-
-/**
- * Variable: indexOfNextAdd
- *
- * Index of the element to be added next.
- */
-mxUndoManager.prototype.indexOfNextAdd = 0;
-
-/**
- * Function: isEmpty
- *
- * Returns true if the history is empty.
- */
-mxUndoManager.prototype.isEmpty = function()
-{
- return this.history.length == 0;
-};
-
-/**
- * Function: clear
- *
- * Clears the command history.
- */
-mxUndoManager.prototype.clear = function()
-{
- this.history = [];
- this.indexOfNextAdd = 0;
- this.fireEvent(new mxEventObject(mxEvent.CLEAR));
-};
-
-/**
- * Function: canUndo
- *
- * Returns true if an undo is possible.
- */
-mxUndoManager.prototype.canUndo = function()
-{
- return this.indexOfNextAdd > 0;
-};
-
-/**
- * Function: undo
- *
- * Undoes the last change.
- */
-mxUndoManager.prototype.undo = function()
-{
- while (this.indexOfNextAdd > 0)
- {
- var edit = this.history[--this.indexOfNextAdd];
- edit.undo();
-
- if (edit.isSignificant())
- {
- this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
- break;
- }
- }
-};
-
-/**
- * Function: canRedo
- *
- * Returns true if a redo is possible.
- */
-mxUndoManager.prototype.canRedo = function()
-{
- return this.indexOfNextAdd < this.history.length;
-};
-
-/**
- * Function: redo
- *
- * Redoes the last change.
- */
-mxUndoManager.prototype.redo = function()
-{
- var n = this.history.length;
-
- while (this.indexOfNextAdd < n)
- {
- var edit = this.history[this.indexOfNextAdd++];
- edit.redo();
-
- if (edit.isSignificant())
- {
- this.fireEvent(new mxEventObject(mxEvent.REDO, 'edit', edit));
- break;
- }
- }
-};
-
-/**
- * Function: undoableEditHappened
- *
- * Method to be called to add new undoable edits to the <history>.
- */
-mxUndoManager.prototype.undoableEditHappened = function(undoableEdit)
-{
- this.trim();
-
- if (this.size > 0 &&
- this.size == this.history.length)
- {
- this.history.shift();
- }
-
- this.history.push(undoableEdit);
- this.indexOfNextAdd = this.history.length;
- this.fireEvent(new mxEventObject(mxEvent.ADD, 'edit', undoableEdit));
-};
-
-/**
- * Function: trim
- *
- * Removes all pending steps after <indexOfNextAdd> from the history,
- * invoking die on each edit. This is called from <undoableEditHappened>.
- */
-mxUndoManager.prototype.trim = function()
-{
- if (this.history.length > this.indexOfNextAdd)
- {
- var edits = this.history.splice(this.indexOfNextAdd,
- this.history.length - this.indexOfNextAdd);
-
- for (var i = 0; i < edits.length; i++)
- {
- edits[i].die();
- }
- }
-};
diff --git a/src/js/util/mxUndoableEdit.js b/src/js/util/mxUndoableEdit.js
deleted file mode 100644
index 886c262..0000000
--- a/src/js/util/mxUndoableEdit.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * $Id: mxUndoableEdit.js,v 1.14 2010-09-15 16:58:51 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxUndoableEdit
- *
- * Implements a composite undoable edit.
- *
- * Constructor: mxUndoableEdit
- *
- * Constructs a new undoable edit for the given source.
- */
-function mxUndoableEdit(source, significant)
-{
- this.source = source;
- this.changes = [];
- this.significant = (significant != null) ? significant : true;
-};
-
-/**
- * Variable: source
- *
- * Specifies the source of the edit.
- */
-mxUndoableEdit.prototype.source = null;
-
-/**
- * Variable: changes
- *
- * Array that contains the changes that make up this edit. The changes are
- * expected to either have an undo and redo function, or an execute
- * function. Default is an empty array.
- */
-mxUndoableEdit.prototype.changes = null;
-
-/**
- * Variable: significant
- *
- * Specifies if the undoable change is significant.
- * Default is true.
- */
-mxUndoableEdit.prototype.significant = null;
-
-/**
- * Variable: undone
- *
- * Specifies if this edit has been undone. Default is false.
- */
-mxUndoableEdit.prototype.undone = false;
-
-/**
- * Variable: redone
- *
- * Specifies if this edit has been redone. Default is false.
- */
-mxUndoableEdit.prototype.redone = false;
-
-/**
- * Function: isEmpty
- *
- * Returns true if the this edit contains no changes.
- */
-mxUndoableEdit.prototype.isEmpty = function()
-{
- return this.changes.length == 0;
-};
-
-/**
- * Function: isSignificant
- *
- * Returns <significant>.
- */
-mxUndoableEdit.prototype.isSignificant = function()
-{
- return this.significant;
-};
-
-/**
- * Function: add
- *
- * Adds the specified change to this edit. The change is an object that is
- * expected to either have an undo and redo, or an execute function.
- */
-mxUndoableEdit.prototype.add = function(change)
-{
- this.changes.push(change);
-};
-
-/**
- * Function: notify
- *
- * Hook to notify any listeners of the changes after an <undo> or <redo>
- * has been carried out. This implementation is empty.
- */
-mxUndoableEdit.prototype.notify = function() { };
-
-/**
- * Function: die
- *
- * Hook to free resources after the edit has been removed from the command
- * history. This implementation is empty.
- */
-mxUndoableEdit.prototype.die = function() { };
-
-/**
- * Function: undo
- *
- * Undoes all changes in this edit.
- */
-mxUndoableEdit.prototype.undo = function()
-{
- if (!this.undone)
- {
- var count = this.changes.length;
-
- for (var i = count - 1; i >= 0; i--)
- {
- var change = this.changes[i];
-
- if (change.execute != null)
- {
- change.execute();
- }
- else if (change.undo != null)
- {
- change.undo();
- }
- }
-
- this.undone = true;
- this.redone = false;
- }
-
- this.notify();
-};
-
-/**
- * Function: redo
- *
- * Redoes all changes in this edit.
- */
-mxUndoableEdit.prototype.redo = function()
-{
- if (!this.redone)
- {
- var count = this.changes.length;
-
- for (var i = 0; i < count; i++)
- {
- var change = this.changes[i];
-
- if (change.execute != null)
- {
- change.execute();
- }
- else if (change.redo != null)
- {
- change.redo();
- }
- }
-
- this.undone = false;
- this.redone = true;
- }
-
- this.notify();
-};
diff --git a/src/js/util/mxUrlConverter.js b/src/js/util/mxUrlConverter.js
deleted file mode 100644
index 764767f..0000000
--- a/src/js/util/mxUrlConverter.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * $Id: mxUrlConverter.js,v 1.3 2012-08-24 17:10:41 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- *
- * Class: mxUrlConverter
- *
- * Converts relative and absolute URLs to absolute URLs with protocol and domain.
- */
-var mxUrlConverter = function(root)
-{
- /**
- * Variable: enabled
- *
- * Specifies if the converter is enabled. Default is true.
- */
- var enabled = true;
-
- /**
- * Variable: baseUrl
- *
- * Specifies the base URL to be used as a prefix for relative URLs.
- */
- var baseUrl = null;
-
- /**
- * Variable: baseDomain
- *
- * Specifies the base domain to be used as a prefix for absolute URLs.
- */
- var baseDomain = null;
-
- // Private helper function to update the base URL
- var updateBaseUrl = function()
- {
- baseDomain = location.protocol + '//' + location.host;
- baseUrl = baseDomain + location.pathname;
- var tmp = baseUrl.lastIndexOf('/');
-
- // Strips filename etc
- if (tmp > 0)
- {
- baseUrl = baseUrl.substring(0, tmp + 1);
- }
- };
-
- // Returns public interface
- return {
-
- /**
- * Function: isEnabled
- *
- * Returns <enabled>.
- */
- isEnabled: function()
- {
- return enabled;
- },
-
- /**
- * Function: setEnabled
- *
- * Sets <enabled>.
- */
- setEnabled: function(value)
- {
- enabled = value;
- },
-
- /**
- * Function: getBaseUrl
- *
- * Returns <baseUrl>.
- */
- getBaseUrl: function()
- {
- return baseUrl;
- },
-
- /**
- * Function: setBaseUrl
- *
- * Sets <baseUrl>.
- */
- setBaseUrl: function(value)
- {
- baseUrl = value;
- },
-
- /**
- * Function: getBaseDomain
- *
- * Returns <baseDomain>.
- */
- getBaseDomain: function()
- {
- return baseUrl;
- },
-
- /**
- * Function: setBaseDomain
- *
- * Sets <baseDomain>.
- */
- setBaseDomain: function(value)
- {
- baseUrl = value;
- },
-
- /**
- * Function: convert
- *
- * Converts the given URL to an absolute URL with protol and domain.
- * Relative URLs are first converted to absolute URLs.
- */
- convert: function(url)
- {
- if (enabled && url.indexOf('http://') != 0 && url.indexOf('https://') != 0 && url.indexOf('data:image') != 0)
- {
- if (baseUrl == null)
- {
- updateBaseUrl();
- }
-
- if (url.charAt(0) == '/')
- {
- url = baseDomain + url;
- }
- else
- {
- url = baseUrl + url;
- }
- }
-
- return url;
- }
-
- };
-
-}; \ No newline at end of file
diff --git a/src/js/util/mxUtils.js b/src/js/util/mxUtils.js
deleted file mode 100644
index 34c0318..0000000
--- a/src/js/util/mxUtils.js
+++ /dev/null
@@ -1,3920 +0,0 @@
-/**
- * $Id: mxUtils.js,v 1.297 2012-12-07 19:47:29 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxUtils =
-{
- /**
- * Class: mxUtils
- *
- * A singleton class that provides cross-browser helper methods.
- * This is a global functionality. To access the functions in this
- * class, use the global classname appended by the functionname.
- * You may have to load chrome://global/content/contentAreaUtils.js
- * to disable certain security restrictions in Mozilla for the <open>,
- * <save>, <saveAs> and <copy> function.
- *
- * For example, the following code displays an error message:
- *
- * (code)
- * mxUtils.error('Browser is not supported!', 200, false);
- * (end)
- *
- * Variable: errorResource
- *
- * Specifies the resource key for the title of the error window. If the
- * resource for this key does not exist then the value is used as
- * the title. Default is 'error'.
- */
- errorResource: (mxClient.language != 'none') ? 'error' : '',
-
- /**
- * Variable: closeResource
- *
- * Specifies the resource key for the label of the close button. If the
- * resource for this key does not exist then the value is used as
- * the label. Default is 'close'.
- */
- closeResource: (mxClient.language != 'none') ? 'close' : '',
-
- /**
- * Variable: errorImage
- *
- * Defines the image used for error dialogs.
- */
- errorImage: mxClient.imageBasePath + '/error.gif',
-
- /**
- * Function: removeCursors
- *
- * Removes the cursors from the style of the given DOM node and its
- * descendants.
- *
- * Parameters:
- *
- * element - DOM node to remove the cursor style from.
- */
- removeCursors: function(element)
- {
- if (element.style != null)
- {
- element.style.cursor = '';
- }
-
- var children = element.childNodes;
-
- if (children != null)
- {
- var childCount = children.length;
-
- for (var i = 0; i < childCount; i += 1)
- {
- mxUtils.removeCursors(children[i]);
- }
- }
- },
-
- /**
- * Function: repaintGraph
- *
- * Normally not required, this contains the code to workaround a repaint
- * issue and force a repaint of the graph container in AppleWebKit.
- *
- * Parameters:
- *
- * graph - <mxGraph> to be repainted.
- * pt - <mxPoint> where the dummy element should be placed.
- */
- repaintGraph: function(graph, pt)
- {
- if (mxClient.IS_GC || mxClient.IS_SF || mxClient.IS_OP)
- {
- var c = graph.container;
-
- if (c != null && pt != null && (c.scrollLeft > 0 || c.scrollTop > 0))
- {
- var dummy = document.createElement('div');
- dummy.style.position = 'absolute';
- dummy.style.left = pt.x + 'px';
- dummy.style.top = pt.y + 'px';
- dummy.style.width = '1px';
- dummy.style.height = '1px';
-
- c.appendChild(dummy);
- c.removeChild(dummy);
- }
- }
- },
-
- /**
- * Function: getCurrentStyle
- *
- * Returns the current style of the specified element.
- *
- * Parameters:
- *
- * element - DOM node whose current style should be returned.
- */
- getCurrentStyle: function()
- {
- if (mxClient.IS_IE)
- {
- return function(element)
- {
- return (element != null) ? element.currentStyle : null;
- };
- }
- else
- {
- return function(element)
- {
- return (element != null) ?
- window.getComputedStyle(element, '') :
- null;
- };
- }
- }(),
-
- /**
- * Function: hasScrollbars
- *
- * Returns true if the overflow CSS property of the given node is either
- * scroll or auto.
- *
- * Parameters:
- *
- * node - DOM node whose style should be checked for scrollbars.
- */
- hasScrollbars: function(node)
- {
- var style = mxUtils.getCurrentStyle(node);
-
- return style != null && (style.overflow == 'scroll' || style.overflow == 'auto');
- },
-
- /**
- * Function: bind
- *
- * Returns a wrapper function that locks the execution scope of the given
- * function to the specified scope. Inside funct, the "this" keyword
- * becomes a reference to that scope.
- */
- bind: function(scope, funct)
- {
- return function()
- {
- return funct.apply(scope, arguments);
- };
- },
-
- /**
- * Function: eval
- *
- * Evaluates the given expression using eval and returns the JavaScript
- * object that represents the expression result. Supports evaluation of
- * expressions that define functions and returns the function object for
- * these expressions.
- *
- * Parameters:
- *
- * expr - A string that represents a JavaScript expression.
- */
- eval: function(expr)
- {
- var result = null;
-
- if (expr.indexOf('function') >= 0)
- {
- try
- {
- eval('var _mxJavaScriptExpression='+expr);
- result = _mxJavaScriptExpression;
- // TODO: Use delete here?
- _mxJavaScriptExpression = null;
- }
- catch (e)
- {
- mxLog.warn(e.message + ' while evaluating ' + expr);
- }
- }
- else
- {
- try
- {
- result = eval(expr);
- }
- catch (e)
- {
- mxLog.warn(e.message + ' while evaluating ' + expr);
- }
- }
-
- return result;
- },
-
- /**
- * Function: findNode
- *
- * Returns the first node where attr equals value.
- * This implementation does not use XPath.
- */
- findNode: function(node, attr, value)
- {
- var tmp = node.getAttribute(attr);
-
- if (tmp != null && tmp == value)
- {
- return node;
- }
-
- node = node.firstChild;
-
- while (node != null)
- {
- var result = mxUtils.findNode(node, attr, value);
-
- if (result != null)
- {
- return result;
- }
-
- node = node.nextSibling;
- }
-
- return null;
- },
-
- /**
- * Function: findNodeByAttribute
- *
- * Returns the first node where the given attribute matches the given value.
- *
- * Parameters:
- *
- * node - Root node where the search should start.
- * attr - Name of the attribute to be checked.
- * value - Value of the attribute to match.
- */
- findNodeByAttribute: function()
- {
- // Workaround for missing XPath support in IE9
- if (document.documentMode >= 9)
- {
- return function(node, attr, value)
- {
- var result = null;
-
- if (node != null)
- {
- if (node.nodeType == mxConstants.NODETYPE_ELEMENT && node.getAttribute(attr) == value)
- {
- result = node;
- }
- else
- {
- var child = node.firstChild;
-
- while (child != null && result == null)
- {
- result = mxUtils.findNodeByAttribute(child, attr, value);
- child = child.nextSibling;
- }
- }
- }
-
- return result;
- };
- }
- else if (mxClient.IS_IE)
- {
- return function(node, attr, value)
- {
- if (node == null)
- {
- return null;
- }
- else
- {
- var expr = '//*[@' + attr + '=\'' + value + '\']';
-
- return node.ownerDocument.selectSingleNode(expr);
- }
- };
- }
- else
- {
- return function(node, attr, value)
- {
- if (node == null)
- {
- return null;
- }
- else
- {
- var result = node.ownerDocument.evaluate(
- '//*[@' + attr + '=\'' + value + '\']',
- node.ownerDocument, null,
- XPathResult.ANY_TYPE, null);
-
- return result.iterateNext();
- }
- };
- }
- }(),
-
- /**
- * Function: getFunctionName
- *
- * Returns the name for the given function.
- *
- * Parameters:
- *
- * f - JavaScript object that represents a function.
- */
- getFunctionName: function(f)
- {
- var str = null;
-
- if (f != null)
- {
- if (f.name != null)
- {
- str = f.name;
- }
- else
- {
- var tmp = f.toString();
- var idx1 = 9;
-
- while (tmp.charAt(idx1) == ' ')
- {
- idx1++;
- }
-
- var idx2 = tmp.indexOf('(', idx1);
- str = tmp.substring(idx1, idx2);
- }
- }
-
- return str;
- },
-
- /**
- * Function: indexOf
- *
- * Returns the index of obj in array or -1 if the array does not contains
- * the given object.
- *
- * Parameters:
- *
- * array - Array to check for the given obj.
- * obj - Object to find in the given array.
- */
- indexOf: function(array, obj)
- {
- if (array != null && obj != null)
- {
- for (var i = 0; i < array.length; i++)
- {
- if (array[i] == obj)
- {
- return i;
- }
- }
- }
-
- return -1;
- },
-
- /**
- * Function: remove
- *
- * Removes all occurrences of the given object in the given array or
- * object. If there are multiple occurrences of the object, be they
- * associative or as an array entry, all occurrences are removed from
- * the array or deleted from the object. By removing the object from
- * the array, all elements following the removed element are shifted
- * by one step towards the beginning of the array.
- *
- * The length of arrays is not modified inside this function.
- *
- * Parameters:
- *
- * obj - Object to find in the given array.
- * array - Array to check for the given obj.
- */
- remove: function(obj, array)
- {
- var result = null;
-
- if (typeof(array) == 'object')
- {
- var index = mxUtils.indexOf(array, obj);
-
- while (index >= 0)
- {
- array.splice(index, 1);
- result = obj;
- index = mxUtils.indexOf(array, obj);
- }
- }
-
- for (var key in array)
- {
- if (array[key] == obj)
- {
- delete array[key];
- result = obj;
- }
- }
-
- return result;
- },
-
- /**
- * Function: isNode
- *
- * Returns true if the given value is an XML node with the node name
- * and if the optional attribute has the specified value.
- *
- * This implementation assumes that the given value is a DOM node if the
- * nodeType property is numeric, that is, if isNaN returns false for
- * value.nodeType.
- *
- * Parameters:
- *
- * value - Object that should be examined as a node.
- * nodeName - String that specifies the node name.
- * attributeName - Optional attribute name to check.
- * attributeValue - Optional attribute value to check.
- */
- isNode: function(value, nodeName, attributeName, attributeValue)
- {
- if (value != null && !isNaN(value.nodeType) && (nodeName == null ||
- value.nodeName.toLowerCase() == nodeName.toLowerCase()))
- {
- return attributeName == null ||
- value.getAttribute(attributeName) == attributeValue;
- }
-
- return false;
- },
-
- /**
- * Function: getChildNodes
- *
- * Returns an array of child nodes that are of the given node type.
- *
- * Parameters:
- *
- * node - Parent DOM node to return the children from.
- * nodeType - Optional node type to return. Default is
- * <mxConstants.NODETYPE_ELEMENT>.
- */
- getChildNodes: function(node, nodeType)
- {
- nodeType = nodeType || mxConstants.NODETYPE_ELEMENT;
-
- var children = [];
- var tmp = node.firstChild;
-
- while (tmp != null)
- {
- if (tmp.nodeType == nodeType)
- {
- children.push(tmp);
- }
-
- tmp = tmp.nextSibling;
- }
-
- return children;
- },
-
- /**
- * Function: createXmlDocument
- *
- * Returns a new, empty XML document.
- */
- createXmlDocument: function()
- {
- var doc = null;
-
- if (document.implementation && document.implementation.createDocument)
- {
- doc = document.implementation.createDocument('', '', null);
- }
- else if (window.ActiveXObject)
- {
- doc = new ActiveXObject('Microsoft.XMLDOM');
- }
-
- return doc;
- },
-
- /**
- * Function: parseXml
- *
- * Parses the specified XML string into a new XML document and returns the
- * new document.
- *
- * Example:
- *
- * (code)
- * var doc = mxUtils.parseXml(
- * '<mxGraphModel><root><MyDiagram id="0"><mxCell/></MyDiagram>'+
- * '<MyLayer id="1"><mxCell parent="0" /></MyLayer><MyObject id="2">'+
- * '<mxCell style="strokeColor=blue;fillColor=red" parent="1" vertex="1">'+
- * '<mxGeometry x="10" y="10" width="80" height="30" as="geometry"/>'+
- * '</mxCell></MyObject></root></mxGraphModel>');
- * (end)
- *
- * Parameters:
- *
- * xml - String that contains the XML data.
- */
- parseXml: function()
- {
- if (mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9))
- {
- return function(xml)
- {
- var result = mxUtils.createXmlDocument();
-
- result.async = 'false';
- result.loadXML(xml);
-
- return result;
- };
- }
- else
- {
- return function(xml)
- {
- var parser = new DOMParser();
-
- return parser.parseFromString(xml, 'text/xml');
- };
- }
- }(),
-
- /**
- * Function: clearSelection
- *
- * Clears the current selection in the page.
- */
- clearSelection: function()
- {
- if (document.selection)
- {
- return function()
- {
- document.selection.empty();
- };
- }
- else if (window.getSelection)
- {
- return function()
- {
- window.getSelection().removeAllRanges();
- };
- }
- }(),
-
- /**
- * Function: getPrettyXML
- *
- * Returns a pretty printed string that represents the XML tree for the
- * given node. This method should only be used to print XML for reading,
- * use <getXml> instead to obtain a string for processing.
- *
- * Parameters:
- *
- * node - DOM node to return the XML for.
- * tab - Optional string that specifies the indentation for one level.
- * Default is two spaces.
- * indent - Optional string that represents the current indentation.
- * Default is an empty string.
- */
- getPrettyXml: function(node, tab, indent)
- {
- var result = [];
-
- if (node != null)
- {
- tab = tab || ' ';
- indent = indent || '';
-
- if (node.nodeType == mxConstants.NODETYPE_TEXT)
- {
- result.push(node.nodeValue);
- }
- else
- {
- result.push(indent + '<'+node.nodeName);
-
- // Creates the string with the node attributes
- // and converts all HTML entities in the values
- var attrs = node.attributes;
-
- if (attrs != null)
- {
- for (var i = 0; i < attrs.length; i++)
- {
- var val = mxUtils.htmlEntities(attrs[i].nodeValue);
- result.push(' ' + attrs[i].nodeName +
- '="' + val + '"');
- }
- }
-
- // Recursively creates the XML string for each
- // child nodes and appends it here with an
- // indentation
- var tmp = node.firstChild;
-
- if (tmp != null)
- {
- result.push('>\n');
-
- while (tmp != null)
- {
- result.push(mxUtils.getPrettyXml(
- tmp, tab, indent + tab));
- tmp = tmp.nextSibling;
- }
-
- result.push(indent + '</'+node.nodeName+'>\n');
- }
- else
- {
- result.push('/>\n');
- }
- }
- }
-
- return result.join('');
- },
-
- /**
- * Function: removeWhitespace
- *
- * Removes the sibling text nodes for the given node that only consists
- * of tabs, newlines and spaces.
- *
- * Parameters:
- *
- * node - DOM node whose siblings should be removed.
- * before - Optional boolean that specifies the direction of the traversal.
- */
- removeWhitespace: function(node, before)
- {
- var tmp = (before) ? node.previousSibling : node.nextSibling;
-
- while (tmp != null && tmp.nodeType == mxConstants.NODETYPE_TEXT)
- {
- var next = (before) ? tmp.previousSibling : tmp.nextSibling;
- var text = mxUtils.getTextContent(tmp);
-
- if (mxUtils.trim(text).length == 0)
- {
- tmp.parentNode.removeChild(tmp);
- }
-
- tmp = next;
- }
- },
-
- /**
- * Function: htmlEntities
- *
- * Replaces characters (less than, greater than, newlines and quotes) with
- * their HTML entities in the given string and returns the result.
- *
- * Parameters:
- *
- * s - String that contains the characters to be converted.
- * newline - If newlines should be replaced. Default is true.
- */
- htmlEntities: function(s, newline)
- {
- s = s || '';
-
- s = s.replace(/&/g,'&amp;'); // 38 26
- s = s.replace(/"/g,'&quot;'); // 34 22
- s = s.replace(/\'/g,'&#39;'); // 39 27
- s = s.replace(/</g,'&lt;'); // 60 3C
- s = s.replace(/>/g,'&gt;'); // 62 3E
-
- if (newline == null || newline)
- {
- s = s.replace(/\n/g, '&#xa;');
- }
-
- return s;
- },
-
- /**
- * Function: isVml
- *
- * Returns true if the given node is in the VML namespace.
- *
- * Parameters:
- *
- * node - DOM node whose tag urn should be checked.
- */
- isVml: function(node)
- {
- return node != null && node.tagUrn == 'urn:schemas-microsoft-com:vml';
- },
-
- /**
- * Function: getXml
- *
- * Returns the XML content of the specified node. For Internet Explorer,
- * all \r\n\t[\t]* are removed from the XML string and the remaining \r\n
- * are replaced by \n. All \n are then replaced with linefeed, or &#xa; if
- * no linefeed is defined.
- *
- * Parameters:
- *
- * node - DOM node to return the XML for.
- * linefeed - Optional string that linefeeds are converted into. Default is
- * &#xa;
- */
- getXml: function(node, linefeed)
- {
- var xml = '';
-
- if (node != null)
- {
- xml = node.xml;
-
- if (xml == null)
- {
- if (node.innerHTML)
- {
- xml = node.innerHTML;
- }
- else
- {
- var xmlSerializer = new XMLSerializer();
- xml = xmlSerializer.serializeToString(node);
- }
- }
- else
- {
- xml = xml.replace(/\r\n\t[\t]*/g, '').
- replace(/>\r\n/g, '>').
- replace(/\r\n/g, '\n');
- }
- }
-
- // Replaces linefeeds with HTML Entities.
- linefeed = linefeed || '&#xa;';
- xml = xml.replace(/\n/g, linefeed);
-
- return xml;
- },
-
- /**
- * Function: getTextContent
- *
- * Returns the text content of the specified node.
- *
- * Parameters:
- *
- * node - DOM node to return the text content for.
- */
- getTextContent: function(node)
- {
- var result = '';
-
- if (node != null)
- {
- if (node.firstChild != null)
- {
- node = node.firstChild;
- }
-
- result = node.nodeValue || '';
- }
-
- return result;
- },
-
- /**
- * Function: getInnerHtml
- *
- * Returns the inner HTML for the given node as a string or an empty string
- * if no node was specified. The inner HTML is the text representing all
- * children of the node, but not the node itself.
- *
- * Parameters:
- *
- * node - DOM node to return the inner HTML for.
- */
- getInnerHtml: function()
- {
- if (mxClient.IS_IE)
- {
- return function(node)
- {
- if (node != null)
- {
- return node.innerHTML;
- }
-
- return '';
- };
- }
- else
- {
- return function(node)
- {
- if (node != null)
- {
- var serializer = new XMLSerializer();
- return serializer.serializeToString(node);
- }
-
- return '';
- };
- }
- }(),
-
- /**
- * Function: getOuterHtml
- *
- * Returns the outer HTML for the given node as a string or an empty
- * string if no node was specified. The outer HTML is the text representing
- * all children of the node including the node itself.
- *
- * Parameters:
- *
- * node - DOM node to return the outer HTML for.
- */
- getOuterHtml: function()
- {
- if (mxClient.IS_IE)
- {
- return function(node)
- {
- if (node != null)
- {
- if (node.outerHTML != null)
- {
- return node.outerHTML;
- }
- else
- {
- var tmp = [];
- tmp.push('<'+node.nodeName);
-
- var attrs = node.attributes;
-
- if (attrs != null)
- {
- for (var i = 0; i < attrs.length; i++)
- {
- var value = attrs[i].nodeValue;
-
- if (value != null && value.length > 0)
- {
- tmp.push(' ');
- tmp.push(attrs[i].nodeName);
- tmp.push('="');
- tmp.push(value);
- tmp.push('"');
- }
- }
- }
-
- if (node.innerHTML.length == 0)
- {
- tmp.push('/>');
- }
- else
- {
- tmp.push('>');
- tmp.push(node.innerHTML);
- tmp.push('</'+node.nodeName+'>');
- }
-
- return tmp.join('');
- }
- }
-
- return '';
- };
- }
- else
- {
- return function(node)
- {
- if (node != null)
- {
- var serializer = new XMLSerializer();
- return serializer.serializeToString(node);
- }
-
- return '';
- };
- }
- }(),
-
- /**
- * Function: write
- *
- * Creates a text node for the given string and appends it to the given
- * parent. Returns the text node.
- *
- * Parameters:
- *
- * parent - DOM node to append the text node to.
- * text - String representing the text to be added.
- */
- write: function(parent, text)
- {
- var doc = parent.ownerDocument;
- var node = doc.createTextNode(text);
-
- if (parent != null)
- {
- parent.appendChild(node);
- }
-
- return node;
- },
-
- /**
- * Function: writeln
- *
- * Creates a text node for the given string and appends it to the given
- * parent with an additional linefeed. Returns the text node.
- *
- * Parameters:
- *
- * parent - DOM node to append the text node to.
- * text - String representing the text to be added.
- */
- writeln: function(parent, text)
- {
- var doc = parent.ownerDocument;
- var node = doc.createTextNode(text);
-
- if (parent != null)
- {
- parent.appendChild(node);
- parent.appendChild(document.createElement('br'));
- }
-
- return node;
- },
-
- /**
- * Function: br
- *
- * Appends a linebreak to the given parent and returns the linebreak.
- *
- * Parameters:
- *
- * parent - DOM node to append the linebreak to.
- */
- br: function(parent, count)
- {
- count = count || 1;
- var br = null;
-
- for (var i = 0; i < count; i++)
- {
- if (parent != null)
- {
- br = parent.ownerDocument.createElement('br');
- parent.appendChild(br);
- }
- }
-
- return br;
- },
-
- /**
- * Function: button
- *
- * Returns a new button with the given level and function as an onclick
- * event handler.
- *
- * (code)
- * document.body.appendChild(mxUtils.button('Test', function(evt)
- * {
- * alert('Hello, World!');
- * }));
- * (end)
- *
- * Parameters:
- *
- * label - String that represents the label of the button.
- * funct - Function to be called if the button is pressed.
- * doc - Optional document to be used for creating the button. Default is the
- * current document.
- */
- button: function(label, funct, doc)
- {
- doc = (doc != null) ? doc : document;
-
- var button = doc.createElement('button');
- mxUtils.write(button, label);
-
- mxEvent.addListener(button, 'click', function(evt)
- {
- funct(evt);
- });
-
- return button;
- },
-
- /**
- * Function: para
- *
- * Appends a new paragraph with the given text to the specified parent and
- * returns the paragraph.
- *
- * Parameters:
- *
- * parent - DOM node to append the text node to.
- * text - String representing the text for the new paragraph.
- */
- para: function(parent, text)
- {
- var p = document.createElement('p');
- mxUtils.write(p, text);
-
- if (parent != null)
- {
- parent.appendChild(p);
- }
-
- return p;
- },
-
- /**
- * Function: linkAction
- *
- * Adds a hyperlink to the specified parent that invokes action on the
- * specified editor.
- *
- * Parameters:
- *
- * parent - DOM node to contain the new link.
- * text - String that is used as the link label.
- * editor - <mxEditor> that will execute the action.
- * action - String that defines the name of the action to be executed.
- * pad - Optional left-padding for the link. Default is 0.
- */
- linkAction: function(parent, text, editor, action, pad)
- {
- return mxUtils.link(parent, text, function()
- {
- editor.execute(action);
- }, pad);
- },
-
- /**
- * Function: linkInvoke
- *
- * Adds a hyperlink to the specified parent that invokes the specified
- * function on the editor passing along the specified argument. The
- * function name is the name of a function of the editor instance,
- * not an action name.
- *
- * Parameters:
- *
- * parent - DOM node to contain the new link.
- * text - String that is used as the link label.
- * editor - <mxEditor> instance to execute the function on.
- * functName - String that represents the name of the function.
- * arg - Object that represents the argument to the function.
- * pad - Optional left-padding for the link. Default is 0.
- */
- linkInvoke: function(parent, text, editor, functName, arg, pad)
- {
- return mxUtils.link(parent, text, function()
- {
- editor[functName](arg);
- }, pad);
- },
-
- /**
- * Function: link
- *
- * Adds a hyperlink to the specified parent and invokes the given function
- * when the link is clicked.
- *
- * Parameters:
- *
- * parent - DOM node to contain the new link.
- * text - String that is used as the link label.
- * funct - Function to execute when the link is clicked.
- * pad - Optional left-padding for the link. Default is 0.
- */
- link: function(parent, text, funct, pad)
- {
- var a = document.createElement('span');
-
- a.style.color = 'blue';
- a.style.textDecoration = 'underline';
- a.style.cursor = 'pointer';
-
- if (pad != null)
- {
- a.style.paddingLeft = pad+'px';
- }
-
- mxEvent.addListener(a, 'click', funct);
- mxUtils.write(a, text);
-
- if (parent != null)
- {
- parent.appendChild(a);
- }
-
- return a;
- },
-
- /**
- * Function: fit
- *
- * Makes sure the given node is inside the visible area of the window. This
- * is done by setting the left and top in the style.
- */
- fit: function(node)
- {
- var left = parseInt(node.offsetLeft);
- var width = parseInt(node.offsetWidth);
-
- var b = document.body;
- var d = document.documentElement;
-
- var right = (b.scrollLeft || d.scrollLeft) +
- (b.clientWidth || d.clientWidth);
-
- if (left + width > right)
- {
- node.style.left = Math.max((b.scrollLeft || d.scrollLeft),
- right - width)+'px';
- }
-
- var top = parseInt(node.offsetTop);
- var height = parseInt(node.offsetHeight);
-
- var bottom = (b.scrollTop || d.scrollTop) +
- Math.max(b.clientHeight || 0, d.clientHeight);
-
- if (top + height > bottom)
- {
- node.style.top = Math.max((b.scrollTop || d.scrollTop),
- bottom - height)+'px';
- }
- },
-
- /**
- * Function: open
- *
- * Opens the specified file from the local filesystem and returns the
- * contents of the file as a string. This implementation requires an
- * ActiveX object in IE and special privileges in Firefox. Relative
- * filenames are only supported in IE and will go onto the users'
- * Desktop. You may have to load
- * chrome://global/content/contentAreaUtils.js to disable certain
- * security restrictions in Mozilla for this to work.
- *
- * See known-issues before using this function.
- *
- * Example:
- * (code)
- * var data = mxUtils.open('C:\\temp\\test.txt');
- * mxUtils.alert('Data: '+data);
- * (end)
- *
- * Parameters:
- *
- * filename - String representing the local file name.
- */
- open: function(filename)
- {
- // Requests required privileges in Firefox
- if (mxClient.IS_NS)
- {
- try
- {
- netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
- }
- catch (e)
- {
- mxUtils.alert('Permission to read file denied.');
-
- return '';
- }
-
- var file = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(filename);
-
- if (!file.exists())
- {
- mxUtils.alert('File not found.');
- return '';
- }
-
- var is = Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream);
- is.init(file,0x01, 00004, null);
-
- var sis = Components.classes['@mozilla.org/scriptableinputstream;1'].createInstance(Components.interfaces.nsIScriptableInputStream);
- sis.init(is);
-
- var output = sis.read(sis.available());
-
- return output;
- }
- else
- {
- var activeXObject = new ActiveXObject('Scripting.FileSystemObject');
-
- var newStream = activeXObject.OpenTextFile(filename, 1);
- var text = newStream.readAll();
- newStream.close();
-
- return text;
- }
- },
-
- /**
- * Function: save
- *
- * Saves the specified content in the given file on the local file system.
- * This implementation requires an ActiveX object in IE and special
- * privileges in Firefox. Relative filenames are only supported in IE and
- * will be loaded from the users' Desktop. You may have to load
- * chrome://global/content/contentAreaUtils.js to disable certain
- * security restrictions in Mozilla for this to work.
- *
- * See known-issues before using this function.
- *
- * Example:
- *
- * (code)
- * var data = 'Hello, World!';
- * mxUtils.save('C:\\test.txt', data);
- * (end)
- *
- * Parameters:
- *
- * filename - String representing the local file name.
- */
- save: function(filename, content)
- {
- if (mxClient.IS_NS)
- {
- try
- {
- netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
- }
- catch (e)
- {
- mxUtils.alert('Permission to write file denied.');
- return;
- }
-
- var file = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(filename);
-
- if (!file.exists())
- {
- file.create(0x00, 0644);
- }
-
- var outputStream = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream);
-
- outputStream.init(file, 0x20 | 0x02,00004, null);
- outputStream.write(content, content.length);
- outputStream.flush();
- outputStream.close();
- }
- else
- {
- var fso = new ActiveXObject('Scripting.FileSystemObject');
-
- var file = fso.CreateTextFile(filename, true);
- file.Write(content);
- file.Close();
- }
- },
-
- /**
- * Function: saveAs
- *
- * Saves the specified content by displaying a dialog to save the content
- * as a file on the local filesystem. This implementation does not use an
- * ActiveX object in IE, however, it does require special privileges in
- * Firefox. You may have to load
- * chrome://global/content/contentAreaUtils.js to disable certain
- * security restrictions in Mozilla for this to work.
- *
- * See known-issues before using this function. It is not recommended using
- * this function in production environment as access to the filesystem
- * cannot be guaranteed in Firefox. The following code is used in
- * Firefox to try and enable saving to the filesystem.
- *
- * (code)
- * netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
- * (end)
- *
- * Example:
- *
- * (code)
- * mxUtils.saveAs('Hello, World!');
- * (end)
- *
- * Parameters:
- *
- * content - String representing the file's content.
- */
- saveAs: function(content)
- {
- var iframe = document.createElement('iframe');
- iframe.setAttribute('src', '');
- iframe.style.visibility = 'hidden';
- document.body.appendChild(iframe);
-
- try
- {
- if (mxClient.IS_NS)
- {
- var doc = iframe.contentDocument;
-
- doc.open();
- doc.write(content);
- doc.close();
-
- try
- {
- netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
- // LATER: Remove existing HTML markup in file
- iframe.focus();
- saveDocument(doc);
- }
- catch (e)
- {
- mxUtils.alert('Permission to save document denied.');
- }
- }
- else
- {
- var doc = iframe.contentWindow.document;
- doc.write(content);
- doc.execCommand('SaveAs', false, document.location);
- }
- }
- finally
- {
- document.body.removeChild(iframe);
- }
- },
-
- /**
- * Function: copy
- *
- * Copies the specified content to the local clipboard. This implementation
- * requires special privileges in Firefox. You may have to load
- * chrome://global/content/contentAreaUtils.js to disable certain
- * security restrictions in Mozilla for this to work.
- *
- * Parameters:
- *
- * content - String to be copied to the clipboard.
- */
- copy: function(content)
- {
- if (window.clipboardData)
- {
- window.clipboardData.setData('Text', content);
- }
- else
- {
- netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-
- var clip = Components.classes['@mozilla.org/widget/clipboard;1']
- .createInstance(Components.interfaces.nsIClipboard);
-
- if (!clip)
- {
- return;
- }
-
- var trans = Components.classes['@mozilla.org/widget/transferable;1']
- .createInstance(Components.interfaces.nsITransferable);
-
- if (!trans)
- {
- return;
- }
-
- trans.addDataFlavor('text/unicode');
- var str = Components.classes['@mozilla.org/supports-string;1']
- .createInstance(Components.interfaces.nsISupportsString);
-
- var copytext=content;
- str.data=copytext;
- trans.setTransferData('text/unicode', str, copytext.length*2);
- var clipid=Components.interfaces.nsIClipboard;
-
- clip.setData(trans,null,clipid.kGlobalClipboard);
- }
- },
-
- /**
- * Function: load
- *
- * Loads the specified URL *synchronously* and returns the <mxXmlRequest>.
- * Throws an exception if the file cannot be loaded. See <mxUtils.get> for
- * an asynchronous implementation.
- *
- * Example:
- *
- * (code)
- * try
- * {
- * var req = mxUtils.load(filename);
- * var root = req.getDocumentElement();
- * // Process XML DOM...
- * }
- * catch (ex)
- * {
- * mxUtils.alert('Cannot load '+filename+': '+ex);
- * }
- * (end)
- *
- * Parameters:
- *
- * url - URL to get the data from.
- */
- load: function(url)
- {
- var req = new mxXmlRequest(url, null, 'GET', false);
- req.send();
-
- return req;
- },
-
- /**
- * Function: get
- *
- * Loads the specified URL *asynchronously* and invokes the given functions
- * depending on the request status. Returns the <mxXmlRequest> in use. Both
- * functions take the <mxXmlRequest> as the only parameter. See
- * <mxUtils.load> for a synchronous implementation.
- *
- * Example:
- *
- * (code)
- * mxUtils.get(url, function(req)
- * {
- * var node = req.getDocumentElement();
- * // Process XML DOM...
- * });
- * (end)
- *
- * So for example, to load a diagram into an existing graph model, the
- * following code is used.
- *
- * (code)
- * mxUtils.get(url, function(req)
- * {
- * var node = req.getDocumentElement();
- * var dec = new mxCodec(node.ownerDocument);
- * dec.decode(node, graph.getModel());
- * });
- * (end)
- *
- * Parameters:
- *
- * url - URL to get the data from.
- * onload - Optional function to execute for a successful response.
- * onerror - Optional function to execute on error.
- */
- get: function(url, onload, onerror)
- {
- return new mxXmlRequest(url, null, 'GET').send(onload, onerror);
- },
-
- /**
- * Function: post
- *
- * Posts the specified params to the given URL *asynchronously* and invokes
- * the given functions depending on the request status. Returns the
- * <mxXmlRequest> in use. Both functions take the <mxXmlRequest> as the
- * only parameter. Make sure to use encodeURIComponent for the parameter
- * values.
- *
- * Example:
- *
- * (code)
- * mxUtils.post(url, 'key=value', function(req)
- * {
- * mxUtils.alert('Ready: '+req.isReady()+' Status: '+req.getStatus());
- * // Process req.getDocumentElement() using DOM API if OK...
- * });
- * (end)
- *
- * Parameters:
- *
- * url - URL to get the data from.
- * params - Parameters for the post request.
- * onload - Optional function to execute for a successful response.
- * onerror - Optional function to execute on error.
- */
- post: function(url, params, onload, onerror)
- {
- return new mxXmlRequest(url, params).send(onload, onerror);
- },
-
- /**
- * Function: submit
- *
- * Submits the given parameters to the specified URL using
- * <mxXmlRequest.simulate> and returns the <mxXmlRequest>.
- * Make sure to use encodeURIComponent for the parameter
- * values.
- *
- * Parameters:
- *
- * url - URL to get the data from.
- * params - Parameters for the form.
- * doc - Document to create the form in.
- * target - Target to send the form result to.
- */
- submit: function(url, params, doc, target)
- {
- return new mxXmlRequest(url, params).simulate(doc, target);
- },
-
- /**
- * Function: loadInto
- *
- * Loads the specified URL *asynchronously* into the specified document,
- * invoking onload after the document has been loaded. This implementation
- * does not use <mxXmlRequest>, but the document.load method.
- *
- * Parameters:
- *
- * url - URL to get the data from.
- * doc - The document to load the URL into.
- * onload - Function to execute when the URL has been loaded.
- */
- loadInto: function(url, doc, onload)
- {
- if (mxClient.IS_IE)
- {
- doc.onreadystatechange = function ()
- {
- if (doc.readyState == 4)
- {
- onload();
- }
- };
- }
- else
- {
- doc.addEventListener('load', onload, false);
- }
-
- doc.load(url);
- },
-
- /**
- * Function: getValue
- *
- * Returns the value for the given key in the given associative array or
- * the given default value if the value is null.
- *
- * Parameters:
- *
- * array - Associative array that contains the value for the key.
- * key - Key whose value should be returned.
- * defaultValue - Value to be returned if the value for the given
- * key is null.
- */
- getValue: function(array, key, defaultValue)
- {
- var value = (array != null) ? array[key] : null;
-
- if (value == null)
- {
- value = defaultValue;
- }
-
- return value;
- },
-
- /**
- * Function: getNumber
- *
- * Returns the numeric value for the given key in the given associative
- * array or the given default value (or 0) if the value is null. The value
- * is converted to a numeric value using the Number function.
- *
- * Parameters:
- *
- * array - Associative array that contains the value for the key.
- * key - Key whose value should be returned.
- * defaultValue - Value to be returned if the value for the given
- * key is null. Default is 0.
- */
- getNumber: function(array, key, defaultValue)
- {
- var value = (array != null) ? array[key] : null;
-
- if (value == null)
- {
- value = defaultValue || 0;
- }
-
- return Number(value);
- },
-
- /**
- * Function: getColor
- *
- * Returns the color value for the given key in the given associative
- * array or the given default value if the value is null. If the value
- * is <mxConstants.NONE> then null is returned.
- *
- * Parameters:
- *
- * array - Associative array that contains the value for the key.
- * key - Key whose value should be returned.
- * defaultValue - Value to be returned if the value for the given
- * key is null. Default is null.
- */
- getColor: function(array, key, defaultValue)
- {
- var value = (array != null) ? array[key] : null;
-
- if (value == null)
- {
- value = defaultValue;
- }
- else if (value == mxConstants.NONE)
- {
- value = null;
- }
-
- return value;
- },
-
- /**
- * Function: clone
- *
- * Recursively clones the specified object ignoring all fieldnames in the
- * given array of transient fields. <mxObjectIdentity.FIELD_NAME> is always
- * ignored by this function.
- *
- * Parameters:
- *
- * obj - Object to be cloned.
- * transients - Optional array of strings representing the fieldname to be
- * ignored.
- * shallow - Optional boolean argument to specify if a shallow clone should
- * be created, that is, one where all object references are not cloned or,
- * in other words, one where only atomic (strings, numbers) values are
- * cloned. Default is false.
- */
- clone: function(obj, transients, shallow)
- {
- shallow = (shallow != null) ? shallow : false;
- var clone = null;
-
- if (obj != null && typeof(obj.constructor) == 'function')
- {
- clone = new obj.constructor();
-
- for (var i in obj)
- {
- if (i != mxObjectIdentity.FIELD_NAME && (transients == null ||
- mxUtils.indexOf(transients, i) < 0))
- {
- if (!shallow && typeof(obj[i]) == 'object')
- {
- clone[i] = mxUtils.clone(obj[i]);
- }
- else
- {
- clone[i] = obj[i];
- }
- }
- }
- }
-
- return clone;
- },
-
- /**
- * Function: equalPoints
- *
- * Compares all mxPoints in the given lists.
- *
- * Parameters:
- *
- * a - Array of <mxPoints> to be compared.
- * b - Array of <mxPoints> to be compared.
- */
- equalPoints: function(a, b)
- {
- if ((a == null && b != null) || (a != null && b == null) ||
- (a != null && b != null && a.length != b.length))
- {
- return false;
- }
- else if (a != null && b != null)
- {
- for (var i = 0; i < a.length; i++)
- {
- if (a[i] == b[i] || (a[i] != null && !a[i].equals(b[i])))
- {
- return false;
- }
- }
- }
-
- return true;
- },
-
- /**
- * Function: equalEntries
- *
- * Compares all entries in the given dictionaries.
- *
- * Parameters:
- *
- * a - <mxRectangle> to be compared.
- * b - <mxRectangle> to be compared.
- */
- equalEntries: function(a, b)
- {
- if ((a == null && b != null) || (a != null && b == null) ||
- (a != null && b != null && a.length != b.length))
- {
- return false;
- }
- else if (a != null && b != null)
- {
- for (var key in a)
- {
- if (a[key] != b[key])
- {
- return false;
- }
- }
- }
-
- return true;
- },
-
- /**
- * Function: extend
- *
- * Assigns a copy of the superclass prototype to the subclass prototype.
- * Note that this does not call the constructor of the superclass at this
- * point, the superclass constructor should be called explicitely in the
- * subclass constructor. Below is an example.
- *
- * (code)
- * MyGraph = function(container, model, renderHint, stylesheet)
- * {
- * mxGraph.call(this, container, model, renderHint, stylesheet);
- * }
- *
- * mxUtils.extend(MyGraph, mxGraph);
- * (end)
- *
- * Parameters:
- *
- * ctor - Constructor of the subclass.
- * superCtor - Constructor of the superclass.
- */
- extend: function(ctor, superCtor)
- {
- var f = function() {};
- f.prototype = superCtor.prototype;
-
- ctor.prototype = new f();
- ctor.prototype.constructor = ctor;
- },
-
- /**
- * Function: toString
- *
- * Returns a textual representation of the specified object.
- *
- * Parameters:
- *
- * obj - Object to return the string representation for.
- */
- toString: function(obj)
- {
- var output = '';
-
- for (var i in obj)
- {
- try
- {
- if (obj[i] == null)
- {
- output += i + ' = [null]\n';
- }
- else if (typeof(obj[i]) == 'function')
- {
- output += i + ' => [Function]\n';
- }
- else if (typeof(obj[i]) == 'object')
- {
- var ctor = mxUtils.getFunctionName(obj[i].constructor);
- output += i + ' => [' + ctor + ']\n';
- }
- else
- {
- output += i + ' = ' + obj[i] + '\n';
- }
- }
- catch (e)
- {
- output += i + '=' + e.message;
- }
- }
-
- return output;
- },
-
- /**
- * Function: toRadians
- *
- * Converts the given degree to radians.
- */
- toRadians: function(deg)
- {
- return Math.PI * deg / 180;
- },
-
- /**
- * Function: arcToCurves
- *
- * Converts the given arc to a series of curves.
- */
- arcToCurves: function(x0, y0, r1, r2, angle, largeArcFlag, sweepFlag, x, y)
- {
- x -= x0;
- y -= y0;
-
- if (r1 === 0 || r2 === 0)
- {
- return result;
- }
-
- var fS = sweepFlag;
- var psai = angle;
- r1 = Math.abs(r1);
- r2 = Math.abs(r2);
- var ctx = -x / 2;
- var cty = -y / 2;
- var cpsi = Math.cos(psai * Math.PI / 180);
- var spsi = Math.sin(psai * Math.PI / 180);
- var rxd = cpsi * ctx + spsi * cty;
- var ryd = -1 * spsi * ctx + cpsi * cty;
- var rxdd = rxd * rxd;
- var rydd = ryd * ryd;
- var r1x = r1 * r1;
- var r2y = r2 * r2;
- var lamda = rxdd / r1x + rydd / r2y;
- var sds;
-
- if (lamda > 1)
- {
- r1 = Math.sqrt(lamda) * r1;
- r2 = Math.sqrt(lamda) * r2;
- sds = 0;
- }
- else
- {
- var seif = 1;
-
- if (largeArcFlag === fS)
- {
- seif = -1;
- }
-
- sds = seif * Math.sqrt((r1x * r2y - r1x * rydd - r2y * rxdd) / (r1x * rydd + r2y * rxdd));
- }
-
- var txd = sds * r1 * ryd / r2;
- var tyd = -1 * sds * r2 * rxd / r1;
- var tx = cpsi * txd - spsi * tyd + x / 2;
- var ty = spsi * txd + cpsi * tyd + y / 2;
- var rad = Math.atan2((ryd - tyd) / r2, (rxd - txd) / r1) - Math.atan2(0, 1);
- var s1 = (rad >= 0) ? rad : 2 * Math.PI + rad;
- rad = Math.atan2((-ryd - tyd) / r2, (-rxd - txd) / r1) - Math.atan2((ryd - tyd) / r2, (rxd - txd) / r1);
- var dr = (rad >= 0) ? rad : 2 * Math.PI + rad;
-
- if (fS == 0 && dr > 0)
- {
- dr -= 2 * Math.PI;
- }
- else if (fS != 0 && dr < 0)
- {
- dr += 2 * Math.PI;
- }
-
- var sse = dr * 2 / Math.PI;
- var seg = Math.ceil(sse < 0 ? -1 * sse : sse);
- var segr = dr / seg;
- var t = 8/3 * Math.sin(segr / 4) * Math.sin(segr / 4) / Math.sin(segr / 2);
- var cpsir1 = cpsi * r1;
- var cpsir2 = cpsi * r2;
- var spsir1 = spsi * r1;
- var spsir2 = spsi * r2;
- var mc = Math.cos(s1);
- var ms = Math.sin(s1);
- var x2 = -t * (cpsir1 * ms + spsir2 * mc);
- var y2 = -t * (spsir1 * ms - cpsir2 * mc);
- var x3 = 0;
- var y3 = 0;
-
- var result = [];
-
- for (var n = 0; n < seg; ++n)
- {
- s1 += segr;
- mc = Math.cos(s1);
- ms = Math.sin(s1);
-
- x3 = cpsir1 * mc - spsir2 * ms + tx;
- y3 = spsir1 * mc + cpsir2 * ms + ty;
- var dx = -t * (cpsir1 * ms + spsir2 * mc);
- var dy = -t * (spsir1 * ms - cpsir2 * mc);
-
- // CurveTo updates x0, y0 so need to restore it
- var index = n * 6;
- result[index] = Number(x2 + x0);
- result[index + 1] = Number(y2 + y0);
- result[index + 2] = Number(x3 - dx + x0);
- result[index + 3] = Number(y3 - dy + y0);
- result[index + 4] = Number(x3 + x0);
- result[index + 5] = Number(y3 + y0);
-
- x2 = x3 + dx;
- y2 = y3 + dy;
- }
-
- return result;
- },
-
- /**
- * Function: getBoundingBox
- *
- * Returns the bounding box for the rotated rectangle.
- */
- getBoundingBox: function(rect, rotation)
- {
- var result = null;
-
- if (rect != null && rotation != null && rotation != 0)
- {
- var rad = mxUtils.toRadians(rotation);
- var cos = Math.cos(rad);
- var sin = Math.sin(rad);
-
- var cx = new mxPoint(
- rect.x + rect.width / 2,
- rect.y + rect.height / 2);
-
- var p1 = new mxPoint(rect.x, rect.y);
- var p2 = new mxPoint(rect.x + rect.width, rect.y);
- var p3 = new mxPoint(p2.x, rect.y + rect.height);
- var p4 = new mxPoint(rect.x, p3.y);
-
- p1 = mxUtils.getRotatedPoint(p1, cos, sin, cx);
- p2 = mxUtils.getRotatedPoint(p2, cos, sin, cx);
- p3 = mxUtils.getRotatedPoint(p3, cos, sin, cx);
- p4 = mxUtils.getRotatedPoint(p4, cos, sin, cx);
-
- result = new mxRectangle(p1.x, p1.y, 0, 0);
- result.add(new mxRectangle(p2.x, p2.y, 0, 0));
- result.add(new mxRectangle(p3.x, p3.y, 0, 0));
- result.add(new mxRectangle(p4.x, p4.y, 0, 0));
- }
-
- return result;
- },
-
- /**
- * Function: getRotatedPoint
- *
- * Rotates the given point by the given cos and sin.
- */
- getRotatedPoint: function(pt, cos, sin, c)
- {
- c = (c != null) ? c : new mxPoint();
- var x = pt.x - c.x;
- var y = pt.y - c.y;
-
- var x1 = x * cos - y * sin;
- var y1 = y * cos + x * sin;
-
- return new mxPoint(x1 + c.x, y1 + c.y);
- },
-
- /**
- * Returns an integer mask of the port constraints of the given map
- * @param dict the style map to determine the port constraints for
- * @param defaultValue Default value to return if the key is undefined.
- * @return the mask of port constraint directions
- *
- * Parameters:
- *
- * terminal - <mxCelState> that represents the terminal.
- * edge - <mxCellState> that represents the edge.
- * source - Boolean that specifies if the terminal is the source terminal.
- * defaultValue - Default value to be returned.
- */
- getPortConstraints: function(terminal, edge, source, defaultValue)
- {
- var value = mxUtils.getValue(terminal.style, mxConstants.STYLE_PORT_CONSTRAINT, null);
-
- if (value == null)
- {
- return defaultValue;
- }
- else
- {
- var directions = value.toString();
- var returnValue = mxConstants.DIRECTION_MASK_NONE;
-
- if (directions.indexOf(mxConstants.DIRECTION_NORTH) >= 0)
- {
- returnValue |= mxConstants.DIRECTION_MASK_NORTH;
- }
- if (directions.indexOf(mxConstants.DIRECTION_WEST) >= 0)
- {
- returnValue |= mxConstants.DIRECTION_MASK_WEST;
- }
- if (directions.indexOf(mxConstants.DIRECTION_SOUTH) >= 0)
- {
- returnValue |= mxConstants.DIRECTION_MASK_SOUTH;
- }
- if (directions.indexOf(mxConstants.DIRECTION_EAST) >= 0)
- {
- returnValue |= mxConstants.DIRECTION_MASK_EAST;
- }
-
- return returnValue;
- }
- },
-
- /**
- * Function: reversePortConstraints
- *
- * Reverse the port constraint bitmask. For example, north | east
- * becomes south | west
- */
- reversePortConstraints: function(constraint)
- {
- var result = 0;
-
- result = (constraint & mxConstants.DIRECTION_MASK_WEST) << 3;
- result |= (constraint & mxConstants.DIRECTION_MASK_NORTH) << 1;
- result |= (constraint & mxConstants.DIRECTION_MASK_SOUTH) >> 1;
- result |= (constraint & mxConstants.DIRECTION_MASK_EAST) >> 3;
-
- return result;
- },
-
- /**
- * Function: findNearestSegment
- *
- * Finds the index of the nearest segment on the given cell state for
- * the specified coordinate pair.
- */
- findNearestSegment: function(state, x, y)
- {
- var index = -1;
-
- if (state.absolutePoints.length > 0)
- {
- var last = state.absolutePoints[0];
- var min = null;
-
- for (var i = 1; i < state.absolutePoints.length; i++)
- {
- var current = state.absolutePoints[i];
- var dist = mxUtils.ptSegDistSq(last.x, last.y,
- current.x, current.y, x, y);
-
- if (min == null || dist < min)
- {
- min = dist;
- index = i - 1;
- }
-
- last = current;
- }
- }
-
- return index;
- },
-
- /**
- * Function: rectangleIntersectsSegment
- *
- * Returns true if the given rectangle intersects the given segment.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that represents the rectangle.
- * p1 - <mxPoint> that represents the first point of the segment.
- * p2 - <mxPoint> that represents the second point of the segment.
- */
- rectangleIntersectsSegment: function(bounds, p1, p2)
- {
- var top = bounds.y;
- var left = bounds.x;
- var bottom = top + bounds.height;
- var right = left + bounds.width;
-
- // Find min and max X for the segment
- var minX = p1.x;
- var maxX = p2.x;
-
- if (p1.x > p2.x)
- {
- minX = p2.x;
- maxX = p1.x;
- }
-
- // Find the intersection of the segment's and rectangle's x-projections
- if (maxX > right)
- {
- maxX = right;
- }
-
- if (minX < left)
- {
- minX = left;
- }
-
- if (minX > maxX) // If their projections do not intersect return false
- {
- return false;
- }
-
- // Find corresponding min and max Y for min and max X we found before
- var minY = p1.y;
- var maxY = p2.y;
- var dx = p2.x - p1.x;
-
- if (Math.abs(dx) > 0.0000001)
- {
- var a = (p2.y - p1.y) / dx;
- var b = p1.y - a * p1.x;
- minY = a * minX + b;
- maxY = a * maxX + b;
- }
-
- if (minY > maxY)
- {
- var tmp = maxY;
- maxY = minY;
- minY = tmp;
- }
-
- // Find the intersection of the segment's and rectangle's y-projections
- if (maxY > bottom)
- {
- maxY = bottom;
- }
-
- if (minY < top)
- {
- minY = top;
- }
-
- if (minY > maxY) // If Y-projections do not intersect return false
- {
- return false;
- }
-
- return true;
- },
-
- /**
- * Function: contains
- *
- * Returns true if the specified point (x, y) is contained in the given rectangle.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that represents the area.
- * x - X-coordinate of the point.
- * y - Y-coordinate of the point.
- */
- contains: function(bounds, x, y)
- {
- return (bounds.x <= x && bounds.x + bounds.width >= x &&
- bounds.y <= y && bounds.y + bounds.height >= y);
- },
-
- /**
- * Function: intersects
- *
- * Returns true if the two rectangles intersect.
- *
- * Parameters:
- *
- * a - <mxRectangle> to be checked for intersection.
- * b - <mxRectangle> to be checked for intersection.
- */
- intersects: function(a, b)
- {
- var tw = a.width;
- var th = a.height;
- var rw = b.width;
- var rh = b.height;
-
- if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0)
- {
- return false;
- }
-
- var tx = a.x;
- var ty = a.y;
- var rx = b.x;
- var ry = b.y;
-
- rw += rx;
- rh += ry;
- tw += tx;
- th += ty;
-
- return ((rw < rx || rw > tx) &&
- (rh < ry || rh > ty) &&
- (tw < tx || tw > rx) &&
- (th < ty || th > ry));
- },
-
- /**
- * Function: intersects
- *
- * Returns true if the two rectangles intersect.
- *
- * Parameters:
- *
- * a - <mxRectangle> to be checked for intersection.
- * b - <mxRectangle> to be checked for intersection.
- */
- intersectsHotspot: function(state, x, y, hotspot, min, max)
- {
- hotspot = (hotspot != null) ? hotspot : 1;
- min = (min != null) ? min : 0;
- max = (max != null) ? max : 0;
-
- if (hotspot > 0)
- {
- var cx = state.getCenterX();
- var cy = state.getCenterY();
- var w = state.width;
- var h = state.height;
-
- var start = mxUtils.getValue(state.style, mxConstants.STYLE_STARTSIZE) * state.view.scale;
-
- if (start > 0)
- {
- if (mxUtils.getValue(state.style,
- mxConstants.STYLE_HORIZONTAL, true))
- {
- cy = state.y + start / 2;
- h = start;
- }
- else
- {
- cx = state.x + start / 2;
- w = start;
- }
- }
-
- w = Math.max(min, w * hotspot);
- h = Math.max(min, h * hotspot);
-
- if (max > 0)
- {
- w = Math.min(w, max);
- h = Math.min(h, max);
- }
-
- var rect = new mxRectangle(cx - w / 2, cy - h / 2, w, h);
-
- return mxUtils.contains(rect, x, y);
- }
-
- return true;
- },
-
- /**
- * Function: getOffset
- *
- * Returns the offset for the specified container as an <mxPoint>. The
- * offset is the distance from the top left corner of the container to the
- * top left corner of the document.
- *
- * Parameters:
- *
- * container - DOM node to return the offset for.
- * scollOffset - Optional boolean to add the scroll offset of the document.
- * Default is false.
- */
- getOffset: function(container, scrollOffset)
- {
- var offsetLeft = 0;
- var offsetTop = 0;
-
- if (scrollOffset != null && scrollOffset)
- {
- var b = document.body;
- var d = document.documentElement;
- offsetLeft += (b.scrollLeft || d.scrollLeft);
- offsetTop += (b.scrollTop || d.scrollTop);
- }
-
- while (container.offsetParent)
- {
- offsetLeft += container.offsetLeft;
- offsetTop += container.offsetTop;
-
- container = container.offsetParent;
- }
-
- return new mxPoint(offsetLeft, offsetTop);
- },
-
- /**
- * Function: getScrollOrigin
- *
- * Returns the top, left corner of the viewrect as an <mxPoint>.
- */
- getScrollOrigin: function(node)
- {
- var b = document.body;
- var d = document.documentElement;
- var sl = (b.scrollLeft || d.scrollLeft);
- var st = (b.scrollTop || d.scrollTop);
-
- var result = new mxPoint(sl, st);
-
- while (node != null && node != b && node != d)
- {
- if (!isNaN(node.scrollLeft) && !isNaN(node.scrollTop))
- {
- result.x += node.scrollLeft;
- result.y += node.scrollTop;
- }
-
- node = node.parentNode;
- }
-
- return result;
- },
-
- /**
- * Function: convertPoint
- *
- * Converts the specified point (x, y) using the offset of the specified
- * container and returns a new <mxPoint> with the result.
- *
- * Parameters:
- *
- * container - DOM node to use for the offset.
- * x - X-coordinate of the point to be converted.
- * y - Y-coordinate of the point to be converted.
- */
- convertPoint: function(container, x, y)
- {
- var origin = mxUtils.getScrollOrigin(container);
- var offset = mxUtils.getOffset(container);
-
- offset.x -= origin.x;
- offset.y -= origin.y;
-
- return new mxPoint(x - offset.x, y - offset.y);
- },
-
- /**
- * Function: ltrim
- *
- * Strips all whitespaces from the beginning of the string.
- * Without the second parameter, Javascript function will trim these
- * characters:
- *
- * - " " (ASCII 32 (0x20)), an ordinary space
- * - "\t" (ASCII 9 (0x09)), a tab
- * - "\n" (ASCII 10 (0x0A)), a new line (line feed)
- * - "\r" (ASCII 13 (0x0D)), a carriage return
- * - "\0" (ASCII 0 (0x00)), the NUL-byte
- * - "\x0B" (ASCII 11 (0x0B)), a vertical tab
- */
- ltrim: function(str, chars)
- {
- chars = chars || "\\s";
-
- return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
- },
-
- /**
- * Function: rtrim
- *
- * Strips all whitespaces from the end of the string.
- * Without the second parameter, Javascript function will trim these
- * characters:
- *
- * - " " (ASCII 32 (0x20)), an ordinary space
- * - "\t" (ASCII 9 (0x09)), a tab
- * - "\n" (ASCII 10 (0x0A)), a new line (line feed)
- * - "\r" (ASCII 13 (0x0D)), a carriage return
- * - "\0" (ASCII 0 (0x00)), the NUL-byte
- * - "\x0B" (ASCII 11 (0x0B)), a vertical tab
- */
- rtrim: function(str, chars)
- {
- chars = chars || "\\s";
-
- return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
- },
-
- /**
- * Function: trim
- *
- * Strips all whitespaces from both end of the string.
- * Without the second parameter, Javascript function will trim these
- * characters:
- *
- * - " " (ASCII 32 (0x20)), an ordinary space
- * - "\t" (ASCII 9 (0x09)), a tab
- * - "\n" (ASCII 10 (0x0A)), a new line (line feed)
- * - "\r" (ASCII 13 (0x0D)), a carriage return
- * - "\0" (ASCII 0 (0x00)), the NUL-byte
- * - "\x0B" (ASCII 11 (0x0B)), a vertical tab
- */
- trim: function(str, chars)
- {
- return mxUtils.ltrim(mxUtils.rtrim(str, chars), chars);
- },
-
- /**
- * Function: isNumeric
- *
- * Returns true if the specified value is numeric, that is, if it is not
- * null, not an empty string, not a HEX number and isNaN returns false.
- *
- * Parameters:
- *
- * str - String representing the possibly numeric value.
- */
- isNumeric: function(str)
- {
- return str != null && (str.length == null || (str.length > 0 &&
- str.indexOf('0x') < 0) && str.indexOf('0X') < 0) && !isNaN(str);
- },
-
- /**
- * Function: mod
- *
- * Returns the remainder of division of n by m. You should use this instead
- * of the built-in operation as the built-in operation does not properly
- * handle negative numbers.
- */
- mod: function(n, m)
- {
- return ((n % m) + m) % m;
- },
-
- /**
- * Function: intersection
- *
- * Returns the intersection of two lines as an <mxPoint>.
- *
- * Parameters:
- *
- * x0 - X-coordinate of the first line's startpoint.
- * y0 - X-coordinate of the first line's startpoint.
- * x1 - X-coordinate of the first line's endpoint.
- * y1 - Y-coordinate of the first line's endpoint.
- * x2 - X-coordinate of the second line's startpoint.
- * y2 - Y-coordinate of the second line's startpoint.
- * x3 - X-coordinate of the second line's endpoint.
- * y3 - Y-coordinate of the second line's endpoint.
- */
- intersection: function (x0, y0, x1, y1, x2, y2, x3, y3)
- {
- var denom = ((y3 - y2)*(x1 - x0)) - ((x3 - x2)*(y1 - y0));
- var nume_a = ((x3 - x2)*(y0 - y2)) - ((y3 - y2)*(x0 - x2));
- var nume_b = ((x1 - x0)*(y0 - y2)) - ((y1 - y0)*(x0 - x2));
-
- var ua = nume_a / denom;
- var ub = nume_b / denom;
-
- if(ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0)
- {
- // Get the intersection point
- var intersectionX = x0 + ua*(x1 - x0);
- var intersectionY = y0 + ua*(y1 - y0);
-
- return new mxPoint(intersectionX, intersectionY);
- }
-
- // No intersection
- return null;
- },
-
- /**
- * Function: ptSeqDistSq
- *
- * Returns the square distance between a segment and a point.
- *
- * Parameters:
- *
- * x1 - X-coordinate of the startpoint of the segment.
- * y1 - Y-coordinate of the startpoint of the segment.
- * x2 - X-coordinate of the endpoint of the segment.
- * y2 - Y-coordinate of the endpoint of the segment.
- * px - X-coordinate of the point.
- * py - Y-coordinate of the point.
- */
- ptSegDistSq: function(x1, y1, x2, y2, px, py)
- {
- x2 -= x1;
- y2 -= y1;
-
- px -= x1;
- py -= y1;
-
- var dotprod = px * x2 + py * y2;
- var projlenSq;
-
- if (dotprod <= 0.0)
- {
- projlenSq = 0.0;
- }
- else
- {
- px = x2 - px;
- py = y2 - py;
- dotprod = px * x2 + py * y2;
-
- if (dotprod <= 0.0)
- {
- projlenSq = 0.0;
- }
- else
- {
- projlenSq = dotprod * dotprod / (x2 * x2 + y2 * y2);
- }
- }
-
- var lenSq = px * px + py * py - projlenSq;
-
- if (lenSq < 0)
- {
- lenSq = 0;
- }
-
- return lenSq;
- },
-
- /**
- * Function: relativeCcw
- *
- * Returns 1 if the given point on the right side of the segment, 0 if its
- * on the segment, and -1 if the point is on the left side of the segment.
- *
- * Parameters:
- *
- * x1 - X-coordinate of the startpoint of the segment.
- * y1 - Y-coordinate of the startpoint of the segment.
- * x2 - X-coordinate of the endpoint of the segment.
- * y2 - Y-coordinate of the endpoint of the segment.
- * px - X-coordinate of the point.
- * py - Y-coordinate of the point.
- */
- relativeCcw: function(x1, y1, x2, y2, px, py)
- {
- x2 -= x1;
- y2 -= y1;
- px -= x1;
- py -= y1;
- var ccw = px * y2 - py * x2;
-
- if (ccw == 0.0)
- {
- ccw = px * x2 + py * y2;
-
- if (ccw > 0.0)
- {
- px -= x2;
- py -= y2;
- ccw = px * x2 + py * y2;
-
- if (ccw < 0.0)
- {
- ccw = 0.0;
- }
- }
- }
-
- return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0);
- },
-
- /**
- * Function: animateChanges
- *
- * See <mxEffects.animateChanges>. This is for backwards compatibility and
- * will be removed later.
- */
- animateChanges: function(graph, changes)
- {
- // LATER: Deprecated, remove this function
- mxEffects.animateChanges.apply(this, arguments);
- },
-
- /**
- * Function: cascadeOpacity
- *
- * See <mxEffects.cascadeOpacity>. This is for backwards compatibility and
- * will be removed later.
- */
- cascadeOpacity: function(graph, cell, opacity)
- {
- mxEffects.cascadeOpacity.apply(this, arguments);
- },
-
- /**
- * Function: fadeOut
- *
- * See <mxEffects.fadeOut>. This is for backwards compatibility and
- * will be removed later.
- */
- fadeOut: function(node, from, remove, step, delay, isEnabled)
- {
- mxEffects.fadeOut.apply(this, arguments);
- },
-
- /**
- * Function: setOpacity
- *
- * Sets the opacity of the specified DOM node to the given value in %.
- *
- * Parameters:
- *
- * node - DOM node to set the opacity for.
- * value - Opacity in %. Possible values are between 0 and 100.
- */
- setOpacity: function(node, value)
- {
- if (mxUtils.isVml(node))
- {
- if (value >= 100)
- {
- node.style.filter = null;
- }
- else
- {
- // TODO: Why is the division by 5 needed in VML?
- node.style.filter = 'alpha(opacity=' + (value/5) + ')';
- }
- }
- else if (mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9))
- {
- if (value >= 100)
- {
- node.style.filter = null;
- }
- else
- {
- node.style.filter = 'alpha(opacity=' + value + ')';
- }
- }
- else
- {
- node.style.opacity = (value / 100);
- }
- },
-
- /**
- * Function: createImage
- *
- * Creates and returns an image (IMG node) or VML image (v:image) in IE6 in
- * quirs mode.
- *
- * Parameters:
- *
- * src - URL that points to the image to be displayed.
- */
- createImage: function(src)
- {
- var imageNode = null;
-
- if (mxClient.IS_IE6 && document.compatMode != 'CSS1Compat')
- {
- imageNode = document.createElement('v:image');
- imageNode.setAttribute('src', src);
- imageNode.style.borderStyle = 'none';
- }
- else
- {
- imageNode = document.createElement('img');
- imageNode.setAttribute('src', src);
- imageNode.setAttribute('border', '0');
- }
-
- return imageNode;
- },
-
- /**
- * Function: sortCells
- *
- * Sorts the given cells according to the order in the cell hierarchy.
- * Ascending is optional and defaults to true.
- */
- sortCells: function(cells, ascending)
- {
- ascending = (ascending != null) ? ascending : true;
- var lookup = new mxDictionary();
- cells.sort(function(o1, o2)
- {
- var p1 = lookup.get(o1);
-
- if (p1 == null)
- {
- p1 = mxCellPath.create(o1).split(mxCellPath.PATH_SEPARATOR);
- lookup.put(o1, p1);
- }
-
- var p2 = lookup.get(o2);
-
- if (p2 == null)
- {
- p2 = mxCellPath.create(o2).split(mxCellPath.PATH_SEPARATOR);
- lookup.put(o2, p2);
- }
-
- var comp = mxCellPath.compare(p1, p2);
-
- return (comp == 0) ? 0 : (((comp > 0) == ascending) ? 1 : -1);
- });
-
- return cells;
- },
-
- /**
- * Function: getStylename
- *
- * Returns the stylename in a style of the form [(stylename|key=value);] or
- * an empty string if the given style does not contain a stylename.
- *
- * Parameters:
- *
- * style - String of the form [(stylename|key=value);].
- */
- getStylename: function(style)
- {
- if (style != null)
- {
- var pairs = style.split(';');
- var stylename = pairs[0];
-
- if (stylename.indexOf('=') < 0)
- {
- return stylename;
- }
- }
-
- return '';
- },
-
- /**
- * Function: getStylenames
- *
- * Returns the stylenames in a style of the form [(stylename|key=value);]
- * or an empty array if the given style does not contain any stylenames.
- *
- * Parameters:
- *
- * style - String of the form [(stylename|key=value);].
- */
- getStylenames: function(style)
- {
- var result = [];
-
- if (style != null)
- {
- var pairs = style.split(';');
-
- for (var i = 0; i < pairs.length; i++)
- {
- if (pairs[i].indexOf('=') < 0)
- {
- result.push(pairs[i]);
- }
- }
- }
-
- return result;
- },
-
- /**
- * Function: indexOfStylename
- *
- * Returns the index of the given stylename in the given style. This
- * returns -1 if the given stylename does not occur (as a stylename) in the
- * given style, otherwise it returns the index of the first character.
- */
- indexOfStylename: function(style, stylename)
- {
- if (style != null && stylename != null)
- {
- var tokens = style.split(';');
- var pos = 0;
-
- for (var i = 0; i < tokens.length; i++)
- {
- if (tokens[i] == stylename)
- {
- return pos;
- }
-
- pos += tokens[i].length + 1;
- }
- }
-
- return -1;
- },
-
- /**
- * Function: addStylename
- *
- * Adds the specified stylename to the given style if it does not already
- * contain the stylename.
- */
- addStylename: function(style, stylename)
- {
- if (mxUtils.indexOfStylename(style, stylename) < 0)
- {
- if (style == null)
- {
- style = '';
- }
- else if (style.length > 0 && style.charAt(style.length - 1) != ';')
- {
- style += ';';
- }
-
- style += stylename;
- }
-
- return style;
- },
-
- /**
- * Function: removeStylename
- *
- * Removes all occurrences of the specified stylename in the given style
- * and returns the updated style. Trailing semicolons are not preserved.
- */
- removeStylename: function(style, stylename)
- {
- var result = [];
-
- if (style != null)
- {
- var tokens = style.split(';');
-
- for (var i = 0; i < tokens.length; i++)
- {
- if (tokens[i] != stylename)
- {
- result.push(tokens[i]);
- }
- }
- }
-
- return result.join(';');
- },
-
- /**
- * Function: removeAllStylenames
- *
- * Removes all stylenames from the given style and returns the updated
- * style.
- */
- removeAllStylenames: function(style)
- {
- var result = [];
-
- if (style != null)
- {
- var tokens = style.split(';');
-
- for (var i = 0; i < tokens.length; i++)
- {
- // Keeps the key, value assignments
- if (tokens[i].indexOf('=') >= 0)
- {
- result.push(tokens[i]);
- }
- }
- }
-
- return result.join(';');
- },
-
- /**
- * Function: setCellStyles
- *
- * Assigns the value for the given key in the styles of the given cells, or
- * removes the key from the styles if the value is null.
- *
- * Parameters:
- *
- * model - <mxGraphModel> to execute the transaction in.
- * cells - Array of <mxCells> to be updated.
- * key - Key of the style to be changed.
- * value - New value for the given key.
- */
- setCellStyles: function(model, cells, key, value)
- {
- if (cells != null && cells.length > 0)
- {
- model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- if (cells[i] != null)
- {
- var style = mxUtils.setStyle(
- model.getStyle(cells[i]),
- key, value);
- model.setStyle(cells[i], style);
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
- },
-
- /**
- * Function: setStyle
- *
- * Adds or removes the given key, value pair to the style and returns the
- * new style. If value is null or zero length then the key is removed from
- * the style. This is for cell styles, not for CSS styles.
- *
- * Parameters:
- *
- * style - String of the form [(stylename|key=value);].
- * key - Key of the style to be changed.
- * value - New value for the given key.
- */
- setStyle: function(style, key, value)
- {
- var isValue = value != null && (typeof(value.length) == 'undefined' || value.length > 0);
-
- if (style == null || style.length == 0)
- {
- if (isValue)
- {
- style = key+'='+value;
- }
- }
- else
- {
- var index = style.indexOf(key+'=');
-
- if (index < 0)
- {
- if (isValue)
- {
- var sep = (style.charAt(style.length-1) == ';') ? '' : ';';
- style = style + sep + key+'='+value;
- }
- }
- else
- {
- var tmp = (isValue) ? (key + '=' + value) : '';
- var cont = style.indexOf(';', index);
-
- if (!isValue)
- {
- cont++;
- }
-
- style = style.substring(0, index) + tmp +
- ((cont > index) ? style.substring(cont) : '');
- }
- }
-
- return style;
- },
-
- /**
- * Function: setCellStyleFlags
- *
- * Sets or toggles the flag bit for the given key in the cell's styles.
- * If value is null then the flag is toggled.
- *
- * Example:
- *
- * (code)
- * var cells = graph.getSelectionCells();
- * mxUtils.setCellStyleFlags(graph.model,
- * cells,
- * mxConstants.STYLE_FONTSTYLE,
- * mxConstants.FONT_BOLD);
- * (end)
- *
- * Toggles the bold font style.
- *
- * Parameters:
- *
- * model - <mxGraphModel> that contains the cells.
- * cells - Array of <mxCells> to change the style for.
- * key - Key of the style to be changed.
- * flag - Integer for the bit to be changed.
- * value - Optional boolean value for the flag.
- */
- setCellStyleFlags: function(model, cells, key, flag, value)
- {
- if (cells != null && cells.length > 0)
- {
- model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- if (cells[i] != null)
- {
- var style = mxUtils.setStyleFlag(
- model.getStyle(cells[i]),
- key, flag, value);
- model.setStyle(cells[i], style);
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
- },
-
- /**
- * Function: setStyleFlag
- *
- * Sets or removes the given key from the specified style and returns the
- * new style. If value is null then the flag is toggled.
- *
- * Parameters:
- *
- * style - String of the form [(stylename|key=value);].
- * key - Key of the style to be changed.
- * flag - Integer for the bit to be changed.
- * value - Optional boolean value for the given flag.
- */
- setStyleFlag: function(style, key, flag, value)
- {
- if (style == null || style.length == 0)
- {
- if (value || value == null)
- {
- style = key+'='+flag;
- }
- else
- {
- style = key+'=0';
- }
- }
- else
- {
- var index = style.indexOf(key+'=');
-
- if (index < 0)
- {
- var sep = (style.charAt(style.length-1) == ';') ? '' : ';';
-
- if (value || value == null)
- {
- style = style + sep + key + '=' + flag;
- }
- else
- {
- style = style + sep + key + '=0';
- }
- }
- else
- {
- var cont = style.indexOf(';', index);
- var tmp = '';
-
- if (cont < 0)
- {
- tmp = style.substring(index+key.length+1);
- }
- else
- {
- tmp = style.substring(index+key.length+1, cont);
- }
-
- if (value == null)
- {
- tmp = parseInt(tmp) ^ flag;
- }
- else if (value)
- {
- tmp = parseInt(tmp) | flag;
- }
- else
- {
- tmp = parseInt(tmp) & ~flag;
- }
-
- style = style.substring(0, index) + key + '=' + tmp +
- ((cont >= 0) ? style.substring(cont) : '');
- }
- }
-
- return style;
- },
-
- /**
- * Function: getSizeForString
- *
- * Returns an <mxRectangle> with the size (width and height in pixels) of
- * the given string. The string may contain HTML markup. Newlines should be
- * converted to <br> before calling this method.
- *
- * Example:
- *
- * (code)
- * var label = graph.getLabel(cell).replace(/\n/g, "<br>");
- * var size = graph.getSizeForString(label);
- * (end)
- *
- * Parameters:
- *
- * text - String whose size should be returned.
- * fontSize - Integer that specifies the font size in pixels. Default is
- * <mxConstants.DEFAULT_FONTSIZE>.
- * fontFamily - String that specifies the name of the font family. Default
- * is <mxConstants.DEFAULT_FONTFAMILY>.
- */
- getSizeForString: function(text, fontSize, fontFamily)
- {
- var div = document.createElement('div');
-
- // Sets the font size and family if non-default
- div.style.fontSize = (fontSize || mxConstants.DEFAULT_FONTSIZE) + 'px';
- div.style.fontFamily = fontFamily || mxConstants.DEFAULT_FONTFAMILY;
-
- // Disables block layout and outside wrapping and hides the div
- div.style.position = 'absolute';
- div.style.display = 'inline';
- div.style.visibility = 'hidden';
-
- // Adds the text and inserts into DOM for updating of size
- div.innerHTML = text;
- document.body.appendChild(div);
-
- // Gets the size and removes from DOM
- var size = new mxRectangle(0, 0, div.offsetWidth, div.offsetHeight);
- document.body.removeChild(div);
-
- return size;
- },
-
- /**
- * Function: getViewXml
- */
- getViewXml: function(graph, scale, cells, x0, y0)
- {
- x0 = (x0 != null) ? x0 : 0;
- y0 = (y0 != null) ? y0 : 0;
- scale = (scale != null) ? scale : 1;
-
- if (cells == null)
- {
- var model = graph.getModel();
- cells = [model.getRoot()];
- }
-
- var view = graph.getView();
- var result = null;
-
- // Disables events on the view
- var eventsEnabled = view.isEventsEnabled();
- view.setEventsEnabled(false);
-
- // Workaround for label bounds not taken into account for image export.
- // Creates a temporary draw pane which is used for rendering the text.
- // Text rendering is required for finding the bounds of the labels.
- var drawPane = view.drawPane;
- var overlayPane = view.overlayPane;
-
- if (graph.dialect == mxConstants.DIALECT_SVG)
- {
- view.drawPane = document.createElementNS(mxConstants.NS_SVG, 'g');
- view.canvas.appendChild(view.drawPane);
-
- // Redirects cell overlays into temporary container
- view.overlayPane = document.createElementNS(mxConstants.NS_SVG, 'g');
- view.canvas.appendChild(view.overlayPane);
- }
- else
- {
- view.drawPane = view.drawPane.cloneNode(false);
- view.canvas.appendChild(view.drawPane);
-
- // Redirects cell overlays into temporary container
- view.overlayPane = view.overlayPane.cloneNode(false);
- view.canvas.appendChild(view.overlayPane);
- }
-
- // Resets the translation
- var translate = view.getTranslate();
- view.translate = new mxPoint(x0, y0);
-
- // Creates the temporary cell states in the view
- var temp = new mxTemporaryCellStates(graph.getView(), scale, cells);
-
- try
- {
- var enc = new mxCodec();
- result = enc.encode(graph.getView());
- }
- finally
- {
- temp.destroy();
- view.translate = translate;
- view.canvas.removeChild(view.drawPane);
- view.canvas.removeChild(view.overlayPane);
- view.drawPane = drawPane;
- view.overlayPane = overlayPane;
- view.setEventsEnabled(eventsEnabled);
- }
-
- return result;
- },
-
- /**
- * Function: getScaleForPageCount
- *
- * Returns the scale to be used for printing the graph with the given
- * bounds across the specifies number of pages with the given format. The
- * scale is always computed such that it given the given amount or fewer
- * pages in the print output. See <mxPrintPreview> for an example.
- *
- * Parameters:
- *
- * pageCount - Specifies the number of pages in the print output.
- * graph - <mxGraph> that should be printed.
- * pageFormat - Optional <mxRectangle> that specifies the page format.
- * Default is <mxConstants.PAGE_FORMAT_A4_PORTRAIT>.
- * border - The border along each side of every page.
- */
- getScaleForPageCount: function(pageCount, graph, pageFormat, border)
- {
- if (pageCount < 1)
- {
- // We can't work with less than 1 page, return no scale
- // change
- return 1;
- }
-
- pageFormat = (pageFormat != null) ? pageFormat : mxConstants.PAGE_FORMAT_A4_PORTRAIT;
- border = (border != null) ? border : 0;
-
- var availablePageWidth = pageFormat.width - (border * 2);
- var availablePageHeight = pageFormat.height - (border * 2);
-
- // Work out the number of pages required if the
- // graph is not scaled.
- var graphBounds = graph.getGraphBounds().clone();
- var sc = graph.getView().getScale();
- graphBounds.width /= sc;
- graphBounds.height /= sc;
- var graphWidth = graphBounds.width;
- var graphHeight = graphBounds.height;
-
- var scale = 1;
-
- // The ratio of the width/height for each printer page
- var pageFormatAspectRatio = availablePageWidth / availablePageHeight;
- // The ratio of the width/height for the graph to be printer
- var graphAspectRatio = graphWidth / graphHeight;
-
- // The ratio of horizontal pages / vertical pages for this
- // graph to maintain its aspect ratio on this page format
- var pagesAspectRatio = graphAspectRatio / pageFormatAspectRatio;
-
- // Factor the square root of the page count up and down
- // by the pages aspect ratio to obtain a horizontal and
- // vertical page count that adds up to the page count
- // and has the correct aspect ratio
- var pageRoot = Math.sqrt(pageCount);
- var pagesAspectRatioSqrt = Math.sqrt(pagesAspectRatio);
- var numRowPages = pageRoot * pagesAspectRatioSqrt;
- var numColumnPages = pageRoot / pagesAspectRatioSqrt;
-
- // These value are rarely more than 2 rounding downs away from
- // a total that meets the page count. In cases of one being less
- // than 1 page, the other value can be too high and take more iterations
- // In this case, just change that value to be the page count, since
- // we know the other value is 1
- if (numRowPages < 1 && numColumnPages > pageCount)
- {
- var scaleChange = numColumnPages / pageCount;
- numColumnPages = pageCount;
- numRowPages /= scaleChange;
- }
-
- if (numColumnPages < 1 && numRowPages > pageCount)
- {
- var scaleChange = numRowPages / pageCount;
- numRowPages = pageCount;
- numColumnPages /= scaleChange;
- }
-
- var currentTotalPages = Math.ceil(numRowPages) * Math.ceil(numColumnPages);
-
- var numLoops = 0;
-
- // Iterate through while the rounded up number of pages comes to
- // a total greater than the required number
- while (currentTotalPages > pageCount)
- {
- // Round down the page count (rows or columns) that is
- // closest to its next integer down in percentage terms.
- // i.e. Reduce the page total by reducing the total
- // page area by the least possible amount
-
- var roundRowDownProportion = Math.floor(numRowPages) / numRowPages;
- var roundColumnDownProportion = Math.floor(numColumnPages) / numColumnPages;
-
- // If the round down proportion is, work out the proportion to
- // round down to 1 page less
- if (roundRowDownProportion == 1)
- {
- roundRowDownProportion = Math.floor(numRowPages-1) / numRowPages;
- }
- if (roundColumnDownProportion == 1)
- {
- roundColumnDownProportion = Math.floor(numColumnPages-1) / numColumnPages;
- }
-
- // Check which rounding down is smaller, but in the case of very small roundings
- // try the other dimension instead
- var scaleChange = 1;
-
- // Use the higher of the two values
- if (roundRowDownProportion > roundColumnDownProportion)
- {
- scaleChange = roundRowDownProportion;
- }
- else
- {
- scaleChange = roundColumnDownProportion;
- }
-
- numRowPages = numRowPages * scaleChange;
- numColumnPages = numColumnPages * scaleChange;
- currentTotalPages = Math.ceil(numRowPages) * Math.ceil(numColumnPages);
-
- numLoops++;
-
- if (numLoops > 10)
- {
- break;
- }
- }
-
- // Work out the scale from the number of row pages required
- // The column pages will give the same value
- var posterWidth = availablePageWidth * numRowPages;
- scale = posterWidth / graphWidth;
-
- // Allow for rounding errors
- return scale * 0.99999;
- },
-
- /**
- * Function: show
- *
- * Copies the styles and the markup from the graph's container into the
- * given document and removes all cursor styles. The document is returned.
- *
- * This function should be called from within the document with the graph.
- * If you experience problems with missing stylesheets in IE then try adding
- * the domain to the trusted sites.
- *
- * Parameters:
- *
- * graph - <mxGraph> to be copied.
- * doc - Document where the new graph is created.
- * x0 - X-coordinate of the graph view origin. Default is 0.
- * y0 - Y-coordinate of the graph view origin. Default is 0.
- */
- show: function(graph, doc, x0, y0)
- {
- x0 = (x0 != null) ? x0 : 0;
- y0 = (y0 != null) ? y0 : 0;
-
- if (doc == null)
- {
- var wnd = window.open();
- doc = wnd.document;
- }
- else
- {
- doc.open();
- }
-
- var bounds = graph.getGraphBounds();
- var dx = -bounds.x + x0;
- var dy = -bounds.y + y0;
-
- // Needs a special way of creating the page so that no click is required
- // to refresh the contents after the external CSS styles have been loaded.
- // To avoid a click or programmatic refresh, the styleSheets[].cssText
- // property is copied over from the original document.
- if (mxClient.IS_IE)
- {
- var html = '<html>';
- html += '<head>';
-
- var base = document.getElementsByTagName('base');
-
- for (var i = 0; i < base.length; i++)
- {
- html += base[i].outerHTML;
- }
-
- html += '<style>';
-
- // Copies the stylesheets without having to load them again
- for (var i = 0; i < document.styleSheets.length; i++)
- {
- try
- {
- html += document.styleSheets(i).cssText;
- }
- catch (e)
- {
- // ignore security exception
- }
- }
-
- html += '</style>';
-
- html += '</head>';
- html += '<body>';
-
- // Copies the contents of the graph container
- html += graph.container.innerHTML;
-
- html += '</body>';
- html += '<html>';
-
- doc.writeln(html);
- doc.close();
-
- // Makes sure the inner container is on the top, left
- var node = doc.body.getElementsByTagName('DIV')[0];
-
- if (node != null)
- {
- node.style.position = 'absolute';
- node.style.left = dx + 'px';
- node.style.top = dy + 'px';
- }
- }
- else
- {
- doc.writeln('<html');
- doc.writeln('<head>');
-
- var base = document.getElementsByTagName('base');
-
- for (var i=0; i<base.length; i++)
- {
- doc.writeln(mxUtils.getOuterHtml(base[i]));
- }
-
- var links = document.getElementsByTagName('link');
-
- for (var i=0; i<links.length; i++)
- {
- doc.writeln(mxUtils.getOuterHtml(links[i]));
- }
-
- var styles = document.getElementsByTagName('style');
-
- for (var i=0; i<styles.length; i++)
- {
- doc.writeln(mxUtils.getOuterHtml(styles[i]));
- }
-
- doc.writeln('</head>');
- doc.writeln('</html>');
- doc.close();
-
- // Workaround for FF2 which has no body element in a document where
- // the body has been added using document.write.
- if (doc.body == null)
- {
- doc.documentElement.appendChild(doc.createElement('body'));
- }
-
- // Workaround for missing scrollbars in FF
- doc.body.style.overflow = 'auto';
-
- var node = graph.container.firstChild;
-
- while (node != null)
- {
- var clone = node.cloneNode(true);
- doc.body.appendChild(clone);
- node = node.nextSibling;
- }
-
- // Shifts negative coordinates into visible space
- var node = doc.getElementsByTagName('g')[0];
-
- if (node != null)
- {
- node.setAttribute('transform', 'translate(' + dx + ',' + dy + ')');
-
- // Updates the size of the SVG container
- var root = node.ownerSVGElement;
- root.setAttribute('width', bounds.width + Math.max(bounds.x, 0) + 3);
- root.setAttribute('height', bounds.height + Math.max(bounds.y, 0) + 3);
- }
- }
-
- mxUtils.removeCursors(doc.body);
-
- return doc;
- },
-
- /**
- * Function: printScreen
- *
- * Prints the specified graph using a new window and the built-in print
- * dialog.
- *
- * This function should be called from within the document with the graph.
- *
- * Parameters:
- *
- * graph - <mxGraph> to be printed.
- */
- printScreen: function(graph)
- {
- var wnd = window.open();
- mxUtils.show(graph, wnd.document);
-
- var print = function()
- {
- wnd.focus();
- wnd.print();
- wnd.close();
- };
-
- // Workaround for Google Chrome which needs a bit of a
- // delay in order to render the SVG contents
- if (mxClient.IS_GC)
- {
- wnd.setTimeout(print, 500);
- }
- else
- {
- print();
- }
- },
-
- /**
- * Function: popup
- *
- * Shows the specified text content in a new <mxWindow> or a new browser
- * window if isInternalWindow is false.
- *
- * Parameters:
- *
- * content - String that specifies the text to be displayed.
- * isInternalWindow - Optional boolean indicating if an mxWindow should be
- * used instead of a new browser window. Default is false.
- */
- popup: function(content, isInternalWindow)
- {
- if (isInternalWindow)
- {
- var div = document.createElement('div');
-
- div.style.overflow = 'scroll';
- div.style.width = '636px';
- div.style.height = '460px';
-
- var pre = document.createElement('pre');
- pre.innerHTML = mxUtils.htmlEntities(content, false).
- replace(/\n/g,'<br>').replace(/ /g, '&nbsp;');
-
- div.appendChild(pre);
-
- var w = document.body.clientWidth;
- var h = (document.body.clientHeight || document.documentElement.clientHeight);
- var wnd = new mxWindow('Popup Window', div,
- w/2-320, h/2-240, 640, 480, false, true);
-
- wnd.setClosable(true);
- wnd.setVisible(true);
- }
- else
- {
- // Wraps up the XML content in a textarea
- if (mxClient.IS_NS)
- {
- var wnd = window.open();
- wnd.document.writeln('<pre>'+mxUtils.htmlEntities(content)+'</pre');
- wnd.document.close();
- }
- else
- {
- var wnd = window.open();
- var pre = wnd.document.createElement('pre');
- pre.innerHTML = mxUtils.htmlEntities(content, false).
- replace(/\n/g,'<br>').replace(/ /g, '&nbsp;');
- wnd.document.body.appendChild(pre);
- }
- }
- },
-
- /**
- * Function: alert
- *
- * Displayss the given alert in a new dialog. This implementation uses the
- * built-in alert function. This is used to display validation errors when
- * connections cannot be changed or created.
- *
- * Parameters:
- *
- * message - String specifying the message to be displayed.
- */
- alert: function(message)
- {
- alert(message);
- },
-
- /**
- * Function: prompt
- *
- * Displays the given message in a prompt dialog. This implementation uses
- * the built-in prompt function.
- *
- * Parameters:
- *
- * message - String specifying the message to be displayed.
- * defaultValue - Optional string specifying the default value.
- */
- prompt: function(message, defaultValue)
- {
- return prompt(message, defaultValue);
- },
-
- /**
- * Function: confirm
- *
- * Displays the given message in a confirm dialog. This implementation uses
- * the built-in confirm function.
- *
- * Parameters:
- *
- * message - String specifying the message to be displayed.
- */
- confirm: function(message)
- {
- return confirm(message);
- },
-
- /**
- * Function: error
- *
- * Displays the given error message in a new <mxWindow> of the given width.
- * If close is true then an additional close button is added to the window.
- * The optional icon specifies the icon to be used for the window. Default
- * is <mxUtils.errorImage>.
- *
- * Parameters:
- *
- * message - String specifying the message to be displayed.
- * width - Integer specifying the width of the window.
- * close - Optional boolean indicating whether to add a close button.
- * icon - Optional icon for the window decoration.
- */
- error: function(message, width, close, icon)
- {
- var div = document.createElement('div');
- div.style.padding = '20px';
-
- var img = document.createElement('img');
- img.setAttribute('src', icon || mxUtils.errorImage);
- img.setAttribute('valign', 'bottom');
- img.style.verticalAlign = 'middle';
- div.appendChild(img);
-
- div.appendChild(document.createTextNode('\u00a0')); // &nbsp;
- div.appendChild(document.createTextNode('\u00a0')); // &nbsp;
- div.appendChild(document.createTextNode('\u00a0')); // &nbsp;
- mxUtils.write(div, message);
-
- var w = document.body.clientWidth;
- var h = (document.body.clientHeight || document.documentElement.clientHeight);
- var warn = new mxWindow(mxResources.get(mxUtils.errorResource) ||
- mxUtils.errorResource, div, (w-width)/2, h/4, width, null,
- false, true);
-
- if (close)
- {
- mxUtils.br(div);
-
- var tmp = document.createElement('p');
- var button = document.createElement('button');
-
- if (mxClient.IS_IE)
- {
- button.style.cssText = 'float:right';
- }
- else
- {
- button.setAttribute('style', 'float:right');
- }
-
- mxEvent.addListener(button, 'click', function(evt)
- {
- warn.destroy();
- });
-
- mxUtils.write(button, mxResources.get(mxUtils.closeResource) ||
- mxUtils.closeResource);
-
- tmp.appendChild(button);
- div.appendChild(tmp);
-
- mxUtils.br(div);
-
- warn.setClosable(true);
- }
-
- warn.setVisible(true);
-
- return warn;
- },
-
- /**
- * Function: makeDraggable
- *
- * Configures the given DOM element to act as a drag source for the
- * specified graph. Returns a a new <mxDragSource>. If
- * <mxDragSource.guideEnabled> is enabled then the x and y arguments must
- * be used in funct to match the preview location.
- *
- * Example:
- *
- * (code)
- * var funct = function(graph, evt, cell, x, y)
- * {
- * if (graph.canImportCell(cell))
- * {
- * var parent = graph.getDefaultParent();
- * var vertex = null;
- *
- * graph.getModel().beginUpdate();
- * try
- * {
- * vertex = graph.insertVertex(parent, null, 'Hello', x, y, 80, 30);
- * }
- * finally
- * {
- * graph.getModel().endUpdate();
- * }
- *
- * graph.setSelectionCell(vertex);
- * }
- * }
- *
- * var img = document.createElement('img');
- * img.setAttribute('src', 'editors/images/rectangle.gif');
- * img.style.position = 'absolute';
- * img.style.left = '0px';
- * img.style.top = '0px';
- * img.style.width = '16px';
- * img.style.height = '16px';
- *
- * var dragImage = img.cloneNode(true);
- * dragImage.style.width = '32px';
- * dragImage.style.height = '32px';
- * mxUtils.makeDraggable(img, graph, funct, dragImage);
- * document.body.appendChild(img);
- * (end)
- *
- * Parameters:
- *
- * element - DOM element to make draggable.
- * graphF - <mxGraph> that acts as the drop target or a function that takes a
- * mouse event and returns the current <mxGraph>.
- * funct - Function to execute on a successful drop.
- * dragElement - Optional DOM node to be used for the drag preview.
- * dx - Optional horizontal offset between the cursor and the drag
- * preview.
- * dy - Optional vertical offset between the cursor and the drag
- * preview.
- * autoscroll - Optional boolean that specifies if autoscroll should be
- * used. Default is mxGraph.autoscroll.
- * scalePreview - Optional boolean that specifies if the preview element
- * should be scaled according to the graph scale. If this is true, then
- * the offsets will also be scaled. Default is false.
- * highlightDropTargets - Optional boolean that specifies if dropTargets
- * should be highlighted. Default is true.
- * getDropTarget - Optional function to return the drop target for a given
- * location (x, y). Default is mxGraph.getCellAt.
- */
- makeDraggable: function(element, graphF, funct, dragElement, dx, dy, autoscroll,
- scalePreview, highlightDropTargets, getDropTarget)
- {
- var dragSource = new mxDragSource(element, funct);
- dragSource.dragOffset = new mxPoint((dx != null) ? dx : 0,
- (dy != null) ? dy : mxConstants.TOOLTIP_VERTICAL_OFFSET);
- dragSource.autoscroll = autoscroll;
-
- // Cannot enable this by default. This needs to be enabled in the caller
- // if the funct argument uses the new x- and y-arguments.
- dragSource.setGuidesEnabled(false);
-
- if (highlightDropTargets != null)
- {
- dragSource.highlightDropTargets = highlightDropTargets;
- }
-
- // Overrides function to find drop target cell
- if (getDropTarget != null)
- {
- dragSource.getDropTarget = getDropTarget;
- }
-
- // Overrides function to get current graph
- dragSource.getGraphForEvent = function(evt)
- {
- return (typeof(graphF) == 'function') ? graphF(evt) : graphF;
- };
-
- // Translates switches into dragSource customizations
- if (dragElement != null)
- {
- dragSource.createDragElement = function()
- {
- return dragElement.cloneNode(true);
- };
-
- if (scalePreview)
- {
- dragSource.createPreviewElement = function(graph)
- {
- var elt = dragElement.cloneNode(true);
-
- var w = parseInt(elt.style.width);
- var h = parseInt(elt.style.height);
- elt.style.width = Math.round(w * graph.view.scale) + 'px';
- elt.style.height = Math.round(h * graph.view.scale) + 'px';
-
- return elt;
- };
- }
- }
-
- return dragSource;
- }
-
-};
diff --git a/src/js/util/mxWindow.js b/src/js/util/mxWindow.js
deleted file mode 100644
index e4cbcfc..0000000
--- a/src/js/util/mxWindow.js
+++ /dev/null
@@ -1,1065 +0,0 @@
-/**
- * $Id: mxWindow.js,v 1.67 2012-10-11 17:18:51 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxWindow
- *
- * Basic window inside a document.
- *
- * Examples:
- *
- * Creating a simple window.
- *
- * (code)
- * var tb = document.createElement('div');
- * var wnd = new mxWindow('Title', tb, 100, 100, 200, 200, true, true);
- * wnd.setVisible(true);
- * (end)
- *
- * Creating a window that contains an iframe.
- *
- * (code)
- * var frame = document.createElement('iframe');
- * frame.setAttribute('width', '192px');
- * frame.setAttribute('height', '172px');
- * frame.setAttribute('src', 'http://www.example.com/');
- * frame.style.backgroundColor = 'white';
- *
- * var w = document.body.clientWidth;
- * var h = (document.body.clientHeight || document.documentElement.clientHeight);
- * var wnd = new mxWindow('Title', frame, (w-200)/2, (h-200)/3, 200, 200);
- * wnd.setVisible(true);
- * (end)
- *
- * To limit the movement of a window, eg. to keep it from being moved beyond
- * the top, left corner the following method can be overridden (recommended):
- *
- * (code)
- * wnd.setLocation = function(x, y)
- * {
- * x = Math.max(0, x);
- * y = Math.max(0, y);
- * mxWindow.prototype.setLocation.apply(this, arguments);
- * };
- * (end)
- *
- * Or the following event handler can be used:
- *
- * (code)
- * wnd.addListener(mxEvent.MOVE, function(e)
- * {
- * wnd.setLocation(Math.max(0, wnd.getX()), Math.max(0, wnd.getY()));
- * });
- * (end)
- *
- * Event: mxEvent.MOVE_START
- *
- * Fires before the window is moved. The <code>event</code> property contains
- * the corresponding mouse event.
- *
- * Event: mxEvent.MOVE
- *
- * Fires while the window is being moved. The <code>event</code> property
- * contains the corresponding mouse event.
- *
- * Event: mxEvent.MOVE_END
- *
- * Fires after the window is moved. The <code>event</code> property contains
- * the corresponding mouse event.
- *
- * Event: mxEvent.RESIZE_START
- *
- * Fires before the window is resized. The <code>event</code> property contains
- * the corresponding mouse event.
- *
- * Event: mxEvent.RESIZE
- *
- * Fires while the window is being resized. The <code>event</code> property
- * contains the corresponding mouse event.
- *
- * Event: mxEvent.RESIZE_END
- *
- * Fires after the window is resized. The <code>event</code> property contains
- * the corresponding mouse event.
- *
- * Event: mxEvent.MAXIMIZE
- *
- * Fires after the window is maximized. The <code>event</code> property
- * contains the corresponding mouse event.
- *
- * Event: mxEvent.MINIMIZE
- *
- * Fires after the window is minimized. The <code>event</code> property
- * contains the corresponding mouse event.
- *
- * Event: mxEvent.NORMALIZE
- *
- * Fires after the window is normalized, that is, it returned from
- * maximized or minimized state. The <code>event</code> property contains the
- * corresponding mouse event.
- *
- * Event: mxEvent.ACTIVATE
- *
- * Fires after a window is activated. The <code>previousWindow</code> property
- * contains the previous window. The event sender is the active window.
- *
- * Event: mxEvent.SHOW
- *
- * Fires after the window is shown. This event has no properties.
- *
- * Event: mxEvent.HIDE
- *
- * Fires after the window is hidden. This event has no properties.
- *
- * Event: mxEvent.CLOSE
- *
- * Fires before the window is closed. The <code>event</code> property contains
- * the corresponding mouse event.
- *
- * Event: mxEvent.DESTROY
- *
- * Fires before the window is destroyed. This event has no properties.
- *
- * Constructor: mxWindow
- *
- * Constructs a new window with the given dimension and title to display
- * the specified content. The window elements use the given style as a
- * prefix for the classnames of the respective window elements, namely,
- * the window title and window pane. The respective postfixes are appended
- * to the given stylename as follows:
- *
- * style - Base style for the window.
- * style+Title - Style for the window title.
- * style+Pane - Style for the window pane.
- *
- * The default value for style is mxWindow, resulting in the following
- * classnames for the window elements: mxWindow, mxWindowTitle and
- * mxWindowPane.
- *
- * If replaceNode is given then the window replaces the given DOM node in
- * the document.
- *
- * Parameters:
- *
- * title - String that represents the title of the new window.
- * content - DOM node that is used as the window content.
- * x - X-coordinate of the window location.
- * y - Y-coordinate of the window location.
- * width - Width of the window.
- * height - Optional height of the window. Default is to match the height
- * of the content at the specified width.
- * minimizable - Optional boolean indicating if the window is minimizable.
- * Default is true.
- * movable - Optional boolean indicating if the window is movable. Default
- * is true.
- * replaceNode - Optional DOM node that the window should replace.
- * style - Optional base classname for the window elements. Default is
- * mxWindow.
- */
-function mxWindow(title, content, x, y, width, height, minimizable, movable, replaceNode, style)
-{
- if (content != null)
- {
- minimizable = (minimizable != null) ? minimizable : true;
- this.content = content;
- this.init(x, y, width, height, style);
-
- this.installMaximizeHandler();
- this.installMinimizeHandler();
- this.installCloseHandler();
- this.setMinimizable(minimizable);
- this.setTitle(title);
-
- if (movable == null || movable)
- {
- this.installMoveHandler();
- }
-
- if (replaceNode != null && replaceNode.parentNode != null)
- {
- replaceNode.parentNode.replaceChild(this.div, replaceNode);
- }
- else
- {
- document.body.appendChild(this.div);
- }
- }
-};
-
-/**
- * Extends mxEventSource.
- */
-mxWindow.prototype = new mxEventSource();
-mxWindow.prototype.constructor = mxWindow;
-
-/**
- * Variable: closeImage
- *
- * URL of the image to be used for the close icon in the titlebar.
- */
-mxWindow.prototype.closeImage = mxClient.imageBasePath + '/close.gif';
-
-/**
- * Variable: minimizeImage
- *
- * URL of the image to be used for the minimize icon in the titlebar.
- */
-mxWindow.prototype.minimizeImage = mxClient.imageBasePath + '/minimize.gif';
-
-/**
- * Variable: normalizeImage
- *
- * URL of the image to be used for the normalize icon in the titlebar.
- */
-mxWindow.prototype.normalizeImage = mxClient.imageBasePath + '/normalize.gif';
-
-/**
- * Variable: maximizeImage
- *
- * URL of the image to be used for the maximize icon in the titlebar.
- */
-mxWindow.prototype.maximizeImage = mxClient.imageBasePath + '/maximize.gif';
-
-/**
- * Variable: normalizeImage
- *
- * URL of the image to be used for the resize icon.
- */
-mxWindow.prototype.resizeImage = mxClient.imageBasePath + '/resize.gif';
-
-/**
- * Variable: visible
- *
- * Boolean flag that represents the visible state of the window.
- */
-mxWindow.prototype.visible = false;
-
-/**
- * Variable: content
- *
- * Reference to the DOM node that represents the window content.
- */
-mxWindow.prototype.content = false;
-
-/**
- * Variable: minimumSize
- *
- * <mxRectangle> that specifies the minimum width and height of the window.
- * Default is (50, 40).
- */
-mxWindow.prototype.minimumSize = new mxRectangle(0, 0, 50, 40);
-
-/**
- * Variable: title
- *
- * Reference to the DOM node (TD) that contains the title.
- */
-mxWindow.prototype.title = false;
-
-/**
- * Variable: content
- *
- * Reference to the DOM node that represents the window content.
- */
-mxWindow.prototype.content = false;
-
-/**
- * Variable: destroyOnClose
- *
- * Specifies if the window should be destroyed when it is closed. If this
- * is false then the window is hidden using <setVisible>. Default is true.
- */
-mxWindow.prototype.destroyOnClose = true;
-
-/**
- * Function: init
- *
- * Initializes the DOM tree that represents the window.
- */
-mxWindow.prototype.init = function(x, y, width, height, style)
-{
- style = (style != null) ? style : 'mxWindow';
-
- this.div = document.createElement('div');
- this.div.className = style;
- this.div.style.left = x+'px';
- this.div.style.top = y+'px';
- this.table = document.createElement('table');
- this.table.className = style;
-
- // Workaround for table size problems in FF
- if (width != null)
- {
- if (!mxClient.IS_IE)
- {
- this.div.style.width = width+'px';
- }
-
- this.table.style.width = width+'px';
- }
-
- if (height != null)
- {
- if (!mxClient.IS_IE)
- {
- this.div.style.height = height+'px';
- }
-
- this.table.style.height = height+'px';
- }
-
- // Creates title row
- var tbody = document.createElement('tbody');
- var tr = document.createElement('tr');
-
- this.title = document.createElement('td');
- this.title.className = style+'Title';
- tr.appendChild(this.title);
- tbody.appendChild(tr);
-
- // Creates content row and table cell
- tr = document.createElement('tr');
- this.td = document.createElement('td');
- this.td.className = style+'Pane';
-
- this.contentWrapper = document.createElement('div');
- this.contentWrapper.className = style+'Pane';
- this.contentWrapper.style.width = '100%';
- this.contentWrapper.appendChild(this.content);
-
- // Workaround for div around div restricts height
- // of inner div if outerdiv has hidden overflow
- if (mxClient.IS_IE || this.content.nodeName.toUpperCase() != 'DIV')
- {
- this.contentWrapper.style.height = '100%';
- }
-
- // Puts all content into the DOM
- this.td.appendChild(this.contentWrapper);
- tr.appendChild(this.td);
- tbody.appendChild(tr);
- this.table.appendChild(tbody);
- this.div.appendChild(this.table);
-
- // Puts the window on top of other windows when clicked
- var activator = mxUtils.bind(this, function(evt)
- {
- this.activate();
- });
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- mxEvent.addListener(this.title, md, activator);
- mxEvent.addListener(this.table, md, activator);
-
- this.hide();
-};
-
-/**
- * Function: setTitle
- *
- * Sets the window title to the given string. HTML markup inside the title
- * will be escaped.
- */
-mxWindow.prototype.setTitle = function(title)
-{
- // Removes all text content nodes (normally just one)
- var child = this.title.firstChild;
-
- while (child != null)
- {
- var next = child.nextSibling;
-
- if (child.nodeType == mxConstants.NODETYPE_TEXT)
- {
- child.parentNode.removeChild(child);
- }
-
- child = next;
- }
-
- mxUtils.write(this.title, title || '');
-};
-
-/**
- * Function: setScrollable
- *
- * Sets if the window contents should be scrollable.
- */
-mxWindow.prototype.setScrollable = function(scrollable)
-{
- // Workaround for hang in Presto 2.5.22 (Opera 10.5)
- if (navigator.userAgent.indexOf('Presto/2.5') < 0)
- {
- if (scrollable)
- {
- this.contentWrapper.style.overflow = 'auto';
- }
- else
- {
- this.contentWrapper.style.overflow = 'hidden';
- }
- }
-};
-
-/**
- * Function: activate
- *
- * Puts the window on top of all other windows.
- */
-mxWindow.prototype.activate = function()
-{
- if (mxWindow.activeWindow != this)
- {
- var style = mxUtils.getCurrentStyle(this.getElement());
- var index = (style != null) ? style.zIndex : 3;
-
- if (mxWindow.activeWindow)
- {
- var elt = mxWindow.activeWindow.getElement();
-
- if (elt != null && elt.style != null)
- {
- elt.style.zIndex = index;
- }
- }
-
- var previousWindow = mxWindow.activeWindow;
- this.getElement().style.zIndex = parseInt(index) + 1;
- mxWindow.activeWindow = this;
-
- this.fireEvent(new mxEventObject(mxEvent.ACTIVATE, 'previousWindow', previousWindow));
- }
-};
-
-/**
- * Function: getElement
- *
- * Returuns the outermost DOM node that makes up the window.
- */
-mxWindow.prototype.getElement = function()
-{
- return this.div;
-};
-
-/**
- * Function: fit
- *
- * Makes sure the window is inside the client area of the window.
- */
-mxWindow.prototype.fit = function()
-{
- mxUtils.fit(this.div);
-};
-
-/**
- * Function: isResizable
- *
- * Returns true if the window is resizable.
- */
-mxWindow.prototype.isResizable = function()
-{
- if (this.resize != null)
- {
- return this.resize.style.display != 'none';
- }
-
- return false;
-};
-
-/**
- * Function: setResizable
- *
- * Sets if the window should be resizable.
- */
-mxWindow.prototype.setResizable = function(resizable)
-{
- if (resizable)
- {
- if (this.resize == null)
- {
- this.resize = document.createElement('img');
- this.resize.style.position = 'absolute';
- this.resize.style.bottom = '2px';
- this.resize.style.right = '2px';
-
- this.resize.setAttribute('src', mxClient.imageBasePath + '/resize.gif');
- this.resize.style.cursor = 'nw-resize';
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- mxEvent.addListener(this.resize, md, mxUtils.bind(this, function(evt)
- {
- this.activate();
- var startX = mxEvent.getClientX(evt);
- var startY = mxEvent.getClientY(evt);
- var width = this.div.offsetWidth;
- var height = this.div.offsetHeight;
-
- // Adds a temporary pair of listeners to intercept
- // the gesture event in the document
- var dragHandler = mxUtils.bind(this, function(evt)
- {
- var dx = mxEvent.getClientX(evt) - startX;
- var dy = mxEvent.getClientY(evt) - startY;
-
- this.setSize(width + dx, height + dy);
-
- this.fireEvent(new mxEventObject(mxEvent.RESIZE, 'event', evt));
- mxEvent.consume(evt);
- });
-
- var dropHandler = mxUtils.bind(this, function(evt)
- {
- mxEvent.removeListener(document, mm, dragHandler);
- mxEvent.removeListener(document, mu, dropHandler);
-
- this.fireEvent(new mxEventObject(mxEvent.RESIZE_END, 'event', evt));
- mxEvent.consume(evt);
- });
-
- mxEvent.addListener(document, mm, dragHandler);
- mxEvent.addListener(document, mu, dropHandler);
-
- this.fireEvent(new mxEventObject(mxEvent.RESIZE_START, 'event', evt));
- mxEvent.consume(evt);
- }));
-
- this.div.appendChild(this.resize);
- }
- else
- {
- this.resize.style.display = 'inline';
- }
- }
- else if (this.resize != null)
- {
- this.resize.style.display = 'none';
- }
-};
-
-/**
- * Function: setSize
- *
- * Sets the size of the window.
- */
-mxWindow.prototype.setSize = function(width, height)
-{
- width = Math.max(this.minimumSize.width, width);
- height = Math.max(this.minimumSize.height, height);
-
- // Workaround for table size problems in FF
- if (!mxClient.IS_IE)
- {
- this.div.style.width = width + 'px';
- this.div.style.height = height + 'px';
- }
-
- this.table.style.width = width + 'px';
- this.table.style.height = height + 'px';
-
- if (!mxClient.IS_IE)
- {
- this.contentWrapper.style.height =
- (this.div.offsetHeight - this.title.offsetHeight - 2)+'px';
- }
-};
-
-/**
- * Function: setMinimizable
- *
- * Sets if the window is minimizable.
- */
-mxWindow.prototype.setMinimizable = function(minimizable)
-{
- this.minimize.style.display = (minimizable) ? '' : 'none';
-};
-
-/**
- * Function: getMinimumSize
- *
- * Returns an <mxRectangle> that specifies the size for the minimized window.
- * A width or height of 0 means keep the existing width or height. This
- * implementation returns the height of the window title and keeps the width.
- */
-mxWindow.prototype.getMinimumSize = function()
-{
- return new mxRectangle(0, 0, 0, this.title.offsetHeight);
-};
-
-/**
- * Function: installMinimizeHandler
- *
- * Installs the event listeners required for minimizing the window.
- */
-mxWindow.prototype.installMinimizeHandler = function()
-{
- this.minimize = document.createElement('img');
-
- this.minimize.setAttribute('src', this.minimizeImage);
- this.minimize.setAttribute('align', 'right');
- this.minimize.setAttribute('title', 'Minimize');
- this.minimize.style.cursor = 'pointer';
- this.minimize.style.marginRight = '1px';
- this.minimize.style.display = 'none';
-
- this.title.appendChild(this.minimize);
-
- var minimized = false;
- var maxDisplay = null;
- var height = null;
-
- var funct = mxUtils.bind(this, function(evt)
- {
- this.activate();
-
- if (!minimized)
- {
- minimized = true;
-
- this.minimize.setAttribute('src', this.normalizeImage);
- this.minimize.setAttribute('title', 'Normalize');
- this.contentWrapper.style.display = 'none';
- maxDisplay = this.maximize.style.display;
-
- this.maximize.style.display = 'none';
- height = this.table.style.height;
-
- var minSize = this.getMinimumSize();
-
- if (minSize.height > 0)
- {
- if (!mxClient.IS_IE)
- {
- this.div.style.height = minSize.height + 'px';
- }
-
- this.table.style.height = minSize.height + 'px';
- }
-
- if (minSize.width > 0)
- {
- if (!mxClient.IS_IE)
- {
- this.div.style.width = minSize.width + 'px';
- }
-
- this.table.style.width = minSize.width + 'px';
- }
-
- if (this.resize != null)
- {
- this.resize.style.visibility = 'hidden';
- }
-
- this.fireEvent(new mxEventObject(mxEvent.MINIMIZE, 'event', evt));
- }
- else
- {
- minimized = false;
-
- this.minimize.setAttribute('src', this.minimizeImage);
- this.minimize.setAttribute('title', 'Minimize');
- this.contentWrapper.style.display = ''; // default
- this.maximize.style.display = maxDisplay;
-
- if (!mxClient.IS_IE)
- {
- this.div.style.height = height;
- }
-
- this.table.style.height = height;
-
- if (this.resize != null)
- {
- this.resize.style.visibility = '';
- }
-
- this.fireEvent(new mxEventObject(mxEvent.NORMALIZE, 'event', evt));
- }
-
- mxEvent.consume(evt);
- });
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- mxEvent.addListener(this.minimize, md, funct);
-};
-
-/**
- * Function: setMaximizable
- *
- * Sets if the window is maximizable.
- */
-mxWindow.prototype.setMaximizable = function(maximizable)
-{
- this.maximize.style.display = (maximizable) ? '' : 'none';
-};
-
-/**
- * Function: installMaximizeHandler
- *
- * Installs the event listeners required for maximizing the window.
- */
-mxWindow.prototype.installMaximizeHandler = function()
-{
- this.maximize = document.createElement('img');
-
- this.maximize.setAttribute('src', this.maximizeImage);
- this.maximize.setAttribute('align', 'right');
- this.maximize.setAttribute('title', 'Maximize');
- this.maximize.style.cursor = 'default';
- this.maximize.style.marginLeft = '1px';
- this.maximize.style.cursor = 'pointer';
- this.maximize.style.display = 'none';
-
- this.title.appendChild(this.maximize);
-
- var maximized = false;
- var x = null;
- var y = null;
- var height = null;
- var width = null;
-
- var funct = mxUtils.bind(this, function(evt)
- {
- this.activate();
-
- if (this.maximize.style.display != 'none')
- {
- if (!maximized)
- {
- maximized = true;
-
- this.maximize.setAttribute('src', this.normalizeImage);
- this.maximize.setAttribute('title', 'Normalize');
- this.contentWrapper.style.display = '';
- this.minimize.style.visibility = 'hidden';
-
- // Saves window state
- x = parseInt(this.div.style.left);
- y = parseInt(this.div.style.top);
- height = this.table.style.height;
- width = this.table.style.width;
-
- this.div.style.left = '0px';
- this.div.style.top = '0px';
-
- if (!mxClient.IS_IE)
- {
- this.div.style.height = (document.body.clientHeight-2)+'px';
- this.div.style.width = (document.body.clientWidth-2)+'px';
- }
-
- this.table.style.width = (document.body.clientWidth-2)+'px';
- this.table.style.height = (document.body.clientHeight-2)+'px';
-
- if (this.resize != null)
- {
- this.resize.style.visibility = 'hidden';
- }
-
- if (!mxClient.IS_IE)
- {
- var style = mxUtils.getCurrentStyle(this.contentWrapper);
-
- if (style.overflow == 'auto' || this.resize != null)
- {
- this.contentWrapper.style.height =
- (this.div.offsetHeight - this.title.offsetHeight - 2)+'px';
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.MAXIMIZE, 'event', evt));
- }
- else
- {
- maximized = false;
-
- this.maximize.setAttribute('src', this.maximizeImage);
- this.maximize.setAttribute('title', 'Maximize');
- this.contentWrapper.style.display = '';
- this.minimize.style.visibility = '';
-
- // Restores window state
- this.div.style.left = x+'px';
- this.div.style.top = y+'px';
-
- if (!mxClient.IS_IE)
- {
- this.div.style.height = height;
- this.div.style.width = width;
-
- var style = mxUtils.getCurrentStyle(this.contentWrapper);
-
- if (style.overflow == 'auto' || this.resize != null)
- {
- this.contentWrapper.style.height =
- (this.div.offsetHeight - this.title.offsetHeight - 2)+'px';
- }
- }
-
- this.table.style.height = height;
- this.table.style.width = width;
-
- if (this.resize != null)
- {
- this.resize.style.visibility = '';
- }
-
- this.fireEvent(new mxEventObject(mxEvent.NORMALIZE, 'event', evt));
- }
-
- mxEvent.consume(evt);
- }
- });
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- mxEvent.addListener(this.maximize, md, funct);
- mxEvent.addListener(this.title, 'dblclick', funct);
-};
-
-/**
- * Function: installMoveHandler
- *
- * Installs the event listeners required for moving the window.
- */
-mxWindow.prototype.installMoveHandler = function()
-{
- this.title.style.cursor = 'move';
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- mxEvent.addListener(this.title, md, mxUtils.bind(this, function(evt)
- {
- var startX = mxEvent.getClientX(evt);
- var startY = mxEvent.getClientY(evt);
- var x = this.getX();
- var y = this.getY();
-
- // Adds a temporary pair of listeners to intercept
- // the gesture event in the document
- var dragHandler = mxUtils.bind(this, function(evt)
- {
- var dx = mxEvent.getClientX(evt) - startX;
- var dy = mxEvent.getClientY(evt) - startY;
- this.setLocation(x + dx, y + dy);
- this.fireEvent(new mxEventObject(mxEvent.MOVE, 'event', evt));
- mxEvent.consume(evt);
- });
-
- var dropHandler = mxUtils.bind(this, function(evt)
- {
- mxEvent.removeListener(document, mm, dragHandler);
- mxEvent.removeListener(document, mu, dropHandler);
-
- this.fireEvent(new mxEventObject(mxEvent.MOVE_END, 'event', evt));
- mxEvent.consume(evt);
- });
-
- mxEvent.addListener(document, mm, dragHandler);
- mxEvent.addListener(document, mu, dropHandler);
-
- this.fireEvent(new mxEventObject(mxEvent.MOVE_START, 'event', evt));
- mxEvent.consume(evt);
- }));
-};
-
-/**
- * Function: setLocation
- *
- * Sets the upper, left corner of the window.
- */
- mxWindow.prototype.setLocation = function(x, y)
- {
- this.div.style.left = x + 'px';
- this.div.style.top = y + 'px';
- };
-
-/**
- * Function: getX
- *
- * Returns the current position on the x-axis.
- */
-mxWindow.prototype.getX = function()
-{
- return parseInt(this.div.style.left);
-};
-
-/**
- * Function: getY
- *
- * Returns the current position on the y-axis.
- */
-mxWindow.prototype.getY = function()
-{
- return parseInt(this.div.style.top);
-};
-
-/**
- * Function: installCloseHandler
- *
- * Adds the <closeImage> as a new image node in <closeImg> and installs the
- * <close> event.
- */
-mxWindow.prototype.installCloseHandler = function()
-{
- this.closeImg = document.createElement('img');
-
- this.closeImg.setAttribute('src', this.closeImage);
- this.closeImg.setAttribute('align', 'right');
- this.closeImg.setAttribute('title', 'Close');
- this.closeImg.style.marginLeft = '2px';
- this.closeImg.style.cursor = 'pointer';
- this.closeImg.style.display = 'none';
-
- this.title.insertBefore(this.closeImg, this.title.firstChild);
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- mxEvent.addListener(this.closeImg, md, mxUtils.bind(this, function(evt)
- {
- this.fireEvent(new mxEventObject(mxEvent.CLOSE, 'event', evt));
-
- if (this.destroyOnClose)
- {
- this.destroy();
- }
- else
- {
- this.setVisible(false);
- }
-
- mxEvent.consume(evt);
- }));
-};
-
-/**
- * Function: setImage
- *
- * Sets the image associated with the window.
- *
- * Parameters:
- *
- * image - URL of the image to be used.
- */
-mxWindow.prototype.setImage = function(image)
-{
- this.image = document.createElement('img');
- this.image.setAttribute('src', image);
- this.image.setAttribute('align', 'left');
- this.image.style.marginRight = '4px';
- this.image.style.marginLeft = '0px';
- this.image.style.marginTop = '-2px';
-
- this.title.insertBefore(this.image, this.title.firstChild);
-};
-
-/**
- * Function: setClosable
- *
- * Sets the image associated with the window.
- *
- * Parameters:
- *
- * closable - Boolean specifying if the window should be closable.
- */
-mxWindow.prototype.setClosable = function(closable)
-{
- this.closeImg.style.display = (closable) ? '' : 'none';
-};
-
-/**
- * Function: isVisible
- *
- * Returns true if the window is visible.
- */
-mxWindow.prototype.isVisible = function()
-{
- if (this.div != null)
- {
- return this.div.style.visibility != 'hidden';
- }
-
- return false;
-};
-
-/**
- * Function: setVisible
- *
- * Shows or hides the window depending on the given flag.
- *
- * Parameters:
- *
- * visible - Boolean indicating if the window should be made visible.
- */
-mxWindow.prototype.setVisible = function(visible)
-{
- if (this.div != null && this.isVisible() != visible)
- {
- if (visible)
- {
- this.show();
- }
- else
- {
- this.hide();
- }
- }
-};
-
-/**
- * Function: show
- *
- * Shows the window.
- */
-mxWindow.prototype.show = function()
-{
- this.div.style.visibility = '';
- this.activate();
-
- var style = mxUtils.getCurrentStyle(this.contentWrapper);
-
- if (!mxClient.IS_IE && (style.overflow == 'auto' || this.resize != null))
- {
- this.contentWrapper.style.height =
- (this.div.offsetHeight - this.title.offsetHeight - 2)+'px';
- }
-
- this.fireEvent(new mxEventObject(mxEvent.SHOW));
-};
-
-/**
- * Function: hide
- *
- * Hides the window.
- */
-mxWindow.prototype.hide = function()
-{
- this.div.style.visibility = 'hidden';
- this.fireEvent(new mxEventObject(mxEvent.HIDE));
-};
-
-/**
- * Function: destroy
- *
- * Destroys the window and removes all associated resources. Fires a
- * <destroy> event prior to destroying the window.
- */
-mxWindow.prototype.destroy = function()
-{
- this.fireEvent(new mxEventObject(mxEvent.DESTROY));
-
- if (this.div != null)
- {
- mxEvent.release(this.div);
- this.div.parentNode.removeChild(this.div);
- this.div = null;
- }
-
- this.title = null;
- this.content = null;
- this.contentWrapper = null;
-};
diff --git a/src/js/util/mxXmlCanvas2D.js b/src/js/util/mxXmlCanvas2D.js
deleted file mode 100644
index 499c71a..0000000
--- a/src/js/util/mxXmlCanvas2D.js
+++ /dev/null
@@ -1,715 +0,0 @@
-/**
- * $Id: mxXmlCanvas2D.js,v 1.9 2012-04-24 13:56:56 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- *
- * Class: mxXmlCanvas2D
- *
- * Implements a canvas to be used with <mxImageExport>. This canvas writes all
- * calls as child nodes to the given root XML node.
- *
- * (code)
- * var xmlDoc = mxUtils.createXmlDocument();
- * var root = xmlDoc.createElement('output');
- * xmlDoc.appendChild(root);
- * var xmlCanvas = new mxXmlCanvas2D(root);
- * (end)
- *
- * Constructor: mxXmlCanvas2D
- *
- * Constructs a XML canvas.
- *
- * Parameters:
- *
- * root - XML node for adding child nodes.
- */
-var mxXmlCanvas2D = function(root)
-{
- /**
- * Variable: converter
- *
- * Holds the <mxUrlConverter> to convert image URLs.
- */
- var converter = new mxUrlConverter();
-
- /**
- * Variable: compressed
- *
- * Specifies if the output should be compressed by removing redundant calls.
- * Default is true.
- */
- var compressed = true;
-
- /**
- * Variable: textEnabled
- *
- * Specifies if text output should be enabled. Default is true.
- */
- var textEnabled = true;
-
- // Private reference to the owner document
- var doc = root.ownerDocument;
-
- // Implements stack for save/restore
- var stack = [];
-
- // Implements state for redundancy checks
- var state =
- {
- alpha: 1,
- dashed: false,
- strokewidth: 1,
- fontsize: mxConstants.DEFAULT_FONTSIZE,
- fontfamily: mxConstants.DEFAULT_FONTFAMILY,
- fontcolor: '#000000'
- };
-
- // Private helper function set set precision to 2
- var f2 = function(x)
- {
- return Math.round(parseFloat(x) * 100) / 100;
- };
-
- // Returns public interface
- return {
-
- /**
- * Function: getConverter
- *
- * Returns <converter>.
- */
- getConverter: function()
- {
- return converter;
- },
-
- /**
- * Function: isCompressed
- *
- * Returns <compressed>.
- */
- isCompressed: function()
- {
- return compressed;
- },
-
- /**
- * Function: setCompressed
- *
- * Sets <compressed>.
- */
- setCompressed: function(value)
- {
- compressed = value;
- },
-
- /**
- * Function: isTextEnabled
- *
- * Returns <textEnabled>.
- */
- isTextEnabled: function()
- {
- return textEnabled;
- },
-
- /**
- * Function: setTextEnabled
- *
- * Sets <textEnabled>.
- */
- setTextEnabled: function(value)
- {
- textEnabled = value;
- },
-
- /**
- * Function: getDocument
- *
- * Returns the owner document of the root element.
- */
- getDocument: function()
- {
- return doc;
- },
-
- /**
- * Function: save
- *
- * Saves the state of the graphics object.
- */
- save: function()
- {
- if (compressed)
- {
- stack.push(state);
- state = mxUtils.clone(state);
- }
-
- root.appendChild(doc.createElement('save'));
- },
-
- /**
- * Function: restore
- *
- * Restores the state of the graphics object.
- */
- restore: function()
- {
- if (compressed)
- {
- state = stack.pop();
- }
-
- root.appendChild(doc.createElement('restore'));
- },
-
- /**
- * Function: scale
- *
- * Scales the current graphics object.
- */
- scale: function(value)
- {
- var elem = doc.createElement('scale');
- elem.setAttribute('scale', value);
- root.appendChild(elem);
- },
-
- /**
- * Function: translate
- *
- * Translates the current graphics object.
- */
- translate: function(dx, dy)
- {
- var elem = doc.createElement('translate');
- elem.setAttribute('dx', f2(dx));
- elem.setAttribute('dy', f2(dy));
- root.appendChild(elem);
- },
-
- /**
- * Function: rotate
- *
- * Rotates and/or flips the current graphics object.
- */
- rotate: function(theta, flipH, flipV, cx, cy)
- {
- var elem = doc.createElement('rotate');
- elem.setAttribute('theta', f2(theta));
- elem.setAttribute('flipH', (flipH) ? '1' : '0');
- elem.setAttribute('flipV', (flipV) ? '1' : '0');
- elem.setAttribute('cx', f2(cx));
- elem.setAttribute('cy', f2(cy));
- root.appendChild(elem);
- },
-
- /**
- * Function: setStrokeWidth
- *
- * Sets the stroke width.
- */
- setStrokeWidth: function(value)
- {
- if (compressed)
- {
- if (state.strokewidth == value)
- {
- return;
- }
-
- state.strokewidth = value;
- }
-
- var elem = doc.createElement('strokewidth');
- elem.setAttribute('width', f2(value));
- root.appendChild(elem);
- },
-
- /**
- * Function: setStrokeColor
- *
- * Sets the stroke color.
- */
- setStrokeColor: function(value)
- {
- var elem = doc.createElement('strokecolor');
- elem.setAttribute('color', value);
- root.appendChild(elem);
- },
-
- /**
- * Function: setDashed
- *
- * Sets the dashed state to true or false.
- */
- setDashed: function(value)
- {
- if (compressed)
- {
- if (state.dashed == value)
- {
- return;
- }
-
- state.dashed = value;
- }
-
- var elem = doc.createElement('dashed');
- elem.setAttribute('dashed', (value) ? '1' : '0');
- root.appendChild(elem);
- },
-
- /**
- * Function: setDashPattern
- *
- * Sets the dashed pattern to the given space separated list of numbers.
- */
- setDashPattern: function(value)
- {
- var elem = doc.createElement('dashpattern');
- elem.setAttribute('pattern', value);
- root.appendChild(elem);
- },
-
- /**
- * Function: setLineCap
- *
- * Sets the linecap.
- */
- setLineCap: function(value)
- {
- var elem = doc.createElement('linecap');
- elem.setAttribute('cap', value);
- root.appendChild(elem);
- },
-
- /**
- * Function: setLineJoin
- *
- * Sets the linejoin.
- */
- setLineJoin: function(value)
- {
- var elem = doc.createElement('linejoin');
- elem.setAttribute('join', value);
- root.appendChild(elem);
- },
-
- /**
- * Function: setMiterLimit
- *
- * Sets the miterlimit.
- */
- setMiterLimit: function(value)
- {
- var elem = doc.createElement('miterlimit');
- elem.setAttribute('limit', value);
- root.appendChild(elem);
- },
-
- /**
- * Function: setFontSize
- *
- * Sets the fontsize.
- */
- setFontSize: function(value)
- {
- if (textEnabled)
- {
- if (compressed)
- {
- if (state.fontsize == value)
- {
- return;
- }
-
- state.fontsize = value;
- }
-
- var elem = doc.createElement('fontsize');
- elem.setAttribute('size', value);
- root.appendChild(elem);
- }
- },
-
- /**
- * Function: setFontColor
- *
- * Sets the fontcolor.
- */
- setFontColor: function(value)
- {
- if (textEnabled)
- {
- if (compressed)
- {
- if (state.fontcolor == value)
- {
- return;
- }
-
- state.fontcolor = value;
- }
-
- var elem = doc.createElement('fontcolor');
- elem.setAttribute('color', value);
- root.appendChild(elem);
- }
- },
-
- /**
- * Function: setFontFamily
- *
- * Sets the fontfamily.
- */
- setFontFamily: function(value)
- {
- if (textEnabled)
- {
- if (compressed)
- {
- if (state.fontfamily == value)
- {
- return;
- }
-
- state.fontfamily = value;
- }
-
- var elem = doc.createElement('fontfamily');
- elem.setAttribute('family', value);
- root.appendChild(elem);
- }
- },
-
- /**
- * Function: setFontStyle
- *
- * Sets the fontstyle.
- */
- setFontStyle: function(value)
- {
- if (textEnabled)
- {
- var elem = doc.createElement('fontstyle');
- elem.setAttribute('style', value);
- root.appendChild(elem);
- }
- },
-
- /**
- * Function: setAlpha
- *
- * Sets the current alpha.
- */
- setAlpha: function(alpha)
- {
- if (compressed)
- {
- if (state.alpha == alpha)
- {
- return;
- }
-
- state.alpha = alpha;
- }
-
- var elem = doc.createElement('alpha');
- elem.setAttribute('alpha', f2(alpha));
- root.appendChild(elem);
- },
-
- /**
- * Function: setFillColor
- *
- * Sets the fillcolor.
- */
- setFillColor: function(value)
- {
- var elem = doc.createElement('fillcolor');
- elem.setAttribute('color', value);
- root.appendChild(elem);
- },
-
- /**
- * Function: setGradient
- *
- * Sets the gradient color.
- */
- setGradient: function(color1, color2, x, y, w, h, direction)
- {
- var elem = doc.createElement('gradient');
- elem.setAttribute('c1', color1);
- elem.setAttribute('c2', color2);
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- elem.setAttribute('w', f2(w));
- elem.setAttribute('h', f2(h));
-
- // Default direction is south
- if (direction != null)
- {
- elem.setAttribute('direction', direction);
- }
-
- root.appendChild(elem);
- },
-
- /**
- * Function: setGlassGradient
- *
- * Sets the glass gradient.
- */
- setGlassGradient: function(x, y, w, h)
- {
- var elem = doc.createElement('glass');
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- elem.setAttribute('w', f2(w));
- elem.setAttribute('h', f2(h));
- root.appendChild(elem);
- },
-
- /**
- * Function: rect
- *
- * Sets the current path to a rectangle.
- */
- rect: function(x, y, w, h)
- {
- var elem = doc.createElement('rect');
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- elem.setAttribute('w', f2(w));
- elem.setAttribute('h', f2(h));
- root.appendChild(elem);
- },
-
- /**
- * Function: roundrect
- *
- * Sets the current path to a rounded rectangle.
- */
- roundrect: function(x, y, w, h, dx, dy)
- {
- var elem = doc.createElement('roundrect');
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- elem.setAttribute('w', f2(w));
- elem.setAttribute('h', f2(h));
- elem.setAttribute('dx', f2(dx));
- elem.setAttribute('dy', f2(dy));
- root.appendChild(elem);
- },
-
- /**
- * Function: ellipse
- *
- * Sets the current path to an ellipse.
- */
- ellipse: function(x, y, w, h)
- {
- var elem = doc.createElement('ellipse');
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- elem.setAttribute('w', f2(w));
- elem.setAttribute('h', f2(h));
- root.appendChild(elem);
- },
-
- /**
- * Function: image
- *
- * Paints an image.
- */
- image: function(x, y, w, h, src, aspect, flipH, flipV)
- {
- src = converter.convert(src);
-
- // TODO: Add option for embedding images as base64
- var elem = doc.createElement('image');
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- elem.setAttribute('w', f2(w));
- elem.setAttribute('h', f2(h));
- elem.setAttribute('src', src);
- elem.setAttribute('aspect', (aspect) ? '1' : '0');
- elem.setAttribute('flipH', (flipH) ? '1' : '0');
- elem.setAttribute('flipV', (flipV) ? '1' : '0');
- root.appendChild(elem);
- },
-
- /**
- * Function: text
- *
- * Paints the given text.
- */
- text: function(x, y, w, h, str, align, valign, vertical, wrap, format)
- {
- if (textEnabled)
- {
- var elem = doc.createElement('text');
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- elem.setAttribute('w', f2(w));
- elem.setAttribute('h', f2(h));
- elem.setAttribute('str', str);
-
- if (align != null)
- {
- elem.setAttribute('align', align);
- }
-
- if (valign != null)
- {
- elem.setAttribute('valign', valign);
- }
-
- elem.setAttribute('vertical', (vertical) ? '1' : '0');
- elem.setAttribute('wrap', (wrap) ? '1' : '0');
- elem.setAttribute('format', format);
- root.appendChild(elem);
- }
- },
-
- /**
- * Function: begin
- *
- * Starts a new path.
- */
- begin: function()
- {
- root.appendChild(doc.createElement('begin'));
- },
-
- /**
- * Function: moveTo
- *
- * Moves the current path the given coordinates.
- */
- moveTo: function(x, y)
- {
- var elem = doc.createElement('move');
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- root.appendChild(elem);
- },
-
- /**
- * Function: lineTo
- *
- * Adds a line to the current path.
- */
- lineTo: function(x, y)
- {
- var elem = doc.createElement('line');
- elem.setAttribute('x', f2(x));
- elem.setAttribute('y', f2(y));
- root.appendChild(elem);
- },
-
- /**
- * Function: quadTo
- *
- * Adds a quadratic curve to the current path.
- */
- quadTo: function(x1, y1, x2, y2)
- {
- var elem = doc.createElement('quad');
- elem.setAttribute('x1', f2(x1));
- elem.setAttribute('y1', f2(y1));
- elem.setAttribute('x2', f2(x2));
- elem.setAttribute('y2', f2(y2));
- root.appendChild(elem);
- },
-
- /**
- * Function: curveTo
- *
- * Adds a bezier curve to the current path.
- */
- curveTo: function(x1, y1, x2, y2, x3, y3)
- {
- var elem = doc.createElement('curve');
- elem.setAttribute('x1', f2(x1));
- elem.setAttribute('y1', f2(y1));
- elem.setAttribute('x2', f2(x2));
- elem.setAttribute('y2', f2(y2));
- elem.setAttribute('x3', f2(x3));
- elem.setAttribute('y3', f2(y3));
- root.appendChild(elem);
- },
-
- /**
- * Function: close
- *
- * Closes the current path.
- */
- close: function()
- {
- root.appendChild(doc.createElement('close'));
- },
-
- /**
- * Function: stroke
- *
- * Paints the outline of the current path.
- */
- stroke: function()
- {
- root.appendChild(doc.createElement('stroke'));
- },
-
- /**
- * Function: fill
- *
- * Fills the current path.
- */
- fill: function()
- {
- root.appendChild(doc.createElement('fill'));
- },
-
- /**
- * Function: fillstroke
- *
- * Fills and paints the outline of the current path.
- */
- fillAndStroke: function()
- {
- root.appendChild(doc.createElement('fillstroke'));
- },
-
- /**
- * Function: shadow
- *
- * Paints the current path as a shadow of the given color.
- */
- shadow: function(value, filled)
- {
- var elem = doc.createElement('shadow');
- elem.setAttribute('value', value);
-
- if (filled != null)
- {
- elem.setAttribute('filled', (filled) ? '1' : '0');
- }
-
- root.appendChild(elem);
- },
-
- /**
- * Function: clip
- *
- * Uses the current path for clipping.
- */
- clip: function()
- {
- root.appendChild(doc.createElement('clip'));
- }
- };
-
-}; \ No newline at end of file
diff --git a/src/js/util/mxXmlRequest.js b/src/js/util/mxXmlRequest.js
deleted file mode 100644
index 0ac55ed..0000000
--- a/src/js/util/mxXmlRequest.js
+++ /dev/null
@@ -1,425 +0,0 @@
-/**
- * $Id: mxXmlRequest.js,v 1.38 2012-04-22 10:16:23 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxXmlRequest
- *
- * XML HTTP request wrapper. See also: <mxUtils.get>, <mxUtils.post> and
- * <mxUtils.load>. This class provides a cross-browser abstraction for Ajax
- * requests.
- *
- * Encoding:
- *
- * For encoding parameter values, the built-in encodeURIComponent JavaScript
- * method must be used. For automatic encoding of post data in <mxEditor> the
- * <mxEditor.escapePostData> switch can be set to true (default). The encoding
- * will be carried out using the conte type of the page. That is, the page
- * containting the editor should contain a meta tag in the header, eg.
- * <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- *
- * Example:
- *
- * (code)
- * var onload = function(req)
- * {
- * mxUtils.alert(req.getDocumentElement());
- * }
- *
- * var onerror = function(req)
- * {
- * mxUtils.alert(req.getStatus());
- * }
- * new mxXmlRequest(url, 'key=value').send(onload, onerror);
- * (end)
- *
- * Sends an asynchronous POST request to the specified URL.
- *
- * Example:
- *
- * (code)
- * var req = new mxXmlRequest(url, 'key=value', 'POST', false);
- * req.send();
- * mxUtils.alert(req.getDocumentElement());
- * (end)
- *
- * Sends a synchronous POST request to the specified URL.
- *
- * Example:
- *
- * (code)
- * var encoder = new mxCodec();
- * var result = encoder.encode(graph.getModel());
- * var xml = encodeURIComponent(mxUtils.getXml(result));
- * new mxXmlRequest(url, 'xml='+xml).send();
- * (end)
- *
- * Sends an encoded graph model to the specified URL using xml as the
- * parameter name. The parameter can then be retrieved in C# as follows:
- *
- * (code)
- * string xml = HttpUtility.UrlDecode(context.Request.Params["xml"]);
- * (end)
- *
- * Or in Java as follows:
- *
- * (code)
- * String xml = URLDecoder.decode(request.getParameter("xml"), "UTF-8").replace("\n", "&#xa;");
- * (end)
- *
- * Note that the linefeeds should only be replaced if the XML is
- * processed in Java, for example when creating an image.
- *
- * Constructor: mxXmlRequest
- *
- * Constructs an XML HTTP request.
- *
- * Parameters:
- *
- * url - Target URL of the request.
- * params - Form encoded parameters to send with a POST request.
- * method - String that specifies the request method. Possible values are
- * POST and GET. Default is POST.
- * async - Boolean specifying if an asynchronous request should be used.
- * Default is true.
- * username - String specifying the username to be used for the request.
- * password - String specifying the password to be used for the request.
- */
-function mxXmlRequest(url, params, method, async, username, password)
-{
- this.url = url;
- this.params = params;
- this.method = method || 'POST';
- this.async = (async != null) ? async : true;
- this.username = username;
- this.password = password;
-};
-
-/**
- * Variable: url
- *
- * Holds the target URL of the request.
- */
-mxXmlRequest.prototype.url = null;
-
-/**
- * Variable: params
- *
- * Holds the form encoded data for the POST request.
- */
-mxXmlRequest.prototype.params = null;
-
-/**
- * Variable: method
- *
- * Specifies the request method. Possible values are POST and GET. Default
- * is POST.
- */
-mxXmlRequest.prototype.method = null;
-
-/**
- * Variable: async
- *
- * Boolean indicating if the request is asynchronous.
- */
-mxXmlRequest.prototype.async = null;
-
-/**
- * Variable: binary
- *
- * Boolean indicating if the request is binary. This option is ignored in IE.
- * In all other browsers the requested mime type is set to
- * text/plain; charset=x-user-defined. Default is false.
- */
-mxXmlRequest.prototype.binary = false;
-
-/**
- * Variable: username
- *
- * Specifies the username to be used for authentication.
- */
-mxXmlRequest.prototype.username = null;
-
-/**
- * Variable: password
- *
- * Specifies the password to be used for authentication.
- */
-mxXmlRequest.prototype.password = null;
-
-/**
- * Variable: request
- *
- * Holds the inner, browser-specific request object.
- */
-mxXmlRequest.prototype.request = null;
-
-/**
- * Function: isBinary
- *
- * Returns <binary>.
- */
-mxXmlRequest.prototype.isBinary = function()
-{
- return this.binary;
-};
-
-/**
- * Function: setBinary
- *
- * Sets <binary>.
- */
-mxXmlRequest.prototype.setBinary = function(value)
-{
- this.binary = value;
-};
-
-/**
- * Function: getText
- *
- * Returns the response as a string.
- */
-mxXmlRequest.prototype.getText = function()
-{
- return this.request.responseText;
-};
-
-/**
- * Function: isReady
- *
- * Returns true if the response is ready.
- */
-mxXmlRequest.prototype.isReady = function()
-{
- return this.request.readyState == 4;
-};
-
-/**
- * Function: getDocumentElement
- *
- * Returns the document element of the response XML document.
- */
-mxXmlRequest.prototype.getDocumentElement = function()
-{
- var doc = this.getXml();
-
- if (doc != null)
- {
- return doc.documentElement;
- }
-
- return null;
-};
-
-/**
- * Function: getXml
- *
- * Returns the response as an XML document. Use <getDocumentElement> to get
- * the document element of the XML document.
- */
-mxXmlRequest.prototype.getXml = function()
-{
- var xml = this.request.responseXML;
-
- // Handles missing response headers in IE, the first condition handles
- // the case where responseXML is there, but using its nodes leads to
- // type errors in the mxCellCodec when putting the nodes into a new
- // document. This happens in IE9 standards mode and with XML user
- // objects only, as they are used directly as values in cells.
- if (document.documentMode >= 9 || xml == null || xml.documentElement == null)
- {
- xml = mxUtils.parseXml(this.request.responseText);
- }
-
- return xml;
-};
-
-/**
- * Function: getText
- *
- * Returns the response as a string.
- */
-mxXmlRequest.prototype.getText = function()
-{
- return this.request.responseText;
-};
-
-/**
- * Function: getStatus
- *
- * Returns the status as a number, eg. 404 for "Not found" or 200 for "OK".
- * Note: The NS_ERROR_NOT_AVAILABLE for invalid responses cannot be cought.
- */
-mxXmlRequest.prototype.getStatus = function()
-{
- return this.request.status;
-};
-
-/**
- * Function: create
- *
- * Creates and returns the inner <request> object.
- */
-mxXmlRequest.prototype.create = function()
-{
- if (window.XMLHttpRequest)
- {
- return function()
- {
- var req = new XMLHttpRequest();
-
- // TODO: Check for overrideMimeType required here?
- if (this.isBinary() && req.overrideMimeType)
- {
- req.overrideMimeType('text/plain; charset=x-user-defined');
- }
-
- return req;
- };
- }
- else if (typeof(ActiveXObject) != "undefined")
- {
- return function()
- {
- // TODO: Implement binary option
- return new ActiveXObject("Microsoft.XMLHTTP");
- };
- }
-}();
-
-/**
- * Function: send
- *
- * Send the <request> to the target URL using the specified functions to
- * process the response asychronously.
- *
- * Parameters:
- *
- * onload - Function to be invoked if a successful response was received.
- * onerror - Function to be called on any error.
- */
-mxXmlRequest.prototype.send = function(onload, onerror)
-{
- this.request = this.create();
-
- if (this.request != null)
- {
- if (onload != null)
- {
- this.request.onreadystatechange = mxUtils.bind(this, function()
- {
- if (this.isReady())
- {
- onload(this);
- this.onreadystatechaange = null;
- }
- });
- }
-
- this.request.open(this.method, this.url, this.async,
- this.username, this.password);
- this.setRequestHeaders(this.request, this.params);
- this.request.send(this.params);
- }
-};
-
-/**
- * Function: setRequestHeaders
- *
- * Sets the headers for the given request and parameters. This sets the
- * content-type to application/x-www-form-urlencoded if any params exist.
- *
- * Example:
- *
- * (code)
- * request.setRequestHeaders = function(request, params)
- * {
- * if (params != null)
- * {
- * request.setRequestHeader('Content-Type',
- * 'multipart/form-data');
- * request.setRequestHeader('Content-Length',
- * params.length);
- * }
- * };
- * (end)
- *
- * Use the code above before calling <send> if you require a
- * multipart/form-data request.
- */
-mxXmlRequest.prototype.setRequestHeaders = function(request, params)
-{
- if (params != null)
- {
- request.setRequestHeader('Content-Type',
- 'application/x-www-form-urlencoded');
- }
-};
-
-/**
- * Function: simulate
- *
- * Creates and posts a request to the given target URL using a dynamically
- * created form inside the given document.
- *
- * Parameters:
- *
- * docs - Document that contains the form element.
- * target - Target to send the form result to.
- */
-mxXmlRequest.prototype.simulate = function(doc, target)
-{
- doc = doc || document;
- var old = null;
-
- if (doc == document)
- {
- old = window.onbeforeunload;
- window.onbeforeunload = null;
- }
-
- var form = doc.createElement('form');
- form.setAttribute('method', this.method);
- form.setAttribute('action', this.url);
-
- if (target != null)
- {
- form.setAttribute('target', target);
- }
-
- form.style.display = 'none';
- form.style.visibility = 'hidden';
-
- var pars = (this.params.indexOf('&') > 0) ?
- this.params.split('&') :
- this.params.split();
-
- // Adds the parameters as textareas to the form
- for (var i=0; i<pars.length; i++)
- {
- var pos = pars[i].indexOf('=');
-
- if (pos > 0)
- {
- var name = pars[i].substring(0, pos);
- var value = pars[i].substring(pos+1);
-
- var textarea = doc.createElement('textarea');
- textarea.setAttribute('name', name);
- value = value.replace(/\n/g, '&#xa;');
-
- var content = doc.createTextNode(value);
- textarea.appendChild(content);
- form.appendChild(textarea);
- }
- }
-
- doc.body.appendChild(form);
- form.submit();
- doc.body.removeChild(form);
-
- if (old != null)
- {
- window.onbeforeunload = old;
- }
-};
diff --git a/src/js/view/mxCellEditor.js b/src/js/view/mxCellEditor.js
deleted file mode 100644
index 2086cca..0000000
--- a/src/js/view/mxCellEditor.js
+++ /dev/null
@@ -1,522 +0,0 @@
-/**
- * $Id: mxCellEditor.js,v 1.62 2012-12-11 16:59:31 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCellEditor
- *
- * In-place editor for the graph. To control this editor, use
- * <mxGraph.invokesStopCellEditing>, <mxGraph.enterStopsCellEditing> and
- * <mxGraph.escapeEnabled>. If <mxGraph.enterStopsCellEditing> is true then
- * ctrl-enter or shift-enter can be used to create a linefeed. The F2 and
- * escape keys can always be used to stop editing. To customize the location
- * of the textbox in the graph, override <getEditorBounds> as follows:
- *
- * (code)
- * graph.cellEditor.getEditorBounds = function(state)
- * {
- * var result = mxCellEditor.prototype.getEditorBounds.apply(this, arguments);
- *
- * if (this.graph.getModel().isEdge(state.cell))
- * {
- * result.x = state.getCenterX() - result.width / 2;
- * result.y = state.getCenterY() - result.height / 2;
- * }
- *
- * return result;
- * };
- * (end)
- *
- * The textarea uses the mxCellEditor CSS class. You can modify this class in
- * your custom CSS. Note: You should modify the CSS after loading the client
- * in the page.
- *
- * Example:
- *
- * To only allow numeric input in the in-place editor, use the following code.
- *
- * (code)
- * var text = graph.cellEditor.textarea;
- *
- * mxEvent.addListener(text, 'keydown', function (evt)
- * {
- * if (!(evt.keyCode >= 48 && evt.keyCode <= 57) &&
- * !(evt.keyCode >= 96 && evt.keyCode <= 105))
- * {
- * mxEvent.consume(evt);
- * }
- * });
- * (end)
- *
- * Initial values:
- *
- * To implement an initial value for cells without a label, use the
- * <emptyLabelText> variable.
- *
- * Resize in Chrome:
- *
- * Resize of the textarea is disabled by default. If you want to enable
- * this feature extend <init> and set this.textarea.style.resize = ''.
- *
- * Constructor: mxCellEditor
- *
- * Constructs a new in-place editor for the specified graph.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- */
-function mxCellEditor(graph)
-{
- this.graph = graph;
-};
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxCellEditor.prototype.graph = null;
-
-/**
- * Variable: textarea
- *
- * Holds the input textarea. Note that this may be null before the first
- * edit. Instantiated in <init>.
- */
-mxCellEditor.prototype.textarea = null;
-
-/**
- * Variable: editingCell
- *
- * Reference to the <mxCell> that is currently being edited.
- */
-mxCellEditor.prototype.editingCell = null;
-
-/**
- * Variable: trigger
- *
- * Reference to the event that was used to start editing.
- */
-mxCellEditor.prototype.trigger = null;
-
-/**
- * Variable: modified
- *
- * Specifies if the label has been modified.
- */
-mxCellEditor.prototype.modified = false;
-
-/**
- * Variable: emptyLabelText
- *
- * Text to be displayed for empty labels. Default is ''. This can be set
- * to eg. "[Type Here]" to easier visualize editing of empty labels. The
- * value is only displayed before the first keystroke and is never used
- * as the actual editin value.
- */
-mxCellEditor.prototype.emptyLabelText = '';
-
-/**
- * Variable: textNode
- *
- * Reference to the label DOM node that has been hidden.
- */
-mxCellEditor.prototype.textNode = '';
-
-/**
- * Function: init
- *
- * Creates the <textarea> and installs the event listeners. The key handler
- * updates the <modified> state.
- */
-mxCellEditor.prototype.init = function ()
-{
- this.textarea = document.createElement('textarea');
-
- this.textarea.className = 'mxCellEditor';
- this.textarea.style.position = 'absolute';
- this.textarea.style.overflow = 'visible';
-
- this.textarea.setAttribute('cols', '20');
- this.textarea.setAttribute('rows', '4');
-
- if (mxClient.IS_GC)
- {
- this.textarea.style.resize = 'none';
- }
-
- mxEvent.addListener(this.textarea, 'blur', mxUtils.bind(this, function(evt)
- {
- this.focusLost();
- }));
-
- mxEvent.addListener(this.textarea, 'keydown', mxUtils.bind(this, function(evt)
- {
- if (!mxEvent.isConsumed(evt))
- {
- if (evt.keyCode == 113 /* F2 */ || (this.graph.isEnterStopsCellEditing() &&
- evt.keyCode == 13 /* Enter */ && !mxEvent.isControlDown(evt) &&
- !mxEvent.isShiftDown(evt)))
- {
- this.graph.stopEditing(false);
- mxEvent.consume(evt);
- }
- else if (evt.keyCode == 27 /* Escape */)
- {
- this.graph.stopEditing(true);
- mxEvent.consume(evt);
- }
- else
- {
- // Clears the initial empty label on the first keystroke
- if (this.clearOnChange)
- {
- this.clearOnChange = false;
- this.textarea.value = '';
- }
-
- // Updates the modified flag for storing the value
- this.setModified(true);
- }
- }
- }));
-};
-
-/**
- * Function: isModified
- *
- * Returns <modified>.
- */
-mxCellEditor.prototype.isModified = function()
-{
- return this.modified;
-};
-
-/**
- * Function: setModified
- *
- * Sets <modified> to the specified boolean value.
- */
-mxCellEditor.prototype.setModified = function(value)
-{
- this.modified = value;
-};
-
-/**
- * Function: focusLost
- *
- * Called if the textarea has lost focus.
- */
-mxCellEditor.prototype.focusLost = function()
-{
- this.stopEditing(!this.graph.isInvokesStopCellEditing());
-};
-
-/**
- * Function: startEditing
- *
- * Starts the editor for the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> to start editing.
- * trigger - Optional mouse event that triggered the editor.
- */
-mxCellEditor.prototype.startEditing = function(cell, trigger)
-{
- // Lazy instantiates textarea to save memory in IE
- if (this.textarea == null)
- {
- this.init();
- }
-
- this.stopEditing(true);
- var state = this.graph.getView().getState(cell);
-
- if (state != null)
- {
- this.editingCell = cell;
- this.trigger = trigger;
- this.textNode = null;
-
- if (state.text != null && this.isHideLabel(state))
- {
- this.textNode = state.text.node;
- this.textNode.style.visibility = 'hidden';
- }
-
- // Configures the style of the in-place editor
- var scale = this.graph.getView().scale;
- var size = mxUtils.getValue(state.style, mxConstants.STYLE_FONTSIZE, mxConstants.DEFAULT_FONTSIZE) * scale;
- var family = mxUtils.getValue(state.style, mxConstants.STYLE_FONTFAMILY, mxConstants.DEFAULT_FONTFAMILY);
- var color = mxUtils.getValue(state.style, mxConstants.STYLE_FONTCOLOR, 'black');
- var align = (this.graph.model.isEdge(state.cell)) ? mxConstants.ALIGN_LEFT :
- mxUtils.getValue(state.style, mxConstants.STYLE_ALIGN, mxConstants.ALIGN_LEFT);
- var bold = (mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0) &
- mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD;
- var italic = (mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0) &
- mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC;
- var uline = (mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0) &
- mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE;
-
- this.textarea.style.fontSize = size + 'px';
- this.textarea.style.fontFamily = family;
- this.textarea.style.textAlign = align;
- this.textarea.style.color = color;
- this.textarea.style.fontWeight = (bold) ? 'bold' : 'normal';
- this.textarea.style.fontStyle = (italic) ? 'italic' : '';
- this.textarea.style.textDecoration = (uline) ? 'underline' : '';
-
- // Specifies the bounds of the editor box
- var bounds = this.getEditorBounds(state);
-
- this.textarea.style.left = bounds.x + 'px';
- this.textarea.style.top = bounds.y + 'px';
- this.textarea.style.width = bounds.width + 'px';
- this.textarea.style.height = bounds.height + 'px';
- this.textarea.style.zIndex = 5;
-
- var value = this.getInitialValue(state, trigger);
-
- // Uses an optional text value for empty labels which is cleared
- // when the first keystroke appears. This makes it easier to see
- // that a label is being edited even if the label is empty.
- if (value == null || value.length == 0)
- {
- value = this.getEmptyLabelText();
- this.clearOnChange = true;
- }
- else
- {
- this.clearOnChange = false;
- }
-
- this.setModified(false);
- this.textarea.value = value;
- this.graph.container.appendChild(this.textarea);
-
- if (this.textarea.style.display != 'none')
- {
- // FIXME: Doesn't bring up the virtual keyboard on iPad
- this.textarea.focus();
- this.textarea.select();
- }
- }
-};
-
-/**
- * Function: stopEditing
- *
- * Stops the editor and applies the value if cancel is false.
- */
-mxCellEditor.prototype.stopEditing = function(cancel)
-{
- cancel = cancel || false;
-
- if (this.editingCell != null)
- {
- if (this.textNode != null)
- {
- this.textNode.style.visibility = 'visible';
- this.textNode = null;
- }
-
- if (!cancel && this.isModified())
- {
- this.graph.labelChanged(this.editingCell, this.getCurrentValue(), this.trigger);
- }
-
- this.editingCell = null;
- this.trigger = null;
- this.textarea.blur();
- this.textarea.parentNode.removeChild(this.textarea);
- }
-};
-
-/**
- * Function: getInitialValue
- *
- * Gets the initial editing value for the given cell.
- */
-mxCellEditor.prototype.getInitialValue = function(state, trigger)
-{
- return this.graph.getEditingValue(state.cell, trigger);
-};
-
-/**
- * Function: getCurrentValue
- *
- * Returns the current editing value.
- */
-mxCellEditor.prototype.getCurrentValue = function()
-{
- return this.textarea.value.replace(/\r/g, '');
-};
-
-/**
- * Function: isHideLabel
- *
- * Returns true if the label should be hidden while the cell is being
- * edited.
- */
-mxCellEditor.prototype.isHideLabel = function(state)
-{
- return true;
-};
-
-/**
- * Function: getMinimumSize
- *
- * Returns the minimum width and height for editing the given state.
- */
-mxCellEditor.prototype.getMinimumSize = function(state)
-{
- var scale = this.graph.getView().scale;
-
- return new mxRectangle(0, 0, (state.text == null) ? 30 : state.text.size * scale + 20,
- (this.textarea.style.textAlign == 'left') ? 120 : 40);
-};
-
-/**
- * Function: getEditorBounds
- *
- * Returns the <mxRectangle> that defines the bounds of the editor.
- */
-mxCellEditor.prototype.getEditorBounds = function(state)
-{
- var isEdge = this.graph.getModel().isEdge(state.cell);
- var scale = this.graph.getView().scale;
- var minSize = this.getMinimumSize(state);
- var minWidth = minSize.width;
- var minHeight = minSize.height;
-
- var spacing = parseInt(state.style[mxConstants.STYLE_SPACING] || 2) * scale;
- var spacingTop = (parseInt(state.style[mxConstants.STYLE_SPACING_TOP] || 0)) * scale + spacing;
- var spacingRight = (parseInt(state.style[mxConstants.STYLE_SPACING_RIGHT] || 0)) * scale + spacing;
- var spacingBottom = (parseInt(state.style[mxConstants.STYLE_SPACING_BOTTOM] || 0)) * scale + spacing;
- var spacingLeft = (parseInt(state.style[mxConstants.STYLE_SPACING_LEFT] || 0)) * scale + spacing;
-
- var result = new mxRectangle(state.x, state.y,
- Math.max(minWidth, state.width - spacingLeft - spacingRight),
- Math.max(minHeight, state.height - spacingTop - spacingBottom));
-
- if (isEdge)
- {
- result.x = state.absoluteOffset.x;
- result.y = state.absoluteOffset.y;
-
- if (state.text != null && state.text.boundingBox != null)
- {
- // Workaround for label containing just spaces in which case
- // the bounding box location contains negative numbers
- if (state.text.boundingBox.x > 0)
- {
- result.x = state.text.boundingBox.x;
- }
-
- if (state.text.boundingBox.y > 0)
- {
- result.y = state.text.boundingBox.y;
- }
- }
- }
- else if (state.text != null && state.text.boundingBox != null)
- {
- result.x = Math.min(result.x, state.text.boundingBox.x);
- result.y = Math.min(result.y, state.text.boundingBox.y);
- }
-
- result.x += spacingLeft;
- result.y += spacingTop;
-
- if (state.text != null && state.text.boundingBox != null)
- {
- if (!isEdge)
- {
- result.width = Math.max(result.width, state.text.boundingBox.width);
- result.height = Math.max(result.height, state.text.boundingBox.height);
- }
- else
- {
- result.width = Math.max(minWidth, state.text.boundingBox.width);
- result.height = Math.max(minHeight, state.text.boundingBox.height);
- }
- }
-
- // Applies the horizontal and vertical label positions
- if (this.graph.getModel().isVertex(state.cell))
- {
- var horizontal = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER);
-
- if (horizontal == mxConstants.ALIGN_LEFT)
- {
- result.x -= state.width;
- }
- else if (horizontal == mxConstants.ALIGN_RIGHT)
- {
- result.x += state.width;
- }
-
- var vertical = mxUtils.getValue(state.style, mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_MIDDLE);
-
- if (vertical == mxConstants.ALIGN_TOP)
- {
- result.y -= state.height;
- }
- else if (vertical == mxConstants.ALIGN_BOTTOM)
- {
- result.y += state.height;
- }
- }
-
- return result;
-};
-
-/**
- * Function: getEmptyLabelText
- *
- * Returns the initial label value to be used of the label of the given
- * cell is empty. This label is displayed and cleared on the first keystroke.
- * This implementation returns <emptyLabelText>.
- *
- * Parameters:
- *
- * cell - <mxCell> for which a text for an empty editing box should be
- * returned.
- */
-mxCellEditor.prototype.getEmptyLabelText = function (cell)
-{
- return this.emptyLabelText;
-};
-
-/**
- * Function: getEditingCell
- *
- * Returns the cell that is currently being edited or null if no cell is
- * being edited.
- */
-mxCellEditor.prototype.getEditingCell = function ()
-{
- return this.editingCell;
-};
-
-/**
- * Function: destroy
- *
- * Destroys the editor and removes all associated resources.
- */
-mxCellEditor.prototype.destroy = function ()
-{
- if (this.textarea != null)
- {
- mxEvent.release(this.textarea);
-
- if (this.textarea.parentNode != null)
- {
- this.textarea.parentNode.removeChild(this.textarea);
- }
-
- this.textarea = null;
- }
-};
diff --git a/src/js/view/mxCellOverlay.js b/src/js/view/mxCellOverlay.js
deleted file mode 100644
index 316e2c4..0000000
--- a/src/js/view/mxCellOverlay.js
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- * $Id: mxCellOverlay.js,v 1.18 2012-12-06 15:58:44 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCellOverlay
- *
- * Extends <mxEventSource> to implement a graph overlay, represented by an icon
- * and a tooltip. Overlays can handle and fire <click> events and are added to
- * the graph using <mxGraph.addCellOverlay>, and removed using
- * <mxGraph.removeCellOverlay>, or <mxGraph.removeCellOverlays> to remove all overlays.
- * The <mxGraph.getCellOverlays> function returns the array of overlays for a given
- * cell in a graph. If multiple overlays exist for the same cell, then
- * <getBounds> should be overridden in at least one of the overlays.
- *
- * Overlays appear on top of all cells in a special layer. If this is not
- * desirable, then the image must be rendered as part of the shape or label of
- * the cell instead.
- *
- * Example:
- *
- * The following adds a new overlays for a given vertex and selects the cell
- * if the overlay is clicked.
- *
- * (code)
- * var overlay = new mxCellOverlay(img, html);
- * graph.addCellOverlay(vertex, overlay);
- * overlay.addListener(mxEvent.CLICK, function(sender, evt)
- * {
- * var cell = evt.getProperty('cell');
- * graph.setSelectionCell(cell);
- * });
- * (end)
- *
- * For cell overlays to be printed use <mxPrintPreview.printOverlays>.
- *
- * Event: mxEvent.CLICK
- *
- * Fires when the user clicks on the overlay. The <code>event</code> property
- * contains the corresponding mouse event and the <code>cell</code> property
- * contains the cell. For touch devices this is fired if the element receives
- * a touchend event.
- *
- * Constructor: mxCellOverlay
- *
- * Constructs a new overlay using the given image and tooltip.
- *
- * Parameters:
- *
- * image - <mxImage> that represents the icon to be displayed.
- * tooltip - Optional string that specifies the tooltip.
- * align - Optional horizontal alignment for the overlay. Possible
- * values are <ALIGN_LEFT>, <ALIGN_CENTER> and <ALIGN_RIGHT>
- * (default).
- * verticalAlign - Vertical alignment for the overlay. Possible
- * values are <ALIGN_TOP>, <ALIGN_MIDDLE> and <ALIGN_BOTTOM>
- * (default).
- */
-function mxCellOverlay(image, tooltip, align, verticalAlign, offset, cursor)
-{
- this.image = image;
- this.tooltip = tooltip;
- this.align = (align != null) ? align : this.align;
- this.verticalAlign = (verticalAlign != null) ? verticalAlign : this.verticalAlign;
- this.offset = (offset != null) ? offset : new mxPoint();
- this.cursor = (cursor != null) ? cursor : 'help';
-};
-
-/**
- * Extends mxEventSource.
- */
-mxCellOverlay.prototype = new mxEventSource();
-mxCellOverlay.prototype.constructor = mxCellOverlay;
-
-/**
- * Variable: image
- *
- * Holds the <mxImage> to be used as the icon.
- */
-mxCellOverlay.prototype.image = null;
-
-/**
- * Variable: tooltip
- *
- * Holds the optional string to be used as the tooltip.
- */
-mxCellOverlay.prototype.tooltip = null;
-
-/**
- * Variable: align
- *
- * Holds the horizontal alignment for the overlay. Default is
- * <mxConstants.ALIGN_RIGHT>. For edges, the overlay always appears in the
- * center of the edge.
- */
-mxCellOverlay.prototype.align = mxConstants.ALIGN_RIGHT;
-
-/**
- * Variable: verticalAlign
- *
- * Holds the vertical alignment for the overlay. Default is
- * <mxConstants.ALIGN_BOTTOM>. For edges, the overlay always appears in the
- * center of the edge.
- */
-mxCellOverlay.prototype.verticalAlign = mxConstants.ALIGN_BOTTOM;
-
-/**
- * Variable: offset
- *
- * Holds the offset as an <mxPoint>. The offset will be scaled according to the
- * current scale.
- */
-mxCellOverlay.prototype.offset = null;
-
-/**
- * Variable: cursor
- *
- * Holds the cursor for the overlay. Default is 'help'.
- */
-mxCellOverlay.prototype.cursor = null;
-
-/**
- * Variable: defaultOverlap
- *
- * Defines the overlapping for the overlay, that is, the proportional distance
- * from the origin to the point defined by the alignment. Default is 0.5.
- */
-mxCellOverlay.prototype.defaultOverlap = 0.5;
-
-/**
- * Function: getBounds
- *
- * Returns the bounds of the overlay for the given <mxCellState> as an
- * <mxRectangle>. This should be overridden when using multiple overlays
- * per cell so that the overlays do not overlap.
- *
- * The following example will place the overlay along an edge (where
- * x=[-1..1] from the start to the end of the edge and y is the
- * orthogonal offset in px).
- *
- * (code)
- * overlay.getBounds = function(state)
- * {
- * var bounds = mxCellOverlay.prototype.getBounds.apply(this, arguments);
- *
- * if (state.view.graph.getModel().isEdge(state.cell))
- * {
- * var pt = state.view.getPoint(state, {x: 0, y: 0, relative: true});
- *
- * bounds.x = pt.x - bounds.width / 2;
- * bounds.y = pt.y - bounds.height / 2;
- * }
- *
- * return bounds;
- * };
- * (end)
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the current state of the
- * associated cell.
- */
-mxCellOverlay.prototype.getBounds = function(state)
-{
- var isEdge = state.view.graph.getModel().isEdge(state.cell);
- var s = state.view.scale;
- var pt = null;
-
- var w = this.image.width;
- var h = this.image.height;
-
- if (isEdge)
- {
- var pts = state.absolutePoints;
-
- if (pts.length % 2 == 1)
- {
- pt = pts[Math.floor(pts.length / 2)];
- }
- else
- {
- var idx = pts.length / 2;
- var p0 = pts[idx-1];
- var p1 = pts[idx];
- pt = new mxPoint(p0.x + (p1.x - p0.x) / 2,
- p0.y + (p1.y - p0.y) / 2);
- }
- }
- else
- {
- pt = new mxPoint();
-
- if (this.align == mxConstants.ALIGN_LEFT)
- {
- pt.x = state.x;
- }
- else if (this.align == mxConstants.ALIGN_CENTER)
- {
- pt.x = state.x + state.width / 2;
- }
- else
- {
- pt.x = state.x + state.width;
- }
-
- if (this.verticalAlign == mxConstants.ALIGN_TOP)
- {
- pt.y = state.y;
- }
- else if (this.verticalAlign == mxConstants.ALIGN_MIDDLE)
- {
- pt.y = state.y + state.height / 2;
- }
- else
- {
- pt.y = state.y + state.height;
- }
- }
-
- return new mxRectangle(pt.x - (w * this.defaultOverlap - this.offset.x) * s,
- pt.y - (h * this.defaultOverlap - this.offset.y) * s, w * s, h * s);
-};
-
-/**
- * Function: toString
- *
- * Returns the textual representation of the overlay to be used as the
- * tooltip. This implementation returns <tooltip>.
- */
-mxCellOverlay.prototype.toString = function()
-{
- return this.tooltip;
-};
diff --git a/src/js/view/mxCellRenderer.js b/src/js/view/mxCellRenderer.js
deleted file mode 100644
index 6b506ad..0000000
--- a/src/js/view/mxCellRenderer.js
+++ /dev/null
@@ -1,1480 +0,0 @@
-/**
- * $Id: mxCellRenderer.js,v 1.189 2012-11-20 09:06:07 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCellRenderer
- *
- * Renders cells into a document object model. The <defaultShapes> is a global
- * map of shapename, constructor pairs that is used in all instances. You can
- * get a list of all available shape names using the following code.
- *
- * In general the cell renderer is in charge of creating, redrawing and
- * destroying the shape and label associated with a cell state, as well as
- * some other graphical objects, namely controls and overlays. The shape
- * hieararchy in the display (ie. the hierarchy in which the DOM nodes
- * appear in the document) does not reflect the cell hierarchy. The shapes
- * are a (flat) sequence of shapes and labels inside the draw pane of the
- * graph view, with some exceptions, namely the HTML labels being placed
- * directly inside the graph container for certain browsers.
- *
- * (code)
- * mxLog.show();
- * for (var i in mxCellRenderer.prototype.defaultShapes)
- * {
- * mxLog.debug(i);
- * }
- * (end)
- *
- * Constructor: mxCellRenderer
- *
- * Constructs a new cell renderer with the following built-in shapes:
- * arrow, rectangle, ellipse, rhombus, image, line, label, cylinder,
- * swimlane, connector, actor and cloud.
- */
-function mxCellRenderer()
-{
- this.shapes = mxUtils.clone(this.defaultShapes);
-};
-
-/**
- * Variable: shapes
- *
- * Array that maps from shape names to shape constructors. All entries
- * in <defaultShapes> are added to this array.
- */
-mxCellRenderer.prototype.shapes = null;
-
-/**
- * Variable: defaultEdgeShape
- *
- * Defines the default shape for edges. Default is <mxConnector>.
- */
-mxCellRenderer.prototype.defaultEdgeShape = mxConnector;
-
-/**
- * Variable: defaultVertexShape
- *
- * Defines the default shape for vertices. Default is <mxRectangleShape>.
- */
-mxCellRenderer.prototype.defaultVertexShape = mxRectangleShape;
-
-/**
- * Variable: defaultShapes
- *
- * Static array that contains the globally registered shapes which are
- * known to all instances of this class. For adding instance-specific
- * shapes you should use <registerShape> on the instance. For adding
- * a shape to this array you can use the following code:
- *
- * (code)
- * mxCellRenderer.prototype.defaultShapes['myshape'] = myShape;
- * (end)
- *
- * Where 'myshape' is the key under which the shape is to be registered
- * and myShape is the name of the constructor function.
- */
-mxCellRenderer.prototype.defaultShapes = new Object();
-
-// Adds default shapes into the default shapes array
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_ARROW] = mxArrow;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_RECTANGLE] = mxRectangleShape;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_ELLIPSE] = mxEllipse;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_DOUBLE_ELLIPSE] = mxDoubleEllipse;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_RHOMBUS] = mxRhombus;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_IMAGE] = mxImageShape;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_LINE] = mxLine;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_LABEL] = mxLabel;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_CYLINDER] = mxCylinder;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_SWIMLANE] = mxSwimlane;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_CONNECTOR] = mxConnector;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_ACTOR] = mxActor;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_CLOUD] = mxCloud;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_TRIANGLE] = mxTriangle;
-mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_HEXAGON] = mxHexagon;
-
-/**
- * Function: registerShape
- *
- * Registers the given constructor under the specified key in this instance
- * of the renderer.
- *
- * Example:
- *
- * (code)
- * this.registerShape(mxConstants.SHAPE_RECTANGLE, mxRectangleShape);
- * (end)
- *
- * Parameters:
- *
- * key - String representing the shape name.
- * shape - Constructor of the <mxShape> subclass.
- */
-mxCellRenderer.prototype.registerShape = function(key, shape)
-{
- this.shapes[key] = shape;
-};
-
-/**
- * Function: initialize
- *
- * Initializes the display for the given cell state. This is required once
- * after the cell state has been created. This is invoked in
- * mxGraphView.createState.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the display should be initialized.
- * rendering - Optional boolean that specifies if the cell should actually
- * be initialized for any given DOM node. If this is false then init
- * will not be called on the shape.
- */
-mxCellRenderer.prototype.initialize = function(state, rendering)
-{
- var model = state.view.graph.getModel();
-
- if (state.view.graph.container != null && state.shape == null &&
- state.cell != state.view.currentRoot &&
- (model.isVertex(state.cell) || model.isEdge(state.cell)))
- {
- this.createShape(state);
-
- if (state.shape != null && (rendering == null || rendering))
- {
- this.initializeShape(state);
-
- // Maintains the model order in the DOM
- if (state.view.graph.ordered || model.isEdge(state.cell))
- {
- //state.orderChanged = true;
- state.invalidOrder = true;
- }
- else if (state.view.graph.keepEdgesInForeground && this.firstEdge != null)
- {
- if (this.firstEdge.parentNode == state.shape.node.parentNode)
- {
- this.insertState(state, this.firstEdge);
- }
- else
- {
- this.firstEdge = null;
- }
- }
-
- state.shape.scale = state.view.scale;
-
- this.createCellOverlays(state);
- this.installListeners(state);
- }
- }
-};
-
-/**
- * Function: initializeShape
- *
- * Initializes the shape in the given state by calling its init method with
- * the correct container.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the shape should be initialized.
- */
-mxCellRenderer.prototype.initializeShape = function(state)
-{
- state.shape.init(state.view.getDrawPane());
-};
-
-/**
- * Returns the previous state that has a shape inside the given parent.
- */
-mxCellRenderer.prototype.getPreviousStateInContainer = function(state, container)
-{
- var result = null;
- var graph = state.view.graph;
- var model = graph.getModel();
- var child = state.cell;
- var p = model.getParent(child);
-
- while (p != null && result == null)
- {
- result = this.findPreviousStateInContainer(graph, p, child, container);
- child = p;
- p = model.getParent(child);
- }
-
- return result;
-};
-
-/**
- * Returns the previous state that has a shape inside the given parent.
- */
-mxCellRenderer.prototype.findPreviousStateInContainer = function(graph, cell, stop, container)
-{
- // Recurse first
- var result = null;
- var model = graph.getModel();
-
- if (stop != null)
- {
- var start = cell.getIndex(stop);
-
- for (var i = start - 1; i >= 0 && result == null; i--)
- {
- result = this.findPreviousStateInContainer(graph, model.getChildAt(cell, i), null, container);
- }
- }
- else
- {
- var childCount = model.getChildCount(cell);
-
- for (var i = childCount - 1; i >= 0 && result == null; i--)
- {
- result = this.findPreviousStateInContainer(graph, model.getChildAt(cell, i), null, container);
- }
- }
-
- if (result == null)
- {
- result = graph.view.getState(cell);
-
- if (result != null && (result.shape == null || result.shape.node == null ||
- result.shape.node.parentNode != container))
- {
- result = null;
- }
- }
-
- return result;
-};
-
-/**
- * Function: order
- *
- * Orders the DOM node of the shape for the given state according to the
- * position of the corresponding cell in the graph model.
- *
- * Parameters:
- *
- * state - <mxCellState> whose shape's DOM node should be ordered.
- */
-mxCellRenderer.prototype.order = function(state)
-{
- var container = state.shape.node.parentNode;
- var previous = this.getPreviousStateInContainer(state, container);
- var nextNode = container.firstChild;
-
- if (previous != null)
- {
- nextNode = previous.shape.node;
-
- if (previous.text != null && previous.text.node != null &&
- previous.text.node.parentNode == container)
- {
- nextNode = previous.text.node;
- }
-
- nextNode = nextNode.nextSibling;
- }
-
- this.insertState(state, nextNode);
-};
-
-/**
- * Function: orderEdge
- *
- * Orders the DOM node of the shape for the given edge's state according to
- * the <mxGraph.keepEdgesInBackground> and <mxGraph.keepEdgesInBackground>
- * rules.
- *
- * Parameters:
- *
- * state - <mxCellState> whose shape's DOM node should be ordered.
- */
-mxCellRenderer.prototype.orderEdge = function(state)
-{
- var view = state.view;
- var model = view.graph.getModel();
-
- // Moves edges to the foreground/background
- if (view.graph.keepEdgesInForeground)
- {
- if (this.firstEdge == null || this.firstEdge.parentNode == null ||
- this.firstEdge.parentNode != state.shape.node.parentNode)
- {
- this.firstEdge = state.shape.node;
- }
- }
- else if (view.graph.keepEdgesInBackground)
- {
- var node = state.shape.node;
- var parent = node.parentNode;
-
- // Keeps the DOM node in front of its parent
- var pcell = model.getParent(state.cell);
- var pstate = view.getState(pcell);
-
- if (pstate != null && pstate.shape != null && pstate.shape.node != null)
- {
- var child = pstate.shape.node.nextSibling;
-
- if (child != null && child != node)
- {
- this.insertState(state, child);
- }
- }
- else
- {
- var child = parent.firstChild;
-
- if (child != null && child != node)
- {
- this.insertState(state, child);
- }
- }
- }
-};
-
-/**
- * Function: insertState
- *
- * Inserts the given state before the given node into its parent.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the shape should be created.
- */
-mxCellRenderer.prototype.insertState = function(state, nextNode)
-{
- state.shape.node.parentNode.insertBefore(state.shape.node, nextNode);
-
- if (state.text != null && state.text.node != null &&
- state.text.node.parentNode == state.shape.node.parentNode)
- {
- state.shape.node.parentNode.insertBefore(state.text.node, state.shape.node.nextSibling);
- }
-};
-
-/**
- * Function: createShape
- *
- * Creates the shape for the given cell state. The shape is configured
- * using <configureShape>.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the shape should be created.
- */
-mxCellRenderer.prototype.createShape = function(state)
-{
- if (state.style != null)
- {
- // Checks if there is a stencil for the name and creates
- // a shape instance for the stencil if one exists
- var key = state.style[mxConstants.STYLE_SHAPE];
- var stencil = mxStencilRegistry.getStencil(key);
-
- if (stencil != null)
- {
- state.shape = new mxStencilShape(stencil);
- }
- else
- {
- var ctor = this.getShapeConstructor(state);
- state.shape = new ctor();
- }
-
- // Sets the initial bounds and points (will be updated in redraw)
- state.shape.points = state.absolutePoints;
- state.shape.bounds = new mxRectangle(
- state.x, state.y, state.width, state.height);
- state.shape.dialect = state.view.graph.dialect;
-
- this.configureShape(state);
- }
-};
-
-/**
- * Function: getShapeConstructor
- *
- * Returns the constructor to be used for creating the shape.
- */
-mxCellRenderer.prototype.getShapeConstructor = function(state)
-{
- var key = state.style[mxConstants.STYLE_SHAPE];
- var ctor = (key != null) ? this.shapes[key] : null;
-
- if (ctor == null)
- {
- ctor = (state.view.graph.getModel().isEdge(state.cell)) ?
- this.defaultEdgeShape : this.defaultVertexShape;
- }
-
- return ctor;
-};
-
-/**
- * Function: configureShape
- *
- * Configures the shape for the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the shape should be configured.
- */
-mxCellRenderer.prototype.configureShape = function(state)
-{
- state.shape.apply(state);
- var image = state.view.graph.getImage(state);
-
- if (image != null)
- {
- state.shape.image = image;
- }
-
- var indicator = state.view.graph.getIndicatorColor(state);
- var key = state.view.graph.getIndicatorShape(state);
- var ctor = (key != null) ? this.shapes[key] : null;
-
- // Configures the indicator shape or image
- if (indicator != null)
- {
- state.shape.indicatorShape = ctor;
- state.shape.indicatorColor = indicator;
- state.shape.indicatorGradientColor =
- state.view.graph.getIndicatorGradientColor(state);
- state.shape.indicatorDirection =
- state.style[mxConstants.STYLE_INDICATOR_DIRECTION];
- }
- else
- {
- var indicator = state.view.graph.getIndicatorImage(state);
-
- if (indicator != null)
- {
- state.shape.indicatorImage = indicator;
- }
- }
-
- this.postConfigureShape(state);
-};
-
-/**
- * Function: postConfigureShape
- *
- * Replaces any reserved words used for attributes, eg. inherit,
- * indicated or swimlane for colors in the shape for the given state.
- * This implementation resolves these keywords on the fill, stroke
- * and gradient color keys.
- */
-mxCellRenderer.prototype.postConfigureShape = function(state)
-{
- if (state.shape != null)
- {
- this.resolveColor(state, 'indicatorColor', mxConstants.STYLE_FILLCOLOR);
- this.resolveColor(state, 'indicatorGradientColor', mxConstants.STYLE_GRADIENTCOLOR);
- this.resolveColor(state, 'fill', mxConstants.STYLE_FILLCOLOR);
- this.resolveColor(state, 'stroke', mxConstants.STYLE_STROKECOLOR);
- this.resolveColor(state, 'gradient', mxConstants.STYLE_GRADIENTCOLOR);
- }
-};
-
-/**
- * Function: resolveColor
- *
- * Resolves special keywords 'inherit', 'indicated' and 'swimlane' and sets
- * the respective color on the shape.
- */
-mxCellRenderer.prototype.resolveColor = function(state, field, key)
-{
- var value = state.shape[field];
- var graph = state.view.graph;
- var referenced = null;
-
- if (value == 'inherit')
- {
- referenced = graph.model.getParent(state.cell);
- }
- else if (value == 'swimlane')
- {
- if (graph.model.getTerminal(state.cell, false) != null)
- {
- referenced = graph.model.getTerminal(state.cell, false);
- }
- else
- {
- referenced = state.cell;
- }
-
- referenced = graph.getSwimlane(referenced);
- key = graph.swimlaneIndicatorColorAttribute;
- }
- else if (value == 'indicated')
- {
- state.shape[field] = state.shape.indicatorColor;
- }
-
- if (referenced != null)
- {
- var rstate = graph.getView().getState(referenced);
- state.shape[field] = null;
-
- if (rstate != null)
- {
- if (rstate.shape != null && field != 'indicatorColor')
- {
- state.shape[field] = rstate.shape[field];
- }
- else
- {
- state.shape[field] = rstate.style[key];
- }
- }
- }
-};
-
-/**
- * Function: getLabelValue
- *
- * Returns the value to be used for the label.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the label should be created.
- */
-mxCellRenderer.prototype.getLabelValue = function(state)
-{
- var graph = state.view.graph;
- var value = graph.getLabel(state.cell);
-
- if (!graph.isHtmlLabel(state.cell) && !mxUtils.isNode(value) &&
- graph.dialect != mxConstants.DIALECT_SVG && value != null)
- {
- value = mxUtils.htmlEntities(value, false);
- }
-
- return value;
-};
-
-/**
- * Function: createLabel
- *
- * Creates the label for the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the label should be created.
- */
-mxCellRenderer.prototype.createLabel = function(state, value)
-{
- var graph = state.view.graph;
- var isEdge = graph.getModel().isEdge(state.cell);
-
- if (state.style[mxConstants.STYLE_FONTSIZE] > 0 ||
- state.style[mxConstants.STYLE_FONTSIZE] == null)
- {
- // Avoids using DOM node for empty labels
- var isForceHtml = (graph.isHtmlLabel(state.cell) ||
- (value != null && mxUtils.isNode(value))) &&
- graph.dialect == mxConstants.DIALECT_SVG;
-
- state.text = new mxText(value, new mxRectangle(),
- (state.style[mxConstants.STYLE_ALIGN] ||
- mxConstants.ALIGN_CENTER),
- graph.getVerticalAlign(state),
- state.style[mxConstants.STYLE_FONTCOLOR],
- state.style[mxConstants.STYLE_FONTFAMILY],
- state.style[mxConstants.STYLE_FONTSIZE],
- state.style[mxConstants.STYLE_FONTSTYLE],
- state.style[mxConstants.STYLE_SPACING],
- state.style[mxConstants.STYLE_SPACING_TOP],
- state.style[mxConstants.STYLE_SPACING_RIGHT],
- state.style[mxConstants.STYLE_SPACING_BOTTOM],
- state.style[mxConstants.STYLE_SPACING_LEFT],
- state.style[mxConstants.STYLE_HORIZONTAL],
- state.style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR],
- state.style[mxConstants.STYLE_LABEL_BORDERCOLOR],
- graph.isWrapping(state.cell) && graph.isHtmlLabel(state.cell),
- graph.isLabelClipped(state.cell),
- state.style[mxConstants.STYLE_OVERFLOW],
- state.style[mxConstants.STYLE_LABEL_PADDING]);
- state.text.opacity = state.style[mxConstants.STYLE_TEXT_OPACITY];
-
- state.text.dialect = (isForceHtml) ?
- mxConstants.DIALECT_STRICTHTML :
- state.view.graph.dialect;
- this.initializeLabel(state);
-
- // Workaround for touch devices routing all events for a mouse
- // gesture (down, move, up) via the initial DOM node. IE is even
- // worse in that it redirects the event via the initial DOM node
- // but the event source is the node under the mouse, so we need
- // to check if this is the case and force getCellAt for the
- // subsequent mouseMoves and the final mouseUp.
- var forceGetCell = false;
-
- var getState = function(evt)
- {
- var result = state;
-
- if (mxClient.IS_TOUCH || forceGetCell)
- {
- var x = mxEvent.getClientX(evt);
- var y = mxEvent.getClientY(evt);
-
- // Dispatches the drop event to the graph which
- // consumes and executes the source function
- var pt = mxUtils.convertPoint(graph.container, x, y);
- result = graph.view.getState(graph.getCellAt(pt.x, pt.y));
- }
-
- return result;
- };
-
- // TODO: Add handling for gestures
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- mxEvent.addListener(state.text.node, md,
- mxUtils.bind(this, function(evt)
- {
- if (this.isLabelEvent(state, evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_DOWN,
- new mxMouseEvent(evt, state));
- forceGetCell = graph.dialect != mxConstants.DIALECT_SVG && mxEvent.getSource(evt).nodeName == 'IMG';
- }
- })
- );
-
- mxEvent.addListener(state.text.node, mm,
- mxUtils.bind(this, function(evt)
- {
- if (this.isLabelEvent(state, evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
- new mxMouseEvent(evt, getState(evt)));
- }
- })
- );
-
- mxEvent.addListener(state.text.node, mu,
- mxUtils.bind(this, function(evt)
- {
- if (this.isLabelEvent(state, evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_UP,
- new mxMouseEvent(evt, getState(evt)));
- forceGetCell = false;
- }
- })
- );
-
- mxEvent.addListener(state.text.node, 'dblclick',
- mxUtils.bind(this, function(evt)
- {
- if (this.isLabelEvent(state, evt))
- {
- graph.dblClick(evt, state.cell);
- mxEvent.consume(evt);
- }
- })
- );
- }
-};
-
-/**
- * Function: initializeLabel
- *
- * Initiailzes the label with a suitable container.
- *
- * Parameters:
- *
- * state - <mxCellState> whose label should be initialized.
- */
-mxCellRenderer.prototype.initializeLabel = function(state)
-{
- var graph = state.view.graph;
-
- if (state.text.dialect != mxConstants.DIALECT_SVG)
- {
- // Adds the text to the container if the dialect is not SVG and we
- // have an SVG-based browser which doesn't support foreignObjects
- if (mxClient.IS_SVG && mxClient.NO_FO)
- {
- state.text.init(graph.container);
- }
- else if (mxUtils.isVml(state.view.getDrawPane()))
- {
- if (state.shape.label != null)
- {
- state.text.init(state.shape.label);
- }
- else
- {
- state.text.init(state.shape.node);
- }
- }
- }
-
- if (state.text.node == null)
- {
- state.text.init(state.view.getDrawPane());
-
- if (state.shape != null && state.text != null)
- {
- state.shape.node.parentNode.insertBefore(
- state.text.node, state.shape.node.nextSibling);
- }
- }
-};
-
-/**
- * Function: createCellOverlays
- *
- * Creates the actual shape for showing the overlay for the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the overlay should be created.
- */
-mxCellRenderer.prototype.createCellOverlays = function(state)
-{
- var graph = state.view.graph;
- var overlays = graph.getCellOverlays(state.cell);
- var dict = null;
-
- if (overlays != null)
- {
- dict = new mxDictionary();
-
- for (var i = 0; i < overlays.length; i++)
- {
- var shape = (state.overlays != null) ? state.overlays.remove(overlays[i]) : null;
-
- if (shape == null)
- {
- var tmp = new mxImageShape(new mxRectangle(),
- overlays[i].image.src);
- tmp.dialect = state.view.graph.dialect;
- tmp.preserveImageAspect = false;
- tmp.overlay = overlays[i];
- this.initializeOverlay(state, tmp);
- this.installCellOverlayListeners(state, overlays[i], tmp);
-
- if (overlays[i].cursor != null)
- {
- tmp.node.style.cursor = overlays[i].cursor;
- }
-
- dict.put(overlays[i], tmp);
- }
- else
- {
- dict.put(overlays[i], shape);
- }
- }
- }
-
- // Removes unused
- if (state.overlays != null)
- {
- state.overlays.visit(function(id, shape)
- {
- shape.destroy();
- });
- }
-
- state.overlays = dict;
-};
-
-/**
- * Function: initializeOverlay
- *
- * Initializes the given overlay.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the overlay should be created.
- * overlay - <mxImageShape> that represents the overlay.
- */
-mxCellRenderer.prototype.initializeOverlay = function(state, overlay)
-{
- overlay.init(state.view.getOverlayPane());
-};
-
-/**
- * Function: installOverlayListeners
- *
- * Installs the listeners for the given <mxCellState>, <mxCellOverlay> and
- * <mxShape> that represents the overlay.
- */
-mxCellRenderer.prototype.installCellOverlayListeners = function(state, overlay, shape)
-{
- var graph = state.view.graph;
-
- mxEvent.addListener(shape.node, 'click', function (evt)
- {
- if (graph.isEditing())
- {
- graph.stopEditing(!graph.isInvokesStopCellEditing());
- }
-
- overlay.fireEvent(new mxEventObject(mxEvent.CLICK,
- 'event', evt, 'cell', state.cell));
- });
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
-
- mxEvent.addListener(shape.node, md, function (evt)
- {
- mxEvent.consume(evt);
- });
-
- mxEvent.addListener(shape.node, mm, function (evt)
- {
- graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
- new mxMouseEvent(evt, state));
- });
-
- if (mxClient.IS_TOUCH)
- {
- mxEvent.addListener(shape.node, 'touchend', function (evt)
- {
- overlay.fireEvent(new mxEventObject(mxEvent.CLICK,
- 'event', evt, 'cell', state.cell));
- });
- }
-};
-
-/**
- * Function: createControl
- *
- * Creates the control for the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the control should be created.
- */
-mxCellRenderer.prototype.createControl = function(state)
-{
- var graph = state.view.graph;
- var image = graph.getFoldingImage(state);
-
- if (graph.foldingEnabled && image != null)
- {
- if (state.control == null)
- {
- var b = new mxRectangle(0, 0, image.width, image.height);
- state.control = new mxImageShape(b, image.src);
- state.control.dialect = graph.dialect;
- state.control.preserveImageAspect = false;
-
- this.initControl(state, state.control, true, function (evt)
- {
- if (graph.isEnabled())
- {
- var collapse = !graph.isCellCollapsed(state.cell);
- graph.foldCells(collapse, false, [state.cell]);
- mxEvent.consume(evt);
- }
- });
- }
- }
- else if (state.control != null)
- {
- state.control.destroy();
- state.control = null;
- }
-};
-
-/**
- * Function: initControl
- *
- * Initializes the given control and returns the corresponding DOM node.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the control should be initialized.
- * control - <mxShape> to be initialized.
- * handleEvents - Boolean indicating if mousedown and mousemove should fire events via the graph.
- * clickHandler - Optional function to implement clicks on the control.
- */
-mxCellRenderer.prototype.initControl = function(state, control, handleEvents, clickHandler)
-{
- var graph = state.view.graph;
-
- // In the special case where the label is in HTML and the display is SVG the image
- // should go into the graph container directly in order to be clickable. Otherwise
- // it is obscured by the HTML label that overlaps the cell.
- var isForceHtml = graph.isHtmlLabel(state.cell) &&
- mxClient.NO_FO &&
- graph.dialect == mxConstants.DIALECT_SVG;
-
- if (isForceHtml)
- {
- control.dialect = mxConstants.DIALECT_PREFERHTML;
- control.init(graph.container);
- control.node.style.zIndex = 1;
- }
- else
- {
- control.init(state.view.getOverlayPane());
- }
-
- var node = control.innerNode || control.node;
-
- if (clickHandler)
- {
- if (graph.isEnabled())
- {
- node.style.cursor = 'pointer';
- }
-
- mxEvent.addListener(node, 'click', clickHandler);
- }
-
- if (handleEvents)
- {
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
-
- mxEvent.addListener(node, md, function (evt)
- {
- graph.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt, state));
- mxEvent.consume(evt);
- });
-
- mxEvent.addListener(node, mm, function (evt)
- {
- graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt, state));
- });
- }
-
- return node;
-};
-
-/**
- * Function: isShapeEvent
- *
- * Returns true if the event is for the shape of the given state. This
- * implementation always returns true.
- *
- * Parameters:
- *
- * state - <mxCellState> whose shape fired the event.
- * evt - Mouse event which was fired.
- */
-mxCellRenderer.prototype.isShapeEvent = function(state, evt)
-{
- return true;
-};
-
-/**
- * Function: isLabelEvent
- *
- * Returns true if the event is for the label of the given state. This
- * implementation always returns true.
- *
- * Parameters:
- *
- * state - <mxCellState> whose label fired the event.
- * evt - Mouse event which was fired.
- */
-mxCellRenderer.prototype.isLabelEvent = function(state, evt)
-{
- return true;
-};
-
-/**
- * Function: installListeners
- *
- * Installs the event listeners for the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the event listeners should be isntalled.
- */
-mxCellRenderer.prototype.installListeners = function(state)
-{
- var graph = state.view.graph;
-
- // Receives events from transparent backgrounds
- if (graph.dialect == mxConstants.DIALECT_SVG)
- {
- var events = 'all';
-
- // Disabled fill-events on non-filled edges
- if (graph.getModel().isEdge(state.cell) && state.shape.stroke != null &&
- (state.shape.fill == null || state.shape.fill == mxConstants.NONE))
- {
- events = 'visibleStroke';
- }
-
- // Specifies the event-processing on the shape
- if (state.shape.innerNode != null)
- {
- state.shape.innerNode.setAttribute('pointer-events', events);
- }
- else
- {
- state.shape.node.setAttribute('pointer-events', events);
- }
- }
-
- // Workaround for touch devices routing all events for a mouse
- // gesture (down, move, up) via the initial DOM node. Same for
- // HTML images in all IE versions (VML images are working).
- var getState = function(evt)
- {
- var result = state;
-
- if ((graph.dialect != mxConstants.DIALECT_SVG && mxEvent.getSource(evt).nodeName == 'IMG') || mxClient.IS_TOUCH)
- {
- var x = mxEvent.getClientX(evt);
- var y = mxEvent.getClientY(evt);
-
- // Dispatches the drop event to the graph which
- // consumes and executes the source function
- var pt = mxUtils.convertPoint(graph.container, x, y);
- result = graph.view.getState(graph.getCellAt(pt.x, pt.y));
- }
-
- return result;
- };
-
- // Experimental support for two-finger pinch to resize cells
- var gestureInProgress = false;
-
- mxEvent.addListener(state.shape.node, 'gesturestart',
- mxUtils.bind(this, function(evt)
- {
- // FIXME: Breaks encapsulation to reset the double
- // tap event handling when gestures take place
- graph.lastTouchTime = 0;
-
- gestureInProgress = true;
- mxEvent.consume(evt);
- })
- );
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- mxEvent.addListener(state.shape.node, md,
- mxUtils.bind(this, function(evt)
- {
- if (this.isShapeEvent(state, evt) && !gestureInProgress)
- {
- // Redirects events from the "event-transparent" region of
- // a swimlane to the graph. This is only required in HTML,
- // SVG and VML do not fire mouse events on transparent
- // backgrounds.
- graph.fireMouseEvent(mxEvent.MOUSE_DOWN,
- new mxMouseEvent(evt, (state.shape != null &&
- mxEvent.getSource(evt) == state.shape.content) ?
- null : state));
- }
- else if (gestureInProgress)
- {
- mxEvent.consume(evt);
- }
- })
- );
-
- mxEvent.addListener(state.shape.node, mm,
- mxUtils.bind(this, function(evt)
- {
- if (this.isShapeEvent(state, evt) && !gestureInProgress)
- {
- graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
- new mxMouseEvent(evt, (state.shape != null &&
- mxEvent.getSource(evt) == state.shape.content) ?
- null : getState(evt)));
- }
- else if (gestureInProgress)
- {
- mxEvent.consume(evt);
- }
- })
- );
-
- mxEvent.addListener(state.shape.node, mu,
- mxUtils.bind(this, function(evt)
- {
- if (this.isShapeEvent(state, evt) && !gestureInProgress)
- {
- graph.fireMouseEvent(mxEvent.MOUSE_UP,
- new mxMouseEvent(evt, (state.shape != null &&
- mxEvent.getSource(evt) == state.shape.content) ?
- null : getState(evt)));
- }
- else if (gestureInProgress)
- {
- mxEvent.consume(evt);
- }
- })
- );
-
- // Experimental handling for gestures. Double-tap handling is implemented
- // in mxGraph.fireMouseEvent.
- var dc = (mxClient.IS_TOUCH) ? 'gestureend' : 'dblclick';
-
- mxEvent.addListener(state.shape.node, dc,
- mxUtils.bind(this, function(evt)
- {
- gestureInProgress = false;
-
- if (dc == 'gestureend')
- {
- // FIXME: Breaks encapsulation to reset the double
- // tap event handling when gestures take place
- graph.lastTouchTime = 0;
-
- if (graph.gestureEnabled)
- {
- graph.handleGesture(state, evt);
- mxEvent.consume(evt);
- }
- }
- else if (this.isShapeEvent(state, evt))
- {
- graph.dblClick(evt, (state.shape != null &&
- mxEvent.getSource(evt) == state.shape.content) ?
- null : state.cell);
- mxEvent.consume(evt);
- }
- })
- );
-};
-
-/**
- * Function: redrawLabel
- *
- * Redraws the label for the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> whose label should be redrawn.
- */
-mxCellRenderer.prototype.redrawLabel = function(state)
-{
- var value = this.getLabelValue(state);
-
- // FIXME: Add label always if HTML label and NO_FO
- if (state.text == null && value != null && (mxUtils.isNode(value) || value.length > 0))
- {
- this.createLabel(state, value);
- }
- else if (state.text != null && (value == null || value.length == 0))
- {
- state.text.destroy();
- state.text = null;
- }
-
- if (state.text != null)
- {
- var graph = state.view.graph;
- var wrapping = graph.isWrapping(state.cell);
- var clipping = graph.isLabelClipped(state.cell);
- var bounds = this.getLabelBounds(state);
-
- if (state.text.value != value || state.text.isWrapping != wrapping ||
- state.text.isClipping != clipping || state.text.scale != state.view.scale ||
- !state.text.bounds.equals(bounds))
- {
- state.text.value = value;
- state.text.bounds = bounds;
- state.text.scale = this.getTextScale(state);
- state.text.isWrapping = wrapping;
- state.text.isClipping = clipping;
-
- state.text.redraw();
- }
- }
-};
-
-/**
- * Function: getTextScale
- *
- * Returns the scaling used for the label of the given state
- *
- * Parameters:
- *
- * state - <mxCellState> whose label scale should be returned.
- */
-mxCellRenderer.prototype.getTextScale = function(state)
-{
- return state.view.scale;
-};
-
-/**
- * Function: getLabelBounds
- *
- * Returns the bounds to be used to draw the label of the given state.
- *
- * Parameters:
- *
- * state - <mxCellState> whose label bounds should be returned.
- */
-mxCellRenderer.prototype.getLabelBounds = function(state)
-{
- var graph = state.view.graph;
- var isEdge = graph.getModel().isEdge(state.cell);
- var bounds = new mxRectangle(state.absoluteOffset.x, state.absoluteOffset.y);
-
- if (!isEdge)
- {
- bounds.x += state.x;
- bounds.y += state.y;
-
- // Minimum of 1 fixes alignment bug in HTML labels
- bounds.width = Math.max(1, state.width);
- bounds.height = Math.max(1, state.height);
-
- if (graph.isSwimlane(state.cell))
- {
- var scale = graph.view.scale;
- var size = graph.getStartSize(state.cell);
-
- if (size.width > 0)
- {
- bounds.width = size.width * scale;
- }
- else if (size.height > 0)
- {
- bounds.height = size.height * scale;
- }
- }
- }
-
- return bounds;
-};
-
-/**
- * Function: redrawCellOverlays
- *
- * Redraws the overlays for the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> whose overlays should be redrawn.
- */
-mxCellRenderer.prototype.redrawCellOverlays = function(state)
-{
- this.createCellOverlays(state);
-
- if (state.overlays != null)
- {
- state.overlays.visit(function(id, shape)
- {
- var bounds = shape.overlay.getBounds(state);
-
- if (shape.bounds == null || shape.scale != state.view.scale ||
- !shape.bounds.equals(bounds))
- {
- shape.bounds = bounds;
- shape.scale = state.view.scale;
- shape.redraw();
- }
- });
- }
-};
-
-/**
- * Function: redrawControl
- *
- * Redraws the control for the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> whose control should be redrawn.
- */
-mxCellRenderer.prototype.redrawControl = function(state)
-{
- if (state.control != null)
- {
- var bounds = this.getControlBounds(state);
- var s = state.view.scale;
-
- if (state.control.scale != s || !state.control.bounds.equals(bounds))
- {
- state.control.bounds = bounds;
- state.control.scale = s;
- state.control.redraw();
- }
- }
-};
-
-/**
- * Function: getControlBounds
- *
- * Returns the bounds to be used to draw the control (folding icon) of the
- * given state.
- */
-mxCellRenderer.prototype.getControlBounds = function(state)
-{
- if (state.control != null)
- {
- var oldScale = state.control.scale;
- var w = state.control.bounds.width / oldScale;
- var h = state.control.bounds.height / oldScale;
- var s = state.view.scale;
-
- return (state.view.graph.getModel().isEdge(state.cell)) ?
- new mxRectangle(state.x + state.width / 2 - w / 2 * s,
- state.y + state.height / 2 - h / 2 * s, w * s, h * s)
- : new mxRectangle(state.x + w / 2 * s,
- state.y + h / 2 * s, w * s, h * s);
- }
-
- return null;
-};
-
-/**
- * Function: redraw
- *
- * Updates the bounds or points and scale of the shapes for the given cell
- * state. This is called in mxGraphView.validatePoints as the last step of
- * updating all cells.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the shapes should be updated.
- * force - Optional boolean that specifies if the cell should be reconfiured
- * and redrawn without any additional checks.
- * rendering - Optional boolean that specifies if the cell should actually
- * be drawn into the DOM. If this is false then redraw and/or reconfigure
- * will not be called on the shape.
- */
-mxCellRenderer.prototype.redraw = function(state, force, rendering)
-{
- if (state.shape != null)
- {
- var model = state.view.graph.getModel();
- var isEdge = model.isEdge(state.cell);
- reconfigure = (force != null) ? force : false;
-
- // Handles changes of the collapse icon
- this.createControl(state);
-
- // Handles changes to the order in the DOM
- if (state.orderChanged || state.invalidOrder)
- {
- if (state.view.graph.ordered)
- {
- this.order(state);
- }
- else
- {
- // Assert state.cell is edge
- this.orderEdge(state);
- }
-
- // Required to update inherited styles
- reconfigure = state.orderChanged;
- }
-
- delete state.invalidOrder;
- delete state.orderChanged;
-
- // Checks if the style in the state is different from the style
- // in the shape and re-applies the style if required
- if (!reconfigure && !mxUtils.equalEntries(state.shape.style, state.style))
- {
- reconfigure = true;
- }
-
- // Reconfiures the shape after an order or style change
- if (reconfigure)
- {
- this.configureShape(state);
- state.shape.reconfigure();
- }
-
- // Redraws the cell if required
- if (force || state.shape.bounds == null || state.shape.scale != state.view.scale ||
- !state.shape.bounds.equals(state) ||
- !mxUtils.equalPoints(state.shape.points, state.absolutePoints))
- {
- // FIXME: Move indicator color update into shape.redraw
-// var indicator = state.view.graph.getIndicatorColor(state);
-// if (indicator != null)
-// {
-// state.shape.indicatorColor = indicator;
-// }
-
- if (state.absolutePoints != null)
- {
- state.shape.points = state.absolutePoints.slice();
- }
- else
- {
- state.shape.points = null;
- }
-
- state.shape.bounds = new mxRectangle(
- state.x, state.y, state.width, state.height);
- state.shape.scale = state.view.scale;
-
- if (rendering == null || rendering)
- {
- state.shape.redraw();
- }
- else
- {
- state.shape.updateBoundingBox();
- }
- }
-
- // Updates the text label, overlays and control
- if (rendering == null || rendering)
- {
- this.redrawLabel(state);
- this.redrawCellOverlays(state);
- this.redrawControl(state);
- }
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the shapes associated with the given cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> for which the shapes should be destroyed.
- */
-mxCellRenderer.prototype.destroy = function(state)
-{
- if (state.shape != null)
- {
- if (state.text != null)
- {
- state.text.destroy();
- state.text = null;
- }
-
- if (state.overlays != null)
- {
- state.overlays.visit(function(id, shape)
- {
- shape.destroy();
- });
-
- state.overlays = null;
- }
-
- if (state.control != null)
- {
- state.control.destroy();
- state.control = null;
- }
-
- state.shape.destroy();
- state.shape = null;
- }
-};
diff --git a/src/js/view/mxCellState.js b/src/js/view/mxCellState.js
deleted file mode 100644
index 7e7a3b0..0000000
--- a/src/js/view/mxCellState.js
+++ /dev/null
@@ -1,375 +0,0 @@
-/**
- * $Id: mxCellState.js,v 1.42 2012-03-19 10:47:08 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxCellState
- *
- * Represents the current state of a cell in a given <mxGraphView>.
- *
- * For edges, the edge label position is stored in <absoluteOffset>.
- *
- * The size for oversize labels can be retrieved using the boundingBox property
- * of the <text> field as shown below.
- *
- * (code)
- * var bbox = (state.text != null) ? state.text.boundingBox : null;
- * (end)
- *
- * Constructor: mxCellState
- *
- * Constructs a new object that represents the current state of the given
- * cell in the specified view.
- *
- * Parameters:
- *
- * view - <mxGraphView> that contains the state.
- * cell - <mxCell> that this state represents.
- * style - Array of key, value pairs that constitute the style.
- */
-function mxCellState(view, cell, style)
-{
- this.view = view;
- this.cell = cell;
- this.style = style;
-
- this.origin = new mxPoint();
- this.absoluteOffset = new mxPoint();
-};
-
-/**
- * Extends mxRectangle.
- */
-mxCellState.prototype = new mxRectangle();
-mxCellState.prototype.constructor = mxCellState;
-
-/**
- * Variable: view
- *
- * Reference to the enclosing <mxGraphView>.
- */
-mxCellState.prototype.view = null;
-
-/**
- * Variable: cell
- *
- * Reference to the <mxCell> that is represented by this state.
- */
-mxCellState.prototype.cell = null;
-
-/**
- * Variable: style
- *
- * Contains an array of key, value pairs that represent the style of the
- * cell.
- */
-mxCellState.prototype.style = null;
-
-/**
- * Variable: invalid
- *
- * Specifies if the state is invalid. Default is true.
- */
-mxCellState.prototype.invalid = true;
-
-/**
- * Variable: invalidOrder
- *
- * Specifies if the cell has an invalid order. For internal use. Default is
- * false.
- */
-mxCellState.prototype.invalidOrder = false;
-
-/**
- * Variable: orderChanged
- *
- * Specifies if the cell has changed order and the display needs to be
- * updated.
- */
-mxCellState.prototype.orderChanged = false;
-
-/**
- * Variable: origin
- *
- * <mxPoint> that holds the origin for all child cells. Default is a new
- * empty <mxPoint>.
- */
-mxCellState.prototype.origin = null;
-
-/**
- * Variable: absolutePoints
- *
- * Holds an array of <mxPoints> that represent the absolute points of an
- * edge.
- */
-mxCellState.prototype.absolutePoints = null;
-
-/**
- * Variable: absoluteOffset
- *
- * <mxPoint> that holds the absolute offset. For edges, this is the
- * absolute coordinates of the label position. For vertices, this is the
- * offset of the label relative to the top, left corner of the vertex.
- */
-mxCellState.prototype.absoluteOffset = null;
-
-/**
- * Variable: visibleSourceState
- *
- * Caches the visible source terminal state.
- */
-mxCellState.prototype.visibleSourceState = null;
-
-/**
- * Variable: visibleTargetState
- *
- * Caches the visible target terminal state.
- */
-mxCellState.prototype.visibleTargetState = null;
-
-/**
- * Variable: terminalDistance
- *
- * Caches the distance between the end points for an edge.
- */
-mxCellState.prototype.terminalDistance = 0;
-
-/**
- * Variable: length
- *
- * Caches the length of an edge.
- */
-mxCellState.prototype.length = 0;
-
-/**
- * Variable: segments
- *
- * Array of numbers that represent the cached length of each segment of the
- * edge.
- */
-mxCellState.prototype.segments = null;
-
-/**
- * Variable: shape
- *
- * Holds the <mxShape> that represents the cell graphically.
- */
-mxCellState.prototype.shape = null;
-
-/**
- * Variable: text
- *
- * Holds the <mxText> that represents the label of the cell. Thi smay be
- * null if the cell has no label.
- */
-mxCellState.prototype.text = null;
-
-/**
- * Function: getPerimeterBounds
- *
- * Returns the <mxRectangle> that should be used as the perimeter of the
- * cell.
- *
- * Parameters:
- *
- * border - Optional border to be added around the perimeter bounds.
- * bounds - Optional <mxRectangle> to be used as the initial bounds.
- */
-mxCellState.prototype.getPerimeterBounds = function (border, bounds)
-{
- border = border || 0;
- bounds = (bounds != null) ? bounds : new mxRectangle(this.x, this.y, this.width, this.height);
-
- if (this.shape != null && this.shape.stencil != null)
- {
- var aspect = this.shape.stencil.computeAspect(this, bounds, null);
-
- bounds.x = aspect.x;
- bounds.y = aspect.y;
- bounds.width = this.shape.stencil.w0 * aspect.width;
- bounds.height = this.shape.stencil.h0 * aspect.height;
- }
-
- if (border != 0)
- {
- bounds.grow(border);
- }
-
- return bounds;
-};
-
-/**
- * Function: setAbsoluteTerminalPoint
- *
- * Sets the first or last point in <absolutePoints> depending on isSource.
- *
- * Parameters:
- *
- * point - <mxPoint> that represents the terminal point.
- * isSource - Boolean that specifies if the first or last point should
- * be assigned.
- */
-mxCellState.prototype.setAbsoluteTerminalPoint = function (point, isSource)
-{
- if (isSource)
- {
- if (this.absolutePoints == null)
- {
- this.absolutePoints = [];
- }
-
- if (this.absolutePoints.length == 0)
- {
- this.absolutePoints.push(point);
- }
- else
- {
- this.absolutePoints[0] = point;
- }
- }
- else
- {
- if (this.absolutePoints == null)
- {
- this.absolutePoints = [];
- this.absolutePoints.push(null);
- this.absolutePoints.push(point);
- }
- else if (this.absolutePoints.length == 1)
- {
- this.absolutePoints.push(point);
- }
- else
- {
- this.absolutePoints[this.absolutePoints.length - 1] = point;
- }
- }
-};
-
-/**
- * Function: setCursor
- *
- * Sets the given cursor on the shape and text shape.
- */
-mxCellState.prototype.setCursor = function (cursor)
-{
- if (this.shape != null)
- {
- this.shape.setCursor(cursor);
- }
-
- if (this.text != null)
- {
- this.text.setCursor(cursor);
- }
-};
-
-/**
- * Function: getVisibleTerminal
- *
- * Returns the visible source or target terminal cell.
- *
- * Parameters:
- *
- * source - Boolean that specifies if the source or target cell should be
- * returned.
- */
-mxCellState.prototype.getVisibleTerminal = function (source)
-{
- var tmp = this.getVisibleTerminalState(source);
-
- return (tmp != null) ? tmp.cell : null;
-};
-
-/**
- * Function: getVisibleTerminalState
- *
- * Returns the visible source or target terminal state.
- *
- * Parameters:
- *
- * source - Boolean that specifies if the source or target state should be
- * returned.
- */
-mxCellState.prototype.getVisibleTerminalState = function (source)
-{
- return (source) ? this.visibleSourceState : this.visibleTargetState;
-};
-
-/**
- * Function: setVisibleTerminalState
- *
- * Sets the visible source or target terminal state.
- *
- * Parameters:
- *
- * terminalState - <mxCellState> that represents the terminal.
- * source - Boolean that specifies if the source or target state should be set.
- */
-mxCellState.prototype.setVisibleTerminalState = function (terminalState, source)
-{
- if (source)
- {
- this.visibleSourceState = terminalState;
- }
- else
- {
- this.visibleTargetState = terminalState;
- }
-};
-
-/**
- * Destructor: destroy
- *
- * Destroys the state and all associated resources.
- */
-mxCellState.prototype.destroy = function ()
-{
- this.view.graph.cellRenderer.destroy(this);
-};
-
-/**
- * Function: clone
- *
- * Returns a clone of this <mxPoint>.
- */
-mxCellState.prototype.clone = function()
-{
- var clone = new mxCellState(this.view, this.cell, this.style);
-
- // Clones the absolute points
- if (this.absolutePoints != null)
- {
- clone.absolutePoints = [];
-
- for (var i = 0; i < this.absolutePoints.length; i++)
- {
- clone.absolutePoints[i] = this.absolutePoints[i].clone();
- }
- }
-
- if (this.origin != null)
- {
- clone.origin = this.origin.clone();
- }
-
- if (this.absoluteOffset != null)
- {
- clone.absoluteOffset = this.absoluteOffset.clone();
- }
-
- if (this.boundingBox != null)
- {
- clone.boundingBox = this.boundingBox.clone();
- }
-
- clone.terminalDistance = this.terminalDistance;
- clone.segments = this.segments;
- clone.length = this.length;
- clone.x = this.x;
- clone.y = this.y;
- clone.width = this.width;
- clone.height = this.height;
-
- return clone;
-};
diff --git a/src/js/view/mxCellStatePreview.js b/src/js/view/mxCellStatePreview.js
deleted file mode 100644
index b853748..0000000
--- a/src/js/view/mxCellStatePreview.js
+++ /dev/null
@@ -1,223 +0,0 @@
-/**
- * $Id: mxCellStatePreview.js,v 1.6 2012-10-26 07:19:11 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- *
- * Class: mxCellStatePreview
- *
- * Implements a live preview for moving cells.
- *
- * Constructor: mxCellStatePreview
- *
- * Constructs a move preview for the given graph.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- */
-function mxCellStatePreview(graph)
-{
- this.graph = graph;
- this.deltas = new Object();
-};
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxCellStatePreview.prototype.graph = null;
-
-/**
- * Variable: deltas
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxCellStatePreview.prototype.deltas = null;
-
-/**
- * Variable: count
- *
- * Contains the number of entries in the map.
- */
-mxCellStatePreview.prototype.count = 0;
-
-/**
- * Function: isEmpty
- *
- * Returns true if this contains no entries.
- */
-mxCellStatePreview.prototype.isEmpty = function()
-{
- return this.count == 0;
-};
-
-/**
- * Function: moveState
- */
-mxCellStatePreview.prototype.moveState = function(state, dx, dy, add, includeEdges)
-{
- add = (add != null) ? add : true;
- includeEdges = (includeEdges != null) ? includeEdges : true;
- var id = mxCellPath.create(state.cell);
- var delta = this.deltas[id];
-
- if (delta == null)
- {
- delta = new mxPoint(dx, dy);
- this.deltas[id] = delta;
- this.count++;
- }
- else
- {
- if (add)
- {
- delta.X += dx;
- delta.Y += dy;
- }
- else
- {
- delta.X = dx;
- delta.Y = dy;
- }
- }
-
- if (includeEdges)
- {
- this.addEdges(state);
- }
-
- return delta;
-};
-
-/**
- * Function: show
- */
-mxCellStatePreview.prototype.show = function(visitor)
-{
- var model = this.graph.getModel();
- var root = model.getRoot();
-
- // Translates the states in step
- for (var id in this.deltas)
- {
- var cell = mxCellPath.resolve(root, id);
- var state = this.graph.view.getState(cell);
- var delta = this.deltas[id];
- var parentState = this.graph.view.getState(
- model.getParent(cell));
- this.translateState(parentState, state, delta.x, delta.y);
- }
-
- // Revalidates the states in step
- for (var id in this.deltas)
- {
- var cell = mxCellPath.resolve(root, id);
- var state = this.graph.view.getState(cell);
- var delta = this.deltas[id];
- var parentState = this.graph.view.getState(
- model.getParent(cell));
- this.revalidateState(parentState, state, delta.x, delta.y, visitor);
- }
-};
-
-/**
- * Function: translateState
- */
-mxCellStatePreview.prototype.translateState = function(parentState, state, dx, dy)
-{
- if (state != null)
- {
- var model = this.graph.getModel();
-
- if (model.isVertex(state.cell))
- {
- // LATER: Use hashtable to store initial state bounds
- state.invalid = true;
- this.graph.view.validateBounds(parentState, state.cell);
- var geo = model.getGeometry(state.cell);
- var id = mxCellPath.create(state.cell);
-
- // Moves selection cells and non-relative vertices in
- // the first phase so that edge terminal points will
- // be updated in the second phase
- if ((dx != 0 || dy != 0) && geo != null &&
- (!geo.relative || this.deltas[id] != null))
- {
- state.x += dx;
- state.y += dy;
- }
- }
-
- var childCount = model.getChildCount(state.cell);
-
- for (var i = 0; i < childCount; i++)
- {
- this.translateState(state, this.graph.view.getState(
- model.getChildAt(state.cell, i)), dx, dy);
- }
- }
-};
-
-/**
- * Function: revalidateState
- */
-mxCellStatePreview.prototype.revalidateState = function(parentState, state, dx, dy, visitor)
-{
- if (state != null)
- {
- // Updates the edge terminal points and restores the
- // (relative) positions of any (relative) children
- state.invalid = true;
- this.graph.view.validatePoints(parentState, state.cell);
-
- // Moves selection vertices which are relative
- var id = mxCellPath.create(state.cell);
- var model = this.graph.getModel();
- var geo = this.graph.getCellGeometry(state.cell);
-
- if ((dx != 0 || dy != 0) && geo != null && geo.relative &&
- model.isVertex(state.cell) && (parentState == null ||
- model.isVertex(parentState.cell) || this.deltas[id] != null))
- {
- state.x += dx;
- state.y += dy;
-
- this.graph.cellRenderer.redraw(state);
- }
-
- // Invokes the visitor on the given state
- if (visitor != null)
- {
- visitor(state);
- }
-
- var childCount = model.getChildCount(state.cell);
-
- for (var i = 0; i < childCount; i++)
- {
- this.revalidateState(state, this.graph.view.getState(model.getChildAt(
- state.cell, i)), dx, dy, visitor);
- }
- }
-};
-
-/**
- * Function: addEdges
- */
-mxCellStatePreview.prototype.addEdges = function(state)
-{
- var model = this.graph.getModel();
- var edgeCount = model.getEdgeCount(state.cell);
-
- for (var i = 0; i < edgeCount; i++)
- {
- var s = this.graph.view.getState(model.getEdgeAt(state.cell, i));
-
- if (s != null)
- {
- this.moveState(s, 0, 0);
- }
- }
-};
diff --git a/src/js/view/mxConnectionConstraint.js b/src/js/view/mxConnectionConstraint.js
deleted file mode 100644
index 70f457f..0000000
--- a/src/js/view/mxConnectionConstraint.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * $Id: mxConnectionConstraint.js,v 1.2 2010-04-29 09:33:52 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxConnectionConstraint
- *
- * Defines an object that contains the constraints about how to connect one
- * side of an edge to its terminal.
- *
- * Constructor: mxConnectionConstraint
- *
- * Constructs a new connection constraint for the given point and boolean
- * arguments.
- *
- * Parameters:
- *
- * point - Optional <mxPoint> that specifies the fixed location of the point
- * in relative coordinates. Default is null.
- * perimeter - Optional boolean that specifies if the fixed point should be
- * projected onto the perimeter of the terminal. Default is true.
- */
-function mxConnectionConstraint(point, perimeter)
-{
- this.point = point;
- this.perimeter = (perimeter != null) ? perimeter : true;
-};
-
-/**
- * Variable: point
- *
- * <mxPoint> that specifies the fixed location of the connection point.
- */
-mxConnectionConstraint.prototype.point = null;
-
-/**
- * Variable: perimeter
- *
- * Boolean that specifies if the point should be projected onto the perimeter
- * of the terminal.
- */
-mxConnectionConstraint.prototype.perimeter = null;
diff --git a/src/js/view/mxEdgeStyle.js b/src/js/view/mxEdgeStyle.js
deleted file mode 100644
index 41493d6..0000000
--- a/src/js/view/mxEdgeStyle.js
+++ /dev/null
@@ -1,1302 +0,0 @@
-/**
- * $Id: mxEdgeStyle.js,v 1.68 2012-11-20 09:06:07 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxEdgeStyle =
-{
- /**
- * Class: mxEdgeStyle
- *
- * Provides various edge styles to be used as the values for
- * <mxConstants.STYLE_EDGE> in a cell style.
- *
- * Example:
- *
- * (code)
- * var style = stylesheet.getDefaultEdgeStyle();
- * style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;
- * (end)
- *
- * Sets the default edge style to <ElbowConnector>.
- *
- * Custom edge style:
- *
- * To write a custom edge style, a function must be added to the mxEdgeStyle
- * object as follows:
- *
- * (code)
- * mxEdgeStyle.MyStyle = function(state, source, target, points, result)
- * {
- * if (source != null && target != null)
- * {
- * var pt = new mxPoint(target.getCenterX(), source.getCenterY());
- *
- * if (mxUtils.contains(source, pt.x, pt.y))
- * {
- * pt.y = source.y + source.height;
- * }
- *
- * result.push(pt);
- * }
- * };
- * (end)
- *
- * In the above example, a right angle is created using a point on the
- * horizontal center of the target vertex and the vertical center of the source
- * vertex. The code checks if that point intersects the source vertex and makes
- * the edge straight if it does. The point is then added into the result array,
- * which acts as the return value of the function.
- *
- * The new edge style should then be registered in the <mxStyleRegistry> as follows:
- * (code)
- * mxStyleRegistry.putValue('myEdgeStyle', mxEdgeStyle.MyStyle);
- * (end)
- *
- * The custom edge style above can now be used in a specific edge as follows:
- *
- * (code)
- * model.setStyle(edge, 'edgeStyle=myEdgeStyle');
- * (end)
- *
- * Note that the key of the <mxStyleRegistry> entry for the function should
- * be used in string values, unless <mxGraphView.allowEval> is true, in
- * which case you can also use mxEdgeStyle.MyStyle for the value in the
- * cell style above.
- *
- * Or it can be used for all edges in the graph as follows:
- *
- * (code)
- * var style = graph.getStylesheet().getDefaultEdgeStyle();
- * style[mxConstants.STYLE_EDGE] = mxEdgeStyle.MyStyle;
- * (end)
- *
- * Note that the object can be used directly when programmatically setting
- * the value, but the key in the <mxStyleRegistry> should be used when
- * setting the value via a key, value pair in a cell style.
- *
- * Function: EntityRelation
- *
- * Implements an entity relation style for edges (as used in database
- * schema diagrams). At the time the function is called, the result
- * array contains a placeholder (null) for the first absolute point,
- * that is, the point where the edge and source terminal are connected.
- * The implementation of the style then adds all intermediate waypoints
- * except for the last point, that is, the connection point between the
- * edge and the target terminal. The first ant the last point in the
- * result array are then replaced with mxPoints that take into account
- * the terminal's perimeter and next point on the edge.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the edge to be updated.
- * source - <mxCellState> that represents the source terminal.
- * target - <mxCellState> that represents the target terminal.
- * points - List of relative control points.
- * result - Array of <mxPoints> that represent the actual points of the
- * edge.
- */
- EntityRelation: function (state, source, target, points, result)
- {
- var view = state.view;
- var graph = view.graph;
- var segment = mxUtils.getValue(state.style,
- mxConstants.STYLE_SEGMENT,
- mxConstants.ENTITY_SEGMENT) * view.scale;
-
- var pts = state.absolutePoints;
- var p0 = pts[0];
- var pe = pts[pts.length-1];
-
- var isSourceLeft = false;
-
- if (p0 != null)
- {
- source = new mxCellState();
- source.x = p0.x;
- source.y = p0.y;
- }
- else if (source != null)
- {
- var constraint = mxUtils.getPortConstraints(source, state, true, mxConstants.DIRECTION_MASK_NONE);
-
- if (constraint != mxConstants.DIRECTION_MASK_NONE)
- {
- isSourceLeft = constraint == mxConstants.DIRECTION_MASK_WEST;
- }
- else
- {
- var sourceGeometry = graph.getCellGeometry(source.cell);
-
- if (sourceGeometry.relative)
- {
- isSourceLeft = sourceGeometry.x <= 0.5;
- }
- else if (target != null)
- {
- isSourceLeft = target.x + target.width < source.x;
- }
- }
- }
- else
- {
- return;
- }
-
- var isTargetLeft = true;
-
- if (pe != null)
- {
- target = new mxCellState();
- target.x = pe.x;
- target.y = pe.y;
- }
- else if (target != null)
- {
- var constraint = mxUtils.getPortConstraints(target, state, false, mxConstants.DIRECTION_MASK_NONE);
-
- if (constraint != mxConstants.DIRECTION_MASK_NONE)
- {
- isTargetLeft = constraint == mxConstants.DIRECTION_MASK_WEST;
- }
- else
- {
- var targetGeometry = graph.getCellGeometry(target.cell);
-
- if (targetGeometry.relative)
- {
- isTargetLeft = targetGeometry.x <= 0.5;
- }
- else if (source != null)
- {
- isTargetLeft = source.x + source.width < target.x;
- }
- }
- }
-
- if (source != null && target != null)
- {
- var x0 = (isSourceLeft) ? source.x : source.x + source.width;
- var y0 = view.getRoutingCenterY(source);
-
- var xe = (isTargetLeft) ? target.x : target.x + target.width;
- var ye = view.getRoutingCenterY(target);
-
- var seg = segment;
-
- var dx = (isSourceLeft) ? -seg : seg;
- var dep = new mxPoint(x0 + dx, y0);
-
- dx = (isTargetLeft) ? -seg : seg;
- var arr = new mxPoint(xe + dx, ye);
-
- // Adds intermediate points if both go out on same side
- if (isSourceLeft == isTargetLeft)
- {
- var x = (isSourceLeft) ?
- Math.min(x0, xe)-segment :
- Math.max(x0, xe)+segment;
-
- result.push(new mxPoint(x, y0));
- result.push(new mxPoint(x, ye));
- }
- else if ((dep.x < arr.x) == isSourceLeft)
- {
- var midY = y0 + (ye - y0) / 2;
-
- result.push(dep);
- result.push(new mxPoint(dep.x, midY));
- result.push(new mxPoint(arr.x, midY));
- result.push(arr);
- }
- else
- {
- result.push(dep);
- result.push(arr);
- }
- }
- },
-
- /**
- * Function: Loop
- *
- * Implements a self-reference, aka. loop.
- */
- Loop: function (state, source, target, points, result)
- {
- if (source != null)
- {
- var view = state.view;
- var graph = view.graph;
- var pt = (points != null && points.length > 0) ? points[0] : null;
-
- if (pt != null)
- {
- pt = view.transformControlPoint(state, pt);
-
- if (mxUtils.contains(source, pt.x, pt.y))
- {
- pt = null;
- }
- }
-
- var x = 0;
- var dx = 0;
- var y = 0;
- var dy = 0;
-
- var seg = mxUtils.getValue(state.style, mxConstants.STYLE_SEGMENT,
- graph.gridSize) * view.scale;
- var dir = mxUtils.getValue(state.style, mxConstants.STYLE_DIRECTION,
- mxConstants.DIRECTION_WEST);
-
- if (dir == mxConstants.DIRECTION_NORTH ||
- dir == mxConstants.DIRECTION_SOUTH)
- {
- x = view.getRoutingCenterX(source);
- dx = seg;
- }
- else
- {
- y = view.getRoutingCenterY(source);
- dy = seg;
- }
-
- if (pt == null ||
- pt.x < source.x ||
- pt.x > source.x + source.width)
- {
- if (pt != null)
- {
- x = pt.x;
- dy = Math.max(Math.abs(y - pt.y), dy);
- }
- else
- {
- if (dir == mxConstants.DIRECTION_NORTH)
- {
- y = source.y - 2 * dx;
- }
- else if (dir == mxConstants.DIRECTION_SOUTH)
- {
- y = source.y + source.height + 2 * dx;
- }
- else if (dir == mxConstants.DIRECTION_EAST)
- {
- x = source.x - 2 * dy;
- }
- else
- {
- x = source.x + source.width + 2 * dy;
- }
- }
- }
- else if (pt != null)
- {
- x = view.getRoutingCenterX(source);
- dx = Math.max(Math.abs(x - pt.x), dy);
- y = pt.y;
- dy = 0;
- }
-
- result.push(new mxPoint(x - dx, y - dy));
- result.push(new mxPoint(x + dx, y + dy));
- }
- },
-
- /**
- * Function: ElbowConnector
- *
- * Uses either <SideToSide> or <TopToBottom> depending on the horizontal
- * flag in the cell style. <SideToSide> is used if horizontal is true or
- * unspecified. See <EntityRelation> for a description of the
- * parameters.
- */
- ElbowConnector: function (state, source, target, points, result)
- {
- var pt = (points != null && points.length > 0) ? points[0] : null;
-
- var vertical = false;
- var horizontal = false;
-
- if (source != null && target != null)
- {
- if (pt != null)
- {
- var left = Math.min(source.x, target.x);
- var right = Math.max(source.x + source.width,
- target.x + target.width);
-
- var top = Math.min(source.y, target.y);
- var bottom = Math.max(source.y + source.height,
- target.y + target.height);
-
- pt = state.view.transformControlPoint(state, pt);
-
- vertical = pt.y < top || pt.y > bottom;
- horizontal = pt.x < left || pt.x > right;
- }
- else
- {
- var left = Math.max(source.x, target.x);
- var right = Math.min(source.x + source.width,
- target.x + target.width);
-
- vertical = left == right;
-
- if (!vertical)
- {
- var top = Math.max(source.y, target.y);
- var bottom = Math.min(source.y + source.height,
- target.y + target.height);
-
- horizontal = top == bottom;
- }
- }
- }
-
- if (!horizontal && (vertical ||
- state.style[mxConstants.STYLE_ELBOW] == mxConstants.ELBOW_VERTICAL))
- {
- mxEdgeStyle.TopToBottom(state, source, target, points, result);
- }
- else
- {
- mxEdgeStyle.SideToSide(state, source, target, points, result);
- }
- },
-
- /**
- * Function: SideToSide
- *
- * Implements a vertical elbow edge. See <EntityRelation> for a description
- * of the parameters.
- */
- SideToSide: function (state, source, target, points, result)
- {
- var view = state.view;
- var pt = (points != null && points.length > 0) ? points[0] : null;
- var pts = state.absolutePoints;
- var p0 = pts[0];
- var pe = pts[pts.length-1];
-
- if (pt != null)
- {
- pt = view.transformControlPoint(state, pt);
- }
-
- if (p0 != null)
- {
- source = new mxCellState();
- source.x = p0.x;
- source.y = p0.y;
- }
-
- if (pe != null)
- {
- target = new mxCellState();
- target.x = pe.x;
- target.y = pe.y;
- }
-
- if (source != null && target != null)
- {
- var l = Math.max(source.x, target.x);
- var r = Math.min(source.x + source.width,
- target.x + target.width);
-
- var x = (pt != null) ? pt.x : r + (l - r) / 2;
-
- var y1 = view.getRoutingCenterY(source);
- var y2 = view.getRoutingCenterY(target);
-
- if (pt != null)
- {
- if (pt.y >= source.y && pt.y <= source.y + source.height)
- {
- y1 = pt.y;
- }
-
- if (pt.y >= target.y && pt.y <= target.y + target.height)
- {
- y2 = pt.y;
- }
- }
-
- if (!mxUtils.contains(target, x, y1) &&
- !mxUtils.contains(source, x, y1))
- {
- result.push(new mxPoint(x, y1));
- }
-
- if (!mxUtils.contains(target, x, y2) &&
- !mxUtils.contains(source, x, y2))
- {
- result.push(new mxPoint(x, y2));
- }
-
- if (result.length == 1)
- {
- if (pt != null)
- {
- if (!mxUtils.contains(target, x, pt.y) &&
- !mxUtils.contains(source, x, pt.y))
- {
- result.push(new mxPoint(x, pt.y));
- }
- }
- else
- {
- var t = Math.max(source.y, target.y);
- var b = Math.min(source.y + source.height,
- target.y + target.height);
-
- result.push(new mxPoint(x, t + (b - t) / 2));
- }
- }
- }
- },
-
- /**
- * Function: TopToBottom
- *
- * Implements a horizontal elbow edge. See <EntityRelation> for a
- * description of the parameters.
- */
- TopToBottom: function(state, source, target, points, result)
- {
- var view = state.view;
- var pt = (points != null && points.length > 0) ? points[0] : null;
- var pts = state.absolutePoints;
- var p0 = pts[0];
- var pe = pts[pts.length-1];
-
- if (pt != null)
- {
- pt = view.transformControlPoint(state, pt);
- }
-
- if (p0 != null)
- {
- source = new mxCellState();
- source.x = p0.x;
- source.y = p0.y;
- }
-
- if (pe != null)
- {
- target = new mxCellState();
- target.x = pe.x;
- target.y = pe.y;
- }
-
- if (source != null && target != null)
- {
- var t = Math.max(source.y, target.y);
- var b = Math.min(source.y + source.height,
- target.y + target.height);
-
- var x = view.getRoutingCenterX(source);
-
- if (pt != null &&
- pt.x >= source.x &&
- pt.x <= source.x + source.width)
- {
- x = pt.x;
- }
-
- var y = (pt != null) ? pt.y : b + (t - b) / 2;
-
- if (!mxUtils.contains(target, x, y) &&
- !mxUtils.contains(source, x, y))
- {
- result.push(new mxPoint(x, y));
- }
-
- if (pt != null &&
- pt.x >= target.x &&
- pt.x <= target.x + target.width)
- {
- x = pt.x;
- }
- else
- {
- x = view.getRoutingCenterX(target);
- }
-
- if (!mxUtils.contains(target, x, y) &&
- !mxUtils.contains(source, x, y))
- {
- result.push(new mxPoint(x, y));
- }
-
- if (result.length == 1)
- {
- if (pt != null && result.length == 1)
- {
- if (!mxUtils.contains(target, pt.x, y) &&
- !mxUtils.contains(source, pt.x, y))
- {
- result.push(new mxPoint(pt.x, y));
- }
- }
- else
- {
- var l = Math.max(source.x, target.x);
- var r = Math.min(source.x + source.width,
- target.x + target.width);
-
- result.push(new mxPoint(l + (r - l) / 2, y));
- }
- }
- }
- },
-
- /**
- * Function: SegmentConnector
- *
- * Implements an orthogonal edge style. Use <mxEdgeSegmentHandler>
- * as an interactive handler for this style.
- */
- SegmentConnector: function(state, source, target, hints, result)
- {
- // Creates array of all way- and terminalpoints
- var pts = state.absolutePoints;
- var horizontal = true;
- var hint = null;
-
- // Adds the first point
- var pt = pts[0];
-
- if (pt == null && source != null)
- {
- pt = new mxPoint(state.view.getRoutingCenterX(source), state.view.getRoutingCenterY(source));
- }
- else if (pt != null)
- {
- pt = pt.clone();
- }
-
- var lastInx = pts.length - 1;
-
- // Adds the waypoints
- if (hints != null && hints.length > 0)
- {
- hint = state.view.transformControlPoint(state, hints[0]);
-
- var currentTerm = source;
- var currentPt = pts[0];
- var hozChan = false;
- var vertChan = false;
- var currentHint = hint;
- var hintsLen = hints.length;
-
- for (var i = 0; i < 2; i++)
- {
- var fixedVertAlign = currentPt != null && currentPt.x == currentHint.x;
- var fixedHozAlign = currentPt != null && currentPt.y == currentHint.y;
- var inHozChan = currentTerm != null && (currentHint.y >= currentTerm.y &&
- currentHint.y <= currentTerm.y + currentTerm.height);
- var inVertChan = currentTerm != null && (currentHint.x >= currentTerm.x &&
- currentHint.x <= currentTerm.x + currentTerm.width);
-
- hozChan = fixedHozAlign || (currentPt == null && inHozChan);
- vertChan = fixedVertAlign || (currentPt == null && inVertChan);
-
- if (currentPt != null && (!fixedHozAlign && !fixedVertAlign) && (inHozChan || inVertChan))
- {
- horizontal = inHozChan ? false : true;
- break;
- }
-
- if (vertChan || hozChan)
- {
- horizontal = hozChan;
-
- if (i == 1)
- {
- // Work back from target end
- horizontal = hints.length % 2 == 0 ? hozChan : vertChan;
- }
-
- break;
- }
-
- currentTerm = target;
- currentPt = pts[lastInx];
- currentHint = state.view.transformControlPoint(state, hints[hintsLen - 1]);
- }
-
- if (horizontal && ((pts[0] != null && pts[0].y != hint.y) ||
- (pts[0] == null && source != null &&
- (hint.y < source.y || hint.y > source.y + source.height))))
- {
- result.push(new mxPoint(pt.x, hint.y));
- }
- else if (!horizontal && ((pts[0] != null && pts[0].x != hint.x) ||
- (pts[0] == null && source != null &&
- (hint.x < source.x || hint.x > source.x + source.width))))
- {
- result.push(new mxPoint(hint.x, pt.y));
- }
-
- if (horizontal)
- {
- pt.y = hint.y;
- }
- else
- {
- pt.x = hint.x;
- }
-
- for (var i = 0; i < hints.length; i++)
- {
- horizontal = !horizontal;
- hint = state.view.transformControlPoint(state, hints[i]);
-
-// mxLog.show();
-// mxLog.debug('hint', i, hint.x, hint.y);
-
- if (horizontal)
- {
- pt.y = hint.y;
- }
- else
- {
- pt.x = hint.x;
- }
-
- result.push(pt.clone());
- }
- }
- else
- {
- hint = pt;
- // FIXME: First click in connect preview toggles orientation
- horizontal = true;
- }
-
- // Adds the last point
- pt = pts[lastInx];
-
- if (pt == null && target != null)
- {
- pt = new mxPoint(state.view.getRoutingCenterX(target), state.view.getRoutingCenterY(target));
- }
-
- if (horizontal && ((pts[lastInx] != null && pts[lastInx].y != hint.y) ||
- (pts[lastInx] == null && target != null &&
- (hint.y < target.y || hint.y > target.y + target.height))))
- {
- result.push(new mxPoint(pt.x, hint.y));
- }
- else if (!horizontal && ((pts[lastInx] != null && pts[lastInx].x != hint.x) ||
- (pts[lastInx] == null && target != null &&
- (hint.x < target.x || hint.x > target.x + target.width))))
- {
- result.push(new mxPoint(hint.x, pt.y));
- }
-
- // Removes bends inside the source terminal for floating ports
- if (pts[0] == null && source != null)
- {
- while (result.length > 1 && mxUtils.contains(source, result[1].x, result[1].y))
- {
- result = result.splice(1, 1);
- }
- }
-
- // Removes bends inside the target terminal
- if (pts[lastInx] == null && target != null)
- {
- while (result.length > 1 && mxUtils.contains(target, result[result.length - 1].x, result[result.length - 1].y))
- {
- result = result.splice(result.length - 1, 1);
- }
- }
-
- },
-
- orthBuffer: 10,
-
- dirVectors: [ [ -1, 0 ],
- [ 0, -1 ], [ 1, 0 ], [ 0, 1 ], [ -1, 0 ], [ 0, -1 ], [ 1, 0 ] ],
-
- wayPoints1: [ [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0],
- [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0] ],
-
- routePatterns: [
- [ [ 513, 2308, 2081, 2562 ], [ 513, 1090, 514, 2184, 2114, 2561 ],
- [ 513, 1090, 514, 2564, 2184, 2562 ],
- [ 513, 2308, 2561, 1090, 514, 2568, 2308 ] ],
- [ [ 514, 1057, 513, 2308, 2081, 2562 ], [ 514, 2184, 2114, 2561 ],
- [ 514, 2184, 2562, 1057, 513, 2564, 2184 ],
- [ 514, 1057, 513, 2568, 2308, 2561 ] ],
- [ [ 1090, 514, 1057, 513, 2308, 2081, 2562 ], [ 2114, 2561 ],
- [ 1090, 2562, 1057, 513, 2564, 2184 ],
- [ 1090, 514, 1057, 513, 2308, 2561, 2568 ] ],
- [ [ 2081, 2562 ], [ 1057, 513, 1090, 514, 2184, 2114, 2561 ],
- [ 1057, 513, 1090, 514, 2184, 2562, 2564 ],
- [ 1057, 2561, 1090, 514, 2568, 2308 ] ] ],
-
- inlineRoutePatterns: [
- [ null, [ 2114, 2568 ], null, null ],
- [ null, [ 514, 2081, 2114, 2568 ] , null, null ],
- [ null, [ 2114, 2561 ], null, null ],
- [ [ 2081, 2562 ], [ 1057, 2114, 2568 ],
- [ 2184, 2562 ],
- null ] ],
- vertexSeperations: [],
-
- limits: [
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ],
-
- LEFT_MASK: 32,
-
- TOP_MASK: 64,
-
- RIGHT_MASK: 128,
-
- BOTTOM_MASK: 256,
-
- LEFT: 1,
-
- TOP: 2,
-
- RIGHT: 4,
-
- BOTTOM: 8,
-
- // TODO remove magic numbers
- SIDE_MASK: 480,
- //mxEdgeStyle.LEFT_MASK | mxEdgeStyle.TOP_MASK | mxEdgeStyle.RIGHT_MASK
- //| mxEdgeStyle.BOTTOM_MASK,
-
- CENTER_MASK: 512,
-
- SOURCE_MASK: 1024,
-
- TARGET_MASK: 2048,
-
- VERTEX_MASK: 3072,
- // mxEdgeStyle.SOURCE_MASK | mxEdgeStyle.TARGET_MASK,
-
- /**
- * Function: OrthConnector
- *
- * Implements a local orthogonal router between the given
- * cells.
- */
- OrthConnector: function(state, source, target, points, result)
- {
- var graph = state.view.graph;
- var sourceEdge = source == null ? false : graph.getModel().isEdge(source.cell);
- var targetEdge = target == null ? false : graph.getModel().isEdge(target.cell);
-
- if ((points != null && points.length > 0) || (sourceEdge) || (targetEdge))
- {
- mxEdgeStyle.SegmentConnector(state, source, target, points, result);
- return;
- }
-
- var pts = state.absolutePoints;
- var p0 = pts[0];
- var pe = pts[pts.length-1];
-
- var sourceX = source != null ? source.x : p0.x;
- var sourceY = source != null ? source.y : p0.y;
- var sourceWidth = source != null ? source.width : 1;
- var sourceHeight = source != null ? source.height : 1;
-
- var targetX = target != null ? target.x : pe.x;
- var targetY = target != null ? target.y : pe.y;
- var targetWidth = target != null ? target.width : 1;
- var targetHeight = target != null ? target.height : 1;
-
- var scaledOrthBuffer = state.view.scale * mxEdgeStyle.orthBuffer;
- // Determine the side(s) of the source and target vertices
- // that the edge may connect to
- // portConstraint [source, target]
- var portConstraint = [mxConstants.DIRECTION_MASK_ALL, mxConstants.DIRECTION_MASK_ALL];
-
- if (source != null)
- {
- portConstraint[0] = mxUtils.getPortConstraints(source, state, true,
- mxConstants.DIRECTION_MASK_ALL);
- }
-
- if (target != null)
- {
- portConstraint[1] = mxUtils.getPortConstraints(target, state, false,
- mxConstants.DIRECTION_MASK_ALL);
- }
-
- var dir = [0, 0] ;
-
- // Work out which faces of the vertices present against each other
- // in a way that would allow a 3-segment connection if port constraints
- // permitted.
- // geo -> [source, target] [x, y, width, height]
- var geo = [ [sourceX, sourceY, sourceWidth, sourceHeight] ,
- [targetX, targetY, targetWidth, targetHeight] ];
-
- for (var i = 0; i < 2; i++)
- {
- mxEdgeStyle.limits[i][1] = geo[i][0] - scaledOrthBuffer;
- mxEdgeStyle.limits[i][2] = geo[i][1] - scaledOrthBuffer;
- mxEdgeStyle.limits[i][4] = geo[i][0] + geo[i][2] + scaledOrthBuffer;
- mxEdgeStyle.limits[i][8] = geo[i][1] + geo[i][3] + scaledOrthBuffer;
- }
-
- // Work out which quad the target is in
- var sourceCenX = geo[0][0] + geo[0][2] / 2.0;
- var sourceCenY = geo[0][1] + geo[0][3] / 2.0;
- var targetCenX = geo[1][0] + geo[1][2] / 2.0;
- var targetCenY = geo[1][1] + geo[1][3] / 2.0;
-
- var dx = sourceCenX - targetCenX;
- var dy = sourceCenY - targetCenY;
-
- var quad = 0;
-
- if (dx < 0)
- {
- if (dy < 0)
- {
- quad = 2;
- }
- else
- {
- quad = 1;
- }
- }
- else
- {
- if (dy <= 0)
- {
- quad = 3;
-
- // Special case on x = 0 and negative y
- if (dx == 0)
- {
- quad = 2;
- }
- }
- }
-
- // Check for connection constraints
- var currentTerm = null;
-
- if (source != null)
- {
- currentTerm = p0;
- }
-
- var constraint = [ [0.5, 0.5] , [0.5, 0.5] ];
-
- for (var i = 0; i < 2; i++)
- {
- if (currentTerm != null)
- {
- constraint[i][0] = (currentTerm.x - geo[i][0]) / geo[i][2];
-
- if (constraint[i][0] < 0.01)
- {
- dir[i] = mxConstants.DIRECTION_MASK_WEST;
- }
- else if (constraint[i][0] > 0.99)
- {
- dir[i] = mxConstants.DIRECTION_MASK_EAST;
- }
-
- constraint[i][1] = (currentTerm.y - geo[i][1]) / geo[i][3];
-
- if (constraint[i][1] < 0.01)
- {
- dir[i] = mxConstants.DIRECTION_MASK_NORTH;
- }
- else if (constraint[i][1] > 0.99)
- {
- dir[i] = mxConstants.DIRECTION_MASK_SOUTH;
- }
- }
-
- currentTerm = null;
-
- if (target != null)
- {
- currentTerm = pe;
- }
- }
-
- var sourceTopDist = geo[0][1] - (geo[1][1] + geo[1][3]);
- var sourceLeftDist = geo[0][0] - (geo[1][0] + geo[1][2]);
- var sourceBottomDist = geo[1][1] - (geo[0][1] + geo[0][3]);
- var sourceRightDist = geo[1][0] - (geo[0][0] + geo[0][2]);
-
- mxEdgeStyle.vertexSeperations[1] = Math.max(
- sourceLeftDist - 2 * scaledOrthBuffer, 0);
- mxEdgeStyle.vertexSeperations[2] = Math.max(sourceTopDist - 2 * scaledOrthBuffer,
- 0);
- mxEdgeStyle.vertexSeperations[4] = Math.max(sourceBottomDist - 2
- * scaledOrthBuffer, 0);
- mxEdgeStyle.vertexSeperations[3] = Math.max(sourceRightDist - 2
- * scaledOrthBuffer, 0);
-
- //==============================================================
- // Start of source and target direction determination
-
- // Work through the preferred orientations by relative positioning
- // of the vertices and list them in preferred and available order
-
- var dirPref = [];
- var horPref = [];
- var vertPref = [];
-
- horPref[0] = (sourceLeftDist >= sourceRightDist) ? mxConstants.DIRECTION_MASK_WEST
- : mxConstants.DIRECTION_MASK_EAST;
- vertPref[0] = (sourceTopDist >= sourceBottomDist) ? mxConstants.DIRECTION_MASK_NORTH
- : mxConstants.DIRECTION_MASK_SOUTH;
-
- horPref[1] = mxUtils.reversePortConstraints(horPref[0]);
- vertPref[1] = mxUtils.reversePortConstraints(vertPref[0]);
-
- var preferredHorizDist = sourceLeftDist >= sourceRightDist ? sourceLeftDist
- : sourceRightDist;
- var preferredVertDist = sourceTopDist >= sourceBottomDist ? sourceTopDist
- : sourceBottomDist;
-
- var prefOrdering = [ [0, 0] , [0, 0] ];
- var preferredOrderSet = false;
-
- // If the preferred port isn't available, switch it
- for (var i = 0; i < 2; i++)
- {
- if (dir[i] != 0x0)
- {
- continue;
- }
-
- if ((horPref[i] & portConstraint[i]) == 0)
- {
- horPref[i] = mxUtils.reversePortConstraints(horPref[i]);
- }
-
- if ((vertPref[i] & portConstraint[i]) == 0)
- {
- vertPref[i] = mxUtils
- .reversePortConstraints(vertPref[i]);
- }
-
- prefOrdering[i][0] = vertPref[i];
- prefOrdering[i][1] = horPref[i];
- }
-
- if (preferredVertDist > scaledOrthBuffer * 2
- && preferredHorizDist > scaledOrthBuffer * 2)
- {
- // Possibility of two segment edge connection
- if (((horPref[0] & portConstraint[0]) > 0)
- && ((vertPref[1] & portConstraint[1]) > 0))
- {
- prefOrdering[0][0] = horPref[0];
- prefOrdering[0][1] = vertPref[0];
- prefOrdering[1][0] = vertPref[1];
- prefOrdering[1][1] = horPref[1];
- preferredOrderSet = true;
- }
- else if (((vertPref[0] & portConstraint[0]) > 0)
- && ((horPref[1] & portConstraint[1]) > 0))
- {
- prefOrdering[0][0] = vertPref[0];
- prefOrdering[0][1] = horPref[0];
- prefOrdering[1][0] = horPref[1];
- prefOrdering[1][1] = vertPref[1];
- preferredOrderSet = true;
- }
- }
- if (preferredVertDist > scaledOrthBuffer * 2 && !preferredOrderSet)
- {
- prefOrdering[0][0] = vertPref[0];
- prefOrdering[0][1] = horPref[0];
- prefOrdering[1][0] = vertPref[1];
- prefOrdering[1][1] = horPref[1];
- preferredOrderSet = true;
-
- }
- if (preferredHorizDist > scaledOrthBuffer * 2 && !preferredOrderSet)
- {
- prefOrdering[0][0] = horPref[0];
- prefOrdering[0][1] = vertPref[0];
- prefOrdering[1][0] = horPref[1];
- prefOrdering[1][1] = vertPref[1];
- preferredOrderSet = true;
- }
-
- // The source and target prefs are now an ordered list of
- // the preferred port selections
- // It the list can contain gaps, compact it
-
- for (var i = 0; i < 2; i++)
- {
- if (dir[i] != 0x0)
- {
- continue;
- }
-
- if ((prefOrdering[i][0] & portConstraint[i]) == 0)
- {
- prefOrdering[i][0] = prefOrdering[i][1];
- }
-
- dirPref[i] = prefOrdering[i][0] & portConstraint[i];
- dirPref[i] |= (prefOrdering[i][1] & portConstraint[i]) << 8;
- dirPref[i] |= (prefOrdering[1 - i][i] & portConstraint[i]) << 16;
- dirPref[i] |= (prefOrdering[1 - i][1 - i] & portConstraint[i]) << 24;
-
- if ((dirPref[i] & 0xF) == 0)
- {
- dirPref[i] = dirPref[i] << 8;
- }
- if ((dirPref[i] & 0xF00) == 0)
- {
- dirPref[i] = (dirPref[i] & 0xF) | dirPref[i] >> 8;
- }
- if ((dirPref[i] & 0xF0000) == 0)
- {
- dirPref[i] = (dirPref[i] & 0xFFFF)
- | ((dirPref[i] & 0xF000000) >> 8);
- }
-
- dir[i] = dirPref[i] & 0xF;
-
- if (portConstraint[i] == mxConstants.DIRECTION_MASK_WEST
- || portConstraint[i] == mxConstants.DIRECTION_MASK_NORTH
- || portConstraint[i] == mxConstants.DIRECTION_MASK_EAST
- || portConstraint[i] == mxConstants.DIRECTION_MASK_SOUTH)
- {
- dir[i] = portConstraint[i];
- }
- }
-
- //==============================================================
- // End of source and target direction determination
-
- var sourceIndex = dir[0] == mxConstants.DIRECTION_MASK_EAST ? 3
- : dir[0];
- var targetIndex = dir[1] == mxConstants.DIRECTION_MASK_EAST ? 3
- : dir[1];
-
- sourceIndex -= quad;
- targetIndex -= quad;
-
- if (sourceIndex < 1)
- {
- sourceIndex += 4;
- }
- if (targetIndex < 1)
- {
- targetIndex += 4;
- }
-
- var routePattern = mxEdgeStyle.routePatterns[sourceIndex - 1][targetIndex - 1];
-
- mxEdgeStyle.wayPoints1[0][0] = geo[0][0];
- mxEdgeStyle.wayPoints1[0][1] = geo[0][1];
-
- switch (dir[0])
- {
- case mxConstants.DIRECTION_MASK_WEST:
- mxEdgeStyle.wayPoints1[0][0] -= scaledOrthBuffer;
- mxEdgeStyle.wayPoints1[0][1] += constraint[0][1] * geo[0][3];
- break;
- case mxConstants.DIRECTION_MASK_SOUTH:
- mxEdgeStyle.wayPoints1[0][0] += constraint[0][0] * geo[0][2];
- mxEdgeStyle.wayPoints1[0][1] += geo[0][3] + scaledOrthBuffer;
- break;
- case mxConstants.DIRECTION_MASK_EAST:
- mxEdgeStyle.wayPoints1[0][0] += geo[0][2] + scaledOrthBuffer;
- mxEdgeStyle.wayPoints1[0][1] += constraint[0][1] * geo[0][3];
- break;
- case mxConstants.DIRECTION_MASK_NORTH:
- mxEdgeStyle.wayPoints1[0][0] += constraint[0][0] * geo[0][2];
- mxEdgeStyle.wayPoints1[0][1] -= scaledOrthBuffer;
- break;
- }
-
- var currentIndex = 0;
-
- // Orientation, 0 horizontal, 1 vertical
- var lastOrientation = (dir[0] & (mxConstants.DIRECTION_MASK_EAST | mxConstants.DIRECTION_MASK_WEST)) > 0 ? 0
- : 1;
- var initialOrientation = lastOrientation;
- var currentOrientation = 0;
-
- for (var i = 0; i < routePattern.length; i++)
- {
- var nextDirection = routePattern[i] & 0xF;
-
- // Rotate the index of this direction by the quad
- // to get the real direction
- var directionIndex = nextDirection == mxConstants.DIRECTION_MASK_EAST ? 3
- : nextDirection;
-
- directionIndex += quad;
-
- if (directionIndex > 4)
- {
- directionIndex -= 4;
- }
-
- var direction = mxEdgeStyle.dirVectors[directionIndex - 1];
-
- currentOrientation = (directionIndex % 2 > 0) ? 0 : 1;
- // Only update the current index if the point moved
- // in the direction of the current segment move,
- // otherwise the same point is moved until there is
- // a segment direction change
- if (currentOrientation != lastOrientation)
- {
- currentIndex++;
- // Copy the previous way point into the new one
- // We can't base the new position on index - 1
- // because sometime elbows turn out not to exist,
- // then we'd have to rewind.
- mxEdgeStyle.wayPoints1[currentIndex][0] = mxEdgeStyle.wayPoints1[currentIndex - 1][0];
- mxEdgeStyle.wayPoints1[currentIndex][1] = mxEdgeStyle.wayPoints1[currentIndex - 1][1];
- }
-
- var tar = (routePattern[i] & mxEdgeStyle.TARGET_MASK) > 0;
- var sou = (routePattern[i] & mxEdgeStyle.SOURCE_MASK) > 0;
- var side = (routePattern[i] & mxEdgeStyle.SIDE_MASK) >> 5;
- side = side << quad;
-
- if (side > 0xF)
- {
- side = side >> 4;
- }
-
- var center = (routePattern[i] & mxEdgeStyle.CENTER_MASK) > 0;
-
- if ((sou || tar) && side < 9)
- {
- var limit = 0;
- var souTar = sou ? 0 : 1;
-
- if (center && currentOrientation == 0)
- {
- limit = geo[souTar][0] + constraint[souTar][0] * geo[souTar][2];
- }
- else if (center)
- {
- limit = geo[souTar][1] + constraint[souTar][1] * geo[souTar][3];
- }
- else
- {
- limit = mxEdgeStyle.limits[souTar][side];
- }
-
- if (currentOrientation == 0)
- {
- var lastX = mxEdgeStyle.wayPoints1[currentIndex][0];
- var deltaX = (limit - lastX) * direction[0];
-
- if (deltaX > 0)
- {
- mxEdgeStyle.wayPoints1[currentIndex][0] += direction[0]
- * deltaX;
- }
- }
- else
- {
- var lastY = mxEdgeStyle.wayPoints1[currentIndex][1];
- var deltaY = (limit - lastY) * direction[1];
-
- if (deltaY > 0)
- {
- mxEdgeStyle.wayPoints1[currentIndex][1] += direction[1]
- * deltaY;
- }
- }
- }
-
- else if (center)
- {
- // Which center we're travelling to depend on the current direction
- mxEdgeStyle.wayPoints1[currentIndex][0] += direction[0]
- * Math.abs(mxEdgeStyle.vertexSeperations[directionIndex] / 2);
- mxEdgeStyle.wayPoints1[currentIndex][1] += direction[1]
- * Math.abs(mxEdgeStyle.vertexSeperations[directionIndex] / 2);
- }
-
- if (currentIndex > 0
- && mxEdgeStyle.wayPoints1[currentIndex][currentOrientation] == mxEdgeStyle.wayPoints1[currentIndex - 1][currentOrientation])
- {
- currentIndex--;
- }
- else
- {
- lastOrientation = currentOrientation;
- }
- }
-
- for (var i = 0; i <= currentIndex; i++)
- {
- if (i == currentIndex)
- {
- // Last point can cause last segment to be in
- // same direction as jetty/approach. If so,
- // check the number of points is consistent
- // with the relative orientation of source and target
- // jettys. Same orientation requires an even
- // number of turns (points), different requires
- // odd.
- var targetOrientation = (dir[1] & (mxConstants.DIRECTION_MASK_EAST | mxConstants.DIRECTION_MASK_WEST)) > 0 ? 0
- : 1;
- var sameOrient = targetOrientation == initialOrientation ? 0 : 1;
-
- // (currentIndex + 1) % 2 is 0 for even number of points,
- // 1 for odd
- if (sameOrient != (currentIndex + 1) % 2)
- {
- // The last point isn't required
- break;
- }
- }
-
- result.push(new mxPoint(mxEdgeStyle.wayPoints1[i][0], mxEdgeStyle.wayPoints1[i][1]));
- }
- },
-
- getRoutePattern: function(dir, quad, dx, dy)
- {
- var sourceIndex = dir[0] == mxConstants.DIRECTION_MASK_EAST ? 3
- : dir[0];
- var targetIndex = dir[1] == mxConstants.DIRECTION_MASK_EAST ? 3
- : dir[1];
-
- sourceIndex -= quad;
- targetIndex -= quad;
-
- if (sourceIndex < 1)
- {
- sourceIndex += 4;
- }
- if (targetIndex < 1)
- {
- targetIndex += 4;
- }
-
- var result = routePatterns[sourceIndex - 1][targetIndex - 1];
-
- if (dx == 0 || dy == 0)
- {
- if (inlineRoutePatterns[sourceIndex - 1][targetIndex - 1] != null)
- {
- result = inlineRoutePatterns[sourceIndex - 1][targetIndex - 1];
- }
- }
-
- return result;
- }
-}; \ No newline at end of file
diff --git a/src/js/view/mxGraph.js b/src/js/view/mxGraph.js
deleted file mode 100644
index 7c90f9b..0000000
--- a/src/js/view/mxGraph.js
+++ /dev/null
@@ -1,11176 +0,0 @@
-/**
- * $Id: mxGraph.js,v 1.702 2012-12-13 15:07:34 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraph
- *
- * Extends <mxEventSource> to implement a graph component for
- * the browser. This is the main class of the package. To activate
- * panning and connections use <setPanning> and <setConnectable>.
- * For rubberband selection you must create a new instance of
- * <mxRubberband>. The following listeners are added to
- * <mouseListeners> by default:
- *
- * - <tooltipHandler>: <mxTooltipHandler> that displays tooltips
- * - <panningHandler>: <mxPanningHandler> for panning and popup menus
- * - <connectionHandler>: <mxConnectionHandler> for creating connections
- * - <graphHandler>: <mxGraphHandler> for moving and cloning cells
- *
- * These listeners will be called in the above order if they are enabled.
- *
- * Background Images:
- *
- * To display a background image, set the image, image width and
- * image height using <setBackgroundImage>. If one of the
- * above values has changed then the <view>'s <mxGraphView.validate>
- * should be invoked.
- *
- * Cell Images:
- *
- * To use images in cells, a shape must be specified in the default
- * vertex style (or any named style). Possible shapes are
- * <mxConstants.SHAPE_IMAGE> and <mxConstants.SHAPE_LABEL>.
- * The code to change the shape used in the default vertex style,
- * the following code is used:
- *
- * (code)
- * var style = graph.getStylesheet().getDefaultVertexStyle();
- * style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE;
- * (end)
- *
- * For the default vertex style, the image to be displayed can be
- * specified in a cell's style using the <mxConstants.STYLE_IMAGE>
- * key and the image URL as a value, for example:
- *
- * (code)
- * image=http://www.example.com/image.gif
- * (end)
- *
- * For a named style, the the stylename must be the first element
- * of the cell style:
- *
- * (code)
- * stylename;image=http://www.example.com/image.gif
- * (end)
- *
- * A cell style can have any number of key=value pairs added, divided
- * by a semicolon as follows:
- *
- * (code)
- * [stylename;|key=value;]
- * (end)
- *
- * Labels:
- *
- * The cell labels are defined by <getLabel> which uses <convertValueToString>
- * if <labelsVisible> is true. If a label must be rendered as HTML markup, then
- * <isHtmlLabel> should return true for the respective cell. If all labels
- * contain HTML markup, <htmlLabels> can be set to true. NOTE: Enabling HTML
- * labels carries a possible security risk (see the section on security in
- * the manual).
- *
- * If wrapping is needed for a label, then <isHtmlLabel> and <isWrapping> must
- * return true for the cell whose label should be wrapped. See <isWrapping> for
- * an example.
- *
- * If clipping is needed to keep the rendering of a HTML label inside the
- * bounds of its vertex, then <isClipping> should return true for the
- * respective cell.
- *
- * By default, edge labels are movable and vertex labels are fixed. This can be
- * changed by setting <edgeLabelsMovable> and <vertexLabelsMovable>, or by
- * overriding <isLabelMovable>.
- *
- * In-place Editing:
- *
- * In-place editing is started with a doubleclick or by typing F2.
- * Programmatically, <edit> is used to check if the cell is editable
- * (<isCellEditable>) and call <startEditingAtCell>, which invokes
- * <mxCellEditor.startEditing>. The editor uses the value returned
- * by <getEditingValue> as the editing value.
- *
- * After in-place editing, <labelChanged> is called, which invokes
- * <mxGraphModel.setValue>, which in turn calls
- * <mxGraphModel.valueForCellChanged> via <mxValueChange>.
- *
- * The event that triggers in-place editing is passed through to the
- * <cellEditor>, which may take special actions depending on the type of the
- * event or mouse location, and is also passed to <getEditingValue>. The event
- * is then passed back to the event processing functions which can perform
- * specific actions based on the trigger event.
- *
- * Tooltips:
- *
- * Tooltips are implemented by <getTooltip>, which calls <getTooltipForCell>
- * if a cell is under the mousepointer. The default implementation checks if
- * the cell has a getTooltip function and calls it if it exists. Hence, in order
- * to provide custom tooltips, the cell must provide a getTooltip function, or
- * one of the two above functions must be overridden.
- *
- * Typically, for custom cell tooltips, the latter function is overridden as
- * follows:
- *
- * (code)
- * graph.getTooltipForCell = function(cell)
- * {
- * var label = this.convertValueToString(cell);
- * return 'Tooltip for '+label;
- * }
- * (end)
- *
- * When using a config file, the function is overridden in the mxGraph section
- * using the following entry:
- *
- * (code)
- * <add as="getTooltipForCell"><![CDATA[
- * function(cell)
- * {
- * var label = this.convertValueToString(cell);
- * return 'Tooltip for '+label;
- * }
- * ]]></add>
- * (end)
- *
- * "this" refers to the graph in the implementation, so for example to check if
- * a cell is an edge, you use this.getModel().isEdge(cell)
- *
- * For replacing the default implementation of <getTooltipForCell> (rather than
- * replacing the function on a specific instance), the following code should be
- * used after loading the JavaScript files, but before creating a new mxGraph
- * instance using <mxGraph>:
- *
- * (code)
- * mxGraph.prototype.getTooltipForCell = function(cell)
- * {
- * var label = this.convertValueToString(cell);
- * return 'Tooltip for '+label;
- * }
- * (end)
- *
- * Shapes & Styles:
- *
- * The implementation of new shapes is demonstrated in the examples. We'll assume
- * that we have implemented a custom shape with the name BoxShape which we want
- * to use for drawing vertices. To use this shape, it must first be registered in
- * the cell renderer as follows:
- *
- * (code)
- * graph.cellRenderer.registerShape('box', BoxShape);
- * (end)
- *
- * The code registers the BoxShape constructor under the name box in the cell
- * renderer of the graph. The shape can now be referenced using the shape-key in
- * a style definition. (The cell renderer contains a set of additional shapes,
- * namely one for each constant with a SHAPE-prefix in <mxConstants>.)
- *
- * Styles are a collection of key, value pairs and a stylesheet is a collection
- * of named styles. The names are referenced by the cellstyle, which is stored
- * in <mxCell.style> with the following format: [stylename;|key=value;]. The
- * string is resolved to a collection of key, value pairs, where the keys are
- * overridden with the values in the string.
- *
- * When introducing a new shape, the name under which the shape is registered
- * must be used in the stylesheet. There are three ways of doing this:
- *
- * - By changing the default style, so that all vertices will use the new
- * shape
- * - By defining a new style, so that only vertices with the respective
- * cellstyle will use the new shape
- * - By using shape=box in the cellstyle's optional list of key, value pairs
- * to be overridden
- *
- * In the first case, the code to fetch and modify the default style for
- * vertices is as follows:
- *
- * (code)
- * var style = graph.getStylesheet().getDefaultVertexStyle();
- * style[mxConstants.STYLE_SHAPE] = 'box';
- * (end)
- *
- * The code takes the default vertex style, which is used for all vertices that
- * do not have a specific cellstyle, and modifies the value for the shape-key
- * in-place to use the new BoxShape for drawing vertices. This is done by
- * assigning the box value in the second line, which refers to the name of the
- * BoxShape in the cell renderer.
- *
- * In the second case, a collection of key, value pairs is created and then
- * added to the stylesheet under a new name. In order to distinguish the
- * shapename and the stylename we'll use boxstyle for the stylename:
- *
- * (code)
- * var style = new Object();
- * style[mxConstants.STYLE_SHAPE] = 'box';
- * style[mxConstants.STYLE_STROKECOLOR] = '#000000';
- * style[mxConstants.STYLE_FONTCOLOR] = '#000000';
- * graph.getStylesheet().putCellStyle('boxstyle', style);
- * (end)
- *
- * The code adds a new style with the name boxstyle to the stylesheet. To use
- * this style with a cell, it must be referenced from the cellstyle as follows:
- *
- * (code)
- * var vertex = graph.insertVertex(parent, null, 'Hello, World!', 20, 20, 80, 20,
- * 'boxstyle');
- * (end)
- *
- * To summarize, each new shape must be registered in the <mxCellRenderer> with
- * a unique name. That name is then used as the value of the shape-key in a
- * default or custom style. If there are multiple custom shapes, then there
- * should be a separate style for each shape.
- *
- * Inheriting Styles:
- *
- * For fill-, stroke-, gradient- and indicatorColors special keywords can be
- * used. The inherit keyword for one of these colors will inherit the color
- * for the same key from the parent cell. The swimlane keyword does the same,
- * but inherits from the nearest swimlane in the ancestor hierarchy. Finally,
- * the indicated keyword will use the color of the indicator as the color for
- * the given key.
- *
- * Scrollbars:
- *
- * The <containers> overflow CSS property defines if scrollbars are used to
- * display the graph. For values of 'auto' or 'scroll', the scrollbars will
- * be shown. Note that the <resizeContainer> flag is normally not used
- * together with scrollbars, as it will resize the container to match the
- * size of the graph after each change.
- *
- * Multiplicities and Validation:
- *
- * To control the possible connections in mxGraph, <getEdgeValidationError> is
- * used. The default implementation of the function uses <multiplicities>,
- * which is an array of <mxMultiplicity>. Using this class allows to establish
- * simple multiplicities, which are enforced by the graph.
- *
- * The <mxMultiplicity> uses <mxCell.is> to determine for which terminals it
- * applies. The default implementation of <mxCell.is> works with DOM nodes (XML
- * nodes) and checks if the given type parameter matches the nodeName of the
- * node (case insensitive). Optionally, an attributename and value can be
- * specified which are also checked.
- *
- * <getEdgeValidationError> is called whenever the connectivity of an edge
- * changes. It returns an empty string or an error message if the edge is
- * invalid or null if the edge is valid. If the returned string is not empty
- * then it is displayed as an error message.
- *
- * <mxMultiplicity> allows to specify the multiplicity between a terminal and
- * its possible neighbors. For example, if any rectangle may only be connected
- * to, say, a maximum of two circles you can add the following rule to
- * <multiplicities>:
- *
- * (code)
- * graph.multiplicities.push(new mxMultiplicity(
- * true, 'rectangle', null, null, 0, 2, ['circle'],
- * 'Only 2 targets allowed',
- * 'Only shape targets allowed'));
- * (end)
- *
- * This will display the first error message whenever a rectangle is connected
- * to more than two circles and the second error message if a rectangle is
- * connected to anything but a circle.
- *
- * For certain multiplicities, such as a minimum of 1 connection, which cannot
- * be enforced at cell creation time (unless the cell is created together with
- * the connection), mxGraph offers <validate> which checks all multiplicities
- * for all cells and displays the respective error messages in an overlay icon
- * on the cells.
- *
- * If a cell is collapsed and contains validation errors, a respective warning
- * icon is attached to the collapsed cell.
- *
- * Auto-Layout:
- *
- * For automatic layout, the <getLayout> hook is provided in <mxLayoutManager>.
- * It can be overridden to return a layout algorithm for the children of a
- * given cell.
- *
- * Unconnected edges:
- *
- * The default values for all switches are designed to meet the requirements of
- * general diagram drawing applications. A very typical set of settings to
- * avoid edges that are not connected is the following:
- *
- * (code)
- * graph.setAllowDanglingEdges(false);
- * graph.setDisconnectOnMove(false);
- * (end)
- *
- * Setting the <cloneInvalidEdges> switch to true is optional. This switch
- * controls if edges are inserted after a copy, paste or clone-drag if they are
- * invalid. For example, edges are invalid if copied or control-dragged without
- * having selected the corresponding terminals and allowDanglingEdges is
- * false, in which case the edges will not be cloned if the switch is false.
- *
- * Output:
- *
- * To produce an XML representation for a diagram, the following code can be
- * used.
- *
- * (code)
- * var enc = new mxCodec(mxUtils.createXmlDocument());
- * var node = enc.encode(graph.getModel());
- * (end)
- *
- * This will produce an XML node than can be handled using the DOM API or
- * turned into a string representation using the following code:
- *
- * (code)
- * var xml = mxUtils.getXml(node);
- * (end)
- *
- * To obtain a formatted string, mxUtils.getPrettyXml can be used instead.
- *
- * This string can now be stored in a local persistent storage (for example
- * using Google Gears) or it can be passed to a backend using mxUtils.post as
- * follows. The url variable is the URL of the Java servlet, PHP page or HTTP
- * handler, depending on the server.
- *
- * (code)
- * var xmlString = encodeURIComponent(mxUtils.getXml(node));
- * mxUtils.post(url, 'xml='+xmlString, function(req)
- * {
- * // Process server response using req of type mxXmlRequest
- * });
- * (end)
- *
- * Input:
- *
- * To load an XML representation of a diagram into an existing graph object
- * mxUtils.load can be used as follows. The url variable is the URL of the Java
- * servlet, PHP page or HTTP handler that produces the XML string.
- *
- * (code)
- * var xmlDoc = mxUtils.load(url).getXml();
- * var node = xmlDoc.documentElement;
- * var dec = new mxCodec(node.ownerDocument);
- * dec.decode(node, graph.getModel());
- * (end)
- *
- * For creating a page that loads the client and a diagram using a single
- * request please refer to the deployment examples in the backends.
- *
- * Functional dependencies:
- *
- * (see images/callgraph.png)
- *
- * Resources:
- *
- * resources/graph - Language resources for mxGraph
- *
- * Group: Events
- *
- * Event: mxEvent.ROOT
- *
- * Fires if the root in the model has changed. This event has no properties.
- *
- * Event: mxEvent.ALIGN_CELLS
- *
- * Fires between begin- and endUpdate in <alignCells>. The <code>cells</code>
- * and <code>align</code> properties contain the respective arguments that were
- * passed to <alignCells>.
- *
- * Event: mxEvent.FLIP_EDGE
- *
- * Fires between begin- and endUpdate in <flipEdge>. The <code>edge</code>
- * property contains the edge passed to <flipEdge>.
- *
- * Event: mxEvent.ORDER_CELLS
- *
- * Fires between begin- and endUpdate in <orderCells>. The <code>cells</code>
- * and <code>back</code> properties contain the respective arguments that were
- * passed to <orderCells>.
- *
- * Event: mxEvent.CELLS_ORDERED
- *
- * Fires between begin- and endUpdate in <cellsOrdered>. The <code>cells</code>
- * and <code>back</code> arguments contain the respective arguments that were
- * passed to <cellsOrdered>.
- *
- * Event: mxEvent.GROUP_CELLS
- *
- * Fires between begin- and endUpdate in <groupCells>. The <code>group</code>,
- * <code>cells</code> and <code>border</code> arguments contain the respective
- * arguments that were passed to <groupCells>.
- *
- * Event: mxEvent.UNGROUP_CELLS
- *
- * Fires between begin- and endUpdate in <ungroupCells>. The <code>cells</code>
- * property contains the array of cells that was passed to <ungroupCells>.
- *
- * Event: mxEvent.REMOVE_CELLS_FROM_PARENT
- *
- * Fires between begin- and endUpdate in <removeCellsFromParent>. The
- * <code>cells</code> property contains the array of cells that was passed to
- * <removeCellsFromParent>.
- *
- * Event: mxEvent.ADD_CELLS
- *
- * Fires between begin- and endUpdate in <addCells>. The <code>cells</code>,
- * <code>parent</code>, <code>index</code>, <code>source</code> and
- * <code>target</code> properties contain the respective arguments that were
- * passed to <addCells>.
- *
- * Event: mxEvent.CELLS_ADDED
- *
- * Fires between begin- and endUpdate in <cellsAdded>. The <code>cells</code>,
- * <code>parent</code>, <code>index</code>, <code>source</code>,
- * <code>target</code> and <code>absolute</code> properties contain the
- * respective arguments that were passed to <cellsAdded>.
- *
- * Event: mxEvent.REMOVE_CELLS
- *
- * Fires between begin- and endUpdate in <removeCells>. The <code>cells</code>
- * and <code>includeEdges</code> arguments contain the respective arguments
- * that were passed to <removeCells>.
- *
- * Event: mxEvent.CELLS_REMOVED
- *
- * Fires between begin- and endUpdate in <cellsRemoved>. The <code>cells</code>
- * argument contains the array of cells that was removed.
- *
- * Event: mxEvent.SPLIT_EDGE
- *
- * Fires between begin- and endUpdate in <splitEdge>. The <code>edge</code>
- * property contains the edge to be splitted, the <code>cells</code>,
- * <code>newEdge</code>, <code>dx</code> and <code>dy</code> properties contain
- * the respective arguments that were passed to <splitEdge>.
- *
- * Event: mxEvent.TOGGLE_CELLS
- *
- * Fires between begin- and endUpdate in <toggleCells>. The <code>show</code>,
- * <code>cells</code> and <code>includeEdges</code> properties contain the
- * respective arguments that were passed to <toggleCells>.
- *
- * Event: mxEvent.FOLD_CELLS
- *
- * Fires between begin- and endUpdate in <foldCells>. The
- * <code>collapse</code>, <code>cells</code> and <code>recurse</code>
- * properties contain the respective arguments that were passed to <foldCells>.
- *
- * Event: mxEvent.CELLS_FOLDED
- *
- * Fires between begin- and endUpdate in cellsFolded. The
- * <code>collapse</code>, <code>cells</code> and <code>recurse</code>
- * properties contain the respective arguments that were passed to
- * <cellsFolded>.
- *
- * Event: mxEvent.UPDATE_CELL_SIZE
- *
- * Fires between begin- and endUpdate in <updateCellSize>. The
- * <code>cell</code> and <code>ignoreChildren</code> properties contain the
- * respective arguments that were passed to <updateCellSize>.
- *
- * Event: mxEvent.RESIZE_CELLS
- *
- * Fires between begin- and endUpdate in <resizeCells>. The <code>cells</code>
- * and <code>bounds</code> properties contain the respective arguments that
- * were passed to <resizeCells>.
- *
- * Event: mxEvent.CELLS_RESIZED
- *
- * Fires between begin- and endUpdate in <cellsResized>. The <code>cells</code>
- * and <code>bounds</code> properties contain the respective arguments that
- * were passed to <cellsResized>.
- *
- * Event: mxEvent.MOVE_CELLS
- *
- * Fires between begin- and endUpdate in <moveCells>. The <code>cells</code>,
- * <code>dx</code>, <code>dy</code>, <code>clone</code>, <code>target</code>
- * and <code>event</code> properties contain the respective arguments that
- * were passed to <moveCells>.
- *
- * Event: mxEvent.CELLS_MOVED
- *
- * Fires between begin- and endUpdate in <cellsMoved>. The <code>cells</code>,
- * <code>dx</code>, <code>dy</code> and <code>disconnect</code> properties
- * contain the respective arguments that were passed to <cellsMoved>.
- *
- * Event: mxEvent.CONNECT_CELL
- *
- * Fires between begin- and endUpdate in <connectCell>. The <code>edge</code>,
- * <code>terminal</code> and <code>source</code> properties contain the
- * respective arguments that were passed to <connectCell>.
- *
- * Event: mxEvent.CELL_CONNECTED
- *
- * Fires between begin- and endUpdate in <cellConnected>. The
- * <code>edge</code>, <code>terminal</code> and <code>source</code> properties
- * contain the respective arguments that were passed to <cellConnected>.
- *
- * Event: mxEvent.REFRESH
- *
- * Fires after <refresh> was executed. This event has no properties.
- *
- * Event: mxEvent.CLICK
- *
- * Fires in <click> after a click event. The <code>event</code> property
- * contains the original mouse event and <code>cell</code> property contains
- * the cell under the mouse or null if the background was clicked.
- *
- * To handle a click event, use the following code:
- *
- * (code)
- * graph.addListener(mxEvent.CLICK, function(sender, evt)
- * {
- * var e = evt.getProperty('event'); // mouse event
- * var cell = evt.getProperty('cell'); // cell may be null
- *
- * if (!evt.isConsumed())
- * {
- * if (cell != null)
- * {
- * // Do something useful with cell and consume the event
- * evt.consume();
- * }
- * }
- * });
- * (end)
- *
- * Event: mxEvent.DOUBLE_CLICK
- *
- * Fires in <dblClick> after a double click. The <code>event</code> property
- * contains the original mouse event and the <code>cell</code> property
- * contains the cell under the mouse or null if the background was clicked.
- *
- * Event: mxEvent.SIZE
- *
- * Fires after <sizeDidChange> was executed. The <code>bounds</code> property
- * contains the new graph bounds.
- *
- * Event: mxEvent.START_EDITING
- *
- * Fires before the in-place editor starts in <startEditingAtCell>. The
- * <code>cell</code> property contains the cell that is being edited and the
- * <code>event</code> property contains the optional event argument that was
- * passed to <startEditingAtCell>.
- *
- * Event: mxEvent.LABEL_CHANGED
- *
- * Fires between begin- and endUpdate in <cellLabelChanged>. The
- * <code>cell</code> property contains the cell, the <code>value</code>
- * property contains the new value for the cell and the optional
- * <code>event</code> property contains the mouse event that started the edit.
- *
- * Event: mxEvent.ADD_OVERLAY
- *
- * Fires after an overlay is added in <addCellOverlay>. The <code>cell</code>
- * property contains the cell and the <code>overlay</code> property contains
- * the <mxCellOverlay> that was added.
- *
- * Event: mxEvent.REMOVE_OVERLAY
- *
- * Fires after an overlay is removed in <removeCellOverlay> and
- * <removeCellOverlays>. The <code>cell</code> property contains the cell and
- * the <code>overlay</code> property contains the <mxCellOverlay> that was
- * removed.
- *
- * Constructor: mxGraph
- *
- * Constructs a new mxGraph in the specified container. Model is an optional
- * mxGraphModel. If no model is provided, a new mxGraphModel instance is
- * used as the model. The container must have a valid owner document prior
- * to calling this function in Internet Explorer. RenderHint is a string to
- * affect the display performance and rendering in IE, but not in SVG-based
- * browsers. The parameter is mapped to <dialect>, which may
- * be one of <mxConstants.DIALECT_SVG> for SVG-based browsers,
- * <mxConstants.DIALECT_STRICTHTML> for fastest display mode,
- * <mxConstants.DIALECT_PREFERHTML> for faster display mode,
- * <mxConstants.DIALECT_MIXEDHTML> for fast and <mxConstants.DIALECT_VML>
- * for exact display mode (slowest). The dialects are defined in mxConstants.
- * The default values are DIALECT_SVG for SVG-based browsers and
- * DIALECT_MIXED for IE.
- *
- * The possible values for the renderingHint parameter are explained below:
- *
- * fast - The parameter is based on the fact that the display performance is
- * highly improved in IE if the VML is not contained within a VML group
- * element. The lack of a group element only slightly affects the display while
- * panning, but improves the performance by almost a factor of 2, while keeping
- * the display sufficiently accurate. This also allows to render certain shapes as HTML
- * if the display accuracy is not affected, which is implemented by
- * <mxShape.isMixedModeHtml>. This is the default setting and is mapped to
- * DIALECT_MIXEDHTML.
- * faster - Same as fast, but more expensive shapes are avoided. This is
- * controlled by <mxShape.preferModeHtml>. The default implementation will
- * avoid gradients and rounded rectangles, but more significant shapes, such
- * as rhombus, ellipse, actor and cylinder will be rendered accurately. This
- * setting is mapped to DIALECT_PREFERHTML.
- * fastest - Almost anything will be rendered in Html. This allows for
- * rectangles, labels and images. This setting is mapped to
- * DIALECT_STRICTHTML.
- * exact - If accurate panning is required and if the diagram is small (up
- * to 100 cells), then this value should be used. In this mode, a group is
- * created that contains the VML. This allows for accurate panning and is
- * mapped to DIALECT_VML.
- *
- * Example:
- *
- * To create a graph inside a DOM node with an id of graph:
- * (code)
- * var container = document.getElementById('graph');
- * var graph = new mxGraph(container);
- * (end)
- *
- * Parameters:
- *
- * container - Optional DOM node that acts as a container for the graph.
- * If this is null then the container can be initialized later using
- * <init>.
- * model - Optional <mxGraphModel> that constitutes the graph data.
- * renderHint - Optional string that specifies the display accuracy and
- * performance. Default is mxConstants.DIALECT_MIXEDHTML (for IE).
- * stylesheet - Optional <mxStylesheet> to be used in the graph.
- */
-function mxGraph(container, model, renderHint, stylesheet)
-{
- // Initializes the variable in case the prototype has been
- // modified to hold some listeners (which is possible because
- // the createHandlers call is executed regardless of the
- // arguments passed into the ctor).
- this.mouseListeners = null;
-
- // Converts the renderHint into a dialect
- this.renderHint = renderHint;
-
- if (mxClient.IS_SVG)
- {
- this.dialect = mxConstants.DIALECT_SVG;
- }
- else if (renderHint == mxConstants.RENDERING_HINT_EXACT && mxClient.IS_VML)
- {
- this.dialect = mxConstants.DIALECT_VML;
- }
- else if (renderHint == mxConstants.RENDERING_HINT_FASTEST)
- {
- this.dialect = mxConstants.DIALECT_STRICTHTML;
- }
- else if (renderHint == mxConstants.RENDERING_HINT_FASTER)
- {
- this.dialect = mxConstants.DIALECT_PREFERHTML;
- }
- else // default for VML
- {
- this.dialect = mxConstants.DIALECT_MIXEDHTML;
- }
-
- // Initializes the main members that do not require a container
- this.model = (model != null) ? model : new mxGraphModel();
- this.multiplicities = [];
- this.imageBundles = [];
- this.cellRenderer = this.createCellRenderer();
- this.setSelectionModel(this.createSelectionModel());
- this.setStylesheet((stylesheet != null) ? stylesheet : this.createStylesheet());
- this.view = this.createGraphView();
-
- // Adds a graph model listener to update the view
- this.graphModelChangeListener = mxUtils.bind(this, function(sender, evt)
- {
- this.graphModelChanged(evt.getProperty('edit').changes);
- });
-
- this.model.addListener(mxEvent.CHANGE, this.graphModelChangeListener);
-
- // Installs basic event handlers with disabled default settings.
- this.createHandlers();
-
- // Initializes the display if a container was specified
- if (container != null)
- {
- this.init(container);
- }
-
- this.view.revalidate();
-};
-
-/**
- * Installs the required language resources at class
- * loading time.
- */
-if (mxLoadResources)
-{
- mxResources.add(mxClient.basePath+'/resources/graph');
-}
-
-/**
- * Extends mxEventSource.
- */
-mxGraph.prototype = new mxEventSource();
-mxGraph.prototype.constructor = mxGraph;
-
-/**
- * Variable: EMPTY_ARRAY
- *
- * Immutable empty array instance.
- */
-mxGraph.prototype.EMPTY_ARRAY = [];
-
-/**
- * Group: Variables
- */
-
-/**
- * Variable: mouseListeners
- *
- * Holds the mouse event listeners. See <fireMouseEvent>.
- */
-mxGraph.prototype.mouseListeners = null;
-
-/**
- * Variable: isMouseDown
- *
- * Holds the state of the mouse button.
- */
-mxGraph.prototype.isMouseDown = false;
-
-/**
- * Variable: model
- *
- * Holds the <mxGraphModel> that contains the cells to be displayed.
- */
-mxGraph.prototype.model = null;
-
-/**
- * Variable: view
- *
- * Holds the <mxGraphView> that caches the <mxCellStates> for the cells.
- */
-mxGraph.prototype.view = null;
-
-/**
- * Variable: stylesheet
- *
- * Holds the <mxStylesheet> that defines the appearance of the cells.
- *
- *
- * Example:
- *
- * Use the following code to read a stylesheet into an existing graph.
- *
- * (code)
- * var req = mxUtils.load('stylesheet.xml');
- * var root = req.getDocumentElement();
- * var dec = new mxCodec(root.ownerDocument);
- * dec.decode(root, graph.stylesheet);
- * (end)
- */
-mxGraph.prototype.stylesheet = null;
-
-/**
- * Variable: selectionModel
- *
- * Holds the <mxGraphSelectionModel> that models the current selection.
- */
-mxGraph.prototype.selectionModel = null;
-
-/**
- * Variable: cellEditor
- *
- * Holds the <mxCellEditor> that is used as the in-place editing.
- */
-mxGraph.prototype.cellEditor = null;
-
-/**
- * Variable: cellRenderer
- *
- * Holds the <mxCellRenderer> for rendering the cells in the graph.
- */
-mxGraph.prototype.cellRenderer = null;
-
-/**
- * Variable: multiplicities
- *
- * An array of <mxMultiplicities> describing the allowed
- * connections in a graph.
- */
-mxGraph.prototype.multiplicities = null;
-
-/**
- * Variable: renderHint
- *
- * RenderHint as it was passed to the constructor.
- */
-mxGraph.prototype.renderHint = null;
-
-/**
- * Variable: dialect
- *
- * Dialect to be used for drawing the graph. Possible values are all
- * constants in <mxConstants> with a DIALECT-prefix.
- */
-mxGraph.prototype.dialect = null;
-
-/**
- * Variable: gridSize
- *
- * Specifies the grid size. Default is 10.
- */
-mxGraph.prototype.gridSize = 10;
-
-/**
- * Variable: gridEnabled
- *
- * Specifies if the grid is enabled. This is used in <snap>. Default is
- * true.
- */
-mxGraph.prototype.gridEnabled = true;
-
-/**
- * Variable: portsEnabled
- *
- * Specifies if ports are enabled. This is used in <cellConnected> to update
- * the respective style. Default is true.
- */
-mxGraph.prototype.portsEnabled = true;
-
-/**
- * Variable: doubleTapEnabled
- *
- * Specifies if double taps on touch-based devices should be handled. Default
- * is true.
- */
-mxGraph.prototype.doubleTapEnabled = true;
-
-/**
- * Variable: doubleTapTimeout
- *
- * Specifies the timeout for double taps. Default is 700 ms.
- */
-mxGraph.prototype.doubleTapTimeout = 700;
-
-/**
- * Variable: doubleTapTolerance
- *
- * Specifies the tolerance for double taps. Default is 25 pixels.
- */
-mxGraph.prototype.doubleTapTolerance = 25;
-
-/**
- * Variable: lastTouchX
- *
- * Holds the x-coordinate of the last touch event for double tap detection.
- */
-mxGraph.prototype.lastTouchY = 0;
-
-/**
- * Variable: lastTouchX
- *
- * Holds the y-coordinate of the last touch event for double tap detection.
- */
-mxGraph.prototype.lastTouchY = 0;
-
-/**
- * Variable: lastTouchTime
- *
- * Holds the time of the last touch event for double click detection.
- */
-mxGraph.prototype.lastTouchTime = 0;
-
-/**
- * Variable: gestureEnabled
- *
- * Specifies if the handleGesture method should be invoked. Default is true. This
- * is an experimental feature for touch-based devices.
- */
-mxGraph.prototype.gestureEnabled = true;
-
-/**
- * Variable: tolerance
- *
- * Tolerance for a move to be handled as a single click.
- * Default is 4 pixels.
- */
-mxGraph.prototype.tolerance = 4;
-
-/**
- * Variable: defaultOverlap
- *
- * Value returned by <getOverlap> if <isAllowOverlapParent> returns
- * true for the given cell. <getOverlap> is used in <constrainChild> if
- * <isConstrainChild> returns true. The value specifies the
- * portion of the child which is allowed to overlap the parent.
- */
-mxGraph.prototype.defaultOverlap = 0.5;
-
-/**
- * Variable: defaultParent
- *
- * Specifies the default parent to be used to insert new cells.
- * This is used in <getDefaultParent>. Default is null.
- */
-mxGraph.prototype.defaultParent = null;
-
-/**
- * Variable: alternateEdgeStyle
- *
- * Specifies the alternate edge style to be used if the main control point
- * on an edge is being doubleclicked. Default is null.
- */
-mxGraph.prototype.alternateEdgeStyle = null;
-
-/**
- * Variable: backgroundImage
- *
- * Specifies the <mxImage> to be returned by <getBackgroundImage>. Default
- * is null.
- *
- * Example:
- *
- * (code)
- * var img = new mxImage('http://www.example.com/maps/examplemap.jpg', 1024, 768);
- * graph.setBackgroundImage(img);
- * graph.view.validate();
- * (end)
- */
-mxGraph.prototype.backgroundImage = null;
-
-/**
- * Variable: pageVisible
- *
- * Specifies if the background page should be visible. Default is false.
- * Not yet implemented.
- */
-mxGraph.prototype.pageVisible = false;
-
-/**
- * Variable: pageBreaksVisible
- *
- * Specifies if a dashed line should be drawn between multiple pages. Default
- * is false. If you change this value while a graph is being displayed then you
- * should call <sizeDidChange> to force an update of the display.
- */
-mxGraph.prototype.pageBreaksVisible = false;
-
-/**
- * Variable: pageBreakColor
- *
- * Specifies the color for page breaks. Default is 'gray'.
- */
-mxGraph.prototype.pageBreakColor = 'gray';
-
-/**
- * Variable: pageBreakDashed
- *
- * Specifies the page breaks should be dashed. Default is true.
- */
-mxGraph.prototype.pageBreakDashed = true;
-
-/**
- * Variable: minPageBreakDist
- *
- * Specifies the minimum distance for page breaks to be visible. Default is
- * 20 (in pixels).
- */
-mxGraph.prototype.minPageBreakDist = 20;
-
-/**
- * Variable: preferPageSize
- *
- * Specifies if the graph size should be rounded to the next page number in
- * <sizeDidChange>. This is only used if the graph container has scrollbars.
- * Default is false.
- */
-mxGraph.prototype.preferPageSize = false;
-
-/**
- * Variable: pageFormat
- *
- * Specifies the page format for the background page. Default is
- * <mxConstants.PAGE_FORMAT_A4_PORTRAIT>. This is used as the default in
- * <mxPrintPreview> and for painting the background page if <pageVisible> is
- * true and the pagebreaks if <pageBreaksVisible> is true.
- */
-mxGraph.prototype.pageFormat = mxConstants.PAGE_FORMAT_A4_PORTRAIT;
-
-/**
- * Variable: pageScale
- *
- * Specifies the scale of the background page. Default is 1.5.
- * Not yet implemented.
- */
-mxGraph.prototype.pageScale = 1.5;
-
-/**
- * Variable: enabled
- *
- * Specifies the return value for <isEnabled>. Default is true.
- */
-mxGraph.prototype.enabled = true;
-
-/**
- * Variable: escapeEnabled
- *
- * Specifies if <mxKeyHandler> should invoke <escape> when the escape key
- * is pressed. Default is true.
- */
-mxGraph.prototype.escapeEnabled = true;
-
-/**
- * Variable: invokesStopCellEditing
- *
- * If true, when editing is to be stopped by way of selection changing,
- * data in diagram changing or other means stopCellEditing is invoked, and
- * changes are saved. This is implemented in a focus handler in
- * <mxCellEditor>. Default is true.
- */
-mxGraph.prototype.invokesStopCellEditing = true;
-
-/**
- * Variable: enterStopsCellEditing
- *
- * If true, pressing the enter key without pressing control or shift will stop
- * editing and accept the new value. This is used in <mxCellEditor> to stop
- * cell editing. Note: You can always use F2 and escape to stop editing.
- * Default is false.
- */
-mxGraph.prototype.enterStopsCellEditing = false;
-
-/**
- * Variable: useScrollbarsForPanning
- *
- * Specifies if scrollbars should be used for panning in <panGraph> if
- * any scrollbars are available. If scrollbars are enabled in CSS, but no
- * scrollbars appear because the graph is smaller than the container size,
- * then no panning occurs if this is true. Default is true.
- */
-mxGraph.prototype.useScrollbarsForPanning = true;
-
-/**
- * Variable: exportEnabled
- *
- * Specifies the return value for <canExportCell>. Default is true.
- */
-mxGraph.prototype.exportEnabled = true;
-
-/**
- * Variable: importEnabled
- *
- * Specifies the return value for <canImportCell>. Default is true.
- */
-mxGraph.prototype.importEnabled = true;
-
-/**
- * Variable: cellsLocked
- *
- * Specifies the return value for <isCellLocked>. Default is false.
- */
-mxGraph.prototype.cellsLocked = false;
-
-/**
- * Variable: cellsCloneable
- *
- * Specifies the return value for <isCellCloneable>. Default is true.
- */
-mxGraph.prototype.cellsCloneable = true;
-
-/**
- * Variable: foldingEnabled
- *
- * Specifies if folding (collapse and expand via an image icon in the graph
- * should be enabled). Default is true.
- */
-mxGraph.prototype.foldingEnabled = true;
-
-/**
- * Variable: cellsEditable
- *
- * Specifies the return value for <isCellEditable>. Default is true.
- */
-mxGraph.prototype.cellsEditable = true;
-
-/**
- * Variable: cellsDeletable
- *
- * Specifies the return value for <isCellDeletable>. Default is true.
- */
-mxGraph.prototype.cellsDeletable = true;
-
-/**
- * Variable: cellsMovable
- *
- * Specifies the return value for <isCellMovable>. Default is true.
- */
-mxGraph.prototype.cellsMovable = true;
-
-/**
- * Variable: edgeLabelsMovable
- *
- * Specifies the return value for edges in <isLabelMovable>. Default is true.
- */
-mxGraph.prototype.edgeLabelsMovable = true;
-
-/**
- * Variable: vertexLabelsMovable
- *
- * Specifies the return value for vertices in <isLabelMovable>. Default is false.
- */
-mxGraph.prototype.vertexLabelsMovable = false;
-
-/**
- * Variable: dropEnabled
- *
- * Specifies the return value for <isDropEnabled>. Default is false.
- */
-mxGraph.prototype.dropEnabled = false;
-
-/**
- * Variable: splitEnabled
- *
- * Specifies if dropping onto edges should be enabled. Default is true.
- */
-mxGraph.prototype.splitEnabled = true;
-
-/**
- * Variable: cellsResizable
- *
- * Specifies the return value for <isCellResizable>. Default is true.
- */
-mxGraph.prototype.cellsResizable = true;
-
-/**
- * Variable: cellsBendable
- *
- * Specifies the return value for <isCellsBendable>. Default is true.
- */
-mxGraph.prototype.cellsBendable = true;
-
-/**
- * Variable: cellsSelectable
- *
- * Specifies the return value for <isCellSelectable>. Default is true.
- */
-mxGraph.prototype.cellsSelectable = true;
-
-/**
- * Variable: cellsDisconnectable
- *
- * Specifies the return value for <isCellDisconntable>. Default is true.
- */
-mxGraph.prototype.cellsDisconnectable = true;
-
-/**
- * Variable: autoSizeCells
- *
- * Specifies if the graph should automatically update the cell size after an
- * edit. This is used in <isAutoSizeCell>. Default is false.
- */
-mxGraph.prototype.autoSizeCells = false;
-
-/**
- * Variable: autoScroll
- *
- * Specifies if the graph should automatically scroll if the mouse goes near
- * the container edge while dragging. This is only taken into account if the
- * container has scrollbars. Default is true.
- *
- * If you need this to work without scrollbars then set <ignoreScrollbars> to
- * true.
- */
-mxGraph.prototype.autoScroll = true;
-
-/**
- * Variable: timerAutoScroll
- *
- * Specifies if timer-based autoscrolling should be used via mxPanningManager.
- * Note that this disables the code in <scrollPointToVisible> and uses code in
- * mxPanningManager instead. Note that <autoExtend> is disabled if this is
- * true and that this should only be used with a scroll buffer or when
- * scollbars are visible and scrollable in all directions. Default is false.
- */
-mxGraph.prototype.timerAutoScroll = false;
-
-/**
- * Variable: allowAutoPanning
- *
- * Specifies if panning via <panGraph> should be allowed to implement autoscroll
- * if no scrollbars are available in <scrollPointToVisible>. Default is false.
- */
-mxGraph.prototype.allowAutoPanning = false;
-
-/**
- * Variable: ignoreScrollbars
- *
- * Specifies if the graph should automatically scroll regardless of the
- * scrollbars.
- */
-mxGraph.prototype.ignoreScrollbars = false;
-
-/**
- * Variable: autoExtend
- *
- * Specifies if the size of the graph should be automatically extended if the
- * mouse goes near the container edge while dragging. This is only taken into
- * account if the container has scrollbars. Default is true. See <autoScroll>.
- */
-mxGraph.prototype.autoExtend = true;
-
-/**
- * Variable: maximumGraphBounds
- *
- * <mxRectangle> that specifies the area in which all cells in the diagram
- * should be placed. Uses in <getMaximumGraphBounds>. Use a width or height of
- * 0 if you only want to give a upper, left corner.
- */
-mxGraph.prototype.maximumGraphBounds = null;
-
-/**
- * Variable: minimumGraphSize
- *
- * <mxRectangle> that specifies the minimum size of the graph. This is ignored
- * if the graph container has no scrollbars. Default is null.
- */
-mxGraph.prototype.minimumGraphSize = null;
-
-/**
- * Variable: minimumContainerSize
- *
- * <mxRectangle> that specifies the minimum size of the <container> if
- * <resizeContainer> is true.
- */
-mxGraph.prototype.minimumContainerSize = null;
-
-/**
- * Variable: maximumContainerSize
- *
- * <mxRectangle> that specifies the maximum size of the container if
- * <resizeContainer> is true.
- */
-mxGraph.prototype.maximumContainerSize = null;
-
-/**
- * Variable: resizeContainer
- *
- * Specifies if the container should be resized to the graph size when
- * the graph size has changed. Default is false.
- */
-mxGraph.prototype.resizeContainer = false;
-
-/**
- * Variable: border
- *
- * Border to be added to the bottom and right side when the container is
- * being resized after the graph has been changed. Default is 0.
- */
-mxGraph.prototype.border = 0;
-
-/**
- * Variable: ordered
- *
- * Specifies if the display should reflect the order of the cells in
- * the model. Default is true. This has precendence over
- * <keepEdgesInBackground> and <keepEdgesInForeground>.
- */
-mxGraph.prototype.ordered = true;
-
-/**
- * Variable: keepEdgesInForeground
- *
- * Specifies if edges should appear in the foreground regardless of their
- * order in the model. This has precendence over <keepEdgeInBackground>,
- * but not over <ordered>. Default is false.
- */
-mxGraph.prototype.keepEdgesInForeground = false;
-
-/**
- * Variable: keepEdgesInBackground
- *
- * Specifies if edges should appear in the background regardless of their
- * order in the model. <ordered> and <keepEdgesInForeground> have
- * precedence over this setting. Default is true.
- */
-mxGraph.prototype.keepEdgesInBackground = true;
-
-/**
- * Variable: allowNegativeCoordinates
- *
- * Specifies if negative coordinates for vertices are allowed. Default is true.
- */
-mxGraph.prototype.allowNegativeCoordinates = true;
-
-/**
- * Variable: constrainChildren
- *
- * Specifies the return value for <isConstrainChildren>. Default is
- * true.
- */
-mxGraph.prototype.constrainChildren = true;
-
-/**
- * Variable: extendParents
- *
- * Specifies if a parent should contain the child bounds after a resize of
- * the child. Default is true.
- */
-mxGraph.prototype.extendParents = true;
-
-/**
- * Variable: extendParentsOnAdd
- *
- * Specifies if parents should be extended according to the <extendParents>
- * switch if cells are added. Default is true.
- */
-mxGraph.prototype.extendParentsOnAdd = true;
-
-/**
- * Variable: collapseToPreferredSize
- *
- * Specifies if the cell size should be changed to the preferred size when
- * a cell is first collapsed. Default is true.
- */
-mxGraph.prototype.collapseToPreferredSize = true;
-
-/**
- * Variable: zoomFactor
- *
- * Specifies the factor used for <zoomIn> and <zoomOut>. Default is 1.2
- * (120%).
- */
-mxGraph.prototype.zoomFactor = 1.2;
-
-/**
- * Variable: keepSelectionVisibleOnZoom
- *
- * Specifies if the viewport should automatically contain the selection cells
- * after a zoom operation. Default is false.
- */
-mxGraph.prototype.keepSelectionVisibleOnZoom = false;
-
-/**
- * Variable: centerZoom
- *
- * Specifies if the zoom operations should go into the center of the actual
- * diagram rather than going from top, left. Default is true.
- */
-mxGraph.prototype.centerZoom = true;
-
-/**
- * Variable: resetViewOnRootChange
- *
- * Specifies if the scale and translate should be reset if the root changes in
- * the model. Default is true.
- */
-mxGraph.prototype.resetViewOnRootChange = true;
-
-/**
- * Variable: resetEdgesOnResize
- *
- * Specifies if edge control points should be reset after the resize of a
- * connected cell. Default is false.
- */
-mxGraph.prototype.resetEdgesOnResize = false;
-
-/**
- * Variable: resetEdgesOnMove
- *
- * Specifies if edge control points should be reset after the move of a
- * connected cell. Default is false.
- */
-mxGraph.prototype.resetEdgesOnMove = false;
-
-/**
- * Variable: resetEdgesOnConnect
- *
- * Specifies if edge control points should be reset after the the edge has been
- * reconnected. Default is true.
- */
-mxGraph.prototype.resetEdgesOnConnect = true;
-
-/**
- * Variable: allowLoops
- *
- * Specifies if loops (aka self-references) are allowed. Default is false.
- */
-mxGraph.prototype.allowLoops = false;
-
-/**
- * Variable: defaultLoopStyle
- *
- * <mxEdgeStyle> to be used for loops. This is a fallback for loops if the
- * <mxConstants.STYLE_LOOP> is undefined. Default is <mxEdgeStyle.Loop>.
- */
-mxGraph.prototype.defaultLoopStyle = mxEdgeStyle.Loop;
-
-/**
- * Variable: multigraph
- *
- * Specifies if multiple edges in the same direction between the same pair of
- * vertices are allowed. Default is true.
- */
-mxGraph.prototype.multigraph = true;
-
-/**
- * Variable: connectableEdges
- *
- * Specifies if edges are connectable. Default is false. This overrides the
- * connectable field in edges.
- */
-mxGraph.prototype.connectableEdges = false;
-
-/**
- * Variable: allowDanglingEdges
- *
- * Specifies if edges with disconnected terminals are allowed in the graph.
- * Default is true.
- */
-mxGraph.prototype.allowDanglingEdges = true;
-
-/**
- * Variable: cloneInvalidEdges
- *
- * Specifies if edges that are cloned should be validated and only inserted
- * if they are valid. Default is true.
- */
-mxGraph.prototype.cloneInvalidEdges = false;
-
-/**
- * Variable: disconnectOnMove
- *
- * Specifies if edges should be disconnected from their terminals when they
- * are moved. Default is true.
- */
-mxGraph.prototype.disconnectOnMove = true;
-
-/**
- * Variable: labelsVisible
- *
- * Specifies if labels should be visible. This is used in <getLabel>. Default
- * is true.
- */
-mxGraph.prototype.labelsVisible = true;
-
-/**
- * Variable: htmlLabels
- *
- * Specifies the return value for <isHtmlLabel>. Default is false.
- */
-mxGraph.prototype.htmlLabels = false;
-
-/**
- * Variable: swimlaneSelectionEnabled
- *
- * Specifies if swimlanes should be selectable via the content if the
- * mouse is released. Default is true.
- */
-mxGraph.prototype.swimlaneSelectionEnabled = true;
-
-/**
- * Variable: swimlaneNesting
- *
- * Specifies if nesting of swimlanes is allowed. Default is true.
- */
-mxGraph.prototype.swimlaneNesting = true;
-
-/**
- * Variable: swimlaneIndicatorColorAttribute
- *
- * The attribute used to find the color for the indicator if the indicator
- * color is set to 'swimlane'. Default is <mxConstants.STYLE_FILLCOLOR>.
- */
-mxGraph.prototype.swimlaneIndicatorColorAttribute = mxConstants.STYLE_FILLCOLOR;
-
-/**
- * Variable: imageBundles
- *
- * Holds the list of image bundles.
- */
-mxGraph.prototype.imageBundles = null;
-
-/**
- * Variable: minFitScale
- *
- * Specifies the minimum scale to be applied in <fit>. Default is 0.1. Set this
- * to null to allow any value.
- */
-mxGraph.prototype.minFitScale = 0.1;
-
-/**
- * Variable: maxFitScale
- *
- * Specifies the maximum scale to be applied in <fit>. Default is 8. Set this
- * to null to allow any value.
- */
-mxGraph.prototype.maxFitScale = 8;
-
-/**
- * Variable: panDx
- *
- * Current horizontal panning value. Default is 0.
- */
-mxGraph.prototype.panDx = 0;
-
-/**
- * Variable: panDy
- *
- * Current vertical panning value. Default is 0.
- */
-mxGraph.prototype.panDy = 0;
-
-/**
- * Variable: collapsedImage
- *
- * Specifies the <mxImage> to indicate a collapsed state.
- * Default value is mxClient.imageBasePath + '/collapsed.gif'
- */
-mxGraph.prototype.collapsedImage = new mxImage(mxClient.imageBasePath + '/collapsed.gif', 9, 9);
-
-/**
- * Variable: expandedImage
- *
- * Specifies the <mxImage> to indicate a expanded state.
- * Default value is mxClient.imageBasePath + '/expanded.gif'
- */
-mxGraph.prototype.expandedImage = new mxImage(mxClient.imageBasePath + '/expanded.gif', 9, 9);
-
-/**
- * Variable: warningImage
- *
- * Specifies the <mxImage> for the image to be used to display a warning
- * overlay. See <setCellWarning>. Default value is mxClient.imageBasePath +
- * '/warning'. The extension for the image depends on the platform. It is
- * '.png' on the Mac and '.gif' on all other platforms.
- */
-mxGraph.prototype.warningImage = new mxImage(mxClient.imageBasePath + '/warning'+
- ((mxClient.IS_MAC) ? '.png' : '.gif'), 16, 16);
-
-/**
- * Variable: alreadyConnectedResource
- *
- * Specifies the resource key for the error message to be displayed in
- * non-multigraphs when two vertices are already connected. If the resource
- * for this key does not exist then the value is used as the error message.
- * Default is 'alreadyConnected'.
- */
-mxGraph.prototype.alreadyConnectedResource = (mxClient.language != 'none') ? 'alreadyConnected' : '';
-
-/**
- * Variable: containsValidationErrorsResource
- *
- * Specifies the resource key for the warning message to be displayed when
- * a collapsed cell contains validation errors. If the resource for this
- * key does not exist then the value is used as the warning message.
- * Default is 'containsValidationErrors'.
- */
-mxGraph.prototype.containsValidationErrorsResource = (mxClient.language != 'none') ? 'containsValidationErrors' : '';
-
-/**
- * Variable: collapseExpandResource
- *
- * Specifies the resource key for the tooltip on the collapse/expand icon.
- * If the resource for this key does not exist then the value is used as
- * the tooltip. Default is 'collapse-expand'.
- */
-mxGraph.prototype.collapseExpandResource = (mxClient.language != 'none') ? 'collapse-expand' : '';
-
-/**
- * Function: init
- *
- * Initializes the <container> and creates the respective datastructures.
- *
- * Parameters:
- *
- * container - DOM node that will contain the graph display.
- */
- mxGraph.prototype.init = function(container)
- {
- this.container = container;
-
- // Initializes the in-place editor
- this.cellEditor = this.createCellEditor();
-
- // Initializes the container using the view
- this.view.init();
-
- // Updates the size of the container for the current graph
- this.sizeDidChange();
-
- // Automatic deallocation of memory
- if (mxClient.IS_IE)
- {
- mxEvent.addListener(window, 'unload', mxUtils.bind(this, function()
- {
- this.destroy();
- }));
-
- // Disable shift-click for text
- mxEvent.addListener(container, 'selectstart',
- mxUtils.bind(this, function()
- {
- return this.isEditing();
- })
- );
- }
-};
-
-/**
- * Function: createHandlers
- *
- * Creates the tooltip-, panning-, connection- and graph-handler (in this
- * order). This is called in the constructor before <init> is called.
- */
-mxGraph.prototype.createHandlers = function(container)
-{
- this.tooltipHandler = new mxTooltipHandler(this);
- this.tooltipHandler.setEnabled(false);
- this.panningHandler = new mxPanningHandler(this);
- this.panningHandler.panningEnabled = false;
- this.selectionCellsHandler = new mxSelectionCellsHandler(this);
- this.connectionHandler = new mxConnectionHandler(this);
- this.connectionHandler.setEnabled(false);
- this.graphHandler = new mxGraphHandler(this);
-};
-
-/**
- * Function: createSelectionModel
- *
- * Creates a new <mxGraphSelectionModel> to be used in this graph.
- */
-mxGraph.prototype.createSelectionModel = function()
-{
- return new mxGraphSelectionModel(this);
-};
-
-/**
- * Function: createStylesheet
- *
- * Creates a new <mxGraphSelectionModel> to be used in this graph.
- */
-mxGraph.prototype.createStylesheet = function()
-{
- return new mxStylesheet();
-};
-
-/**
- * Function: createGraphView
- *
- * Creates a new <mxGraphView> to be used in this graph.
- */
-mxGraph.prototype.createGraphView = function()
-{
- return new mxGraphView(this);
-};
-
-/**
- * Function: createCellRenderer
- *
- * Creates a new <mxCellRenderer> to be used in this graph.
- */
-mxGraph.prototype.createCellRenderer = function()
-{
- return new mxCellRenderer();
-};
-
-/**
- * Function: createCellEditor
- *
- * Creates a new <mxCellEditor> to be used in this graph.
- */
-mxGraph.prototype.createCellEditor = function()
-{
- return new mxCellEditor(this);
-};
-
-/**
- * Function: getModel
- *
- * Returns the <mxGraphModel> that contains the cells.
- */
-mxGraph.prototype.getModel = function()
-{
- return this.model;
-};
-
-/**
- * Function: getView
- *
- * Returns the <mxGraphView> that contains the <mxCellStates>.
- */
-mxGraph.prototype.getView = function()
-{
- return this.view;
-};
-
-/**
- * Function: getStylesheet
- *
- * Returns the <mxStylesheet> that defines the style.
- */
-mxGraph.prototype.getStylesheet = function()
-{
- return this.stylesheet;
-};
-
-/**
- * Function: setStylesheet
- *
- * Sets the <mxStylesheet> that defines the style.
- */
-mxGraph.prototype.setStylesheet = function(stylesheet)
-{
- this.stylesheet = stylesheet;
-};
-
-/**
- * Function: getSelectionModel
- *
- * Returns the <mxGraphSelectionModel> that contains the selection.
- */
-mxGraph.prototype.getSelectionModel = function()
-{
- return this.selectionModel;
-};
-
-/**
- * Function: setSelectionModel
- *
- * Sets the <mxSelectionModel> that contains the selection.
- */
-mxGraph.prototype.setSelectionModel = function(selectionModel)
-{
- this.selectionModel = selectionModel;
-};
-
-/**
- * Function: getSelectionCellsForChanges
- *
- * Returns the cells to be selected for the given array of changes.
- */
-mxGraph.prototype.getSelectionCellsForChanges = function(changes)
-{
- var cells = [];
-
- for (var i = 0; i < changes.length; i++)
- {
- var change = changes[i];
-
- if (change.constructor != mxRootChange)
- {
- var cell = null;
-
- if (change instanceof mxChildChange && change.previous == null)
- {
- cell = change.child;
- }
- else if (change.cell != null && change.cell instanceof mxCell)
- {
- cell = change.cell;
- }
-
- if (cell != null && mxUtils.indexOf(cells, cell) < 0)
- {
- cells.push(cell);
- }
- }
- }
-
- return this.getModel().getTopmostCells(cells);
-};
-
-/**
- * Function: graphModelChanged
- *
- * Called when the graph model changes. Invokes <processChange> on each
- * item of the given array to update the view accordingly.
- *
- * Parameters:
- *
- * changes - Array that contains the individual changes.
- */
-mxGraph.prototype.graphModelChanged = function(changes)
-{
- for (var i = 0; i < changes.length; i++)
- {
- this.processChange(changes[i]);
- }
-
- this.removeSelectionCells(this.getRemovedCellsForChanges(changes));
-
- this.view.validate();
- this.sizeDidChange();
-};
-
-/**
- * Function: getRemovedCellsForChanges
- *
- * Returns the cells that have been removed from the model.
- */
-mxGraph.prototype.getRemovedCellsForChanges = function(changes)
-{
- var result = [];
-
- for (var i = 0; i < changes.length; i++)
- {
- var change = changes[i];
-
- // Resets the view settings, removes all cells and clears
- // the selection if the root changes.
- if (change instanceof mxRootChange)
- {
- break;
- }
- else if (change instanceof mxChildChange)
- {
- if (change.previous != null && change.parent == null)
- {
- result = result.concat(this.model.getDescendants(change.child));
- }
- }
- else if (change instanceof mxVisibleChange)
- {
- result = result.concat(this.model.getDescendants(change.cell));
- }
- }
-
- return result;
-};
-
-/**
- * Function: processChange
- *
- * Processes the given change and invalidates the respective cached data
- * in <view>. This fires a <root> event if the root has changed in the
- * model.
- *
- * Parameters:
- *
- * change - Object that represents the change on the model.
- */
-mxGraph.prototype.processChange = function(change)
-{
- // Resets the view settings, removes all cells and clears
- // the selection if the root changes.
- if (change instanceof mxRootChange)
- {
- this.clearSelection();
- this.removeStateForCell(change.previous);
-
- if (this.resetViewOnRootChange)
- {
- this.view.scale = 1;
- this.view.translate.x = 0;
- this.view.translate.y = 0;
- }
-
- this.fireEvent(new mxEventObject(mxEvent.ROOT));
- }
-
- // Adds or removes a child to the view by online invaliding
- // the minimal required portions of the cache, namely, the
- // old and new parent and the child.
- else if (change instanceof mxChildChange)
- {
- var newParent = this.model.getParent(change.child);
-
- if (newParent != null)
- {
- // Flags the cell for updating the order in the renderer
- this.view.invalidate(change.child, true, false, change.previous != null);
- }
- else
- {
- this.removeStateForCell(change.child);
-
- // Handles special case of current root of view being removed
- if (this.view.currentRoot == change.child)
- {
- this.home();
- }
- }
-
- if (newParent != change.previous)
- {
- // Refreshes the collapse/expand icons on the parents
- if (newParent != null)
- {
- this.view.invalidate(newParent, false, false);
- }
-
- if (change.previous != null)
- {
- this.view.invalidate(change.previous, false, false);
- }
- }
- }
-
- // Handles two special cases where the shape does not need to be
- // recreated from scratch, it only need to be invalidated.
- else if (change instanceof mxTerminalChange ||
- change instanceof mxGeometryChange)
- {
- this.view.invalidate(change.cell);
- }
-
- // Handles two special cases where only the shape, but no
- // descendants need to be recreated
- else if (change instanceof mxValueChange)
- {
- this.view.invalidate(change.cell, false, false);
- }
-
- // Requires a new mxShape in JavaScript
- else if (change instanceof mxStyleChange)
- {
- this.view.invalidate(change.cell, true, true, false);
- this.view.removeState(change.cell);
- }
-
- // Removes the state from the cache by default
- else if (change.cell != null &&
- change.cell instanceof mxCell)
- {
- this.removeStateForCell(change.cell);
- }
-};
-
-/**
- * Function: removeStateForCell
- *
- * Removes all cached information for the given cell and its descendants.
- * This is called when a cell was removed from the model.
- *
- * Paramters:
- *
- * cell - <mxCell> that was removed from the model.
- */
-mxGraph.prototype.removeStateForCell = function(cell)
-{
- var childCount = this.model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- this.removeStateForCell(this.model.getChildAt(cell, i));
- }
-
- this.view.removeState(cell);
-};
-
-/**
- * Group: Overlays
- */
-
-/**
- * Function: addCellOverlay
- *
- * Adds an <mxCellOverlay> for the specified cell. This method fires an
- * <addoverlay> event and returns the new <mxCellOverlay>.
- *
- * Parameters:
- *
- * cell - <mxCell> to add the overlay for.
- * overlay - <mxCellOverlay> to be added for the cell.
- */
-mxGraph.prototype.addCellOverlay = function(cell, overlay)
-{
- if (cell.overlays == null)
- {
- cell.overlays = [];
- }
-
- cell.overlays.push(overlay);
-
- var state = this.view.getState(cell);
-
- // Immediately updates the cell display if the state exists
- if (state != null)
- {
- this.cellRenderer.redraw(state);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.ADD_OVERLAY,
- 'cell', cell, 'overlay', overlay));
-
- return overlay;
-};
-
-/**
- * Function: getCellOverlays
- *
- * Returns the array of <mxCellOverlays> for the given cell or null, if
- * no overlays are defined.
- *
- * Parameters:
- *
- * cell - <mxCell> whose overlays should be returned.
- */
-mxGraph.prototype.getCellOverlays = function(cell)
-{
- return cell.overlays;
-};
-
-/**
- * Function: removeCellOverlay
- *
- * Removes and returns the given <mxCellOverlay> from the given cell. This
- * method fires a <removeoverlay> event. If no overlay is given, then all
- * overlays are removed using <removeOverlays>.
- *
- * Parameters:
- *
- * cell - <mxCell> whose overlay should be removed.
- * overlay - Optional <mxCellOverlay> to be removed.
- */
-mxGraph.prototype.removeCellOverlay = function(cell, overlay)
-{
- if (overlay == null)
- {
- this.removeCellOverlays(cell);
- }
- else
- {
- var index = mxUtils.indexOf(cell.overlays, overlay);
-
- if (index >= 0)
- {
- cell.overlays.splice(index, 1);
-
- if (cell.overlays.length == 0)
- {
- cell.overlays = null;
- }
-
- // Immediately updates the cell display if the state exists
- var state = this.view.getState(cell);
-
- if (state != null)
- {
- this.cellRenderer.redraw(state);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.REMOVE_OVERLAY,
- 'cell', cell, 'overlay', overlay));
- }
- else
- {
- overlay = null;
- }
- }
-
- return overlay;
-};
-
-/**
- * Function: removeCellOverlays
- *
- * Removes all <mxCellOverlays> from the given cell. This method
- * fires a <removeoverlay> event for each <mxCellOverlay> and returns
- * the array of <mxCellOverlays> that was removed from the cell.
- *
- * Parameters:
- *
- * cell - <mxCell> whose overlays should be removed
- */
-mxGraph.prototype.removeCellOverlays = function(cell)
-{
- var overlays = cell.overlays;
-
- if (overlays != null)
- {
- cell.overlays = null;
-
- // Immediately updates the cell display if the state exists
- var state = this.view.getState(cell);
-
- if (state != null)
- {
- this.cellRenderer.redraw(state);
- }
-
- for (var i = 0; i < overlays.length; i++)
- {
- this.fireEvent(new mxEventObject(mxEvent.REMOVE_OVERLAY,
- 'cell', cell, 'overlay', overlays[i]));
- }
- }
-
- return overlays;
-};
-
-/**
- * Function: clearCellOverlays
- *
- * Removes all <mxCellOverlays> in the graph for the given cell and all its
- * descendants. If no cell is specified then all overlays are removed from
- * the graph. This implementation uses <removeCellOverlays> to remove the
- * overlays from the individual cells.
- *
- * Parameters:
- *
- * cell - Optional <mxCell> that represents the root of the subtree to
- * remove the overlays from. Default is the root in the model.
- */
-mxGraph.prototype.clearCellOverlays = function(cell)
-{
- cell = (cell != null) ? cell : this.model.getRoot();
- this.removeCellOverlays(cell);
-
- // Recursively removes all overlays from the children
- var childCount = this.model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = this.model.getChildAt(cell, i);
- this.clearCellOverlays(child); // recurse
- }
-};
-
-/**
- * Function: setCellWarning
- *
- * Creates an overlay for the given cell using the warning and image or
- * <warningImage> and returns the new <mxCellOverlay>. The warning is
- * displayed as a tooltip in a red font and may contain HTML markup. If
- * the warning is null or a zero length string, then all overlays are
- * removed from the cell.
- *
- * Example:
- *
- * (code)
- * graph.setCellWarning(cell, '<b>Warning:</b>: Hello, World!');
- * (end)
- *
- * Parameters:
- *
- * cell - <mxCell> whose warning should be set.
- * warning - String that represents the warning to be displayed.
- * img - Optional <mxImage> to be used for the overlay. Default is
- * <warningImage>.
- * isSelect - Optional boolean indicating if a click on the overlay
- * should select the corresponding cell. Default is false.
- */
-mxGraph.prototype.setCellWarning = function(cell, warning, img, isSelect)
-{
- if (warning != null && warning.length > 0)
- {
- img = (img != null) ? img : this.warningImage;
-
- // Creates the overlay with the image and warning
- var overlay = new mxCellOverlay(img,
- '<font color=red>'+warning+'</font>');
-
- // Adds a handler for single mouseclicks to select the cell
- if (isSelect)
- {
- overlay.addListener(mxEvent.CLICK,
- mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled())
- {
- this.setSelectionCell(cell);
- }
- })
- );
- }
-
- // Sets and returns the overlay in the graph
- return this.addCellOverlay(cell, overlay);
- }
- else
- {
- this.removeCellOverlays(cell);
- }
-
- return null;
-};
-
-/**
- * Group: In-place editing
- */
-
-/**
- * Function: startEditing
- *
- * Calls <startEditingAtCell> using the given cell or the first selection
- * cell.
- *
- * Parameters:
- *
- * evt - Optional mouse event that triggered the editing.
- */
-mxGraph.prototype.startEditing = function(evt)
-{
- this.startEditingAtCell(null, evt);
-};
-
-/**
- * Function: startEditingAtCell
- *
- * Fires a <startEditing> event and invokes <mxCellEditor.startEditing>
- * on <editor>.
- *
- * Parameters:
- *
- * cell - <mxCell> to start the in-place editor for.
- * evt - Optional mouse event that triggered the editing.
- */
-mxGraph.prototype.startEditingAtCell = function(cell, evt)
-{
- if (cell == null)
- {
- cell = this.getSelectionCell();
-
- if (cell != null && !this.isCellEditable(cell))
- {
- cell = null;
- }
- }
-
- if (cell != null)
- {
- this.fireEvent(new mxEventObject(mxEvent.START_EDITING,
- 'cell', cell, 'event', evt));
- this.cellEditor.startEditing(cell, evt);
- }
-};
-
-/**
- * Function: getEditingValue
- *
- * Returns the initial value for in-place editing. This implementation
- * returns <convertValueToString> for the given cell. If this function is
- * overridden, then <mxGraphModel.valueForCellChanged> should take care
- * of correctly storing the actual new value inside the user object.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the initial editing value should be returned.
- * evt - Optional mouse event that triggered the editor.
- */
-mxGraph.prototype.getEditingValue = function(cell, evt)
-{
- return this.convertValueToString(cell);
-};
-
-/**
- * Function: stopEditing
- *
- * Stops the current editing.
- *
- * Parameters:
- *
- * cancel - Boolean that specifies if the current editing value
- * should be stored.
- */
-mxGraph.prototype.stopEditing = function(cancel)
-{
- this.cellEditor.stopEditing(cancel);
-};
-
-/**
- * Function: labelChanged
- *
- * Sets the label of the specified cell to the given value using
- * <cellLabelChanged> and fires <mxEvent.LABEL_CHANGED> while the
- * transaction is in progress. Returns the cell whose label was changed.
- *
- * Parameters:
- *
- * cell - <mxCell> whose label should be changed.
- * value - New label to be assigned.
- * evt - Optional event that triggered the change.
- */
-mxGraph.prototype.labelChanged = function(cell, value, evt)
-{
- this.model.beginUpdate();
- try
- {
- this.cellLabelChanged(cell, value, this.isAutoSizeCell(cell));
- this.fireEvent(new mxEventObject(mxEvent.LABEL_CHANGED,
- 'cell', cell, 'value', value, 'event', evt));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cell;
-};
-
-/**
- * Function: cellLabelChanged
- *
- * Sets the new label for a cell. If autoSize is true then
- * <cellSizeUpdated> will be called.
- *
- * In the following example, the function is extended to map changes to
- * attributes in an XML node, as shown in <convertValueToString>.
- * Alternatively, the handling of this can be implemented as shown in
- * <mxGraphModel.valueForCellChanged> without the need to clone the
- * user object.
- *
- * (code)
- * var graphCellLabelChanged = graph.cellLabelChanged;
- * graph.cellLabelChanged = function(cell, newValue, autoSize)
- * {
- * // Cloned for correct undo/redo
- * var elt = cell.value.cloneNode(true);
- * elt.setAttribute('label', newValue);
- *
- * newValue = elt;
- * graphCellLabelChanged.apply(this, arguments);
- * };
- * (end)
- *
- * Parameters:
- *
- * cell - <mxCell> whose label should be changed.
- * value - New label to be assigned.
- * autoSize - Boolean that specifies if <cellSizeUpdated> should be called.
- */
-mxGraph.prototype.cellLabelChanged = function(cell, value, autoSize)
-{
- this.model.beginUpdate();
- try
- {
- this.model.setValue(cell, value);
-
- if (autoSize)
- {
- this.cellSizeUpdated(cell, false);
- }
- }
- finally
- {
- this.model.endUpdate();
- }
-};
-
-/**
- * Group: Event processing
- */
-
-/**
- * Function: escape
- *
- * Processes an escape keystroke.
- *
- * Parameters:
- *
- * evt - Mouseevent that represents the keystroke.
- */
-mxGraph.prototype.escape = function(evt)
-{
- this.stopEditing(true);
- this.connectionHandler.reset();
- this.graphHandler.reset();
-
- // Cancels all cell-based editing
- var cells = this.getSelectionCells();
-
- for (var i = 0; i < cells.length; i++)
- {
- var state = this.view.getState(cells[i]);
-
- if (state != null && state.handler != null)
- {
- state.handler.reset();
- }
- }
-};
-
-/**
- * Function: click
- *
- * Processes a singleclick on an optional cell and fires a <click> event.
- * The click event is fired initially. If the graph is enabled and the
- * event has not been consumed, then the cell is selected using
- * <selectCellForEvent> or the selection is cleared using
- * <clearSelection>. The events consumed state is set to true if the
- * corresponding <mxMouseEvent> has been consumed.
- *
- * Parameters:
- *
- * me - <mxMouseEvent> that represents the single click.
- */
-mxGraph.prototype.click = function(me)
-{
- var evt = me.getEvent();
- var cell = me.getCell();
- var mxe = new mxEventObject(mxEvent.CLICK, 'event', evt, 'cell', cell);
-
- if (me.isConsumed())
- {
- mxe.consume();
- }
-
- this.fireEvent(mxe);
-
- // Handles the event if it has not been consumed
- if (this.isEnabled() && !mxEvent.isConsumed(evt) && !mxe.isConsumed())
- {
- if (cell != null)
- {
- this.selectCellForEvent(cell, evt);
- }
- else
- {
- var swimlane = null;
-
- if (this.isSwimlaneSelectionEnabled())
- {
- // Gets the swimlane at the location (includes
- // content area of swimlanes)
- swimlane = this.getSwimlaneAt(me.getGraphX(), me.getGraphY());
- }
-
- // Selects the swimlane and consumes the event
- if (swimlane != null)
- {
- this.selectCellForEvent(swimlane, evt);
- }
-
- // Ignores the event if the control key is pressed
- else if (!this.isToggleEvent(evt))
- {
- this.clearSelection();
- }
- }
- }
-};
-
-/**
- * Function: dblClick
- *
- * Processes a doubleclick on an optional cell and fires a <dblclick>
- * event. The event is fired initially. If the graph is enabled and the
- * event has not been consumed, then <edit> is called with the given
- * cell. The event is ignored if no cell was specified.
- *
- * Example for overriding this method.
- *
- * (code)
- * graph.dblClick = function(evt, cell)
- * {
- * var mxe = new mxEventObject(mxEvent.DOUBLE_CLICK, 'event', evt, 'cell', cell);
- * this.fireEvent(mxe);
- *
- * if (this.isEnabled() && !mxEvent.isConsumed(evt) && !mxe.isConsumed())
- * {
- * mxUtils.alert('Hello, World!');
- * mxe.consume();
- * }
- * }
- * (end)
- *
- * Example listener for this event.
- *
- * (code)
- * graph.addListener(mxEvent.DOUBLE_CLICK, function(sender, evt)
- * {
- * var cell = evt.getProperty('cell');
- * // do something with the cell...
- * });
- * (end)
- *
- * Parameters:
- *
- * evt - Mouseevent that represents the doubleclick.
- * cell - Optional <mxCell> under the mousepointer.
- */
-mxGraph.prototype.dblClick = function(evt, cell)
-{
- var mxe = new mxEventObject(mxEvent.DOUBLE_CLICK, 'event', evt, 'cell', cell);
- this.fireEvent(mxe);
-
- // Handles the event if it has not been consumed
- if (this.isEnabled() && !mxEvent.isConsumed(evt) && !mxe.isConsumed() &&
- cell != null && this.isCellEditable(cell))
- {
- this.startEditingAtCell(cell, evt);
- }
-};
-
-/**
- * Function: scrollPointToVisible
- *
- * Scrolls the graph to the given point, extending the graph container if
- * specified.
- */
-mxGraph.prototype.scrollPointToVisible = function(x, y, extend, border)
-{
- if (!this.timerAutoScroll && (this.ignoreScrollbars || mxUtils.hasScrollbars(this.container)))
- {
- var c = this.container;
- border = (border != null) ? border : 20;
-
- if (x >= c.scrollLeft && y >= c.scrollTop && x <= c.scrollLeft + c.clientWidth &&
- y <= c.scrollTop + c.clientHeight)
- {
- var dx = c.scrollLeft + c.clientWidth - x;
-
- if (dx < border)
- {
- var old = c.scrollLeft;
- c.scrollLeft += border - dx;
-
- // Automatically extends the canvas size to the bottom, right
- // if the event is outside of the canvas and the edge of the
- // canvas has been reached. Notes: Needs fix for IE.
- if (extend && old == c.scrollLeft)
- {
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- var root = this.view.getDrawPane().ownerSVGElement;
- var width = this.container.scrollWidth + border - dx;
-
- // Updates the clipping region. This is an expensive
- // operation that should not be executed too often.
- root.setAttribute('width', width);
- }
- else
- {
- var width = Math.max(c.clientWidth, c.scrollWidth) + border - dx;
- var canvas = this.view.getCanvas();
- canvas.style.width = width + 'px';
- }
-
- c.scrollLeft += border - dx;
- }
- }
- else
- {
- dx = x - c.scrollLeft;
-
- if (dx < border)
- {
- c.scrollLeft -= border - dx;
- }
- }
-
- var dy = c.scrollTop + c.clientHeight - y;
-
- if (dy < border)
- {
- var old = c.scrollTop;
- c.scrollTop += border - dy;
-
- if (old == c.scrollTop && extend)
- {
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- var root = this.view.getDrawPane().ownerSVGElement;
- var height = this.container.scrollHeight + border - dy;
-
- // Updates the clipping region. This is an expensive
- // operation that should not be executed too often.
- root.setAttribute('height', height);
- }
- else
- {
- var height = Math.max(c.clientHeight, c.scrollHeight) + border - dy;
- var canvas = this.view.getCanvas();
- canvas.style.height = height + 'px';
- }
-
- c.scrollTop += border - dy;
- }
- }
- else
- {
- dy = y - c.scrollTop;
-
- if (dy < border)
- {
- c.scrollTop -= border - dy;
- }
- }
- }
- }
- else if (this.allowAutoPanning && !this.panningHandler.active)
- {
- if (this.panningManager == null)
- {
- this.panningManager = this.createPanningManager();
- }
-
- this.panningManager.panTo(x + this.panDx, y + this.panDy);
- }
-};
-
-
-/**
- * Function: createPanningManager
- *
- * Creates and returns an <mxPanningManager>.
- */
-mxGraph.prototype.createPanningManager = function()
-{
- return new mxPanningManager(this);
-};
-
-/**
- * Function: getBorderSizes
- *
- * Returns the size of the border and padding on all four sides of the
- * container. The left, top, right and bottom borders are stored in the x, y,
- * width and height of the returned <mxRectangle>, respectively.
- */
-mxGraph.prototype.getBorderSizes = function()
-{
- // Helper function to handle string values for border widths (approx)
- function parseBorder(value)
- {
- var result = 0;
-
- if (value == 'thin')
- {
- result = 2;
- }
- else if (value == 'medium')
- {
- result = 4;
- }
- else if (value == 'thick')
- {
- result = 6;
- }
- else
- {
- result = parseInt(value);
- }
-
- if (isNaN(result))
- {
- result = 0;
- }
-
- return result;
- }
-
- var style = mxUtils.getCurrentStyle(this.container);
- var result = new mxRectangle();
- result.x = parseBorder(style.borderLeftWidth) + parseInt(style.paddingLeft || 0);
- result.y = parseBorder(style.borderTopWidth) + parseInt(style.paddingTop || 0);
- result.width = parseBorder(style.borderRightWidth) + parseInt(style.paddingRight || 0);
- result.height = parseBorder(style.borderBottomWidth) + parseInt(style.paddingBottom || 0);
-
- return result;
-};
-
-
-/**
- * Function: getPreferredPageSize
- *
- * Returns the preferred size of the background page if <preferPageSize> is true.
- */
-mxGraph.prototype.getPreferredPageSize = function(bounds, width, height)
-{
- var scale = this.view.scale;
- var tr = this.view.translate;
- var fmt = this.pageFormat;
- var ps = scale * this.pageScale;
- var page = new mxRectangle(0, 0, fmt.width * ps, fmt.height * ps);
-
- var hCount = (this.pageBreaksVisible) ? Math.ceil(width / page.width) : 1;
- var vCount = (this.pageBreaksVisible) ? Math.ceil(height / page.height) : 1;
-
- return new mxRectangle(0, 0, hCount * page.width + 2 + tr.x / scale, vCount * page.height + 2 + tr.y / scale);
-};
-
-/**
- * Function: sizeDidChange
- *
- * Called when the size of the graph has changed. This implementation fires
- * a <size> event after updating the clipping region of the SVG element in
- * SVG-bases browsers.
- */
-mxGraph.prototype.sizeDidChange = function()
-{
- var bounds = this.getGraphBounds();
-
- if (this.container != null)
- {
- var border = this.getBorder();
-
- var width = Math.max(0, bounds.x + bounds.width + 1 + border);
- var height = Math.max(0, bounds.y + bounds.height + 1 + border);
-
- if (this.minimumContainerSize != null)
- {
- width = Math.max(width, this.minimumContainerSize.width);
- height = Math.max(height, this.minimumContainerSize.height);
- }
-
- if (this.resizeContainer)
- {
- this.doResizeContainer(width, height);
- }
-
- if (this.preferPageSize || (!mxClient.IS_IE && this.pageVisible))
- {
- var size = this.getPreferredPageSize(bounds, width, height);
-
- if (size != null)
- {
- width = size.width;
- height = size.height;
- }
- }
-
- if (this.minimumGraphSize != null)
- {
- width = Math.max(width, this.minimumGraphSize.width * this.view.scale);
- height = Math.max(height, this.minimumGraphSize.height * this.view.scale);
- }
-
- width = Math.ceil(width - 1);
- height = Math.ceil(height - 1);
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- var root = this.view.getDrawPane().ownerSVGElement;
-
- root.style.minWidth = Math.max(1, width) + 'px';
- root.style.minHeight = Math.max(1, height) + 'px';
- }
- else
- {
- if (mxClient.IS_QUIRKS)
- {
- // Quirks mode has no minWidth/minHeight support
- this.view.updateHtmlCanvasSize(Math.max(1, width), Math.max(1, height));
- }
- else
- {
- this.view.canvas.style.minWidth = Math.max(1, width) + 'px';
- this.view.canvas.style.minHeight = Math.max(1, height) + 'px';
- }
- }
-
- this.updatePageBreaks(this.pageBreaksVisible, width - 1, height - 1);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.SIZE, 'bounds', bounds));
-};
-
-/**
- * Function: doResizeContainer
- *
- * Resizes the container for the given graph width and height.
- */
-mxGraph.prototype.doResizeContainer = function(width, height)
-{
- // Fixes container size for different box models
- if (mxClient.IS_IE)
- {
- if (mxClient.IS_QUIRKS)
- {
- var borders = this.getBorderSizes();
-
- // max(2, ...) required for native IE8 in quirks mode
- width += Math.max(2, borders.x + borders.width + 1);
- height += Math.max(2, borders.y + borders.height + 1);
- }
- else if (document.documentMode >= 9)
- {
- width += 3;
- height += 5;
- }
- else
- {
- width += 1;
- height += 1;
- }
- }
- else
- {
- height += 1;
- }
-
- if (this.maximumContainerSize != null)
- {
- width = Math.min(this.maximumContainerSize.width, width);
- height = Math.min(this.maximumContainerSize.height, height);
- }
-
- this.container.style.width = Math.ceil(width) + 'px';
- this.container.style.height = Math.ceil(height) + 'px';
-};
-
-/**
- * Function: redrawPageBreaks
- *
- * Invokes from <sizeDidChange> to redraw the page breaks.
- *
- * Parameters:
- *
- * visible - Boolean that specifies if page breaks should be shown.
- * width - Specifies the width of the container in pixels.
- * height - Specifies the height of the container in pixels.
- */
-mxGraph.prototype.updatePageBreaks = function(visible, width, height)
-{
- var scale = this.view.scale;
- var tr = this.view.translate;
- var fmt = this.pageFormat;
- var ps = scale * this.pageScale;
- var bounds = new mxRectangle(scale * tr.x, scale * tr.y,
- fmt.width * ps, fmt.height * ps);
-
- // Does not show page breaks if the scale is too small
- visible = visible && Math.min(bounds.width, bounds.height) > this.minPageBreakDist;
-
- // Draws page breaks independent of translate. To ignore
- // the translate set bounds.x/y = 0. Note that modulo
- // in JavaScript has a bug, so use mxUtils instead.
- bounds.x = mxUtils.mod(bounds.x, bounds.width);
- bounds.y = mxUtils.mod(bounds.y, bounds.height);
-
- var horizontalCount = (visible) ? Math.ceil((width - bounds.x) / bounds.width) : 0;
- var verticalCount = (visible) ? Math.ceil((height - bounds.y) / bounds.height) : 0;
- var right = width;
- var bottom = height;
-
- if (this.horizontalPageBreaks == null && horizontalCount > 0)
- {
- this.horizontalPageBreaks = [];
- }
-
- if (this.horizontalPageBreaks != null)
- {
- for (var i = 0; i <= horizontalCount; i++)
- {
- var pts = [new mxPoint(bounds.x + i * bounds.width, 1),
- new mxPoint(bounds.x + i * bounds.width, bottom)];
-
- if (this.horizontalPageBreaks[i] != null)
- {
- this.horizontalPageBreaks[i].scale = 1;
- this.horizontalPageBreaks[i].points = pts;
- this.horizontalPageBreaks[i].redraw();
- }
- else
- {
- var pageBreak = new mxPolyline(pts, this.pageBreakColor, this.scale);
- pageBreak.dialect = this.dialect;
- pageBreak.isDashed = this.pageBreakDashed;
- pageBreak.scale = scale;
- pageBreak.crisp = true;
- pageBreak.init(this.view.backgroundPane);
- pageBreak.redraw();
-
- this.horizontalPageBreaks[i] = pageBreak;
- }
- }
-
- for (var i = horizontalCount; i < this.horizontalPageBreaks.length; i++)
- {
- this.horizontalPageBreaks[i].destroy();
- }
-
- this.horizontalPageBreaks.splice(horizontalCount, this.horizontalPageBreaks.length - horizontalCount);
- }
-
- if (this.verticalPageBreaks == null && verticalCount > 0)
- {
- this.verticalPageBreaks = [];
- }
-
- if (this.verticalPageBreaks != null)
- {
- for (var i = 0; i <= verticalCount; i++)
- {
- var pts = [new mxPoint(1, bounds.y + i * bounds.height),
- new mxPoint(right, bounds.y + i * bounds.height)];
-
- if (this.verticalPageBreaks[i] != null)
- {
- this.verticalPageBreaks[i].scale = 1;
- this.verticalPageBreaks[i].points = pts;
- this.verticalPageBreaks[i].redraw();
- }
- else
- {
- var pageBreak = new mxPolyline(pts, this.pageBreakColor, scale);
- pageBreak.dialect = this.dialect;
- pageBreak.isDashed = this.pageBreakDashed;
- pageBreak.scale = scale;
- pageBreak.crisp = true;
- pageBreak.init(this.view.backgroundPane);
- pageBreak.redraw();
-
- this.verticalPageBreaks[i] = pageBreak;
- }
- }
-
- for (var i = verticalCount; i < this.verticalPageBreaks.length; i++)
- {
- this.verticalPageBreaks[i].destroy();
- }
-
- this.verticalPageBreaks.splice(verticalCount, this.verticalPageBreaks.length - verticalCount);
- }
-};
-
-/**
- * Group: Cell styles
- */
-
-/**
- * Function: getCellStyle
- *
- * Returns an array of key, value pairs representing the cell style for the
- * given cell. If no string is defined in the model that specifies the
- * style, then the default style for the cell is returned or <EMPTY_ARRAY>,
- * if not style can be found. Note: You should try and get the cell state
- * for the given cell and use the cached style in the state before using
- * this method.
- *
- * Parameters:
- *
- * cell - <mxCell> whose style should be returned as an array.
- */
-mxGraph.prototype.getCellStyle = function(cell)
-{
- var stylename = this.model.getStyle(cell);
- var style = null;
-
- // Gets the default style for the cell
- if (this.model.isEdge(cell))
- {
- style = this.stylesheet.getDefaultEdgeStyle();
- }
- else
- {
- style = this.stylesheet.getDefaultVertexStyle();
- }
-
- // Resolves the stylename using the above as the default
- if (stylename != null)
- {
- style = this.postProcessCellStyle(this.stylesheet.getCellStyle(stylename, style));
- }
-
- // Returns a non-null value if no style can be found
- if (style == null)
- {
- style = mxGraph.prototype.EMPTY_ARRAY;
- }
-
- return style;
-};
-
-/**
- * Function: postProcessCellStyle
- *
- * Tries to resolve the value for the image style in the image bundles and
- * turns short data URIs as defined in mxImageBundle to data URIs as
- * defined in RFC 2397 of the IETF.
- */
-mxGraph.prototype.postProcessCellStyle = function(style)
-{
- if (style != null)
- {
- var key = style[mxConstants.STYLE_IMAGE];
- var image = this.getImageFromBundles(key);
-
- if (image != null)
- {
- style[mxConstants.STYLE_IMAGE] = image;
- }
- else
- {
- image = key;
- }
-
- // Converts short data uris to normal data uris
- if (image != null && image.substring(0, 11) == "data:image/")
- {
- var comma = image.indexOf(',');
-
- if (comma > 0)
- {
- image = image.substring(0, comma) + ";base64,"
- + image.substring(comma + 1);
- }
-
- style[mxConstants.STYLE_IMAGE] = image;
- }
- }
-
- return style;
-};
-
-/**
- * Function: setCellStyle
- *
- * Sets the style of the specified cells. If no cells are given, then the
- * selection cells are changed.
- *
- * Parameters:
- *
- * style - String representing the new style of the cells.
- * cells - Optional array of <mxCells> to set the style for. Default is the
- * selection cells.
- */
-mxGraph.prototype.setCellStyle = function(style, cells)
-{
- cells = cells || this.getSelectionCells();
-
- if (cells != null)
- {
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- this.model.setStyle(cells[i], style);
- }
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: toggleCellStyle
- *
- * Toggles the boolean value for the given key in the style of the
- * given cell. If no cell is specified then the selection cell is
- * used.
- *
- * Parameter:
- *
- * key - String representing the key for the boolean value to be toggled.
- * defaultValue - Optional boolean default value if no value is defined.
- * Default is false.
- * cell - Optional <mxCell> whose style should be modified. Default is
- * the selection cell.
- */
-mxGraph.prototype.toggleCellStyle = function(key, defaultValue, cell)
-{
- cell = cell || this.getSelectionCell();
-
- this.toggleCellStyles(key, defaultValue, [cell]);
-};
-
-/**
- * Function: toggleCellStyles
- *
- * Toggles the boolean value for the given key in the style of the given
- * cells. If no cells are specified, then the selection cells are used. For
- * example, this can be used to toggle <mxConstants.STYLE_ROUNDED> or any
- * other style with a boolean value.
- *
- * Parameter:
- *
- * key - String representing the key for the boolean value to be toggled.
- * defaultValue - Optional boolean default value if no value is defined.
- * Default is false.
- * cells - Optional array of <mxCells> whose styles should be modified.
- * Default is the selection cells.
- */
-mxGraph.prototype.toggleCellStyles = function(key, defaultValue, cells)
-{
- defaultValue = (defaultValue != null) ? defaultValue : false;
- cells = cells || this.getSelectionCells();
-
- if (cells != null && cells.length > 0)
- {
- var state = this.view.getState(cells[0]);
- var style = (state != null) ? state.style : this.getCellStyle(cells[0]);
-
- if (style != null)
- {
- var val = (mxUtils.getValue(style, key, defaultValue)) ? 0 : 1;
- this.setCellStyles(key, val, cells);
- }
- }
-};
-
-/**
- * Function: setCellStyles
- *
- * Sets the key to value in the styles of the given cells. This will modify
- * the existing cell styles in-place and override any existing assignment
- * for the given key. If no cells are specified, then the selection cells
- * are changed. If no value is specified, then the respective key is
- * removed from the styles.
- *
- * Parameters:
- *
- * key - String representing the key to be assigned.
- * value - String representing the new value for the key.
- * cells - Optional array of <mxCells> to change the style for. Default is
- * the selection cells.
- */
-mxGraph.prototype.setCellStyles = function(key, value, cells)
-{
- cells = cells || this.getSelectionCells();
- mxUtils.setCellStyles(this.model, cells, key, value);
-};
-
-/**
- * Function: toggleCellStyleFlags
- *
- * Toggles the given bit for the given key in the styles of the specified
- * cells.
- *
- * Parameters:
- *
- * key - String representing the key to toggle the flag in.
- * flag - Integer that represents the bit to be toggled.
- * cells - Optional array of <mxCells> to change the style for. Default is
- * the selection cells.
- */
-mxGraph.prototype.toggleCellStyleFlags = function(key, flag, cells)
-{
- this.setCellStyleFlags(key, flag, null, cells);
-};
-
-/**
- * Function: setCellStyleFlags
- *
- * Sets or toggles the given bit for the given key in the styles of the
- * specified cells.
- *
- * Parameters:
- *
- * key - String representing the key to toggle the flag in.
- * flag - Integer that represents the bit to be toggled.
- * value - Boolean value to be used or null if the value should be toggled.
- * cells - Optional array of <mxCells> to change the style for. Default is
- * the selection cells.
- */
-mxGraph.prototype.setCellStyleFlags = function(key, flag, value, cells)
-{
- cells = cells || this.getSelectionCells();
-
- if (cells != null && cells.length > 0)
- {
- if (value == null)
- {
- var state = this.view.getState(cells[0]);
- var style = (state != null) ? state.style : this.getCellStyle(cells[0]);
-
- if (style != null)
- {
- var current = parseInt(style[key] || 0);
- value = !((current & flag) == flag);
- }
- }
-
- mxUtils.setCellStyleFlags(this.model, cells, key, flag, value);
- }
-};
-
-/**
- * Group: Cell alignment and orientation
- */
-
-/**
- * Function: alignCells
- *
- * Aligns the given cells vertically or horizontally according to the given
- * alignment using the optional parameter as the coordinate.
- *
- * Parameters:
- *
- * align - Specifies the alignment. Possible values are all constants in
- * mxConstants with an ALIGN prefix.
- * cells - Array of <mxCells> to be aligned.
- * param - Optional coordinate for the alignment.
- */
-mxGraph.prototype.alignCells = function(align, cells, param)
-{
- if (cells == null)
- {
- cells = this.getSelectionCells();
- }
-
- if (cells != null && cells.length > 1)
- {
- // Finds the required coordinate for the alignment
- if (param == null)
- {
- for (var i = 0; i < cells.length; i++)
- {
- var geo = this.getCellGeometry(cells[i]);
-
- if (geo != null && !this.model.isEdge(cells[i]))
- {
- if (param == null)
- {
- if (align == mxConstants.ALIGN_CENTER)
- {
- param = geo.x + geo.width / 2;
- break;
- }
- else if (align == mxConstants.ALIGN_RIGHT)
- {
- param = geo.x + geo.width;
- }
- else if (align == mxConstants.ALIGN_TOP)
- {
- param = geo.y;
- }
- else if (align == mxConstants.ALIGN_MIDDLE)
- {
- param = geo.y + geo.height / 2;
- break;
- }
- else if (align == mxConstants.ALIGN_BOTTOM)
- {
- param = geo.y + geo.height;
- }
- else
- {
- param = geo.x;
- }
- }
- else
- {
- if (align == mxConstants.ALIGN_RIGHT)
- {
- param = Math.max(param, geo.x + geo.width);
- }
- else if (align == mxConstants.ALIGN_TOP)
- {
- param = Math.min(param, geo.y);
- }
- else if (align == mxConstants.ALIGN_BOTTOM)
- {
- param = Math.max(param, geo.y + geo.height);
- }
- else
- {
- param = Math.min(param, geo.x);
- }
- }
- }
- }
- }
-
- // Aligns the cells to the coordinate
- if (param != null)
- {
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- var geo = this.getCellGeometry(cells[i]);
-
- if (geo != null && !this.model.isEdge(cells[i]))
- {
- geo = geo.clone();
-
- if (align == mxConstants.ALIGN_CENTER)
- {
- geo.x = param - geo.width / 2;
- }
- else if (align == mxConstants.ALIGN_RIGHT)
- {
- geo.x = param - geo.width;
- }
- else if (align == mxConstants.ALIGN_TOP)
- {
- geo.y = param;
- }
- else if (align == mxConstants.ALIGN_MIDDLE)
- {
- geo.y = param - geo.height / 2;
- }
- else if (align == mxConstants.ALIGN_BOTTOM)
- {
- geo.y = param - geo.height;
- }
- else
- {
- geo.x = param;
- }
-
- this.model.setGeometry(cells[i], geo);
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.ALIGN_CELLS,
- 'align', align, 'cells', cells));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
- }
-
- return cells;
-};
-
-/**
- * Function: flipEdge
- *
- * Toggles the style of the given edge between null (or empty) and
- * <alternateEdgeStyle>. This method fires <mxEvent.FLIP_EDGE> while the
- * transaction is in progress. Returns the edge that was flipped.
- *
- * Here is an example that overrides this implementation to invert the
- * value of <mxConstants.STYLE_ELBOW> without removing any existing styles.
- *
- * (code)
- * graph.flipEdge = function(edge)
- * {
- * if (edge != null)
- * {
- * var state = this.view.getState(edge);
- * var style = (state != null) ? state.style : this.getCellStyle(edge);
- *
- * if (style != null)
- * {
- * var elbow = mxUtils.getValue(style, mxConstants.STYLE_ELBOW,
- * mxConstants.ELBOW_HORIZONTAL);
- * var value = (elbow == mxConstants.ELBOW_HORIZONTAL) ?
- * mxConstants.ELBOW_VERTICAL : mxConstants.ELBOW_HORIZONTAL;
- * this.setCellStyles(mxConstants.STYLE_ELBOW, value, [edge]);
- * }
- * }
- * };
- * (end)
- *
- * Parameters:
- *
- * edge - <mxCell> whose style should be changed.
- */
-mxGraph.prototype.flipEdge = function(edge)
-{
- if (edge != null &&
- this.alternateEdgeStyle != null)
- {
- this.model.beginUpdate();
- try
- {
- var style = this.model.getStyle(edge);
-
- if (style == null || style.length == 0)
- {
- this.model.setStyle(edge, this.alternateEdgeStyle);
- }
- else
- {
- this.model.setStyle(edge, null);
- }
-
- // Removes all existing control points
- this.resetEdge(edge);
- this.fireEvent(new mxEventObject(mxEvent.FLIP_EDGE, 'edge', edge));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-
- return edge;
-};
-
-/**
- * Function: addImageBundle
- *
- * Adds the specified <mxImageBundle>.
- */
-mxGraph.prototype.addImageBundle = function(bundle)
-{
- this.imageBundles.push(bundle);
-};
-
-/**
- * Function: removeImageBundle
- *
- * Removes the specified <mxImageBundle>.
- */
-mxGraph.prototype.removeImageBundle = function(bundle)
-{
- var tmp = [];
-
- for (var i = 0; i < this.imageBundles.length; i++)
- {
- if (this.imageBundles[i] != bundle)
- {
- tmp.push(this.imageBundles[i]);
- }
- }
-
- this.imageBundles = tmp;
-};
-
-/**
- * Function: getImageFromBundles
- *
- * Searches all <imageBundles> for the specified key and returns the value
- * for the first match or null if the key is not found.
- */
-mxGraph.prototype.getImageFromBundles = function(key)
-{
- if (key != null)
- {
- for (var i = 0; i < this.imageBundles.length; i++)
- {
- var image = this.imageBundles[i].getImage(key);
-
- if (image != null)
- {
- return image;
- }
- }
- }
-
- return null;
-};
-
-/**
- * Group: Order
- */
-
-/**
- * Function: orderCells
- *
- * Moves the given cells to the front or back. The change is carried out
- * using <cellsOrdered>. This method fires <mxEvent.ORDER_CELLS> while the
- * transaction is in progress.
- *
- * Parameters:
- *
- * back - Boolean that specifies if the cells should be moved to back.
- * cells - Array of <mxCells> to move to the background. If null is
- * specified then the selection cells are used.
- */
- mxGraph.prototype.orderCells = function(back, cells)
- {
- if (cells == null)
- {
- cells = mxUtils.sortCells(this.getSelectionCells(), true);
- }
-
- this.model.beginUpdate();
- try
- {
- this.cellsOrdered(cells, back);
- this.fireEvent(new mxEventObject(mxEvent.ORDER_CELLS,
- 'back', back, 'cells', cells));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cells;
- };
-
-/**
- * Function: cellsOrdered
- *
- * Moves the given cells to the front or back. This method fires
- * <mxEvent.CELLS_ORDERED> while the transaction is in progress.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> whose order should be changed.
- * back - Boolean that specifies if the cells should be moved to back.
- */
- mxGraph.prototype.cellsOrdered = function(cells, back)
- {
- if (cells != null)
- {
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- var parent = this.model.getParent(cells[i]);
-
- if (back)
- {
- this.model.add(parent, cells[i], i);
- }
- else
- {
- this.model.add(parent, cells[i],
- this.model.getChildCount(parent) - 1);
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.CELLS_ORDERED,
- 'back', back, 'cells', cells));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Group: Grouping
- */
-
-/**
- * Function: groupCells
- *
- * Adds the cells into the given group. The change is carried out using
- * <cellsAdded>, <cellsMoved> and <cellsResized>. This method fires
- * <mxEvent.GROUP_CELLS> while the transaction is in progress. Returns the
- * new group. A group is only created if there is at least one entry in the
- * given array of cells.
- *
- * Parameters:
- *
- * group - <mxCell> that represents the target group. If null is specified
- * then a new group is created using <createGroupCell>.
- * border - Optional integer that specifies the border between the child
- * area and the group bounds. Default is 0.
- * cells - Optional array of <mxCells> to be grouped. If null is specified
- * then the selection cells are used.
- */
-mxGraph.prototype.groupCells = function(group, border, cells)
-{
- if (cells == null)
- {
- cells = mxUtils.sortCells(this.getSelectionCells(), true);
- }
-
- cells = this.getCellsForGroup(cells);
-
- if (group == null)
- {
- group = this.createGroupCell(cells);
- }
-
- var bounds = this.getBoundsForGroup(group, cells, border);
-
- if (cells.length > 0 && bounds != null)
- {
- // Uses parent of group or previous parent of first child
- var parent = this.model.getParent(group);
-
- if (parent == null)
- {
- parent = this.model.getParent(cells[0]);
- }
-
- this.model.beginUpdate();
- try
- {
- // Checks if the group has a geometry and
- // creates one if one does not exist
- if (this.getCellGeometry(group) == null)
- {
- this.model.setGeometry(group, new mxGeometry());
- }
-
- // Adds the children into the group and moves
- var index = this.model.getChildCount(group);
- this.cellsAdded(cells, group, index, null, null, false, false);
- this.cellsMoved(cells, -bounds.x, -bounds.y, false, true);
-
- // Adds the group into the parent and resizes
- index = this.model.getChildCount(parent);
- this.cellsAdded([group], parent, index, null, null, false);
- this.cellsResized([group], [bounds]);
-
- this.fireEvent(new mxEventObject(mxEvent.GROUP_CELLS,
- 'group', group, 'border', border, 'cells', cells));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-
- return group;
-};
-
-/**
- * Function: getCellsForGroup
- *
- * Returns the cells with the same parent as the first cell
- * in the given array.
- */
-mxGraph.prototype.getCellsForGroup = function(cells)
-{
- var result = [];
-
- if (cells != null && cells.length > 0)
- {
- var parent = this.model.getParent(cells[0]);
- result.push(cells[0]);
-
- // Filters selection cells with the same parent
- for (var i = 1; i < cells.length; i++)
- {
- if (this.model.getParent(cells[i]) == parent)
- {
- result.push(cells[i]);
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: getBoundsForGroup
- *
- * Returns the bounds to be used for the given group and children.
- */
-mxGraph.prototype.getBoundsForGroup = function(group, children, border)
-{
- var result = this.getBoundingBoxFromGeometry(children);
-
- if (result != null)
- {
- if (this.isSwimlane(group))
- {
- var size = this.getStartSize(group);
-
- result.x -= size.width;
- result.y -= size.height;
- result.width += size.width;
- result.height += size.height;
- }
-
- // Adds the border
- result.x -= border;
- result.y -= border;
- result.width += 2 * border;
- result.height += 2 * border;
- }
-
- return result;
-};
-
-/**
- * Function: createGroupCell
- *
- * Hook for creating the group cell to hold the given array of <mxCells> if
- * no group cell was given to the <group> function.
- *
- * The following code can be used to set the style of new group cells.
- *
- * (code)
- * var graphCreateGroupCell = graph.createGroupCell;
- * graph.createGroupCell = function(cells)
- * {
- * var group = graphCreateGroupCell.apply(this, arguments);
- * group.setStyle('group');
- *
- * return group;
- * };
- */
-mxGraph.prototype.createGroupCell = function(cells)
-{
- var group = new mxCell('');
- group.setVertex(true);
- group.setConnectable(false);
-
- return group;
-};
-
-/**
- * Function: ungroupCells
- *
- * Ungroups the given cells by moving the children the children to their
- * parents parent and removing the empty groups. Returns the children that
- * have been removed from the groups.
- *
- * Parameters:
- *
- * cells - Array of cells to be ungrouped. If null is specified then the
- * selection cells are used.
- */
-mxGraph.prototype.ungroupCells = function(cells)
-{
- var result = [];
-
- if (cells == null)
- {
- cells = this.getSelectionCells();
-
- // Finds the cells with children
- var tmp = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- if (this.model.getChildCount(cells[i]) > 0)
- {
- tmp.push(cells[i]);
- }
- }
-
- cells = tmp;
- }
-
- if (cells != null && cells.length > 0)
- {
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- var children = this.model.getChildren(cells[i]);
-
- if (children != null && children.length > 0)
- {
- children = children.slice();
- var parent = this.model.getParent(cells[i]);
- var index = this.model.getChildCount(parent);
-
- this.cellsAdded(children, parent, index, null, null, true);
- result = result.concat(children);
- }
- }
-
- this.cellsRemoved(this.addAllEdges(cells));
- this.fireEvent(new mxEventObject(mxEvent.UNGROUP_CELLS,
- 'cells', cells));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-
- return result;
-};
-
-/**
- * Function: removeCellsFromParent
- *
- * Removes the specified cells from their parents and adds them to the
- * default parent. Returns the cells that were removed from their parents.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be removed from their parents.
- */
-mxGraph.prototype.removeCellsFromParent = function(cells)
-{
- if (cells == null)
- {
- cells = this.getSelectionCells();
- }
-
- this.model.beginUpdate();
- try
- {
- var parent = this.getDefaultParent();
- var index = this.model.getChildCount(parent);
-
- this.cellsAdded(cells, parent, index, null, null, true);
- this.fireEvent(new mxEventObject(mxEvent.REMOVE_CELLS_FROM_PARENT,
- 'cells', cells));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cells;
-};
-
-/**
- * Function: updateGroupBounds
- *
- * Updates the bounds of the given array of groups so that it includes
- * all child vertices.
- *
- * Parameters:
- *
- * cells - The groups whose bounds should be updated.
- * border - Optional border to be added in the group. Default is 0.
- * moveGroup - Optional boolean that allows the group to be moved. Default
- * is false.
- */
-mxGraph.prototype.updateGroupBounds = function(cells, border, moveGroup)
-{
- if (cells == null)
- {
- cells = this.getSelectionCells();
- }
-
- border = (border != null) ? border : 0;
- moveGroup = (moveGroup != null) ? moveGroup : false;
-
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- var geo = this.getCellGeometry(cells[i]);
-
- if (geo != null)
- {
- var children = this.getChildCells(cells[i]);
-
- if (children != null && children.length > 0)
- {
- var childBounds = this.getBoundingBoxFromGeometry(children);
-
- if (childBounds.width > 0 && childBounds.height > 0)
- {
- var size = (this.isSwimlane(cells[i])) ?
- this.getStartSize(cells[i]) : new mxRectangle();
-
- geo = geo.clone();
-
- if (moveGroup)
- {
- geo.x += childBounds.x - size.width - border;
- geo.y += childBounds.y - size.height - border;
- }
-
- geo.width = childBounds.width + size.width + 2 * border;
- geo.height = childBounds.height + size.height + 2 * border;
-
- this.model.setGeometry(cells[i], geo);
- this.moveCells(children, -childBounds.x + size.width + border,
- -childBounds.y + size.height + border);
- }
- }
- }
- }
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cells;
-};
-
-/**
- * Group: Cell cloning, insertion and removal
- */
-
-/**
- * Function: cloneCells
- *
- * Returns the clones for the given cells. If the terminal of an edge is
- * not in the given array, then the respective end is assigned a terminal
- * point and the terminal is removed.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be cloned.
- * allowInvalidEdges - Optional boolean that specifies if invalid edges
- * should be cloned. Default is true.
- */
-mxGraph.prototype.cloneCells = function(cells, allowInvalidEdges)
-{
- allowInvalidEdges = (allowInvalidEdges != null) ? allowInvalidEdges : true;
- var clones = null;
-
- if (cells != null)
- {
- // Creates a hashtable for cell lookups
- var hash = new Object();
- var tmp = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- var id = mxCellPath.create(cells[i]);
- hash[id] = cells[i];
- tmp.push(cells[i]);
- }
-
- if (tmp.length > 0)
- {
- var scale = this.view.scale;
- var trans = this.view.translate;
- clones = this.model.cloneCells(cells, true);
-
- for (var i = 0; i < cells.length; i++)
- {
- if (!allowInvalidEdges && this.model.isEdge(clones[i]) &&
- this.getEdgeValidationError(clones[i],
- this.model.getTerminal(clones[i], true),
- this.model.getTerminal(clones[i], false)) != null)
- {
- clones[i] = null;
- }
- else
- {
- var g = this.model.getGeometry(clones[i]);
-
- if (g != null)
- {
- var state = this.view.getState(cells[i]);
- var pstate = this.view.getState(
- this.model.getParent(cells[i]));
-
- if (state != null && pstate != null)
- {
- var dx = pstate.origin.x;
- var dy = pstate.origin.y;
-
- if (this.model.isEdge(clones[i]))
- {
- var pts = state.absolutePoints;
-
- // Checks if the source is cloned or sets the terminal point
- var src = this.model.getTerminal(cells[i], true);
- var srcId = mxCellPath.create(src);
-
- while (src != null && hash[srcId] == null)
- {
- src = this.model.getParent(src);
- srcId = mxCellPath.create(src);
- }
-
- if (src == null)
- {
- g.setTerminalPoint(
- new mxPoint(pts[0].x / scale - trans.x,
- pts[0].y / scale - trans.y), true);
- }
-
- // Checks if the target is cloned or sets the terminal point
- var trg = this.model.getTerminal(cells[i], false);
- var trgId = mxCellPath.create(trg);
-
- while (trg != null && hash[trgId] == null)
- {
- trg = this.model.getParent(trg);
- trgId = mxCellPath.create(trg);
- }
-
- if (trg == null)
- {
- var n = pts.length - 1;
- g.setTerminalPoint(
- new mxPoint(pts[n].x / scale - trans.x,
- pts[n].y / scale - trans.y), false);
- }
-
- // Translates the control points
- var points = g.points;
-
- if (points != null)
- {
- for (var j = 0; j < points.length; j++)
- {
- points[j].x += dx;
- points[j].y += dy;
- }
- }
- }
- else
- {
- g.x += dx;
- g.y += dy;
- }
- }
- }
- }
- }
- }
- else
- {
- clones = [];
- }
- }
-
- return clones;
-};
-
-/**
- * Function: insertVertex
- *
- * Adds a new vertex into the given parent <mxCell> using value as the user
- * object and the given coordinates as the <mxGeometry> of the new vertex.
- * The id and style are used for the respective properties of the new
- * <mxCell>, which is returned.
- *
- * When adding new vertices from a mouse event, one should take into
- * account the offset of the graph container and the scale and translation
- * of the view in order to find the correct unscaled, untranslated
- * coordinates using <mxGraph.getPointForEvent> as follows:
- *
- * (code)
- * var pt = graph.getPointForEvent(evt);
- * var parent = graph.getDefaultParent();
- * graph.insertVertex(parent, null,
- * 'Hello, World!', x, y, 220, 30);
- * (end)
- *
- * For adding image cells, the style parameter can be assigned as
- *
- * (code)
- * stylename;image=imageUrl
- * (end)
- *
- * See <mxGraph> for more information on using images.
- *
- * Parameters:
- *
- * parent - <mxCell> that specifies the parent of the new vertex.
- * id - Optional string that defines the Id of the new vertex.
- * value - Object to be used as the user object.
- * x - Integer that defines the x coordinate of the vertex.
- * y - Integer that defines the y coordinate of the vertex.
- * width - Integer that defines the width of the vertex.
- * height - Integer that defines the height of the vertex.
- * style - Optional string that defines the cell style.
- * relative - Optional boolean that specifies if the geometry is relative.
- * Default is false.
- */
-mxGraph.prototype.insertVertex = function(parent, id, value,
- x, y, width, height, style, relative)
-{
- var vertex = this.createVertex(parent, id, value, x, y, width, height, style, relative);
-
- return this.addCell(vertex, parent);
-};
-
-/**
- * Function: createVertex
- *
- * Hook method that creates the new vertex for <insertVertex>.
- */
-mxGraph.prototype.createVertex = function(parent, id, value,
- x, y, width, height, style, relative)
-{
- // Creates the geometry for the vertex
- var geometry = new mxGeometry(x, y, width, height);
- geometry.relative = (relative != null) ? relative : false;
-
- // Creates the vertex
- var vertex = new mxCell(value, geometry, style);
- vertex.setId(id);
- vertex.setVertex(true);
- vertex.setConnectable(true);
-
- return vertex;
-};
-
-/**
- * Function: insertEdge
- *
- * Adds a new edge into the given parent <mxCell> using value as the user
- * object and the given source and target as the terminals of the new edge.
- * The id and style are used for the respective properties of the new
- * <mxCell>, which is returned.
- *
- * Parameters:
- *
- * parent - <mxCell> that specifies the parent of the new edge.
- * id - Optional string that defines the Id of the new edge.
- * value - JavaScript object to be used as the user object.
- * source - <mxCell> that defines the source of the edge.
- * target - <mxCell> that defines the target of the edge.
- * style - Optional string that defines the cell style.
- */
-mxGraph.prototype.insertEdge = function(parent, id, value, source, target, style)
-{
- var edge = this.createEdge(parent, id, value, source, target, style);
-
- return this.addEdge(edge, parent, source, target);
-};
-
-/**
- * Function: createEdge
- *
- * Hook method that creates the new edge for <insertEdge>. This
- * implementation does not set the source and target of the edge, these
- * are set when the edge is added to the model.
- *
- */
-mxGraph.prototype.createEdge = function(parent, id, value, source, target, style)
-{
- // Creates the edge
- var edge = new mxCell(value, new mxGeometry(), style);
- edge.setId(id);
- edge.setEdge(true);
- edge.geometry.relative = true;
-
- return edge;
-};
-
-/**
- * Function: addEdge
- *
- * Adds the edge to the parent and connects it to the given source and
- * target terminals. This is a shortcut method. Returns the edge that was
- * added.
- *
- * Parameters:
- *
- * edge - <mxCell> to be inserted into the given parent.
- * parent - <mxCell> that represents the new parent. If no parent is
- * given then the default parent is used.
- * source - Optional <mxCell> that represents the source terminal.
- * target - Optional <mxCell> that represents the target terminal.
- * index - Optional index to insert the cells at. Default is to append.
- */
-mxGraph.prototype.addEdge = function(edge, parent, source, target, index)
-{
- return this.addCell(edge, parent, index, source, target);
-};
-
-/**
- * Function: addCell
- *
- * Adds the cell to the parent and connects it to the given source and
- * target terminals. This is a shortcut method. Returns the cell that was
- * added.
- *
- * Parameters:
- *
- * cell - <mxCell> to be inserted into the given parent.
- * parent - <mxCell> that represents the new parent. If no parent is
- * given then the default parent is used.
- * index - Optional index to insert the cells at. Default is to append.
- * source - Optional <mxCell> that represents the source terminal.
- * target - Optional <mxCell> that represents the target terminal.
- */
-mxGraph.prototype.addCell = function(cell, parent, index, source, target)
-{
- return this.addCells([cell], parent, index, source, target)[0];
-};
-
-/**
- * Function: addCells
- *
- * Adds the cells to the parent at the given index, connecting each cell to
- * the optional source and target terminal. The change is carried out using
- * <cellsAdded>. This method fires <mxEvent.ADD_CELLS> while the
- * transaction is in progress. Returns the cells that were added.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be inserted.
- * parent - <mxCell> that represents the new parent. If no parent is
- * given then the default parent is used.
- * index - Optional index to insert the cells at. Default is to append.
- * source - Optional source <mxCell> for all inserted cells.
- * target - Optional target <mxCell> for all inserted cells.
- */
-mxGraph.prototype.addCells = function(cells, parent, index, source, target)
-{
- if (parent == null)
- {
- parent = this.getDefaultParent();
- }
-
- if (index == null)
- {
- index = this.model.getChildCount(parent);
- }
-
- this.model.beginUpdate();
- try
- {
- this.cellsAdded(cells, parent, index, source, target, false, true);
- this.fireEvent(new mxEventObject(mxEvent.ADD_CELLS, 'cells', cells,
- 'parent', parent, 'index', index, 'source', source, 'target', target));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cells;
-};
-
-/**
- * Function: cellsAdded
- *
- * Adds the specified cells to the given parent. This method fires
- * <mxEvent.CELLS_ADDED> while the transaction is in progress.
- */
-mxGraph.prototype.cellsAdded = function(cells, parent, index, source, target, absolute, constrain)
-{
- if (cells != null && parent != null && index != null)
- {
- this.model.beginUpdate();
- try
- {
- var parentState = (absolute) ? this.view.getState(parent) : null;
- var o1 = (parentState != null) ? parentState.origin : null;
- var zero = new mxPoint(0, 0);
-
- for (var i = 0; i < cells.length; i++)
- {
- if (cells[i] == null)
- {
- index--;
- }
- else
- {
- var previous = this.model.getParent(cells[i]);
-
- // Keeps the cell at its absolute location
- if (o1 != null && cells[i] != parent && parent != previous)
- {
- var oldState = this.view.getState(previous);
- var o2 = (oldState != null) ? oldState.origin : zero;
- var geo = this.model.getGeometry(cells[i]);
-
- if (geo != null)
- {
- var dx = o2.x - o1.x;
- var dy = o2.y - o1.y;
-
- // FIXME: Cells should always be inserted first before any other edit
- // to avoid forward references in sessions.
- geo = geo.clone();
- geo.translate(dx, dy);
-
- if (!geo.relative && this.model.isVertex(cells[i]) &&
- !this.isAllowNegativeCoordinates())
- {
- geo.x = Math.max(0, geo.x);
- geo.y = Math.max(0, geo.y);
- }
-
- this.model.setGeometry(cells[i], geo);
- }
- }
-
- // Decrements all following indices
- // if cell is already in parent
- if (parent == previous)
- {
- index--;
- }
-
- this.model.add(parent, cells[i], index + i);
-
- // Extends the parent
- if (this.isExtendParentsOnAdd() && this.isExtendParent(cells[i]))
- {
- this.extendParent(cells[i]);
- }
-
- // Constrains the child
- if (constrain == null || constrain)
- {
- this.constrainChild(cells[i]);
- }
-
- // Sets the source terminal
- if (source != null)
- {
- this.cellConnected(cells[i], source, true);
- }
-
- // Sets the target terminal
- if (target != null)
- {
- this.cellConnected(cells[i], target, false);
- }
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.CELLS_ADDED, 'cells', cells,
- 'parent', parent, 'index', index, 'source', source, 'target', target,
- 'absolute', absolute));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: removeCells
- *
- * Removes the given cells from the graph including all connected edges if
- * includeEdges is true. The change is carried out using <cellsRemoved>.
- * This method fires <mxEvent.REMOVE_CELLS> while the transaction is in
- * progress. The removed cells are returned as an array.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to remove. If null is specified then the
- * selection cells which are deletable are used.
- * includeEdges - Optional boolean which specifies if all connected edges
- * should be removed as well. Default is true.
- */
-mxGraph.prototype.removeCells = function(cells, includeEdges)
-{
- includeEdges = (includeEdges != null) ? includeEdges : true;
-
- if (cells == null)
- {
- cells = this.getDeletableCells(this.getSelectionCells());
- }
-
- // Adds all edges to the cells
- if (includeEdges)
- {
- cells = this.getDeletableCells(this.addAllEdges(cells));
- }
-
- this.model.beginUpdate();
- try
- {
- this.cellsRemoved(cells);
- this.fireEvent(new mxEventObject(mxEvent.REMOVE_CELLS,
- 'cells', cells, 'includeEdges', includeEdges));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cells;
-};
-
-/**
- * Function: cellsRemoved
- *
- * Removes the given cells from the model. This method fires
- * <mxEvent.CELLS_REMOVED> while the transaction is in progress.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to remove.
- */
-mxGraph.prototype.cellsRemoved = function(cells)
-{
- if (cells != null && cells.length > 0)
- {
- var scale = this.view.scale;
- var tr = this.view.translate;
-
- this.model.beginUpdate();
- try
- {
- // Creates hashtable for faster lookup
- var hash = new Object();
-
- for (var i = 0; i < cells.length; i++)
- {
- var id = mxCellPath.create(cells[i]);
- hash[id] = cells[i];
- }
-
- for (var i = 0; i < cells.length; i++)
- {
- // Disconnects edges which are not in cells
- var edges = this.getConnections(cells[i]);
-
- for (var j = 0; j < edges.length; j++)
- {
- var id = mxCellPath.create(edges[j]);
-
- if (hash[id] == null)
- {
- var geo = this.model.getGeometry(edges[j]);
-
- if (geo != null)
- {
- var state = this.view.getState(edges[j]);
-
- if (state != null)
- {
- geo = geo.clone();
- var source = state.getVisibleTerminal(true) == cells[i];
- var pts = state.absolutePoints;
- var n = (source) ? 0 : pts.length - 1;
-
- geo.setTerminalPoint(
- new mxPoint(pts[n].x / scale - tr.x,
- pts[n].y / scale - tr.y), source);
- this.model.setTerminal(edges[j], null, source);
- this.model.setGeometry(edges[j], geo);
- }
- }
- }
- }
-
- this.model.remove(cells[i]);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.CELLS_REMOVED,
- 'cells', cells));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: splitEdge
- *
- * Splits the given edge by adding the newEdge between the previous source
- * and the given cell and reconnecting the source of the given edge to the
- * given cell. This method fires <mxEvent.SPLIT_EDGE> while the transaction
- * is in progress. Returns the new edge that was inserted.
- *
- * Parameters:
- *
- * edge - <mxCell> that represents the edge to be splitted.
- * cells - <mxCells> that represents the cells to insert into the edge.
- * newEdge - <mxCell> that represents the edge to be inserted.
- * dx - Optional integer that specifies the vector to move the cells.
- * dy - Optional integer that specifies the vector to move the cells.
- */
-mxGraph.prototype.splitEdge = function(edge, cells, newEdge, dx, dy)
-{
- dx = dx || 0;
- dy = dy || 0;
-
- if (newEdge == null)
- {
- newEdge = this.cloneCells([edge])[0];
- }
-
- var parent = this.model.getParent(edge);
- var source = this.model.getTerminal(edge, true);
-
- this.model.beginUpdate();
- try
- {
- this.cellsMoved(cells, dx, dy, false, false);
- this.cellsAdded(cells, parent, this.model.getChildCount(parent), null, null,
- true);
- this.cellsAdded([newEdge], parent, this.model.getChildCount(parent),
- source, cells[0], false);
- this.cellConnected(edge, cells[0], true);
- this.fireEvent(new mxEventObject(mxEvent.SPLIT_EDGE, 'edge', edge,
- 'cells', cells, 'newEdge', newEdge, 'dx', dx, 'dy', dy));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return newEdge;
-};
-
-/**
- * Group: Cell visibility
- */
-
-/**
- * Function: toggleCells
- *
- * Sets the visible state of the specified cells and all connected edges
- * if includeEdges is true. The change is carried out using <cellsToggled>.
- * This method fires <mxEvent.TOGGLE_CELLS> while the transaction is in
- * progress. Returns the cells whose visible state was changed.
- *
- * Parameters:
- *
- * show - Boolean that specifies the visible state to be assigned.
- * cells - Array of <mxCells> whose visible state should be changed. If
- * null is specified then the selection cells are used.
- * includeEdges - Optional boolean indicating if the visible state of all
- * connected edges should be changed as well. Default is true.
- */
-mxGraph.prototype.toggleCells = function(show, cells, includeEdges)
-{
- if (cells == null)
- {
- cells = this.getSelectionCells();
- }
-
- // Adds all connected edges recursively
- if (includeEdges)
- {
- cells = this.addAllEdges(cells);
- }
-
- this.model.beginUpdate();
- try
- {
- this.cellsToggled(cells, show);
- this.fireEvent(new mxEventObject(mxEvent.TOGGLE_CELLS,
- 'show', show, 'cells', cells, 'includeEdges', includeEdges));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cells;
-};
-
-/**
- * Function: cellsToggled
- *
- * Sets the visible state of the specified cells.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> whose visible state should be changed.
- * show - Boolean that specifies the visible state to be assigned.
- */
-mxGraph.prototype.cellsToggled = function(cells, show)
-{
- if (cells != null && cells.length > 0)
- {
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- this.model.setVisible(cells[i], show);
- }
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Group: Folding
- */
-
-/**
- * Function: foldCells
- *
- * Sets the collapsed state of the specified cells and all descendants
- * if recurse is true. The change is carried out using <cellsFolded>.
- * This method fires <mxEvent.FOLD_CELLS> while the transaction is in
- * progress. Returns the cells whose collapsed state was changed.
- *
- * Parameters:
- *
- * collapsed - Boolean indicating the collapsed state to be assigned.
- * recurse - Optional boolean indicating if the collapsed state of all
- * descendants should be set. Default is false.
- * cells - Array of <mxCells> whose collapsed state should be set. If
- * null is specified then the foldable selection cells are used.
- * checkFoldable - Optional boolean indicating of isCellFoldable should be
- * checked. Default is false.
- */
-mxGraph.prototype.foldCells = function(collapse, recurse, cells, checkFoldable)
-{
- recurse = (recurse != null) ? recurse : false;
-
- if (cells == null)
- {
- cells = this.getFoldableCells(this.getSelectionCells(), collapse);
- }
-
- this.stopEditing(false);
-
- this.model.beginUpdate();
- try
- {
- this.cellsFolded(cells, collapse, recurse, checkFoldable);
- this.fireEvent(new mxEventObject(mxEvent.FOLD_CELLS,
- 'collapse', collapse, 'recurse', recurse, 'cells', cells));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cells;
-};
-
-/**
- * Function: cellsFolded
- *
- * Sets the collapsed state of the specified cells. This method fires
- * <mxEvent.CELLS_FOLDED> while the transaction is in progress. Returns the
- * cells whose collapsed state was changed.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> whose collapsed state should be set.
- * collapsed - Boolean indicating the collapsed state to be assigned.
- * recurse - Boolean indicating if the collapsed state of all descendants
- * should be set.
- * checkFoldable - Optional boolean indicating of isCellFoldable should be
- * checked. Default is false.
- */
-mxGraph.prototype.cellsFolded = function(cells, collapse, recurse, checkFoldable)
-{
- if (cells != null && cells.length > 0)
- {
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- if ((!checkFoldable || this.isCellFoldable(cells[i], collapse)) &&
- collapse != this.isCellCollapsed(cells[i]))
- {
- this.model.setCollapsed(cells[i], collapse);
- this.swapBounds(cells[i], collapse);
-
- if (this.isExtendParent(cells[i]))
- {
- this.extendParent(cells[i]);
- }
-
- if (recurse)
- {
- var children = this.model.getChildren(cells[i]);
- this.foldCells(children, collapse, recurse);
- }
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.CELLS_FOLDED,
- 'cells', cells, 'collapse', collapse, 'recurse', recurse));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: swapBounds
- *
- * Swaps the alternate and the actual bounds in the geometry of the given
- * cell invoking <updateAlternateBounds> before carrying out the swap.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the bounds should be swapped.
- * willCollapse - Boolean indicating if the cell is going to be collapsed.
- */
-mxGraph.prototype.swapBounds = function(cell, willCollapse)
-{
- if (cell != null)
- {
- var geo = this.model.getGeometry(cell);
-
- if (geo != null)
- {
- geo = geo.clone();
-
- this.updateAlternateBounds(cell, geo, willCollapse);
- geo.swap();
-
- this.model.setGeometry(cell, geo);
- }
- }
-};
-
-/**
- * Function: updateAlternateBounds
- *
- * Updates or sets the alternate bounds in the given geometry for the given
- * cell depending on whether the cell is going to be collapsed. If no
- * alternate bounds are defined in the geometry and
- * <collapseToPreferredSize> is true, then the preferred size is used for
- * the alternate bounds. The top, left corner is always kept at the same
- * location.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the geometry is being udpated.
- * g - <mxGeometry> for which the alternate bounds should be updated.
- * willCollapse - Boolean indicating if the cell is going to be collapsed.
- */
-mxGraph.prototype.updateAlternateBounds = function(cell, geo, willCollapse)
-{
- if (cell != null && geo != null)
- {
- if (geo.alternateBounds == null)
- {
- var bounds = geo;
-
- if (this.collapseToPreferredSize)
- {
- var tmp = this.getPreferredSizeForCell(cell);
-
- if (tmp != null)
- {
- bounds = tmp;
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- var startSize = mxUtils.getValue(style, mxConstants.STYLE_STARTSIZE);
-
- if (startSize > 0)
- {
- bounds.height = Math.max(bounds.height, startSize);
- }
- }
- }
-
- geo.alternateBounds = new mxRectangle(
- geo.x, geo.y, bounds.width, bounds.height);
- }
- else
- {
- geo.alternateBounds.x = geo.x;
- geo.alternateBounds.y = geo.y;
- }
- }
-};
-
-/**
- * Function: addAllEdges
- *
- * Returns an array with the given cells and all edges that are connected
- * to a cell or one of its descendants.
- */
-mxGraph.prototype.addAllEdges = function(cells)
-{
- var allCells = cells.slice(); // FIXME: Required?
- allCells = allCells.concat(this.getAllEdges(cells));
-
- return allCells;
-};
-
-/**
- * Function: getAllEdges
- *
- * Returns all edges connected to the given cells or its descendants.
- */
-mxGraph.prototype.getAllEdges = function(cells)
-{
- var edges = [];
-
- if (cells != null)
- {
- for (var i = 0; i < cells.length; i++)
- {
- var edgeCount = this.model.getEdgeCount(cells[i]);
-
- for (var j = 0; j < edgeCount; j++)
- {
- edges.push(this.model.getEdgeAt(cells[i], j));
- }
-
- // Recurses
- var children = this.model.getChildren(cells[i]);
- edges = edges.concat(this.getAllEdges(children));
- }
- }
-
- return edges;
-};
-
-/**
- * Group: Cell sizing
- */
-
-/**
- * Function: updateCellSize
- *
- * Updates the size of the given cell in the model using <cellSizeUpdated>.
- * This method fires <mxEvent.UPDATE_CELL_SIZE> while the transaction is in
- * progress. Returns the cell whose size was updated.
- *
- * Parameters:
- *
- * cell - <mxCell> whose size should be updated.
- */
-mxGraph.prototype.updateCellSize = function(cell, ignoreChildren)
-{
- ignoreChildren = (ignoreChildren != null) ? ignoreChildren : false;
-
- this.model.beginUpdate();
- try
- {
- this.cellSizeUpdated(cell, ignoreChildren);
- this.fireEvent(new mxEventObject(mxEvent.UPDATE_CELL_SIZE,
- 'cell', cell, 'ignoreChildren', ignoreChildren));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cell;
-};
-
-/**
- * Function: cellSizeUpdated
- *
- * Updates the size of the given cell in the model using
- * <getPreferredSizeForCell> to get the new size.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the size should be changed.
- */
-mxGraph.prototype.cellSizeUpdated = function(cell, ignoreChildren)
-{
- if (cell != null)
- {
- this.model.beginUpdate();
- try
- {
- var size = this.getPreferredSizeForCell(cell);
- var geo = this.model.getGeometry(cell);
-
- if (size != null && geo != null)
- {
- var collapsed = this.isCellCollapsed(cell);
- geo = geo.clone();
-
- if (this.isSwimlane(cell))
- {
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
- var cellStyle = this.model.getStyle(cell);
-
- if (cellStyle == null)
- {
- cellStyle = '';
- }
-
- if (mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, true))
- {
- cellStyle = mxUtils.setStyle(cellStyle,
- mxConstants.STYLE_STARTSIZE, size.height + 8);
-
- if (collapsed)
- {
- geo.height = size.height + 8;
- }
-
- geo.width = size.width;
- }
- else
- {
- cellStyle = mxUtils.setStyle(cellStyle,
- mxConstants.STYLE_STARTSIZE, size.width + 8);
-
- if (collapsed)
- {
- geo.width = size.width + 8;
- }
-
- geo.height = size.height;
- }
-
- this.model.setStyle(cell, cellStyle);
- }
- else
- {
- geo.width = size.width;
- geo.height = size.height;
- }
-
- if (!ignoreChildren && !collapsed)
- {
- var bounds = this.view.getBounds(this.model.getChildren(cell));
-
- if (bounds != null)
- {
- var tr = this.view.translate;
- var scale = this.view.scale;
-
- var width = (bounds.x + bounds.width) / scale - geo.x - tr.x;
- var height = (bounds.y + bounds.height) / scale - geo.y - tr.y;
-
- geo.width = Math.max(geo.width, width);
- geo.height = Math.max(geo.height, height);
- }
- }
-
- this.cellsResized([cell], [geo]);
- }
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: getPreferredSizeForCell
- *
- * Returns the preferred width and height of the given <mxCell> as an
- * <mxRectangle>.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the preferred size should be returned.
- */
-mxGraph.prototype.getPreferredSizeForCell = function(cell)
-{
- var result = null;
-
- if (cell != null)
- {
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- if (style != null && !this.model.isEdge(cell))
- {
- var fontSize = style[mxConstants.STYLE_FONTSIZE] || mxConstants.DEFAULT_FONTSIZE;
- var dx = 0;
- var dy = 0;
-
- // Adds dimension of image if shape is a label
- if (this.getImage(state) != null || style[mxConstants.STYLE_IMAGE] != null)
- {
- if (style[mxConstants.STYLE_SHAPE] == mxConstants.SHAPE_LABEL)
- {
- if (style[mxConstants.STYLE_VERTICAL_ALIGN] == mxConstants.ALIGN_MIDDLE)
- {
- dx += parseFloat(style[mxConstants.STYLE_IMAGE_WIDTH]) || mxLabel.prototype.imageSize;
- }
-
- if (style[mxConstants.STYLE_ALIGN] != mxConstants.ALIGN_CENTER)
- {
- dy += parseFloat(style[mxConstants.STYLE_IMAGE_HEIGHT]) || mxLabel.prototype.imageSize;
- }
- }
- }
-
- // Adds spacings
- dx += 2 * (style[mxConstants.STYLE_SPACING] || 0);
- dx += style[mxConstants.STYLE_SPACING_LEFT] || 0;
- dx += style[mxConstants.STYLE_SPACING_RIGHT] || 0;
-
- dy += 2 * (style[mxConstants.STYLE_SPACING] || 0);
- dy += style[mxConstants.STYLE_SPACING_TOP] || 0;
- dy += style[mxConstants.STYLE_SPACING_BOTTOM] || 0;
-
- // Add spacing for collapse/expand icon
- // LATER: Check alignment and use constants
- // for image spacing
- var image = this.getFoldingImage(state);
-
- if (image != null)
- {
- dx += image.width + 8;
- }
-
- // Adds space for label
- var value = this.getLabel(cell);
-
- if (value != null && value.length > 0)
- {
- if (!this.isHtmlLabel(cell))
- {
- value = value.replace(/\n/g, '<br>');
- }
-
- var size = mxUtils.getSizeForString(value,
- fontSize, style[mxConstants.STYLE_FONTFAMILY]);
- var width = size.width + dx;
- var height = size.height + dy;
-
- if (!mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, true))
- {
- var tmp = height;
-
- height = width;
- width = tmp;
- }
-
- if (this.gridEnabled)
- {
- width = this.snap(width + this.gridSize / 2);
- height = this.snap(height + this.gridSize / 2);
- }
-
- result = new mxRectangle(0, 0, width, height);
- }
- else
- {
- var gs2 = 4 * this.gridSize;
- result = new mxRectangle(0, 0, gs2, gs2);
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: handleGesture
- *
- * Invokes if a gesture event has been detected on a cell state.
- *
- * Parameters:
- *
- * state - <mxCellState> which was pinched.
- * evt - Object that represents the gesture event.
- */
-mxGraph.prototype.handleGesture = function(state, evt)
-{
- if (Math.abs(1 - evt.scale) > 0.2)
- {
- var scale = this.view.scale;
- var tr = this.view.translate;
-
- var w = state.width * evt.scale;
- var h = state.height * evt.scale;
- var x = state.x - (w - state.width) / 2;
- var y = state.y - (h - state.height) / 2;
-
- var bounds = new mxRectangle(this.snap(x / scale) - tr.x,
- this.snap(y / scale) - tr.y,
- this.snap(w / scale), this.snap(h / scale));
- this.resizeCell(state.cell, bounds);
- }
-};
-
-/**
- * Function: resizeCell
- *
- * Sets the bounds of the given cell using <resizeCells>. Returns the
- * cell which was passed to the function.
- *
- * Parameters:
- *
- * cell - <mxCell> whose bounds should be changed.
- * bounds - <mxRectangle> that represents the new bounds.
- */
-mxGraph.prototype.resizeCell = function(cell, bounds)
-{
- return this.resizeCells([cell], [bounds])[0];
-};
-
-/**
- * Function: resizeCells
- *
- * Sets the bounds of the given cells and fires a <mxEvent.RESIZE_CELLS>
- * event while the transaction is in progress. Returns the cells which
- * have been passed to the function.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> whose bounds should be changed.
- * bounds - Array of <mxRectangles> that represent the new bounds.
- */
-mxGraph.prototype.resizeCells = function(cells, bounds)
-{
- this.model.beginUpdate();
- try
- {
- this.cellsResized(cells, bounds);
- this.fireEvent(new mxEventObject(mxEvent.RESIZE_CELLS,
- 'cells', cells, 'bounds', bounds));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return cells;
-};
-
-/**
- * Function: cellsResized
- *
- * Sets the bounds of the given cells and fires a <mxEvent.CELLS_RESIZED>
- * event. If <extendParents> is true, then the parent is extended if a
- * child size is changed so that it overlaps with the parent.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> whose bounds should be changed.
- * bounds - Array of <mxRectangles> that represent the new bounds.
- */
-mxGraph.prototype.cellsResized = function(cells, bounds)
-{
- if (cells != null && bounds != null && cells.length == bounds.length)
- {
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- var tmp = bounds[i];
- var geo = this.model.getGeometry(cells[i]);
-
- if (geo != null && (geo.x != tmp.x || geo.y != tmp.y ||
- geo.width != tmp.width || geo.height != tmp.height))
- {
- geo = geo.clone();
-
- if (geo.relative)
- {
- var offset = geo.offset;
-
- if (offset != null)
- {
- offset.x += tmp.x - geo.x;
- offset.y += tmp.y - geo.y;
- }
- }
- else
- {
- geo.x = tmp.x;
- geo.y = tmp.y;
- }
-
- geo.width = tmp.width;
- geo.height = tmp.height;
-
- if (!geo.relative && this.model.isVertex(cells[i]) &&
- !this.isAllowNegativeCoordinates())
- {
- geo.x = Math.max(0, geo.x);
- geo.y = Math.max(0, geo.y);
- }
-
- this.model.setGeometry(cells[i], geo);
-
- if (this.isExtendParent(cells[i]))
- {
- this.extendParent(cells[i]);
- }
- }
- }
-
- if (this.resetEdgesOnResize)
- {
- this.resetEdges(cells);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.CELLS_RESIZED,
- 'cells', cells, 'bounds', bounds));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: extendParent
- *
- * Resizes the parents recursively so that they contain the complete area
- * of the resized child cell.
- *
- * Parameters:
- *
- * cell - <mxCell> that has been resized.
- */
-mxGraph.prototype.extendParent = function(cell)
-{
- if (cell != null)
- {
- var parent = this.model.getParent(cell);
- var p = this.model.getGeometry(parent);
-
- if (parent != null && p != null && !this.isCellCollapsed(parent))
- {
- var geo = this.model.getGeometry(cell);
-
- if (geo != null && (p.width < geo.x + geo.width ||
- p.height < geo.y + geo.height))
- {
- p = p.clone();
-
- p.width = Math.max(p.width, geo.x + geo.width);
- p.height = Math.max(p.height, geo.y + geo.height);
-
- this.cellsResized([parent], [p]);
- }
- }
- }
-};
-
-/**
- * Group: Cell moving
- */
-
-/**
- * Function: importCells
- *
- * Clones and inserts the given cells into the graph using the move
- * method and returns the inserted cells. This shortcut is used if
- * cells are inserted via datatransfer.
- */
-mxGraph.prototype.importCells = function(cells, dx, dy, target, evt)
-{
- return this.moveCells(cells, dx, dy, true, target, evt);
-};
-
-/**
- * Function: moveCells
- *
- * Moves or clones the specified cells and moves the cells or clones by the
- * given amount, adding them to the optional target cell. The evt is the
- * mouse event as the mouse was released. The change is carried out using
- * <cellsMoved>. This method fires <mxEvent.MOVE_CELLS> while the
- * transaction is in progress. Returns the cells that were moved.
- *
- * Use the following code to move all cells in the graph.
- *
- * (code)
- * graph.moveCells(graph.getChildCells(null, true, true), 10, 10);
- * (end)
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be moved, cloned or added to the target.
- * dx - Integer that specifies the x-coordinate of the vector. Default is 0.
- * dy - Integer that specifies the y-coordinate of the vector. Default is 0.
- * clone - Boolean indicating if the cells should be cloned. Default is false.
- * target - <mxCell> that represents the new parent of the cells.
- * evt - Mouseevent that triggered the invocation.
- */
-mxGraph.prototype.moveCells = function(cells, dx, dy, clone, target, evt)
-{
- dx = (dx != null) ? dx : 0;
- dy = (dy != null) ? dy : 0;
- clone = (clone != null) ? clone : false;
-
- if (cells != null && (dx != 0 || dy != 0 || clone || target != null))
- {
- this.model.beginUpdate();
- try
- {
- if (clone)
- {
- cells = this.cloneCells(cells, this.isCloneInvalidEdges());
-
- if (target == null)
- {
- target = this.getDefaultParent();
- }
- }
-
- // FIXME: Cells should always be inserted first before any other edit
- // to avoid forward references in sessions.
- // Need to disable allowNegativeCoordinates if target not null to
- // allow for temporary negative numbers until cellsAdded is called.
- var previous = this.isAllowNegativeCoordinates();
-
- if (target != null)
- {
- this.setAllowNegativeCoordinates(true);
- }
-
- this.cellsMoved(cells, dx, dy, !clone && this.isDisconnectOnMove()
- && this.isAllowDanglingEdges(), target == null);
-
- this.setAllowNegativeCoordinates(previous);
-
- if (target != null)
- {
- var index = this.model.getChildCount(target);
- this.cellsAdded(cells, target, index, null, null, true);
- }
-
- // Dispatches a move event
- this.fireEvent(new mxEventObject(mxEvent.MOVE_CELLS, 'cells', cells,
- 'dx', dx, 'dy', dy, 'clone', clone, 'target', target, 'event', evt));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-
- return cells;
-};
-
-/**
- * Function: cellsMoved
- *
- * Moves the specified cells by the given vector, disconnecting the cells
- * using disconnectGraph is disconnect is true. This method fires
- * <mxEvent.CELLS_MOVED> while the transaction is in progress.
- */
-mxGraph.prototype.cellsMoved = function(cells, dx, dy, disconnect, constrain)
-{
- if (cells != null && (dx != 0 || dy != 0))
- {
- this.model.beginUpdate();
- try
- {
- if (disconnect)
- {
- this.disconnectGraph(cells);
- }
-
- for (var i = 0; i < cells.length; i++)
- {
- this.translateCell(cells[i], dx, dy);
-
- if (constrain)
- {
- this.constrainChild(cells[i]);
- }
- }
-
- if (this.resetEdgesOnMove)
- {
- this.resetEdges(cells);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.CELLS_MOVED,
- 'cells', cells, 'dx', dy, 'dy', dy, 'disconnect', disconnect));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: translateCell
- *
- * Translates the geometry of the given cell and stores the new,
- * translated geometry in the model as an atomic change.
- */
-mxGraph.prototype.translateCell = function(cell, dx, dy)
-{
- var geo = this.model.getGeometry(cell);
-
- if (geo != null)
- {
- geo = geo.clone();
- geo.translate(dx, dy);
-
- if (!geo.relative && this.model.isVertex(cell) && !this.isAllowNegativeCoordinates())
- {
- geo.x = Math.max(0, geo.x);
- geo.y = Math.max(0, geo.y);
- }
-
- if (geo.relative && !this.model.isEdge(cell))
- {
- if (geo.offset == null)
- {
- geo.offset = new mxPoint(dx, dy);
- }
- else
- {
- geo.offset.x += dx;
- geo.offset.y += dy;
- }
- }
-
- this.model.setGeometry(cell, geo);
- }
-};
-
-/**
- * Function: getCellContainmentArea
- *
- * Returns the <mxRectangle> inside which a cell is to be kept.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the area should be returned.
- */
-mxGraph.prototype.getCellContainmentArea = function(cell)
-{
- if (cell != null && !this.model.isEdge(cell))
- {
- var parent = this.model.getParent(cell);
-
- if (parent == this.getDefaultParent() || parent == this.getCurrentRoot())
- {
- return this.getMaximumGraphBounds();
- }
- else if (parent != null && parent != this.getDefaultParent())
- {
- var g = this.model.getGeometry(parent);
-
- if (g != null)
- {
- var x = 0;
- var y = 0;
- var w = g.width;
- var h = g.height;
-
- if (this.isSwimlane(parent))
- {
- var size = this.getStartSize(parent);
-
- x = size.width;
- w -= size.width;
- y = size.height;
- h -= size.height;
- }
-
- return new mxRectangle(x, y, w, h);
- }
- }
- }
-
- return null;
-};
-
-/**
- * Function: getMaximumGraphBounds
- *
- * Returns the bounds inside which the diagram should be kept as an
- * <mxRectangle>.
- */
-mxGraph.prototype.getMaximumGraphBounds = function()
-{
- return this.maximumGraphBounds;
-};
-
-/**
- * Function: constrainChild
- *
- * Keeps the given cell inside the bounds returned by
- * <getCellContainmentArea> for its parent, according to the rules defined by
- * <getOverlap> and <isConstrainChild>. This modifies the cell's geometry
- * in-place and does not clone it.
- *
- * Parameters:
- *
- * cells - <mxCell> which should be constrained.
- */
-mxGraph.prototype.constrainChild = function(cell)
-{
- if (cell != null)
- {
- var geo = this.model.getGeometry(cell);
- var area = (this.isConstrainChild(cell)) ?
- this.getCellContainmentArea(cell) :
- this.getMaximumGraphBounds();
-
- if (geo != null && area != null)
- {
- // Keeps child within the content area of the parent
- if (!geo.relative && (geo.x < area.x || geo.y < area.y ||
- area.width < geo.x + geo.width || area.height < geo.y + geo.height))
- {
- var overlap = this.getOverlap(cell);
-
- if (area.width > 0)
- {
- geo.x = Math.min(geo.x, area.x + area.width -
- (1 - overlap) * geo.width);
- }
-
- if (area.height > 0)
- {
- geo.y = Math.min(geo.y, area.y + area.height -
- (1 - overlap) * geo.height);
- }
-
- geo.x = Math.max(geo.x, area.x - geo.width * overlap);
- geo.y = Math.max(geo.y, area.y - geo.height * overlap);
- }
- }
- }
-};
-
-/**
- * Function: resetEdges
- *
- * Resets the control points of the edges that are connected to the given
- * cells if not both ends of the edge are in the given cells array.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> for which the connected edges should be
- * reset.
- */
-mxGraph.prototype.resetEdges = function(cells)
-{
- if (cells != null)
- {
- // Prepares a hashtable for faster cell lookups
- var hash = new Object();
-
- for (var i = 0; i < cells.length; i++)
- {
- var id = mxCellPath.create(cells[i]);
- hash[id] = cells[i];
- }
-
- this.model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- var edges = this.model.getEdges(cells[i]);
-
- if (edges != null)
- {
- for (var j = 0; j < edges.length; j++)
- {
- var state = this.view.getState(edges[j]);
-
- var source = (state != null) ? state.getVisibleTerminal(true) : this.view.getVisibleTerminal(edges[j], true);
- var target = (state != null) ? state.getVisibleTerminal(false) : this.view.getVisibleTerminal(edges[j], false);
-
- var sourceId = mxCellPath.create(source);
- var targetId = mxCellPath.create(target);
-
- // Checks if one of the terminals is not in the given array
- if (hash[sourceId] == null || hash[targetId] == null)
- {
- this.resetEdge(edges[j]);
- }
- }
- }
-
- this.resetEdges(this.model.getChildren(cells[i]));
- }
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: resetEdge
- *
- * Resets the control points of the given edge.
- *
- * Parameters:
- *
- * edge - <mxCell> whose points should be reset.
- */
-mxGraph.prototype.resetEdge = function(edge)
-{
- var geo = this.model.getGeometry(edge);
-
- // Resets the control points
- if (geo != null && geo.points != null && geo.points.length > 0)
- {
- geo = geo.clone();
- geo.points = [];
- this.model.setGeometry(edge, geo);
- }
-
- return edge;
-};
-
-/**
- * Group: Cell connecting and connection constraints
- */
-
-/**
- * Function: getAllConnectionConstraints
- *
- * Returns an array of all <mxConnectionConstraints> for the given terminal. If
- * the shape of the given terminal is a <mxStencilShape> then the constraints
- * of the corresponding <mxStencil> are returned.
- *
- * Parameters:
- *
- * terminal - <mxCellState> that represents the terminal.
- * source - Boolean that specifies if the terminal is the source or target.
- */
-mxGraph.prototype.getAllConnectionConstraints = function(terminal, source)
-{
- if (terminal != null && terminal.shape != null &&
- terminal.shape instanceof mxStencilShape)
- {
- if (terminal.shape.stencil != null)
- {
- return terminal.shape.stencil.constraints;
- }
- }
-
- return null;
-};
-
-/**
- * Function: getConnectionConstraint
- *
- * Returns an <mxConnectionConstraint> that describes the given connection
- * point. This result can then be passed to <getConnectionPoint>.
- *
- * Parameters:
- *
- * edge - <mxCellState> that represents the edge.
- * terminal - <mxCellState> that represents the terminal.
- * source - Boolean indicating if the terminal is the source or target.
- */
-mxGraph.prototype.getConnectionConstraint = function(edge, terminal, source)
-{
- var point = null;
- var x = edge.style[(source) ?
- mxConstants.STYLE_EXIT_X :
- mxConstants.STYLE_ENTRY_X];
-
- if (x != null)
- {
- var y = edge.style[(source) ?
- mxConstants.STYLE_EXIT_Y :
- mxConstants.STYLE_ENTRY_Y];
-
- if (y != null)
- {
- point = new mxPoint(parseFloat(x), parseFloat(y));
- }
- }
-
- var perimeter = false;
-
- if (point != null)
- {
- perimeter = mxUtils.getValue(edge.style, (source) ? mxConstants.STYLE_EXIT_PERIMETER :
- mxConstants.STYLE_ENTRY_PERIMETER, true);
- }
-
- return new mxConnectionConstraint(point, perimeter);
-};
-
-/**
- * Function: setConnectionConstraint
- *
- * Sets the <mxConnectionConstraint> that describes the given connection point.
- * If no constraint is given then nothing is changed. To remove an existing
- * constraint from the given edge, use an empty constraint instead.
- *
- * Parameters:
- *
- * edge - <mxCell> that represents the edge.
- * terminal - <mxCell> that represents the terminal.
- * source - Boolean indicating if the terminal is the source or target.
- * constraint - Optional <mxConnectionConstraint> to be used for this
- * connection.
- */
-mxGraph.prototype.setConnectionConstraint = function(edge, terminal, source, constraint)
-{
- if (constraint != null)
- {
- this.model.beginUpdate();
- try
- {
- if (constraint == null || constraint.point == null)
- {
- this.setCellStyles((source) ? mxConstants.STYLE_EXIT_X :
- mxConstants.STYLE_ENTRY_X, null, [edge]);
- this.setCellStyles((source) ? mxConstants.STYLE_EXIT_Y :
- mxConstants.STYLE_ENTRY_Y, null, [edge]);
- this.setCellStyles((source) ? mxConstants.STYLE_EXIT_PERIMETER :
- mxConstants.STYLE_ENTRY_PERIMETER, null, [edge]);
- }
- else if (constraint.point != null)
- {
- this.setCellStyles((source) ? mxConstants.STYLE_EXIT_X :
- mxConstants.STYLE_ENTRY_X, constraint.point.x, [edge]);
- this.setCellStyles((source) ? mxConstants.STYLE_EXIT_Y :
- mxConstants.STYLE_ENTRY_Y, constraint.point.y, [edge]);
-
- // Only writes 0 since 1 is default
- if (!constraint.perimeter)
- {
- this.setCellStyles((source) ? mxConstants.STYLE_EXIT_PERIMETER :
- mxConstants.STYLE_ENTRY_PERIMETER, '0', [edge]);
- }
- else
- {
- this.setCellStyles((source) ? mxConstants.STYLE_EXIT_PERIMETER :
- mxConstants.STYLE_ENTRY_PERIMETER, null, [edge]);
- }
- }
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: getConnectionPoint
- *
- * Returns the nearest point in the list of absolute points or the center
- * of the opposite terminal.
- *
- * Parameters:
- *
- * vertex - <mxCellState> that represents the vertex.
- * constraint - <mxConnectionConstraint> that represents the connection point
- * constraint as returned by <getConnectionConstraint>.
- */
-mxGraph.prototype.getConnectionPoint = function(vertex, constraint)
-{
- var point = null;
-
- if (vertex != null)
- {
- var bounds = this.view.getPerimeterBounds(vertex);
- var cx = new mxPoint(bounds.getCenterX(), bounds.getCenterY());
-
- var direction = vertex.style[mxConstants.STYLE_DIRECTION];
- var r1 = 0;
-
- // Bounds need to be rotated by 90 degrees for further computation
- if (direction != null)
- {
- if (direction == 'north')
- {
- r1 += 270;
- }
- else if (direction == 'west')
- {
- r1 += 180;
- }
- else if (direction == 'south')
- {
- r1 += 90;
- }
-
- // Bounds need to be rotated by 90 degrees for further computation
- if (direction == 'north' || direction == 'south')
- {
- bounds.x += bounds.width / 2 - bounds.height / 2;
- bounds.y += bounds.height / 2 - bounds.width / 2;
- var tmp = bounds.width;
- bounds.width = bounds.height;
- bounds.height = tmp;
- }
- }
-
- if (constraint.point != null)
- {
- var sx = 1;
- var sy = 1;
- var dx = 0;
- var dy = 0;
-
- // LATER: Add flipping support for image shapes
- if (vertex.shape instanceof mxStencilShape)
- {
- var flipH = vertex.style[mxConstants.STYLE_STENCIL_FLIPH];
- var flipV = vertex.style[mxConstants.STYLE_STENCIL_FLIPV];
-
- if (direction == 'north' || direction == 'south')
- {
- var tmp = flipH;
- flipH = flipV;
- flipV = tmp;
- }
-
- if (flipH)
- {
- sx = -1;
- dx = -bounds.width;
- }
-
- if (flipV)
- {
- sy = -1;
- dy = -bounds.height ;
- }
- }
-
- point = new mxPoint(bounds.x + constraint.point.x * bounds.width * sx - dx,
- bounds.y + constraint.point.y * bounds.height * sy - dy);
- }
-
- // Rotation for direction before projection on perimeter
- var r2 = vertex.style[mxConstants.STYLE_ROTATION] || 0;
-
- if (constraint.perimeter)
- {
- if (r1 != 0 && point != null)
- {
- // Only 90 degrees steps possible here so no trig needed
- var cos = 0;
- var sin = 0;
-
- if (r1 == 90)
- {
- sin = 1;
- }
- else if (r1 == 180)
- {
- cos = -1;
- }
- else if (r2 == 270)
- {
- sin = -1;
- }
-
- point = mxUtils.getRotatedPoint(point, cos, sin, cx);
- }
-
- if (point != null && constraint.perimeter)
- {
- point = this.view.getPerimeterPoint(vertex, point, false);
- }
- }
- else
- {
- r2 += r1;
- }
-
- // Generic rotation after projection on perimeter
- if (r2 != 0 && point != null)
- {
- var rad = mxUtils.toRadians(r2);
- var cos = Math.cos(rad);
- var sin = Math.sin(rad);
-
- point = mxUtils.getRotatedPoint(point, cos, sin, cx);
- }
- }
-
- return point;
-};
-
-/**
- * Function: connectCell
- *
- * Connects the specified end of the given edge to the given terminal
- * using <cellConnected> and fires <mxEvent.CONNECT_CELL> while the
- * transaction is in progress. Returns the updated edge.
- *
- * Parameters:
- *
- * edge - <mxCell> whose terminal should be updated.
- * terminal - <mxCell> that represents the new terminal to be used.
- * source - Boolean indicating if the new terminal is the source or target.
- * constraint - Optional <mxConnectionConstraint> to be used for this
- * connection.
- */
-mxGraph.prototype.connectCell = function(edge, terminal, source, constraint)
-{
- this.model.beginUpdate();
- try
- {
- var previous = this.model.getTerminal(edge, source);
- this.cellConnected(edge, terminal, source, constraint);
- this.fireEvent(new mxEventObject(mxEvent.CONNECT_CELL,
- 'edge', edge, 'terminal', terminal, 'source', source,
- 'previous', previous));
- }
- finally
- {
- this.model.endUpdate();
- }
-
- return edge;
-};
-
-/**
- * Function: cellConnected
- *
- * Sets the new terminal for the given edge and resets the edge points if
- * <resetEdgesOnConnect> is true. This method fires
- * <mxEvent.CELL_CONNECTED> while the transaction is in progress.
- *
- * Parameters:
- *
- * edge - <mxCell> whose terminal should be updated.
- * terminal - <mxCell> that represents the new terminal to be used.
- * source - Boolean indicating if the new terminal is the source or target.
- * constraint - <mxConnectionConstraint> to be used for this connection.
- */
-mxGraph.prototype.cellConnected = function(edge, terminal, source, constraint)
-{
- if (edge != null)
- {
- this.model.beginUpdate();
- try
- {
- var previous = this.model.getTerminal(edge, source);
-
- // Updates the constraint
- this.setConnectionConstraint(edge, terminal, source, constraint);
-
- // Checks if the new terminal is a port, uses the ID of the port in the
- // style and the parent of the port as the actual terminal of the edge.
- if (this.isPortsEnabled())
- {
- var id = null;
-
- if (this.isPort(terminal))
- {
- id = terminal.getId();
- terminal = this.getTerminalForPort(terminal, source);
- }
-
- // Sets or resets all previous information for connecting to a child port
- var key = (source) ? mxConstants.STYLE_SOURCE_PORT :
- mxConstants.STYLE_TARGET_PORT;
- this.setCellStyles(key, id, [edge]);
- }
-
- this.model.setTerminal(edge, terminal, source);
-
- if (this.resetEdgesOnConnect)
- {
- this.resetEdge(edge);
- }
-
- this.fireEvent(new mxEventObject(mxEvent.CELL_CONNECTED,
- 'edge', edge, 'terminal', terminal, 'source', source,
- 'previous', previous));
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Function: disconnectGraph
- *
- * Disconnects the given edges from the terminals which are not in the
- * given array.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be disconnected.
- */
-mxGraph.prototype.disconnectGraph = function(cells)
-{
- if (cells != null)
- {
- this.model.beginUpdate();
- try
- {
- var scale = this.view.scale;
- var tr = this.view.translate;
-
- // Prepares a hashtable for faster cell lookups
- var hash = new Object();
-
- for (var i = 0; i < cells.length; i++)
- {
- var id = mxCellPath.create(cells[i]);
- hash[id] = cells[i];
- }
-
- for (var i = 0; i < cells.length; i++)
- {
- if (this.model.isEdge(cells[i]))
- {
- var geo = this.model.getGeometry(cells[i]);
-
- if (geo != null)
- {
- var state = this.view.getState(cells[i]);
- var pstate = this.view.getState(
- this.model.getParent(cells[i]));
-
- if (state != null &&
- pstate != null)
- {
- geo = geo.clone();
-
- var dx = -pstate.origin.x;
- var dy = -pstate.origin.y;
- var pts = state.absolutePoints;
-
- var src = this.model.getTerminal(cells[i], true);
-
- if (src != null && this.isCellDisconnectable(cells[i], src, true))
- {
- var srcId = mxCellPath.create(src);
-
- while (src != null && hash[srcId] == null)
- {
- src = this.model.getParent(src);
- srcId = mxCellPath.create(src);
- }
-
- if (src == null)
- {
- geo.setTerminalPoint(
- new mxPoint(pts[0].x / scale - tr.x + dx,
- pts[0].y / scale - tr.y + dy), true);
- this.model.setTerminal(cells[i], null, true);
- }
- }
-
- var trg = this.model.getTerminal(cells[i], false);
-
- if (trg != null && this.isCellDisconnectable(cells[i], trg, false))
- {
- var trgId = mxCellPath.create(trg);
-
- while (trg != null && hash[trgId] == null)
- {
- trg = this.model.getParent(trg);
- trgId = mxCellPath.create(trg);
- }
-
- if (trg == null)
- {
- var n = pts.length - 1;
- geo.setTerminalPoint(
- new mxPoint(pts[n].x / scale - tr.x + dx,
- pts[n].y / scale - tr.y + dy), false);
- this.model.setTerminal(cells[i], null, false);
- }
- }
-
- this.model.setGeometry(cells[i], geo);
- }
- }
- }
- }
- }
- finally
- {
- this.model.endUpdate();
- }
- }
-};
-
-/**
- * Group: Drilldown
- */
-
-/**
- * Function: getCurrentRoot
- *
- * Returns the current root of the displayed cell hierarchy. This is a
- * shortcut to <mxGraphView.currentRoot> in <view>.
- */
- mxGraph.prototype.getCurrentRoot = function()
- {
- return this.view.currentRoot;
- };
-
- /**
- * Function: getTranslateForRoot
- *
- * Returns the translation to be used if the given cell is the root cell as
- * an <mxPoint>. This implementation returns null.
- *
- * Example:
- *
- * To keep the children at their absolute position while stepping into groups,
- * this function can be overridden as follows.
- *
- * (code)
- * var offset = new mxPoint(0, 0);
- *
- * while (cell != null)
- * {
- * var geo = this.model.getGeometry(cell);
- *
- * if (geo != null)
- * {
- * offset.x -= geo.x;
- * offset.y -= geo.y;
- * }
- *
- * cell = this.model.getParent(cell);
- * }
- *
- * return offset;
- * (end)
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the root.
- */
-mxGraph.prototype.getTranslateForRoot = function(cell)
-{
- return null;
-};
-
-/**
- * Function: isPort
- *
- * Returns true if the given cell is a "port", that is, when connecting to
- * it, the cell returned by getTerminalForPort should be used as the
- * terminal and the port should be referenced by the ID in either the
- * mxConstants.STYLE_SOURCE_PORT or the or the
- * mxConstants.STYLE_TARGET_PORT. Note that a port should not be movable.
- * This implementation always returns false.
- *
- * A typical implementation is the following:
- *
- * (code)
- * graph.isPort = function(cell)
- * {
- * var geo = this.getCellGeometry(cell);
- *
- * return (geo != null) ? geo.relative : false;
- * };
- * (end)
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the port.
- */
-mxGraph.prototype.isPort = function(cell)
-{
- return false;
-};
-
-/**
- * Function: getTerminalForPort
- *
- * Returns the terminal to be used for a given port. This implementation
- * always returns the parent cell.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the port.
- * source - If the cell is the source or target port.
- */
-mxGraph.prototype.getTerminalForPort = function(cell, source)
-{
- return this.model.getParent(cell);
-};
-
-/**
- * Function: getChildOffsetForCell
- *
- * Returns the offset to be used for the cells inside the given cell. The
- * root and layer cells may be identified using <mxGraphModel.isRoot> and
- * <mxGraphModel.isLayer>. For all other current roots, the
- * <mxGraphView.currentRoot> field points to the respective cell, so that
- * the following holds: cell == this.view.currentRoot. This implementation
- * returns null.
- *
- * Parameters:
- *
- * cell - <mxCell> whose offset should be returned.
- */
-mxGraph.prototype.getChildOffsetForCell = function(cell)
-{
- return null;
-};
-
-/**
- * Function: enterGroup
- *
- * Uses the given cell as the root of the displayed cell hierarchy. If no
- * cell is specified then the selection cell is used. The cell is only used
- * if <isValidRoot> returns true.
- *
- * Parameters:
- *
- * cell - Optional <mxCell> to be used as the new root. Default is the
- * selection cell.
- */
-mxGraph.prototype.enterGroup = function(cell)
-{
- cell = cell || this.getSelectionCell();
-
- if (cell != null && this.isValidRoot(cell))
- {
- this.view.setCurrentRoot(cell);
- this.clearSelection();
- }
-};
-
-/**
- * Function: exitGroup
- *
- * Changes the current root to the next valid root in the displayed cell
- * hierarchy.
- */
-mxGraph.prototype.exitGroup = function()
-{
- var root = this.model.getRoot();
- var current = this.getCurrentRoot();
-
- if (current != null)
- {
- var next = this.model.getParent(current);
-
- // Finds the next valid root in the hierarchy
- while (next != root && !this.isValidRoot(next) &&
- this.model.getParent(next) != root)
- {
- next = this.model.getParent(next);
- }
-
- // Clears the current root if the new root is
- // the model's root or one of the layers.
- if (next == root || this.model.getParent(next) == root)
- {
- this.view.setCurrentRoot(null);
- }
- else
- {
- this.view.setCurrentRoot(next);
- }
-
- var state = this.view.getState(current);
-
- // Selects the previous root in the graph
- if (state != null)
- {
- this.setSelectionCell(current);
- }
- }
-};
-
-/**
- * Function: home
- *
- * Uses the root of the model as the root of the displayed cell hierarchy
- * and selects the previous root.
- */
-mxGraph.prototype.home = function()
-{
- var current = this.getCurrentRoot();
-
- if (current != null)
- {
- this.view.setCurrentRoot(null);
- var state = this.view.getState(current);
-
- if (state != null)
- {
- this.setSelectionCell(current);
- }
- }
-};
-
-/**
- * Function: isValidRoot
- *
- * Returns true if the given cell is a valid root for the cell display
- * hierarchy. This implementation returns true for all non-null values.
- *
- * Parameters:
- *
- * cell - <mxCell> which should be checked as a possible root.
- */
-mxGraph.prototype.isValidRoot = function(cell)
-{
- return (cell != null);
-};
-
-/**
- * Group: Graph display
- */
-
-/**
- * Function: getGraphBounds
- *
- * Returns the bounds of the visible graph. Shortcut to
- * <mxGraphView.getGraphBounds>. See also: <getBoundingBoxFromGeometry>.
- */
- mxGraph.prototype.getGraphBounds = function()
- {
- return this.view.getGraphBounds();
- };
-
-/**
- * Function: getCellBounds
- *
- * Returns the scaled, translated bounds for the given cell. See
- * <mxGraphView.getBounds> for arrays.
- *
- * Parameters:
- *
- * cell - <mxCell> whose bounds should be returned.
- * includeEdge - Optional boolean that specifies if the bounds of
- * the connected edges should be included. Default is false.
- * includeDescendants - Optional boolean that specifies if the bounds
- * of all descendants should be included. Default is false.
- */
-mxGraph.prototype.getCellBounds = function(cell, includeEdges, includeDescendants)
-{
- var cells = [cell];
-
- // Includes all connected edges
- if (includeEdges)
- {
- cells = cells.concat(this.model.getEdges(cell));
- }
-
- var result = this.view.getBounds(cells);
-
- // Recursively includes the bounds of the children
- if (includeDescendants)
- {
- var childCount = this.model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var tmp = this.getCellBounds(this.model.getChildAt(cell, i),
- includeEdges, true);
-
- if (result != null)
- {
- result.add(tmp);
- }
- else
- {
- result = tmp;
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: getBoundingBoxFromGeometry
- *
- * Returns the bounding box for the geometries of the vertices in the
- * given array of cells. This can be used to find the graph bounds during
- * a layout operation (ie. before the last endUpdate) as follows:
- *
- * (code)
- * var cells = graph.getChildCells(graph.getDefaultParent(), true, true);
- * var bounds = graph.getBoundingBoxFromGeometry(cells, true);
- * (end)
- *
- * This can then be used to move cells to the origin:
- *
- * (code)
- * if (bounds.x < 0 || bounds.y < 0)
- * {
- * graph.moveCells(cells, -Math.min(bounds.x, 0), -Math.min(bounds.y, 0))
- * }
- * (end)
- *
- * Or to translate the graph view:
- *
- * (code)
- * if (bounds.x < 0 || bounds.y < 0)
- * {
- * graph.view.setTranslate(-Math.min(bounds.x, 0), -Math.min(bounds.y, 0));
- * }
- * (end)
- *
- * Parameters:
- *
- * cells - Array of <mxCells> whose bounds should be returned.
- * includeEdges - Specifies if edge bounds should be included by computing
- * the bounding box for all points its geometry. Default is false.
- */
-mxGraph.prototype.getBoundingBoxFromGeometry = function(cells, includeEdges)
-{
- includeEdges = (includeEdges != null) ? includeEdges : false;
- var result = null;
-
- if (cells != null)
- {
- for (var i = 0; i < cells.length; i++)
- {
- if (includeEdges || this.model.isVertex(cells[i]))
- {
- // Computes the bounding box for the points in the geometry
- var geo = this.getCellGeometry(cells[i]);
-
- if (geo != null)
- {
- var pts = geo.points;
-
- if (pts != null && pts.length > 0)
- {
- var tmp = new mxRectangle(pts[0].x, pts[0].y, 0, 0);
- var addPoint = function(pt)
- {
- if (pt != null)
- {
- tmp.add(new mxRectangle(pt.x, pt.y, 0, 0));
- }
- };
-
- for (var j = 1; j < pts.length; j++)
- {
- addPoint(pts[j]);
- }
-
- addPoint(geo.getTerminalPoint(true));
- addPoint(geo.getTerminalPoint(false));
- }
-
- if (result == null)
- {
- result = new mxRectangle(geo.x, geo.y, geo.width, geo.height);
- }
- else
- {
- result.add(geo);
- }
- }
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: refresh
- *
- * Clears all cell states or the states for the hierarchy starting at the
- * given cell and validates the graph. This fires a refresh event as the
- * last step.
- *
- * Parameters:
- *
- * cell - Optional <mxCell> for which the cell states should be cleared.
- */
-mxGraph.prototype.refresh = function(cell)
-{
- this.view.clear(cell, cell == null);
- this.view.validate();
- this.sizeDidChange();
- this.fireEvent(new mxEventObject(mxEvent.REFRESH));
-};
-
-/**
- * Function: snap
- *
- * Snaps the given numeric value to the grid if <gridEnabled> is true.
- *
- * Parameters:
- *
- * value - Numeric value to be snapped to the grid.
- */
-mxGraph.prototype.snap = function(value)
-{
- if (this.gridEnabled)
- {
- value = Math.round(value / this.gridSize ) * this.gridSize;
- }
-
- return value;
-};
-
-/**
- * Function: panGraph
- *
- * Shifts the graph display by the given amount. This is used to preview
- * panning operations, use <mxGraphView.setTranslate> to set a persistent
- * translation of the view. Fires <mxEvent.PAN>.
- *
- * Parameters:
- *
- * dx - Amount to shift the graph along the x-axis.
- * dy - Amount to shift the graph along the y-axis.
- */
-mxGraph.prototype.panGraph = function(dx, dy)
-{
- if (this.useScrollbarsForPanning && mxUtils.hasScrollbars(this.container))
- {
- this.container.scrollLeft = -dx;
- this.container.scrollTop = -dy;
- }
- else
- {
- var canvas = this.view.getCanvas();
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- // Puts everything inside the container in a DIV so that it
- // can be moved without changing the state of the container
- if (dx == 0 && dy == 0)
- {
- // Workaround for ignored removeAttribute on SVG element in IE9 standards
- if (mxClient.IS_IE)
- {
- canvas.setAttribute('transform', 'translate('+ dx + ',' + dy + ')');
- }
- else
- {
- canvas.removeAttribute('transform');
- }
-
- if (this.shiftPreview1 != null)
- {
- var child = this.shiftPreview1.firstChild;
-
- while (child != null)
- {
- var next = child.nextSibling;
- this.container.appendChild(child);
- child = next;
- }
-
- this.shiftPreview1.parentNode.removeChild(this.shiftPreview1);
- this.shiftPreview1 = null;
-
- this.container.appendChild(canvas.parentNode);
-
- child = this.shiftPreview2.firstChild;
-
- while (child != null)
- {
- var next = child.nextSibling;
- this.container.appendChild(child);
- child = next;
- }
-
- this.shiftPreview2.parentNode.removeChild(this.shiftPreview2);
- this.shiftPreview2 = null;
- }
- }
- else
- {
- canvas.setAttribute('transform', 'translate('+ dx + ',' + dy + ')');
-
- if (this.shiftPreview1 == null)
- {
- // Needs two divs for stuff before and after the SVG element
- this.shiftPreview1 = document.createElement('div');
- this.shiftPreview1.style.position = 'absolute';
- this.shiftPreview1.style.overflow = 'visible';
-
- this.shiftPreview2 = document.createElement('div');
- this.shiftPreview2.style.position = 'absolute';
- this.shiftPreview2.style.overflow = 'visible';
-
- var current = this.shiftPreview1;
- var child = this.container.firstChild;
-
- while (child != null)
- {
- var next = child.nextSibling;
-
- // SVG element is moved via transform attribute
- if (child != canvas.parentNode)
- {
- current.appendChild(child);
- }
- else
- {
- current = this.shiftPreview2;
- }
-
- child = next;
- }
-
- this.container.insertBefore(this.shiftPreview1, canvas.parentNode);
- this.container.appendChild(this.shiftPreview2);
- }
-
- this.shiftPreview1.style.left = dx + 'px';
- this.shiftPreview1.style.top = dy + 'px';
- this.shiftPreview2.style.left = dx + 'px';
- this.shiftPreview2.style.top = dy + 'px';
- }
- }
- else
- {
- canvas.style.left = dx + 'px';
- canvas.style.top = dy + 'px';
- }
-
- this.panDx = dx;
- this.panDy = dy;
-
- this.fireEvent(new mxEventObject(mxEvent.PAN));
- }
-};
-
-/**
- * Function: zoomIn
- *
- * Zooms into the graph by <zoomFactor>.
- */
-mxGraph.prototype.zoomIn = function()
-{
- this.zoom(this.zoomFactor);
-};
-
-/**
- * Function: zoomOut
- *
- * Zooms out of the graph by <zoomFactor>.
- */
-mxGraph.prototype.zoomOut = function()
-{
- this.zoom(1 / this.zoomFactor);
-};
-
-/**
- * Function: zoomActual
- *
- * Resets the zoom and panning in the view.
- */
-mxGraph.prototype.zoomActual = function()
-{
- if (this.view.scale == 1)
- {
- this.view.setTranslate(0, 0);
- }
- else
- {
- this.view.translate.x = 0;
- this.view.translate.y = 0;
-
- this.view.setScale(1);
- }
-};
-
-/**
- * Function: zoomTo
- *
- * Zooms the graph to the given scale with an optional boolean center
- * argument, which is passd to <zoom>.
- */
-mxGraph.prototype.zoomTo = function(scale, center)
-{
- this.zoom(scale / this.view.scale, center);
-};
-
-/**
- * Function: zoom
- *
- * Zooms the graph using the given factor. Center is an optional boolean
- * argument that keeps the graph scrolled to the center. If the center argument
- * is omitted, then <centerZoom> will be used as its value.
- */
-mxGraph.prototype.zoom = function(factor, center)
-{
- center = (center != null) ? center : this.centerZoom;
- var scale = this.view.scale * factor;
- var state = this.view.getState(this.getSelectionCell());
-
- if (this.keepSelectionVisibleOnZoom && state != null)
- {
- var rect = new mxRectangle(
- state.x * factor,
- state.y * factor,
- state.width * factor,
- state.height * factor);
-
- // Refreshes the display only once if a
- // scroll is carried out
- this.view.scale = scale;
-
- if (!this.scrollRectToVisible(rect))
- {
- this.view.revalidate();
-
- // Forces an event to be fired but does not revalidate again
- this.view.setScale(scale);
- }
- }
- else if (center && !mxUtils.hasScrollbars(this.container))
- {
- var dx = this.container.offsetWidth;
- var dy = this.container.offsetHeight;
-
- if (factor > 1)
- {
- var f = (factor -1) / (scale * 2);
- dx *= -f;
- dy *= -f;
- }
- else
- {
- var f = (1/factor -1) / (this.view.scale * 2);
- dx *= f;
- dy *= f;
- }
-
- this.view.scaleAndTranslate(scale,
- this.view.translate.x + dx,
- this.view.translate.y + dy);
- }
- else
- {
- this.view.setScale(scale);
-
- if (mxUtils.hasScrollbars(this.container))
- {
- var dx = 0;
- var dy = 0;
-
- if (center)
- {
- dx = this.container.offsetWidth * (factor - 1) / 2;
- dy = this.container.offsetHeight * (factor - 1) / 2;
- }
-
- this.container.scrollLeft = Math.round(this.container.scrollLeft * factor + dx);
- this.container.scrollTop = Math.round(this.container.scrollTop * factor + dy);
- }
- }
-};
-
-/**
- * Function: zoomToRect
- *
- * Zooms the graph to the specified rectangle. If the rectangle does not have same aspect
- * ratio as the display container, it is increased in the smaller relative dimension only
- * until the aspect match. The original rectangle is centralised within this expanded one.
- *
- * Note that the input rectangular must be un-scaled and un-translated.
- *
- * Parameters:
- *
- * rect - The un-scaled and un-translated rectangluar region that should be just visible
- * after the operation
- */
-mxGraph.prototype.zoomToRect = function(rect)
-{
- var scaleX = this.container.clientWidth / rect.width;
- var scaleY = this.container.clientHeight / rect.height;
- var aspectFactor = scaleX / scaleY;
-
- // Remove any overlap of the rect outside the client area
- rect.x = Math.max(0, rect.x);
- rect.y = Math.max(0, rect.y);
- var rectRight = Math.min(this.container.scrollWidth, rect.x + rect.width);
- var rectBottom = Math.min(this.container.scrollHeight, rect.y + rect.height);
- rect.width = rectRight - rect.x;
- rect.height = rectBottom - rect.y;
-
- // The selection area has to be increased to the same aspect
- // ratio as the container, centred around the centre point of the
- // original rect passed in.
- if (aspectFactor < 1.0)
- {
- // Height needs increasing
- var newHeight = rect.height / aspectFactor;
- var deltaHeightBuffer = (newHeight - rect.height) / 2.0;
- rect.height = newHeight;
-
- // Assign up to half the buffer to the upper part of the rect, not crossing 0
- // put the rest on the bottom
- var upperBuffer = Math.min(rect.y , deltaHeightBuffer);
- rect.y = rect.y - upperBuffer;
-
- // Check if the bottom has extended too far
- rectBottom = Math.min(this.container.scrollHeight, rect.y + rect.height);
- rect.height = rectBottom - rect.y;
- }
- else
- {
- // Width needs increasing
- var newWidth = rect.width * aspectFactor;
- var deltaWidthBuffer = (newWidth - rect.width) / 2.0;
- rect.width = newWidth;
-
- // Assign up to half the buffer to the upper part of the rect, not crossing 0
- // put the rest on the bottom
- var leftBuffer = Math.min(rect.x , deltaWidthBuffer);
- rect.x = rect.x - leftBuffer;
-
- // Check if the right hand side has extended too far
- rectRight = Math.min(this.container.scrollWidth, rect.x + rect.width);
- rect.width = rectRight - rect.x;
- }
-
- var scale = this.container.clientWidth / rect.width;
-
- if (!mxUtils.hasScrollbars(this.container))
- {
- this.view.scaleAndTranslate(scale, -rect.x, -rect.y);
- }
- else
- {
- this.view.setScale(scale);
- this.container.scrollLeft = Math.round(rect.x * scale);
- this.container.scrollTop = Math.round(rect.y * scale);
- }
-};
-
-/**
- * Function: fit
- *
- * Scales the graph such that the complete diagram fits into <container> and
- * returns the current scale in the view. To fit an initial graph prior to
- * rendering, set <mxGraphView.rendering> to false prior to changing the model
- * and execute the following after changing the model.
- *
- * (code)
- * graph.fit();
- * graph.view.rendering = true;
- * graph.refresh();
- * (end)
- *
- * Parameters:
- *
- * border - Optional number that specifies the border. Default is 0.
- * keepOrigin - Optional boolean that specifies if the translate should be
- * changed. Default is false.
- */
-mxGraph.prototype.fit = function(border, keepOrigin)
-{
- if (this.container != null)
- {
- border = (border != null) ? border : 0;
- keepOrigin = (keepOrigin != null) ? keepOrigin : false;
-
- var w1 = this.container.clientWidth;
- var h1 = this.container.clientHeight;
-
- var bounds = this.view.getGraphBounds();
-
- if (keepOrigin && bounds.x != null && bounds.y != null)
- {
- bounds.width += bounds.x;
- bounds.height += bounds.y;
- bounds.x = 0;
- bounds.y = 0;
- }
-
- var s = this.view.scale;
- var w2 = bounds.width / s;
- var h2 = bounds.height / s;
-
- // Fits to the size of the background image if required
- if (this.backgroundImage != null)
- {
- w2 = Math.max(w2, this.backgroundImage.width - bounds.x / s);
- h2 = Math.max(h2, this.backgroundImage.height - bounds.y / s);
- }
-
- var b = (keepOrigin) ? border : 2 * border;
- var s2 = Math.floor(Math.min(w1 / (w2 + b), h1 / (h2 + b)) * 100) / 100;
-
- if (this.minFitScale != null)
- {
- s2 = Math.max(s2, this.minFitScale);
- }
-
- if (this.maxFitScale != null)
- {
- s2 = Math.min(s2, this.maxFitScale);
- }
-
- if (!keepOrigin)
- {
- if (!mxUtils.hasScrollbars(this.container))
- {
- var x0 = (bounds.x != null) ? Math.floor(this.view.translate.x - bounds.x / s + border + 1) : border;
- var y0 = (bounds.y != null) ? Math.floor(this.view.translate.y - bounds.y / s + border + 1) : border;
-
- this.view.scaleAndTranslate(s2, x0, y0);
- }
- else
- {
- this.view.setScale(s2);
-
- if (bounds.x != null)
- {
- this.container.scrollLeft = Math.round(bounds.x / s) * s2 - border -
- Math.max(0, (this.container.clientWidth - w2 * s2) / 2);
- }
-
- if (bounds.y != null)
- {
- this.container.scrollTop = Math.round(bounds.y / s) * s2 - border -
- Math.max(0, (this.container.clientHeight - h2 * s2) / 2);
- }
- }
- }
- else if (this.view.scale != s2)
- {
- this.view.setScale(s2);
- }
- }
-
- return this.view.scale;
-};
-
-/**
- * Function: scrollCellToVisible
- *
- * Pans the graph so that it shows the given cell. Optionally the cell may
- * be centered in the container.
- *
- * To center a given graph if the <container> has no scrollbars, use the following code.
- *
- * [code]
- * var bounds = graph.getGraphBounds();
- * graph.view.setTranslate(-bounds.x - (bounds.width - container.clientWidth) / 2,
- * -bounds.y - (bounds.height - container.clientHeight) / 2);
- * [/code]
- *
- * Parameters:
- *
- * cell - <mxCell> to be made visible.
- * center - Optional boolean flag. Default is false.
- */
-mxGraph.prototype.scrollCellToVisible = function(cell, center)
-{
- var x = -this.view.translate.x;
- var y = -this.view.translate.y;
-
- var state = this.view.getState(cell);
-
- if (state != null)
- {
- var bounds = new mxRectangle(x + state.x, y + state.y, state.width,
- state.height);
-
- if (center && this.container != null)
- {
- var w = this.container.clientWidth;
- var h = this.container.clientHeight;
-
- bounds.x = bounds.getCenterX() - w / 2;
- bounds.width = w;
- bounds.y = bounds.getCenterY() - h / 2;
- bounds.height = h;
- }
-
- if (this.scrollRectToVisible(bounds))
- {
- // Triggers an update via the view's event source
- this.view.setTranslate(this.view.translate.x, this.view.translate.y);
- }
- }
-};
-
-/**
- * Function: scrollRectToVisible
- *
- * Pans the graph so that it shows the given rectangle.
- *
- * Parameters:
- *
- * rect - <mxRectangle> to be made visible.
- */
-mxGraph.prototype.scrollRectToVisible = function(rect)
-{
- var isChanged = false;
-
- if (rect != null)
- {
- var w = this.container.offsetWidth;
- var h = this.container.offsetHeight;
-
- var widthLimit = Math.min(w, rect.width);
- var heightLimit = Math.min(h, rect.height);
-
- if (mxUtils.hasScrollbars(this.container))
- {
- var c = this.container;
- rect.x += this.view.translate.x;
- rect.y += this.view.translate.y;
- var dx = c.scrollLeft - rect.x;
- var ddx = Math.max(dx - c.scrollLeft, 0);
-
- if (dx > 0)
- {
- c.scrollLeft -= dx + 2;
- }
- else
- {
- dx = rect.x + widthLimit - c.scrollLeft - c.clientWidth;
-
- if (dx > 0)
- {
- c.scrollLeft += dx + 2;
- }
- }
-
- var dy = c.scrollTop - rect.y;
- var ddy = Math.max(0, dy - c.scrollTop);
-
- if (dy > 0)
- {
- c.scrollTop -= dy + 2;
- }
- else
- {
- dy = rect.y + heightLimit - c.scrollTop - c.clientHeight;
-
- if (dy > 0)
- {
- c.scrollTop += dy + 2;
- }
- }
-
- if (!this.useScrollbarsForPanning && (ddx != 0 || ddy != 0))
- {
- this.view.setTranslate(ddx, ddy);
- }
- }
- else
- {
- var x = -this.view.translate.x;
- var y = -this.view.translate.y;
-
- var s = this.view.scale;
-
- if (rect.x + widthLimit > x + w)
- {
- this.view.translate.x -= (rect.x + widthLimit - w - x) / s;
- isChanged = true;
- }
-
- if (rect.y + heightLimit > y + h)
- {
- this.view.translate.y -= (rect.y + heightLimit - h - y) / s;
- isChanged = true;
- }
-
- if (rect.x < x)
- {
- this.view.translate.x += (x - rect.x) / s;
- isChanged = true;
- }
-
- if (rect.y < y)
- {
- this.view.translate.y += (y - rect.y) / s;
- isChanged = true;
- }
-
- if (isChanged)
- {
- this.view.refresh();
-
- // Repaints selection marker (ticket 18)
- if (this.selectionCellsHandler != null)
- {
- this.selectionCellsHandler.refresh();
- }
- }
- }
- }
-
- return isChanged;
-};
-
-/**
- * Function: getCellGeometry
- *
- * Returns the <mxGeometry> for the given cell. This implementation uses
- * <mxGraphModel.getGeometry>. Subclasses can override this to implement
- * specific geometries for cells in only one graph, that is, it can return
- * geometries that depend on the current state of the view.
- *
- * Parameters:
- *
- * cell - <mxCell> whose geometry should be returned.
- */
-mxGraph.prototype.getCellGeometry = function(cell)
-{
- return this.model.getGeometry(cell);
-};
-
-/**
- * Function: isCellVisible
- *
- * Returns true if the given cell is visible in this graph. This
- * implementation uses <mxGraphModel.isVisible>. Subclassers can override
- * this to implement specific visibility for cells in only one graph, that
- * is, without affecting the visible state of the cell.
- *
- * When using dynamic filter expressions for cell visibility, then the
- * graph should be revalidated after the filter expression has changed.
- *
- * Parameters:
- *
- * cell - <mxCell> whose visible state should be returned.
- */
-mxGraph.prototype.isCellVisible = function(cell)
-{
- return this.model.isVisible(cell);
-};
-
-/**
- * Function: isCellCollapsed
- *
- * Returns true if the given cell is collapsed in this graph. This
- * implementation uses <mxGraphModel.isCollapsed>. Subclassers can override
- * this to implement specific collapsed states for cells in only one graph,
- * that is, without affecting the collapsed state of the cell.
- *
- * When using dynamic filter expressions for the collapsed state, then the
- * graph should be revalidated after the filter expression has changed.
- *
- * Parameters:
- *
- * cell - <mxCell> whose collapsed state should be returned.
- */
-mxGraph.prototype.isCellCollapsed = function(cell)
-{
- return this.model.isCollapsed(cell);
-};
-
-/**
- * Function: isCellConnectable
- *
- * Returns true if the given cell is connectable in this graph. This
- * implementation uses <mxGraphModel.isConnectable>. Subclassers can override
- * this to implement specific connectable states for cells in only one graph,
- * that is, without affecting the connectable state of the cell in the model.
- *
- * Parameters:
- *
- * cell - <mxCell> whose connectable state should be returned.
- */
-mxGraph.prototype.isCellConnectable = function(cell)
-{
- return this.model.isConnectable(cell);
-};
-
-/**
- * Function: isOrthogonal
- *
- * Returns true if perimeter points should be computed such that the
- * resulting edge has only horizontal or vertical segments.
- *
- * Parameters:
- *
- * edge - <mxCellState> that represents the edge.
- */
-mxGraph.prototype.isOrthogonal = function(edge)
-{
- var orthogonal = edge.style[mxConstants.STYLE_ORTHOGONAL];
-
- if (orthogonal != null)
- {
- return orthogonal;
- }
-
- var tmp = this.view.getEdgeStyle(edge);
-
- return tmp == mxEdgeStyle.SegmentConnector ||
- tmp == mxEdgeStyle.ElbowConnector ||
- tmp == mxEdgeStyle.SideToSide ||
- tmp == mxEdgeStyle.TopToBottom ||
- tmp == mxEdgeStyle.EntityRelation ||
- tmp == mxEdgeStyle.OrthConnector;
-};
-
-/**
- * Function: isLoop
- *
- * Returns true if the given cell state is a loop.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents a potential loop.
- */
-mxGraph.prototype.isLoop = function(state)
-{
- var src = state.getVisibleTerminalState(true);
- var trg = state.getVisibleTerminalState(false);
-
- return (src != null && src == trg);
-};
-
-/**
- * Function: isCloneEvent
- *
- * Returns true if the given event is a clone event. This implementation
- * returns true if control is pressed.
- */
-mxGraph.prototype.isCloneEvent = function(evt)
-{
- return mxEvent.isControlDown(evt);
-};
-
-/**
- * Function: isToggleEvent
- *
- * Returns true if the given event is a toggle event. This implementation
- * returns true if the meta key (Cmd) is pressed on Macs or if control is
- * pressed on any other platform.
- */
-mxGraph.prototype.isToggleEvent = function(evt)
-{
- return (mxClient.IS_MAC) ? mxEvent.isMetaDown(evt) : mxEvent.isControlDown(evt);
-};
-
-/**
- * Function: isGridEnabledEvent
- *
- * Returns true if the given mouse event should be aligned to the grid.
- */
-mxGraph.prototype.isGridEnabledEvent = function(evt)
-{
- return evt != null && !mxEvent.isAltDown(evt);
-};
-
-/**
- * Function: isConstrainedEvent
- *
- * Returns true if the given mouse event should be aligned to the grid.
- */
-mxGraph.prototype.isConstrainedEvent = function(evt)
-{
- return mxEvent.isShiftDown(evt);
-};
-
-/**
- * Function: isForceMarqueeEvent
- *
- * Returns true if the given event forces marquee selection. This implementation
- * returns true if alt is pressed.
- */
-mxGraph.prototype.isForceMarqueeEvent = function(evt)
-{
- return mxEvent.isAltDown(evt);
-};
-
-/**
- * Group: Validation
- */
-
-/**
- * Function: validationAlert
- *
- * Displays the given validation error in a dialog. This implementation uses
- * mxUtils.alert.
- */
-mxGraph.prototype.validationAlert = function(message)
-{
- mxUtils.alert(message);
-};
-
-/**
- * Function: isEdgeValid
- *
- * Checks if the return value of <getEdgeValidationError> for the given
- * arguments is null.
- *
- * Parameters:
- *
- * edge - <mxCell> that represents the edge to validate.
- * source - <mxCell> that represents the source terminal.
- * target - <mxCell> that represents the target terminal.
- */
-mxGraph.prototype.isEdgeValid = function(edge, source, target)
-{
- return this.getEdgeValidationError(edge, source, target) == null;
-};
-
-/**
- * Function: getEdgeValidationError
- *
- * Returns the validation error message to be displayed when inserting or
- * changing an edges' connectivity. A return value of null means the edge
- * is valid, a return value of '' means it's not valid, but do not display
- * an error message. Any other (non-empty) string returned from this method
- * is displayed as an error message when trying to connect an edge to a
- * source and target. This implementation uses the <multiplicities>, and
- * checks <multigraph>, <allowDanglingEdges> and <allowLoops> to generate
- * validation errors.
- *
- * For extending this method with specific checks for source/target cells,
- * the method can be extended as follows. Returning an empty string means
- * the edge is invalid with no error message, a non-null string specifies
- * the error message, and null means the edge is valid.
- *
- * (code)
- * graph.getEdgeValidationError = function(edge, source, target)
- * {
- * if (source != null && target != null &&
- * this.model.getValue(source) != null &&
- * this.model.getValue(target) != null)
- * {
- * if (target is not valid for source)
- * {
- * return 'Invalid Target';
- * }
- * }
- *
- * // "Supercall"
- * return mxGraph.prototype.getEdgeValidationError.apply(this, arguments);
- * }
- * (end)
- *
- * Parameters:
- *
- * edge - <mxCell> that represents the edge to validate.
- * source - <mxCell> that represents the source terminal.
- * target - <mxCell> that represents the target terminal.
- */
-mxGraph.prototype.getEdgeValidationError = function(edge, source, target)
-{
- if (edge != null && !this.isAllowDanglingEdges() && (source == null || target == null))
- {
- return '';
- }
-
- if (edge != null && this.model.getTerminal(edge, true) == null &&
- this.model.getTerminal(edge, false) == null)
- {
- return null;
- }
-
- // Checks if we're dealing with a loop
- if (!this.allowLoops && source == target && source != null)
- {
- return '';
- }
-
- // Checks if the connection is generally allowed
- if (!this.isValidConnection(source, target))
- {
- return '';
- }
-
- if (source != null && target != null)
- {
- var error = '';
-
- // Checks if the cells are already connected
- // and adds an error message if required
- if (!this.multigraph)
- {
- var tmp = this.model.getEdgesBetween(source, target, true);
-
- // Checks if the source and target are not connected by another edge
- if (tmp.length > 1 || (tmp.length == 1 && tmp[0] != edge))
- {
- error += (mxResources.get(this.alreadyConnectedResource) ||
- this.alreadyConnectedResource)+'\n';
- }
- }
-
- // Gets the number of outgoing edges from the source
- // and the number of incoming edges from the target
- // without counting the edge being currently changed.
- var sourceOut = this.model.getDirectedEdgeCount(source, true, edge);
- var targetIn = this.model.getDirectedEdgeCount(target, false, edge);
-
- // Checks the change against each multiplicity rule
- if (this.multiplicities != null)
- {
- for (var i = 0; i < this.multiplicities.length; i++)
- {
- var err = this.multiplicities[i].check(this, edge, source,
- target, sourceOut, targetIn);
-
- if (err != null)
- {
- error += err;
- }
- }
- }
-
- // Validates the source and target terminals independently
- var err = this.validateEdge(edge, source, target);
-
- if (err != null)
- {
- error += err;
- }
-
- return (error.length > 0) ? error : null;
- }
-
- return (this.allowDanglingEdges) ? null : '';
-};
-
-/**
- * Function: validateEdge
- *
- * Hook method for subclassers to return an error message for the given
- * edge and terminals. This implementation returns null.
- *
- * Parameters:
- *
- * edge - <mxCell> that represents the edge to validate.
- * source - <mxCell> that represents the source terminal.
- * target - <mxCell> that represents the target terminal.
- */
-mxGraph.prototype.validateEdge = function(edge, source, target)
-{
- return null;
-};
-
-/**
- * Function: validateGraph
- *
- * Validates the graph by validating each descendant of the given cell or
- * the root of the model. Context is an object that contains the validation
- * state for the complete validation run. The validation errors are
- * attached to their cells using <setCellWarning>. This function returns true
- * if no validation errors exist in the graph.
- *
- * Paramters:
- *
- * cell - Optional <mxCell> to start the validation recursion. Default is
- * the graph root.
- * context - Object that represents the global validation state.
- */
-mxGraph.prototype.validateGraph = function(cell, context)
-{
- cell = (cell != null) ? cell : this.model.getRoot();
- context = (context != null) ? context : new Object();
-
- var isValid = true;
- var childCount = this.model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var tmp = this.model.getChildAt(cell, i);
- var ctx = context;
-
- if (this.isValidRoot(tmp))
- {
- ctx = new Object();
- }
-
- var warn = this.validateGraph(tmp, ctx);
-
- if (warn != null)
- {
- this.setCellWarning(tmp, warn.replace(/\n/g, '<br>'));
- }
- else
- {
- this.setCellWarning(tmp, null);
- }
-
- isValid = isValid && warn == null;
- }
-
- var warning = '';
-
- // Adds error for invalid children if collapsed (children invisible)
- if (this.isCellCollapsed(cell) && !isValid)
- {
- warning += (mxResources.get(this.containsValidationErrorsResource) ||
- this.containsValidationErrorsResource)+'\n';
- }
-
- // Checks edges and cells using the defined multiplicities
- if (this.model.isEdge(cell))
- {
- warning += this.getEdgeValidationError(cell,
- this.model.getTerminal(cell, true),
- this.model.getTerminal(cell, false)) || '';
- }
- else
- {
- warning += this.getCellValidationError(cell) || '';
- }
-
- // Checks custom validation rules
- var err = this.validateCell(cell, context);
-
- if (err != null)
- {
- warning += err;
- }
-
- // Updates the display with the warning icons
- // before any potential alerts are displayed.
- // LATER: Move this into addCellOverlay. Redraw
- // should check if overlay was added or removed.
- if (this.model.getParent(cell) == null)
- {
- this.view.validate();
- }
-
- return (warning.length > 0 || !isValid) ? warning : null;
-};
-
-/**
- * Function: getCellValidationError
- *
- * Checks all <multiplicities> that cannot be enforced while the graph is
- * being modified, namely, all multiplicities that require a minimum of
- * 1 edge.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the multiplicities should be checked.
- */
-mxGraph.prototype.getCellValidationError = function(cell)
-{
- var outCount = this.model.getDirectedEdgeCount(cell, true);
- var inCount = this.model.getDirectedEdgeCount(cell, false);
- var value = this.model.getValue(cell);
- var error = '';
-
- if (this.multiplicities != null)
- {
- for (var i = 0; i < this.multiplicities.length; i++)
- {
- var rule = this.multiplicities[i];
-
- if (rule.source && mxUtils.isNode(value, rule.type,
- rule.attr, rule.value) && ((rule.max == 0 && outCount > 0) ||
- (rule.min == 1 && outCount == 0) || (rule.max == 1 && outCount > 1)))
- {
- error += rule.countError + '\n';
- }
- else if (!rule.source && mxUtils.isNode(value, rule.type,
- rule.attr, rule.value) && ((rule.max == 0 && inCount > 0) ||
- (rule.min == 1 && inCount == 0) || (rule.max == 1 && inCount > 1)))
- {
- error += rule.countError + '\n';
- }
- }
- }
-
- return (error.length > 0) ? error : null;
-};
-
-/**
- * Function: validateCell
- *
- * Hook method for subclassers to return an error message for the given
- * cell and validation context. This implementation returns null. Any HTML
- * breaks will be converted to linefeeds in the calling method.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the cell to validate.
- * context - Object that represents the global validation state.
- */
-mxGraph.prototype.validateCell = function(cell, context)
-{
- return null;
-};
-
-/**
- * Group: Graph appearance
- */
-
-/**
- * Function: getBackgroundImage
- *
- * Returns the <backgroundImage> as an <mxImage>.
- */
-mxGraph.prototype.getBackgroundImage = function()
-{
- return this.backgroundImage;
-};
-
-/**
- * Function: setBackgroundImage
- *
- * Sets the new <backgroundImage>.
- *
- * Parameters:
- *
- * image - New <mxImage> to be used for the background.
- */
-mxGraph.prototype.setBackgroundImage = function(image)
-{
- this.backgroundImage = image;
-};
-
-/**
- * Function: getFoldingImage
- *
- * Returns the <mxImage> used to display the collapsed state of
- * the specified cell state. This returns null for all edges.
- */
-mxGraph.prototype.getFoldingImage = function(state)
-{
- if (state != null && this.foldingEnabled && !this.getModel().isEdge(state.cell))
- {
- var tmp = this.isCellCollapsed(state.cell);
-
- if (this.isCellFoldable(state.cell, !tmp))
- {
- return (tmp) ? this.collapsedImage : this.expandedImage;
- }
- }
-
- return null;
-};
-
-/**
- * Function: convertValueToString
- *
- * Returns the textual representation for the given cell. This
- * implementation returns the nodename or string-representation of the user
- * object.
- *
- * Example:
- *
- * The following returns the label attribute from the cells user
- * object if it is an XML node.
- *
- * (code)
- * graph.convertValueToString = function(cell)
- * {
- * return cell.getAttribute('label');
- * }
- * (end)
- *
- * See also: <cellLabelChanged>.
- *
- * Parameters:
- *
- * cell - <mxCell> whose textual representation should be returned.
- */
-mxGraph.prototype.convertValueToString = function(cell)
-{
- var value = this.model.getValue(cell);
-
- if (value != null)
- {
- if (mxUtils.isNode(value))
- {
- return value.nodeName;
- }
- else if (typeof(value.toString) == 'function')
- {
- return value.toString();
- }
- }
-
- return '';
-};
-
-/**
- * Function: getLabel
- *
- * Returns a string or DOM node that represents the label for the given
- * cell. This implementation uses <convertValueToString> if <labelsVisible>
- * is true. Otherwise it returns an empty string.
- *
- * To truncate label to match the size of the cell, the following code
- * can be used.
- *
- * (code)
- * graph.getLabel = function(cell)
- * {
- * var label = mxGraph.prototype.getLabel.apply(this, arguments);
- *
- * if (label != null && this.model.isVertex(cell))
- * {
- * var geo = this.getCellGeometry(cell);
- *
- * if (geo != null)
- * {
- * var max = parseInt(geo.width / 8);
- *
- * if (label.length > max)
- * {
- * label = label.substring(0, max)+'...';
- * }
- * }
- * }
- * return mxUtils.htmlEntities(label);
- * }
- * (end)
- *
- * A resize listener is needed in the graph to force a repaint of the label
- * after a resize.
- *
- * (code)
- * graph.addListener(mxEvent.RESIZE_CELLS, function(sender, evt)
- * {
- * var cells = evt.getProperty('cells');
- *
- * for (var i = 0; i < cells.length; i++)
- * {
- * this.view.removeState(cells[i]);
- * }
- * });
- * (end)
- *
- * Parameters:
- *
- * cell - <mxCell> whose label should be returned.
- */
-mxGraph.prototype.getLabel = function(cell)
-{
- var result = '';
-
- if (this.labelsVisible && cell != null)
- {
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- if (!mxUtils.getValue(style, mxConstants.STYLE_NOLABEL, false))
- {
- result = this.convertValueToString(cell);
- }
- }
-
- return result;
-};
-
-/**
- * Function: isHtmlLabel
- *
- * Returns true if the label must be rendered as HTML markup. The default
- * implementation returns <htmlLabels>.
- *
- * Parameters:
- *
- * cell - <mxCell> whose label should be displayed as HTML markup.
- */
-mxGraph.prototype.isHtmlLabel = function(cell)
-{
- return this.isHtmlLabels();
-};
-
-/**
- * Function: isHtmlLabels
- *
- * Returns <htmlLabels>.
- */
-mxGraph.prototype.isHtmlLabels = function()
-{
- return this.htmlLabels;
-};
-
-/**
- * Function: setHtmlLabels
- *
- * Sets <htmlLabels>.
- */
-mxGraph.prototype.setHtmlLabels = function(value)
-{
- this.htmlLabels = value;
-};
-
-/**
- * Function: isWrapping
- *
- * This enables wrapping for HTML labels.
- *
- * Returns true if no white-space CSS style directive should be used for
- * displaying the given cells label. This implementation returns true if
- * <mxConstants.STYLE_WHITE_SPACE> in the style of the given cell is 'wrap'.
- *
- * This is used as a workaround for IE ignoring the white-space directive
- * of child elements if the directive appears in a parent element. It
- * should be overridden to return true if a white-space directive is used
- * in the HTML markup that represents the given cells label. In order for
- * HTML markup to work in labels, <isHtmlLabel> must also return true
- * for the given cell.
- *
- * Example:
- *
- * (code)
- * graph.getLabel = function(cell)
- * {
- * var tmp = mxGraph.prototype.getLabel.apply(this, arguments); // "supercall"
- *
- * if (this.model.isEdge(cell))
- * {
- * tmp = '<div style="width: 150px; white-space:normal;">'+tmp+'</div>';
- * }
- *
- * return tmp;
- * }
- *
- * graph.isWrapping = function(state)
- * {
- * return this.model.isEdge(state.cell);
- * }
- * (end)
- *
- * Makes sure no edge label is wider than 150 pixels, otherwise the content
- * is wrapped. Note: No width must be specified for wrapped vertex labels as
- * the vertex defines the width in its geometry.
- *
- * Parameters:
- *
- * state - <mxCell> whose label should be wrapped.
- */
-mxGraph.prototype.isWrapping = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return (style != null) ? style[mxConstants.STYLE_WHITE_SPACE] == 'wrap' : false;
-};
-
-/**
- * Function: isLabelClipped
- *
- * Returns true if the overflow portion of labels should be hidden. If this
- * returns true then vertex labels will be clipped to the size of the vertices.
- * This implementation returns true if <mxConstants.STYLE_OVERFLOW> in the
- * style of the given cell is 'hidden'.
- *
- * Parameters:
- *
- * state - <mxCell> whose label should be clipped.
- */
-mxGraph.prototype.isLabelClipped = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return (style != null) ? style[mxConstants.STYLE_OVERFLOW] == 'hidden' : false;
-};
-
-/**
- * Function: getTooltip
- *
- * Returns the string or DOM node that represents the tooltip for the given
- * state, node and coordinate pair. This implementation checks if the given
- * node is a folding icon or overlay and returns the respective tooltip. If
- * this does not result in a tooltip, the handler for the cell is retrieved
- * from <selectionCellsHandler> and the optional getTooltipForNode method is
- * called. If no special tooltip exists here then <getTooltipForCell> is used
- * with the cell in the given state as the argument to return a tooltip for the
- * given state.
- *
- * Parameters:
- *
- * state - <mxCellState> whose tooltip should be returned.
- * node - DOM node that is currently under the mouse.
- * x - X-coordinate of the mouse.
- * y - Y-coordinate of the mouse.
- */
-mxGraph.prototype.getTooltip = function(state, node, x, y)
-{
- var tip = null;
-
- if (state != null)
- {
- // Checks if the mouse is over the folding icon
- if (state.control != null && (node == state.control.node ||
- node.parentNode == state.control.node))
- {
- tip = this.collapseExpandResource;
- tip = mxResources.get(tip) || tip;
- }
-
- if (tip == null && state.overlays != null)
- {
- state.overlays.visit(function(id, shape)
- {
- // LATER: Exit loop if tip is not null
- if (tip == null && (node == shape.node || node.parentNode == shape.node))
- {
- tip = shape.overlay.toString();
- }
- });
- }
-
- if (tip == null)
- {
- var handler = this.selectionCellsHandler.getHandler(state.cell);
-
- if (handler != null && typeof(handler.getTooltipForNode) == 'function')
- {
- tip = handler.getTooltipForNode(node);
- }
- }
-
- if (tip == null)
- {
- tip = this.getTooltipForCell(state.cell);
- }
- }
-
- return tip;
-};
-
-/**
- * Function: getTooltipForCell
- *
- * Returns the string or DOM node to be used as the tooltip for the given
- * cell. This implementation uses the cells getTooltip function if it
- * exists, or else it returns <convertValueToString> for the cell.
- *
- * Example:
- *
- * (code)
- * graph.getTooltipForCell = function(cell)
- * {
- * return 'Hello, World!';
- * }
- * (end)
- *
- * Replaces all tooltips with the string Hello, World!
- *
- * Parameters:
- *
- * cell - <mxCell> whose tooltip should be returned.
- */
-mxGraph.prototype.getTooltipForCell = function(cell)
-{
- var tip = null;
-
- if (cell != null && cell.getTooltip != null)
- {
- tip = cell.getTooltip();
- }
- else
- {
- tip = this.convertValueToString(cell);
- }
-
- return tip;
-};
-
-/**
- * Function: getCursorForCell
- *
- * Returns the cursor value to be used for the CSS of the shape for the
- * given cell. This implementation returns null.
- *
- * Parameters:
- *
- * cell - <mxCell> whose cursor should be returned.
- */
-mxGraph.prototype.getCursorForCell = function(cell)
-{
- return null;
-};
-
-/**
- * Function: getStartSize
- *
- * Returns the start size of the given swimlane, that is, the width or
- * height of the part that contains the title, depending on the
- * horizontal style. The return value is an <mxRectangle> with either
- * width or height set as appropriate.
- *
- * Parameters:
- *
- * swimlane - <mxCell> whose start size should be returned.
- */
-mxGraph.prototype.getStartSize = function(swimlane)
-{
- var result = new mxRectangle();
- var state = this.view.getState(swimlane);
- var style = (state != null) ? state.style : this.getCellStyle(swimlane);
-
- if (style != null)
- {
- var size = parseInt(mxUtils.getValue(style,
- mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE));
-
- if (mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, true))
- {
- result.height = size;
- }
- else
- {
- result.width = size;
- }
- }
-
- return result;
-};
-
-/**
- * Function: getImage
- *
- * Returns the image URL for the given cell state. This implementation
- * returns the value stored under <mxConstants.STYLE_IMAGE> in the cell
- * style.
- *
- * Parameters:
- *
- * state - <mxCellState> whose image URL should be returned.
- */
-mxGraph.prototype.getImage = function(state)
-{
- return (state != null && state.style != null) ?
- state.style[mxConstants.STYLE_IMAGE] : null;
-};
-
-/**
- * Function: getVerticalAlign
- *
- * Returns the vertical alignment for the given cell state. This
- * implementation returns the value stored under
- * <mxConstants.STYLE_VERTICAL_ALIGN> in the cell style.
- *
- * Parameters:
- *
- * state - <mxCellState> whose vertical alignment should be
- * returned.
- */
-mxGraph.prototype.getVerticalAlign = function(state)
-{
- return (state != null && state.style != null) ?
- (state.style[mxConstants.STYLE_VERTICAL_ALIGN] ||
- mxConstants.ALIGN_MIDDLE ):
- null;
-};
-
-/**
- * Function: getIndicatorColor
- *
- * Returns the indicator color for the given cell state. This
- * implementation returns the value stored under
- * <mxConstants.STYLE_INDICATOR_COLOR> in the cell style.
- *
- * Parameters:
- *
- * state - <mxCellState> whose indicator color should be
- * returned.
- */
-mxGraph.prototype.getIndicatorColor = function(state)
-{
- return (state != null && state.style != null) ?
- state.style[mxConstants.STYLE_INDICATOR_COLOR] : null;
-};
-
-/**
- * Function: getIndicatorGradientColor
- *
- * Returns the indicator gradient color for the given cell state. This
- * implementation returns the value stored under
- * <mxConstants.STYLE_INDICATOR_GRADIENTCOLOR> in the cell style.
- *
- * Parameters:
- *
- * state - <mxCellState> whose indicator gradient color should be
- * returned.
- */
-mxGraph.prototype.getIndicatorGradientColor = function(state)
-{
- return (state != null && state.style != null) ?
- state.style[mxConstants.STYLE_INDICATOR_GRADIENTCOLOR] : null;
-};
-
-/**
- * Function: getIndicatorShape
- *
- * Returns the indicator shape for the given cell state. This
- * implementation returns the value stored under
- * <mxConstants.STYLE_INDICATOR_SHAPE> in the cell style.
- *
- * Parameters:
- *
- * state - <mxCellState> whose indicator shape should be returned.
- */
-mxGraph.prototype.getIndicatorShape = function(state)
-{
- return (state != null && state.style != null) ?
- state.style[mxConstants.STYLE_INDICATOR_SHAPE] : null;
-};
-
-/**
- * Function: getIndicatorImage
- *
- * Returns the indicator image for the given cell state. This
- * implementation returns the value stored under
- * <mxConstants.STYLE_INDICATOR_IMAGE> in the cell style.
- *
- * Parameters:
- *
- * state - <mxCellState> whose indicator image should be returned.
- */
-mxGraph.prototype.getIndicatorImage = function(state)
-{
- return (state != null && state.style != null) ?
- state.style[mxConstants.STYLE_INDICATOR_IMAGE] : null;
-};
-
-/**
- * Function: getBorder
- *
- * Returns the value of <border>.
- */
-mxGraph.prototype.getBorder = function()
-{
- return this.border;
-};
-
-/**
- * Function: setBorder
- *
- * Sets the value of <border>.
- *
- * Parameters:
- *
- * value - Positive integer that represents the border to be used.
- */
-mxGraph.prototype.setBorder = function(value)
-{
- this.border = value;
-};
-
-/**
- * Function: isSwimlane
- *
- * Returns true if the given cell is a swimlane in the graph. A swimlane is
- * a container cell with some specific behaviour. This implementation
- * checks if the shape associated with the given cell is a <mxSwimlane>.
- *
- * Parameters:
- *
- * cell - <mxCell> to be checked.
- */
-mxGraph.prototype.isSwimlane = function (cell)
-{
- if (cell != null)
- {
- if (this.model.getParent(cell) != this.model.getRoot())
- {
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- if (style != null && !this.model.isEdge(cell))
- {
- return style[mxConstants.STYLE_SHAPE] ==
- mxConstants.SHAPE_SWIMLANE;
- }
- }
- }
-
- return false;
-};
-
-/**
- * Group: Graph behaviour
- */
-
-/**
- * Function: isResizeContainer
- *
- * Returns <resizeContainer>.
- */
-mxGraph.prototype.isResizeContainer = function()
-{
- return this.resizeContainer;
-};
-
-/**
- * Function: setResizeContainer
- *
- * Sets <resizeContainer>.
- *
- * Parameters:
- *
- * value - Boolean indicating if the container should be resized.
- */
-mxGraph.prototype.setResizeContainer = function(value)
-{
- this.resizeContainer = value;
-};
-
-/**
- * Function: isEnabled
- *
- * Returns true if the graph is <enabled>.
- */
-mxGraph.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Specifies if the graph should allow any interactions. This
- * implementation updates <enabled>.
- *
- * Parameters:
- *
- * value - Boolean indicating if the graph should be enabled.
- */
-mxGraph.prototype.setEnabled = function(value)
-{
- this.enabled = value;
-};
-
-/**
- * Function: isEscapeEnabled
- *
- * Returns <escapeEnabled>.
- */
-mxGraph.prototype.isEscapeEnabled = function()
-{
- return this.escapeEnabled;
-};
-
-/**
- * Function: setEscapeEnabled
- *
- * Sets <escapeEnabled>.
- *
- * Parameters:
- *
- * enabled - Boolean indicating if escape should be enabled.
- */
-mxGraph.prototype.setEscapeEnabled = function(value)
-{
- this.escapeEnabled = value;
-};
-
-/**
- * Function: isInvokesStopCellEditing
- *
- * Returns <invokesStopCellEditing>.
- */
-mxGraph.prototype.isInvokesStopCellEditing = function()
-{
- return this.invokesStopCellEditing;
-};
-
-/**
- * Function: setInvokesStopCellEditing
- *
- * Sets <invokesStopCellEditing>.
- */
-mxGraph.prototype.setInvokesStopCellEditing = function(value)
-{
- this.invokesStopCellEditing = value;
-};
-
-/**
- * Function: isEnterStopsCellEditing
- *
- * Returns <enterStopsCellEditing>.
- */
-mxGraph.prototype.isEnterStopsCellEditing = function()
-{
- return this.enterStopsCellEditing;
-};
-
-/**
- * Function: setEnterStopsCellEditing
- *
- * Sets <enterStopsCellEditing>.
- */
-mxGraph.prototype.setEnterStopsCellEditing = function(value)
-{
- this.enterStopsCellEditing = value;
-};
-
-/**
- * Function: isCellLocked
- *
- * Returns true if the given cell may not be moved, sized, bended,
- * disconnected, edited or selected. This implementation returns true for
- * all vertices with a relative geometry if <locked> is false.
- *
- * Parameters:
- *
- * cell - <mxCell> whose locked state should be returned.
- */
-mxGraph.prototype.isCellLocked = function(cell)
-{
- var geometry = this.model.getGeometry(cell);
-
- return this.isCellsLocked() || (geometry != null &&
- this.model.isVertex(cell) && geometry.relative);
-};
-
-/**
- * Function: isCellsLocked
- *
- * Returns true if the given cell may not be moved, sized, bended,
- * disconnected, edited or selected. This implementation returns true for
- * all vertices with a relative geometry if <locked> is false.
- *
- * Parameters:
- *
- * cell - <mxCell> whose locked state should be returned.
- */
-mxGraph.prototype.isCellsLocked = function()
-{
- return this.cellsLocked;
-};
-
-/**
- * Function: setLocked
- *
- * Sets if any cell may be moved, sized, bended, disconnected, edited or
- * selected.
- *
- * Parameters:
- *
- * value - Boolean that defines the new value for <cellsLocked>.
- */
-mxGraph.prototype.setCellsLocked = function(value)
-{
- this.cellsLocked = value;
-};
-
-/**
- * Function: getCloneableCells
- *
- * Returns the cells which may be exported in the given array of cells.
- */
-mxGraph.prototype.getCloneableCells = function(cells)
-{
- return this.model.filterCells(cells, mxUtils.bind(this, function(cell)
- {
- return this.isCellCloneable(cell);
- }));
-};
-
-/**
- * Function: isCellCloneable
- *
- * Returns true if the given cell is cloneable. This implementation returns
- * <isCellsCloneable> for all cells unless a cell style specifies
- * <mxConstants.STYLE_CLONEABLE> to be 0.
- *
- * Parameters:
- *
- * cell - Optional <mxCell> whose cloneable state should be returned.
- */
-mxGraph.prototype.isCellCloneable = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return this.isCellsCloneable() && style[mxConstants.STYLE_CLONEABLE] != 0;
-};
-
-/**
- * Function: isCellsCloneable
- *
- * Returns <cellsCloneable>, that is, if the graph allows cloning of cells
- * by using control-drag.
- */
-mxGraph.prototype.isCellsCloneable = function()
-{
- return this.cellsCloneable;
-};
-
-/**
- * Function: setCellsCloneable
- *
- * Specifies if the graph should allow cloning of cells by holding down the
- * control key while cells are being moved. This implementation updates
- * <cellsCloneable>.
- *
- * Parameters:
- *
- * value - Boolean indicating if the graph should be cloneable.
- */
-mxGraph.prototype.setCellsCloneable = function(value)
-{
- this.cellsCloneable = value;
-};
-
-/**
- * Function: getExportableCells
- *
- * Returns the cells which may be exported in the given array of cells.
- */
-mxGraph.prototype.getExportableCells = function(cells)
-{
- return this.model.filterCells(cells, mxUtils.bind(this, function(cell)
- {
- return this.canExportCell(cell);
- }));
-};
-
-/**
- * Function: canExportCell
- *
- * Returns true if the given cell may be exported to the clipboard. This
- * implementation returns <exportEnabled> for all cells.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the cell to be exported.
- */
-mxGraph.prototype.canExportCell = function(cell)
-{
- return this.exportEnabled;
-};
-
-/**
- * Function: getImportableCells
- *
- * Returns the cells which may be imported in the given array of cells.
- */
-mxGraph.prototype.getImportableCells = function(cells)
-{
- return this.model.filterCells(cells, mxUtils.bind(this, function(cell)
- {
- return this.canImportCell(cell);
- }));
-};
-
-/**
- * Function: canImportCell
- *
- * Returns true if the given cell may be imported from the clipboard.
- * This implementation returns <importEnabled> for all cells.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the cell to be imported.
- */
-mxGraph.prototype.canImportCell = function(cell)
-{
- return this.importEnabled;
-};
-
-/**
- * Function: isCellSelectable
- *
- * Returns true if the given cell is selectable. This implementation
- * returns <cellsSelectable>.
- *
- * To add a new style for making cells (un)selectable, use the following code.
- *
- * (code)
- * mxGraph.prototype.isCellSelectable = function(cell)
- * {
- * var state = this.view.getState(cell);
- * var style = (state != null) ? state.style : this.getCellStyle(cell);
- *
- * return this.isCellsSelectable() && !this.isCellLocked(cell) && style['selectable'] != 0;
- * };
- * (end)
- *
- * You can then use the new style as shown in this example.
- *
- * (code)
- * graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30, 'selectable=0');
- * (end)
- *
- * Parameters:
- *
- * cell - <mxCell> whose selectable state should be returned.
- */
-mxGraph.prototype.isCellSelectable = function(cell)
-{
- return this.isCellsSelectable();
-};
-
-/**
- * Function: isCellsSelectable
- *
- * Returns <cellsSelectable>.
- */
-mxGraph.prototype.isCellsSelectable = function()
-{
- return this.cellsSelectable;
-};
-
-/**
- * Function: setCellsSelectable
- *
- * Sets <cellsSelectable>.
- */
-mxGraph.prototype.setCellsSelectable = function(value)
-{
- this.cellsSelectable = value;
-};
-
-/**
- * Function: getDeletableCells
- *
- * Returns the cells which may be exported in the given array of cells.
- */
-mxGraph.prototype.getDeletableCells = function(cells)
-{
- return this.model.filterCells(cells, mxUtils.bind(this, function(cell)
- {
- return this.isCellDeletable(cell);
- }));
-};
-
-/**
- * Function: isCellDeletable
- *
- * Returns true if the given cell is moveable. This returns
- * <cellsDeletable> for all given cells if a cells style does not specify
- * <mxConstants.STYLE_DELETABLE> to be 0.
- *
- * Parameters:
- *
- * cell - <mxCell> whose deletable state should be returned.
- */
-mxGraph.prototype.isCellDeletable = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return this.isCellsDeletable() && style[mxConstants.STYLE_DELETABLE] != 0;
-};
-
-/**
- * Function: isCellsDeletable
- *
- * Returns <cellsDeletable>.
- */
-mxGraph.prototype.isCellsDeletable = function()
-{
- return this.cellsDeletable;
-};
-
-/**
- * Function: setCellsDeletable
- *
- * Sets <cellsDeletable>.
- *
- * Parameters:
- *
- * value - Boolean indicating if the graph should allow deletion of cells.
- */
-mxGraph.prototype.setCellsDeletable = function(value)
-{
- this.cellsDeletable = value;
-};
-
-/**
- * Function: isLabelMovable
- *
- * Returns true if the given edges's label is moveable. This returns
- * <movable> for all given cells if <isLocked> does not return true
- * for the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> whose label should be moved.
- */
-mxGraph.prototype.isLabelMovable = function(cell)
-{
- return !this.isCellLocked(cell) &&
- ((this.model.isEdge(cell) && this.edgeLabelsMovable) ||
- (this.model.isVertex(cell) && this.vertexLabelsMovable));
-};
-
-/**
- * Function: getMovableCells
- *
- * Returns the cells which are movable in the given array of cells.
- */
-mxGraph.prototype.getMovableCells = function(cells)
-{
- return this.model.filterCells(cells, mxUtils.bind(this, function(cell)
- {
- return this.isCellMovable(cell);
- }));
-};
-
-/**
- * Function: isCellMovable
- *
- * Returns true if the given cell is moveable. This returns <cellsMovable>
- * for all given cells if <isCellLocked> does not return true for the given
- * cell and its style does not specify <mxConstants.STYLE_MOVABLE> to be 0.
- *
- * Parameters:
- *
- * cell - <mxCell> whose movable state should be returned.
- */
-mxGraph.prototype.isCellMovable = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return this.isCellsMovable() && !this.isCellLocked(cell) && style[mxConstants.STYLE_MOVABLE] != 0;
-};
-
-/**
- * Function: isCellsMovable
- *
- * Returns <cellsMovable>.
- */
-mxGraph.prototype.isCellsMovable = function()
-{
- return this.cellsMovable;
-};
-
-/**
- * Function: setCellsMovable
- *
- * Specifies if the graph should allow moving of cells. This implementation
- * updates <cellsMsovable>.
- *
- * Parameters:
- *
- * value - Boolean indicating if the graph should allow moving of cells.
- */
-mxGraph.prototype.setCellsMovable = function(value)
-{
- this.cellsMovable = value;
-};
-
-/**
- * Function: isGridEnabled
- *
- * Returns <gridEnabled> as a boolean.
- */
-mxGraph.prototype.isGridEnabled = function()
-{
- return this.gridEnabled;
-};
-
-/**
- * Function: setGridEnabled
- *
- * Specifies if the grid should be enabled.
- *
- * Parameters:
- *
- * value - Boolean indicating if the grid should be enabled.
- */
-mxGraph.prototype.setGridEnabled = function(value)
-{
- this.gridEnabled = value;
-};
-
-/**
- * Function: isPortsEnabled
- *
- * Returns <portsEnabled> as a boolean.
- */
-mxGraph.prototype.isPortsEnabled = function()
-{
- return this.portsEnabled;
-};
-
-/**
- * Function: setPortsEnabled
- *
- * Specifies if the ports should be enabled.
- *
- * Parameters:
- *
- * value - Boolean indicating if the ports should be enabled.
- */
-mxGraph.prototype.setPortsEnabled = function(value)
-{
- this.portsEnabled = value;
-};
-
-/**
- * Function: getGridSize
- *
- * Returns <gridSize>.
- */
-mxGraph.prototype.getGridSize = function()
-{
- return this.gridSize;
-};
-
-/**
- * Function: setGridSize
- *
- * Sets <gridSize>.
- */
-mxGraph.prototype.setGridSize = function(value)
-{
- this.gridSize = value;
-};
-
-/**
- * Function: getTolerance
- *
- * Returns <tolerance>.
- */
-mxGraph.prototype.getTolerance = function()
-{
- return this.tolerance;
-};
-
-/**
- * Function: setTolerance
- *
- * Sets <tolerance>.
- */
-mxGraph.prototype.setTolerance = function(value)
-{
- this.tolerance = value;
-};
-
-/**
- * Function: isVertexLabelsMovable
- *
- * Returns <vertexLabelsMovable>.
- */
-mxGraph.prototype.isVertexLabelsMovable = function()
-{
- return this.vertexLabelsMovable;
-};
-
-/**
- * Function: setVertexLabelsMovable
- *
- * Sets <vertexLabelsMovable>.
- */
-mxGraph.prototype.setVertexLabelsMovable = function(value)
-{
- this.vertexLabelsMovable = value;
-};
-
-/**
- * Function: isEdgeLabelsMovable
- *
- * Returns <edgeLabelsMovable>.
- */
-mxGraph.prototype.isEdgeLabelsMovable = function()
-{
- return this.edgeLabelsMovable;
-};
-
-/**
- * Function: isEdgeLabelsMovable
- *
- * Sets <edgeLabelsMovable>.
- */
-mxGraph.prototype.setEdgeLabelsMovable = function(value)
-{
- this.edgeLabelsMovable = value;
-};
-
-/**
- * Function: isSwimlaneNesting
- *
- * Returns <swimlaneNesting> as a boolean.
- */
-mxGraph.prototype.isSwimlaneNesting = function()
-{
- return this.swimlaneNesting;
-};
-
-/**
- * Function: setSwimlaneNesting
- *
- * Specifies if swimlanes can be nested by drag and drop. This is only
- * taken into account if dropEnabled is true.
- *
- * Parameters:
- *
- * value - Boolean indicating if swimlanes can be nested.
- */
-mxGraph.prototype.setSwimlaneNesting = function(value)
-{
- this.swimlaneNesting = value;
-};
-
-/**
- * Function: isSwimlaneSelectionEnabled
- *
- * Returns <swimlaneSelectionEnabled> as a boolean.
- */
-mxGraph.prototype.isSwimlaneSelectionEnabled = function()
-{
- return this.swimlaneSelectionEnabled;
-};
-
-/**
- * Function: setSwimlaneSelectionEnabled
- *
- * Specifies if swimlanes should be selected if the mouse is released
- * over their content area.
- *
- * Parameters:
- *
- * value - Boolean indicating if swimlanes content areas
- * should be selected when the mouse is released over them.
- */
-mxGraph.prototype.setSwimlaneSelectionEnabled = function(value)
-{
- this.swimlaneSelectionEnabled = value;
-};
-
-/**
- * Function: isMultigraph
- *
- * Returns <multigraph> as a boolean.
- */
-mxGraph.prototype.isMultigraph = function()
-{
- return this.multigraph;
-};
-
-/**
- * Function: setMultigraph
- *
- * Specifies if the graph should allow multiple connections between the
- * same pair of vertices.
- *
- * Parameters:
- *
- * value - Boolean indicating if the graph allows multiple connections
- * between the same pair of vertices.
- */
-mxGraph.prototype.setMultigraph = function(value)
-{
- this.multigraph = value;
-};
-
-/**
- * Function: isAllowLoops
- *
- * Returns <allowLoops> as a boolean.
- */
-mxGraph.prototype.isAllowLoops = function()
-{
- return this.allowLoops;
-};
-
-/**
- * Function: setAllowDanglingEdges
- *
- * Specifies if dangling edges are allowed, that is, if edges are allowed
- * that do not have a source and/or target terminal defined.
- *
- * Parameters:
- *
- * value - Boolean indicating if dangling edges are allowed.
- */
-mxGraph.prototype.setAllowDanglingEdges = function(value)
-{
- this.allowDanglingEdges = value;
-};
-
-/**
- * Function: isAllowDanglingEdges
- *
- * Returns <allowDanglingEdges> as a boolean.
- */
-mxGraph.prototype.isAllowDanglingEdges = function()
-{
- return this.allowDanglingEdges;
-};
-
-/**
- * Function: setConnectableEdges
- *
- * Specifies if edges should be connectable.
- *
- * Parameters:
- *
- * value - Boolean indicating if edges should be connectable.
- */
-mxGraph.prototype.setConnectableEdges = function(value)
-{
- this.connectableEdges = value;
-};
-
-/**
- * Function: isConnectableEdges
- *
- * Returns <connectableEdges> as a boolean.
- */
-mxGraph.prototype.isConnectableEdges = function()
-{
- return this.connectableEdges;
-};
-
-/**
- * Function: setCloneInvalidEdges
- *
- * Specifies if edges should be inserted when cloned but not valid wrt.
- * <getEdgeValidationError>. If false such edges will be silently ignored.
- *
- * Parameters:
- *
- * value - Boolean indicating if cloned invalid edges should be
- * inserted into the graph or ignored.
- */
-mxGraph.prototype.setCloneInvalidEdges = function(value)
-{
- this.cloneInvalidEdges = value;
-};
-
-/**
- * Function: isCloneInvalidEdges
- *
- * Returns <cloneInvalidEdges> as a boolean.
- */
-mxGraph.prototype.isCloneInvalidEdges = function()
-{
- return this.cloneInvalidEdges;
-};
-
-/**
- * Function: setAllowLoops
- *
- * Specifies if loops are allowed.
- *
- * Parameters:
- *
- * value - Boolean indicating if loops are allowed.
- */
-mxGraph.prototype.setAllowLoops = function(value)
-{
- this.allowLoops = value;
-};
-
-/**
- * Function: isDisconnectOnMove
- *
- * Returns <disconnectOnMove> as a boolean.
- */
-mxGraph.prototype.isDisconnectOnMove = function()
-{
- return this.disconnectOnMove;
-};
-
-/**
- * Function: setDisconnectOnMove
- *
- * Specifies if edges should be disconnected when moved. (Note: Cloned
- * edges are always disconnected.)
- *
- * Parameters:
- *
- * value - Boolean indicating if edges should be disconnected
- * when moved.
- */
-mxGraph.prototype.setDisconnectOnMove = function(value)
-{
- this.disconnectOnMove = value;
-};
-
-/**
- * Function: isDropEnabled
- *
- * Returns <dropEnabled> as a boolean.
- */
-mxGraph.prototype.isDropEnabled = function()
-{
- return this.dropEnabled;
-};
-
-/**
- * Function: setDropEnabled
- *
- * Specifies if the graph should allow dropping of cells onto or into other
- * cells.
- *
- * Parameters:
- *
- * dropEnabled - Boolean indicating if the graph should allow dropping
- * of cells into other cells.
- */
-mxGraph.prototype.setDropEnabled = function(value)
-{
- this.dropEnabled = value;
-};
-
-/**
- * Function: isSplitEnabled
- *
- * Returns <splitEnabled> as a boolean.
- */
-mxGraph.prototype.isSplitEnabled = function()
-{
- return this.splitEnabled;
-};
-
-/**
- * Function: setSplitEnabled
- *
- * Specifies if the graph should allow dropping of cells onto or into other
- * cells.
- *
- * Parameters:
- *
- * dropEnabled - Boolean indicating if the graph should allow dropping
- * of cells into other cells.
- */
-mxGraph.prototype.setSplitEnabled = function(value)
-{
- this.splitEnabled = value;
-};
-
-/**
- * Function: isCellResizable
- *
- * Returns true if the given cell is resizable. This returns
- * <cellsResizable> for all given cells if <isCellLocked> does not return
- * true for the given cell and its style does not specify
- * <mxConstants.STYLE_RESIZABLE> to be 0.
- *
- * Parameters:
- *
- * cell - <mxCell> whose resizable state should be returned.
- */
-mxGraph.prototype.isCellResizable = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return this.isCellsResizable() && !this.isCellLocked(cell) && style[mxConstants.STYLE_RESIZABLE] != 0;
-};
-
-/**
- * Function: isCellsResizable
- *
- * Returns <cellsResizable>.
- */
-mxGraph.prototype.isCellsResizable = function()
-{
- return this.cellsResizable;
-};
-
-/**
- * Function: setCellsResizable
- *
- * Specifies if the graph should allow resizing of cells. This
- * implementation updates <cellsResizable>.
- *
- * Parameters:
- *
- * value - Boolean indicating if the graph should allow resizing of
- * cells.
- */
-mxGraph.prototype.setCellsResizable = function(value)
-{
- this.cellsResizable = value;
-};
-
-/**
- * Function: isTerminalPointMovable
- *
- * Returns true if the given terminal point is movable. This is independent
- * from <isCellConnectable> and <isCellDisconnectable> and controls if terminal
- * points can be moved in the graph if the edge is not connected. Note that it
- * is required for this to return true to connect unconnected edges. This
- * implementation returns true.
- *
- * Parameters:
- *
- * cell - <mxCell> whose terminal point should be moved.
- * source - Boolean indicating if the source or target terminal should be moved.
- */
-mxGraph.prototype.isTerminalPointMovable = function(cell, source)
-{
- return true;
-};
-
-/**
- * Function: isCellBendable
- *
- * Returns true if the given cell is bendable. This returns <cellsBendable>
- * for all given cells if <isLocked> does not return true for the given
- * cell and its style does not specify <mxConstants.STYLE_BENDABLE> to be 0.
- *
- * Parameters:
- *
- * cell - <mxCell> whose bendable state should be returned.
- */
-mxGraph.prototype.isCellBendable = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return this.isCellsBendable() && !this.isCellLocked(cell) && style[mxConstants.STYLE_BENDABLE] != 0;
-};
-
-/**
- * Function: isCellsBendable
- *
- * Returns <cellsBenadable>.
- */
-mxGraph.prototype.isCellsBendable = function()
-{
- return this.cellsBendable;
-};
-
-/**
- * Function: setCellsBendable
- *
- * Specifies if the graph should allow bending of edges. This
- * implementation updates <bendable>.
- *
- * Parameters:
- *
- * value - Boolean indicating if the graph should allow bending of
- * edges.
- */
-mxGraph.prototype.setCellsBendable = function(value)
-{
- this.cellsBendable = value;
-};
-
-/**
- * Function: isCellEditable
- *
- * Returns true if the given cell is editable. This returns <cellsEditable> for
- * all given cells if <isCellLocked> does not return true for the given cell
- * and its style does not specify <mxConstants.STYLE_EDITABLE> to be 0.
- *
- * Parameters:
- *
- * cell - <mxCell> whose editable state should be returned.
- */
-mxGraph.prototype.isCellEditable = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return this.isCellsEditable() && !this.isCellLocked(cell) && style[mxConstants.STYLE_EDITABLE] != 0;
-};
-
-/**
- * Function: isCellsEditable
- *
- * Returns <cellsEditable>.
- */
-mxGraph.prototype.isCellsEditable = function()
-{
- return this.cellsEditable;
-};
-
-/**
- * Function: setCellsEditable
- *
- * Specifies if the graph should allow in-place editing for cell labels.
- * This implementation updates <cellsEditable>.
- *
- * Parameters:
- *
- * value - Boolean indicating if the graph should allow in-place
- * editing.
- */
-mxGraph.prototype.setCellsEditable = function(value)
-{
- this.cellsEditable = value;
-};
-
-/**
- * Function: isCellDisconnectable
- *
- * Returns true if the given cell is disconnectable from the source or
- * target terminal. This returns <isCellsDisconnectable> for all given
- * cells if <isCellLocked> does not return true for the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> whose disconnectable state should be returned.
- * terminal - <mxCell> that represents the source or target terminal.
- * source - Boolean indicating if the source or target terminal is to be
- * disconnected.
- */
-mxGraph.prototype.isCellDisconnectable = function(cell, terminal, source)
-{
- return this.isCellsDisconnectable() && !this.isCellLocked(cell);
-};
-
-/**
- * Function: isCellsDisconnectable
- *
- * Returns <cellsDisconnectable>.
- */
-mxGraph.prototype.isCellsDisconnectable = function()
-{
- return this.cellsDisconnectable;
-};
-
-/**
- * Function: setCellsDisconnectable
- *
- * Sets <cellsDisconnectable>.
- */
-mxGraph.prototype.setCellsDisconnectable = function(value)
-{
- this.cellsDisconnectable = value;
-};
-
-/**
- * Function: isValidSource
- *
- * Returns true if the given cell is a valid source for new connections.
- * This implementation returns true for all non-null values and is
- * called by is called by <isValidConnection>.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents a possible source or null.
- */
-mxGraph.prototype.isValidSource = function(cell)
-{
- return (cell == null && this.allowDanglingEdges) ||
- (cell != null && (!this.model.isEdge(cell) ||
- this.connectableEdges) && this.isCellConnectable(cell));
-};
-
-/**
- * Function: isValidTarget
- *
- * Returns <isValidSource> for the given cell. This is called by
- * <isValidConnection>.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents a possible target or null.
- */
-mxGraph.prototype.isValidTarget = function(cell)
-{
- return this.isValidSource(cell);
-};
-
-/**
- * Function: isValidConnection
- *
- * Returns true if the given target cell is a valid target for source.
- * This is a boolean implementation for not allowing connections between
- * certain pairs of vertices and is called by <getEdgeValidationError>.
- * This implementation returns true if <isValidSource> returns true for
- * the source and <isValidTarget> returns true for the target.
- *
- * Parameters:
- *
- * source - <mxCell> that represents the source cell.
- * target - <mxCell> that represents the target cell.
- */
-mxGraph.prototype.isValidConnection = function(source, target)
-{
- return this.isValidSource(source) && this.isValidTarget(target);
-};
-
-/**
- * Function: setConnectable
- *
- * Specifies if the graph should allow new connections. This implementation
- * updates <mxConnectionHandler.enabled> in <connectionHandler>.
- *
- * Parameters:
- *
- * connectable - Boolean indicating if new connections should be allowed.
- */
-mxGraph.prototype.setConnectable = function(connectable)
-{
- this.connectionHandler.setEnabled(connectable);
-};
-
-/**
- * Function: isConnectable
- *
- * Returns true if the <connectionHandler> is enabled.
- */
-mxGraph.prototype.isConnectable = function(connectable)
-{
- return this.connectionHandler.isEnabled();
-};
-
-/**
- * Function: setTooltips
- *
- * Specifies if tooltips should be enabled. This implementation updates
- * <mxTooltipHandler.enabled> in <tooltipHandler>.
- *
- * Parameters:
- *
- * enabled - Boolean indicating if tooltips should be enabled.
- */
-mxGraph.prototype.setTooltips = function (enabled)
-{
- this.tooltipHandler.setEnabled(enabled);
-};
-
-/**
- * Function: setPanning
- *
- * Specifies if panning should be enabled. This implementation updates
- * <mxPanningHandler.panningEnabled> in <panningHandler>.
- *
- * Parameters:
- *
- * enabled - Boolean indicating if panning should be enabled.
- */
-mxGraph.prototype.setPanning = function(enabled)
-{
- this.panningHandler.panningEnabled = enabled;
-};
-
-/**
- * Function: isEditing
- *
- * Returns true if the given cell is currently being edited.
- * If no cell is specified then this returns true if any
- * cell is currently being edited.
- *
- * Parameters:
- *
- * cell - <mxCell> that should be checked.
- */
-mxGraph.prototype.isEditing = function(cell)
-{
- if (this.cellEditor != null)
- {
- var editingCell = this.cellEditor.getEditingCell();
-
- return (cell == null) ?
- editingCell != null :
- cell == editingCell;
- }
-
- return false;
-};
-
-/**
- * Function: isAutoSizeCell
- *
- * Returns true if the size of the given cell should automatically be
- * updated after a change of the label. This implementation returns
- * <autoSizeCells> or checks if the cell style does specify
- * <mxConstants.STYLE_AUTOSIZE> to be 1.
- *
- * Parameters:
- *
- * cell - <mxCell> that should be resized.
- */
-mxGraph.prototype.isAutoSizeCell = function(cell)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return this.isAutoSizeCells() || style[mxConstants.STYLE_AUTOSIZE] == 1;
-};
-
-/**
- * Function: isAutoSizeCells
- *
- * Returns <autoSizeCells>.
- */
-mxGraph.prototype.isAutoSizeCells = function()
-{
- return this.autoSizeCells;
-};
-
-/**
- * Function: setAutoSizeCells
- *
- * Specifies if cell sizes should be automatically updated after a label
- * change. This implementation sets <autoSizeCells> to the given parameter.
- *
- * Parameters:
- *
- * value - Boolean indicating if cells should be resized
- * automatically.
- */
-mxGraph.prototype.setAutoSizeCells = function(value)
-{
- this.autoSizeCells = value;
-};
-
-/**
- * Function: isExtendParent
- *
- * Returns true if the parent of the given cell should be extended if the
- * child has been resized so that it overlaps the parent. This
- * implementation returns <isExtendParents> if the cell is not an edge.
- *
- * Parameters:
- *
- * cell - <mxCell> that has been resized.
- */
-mxGraph.prototype.isExtendParent = function(cell)
-{
- return !this.getModel().isEdge(cell) && this.isExtendParents();
-};
-
-/**
- * Function: isExtendParents
- *
- * Returns <extendParents>.
- */
-mxGraph.prototype.isExtendParents = function()
-{
- return this.extendParents;
-};
-
-/**
- * Function: setExtendParents
- *
- * Sets <extendParents>.
- *
- * Parameters:
- *
- * value - New boolean value for <extendParents>.
- */
-mxGraph.prototype.setExtendParents = function(value)
-{
- this.extendParents = value;
-};
-
-/**
- * Function: isExtendParentsOnAdd
- *
- * Returns <extendParentsOnAdd>.
- */
-mxGraph.prototype.isExtendParentsOnAdd = function()
-{
- return this.extendParentsOnAdd;
-};
-
-/**
- * Function: setExtendParentsOnAdd
- *
- * Sets <extendParentsOnAdd>.
- *
- * Parameters:
- *
- * value - New boolean value for <extendParentsOnAdd>.
- */
-mxGraph.prototype.setExtendParentsOnAdd = function(value)
-{
- this.extendParentsOnAdd = value;
-};
-
-/**
- * Function: isConstrainChild
- *
- * Returns true if the given cell should be kept inside the bounds of its
- * parent according to the rules defined by <getOverlap> and
- * <isAllowOverlapParent>. This implementation returns false for all children
- * of edges and <isConstrainChildren> otherwise.
- *
- * Parameters:
- *
- * cell - <mxCell> that should be constrained.
- */
-mxGraph.prototype.isConstrainChild = function(cell)
-{
- return this.isConstrainChildren() && !this.getModel().isEdge(this.getModel().getParent(cell));
-
-};
-
-/**
- * Function: isConstrainChildren
- *
- * Returns <constrainChildren>.
- */
-mxGraph.prototype.isConstrainChildren = function()
-{
- return this.constrainChildren;
-};
-
-/**
- * Function: setConstrainChildren
- *
- * Sets <constrainChildren>.
- */
-mxGraph.prototype.setConstrainChildren = function(value)
-{
- this.constrainChildren = value;
-};
-
-/**
- * Function: isConstrainChildren
- *
- * Returns <allowNegativeCoordinates>.
- */
-mxGraph.prototype.isAllowNegativeCoordinates = function()
-{
- return this.allowNegativeCoordinates;
-};
-
-/**
- * Function: setConstrainChildren
- *
- * Sets <allowNegativeCoordinates>.
- */
-mxGraph.prototype.setAllowNegativeCoordinates = function(value)
-{
- this.allowNegativeCoordinates = value;
-};
-
-/**
- * Function: getOverlap
- *
- * Returns a decimal number representing the amount of the width and height
- * of the given cell that is allowed to overlap its parent. A value of 0
- * means all children must stay inside the parent, 1 means the child is
- * allowed to be placed outside of the parent such that it touches one of
- * the parents sides. If <isAllowOverlapParent> returns false for the given
- * cell, then this method returns 0.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the overlap ratio should be returned.
- */
-mxGraph.prototype.getOverlap = function(cell)
-{
- return (this.isAllowOverlapParent(cell)) ? this.defaultOverlap : 0;
-};
-
-/**
- * Function: isAllowOverlapParent
- *
- * Returns true if the given cell is allowed to be placed outside of the
- * parents area.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the child to be checked.
- */
-mxGraph.prototype.isAllowOverlapParent = function(cell)
-{
- return false;
-};
-
-/**
- * Function: getFoldableCells
- *
- * Returns the cells which are movable in the given array of cells.
- */
-mxGraph.prototype.getFoldableCells = function(cells, collapse)
-{
- return this.model.filterCells(cells, mxUtils.bind(this, function(cell)
- {
- return this.isCellFoldable(cell, collapse);
- }));
-};
-
-/**
- * Function: isCellFoldable
- *
- * Returns true if the given cell is foldable. This implementation
- * returns true if the cell has at least one child and its style
- * does not specify <mxConstants.STYLE_FOLDABLE> to be 0.
- *
- * Parameters:
- *
- * cell - <mxCell> whose foldable state should be returned.
- */
-mxGraph.prototype.isCellFoldable = function(cell, collapse)
-{
- var state = this.view.getState(cell);
- var style = (state != null) ? state.style : this.getCellStyle(cell);
-
- return this.model.getChildCount(cell) > 0 && style[mxConstants.STYLE_FOLDABLE] != 0;
-};
-
-/**
- * Function: isValidDropTarget
- *
- * Returns true if the given cell is a valid drop target for the specified
- * cells. If the given cell is an edge, then <isSplitDropTarget> is used,
- * else <isParentDropTarget> is used to compute the return value.
- *
- * Parameters:
- *
- * cell - <mxCell> that represents the possible drop target.
- * cells - <mxCells> that should be dropped into the target.
- * evt - Mouseevent that triggered the invocation.
- */
-mxGraph.prototype.isValidDropTarget = function(cell, cells, evt)
-{
- return cell != null && ((this.isSplitEnabled() &&
- this.isSplitTarget(cell, cells, evt)) || (!this.model.isEdge(cell) &&
- (this.isSwimlane(cell) || (this.model.getChildCount(cell) > 0 &&
- !this.isCellCollapsed(cell)))));
-};
-
-/**
- * Function: isSplitTarget
- *
- * Returns true if the given edge may be splitted into two edges with the
- * given cell as a new terminal between the two.
- *
- * Parameters:
- *
- * target - <mxCell> that represents the edge to be splitted.
- * cells - <mxCells> that should split the edge.
- * evt - Mouseevent that triggered the invocation.
- */
-mxGraph.prototype.isSplitTarget = function(target, cells, evt)
-{
- if (this.model.isEdge(target) && cells != null && cells.length == 1 &&
- this.isCellConnectable(cells[0]) && this.getEdgeValidationError(target,
- this.model.getTerminal(target, true), cells[0]) == null)
- {
- var src = this.model.getTerminal(target, true);
- var trg = this.model.getTerminal(target, false);
-
- return (!this.model.isAncestor(cells[0], src) &&
- !this.model.isAncestor(cells[0], trg));
- }
-
- return false;
-};
-
-/**
- * Function: getDropTarget
- *
- * Returns the given cell if it is a drop target for the given cells or the
- * nearest ancestor that may be used as a drop target for the given cells.
- * If the given array contains a swimlane and <swimlaneNesting> is false
- * then this always returns null. If no cell is given, then the bottommost
- * swimlane at the location of the given event is returned.
- *
- * This function should only be used if <isDropEnabled> returns true.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> which are to be dropped onto the target.
- * evt - Mouseevent for the drag and drop.
- * cell - <mxCell> that is under the mousepointer.
- */
-mxGraph.prototype.getDropTarget = function(cells, evt, cell)
-{
- if (!this.isSwimlaneNesting())
- {
- for (var i = 0; i < cells.length; i++)
- {
- if (this.isSwimlane(cells[i]))
- {
- return null;
- }
- }
- }
-
- var pt = mxUtils.convertPoint(this.container,
- mxEvent.getClientX(evt), mxEvent.getClientY(evt));
- pt.x -= this.panDx;
- pt.y -= this.panDy;
- var swimlane = this.getSwimlaneAt(pt.x, pt.y);
-
- if (cell == null)
- {
- cell = swimlane;
- }
- else if (swimlane != null)
- {
- // Checks if the cell is an ancestor of the swimlane
- // under the mouse and uses the swimlane in that case
- var tmp = this.model.getParent(swimlane);
-
- while (tmp != null && this.isSwimlane(tmp) && tmp != cell)
- {
- tmp = this.model.getParent(tmp);
- }
-
- if (tmp == cell)
- {
- cell = swimlane;
- }
- }
-
- while (cell != null && !this.isValidDropTarget(cell, cells, evt) &&
- !this.model.isLayer(cell))
- {
- cell = this.model.getParent(cell);
- }
-
- return (!this.model.isLayer(cell) && mxUtils.indexOf(cells, cell) < 0) ? cell : null;
-};
-
-/**
- * Group: Cell retrieval
- */
-
-/**
- * Function: getDefaultParent
- *
- * Returns <defaultParent> or <mxGraphView.currentRoot> or the first child
- * child of <mxGraphModel.root> if both are null. The value returned by
- * this function should be used as the parent for new cells (aka default
- * layer).
- */
-mxGraph.prototype.getDefaultParent = function()
-{
- var parent = this.defaultParent;
-
- if (parent == null)
- {
- parent = this.getCurrentRoot();
-
- if (parent == null)
- {
- var root = this.model.getRoot();
- parent = this.model.getChildAt(root, 0);
- }
- }
-
- return parent;
-};
-
-/**
- * Function: setDefaultParent
- *
- * Sets the <defaultParent> to the given cell. Set this to null to return
- * the first child of the root in getDefaultParent.
- */
-mxGraph.prototype.setDefaultParent = function(cell)
-{
- this.defaultParent = cell;
-};
-
-/**
- * Function: getSwimlane
- *
- * Returns the nearest ancestor of the given cell which is a swimlane, or
- * the given cell, if it is itself a swimlane.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the ancestor swimlane should be returned.
- */
-mxGraph.prototype.getSwimlane = function(cell)
-{
- while (cell != null && !this.isSwimlane(cell))
- {
- cell = this.model.getParent(cell);
- }
-
- return cell;
-};
-
-/**
- * Function: getSwimlaneAt
- *
- * Returns the bottom-most swimlane that intersects the given point (x, y)
- * in the cell hierarchy that starts at the given parent.
- *
- * Parameters:
- *
- * x - X-coordinate of the location to be checked.
- * y - Y-coordinate of the location to be checked.
- * parent - <mxCell> that should be used as the root of the recursion.
- * Default is <defaultParent>.
- */
-mxGraph.prototype.getSwimlaneAt = function (x, y, parent)
-{
- parent = parent || this.getDefaultParent();
-
- if (parent != null)
- {
- var childCount = this.model.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = this.model.getChildAt(parent, i);
- var result = this.getSwimlaneAt(x, y, child);
-
- if (result != null)
- {
- return result;
- }
- else if (this.isSwimlane(child))
- {
- var state = this.view.getState(child);
-
- if (this.intersects(state, x, y))
- {
- return child;
- }
- }
- }
- }
-
- return null;
-};
-
-/**
- * Function: getCellAt
- *
- * Returns the bottom-most cell that intersects the given point (x, y) in
- * the cell hierarchy starting at the given parent. This will also return
- * swimlanes if the given location intersects the content area of the
- * swimlane. If this is not desired, then the <hitsSwimlaneContent> may be
- * used if the returned cell is a swimlane to determine if the location
- * is inside the content area or on the actual title of the swimlane.
- *
- * Parameters:
- *
- * x - X-coordinate of the location to be checked.
- * y - Y-coordinate of the location to be checked.
- * parent - <mxCell> that should be used as the root of the recursion.
- * Default is <defaultParent>.
- * vertices - Optional boolean indicating if vertices should be returned.
- * Default is true.
- * edges - Optional boolean indicating if edges should be returned. Default
- * is true.
- */
-mxGraph.prototype.getCellAt = function(x, y, parent, vertices, edges)
-{
- vertices = (vertices != null) ? vertices : true;
- edges = (edges != null) ? edges : true;
- parent = (parent != null) ? parent : this.getDefaultParent();
-
- if (parent != null)
- {
- var childCount = this.model.getChildCount(parent);
-
- for (var i = childCount - 1; i >= 0; i--)
- {
- var cell = this.model.getChildAt(parent, i);
- var result = this.getCellAt(x, y, cell, vertices, edges);
-
- if (result != null)
- {
- return result;
- }
- else if (this.isCellVisible(cell) && (edges && this.model.isEdge(cell) ||
- vertices && this.model.isVertex(cell)))
- {
- var state = this.view.getState(cell);
-
- if (this.intersects(state, x, y))
- {
- return cell;
- }
- }
- }
- }
-
- return null;
-};
-
-/**
- * Function: intersects
- *
- * Returns the bottom-most cell that intersects the given point (x, y) in
- * the cell hierarchy that starts at the given parent.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the cell state.
- * x - X-coordinate of the location to be checked.
- * y - Y-coordinate of the location to be checked.
- */
-mxGraph.prototype.intersects = function(state, x, y)
-{
- if (state != null)
- {
- var pts = state.absolutePoints;
-
- if (pts != null)
- {
- var t2 = this.tolerance * this.tolerance;
-
- var pt = pts[0];
-
- for (var i = 1; i<pts.length; i++)
- {
- var next = pts[i];
- var dist = mxUtils.ptSegDistSq(
- pt.x, pt.y, next.x, next.y, x, y);
-
- if (dist <= t2)
- {
- return true;
- }
-
- pt = next;
- }
- }
- else if (mxUtils.contains(state, x, y))
- {
- return true;
- }
- }
-
- return false;
-};
-
-/**
- * Function: hitsSwimlaneContent
- *
- * Returns true if the given coordinate pair is inside the content
- * are of the given swimlane.
- *
- * Parameters:
- *
- * swimlane - <mxCell> that specifies the swimlane.
- * x - X-coordinate of the mouse event.
- * y - Y-coordinate of the mouse event.
- */
-mxGraph.prototype.hitsSwimlaneContent = function(swimlane, x, y)
-{
- var state = this.getView().getState(swimlane);
- var size = this.getStartSize(swimlane);
-
- if (state != null)
- {
- var scale = this.getView().getScale();
- x -= state.x;
- y -= state.y;
-
- if (size.width > 0 && x > 0 && x > size.width * scale)
- {
- return true;
- }
- else if (size.height > 0 && y > 0 && y > size.height * scale)
- {
- return true;
- }
- }
-
- return false;
-};
-
-/**
- * Function: getChildVertices
- *
- * Returns the visible child vertices of the given parent.
- *
- * Parameters:
- *
- * parent - <mxCell> whose children should be returned.
- */
-mxGraph.prototype.getChildVertices = function(parent)
-{
- return this.getChildCells(parent, true, false);
-};
-
-/**
- * Function: getChildEdges
- *
- * Returns the visible child edges of the given parent.
- *
- * Parameters:
- *
- * parent - <mxCell> whose child vertices should be returned.
- */
-mxGraph.prototype.getChildEdges = function(parent)
-{
- return this.getChildCells(parent, false, true);
-};
-
-/**
- * Function: getChildCells
- *
- * Returns the visible child vertices or edges in the given parent. If
- * vertices and edges is false, then all children are returned.
- *
- * Parameters:
- *
- * parent - <mxCell> whose children should be returned.
- * vertices - Optional boolean that specifies if child vertices should
- * be returned. Default is false.
- * edges - Optional boolean that specifies if child edges should
- * be returned. Default is false.
- */
-mxGraph.prototype.getChildCells = function(parent, vertices, edges)
-{
- parent = (parent != null) ? parent : this.getDefaultParent();
- vertices = (vertices != null) ? vertices : false;
- edges = (edges != null) ? edges : false;
-
- var cells = this.model.getChildCells(parent, vertices, edges);
- var result = [];
-
- // Filters out the non-visible child cells
- for (var i = 0; i < cells.length; i++)
- {
- if (this.isCellVisible(cells[i]))
- {
- result.push(cells[i]);
- }
- }
-
- return result;
-};
-
-/**
- * Function: getConnections
- *
- * Returns all visible edges connected to the given cell without loops.
- *
- * Parameters:
- *
- * cell - <mxCell> whose connections should be returned.
- * parent - Optional parent of the opposite end for a connection to be
- * returned.
- */
-mxGraph.prototype.getConnections = function(cell, parent)
-{
- return this.getEdges(cell, parent, true, true, false);
-};
-
-/**
- * Function: getIncomingEdges
- *
- * Returns the visible incoming edges for the given cell. If the optional
- * parent argument is specified, then only child edges of the given parent
- * are returned.
- *
- * Parameters:
- *
- * cell - <mxCell> whose incoming edges should be returned.
- * parent - Optional parent of the opposite end for an edge to be
- * returned.
- */
-mxGraph.prototype.getIncomingEdges = function(cell, parent)
-{
- return this.getEdges(cell, parent, true, false, false);
-};
-
-/**
- * Function: getOutgoingEdges
- *
- * Returns the visible outgoing edges for the given cell. If the optional
- * parent argument is specified, then only child edges of the given parent
- * are returned.
- *
- * Parameters:
- *
- * cell - <mxCell> whose outgoing edges should be returned.
- * parent - Optional parent of the opposite end for an edge to be
- * returned.
- */
-mxGraph.prototype.getOutgoingEdges = function(cell, parent)
-{
- return this.getEdges(cell, parent, false, true, false);
-};
-
-/**
- * Function: getEdges
- *
- * Returns the incoming and/or outgoing edges for the given cell.
- * If the optional parent argument is specified, then only edges are returned
- * where the opposite is in the given parent cell. If at least one of incoming
- * or outgoing is true, then loops are ignored, if both are false, then all
- * edges connected to the given cell are returned including loops.
- *
- * Parameters:
- *
- * cell - <mxCell> whose edges should be returned.
- * parent - Optional parent of the opposite end for an edge to be
- * returned.
- * incoming - Optional boolean that specifies if incoming edges should
- * be included in the result. Default is true.
- * outgoing - Optional boolean that specifies if outgoing edges should
- * be included in the result. Default is true.
- * includeLoops - Optional boolean that specifies if loops should be
- * included in the result. Default is true.
- * recurse - Optional boolean the specifies if the parent specified only
- * need be an ancestral parent, true, or the direct parent, false.
- * Default is false
- */
-mxGraph.prototype.getEdges = function(cell, parent, incoming, outgoing, includeLoops, recurse)
-{
- incoming = (incoming != null) ? incoming : true;
- outgoing = (outgoing != null) ? outgoing : true;
- includeLoops = (includeLoops != null) ? includeLoops : true;
- recurse = (recurse != null) ? recurse : false;
-
- var edges = [];
- var isCollapsed = this.isCellCollapsed(cell);
- var childCount = this.model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = this.model.getChildAt(cell, i);
-
- if (isCollapsed || !this.isCellVisible(child))
- {
- edges = edges.concat(this.model.getEdges(child, incoming, outgoing));
- }
- }
-
- edges = edges.concat(this.model.getEdges(cell, incoming, outgoing));
- var result = [];
-
- for (var i = 0; i < edges.length; i++)
- {
- var state = this.view.getState(edges[i]);
-
- var source = (state != null) ? state.getVisibleTerminal(true) : this.view.getVisibleTerminal(edges[i], true);
- var target = (state != null) ? state.getVisibleTerminal(false) : this.view.getVisibleTerminal(edges[i], false);
-
- if ((includeLoops && source == target) || ((source != target) && ((incoming &&
- target == cell && (parent == null || this.isValidAncestor(source, parent, recurse))) ||
- (outgoing && source == cell && (parent == null ||
- this.isValidAncestor(target, parent, recurse))))))
- {
- result.push(edges[i]);
- }
- }
-
- return result;
-};
-
-/**
- * Function: isValidAncestor
- *
- * Returns whether or not the specified parent is a valid
- * ancestor of the specified cell, either direct or indirectly
- * based on whether ancestor recursion is enabled.
- *
- * Parameters:
- *
- * cell - <mxCell> the possible child cell
- * parent - <mxCell> the possible parent cell
- * recurse - boolean whether or not to recurse the child ancestors
- */
-mxGraph.prototype.isValidAncestor = function(cell, parent, recurse)
-{
- return (recurse ? this.model.isAncestor(parent, cell) : this.model
- .getParent(cell) == parent);
-};
-
-/**
- * Function: getOpposites
- *
- * Returns all distinct visible opposite cells for the specified terminal
- * on the given edges.
- *
- * Parameters:
- *
- * edges - Array of <mxCells> that contains the edges whose opposite
- * terminals should be returned.
- * terminal - Terminal that specifies the end whose opposite should be
- * returned.
- * source - Optional boolean that specifies if source terminals should be
- * included in the result. Default is true.
- * targets - Optional boolean that specifies if targer terminals should be
- * included in the result. Default is true.
- */
-mxGraph.prototype.getOpposites = function(edges, terminal, sources, targets)
-{
- sources = (sources != null) ? sources : true;
- targets = (targets != null) ? targets : true;
-
- var terminals = [];
-
- // Implements set semantic on the terminals array using a string
- // representation of each cell in an associative array lookup
- var hash = new Object();
-
- if (edges != null)
- {
- for (var i = 0; i < edges.length; i++)
- {
- var state = this.view.getState(edges[i]);
-
- var source = (state != null) ? state.getVisibleTerminal(true) : this.view.getVisibleTerminal(edges[i], true);
- var target = (state != null) ? state.getVisibleTerminal(false) : this.view.getVisibleTerminal(edges[i], false);
-
- // Checks if the terminal is the source of the edge and if the
- // target should be stored in the result
- if (source == terminal && target != null &&
- target != terminal && targets)
- {
- var id = mxCellPath.create(target);
-
- if (hash[id] == null)
- {
- hash[id] = target;
- terminals.push(target);
- }
- }
-
- // Checks if the terminal is the taget of the edge and if the
- // source should be stored in the result
- else if (target == terminal && source != null &&
- source != terminal && sources)
- {
- var id = mxCellPath.create(source);
-
- if (hash[id] == null)
- {
- hash[id] = source;
- terminals.push(source);
- }
- }
- }
- }
-
- return terminals;
-};
-
-/**
- * Function: getEdgesBetween
- *
- * Returns the edges between the given source and target. This takes into
- * account collapsed and invisible cells and returns the connected edges
- * as displayed on the screen.
- *
- * Parameters:
- *
- * source -
- * target -
- * directed -
- */
-mxGraph.prototype.getEdgesBetween = function(source, target, directed)
-{
- directed = (directed != null) ? directed : false;
- var edges = this.getEdges(source);
- var result = [];
-
- // Checks if the edge is connected to the correct
- // cell and returns the first match
- for (var i = 0; i < edges.length; i++)
- {
- var state = this.view.getState(edges[i]);
-
- var src = (state != null) ? state.getVisibleTerminal(true) : this.view.getVisibleTerminal(edges[i], true);
- var trg = (state != null) ? state.getVisibleTerminal(false) : this.view.getVisibleTerminal(edges[i], false);
-
- if ((src == source && trg == target) || (!directed && src == target && trg == source))
- {
- result.push(edges[i]);
- }
- }
-
- return result;
-};
-
-/**
- * Function: getPointForEvent
- *
- * Returns an <mxPoint> representing the given event in the unscaled,
- * non-translated coordinate space of <container> and applies the grid.
- *
- * Parameters:
- *
- * evt - Mousevent that contains the mouse pointer location.
- * addOffset - Optional boolean that specifies if the position should be
- * offset by half of the <gridSize>. Default is true.
- */
- mxGraph.prototype.getPointForEvent = function(evt, addOffset)
- {
- var p = mxUtils.convertPoint(this.container,
- mxEvent.getClientX(evt), mxEvent.getClientY(evt));
-
- var s = this.view.scale;
- var tr = this.view.translate;
- var off = (addOffset != false) ? this.gridSize / 2 : 0;
-
- p.x = this.snap(p.x / s - tr.x - off);
- p.y = this.snap(p.y / s - tr.y - off);
-
- return p;
- };
-
-/**
- * Function: getCells
- *
- * Returns the children of the given parent that are contained in the given
- * rectangle (x, y, width, height). The result is added to the optional
- * result array, which is returned from the function. If no result array
- * is specified then a new array is created and returned.
- *
- * Parameters:
- *
- * x - X-coordinate of the rectangle.
- * y - Y-coordinate of the rectangle.
- * width - Width of the rectangle.
- * height - Height of the rectangle.
- * parent - <mxCell> whose children should be checked. Default is
- * <defaultParent>.
- * result - Optional array to store the result in.
- */
-mxGraph.prototype.getCells = function(x, y, width, height, parent, result)
-{
- result = (result != null) ? result : [];
-
- if (width > 0 || height > 0)
- {
- var right = x + width;
- var bottom = y + height;
-
- parent = parent || this.getDefaultParent();
-
- if (parent != null)
- {
- var childCount = this.model.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var cell = this.model.getChildAt(parent, i);
- var state = this.view.getState(cell);
-
- if (this.isCellVisible(cell) && state != null)
- {
- if (state.x >= x && state.y >= y &&
- state.x + state.width <= right &&
- state.y + state.height <= bottom)
- {
- result.push(cell);
- }
- else
- {
- this.getCells(x, y, width, height, cell, result);
- }
- }
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: getCellsBeyond
- *
- * Returns the children of the given parent that are contained in the
- * halfpane from the given point (x0, y0) rightwards and/or downwards
- * depending on rightHalfpane and bottomHalfpane.
- *
- * Parameters:
- *
- * x0 - X-coordinate of the origin.
- * y0 - Y-coordinate of the origin.
- * parent - Optional <mxCell> whose children should be checked. Default is
- * <defaultParent>.
- * rightHalfpane - Boolean indicating if the cells in the right halfpane
- * from the origin should be returned.
- * bottomHalfpane - Boolean indicating if the cells in the bottom halfpane
- * from the origin should be returned.
- */
-mxGraph.prototype.getCellsBeyond = function(x0, y0, parent, rightHalfpane, bottomHalfpane)
-{
- var result = [];
-
- if (rightHalfpane || bottomHalfpane)
- {
- if (parent == null)
- {
- parent = this.getDefaultParent();
- }
-
- if (parent != null)
- {
- var childCount = this.model.getChildCount(parent);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = this.model.getChildAt(parent, i);
- var state = this.view.getState(child);
-
- if (this.isCellVisible(child) && state != null)
- {
- if ((!rightHalfpane ||
- state.x >= x0) &&
- (!bottomHalfpane ||
- state.y >= y0))
- {
- result.push(child);
- }
- }
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: findTreeRoots
- *
- * Returns all children in the given parent which do not have incoming
- * edges. If the result is empty then the with the greatest difference
- * between incoming and outgoing edges is returned.
- *
- * Parameters:
- *
- * parent - <mxCell> whose children should be checked.
- * isolate - Optional boolean that specifies if edges should be ignored if
- * the opposite end is not a child of the given parent cell. Default is
- * false.
- * invert - Optional boolean that specifies if outgoing or incoming edges
- * should be counted for a tree root. If false then outgoing edges will be
- * counted. Default is false.
- */
-mxGraph.prototype.findTreeRoots = function(parent, isolate, invert)
-{
- isolate = (isolate != null) ? isolate : false;
- invert = (invert != null) ? invert : false;
- var roots = [];
-
- if (parent != null)
- {
- var model = this.getModel();
- var childCount = model.getChildCount(parent);
- var best = null;
- var maxDiff = 0;
-
- for (var i=0; i<childCount; i++)
- {
- var cell = model.getChildAt(parent, i);
-
- if (this.model.isVertex(cell) && this.isCellVisible(cell))
- {
- var conns = this.getConnections(cell, (isolate) ? parent : null);
- var fanOut = 0;
- var fanIn = 0;
-
- for (var j = 0; j < conns.length; j++)
- {
- var src = this.view.getVisibleTerminal(conns[j], true);
-
- if (src == cell)
- {
- fanOut++;
- }
- else
- {
- fanIn++;
- }
- }
-
- if ((invert && fanOut == 0 && fanIn > 0) ||
- (!invert && fanIn == 0 && fanOut > 0))
- {
- roots.push(cell);
- }
-
- var diff = (invert) ? fanIn - fanOut : fanOut - fanIn;
-
- if (diff > maxDiff)
- {
- maxDiff = diff;
- best = cell;
- }
- }
- }
-
- if (roots.length == 0 && best != null)
- {
- roots.push(best);
- }
- }
-
- return roots;
-};
-
-/**
- * Function: traverse
- *
- * Traverses the (directed) graph invoking the given function for each
- * visited vertex and edge. The function is invoked with the current vertex
- * and the incoming edge as a parameter. This implementation makes sure
- * each vertex is only visited once. The function may return false if the
- * traversal should stop at the given vertex.
- *
- * Example:
- *
- * (code)
- * mxLog.show();
- * var cell = graph.getSelectionCell();
- * graph.traverse(cell, false, function(vertex, edge)
- * {
- * mxLog.debug(graph.getLabel(vertex));
- * });
- * (end)
- *
- * Parameters:
- *
- * vertex - <mxCell> that represents the vertex where the traversal starts.
- * directed - Optional boolean indicating if edges should only be traversed
- * from source to target. Default is true.
- * func - Visitor function that takes the current vertex and the incoming
- * edge as arguments. The traversal stops if the function returns false.
- * edge - Optional <mxCell> that represents the incoming edge. This is
- * null for the first step of the traversal.
- * visited - Optional array of cell paths for the visited cells.
- */
-mxGraph.prototype.traverse = function(vertex, directed, func, edge, visited)
-{
- if (func != null && vertex != null)
- {
- directed = (directed != null) ? directed : true;
- visited = visited || [];
- var id = mxCellPath.create(vertex);
-
- if (visited[id] == null)
- {
- visited[id] = vertex;
- var result = func(vertex, edge);
-
- if (result == null || result)
- {
- var edgeCount = this.model.getEdgeCount(vertex);
-
- if (edgeCount > 0)
- {
- for (var i = 0; i < edgeCount; i++)
- {
- var e = this.model.getEdgeAt(vertex, i);
- var isSource = this.model.getTerminal(e, true) == vertex;
-
- if (!directed || isSource)
- {
- var next = this.model.getTerminal(e, !isSource);
- this.traverse(next, directed, func, e, visited);
- }
- }
- }
- }
- }
- }
-};
-
-/**
- * Group: Selection
- */
-
-/**
- * Function: isCellSelected
- *
- * Returns true if the given cell is selected.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the selection state should be returned.
- */
-mxGraph.prototype.isCellSelected = function(cell)
-{
- return this.getSelectionModel().isSelected(cell);
-};
-
-/**
- * Function: isSelectionEmpty
- *
- * Returns true if the selection is empty.
- */
-mxGraph.prototype.isSelectionEmpty = function()
-{
- return this.getSelectionModel().isEmpty();
-};
-
-/**
- * Function: clearSelection
- *
- * Clears the selection using <mxGraphSelectionModel.clear>.
- */
-mxGraph.prototype.clearSelection = function()
-{
- return this.getSelectionModel().clear();
-};
-
-/**
- * Function: getSelectionCount
- *
- * Returns the number of selected cells.
- */
-mxGraph.prototype.getSelectionCount = function()
-{
- return this.getSelectionModel().cells.length;
-};
-
-/**
- * Function: getSelectionCell
- *
- * Returns the first cell from the array of selected <mxCells>.
- */
-mxGraph.prototype.getSelectionCell = function()
-{
- return this.getSelectionModel().cells[0];
-};
-
-/**
- * Function: getSelectionCells
- *
- * Returns the array of selected <mxCells>.
- */
-mxGraph.prototype.getSelectionCells = function()
-{
- return this.getSelectionModel().cells.slice();
-};
-
-/**
- * Function: setSelectionCell
- *
- * Sets the selection cell.
- *
- * Parameters:
- *
- * cell - <mxCell> to be selected.
- */
-mxGraph.prototype.setSelectionCell = function(cell)
-{
- this.getSelectionModel().setCell(cell);
-};
-
-/**
- * Function: setSelectionCells
- *
- * Sets the selection cell.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be selected.
- */
-mxGraph.prototype.setSelectionCells = function(cells)
-{
- this.getSelectionModel().setCells(cells);
-};
-
-/**
- * Function: addSelectionCell
- *
- * Adds the given cell to the selection.
- *
- * Parameters:
- *
- * cell - <mxCell> to be add to the selection.
- */
-mxGraph.prototype.addSelectionCell = function(cell)
-{
- this.getSelectionModel().addCell(cell);
-};
-
-/**
- * Function: addSelectionCells
- *
- * Adds the given cells to the selection.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be added to the selection.
- */
-mxGraph.prototype.addSelectionCells = function(cells)
-{
- this.getSelectionModel().addCells(cells);
-};
-
-/**
- * Function: removeSelectionCell
- *
- * Removes the given cell from the selection.
- *
- * Parameters:
- *
- * cell - <mxCell> to be removed from the selection.
- */
-mxGraph.prototype.removeSelectionCell = function(cell)
-{
- this.getSelectionModel().removeCell(cell);
-};
-
-/**
- * Function: removeSelectionCells
- *
- * Removes the given cells from the selection.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be removed from the selection.
- */
-mxGraph.prototype.removeSelectionCells = function(cells)
-{
- this.getSelectionModel().removeCells(cells);
-};
-
-/**
- * Function: selectRegion
- *
- * Selects and returns the cells inside the given rectangle for the
- * specified event.
- *
- * Parameters:
- *
- * rect - <mxRectangle> that represents the region to be selected.
- * evt - Mouseevent that triggered the selection.
- */
-mxGraph.prototype.selectRegion = function(rect, evt)
-{
- var cells = this.getCells(rect.x, rect.y, rect.width, rect.height);
- this.selectCellsForEvent(cells, evt);
-
- return cells;
-};
-
-/**
- * Function: selectNextCell
- *
- * Selects the next cell.
- */
-mxGraph.prototype.selectNextCell = function()
-{
- this.selectCell(true);
-};
-
-/**
- * Function: selectPreviousCell
- *
- * Selects the previous cell.
- */
-mxGraph.prototype.selectPreviousCell = function()
-{
- this.selectCell();
-};
-
-/**
- * Function: selectParentCell
- *
- * Selects the parent cell.
- */
-mxGraph.prototype.selectParentCell = function()
-{
- this.selectCell(false, true);
-};
-
-/**
- * Function: selectChildCell
- *
- * Selects the first child cell.
- */
-mxGraph.prototype.selectChildCell = function()
-{
- this.selectCell(false, false, true);
-};
-
-/**
- * Function: selectCell
- *
- * Selects the next, parent, first child or previous cell, if all arguments
- * are false.
- *
- * Parameters:
- *
- * isNext - Boolean indicating if the next cell should be selected.
- * isParent - Boolean indicating if the parent cell should be selected.
- * isChild - Boolean indicating if the first child cell should be selected.
- */
-mxGraph.prototype.selectCell = function(isNext, isParent, isChild)
-{
- var sel = this.selectionModel;
- var cell = (sel.cells.length > 0) ? sel.cells[0] : null;
-
- if (sel.cells.length > 1)
- {
- sel.clear();
- }
-
- var parent = (cell != null) ?
- this.model.getParent(cell) :
- this.getDefaultParent();
-
- var childCount = this.model.getChildCount(parent);
-
- if (cell == null && childCount > 0)
- {
- var child = this.model.getChildAt(parent, 0);
- this.setSelectionCell(child);
- }
- else if ((cell == null || isParent) &&
- this.view.getState(parent) != null &&
- this.model.getGeometry(parent) != null)
- {
- if (this.getCurrentRoot() != parent)
- {
- this.setSelectionCell(parent);
- }
- }
- else if (cell != null && isChild)
- {
- var tmp = this.model.getChildCount(cell);
-
- if (tmp > 0)
- {
- var child = this.model.getChildAt(cell, 0);
- this.setSelectionCell(child);
- }
- }
- else if (childCount > 0)
- {
- var i = parent.getIndex(cell);
-
- if (isNext)
- {
- i++;
- var child = this.model.getChildAt(parent, i % childCount);
- this.setSelectionCell(child);
- }
- else
- {
- i--;
- var index = (i < 0) ? childCount - 1 : i;
- var child = this.model.getChildAt(parent, index);
- this.setSelectionCell(child);
- }
- }
-};
-
-/**
- * Function: selectAll
- *
- * Selects all children of the given parent cell or the children of the
- * default parent if no parent is specified. To select leaf vertices and/or
- * edges use <selectCells>.
- *
- * Parameters:
- *
- * parent - Optional <mxCell> whose children should be selected.
- * Default is <defaultParent>.
- */
-mxGraph.prototype.selectAll = function(parent)
-{
- parent = parent || this.getDefaultParent();
-
- var children = this.model.getChildren(parent);
-
- if (children != null)
- {
- this.setSelectionCells(children);
- }
-};
-
-/**
- * Function: selectVertices
- *
- * Select all vertices inside the given parent or the default parent.
- */
-mxGraph.prototype.selectVertices = function(parent)
-{
- this.selectCells(true, false, parent);
-};
-
-/**
- * Function: selectVertices
- *
- * Select all vertices inside the given parent or the default parent.
- */
-mxGraph.prototype.selectEdges = function(parent)
-{
- this.selectCells(false, true, parent);
-};
-
-/**
- * Function: selectCells
- *
- * Selects all vertices and/or edges depending on the given boolean
- * arguments recursively, starting at the given parent or the default
- * parent if no parent is specified. Use <selectAll> to select all cells.
- *
- * Parameters:
- *
- * vertices - Boolean indicating if vertices should be selected.
- * edges - Boolean indicating if edges should be selected.
- * parent - Optional <mxCell> that acts as the root of the recursion.
- * Default is <defaultParent>.
- */
-mxGraph.prototype.selectCells = function(vertices, edges, parent)
-{
- parent = parent || this.getDefaultParent();
-
- var filter = mxUtils.bind(this, function(cell)
- {
- return this.view.getState(cell) != null &&
- this.model.getChildCount(cell) == 0 &&
- ((this.model.isVertex(cell) && vertices) ||
- (this.model.isEdge(cell) && edges));
- });
-
- var cells = this.model.filterDescendants(filter, parent);
- this.setSelectionCells(cells);
-};
-
-/**
- * Function: selectCellForEvent
- *
- * Selects the given cell by either adding it to the selection or
- * replacing the selection depending on whether the given mouse event is a
- * toggle event.
- *
- * Parameters:
- *
- * cell - <mxCell> to be selected.
- * evt - Optional mouseevent that triggered the selection.
- */
-mxGraph.prototype.selectCellForEvent = function(cell, evt)
-{
- var isSelected = this.isCellSelected(cell);
-
- if (this.isToggleEvent(evt))
- {
- if (isSelected)
- {
- this.removeSelectionCell(cell);
- }
- else
- {
- this.addSelectionCell(cell);
- }
- }
- else if (!isSelected || this.getSelectionCount() != 1)
- {
- this.setSelectionCell(cell);
- }
-};
-
-/**
- * Function: selectCellsForEvent
- *
- * Selects the given cells by either adding them to the selection or
- * replacing the selection depending on whether the given mouse event is a
- * toggle event.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be selected.
- * evt - Optional mouseevent that triggered the selection.
- */
-mxGraph.prototype.selectCellsForEvent = function(cells, evt)
-{
- if (this.isToggleEvent(evt))
- {
- this.addSelectionCells(cells);
- }
- else
- {
- this.setSelectionCells(cells);
- }
-};
-
-/**
- * Group: Selection state
- */
-
-/**
- * Function: createHandler
- *
- * Creates a new handler for the given cell state. This implementation
- * returns a new <mxEdgeHandler> of the corresponding cell is an edge,
- * otherwise it returns an <mxVertexHandler>.
- *
- * Parameters:
- *
- * state - <mxCellState> whose handler should be created.
- */
-mxGraph.prototype.createHandler = function(state)
-{
- var result = null;
-
- if (state != null)
- {
- if (this.model.isEdge(state.cell))
- {
- var style = this.view.getEdgeStyle(state);
-
- if (this.isLoop(state) ||
- style == mxEdgeStyle.ElbowConnector ||
- style == mxEdgeStyle.SideToSide ||
- style == mxEdgeStyle.TopToBottom)
- {
- result = new mxElbowEdgeHandler(state);
- }
- else if (style == mxEdgeStyle.SegmentConnector ||
- style == mxEdgeStyle.OrthConnector)
- {
- result = new mxEdgeSegmentHandler(state);
- }
- else
- {
- result = new mxEdgeHandler(state);
- }
- }
- else
- {
- result = new mxVertexHandler(state);
- }
- }
-
- return result;
-};
-
-/**
- * Group: Graph events
- */
-
-/**
- * Function: addMouseListener
- *
- * Adds a listener to the graph event dispatch loop. The listener
- * must implement the mouseDown, mouseMove and mouseUp methods
- * as shown in the <mxMouseEvent> class.
- *
- * Parameters:
- *
- * listener - Listener to be added to the graph event listeners.
- */
-mxGraph.prototype.addMouseListener = function(listener)
-{
- if (this.mouseListeners == null)
- {
- this.mouseListeners = [];
- }
-
- this.mouseListeners.push(listener);
-};
-
-/**
- * Function: removeMouseListener
- *
- * Removes the specified graph listener.
- *
- * Parameters:
- *
- * listener - Listener to be removed from the graph event listeners.
- */
-mxGraph.prototype.removeMouseListener = function(listener)
-{
- if (this.mouseListeners != null)
- {
- for (var i = 0; i < this.mouseListeners.length; i++)
- {
- if (this.mouseListeners[i] == listener)
- {
- this.mouseListeners.splice(i, 1);
- break;
- }
- }
- }
-};
-
-/**
- * Function: updateMouseEvent
- *
- * Sets the graphX and graphY properties if the given <mxMouseEvent> if
- * required.
- */
-mxGraph.prototype.updateMouseEvent = function(me)
-{
- if (me.graphX == null || me.graphY == null)
- {
- var pt = mxUtils.convertPoint(this.container, me.getX(), me.getY());
-
- me.graphX = pt.x - this.panDx;
- me.graphY = pt.y - this.panDy;
- }
-};
-
-/**
- * Function: fireMouseEvent
- *
- * Dispatches the given event in the graph event dispatch loop. Possible
- * event names are <mxEvent.MOUSE_DOWN>, <mxEvent.MOUSE_MOVE> and
- * <mxEvent.MOUSE_UP>. All listeners are invoked for all events regardless
- * of the consumed state of the event.
- *
- * Parameters:
- *
- * evtName - String that specifies the type of event to be dispatched.
- * me - <mxMouseEvent> to be fired.
- * sender - Optional sender argument. Default is this.
- */
-mxGraph.prototype.fireMouseEvent = function(evtName, me, sender)
-{
- if (sender == null)
- {
- sender = this;
- }
-
- // Updates the graph coordinates in the event
- this.updateMouseEvent(me);
-
- // Makes sure we have a uniform event-sequence across all
- // browsers for a double click. Since evt.detail == 2 is only
- // available on Firefox we use the fact that each mousedown
- // must be followed by a mouseup, all out-of-sync downs
- // will be dropped silently.
- if (evtName == mxEvent.MOUSE_DOWN)
- {
- this.isMouseDown = true;
- }
-
- // Detects and processes double taps for touch-based devices
- // which do not have native double click events
- if (mxClient.IS_TOUCH && this.doubleTapEnabled && evtName == mxEvent.MOUSE_DOWN)
- {
- var currentTime = new Date().getTime();
-
- if (currentTime - this.lastTouchTime < this.doubleTapTimeout &&
- Math.abs(this.lastTouchX - me.getX()) < this.doubleTapTolerance &&
- Math.abs(this.lastTouchY - me.getY()) < this.doubleTapTolerance)
- {
- // FIXME: The actual editing should start on MOUSE_UP event but
- // the detection of the double click should use the mouse_down event
- // to make it consistent with behaviour in browser with mouse.
- this.lastTouchTime = 0;
- this.dblClick(me.getEvent(), me.getCell());
-
- // Stop bubbling but do not consume to make sure the device
- // can bring up the virtual keyboard for editing
- me.getEvent().cancelBubble = true;
- }
- else
- {
- this.lastTouchX = me.getX();
- this.lastTouchY = me.getY();
- this.lastTouchTime = currentTime;
- }
- }
-
- // Workaround for IE9 standards mode ignoring tolerance for double clicks
- var noDoubleClick = me.getEvent().detail/*clickCount*/ != 2;
-
- if (mxClient.IS_IE && document.compatMode == 'CSS1Compat')
- {
- if ((this.lastMouseX != null && Math.abs(this.lastMouseX - me.getX()) > this.doubleTapTolerance) ||
- (this.lastMouseY != null && Math.abs(this.lastMouseY - me.getY()) > this.doubleTapTolerance))
- {
- noDoubleClick = true;
- }
-
- if (evtName == mxEvent.MOUSE_UP)
- {
- this.lastMouseX = me.getX();
- this.lastMouseY = me.getY();
- }
- }
-
- // Filters too many mouse ups when the mouse is down
- if ((evtName != mxEvent.MOUSE_UP || this.isMouseDown) && noDoubleClick)
- {
- if (evtName == mxEvent.MOUSE_UP)
- {
- this.isMouseDown = false;
- }
-
- if (!this.isEditing() && (mxClient.IS_OP || mxClient.IS_SF || mxClient.IS_GC ||
- (mxClient.IS_IE && mxClient.IS_SVG) || me.getEvent().target != this.container))
- {
- if (evtName == mxEvent.MOUSE_MOVE && this.isMouseDown && this.autoScroll)
- {
- this.scrollPointToVisible(me.getGraphX(), me.getGraphY(), this.autoExtend);
- }
-
- if (this.mouseListeners != null)
- {
- var args = [sender, me];
-
- // Does not change returnValue in Opera
- me.getEvent().returnValue = true;
-
- for (var i = 0; i < this.mouseListeners.length; i++)
- {
- var l = this.mouseListeners[i];
-
- if (evtName == mxEvent.MOUSE_DOWN)
- {
- l.mouseDown.apply(l, args);
- }
- else if (evtName == mxEvent.MOUSE_MOVE)
- {
- l.mouseMove.apply(l, args);
- }
- else if (evtName == mxEvent.MOUSE_UP)
- {
- l.mouseUp.apply(l, args);
- }
- }
- }
-
- // Invokes the click handler
- if (evtName == mxEvent.MOUSE_UP)
- {
- this.click(me);
- }
- }
- }
- else if (evtName == mxEvent.MOUSE_UP)
- {
- this.isMouseDown = false;
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the graph and all its resources.
- */
-mxGraph.prototype.destroy = function()
-{
- if (!this.destroyed)
- {
- this.destroyed = true;
-
- if (this.tooltipHandler != null)
- {
- this.tooltipHandler.destroy();
- }
-
- if (this.selectionCellsHandler != null)
- {
- this.selectionCellsHandler.destroy();
- }
-
- if (this.panningHandler != null)
- {
- this.panningHandler.destroy();
- }
-
- if (this.connectionHandler != null)
- {
- this.connectionHandler.destroy();
- }
-
- if (this.graphHandler != null)
- {
- this.graphHandler.destroy();
- }
-
- if (this.cellEditor != null)
- {
- this.cellEditor.destroy();
- }
-
- if (this.view != null)
- {
- this.view.destroy();
- }
-
- if (this.model != null && this.graphModelChangeListener != null)
- {
- this.model.removeListener(this.graphModelChangeListener);
- this.graphModelChangeListener = null;
- }
-
- this.container = null;
- }
-};
diff --git a/src/js/view/mxGraphSelectionModel.js b/src/js/view/mxGraphSelectionModel.js
deleted file mode 100644
index 5cd16a8..0000000
--- a/src/js/view/mxGraphSelectionModel.js
+++ /dev/null
@@ -1,435 +0,0 @@
-/**
- * $Id: mxGraphSelectionModel.js,v 1.14 2011-11-25 10:16:08 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraphSelectionModel
- *
- * Implements the selection model for a graph. Here is a listener that handles
- * all removed selection cells.
- *
- * (code)
- * graph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt)
- * {
- * var cells = evt.getProperty('added');
- *
- * for (var i = 0; i < cells.length; i++)
- * {
- * // Handle cells[i]...
- * }
- * });
- * (end)
- *
- * Event: mxEvent.UNDO
- *
- * Fires after the selection was changed in <changeSelection>. The
- * <code>edit</code> property contains the <mxUndoableEdit> which contains the
- * <mxSelectionChange>.
- *
- * Event: mxEvent.CHANGE
- *
- * Fires after the selection changes by executing an <mxSelectionChange>. The
- * <code>added</code> and <code>removed</code> properties contain arrays of
- * cells that have been added to or removed from the selection, respectively.
- *
- * Constructor: mxGraphSelectionModel
- *
- * Constructs a new graph selection model for the given <mxGraph>.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- */
-function mxGraphSelectionModel(graph)
-{
- this.graph = graph;
- this.cells = [];
-};
-
-/**
- * Extends mxEventSource.
- */
-mxGraphSelectionModel.prototype = new mxEventSource();
-mxGraphSelectionModel.prototype.constructor = mxGraphSelectionModel;
-
-/**
- * Variable: doneResource
- *
- * Specifies the resource key for the status message after a long operation.
- * If the resource for this key does not exist then the value is used as
- * the status message. Default is 'done'.
- */
-mxGraphSelectionModel.prototype.doneResource = (mxClient.language != 'none') ? 'done' : '';
-
-/**
- * Variable: updatingSelectionResource
- *
- * Specifies the resource key for the status message while the selection is
- * being updated. If the resource for this key does not exist then the
- * value is used as the status message. Default is 'updatingSelection'.
- */
-mxGraphSelectionModel.prototype.updatingSelectionResource = (mxClient.language != 'none') ? 'updatingSelection' : '';
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxGraphSelectionModel.prototype.graph = null;
-
-/**
- * Variable: singleSelection
- *
- * Specifies if only one selected item at a time is allowed.
- * Default is false.
- */
-mxGraphSelectionModel.prototype.singleSelection = false;
-
-/**
- * Function: isSingleSelection
- *
- * Returns <singleSelection> as a boolean.
- */
-mxGraphSelectionModel.prototype.isSingleSelection = function()
-{
- return this.singleSelection;
-};
-
-/**
- * Function: setSingleSelection
- *
- * Sets the <singleSelection> flag.
- *
- * Parameters:
- *
- * singleSelection - Boolean that specifies the new value for
- * <singleSelection>.
- */
-mxGraphSelectionModel.prototype.setSingleSelection = function(singleSelection)
-{
- this.singleSelection = singleSelection;
-};
-
-/**
- * Function: isSelected
- *
- * Returns true if the given <mxCell> is selected.
- */
-mxGraphSelectionModel.prototype.isSelected = function(cell)
-{
- if (cell != null)
- {
- return mxUtils.indexOf(this.cells, cell) >= 0;
- }
-
- return false;
-};
-
-/**
- * Function: isEmpty
- *
- * Returns true if no cells are currently selected.
- */
-mxGraphSelectionModel.prototype.isEmpty = function()
-{
- return this.cells.length == 0;
-};
-
-/**
- * Function: clear
- *
- * Clears the selection and fires a <change> event if the selection was not
- * empty.
- */
-mxGraphSelectionModel.prototype.clear = function()
-{
- this.changeSelection(null, this.cells);
-};
-
-/**
- * Function: setCell
- *
- * Selects the specified <mxCell> using <setCells>.
- *
- * Parameters:
- *
- * cell - <mxCell> to be selected.
- */
-mxGraphSelectionModel.prototype.setCell = function(cell)
-{
- if (cell != null)
- {
- this.setCells([cell]);
- }
-};
-
-/**
- * Function: setCells
- *
- * Selects the given array of <mxCells> and fires a <change> event.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to be selected.
- */
-mxGraphSelectionModel.prototype.setCells = function(cells)
-{
- if (cells != null)
- {
- if (this.singleSelection)
- {
- cells = [this.getFirstSelectableCell(cells)];
- }
-
- var tmp = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- if (this.graph.isCellSelectable(cells[i]))
- {
- tmp.push(cells[i]);
- }
- }
-
- this.changeSelection(tmp, this.cells);
- }
-};
-
-/**
- * Function: getFirstSelectableCell
- *
- * Returns the first selectable cell in the given array of cells.
- */
-mxGraphSelectionModel.prototype.getFirstSelectableCell = function(cells)
-{
- if (cells != null)
- {
- for (var i = 0; i < cells.length; i++)
- {
- if (this.graph.isCellSelectable(cells[i]))
- {
- return cells[i];
- }
- }
- }
-
- return null;
-};
-
-/**
- * Function: addCell
- *
- * Adds the given <mxCell> to the selection and fires a <select> event.
- *
- * Parameters:
- *
- * cell - <mxCell> to add to the selection.
- */
-mxGraphSelectionModel.prototype.addCell = function(cell)
-{
- if (cell != null)
- {
- this.addCells([cell]);
- }
-};
-
-/**
- * Function: addCells
- *
- * Adds the given array of <mxCells> to the selection and fires a <select>
- * event.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to add to the selection.
- */
-mxGraphSelectionModel.prototype.addCells = function(cells)
-{
- if (cells != null)
- {
- var remove = null;
-
- if (this.singleSelection)
- {
- remove = this.cells;
- cells = [this.getFirstSelectableCell(cells)];
- }
-
- var tmp = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- if (!this.isSelected(cells[i]) &&
- this.graph.isCellSelectable(cells[i]))
- {
- tmp.push(cells[i]);
- }
- }
-
- this.changeSelection(tmp, remove);
- }
-};
-
-/**
- * Function: removeCell
- *
- * Removes the specified <mxCell> from the selection and fires a <select>
- * event for the remaining cells.
- *
- * Parameters:
- *
- * cell - <mxCell> to remove from the selection.
- */
-mxGraphSelectionModel.prototype.removeCell = function(cell)
-{
- if (cell != null)
- {
- this.removeCells([cell]);
- }
-};
-
-/**
- * Function: removeCells
- */
-mxGraphSelectionModel.prototype.removeCells = function(cells)
-{
- if (cells != null)
- {
- var tmp = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- if (this.isSelected(cells[i]))
- {
- tmp.push(cells[i]);
- }
- }
-
- this.changeSelection(null, tmp);
- }
-};
-
-/**
- * Function: changeSelection
- *
- * Inner callback to add the specified <mxCell> to the selection. No event
- * is fired in this implementation.
- *
- * Paramters:
- *
- * cell - <mxCell> to add to the selection.
- */
-mxGraphSelectionModel.prototype.changeSelection = function(added, removed)
-{
- if ((added != null &&
- added.length > 0 &&
- added[0] != null) ||
- (removed != null &&
- removed.length > 0 &&
- removed[0] != null))
- {
- var change = new mxSelectionChange(this, added, removed);
- change.execute();
- var edit = new mxUndoableEdit(this, false);
- edit.add(change);
- this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
- }
-};
-
-/**
- * Function: cellAdded
- *
- * Inner callback to add the specified <mxCell> to the selection. No event
- * is fired in this implementation.
- *
- * Paramters:
- *
- * cell - <mxCell> to add to the selection.
- */
-mxGraphSelectionModel.prototype.cellAdded = function(cell)
-{
- if (cell != null &&
- !this.isSelected(cell))
- {
- this.cells.push(cell);
- }
-};
-
-/**
- * Function: cellRemoved
- *
- * Inner callback to remove the specified <mxCell> from the selection. No
- * event is fired in this implementation.
- *
- * Parameters:
- *
- * cell - <mxCell> to remove from the selection.
- */
-mxGraphSelectionModel.prototype.cellRemoved = function(cell)
-{
- if (cell != null)
- {
- var index = mxUtils.indexOf(this.cells, cell);
-
- if (index >= 0)
- {
- this.cells.splice(index, 1);
- }
- }
-};
-
-/**
- * Class: mxSelectionChange
- *
- * Action to change the current root in a view.
- *
- * Constructor: mxCurrentRootChange
- *
- * Constructs a change of the current root in the given view.
- */
-function mxSelectionChange(selectionModel, added, removed)
-{
- this.selectionModel = selectionModel;
- this.added = (added != null) ? added.slice() : null;
- this.removed = (removed != null) ? removed.slice() : null;
-};
-
-/**
- * Function: execute
- *
- * Changes the current root of the view.
- */
-mxSelectionChange.prototype.execute = function()
-{
- var t0 = mxLog.enter('mxSelectionChange.execute');
- window.status = mxResources.get(
- this.selectionModel.updatingSelectionResource) ||
- this.selectionModel.updatingSelectionResource;
-
- if (this.removed != null)
- {
- for (var i = 0; i < this.removed.length; i++)
- {
- this.selectionModel.cellRemoved(this.removed[i]);
- }
- }
-
- if (this.added != null)
- {
- for (var i = 0; i < this.added.length; i++)
- {
- this.selectionModel.cellAdded(this.added[i]);
- }
- }
-
- var tmp = this.added;
- this.added = this.removed;
- this.removed = tmp;
-
- window.status = mxResources.get(this.selectionModel.doneResource) ||
- this.selectionModel.doneResource;
- mxLog.leave('mxSelectionChange.execute', t0);
-
- this.selectionModel.fireEvent(new mxEventObject(mxEvent.CHANGE,
- 'added', this.added, 'removed', this.removed));
-};
diff --git a/src/js/view/mxGraphView.js b/src/js/view/mxGraphView.js
deleted file mode 100644
index 0ef2dc8..0000000
--- a/src/js/view/mxGraphView.js
+++ /dev/null
@@ -1,2545 +0,0 @@
-/**
- * $Id: mxGraphView.js,v 1.195 2012-11-20 09:06:07 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxGraphView
- *
- * Extends <mxEventSource> to implement a view for a graph. This class is in
- * charge of computing the absolute coordinates for the relative child
- * geometries, the points for perimeters and edge styles and keeping them
- * cached in <mxCellStates> for faster retrieval. The states are updated
- * whenever the model or the view state (translate, scale) changes. The scale
- * and translate are honoured in the bounds.
- *
- * Event: mxEvent.UNDO
- *
- * Fires after the root was changed in <setCurrentRoot>. The <code>edit</code>
- * property contains the <mxUndoableEdit> which contains the
- * <mxCurrentRootChange>.
- *
- * Event: mxEvent.SCALE_AND_TRANSLATE
- *
- * Fires after the scale and translate have been changed in <scaleAndTranslate>.
- * The <code>scale</code>, <code>previousScale</code>, <code>translate</code>
- * and <code>previousTranslate</code> properties contain the new and previous
- * scale and translate, respectively.
- *
- * Event: mxEvent.SCALE
- *
- * Fires after the scale was changed in <setScale>. The <code>scale</code> and
- * <code>previousScale</code> properties contain the new and previous scale.
- *
- * Event: mxEvent.TRANSLATE
- *
- * Fires after the translate was changed in <setTranslate>. The
- * <code>translate</code> and <code>previousTranslate</code> properties contain
- * the new and previous value for translate.
- *
- * Event: mxEvent.DOWN and mxEvent.UP
- *
- * Fire if the current root is changed by executing an <mxCurrentRootChange>.
- * The event name depends on the location of the root in the cell hierarchy
- * with respect to the current root. The <code>root</code> and
- * <code>previous</code> properties contain the new and previous root,
- * respectively.
- *
- * Constructor: mxGraphView
- *
- * Constructs a new view for the given <mxGraph>.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph>.
- */
-function mxGraphView(graph)
-{
- this.graph = graph;
- this.translate = new mxPoint();
- this.graphBounds = new mxRectangle();
- this.states = new mxDictionary();
-};
-
-/**
- * Extends mxEventSource.
- */
-mxGraphView.prototype = new mxEventSource();
-mxGraphView.prototype.constructor = mxGraphView;
-
-/**
- *
- */
-mxGraphView.prototype.EMPTY_POINT = new mxPoint();
-
-/**
- * Variable: doneResource
- *
- * Specifies the resource key for the status message after a long operation.
- * If the resource for this key does not exist then the value is used as
- * the status message. Default is 'done'.
- */
-mxGraphView.prototype.doneResource = (mxClient.language != 'none') ? 'done' : '';
-
-/**
- * Function: updatingDocumentResource
- *
- * Specifies the resource key for the status message while the document is
- * being updated. If the resource for this key does not exist then the
- * value is used as the status message. Default is 'updatingDocument'.
- */
-mxGraphView.prototype.updatingDocumentResource = (mxClient.language != 'none') ? 'updatingDocument' : '';
-
-/**
- * Variable: allowEval
- *
- * Specifies if string values in cell styles should be evaluated using
- * <mxUtils.eval>. This will only be used if the string values can't be mapped
- * to objects using <mxStyleRegistry>. Default is false. NOTE: Enabling this
- * switch carries a possible security risk (see the section on security in
- * the manual).
- */
-mxGraphView.prototype.allowEval = false;
-
-/**
- * Variable: captureDocumentGesture
- *
- * Specifies if a gesture should be captured when it goes outside of the
- * graph container. Default is true.
- */
-mxGraphView.prototype.captureDocumentGesture = true;
-
-/**
- * Variable: rendering
- *
- * Specifies if shapes should be created, updated and destroyed using the
- * methods of <mxCellRenderer> in <graph>. Default is true.
- */
-mxGraphView.prototype.rendering = true;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxGraphView.prototype.graph = null;
-
-/**
- * Variable: currentRoot
- *
- * <mxCell> that acts as the root of the displayed cell hierarchy.
- */
-mxGraphView.prototype.currentRoot = null;
-
-/**
- * Variable: graphBounds
- *
- * <mxRectangle> that caches the scales, translated bounds of the current view.
- */
-mxGraphView.prototype.graphBounds = null;
-
-/**
- * Variable: scale
- *
- * Specifies the scale. Default is 1 (100%).
- */
-mxGraphView.prototype.scale = 1;
-
-/**
- * Variable: translate
- *
- * <mxPoint> that specifies the current translation. Default is a new
- * empty <mxPoint>.
- */
-mxGraphView.prototype.translate = null;
-
-/**
- * Variable: updateStyle
- *
- * Specifies if the style should be updated in each validation step. If this
- * is false then the style is only updated if the state is created or if the
- * style of the cell was changed. Default is false.
- */
-mxGraphView.prototype.updateStyle = false;
-
-/**
- * Function: getGraphBounds
- *
- * Returns <graphBounds>.
- */
-mxGraphView.prototype.getGraphBounds = function()
-{
- return this.graphBounds;
-};
-
-/**
- * Function: setGraphBounds
- *
- * Sets <graphBounds>.
- */
-mxGraphView.prototype.setGraphBounds = function(value)
-{
- this.graphBounds = value;
-};
-
-/**
- * Function: getBounds
- *
- * Returns the bounds (on the screen) for the given array of <mxCells>.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> to return the bounds for.
- */
-mxGraphView.prototype.getBounds = function(cells)
-{
- var result = null;
-
- if (cells != null && cells.length > 0)
- {
- var model = this.graph.getModel();
-
- for (var i = 0; i < cells.length; i++)
- {
- if (model.isVertex(cells[i]) || model.isEdge(cells[i]))
- {
- var state = this.getState(cells[i]);
-
- if (state != null)
- {
- if (result == null)
- {
- result = new mxRectangle(state.x, state.y,
- state.width, state.height);
- }
- else
- {
- result.add(state);
- }
- }
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: setCurrentRoot
- *
- * Sets and returns the current root and fires an <undo> event before
- * calling <mxGraph.sizeDidChange>.
- *
- * Parameters:
- *
- * root - <mxCell> that specifies the root of the displayed cell hierarchy.
- */
-mxGraphView.prototype.setCurrentRoot = function(root)
-{
- if (this.currentRoot != root)
- {
- var change = new mxCurrentRootChange(this, root);
- change.execute();
- var edit = new mxUndoableEdit(this, false);
- edit.add(change);
- this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
- this.graph.sizeDidChange();
- }
-
- return root;
-};
-
-/**
- * Function: scaleAndTranslate
- *
- * Sets the scale and translation and fires a <scale> and <translate> event
- * before calling <revalidate> followed by <mxGraph.sizeDidChange>.
- *
- * Parameters:
- *
- * scale - Decimal value that specifies the new scale (1 is 100%).
- * dx - X-coordinate of the translation.
- * dy - Y-coordinate of the translation.
- */
-mxGraphView.prototype.scaleAndTranslate = function(scale, dx, dy)
-{
- var previousScale = this.scale;
- var previousTranslate = new mxPoint(this.translate.x, this.translate.y);
-
- if (this.scale != scale || this.translate.x != dx || this.translate.y != dy)
- {
- this.scale = scale;
-
- this.translate.x = dx;
- this.translate.y = dy;
-
- if (this.isEventsEnabled())
- {
- this.revalidate();
- this.graph.sizeDidChange();
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.SCALE_AND_TRANSLATE,
- 'scale', scale, 'previousScale', previousScale,
- 'translate', this.translate, 'previousTranslate', previousTranslate));
-};
-
-/**
- * Function: getScale
- *
- * Returns the <scale>.
- */
-mxGraphView.prototype.getScale = function()
-{
- return this.scale;
-};
-
-/**
- * Function: setScale
- *
- * Sets the scale and fires a <scale> event before calling <revalidate> followed
- * by <mxGraph.sizeDidChange>.
- *
- * Parameters:
- *
- * value - Decimal value that specifies the new scale (1 is 100%).
- */
-mxGraphView.prototype.setScale = function(value)
-{
- var previousScale = this.scale;
-
- if (this.scale != value)
- {
- this.scale = value;
-
- if (this.isEventsEnabled())
- {
- this.revalidate();
- this.graph.sizeDidChange();
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.SCALE,
- 'scale', value, 'previousScale', previousScale));
-};
-
-/**
- * Function: getTranslate
- *
- * Returns the <translate>.
- */
-mxGraphView.prototype.getTranslate = function()
-{
- return this.translate;
-};
-
-/**
- * Function: setTranslate
- *
- * Sets the translation and fires a <translate> event before calling
- * <revalidate> followed by <mxGraph.sizeDidChange>. The translation is the
- * negative of the origin.
- *
- * Parameters:
- *
- * dx - X-coordinate of the translation.
- * dy - Y-coordinate of the translation.
- */
-mxGraphView.prototype.setTranslate = function(dx, dy)
-{
- var previousTranslate = new mxPoint(this.translate.x, this.translate.y);
-
- if (this.translate.x != dx || this.translate.y != dy)
- {
- this.translate.x = dx;
- this.translate.y = dy;
-
- if (this.isEventsEnabled())
- {
- this.revalidate();
- this.graph.sizeDidChange();
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.TRANSLATE,
- 'translate', this.translate, 'previousTranslate', previousTranslate));
-};
-
-/**
- * Function: refresh
- *
- * Clears the view if <currentRoot> is not null and revalidates.
- */
-mxGraphView.prototype.refresh = function()
-{
- if (this.currentRoot != null)
- {
- this.clear();
- }
-
- this.revalidate();
-};
-
-/**
- * Function: revalidate
- *
- * Revalidates the complete view with all cell states.
- */
-mxGraphView.prototype.revalidate = function()
-{
- this.invalidate();
- this.validate();
-};
-
-/**
- * Function: clear
- *
- * Removes the state of the given cell and all descendants if the given
- * cell is not the current root.
- *
- * Parameters:
- *
- * cell - Optional <mxCell> for which the state should be removed. Default
- * is the root of the model.
- * force - Boolean indicating if the current root should be ignored for
- * recursion.
- */
-mxGraphView.prototype.clear = function(cell, force, recurse)
-{
- var model = this.graph.getModel();
- cell = cell || model.getRoot();
- force = (force != null) ? force : false;
- recurse = (recurse != null) ? recurse : true;
-
- this.removeState(cell);
-
- if (recurse && (force || cell != this.currentRoot))
- {
- var childCount = model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- this.clear(model.getChildAt(cell, i), force);
- }
- }
- else
- {
- this.invalidate(cell);
- }
-};
-
-/**
- * Function: invalidate
- *
- * Invalidates the state of the given cell, all its descendants and
- * connected edges.
- *
- * Parameters:
- *
- * cell - Optional <mxCell> to be invalidated. Default is the root of the
- * model.
- */
-mxGraphView.prototype.invalidate = function(cell, recurse, includeEdges, orderChanged)
-{
- var model = this.graph.getModel();
- cell = cell || model.getRoot();
- recurse = (recurse != null) ? recurse : true;
- includeEdges = (includeEdges != null) ? includeEdges : true;
- orderChanged = (orderChanged != null) ? orderChanged : false;
-
- var state = this.getState(cell);
-
- if (state != null)
- {
- state.invalid = true;
-
- if (orderChanged)
- {
- state.orderChanged = true;
- }
- }
-
- // Recursively invalidates all descendants
- if (recurse)
- {
- var childCount = model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(cell, i);
- this.invalidate(child, recurse, includeEdges, orderChanged);
- }
- }
-
- // Propagates invalidation to all connected edges
- if (includeEdges)
- {
- var edgeCount = model.getEdgeCount(cell);
-
- for (var i = 0; i < edgeCount; i++)
- {
- this.invalidate(model.getEdgeAt(cell, i), recurse, includeEdges);
- }
- }
-};
-
-/**
- * Function: validate
- *
- * First validates all bounds and then validates all points recursively on
- * all visible cells starting at the given cell. Finally the background
- * is validated using <validateBackground>.
- *
- * Parameters:
- *
- * cell - Optional <mxCell> to be used as the root of the validation.
- * Default is <currentRoot> or the root of the model.
- */
-mxGraphView.prototype.validate = function(cell)
-{
- var t0 = mxLog.enter('mxGraphView.validate');
- window.status = mxResources.get(this.updatingDocumentResource) ||
- this.updatingDocumentResource;
-
- cell = cell || ((this.currentRoot != null) ?
- this.currentRoot :
- this.graph.getModel().getRoot());
- this.validateBounds(null, cell);
- var graphBounds = this.validatePoints(null, cell);
-
- if (graphBounds == null)
- {
- graphBounds = new mxRectangle();
- }
-
- this.setGraphBounds(graphBounds);
- this.validateBackground();
-
- window.status = mxResources.get(this.doneResource) ||
- this.doneResource;
- mxLog.leave('mxGraphView.validate', t0);
-};
-
-/**
- * Function: createBackgroundPageShape
- *
- * Creates and returns the shape used as the background page.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that represents the bounds of the shape.
- */
-mxGraphView.prototype.createBackgroundPageShape = function(bounds)
-{
- return new mxRectangleShape(bounds, 'white', 'black');
-};
-
-/**
- * Function: validateBackground
- *
- * Validates the background image.
- */
-mxGraphView.prototype.validateBackground = function()
-{
- var bg = this.graph.getBackgroundImage();
-
- if (bg != null)
- {
- if (this.backgroundImage == null || this.backgroundImage.image != bg.src)
- {
- if (this.backgroundImage != null)
- {
- this.backgroundImage.destroy();
- }
-
- var bounds = new mxRectangle(0, 0, 1, 1);
-
- this.backgroundImage = new mxImageShape(bounds, bg.src);
- this.backgroundImage.dialect = this.graph.dialect;
- this.backgroundImage.init(this.backgroundPane);
- this.backgroundImage.redraw();
- }
-
- this.redrawBackgroundImage(this.backgroundImage, bg);
- }
- else if (this.backgroundImage != null)
- {
- this.backgroundImage.destroy();
- this.backgroundImage = null;
- }
-
- if (this.graph.pageVisible)
- {
- var bounds = this.getBackgroundPageBounds();
-
- if (this.backgroundPageShape == null)
- {
- this.backgroundPageShape = this.createBackgroundPageShape(bounds);
- this.backgroundPageShape.scale = this.scale;
- this.backgroundPageShape.isShadow = true;
- this.backgroundPageShape.dialect = this.graph.dialect;
- this.backgroundPageShape.init(this.backgroundPane);
- this.backgroundPageShape.redraw();
-
- // Adds listener for double click handling on background
- mxEvent.addListener(this.backgroundPageShape.node, 'dblclick',
- mxUtils.bind(this, function(evt)
- {
- this.graph.dblClick(evt);
- })
- );
-
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- // Adds basic listeners for graph event dispatching outside of the
- // container and finishing the handling of a single gesture
- mxEvent.addListener(this.backgroundPageShape.node, md,
- mxUtils.bind(this, function(evt)
- {
- this.graph.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt));
- })
- );
- mxEvent.addListener(this.backgroundPageShape.node, mm,
- mxUtils.bind(this, function(evt)
- {
- // Hides the tooltip if mouse is outside container
- if (this.graph.tooltipHandler != null &&
- this.graph.tooltipHandler.isHideOnHover())
- {
- this.graph.tooltipHandler.hide();
- }
-
- if (this.graph.isMouseDown &&
- !mxEvent.isConsumed(evt))
- {
- this.graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
- new mxMouseEvent(evt));
- }
- })
- );
- mxEvent.addListener(this.backgroundPageShape.node, mu,
- mxUtils.bind(this, function(evt)
- {
- this.graph.fireMouseEvent(mxEvent.MOUSE_UP,
- new mxMouseEvent(evt));
- })
- );
- }
- else
- {
- this.backgroundPageShape.scale = this.scale;
- this.backgroundPageShape.bounds = bounds;
- this.backgroundPageShape.redraw();
- }
- }
- else if (this.backgroundPageShape != null)
- {
- this.backgroundPageShape.destroy();
- this.backgroundPageShape = null;
- }
-};
-
-/**
- * Function: getBackgroundPageBounds
- *
- * Returns the bounds for the background page.
- */
-mxGraphView.prototype.getBackgroundPageBounds = function()
-{
- var fmt = this.graph.pageFormat;
- var ps = this.scale * this.graph.pageScale;
- var bounds = new mxRectangle(this.scale * this.translate.x, this.scale * this.translate.y,
- fmt.width * ps, fmt.height * ps);
-
- return bounds;
-};
-
-/**
- * Function: redrawBackgroundImage
- *
- * Updates the bounds and redraws the background image.
- *
- * Example:
- *
- * If the background image should not be scaled, this can be replaced with
- * the following.
- *
- * (code)
- * mxGraphView.prototype.redrawBackground = function(backgroundImage, bg)
- * {
- * backgroundImage.bounds.x = this.translate.x;
- * backgroundImage.bounds.y = this.translate.y;
- * backgroundImage.bounds.width = bg.width;
- * backgroundImage.bounds.height = bg.height;
- *
- * backgroundImage.redraw();
- * };
- * (end)
- *
- * Parameters:
- *
- * backgroundImage - <mxImageShape> that represents the background image.
- * bg - <mxImage> that specifies the image and its dimensions.
- */
-mxGraphView.prototype.redrawBackgroundImage = function(backgroundImage, bg)
-{
- backgroundImage.scale = this.scale;
- backgroundImage.bounds.x = this.scale * this.translate.x;
- backgroundImage.bounds.y = this.scale * this.translate.y;
- backgroundImage.bounds.width = this.scale * bg.width;
- backgroundImage.bounds.height = this.scale * bg.height;
-
- backgroundImage.redraw();
-};
-
-/**
- * Function: validateBounds
- *
- * Validates the bounds of the given parent's child using the given parent
- * state as the origin for the child. The validation is carried out
- * recursively for all non-collapsed descendants.
- *
- * Parameters:
- *
- * parentState - <mxCellState> for the given parent.
- * cell - <mxCell> for which the bounds in the state should be updated.
- */
-mxGraphView.prototype.validateBounds = function(parentState, cell)
-{
- var model = this.graph.getModel();
- var state = this.getState(cell, true);
-
- if (state != null && state.invalid)
- {
- if (!this.graph.isCellVisible(cell))
- {
- this.removeState(cell);
- }
-
- // Updates the cell state's origin
- else if (cell != this.currentRoot && parentState != null)
- {
- state.absoluteOffset.x = 0;
- state.absoluteOffset.y = 0;
- state.origin.x = parentState.origin.x;
- state.origin.y = parentState.origin.y;
- var geo = this.graph.getCellGeometry(cell);
-
- if (geo != null)
- {
- if (!model.isEdge(cell))
- {
- var offset = geo.offset || this.EMPTY_POINT;
-
- if (geo.relative)
- {
- state.origin.x += geo.x * parentState.width /
- this.scale + offset.x;
- state.origin.y += geo.y * parentState.height /
- this.scale + offset.y;
- }
- else
- {
- state.absoluteOffset.x = this.scale * offset.x;
- state.absoluteOffset.y = this.scale * offset.y;
- state.origin.x += geo.x;
- state.origin.y += geo.y;
- }
- }
-
- // Updates cell state's bounds
- state.x = this.scale * (this.translate.x + state.origin.x);
- state.y = this.scale * (this.translate.y + state.origin.y);
- state.width = this.scale * geo.width;
- state.height = this.scale * geo.height;
-
- if (model.isVertex(cell))
- {
- this.updateVertexLabelOffset(state);
- }
- }
- }
-
- // Applies child offset to origin
- var offset = this.graph.getChildOffsetForCell(cell);
-
- if (offset != null)
- {
- state.origin.x += offset.x;
- state.origin.y += offset.y;
- }
- }
-
- // Recursively validates the child bounds
- if (state != null && (!this.graph.isCellCollapsed(cell) ||
- cell == this.currentRoot))
- {
- var childCount = model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(cell, i);
- this.validateBounds(state, child);
- }
- }
-};
-
-/**
- * Function: updateVertexLabelOffset
- *
- * Updates the absoluteOffset of the given vertex cell state. This takes
- * into account the label position styles.
- *
- * Parameters:
- *
- * state - <mxCellState> whose absolute offset should be updated.
- */
-mxGraphView.prototype.updateVertexLabelOffset = function(state)
-{
- var horizontal = mxUtils.getValue(state.style,
- mxConstants.STYLE_LABEL_POSITION,
- mxConstants.ALIGN_CENTER);
-
- if (horizontal == mxConstants.ALIGN_LEFT)
- {
- state.absoluteOffset.x -= state.width;
- }
- else if (horizontal == mxConstants.ALIGN_RIGHT)
- {
- state.absoluteOffset.x += state.width;
- }
-
- var vertical = mxUtils.getValue(state.style,
- mxConstants.STYLE_VERTICAL_LABEL_POSITION,
- mxConstants.ALIGN_MIDDLE);
-
- if (vertical == mxConstants.ALIGN_TOP)
- {
- state.absoluteOffset.y -= state.height;
- }
- else if (vertical == mxConstants.ALIGN_BOTTOM)
- {
- state.absoluteOffset.y += state.height;
- }
-};
-
-/**
- * Function: validatePoints
- *
- * Validates the points for the state of the given cell recursively if the
- * cell is not collapsed and returns the bounding box of all visited states
- * as an <mxRectangle>.
- *
- * Parameters:
- *
- * parentState - <mxCellState> for the parent cell.
- * cell - <mxCell> whose points in the state should be updated.
- */
-mxGraphView.prototype.validatePoints = function(parentState, cell)
-{
- var model = this.graph.getModel();
- var state = this.getState(cell);
- var bbox = null;
-
- if (state != null)
- {
- if (state.invalid)
- {
- var geo = this.graph.getCellGeometry(cell);
-
- if (geo != null && model.isEdge(cell))
- {
- // Updates the points on the source terminal if its an edge
- var source = this.getState(this.getVisibleTerminal(cell, true));
- state.setVisibleTerminalState(source, true);
-
- if (source != null && model.isEdge(source.cell) &&
- !model.isAncestor(source.cell, cell))
- {
- var tmp = this.getState(model.getParent(source.cell));
- this.validatePoints(tmp, source.cell);
- }
-
- // Updates the points on the target terminal if its an edge
- var target = this.getState(this.getVisibleTerminal(cell, false));
- state.setVisibleTerminalState(target, false);
-
- if (target != null && model.isEdge(target.cell) &&
- !model.isAncestor(target.cell, cell))
- {
- var tmp = this.getState(model.getParent(target.cell));
- this.validatePoints(tmp, target.cell);
- }
-
- this.updateFixedTerminalPoints(state, source, target);
- this.updatePoints(state, geo.points, source, target);
- this.updateFloatingTerminalPoints(state, source, target);
- this.updateEdgeBounds(state);
- this.updateEdgeLabelOffset(state);
- }
- else if (geo != null && geo.relative && parentState != null &&
- model.isEdge(parentState.cell))
- {
- var origin = this.getPoint(parentState, geo);
-
- if (origin != null)
- {
- state.x = origin.x;
- state.y = origin.y;
-
- origin.x = (origin.x / this.scale) - this.translate.x;
- origin.y = (origin.y / this.scale) - this.translate.y;
- state.origin = origin;
-
- this.childMoved(parentState, state);
- }
- }
-
- state.invalid = false;
-
- if (cell != this.currentRoot)
- {
- // NOTE: Label bounds currently ignored if rendering is false
- this.graph.cellRenderer.redraw(state, false, this.isRendering());
- }
- }
-
- if (model.isEdge(cell) || model.isVertex(cell))
- {
- if (state.shape != null && state.shape.boundingBox != null)
- {
- bbox = state.shape.boundingBox.clone();
- }
-
- if (state.text != null && !this.graph.isLabelClipped(state.cell))
- {
- // Adds label bounding box to graph bounds
- if (state.text.boundingBox != null)
- {
- if (bbox != null)
- {
- bbox.add(state.text.boundingBox);
- }
- else
- {
- bbox = state.text.boundingBox.clone();
- }
- }
- }
- }
- }
-
- if (state != null && (!this.graph.isCellCollapsed(cell) ||
- cell == this.currentRoot))
- {
- var childCount = model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(cell, i);
- var bounds = this.validatePoints(state, child);
-
- if (bounds != null)
- {
- if (bbox == null)
- {
- bbox = bounds;
- }
- else
- {
- bbox.add(bounds);
- }
- }
- }
- }
-
- return bbox;
-};
-
-/**
- * Function: childMoved
- *
- * Invoked when a child state was moved as a result of late evaluation
- * of its position. This is invoked for relative edge children whose
- * position can only be determined after the points of the parent edge
- * are updated in validatePoints, and validates the bounds of all
- * descendants of the child using validateBounds.
- *
- * Parameters:
- *
- * parent - <mxCellState> that represents the parent state.
- * child - <mxCellState> that represents the child state.
- */
-mxGraphView.prototype.childMoved = function(parent, child)
-{
- var cell = child.cell;
-
- // Children of relative edge children need to validate
- // their bounds after their parent state was updated
- if (!this.graph.isCellCollapsed(cell) || cell == this.currentRoot)
- {
- var model = this.graph.getModel();
- var childCount = model.getChildCount(cell);
-
- for (var i = 0; i < childCount; i++)
- {
- this.validateBounds(child, model.getChildAt(cell, i));
- }
- }
-};
-
-/**
- * Function: updateFixedTerminalPoints
- *
- * Sets the initial absolute terminal points in the given state before the edge
- * style is computed.
- *
- * Parameters:
- *
- * edge - <mxCellState> whose initial terminal points should be updated.
- * source - <mxCellState> which represents the source terminal.
- * target - <mxCellState> which represents the target terminal.
- */
-mxGraphView.prototype.updateFixedTerminalPoints = function(edge, source, target)
-{
- this.updateFixedTerminalPoint(edge, source, true,
- this.graph.getConnectionConstraint(edge, source, true));
- this.updateFixedTerminalPoint(edge, target, false,
- this.graph.getConnectionConstraint(edge, target, false));
-};
-
-/**
- * Function: updateFixedTerminalPoint
- *
- * Sets the fixed source or target terminal point on the given edge.
- *
- * Parameters:
- *
- * edge - <mxCellState> whose terminal point should be updated.
- * terminal - <mxCellState> which represents the actual terminal.
- * source - Boolean that specifies if the terminal is the source.
- * constraint - <mxConnectionConstraint> that specifies the connection.
- */
-mxGraphView.prototype.updateFixedTerminalPoint = function(edge, terminal, source, constraint)
-{
- var pt = null;
-
- if (constraint != null)
- {
- pt = this.graph.getConnectionPoint(terminal, constraint);
- }
-
- if (pt == null && terminal == null)
- {
- var s = this.scale;
- var tr = this.translate;
- var orig = edge.origin;
- var geo = this.graph.getCellGeometry(edge.cell);
- pt = geo.getTerminalPoint(source);
-
- if (pt != null)
- {
- pt = new mxPoint(s * (tr.x + pt.x + orig.x),
- s * (tr.y + pt.y + orig.y));
- }
- }
-
- edge.setAbsoluteTerminalPoint(pt, source);
-};
-
-/**
- * Function: updatePoints
- *
- * Updates the absolute points in the given state using the specified array
- * of <mxPoints> as the relative points.
- *
- * Parameters:
- *
- * edge - <mxCellState> whose absolute points should be updated.
- * points - Array of <mxPoints> that constitute the relative points.
- * source - <mxCellState> that represents the source terminal.
- * target - <mxCellState> that represents the target terminal.
- */
-mxGraphView.prototype.updatePoints = function(edge, points, source, target)
-{
- if (edge != null)
- {
- var pts = [];
- pts.push(edge.absolutePoints[0]);
- var edgeStyle = this.getEdgeStyle(edge, points, source, target);
-
- if (edgeStyle != null)
- {
- var src = this.getTerminalPort(edge, source, true);
- var trg = this.getTerminalPort(edge, target, false);
-
- edgeStyle(edge, src, trg, points, pts);
- }
- else if (points != null)
- {
- for (var i = 0; i < points.length; i++)
- {
- if (points[i] != null)
- {
- var pt = mxUtils.clone(points[i]);
- pts.push(this.transformControlPoint(edge, pt));
- }
- }
- }
-
- var tmp = edge.absolutePoints;
- pts.push(tmp[tmp.length-1]);
-
- edge.absolutePoints = pts;
- }
-};
-
-/**
- * Function: transformControlPoint
- *
- * Transforms the given control point to an absolute point.
- */
-mxGraphView.prototype.transformControlPoint = function(state, pt)
-{
- var orig = state.origin;
-
- return new mxPoint(this.scale * (pt.x + this.translate.x + orig.x),
- this.scale * (pt.y + this.translate.y + orig.y));
-};
-
-/**
- * Function: getEdgeStyle
- *
- * Returns the edge style function to be used to render the given edge
- * state.
- */
-mxGraphView.prototype.getEdgeStyle = function(edge, points, source, target)
-{
- var edgeStyle = (source != null && source == target) ?
- mxUtils.getValue(edge.style, mxConstants.STYLE_LOOP,
- this.graph.defaultLoopStyle) :
- (!mxUtils.getValue(edge.style,
- mxConstants.STYLE_NOEDGESTYLE, false) ?
- edge.style[mxConstants.STYLE_EDGE] :
- null);
-
- // Converts string values to objects
- if (typeof(edgeStyle) == "string")
- {
- var tmp = mxStyleRegistry.getValue(edgeStyle);
-
- if (tmp == null && this.isAllowEval())
- {
- tmp = mxUtils.eval(edgeStyle);
- }
-
- edgeStyle = tmp;
- }
-
- if (typeof(edgeStyle) == "function")
- {
- return edgeStyle;
- }
-
- return null;
-};
-
-/**
- * Function: updateFloatingTerminalPoints
- *
- * Updates the terminal points in the given state after the edge style was
- * computed for the edge.
- *
- * Parameters:
- *
- * state - <mxCellState> whose terminal points should be updated.
- * source - <mxCellState> that represents the source terminal.
- * target - <mxCellState> that represents the target terminal.
- */
-mxGraphView.prototype.updateFloatingTerminalPoints = function(state, source, target)
-{
- var pts = state.absolutePoints;
- var p0 = pts[0];
- var pe = pts[pts.length - 1];
-
- if (pe == null && target != null)
- {
- this.updateFloatingTerminalPoint(state, target, source, false);
- }
-
- if (p0 == null && source != null)
- {
- this.updateFloatingTerminalPoint(state, source, target, true);
- }
-};
-
-/**
- * Function: updateFloatingTerminalPoint
- *
- * Updates the absolute terminal point in the given state for the given
- * start and end state, where start is the source if source is true.
- *
- * Parameters:
- *
- * edge - <mxCellState> whose terminal point should be updated.
- * start - <mxCellState> for the terminal on "this" side of the edge.
- * end - <mxCellState> for the terminal on the other side of the edge.
- * source - Boolean indicating if start is the source terminal state.
- */
-mxGraphView.prototype.updateFloatingTerminalPoint = function(edge, start, end, source)
-{
- start = this.getTerminalPort(edge, start, source);
- var next = this.getNextPoint(edge, end, source);
-
- var alpha = mxUtils.toRadians(Number(start.style[mxConstants.STYLE_ROTATION] || '0'));
- var center = new mxPoint(start.getCenterX(), start.getCenterY());
-
- if (alpha != 0)
- {
- var cos = Math.cos(-alpha);
- var sin = Math.sin(-alpha);
- next = mxUtils.getRotatedPoint(next, cos, sin, center);
- }
-
- var border = parseFloat(edge.style[mxConstants.STYLE_PERIMETER_SPACING] || 0);
- border += parseFloat(edge.style[(source) ?
- mxConstants.STYLE_SOURCE_PERIMETER_SPACING :
- mxConstants.STYLE_TARGET_PERIMETER_SPACING] || 0);
- var pt = this.getPerimeterPoint(start, next, this.graph.isOrthogonal(edge), border);
-
- if (alpha != 0)
- {
- var cos = Math.cos(alpha);
- var sin = Math.sin(alpha);
- pt = mxUtils.getRotatedPoint(pt, cos, sin, center);
- }
-
- edge.setAbsoluteTerminalPoint(pt, source);
-};
-
-/**
- * Function: getTerminalPort
- *
- * Returns an <mxCellState> that represents the source or target terminal or
- * port for the given edge.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the state of the edge.
- * terminal - <mxCellState> that represents the terminal.
- * source - Boolean indicating if the given terminal is the source terminal.
- */
-mxGraphView.prototype.getTerminalPort = function(state, terminal, source)
-{
- var key = (source) ? mxConstants.STYLE_SOURCE_PORT :
- mxConstants.STYLE_TARGET_PORT;
- var id = mxUtils.getValue(state.style, key);
-
- if (id != null)
- {
- var tmp = this.getState(this.graph.getModel().getCell(id));
-
- // Only uses ports where a cell state exists
- if (tmp != null)
- {
- terminal = tmp;
- }
- }
-
- return terminal;
-};
-
-/**
- * Function: getPerimeterPoint
- *
- * Returns an <mxPoint> that defines the location of the intersection point between
- * the perimeter and the line between the center of the shape and the given point.
- *
- * Parameters:
- *
- * terminal - <mxCellState> for the source or target terminal.
- * next - <mxPoint> that lies outside of the given terminal.
- * orthogonal - Boolean that specifies if the orthogonal projection onto
- * the perimeter should be returned. If this is false then the intersection
- * of the perimeter and the line between the next and the center point is
- * returned.
- * border - Optional border between the perimeter and the shape.
- */
-mxGraphView.prototype.getPerimeterPoint = function(terminal, next, orthogonal, border)
-{
- var point = null;
-
- if (terminal != null)
- {
- var perimeter = this.getPerimeterFunction(terminal);
-
- if (perimeter != null && next != null)
- {
- var bounds = this.getPerimeterBounds(terminal, border);
-
- if (bounds.width > 0 || bounds.height > 0)
- {
- point = perimeter(bounds, terminal, next, orthogonal);
- }
- }
-
- if (point == null)
- {
- point = this.getPoint(terminal);
- }
- }
-
- return point;
-};
-
-/**
- * Function: getRoutingCenterX
- *
- * Returns the x-coordinate of the center point for automatic routing.
- */
-mxGraphView.prototype.getRoutingCenterX = function (state)
-{
- var f = (state.style != null) ? parseFloat(state.style
- [mxConstants.STYLE_ROUTING_CENTER_X]) || 0 : 0;
-
- return state.getCenterX() + f * state.width;
-};
-
-/**
- * Function: getRoutingCenterY
- *
- * Returns the y-coordinate of the center point for automatic routing.
- */
-mxGraphView.prototype.getRoutingCenterY = function (state)
-{
- var f = (state.style != null) ? parseFloat(state.style
- [mxConstants.STYLE_ROUTING_CENTER_Y]) || 0 : 0;
-
- return state.getCenterY() + f * state.height;
-};
-
-/**
- * Function: getPerimeterBounds
- *
- * Returns the perimeter bounds for the given terminal, edge pair as an
- * <mxRectangle>.
- *
- * If you have a model where each terminal has a relative child that should
- * act as the graphical endpoint for a connection from/to the terminal, then
- * this method can be replaced as follows:
- *
- * (code)
- * var oldGetPerimeterBounds = mxGraphView.prototype.getPerimeterBounds;
- * mxGraphView.prototype.getPerimeterBounds = function(terminal, edge, isSource)
- * {
- * var model = this.graph.getModel();
- * var childCount = model.getChildCount(terminal.cell);
- *
- * if (childCount > 0)
- * {
- * var child = model.getChildAt(terminal.cell, 0);
- * var geo = model.getGeometry(child);
- *
- * if (geo != null &&
- * geo.relative)
- * {
- * var state = this.getState(child);
- *
- * if (state != null)
- * {
- * terminal = state;
- * }
- * }
- * }
- *
- * return oldGetPerimeterBounds.apply(this, arguments);
- * };
- * (end)
- *
- * Parameters:
- *
- * terminal - <mxCellState> that represents the terminal.
- * border - Number that adds a border between the shape and the perimeter.
- */
-mxGraphView.prototype.getPerimeterBounds = function(terminal, border)
-{
- border = (border != null) ? border : 0;
-
- if (terminal != null)
- {
- border += parseFloat(terminal.style[mxConstants.STYLE_PERIMETER_SPACING] || 0);
- }
-
- return terminal.getPerimeterBounds(border * this.scale);
-};
-
-/**
- * Function: getPerimeterFunction
- *
- * Returns the perimeter function for the given state.
- */
-mxGraphView.prototype.getPerimeterFunction = function(state)
-{
- var perimeter = state.style[mxConstants.STYLE_PERIMETER];
-
- // Converts string values to objects
- if (typeof(perimeter) == "string")
- {
- var tmp = mxStyleRegistry.getValue(perimeter);
-
- if (tmp == null && this.isAllowEval())
- {
- tmp = mxUtils.eval(perimeter);
- }
-
- perimeter = tmp;
- }
-
- if (typeof(perimeter) == "function")
- {
- return perimeter;
- }
-
- return null;
-};
-
-/**
- * Function: getNextPoint
- *
- * Returns the nearest point in the list of absolute points or the center
- * of the opposite terminal.
- *
- * Parameters:
- *
- * edge - <mxCellState> that represents the edge.
- * opposite - <mxCellState> that represents the opposite terminal.
- * source - Boolean indicating if the next point for the source or target
- * should be returned.
- */
-mxGraphView.prototype.getNextPoint = function(edge, opposite, source)
-{
- var pts = edge.absolutePoints;
- var point = null;
-
- if (pts != null && (source || pts.length > 2 || opposite == null))
- {
- var count = pts.length;
- point = pts[(source) ? Math.min(1, count - 1) : Math.max(0, count - 2)];
- }
-
- if (point == null && opposite != null)
- {
- point = new mxPoint(opposite.getCenterX(), opposite.getCenterY());
- }
-
- return point;
-};
-
-/**
- * Function: getVisibleTerminal
- *
- * Returns the nearest ancestor terminal that is visible. The edge appears
- * to be connected to this terminal on the display. The result of this method
- * is cached in <mxCellState.getVisibleTerminalState>.
- *
- * Parameters:
- *
- * edge - <mxCell> whose visible terminal should be returned.
- * source - Boolean that specifies if the source or target terminal
- * should be returned.
- */
-mxGraphView.prototype.getVisibleTerminal = function(edge, source)
-{
- var model = this.graph.getModel();
- var result = model.getTerminal(edge, source);
- var best = result;
-
- while (result != null && result != this.currentRoot)
- {
- if (!this.graph.isCellVisible(best) || this.graph.isCellCollapsed(result))
- {
- best = result;
- }
-
- result = model.getParent(result);
- }
-
- // Checks if the result is not a layer
- if (model.getParent(best) == model.getRoot())
- {
- best = null;
- }
-
- return best;
-};
-
-/**
- * Function: updateEdgeBounds
- *
- * Updates the given state using the bounding box of the absolute points.
- * Also updates <mxCellState.terminalDistance>, <mxCellState.length> and
- * <mxCellState.segments>.
- *
- * Parameters:
- *
- * state - <mxCellState> whose bounds should be updated.
- */
-mxGraphView.prototype.updateEdgeBounds = function(state)
-{
- var points = state.absolutePoints;
- state.length = 0;
-
- if (points != null && points.length > 0)
- {
- var p0 = points[0];
- var pe = points[points.length - 1];
-
- if (p0 == null || pe == null)
- {
- // Drops the edge state if the edge is not the root
- if (state.cell != this.currentRoot)
- {
- // Note: This condition normally occurs if a connected edge has a
- // null-terminal, ie. edge.source == null or edge.target == null,
- // and no corresponding terminal point defined, which happens for
- // example if the terminal-id was not resolved at cell decoding time.
- this.clear(state.cell, true);
- }
- }
- else
- {
- if (p0.x != pe.x || p0.y != pe.y)
- {
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
- state.terminalDistance = Math.sqrt(dx * dx + dy * dy);
- }
- else
- {
- state.terminalDistance = 0;
- }
-
- var length = 0;
- var segments = [];
- var pt = p0;
-
- if (pt != null)
- {
- var minX = pt.x;
- var minY = pt.y;
- var maxX = minX;
- var maxY = minY;
-
- for (var i = 1; i < points.length; i++)
- {
- var tmp = points[i];
-
- if (tmp != null)
- {
- var dx = pt.x - tmp.x;
- var dy = pt.y - tmp.y;
-
- var segment = Math.sqrt(dx * dx + dy * dy);
- segments.push(segment);
- length += segment;
-
- pt = tmp;
-
- minX = Math.min(pt.x, minX);
- minY = Math.min(pt.y, minY);
- maxX = Math.max(pt.x, maxX);
- maxY = Math.max(pt.y, maxY);
- }
- }
-
- state.length = length;
- state.segments = segments;
-
- var markerSize = 1; // TODO: include marker size
-
- state.x = minX;
- state.y = minY;
- state.width = Math.max(markerSize, maxX - minX);
- state.height = Math.max(markerSize, maxY - minY);
- }
- }
- }
-};
-
-/**
- * Function: getPoint
- *
- * Returns the absolute point on the edge for the given relative
- * <mxGeometry> as an <mxPoint>. The edge is represented by the given
- * <mxCellState>.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the state of the parent edge.
- * geometry - <mxGeometry> that represents the relative location.
- */
-mxGraphView.prototype.getPoint = function(state, geometry)
-{
- var x = state.getCenterX();
- var y = state.getCenterY();
-
- if (state.segments != null && (geometry == null || geometry.relative))
- {
- var gx = (geometry != null) ? geometry.x / 2 : 0;
- var pointCount = state.absolutePoints.length;
- var dist = (gx + 0.5) * state.length;
- var segment = state.segments[0];
- var length = 0;
- var index = 1;
-
- while (dist > length + segment && index < pointCount-1)
- {
- length += segment;
- segment = state.segments[index++];
- }
-
- var factor = (segment == 0) ? 0 : (dist - length) / segment;
- var p0 = state.absolutePoints[index-1];
- var pe = state.absolutePoints[index];
-
- if (p0 != null && pe != null)
- {
- var gy = 0;
- var offsetX = 0;
- var offsetY = 0;
-
- if (geometry != null)
- {
- gy = geometry.y;
- var offset = geometry.offset;
-
- if (offset != null)
- {
- offsetX = offset.x;
- offsetY = offset.y;
- }
- }
-
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
- var nx = (segment == 0) ? 0 : dy / segment;
- var ny = (segment == 0) ? 0 : dx / segment;
-
- x = p0.x + dx * factor + (nx * gy + offsetX) * this.scale;
- y = p0.y + dy * factor - (ny * gy - offsetY) * this.scale;
- }
- }
- else if (geometry != null)
- {
- var offset = geometry.offset;
-
- if (offset != null)
- {
- x += offset.x;
- y += offset.y;
- }
- }
-
- return new mxPoint(x, y);
-};
-
-/**
- * Function: getRelativePoint
- *
- * Gets the relative point that describes the given, absolute label
- * position for the given edge state.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the state of the parent edge.
- * x - Specifies the x-coordinate of the absolute label location.
- * y - Specifies the y-coordinate of the absolute label location.
- */
-mxGraphView.prototype.getRelativePoint = function(edgeState, x, y)
-{
- var model = this.graph.getModel();
- var geometry = model.getGeometry(edgeState.cell);
-
- if (geometry != null)
- {
- var pointCount = edgeState.absolutePoints.length;
-
- if (geometry.relative && pointCount > 1)
- {
- var totalLength = edgeState.length;
- var segments = edgeState.segments;
-
- // Works which line segment the point of the label is closest to
- var p0 = edgeState.absolutePoints[0];
- var pe = edgeState.absolutePoints[1];
- var minDist = mxUtils.ptSegDistSq(p0.x, p0.y, pe.x, pe.y, x, y);
-
- var index = 0;
- var tmp = 0;
- var length = 0;
-
- for (var i = 2; i < pointCount; i++)
- {
- tmp += segments[i - 2];
- pe = edgeState.absolutePoints[i];
- var dist = mxUtils.ptSegDistSq(p0.x, p0.y, pe.x, pe.y, x, y);
-
- if (dist <= minDist)
- {
- minDist = dist;
- index = i - 1;
- length = tmp;
- }
-
- p0 = pe;
- }
-
- var seg = segments[index];
- p0 = edgeState.absolutePoints[index];
- pe = edgeState.absolutePoints[index + 1];
-
- var x2 = p0.x;
- var y2 = p0.y;
-
- var x1 = pe.x;
- var y1 = pe.y;
-
- var px = x;
- var py = y;
-
- var xSegment = x2 - x1;
- var ySegment = y2 - y1;
-
- px -= x1;
- py -= y1;
- var projlenSq = 0;
-
- px = xSegment - px;
- py = ySegment - py;
- var dotprod = px * xSegment + py * ySegment;
-
- if (dotprod <= 0.0)
- {
- projlenSq = 0;
- }
- else
- {
- projlenSq = dotprod * dotprod
- / (xSegment * xSegment + ySegment * ySegment);
- }
-
- var projlen = Math.sqrt(projlenSq);
-
- if (projlen > seg)
- {
- projlen = seg;
- }
-
- var yDistance = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, pe
- .x, pe.y, x, y));
- var direction = mxUtils.relativeCcw(p0.x, p0.y, pe.x, pe.y, x, y);
-
- if (direction == -1)
- {
- yDistance = -yDistance;
- }
-
- // Constructs the relative point for the label
- return new mxPoint(((totalLength / 2 - length - projlen) / totalLength) * -2,
- yDistance / this.scale);
- }
- }
-
- return new mxPoint();
-};
-
-/**
- * Function: updateEdgeLabelOffset
- *
- * Updates <mxCellState.absoluteOffset> for the given state. The absolute
- * offset is normally used for the position of the edge label. Is is
- * calculated from the geometry as an absolute offset from the center
- * between the two endpoints if the geometry is absolute, or as the
- * relative distance between the center along the line and the absolute
- * orthogonal distance if the geometry is relative.
- *
- * Parameters:
- *
- * state - <mxCellState> whose absolute offset should be updated.
- */
-mxGraphView.prototype.updateEdgeLabelOffset = function(state)
-{
- var points = state.absolutePoints;
-
- state.absoluteOffset.x = state.getCenterX();
- state.absoluteOffset.y = state.getCenterY();
-
- if (points != null && points.length > 0 && state.segments != null)
- {
- var geometry = this.graph.getCellGeometry(state.cell);
-
- if (geometry.relative)
- {
- var offset = this.getPoint(state, geometry);
-
- if (offset != null)
- {
- state.absoluteOffset = offset;
- }
- }
- else
- {
- var p0 = points[0];
- var pe = points[points.length - 1];
-
- if (p0 != null && pe != null)
- {
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
- var x0 = 0;
- var y0 = 0;
-
- var off = geometry.offset;
-
- if (off != null)
- {
- x0 = off.x;
- y0 = off.y;
- }
-
- var x = p0.x + dx / 2 + x0 * this.scale;
- var y = p0.y + dy / 2 + y0 * this.scale;
-
- state.absoluteOffset.x = x;
- state.absoluteOffset.y = y;
- }
- }
- }
-};
-
-/**
- * Function: getState
- *
- * Returns the <mxCellState> for the given cell. If create is true, then
- * the state is created if it does not yet exist.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the <mxCellState> should be returned.
- * create - Optional boolean indicating if a new state should be created
- * if it does not yet exist. Default is false.
- */
-mxGraphView.prototype.getState = function(cell, create)
-{
- create = create || false;
- var state = null;
-
- if (cell != null)
- {
- state = this.states.get(cell);
-
- if (this.graph.isCellVisible(cell))
- {
- if (state == null && create && this.graph.isCellVisible(cell))
- {
- state = this.createState(cell);
- this.states.put(cell, state);
- }
- else if (create && state != null && this.updateStyle)
- {
- state.style = this.graph.getCellStyle(cell);
- }
- }
- }
-
- return state;
-};
-
-/**
- * Function: isRendering
- *
- * Returns <rendering>.
- */
-mxGraphView.prototype.isRendering = function()
-{
- return this.rendering;
-};
-
-/**
- * Function: setRendering
- *
- * Sets <rendering>.
- */
-mxGraphView.prototype.setRendering = function(value)
-{
- this.rendering = value;
-};
-
-/**
- * Function: isAllowEval
- *
- * Returns <allowEval>.
- */
-mxGraphView.prototype.isAllowEval = function()
-{
- return this.allowEval;
-};
-
-/**
- * Function: setAllowEval
- *
- * Sets <allowEval>.
- */
-mxGraphView.prototype.setAllowEval = function(value)
-{
- this.allowEval = value;
-};
-
-/**
- * Function: getStates
- *
- * Returns <states>.
- */
-mxGraphView.prototype.getStates = function()
-{
- return this.states;
-};
-
-/**
- * Function: setStates
- *
- * Sets <states>.
- */
-mxGraphView.prototype.setStates = function(value)
-{
- this.states = value;
-};
-
-/**
- * Function: getCellStates
- *
- * Returns the <mxCellStates> for the given array of <mxCells>. The array
- * contains all states that are not null, that is, the returned array may
- * have less elements than the given array. If no argument is given, then
- * this returns <states>.
- */
-mxGraphView.prototype.getCellStates = function(cells)
-{
- if (cells == null)
- {
- return this.states;
- }
- else
- {
- var result = [];
-
- for (var i = 0; i < cells.length; i++)
- {
- var state = this.getState(cells[i]);
-
- if (state != null)
- {
- result.push(state);
- }
- }
-
- return result;
- }
-};
-
-/**
- * Function: removeState
- *
- * Removes and returns the <mxCellState> for the given cell.
- *
- * Parameters:
- *
- * cell - <mxCell> for which the <mxCellState> should be removed.
- */
-mxGraphView.prototype.removeState = function(cell)
-{
- var state = null;
-
- if (cell != null)
- {
- state = this.states.remove(cell);
-
- if (state != null)
- {
- this.graph.cellRenderer.destroy(state);
- state.destroy();
- }
- }
-
- return state;
-};
-
-/**
- * Function: createState
- *
- * Creates and returns an <mxCellState> for the given cell and initializes
- * it using <mxCellRenderer.initialize>.
- *
- * Parameters:
- *
- * cell - <mxCell> for which a new <mxCellState> should be created.
- */
-mxGraphView.prototype.createState = function(cell)
-{
- var style = this.graph.getCellStyle(cell);
- var state = new mxCellState(this, cell, style);
- this.graph.cellRenderer.initialize(state, this.isRendering());
-
- return state;
-};
-
-/**
- * Function: getCanvas
- *
- * Returns the DOM node that contains the background-, draw- and
- * overlaypane.
- */
-mxGraphView.prototype.getCanvas = function()
-{
- return this.canvas;
-};
-
-/**
- * Function: getBackgroundPane
- *
- * Returns the DOM node that represents the background layer.
- */
-mxGraphView.prototype.getBackgroundPane = function()
-{
- return this.backgroundPane;
-};
-
-/**
- * Function: getDrawPane
- *
- * Returns the DOM node that represents the main drawing layer.
- */
-mxGraphView.prototype.getDrawPane = function()
-{
- return this.drawPane;
-};
-
-/**
- * Function: getOverlayPane
- *
- * Returns the DOM node that represents the topmost drawing layer.
- */
-mxGraphView.prototype.getOverlayPane = function()
-{
- return this.overlayPane;
-};
-
-/**
- * Function: isContainerEvent
- *
- * Returns true if the event origin is one of the drawing panes or
- * containers of the view.
- */
-mxGraphView.prototype.isContainerEvent = function(evt)
-{
- var source = mxEvent.getSource(evt);
-
- return (source == this.graph.container ||
- source.parentNode == this.backgroundPane ||
- (source.parentNode != null &&
- source.parentNode.parentNode == this.backgroundPane) ||
- source == this.canvas.parentNode ||
- source == this.canvas ||
- source == this.backgroundPane ||
- source == this.drawPane ||
- source == this.overlayPane);
-};
-
-/**
- * Function: isScrollEvent
- *
- * Returns true if the event origin is one of the scrollbars of the
- * container in IE. Such events are ignored.
- */
- mxGraphView.prototype.isScrollEvent = function(evt)
-{
- var offset = mxUtils.getOffset(this.graph.container);
- var pt = new mxPoint(evt.clientX - offset.x, evt.clientY - offset.y);
-
- var outWidth = this.graph.container.offsetWidth;
- var inWidth = this.graph.container.clientWidth;
-
- if (outWidth > inWidth && pt.x > inWidth + 2 && pt.x <= outWidth)
- {
- return true;
- }
-
- var outHeight = this.graph.container.offsetHeight;
- var inHeight = this.graph.container.clientHeight;
-
- if (outHeight > inHeight && pt.y > inHeight + 2 && pt.y <= outHeight)
- {
- return true;
- }
-
- return false;
-};
-
-/**
- * Function: init
- *
- * Initializes the graph event dispatch loop for the specified container
- * and invokes <create> to create the required DOM nodes for the display.
- */
-mxGraphView.prototype.init = function()
-{
- this.installListeners();
-
- // Creates the DOM nodes for the respective display dialect
- var graph = this.graph;
-
- if (graph.dialect == mxConstants.DIALECT_SVG)
- {
- this.createSvg();
- }
- else if (graph.dialect == mxConstants.DIALECT_VML)
- {
- this.createVml();
- }
- else
- {
- this.createHtml();
- }
-};
-
-/**
- * Function: installListeners
- *
- * Installs the required listeners in the container.
- */
-mxGraphView.prototype.installListeners = function()
-{
- var graph = this.graph;
- var container = graph.container;
-
- if (container != null)
- {
- var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
- var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
- var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
-
- // Adds basic listeners for graph event dispatching
- mxEvent.addListener(container, md,
- mxUtils.bind(this, function(evt)
- {
- // Workaround for touch-based device not transferring
- // the focus while editing with virtual keyboard
- if (mxClient.IS_TOUCH && graph.isEditing())
- {
- graph.stopEditing(!graph.isInvokesStopCellEditing());
- }
-
- // Condition to avoid scrollbar events starting a rubberband
- // selection
- if (this.isContainerEvent(evt) && ((!mxClient.IS_IE &&
- !mxClient.IS_GC && !mxClient.IS_OP && !mxClient.IS_SF) ||
- !this.isScrollEvent(evt)))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_DOWN,
- new mxMouseEvent(evt));
- }
- })
- );
- mxEvent.addListener(container, mm,
- mxUtils.bind(this, function(evt)
- {
- if (this.isContainerEvent(evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
- new mxMouseEvent(evt));
- }
- })
- );
- mxEvent.addListener(container, mu,
- mxUtils.bind(this, function(evt)
- {
- if (this.isContainerEvent(evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_UP,
- new mxMouseEvent(evt));
- }
- })
- );
-
- // Adds listener for double click handling on background
- mxEvent.addListener(container, 'dblclick',
- mxUtils.bind(this, function(evt)
- {
- graph.dblClick(evt);
- })
- );
-
- // Workaround for touch events which started on some DOM node
- // on top of the container, in which case the cells under the
- // mouse for the move and up events are not detected.
- var getState = function(evt)
- {
- var state = null;
-
- // Workaround for touch events which started on some DOM node
- // on top of the container, in which case the cells under the
- // mouse for the move and up events are not detected.
- if (mxClient.IS_TOUCH)
- {
- var x = mxEvent.getClientX(evt);
- var y = mxEvent.getClientY(evt);
-
- // Dispatches the drop event to the graph which
- // consumes and executes the source function
- var pt = mxUtils.convertPoint(container, x, y);
- state = graph.view.getState(graph.getCellAt(pt.x, pt.y));
- }
-
- return state;
- };
-
- // Adds basic listeners for graph event dispatching outside of the
- // container and finishing the handling of a single gesture
- // Implemented via graph event dispatch loop to avoid duplicate events
- // in Firefox and Chrome
- graph.addMouseListener(
- {
- mouseDown: function(sender, me)
- {
- graph.panningHandler.hideMenu();
- },
- mouseMove: function() { },
- mouseUp: function() { }
- });
- mxEvent.addListener(document, mm,
- mxUtils.bind(this, function(evt)
- {
- // Hides the tooltip if mouse is outside container
- if (graph.tooltipHandler != null &&
- graph.tooltipHandler.isHideOnHover())
- {
- graph.tooltipHandler.hide();
- }
-
- if (this.captureDocumentGesture && graph.isMouseDown &&
- !mxEvent.isConsumed(evt))
- {
- graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
- new mxMouseEvent(evt, getState(evt)));
- }
- })
- );
- mxEvent.addListener(document, mu,
- mxUtils.bind(this, function(evt)
- {
- if (this.captureDocumentGesture)
- {
- graph.fireMouseEvent(mxEvent.MOUSE_UP,
- new mxMouseEvent(evt));
- }
- })
- );
- }
-};
-
-/**
- * Function: create
- *
- * Creates the DOM nodes for the HTML display.
- */
-mxGraphView.prototype.createHtml = function()
-{
- var container = this.graph.container;
-
- if (container != null)
- {
- this.canvas = this.createHtmlPane('100%', '100%');
-
- // Uses minimal size for inner DIVs on Canvas. This is required
- // for correct event processing in IE. If we have an overlapping
- // DIV then the events on the cells are only fired for labels.
- this.backgroundPane = this.createHtmlPane('1px', '1px');
- this.drawPane = this.createHtmlPane('1px', '1px');
- this.overlayPane = this.createHtmlPane('1px', '1px');
-
- this.canvas.appendChild(this.backgroundPane);
- this.canvas.appendChild(this.drawPane);
- this.canvas.appendChild(this.overlayPane);
-
- container.appendChild(this.canvas);
-
- // Implements minWidth/minHeight in quirks mode
- if (mxClient.IS_QUIRKS)
- {
- var onResize = mxUtils.bind(this, function(evt)
- {
- var bounds = this.getGraphBounds();
- var width = bounds.x + bounds.width + this.graph.border;
- var height = bounds.y + bounds.height + this.graph.border;
-
- this.updateHtmlCanvasSize(width, height);
- });
-
- mxEvent.addListener(window, 'resize', onResize);
- }
- }
-};
-
-/**
- * Function: updateHtmlCanvasSize
- *
- * Updates the size of the HTML canvas.
- */
-mxGraphView.prototype.updateHtmlCanvasSize = function(width, height)
-{
- if (this.graph.container != null)
- {
- var ow = this.graph.container.offsetWidth;
- var oh = this.graph.container.offsetHeight;
-
- if (ow < width)
- {
- this.canvas.style.width = width + 'px';
- }
- else
- {
- this.canvas.style.width = '100%';
- }
-
- if (oh < height)
- {
- this.canvas.style.height = height + 'px';
- }
- else
- {
- this.canvas.style.height = '100%';
- }
- }
-};
-
-/**
- * Function: createHtmlPane
- *
- * Creates and returns a drawing pane in HTML (DIV).
- */
-mxGraphView.prototype.createHtmlPane = function(width, height)
-{
- var pane = document.createElement('DIV');
-
- if (width != null && height != null)
- {
- pane.style.position = 'absolute';
- pane.style.left = '0px';
- pane.style.top = '0px';
-
- pane.style.width = width;
- pane.style.height = height;
- }
- else
- {
- pane.style.position = 'relative';
- }
-
- return pane;
-};
-
-/**
- * Function: create
- *
- * Creates the DOM nodes for the VML display.
- */
-mxGraphView.prototype.createVml = function()
-{
- var container = this.graph.container;
-
- if (container != null)
- {
- var width = container.offsetWidth;
- var height = container.offsetHeight;
- this.canvas = this.createVmlPane(width, height);
-
- this.backgroundPane = this.createVmlPane(width, height);
- this.drawPane = this.createVmlPane(width, height);
- this.overlayPane = this.createVmlPane(width, height);
-
- this.canvas.appendChild(this.backgroundPane);
- this.canvas.appendChild(this.drawPane);
- this.canvas.appendChild(this.overlayPane);
-
- container.appendChild(this.canvas);
- }
-};
-
-/**
- * Function: createVmlPane
- *
- * Creates a drawing pane in VML (group).
- */
-mxGraphView.prototype.createVmlPane = function(width, height)
-{
- var pane = document.createElement('v:group');
-
- // At this point the width and height are potentially
- // uninitialized. That's OK.
- pane.style.position = 'absolute';
- pane.style.left = '0px';
- pane.style.top = '0px';
-
- pane.style.width = width+'px';
- pane.style.height = height+'px';
-
- pane.setAttribute('coordsize', width+','+height);
- pane.setAttribute('coordorigin', '0,0');
-
- return pane;
-};
-
-/**
- * Function: create
- *
- * Creates and returns the DOM nodes for the SVG display.
- */
-mxGraphView.prototype.createSvg = function()
-{
- var container = this.graph.container;
- this.canvas = document.createElementNS(mxConstants.NS_SVG, 'g');
-
- // For background image
- this.backgroundPane = document.createElementNS(mxConstants.NS_SVG, 'g');
- this.canvas.appendChild(this.backgroundPane);
-
- // Adds two layers (background is early feature)
- this.drawPane = document.createElementNS(mxConstants.NS_SVG, 'g');
- this.canvas.appendChild(this.drawPane);
-
- this.overlayPane = document.createElementNS(mxConstants.NS_SVG, 'g');
- this.canvas.appendChild(this.overlayPane);
-
- var root = document.createElementNS(mxConstants.NS_SVG, 'svg');
- root.style.width = '100%';
- root.style.height = '100%';
-
- if (mxClient.IS_IE)
- {
- root.style.marginBottom = '-4px';
- }
-
- root.appendChild(this.canvas);
-
- if (container != null)
- {
- container.appendChild(root);
-
- // Workaround for offset of container
- var style = mxUtils.getCurrentStyle(container);
-
- if (style.position == 'static')
- {
- container.style.position = 'relative';
- }
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroys the view and all its resources.
- */
-mxGraphView.prototype.destroy = function()
-{
- var root = (this.canvas != null) ? this.canvas.ownerSVGElement : null;
-
- if (root == null)
- {
- root = this.canvas;
- }
-
- if (root != null && root.parentNode != null)
- {
- this.clear(this.currentRoot, true);
- mxEvent.removeAllListeners(document);
- mxEvent.release(this.graph.container);
- root.parentNode.removeChild(root);
-
- this.canvas = null;
- this.backgroundPane = null;
- this.drawPane = null;
- this.overlayPane = null;
- }
-};
-
-/**
- * Class: mxCurrentRootChange
- *
- * Action to change the current root in a view.
- *
- * Constructor: mxCurrentRootChange
- *
- * Constructs a change of the current root in the given view.
- */
-function mxCurrentRootChange(view, root)
-{
- this.view = view;
- this.root = root;
- this.previous = root;
- this.isUp = root == null;
-
- if (!this.isUp)
- {
- var tmp = this.view.currentRoot;
- var model = this.view.graph.getModel();
-
- while (tmp != null)
- {
- if (tmp == root)
- {
- this.isUp = true;
- break;
- }
-
- tmp = model.getParent(tmp);
- }
- }
-};
-
-/**
- * Function: execute
- *
- * Changes the current root of the view.
- */
-mxCurrentRootChange.prototype.execute = function()
-{
- var tmp = this.view.currentRoot;
- this.view.currentRoot = this.previous;
- this.previous = tmp;
-
- var translate = this.view.graph.getTranslateForRoot(this.view.currentRoot);
-
- if (translate != null)
- {
- this.view.translate = new mxPoint(-translate.x, -translate.y);
- }
-
- var name = (this.isUp) ? mxEvent.UP : mxEvent.DOWN;
- this.view.fireEvent(new mxEventObject(name,
- 'root', this.view.currentRoot, 'previous', this.previous));
-
- if (this.isUp)
- {
- this.view.clear(this.view.currentRoot, true);
- this.view.validate();
- }
- else
- {
- this.view.refresh();
- }
-
- this.isUp = !this.isUp;
-};
diff --git a/src/js/view/mxLayoutManager.js b/src/js/view/mxLayoutManager.js
deleted file mode 100644
index ee8ec65..0000000
--- a/src/js/view/mxLayoutManager.js
+++ /dev/null
@@ -1,375 +0,0 @@
-/**
- * $Id: mxLayoutManager.js,v 1.21 2012-01-04 10:01:16 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxLayoutManager
- *
- * Implements a layout manager that updates the layout for a given transaction.
- *
- * Example:
- *
- * (code)
- * var layoutMgr = new mxLayoutManager(graph);
- * layoutMgr.getLayout = function(cell)
- * {
- * return layout;
- * };
- * (end)
- *
- * Event: mxEvent.LAYOUT_CELLS
- *
- * Fires between begin- and endUpdate after all cells have been layouted in
- * <layoutCells>. The <code>cells</code> property contains all cells that have
- * been passed to <layoutCells>.
- *
- * Constructor: mxLayoutManager
- *
- * Constructs a new automatic layout for the given graph.
- *
- * Arguments:
- *
- * graph - Reference to the enclosing graph.
- */
-function mxLayoutManager(graph)
-{
- // Executes the layout before the changes are dispatched
- this.undoHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled())
- {
- this.beforeUndo(evt.getProperty('edit'));
- }
- });
-
- // Notifies the layout of a move operation inside a parent
- this.moveHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled())
- {
- this.cellsMoved(evt.getProperty('cells'), evt.getProperty('event'));
- }
- });
-
- this.setGraph(graph);
-};
-
-/**
- * Extends mxEventSource.
- */
-mxLayoutManager.prototype = new mxEventSource();
-mxLayoutManager.prototype.constructor = mxLayoutManager;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxLayoutManager.prototype.graph = null;
-
-/**
- * Variable: bubbling
- *
- * Specifies if the layout should bubble along
- * the cell hierarchy. Default is true.
- */
-mxLayoutManager.prototype.bubbling = true;
-
-/**
- * Variable: enabled
- *
- * Specifies if event handling is enabled. Default is true.
- */
-mxLayoutManager.prototype.enabled = true;
-
-/**
- * Variable: updateHandler
- *
- * Holds the function that handles the endUpdate event.
- */
-mxLayoutManager.prototype.updateHandler = null;
-
-/**
- * Variable: moveHandler
- *
- * Holds the function that handles the move event.
- */
-mxLayoutManager.prototype.moveHandler = null;
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxLayoutManager.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxLayoutManager.prototype.setEnabled = function(enabled)
-{
- this.enabled = enabled;
-};
-
-/**
- * Function: isBubbling
- *
- * Returns true if a layout should bubble, that is, if the parent layout
- * should be executed whenever a cell layout (layout of the children of
- * a cell) has been executed. This implementation returns <bubbling>.
- */
-mxLayoutManager.prototype.isBubbling = function()
-{
- return this.bubbling;
-};
-
-/**
- * Function: setBubbling
- *
- * Sets <bubbling>.
- */
-mxLayoutManager.prototype.setBubbling = function(value)
-{
- this.bubbling = value;
-};
-
-/**
- * Function: getGraph
- *
- * Returns the graph that this layout operates on.
- */
-mxLayoutManager.prototype.getGraph = function()
-{
- return this.graph;
-};
-
-/**
- * Function: setGraph
- *
- * Sets the graph that the layouts operate on.
- */
-mxLayoutManager.prototype.setGraph = function(graph)
-{
- if (this.graph != null)
- {
- var model = this.graph.getModel();
- model.removeListener(this.undoHandler);
- this.graph.removeListener(this.moveHandler);
- }
-
- this.graph = graph;
-
- if (this.graph != null)
- {
- var model = this.graph.getModel();
- model.addListener(mxEvent.BEFORE_UNDO, this.undoHandler);
- this.graph.addListener(mxEvent.MOVE_CELLS, this.moveHandler);
- }
-};
-
-/**
- * Function: getLayout
- *
- * Returns the layout to be executed for the given graph and parent.
- */
-mxLayoutManager.prototype.getLayout = function(parent)
-{
- return null;
-};
-
-/**
- * Function: beforeUndo
- *
- * Called from the undoHandler.
- *
- * Parameters:
- *
- * cell - Array of <mxCells> that have been moved.
- * evt - Mouse event that represents the mousedown.
- */
-mxLayoutManager.prototype.beforeUndo = function(undoableEdit)
-{
- var cells = this.getCellsForChanges(undoableEdit.changes);
- var model = this.getGraph().getModel();
-
- // Adds all parent ancestors
- if (this.isBubbling())
- {
- var tmp = model.getParents(cells);
-
- while (tmp.length > 0)
- {
- cells = cells.concat(tmp);
- tmp = model.getParents(tmp);
- }
- }
-
- this.layoutCells(mxUtils.sortCells(cells, false));
-};
-
-/**
- * Function: cellsMoved
- *
- * Called from the moveHandler.
- *
- * Parameters:
- *
- * cell - Array of <mxCells> that have been moved.
- * evt - Mouse event that represents the mousedown.
- */
-mxLayoutManager.prototype.cellsMoved = function(cells, evt)
-{
- if (cells != null &&
- evt != null)
- {
- var point = mxUtils.convertPoint(this.getGraph().container,
- mxEvent.getClientX(evt), mxEvent.getClientY(evt));
- var model = this.getGraph().getModel();
-
- // Checks if a layout exists to take care of the moving
- for (var i = 0; i < cells.length; i++)
- {
- var layout = this.getLayout(model.getParent(cells[i]));
-
- if (layout != null)
- {
- layout.moveCell(cells[i], point.x, point.y);
- }
- }
- }
-};
-
-/**
- * Function: getCellsForEdit
- *
- * Returns the cells to be layouted for the given sequence of changes.
- */
-mxLayoutManager.prototype.getCellsForChanges = function(changes)
-{
- var result = [];
- var hash = new Object();
-
- for (var i = 0; i < changes.length; i++)
- {
- var change = changes[i];
-
- if (change instanceof mxRootChange)
- {
- return [];
- }
- else
- {
- var cells = this.getCellsForChange(change);
-
- for (var j = 0; j < cells.length; j++)
- {
- if (cells[j] != null)
- {
- var id = mxCellPath.create(cells[j]);
-
- if (hash[id] == null)
- {
- hash[id] = cells[j];
- result.push(cells[j]);
- }
- }
- }
- }
- }
-
- return result;
-};
-
-/**
- * Function: getCellsForChange
- *
- * Executes all layouts which have been scheduled during the
- * changes.
- */
-mxLayoutManager.prototype.getCellsForChange = function(change)
-{
- var model = this.getGraph().getModel();
-
- if (change instanceof mxChildChange)
- {
- return [change.child, change.previous, model.getParent(change.child)];
- }
- else if (change instanceof mxTerminalChange ||
- change instanceof mxGeometryChange)
- {
- return [change.cell, model.getParent(change.cell)];
- }
-
- return [];
-};
-
-/**
- * Function: layoutCells
- *
- * Executes all layouts which have been scheduled during the
- * changes.
- */
-mxLayoutManager.prototype.layoutCells = function(cells)
-{
- if (cells.length > 0)
- {
- // Invokes the layouts while removing duplicates
- var model = this.getGraph().getModel();
-
- model.beginUpdate();
- try
- {
- var last = null;
-
- for (var i = 0; i < cells.length; i++)
- {
- if (cells[i] != model.getRoot() &&
- cells[i] != last)
- {
- last = cells[i];
- this.executeLayout(this.getLayout(last), last);
- }
- }
-
- this.fireEvent(new mxEventObject(mxEvent.LAYOUT_CELLS, 'cells', cells));
- }
- finally
- {
- model.endUpdate();
- }
- }
-};
-
-/**
- * Function: executeLayout
- *
- * Executes the given layout on the given parent.
- */
-mxLayoutManager.prototype.executeLayout = function(layout, parent)
-{
- if (layout != null && parent != null)
- {
- layout.execute(parent);
- }
-};
-
-/**
- * Function: destroy
- *
- * Removes all handlers from the <graph> and deletes the reference to it.
- */
-mxLayoutManager.prototype.destroy = function()
-{
- this.setGraph(null);
-};
diff --git a/src/js/view/mxMultiplicity.js b/src/js/view/mxMultiplicity.js
deleted file mode 100644
index c927d3f..0000000
--- a/src/js/view/mxMultiplicity.js
+++ /dev/null
@@ -1,257 +0,0 @@
-/**
- * $Id: mxMultiplicity.js,v 1.24 2010-11-03 14:52:40 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxMultiplicity
- *
- * Defines invalid connections along with the error messages that they produce.
- * To add or remove rules on a graph, you must add/remove instances of this
- * class to <mxGraph.multiplicities>.
- *
- * Example:
- *
- * (code)
- * graph.multiplicities.push(new mxMultiplicity(
- * true, 'rectangle', null, null, 0, 2, ['circle'],
- * 'Only 2 targets allowed',
- * 'Only circle targets allowed'));
- * (end)
- *
- * Defines a rule where each rectangle must be connected to no more than 2
- * circles and no other types of targets are allowed.
- *
- * Constructor: mxMultiplicity
- *
- * Instantiate class mxMultiplicity in order to describe allowed
- * connections in a graph. Not all constraints can be enforced while
- * editing, some must be checked at validation time. The <countError> and
- * <typeError> are treated as resource keys in <mxResources>.
- *
- * Parameters:
- *
- * source - Boolean indicating if this rule applies to the source or target
- * terminal.
- * type - Type of the source or target terminal that this rule applies to.
- * See <type> for more information.
- * attr - Optional attribute name to match the source or target terminal.
- * value - Optional attribute value to match the source or target terminal.
- * min - Minimum number of edges for this rule. Default is 1.
- * max - Maximum number of edges for this rule. n means infinite. Default
- * is n.
- * validNeighbors - Array of types of the opposite terminal for which this
- * rule applies.
- * countError - Error to be displayed for invalid number of edges.
- * typeError - Error to be displayed for invalid opposite terminals.
- * validNeighborsAllowed - Optional boolean indicating if the array of
- * opposite types should be valid or invalid.
- */
-function mxMultiplicity(source, type, attr, value, min, max,
- validNeighbors, countError, typeError, validNeighborsAllowed)
-{
- this.source = source;
- this.type = type;
- this.attr = attr;
- this.value = value;
- this.min = (min != null) ? min : 0;
- this.max = (max != null) ? max : 'n';
- this.validNeighbors = validNeighbors;
- this.countError = mxResources.get(countError) || countError;
- this.typeError = mxResources.get(typeError) || typeError;
- this.validNeighborsAllowed = (validNeighborsAllowed != null) ?
- validNeighborsAllowed : true;
-};
-
-/**
- * Variable: type
- *
- * Defines the type of the source or target terminal. The type is a string
- * passed to <mxUtils.isNode> together with the source or target vertex
- * value as the first argument.
- */
-mxMultiplicity.prototype.type = null;
-
-/**
- * Variable: attr
- *
- * Optional string that specifies the attributename to be passed to
- * <mxUtils.isNode> to check if the rule applies to a cell.
- */
-mxMultiplicity.prototype.attr = null;
-
-/**
- * Variable: value
- *
- * Optional string that specifies the value of the attribute to be passed
- * to <mxUtils.isNode> to check if the rule applies to a cell.
- */
-mxMultiplicity.prototype.value = null;
-
-/**
- * Variable: source
- *
- * Boolean that specifies if the rule is applied to the source or target
- * terminal of an edge.
- */
-mxMultiplicity.prototype.source = null;
-
-/**
- * Variable: min
- *
- * Defines the minimum number of connections for which this rule applies.
- * Default is 0.
- */
-mxMultiplicity.prototype.min = null;
-
-/**
- * Variable: max
- *
- * Defines the maximum number of connections for which this rule applies.
- * A value of 'n' means unlimited times. Default is 'n'.
- */
-mxMultiplicity.prototype.max = null;
-
-/**
- * Variable: validNeighbors
- *
- * Holds an array of strings that specify the type of neighbor for which
- * this rule applies. The strings are used in <mxCell.is> on the opposite
- * terminal to check if the rule applies to the connection.
- */
-mxMultiplicity.prototype.validNeighbors = null;
-
-/**
- * Variable: validNeighborsAllowed
- *
- * Boolean indicating if the list of validNeighbors are those that are allowed
- * for this rule or those that are not allowed for this rule.
- */
-mxMultiplicity.prototype.validNeighborsAllowed = true;
-
-/**
- * Variable: countError
- *
- * Holds the localized error message to be displayed if the number of
- * connections for which the rule applies is smaller than <min> or greater
- * than <max>.
- */
-mxMultiplicity.prototype.countError = null;
-
-/**
- * Variable: typeError
- *
- * Holds the localized error message to be displayed if the type of the
- * neighbor for a connection does not match the rule.
- */
-mxMultiplicity.prototype.typeError = null;
-
-/**
- * Function: check
- *
- * Checks the multiplicity for the given arguments and returns the error
- * for the given connection or null if the multiplicity does not apply.
- *
- * Parameters:
- *
- * graph - Reference to the enclosing <mxGraph> instance.
- * edge - <mxCell> that represents the edge to validate.
- * source - <mxCell> that represents the source terminal.
- * target - <mxCell> that represents the target terminal.
- * sourceOut - Number of outgoing edges from the source terminal.
- * targetIn - Number of incoming edges for the target terminal.
- */
-mxMultiplicity.prototype.check = function(graph, edge, source, target, sourceOut, targetIn)
-{
- var error = '';
-
- if ((this.source && this.checkTerminal(graph, source, edge)) ||
- (!this.source && this.checkTerminal(graph, target, edge)))
- {
- if (this.countError != null &&
- ((this.source && (this.max == 0 || (sourceOut >= this.max))) ||
- (!this.source && (this.max == 0 || (targetIn >= this.max)))))
- {
- error += this.countError + '\n';
- }
-
- if (this.validNeighbors != null && this.typeError != null && this.validNeighbors.length > 0)
- {
- var isValid = this.checkNeighbors(graph, edge, source, target);
-
- if (!isValid)
- {
- error += this.typeError + '\n';
- }
- }
- }
-
- return (error.length > 0) ? error : null;
-};
-
-/**
- * Function: checkNeighbors
- *
- * Checks if there are any valid neighbours in <validNeighbors>. This is only
- * called if <validNeighbors> is a non-empty array.
- */
-mxMultiplicity.prototype.checkNeighbors = function(graph, edge, source, target)
-{
- var sourceValue = graph.model.getValue(source);
- var targetValue = graph.model.getValue(target);
- var isValid = !this.validNeighborsAllowed;
- var valid = this.validNeighbors;
-
- for (var j = 0; j < valid.length; j++)
- {
- if (this.source &&
- this.checkType(graph, targetValue, valid[j]))
- {
- isValid = this.validNeighborsAllowed;
- break;
- }
- else if (!this.source &&
- this.checkType(graph, sourceValue, valid[j]))
- {
- isValid = this.validNeighborsAllowed;
- break;
- }
- }
-
- return isValid;
-};
-
-/**
- * Function: checkTerminal
- *
- * Checks the given terminal cell and returns true if this rule applies. The
- * given cell is the source or target of the given edge, depending on
- * <source>. This implementation uses <checkType> on the terminal's value.
- */
-mxMultiplicity.prototype.checkTerminal = function(graph, terminal, edge)
-{
- var value = graph.model.getValue(terminal);
-
- return this.checkType(graph, value, this.type, this.attr, this.value);
-};
-
-/**
- * Function: checkType
- *
- * Checks the type of the given value.
- */
-mxMultiplicity.prototype.checkType = function(graph, value, type, attr, attrValue)
-{
- if (value != null)
- {
- if (!isNaN(value.nodeType)) // Checks if value is a DOM node
- {
- return mxUtils.isNode(value, type, attr, attrValue);
- }
- else
- {
- return value == type;
- }
- }
-
- return false;
-};
diff --git a/src/js/view/mxOutline.js b/src/js/view/mxOutline.js
deleted file mode 100644
index a0d6fd3..0000000
--- a/src/js/view/mxOutline.js
+++ /dev/null
@@ -1,649 +0,0 @@
-/**
- * $Id: mxOutline.js,v 1.81 2012-06-20 14:13:37 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxOutline
- *
- * Implements an outline (aka overview) for a graph. Set <updateOnPan> to true
- * to enable updates while the source graph is panning.
- *
- * Example:
- *
- * (code)
- * var outline = new mxOutline(graph, div);
- * (end)
- *
- * If the selection border in the outline appears behind the contents of the
- * graph, then you can use the following code. (This may happen when using a
- * transparent container for the outline in IE.)
- *
- * (code)
- * mxOutline.prototype.graphRenderHint = mxConstants.RENDERING_HINT_EXACT;
- * (end)
- *
- * To move the graph to the top, left corner the following code can be used.
- *
- * (code)
- * var scale = graph.view.scale;
- * var bounds = graph.getGraphBounds();
- * graph.view.setTranslate(-bounds.x / scale, -bounds.y / scale);
- * (end)
- *
- * To toggle the suspended mode, the following can be used.
- *
- * (code)
- * outline.suspended = !outln.suspended;
- * if (!outline.suspended)
- * {
- * outline.update(true);
- * }
- * (end)
- *
- * Constructor: mxOutline
- *
- * Constructs a new outline for the specified graph inside the given
- * container.
- *
- * Parameters:
- *
- * source - <mxGraph> to create the outline for.
- * container - DOM node that will contain the outline.
- */
-function mxOutline(source, container)
-{
- this.source = source;
-
- if (container != null)
- {
- this.init(container);
- }
-};
-
-/**
- * Function: source
- *
- * Reference to the source <mxGraph>.
- */
-mxOutline.prototype.source = null;
-
-/**
- * Function: outline
- *
- * Reference to the outline <mxGraph>.
- */
-mxOutline.prototype.outline = null;
-
-/**
- * Function: graphRenderHint
- *
- * Renderhint to be used for the outline graph. Default is faster.
- */
-mxOutline.prototype.graphRenderHint = mxConstants.RENDERING_HINT_FASTER;
-
-/**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
-mxOutline.prototype.enabled = true;
-
-/**
- * Variable: showViewport
- *
- * Specifies a viewport rectangle should be shown. Default is true.
- */
-mxOutline.prototype.showViewport = true;
-
-/**
- * Variable: border
- *
- * Border to be added at the bottom and right. Default is 10.
- */
-mxOutline.prototype.border = 10;
-
-/**
- * Variable: enabled
- *
- * Specifies the size of the sizer handler. Default is 8.
- */
-mxOutline.prototype.sizerSize = 8;
-
-/**
- * Variable: updateOnPan
- *
- * Specifies if <update> should be called for <mxEvent.PAN> in the source
- * graph. Default is false.
- */
-mxOutline.prototype.updateOnPan = false;
-
-/**
- * Variable: sizerImage
- *
- * Optional <mxImage> to be used for the sizer. Default is null.
- */
-mxOutline.prototype.sizerImage = null;
-
-/**
- * Variable: suspended
- *
- * Optional boolean flag to suspend updates. Default is false. This flag will
- * also suspend repaints of the outline. To toggle this switch, use the
- * following code.
- *
- * (code)
- * nav.suspended = !nav.suspended;
- *
- * if (!nav.suspended)
- * {
- * nav.update(true);
- * }
- * (end)
- */
-mxOutline.prototype.suspended = false;
-
-/**
- * Function: init
- *
- * Initializes the outline inside the given container.
- */
-mxOutline.prototype.init = function(container)
-{
- this.outline = new mxGraph(container, this.source.getModel(), this.graphRenderHint, this.source.getStylesheet());
- this.outline.foldingEnabled = false;
- this.outline.autoScroll = false;
-
- // Do not repaint when suspended
- var outlineGraphModelChanged = this.outline.graphModelChanged;
- this.outline.graphModelChanged = mxUtils.bind(this, function(changes)
- {
- if (!this.suspended && this.outline != null)
- {
- outlineGraphModelChanged.apply(this.outline, arguments);
- }
- });
-
- // Enables faster painting in SVG
- if (mxClient.IS_SVG)
- {
- var node = this.outline.getView().getCanvas().parentNode;
- node.setAttribute('shape-rendering', 'optimizeSpeed');
- node.setAttribute('image-rendering', 'optimizeSpeed');
- }
-
- // Hides cursors and labels
- this.outline.labelsVisible = false;
- this.outline.setEnabled(false);
-
- this.updateHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (!this.suspended && !this.active)
- {
- this.update();
- }
- });
-
- // Updates the scale of the outline after a change of the main graph
- this.source.getModel().addListener(mxEvent.CHANGE, this.updateHandler);
- this.outline.addMouseListener(this);
-
- // Adds listeners to keep the outline in sync with the source graph
- var view = this.source.getView();
- view.addListener(mxEvent.SCALE, this.updateHandler);
- view.addListener(mxEvent.TRANSLATE, this.updateHandler);
- view.addListener(mxEvent.SCALE_AND_TRANSLATE, this.updateHandler);
- view.addListener(mxEvent.DOWN, this.updateHandler);
- view.addListener(mxEvent.UP, this.updateHandler);
-
- // Updates blue rectangle on scroll
- mxEvent.addListener(this.source.container, 'scroll', this.updateHandler);
-
- this.panHandler = mxUtils.bind(this, function(sender)
- {
- if (this.updateOnPan)
- {
- this.updateHandler.apply(this, arguments);
- }
- });
- this.source.addListener(mxEvent.PAN, this.panHandler);
-
- // Refreshes the graph in the outline after a refresh of the main graph
- this.refreshHandler = mxUtils.bind(this, function(sender)
- {
- this.outline.setStylesheet(this.source.getStylesheet());
- this.outline.refresh();
- });
- this.source.addListener(mxEvent.REFRESH, this.refreshHandler);
-
- // Creates the blue rectangle for the viewport
- this.bounds = new mxRectangle(0, 0, 0, 0);
- this.selectionBorder = new mxRectangleShape(this.bounds, null,
- mxConstants.OUTLINE_COLOR, mxConstants.OUTLINE_STROKEWIDTH);
- this.selectionBorder.dialect =
- (this.outline.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- this.selectionBorder.crisp = true;
- this.selectionBorder.init(this.outline.getView().getOverlayPane());
- mxEvent.redirectMouseEvents(this.selectionBorder.node, this.outline);
- this.selectionBorder.node.style.background = '';
-
- // Creates a small blue rectangle for sizing (sizer handle)
- this.sizer = this.createSizer();
- this.sizer.init(this.outline.getView().getOverlayPane());
-
- if (this.enabled)
- {
- this.sizer.node.style.cursor = 'pointer';
- }
-
- // Redirects all events from the sizerhandle to the outline
- mxEvent.addListener(this.sizer.node, (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown',
- mxUtils.bind(this, function(evt)
- {
- this.outline.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt));
- })
- );
-
- this.selectionBorder.node.style.display = (this.showViewport) ? '' : 'none';
- this.sizer.node.style.display = this.selectionBorder.node.style.display;
- this.selectionBorder.node.style.cursor = 'move';
-
- this.update(false);
-};
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxOutline.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * value - Boolean that specifies the new enabled state.
- */
-mxOutline.prototype.setEnabled = function(value)
-{
- this.enabled = value;
-};
-
-/**
- * Function: setZoomEnabled
- *
- * Enables or disables the zoom handling by showing or hiding the respective
- * handle.
- *
- * Parameters:
- *
- * value - Boolean that specifies the new enabled state.
- */
-mxOutline.prototype.setZoomEnabled = function(value)
-{
- this.sizer.node.style.visibility = (value) ? 'visible' : 'hidden';
-};
-
-/**
- * Function: refresh
- *
- * Invokes <update> and revalidate the outline. This method is deprecated.
- */
-mxOutline.prototype.refresh = function()
-{
- this.update(true);
-};
-
-/**
- * Function: createSizer
- *
- * Creates the shape used as the sizer.
- */
-mxOutline.prototype.createSizer = function()
-{
- if (this.sizerImage != null)
- {
- var sizer = new mxImageShape(new mxRectangle(0, 0, this.sizerImage.width, this.sizerImage.height), this.sizerImage.src);
- sizer.dialect = this.outline.dialect;
-
- return sizer;
- }
- else
- {
- var sizer = new mxRectangleShape(new mxRectangle(0, 0, this.sizerSize, this.sizerSize),
- mxConstants.OUTLINE_HANDLE_FILLCOLOR, mxConstants.OUTLINE_HANDLE_STROKECOLOR);
- sizer.dialect = this.outline.dialect;
- sizer.crisp = true;
-
- return sizer;
- }
-};
-
-/**
- * Function: getSourceContainerSize
- *
- * Returns the size of the source container.
- */
-mxOutline.prototype.getSourceContainerSize = function()
-{
- return new mxRectangle(0, 0, this.source.container.scrollWidth, this.source.container.scrollHeight);
-};
-
-/**
- * Function: getOutlineOffset
- *
- * Returns the offset for drawing the outline graph.
- */
-mxOutline.prototype.getOutlineOffset = function(scale)
-{
- return null;
-};
-
-/**
- * Function: update
- *
- * Updates the outline.
- */
-mxOutline.prototype.update = function(revalidate)
-{
- if (this.source != null)
- {
- var sourceScale = this.source.view.scale;
- var scaledGraphBounds = this.source.getGraphBounds();
- var unscaledGraphBounds = new mxRectangle(scaledGraphBounds.x / sourceScale + this.source.panDx,
- scaledGraphBounds.y / sourceScale + this.source.panDy, scaledGraphBounds.width / sourceScale,
- scaledGraphBounds.height / sourceScale);
-
- var unscaledFinderBounds = new mxRectangle(0, 0,
- this.source.container.clientWidth / sourceScale,
- this.source.container.clientHeight / sourceScale);
-
- var union = unscaledGraphBounds.clone();
- union.add(unscaledFinderBounds);
-
- // Zooms to the scrollable area if that is bigger than the graph
- var size = this.getSourceContainerSize();
- var completeWidth = Math.max(size.width / sourceScale, union.width);
- var completeHeight = Math.max(size.height / sourceScale, union.height);
-
- var availableWidth = Math.max(0, this.outline.container.clientWidth - this.border);
- var availableHeight = Math.max(0, this.outline.container.clientHeight - this.border);
-
- var outlineScale = Math.min(availableWidth / completeWidth, availableHeight / completeHeight);
- var scale = outlineScale;
-
- if (scale > 0)
- {
- if (this.outline.getView().scale != scale)
- {
- this.outline.getView().scale = scale;
- revalidate = true;
- }
-
- var navView = this.outline.getView();
-
- if (navView.currentRoot != this.source.getView().currentRoot)
- {
- navView.setCurrentRoot(this.source.getView().currentRoot);
- }
-
- var t = this.source.view.translate;
- var tx = t.x + this.source.panDx;
- var ty = t.y + this.source.panDy;
-
- var off = this.getOutlineOffset(scale);
-
- if (off != null)
- {
- tx += off.x;
- ty += off.y;
- }
-
- if (unscaledGraphBounds.x < 0)
- {
- tx = tx - unscaledGraphBounds.x;
- }
- if (unscaledGraphBounds.y < 0)
- {
- ty = ty - unscaledGraphBounds.y;
- }
-
- if (navView.translate.x != tx || navView.translate.y != ty)
- {
- navView.translate.x = tx;
- navView.translate.y = ty;
- revalidate = true;
- }
-
- // Prepares local variables for computations
- var t2 = navView.translate;
- scale = this.source.getView().scale;
- var scale2 = scale / navView.scale;
- var scale3 = 1.0 / navView.scale;
- var container = this.source.container;
-
- // Updates the bounds of the viewrect in the navigation
- this.bounds = new mxRectangle(
- (t2.x - t.x - this.source.panDx) / scale3,
- (t2.y - t.y - this.source.panDy) / scale3,
- (container.clientWidth / scale2),
- (container.clientHeight / scale2));
-
- // Adds the scrollbar offset to the finder
- this.bounds.x += this.source.container.scrollLeft * navView.scale / scale;
- this.bounds.y += this.source.container.scrollTop * navView.scale / scale;
-
- var b = this.selectionBorder.bounds;
-
- if (b.x != this.bounds.x || b.y != this.bounds.y || b.width != this.bounds.width || b.height != this.bounds.height)
- {
- this.selectionBorder.bounds = this.bounds;
- this.selectionBorder.redraw();
- }
-
- // Updates the bounds of the zoom handle at the bottom right
- var b = this.sizer.bounds;
- var b2 = new mxRectangle(this.bounds.x + this.bounds.width - b.width / 2,
- this.bounds.y + this.bounds.height - b.height / 2, b.width, b.height);
-
- if (b.x != b2.x || b.y != b2.y || b.width != b2.width || b.height != b2.height)
- {
- this.sizer.bounds = b2;
-
- // Avoids update of visibility in redraw for VML
- if (this.sizer.node.style.visibility != 'hidden')
- {
- this.sizer.redraw();
- }
- }
-
- if (revalidate)
- {
- this.outline.view.revalidate();
- }
- }
- }
-};
-
-/**
- * Function: mouseDown
- *
- * Handles the event by starting a translation or zoom.
- */
-mxOutline.prototype.mouseDown = function(sender, me)
-{
- if (this.enabled && this.showViewport)
- {
- this.zoom = me.isSource(this.sizer);
- this.startX = me.getX();
- this.startY = me.getY();
- this.active = true;
-
- if (this.source.useScrollbarsForPanning &&
- mxUtils.hasScrollbars(this.source.container))
- {
- this.dx0 = this.source.container.scrollLeft;
- this.dy0 = this.source.container.scrollTop;
- }
- else
- {
- this.dx0 = 0;
- this.dy0 = 0;
- }
- }
-
- me.consume();
-};
-
-/**
- * Function: mouseMove
- *
- * Handles the event by previewing the viewrect in <graph> and updating the
- * rectangle that represents the viewrect in the outline.
- */
-mxOutline.prototype.mouseMove = function(sender, me)
-{
- if (this.active)
- {
- this.selectionBorder.node.style.display = (this.showViewport) ? '' : 'none';
- this.sizer.node.style.display = this.selectionBorder.node.style.display;
-
- var dx = me.getX() - this.startX;
- var dy = me.getY() - this.startY;
- var bounds = null;
-
- if (!this.zoom)
- {
- // Previews the panning on the source graph
- var scale = this.outline.getView().scale;
- bounds = new mxRectangle(this.bounds.x + dx,
- this.bounds.y + dy, this.bounds.width, this.bounds.height);
- this.selectionBorder.bounds = bounds;
- this.selectionBorder.redraw();
- dx /= scale;
- dx *= this.source.getView().scale;
- dy /= scale;
- dy *= this.source.getView().scale;
- this.source.panGraph(-dx - this.dx0, -dy - this.dy0);
- }
- else
- {
- // Does *not* preview zooming on the source graph
- var container = this.source.container;
- var viewRatio = container.clientWidth / container.clientHeight;
- dy = dx / viewRatio;
- bounds = new mxRectangle(this.bounds.x,
- this.bounds.y,
- Math.max(1, this.bounds.width + dx),
- Math.max(1, this.bounds.height + dy));
- this.selectionBorder.bounds = bounds;
- this.selectionBorder.redraw();
- }
-
- // Updates the zoom handle
- var b = this.sizer.bounds;
- this.sizer.bounds = new mxRectangle(
- bounds.x + bounds.width - b.width / 2,
- bounds.y + bounds.height - b.height / 2,
- b.width, b.height);
-
- // Avoids update of visibility in redraw for VML
- if (this.sizer.node.style.visibility != 'hidden')
- {
- this.sizer.redraw();
- }
-
- me.consume();
- }
-};
-
-/**
- * Function: mouseUp
- *
- * Handles the event by applying the translation or zoom to <graph>.
- */
-mxOutline.prototype.mouseUp = function(sender, me)
-{
- if (this.active)
- {
- var dx = me.getX() - this.startX;
- var dy = me.getY() - this.startY;
-
- if (Math.abs(dx) > 0 || Math.abs(dy) > 0)
- {
- if (!this.zoom)
- {
- // Applies the new translation if the source
- // has no scrollbars
- if (!this.source.useScrollbarsForPanning ||
- !mxUtils.hasScrollbars(this.source.container))
- {
- this.source.panGraph(0, 0);
- dx /= this.outline.getView().scale;
- dy /= this.outline.getView().scale;
- var t = this.source.getView().translate;
- this.source.getView().setTranslate(t.x - dx, t.y - dy);
- }
- }
- else
- {
- // Applies the new zoom
- var w = this.selectionBorder.bounds.width;
- var scale = this.source.getView().scale;
- this.source.zoomTo(scale - (dx * scale) / w, false);
- }
-
- this.update();
- me.consume();
- }
-
- // Resets the state of the handler
- this.index = null;
- this.active = false;
- }
-};
-
-/**
- * Function: destroy
- *
- * Destroy this outline and removes all listeners from <source>.
- */
-mxOutline.prototype.destroy = function()
-{
- if (this.source != null)
- {
- this.source.removeListener(this.panHandler);
- this.source.removeListener(this.refreshHandler);
- this.source.getModel().removeListener(this.updateHandler);
- this.source.getView().removeListener(this.updateHandler);
- mxEvent.addListener(this.source.container, 'scroll', this.updateHandler);
- this.source = null;
- }
-
- if (this.outline != null)
- {
- this.outline.removeMouseListener(this);
- this.outline.destroy();
- this.outline = null;
- }
-
- if (this.selectionBorder != null)
- {
- this.selectionBorder.destroy();
- this.selectionBorder = null;
- }
-
- if (this.sizer != null)
- {
- this.sizer.destroy();
- this.sizer = null;
- }
-};
diff --git a/src/js/view/mxPerimeter.js b/src/js/view/mxPerimeter.js
deleted file mode 100644
index 7aaa187..0000000
--- a/src/js/view/mxPerimeter.js
+++ /dev/null
@@ -1,484 +0,0 @@
-/**
- * $Id: mxPerimeter.js,v 1.28 2012-01-11 09:06:56 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxPerimeter =
-{
- /**
- * Class: mxPerimeter
- *
- * Provides various perimeter functions to be used in a style
- * as the value of <mxConstants.STYLE_PERIMETER>. Perimeters for
- * rectangle, circle, rhombus and triangle are available.
- *
- * Example:
- *
- * (code)
- * <add as="perimeter">mxPerimeter.RightAngleRectanglePerimeter</add>
- * (end)
- *
- * Or programmatically:
- *
- * (code)
- * style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
- * (end)
- *
- * When adding new perimeter functions, it is recommended to use the
- * mxPerimeter-namespace as follows:
- *
- * (code)
- * mxPerimeter.CustomPerimeter = function (bounds, vertex, next, orthogonal)
- * {
- * var x = 0; // Calculate x-coordinate
- * var y = 0; // Calculate y-coordainte
- *
- * return new mxPoint(x, y);
- * }
- * (end)
- *
- * The new perimeter should then be registered in the <mxStyleRegistry> as follows:
- * (code)
- * mxStyleRegistry.putValue('customPerimeter', mxPerimeter.CustomPerimeter);
- * (end)
- *
- * The custom perimeter above can now be used in a specific vertex as follows:
- *
- * (code)
- * model.setStyle(vertex, 'perimeter=customPerimeter');
- * (end)
- *
- * Note that the key of the <mxStyleRegistry> entry for the function should
- * be used in string values, unless <mxGraphView.allowEval> is true, in
- * which case you can also use mxPerimeter.CustomPerimeter for the value in
- * the cell style above.
- *
- * Or it can be used for all vertices in the graph as follows:
- *
- * (code)
- * var style = graph.getStylesheet().getDefaultVertexStyle();
- * style[mxConstants.STYLE_PERIMETER] = mxPerimeter.CustomPerimeter;
- * (end)
- *
- * Note that the object can be used directly when programmatically setting
- * the value, but the key in the <mxStyleRegistry> should be used when
- * setting the value via a key, value pair in a cell style.
- *
- * The parameters are explained in <RectanglePerimeter>.
- *
- * Function: RectanglePerimeter
- *
- * Describes a rectangular perimeter for the given bounds.
- *
- * Parameters:
- *
- * bounds - <mxRectangle> that represents the absolute bounds of the
- * vertex.
- * vertex - <mxCellState> that represents the vertex.
- * next - <mxPoint> that represents the nearest neighbour point on the
- * given edge.
- * orthogonal - Boolean that specifies if the orthogonal projection onto
- * the perimeter should be returned. If this is false then the intersection
- * of the perimeter and the line between the next and the center point is
- * returned.
- */
- RectanglePerimeter: function (bounds, vertex, next, orthogonal)
- {
- var cx = bounds.getCenterX();
- var cy = bounds.getCenterY();
- var dx = next.x - cx;
- var dy = next.y - cy;
- var alpha = Math.atan2(dy, dx);
- var p = new mxPoint(0, 0);
- var pi = Math.PI;
- var pi2 = Math.PI/2;
- var beta = pi2 - alpha;
- var t = Math.atan2(bounds.height, bounds.width);
-
- if (alpha < -pi + t || alpha > pi - t)
- {
- // Left edge
- p.x = bounds.x;
- p.y = cy - bounds.width * Math.tan(alpha) / 2;
- }
- else if (alpha < -t)
- {
- // Top Edge
- p.y = bounds.y;
- p.x = cx - bounds.height * Math.tan(beta) / 2;
- }
- else if (alpha < t)
- {
- // Right Edge
- p.x = bounds.x + bounds.width;
- p.y = cy + bounds.width * Math.tan(alpha) / 2;
- }
- else
- {
- // Bottom Edge
- p.y = bounds.y + bounds.height;
- p.x = cx + bounds.height * Math.tan(beta) / 2;
- }
-
- if (orthogonal)
- {
- if (next.x >= bounds.x &&
- next.x <= bounds.x + bounds.width)
- {
- p.x = next.x;
- }
- else if (next.y >= bounds.y &&
- next.y <= bounds.y + bounds.height)
- {
- p.y = next.y;
- }
- if (next.x < bounds.x)
- {
- p.x = bounds.x;
- }
- else if (next.x > bounds.x + bounds.width)
- {
- p.x = bounds.x + bounds.width;
- }
- if (next.y < bounds.y)
- {
- p.y = bounds.y;
- }
- else if (next.y > bounds.y + bounds.height)
- {
- p.y = bounds.y + bounds.height;
- }
- }
-
- return p;
- },
-
- /**
- * Function: EllipsePerimeter
- *
- * Describes an elliptic perimeter. See <RectanglePerimeter>
- * for a description of the parameters.
- */
- EllipsePerimeter: function (bounds, vertex, next, orthogonal)
- {
- var x = bounds.x;
- var y = bounds.y;
- var a = bounds.width / 2;
- var b = bounds.height / 2;
- var cx = x + a;
- var cy = y + b;
- var px = next.x;
- var py = next.y;
-
- // Calculates straight line equation through
- // point and ellipse center y = d * x + h
- var dx = parseInt(px - cx);
- var dy = parseInt(py - cy);
-
- if (dx == 0 && dy != 0)
- {
- return new mxPoint(cx, cy + b * dy / Math.abs(dy));
- }
- else if (dx == 0 && dy == 0)
- {
- return new mxPoint(px, py);
- }
-
- if (orthogonal)
- {
- if (py >= y && py <= y + bounds.height)
- {
- var ty = py - cy;
- var tx = Math.sqrt(a*a*(1-(ty*ty)/(b*b))) || 0;
-
- if (px <= x)
- {
- tx = -tx;
- }
-
- return new mxPoint(cx+tx, py);
- }
-
- if (px >= x && px <= x + bounds.width)
- {
- var tx = px - cx;
- var ty = Math.sqrt(b*b*(1-(tx*tx)/(a*a))) || 0;
-
- if (py <= y)
- {
- ty = -ty;
- }
-
- return new mxPoint(px, cy+ty);
- }
- }
-
- // Calculates intersection
- var d = dy / dx;
- var h = cy - d * cx;
- var e = a * a * d * d + b * b;
- var f = -2 * cx * e;
- var g = a * a * d * d * cx * cx +
- b * b * cx * cx -
- a * a * b * b;
- var det = Math.sqrt(f * f - 4 * e * g);
-
- // Two solutions (perimeter points)
- var xout1 = (-f + det) / (2 * e);
- var xout2 = (-f - det) / (2 * e);
- var yout1 = d * xout1 + h;
- var yout2 = d * xout2 + h;
- var dist1 = Math.sqrt(Math.pow((xout1 - px), 2)
- + Math.pow((yout1 - py), 2));
- var dist2 = Math.sqrt(Math.pow((xout2 - px), 2)
- + Math.pow((yout2 - py), 2));
-
- // Correct solution
- var xout = 0;
- var yout = 0;
-
- if (dist1 < dist2)
- {
- xout = xout1;
- yout = yout1;
- }
- else
- {
- xout = xout2;
- yout = yout2;
- }
-
- return new mxPoint(xout, yout);
- },
-
- /**
- * Function: RhombusPerimeter
- *
- * Describes a rhombus (aka diamond) perimeter. See <RectanglePerimeter>
- * for a description of the parameters.
- */
- RhombusPerimeter: function (bounds, vertex, next, orthogonal)
- {
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
-
- var cx = x + w / 2;
- var cy = y + h / 2;
-
- var px = next.x;
- var py = next.y;
-
- // Special case for intersecting the diamond's corners
- if (cx == px)
- {
- if (cy > py)
- {
- return new mxPoint(cx, y); // top
- }
- else
- {
- return new mxPoint(cx, y + h); // bottom
- }
- }
- else if (cy == py)
- {
- if (cx > px)
- {
- return new mxPoint(x, cy); // left
- }
- else
- {
- return new mxPoint(x + w, cy); // right
- }
- }
-
- var tx = cx;
- var ty = cy;
-
- if (orthogonal)
- {
- if (px >= x && px <= x + w)
- {
- tx = px;
- }
- else if (py >= y && py <= y + h)
- {
- ty = py;
- }
- }
-
- // In which quadrant will the intersection be?
- // set the slope and offset of the border line accordingly
- if (px < cx)
- {
- if (py < cy)
- {
- return mxUtils.intersection(px, py, tx, ty, cx, y, x, cy);
- }
- else
- {
- return mxUtils.intersection(px, py, tx, ty, cx, y + h, x, cy);
- }
- }
- else if (py < cy)
- {
- return mxUtils.intersection(px, py, tx, ty, cx, y, x + w, cy);
- }
- else
- {
- return mxUtils.intersection(px, py, tx, ty, cx, y + h, x + w, cy);
- }
- },
-
- /**
- * Function: TrianglePerimeter
- *
- * Describes a triangle perimeter. See <RectanglePerimeter>
- * for a description of the parameters.
- */
- TrianglePerimeter: function (bounds, vertex, next, orthogonal)
- {
- var direction = (vertex != null) ?
- vertex.style[mxConstants.STYLE_DIRECTION] : null;
- var vertical = direction == mxConstants.DIRECTION_NORTH ||
- direction == mxConstants.DIRECTION_SOUTH;
-
- var x = bounds.x;
- var y = bounds.y;
- var w = bounds.width;
- var h = bounds.height;
-
- var cx = x + w / 2;
- var cy = y + h / 2;
-
- var start = new mxPoint(x, y);
- var corner = new mxPoint(x + w, cy);
- var end = new mxPoint(x, y + h);
-
- if (direction == mxConstants.DIRECTION_NORTH)
- {
- start = end;
- corner = new mxPoint(cx, y);
- end = new mxPoint(x + w, y + h);
- }
- else if (direction == mxConstants.DIRECTION_SOUTH)
- {
- corner = new mxPoint(cx, y + h);
- end = new mxPoint(x + w, y);
- }
- else if (direction == mxConstants.DIRECTION_WEST)
- {
- start = new mxPoint(x + w, y);
- corner = new mxPoint(x, cy);
- end = new mxPoint(x + w, y + h);
- }
-
- var dx = next.x - cx;
- var dy = next.y - cy;
-
- var alpha = (vertical) ? Math.atan2(dx, dy) : Math.atan2(dy, dx);
- var t = (vertical) ? Math.atan2(w, h) : Math.atan2(h, w);
-
- var base = false;
-
- if (direction == mxConstants.DIRECTION_NORTH ||
- direction == mxConstants.DIRECTION_WEST)
- {
- base = alpha > -t && alpha < t;
- }
- else
- {
- base = alpha < -Math.PI + t || alpha > Math.PI - t;
- }
-
- var result = null;
-
- if (base)
- {
- if (orthogonal && ((vertical && next.x >= start.x && next.x <= end.x) ||
- (!vertical && next.y >= start.y && next.y <= end.y)))
- {
- if (vertical)
- {
- result = new mxPoint(next.x, start.y);
- }
- else
- {
- result = new mxPoint(start.x, next.y);
- }
- }
- else
- {
- if (direction == mxConstants.DIRECTION_NORTH)
- {
- result = new mxPoint(x + w / 2 + h * Math.tan(alpha) / 2,
- y + h);
- }
- else if (direction == mxConstants.DIRECTION_SOUTH)
- {
- result = new mxPoint(x + w / 2 - h * Math.tan(alpha) / 2,
- y);
- }
- else if (direction == mxConstants.DIRECTION_WEST)
- {
- result = new mxPoint(x + w, y + h / 2 +
- w * Math.tan(alpha) / 2);
- }
- else
- {
- result = new mxPoint(x, y + h / 2 -
- w * Math.tan(alpha) / 2);
- }
- }
- }
- else
- {
- if (orthogonal)
- {
- var pt = new mxPoint(cx, cy);
-
- if (next.y >= y && next.y <= y + h)
- {
- pt.x = (vertical) ? cx : (
- (direction == mxConstants.DIRECTION_WEST) ?
- x + w : x);
- pt.y = next.y;
- }
- else if (next.x >= x && next.x <= x + w)
- {
- pt.x = next.x;
- pt.y = (!vertical) ? cy : (
- (direction == mxConstants.DIRECTION_NORTH) ?
- y + h : y);
- }
-
- // Compute angle
- dx = next.x - pt.x;
- dy = next.y - pt.y;
-
- cx = pt.x;
- cy = pt.y;
- }
-
- if ((vertical && next.x <= x + w / 2) ||
- (!vertical && next.y <= y + h / 2))
- {
- result = mxUtils.intersection(next.x, next.y, cx, cy,
- start.x, start.y, corner.x, corner.y);
- }
- else
- {
- result = mxUtils.intersection(next.x, next.y, cx, cy,
- corner.x, corner.y, end.x, end.y);
- }
- }
-
- if (result == null)
- {
- result = new mxPoint(cx, cy);
- }
-
- return result;
- }
-};
diff --git a/src/js/view/mxPrintPreview.js b/src/js/view/mxPrintPreview.js
deleted file mode 100644
index 24a65e6..0000000
--- a/src/js/view/mxPrintPreview.js
+++ /dev/null
@@ -1,801 +0,0 @@
-/**
- * $Id: mxPrintPreview.js,v 1.61 2012-05-15 14:12:40 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxPrintPreview
- *
- * Implements printing of a diagram across multiple pages. The following opens
- * a print preview for an existing graph:
- *
- * (code)
- * var preview = new mxPrintPreview(graph);
- * preview.open();
- * (end)
- *
- * Use <mxUtils.getScaleForPageCount> as follows in order to print the graph
- * across a given number of pages:
- *
- * (code)
- * var pageCount = mxUtils.prompt('Enter page count', '1');
- *
- * if (pageCount != null)
- * {
- * var scale = mxUtils.getScaleForPageCount(pageCount, graph);
- * var preview = new mxPrintPreview(graph, scale);
- * preview.open();
- * }
- * (end)
- *
- * Headers:
- *
- * Apart from setting the title argument in the mxPrintPreview constructor you
- * can override <renderPage> as follows to add a header to any page:
- *
- * (code)
- * var oldRenderPage = mxPrintPreview.prototype.renderPage;
- * mxPrintPreview.prototype.renderPage = function(w, h, dx, dy, scale, pageNumber)
- * {
- * var div = oldRenderPage.apply(this, arguments);
- *
- * var header = document.createElement('div');
- * header.style.position = 'absolute';
- * header.style.top = '0px';
- * header.style.width = '100%';
- * header.style.textAlign = 'right';
- * mxUtils.write(header, 'Your header here - Page ' + pageNumber + ' / ' + this.pageCount);
- * div.firstChild.appendChild(header);
- *
- * return div;
- * };
- * (end)
- *
- * Page Format:
- *
- * For landscape printing, use <mxConstants.PAGE_FORMAT_A4_LANDSCAPE> as
- * the pageFormat in <mxUtils.getScaleForPageCount> and <mxPrintPreview>.
- * Keep in mind that one can not set the defaults for the print dialog
- * of the operating system from JavaScript so the user must manually choose
- * a page format that matches this setting.
- *
- * You can try passing the following CSS directive to <open> to set the
- * page format in the print dialog to landscape. However, this CSS
- * directive seems to be ignored in most major browsers, including IE.
- *
- * (code)
- * @page {
- * size: landscape;
- * }
- * (end)
- *
- * Note that the print preview behaves differently in IE when used from the
- * filesystem or via HTTP so printing should always be tested via HTTP.
- *
- * If you are using a DOCTYPE in the source page you can override <getDoctype>
- * and provide the same DOCTYPE for the print preview if required. Here is
- * an example for IE8 standards mode.
- *
- * (code)
- * var preview = new mxPrintPreview(graph);
- * preview.getDoctype = function()
- * {
- * return '<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=5,IE=8" ><![endif]-->';
- * };
- * preview.open();
- * (end)
- *
- * Constructor: mxPrintPreview
- *
- * Constructs a new print preview for the given parameters.
- *
- * Parameters:
- *
- * graph - <mxGraph> to be previewed.
- * scale - Optional scale of the output. Default is 1 / <mxGraph.pageScale>.
- * border - Border in pixels along each side of every page. Note that the
- * actual print function in the browser will add another border for
- * printing.
- * pageFormat - <mxRectangle> that specifies the page format (in pixels).
- * This should match the page format of the printer. Default uses the
- * <mxGraph.pageFormat> of the given graph.
- * x0 - Optional left offset of the output. Default is 0.
- * y0 - Optional top offset of the output. Default is 0.
- * borderColor - Optional color of the page border. Default is no border.
- * Note that a border is sometimes useful to highlight the printed page
- * border in the print preview of the browser.
- * title - Optional string that is used for the window title. Default
- * is 'Printer-friendly version'.
- * pageSelector - Optional boolean that specifies if the page selector
- * should appear in the window with the print preview. Default is true.
- */
-function mxPrintPreview(graph, scale, pageFormat, border, x0, y0, borderColor, title, pageSelector)
-{
- this.graph = graph;
- this.scale = (scale != null) ? scale : 1 / graph.pageScale;
- this.border = (border != null) ? border : 0;
- this.pageFormat = (pageFormat != null) ? pageFormat : graph.pageFormat;
- this.title = (title != null) ? title : 'Printer-friendly version';
- this.x0 = (x0 != null) ? x0 : 0;
- this.y0 = (y0 != null) ? y0 : 0;
- this.borderColor = borderColor;
- this.pageSelector = (pageSelector != null) ? pageSelector : true;
-};
-
-/**
- * Variable: graph
- *
- * Reference to the <mxGraph> that should be previewed.
- */
-mxPrintPreview.prototype.graph = null;
-
-/**
- * Variable: pageFormat
- *
- * Holds the <mxRectangle> that defines the page format.
- */
-mxPrintPreview.prototype.pageFormat = null;
-
-/**
- * Variable: scale
- *
- * Holds the scale of the print preview.
- */
-mxPrintPreview.prototype.scale = null;
-
-/**
- * Variable: border
- *
- * The border inset around each side of every page in the preview. This is set
- * to 0 if autoOrigin is false.
- */
-mxPrintPreview.prototype.border = 0;
-
-/**
-/**
- * Variable: x0
- *
- * Holds the horizontal offset of the output.
- */
-mxPrintPreview.prototype.x0 = 0;
-
-/**
- * Variable: y0
- *
- * Holds the vertical offset of the output.
- */
-mxPrintPreview.prototype.y0 = 0;
-
-/**
- * Variable: autoOrigin
- *
- * Specifies if the origin should be automatically computed based on the top,
- * left corner of the actual diagram contents. If this is set to false then the
- * values for <x0> and <y0> will be overridden in <open>. Default is true.
- */
-mxPrintPreview.prototype.autoOrigin = true;
-
-/**
- * Variable: printOverlays
- *
- * Specifies if overlays should be printed. Default is false.
- */
-mxPrintPreview.prototype.printOverlays = false;
-
-/**
- * Variable: borderColor
- *
- * Holds the color value for the page border.
- */
-mxPrintPreview.prototype.borderColor = null;
-
-/**
- * Variable: title
- *
- * Holds the title of the preview window.
- */
-mxPrintPreview.prototype.title = null;
-
-/**
- * Variable: pageSelector
- *
- * Boolean that specifies if the page selector should be
- * displayed. Default is true.
- */
-mxPrintPreview.prototype.pageSelector = null;
-
-/**
- * Variable: wnd
- *
- * Reference to the preview window.
- */
-mxPrintPreview.prototype.wnd = null;
-
-/**
- * Variable: pageCount
- *
- * Holds the actual number of pages in the preview.
- */
-mxPrintPreview.prototype.pageCount = 0;
-
-/**
- * Function: getWindow
- *
- * Returns <wnd>.
- */
-mxPrintPreview.prototype.getWindow = function()
-{
- return this.wnd;
-};
-
-/**
- * Function: getDocType
- *
- * Returns the string that should go before the HTML tag in the print preview
- * page. This implementation returns an empty string.
- */
-mxPrintPreview.prototype.getDoctype = function()
-{
- return '';
-};
-
-/**
- * Function: open
- *
- * Shows the print preview window. The window is created here if it does
- * not exist.
- *
- * Parameters:
- *
- * css - Optional CSS string to be used in the new page's head section.
- */
-mxPrintPreview.prototype.open = function(css)
-{
- // Closing the window while the page is being rendered may cause an
- // exception in IE. This and any other exceptions are simply ignored.
- var previousInitializeOverlay = this.graph.cellRenderer.initializeOverlay;
- var div = null;
-
- try
- {
- // Temporarily overrides the method to redirect rendering of overlays
- // to the draw pane so that they are visible in the printout
- if (this.printOverlays)
- {
- this.graph.cellRenderer.initializeOverlay = function(state, overlay)
- {
- overlay.init(state.view.getDrawPane());
- };
- }
-
- if (this.wnd == null)
- {
- this.wnd = window.open();
- var doc = this.wnd.document;
- var dt = this.getDoctype();
-
- if (dt != null && dt.length > 0)
- {
- doc.writeln(dt);
- }
-
- doc.writeln('<html>');
- doc.writeln('<head>');
- this.writeHead(doc, css);
- doc.writeln('</head>');
- doc.writeln('<body class="mxPage">');
-
- // Adds all required stylesheets and namespaces
- mxClient.link('stylesheet', mxClient.basePath + '/css/common.css', doc);
-
- if (mxClient.IS_IE && document.documentMode != 9)
- {
- doc.namespaces.add('v', 'urn:schemas-microsoft-com:vml');
- doc.namespaces.add('o', 'urn:schemas-microsoft-com:office:office');
- var ss = doc.createStyleSheet();
- ss.cssText = 'v\\:*{behavior:url(#default#VML)}o\\:*{behavior:url(#default#VML)}';
- mxClient.link('stylesheet', mxClient.basePath + '/css/explorer.css', doc);
- }
-
- // Computes the horizontal and vertical page count
- var bounds = this.graph.getGraphBounds().clone();
- var currentScale = this.graph.getView().getScale();
- var sc = currentScale / this.scale;
- var tr = this.graph.getView().getTranslate();
-
- // Uses the absolute origin with no offset for all printing
- if (!this.autoOrigin)
- {
- this.x0 = -tr.x * this.scale;
- this.y0 = -tr.y * this.scale;
- bounds.width += bounds.x;
- bounds.height += bounds.y;
- bounds.x = 0;
- bounds.y = 0;
- this.border = 0;
- }
-
- // Compute the unscaled, untranslated bounds to find
- // the number of vertical and horizontal pages
- bounds.width /= sc;
- bounds.height /= sc;
-
- // Store the available page area
- var availableWidth = this.pageFormat.width - (this.border * 2);
- var availableHeight = this.pageFormat.height - (this.border * 2);
-
- var hpages = Math.max(1, Math.ceil((bounds.width + this.x0) / availableWidth));
- var vpages = Math.max(1, Math.ceil((bounds.height + this.y0) / availableHeight));
- this.pageCount = hpages * vpages;
-
- var writePageSelector = mxUtils.bind(this, function()
- {
- if (this.pageSelector && (vpages > 1 || hpages > 1))
- {
- var table = this.createPageSelector(vpages, hpages);
- doc.body.appendChild(table);
-
- // Workaround for position: fixed which isn't working in IE
- if (mxClient.IS_IE)
- {
- table.style.position = 'absolute';
-
- var update = function()
- {
- table.style.top = (doc.body.scrollTop + 10) + 'px';
- };
-
- mxEvent.addListener(this.wnd, 'scroll', function(evt)
- {
- update();
- });
-
- mxEvent.addListener(this.wnd, 'resize', function(evt)
- {
- update();
- });
- }
- }
- });
-
- // Stores pages for later retrieval
- var pages = null;
-
- // Workaround for aspect of image shapes updated asynchronously
- // in VML so we need to fetch the markup of the DIV containing
- // the image after the udpate of the style of the DOM node.
- // LATER: Allow document for display markup to be customized.
- if (mxClient.IS_IE && document.documentMode != 9)
- {
- pages = [];
-
- // Overrides asynchronous loading of images for fetching HTML markup
- var waitCounter = 0;
- var isDone = false;
-
- var mxImageShapeScheduleUpdateAspect = mxImageShape.prototype.scheduleUpdateAspect;
- var mxImageShapeUpdateAspect = mxImageShape.prototype.updateAspect;
-
- var writePages = function()
- {
- if (isDone && waitCounter == 0)
- {
- // Restores previous implementations
- mxImageShape.prototype.scheduleUpdateAspect = mxImageShapeScheduleUpdateAspect;
- mxImageShape.prototype.updateAspect = mxImageShapeUpdateAspect;
-
- var markup = '';
-
- for (var i = 0; i < pages.length; i++)
- {
- markup += pages[i].outerHTML;
- pages[i].parentNode.removeChild(pages[i]);
-
- if (i < pages.length - 1)
- {
- markup += '<hr/>';
- }
- }
-
- doc.body.innerHTML = markup;
- writePageSelector();
- }
- };
-
- // Overrides functions to implement wait counter
- mxImageShape.prototype.scheduleUpdateAspect = function()
- {
- waitCounter++;
- mxImageShapeScheduleUpdateAspect.apply(this, arguments);
- };
-
- // Overrides functions to implement wait counter
- mxImageShape.prototype.updateAspect = function()
- {
- mxImageShapeUpdateAspect.apply(this, arguments);
- waitCounter--;
- writePages();
- };
- }
-
- // Appends each page to the page output for printing, making
- // sure there will be a page break after each page (ie. div)
- for (var i = 0; i < vpages; i++)
- {
- var dy = i * availableHeight / this.scale - this.y0 / this.scale +
- (bounds.y - tr.y * currentScale) / currentScale;
-
- for (var j = 0; j < hpages; j++)
- {
- if (this.wnd == null)
- {
- return null;
- }
-
- var dx = j * availableWidth / this.scale - this.x0 / this.scale +
- (bounds.x - tr.x * currentScale) / currentScale;
- var pageNum = i * hpages + j + 1;
-
- div = this.renderPage(this.pageFormat.width, this.pageFormat.height,
- -dx, -dy, this.scale, pageNum);
-
- // Gives the page a unique ID for later accessing the page
- div.setAttribute('id', 'mxPage-'+pageNum);
-
- // Border of the DIV (aka page) inside the document
- if (this.borderColor != null)
- {
- div.style.borderColor = this.borderColor;
- div.style.borderStyle = 'solid';
- div.style.borderWidth = '1px';
- }
-
- // Needs to be assigned directly because IE doesn't support
- // child selectors, eg. body > div { background: white; }
- div.style.background = 'white';
-
- if (i < vpages - 1 || j < hpages - 1)
- {
- div.style.pageBreakAfter = 'always';
- }
-
- // NOTE: We are dealing with cross-window DOM here, which
- // is a problem in IE, so we copy the HTML markup instead.
- // The underlying problem is that the graph display markup
- // creation (in mxShape, mxGraphView) is hardwired to using
- // document.createElement and hence we must use document
- // to create the complete page and then copy it over to the
- // new window.document. This can be fixed later by using the
- // ownerDocument of the container in mxShape and mxGraphView.
- if (mxClient.IS_IE)
- {
- // For some obscure reason, removing the DIV from the
- // parent before fetching its outerHTML has missing
- // fillcolor properties and fill children, so the div
- // must be removed afterwards to keep the fillcolors.
- // For delayed output we remote the DIV from the
- // original document when we write out all pages.
- doc.writeln(div.outerHTML);
-
- if (pages != null)
- {
- pages.push(div);
- }
- else
- {
- div.parentNode.removeChild(div);
- }
- }
- else
- {
- div.parentNode.removeChild(div);
- doc.body.appendChild(div);
- }
-
- if (i < vpages - 1 || j < hpages - 1)
- {
- var hr = doc.createElement('hr');
- hr.className = 'mxPageBreak';
- doc.body.appendChild(hr);
- }
- }
- }
-
- doc.writeln('</body>');
- doc.writeln('</html>');
- doc.close();
-
- // Marks the printing complete for async handling
- if (pages != null)
- {
- isDone = true;
- writePages();
- }
- else
- {
- writePageSelector();
- }
-
- // Removes all event handlers in the print output
- mxEvent.release(doc.body);
- }
-
- this.wnd.focus();
- }
- catch (e)
- {
- // Removes the DIV from the document in case of an error
- if (div != null && div.parentNode != null)
- {
- div.parentNode.removeChild(div);
- }
- }
- finally
- {
- this.graph.cellRenderer.initializeOverlay = previousInitializeOverlay;
- }
-
- return this.wnd;
-};
-
-/**
- * Function: writeHead
- *
- * Writes the HEAD section into the given document, without the opening
- * and closing HEAD tags.
- */
-mxPrintPreview.prototype.writeHead = function(doc, css)
-{
- if (this.title != null)
- {
- doc.writeln('<title>' + this.title + '</title>');
- }
-
- // Makes sure no horizontal rulers are printed
- doc.writeln('<style type="text/css">');
- doc.writeln('@media print {');
- doc.writeln(' table.mxPageSelector { display: none; }');
- doc.writeln(' hr.mxPageBreak { display: none; }');
- doc.writeln('}');
- doc.writeln('@media screen {');
-
- // NOTE: position: fixed is not supported in IE, so the page selector
- // position (absolute) needs to be updated in IE (see below)
- doc.writeln(' table.mxPageSelector { position: fixed; right: 10px; top: 10px;' +
- 'font-family: Arial; font-size:10pt; border: solid 1px darkgray;' +
- 'background: white; border-collapse:collapse; }');
- doc.writeln(' table.mxPageSelector td { border: solid 1px gray; padding:4px; }');
- doc.writeln(' body.mxPage { background: gray; }');
- doc.writeln('}');
-
- if (css != null)
- {
- doc.writeln(css);
- }
-
- doc.writeln('</style>');
-};
-
-/**
- * Function: createPageSelector
- *
- * Creates the page selector table.
- */
-mxPrintPreview.prototype.createPageSelector = function(vpages, hpages)
-{
- var doc = this.wnd.document;
- var table = doc.createElement('table');
- table.className = 'mxPageSelector';
- table.setAttribute('border', '0');
-
- var tbody = doc.createElement('tbody');
-
- for (var i = 0; i < vpages; i++)
- {
- var row = doc.createElement('tr');
-
- for (var j = 0; j < hpages; j++)
- {
- var pageNum = i * hpages + j + 1;
- var cell = doc.createElement('td');
-
- // Needs anchor for all browers to work without JavaScript
- // LATER: Does not work in Firefox because the generated document
- // has the URL of the opening document, the anchor is appended
- // to that URL and the full URL is loaded on click.
- if (!mxClient.IS_NS || mxClient.IS_SF || mxClient.IS_GC)
- {
- var a = doc.createElement('a');
- a.setAttribute('href', '#mxPage-' + pageNum);
- mxUtils.write(a, pageNum, doc);
- cell.appendChild(a);
- }
- else
- {
- mxUtils.write(cell, pageNum, doc);
- }
-
- row.appendChild(cell);
- }
-
- tbody.appendChild(row);
- }
-
- table.appendChild(tbody);
-
- return table;
-};
-
-/**
- * Function: renderPage
- *
- * Creates a DIV that prints a single page of the given
- * graph using the given scale and returns the DIV that
- * represents the page.
- *
- * Parameters:
- *
- * w - Width of the page in pixels.
- * h - Height of the page in pixels.
- * dx - Horizontal translation for the diagram.
- * dy - Vertical translation for the diagram.
- * scale - Scale for the diagram.
- * pageNumber - Number of the page to be rendered.
- */
-mxPrintPreview.prototype.renderPage = function(w, h, dx, dy, scale, pageNumber)
-{
- var div = document.createElement('div');
-
- try
- {
- div.style.width = w + 'px';
- div.style.height = h + 'px';
- div.style.overflow = 'hidden';
- div.style.pageBreakInside = 'avoid';
-
- var innerDiv = document.createElement('div');
- innerDiv.style.top = this.border + 'px';
- innerDiv.style.left = this.border + 'px';
- innerDiv.style.width = (w - 2 * this.border) + 'px';
- innerDiv.style.height = (h - 2 * this.border) + 'px';
- innerDiv.style.overflow = 'hidden';
-
- if (this.graph.dialect == mxConstants.DIALECT_VML)
- {
- innerDiv.style.position = 'absolute';
- }
-
- div.appendChild(innerDiv);
- document.body.appendChild(div);
- var view = this.graph.getView();
-
- var previousContainer = this.graph.container;
- this.graph.container = innerDiv;
-
- var canvas = view.getCanvas();
- var backgroundPane = view.getBackgroundPane();
- var drawPane = view.getDrawPane();
- var overlayPane = view.getOverlayPane();
-
- if (this.graph.dialect == mxConstants.DIALECT_SVG)
- {
- view.createSvg();
- }
- else if (this.graph.dialect == mxConstants.DIALECT_VML)
- {
- view.createVml();
- }
- else
- {
- view.createHtml();
- }
-
- // Disables events on the view
- var eventsEnabled = view.isEventsEnabled();
- view.setEventsEnabled(false);
-
- // Disables the graph to avoid cursors
- var graphEnabled = this.graph.isEnabled();
- this.graph.setEnabled(false);
-
- // Resets the translation
- var translate = view.getTranslate();
- view.translate = new mxPoint(dx, dy);
-
- var temp = null;
-
- try
- {
- // Creates the temporary cell states in the view and
- // draws them onto the temporary DOM nodes in the view
- var model = this.graph.getModel();
- var cells = [model.getRoot()];
- temp = new mxTemporaryCellStates(view, scale, cells);
- }
- finally
- {
- // Removes overlay pane with selection handles
- // controls and icons from the print output
- if (mxClient.IS_IE)
- {
- view.overlayPane.innerHTML = '';
- }
- else
- {
- // Removes everything but the SVG node
- var tmp = innerDiv.firstChild;
-
- while (tmp != null)
- {
- var next = tmp.nextSibling;
- var name = tmp.nodeName.toLowerCase();
-
- // Note: Width and heigh are required in FF 11
- if (name == 'svg')
- {
- tmp.setAttribute('width', parseInt(innerDiv.style.width));
- tmp.setAttribute('height', parseInt(innerDiv.style.height));
- }
- // Tries to fetch all text labels and only text labels
- else if (tmp.style.cursor != 'default' && name != 'table')
- {
- tmp.parentNode.removeChild(tmp);
- }
-
- tmp = next;
- }
- }
-
- // Completely removes the overlay pane to remove more handles
- view.overlayPane.parentNode.removeChild(view.overlayPane);
-
- // Restores the state of the view
- this.graph.setEnabled(graphEnabled);
- this.graph.container = previousContainer;
- view.canvas = canvas;
- view.backgroundPane = backgroundPane;
- view.drawPane = drawPane;
- view.overlayPane = overlayPane;
- view.translate = translate;
- temp.destroy();
- view.setEventsEnabled(eventsEnabled);
- }
- }
- catch (e)
- {
- div.parentNode.removeChild(div);
- div = null;
-
- throw e;
- }
-
- return div;
-};
-
-/**
- * Function: print
- *
- * Opens the print preview and shows the print dialog.
- */
-mxPrintPreview.prototype.print = function()
-{
- var wnd = this.open();
-
- if (wnd != null)
- {
- wnd.print();
- }
-};
-
-/**
- * Function: close
- *
- * Closes the print preview window.
- */
-mxPrintPreview.prototype.close = function()
-{
- if (this.wnd != null)
- {
- this.wnd.close();
- this.wnd = null;
- }
-};
diff --git a/src/js/view/mxSpaceManager.js b/src/js/view/mxSpaceManager.js
deleted file mode 100644
index 2a2dd11..0000000
--- a/src/js/view/mxSpaceManager.js
+++ /dev/null
@@ -1,460 +0,0 @@
-/**
- * $Id: mxSpaceManager.js,v 1.9 2010-01-02 09:45:15 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxSpaceManager
- *
- * In charge of moving cells after a resize.
- *
- * Constructor: mxSpaceManager
- *
- * Constructs a new automatic layout for the given graph.
- *
- * Arguments:
- *
- * graph - Reference to the enclosing graph.
- */
-function mxSpaceManager(graph, shiftRightwards, shiftDownwards, extendParents)
-{
- this.resizeHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled())
- {
- this.cellsResized(evt.getProperty('cells'));
- }
- });
-
- this.foldHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled())
- {
- this.cellsResized(evt.getProperty('cells'));
- }
- });
-
- this.shiftRightwards = (shiftRightwards != null) ? shiftRightwards : true;
- this.shiftDownwards = (shiftDownwards != null) ? shiftDownwards : true;
- this.extendParents = (extendParents != null) ? extendParents : true;
- this.setGraph(graph);
-};
-
-/**
- * Extends mxEventSource.
- */
-mxSpaceManager.prototype = new mxEventSource();
-mxSpaceManager.prototype.constructor = mxSpaceManager;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxSpaceManager.prototype.graph = null;
-
-/**
- * Variable: enabled
- *
- * Specifies if event handling is enabled. Default is true.
- */
-mxSpaceManager.prototype.enabled = true;
-
-/**
- * Variable: shiftRightwards
- *
- * Specifies if event handling is enabled. Default is true.
- */
-mxSpaceManager.prototype.shiftRightwards = true;
-
-/**
- * Variable: shiftDownwards
- *
- * Specifies if event handling is enabled. Default is true.
- */
-mxSpaceManager.prototype.shiftDownwards = true;
-
-/**
- * Variable: extendParents
- *
- * Specifies if event handling is enabled. Default is true.
- */
-mxSpaceManager.prototype.extendParents = true;
-
-/**
- * Variable: resizeHandler
- *
- * Holds the function that handles the move event.
- */
-mxSpaceManager.prototype.resizeHandler = null;
-
-/**
- * Variable: foldHandler
- *
- * Holds the function that handles the fold event.
- */
-mxSpaceManager.prototype.foldHandler = null;
-
-/**
- * Function: isCellIgnored
- *
- * Sets the graph that the layouts operate on.
- */
-mxSpaceManager.prototype.isCellIgnored = function(cell)
-{
- return !this.getGraph().getModel().isVertex(cell);
-};
-
-/**
- * Function: isCellShiftable
- *
- * Sets the graph that the layouts operate on.
- */
-mxSpaceManager.prototype.isCellShiftable = function(cell)
-{
- return this.getGraph().getModel().isVertex(cell) &&
- this.getGraph().isCellMovable(cell);
-};
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxSpaceManager.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxSpaceManager.prototype.setEnabled = function(value)
-{
- this.enabled = value;
-};
-
-/**
- * Function: isShiftRightwards
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxSpaceManager.prototype.isShiftRightwards = function()
-{
- return this.shiftRightwards;
-};
-
-/**
- * Function: setShiftRightwards
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxSpaceManager.prototype.setShiftRightwards = function(value)
-{
- this.shiftRightwards = value;
-};
-
-/**
- * Function: isShiftDownwards
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxSpaceManager.prototype.isShiftDownwards = function()
-{
- return this.shiftDownwards;
-};
-
-/**
- * Function: setShiftDownwards
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxSpaceManager.prototype.setShiftDownwards = function(value)
-{
- this.shiftDownwards = value;
-};
-
-/**
- * Function: isExtendParents
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxSpaceManager.prototype.isExtendParents = function()
-{
- return this.extendParents;
-};
-
-/**
- * Function: setShiftDownwards
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxSpaceManager.prototype.setExtendParents = function(value)
-{
- this.extendParents = value;
-};
-
-/**
- * Function: getGraph
- *
- * Returns the graph that this layout operates on.
- */
-mxSpaceManager.prototype.getGraph = function()
-{
- return this.graph;
-};
-
-/**
- * Function: setGraph
- *
- * Sets the graph that the layouts operate on.
- */
-mxSpaceManager.prototype.setGraph = function(graph)
-{
- if (this.graph != null)
- {
- this.graph.removeListener(this.resizeHandler);
- this.graph.removeListener(this.foldHandler);
- }
-
- this.graph = graph;
-
- if (this.graph != null)
- {
- this.graph.addListener(mxEvent.RESIZE_CELLS, this.resizeHandler);
- this.graph.addListener(mxEvent.FOLD_CELLS, this.foldHandler);
- }
-};
-
-/**
- * Function: cellsResized
- *
- * Called from <moveCellsIntoParent> to invoke the <move> hook in the
- * automatic layout of each modified cell's parent. The event is used to
- * define the x- and y-coordinates passed to the move function.
- *
- * Parameters:
- *
- * cell - Array of <mxCells> that have been resized.
- */
-mxSpaceManager.prototype.cellsResized = function(cells)
-{
- if (cells != null)
- {
- var model = this.graph.getModel();
-
- // Raising the update level should not be required
- // since only one call is made below
- model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- if (!this.isCellIgnored(cells[i]))
- {
- this.cellResized(cells[i]);
- break;
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
-};
-
-/**
- * Function: cellResized
- *
- * Called from <moveCellsIntoParent> to invoke the <move> hook in the
- * automatic layout of each modified cell's parent. The event is used to
- * define the x- and y-coordinates passed to the move function.
- *
- * Parameters:
- *
- * cell - <mxCell> that has been resized.
- */
-mxSpaceManager.prototype.cellResized = function(cell)
-{
- var graph = this.getGraph();
- var view = graph.getView();
- var model = graph.getModel();
-
- var state = view.getState(cell);
- var pstate = view.getState(model.getParent(cell));
-
- if (state != null &&
- pstate != null)
- {
- var cells = this.getCellsToShift(state);
- var geo = model.getGeometry(cell);
-
- if (cells != null &&
- geo != null)
- {
- var tr = view.translate;
- var scale = view.scale;
-
- var x0 = state.x - pstate.origin.x - tr.x * scale;
- var y0 = state.y - pstate.origin.y - tr.y * scale;
- var right = state.x + state.width;
- var bottom = state.y + state.height;
-
- var dx = state.width - geo.width * scale + x0 - geo.x * scale;
- var dy = state.height - geo.height * scale + y0 - geo.y * scale;
-
- var fx = 1 - geo.width * scale / state.width;
- var fy = 1 - geo.height * scale / state.height;
-
- model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- if (cells[i] != cell &&
- this.isCellShiftable(cells[i]))
- {
- this.shiftCell(cells[i], dx, dy, x0, y0, right, bottom, fx, fy,
- this.isExtendParents() &&
- graph.isExtendParent(cells[i]));
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
- }
-};
-
-/**
- * Function: shiftCell
- *
- * Called from <moveCellsIntoParent> to invoke the <move> hook in the
- * automatic layout of each modified cell's parent. The event is used to
- * define the x- and y-coordinates passed to the move function.
- *
- * Parameters:
- *
- * cell - Array of <mxCells> that have been moved.
- * evt - Mouse event that represents the mousedown.
- */
-mxSpaceManager.prototype.shiftCell = function(cell, dx, dy, Ox0, y0, right,
- bottom, fx, fy, extendParent)
-{
- var graph = this.getGraph();
- var state = graph.getView().getState(cell);
-
- if (state != null)
- {
- var model = graph.getModel();
- var geo = model.getGeometry(cell);
-
- if (geo != null)
- {
- model.beginUpdate();
- try
- {
- if (this.isShiftRightwards())
- {
- if (state.x >= right)
- {
- geo = geo.clone();
- geo.translate(-dx, 0);
- }
- else
- {
- var tmpDx = Math.max(0, state.x - x0);
- geo = geo.clone();
- geo.translate(-fx * tmpDx, 0);
- }
- }
-
- if (this.isShiftDownwards())
- {
- if (state.y >= bottom)
- {
- geo = geo.clone();
- geo.translate(0, -dy);
- }
- else
- {
- var tmpDy = Math.max(0, state.y - y0);
- geo = geo.clone();
- geo.translate(0, -fy * tmpDy);
- }
- }
-
- if (geo != model.getGeometry(cell))
- {
- model.setGeometry(cell, geo);
-
- // Parent size might need to be updated if this
- // is seen as part of the resize
- if (extendParent)
- {
- graph.extendParent(cell);
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
- }
-};
-
-/**
- * Function: getCellsToShift
- *
- * Returns the cells to shift after a resize of the
- * specified <mxCellState>.
- */
-mxSpaceManager.prototype.getCellsToShift = function(state)
-{
- var graph = this.getGraph();
- var parent = graph.getModel().getParent(state.cell);
- var down = this.isShiftDownwards();
- var right = this.isShiftRightwards();
-
- return graph.getCellsBeyond(state.x + ((down) ? 0 : state.width),
- state.y + ((down && right) ? 0 : state.height), parent, right, down);
-};
-
-/**
- * Function: destroy
- *
- * Removes all handlers from the <graph> and deletes the reference to it.
- */
-mxSpaceManager.prototype.destroy = function()
-{
- this.setGraph(null);
-};
diff --git a/src/js/view/mxStyleRegistry.js b/src/js/view/mxStyleRegistry.js
deleted file mode 100644
index 6ad878d..0000000
--- a/src/js/view/mxStyleRegistry.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * $Id: mxStyleRegistry.js,v 1.10 2011-04-27 10:15:39 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-var mxStyleRegistry =
-{
- /**
- * Class: mxStyleRegistry
- *
- * Singleton class that acts as a global converter from string to object values
- * in a style. This is currently only used to perimeters and edge styles.
- *
- * Variable: values
- *
- * Maps from strings to objects.
- */
- values: [],
-
- /**
- * Function: putValue
- *
- * Puts the given object into the registry under the given name.
- */
- putValue: function(name, obj)
- {
- mxStyleRegistry.values[name] = obj;
- },
-
- /**
- * Function: getValue
- *
- * Returns the value associated with the given name.
- */
- getValue: function(name)
- {
- return mxStyleRegistry.values[name];
- },
-
- /**
- * Function: getName
- *
- * Returns the name for the given value.
- */
- getName: function(value)
- {
- for (var key in mxStyleRegistry.values)
- {
- if (mxStyleRegistry.values[key] == value)
- {
- return key;
- }
- }
-
- return null;
- }
-
-};
-
-mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ELBOW, mxEdgeStyle.ElbowConnector);
-mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ENTITY_RELATION, mxEdgeStyle.EntityRelation);
-mxStyleRegistry.putValue(mxConstants.EDGESTYLE_LOOP, mxEdgeStyle.Loop);
-mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SIDETOSIDE, mxEdgeStyle.SideToSide);
-mxStyleRegistry.putValue(mxConstants.EDGESTYLE_TOPTOBOTTOM, mxEdgeStyle.TopToBottom);
-mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ORTHOGONAL, mxEdgeStyle.OrthConnector);
-mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SEGMENT, mxEdgeStyle.SegmentConnector);
-
-mxStyleRegistry.putValue(mxConstants.PERIMETER_ELLIPSE, mxPerimeter.EllipsePerimeter);
-mxStyleRegistry.putValue(mxConstants.PERIMETER_RECTANGLE, mxPerimeter.RectanglePerimeter);
-mxStyleRegistry.putValue(mxConstants.PERIMETER_RHOMBUS, mxPerimeter.RhombusPerimeter);
-mxStyleRegistry.putValue(mxConstants.PERIMETER_TRIANGLE, mxPerimeter.TrianglePerimeter);
diff --git a/src/js/view/mxStylesheet.js b/src/js/view/mxStylesheet.js
deleted file mode 100644
index 82a520e..0000000
--- a/src/js/view/mxStylesheet.js
+++ /dev/null
@@ -1,266 +0,0 @@
-/**
- * $Id: mxStylesheet.js,v 1.35 2010-03-26 10:24:58 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxStylesheet
- *
- * Defines the appearance of the cells in a graph. See <putCellStyle> for an
- * example of creating a new cell style. It is recommended to use objects, not
- * arrays for holding cell styles. Existing styles can be cloned using
- * <mxUtils.clone> and turned into a string for debugging using
- * <mxUtils.toString>.
- *
- * Default Styles:
- *
- * The stylesheet contains two built-in styles, which are used if no style is
- * defined for a cell:
- *
- * defaultVertex - Default style for vertices
- * defaultEdge - Default style for edges
- *
- * Example:
- *
- * (code)
- * var vertexStyle = stylesheet.getDefaultVertexStyle();
- * vertexStyle[mxConstants.ROUNDED] = true;
- * var edgeStyle = stylesheet.getDefaultEdgeStyle();
- * edgeStyle[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation;
- * (end)
- *
- * Modifies the built-in default styles.
- *
- * To avoid the default style for a cell, add a leading semicolon
- * to the style definition, eg.
- *
- * (code)
- * ;shadow=1
- * (end)
- *
- * Removing keys:
- *
- * For removing a key in a cell style of the form [stylename;|key=value;] the
- * special value none can be used, eg. highlight;fillColor=none
- *
- * See also the helper methods in mxUtils to modify strings of this format,
- * namely <mxUtils.setStyle>, <mxUtils.indexOfStylename>,
- * <mxUtils.addStylename>, <mxUtils.removeStylename>,
- * <mxUtils.removeAllStylenames> and <mxUtils.setStyleFlag>.
- *
- * Constructor: mxStylesheet
- *
- * Constructs a new stylesheet and assigns default styles.
- */
-function mxStylesheet()
-{
- this.styles = new Object();
-
- this.putDefaultVertexStyle(this.createDefaultVertexStyle());
- this.putDefaultEdgeStyle(this.createDefaultEdgeStyle());
-};
-
-/**
- * Function: styles
- *
- * Maps from names to cell styles. Each cell style is a map of key,
- * value pairs.
- */
-mxStylesheet.prototype.styles;
-
-/**
- * Function: createDefaultVertexStyle
- *
- * Creates and returns the default vertex style.
- */
-mxStylesheet.prototype.createDefaultVertexStyle = function()
-{
- var style = new Object();
-
- style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
- style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
- style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;
- style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;
- style[mxConstants.STYLE_FILLCOLOR] = '#C3D9FF';
- style[mxConstants.STYLE_STROKECOLOR] = '#6482B9';
- style[mxConstants.STYLE_FONTCOLOR] = '#774400';
-
- return style;
-};
-
-/**
- * Function: createDefaultEdgeStyle
- *
- * Creates and returns the default edge style.
- */
-mxStylesheet.prototype.createDefaultEdgeStyle = function()
-{
- var style = new Object();
-
- style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_CONNECTOR;
- style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
- style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;
- style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;
- style[mxConstants.STYLE_STROKECOLOR] = '#6482B9';
- style[mxConstants.STYLE_FONTCOLOR] = '#446299';
-
- return style;
-};
-
-/**
- * Function: putDefaultVertexStyle
- *
- * Sets the default style for vertices using defaultVertex as the
- * stylename.
- *
- * Parameters:
- * style - Key, value pairs that define the style.
- */
-mxStylesheet.prototype.putDefaultVertexStyle = function(style)
-{
- this.putCellStyle('defaultVertex', style);
-};
-
-/**
- * Function: putDefaultEdgeStyle
- *
- * Sets the default style for edges using defaultEdge as the stylename.
- */
-mxStylesheet.prototype.putDefaultEdgeStyle = function(style)
-{
- this.putCellStyle('defaultEdge', style);
-};
-
-/**
- * Function: getDefaultVertexStyle
- *
- * Returns the default style for vertices.
- */
-mxStylesheet.prototype.getDefaultVertexStyle = function()
-{
- return this.styles['defaultVertex'];
-};
-
-/**
- * Function: getDefaultEdgeStyle
- *
- * Sets the default style for edges.
- */
-mxStylesheet.prototype.getDefaultEdgeStyle = function()
-{
- return this.styles['defaultEdge'];
-};
-
-/**
- * Function: putCellStyle
- *
- * Stores the given map of key, value pairs under the given name in
- * <styles>.
- *
- * Example:
- *
- * The following example adds a new style called 'rounded' into an
- * existing stylesheet:
- *
- * (code)
- * var style = new Object();
- * style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
- * style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
- * style[mxConstants.STYLE_ROUNDED] = true;
- * graph.getStylesheet().putCellStyle('rounded', style);
- * (end)
- *
- * In the above example, the new style is an object. The possible keys of
- * the object are all the constants in <mxConstants> that start with STYLE
- * and the values are either JavaScript objects, such as
- * <mxPerimeter.RightAngleRectanglePerimeter> (which is in fact a function)
- * or expressions, such as true. Note that not all keys will be
- * interpreted by all shapes (eg. the line shape ignores the fill color).
- * The final call to this method associates the style with a name in the
- * stylesheet. The style is used in a cell with the following code:
- *
- * (code)
- * model.setStyle(cell, 'rounded');
- * (end)
- *
- * Parameters:
- *
- * name - Name for the style to be stored.
- * style - Key, value pairs that define the style.
- */
-mxStylesheet.prototype.putCellStyle = function(name, style)
-{
- this.styles[name] = style;
-};
-
-/**
- * Function: getCellStyle
- *
- * Returns the cell style for the specified stylename or the given
- * defaultStyle if no style can be found for the given stylename.
- *
- * Parameters:
- *
- * name - String of the form [(stylename|key=value);] that represents the
- * style.
- * defaultStyle - Default style to be returned if no style can be found.
- */
-mxStylesheet.prototype.getCellStyle = function(name, defaultStyle)
-{
- var style = defaultStyle;
-
- if (name != null && name.length > 0)
- {
- var pairs = name.split(';');
-
- if (style != null &&
- name.charAt(0) != ';')
- {
- style = mxUtils.clone(style);
- }
- else
- {
- style = new Object();
- }
-
- // Parses each key, value pair into the existing style
- for (var i = 0; i < pairs.length; i++)
- {
- var tmp = pairs[i];
- var pos = tmp.indexOf('=');
-
- if (pos >= 0)
- {
- var key = tmp.substring(0, pos);
- var value = tmp.substring(pos + 1);
-
- if (value == mxConstants.NONE)
- {
- delete style[key];
- }
- else if (mxUtils.isNumeric(value))
- {
- style[key] = parseFloat(value);
- }
- else
- {
- style[key] = value;
- }
- }
- else
- {
- // Merges the entries from a named style
- var tmpStyle = this.styles[tmp];
-
- if (tmpStyle != null)
- {
- for (var key in tmpStyle)
- {
- style[key] = tmpStyle[key];
- }
- }
- }
- }
- }
-
- return style;
-};
diff --git a/src/js/view/mxSwimlaneManager.js b/src/js/view/mxSwimlaneManager.js
deleted file mode 100644
index fe40613..0000000
--- a/src/js/view/mxSwimlaneManager.js
+++ /dev/null
@@ -1,449 +0,0 @@
-/**
- * $Id: mxSwimlaneManager.js,v 1.17 2011-01-14 15:21:10 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxSwimlaneManager
- *
- * Manager for swimlanes and nested swimlanes that sets the size of newly added
- * swimlanes to that of their siblings, and propagates changes to the size of a
- * swimlane to its siblings, if <siblings> is true, and its ancestors, if
- * <bubbling> is true.
- *
- * Constructor: mxSwimlaneManager
- *
- * Constructs a new swimlane manager for the given graph.
- *
- * Arguments:
- *
- * graph - Reference to the enclosing graph.
- */
-function mxSwimlaneManager(graph, horizontal, addEnabled, resizeEnabled)
-{
- this.horizontal = (horizontal != null) ? horizontal : true;
- this.addEnabled = (addEnabled != null) ? addEnabled : true;
- this.resizeEnabled = (resizeEnabled != null) ? resizeEnabled : true;
-
- this.addHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled() && this.isAddEnabled())
- {
- this.cellsAdded(evt.getProperty('cells'));
- }
- });
-
- this.resizeHandler = mxUtils.bind(this, function(sender, evt)
- {
- if (this.isEnabled() && this.isResizeEnabled())
- {
- this.cellsResized(evt.getProperty('cells'));
- }
- });
-
- this.setGraph(graph);
-};
-
-/**
- * Extends mxEventSource.
- */
-mxSwimlaneManager.prototype = new mxEventSource();
-mxSwimlaneManager.prototype.constructor = mxSwimlaneManager;
-
-/**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph>.
- */
-mxSwimlaneManager.prototype.graph = null;
-
-/**
- * Variable: enabled
- *
- * Specifies if event handling is enabled. Default is true.
- */
-mxSwimlaneManager.prototype.enabled = true;
-
-/**
- * Variable: horizontal
- *
- * Specifies the orientation of the swimlanes. Default is true.
- */
-mxSwimlaneManager.prototype.horizontal = true;
-
-/**
- * Variable: addEnabled
- *
- * Specifies if newly added cells should be resized to match the size of their
- * existing siblings. Default is true.
- */
-mxSwimlaneManager.prototype.addEnabled = true;
-
-/**
- * Variable: resizeEnabled
- *
- * Specifies if resizing of swimlanes should be handled. Default is true.
- */
-mxSwimlaneManager.prototype.resizeEnabled = true;
-
-/**
- * Variable: moveHandler
- *
- * Holds the function that handles the move event.
- */
-mxSwimlaneManager.prototype.addHandler = null;
-
-/**
- * Variable: moveHandler
- *
- * Holds the function that handles the move event.
- */
-mxSwimlaneManager.prototype.resizeHandler = null;
-
-/**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation
- * returns <enabled>.
- */
-mxSwimlaneManager.prototype.isEnabled = function()
-{
- return this.enabled;
-};
-
-/**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation
- * updates <enabled>.
- *
- * Parameters:
- *
- * enabled - Boolean that specifies the new enabled state.
- */
-mxSwimlaneManager.prototype.setEnabled = function(value)
-{
- this.enabled = value;
-};
-
-/**
- * Function: isHorizontal
- *
- * Returns <horizontal>.
- */
-mxSwimlaneManager.prototype.isHorizontal = function()
-{
- return this.horizontal;
-};
-
-/**
- * Function: setHorizontal
- *
- * Sets <horizontal>.
- */
-mxSwimlaneManager.prototype.setHorizontal = function(value)
-{
- this.horizontal = value;
-};
-
-/**
- * Function: isAddEnabled
- *
- * Returns <addEnabled>.
- */
-mxSwimlaneManager.prototype.isAddEnabled = function()
-{
- return this.addEnabled;
-};
-
-/**
- * Function: setAddEnabled
- *
- * Sets <addEnabled>.
- */
-mxSwimlaneManager.prototype.setAddEnabled = function(value)
-{
- this.addEnabled = value;
-};
-
-/**
- * Function: isResizeEnabled
- *
- * Returns <resizeEnabled>.
- */
-mxSwimlaneManager.prototype.isResizeEnabled = function()
-{
- return this.resizeEnabled;
-};
-
-/**
- * Function: setResizeEnabled
- *
- * Sets <resizeEnabled>.
- */
-mxSwimlaneManager.prototype.setResizeEnabled = function(value)
-{
- this.resizeEnabled = value;
-};
-
-/**
- * Function: getGraph
- *
- * Returns the graph that this manager operates on.
- */
-mxSwimlaneManager.prototype.getGraph = function()
-{
- return this.graph;
-};
-
-/**
- * Function: setGraph
- *
- * Sets the graph that the manager operates on.
- */
-mxSwimlaneManager.prototype.setGraph = function(graph)
-{
- if (this.graph != null)
- {
- this.graph.removeListener(this.addHandler);
- this.graph.removeListener(this.resizeHandler);
- }
-
- this.graph = graph;
-
- if (this.graph != null)
- {
- this.graph.addListener(mxEvent.ADD_CELLS, this.addHandler);
- this.graph.addListener(mxEvent.CELLS_RESIZED, this.resizeHandler);
- }
-};
-
-/**
- * Function: isSwimlaneIgnored
- *
- * Returns true if the given swimlane should be ignored.
- */
-mxSwimlaneManager.prototype.isSwimlaneIgnored = function(swimlane)
-{
- return !this.getGraph().isSwimlane(swimlane);
-};
-
-/**
- * Function: isCellHorizontal
- *
- * Returns true if the given cell is horizontal. If the given cell is not a
- * swimlane, then the global orientation is returned.
- */
-mxSwimlaneManager.prototype.isCellHorizontal = function(cell)
-{
- if (this.graph.isSwimlane(cell))
- {
- var state = this.graph.view.getState(cell);
- var style = (state != null) ? state.style : this.graph.getCellStyle(cell);
-
- return mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, 1) == 1;
- }
-
- return !this.isHorizontal();
-};
-
-/**
- * Function: cellsAdded
- *
- * Called if any cells have been added.
- *
- * Parameters:
- *
- * cell - Array of <mxCells> that have been added.
- */
-mxSwimlaneManager.prototype.cellsAdded = function(cells)
-{
- if (cells != null)
- {
- var model = this.getGraph().getModel();
-
- model.beginUpdate();
- try
- {
- for (var i = 0; i < cells.length; i++)
- {
- if (!this.isSwimlaneIgnored(cells[i]))
- {
- this.swimlaneAdded(cells[i]);
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
-};
-
-/**
- * Function: swimlaneAdded
- *
- * Updates the size of the given swimlane to match that of any existing
- * siblings swimlanes.
- *
- * Parameters:
- *
- * swimlane - <mxCell> that represents the new swimlane.
- */
-mxSwimlaneManager.prototype.swimlaneAdded = function(swimlane)
-{
- var model = this.getGraph().getModel();
- var parent = model.getParent(swimlane);
- var childCount = model.getChildCount(parent);
- var geo = null;
-
- // Finds the first valid sibling swimlane as reference
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(parent, i);
-
- if (child != swimlane && !this.isSwimlaneIgnored(child))
- {
- geo = model.getGeometry(child);
-
- if (geo != null)
- {
- break;
- }
- }
- }
-
- // Applies the size of the refernece to the newly added swimlane
- if (geo != null)
- {
- this.resizeSwimlane(swimlane, geo.width, geo.height);
- }
-};
-
-/**
- * Function: cellsResized
- *
- * Called if any cells have been resizes. Calls <swimlaneResized> for all
- * swimlanes where <isSwimlaneIgnored> returns false.
- *
- * Parameters:
- *
- * cells - Array of <mxCells> whose size was changed.
- */
-mxSwimlaneManager.prototype.cellsResized = function(cells)
-{
- if (cells != null)
- {
- var model = this.getGraph().getModel();
-
- model.beginUpdate();
- try
- {
- // Finds the top-level swimlanes and adds offsets
- for (var i = 0; i < cells.length; i++)
- {
- if (!this.isSwimlaneIgnored(cells[i]))
- {
- var geo = model.getGeometry(cells[i]);
-
- if (geo != null)
- {
- var size = new mxRectangle(0, 0, geo.width, geo.height);
- var top = cells[i];
- var current = top;
-
- while (current != null)
- {
- top = current;
- current = model.getParent(current);
- var tmp = (this.graph.isSwimlane(current)) ?
- this.graph.getStartSize(current) :
- new mxRectangle();
- size.width += tmp.width;
- size.height += tmp.height;
- }
-
- this.resizeSwimlane(top, size.width, size.height);
- }
- }
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
-};
-
-/**
- * Function: resizeSwimlane
- *
- * Called from <cellsResized> for all swimlanes that are not ignored to update
- * the size of the siblings and the size of the parent swimlanes, recursively,
- * if <bubbling> is true.
- *
- * Parameters:
- *
- * swimlane - <mxCell> whose size has changed.
- */
-mxSwimlaneManager.prototype.resizeSwimlane = function(swimlane, w, h)
-{
- var model = this.getGraph().getModel();
-
- model.beginUpdate();
- try
- {
- if (!this.isSwimlaneIgnored(swimlane))
- {
- var geo = model.getGeometry(swimlane);
-
- if (geo != null)
- {
- var horizontal = this.isCellHorizontal(swimlane);
-
- if ((horizontal && geo.height != h) || (!horizontal && geo.width != w))
- {
- geo = geo.clone();
-
- if (horizontal)
- {
- geo.height = h;
- }
- else
- {
- geo.width = w;
- }
-
- model.setGeometry(swimlane, geo);
- }
- }
- }
-
- var tmp = (this.graph.isSwimlane(swimlane)) ?
- this.graph.getStartSize(swimlane) :
- new mxRectangle();
- w -= tmp.width;
- h -= tmp.height;
-
- var childCount = model.getChildCount(swimlane);
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(swimlane, i);
- this.resizeSwimlane(child, w, h);
- }
- }
- finally
- {
- model.endUpdate();
- }
-};
-
-/**
- * Function: destroy
- *
- * Removes all handlers from the <graph> and deletes the reference to it.
- */
-mxSwimlaneManager.prototype.destroy = function()
-{
- this.setGraph(null);
-};
diff --git a/src/js/view/mxTemporaryCellStates.js b/src/js/view/mxTemporaryCellStates.js
deleted file mode 100644
index ce8232c..0000000
--- a/src/js/view/mxTemporaryCellStates.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * $Id: mxTemporaryCellStates.js,v 1.10 2010-04-20 14:43:12 gaudenz Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxTemporaryCellStates
- *
- * Extends <mxPoint> to implement a 2-dimensional rectangle with double
- * precision coordinates.
- *
- * Constructor: mxRectangle
- *
- * Constructs a new rectangle for the optional parameters. If no parameters
- * are given then the respective default values are used.
- */
-function mxTemporaryCellStates(view, scale, cells)
-{
- this.view = view;
- scale = (scale != null) ? scale : 1;
-
- // Stores the previous state
- this.oldBounds = view.getGraphBounds();
- this.oldStates = view.getStates();
- this.oldScale = view.getScale();
-
- // Creates space for new states
- view.setStates(new mxDictionary());
- view.setScale(scale);
-
- if (cells != null)
- {
- // Creates virtual parent state for validation
- var state = view.createState(new mxCell());
-
- // Validates the vertices and edges without adding them to
- // the model so that the original cells are not modified
- for (var i = 0; i < cells.length; i++)
- {
- view.validateBounds(state, cells[i]);
- }
-
- var bbox = null;
-
- for (var i = 0; i < cells.length; i++)
- {
- var bounds = view.validatePoints(state, cells[i]);
-
- if (bbox == null)
- {
- bbox = bounds;
- }
- else
- {
- bbox.add(bounds);
- }
- }
-
- if (bbox == null)
- {
- bbox = new mxRectangle();
- }
-
- view.setGraphBounds(bbox);
- }
-};
-
-/**
- * Variable: view
- *
- * Holds the width of the rectangle. Default is 0.
- */
-mxTemporaryCellStates.prototype.view = null;
-
-/**
- * Variable: oldStates
- *
- * Holds the height of the rectangle. Default is 0.
- */
-mxTemporaryCellStates.prototype.oldStates = null;
-
-/**
- * Variable: oldBounds
- *
- * Holds the height of the rectangle. Default is 0.
- */
-mxTemporaryCellStates.prototype.oldBounds = null;
-
-/**
- * Variable: oldScale
- *
- * Holds the height of the rectangle. Default is 0.
- */
-mxTemporaryCellStates.prototype.oldScale = null;
-
-/**
- * Function: destroy
- *
- * Returns the top, left corner as a new <mxPoint>.
- */
-mxTemporaryCellStates.prototype.destroy = function()
-{
- this.view.setScale(this.oldScale);
- this.view.setStates(this.oldStates);
- this.view.setGraphBounds(this.oldBounds);
-};
diff --git a/src/js/xcos/core/details.js b/src/js/xcos/core/details.js
deleted file mode 100644
index fbeffda..0000000
--- a/src/js/xcos/core/details.js
+++ /dev/null
@@ -1,204 +0,0 @@
-// All arrays - separated by ',' or ';' or ' ' are taken to be 1 Dimensional
-// Only during printing, their nomenclature will change
-// Good read: http://javascript.info/tutorial/arguments#keyword-arguments
-
-function scicos_block() {
- var options = arguments[0] || new Object();
- this.graphics = options.graphics || new scicos_graphics();
- this.model = options.model || new scicos_model();
- this.gui = options.gui || '';
- this.docs = options.docs || [];
-}
-
-function scicos_graphics() {
- var options = arguments[0] || new Object();
- this.orig = options.orig || [0, 0];
- this.sz = options.sz || [80, 80]; // Space and comma works the same!
- this.flip = options.flip || true;
- this.theta = options.theta || 0;
- this.exprs = options.exprs || [];
- this.pin = options.pin || [];
- this.pout = options.pout || [];
- this.pein = options.pein || [];
- this.peout = options.peout || [];
- this.gr_i = options.gr_i || [];
- this.id = options.id || '';
- this.in_implicit = options.in_implicit || [];
- this.out_implicit = options.out_implicit || ''; // There is only one!
- this.in_style = options.in_style || [];
- this.out_style = options.out_style || '';
- this.in_label = options.in_label || [];
- this.out_label = options.out_label || '';
- this.style = options.style || '';
-}
-
-function scicos_model() {
- var options = arguments[0] || new Object();
- this.sim = options.sim || '';
- this.in = options.in || [];
- this.in2 = options.in2 || [];
- this.intyp = options.intyp || [];
- this.out = options.out || [];
- this.out2 = options.out2 || [];
- this.outtyp = options.outtyp || 1;
- this.evtin = options.evtin || [];
- this.evtout = options.evtout || [];
- this.state = options.state || [];
- this.dstate = options.dstate || [];
- this.odstate = options.odstate || [];
- this.ipar = options.ipar || [];
- this.rpar = options.rpar || [];
- this.opar = options.opar || [];
- this.blocktype = options.blocktype || 'c';
- this.firing = options.firing || [];
- this.dep_ut = options.dep_ut || [false, false];
- this.label = options.label || ''; // If label not available, use image
- this.nzcross = options.nzcross || 0;
- this.nmode = options.nmode || 0;
- this.equations = options.equations || [];
- this.uid = options.uid || '';
-}
-
-// This might also have to be overloaded
-function scicos_diagram() {
- this.props = new scicos_params();
- this.objs = [];
- this.version = '';
- this.contrib = [];
-}
-
-// This might also have to be overloaded
-function scicos_params() {
- this.wpar = [600, 450, 0, 0, 600, 450];
- this.titlex = 'Untitled';
- this.tf = 100000;
- this.tol = [Math.pow(10, -6), Math.pow(10, -6), Math.pow(10, -10), this.tf+1, 0, 1, 0];
- this.context = [];
- this.void1 = [];
- this.options = new default_options();
- this.void2 = [];
- this.void3 = [];
- this.doc = [];
-}
-
-// This might also have to be overloaded
-function default_options() {
- var options = new Object();
- var col3d = [0.8, 0.8, 0.8];
- options['3D'] = [true, 33];
- options['Background'] = [8, 1]; // white,black
- options['Link'] = [1, 5]; // black,red
- options['ID'] = [[4, 1, 10, 1], [4, 1, 2, 1]];
- options['Cmap'] = col3d;
- return options;
-}
-
-function zeros(n){
- return new Array(n+1).join('0').split('').map(parseFloat);
-}
-
-function standard_define() {
- var sz = arguments[0];
- var model = arguments[1];
- var label = arguments[2];
- var gr_i = arguments[3] || [];
-
- var pin = [];
- var pout = [];
- var pein = [];
- var peout = [];
-
- var nin = model.in.length;
- if(nin > 0){
- pin = zeros(nin);
- }
- var nout = model.out.length;
- if(nout > 0){
- pout = zeros(nout);
- }
- var ncin = model.evtin.length;
- if(ncin > 0){
- pein = zeros(ncin);
- }
- var ncout = model.evtout.length;
- if(ncout > 0){
- peout = zeros(ncout);
- }
- gr_i = [gr_i, 8];
- if(gr_i[1] == []){
- gr_i[1] = 8;
- }
- if(gr_i[1] == 0){
- gr_i[1] = [];
- }
- var graphics_options = {
- sz: sz,
- pin: pin,
- pout: pout,
- pein: pein,
- peout: peout,
- gr_i: gr_i,
- exprs: label
- };
- var graphics = new scicos_graphics(graphics_options);
- var block_options = {
- graphics: graphics,
- model: model,
- gui: arguments.callee.caller.name
- };
- return new scicos_block(block_options);
-}
-
-function scicos_link (){
- this.xx = [];
- this.yy = [];
- this.id = '';
- this.thick = [0, 0];
- this.ct = [1, 1];
- this.from = [];
- this.to = [];
-}
-
-function ANDLOG_f(){
- var model = new scicos_model();
- model.sim = "andlog";
- model.out = [1];
- model.out2 = [1]; // null -> 1
- model.evtin = [-1,-1]; // 1, 1 -> -1, -1
- model.blocktype = "d";
- model.firing = [];
- model.dep_ut = [false, false];
- var gr_i = "xstringb(orig(1),orig(2),txt,sz(1),sz(2),'fill');";
- var block = new standard_define([80,80], model, 'LOGICAL<BR>AND', gr_i); // 3 -> 80
-
- // Style
- block.graphics.out_implicit = "E";
- block.graphics.out_style = "ExplicitOutputPort;align=right;verticalAlign=middle;spacing=10.0;rotation=0";
- block.graphics.style = "ANDLOG_f";
- return block;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/resources/editor.properties b/src/resources/editor.properties
deleted file mode 100644
index 23432a8..0000000
--- a/src/resources/editor.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-askZoom=Enter zoom (%25)
-properties=Properties
-outline=Outline
-tasks=Tasks
-help=Help
diff --git a/src/resources/graph.properties b/src/resources/graph.properties
deleted file mode 100644
index baf61f8..0000000
--- a/src/resources/graph.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-alreadyConnected=Nodes already connected
-containsValidationErrors=Contains validation errors
-updatingDocument=Updating Document. Please wait...
-updatingSelection=Updating Selection. Please wait...
-collapse-expand=Collapse/Expand
-doubleClickOrientation=Doubleclick to change orientation
-close=Close
-error=Error
-done=Done
-cancel=Cancel
-ok=OK