/* * GxUI Library 2.0.1 * Copyright (c) 2009, Artech * All rights reserved. * * GxUI Library is freely distributable under the terms of the BSD license. * */ /// <reference path="..\Freezer\Ext\ext-all-dev.js" /> /** * @class gxui.UserControl * Abstract base class for gxui UserControls. * @ignore */ Ext.define('gxui.UserControl', { mixins: { observable: 'Ext.util.Observable' }, /** * Indicates if this control should be ignored in the layout process made by GxUI * @private * @ignore */ unmanagedLayout: false, /** * Creates a new GxUI UserControl * @param {Object} [options] User control configuration options * @param {Boolean} [options.register] Indicates wether the newly created UserControl should be registered in gxui.UserControlManager. * @method constructor * @ignore */ constructor: function (options) { this.setOptions(options) this.initialize(); return this; }, //private setOptions: function (options) { this.options = { register: true }; for (property in (options || {})) { this.options[property] = options[property]; } }, //private initialize: function () { this.rendered = false; this.mixins.observable.constructor.call(this); this.addEvents({ /** * @event show * Fires after the User Control has been shown. * @param {gxui.UserControl} this * @ignore */ "show": true, /** * @event destroy * Fires after the User Control is destroyed. * @param {gxui.UserControl} this * @ignore */ "destroy": true }); if (this.options.register) this.register(); if (this.methods) this.addDeferredMethods(this.methods); }, /** * Shows the user control and fires the 'show' event after showing it. * @ignore */ show: function () { if (!this.rendered) { Ext.onReady(function () { try { this.renderControl(); } catch (e) { gx.dbg.logEx(e, 'gxui.js', 'show'); } finally { this.fireEvent("show", this); } }, this); } else { try { if (this.onRefresh) this.onRefresh(); } catch (e) { gx.dbg.logEx(e, 'gxui.js', 'show'); } finally { this.fireEvent("show", this); } } }, renderControl: function () { this.onRender(); this.rendered = true; this.addToContainer(); if (this.onAfterRender) { var control = this.getUnderlyingControl(); if (control) { if (control.rendered) this.onAfterRender.call(this, control); else control.on('afterrender', this.onAfterRender, this, [control]); } } }, /** * Force the user control rendering. * @ignore */ forceRendering: function () { this.rendered = false; }, /** * Destroys the user control and fires the 'destroy' event after destroying it. Each User Control must implement * in the onDestroy method the destruction of the User Control. * @ignore */ destroy: function () { try { this.onDestroy(); } catch (e) { gx.dbg.logEx(e, 'gxui.js', 'destroy'); } this.fireEvent("destroy", this); }, /** * Called by show method to render the User Control. This method has no default implementation * so it must be provided by inheriting classes. * @ignore */ onRender: Ext.emptyFn, /** * Called by show method instead of the onRender method, from the second time onwards, to refresh the User Control. * This method has no default implementation so it must be provided by inheriting classes. * @ignore */ onRefresh: Ext.emptyFn, /** * Called by destroy method to destroy the User Control. This method has a default implementation and can be * overriden. The default implementation relays on a correct implementation of getUnderlyingControl method. * @ignore */ onDestroy: function () { var c = this.getUnderlyingControl(); if (c) { var ct = c.ownerCt; if (ct) { if (ct.remove) { ct.remove(c); } } else { if (c.destroy) { c.destroy(); } } } }, /** * Returns the underlying control associated to the UserControl. If the UserControl has no underlying control, return false (defualt behavior) * @ignore */ getUnderlyingControl: function () { return false }, /** * Returns true if the control should be added to its parent GxUI control. This method default implementation * always returns false, so an implementation should be provided by inheriting classes that can be added to a container. * @ignore */ addToParent: function () { return false; }, /** * Registers the User Control * @ignore * @private */ register: function () { gxui.UserControlManager.register(this); }, /** * Registers the User Control * @ignore * @private */ unregister: function () { gxui.UserControlManager.unregister(this); }, /** * Registers the User Control as a container. * @ignore * @private */ registerCt: function (el, addFn, doLayoutFn, scope) { gxui.UserControlManager.registerContainer(this, el, addFn, doLayoutFn, scope); }, /** * Unregister the user Control to its parent container. * @ignore * @private */ unregisterCt: function (toRem) { gxui.UserControlManager.unregisterContainer(toRem); }, /** * Adds the User Control to its parent container. * @ignore * @private */ addToContainer: function () { var control = this.getUnderlyingControl(); if (control) { if (this.addToParent()) { gxui.UserControlManager.addToParentContainer(this, control); } else { if (!this.unmanagedLayout && !control.rendered) { control.render(this.getContainerControl()); } } } }, checkIfInline: function (el) { if (el.id.indexOf("gxHTMLWrp") >= 0 || el.hasCls("gx_usercontrol") || el.hasCls("gxui-uc-container")) el.setStyle("display", "inline"); if (this.getContainerControl() == el.dom && gxui.CBoolean(this.AutoWidth) && this.getUnderlyingControl() && !this.getUnderlyingControl().ownerCt) el.setStyle("display", "inline-block"); }, /** * @ignore * @private */ getUniqueId: function () { var pO = this.ParentObject; return "gxui20" + (pO ? (pO.CmpContext ? "-" + pO.CmpContext : "") + "-" + pO.ServerClass.replace(/\./g, "-") || "" : "") + "-" + this.ControlName + (this.GridRow || ""); }, addDeferredMethods: function (methods) { for (var m in methods) { if (typeof (methods[m]) == 'function') { this[m] = Ext.bind(function () { var fn = arguments[arguments.length - 1], args = Array.prototype.slice.call(arguments, 0, arguments.length - 1); if (this.runDeferredMethod(m)) return fn.apply(this, args); else gxui.afterShow(Ext.bind(fn, this, args), this, { single: true }); }, this, [methods[m]], true); } } }, runDeferredMethod: function (methodName) { var control = this.getUnderlyingControl(); return control === false || (control && control.rendered); } }); /** * @class gxui.UserControlManager * Class for managing gxui UserControls. * @singleton * @ignore */ gxui.UserControlManager = function () { var mgr; var ucList = []; var ctList = []; var afterShowEvent; var initAfterShow = function () { afterShowEvent = new Ext.util.Event(); }; var allShownHandler = function () { afterShowEvent.fire(); this.addControlsToContainer(); for (var i = 0, len = ucList.length; i < len; i++) { var item = ucList[i], extUC = item.getUnderlyingControl(); if (extUC) { if (!item.unmanagedLayout && !extUC.rendered) extUC.render(item.getContainerControl()); else { // Fire doLayout function in those controls that don't have a parent control. if (extUC && !extUC.ownerCt && extUC.doLayout) { extUC.doLayout(); } if (item.fixAutoDimensions) { item.fixAutoDimensions(extUC); } } } item.shown = false; } }; var ucShowListener = function (uc) { try { var ucListItem = this.isRegisteredUC(uc) if (ucListItem) { ucListItem.shown = true; } var allShown = true; for (var i = 0, len = ucList.length; i < len; i++) { allShown = ucList[i].shown && allShown; if (!allShown) break; } if (allShown && afterShowEvent) { allShownHandler.call(this); } } catch (e) { gx.dbg.logEx(e, 'gxui.js', 'ucShowListener'); } }; gx.fx.obs.addObserver('gx.onobjectpostback', mgr, function () { for (var i = 0, len = ucList.length; i < len; i++) { if (ucList[i].shown === true) { allShownHandler.call(mgr); return; } } }); mgr = { childControls: {}, getUCList: function () { var l = []; for (var i = 0, len = ucList.length; i < len; i++) { l.push(ucList[i]); } return l; }, getContainersList: function () { return ctList; }, register: function (uc) { ucList.push(uc); uc.shown = false; uc.on("show", ucShowListener, this); uc.on("destroy", function (uc) { this.unregister(uc); this.unregisterContainer(uc); if (uc.afterShowHandler) afterShowEvent.removeListener(uc.afterShowHandler, uc); }, this); }, unregister: function (uc) { var toRem = this.isRegisteredUC(uc); if (toRem) { for (var i = ucList.length - 1; i >= 0; i--) { if (toRem == ucList[i]) { ucList.splice(i, 1); break; } } } }, registerContainer: function (uc, el, addFn, doLayoutFn, scope) { ctList.push({ uc: uc, el: el, addFn: addFn, doLayoutFn: doLayoutFn, scope: scope }); }, unregisterContainer: function (obj) { toRem = this.isRegisteredContainer(obj); if (toRem) { for (var i = ctList.length - 1; i >= 0; i--) { if (toRem == ctList[i]) { ctList.splice(i, 1); break; } } } }, isRegisteredUC: function (uc) { var obj = null; for (var i = 0, len = ucList.length; i < len; i++) { var item = ucList[i]; if (uc == item) { obj = item; break; } } return obj; }, isRegisteredContainer: function (el) { var ct = null; if (el.layout) { for (var i = 0, len = ctList.length; i < len; i++) { var item = ctList[i]; if (el == item.scope) { ct = item; break; } } } else if (el.tagName) { // If el argument is a HTMLElement for (var i = 0, len = ctList.length; i < len; i++) { var item = ctList[i]; if (el == item.el) { ct = item; break; } } } else { // If el argument is a gxui.UserControl uc = el; for (var i = 0, len = ctList.length; i < len; i++) { var item = ctList[i]; if (uc == item.uc) { ct = item; break; } } } return ct; }, setControlContainer: function (control, container) { if (!this.childControls) this.childControls = {}; var containerId = container == 'ROOT' ? container : container.scope.id; if (!this.childControls[containerId]) this.childControls[containerId] = []; this.childControls[containerId].push(control); }, addToParentContainer: function (uc, control) { control.on('added', function () { control.width = undefined; control.height = undefined; }, uc); var findParentContainerFn = this.findParentContainer.closure(this, arguments); var afterShowEvent = gxui.afterShow(findParentContainerFn, this); uc.on('destroy', function () { if (afterShowEvent) { afterShowEvent.removeListener(findParentContainerFn, this); } }, this); }, findParentContainer: function (uc, control) { try { var el = Ext.get(uc.getContainerControl()); uc.checkIfInline(el); for (var el = Ext.get(uc.getContainerControl()); el; el = el.parent("div")) { var container = gxui.UserControlManager.isRegisteredContainer(el.dom) uc.checkIfInline(el); if (container) { this.setControlContainer(control, container); return; } } // Controls that don't have a parent container this.setControlContainer(control, 'ROOT'); } catch (e) { gx.dbg.logEx(e, 'gxui.UserControl.js', 'addToParentContainer->' + uc.getUniqueId()); } }, addControlsToContainer: function () { try { var containers = this.getContainersList(); for (var i = 0, len = containers.length; i < len; i++) { var container = containers[i], children = this.childControls[container.scope.id]; var safeChildren = []; if (children) { for (var j = 0, len2 = children.length; j < len2; j++) { if (!children[j].isDestroyed) safeChildren.push(children[j]); } if (safeChildren && safeChildren.length > 0) container.addFn.call(container.scope, safeChildren); } } delete this.childControls; } catch (e) { gx.dbg.logEx(e, 'gxui.UserControl.js', 'addControlsToContainer'); } }, /** * Fires after the show method of all the registered User Controls has been executed. * @param {Function} fn The method the event invokes * @param {Object} [scope] An object that becomes the scope of the handler * @param {Boolean} [options] An object containing standard Ext.EventManager.addListener options * @method * @ignore */ afterShow: function (fn, scope, options) { if (!afterShowEvent) initAfterShow(); scope.afterShowHandler = fn; afterShowEvent.addListener(fn, scope, options); return afterShowEvent; } }; return mgr; } ();