From be0af7be686838c53b4ddeef30711aae57b71ca4 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 14 Jun 2021 11:47:02 +0200 Subject: [PATCH] split implements and instanceOf from ClassWithAttributes in own ClassWithInterfaces and let et2_dataview_view_container inherit from it --- api/js/etemplate/et2_core_inheritance.js | 60 +-- api/js/etemplate/et2_core_inheritance.ts | 408 ++++++++---------- .../etemplate/et2_dataview_view_container.js | 4 +- .../etemplate/et2_dataview_view_container.ts | 5 +- 4 files changed, 228 insertions(+), 249 deletions(-) diff --git a/api/js/etemplate/et2_core_inheritance.js b/api/js/etemplate/et2_core_inheritance.js index 91d8fd6f3a..a2df86f54a 100644 --- a/api/js/etemplate/et2_core_inheritance.js +++ b/api/js/etemplate/et2_core_inheritance.js @@ -13,7 +13,37 @@ import { egw } from "../jsapi/egw_global"; import { et2_checkType, et2_no_init, et2_validateAttrib } from "./et2_core_common"; import { et2_implements_registry } from "./et2_core_interfaces"; -export class ClassWithAttributes { +export class ClassWithInterfaces { + /** + * The implements function can be used to check whether the object + * implements the given interface. + * + * As TypeScript can not (yet) check if an objects implements an interface on runtime, + * we currently implements with each interface a function called 'implements_'+interfacename + * to be able to check here. + * + * @param _iface name of interface to check + */ + implements(_iface_name) { + if (typeof et2_implements_registry[_iface_name] === 'function' && + et2_implements_registry[_iface_name](this)) { + return true; + } + return false; + } + /** + * Check if object is an instance of a class or implements an interface (specified by the interfaces name) + * + * @param _class_or_interfacename class(-name) or string with name of interface + */ + instanceOf(_class_or_interfacename) { + if (typeof _class_or_interfacename === 'string') { + return this.implements(_class_or_interfacename); + } + return this instanceof _class_or_interfacename; + } +} +export class ClassWithAttributes extends ClassWithInterfaces { /** * Returns the value of the given attribute. If the property does not * exist, an error message is issued. @@ -169,33 +199,5 @@ export class ClassWithAttributes { } return attributes; } - /** - * The implements function can be used to check whether the object - * implements the given interface. - * - * As TypeScript can not (yet) check if an objects implements an interface on runtime, - * we currently implements with each interface a function called 'implements_'+interfacename - * to be able to check here. - * - * @param _iface name of interface to check - */ - implements(_iface_name) { - if (typeof et2_implements_registry[_iface_name] === 'function' && - et2_implements_registry[_iface_name](this)) { - return true; - } - return false; - } - /** - * Check if object is an instance of a class or implements an interface (specified by the interfaces name) - * - * @param _class_or_interfacename class(-name) or string with name of interface - */ - instanceOf(_class_or_interfacename) { - if (typeof _class_or_interfacename === 'string') { - return this.implements(_class_or_interfacename); - } - return this instanceof _class_or_interfacename; - } } //# sourceMappingURL=et2_core_inheritance.js.map \ No newline at end of file diff --git a/api/js/etemplate/et2_core_inheritance.ts b/api/js/etemplate/et2_core_inheritance.ts index 2f3c1f674f..03e713ec06 100644 --- a/api/js/etemplate/et2_core_inheritance.ts +++ b/api/js/etemplate/et2_core_inheritance.ts @@ -16,224 +16,8 @@ import {egw} from "../jsapi/egw_global"; import {et2_checkType, et2_no_init, et2_validateAttrib} from "./et2_core_common"; import {et2_implements_registry} from "./et2_core_interfaces"; -export class ClassWithAttributes +export class ClassWithInterfaces { - /** - * Object to collect the attributes we operate on - */ - attributes: object; - - /** - * Returns the value of the given attribute. If the property does not - * exist, an error message is issued. - * - * @param {string} _name - * @return {*} - */ - getAttribute(_name) { - if (typeof this.attributes[_name] != "undefined" && - !this.attributes[_name].ignore) - { - if (typeof this["get_" + _name] == "function") - { - return this["get_" + _name](); - } - else - { - return this[_name]; - } - } - else - { - egw.debug("error", this, "Attribute '" + _name + "' does not exist!"); - } - } - - /** - * The setAttribute function sets the attribute with the given name to - * the given value. _override defines, whether this[_name] will be set, - * if this key already exists. _override defaults to true. A warning - * is issued if the attribute does not exist. - * - * @param {string} _name - * @param {*} _value - * @param {boolean} _override - */ - setAttribute(_name, _value, _override) - { - if (typeof this.attributes[_name] != "undefined") - { - if (!this.attributes[_name].ignore) - { - if (typeof _override == "undefined") - { - _override = true; - } - - var val = et2_checkType(_value, this.attributes[_name].type, - _name, this); - - if (typeof this["set_" + _name] == "function") - { - this["set_" + _name](val); - } - else if (_override || typeof this[_name] == "undefined") - { - this[_name] = val; - } - } - } - else - { - egw.debug("warn", this, "Attribute '" + _name + "' does not exist!"); - } - } - - /** - * generateAttributeSet sanitizes the given associative array of attributes - * (by passing each entry to "et2_checkType" and checking for existance of - * the attribute) and adds the default values to the associative array. - * - * @param {object} _attrs is the associative array containing the attributes. - */ - static generateAttributeSet(widget, _attrs) - { - // Sanity check and validation - for (var key in _attrs) - { - if (typeof widget[key] != "undefined") - { - if (!widget[key].ignore) - { - _attrs[key] = et2_checkType(_attrs[key], widget[key].type, - key, this); - } - } - else - { - // Key does not exist - delete it and issue a warning - delete(_attrs[key]); - egw.debug("warn", this, "Attribute '" + key + - "' does not exist in " + _attrs.type+"!"); - } - } - - // Include default values or already set values for this attribute - for (var key in widget) - { - if (typeof _attrs[key] == "undefined") - { - var _default = widget[key]["default"]; - if (_default == et2_no_init) - { - _default = undefined; - } - - _attrs[key] = _default; - } - } - - return _attrs; - } - - /** - * The initAttributes function sets the attributes to their default - * values. The attributes are not overwritten, which means, that the - * default is only set, if either a setter exists or this[propName] does - * not exist yet. - * - * @param {object} _attrs is the associative array containing the attributes. - */ - initAttributes(_attrs) - { - for (var key in _attrs) - { - if (typeof this.attributes[key] != "undefined" && !this.attributes[key].ignore && !(_attrs[key] == undefined)) - { - this.setAttribute(key, _attrs[key], false); - } - } - } - - static buildAttributes(class_prototype: object) - { - let class_tree = []; - let attributes = {}; - let n = 0; - do - { - n++; - class_tree.push(class_prototype); - class_prototype = Object.getPrototypeOf(class_prototype); - } while (class_prototype !== ClassWithAttributes && n < 50); - - for(let i = class_tree.length - 1; i >= 0; i--) - { - attributes = ClassWithAttributes.extendAttributes(attributes, class_tree[i]._attributes); - } - return attributes; - } - /** - * Extend current _attributes with the one from the parent class - * - * This gives inheritance from the parent plus the ability to override in the current class. - * - * @param _attributes - * @param _parent - */ - static extendAttributes(_parent : object, _attributes : object) : object - { - function _copyMerge(_new, _old) - { - var result = {}; - - // Copy the new object - if (typeof _new != "undefined") - { - for (var key in _new) - { - result[key] = _new[key]; - } - } - - // Merge the old object - for (var key in _old) - { - if (typeof result[key] == "undefined") - { - result[key] = _old[key]; - } - } - - return result; - } - - var attributes = {}; - - // Copy the old attributes - for (var key in _attributes) - { - attributes[key] = _copyMerge({}, _attributes[key]); - } - - // Add the old attributes to the new ones. If the attributes already - // exist, they are merged. - for (var key in _parent) - { - var _old = _parent[key]; - - attributes[key] = _copyMerge(attributes[key], _old); - } - - // Validate the attributes - for (var key in attributes) - { - et2_validateAttrib(key, attributes[key]); - } - - return attributes; - } - /** * The implements function can be used to check whether the object * implements the given interface. @@ -267,4 +51,192 @@ export class ClassWithAttributes } return this instanceof _class_or_interfacename; } -} \ No newline at end of file +} + +export class ClassWithAttributes extends ClassWithInterfaces +{ + /** + * Object to collect the attributes we operate on + */ + attributes: object; + + /** + * Returns the value of the given attribute. If the property does not + * exist, an error message is issued. + * + * @param {string} _name + * @return {*} + */ + getAttribute(_name) + { + if (typeof this.attributes[_name] != "undefined" && + !this.attributes[_name].ignore) { + if (typeof this["get_" + _name] == "function") { + return this["get_" + _name](); + } else { + return this[_name]; + } + } else { + egw.debug("error", this, "Attribute '" + _name + "' does not exist!"); + } + } + + /** + * The setAttribute function sets the attribute with the given name to + * the given value. _override defines, whether this[_name] will be set, + * if this key already exists. _override defaults to true. A warning + * is issued if the attribute does not exist. + * + * @param {string} _name + * @param {*} _value + * @param {boolean} _override + */ + setAttribute(_name, _value, _override) + { + if (typeof this.attributes[_name] != "undefined") { + if (!this.attributes[_name].ignore) { + if (typeof _override == "undefined") { + _override = true; + } + + var val = et2_checkType(_value, this.attributes[_name].type, + _name, this); + + if (typeof this["set_" + _name] == "function") { + this["set_" + _name](val); + } else if (_override || typeof this[_name] == "undefined") { + this[_name] = val; + } + } + } else { + egw.debug("warn", this, "Attribute '" + _name + "' does not exist!"); + } + } + + /** + * generateAttributeSet sanitizes the given associative array of attributes + * (by passing each entry to "et2_checkType" and checking for existance of + * the attribute) and adds the default values to the associative array. + * + * @param {object} _attrs is the associative array containing the attributes. + */ + static generateAttributeSet(widget, _attrs) + { + // Sanity check and validation + for (var key in _attrs) { + if (typeof widget[key] != "undefined") { + if (!widget[key].ignore) { + _attrs[key] = et2_checkType(_attrs[key], widget[key].type, + key, this); + } + } else { + // Key does not exist - delete it and issue a warning + delete (_attrs[key]); + egw.debug("warn", this, "Attribute '" + key + + "' does not exist in " + _attrs.type + "!"); + } + } + + // Include default values or already set values for this attribute + for (var key in widget) { + if (typeof _attrs[key] == "undefined") { + var _default = widget[key]["default"]; + if (_default == et2_no_init) { + _default = undefined; + } + + _attrs[key] = _default; + } + } + + return _attrs; + } + + /** + * The initAttributes function sets the attributes to their default + * values. The attributes are not overwritten, which means, that the + * default is only set, if either a setter exists or this[propName] does + * not exist yet. + * + * @param {object} _attrs is the associative array containing the attributes. + */ + initAttributes(_attrs) + { + for (var key in _attrs) { + if (typeof this.attributes[key] != "undefined" && !this.attributes[key].ignore && !(_attrs[key] == undefined)) { + this.setAttribute(key, _attrs[key], false); + } + } + } + + static buildAttributes(class_prototype: object) + { + let class_tree = []; + let attributes = {}; + let n = 0; + do { + n++; + class_tree.push(class_prototype); + class_prototype = Object.getPrototypeOf(class_prototype); + } while (class_prototype !== ClassWithAttributes && n < 50); + + for (let i = class_tree.length - 1; i >= 0; i--) { + attributes = ClassWithAttributes.extendAttributes(attributes, class_tree[i]._attributes); + } + return attributes; + } + + /** + * Extend current _attributes with the one from the parent class + * + * This gives inheritance from the parent plus the ability to override in the current class. + * + * @param _attributes + * @param _parent + */ + static extendAttributes(_parent: object, _attributes: object): object + { + function _copyMerge(_new, _old) + { + var result = {}; + + // Copy the new object + if (typeof _new != "undefined") { + for (var key in _new) { + result[key] = _new[key]; + } + } + + // Merge the old object + for (var key in _old) { + if (typeof result[key] == "undefined") { + result[key] = _old[key]; + } + } + + return result; + } + + var attributes = {}; + + // Copy the old attributes + for (var key in _attributes) { + attributes[key] = _copyMerge({}, _attributes[key]); + } + + // Add the old attributes to the new ones. If the attributes already + // exist, they are merged. + for (var key in _parent) { + var _old = _parent[key]; + + attributes[key] = _copyMerge(attributes[key], _old); + } + + // Validate the attributes + for (var key in attributes) { + et2_validateAttrib(key, attributes[key]); + } + + return attributes; + } +} diff --git a/api/js/etemplate/et2_dataview_view_container.js b/api/js/etemplate/et2_dataview_view_container.js index d83b958bd7..e58bf87c57 100644 --- a/api/js/etemplate/et2_dataview_view_container.js +++ b/api/js/etemplate/et2_dataview_view_container.js @@ -10,6 +10,7 @@ * @version $Id$ */ import { et2_bounds } from "./et2_core_common"; +import { ClassWithInterfaces } from "./et2_core_inheritance"; /** * The et2_dataview_container class is the main object each dataview consits of. * Each row, spacer as well as the grid itself are containers. A container is @@ -26,7 +27,7 @@ import { et2_bounds } from "./et2_core_common"; * * @augments Class */ -export class et2_dataview_container { +export class et2_dataview_container extends ClassWithInterfaces { /** * Initializes the container object. * @@ -35,6 +36,7 @@ export class et2_dataview_container { * @memberOf et2_dataview_container */ constructor(_parent) { + super(); // Copy the given invalidation element this._parent = _parent; this._nodes = []; diff --git a/api/js/etemplate/et2_dataview_view_container.ts b/api/js/etemplate/et2_dataview_view_container.ts index 5013d333c1..89bd66ae81 100644 --- a/api/js/etemplate/et2_dataview_view_container.ts +++ b/api/js/etemplate/et2_dataview_view_container.ts @@ -17,6 +17,7 @@ import {et2_dataview_IInvalidatable} from "./et2_dataview_interfaces"; import {et2_bounds} from "./et2_core_common"; +import {ClassWithInterfaces} from "./et2_core_inheritance"; /** * The et2_dataview_container class is the main object each dataview consits of. @@ -34,7 +35,7 @@ import {et2_bounds} from "./et2_core_common"; * * @augments Class */ -export class et2_dataview_container implements et2_dataview_IInvalidatable +export class et2_dataview_container extends ClassWithInterfaces implements et2_dataview_IInvalidatable { protected _parent: any; @@ -61,6 +62,8 @@ export class et2_dataview_container implements et2_dataview_IInvalidatable */ constructor(_parent) { + super(); + // Copy the given invalidation element this._parent = _parent;