/*############################################################################## # HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ############################################################################## */ define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array", "dojo/_base/Deferred", "dojo/dom", "dojo/dom-construct", "dojo/on", "dojo/html", "dojo/store/Memory", "dojo/store/Observable", "dijit/layout/BorderContainer", "dijit/layout/TabContainer", "dijit/layout/ContentPane", "dijit/registry", "dijit/Dialog", "dojox/html/entities", "dgrid/OnDemandGrid", "dgrid/Keyboard", "dgrid/Selection", "dgrid/selector", "dgrid/extensions/ColumnResizer", "dgrid/extensions/DijitRegistry", "hpcc/_Widget", "hpcc/GraphWidget", "hpcc/ESPUtil", "hpcc/ESPWorkunit", "hpcc/TimingGridWidget", "hpcc/TimingTreeMapWidget", "hpcc/WsWorkunits", "dojo/text!../templates/GraphPageWidget.html", "dijit/PopupMenuItem", "dijit/Menu", "dijit/MenuItem", "dijit/MenuSeparator", "dijit/Dialog", "dijit/form/TextBox", "dijit/form/SimpleTextarea", "dijit/form/NumberSpinner", "dijit/form/DropDownButton" ], function (declare, lang, arrayUtil, Deferred, dom, domConstruct, on, html, Memory, Observable, BorderContainer, TabContainer, ContentPane, registry, Dialog, entities, OnDemandGrid, Keyboard, Selection, selector, ColumnResizer, DijitRegistry, _Widget, GraphWidget, ESPUtil, ESPWorkunit, TimingGridWidget, TimingTreeMapWidget, WsWorkunits, template) { return declare("GraphPageWidget", [_Widget], { templateString: template, baseClass: "GraphPageWidget", borderContainer: null, rightBorderContainer: null, graphName: "", wu: null, editorControl: null, global: null, main: null, overview: null, local: null, timingGrid: null, timingTreeMap: null, subgraphsGrid: null, verticesGrid: null, edgesGrid: null, xgmmlDialog: null, infoDialog: null, findField: null, findText: "", found: [], foundIndex: 0, overviewDepth: null, localDepth: null, localDistance: null, buildRendering: function (args) { this.inherited(arguments); }, postCreate: function (args) { this.inherited(arguments); this.borderContainer = registry.byId(this.id + "BorderContainer"); this.rightBorderContainer = registry.byId(this.id + "RightBorderContainer"); this.findField = registry.byId(this.id + "FindField"); this.mainDepth = registry.byId(this.id + "MainDepth"); this.overviewDepth = registry.byId(this.id + "OverviewDepth"); this.localDepth = registry.byId(this.id + "LocalDepth"); this.localDistance = registry.byId(this.id + "LocalDistance"); this._initGraphControls(); this._initTimings(); this._initDialogs(); }, startup: function (args) { this.inherited(arguments); this._initSubgraphs(); this._initVertices(); this._initEdges(); var splitter = this.borderContainer.getSplitter("right"); this.main.watchSplitter(splitter); this.overview.watchSplitter(splitter); this.local.watchSplitter(splitter); splitter = this.rightBorderContainer.getSplitter("bottom"); this.main.watchSplitter(splitter); this.overview.watchSplitter(splitter); this.local.watchSplitter(splitter); this.main.watchSelect(registry.byId(this.id + "AdvancedMenu")); }, resize: function (args) { this.inherited(arguments); this.borderContainer.resize(); }, layout: function (args) { this.inherited(arguments); }, destroy: function (args) { this.xgmmlDialog.destroyRecursive(); this.infoDialog.destroyRecursive(); this.inherited(arguments); }, // Implementation --- _initGraphControls: function () { var context = this; this.global = registry.byId(this.id + "GlobalGraphWidget"); this.main = registry.byId(this.id + "MainGraphWidget"); this.main.onSelectionChanged = function (items) { context.syncSelectionFrom(context.main); }; this.main.onLayoutFinished = function () { // TODO: Could be too expensive --- //context.wu.setGraphSvg(context.graphName, context.main.svg); }; this.main.onDoubleClick = function (globalID) { var mainItem = context.main.getItem(globalID); context.main.centerOnItem(mainItem, true); }; this.overview = registry.byId(this.id + "MiniGraphWidget"); this.overview.onSelectionChanged = function (items) { context.syncSelectionFrom(context.overview); }; this.overview.onDoubleClick = function (globalID) { var mainItem = context.main.getItem(globalID); context.main.centerOnItem(mainItem, true); }; this.local = registry.byId(this.id + "LocalGraphWidget"); this.local.onSelectionChanged = function (items) { context.syncSelectionFrom(context.local); }; this.local.onDoubleClick = function (globalID) { var mainItem = context.main.getItem(globalID); context._onLocalRefresh(); context.main.centerOnItem(mainItem, true); context.syncSelectionFrom(context.local); }; }, _initTimings: function () { this.timingGrid = registry.byId(this.id + "TimingsGrid"); var context = this; this.timingGrid.onClick = function (items) { context.syncSelectionFrom(context.timingGrid); }; this.timingGrid.onDblClick = function (item) { var subgraphID = item.SubGraphId; var mainItem = context.main.getItem(subgraphID); context.main.centerOnItem(mainItem, true); }; this.timingTreeMap = registry.byId(this.id + "TimingsTreeMap"); this.timingTreeMap.onClick = function (value) { context.syncSelectionFrom(context.timingTreeMap); } this.timingTreeMap.onDblClick = function (value) { var mainItem = context.main.getItem(value.SubGraphId); context.main.centerOnItem(mainItem, true); } }, _initDialogs: function () { var context = this; this.infoDialog = registry.byId(this.id + "InfoDialog"); on(dom.byId(this.id + "InfoDialogCancel"), "click", function (event) { context.infoDialog.hide(); }); this.xgmmlDialog = registry.byId(this.id + "XGMMLDialog"); this.xgmmlTextArea = registry.byId(this.id + "XGMMLTextArea"); on(dom.byId(this.id + "XGMMLDialogApply"), "click", function (event) { context.xgmmlDialog.hide(); if (context.xgmmlDialog.get("hpccMode") === "XGMML") { var xgmml = context.xgmmlTextArea.get("value"); context.loadGraphFromXGMML(xgmml); } else if (context.xgmmlDialog.get("hpccMode") === "DOT") { var dot = context.xgmmlTextArea.get("value"); context.loadGraphFromDOT(dot); } else if (context.xgmmlDialog.get("hpccMode") === "DOTATTRS") { var dotAttrs = context.xgmmlTextArea.get("value"); context.global.setDotMetaAttributes(dotAttrs); context.main.setDotMetaAttributes(dotAttrs); context.overview.setDotMetaAttributes(dotAttrs); context.local.setDotMetaAttributes(dotAttrs); context._onMainRefresh(); } }); on(dom.byId(this.id + "XGMMLDialogCancel"), "click", function (event) { context.xgmmlDialog.hide(); }); }, _initItemGrid: function (grid) { var context = this; grid.on(".dgrid-row:click", function (evt) { context.syncSelectionFrom(grid); }); grid.on(".dgrid-row:dblclick", function (evt) { var item = grid.row(evt).data; if (item._globalID) { var mainItem = context.main.getItem(item._globalID); context.main.centerOnItem(mainItem, true); } }); }, _initSubgraphs: function () { var store = new Memory({ idProperty: "id", data: [] }); this.subgraphsStore = Observable(store); this.subgraphsGrid = new declare([OnDemandGrid, Keyboard, Selection, ColumnResizer, DijitRegistry, ESPUtil.GridHelper])({ store: this.subgraphsStore }, this.id + "SubgraphsGrid"); this._initItemGrid(this.subgraphsGrid); }, _initVertices: function () { var store = new Memory({ idProperty: "id", data: [] }); this.verticesStore = Observable(store); this.verticesGrid = new declare([OnDemandGrid, Keyboard, Selection, ColumnResizer, DijitRegistry, ESPUtil.GridHelper])({ store: this.verticesStore }, this.id + "VerticesGrid"); this._initItemGrid(this.verticesGrid); }, _initEdges: function () { var store = new Memory({ idProperty: "id", data: [] }); this.edgesStore = Observable(store); this.edgesGrid = new declare([OnDemandGrid, Keyboard, Selection, ColumnResizer, DijitRegistry, ESPUtil.GridHelper])({ store: this.edgesStore }, this.id + "EdgesGrid"); this._initItemGrid(this.edgesGrid); }, _onMainRefresh: function () { this.main.setMessage("Performing Layout..."); this.main.startLayout("dot"); }, _onLocalRefresh: function () { this.refreshLocal(this.local.getSelectionAsGlobalID()); }, _doFind: function (prev) { if (this.findText != this.findField.value) { this.findText = this.findField.value; this.found = this.global.findAsGlobalID(this.findText); this.global.setSelectedAsGlobalID(this.found); this.syncSelectionFrom(this.global); this.foundIndex = -1; } this.foundIndex += prev ? -1 : +1; if (this.foundIndex < 0) { this.foundIndex = this.found.length - 1; } else if (this.foundIndex >= this.found.length) { this.foundIndex = 0; } if (this.found.length) { this.main.centerOnGlobalID(this.found[this.foundIndex], true); this.local.centerOnGlobalID(this.found[this.foundIndex], true); } }, _onFind: function (prev) { this.findText = ""; this._doFind(false); }, _onFindNext: function () { this._doFind(false); }, _onFindPrevious: function () { this._doFind(true); }, _onAbout: function () { html.set(dom.byId(this.id + "InfoDialogContent"), "
Version: " + this.main.getVersion() + "
" + this.main.getResourceLinks() + "
"); this.infoDialog.set("title", "About HPCC Systems Graph Control"); this.infoDialog.show(); }, _onGetSVG: function () { html.set(dom.byId(this.id + "InfoDialogContent"), ""); this.infoDialog.set("title", "SVG Source"); this.infoDialog.show(); }, _onRenderSVG: function () { var context = this this.main.localLayout(function (svg) { html.set(dom.byId(context.id + "InfoDialogContent"), "