UNPKG

kekule

Version:

Open source JavaScript toolkit for chemoinformatics

470 lines (445 loc) 13.3 kB
/** * Created by ginger on 2015/1/28. */ /* * requires /lan/classes.js * requires /utils/kekule.utils.js * requires /utils/kekule.domUtils.js * requires /xbrowsers/kekule.x.js * requires /widgets/kekule.widget.base.js * requires /widgets/operation/kekule.actions.js * requires /widgets/commonCtrls/kekule.widget.container.js * requires /widgets/commonCtrls/kekule.widget.tabViews.js * requires /widgets/advCtrls/objInspector/kekule.widget.objInspector.js */ (function(){ "use strict"; /** @ignore */ Kekule.Widget.HtmlClassNames = Object.extend(Kekule.Widget.HtmlClassNames, { WIDGET_CONFIGURATOR: 'K-Widget-Configurator', WIDGET_CONFIGURATOR_CLIENT: 'K-Widget-Configurator-Client', ACTION_OPEN_CONFIGURATOR: 'K-Action-Open-Configurator' }); var CNS = Kekule.Widget.HtmlClassNames; /** * A special widget class to open a config widget for ChemObjDisplayer. * Do not use this widget alone. * @class * @augments Kekule.Widget.Panel * * @param {Kekule.Widget.BaseWidget} widget * @property {Bool} autoUpdate Whether load and save config values automatically when configurator is shown or hide. */ /** * Invoked when the config has been changed. Event param of it has fields: {object, propertyName, oldValue, newValue}. * @name Kekule.Widget.Configurator#configChange * @event */ Kekule.Widget.Configurator = Class.create(Kekule.Widget.Panel, /** @lends Kekule.Widget.Configurator# */ { /** @private */ CLASS_NAME: 'Kekule.Widget.Configurator', /** @private */ TAB_BTN_DATA_FIELD: '__$data__', /** @private */ DEF_TAB_POSITION: Kekule.Widget.Position.RIGHT, /** @construct */ initialize: function(/*$super, */widget) { this.setPropStoreFieldValue('widget', widget); this._objInspector = null; this._tabGroup = null; this.tryApplySuper('initialize', [widget]) /* $super(widget) */; }, /** @private */ initProperties: function() { this.defineProp('widget', {'dataType': 'Kekule.Widget.BaseWidget', 'serializable': false}); this.defineProp('autoUpdate', {'dataType': DataType.BOOL}); // TODO: tabPosition now is not totally workable this.defineProp('tabPosition', {'dataType': DataType.INT, 'setter': function(value) { this.setPropStoreFieldValue('tabPosition', value); if (this._tabGroup) this._tabGroup.setTabButtonPosition(value || this.DEF_TAB_POSITION); } }); }, /** @ignore */ initPropValues: function(/*$super*/) { this.tryApplySuper('initPropValues') /* $super() */; this.setLayout(Kekule.Widget.Layout.HORIZONTAL); }, /** @ignore */ doGetWidgetClassName: function(/*$super*/) { return this.tryApplySuper('doGetWidgetClassName') /* $super() */ + ' ' + CNS.WIDGET_CONFIGURATOR; }, /** @ignore */ doCreateRootElement: function(doc) { var result = doc.createElement('div'); return result; }, /** @ignore */ doCreateSubElements: function(/*$super, */doc, element) { var result = []; var rootElem = doc.createElement('div'); rootElem.className = CNS.WIDGET_CONFIGURATOR_CLIENT; result.push(rootElem); // obj inspector var objInspector = new Kekule.Widget.ObjectInspector(this); objInspector.setShowObjsInfoPanel(false); objInspector.setSortField(null); objInspector.appendToElem(rootElem); this._objInspector = objInspector; objInspector.addEventListener('propertyChange', function(e){ this.invokeEvent('configChange', { 'obj': objInspector.getObjects()[0], 'propertyName': e.propertyInfo.name, 'oldValue': e.oldValue, 'newValue': e.newValue }); //console.log(objInspector.getObjects()[0]); }, this); // tab head var categories = this.getCategoryInfos(); var tabBtnGroup = new Kekule.Widget.TabButtonGroup(this); this._tabGroup = tabBtnGroup; //console.log('tab position', this.getTabPosition()); tabBtnGroup.setTabButtonPosition(this.getTabPosition() || this.DEF_TAB_POSITION/*Kekule.Widget.Position.RIGHT*/); var firstBtn; for (var i = 0, l = categories.length; i < l; ++i) { var c = categories[i]; var btn = new Kekule.Widget.RadioButton(tabBtnGroup); btn.setText(c.title || c.name); btn.setHint(c.description || ''); btn[this.TAB_BTN_DATA_FIELD] = c.obj; btn.appendToWidget(tabBtnGroup); if (i === 0) { firstBtn = btn; } } tabBtnGroup.addEventListener('execute', function(e){ var btn = e.widget; if (btn instanceof Kekule.Widget.RadioButton) this._switchToTab(btn); }, this); tabBtnGroup.appendToElem(rootElem); if (categories.length <= 1) tabBtnGroup.setDisplayed('none'); // switch firstBtn.setChecked(true); this._switchToTab(firstBtn); element.appendChild(rootElem); return result; }, /** @ignore */ doWidgetShowStateChanged: function(/*$super, */isShown) { this.tryApplySuper('doWidgetShowStateChanged', [isShown]) /* $super(isShown) */; if (this.getAutoUpdate()) { if (isShown) this.loadConfigValues(); else this.saveConfigValues(); } }, /** * Load config setting values from widget. * Descendants may override this method. */ loadConfigValues: function() { // do nothing here }, /** * Save config setting values back to widget. * Descendants may override this method. */ saveConfigValues: function() { // do nothing here }, /** * Get settings category, descendants need to override this method. * @returns {Array} */ getCategoryInfos: function() { var widget = this.getWidget(); var result = []; // configFacade var facade = widget.getSettingFacade(); if (facade) { var propInfo = widget.getPropInfo('settingFacade'); result.push({ 'obj': facade, 'name': propInfo.name, 'title': propInfo.title, 'descrption': propInfo.description }); } /* // renderConfigs and displayerConfigs var configObjs = [displayer.getDisplayerConfigs(), displayer.getRenderConfigs()]; for (var j = 0, k = configObjs.length; j < k; ++j) { var config = configObjs[j]; var props = config.getPropListOfScopes([Class.PropertyScope.PUBLISHED]); for (var i = 0, l = props.getLength(); i < l; ++i) { var propInfo = props.getPropInfoAt(i); var obj = config.getPropValue(propInfo.name); if (obj) { result.push({ 'obj': obj, 'name': propInfo.name, 'title': propInfo.title, 'description': propInfo.description }); } } } */ return result; }, /** @private */ _switchToTab: function(tabBtn) { var obj = tabBtn[this.TAB_BTN_DATA_FIELD]; this._objInspector.setObjects(obj); } }); /** * Action for open a widget to change widget configs. * @class * @augments Kekule.ActionDisplayerOpenConfigWidget */ Kekule.Widget.ActionOpenConfigWidget = Class.create(Kekule.Action, /** @lends Kekule.Widget.ActionOpenConfigWidget# */ { /** @private */ CLASS_NAME: 'Kekule.Widget.ActionOpenConfigWidget', /** @private */ HTML_CLASSNAME: CNS.ACTION_OPEN_CONFIGURATOR, /** @constructs */ initialize: function(/*$super, */widget) { this.tryApplySuper('initialize') /* $super() */; this.setWidget(widget); this.setText(/*Kekule.WidgetTexts.CAPTION_CONFIG*/Kekule.$L('WidgetTexts.CAPTION_CONFIG')); this.setHint(/*Kekule.WidgetTexts.HINT_CONFIG*/Kekule.$L('WidgetTexts.HINT_CONFIG')); }, /** @private */ initProperties: function() { this.defineProp('widget', {'dataType': 'Kekule.Widget.BaseWidget', 'serializable': false}); }, /** @private */ doUpdate: function() { var w = this.getWidget(); this.setEnabled(w && w.getEnabled()); }, /** @private */ doExecute: function(target) { this.getWidget().openConfigurator(target); } }); ClassEx.extend(Kekule.Widget.BaseWidget, /** @lends Kekule.Widget.BaseWidget# */ { /** @private */ getSettingFacadeClass: function() { var c = this.getClass(); var result = null; do { var className = ClassEx.getClassName(c) + '.Settings'; result = ClassEx.findClass(className); c = ClassEx.getSuperClass(c); } while (c && !result) return result; }, /** * Returns configurator class of displayer. Descendants may override this method. * @returns {Class} * @private */ getConfiguratorClass: function() { var c = this.getClass(); var result = null; do { var className = ClassEx.getClassName(c) + '.Configurator'; result = ClassEx.findClass(className); c = ClassEx.getSuperClass(c); } while (c && !result) return result; }, /** * Create a new configurator. * @private */ createConfigurator: function() { var cclass = this.getConfiguratorClass(); return new cclass(this); }, /** * Returns widget instance of configurator. * @returns {Kekule.Widget.BaseWidget} */ getConfigurator: function() { if (!this._configurator) { this._configurator = this.createConfigurator(); } return this._configurator; }, /** * Open a popup configurator to modify settings of displayer. * @param {Kekule.Widget.BaseWidget} callerWidget Who invokes the action. */ openConfigurator: function(callerWidget) { var c = this.getConfigurator(); //c.appendToWidget(this); c.show(callerWidget || this, null, Kekule.Widget.ShowHideType.DROPDOWN); } }); ClassEx.defineProp(Kekule.Widget.BaseWidget, 'settingFacade', {'dataType': DataType.OBJECTEX, 'serializable': false, 'scope': Class.PropertyScope.PUBLIC, 'setter': null, 'getter': function() { var result = this.getPropStoreFieldValue('settingFacade'); if (!result) { var c = this.getSettingFacadeClass(); if (c) { result = new c(this); this.setPropStoreFieldValue('settingFacade', result); } } return result; } }); /** * A special class to give a setting facade for BaseWidget. * Should use the following naming pattern: BaseClass.Settings (e.g. Kekule.ChemObject.Settings). * Do not use this class alone. * @class * @augments ObjectEx * * @param {Kekule.Widget.BaseWidget} widget * @ignore */ Kekule.Widget.BaseWidget.Settings = Class.create(ObjectEx, /** @lends Kekule.Widget.BaseWidget.Settings# */ { /** @private */ CLASS_NAME: 'Kekule.Widget.BaseWidget.Settings', /** @construct */ initialize: function(/*$super, */widget) { this._basedClass = null; this.tryApplySuper('initialize') /* $super() */; this.setWidget(widget); }, /** @private */ initProperties: function() { this.defineProp('widget', {'dataType': 'Kekule.Widget.BaseWidget', 'serializable': false, 'scope': Class.PropertyScope.PUBLIC}); //this.defineProp('widgetClass', {'dataType': DataType.CLASS, 'serializable': false, 'setter': null, 'scope': Class.PropertyScope.PUBLIC}); }, /** @private */ getBasedClass: function() { if (!this.hasOwnProperty('_basedClass') || !this._basedClass) // important, must check own property to avoid conflict by parent classes { var className = this.getClassName(); var cascadeNames = className.split('.'); cascadeNames.pop(); // remove '.Settings' className = cascadeNames.join('.'); this._basedClass = ClassEx.findClass(className); } return this._basedClass; }, /** * Define property that directly mapped to widget's property. * @param {String} propName * @param {String} widgetPropName Name of corresponding property in widget. * @return {Object} Property info object added to property list. * @private */ defineDelegatedProp: function(propName, widgetPropName) { if (!widgetPropName) widgetPropName = propName; var widgetPropInfo = ClassEx.getPropInfo(this.getBasedClass(), widgetPropName); /* var propOptions = { 'serializable': widgetPropInfo.serializable, 'dataType': widgetPropInfo.dataType, 'title': widgetPropInfo.title, 'description': widgetPropInfo.description, 'getter': null, 'setter': null }; */ var propOptions = Object.create(widgetPropInfo); // clear getter and setter propOptions.setter = null; propOptions.getter = null; if (widgetPropInfo.getter) { propOptions.getter = function() { //console.log('get delegate value', widgetPropName, this.getWidget().getPropValue(widgetPropName)); return this.getWidget().getPropValue(widgetPropName); }; } if (widgetPropInfo.setter) { propOptions.setter = function(value) { this.getWidget().setPropValue(widgetPropName, value); } } //console.log('define delegate prop', propOptions); this.defineProp(propName, propOptions); }, /** * Define a series of property that directly mapped to widget's property. * @param {Array} propNames * @param {Array} widgetPropNames Names of corresponding property in widget. * @private */ defineDelegatedProps: function(propNames, widgetPropNames) { if (!widgetPropNames) widgetPropNames = []; for (var i = 0, l = propNames.length; i < l; ++i) { var propName = propNames[i]; var widgetPropName = widgetPropNames[i] || propName; this.defineDelegatedProp(propName, widgetPropName); } } }); })();