From 92f3207b50a1caca07df5c5b238212af3358905b Mon Sep 17 00:00:00 2001 From: adhitya Date: Mon, 11 Apr 2016 15:10:54 +0000 Subject: Revert last two commits - Keyboard shortcuts are not working --- css/common.css | 152 - css/explorer.css | 15 - details.js | 204 - images/button.gif | Bin 137 -> 0 bytes images/close.gif | Bin 70 -> 0 bytes images/collapsed.gif | Bin 877 -> 0 bytes images/error.gif | Bin 907 -> 0 bytes images/expanded.gif | Bin 878 -> 0 bytes images/icons48/column.png | Bin 0 -> 1787 bytes images/icons48/earth.png | Bin 0 -> 4520 bytes images/icons48/gear.png | Bin 0 -> 4418 bytes images/icons48/keys.png | Bin 0 -> 4295 bytes images/icons48/mail_new.png | Bin 0 -> 3944 bytes images/icons48/server.png | Bin 0 -> 3556 bytes images/icons48/table.png | Bin 0 -> 1574 bytes images/maximize.gif | Bin 843 -> 0 bytes images/minimize.gif | Bin 64 -> 0 bytes images/normalize.gif | Bin 845 -> 0 bytes images/point.gif | Bin 55 -> 0 bytes images/resize.gif | Bin 74 -> 0 bytes images/separator.gif | Bin 146 -> 0 bytes images/submenu.gif | Bin 56 -> 0 bytes images/transparent.gif | Bin 90 -> 0 bytes images/warning.gif | Bin 276 -> 0 bytes images/warning.png | Bin 425 -> 0 bytes images/window-title.gif | Bin 275 -> 0 bytes images/window.gif | Bin 75 -> 0 bytes index.html | 12 +- mxClient.min.js | 1564 --- resources/editor.properties | 5 - resources/graph.properties | 11 - src/css/common.css | 152 + src/css/explorer.css | 15 + src/images/button.gif | Bin 0 -> 137 bytes src/images/close.gif | Bin 0 -> 70 bytes src/images/collapsed.gif | Bin 0 -> 877 bytes src/images/error.gif | Bin 0 -> 907 bytes src/images/expanded.gif | Bin 0 -> 878 bytes src/images/maximize.gif | Bin 0 -> 843 bytes src/images/minimize.gif | Bin 0 -> 64 bytes src/images/normalize.gif | Bin 0 -> 845 bytes src/images/point.gif | Bin 0 -> 55 bytes src/images/resize.gif | Bin 0 -> 74 bytes src/images/separator.gif | Bin 0 -> 146 bytes src/images/submenu.gif | Bin 0 -> 56 bytes src/images/transparent.gif | Bin 0 -> 90 bytes src/images/warning.gif | Bin 0 -> 276 bytes src/images/warning.png | Bin 0 -> 425 bytes src/images/window-title.gif | Bin 0 -> 275 bytes src/images/window.gif | Bin 0 -> 75 bytes src/js/editor/mxDefaultKeyHandler.js | 126 + src/js/editor/mxDefaultPopupMenu.js | 300 + src/js/editor/mxDefaultToolbar.js | 567 + src/js/editor/mxEditor.js | 3220 ++++++ src/js/handler/mxCellHighlight.js | 271 + src/js/handler/mxCellMarker.js | 419 + src/js/handler/mxCellTracker.js | 149 + src/js/handler/mxConnectionHandler.js | 1969 ++++ src/js/handler/mxConstraintHandler.js | 308 + src/js/handler/mxEdgeHandler.js | 1529 +++ src/js/handler/mxEdgeSegmentHandler.js | 284 + src/js/handler/mxElbowEdgeHandler.js | 248 + src/js/handler/mxGraphHandler.js | 916 ++ src/js/handler/mxKeyHandler.js | 402 + src/js/handler/mxPanningHandler.js | 390 + src/js/handler/mxRubberband.js | 348 + src/js/handler/mxSelectionCellsHandler.js | 260 + src/js/handler/mxTooltipHandler.js | 317 + src/js/handler/mxVertexHandler.js | 753 ++ src/js/index.txt | 316 + src/js/io/mxCellCodec.js | 170 + src/js/io/mxChildChangeCodec.js | 149 + src/js/io/mxCodec.js | 531 + src/js/io/mxCodecRegistry.js | 137 + src/js/io/mxDefaultKeyHandlerCodec.js | 88 + src/js/io/mxDefaultPopupMenuCodec.js | 54 + src/js/io/mxDefaultToolbarCodec.js | 301 + src/js/io/mxEditorCodec.js | 246 + src/js/io/mxGenericChangeCodec.js | 64 + src/js/io/mxGraphCodec.js | 28 + src/js/io/mxGraphViewCodec.js | 197 + src/js/io/mxModelCodec.js | 80 + src/js/io/mxObjectCodec.js | 983 ++ src/js/io/mxRootChangeCodec.js | 83 + src/js/io/mxStylesheetCodec.js | 210 + src/js/io/mxTerminalChangeCodec.js | 42 + .../model/mxGraphAbstractHierarchyCell.js | 206 + .../hierarchical/model/mxGraphHierarchyEdge.js | 174 + .../hierarchical/model/mxGraphHierarchyModel.js | 685 ++ .../hierarchical/model/mxGraphHierarchyNode.js | 210 + src/js/layout/hierarchical/mxHierarchicalLayout.js | 623 ++ .../hierarchical/stage/mxCoordinateAssignment.js | 1836 +++ .../stage/mxHierarchicalLayoutStage.js | 25 + .../stage/mxMedianHybridCrossingReduction.js | 674 ++ .../hierarchical/stage/mxMinimumCycleRemover.js | 131 + src/js/layout/mxCircleLayout.js | 203 + src/js/layout/mxCompactTreeLayout.js | 995 ++ src/js/layout/mxCompositeLayout.js | 101 + src/js/layout/mxEdgeLabelLayout.js | 165 + src/js/layout/mxFastOrganicLayout.js | 591 + src/js/layout/mxGraphLayout.js | 503 + src/js/layout/mxParallelEdgeLayout.js | 198 + src/js/layout/mxPartitionLayout.js | 240 + src/js/layout/mxStackLayout.js | 381 + src/js/model/mxCell.js | 806 ++ src/js/model/mxCellPath.js | 163 + src/js/model/mxGeometry.js | 277 + src/js/model/mxGraphModel.js | 2622 +++++ src/js/mxClient.js | 643 ++ src/js/shape/mxActor.js | 183 + src/js/shape/mxArrow.js | 226 + src/js/shape/mxCloud.js | 56 + src/js/shape/mxConnector.js | 446 + src/js/shape/mxCylinder.js | 319 + src/js/shape/mxDoubleEllipse.js | 203 + src/js/shape/mxEllipse.js | 132 + src/js/shape/mxHexagon.js | 37 + src/js/shape/mxImageShape.js | 405 + src/js/shape/mxLabel.js | 427 + src/js/shape/mxLine.js | 217 + src/js/shape/mxMarker.js | 267 + src/js/shape/mxPolyline.js | 146 + src/js/shape/mxRectangleShape.js | 61 + src/js/shape/mxRhombus.js | 172 + src/js/shape/mxShape.js | 2045 ++++ src/js/shape/mxStencil.js | 1585 +++ src/js/shape/mxStencilRegistry.js | 53 + src/js/shape/mxStencilShape.js | 209 + src/js/shape/mxSwimlane.js | 553 + src/js/shape/mxText.js | 1811 +++ src/js/shape/mxTriangle.js | 34 + src/js/util/mxAnimation.js | 82 + src/js/util/mxAutoSaveManager.js | 213 + src/js/util/mxClipboard.js | 144 + src/js/util/mxConstants.js | 1911 ++++ src/js/util/mxDictionary.js | 130 + src/js/util/mxDivResizer.js | 151 + src/js/util/mxDragSource.js | 594 + src/js/util/mxEffects.js | 214 + src/js/util/mxEvent.js | 1175 ++ src/js/util/mxEventObject.js | 111 + src/js/util/mxEventSource.js | 191 + src/js/util/mxForm.js | 202 + src/js/util/mxGuide.js | 364 + src/js/util/mxImage.js | 40 + src/js/util/mxImageBundle.js | 98 + src/js/util/mxImageExport.js | 1412 +++ src/js/util/mxLog.js | 410 + src/js/util/mxMorphing.js | 239 + src/js/util/mxMouseEvent.js | 241 + src/js/util/mxObjectIdentity.js | 59 + src/js/util/mxPanningManager.js | 262 + src/js/util/mxPath.js | 314 + src/js/util/mxPoint.js | 55 + src/js/util/mxPopupMenu.js | 574 + src/js/util/mxRectangle.js | 134 + src/js/util/mxResources.js | 366 + src/js/util/mxSession.js | 674 ++ src/js/util/mxSvgCanvas2D.js | 1234 ++ src/js/util/mxToolbar.js | 528 + src/js/util/mxUndoManager.js | 229 + src/js/util/mxUndoableEdit.js | 168 + src/js/util/mxUrlConverter.js | 141 + src/js/util/mxUtils.js | 3920 +++++++ src/js/util/mxWindow.js | 1065 ++ src/js/util/mxXmlCanvas2D.js | 715 ++ src/js/util/mxXmlRequest.js | 425 + src/js/view/mxCellEditor.js | 522 + src/js/view/mxCellOverlay.js | 233 + src/js/view/mxCellRenderer.js | 1480 +++ src/js/view/mxCellState.js | 375 + src/js/view/mxCellStatePreview.js | 223 + src/js/view/mxConnectionConstraint.js | 42 + src/js/view/mxEdgeStyle.js | 1302 +++ src/js/view/mxGraph.js | 11176 +++++++++++++++++++ src/js/view/mxGraphSelectionModel.js | 435 + src/js/view/mxGraphView.js | 2545 +++++ src/js/view/mxLayoutManager.js | 375 + src/js/view/mxMultiplicity.js | 257 + src/js/view/mxOutline.js | 649 ++ src/js/view/mxPerimeter.js | 484 + src/js/view/mxPrintPreview.js | 801 ++ src/js/view/mxSpaceManager.js | 460 + src/js/view/mxStyleRegistry.js | 70 + src/js/view/mxStylesheet.js | 266 + src/js/view/mxSwimlaneManager.js | 449 + src/js/view/mxTemporaryCellStates.js | 105 + src/js/xcos/core/details.js | 204 + src/resources/editor.properties | 5 + src/resources/graph.properties | 11 + test.html | 2 +- 191 files changed, 79925 insertions(+), 1955 deletions(-) delete mode 100644 css/common.css delete mode 100644 css/explorer.css delete mode 100644 details.js delete mode 100644 images/button.gif delete mode 100644 images/close.gif delete mode 100644 images/collapsed.gif delete mode 100644 images/error.gif delete mode 100644 images/expanded.gif create mode 100644 images/icons48/column.png create mode 100644 images/icons48/earth.png create mode 100644 images/icons48/gear.png create mode 100644 images/icons48/keys.png create mode 100644 images/icons48/mail_new.png create mode 100644 images/icons48/server.png create mode 100644 images/icons48/table.png delete mode 100644 images/maximize.gif delete mode 100644 images/minimize.gif delete mode 100644 images/normalize.gif delete mode 100644 images/point.gif delete mode 100644 images/resize.gif delete mode 100644 images/separator.gif delete mode 100644 images/submenu.gif delete mode 100644 images/transparent.gif delete mode 100644 images/warning.gif delete mode 100644 images/warning.png delete mode 100644 images/window-title.gif delete mode 100644 images/window.gif delete mode 100644 mxClient.min.js delete mode 100644 resources/editor.properties delete mode 100644 resources/graph.properties create mode 100644 src/css/common.css create mode 100644 src/css/explorer.css create mode 100644 src/images/button.gif create mode 100644 src/images/close.gif create mode 100644 src/images/collapsed.gif create mode 100644 src/images/error.gif create mode 100644 src/images/expanded.gif create mode 100644 src/images/maximize.gif create mode 100644 src/images/minimize.gif create mode 100644 src/images/normalize.gif create mode 100644 src/images/point.gif create mode 100644 src/images/resize.gif create mode 100644 src/images/separator.gif create mode 100644 src/images/submenu.gif create mode 100644 src/images/transparent.gif create mode 100644 src/images/warning.gif create mode 100644 src/images/warning.png create mode 100644 src/images/window-title.gif create mode 100644 src/images/window.gif create mode 100644 src/js/editor/mxDefaultKeyHandler.js create mode 100644 src/js/editor/mxDefaultPopupMenu.js create mode 100644 src/js/editor/mxDefaultToolbar.js create mode 100644 src/js/editor/mxEditor.js create mode 100644 src/js/handler/mxCellHighlight.js create mode 100644 src/js/handler/mxCellMarker.js create mode 100644 src/js/handler/mxCellTracker.js create mode 100644 src/js/handler/mxConnectionHandler.js create mode 100644 src/js/handler/mxConstraintHandler.js create mode 100644 src/js/handler/mxEdgeHandler.js create mode 100644 src/js/handler/mxEdgeSegmentHandler.js create mode 100644 src/js/handler/mxElbowEdgeHandler.js create mode 100644 src/js/handler/mxGraphHandler.js create mode 100644 src/js/handler/mxKeyHandler.js create mode 100644 src/js/handler/mxPanningHandler.js create mode 100644 src/js/handler/mxRubberband.js create mode 100644 src/js/handler/mxSelectionCellsHandler.js create mode 100644 src/js/handler/mxTooltipHandler.js create mode 100644 src/js/handler/mxVertexHandler.js create mode 100644 src/js/index.txt create mode 100644 src/js/io/mxCellCodec.js create mode 100644 src/js/io/mxChildChangeCodec.js create mode 100644 src/js/io/mxCodec.js create mode 100644 src/js/io/mxCodecRegistry.js create mode 100644 src/js/io/mxDefaultKeyHandlerCodec.js create mode 100644 src/js/io/mxDefaultPopupMenuCodec.js create mode 100644 src/js/io/mxDefaultToolbarCodec.js create mode 100644 src/js/io/mxEditorCodec.js create mode 100644 src/js/io/mxGenericChangeCodec.js create mode 100644 src/js/io/mxGraphCodec.js create mode 100644 src/js/io/mxGraphViewCodec.js create mode 100644 src/js/io/mxModelCodec.js create mode 100644 src/js/io/mxObjectCodec.js create mode 100644 src/js/io/mxRootChangeCodec.js create mode 100644 src/js/io/mxStylesheetCodec.js create mode 100644 src/js/io/mxTerminalChangeCodec.js create mode 100644 src/js/layout/hierarchical/model/mxGraphAbstractHierarchyCell.js create mode 100644 src/js/layout/hierarchical/model/mxGraphHierarchyEdge.js create mode 100644 src/js/layout/hierarchical/model/mxGraphHierarchyModel.js create mode 100644 src/js/layout/hierarchical/model/mxGraphHierarchyNode.js create mode 100644 src/js/layout/hierarchical/mxHierarchicalLayout.js create mode 100644 src/js/layout/hierarchical/stage/mxCoordinateAssignment.js create mode 100644 src/js/layout/hierarchical/stage/mxHierarchicalLayoutStage.js create mode 100644 src/js/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js create mode 100644 src/js/layout/hierarchical/stage/mxMinimumCycleRemover.js create mode 100644 src/js/layout/mxCircleLayout.js create mode 100644 src/js/layout/mxCompactTreeLayout.js create mode 100644 src/js/layout/mxCompositeLayout.js create mode 100644 src/js/layout/mxEdgeLabelLayout.js create mode 100644 src/js/layout/mxFastOrganicLayout.js create mode 100644 src/js/layout/mxGraphLayout.js create mode 100644 src/js/layout/mxParallelEdgeLayout.js create mode 100644 src/js/layout/mxPartitionLayout.js create mode 100644 src/js/layout/mxStackLayout.js create mode 100644 src/js/model/mxCell.js create mode 100644 src/js/model/mxCellPath.js create mode 100644 src/js/model/mxGeometry.js create mode 100644 src/js/model/mxGraphModel.js create mode 100644 src/js/mxClient.js create mode 100644 src/js/shape/mxActor.js create mode 100644 src/js/shape/mxArrow.js create mode 100644 src/js/shape/mxCloud.js create mode 100644 src/js/shape/mxConnector.js create mode 100644 src/js/shape/mxCylinder.js create mode 100644 src/js/shape/mxDoubleEllipse.js create mode 100644 src/js/shape/mxEllipse.js create mode 100644 src/js/shape/mxHexagon.js create mode 100644 src/js/shape/mxImageShape.js create mode 100644 src/js/shape/mxLabel.js create mode 100644 src/js/shape/mxLine.js create mode 100644 src/js/shape/mxMarker.js create mode 100644 src/js/shape/mxPolyline.js create mode 100644 src/js/shape/mxRectangleShape.js create mode 100644 src/js/shape/mxRhombus.js create mode 100644 src/js/shape/mxShape.js create mode 100644 src/js/shape/mxStencil.js create mode 100644 src/js/shape/mxStencilRegistry.js create mode 100644 src/js/shape/mxStencilShape.js create mode 100644 src/js/shape/mxSwimlane.js create mode 100644 src/js/shape/mxText.js create mode 100644 src/js/shape/mxTriangle.js create mode 100644 src/js/util/mxAnimation.js create mode 100644 src/js/util/mxAutoSaveManager.js create mode 100644 src/js/util/mxClipboard.js create mode 100644 src/js/util/mxConstants.js create mode 100644 src/js/util/mxDictionary.js create mode 100644 src/js/util/mxDivResizer.js create mode 100644 src/js/util/mxDragSource.js create mode 100644 src/js/util/mxEffects.js create mode 100644 src/js/util/mxEvent.js create mode 100644 src/js/util/mxEventObject.js create mode 100644 src/js/util/mxEventSource.js create mode 100644 src/js/util/mxForm.js create mode 100644 src/js/util/mxGuide.js create mode 100644 src/js/util/mxImage.js create mode 100644 src/js/util/mxImageBundle.js create mode 100644 src/js/util/mxImageExport.js create mode 100644 src/js/util/mxLog.js create mode 100644 src/js/util/mxMorphing.js create mode 100644 src/js/util/mxMouseEvent.js create mode 100644 src/js/util/mxObjectIdentity.js create mode 100644 src/js/util/mxPanningManager.js create mode 100644 src/js/util/mxPath.js create mode 100644 src/js/util/mxPoint.js create mode 100644 src/js/util/mxPopupMenu.js create mode 100644 src/js/util/mxRectangle.js create mode 100644 src/js/util/mxResources.js create mode 100644 src/js/util/mxSession.js create mode 100644 src/js/util/mxSvgCanvas2D.js create mode 100644 src/js/util/mxToolbar.js create mode 100644 src/js/util/mxUndoManager.js create mode 100644 src/js/util/mxUndoableEdit.js create mode 100644 src/js/util/mxUrlConverter.js create mode 100644 src/js/util/mxUtils.js create mode 100644 src/js/util/mxWindow.js create mode 100644 src/js/util/mxXmlCanvas2D.js create mode 100644 src/js/util/mxXmlRequest.js create mode 100644 src/js/view/mxCellEditor.js create mode 100644 src/js/view/mxCellOverlay.js create mode 100644 src/js/view/mxCellRenderer.js create mode 100644 src/js/view/mxCellState.js create mode 100644 src/js/view/mxCellStatePreview.js create mode 100644 src/js/view/mxConnectionConstraint.js create mode 100644 src/js/view/mxEdgeStyle.js create mode 100644 src/js/view/mxGraph.js create mode 100644 src/js/view/mxGraphSelectionModel.js create mode 100644 src/js/view/mxGraphView.js create mode 100644 src/js/view/mxLayoutManager.js create mode 100644 src/js/view/mxMultiplicity.js create mode 100644 src/js/view/mxOutline.js create mode 100644 src/js/view/mxPerimeter.js create mode 100644 src/js/view/mxPrintPreview.js create mode 100644 src/js/view/mxSpaceManager.js create mode 100644 src/js/view/mxStyleRegistry.js create mode 100644 src/js/view/mxStylesheet.js create mode 100644 src/js/view/mxSwimlaneManager.js create mode 100644 src/js/view/mxTemporaryCellStates.js create mode 100644 src/js/xcos/core/details.js create mode 100644 src/resources/editor.properties create mode 100644 src/resources/graph.properties diff --git a/css/common.css b/css/common.css deleted file mode 100644 index 5eb0b45..0000000 --- a/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/css/explorer.css b/css/explorer.css deleted file mode 100644 index dfbbd21..0000000 --- a/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/details.js b/details.js deleted file mode 100644 index fbeffda..0000000 --- a/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
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/images/button.gif b/images/button.gif deleted file mode 100644 index ad55cab..0000000 Binary files a/images/button.gif and /dev/null differ diff --git a/images/close.gif b/images/close.gif deleted file mode 100644 index 1069e94..0000000 Binary files a/images/close.gif and /dev/null differ diff --git a/images/collapsed.gif b/images/collapsed.gif deleted file mode 100644 index 0276444..0000000 Binary files a/images/collapsed.gif and /dev/null differ diff --git a/images/error.gif b/images/error.gif deleted file mode 100644 index 14e1aee..0000000 Binary files a/images/error.gif and /dev/null differ diff --git a/images/expanded.gif b/images/expanded.gif deleted file mode 100644 index 3767b0b..0000000 Binary files a/images/expanded.gif and /dev/null differ diff --git a/images/icons48/column.png b/images/icons48/column.png new file mode 100644 index 0000000..5ae2c24 Binary files /dev/null and b/images/icons48/column.png differ diff --git a/images/icons48/earth.png b/images/icons48/earth.png new file mode 100644 index 0000000..4493880 Binary files /dev/null and b/images/icons48/earth.png differ diff --git a/images/icons48/gear.png b/images/icons48/gear.png new file mode 100644 index 0000000..647d897 Binary files /dev/null and b/images/icons48/gear.png differ diff --git a/images/icons48/keys.png b/images/icons48/keys.png new file mode 100644 index 0000000..41828e4 Binary files /dev/null and b/images/icons48/keys.png differ diff --git a/images/icons48/mail_new.png b/images/icons48/mail_new.png new file mode 100644 index 0000000..16c6662 Binary files /dev/null and b/images/icons48/mail_new.png differ diff --git a/images/icons48/server.png b/images/icons48/server.png new file mode 100644 index 0000000..9621c6e Binary files /dev/null and b/images/icons48/server.png differ diff --git a/images/icons48/table.png b/images/icons48/table.png new file mode 100644 index 0000000..d4df646 Binary files /dev/null and b/images/icons48/table.png differ diff --git a/images/maximize.gif b/images/maximize.gif deleted file mode 100644 index e27cf3e..0000000 Binary files a/images/maximize.gif and /dev/null differ diff --git a/images/minimize.gif b/images/minimize.gif deleted file mode 100644 index 1e95e7c..0000000 Binary files a/images/minimize.gif and /dev/null differ diff --git a/images/normalize.gif b/images/normalize.gif deleted file mode 100644 index 34a8d30..0000000 Binary files a/images/normalize.gif and /dev/null differ diff --git a/images/point.gif b/images/point.gif deleted file mode 100644 index 9074c39..0000000 Binary files a/images/point.gif and /dev/null differ diff --git a/images/resize.gif b/images/resize.gif deleted file mode 100644 index ff558db..0000000 Binary files a/images/resize.gif and /dev/null differ diff --git a/images/separator.gif b/images/separator.gif deleted file mode 100644 index 5c1b895..0000000 Binary files a/images/separator.gif and /dev/null differ diff --git a/images/submenu.gif b/images/submenu.gif deleted file mode 100644 index ffe7617..0000000 Binary files a/images/submenu.gif and /dev/null differ diff --git a/images/transparent.gif b/images/transparent.gif deleted file mode 100644 index 76040f2..0000000 Binary files a/images/transparent.gif and /dev/null differ diff --git a/images/warning.gif b/images/warning.gif deleted file mode 100644 index 705235f..0000000 Binary files a/images/warning.gif and /dev/null differ diff --git a/images/warning.png b/images/warning.png deleted file mode 100644 index 2f78789..0000000 Binary files a/images/warning.png and /dev/null differ diff --git a/images/window-title.gif b/images/window-title.gif deleted file mode 100644 index 231def8..0000000 Binary files a/images/window-title.gif and /dev/null differ diff --git a/images/window.gif b/images/window.gif deleted file mode 100644 index 6631c4f..0000000 Binary files a/images/window.gif and /dev/null differ diff --git a/index.html b/index.html index 2fde407..f21c095 100644 --- a/index.html +++ b/index.html @@ -14,12 +14,18 @@ font-size: 16px; } + + + + - + - + + (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, 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 . 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 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 new file mode 100644 index 0000000..cbcd651 --- /dev/null +++ b/src/js/io/mxCellCodec.js @@ -0,0 +1,170 @@ +/** + * $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 s. This class is created and registered + * dynamically at load time and used implicitely via + * and the . + * + * 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 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 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 new file mode 100644 index 0000000..deeb57b --- /dev/null +++ b/src/js/io/mxChildChangeCodec.js @@ -0,0 +1,149 @@ +/** + * $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 s. This class is created and registered + * dynamically at load time and used implicitely via and + * the . + * + * 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 new file mode 100644 index 0000000..b8bfc6a --- /dev/null +++ b/src/js/io/mxCodec.js @@ -0,0 +1,531 @@ +/** + * $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 for a + * description of the general encoding/decoding scheme. This class uses the + * codecs registered in 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
, in which case a '
' argument + * must be passed to 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. , or using 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 . + */ +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 + * . If the object is not known then is used to find an + * object. If no object is found, then the element with the respective ID + * from the document is parsed using . + */ +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 . 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 first and if that returns null handles + * the object as an by returning their IDs using + * . If no ID exists for the given cell, then + * an on-the-fly ID is generated using . + * + * 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. , + * and ). 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 - 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 + * 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 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 new file mode 100644 index 0000000..a0a0f20 --- /dev/null +++ b/src/js/io/mxCodecRegistry.js @@ -0,0 +1,137 @@ +/** + * $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 : + * + * 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 . + * + * (code) + * mxCodecRegistry.register(codec); + * (end) + * + * 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 - 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 new file mode 100644 index 0000000..628524a --- /dev/null +++ b/src/js/io/mxDefaultKeyHandlerCodec.js @@ -0,0 +1,88 @@ +/** + * $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 s. This class is created + * and registered dynamically at load time and used implicitely via + * and the . 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) + * + * + * + * + * + * (end) + * + * The keycodes are for the x, c and v keys. + * + * See also: , + * 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 new file mode 100644 index 0000000..8d949ea --- /dev/null +++ b/src/js/io/mxDefaultPopupMenuCodec.js @@ -0,0 +1,54 @@ +/** + * $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 s. This class is created + * and registered dynamically at load time and used implicitely via + * and the . 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 + * . + */ + 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 . + */ + 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 new file mode 100644 index 0000000..6698b9b --- /dev/null +++ b/src/js/io/mxDefaultToolbarCodec.js @@ -0,0 +1,301 @@ +/** + * $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 s. This class is created + * and registered dynamically at load time and used implicitely via + * and the . 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) + * + * (end) + * + * In the above function, editor is the enclosing 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 . + * + * 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) + * + * (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) + * + * + *

+ * + * + *
+ * (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 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 new file mode 100644 index 0000000..f61bd95 --- /dev/null +++ b/src/js/io/mxEditorCodec.js @@ -0,0 +1,246 @@ +/** + * $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 s. This class is created and registered + * dynamically at load time and used implicitely via + * and the . + * + * 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 ). + * + * The x, y, width and height attributes are used to create a new + * 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 ). + * title - Title element (see ). + * toolbar - Toolbar element (see ). + * status - Status bar element (see ). + * + * Example: + * + * (code) + * + * + * + * + * + * + * + * (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; js, s, s, + * s and s. This class is created + * and registered dynamically at load time and used implicitely + * via and the . + * + * Transient Fields: + * + * - model + * - previous + * + * Reference Fields: + * + * - cell + * + * Constructor: mxGenericChangeCodec + * + * Factory function that creates a 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 new file mode 100644 index 0000000..f052e13 --- /dev/null +++ b/src/js/io/mxGraphCodec.js @@ -0,0 +1,28 @@ +/** + * $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 s. This class is created and registered + * dynamically at load time and used implicitely via + * and the . + * + * 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 new file mode 100644 index 0000000..110b212 --- /dev/null +++ b/src/js/io/mxGraphViewCodec.js @@ -0,0 +1,197 @@ +/** + * $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 s. This class is created + * and registered dynamically at load time and used implicitely via + * and the . 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 using + * 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 + * returns true for the cell, + * then edge is used for the nodename, else if + * returns true for the cell, + * then vertex is used for the nodename. + * + * 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; is. This class is created and registered + * dynamically at load time and used implicitely via + * and the . + */ + var codec = new mxObjectCodec(new mxGraphModel()); + + /** + * Function: encodeObject + * + * Encodes the given by writing a (flat) XML sequence of + * cell nodes as produced by the . 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 new file mode 100644 index 0000000..9d2473a --- /dev/null +++ b/src/js/io/mxObjectCodec.js @@ -0,0 +1,983 @@ +/** + * $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 as follows. + * + * (code) + * mxLog.show(); + * mxLog.debug(mxUtils.getPrettyXml(node)); + * (end) + * + * Finally, the result of the encoding looks as follows. + * + * (code) + * + * (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) + * + * + * + * (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) + * + * + * + * + * + * (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 . The + * 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 , an array of strings that is used to configure + * the . + * + * 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 , 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 . 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, 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 . + * + * (code) + * + * mxConstants.ALIGN_LEFT + * + * (end) + * + * The resulting object has a field called foo with the value "left". Its XML + * representation looks as follows. + * + * (code) + * + * (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 + * and . + */ +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 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 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 or + * if the fieldname equals . + * + * 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 . + * + * 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 + * after creating the node and 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 then it is ignored. + * - If the variable name is in then + * is used to replace the object with its ID. + * - The variable name is mapped using . + * - 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 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 or if an object + * cannot be encoded, a warning is issued using . + * + * Returns the resulting XML node that represents the given + * object. + * + * Parameters: + * + * enc - 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 + * . + * + * Parameters: + * + * enc - 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 + * to write the attribute into the given node. + * + * Parameters: + * + * enc - 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 + * or 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 to perform + * the default encoding into the given node. + * + * Parameters: + * + * enc - 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 . + * + * Parameters: + * + * enc - 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