X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/layout/Layout.js diff --git a/src/layout/Layout.js b/src/layout/Layout.js new file mode 100644 index 00000000..4dc84d3c --- /dev/null +++ b/src/layout/Layout.js @@ -0,0 +1,211 @@ +/** + * @class Ext.layout.Layout + * @extends Object + * @private + * Base Layout class - extended by ComponentLayout and ContainerLayout + */ + +Ext.define('Ext.layout.Layout', { + + /* Begin Definitions */ + + /* End Definitions */ + + isLayout: true, + initialized: false, + + statics: { + create: function(layout, defaultType) { + var type; + if (layout instanceof Ext.layout.Layout) { + return Ext.createByAlias('layout.' + layout); + } else { + if (Ext.isObject(layout)) { + type = layout.type; + } + else { + type = layout || defaultType; + layout = {}; + } + return Ext.createByAlias('layout.' + type, layout || {}); + } + } + }, + + constructor : function(config) { + this.id = Ext.id(null, this.type + '-'); + Ext.apply(this, config); + }, + + /** + * @private + */ + layout : function() { + var me = this; + me.layoutBusy = true; + me.initLayout(); + + if (me.beforeLayout.apply(me, arguments) !== false) { + me.layoutCancelled = false; + me.onLayout.apply(me, arguments); + me.childrenChanged = false; + me.owner.needsLayout = false; + me.layoutBusy = false; + me.afterLayout.apply(me, arguments); + } + else { + me.layoutCancelled = true; + } + me.layoutBusy = false; + me.doOwnerCtLayouts(); + }, + + beforeLayout : function() { + this.renderItems(this.getLayoutItems(), this.getRenderTarget()); + return true; + }, + + /** + * @private + * Iterates over all passed items, ensuring they are rendered. If the items are already rendered, + * also determines if the items are in the proper place dom. + */ + renderItems : function(items, target) { + var ln = items.length, + i = 0, + item; + + for (; i < ln; i++) { + item = items[i]; + if (item && !item.rendered) { + this.renderItem(item, target, i); + } + else if (!this.isValidParent(item, target, i)) { + this.moveItem(item, target, i); + } + } + }, + + // @private - Validates item is in the proper place in the dom. + isValidParent : function(item, target, position) { + var dom = item.el ? item.el.dom : Ext.getDom(item); + if (dom && target && target.dom) { + if (Ext.isNumber(position) && dom !== target.dom.childNodes[position]) { + return false; + } + return (dom.parentNode == (target.dom || target)); + } + return false; + }, + + /** + * @private + * Renders the given Component into the target Element. + * @param {Ext.Component} item The Component to render + * @param {Ext.core.Element} target The target Element + * @param {Number} position The position within the target to render the item to + */ + renderItem : function(item, target, position) { + if (!item.rendered) { + item.render(target, position); + this.configureItem(item); + this.childrenChanged = true; + } + }, + + /** + * @private + * Moved Component to the provided target instead. + */ + moveItem : function(item, target, position) { + // Make sure target is a dom element + target = target.dom || target; + if (typeof position == 'number') { + position = target.childNodes[position]; + } + target.insertBefore(item.el.dom, position || null); + item.container = Ext.get(target); + this.configureItem(item); + this.childrenChanged = true; + }, + + /** + * @private + * Adds the layout's targetCls if necessary and sets + * initialized flag when complete. + */ + initLayout : function() { + if (!this.initialized && !Ext.isEmpty(this.targetCls)) { + this.getTarget().addCls(this.targetCls); + } + this.initialized = true; + }, + + // @private Sets the layout owner + setOwner : function(owner) { + this.owner = owner; + }, + + // @private - Returns empty array + getLayoutItems : function() { + return []; + }, + + /** + * @private + * Applies itemCls + */ + configureItem: function(item) { + var me = this, + el = item.el, + owner = me.owner; + + if (me.itemCls) { + el.addCls(me.itemCls); + } + if (owner.itemCls) { + el.addCls(owner.itemCls); + } + }, + + // Placeholder empty functions for subclasses to extend + onLayout : Ext.emptyFn, + afterLayout : Ext.emptyFn, + onRemove : Ext.emptyFn, + onDestroy : Ext.emptyFn, + doOwnerCtLayouts : Ext.emptyFn, + + /** + * @private + * Removes itemCls + */ + afterRemove : function(item) { + var me = this, + el = item.el, + owner = me.owner; + + if (item.rendered) { + if (me.itemCls) { + el.removeCls(me.itemCls); + } + if (owner.itemCls) { + el.removeCls(owner.itemCls); + } + } + }, + + /* + * Destroys this layout. This is a template method that is empty by default, but should be implemented + * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes. + * @protected + */ + destroy : function() { + if (!Ext.isEmpty(this.targetCls)) { + var target = this.getTarget(); + if (target) { + target.removeCls(this.targetCls); + } + } + this.onDestroy(); + } +}); \ No newline at end of file