UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

1,108 lines (1,107 loc) • 96.4 kB
/** * DevExtreme (esm/ui/diagram/ui.diagram.js) * Version: 21.1.4 * Build date: Mon Jun 21 2021 * * Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import $ from "../../core/renderer"; import Widget from "../widget/ui.widget"; import LoadIndicator from "../load_indicator"; import registerComponent from "../../core/component_registrator"; import { extend } from "../../core/utils/extend"; import { isFunction, isDefined } from "../../core/utils/type"; import { compileSetter, compileGetter } from "../../core/utils/data"; import positionUtils from "../../animation/position"; import resizeCallbacks from "../../core/utils/resize_callbacks"; import { getDiagram } from "./diagram.importer"; import { getWindow, hasWindow } from "../../core/utils/window"; import { getPublicElement } from "../../core/element"; import eventsEngine from "../../events/core/events_engine"; import { addNamespace } from "../../events/utils/index"; import messageLocalization from "../../localization/message"; import numberLocalization from "../../localization/number"; import * as zIndexPool from "../overlay/z_index"; import Overlay from "../overlay/ui.overlay"; import DiagramToolbar from "./ui.diagram.toolbar"; import DiagramMainToolbar from "./ui.diagram.main_toolbar"; import DiagramHistoryToolbar from "./ui.diagram.history_toolbar"; import DiagramViewToolbar from "./ui.diagram.view_toolbar"; import DiagramPropertiesToolbar from "./ui.diagram.properties_toolbar"; import diagramContextMenuModule from "./ui.diagram.context_menu"; import DiagramContextToolbox from "./ui.diagram.context_toolbox"; import DiagramDialog from "./ui.diagram.dialogs"; import DiagramScrollView from "./ui.diagram.scroll_view"; import DiagramToolboxManager from "./diagram.toolbox_manager"; import DiagramToolbox from "./ui.diagram.toolbox"; import DiagramPropertiesPanel from "./ui.diagram.properties_panel"; import DiagramOptionsUpdateBar from "./diagram.options_update"; import DiagramDialogManager from "./ui.diagram.dialog_manager"; import DiagramCommandsManager from "./diagram.commands_manager"; import NodesOption from "./diagram.nodes_option"; import EdgesOption from "./diagram.edges_option"; var DIAGRAM_CLASS = "dx-diagram"; var DIAGRAM_FULLSCREEN_CLASS = "dx-diagram-fullscreen"; var DIAGRAM_TOOLBAR_WRAPPER_CLASS = DIAGRAM_CLASS + "-toolbar-wrapper"; var DIAGRAM_CONTENT_WRAPPER_CLASS = DIAGRAM_CLASS + "-content-wrapper"; var DIAGRAM_CONTENT_CLASS = DIAGRAM_CLASS + "-content"; var DIAGRAM_SCROLL_VIEW_CLASS = DIAGRAM_CLASS + "-scroll-view"; var DIAGRAM_FLOATING_TOOLBAR_CONTAINER_CLASS = DIAGRAM_CLASS + "-floating-toolbar-container"; var DIAGRAM_PROPERTIES_PANEL_TOOLBAR_CONTAINER_CLASS = DIAGRAM_CLASS + "-properties-panel-toolbar-container"; var DIAGRAM_LOADING_INDICATOR_CLASS = DIAGRAM_CLASS + "-loading-indicator"; var DIAGRAM_FLOATING_PANEL_OFFSET = 12; var DIAGRAM_DEFAULT_UNIT = "in"; var DIAGRAM_DEFAULT_ZOOMLEVEL = 1; var DIAGRAM_DEFAULT_AUTOZOOM_MODE = "disabled"; var DIAGRAM_DEFAULT_PAGE_ORIENTATION = "portrait"; var DIAGRAM_DEFAULT_PAGE_COLOR = "#ffffff"; var DIAGRAM_MAX_MOBILE_WINDOW_WIDTH = 576; var DIAGRAM_TOOLBOX_SHAPE_SPACING = 12; var DIAGRAM_TOOLBOX_SHAPES_PER_ROW = 3; var DIAGRAM_CONTEXT_TOOLBOX_SHAPE_SPACING = 12; var DIAGRAM_CONTEXT_TOOLBOX_SHAPES_PER_ROW = 4; var DIAGRAM_CONTEXT_TOOLBOX_DEFAULT_WIDTH = 152; var DIAGRAM_NAMESPACE = "dxDiagramEvent"; var FULLSCREEN_CHANGE_EVENT_NAME = addNamespace("fullscreenchange", DIAGRAM_NAMESPACE); var IE_FULLSCREEN_CHANGE_EVENT_NAME = addNamespace("msfullscreenchange", DIAGRAM_NAMESPACE); var WEBKIT_FULLSCREEN_CHANGE_EVENT_NAME = addNamespace("webkitfullscreenchange", DIAGRAM_NAMESPACE); var MOZ_FULLSCREEN_CHANGE_EVENT_NAME = addNamespace("mozfullscreenchange", DIAGRAM_NAMESPACE); class Diagram extends Widget { _init() { this._updateDiagramLockCount = 0; this.toggleFullscreenLock = 0; this._browserResizeTimer = -1; this._toolbars = []; super._init(); this._initDiagram(); this._createCustomCommand() } _initMarkup() { super._initMarkup(); this._toolbars = []; delete this._isMobileScreenSize; var isServerSide = !hasWindow(); this.$element().addClass(DIAGRAM_CLASS); delete this._mainToolbar; if (this.option("mainToolbar.visible")) { this._renderMainToolbar() } var $contentWrapper = $("<div>").addClass(DIAGRAM_CONTENT_WRAPPER_CLASS).appendTo(this.$element()); delete this._historyToolbar; delete this._historyToolbarResizeCallback; if (this._isHistoryToolbarVisible()) { this._renderHistoryToolbar($contentWrapper) } delete this._propertiesToolbar; delete this._propertiesToolbarResizeCallback; if (this._isPropertiesPanelEnabled()) { this._renderPropertiesToolbar($contentWrapper) } delete this._viewToolbar; delete this._viewToolbarResizeCallback; if (this.option("viewToolbar.visible")) { this._renderViewToolbar($contentWrapper) } delete this._toolbox; delete this._toolboxResizeCallback; if (this._isToolboxEnabled()) { this._renderToolbox($contentWrapper) } delete this._propertiesPanel; delete this._propertiesPanelResizeCallback; if (this._isPropertiesPanelEnabled()) { this._renderPropertiesPanel($contentWrapper) } this._$content = $("<div>").addClass(DIAGRAM_CONTENT_CLASS).appendTo($contentWrapper); delete this._contextMenu; this._diagramInstance.settings.contextMenuEnabled = this.option("contextMenu.enabled"); if (this._diagramInstance.settings.contextMenuEnabled) { this._renderContextMenu($contentWrapper) } delete this._contextToolbox; if (this.option("contextToolbox.enabled")) { this._renderContextToolbox($contentWrapper) } this._renderDialog($contentWrapper); if (!isServerSide) { var $scrollViewWrapper = $("<div>").addClass(DIAGRAM_SCROLL_VIEW_CLASS).appendTo(this._$content); this._createComponent($scrollViewWrapper, DiagramScrollView, { onCreateDiagram: e => { this._diagramInstance.createDocument(e.$parent[0], e.scrollView) } }) } if (hasWindow()) { resizeCallbacks.add(() => { this._killBrowserResizeTimer(); this._browserResizeTimer = setTimeout(() => this._processBrowserResize(), 100) }) } this._setCustomCommandChecked(DiagramCommandsManager.SHOW_PROPERTIES_PANEL_COMMAND_NAME, this._isPropertiesPanelVisible()); this._setCustomCommandChecked(DiagramCommandsManager.SHOW_TOOLBOX_COMMAND_NAME, this._isToolboxVisible()) } _processBrowserResize() { this._isMobileScreenSize = void 0; this._processDiagramResize(); this._killBrowserResizeTimer() } _processDiagramResize() { if (this._historyToolbarResizeCallback) { this._historyToolbarResizeCallback.call(this) } if (this._propertiesToolbarResizeCallback) { this._propertiesToolbarResizeCallback.call(this) } if (this._propertiesPanelResizeCallback) { this._propertiesPanelResizeCallback.call(this) } if (this._viewToolbarResizeCallback) { this._viewToolbarResizeCallback.call(this) } if (this._toolboxResizeCallback) { this._toolboxResizeCallback.call(this) } } _killBrowserResizeTimer() { if (this._browserResizeTimer > -1) { clearTimeout(this._browserResizeTimer) } this._browserResizeTimer = -1 } isMobileScreenSize() { if (void 0 === this._isMobileScreenSize) { this._isMobileScreenSize = hasWindow() && this.$element().outerWidth() < DIAGRAM_MAX_MOBILE_WINDOW_WIDTH } return this._isMobileScreenSize } _captureFocus() { if (this._diagramInstance) { this._diagramInstance.captureFocus() } } _captureFocusOnTimeout() { this._captureFocusTimeout = setTimeout(() => { this._captureFocus(); delete this._captureFocusTimeout }, 100) } _killCaptureFocusTimeout() { if (this._captureFocusTimeout) { clearTimeout(this._captureFocusTimeout); delete this._captureFocusTimeout } } notifyBarCommandExecuted() { this._captureFocusOnTimeout() } _registerToolbar(component) { this._registerBar(component); this._toolbars.push(component) } _registerBar(component) { component.bar.onChanged.add(this); this._diagramInstance.registerBar(component.bar) } _getExcludeCommands() { var excludeCommands = []; if (!this._isToolboxEnabled()) { excludeCommands.push(DiagramCommandsManager.SHOW_TOOLBOX_COMMAND_NAME) } if (!this._isPropertiesPanelEnabled()) { excludeCommands.push(DiagramCommandsManager.SHOW_PROPERTIES_PANEL_COMMAND_NAME) } return excludeCommands } _getToolbarBaseOptions() { return { onContentReady: _ref => { var { component: component } = _ref; return this._registerToolbar(component) }, onSubMenuVisibilityChanging: _ref2 => { var { component: component } = _ref2; return this._diagramInstance.updateBarItemsState(component.bar) }, onPointerUp: this._onPanelPointerUp.bind(this), export: this.option("export"), container: this.$element(), excludeCommands: this._getExcludeCommands(), onInternalCommand: this._onInternalCommand.bind(this), onCustomCommand: this._onCustomCommand.bind(this), isMobileView: this.isMobileScreenSize() } } _onInternalCommand(e) { switch (e.command) { case DiagramCommandsManager.SHOW_TOOLBOX_COMMAND_NAME: if (this._toolbox) { this._toolbox.toggle() } break; case DiagramCommandsManager.SHOW_PROPERTIES_PANEL_COMMAND_NAME: if (this._propertiesPanel) { this._propertiesPanel.toggle() } } } _onCustomCommand(e) { this._customCommandAction({ name: e.name }) } _renderMainToolbar() { var $toolbarWrapper = $("<div>").addClass(DIAGRAM_TOOLBAR_WRAPPER_CLASS).appendTo(this.$element()); this._mainToolbar = this._createComponent($toolbarWrapper, DiagramMainToolbar, extend(this._getToolbarBaseOptions(), { commands: this.option("mainToolbar.commands"), skipAdjustSize: true })) } _isHistoryToolbarVisible() { return this.option("historyToolbar.visible") && !this.isReadOnlyMode() } _renderHistoryToolbar($parent) { var isServerSide = !hasWindow(); var $container = $("<div>").addClass(DIAGRAM_FLOATING_TOOLBAR_CONTAINER_CLASS).appendTo($parent); this._historyToolbar = this._createComponent($container, DiagramHistoryToolbar, extend(this._getToolbarBaseOptions(), { commands: this.option("historyToolbar.commands"), locateInMenu: "never" })); this._updateHistoryToolbarPosition($container, $parent, isServerSide); this._historyToolbarResizeCallback = () => { this._historyToolbar.option("isMobileView", this.isMobileScreenSize()) } } _updateHistoryToolbarPosition($container, $parent, isServerSide) { if (isServerSide) { return } positionUtils.setup($container, { my: "left top", at: "left top", of: $parent, offset: DIAGRAM_FLOATING_PANEL_OFFSET + " " + DIAGRAM_FLOATING_PANEL_OFFSET }) } _isToolboxEnabled() { return "disabled" !== this.option("toolbox.visibility") && !this.isReadOnlyMode() } _isToolboxVisible() { return "visible" === this.option("toolbox.visibility") || "auto" === this.option("toolbox.visibility") && !this.isMobileScreenSize() } _renderToolbox($parent) { var isServerSide = !hasWindow(); var $toolBox = $("<div>").appendTo($parent); var bounds = this._getToolboxBounds($parent, isServerSide); this._toolbox = this._createComponent($toolBox, DiagramToolbox, { isMobileView: this.isMobileScreenSize(), isVisible: this._isToolboxVisible(), container: this.$element(), height: bounds.height, offsetParent: $parent, offsetX: bounds.offsetX, offsetY: bounds.offsetY, showSearch: this.option("toolbox.showSearch"), toolboxGroups: this._getToolboxGroups(), toolboxWidth: this.option("toolbox.width"), onShapeCategoryRendered: e => { if (isServerSide) { return } this._diagramInstance.createToolbox(e.$element[0], "texts" === e.displayMode, e.shapes || e.category, { shapeIconSpacing: DIAGRAM_TOOLBOX_SHAPE_SPACING, shapeIconCountInRow: this.option("toolbox.shapeIconsPerRow"), shapeIconAttributes: { "data-toggle": e.dataToggle } }) }, onFilterChanged: e => { if (isServerSide) { return } this._diagramInstance.applyToolboxFilter(e.text, e.filteringToolboxes) }, onVisibilityChanging: e => { if (isServerSide) { return } this._setCustomCommandChecked(DiagramCommandsManager.SHOW_TOOLBOX_COMMAND_NAME, e.visible); if (this._propertiesPanel) { if (e.visible && this.isMobileScreenSize()) { this._propertiesPanel.hide() } } if (this._historyToolbar) { if (e.visible && this.isMobileScreenSize()) { this._historyToolbarZIndex = zIndexPool.create(Overlay.baseZIndex()); this._historyToolbar.$element().css("zIndex", this._historyToolbarZIndex); this._historyToolbar.$element().css("boxShadow", "none") } } if (this._viewToolbar) { this._viewToolbar.$element().css("opacity", e.visible && this.isMobileScreenSize() ? "0" : "1"); this._viewToolbar.$element().css("pointerEvents", e.visible && this.isMobileScreenSize() ? "none" : "") } }, onVisibilityChanged: e => { if (!e.visible && !this._textInputStarted) { this._captureFocus() } if (!isServerSide) { if (this._historyToolbar) { if (!e.visible && this.isMobileScreenSize() && this._historyToolbarZIndex) { zIndexPool.remove(this._historyToolbarZIndex); this._historyToolbar.$element().css("zIndex", ""); this._historyToolbar.$element().css("boxShadow", ""); this._historyToolbarZIndex = void 0 } } } }, onPointerUp: this._onPanelPointerUp.bind(this) }); this._toolboxResizeCallback = () => { var bounds = this._getToolboxBounds($parent, isServerSide); this._toolbox.option("height", bounds.height); var prevIsMobileView = this._toolbox.option("isMobileView"); if (prevIsMobileView !== this.isMobileScreenSize()) { this._toolbox.option({ isMobileView: this.isMobileScreenSize(), isVisible: this._isToolboxVisible() }); this._setCustomCommandChecked(DiagramCommandsManager.SHOW_TOOLBOX_COMMAND_NAME, this._isToolboxVisible()) } this._toolbox.updateMaxHeight() } } _getToolboxBounds($parent, isServerSide) { var result = { offsetX: DIAGRAM_FLOATING_PANEL_OFFSET, offsetY: DIAGRAM_FLOATING_PANEL_OFFSET, height: !isServerSide ? $parent.height() - 2 * DIAGRAM_FLOATING_PANEL_OFFSET : 0 }; if (this._historyToolbar && !isServerSide) { result.offsetY += this._historyToolbar.$element().outerHeight() + DIAGRAM_FLOATING_PANEL_OFFSET; result.height -= this._historyToolbar.$element().outerHeight() + DIAGRAM_FLOATING_PANEL_OFFSET } if (this._viewToolbar && !isServerSide) { result.height -= this._viewToolbar.$element().outerHeight() + this._getViewToolbarYOffset(isServerSide) } return result } _renderViewToolbar($parent) { var isServerSide = !hasWindow(); var $container = $("<div>").addClass(DIAGRAM_FLOATING_TOOLBAR_CONTAINER_CLASS).appendTo($parent); this._viewToolbar = this._createComponent($container, DiagramViewToolbar, extend(this._getToolbarBaseOptions(), { commands: this.option("viewToolbar.commands"), locateInMenu: "never" })); this._updateViewToolbarPosition($container, $parent, isServerSide); this._viewToolbarResizeCallback = () => { this._updateViewToolbarPosition($container, $parent, isServerSide) } } _getViewToolbarYOffset(isServerSide) { if (isServerSide) { return } var result = DIAGRAM_FLOATING_PANEL_OFFSET; if (this._viewToolbar && this._propertiesToolbar) { result += (this._propertiesToolbar.$element().outerHeight() - this._viewToolbar.$element().outerHeight()) / 2 } return result } _updateViewToolbarPosition($container, $parent, isServerSide) { if (isServerSide) { return } positionUtils.setup($container, { my: "left bottom", at: "left bottom", of: $parent, offset: DIAGRAM_FLOATING_PANEL_OFFSET + " -" + this._getViewToolbarYOffset(isServerSide) }) } _isPropertiesPanelEnabled() { return "disabled" !== this.option("propertiesPanel.visibility") && !this.isReadOnlyMode() } _isPropertiesPanelVisible() { return "visible" === this.option("propertiesPanel.visibility") } _renderPropertiesToolbar($parent) { var isServerSide = !hasWindow(); var $container = $("<div>").addClass(DIAGRAM_FLOATING_TOOLBAR_CONTAINER_CLASS).addClass(DIAGRAM_PROPERTIES_PANEL_TOOLBAR_CONTAINER_CLASS).appendTo($parent); this._propertiesToolbar = this._createComponent($container, DiagramPropertiesToolbar, extend(this._getToolbarBaseOptions(), { buttonStylingMode: "contained", buttonType: "default", locateInMenu: "never" })); this._updatePropertiesToolbarPosition($container, $parent, isServerSide); this._propertiesToolbarResizeCallback = () => { this._updatePropertiesToolbarPosition($container, $parent, isServerSide) } } _updatePropertiesToolbarPosition($container, $parent, isServerSide) { if (isServerSide) { return } positionUtils.setup($container, { my: "right bottom", at: "right bottom", of: $parent, offset: "-" + DIAGRAM_FLOATING_PANEL_OFFSET + " -" + DIAGRAM_FLOATING_PANEL_OFFSET }) } _renderPropertiesPanel($parent) { var isServerSide = !hasWindow(); var $propertiesPanel = $("<div>").appendTo($parent); var offsetX = DIAGRAM_FLOATING_PANEL_OFFSET; var offsetY = 2 * DIAGRAM_FLOATING_PANEL_OFFSET + (!isServerSide ? this._propertiesToolbar.$element().outerHeight() : 0); this._propertiesPanel = this._createComponent($propertiesPanel, DiagramPropertiesPanel, { isMobileView: this.isMobileScreenSize(), isVisible: this._isPropertiesPanelVisible(), container: this.$element(), offsetParent: $parent, offsetX: offsetX, offsetY: offsetY, propertyTabs: this.option("propertiesPanel.tabs"), onCreateToolbar: e => { e.toolbar = this._createComponent(e.$parent, DiagramToolbar, extend(this._getToolbarBaseOptions(), { commands: e.commands, locateInMenu: "never", editorStylingMode: "outlined" })) }, onVisibilityChanging: e => { if (isServerSide) { return } this._updatePropertiesPanelGroupBars(e.component); this._setCustomCommandChecked(DiagramCommandsManager.SHOW_PROPERTIES_PANEL_COMMAND_NAME, e.visible); if (this._toolbox) { if (e.visible && this.isMobileScreenSize()) { this._toolbox.hide() } } }, onVisibilityChanged: e => { if (!e.visible && !this._textInputStarted) { this._captureFocus() } }, onSelectedGroupChanged: _ref3 => { var { component: component } = _ref3; return this._updatePropertiesPanelGroupBars(component) }, onPointerUp: this._onPanelPointerUp.bind(this) }); this._propertiesPanelResizeCallback = () => { var prevIsMobileView = this._propertiesPanel.option("isMobileView"); if (prevIsMobileView !== this.isMobileScreenSize()) { this._propertiesPanel.option({ isMobileView: this.isMobileScreenSize(), isVisible: this._isPropertiesPanelVisible() }); this._setCustomCommandChecked(DiagramCommandsManager.SHOW_PROPERTIES_PANEL_COMMAND_NAME, this._isPropertiesPanelVisible()) } } } _updatePropertiesPanelGroupBars(component) { component.getActiveToolbars().forEach(toolbar => { this._diagramInstance.updateBarItemsState(toolbar.bar) }) } _onPanelPointerUp() { this._captureFocusOnTimeout() } _renderContextMenu($parent) { var $contextMenu = $("<div>").appendTo($parent); this._contextMenu = this._createComponent($contextMenu, diagramContextMenuModule.DiagramContextMenuWrapper, { commands: this.option("contextMenu.commands"), onContentReady: _ref4 => { var { component: component } = _ref4; return this._registerBar(component) }, onVisibilityChanging: _ref5 => { var { component: component } = _ref5; return this._diagramInstance.updateBarItemsState(component.bar) }, onItemClick: itemData => this._onBeforeCommandExecuted(itemData.command), export: this.option("export"), excludeCommands: this._getExcludeCommands(), onInternalCommand: this._onInternalCommand.bind(this), onCustomCommand: this._onCustomCommand.bind(this) }) } _renderContextToolbox($parent) { var isServerSide = !hasWindow(); var category = this.option("contextToolbox.category"); var displayMode = this.option("contextToolbox.displayMode"); var shapes = this.option("contextToolbox.shapes"); var $contextToolbox = $("<div>").appendTo($parent); this._contextToolbox = this._createComponent($contextToolbox, DiagramContextToolbox, { toolboxWidth: this.option("contextToolbox.width"), onShown: e => { if (isServerSide) { return } var $toolboxContainer = $(e.$element); var isTextGroup = "texts" === displayMode; if (!shapes && !category && !isTextGroup) { var group = this._getToolboxGroups().filter((function(g) { return g.category === e.category }))[0]; if (group) { isTextGroup = "texts" === group.displayMode } } this._diagramInstance.createContextToolbox($toolboxContainer[0], isTextGroup, shapes || category || e.category, { shapeIconSpacing: DIAGRAM_CONTEXT_TOOLBOX_SHAPE_SPACING, shapeIconCountInRow: this.option("contextToolbox.shapeIconsPerRow") }, shapeType => { e.callback(shapeType); this._captureFocus(); e.hide() }) } }) } _setCustomCommandChecked(command, checked) { this._toolbars.forEach(tb => { tb.setCommandChecked(command, checked) }) } _onBeforeCommandExecuted(command) { var dialogParameters = DiagramDialogManager.getDialogParameters(command); if (dialogParameters) { this._showDialog(dialogParameters) } return !!dialogParameters } _renderDialog($parent) { var $dialogElement = $("<div>").appendTo($parent); this._dialogInstance = this._createComponent($dialogElement, DiagramDialog, {}) } _showDialog(dialogParameters) { if (this._dialogInstance) { this._dialogInstance.option("onGetContent", dialogParameters.onGetContent); this._dialogInstance.option("onHidden", function() { this._captureFocus() }.bind(this)); this._dialogInstance.option("command", this._diagramInstance.getCommand(dialogParameters.command)); this._dialogInstance.option("title", dialogParameters.title); this._dialogInstance._show() } } _showLoadingIndicator() { this._loadingIndicator = $("<div>").addClass(DIAGRAM_LOADING_INDICATOR_CLASS); this._createComponent(this._loadingIndicator, LoadIndicator, {}); var $parent = this._$content || this.$element(); $parent.append(this._loadingIndicator) } _hideLoadingIndicator() { if (!this._loadingIndicator) { return } this._loadingIndicator.remove(); this._loadingIndicator = null } _initDiagram() { var { DiagramControl: DiagramControl } = getDiagram(); this._diagramInstance = new DiagramControl; this._diagramInstance.onChanged = this._raiseDataChangeAction.bind(this); this._diagramInstance.onEdgeInserted = this._raiseEdgeInsertedAction.bind(this); this._diagramInstance.onEdgeUpdated = this._raiseEdgeUpdatedAction.bind(this); this._diagramInstance.onEdgeRemoved = this._raiseEdgeRemovedAction.bind(this); this._diagramInstance.onNodeInserted = this._raiseNodeInsertedAction.bind(this); this._diagramInstance.onNodeUpdated = this._raiseNodeUpdatedAction.bind(this); this._diagramInstance.onNodeRemoved = this._raiseNodeRemovedAction.bind(this); this._diagramInstance.onToolboxDragStart = this._raiseToolboxDragStart.bind(this); this._diagramInstance.onToolboxDragEnd = this._raiseToolboxDragEnd.bind(this); this._diagramInstance.onTextInputStart = this._raiseTextInputStart.bind(this); this._diagramInstance.onTextInputEnd = this._raiseTextInputEnd.bind(this); this._diagramInstance.onToggleFullscreen = this._onToggleFullScreen.bind(this); this._diagramInstance.onShowContextMenu = this._onShowContextMenu.bind(this); this._diagramInstance.onHideContextMenu = this._onHideContextMenu.bind(this); this._diagramInstance.onShowContextToolbox = this._onShowContextToolbox.bind(this); this._diagramInstance.onHideContextToolbox = this._onHideContextToolbox.bind(this); this._diagramInstance.onNativeAction.add({ notifyItemClick: this._raiseItemClickAction.bind(this), notifyItemDblClick: this._raiseItemDblClickAction.bind(this), notifySelectionChanged: this._raiseSelectionChanged.bind(this) }); this._diagramInstance.onRequestOperation = this._raiseRequestEditOperation.bind(this); this._updateEventSubscriptionMethods(); this._updateDefaultItemProperties(); this._updateEditingSettings(); this._updateShapeTexts(); this._updateUnitItems(); this._updateFormatUnitsMethod(); if (this.option("units") !== DIAGRAM_DEFAULT_UNIT) { this._updateUnitsState() } if (this.isReadOnlyMode()) { this._updateReadOnlyState() } if (this.option("pageSize")) { if (this.option("pageSize.items")) { this._updatePageSizeItemsState() } if (this.option("pageSize.width") && this.option("pageSize.height")) { this._updatePageSizeState() } } if (this.option("pageOrientation") !== DIAGRAM_DEFAULT_PAGE_ORIENTATION) { this._updatePageOrientationState() } if (this.option("pageColor") !== DIAGRAM_DEFAULT_PAGE_COLOR) { this._updatePageColorState() } if (this.option("viewUnits") !== DIAGRAM_DEFAULT_UNIT) { this._updateViewUnitsState() } if (!this.option("showGrid")) { this._updateShowGridState() } if (!this.option("snapToGrid")) { this._updateSnapToGridState() } if (this.option("gridSize")) { this._updateGridSizeState() } if (this.option("zoomLevel") !== DIAGRAM_DEFAULT_ZOOMLEVEL) { this._updateZoomLevelState() } if (this.option("simpleView")) { this._updateSimpleViewState() } if (this.option("autoZoomMode") !== DIAGRAM_DEFAULT_AUTOZOOM_MODE) { this._updateAutoZoomState() } if (this.option("fullScreen")) { var window = getWindow(); if (window && window.self !== window.top) { this.option("fullScreen", false) } else { this._updateFullscreenState() } } this.optionsUpdateBar = new DiagramOptionsUpdateBar(this); this._diagramInstance.registerBar(this.optionsUpdateBar); if (hasWindow()) { this._diagramInstance.initMeasurer(this.$element()[0]) } this._updateCustomShapes(this._getCustomShapes()); this._refreshDataSources() } _clean() { if (this._diagramInstance) { this._diagramInstance.cleanMarkup(element => { $(element).empty() }) } super._clean() } _dispose() { this._killCaptureFocusTimeout(); super._dispose(); this._diagramInstance = void 0 } _executeDiagramCommand(command, parameter) { this._diagramInstance.getCommand(command).execute(parameter) } getNodeDataSource() { return this._nodesOption && this._nodesOption.getDataSource() } getEdgeDataSource() { return this._edgesOption && this._edgesOption.getDataSource() } _refreshDataSources() { this._beginUpdateDiagram(); this._refreshNodesDataSource(); this._refreshEdgesDataSource(); this._endUpdateDiagram() } _refreshNodesDataSource() { if (this._nodesOption) { this._nodesOption._disposeDataSource(); delete this._nodesOption } if (this.option("nodes.dataSource")) { this._nodesOption = new NodesOption(this); this._nodesOption.option("dataSource", this.option("nodes.dataSource")); this._nodesOption._refreshDataSource() } } _refreshEdgesDataSource() { if (this._edgesOption) { this._edgesOption._disposeDataSource(); delete this._edgesOption } if (this.option("edges.dataSource")) { this._edgesOption = new EdgesOption(this); this._edgesOption.option("dataSource", this.option("edges.dataSource")); this._edgesOption._refreshDataSource() } } _getDiagramData() { var value; var { DiagramCommand: DiagramCommand } = getDiagram(); this._executeDiagramCommand(DiagramCommand.Export, (function(data) { value = data })); return value } _setDiagramData(data, keepExistingItems) { var { DiagramCommand: DiagramCommand } = getDiagram(); this._executeDiagramCommand(DiagramCommand.Import, { data: data, keepExistingItems: keepExistingItems }) } isReadOnlyMode() { return this.option("readOnly") || this.option("disabled") } _onDataSourceChanged() { this._bindDiagramData() } _getChangesKeys(changes) { return changes.map(change => { if (isDefined(change.internalKey)) { return change.internalKey } else if (isDefined(change.key)) { return change.key } else { return null } }).filter(key => isDefined(key)) } _createOptionGetter(optionName) { var expr = this.option(optionName); return expr && compileGetter(expr) } _onRequestUpdateLayout(changes) { if (!this._requestLayoutUpdateAction) { this._createRequestLayoutUpdateAction() } var eventArgs = { changes: changes, allowed: false }; this._requestLayoutUpdateAction(eventArgs); return eventArgs.allowed } _createOptionSetter(optionName) { var expr = this.option(optionName); if (isFunction(expr)) { return expr } return expr && compileSetter(expr) } _bindDiagramData() { if (this._updateDiagramLockCount || !this._isBindingMode()) { return } var { DiagramCommand: DiagramCommand, ConnectorLineOption: ConnectorLineOption, ConnectorLineEnding: ConnectorLineEnding } = getDiagram(); var lineOptionGetter; var lineOptionSetter; var startLineEndingGetter; var startLineEndingSetter; var endLineEndingGetter; var endLineEndingSetter; var containerKeyGetter; var containerKeySetter; var data = { nodeDataSource: this._nodesOption && this._nodesOption.getItems(), edgeDataSource: this._edgesOption && this._edgesOption.getItems(), nodeDataImporter: { getKey: this._createOptionGetter("nodes.keyExpr"), setKey: this._createOptionSetter("nodes.keyExpr"), getCustomData: this._createOptionGetter("nodes.customDataExpr"), setCustomData: this._createOptionSetter("nodes.customDataExpr"), getLocked: this._createOptionGetter("nodes.lockedExpr"), setLocked: this._createOptionSetter("nodes.lockedExpr"), getStyle: this._createOptionGetter("nodes.styleExpr"), setStyle: this._createOptionSetter("nodes.styleExpr"), getStyleText: this._createOptionGetter("nodes.textStyleExpr"), setStyleText: this._createOptionSetter("nodes.textStyleExpr"), getZIndex: this._createOptionGetter("nodes.zIndexExpr"), setZIndex: this._createOptionSetter("nodes.zIndexExpr"), getType: this._createOptionGetter("nodes.typeExpr"), setType: this._createOptionSetter("nodes.typeExpr"), getText: this._createOptionGetter("nodes.textExpr"), setText: this._createOptionSetter("nodes.textExpr"), getImage: this._createOptionGetter("nodes.imageUrlExpr"), setImage: this._createOptionSetter("nodes.imageUrlExpr"), getLeft: this._createOptionGetter("nodes.leftExpr"), setLeft: this._createOptionSetter("nodes.leftExpr"), getTop: this._createOptionGetter("nodes.topExpr"), setTop: this._createOptionSetter("nodes.topExpr"), getWidth: this._createOptionGetter("nodes.widthExpr"), setWidth: this._createOptionSetter("nodes.widthExpr"), getHeight: this._createOptionGetter("nodes.heightExpr"), setHeight: this._createOptionSetter("nodes.heightExpr"), getParentKey: this._createOptionGetter("nodes.parentKeyExpr"), setParentKey: this._createOptionSetter("nodes.parentKeyExpr"), getItems: this._createOptionGetter("nodes.itemsExpr"), setItems: this._createOptionSetter("nodes.itemsExpr"), getContainerKey: containerKeyGetter = this._createOptionGetter("nodes.containerKeyExpr"), setContainerKey: containerKeySetter = this._createOptionSetter("nodes.containerKeyExpr"), getChildren: !containerKeyGetter && !containerKeySetter && this._createOptionGetter("nodes.containerChildrenExpr"), setChildren: !containerKeyGetter && !containerKeySetter && this._createOptionSetter("nodes.containerChildrenExpr") }, edgeDataImporter: { getKey: this._createOptionGetter("edges.keyExpr"), setKey: this._createOptionSetter("edges.keyExpr"), getCustomData: this._createOptionGetter("edges.customDataExpr"), setCustomData: this._createOptionSetter("edges.customDataExpr"), getLocked: this._createOptionGetter("edges.lockedExpr"), setLocked: this._createOptionSetter("edges.lockedExpr"), getStyle: this._createOptionGetter("edges.styleExpr"), setStyle: this._createOptionSetter("edges.styleExpr"), getStyleText: this._createOptionGetter("edges.textStyleExpr"), setStyleText: this._createOptionSetter("edges.textStyleExpr"), getZIndex: this._createOptionGetter("edges.zIndexExpr"), setZIndex: this._createOptionSetter("edges.zIndexExpr"), getFrom: this._createOptionGetter("edges.fromExpr"), setFrom: this._createOptionSetter("edges.fromExpr"), getFromPointIndex: this._createOptionGetter("edges.fromPointIndexExpr"), setFromPointIndex: this._createOptionSetter("edges.fromPointIndexExpr"), getTo: this._createOptionGetter("edges.toExpr"), setTo: this._createOptionSetter("edges.toExpr"), getToPointIndex: this._createOptionGetter("edges.toPointIndexExpr"), setToPointIndex: this._createOptionSetter("edges.toPointIndexExpr"), getPoints: this._createOptionGetter("edges.pointsExpr"), setPoints: this._createOptionSetter("edges.pointsExpr"), getText: this._createOptionGetter("edges.textExpr"), setText: this._createOptionSetter("edges.textExpr"), getLineOption: (lineOptionGetter = this._createOptionGetter("edges.lineTypeExpr")) && function(obj) { var lineType = lineOptionGetter(obj); return this._getConnectorLineOption(lineType) }.bind(this), setLineOption: (lineOptionSetter = this._createOptionSetter("edges.lineTypeExpr")) && function(obj, value) { switch (value) { case ConnectorLineOption.Straight: value = "straight"; break; case ConnectorLineOption.Orthogonal: value = "orthogonal" } lineOptionSetter(obj, value) }.bind(this), getStartLineEnding: (startLineEndingGetter = this._createOptionGetter("edges.fromLineEndExpr")) && function(obj) { var lineEnd = startLineEndingGetter(obj); return this._getConnectorLineEnding(lineEnd) }.bind(this), setStartLineEnding: (startLineEndingSetter = this._createOptionSetter("edges.fromLineEndExpr")) && function(obj, value) { switch (value) { case ConnectorLineEnding.Arrow: value = "arrow"; break; case ConnectorLineEnding.OutlinedTriangle: value = "outlinedTriangle"; break; case ConnectorLineEnding.FilledTriangle: value = "filledTriangle"; break; case ConnectorLineEnding.None: value = "none" } startLineEndingSetter(obj, value) }.bind(this), getEndLineEnding: (endLineEndingGetter = this._createOptionGetter("edges.toLineEndExpr")) && function(obj) { var lineEnd = endLineEndingGetter(obj); return this._getConnectorLineEnding(lineEnd) }.bind(this), setEndLineEnding: (endLineEndingSetter = this._createOptionSetter("edges.toLineEndExpr")) && function(obj, value) { switch (value) { case ConnectorLineEnding.Arrow: value = "arrow"; break; case ConnectorLineEnding.OutlinedTriangle: value = "outlinedTriangle"; break; case ConnectorLineEnding.FilledTriangle: value = "filledTriangle"; break; case ConnectorLineEnding.None: value = "none" } endLineEndingSetter(obj, value) }.bind(this) }, layoutParameters: this._getDataBindingLayoutParameters() }; this._executeDiagramCommand(DiagramCommand.BindDocument, data) } _reloadContentByChanges(changes, isExternalChanges) { var keys = this._getChangesKeys(changes); var applyLayout = this._onRequestUpdateLayout(changes); this._reloadContent(keys, applyLayout, isExternalChanges) } _reloadContent(itemKeys, applyLayout, isExternalChanges) { this._diagramInstance.reloadContent(itemKeys, () => { var nodeDataSource; var edgeDataSource; if (this._nodesOption && isExternalChanges) { nodeDataSource = this._nodesOption.getItems() } if (this._edgesOption && isExternalChanges) { edgeDataSource = this._edgesOption.getItems() } return { nodeDataSource: nodeDataSource, edgeDataSource: edgeDataSource } }, applyLayout && this._getDataBindingLayoutParameters(), isExternalChanges) } _getConnectorLineOption(lineType) { var { ConnectorLineOption: ConnectorLineOption } = getDiagram(); switch (lineType) { case "straight": return ConnectorLineOption.Straight; default: return ConnectorLineOption.Orthogonal } } _getConnectorLineEnding(lineEnd) { var { ConnectorLineEnding: ConnectorLineEnding } = getDiagram(); switch (lineEnd) { case "arrow": return ConnectorLineEnding.Arrow; case "outlinedTriangle": return ConnectorLineEnding.OutlinedTriangle; case "filledTriangle": return ConnectorLineEnding.FilledTriangle; default: return ConnectorLineEnding.None } } _getDataBindingLayoutParameters() { var { DataLayoutType: DataLayoutType, DataLayoutOrientation: DataLayoutOrientation } = getDiagram(); var layoutParametersOption = this.option("nodes.autoLayout") || "off"; var layoutType = layoutParametersOption.type || layoutParametersOption; var parameters = {}; if ("off" !== layoutType && ("auto" !== layoutType || !this._hasNodePositionExprs())) { switch (layoutType) { case "tree": parameters.type = DataLayoutType.Tree; break; default: parameters.type = DataLayoutType.Sugiyama } switch (layoutParametersOption.orientation) { case "vertical": parameters.orientation = DataLayoutOrientation.Vertical; break; case "horizontal": parameters.orientation = DataLayoutOrientation.Horizontal } if (this.option("edges.fromPointIndexExpr") || this.option("edges.toPointIndexExpr")) { parameters.skipPointIndices = true } } parameters.autoSizeEnabled = !!this.option("nodes.autoSizeEnabled"); return parameters } _hasNodePositionExprs() { return this.option("nodes.topExpr") && this.option("nodes.leftExpr") } _getAutoZoomValue(option) { var { AutoZoomMode: AutoZoomMode } = getDiagram(); switch (option) { case "fitContent": return AutoZoomMode.FitContent; case "fitWidth": return AutoZoomMode.FitToWidth; default: return AutoZoomMode.Disabled } } _isBindingMode() { return this._nodesOption && this._nodesOption.hasItems() || this._edgesOption && this._nodesOption.hasItems() } _beginUpdateDiagram() { this._updateDiagramLockCount++ } _endUpdateDiagram() { this._updateDiagramLockCount = Math.max(this._updateDiagramLockCount - 1, 0); if (!this._updateDiagramLockCount) { this._bindDiagramData() } } _getCustomShapes() { return this.option("customShapes") || [] } _getToolboxGroups() { return DiagramToolboxManager.getGroups(this.option("toolbox.groups")) } _updateAllCustomShapes() { this._diagramInstance.removeAllCustomShapes(); this._updateCustomShapes(this._getCustomShapes()) } _updateCustomShapes(customShapes, prevCustomShapes) { if (Array.isArray(prevCustomShapes)) { this._diagramInstance.removeCustomShapes(prevCustomShapes.map(s => s.type)) } if (Array.isArray(customShapes)) { this._diagramInstance.addCustomShapes(customShapes.map(s => { var templateOption = s.template || this.option("customShapeTemplate"); var template = templateOption && this._getTemplate(templateOption); var toolboxTemplateOption = s.toolboxTemplate || this.option("customShapeToolboxTemplate"); var toolboxTemplate = toolboxTemplateOption && this._getTemplate(toolboxTemplateOption); return { category: s.category, type: s.type, baseType: s.baseType, title: s.title, svgUrl: s.backgroundImageUrl, svgToolboxUrl: s.backgroundImageToolboxUrl, svgLeft: s.backgroundImageLeft,