UNPKG

kekule

Version:

Open source JavaScript toolkit for chemoinformatics

328 lines (313 loc) 9.62 kB
/** * @fileoverview * Implementation of some concrete property markers (e.g. charge mark, lone pair, etc.) binding to the chem object. * @author Partridge Jiang */ /* * requires /lan/classes.js * requires /core/kekule.common.js * requires /core/kekule.structures.js * requires /chemdoc/kekule.attachedMarkers.js * requires /chemdoc/kekule.contentBlocks.js */ (function(){ "use strict"; /** * Base class of chem marker representing chemical concepts (e.g. charge, lone pair...) of parent chem object. * @class * @augments Kekule.ChemObject * @param {String} id Id of this marker. * @param {Hash} coord2D The 2D coordinates of marker, {x, y}, can be null. * @param {Hash} coord3D The 3D coordinates of marker, {x, y, z}, can be null. * * @property {Variant} value Value of the property value of parent chem object. */ Kekule.ChemMarker.BaseMarker = Class.create(Kekule.ChemObject, /** @lends Kekule.ChemMarker.BaseMarker# */ { /** @private */ CLASS_NAME: 'Kekule.ChemMarker.BaseMarker', /** * @constructs */ initialize: function (/*$super, */id, coord2D, coord3D) { this.tryApplySuper('initialize', [id, coord2D, coord3D]) /* $super(id, coord2D, coord3D) */; }, /** @ignore */ getAutoIdPrefix: function() { return 'marker'; }, /** @private */ getAcceptCoordStickFrom: function(fromObj) { return (!this.isSiblingWith(fromObj) && !(fromObj instanceof Kekule.ChemStructureNode) && !(fromObj instanceof Kekule.BaseStructureConnector)); }, }); Kekule.ClassDefineUtils.addStandardCoordSupport(Kekule.ChemMarker.BaseMarker); /** * Represent a lone pair marker in rendering parent chem object. * @class * @augments ChemMarker.BaseMarker */ Kekule.ChemMarker.UnbondedElectronSet = Class.create(Kekule.ChemMarker.BaseMarker, /** @lends Kekule.ChemMarker.UnbondedElectronSet# */ { /** @private */ CLASS_NAME: 'Kekule.ChemMarker.UnbondedElectronSet', /** @private */ initProperties: function() { this.defineProp('electronCount', {'dataType': DataType.VARIANT}); }, /** @ignore */ initPropValues: function(/*$super*/) { this.tryApplySuper('initPropValues') /* $super() */; this.setElectronCount(2); // default is lone pair }, /** @ignore */ getAutoIdPrefix: function() { return 'electron'; } }); /** * Represent a marker represents property (e.g. charge, radical...) of parent chem object. * @class * @augments Kekule.ChemMarker.BaseMarker * @param {String} id Id of this node. * @param {Hash} coord2D The 2D coordinates of marker, {x, y}, can be null. * @param {Hash} coord3D The 3D coordinates of marker, {x, y, z}, can be null. * * @property {Variant} value Value of the property value of parent chem object. */ Kekule.ChemMarker.ChemPropertyMarker = Class.create(Kekule.ChemMarker.BaseMarker, /** @lends Kekule.ChemMarker.ChemPropertyMarker# */ { /** @private */ CLASS_NAME: 'Kekule.ChemMarker.ChemPropertyMarker', /** @private */ initProperties: function() { this.defineProp('value', {'dataType': DataType.VARIANT, 'serializable': false, 'getter': function() { var result; var p = this.getParent(); var propName = this.getPropertyName(); if (p && propName) { result = p.getPropValue(propName); this.setPropStoreFieldValue('value', result); // update cached value when possible } else { result = this.getPropStoreFieldValue('value'); } return result; }, 'setter': function(value) { this.setPropStoreFieldValue('value', value); this.setParentPropValue(value); } }); }, /** @ignore */ initPropValues: function(/*$super*/) { this.tryApplySuper('initPropValues') /* $super() */; /* this.setNeedRecalcSize(true); this.setSize2D({'x': 0, 'y': 0}); */ }, /** @private */ setParentPropValue: function(value) { var p = this.getParent(); if (p) { var propName = this.getPropertyName(); if (propName && p) p.setPropValue(propName, value); } return this; }, /** @private */ resetParentPropValue: function() { return this.setParentPropValue(undefined); }, /* @ignore */ /* doObjectChange: function($super, modifiedPropNames) { // when text block changed, size may need to be recalculated if (Kekule.ArrayUtils.intersect(['text', 'renderOptions'], modifiedPropNames).length) this.setNeedRecalcSize(true); }, */ /** * Returns the mapped property name of parent chem object. * Descendants should override this method. * @returns {Variant} */ getPropertyName: function() { return null; }, // editor related methods /** @ignore */ beforAddingByEditor: function(/*$super, */newParent, refSibling) { if (newParent) // when adding to new parent, update value of parent { var value = this.getPropStoreFieldValue('value'); if (Kekule.ObjUtils.notUnset(value)) this.setParentPropValue(value); // update to parent } this.tryApplySuper('beforAddingByEditor') /* $super() */; }, /** @ignore */ beforeRemovingByEditor: function(parent) { // when removing from editor, usually we should reset the value of property // ensure cached the property value this.setPropStoreFieldValue('value', this.getValue()); this.resetParentPropValue(); } }); /** * Represent a charge marker (+/-) in rendering parent chem object. * @class * @augments Kekule.ChemMarker.ChemPropertyMarker * @param {String} id Id of this node. * @param {Hash} coord2D The 2D coordinates of marker, {x, y}, can be null. * @param {Hash} coord3D The 3D coordinates of marker, {x, y, z}, can be null. */ Kekule.ChemMarker.Charge = Class.create(Kekule.ChemMarker.ChemPropertyMarker, /** @lends Kekule.ChemMarker.Charge# */ { /** @private */ CLASS_NAME: 'Kekule.ChemMarker.Charge', /** @ignore */ getPropertyName: function() { return 'chargeEx'; }, /** @ignore */ getAutoIdPrefix: function() { return 'charge'; }, // for backward compatibility doSetValue: function(value) { // console.log('set marker value', value); if (typeof(value) === 'number') // simple precise charge value { this.tryApplySuper('doSetValue', [{precise: value}]); } else this.tryApplySuper('doSetValue', [value]); } }); /** * Represent a radical marker in rendering parent chem object. * @class * @augments Kekule.ChemMarker.ChemPropertyMarker * @param {String} id Id of this node. * @param {Hash} coord2D The 2D coordinates of marker, {x, y}, can be null. * @param {Hash} coord3D The 3D coordinates of marker, {x, y, z}, can be null. */ Kekule.ChemMarker.Radical = Class.create(Kekule.ChemMarker.ChemPropertyMarker, /** @lends Kekule.ChemMarker.Radical# */ { /** @private */ CLASS_NAME: 'Kekule.ChemMarker.Radical', /** @ignore */ getPropertyName: function() { return 'radical'; }, /** @ignore */ getAutoIdPrefix: function() { return 'radical'; } }); ClassEx.extend(Kekule.ChemStructureNode, /** @lends Kekule.ChemStructureNode# */ { /** * Get charge marker of node. If no such a marker currently and canCreate is true, a new marker will be created. * @returns {Kekule.ChemMarker.ChemPropertyMarker} */ fetchChargeMarker: function(canCreate, defProps) { return this.fetchMarkerOfType(Kekule.ChemMarker.Charge, canCreate, false, defProps); }, /** * Get radical marker of node. If no such a marker currently and canCreate is true, a new marker will be created. * @returns {Kekule.ChemMarker.ChemPropertyMarker} */ fetchRadicalMarker: function(canCreate, defProps) { return this.fetchMarkerOfType(Kekule.ChemMarker.Radical, canCreate, false, defProps); } }); ClassEx.defineProp(Kekule.AbstractAtom, 'lonePairCount', { 'dataType': DataType.INT, 'scope': Class.PropertyScope.PUBLISHED, 'serializable': false, 'setter': null, // currently disable setter 'getter': function() { var result = 0; var unbondedESets = this.getMarkersOfType(Kekule.ChemMarker.UnbondedElectronSet); for (var i = 0, l = unbondedESets.length; i < l; ++i) { var eSet = unbondedESets[i]; if (eSet.getElectronCount() === 2) // a lone pair ++result; } return result; } }); ClassEx.extendMethod(Kekule.AbstractAtom, 'doCompare', function($origin, targetObj, options) { var result = $origin(targetObj, options); if (!result && options.method === Kekule.ComparisonMethod.CHEM_STRUCTURE) // can not find different in origin method { if (this._getComparisonOptionFlagValue(options, 'lonePair') || this._getComparisonOptionFlagValue(options, 'unbondedElectron')) // parity null/0 should be regard as one in comparison { /* var c1 = this.getLonePairCount() || 0; var c2 = (targetObj.getLonePairCount && targetObj.getLonePairCount()) || 0; result = this.doCompareOnValue(c1, c2, options); */ var _getUnbondedElectronArray = function(atom) { var result = []; if (atom.getMarkersOfType) { var unbondedESets = atom.getMarkersOfType(Kekule.ChemMarker.UnbondedElectronSet); for (var i = 0, l = unbondedESets.length; i < l; ++i) { var eSet = unbondedESets[i]; result.push(eSet.getElectronCount()) } } result.sort(); return result; }; var a1 = _getUnbondedElectronArray(this); var a2 = _getUnbondedElectronArray(targetObj); return Kekule.ArrayUtils.compare(a1, a2); } } return result; }); })();