UNPKG

kekule

Version:

Open source JavaScript toolkit for chemoinformatics

274 lines (260 loc) 7.42 kB
/** * @fileoverview * A tree widget to display the internal structure of chem object (such as ChemSpace, Molecule and so on). * @author Partridge Jiang */ /* * requires /lan/classes.js * requires /utils/kekule.utils.js * requires /widgets/kekule.widget.nestedContainers.js * requires /widgets/commonCtrls/kekule.widget.treeViews.js * requires /widgets/chem/kekule.chemWidget.base.js */ (function(){ "use strict"; var CCNS = Kekule.ChemWidget.HtmlClassNames; /** @ignore */ Kekule.ChemWidget.HtmlClassNames = Object.extend(Kekule.ChemWidget.HtmlClassNames, { CHEM_STRUCT_TREE_VIEW: 'K-Chem-Struct-TreeView', CHEM_STRUCT_TREE_VIEW_ITEM_TITLE: 'K-Chem-Struct-TreeView-ItemTitle', CHEM_STRUCT_TREE_VIEW_ITEM_TYPE: 'K-Chem-Struct-TreeView-ItemType' }); /** * An tree view widget to display internal relationship of chem objects. * @class * @augments Kekule.Widget.TreeView * * @param {Variant} parentOrElementOrDocument * @param {Kekule.ChemObject} rootObj * * @property {Kekule.ChemObject} rootObj Root chem object to be displayed in tree view. * @property {Bool} enableLiveUpdate If set to true, the tree view will automatically updated when chem objects changed. */ Kekule.ChemWidget.StructureTreeView = Class.create(Kekule.Widget.TreeView, /** @lends Kekule.ChemWidget.StructureTreeView# */ { /** @private */ CLASS_NAME: 'Kekule.ChemWidget.StructureTreeView', /** @construct */ initialize: function(/*$super, */parentOrElementOrDocument, rootObj) { this.tryApplySuper('initialize', [parentOrElementOrDocument]) /* $super(parentOrElementOrDocument) */; this.setPropStoreFieldValue('objMap', new Kekule.MapEx(true)); this.setEnableLiveUpdate(true); this.setEnableMultiSelect(true); this.setRootObj(rootObj); this._pauseLiveUpdateFlag = 0; this._changedObjects = []; }, /** @private */ initProperties: function() { this.defineProp('rootObj', {'dataType': 'Kekule.ChemObject', 'serializable': false, 'setter': function(value) { var oldObj = this.getPropStoreFieldValue('rootObj'); this.setPropStoreFieldValue('rootObj', value); this.rootObjChanged(value, oldObj); } }); this.defineProp('enableLiveUpdate', {'dataType': DataType.BOOL}); this.defineProp('objMap', {'dataType': 'Kekule.MapEx', 'setter': null, 'serializable': false}); // private property }, /** @ignore */ doGetWidgetClassName: function(/*$super*/) { return this.tryApplySuper('doGetWidgetClassName') /* $super() */ + ' ' + CCNS.CHEM_STRUCT_TREE_VIEW; }, /** @private */ rootObjChanged: function(newValue, oldValue) { this.clearChildItems(); this.getObjMap().clear(); if (oldValue) this._uninstallRootEventHandler(oldValue); if (newValue) { this._fillTree(newValue); this._installRootEventHandler(newValue); } }, /** * Pause the live update process. * Changed objects will be stored and the corresponding tree items will be refreshed * after the live update is resumed. */ pauseLiveUpdate: function() { if (this._pauseLiveUpdateFlag >= 0) { this._pauseLiveUpdateFlag = 0; this._changedObjects = []; } --this._pauseLiveUpdateFlag; return this; }, /** * Resume the live update process. */ resumeLiveUpdate: function() { ++this._pauseLiveUpdateFlag; if (this._pauseLiveUpdateFlag >= 0) // do actual resume { this._pauseLiveUpdateFlag = 0; for (var i = 0, l = this._changedObjects.length; i < l; ++i) { this.refreshObject(this._changedObjects[i]); } } }, isLiveUpdatePaused: function() { return (this._pauseLiveUpdateFlag < 0); }, /** @private */ _installRootEventHandler: function(root) { root.addEventListener('change', this.reactChemObjChange, this); }, /** @private */ _uninstallRootEventHandler: function(root) { root.removeEventListener('change', this.reactChemObjChange, this); }, /** @private */ reactChemObjChange: function(e) { if (this.getEnableLiveUpdate()) { if (this.isLiveUpdatePaused()) { if (this.getObjMap().get(e.target)) Kekule.ArrayUtils.pushUnique(this._changedObjects, e.target); } else { this.refreshObject(e.target); } } }, /** * Refresh tree item on chemObj. * @param {Kekule.ChemObject} chemObj */ refreshObject: function(chemObj) { // get corresponding tree node var treeItem = this.getObjMap().get(chemObj); if (treeItem) { this._updateTreeItem(treeItem, chemObj); } return this; }, /** * Fill tree with rootObj data. * @param {Kekule.ChemObject} rootObj * @private */ _fillTree: function(rootObj) { if (rootObj) { this.clearChildItems(); this._updateTreeItem(this.appendChildItem(), rootObj); } }, /** * Update tree item properties according to chemObj data. * @param {HTMLElement} treeItem * @param {Kekule.ChemObject} chemObj * @private */ _updateTreeItem: function(treeItem, chemObj) { //console.log('update tree', chemObj.getClassName()); var title = this._getChemObjDisplayTitle(chemObj); var data = {'text': title, 'obj': chemObj}; this.setItemData(treeItem, data); this.getObjMap().set(chemObj, treeItem); //this.clearChildItems(treeItem); var oldChildItemCount = this.getChildItemCount(treeItem); var l = chemObj.getChildCount(); for (var i = 0; i < l; ++i) { var child = chemObj.getChildAt(i); /* if (!child.isSelectable()) continue; */ //var childItem = this.appendChildItem(treeItem); var childItem; if (i < oldChildItemCount) childItem = this.getChildItemAt(treeItem, i); else childItem = this.appendChildItem(treeItem); this._updateTreeItem(childItem, child); } // remove extra tree nodes if (oldChildItemCount > l) { for (var i = oldChildItemCount - 1; i >= l; --i) { this.removeChildItemAt(treeItem, i); } } }, /** @private */ _getChemObjDisplayTitle: function(chemObj) { var result = ''; var id = chemObj.getId(); if (id) result += '<span class="' + CCNS.CHEM_STRUCT_TREE_VIEW_ITEM_TITLE + '">' + id + '</span>'; var className = chemObj.getClassName(); // get last part of className var cnameParts = className.split('.'); var cname = cnameParts.length? cnameParts[cnameParts.length - 1]: className; var stype = '<span class="' + CCNS.CHEM_STRUCT_TREE_VIEW_ITEM_TYPE + '">(' + cname + ')</span>'; //return result + '(' + cname + ')'; return result + stype; }, /** * Make tree items corresponding to chemObjs to be selected. * @param {Array} chemObjs */ selectChemObjs: function(chemObjs) { var items = []; for (var i = 0, l = chemObjs.length; i < l; ++i) { var obj = chemObjs[i]; var item = this.getObjMap().get(obj); if (item) items.push(item); } this.select(items); return this; }, /** * Returns corresponding chemObjs linked to selected tree items. * @returns {Array} */ getSelectedChemObjs: function() { var result = []; var items = this.getSelection(); if (items && items.length) { for (var i = 0, l = items.length; i < l; ++i) { var data = this.getItemData(items[i]); if (data && data.obj) result.push(data.obj); } } return result; } }); })();