/////////////////////////////////////////////////////////////////////////// // Copyright © 2014 - 2018 Esri. All Rights Reserved. // // 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', 'dijit/_WidgetBase', 'dojo/dom-geometry', 'dojo/dom-class', 'dojo/Evented', 'dojo/debounce' ], function(declare, lang, array, _WidgetBase, domGeometry, domClass, Evented, debounce) { var COMPONENT_NAME = 'jimu grid'; /** * The structure of the this layout has one limitation: * A stack only contains one component. */ return declare([_WidgetBase, Evented], { 'baseClass': 'jimu-dijit-gridlayout', declaredClass: 'jimu.dijit.GridLayout', container: null, // the container domNode of golden layout layoutDefinition: null, // configuration of golden layout components: null, // array of {id: string, dijit: dijit instance} editable: false, _layout: null, // instance of goldenLayout _coordinates: null, // an object whose key is component id and value is component coordinate. _isCreatingLayout: null, postCreate: function(){ this.inherited(arguments); this._isCreatingLayout = false; this._createLayout(this.layoutDefinition); }, restoreLayout: function(layoutDefinition) { layoutDefinition = layoutDefinition || this.layoutDefinition; this._createLayout(layoutDefinition); }, destroy: function() { array.forEach(this.components, function(component) { component.dijit.destroy(); }); this._layout.destroy(); this.inherited(arguments); }, getLayoutDefinition: function() { var currentConfig = this._layout.toConfig(); return currentConfig.content; }, resize: function() { var box = domGeometry.getMarginBox(this.container); this._layout.updateSize(box.w, box.h); }, getComponentSize: function(componentId) { var rootElem = this._layout.root.contentItems[0]; var contentItem = rootElem.getItemsById(componentId), container; if (contentItem && contentItem.length > 0) { container = contentItem[0].container; return { w: container.width, h: container.height }; } return { w: 0, h: 0 }; }, getSize: function() { return { w: this._layout.width, h: this._layout.height }; }, /** * */ setVisible: function(componentId, visible) { var rootElem = this._layout.root.contentItems[0]; var contentItem = rootElem.getItemsById(componentId); if (contentItem && contentItem.length > 0 && visible === false) { this._hideComponent(contentItem[0]); } else if ((!contentItem || contentItem.length === 0) && visible === true) { this._showComponent(componentId); } }, highlightItem: function(componentId) { var rootElem = this._layout.root.contentItems[0]; var contentItem = rootElem.getItemsById(componentId); if (contentItem && contentItem.length > 0) { contentItem[0].highlight(); } }, unhighlightItem: function(componentId) { var rootElem = this._layout.root.contentItems[0]; var contentItem = rootElem.getItemsById(componentId); if (contentItem && contentItem.length > 0) { contentItem[0].unhighlight(); } }, _createLayout: function(layoutDefinition) { if (this._isCreatingLayout) { return; } this._coordinates = {}; this._isCreatingLayout = true; var config = { settings: { hasHeaders: false, resizeEnabled: this.editable, reorderEnabled: this.editable, selectionEnabled: this.editable, highlightEnabled: this.editable }, dimensions: { borderWidth: 1, dragProxyWidth: 0, dragProxyHeight: 0 }, content: layoutDefinition }; var oldLayout = this._layout; require(['libs/goldenlayout/goldenlayout'], lang.hitch(this, function(GoldenLayout){ this._layout = new GoldenLayout(config, this.container); this._layout.registerComponent(COMPONENT_NAME, lang.hitch(this, function(container, componentState){ var targetDijit; container.parent.config.id = componentState.id; array.some(this.components, function(item) { if (item.id === componentState.id) { targetDijit = item.dijit; container.getElement().html(item.dijit.domNode); return true; } }, this); container.on('resize', debounce(lang.hitch(this, function() { if (container.width > 0 && container.height > 0 && targetDijit && typeof targetDijit.resize === 'function') { targetDijit.resize(container.width, container.height); } }), 200)); container.on('select', lang.hitch(this, function() { if(this.editable) { container.parent.select(); } this.emit('mask-click', container.parent.config.id); })); })); this._layout.on( 'initialised', lang.hitch(this, function(){ this._resetCoordinate(); this.emit("initialised"); this._isCreatingLayout = false; if (oldLayout) { oldLayout.destroy(); } })); this._layout.on('stateChanged', lang.hitch(this, function(){ this._resetCoordinate(); })); this._layout.init(); if (!this.editable) { domClass.add(this._layout.root.childElementContainer[0], 'viewonly'); } domClass.add(this._layout.root.childElementContainer[0], 'jimu-dijit-gridlayout'); setTimeout(lang.hitch(this, this.resize), 100); })); }, _hideComponent: function(contentItem) { if (contentItem.parent) { // remove component but won't destroy it contentItem.parent.removeChild(contentItem, true); } }, _showComponent: function(componentId) { var component, coordinates, currentNode, config, rootItem, rootContentItem, actualIndex; array.some(this.components, function(item) { if (item.id === componentId) { component = item; return true; } }, this); if (component) { config = { id: componentId, type: 'component', componentName: COMPONENT_NAME, componentState: { id: componentId } }; coordinates = this._coordinates[componentId]; rootItem = this._layout.root; if (coordinates) { // rootItem.type may be stack is there is only one component if (coordinates[0].type !== rootItem.contentItems[0].type) { rootContentItem = rootItem.contentItems[0]; rootItem.replaceChild(rootContentItem, { type: coordinates[0].type, content: [] }); rootItem.contentItems[0].addChild(rootContentItem); } currentNode = rootItem; array.forEach(coordinates, function(pos) { actualIndex = pos.index <= currentNode.contentItems.length ? pos.index : currentNode.contentItems.length; if (pos.type === 'component') { currentNode.addChild(config, actualIndex); } else { //stack, column or row if (pos.type === 'stack' || currentNode.contentItems[pos.index].type !== pos.type) { currentNode.addChild({ type: pos.type, content: [] }, actualIndex); } currentNode = currentNode.contentItems[actualIndex]; } }, this); } else { if (rootItem.contentItems[0].type === 'stack') { rootContentItem = rootItem.contentItems[0]; rootItem.replaceChild(rootContentItem, { type: 'column', content: [] }); rootItem.contentItems[0].addChild(rootContentItem); } rootItem.contentItems[0].addChild(config); } } }, /** * Calculate the coordinate of each component */ _resetCoordinate: function() { var components = this._layout.root.getItemsByType('component'); var next = function(item, coordinates) { var parent = item.parent; if (!parent) { return; } // get the index of the item in the contentItems array of its parent array.some(parent.contentItems, function(sibliingItem, index) { if (sibliingItem === item) { coordinates.push({ type: sibliingItem.type, index: index }); return true; } }); next(parent, coordinates); }; array.forEach(components, function(component) { var coordinates = []; next(component, coordinates); this._coordinates[component.config.id] = coordinates.reverse(); }, this); } }); });