Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / layout / component / AbstractDock.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.layout.component.AbstractDock
17  * @extends Ext.layout.component.Component
18  * @private
19  * This ComponentLayout handles docking for Panels. It takes care of panels that are
20  * part of a ContainerLayout that sets this Panel's size and Panels that are part of
21  * an AutoContainerLayout in which this panel get his height based of the CSS or
22  * or its content.
23  */
24
25 Ext.define('Ext.layout.component.AbstractDock', {
26
27     /* Begin Definitions */
28
29     extend: 'Ext.layout.component.Component',
30
31     /* End Definitions */
32
33     type: 'dock',
34
35     /**
36      * @private
37      * @property autoSizing
38      * @type boolean
39      * This flag is set to indicate this layout may have an autoHeight/autoWidth.
40      */
41     autoSizing: true,
42
43     beforeLayout: function() {
44         var returnValue = this.callParent(arguments);
45         if (returnValue !== false && (!this.initializedBorders || this.childrenChanged) && (!this.owner.border || this.owner.manageBodyBorders)) {
46             this.handleItemBorders();
47             this.initializedBorders = true;
48         }
49         return returnValue;
50     },
51     
52     handleItemBorders: function() {
53         var owner = this.owner,
54             body = owner.body,
55             docked = this.getLayoutItems(),
56             borders = {
57                 top: [],
58                 right: [],
59                 bottom: [],
60                 left: []
61             },
62             oldBorders = this.borders,
63             opposites = {
64                 top: 'bottom',
65                 right: 'left',
66                 bottom: 'top',
67                 left: 'right'
68             },
69             i, ln, item, dock, side;
70
71         for (i = 0, ln = docked.length; i < ln; i++) {
72             item = docked[i];
73             dock = item.dock;
74             
75             if (item.ignoreBorderManagement) {
76                 continue;
77             }
78             
79             if (!borders[dock].satisfied) {
80                 borders[dock].push(item);
81                 borders[dock].satisfied = true;
82             }
83             
84             if (!borders.top.satisfied && opposites[dock] !== 'top') {
85                 borders.top.push(item);
86             }
87             if (!borders.right.satisfied && opposites[dock] !== 'right') {
88                 borders.right.push(item);
89             }            
90             if (!borders.bottom.satisfied && opposites[dock] !== 'bottom') {
91                 borders.bottom.push(item);
92             }            
93             if (!borders.left.satisfied && opposites[dock] !== 'left') {
94                 borders.left.push(item);
95             }
96         }
97
98         if (oldBorders) {
99             for (side in oldBorders) {
100                 if (oldBorders.hasOwnProperty(side)) {
101                     ln = oldBorders[side].length;
102                     if (!owner.manageBodyBorders) {
103                         for (i = 0; i < ln; i++) {
104                             oldBorders[side][i].removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
105                         }
106                         if (!oldBorders[side].satisfied && !owner.bodyBorder) {
107                             body.removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
108                         }                    
109                     }
110                     else if (oldBorders[side].satisfied) {
111                         body.setStyle('border-' + side + '-width', '');
112                     }
113                 }
114             }
115         }
116                 
117         for (side in borders) {
118             if (borders.hasOwnProperty(side)) {
119                 ln = borders[side].length;
120                 if (!owner.manageBodyBorders) {
121                     for (i = 0; i < ln; i++) {
122                         borders[side][i].addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
123                     }
124                     if ((!borders[side].satisfied && !owner.bodyBorder) || owner.bodyBorder === false) {
125                         body.addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
126                     }                    
127                 }
128                 else if (borders[side].satisfied) {
129                     body.setStyle('border-' + side + '-width', '1px');
130                 }
131             }
132         }
133         
134         this.borders = borders;
135     },
136     
137     /**
138      * @protected
139      * @param {Ext.Component} owner The Panel that owns this DockLayout
140      * @param {Ext.core.Element} target The target in which we are going to render the docked items
141      * @param {Array} args The arguments passed to the ComponentLayout.layout method
142      */
143     onLayout: function(width, height) {
144         var me = this,
145             owner = me.owner,
146             body = owner.body,
147             layout = owner.layout,
148             target = me.getTarget(),
149             autoWidth = false,
150             autoHeight = false,
151             padding, border, frameSize;
152
153         // We start of by resetting all the layouts info
154         var info = me.info = {
155             boxes: [],
156             size: {
157                 width: width,
158                 height: height
159             },
160             bodyBox: {}
161         };
162         // Clear isAutoDock flag
163         delete layout.isAutoDock;
164
165         Ext.applyIf(info, me.getTargetInfo());
166
167         // We need to bind to the ownerCt whenever we do not have a user set height or width.
168         if (owner && owner.ownerCt && owner.ownerCt.layout && owner.ownerCt.layout.isLayout) {
169             if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
170                 owner.ownerCt.layout.bindToOwnerCtComponent = true;
171             }
172             else {
173                 owner.ownerCt.layout.bindToOwnerCtComponent = false;
174             }
175         }
176
177         // Determine if we have an autoHeight or autoWidth.
178         if (height === undefined || height === null || width === undefined || width === null) {
179             padding = info.padding;
180             border = info.border;
181             frameSize = me.frameSize;
182
183             // Auto-everything, clear out any style height/width and read from css
184             if ((height === undefined || height === null) && (width === undefined || width === null)) {
185                 autoHeight = true;
186                 autoWidth = true;
187                 me.setTargetSize(null);
188                 me.setBodyBox({width: null, height: null});
189             }
190             // Auto-height
191             else if (height === undefined || height === null) {
192                 autoHeight = true;
193                 // Clear any sizing that we already set in a previous layout
194                 me.setTargetSize(width);
195                 me.setBodyBox({width: width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right, height: null});
196             // Auto-width
197             }
198             else {
199                 autoWidth = true;
200                 // Clear any sizing that we already set in a previous layout
201                 me.setTargetSize(null, height);
202                 me.setBodyBox({width: null, height: height - padding.top - padding.bottom - border.top - border.bottom - frameSize.top - frameSize.bottom});
203             }
204
205             // Run the container
206             if (layout && layout.isLayout) {
207                 // Auto-Sized so have the container layout notify the component layout.
208                 layout.bindToOwnerCtComponent = true;
209                 // Set flag so we don't do a redundant container layout
210                 layout.isAutoDock = layout.autoSize !== true;
211                 layout.layout();
212
213                 // If this is an autosized container layout, then we must compensate for a
214                 // body that is being autosized.  We do not want to adjust the body's size
215                 // to accommodate the dock items, but rather we will want to adjust the
216                 // target's size.
217                 //
218                 // This is necessary because, particularly in a Box layout, all child items
219                 // are set with absolute dimensions that are not flexible to the size of its
220                 // innerCt/target.  So once they are laid out, they are sized for good. By
221                 // shrinking the body box to accommodate dock items, we're merely cutting off
222                 // parts of the body.  Not good.  Instead, the target's size should expand
223                 // to fit the dock items in.  This is valid because the target container is
224                 // suppose to be autosized to fit everything accordingly.
225                 info.autoSizedCtLayout = layout.autoSize === true;
226             }
227
228             // The dockItems method will add all the top and bottom docked items height
229             // to the info.panelSize height. That's why we have to call setSize after
230             // we dock all the items to actually set the panel's width and height.
231             // We have to do this because the panel body and docked items will be position
232             // absolute which doesn't stretch the panel.
233             me.dockItems(autoWidth, autoHeight);
234             me.setTargetSize(info.size.width, info.size.height);
235         }
236         else {
237             me.setTargetSize(width, height);
238             me.dockItems();
239         }
240         me.callParent(arguments);
241     },
242
243     /**
244      * @protected
245      * This method will first update all the information about the docked items,
246      * body dimensions and position, the panel's total size. It will then
247      * set all these values on the docked items and panel body.
248      * @param {Array} items Array containing all the docked items
249      * @param {Boolean} autoBoxes Set this to true if the Panel is part of an
250      * AutoContainerLayout
251      */
252     dockItems : function(autoWidth, autoHeight) {
253         this.calculateDockBoxes(autoWidth, autoHeight);
254
255         // Both calculateAutoBoxes and calculateSizedBoxes are changing the
256         // information about the body, panel size, and boxes for docked items
257         // inside a property called info.
258         var info = this.info,
259             boxes = info.boxes,
260             ln = boxes.length,
261             dock, i;
262
263         // We are going to loop over all the boxes that were calculated
264         // and set the position of each item the box belongs to.
265         for (i = 0; i < ln; i++) {
266             dock = boxes[i];
267             dock.item.setPosition(dock.x, dock.y);
268             if ((autoWidth || autoHeight) && dock.layout && dock.layout.isLayout) {
269                 // Auto-Sized so have the container layout notify the component layout.
270                 dock.layout.bindToOwnerCtComponent = true;
271             }
272         }
273
274         // Don't adjust body width/height if the target is using an auto container layout.
275         // But, we do want to adjust the body size if the container layout is auto sized.
276         if (!info.autoSizedCtLayout) {
277             if (autoWidth) {
278                 info.bodyBox.width = null;
279             }
280             if (autoHeight) {
281                 info.bodyBox.height = null;
282             }
283         }
284
285         // If the bodyBox has been adjusted because of the docked items
286         // we will update the dimensions and position of the panel's body.
287         this.setBodyBox(info.bodyBox);
288     },
289
290     /**
291      * @protected
292      * This method will set up some initial information about the panel size and bodybox
293      * and then loop over all the items you pass it to take care of stretching, aligning,
294      * dock position and all calculations involved with adjusting the body box.
295      * @param {Array} items Array containing all the docked items we have to layout
296      */
297     calculateDockBoxes : function(autoWidth, autoHeight) {
298         // We want to use the Panel's el width, and the Panel's body height as the initial
299         // size we are going to use in calculateDockBoxes. We also want to account for
300         // the border of the panel.
301         var me = this,
302             target = me.getTarget(),
303             items = me.getLayoutItems(),
304             owner = me.owner,
305             bodyEl = owner.body,
306             info = me.info,
307             size = info.size,
308             ln = items.length,
309             padding = info.padding,
310             border = info.border,
311             frameSize = me.frameSize,
312             item, i, box, rect;
313
314         // If this Panel is inside an AutoContainerLayout, we will base all the calculations
315         // around the height of the body and the width of the panel.
316         if (autoHeight) {
317             size.height = bodyEl.getHeight() + padding.top + border.top + padding.bottom + border.bottom + frameSize.top + frameSize.bottom;
318         }
319         else {
320             size.height = target.getHeight();
321         }
322         if (autoWidth) {
323             size.width = bodyEl.getWidth() + padding.left + border.left + padding.right + border.right + frameSize.left + frameSize.right;
324         }
325         else {
326             size.width = target.getWidth();
327         }
328
329         info.bodyBox = {
330             x: padding.left + frameSize.left,
331             y: padding.top + frameSize.top,
332             width: size.width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right,
333             height: size.height - border.top - padding.top - border.bottom - padding.bottom - frameSize.top - frameSize.bottom
334         };
335
336         // Loop over all the docked items
337         for (i = 0; i < ln; i++) {
338             item = items[i];
339             // The initBox method will take care of stretching and alignment
340             // In some cases it will also layout the dock items to be able to
341             // get a width or height measurement
342             box = me.initBox(item);
343
344             if (autoHeight === true) {
345                 box = me.adjustAutoBox(box, i);
346             }
347             else {
348                 box = me.adjustSizedBox(box, i);
349             }
350
351             // Save our box. This allows us to loop over all docked items and do all
352             // calculations first. Then in one loop we will actually size and position
353             // all the docked items that have changed.
354             info.boxes.push(box);
355         }
356     },
357
358     /**
359      * @protected
360      * This method will adjust the position of the docked item and adjust the body box
361      * accordingly.
362      * @param {Object} box The box containing information about the width and height
363      * of this docked item
364      * @param {Number} index The index position of this docked item
365      * @return {Object} The adjusted box
366      */
367     adjustSizedBox : function(box, index) {
368         var bodyBox = this.info.bodyBox,
369             frameSize = this.frameSize,
370             info = this.info,
371             padding = info.padding,
372             pos = box.type,
373             border = info.border;
374
375         switch (pos) {
376             case 'top':
377                 box.y = bodyBox.y;
378                 break;
379
380             case 'left':
381                 box.x = bodyBox.x;
382                 break;
383
384             case 'bottom':
385                 box.y = (bodyBox.y + bodyBox.height) - box.height;
386                 break;
387
388             case 'right':
389                 box.x = (bodyBox.x + bodyBox.width) - box.width;
390                 break;
391         }
392
393         if (box.ignoreFrame) {
394             if (pos == 'bottom') {
395                 box.y += (frameSize.bottom + padding.bottom + border.bottom);
396             }
397             else {
398                 box.y -= (frameSize.top + padding.top + border.top);
399             }
400             if (pos == 'right') {
401                 box.x += (frameSize.right + padding.right + border.right);
402             }
403             else {
404                 box.x -= (frameSize.left + padding.left + border.left);
405             }
406         }
407
408         // If this is not an overlaying docked item, we have to adjust the body box
409         if (!box.overlay) {
410             switch (pos) {
411                 case 'top':
412                     bodyBox.y += box.height;
413                     bodyBox.height -= box.height;
414                     break;
415
416                 case 'left':
417                     bodyBox.x += box.width;
418                     bodyBox.width -= box.width;
419                     break;
420
421                 case 'bottom':
422                     bodyBox.height -= box.height;
423                     break;
424
425                 case 'right':
426                     bodyBox.width -= box.width;
427                     break;
428             }
429         }
430         return box;
431     },
432
433     /**
434      * @protected
435      * This method will adjust the position of the docked item inside an AutoContainerLayout
436      * and adjust the body box accordingly.
437      * @param {Object} box The box containing information about the width and height
438      * of this docked item
439      * @param {Number} index The index position of this docked item
440      * @return {Object} The adjusted box
441      */
442     adjustAutoBox : function (box, index) {
443         var info = this.info,
444             owner = this.owner,
445             bodyBox = info.bodyBox,
446             size = info.size,
447             boxes = info.boxes,
448             boxesLn = boxes.length,
449             pos = box.type,
450             frameSize = this.frameSize,
451             padding = info.padding,
452             border = info.border,
453             autoSizedCtLayout = info.autoSizedCtLayout,
454             ln = (boxesLn < index) ? boxesLn : index,
455             i, adjustBox;
456
457         if (pos == 'top' || pos == 'bottom') {
458             // This can affect the previously set left and right and bottom docked items
459             for (i = 0; i < ln; i++) {
460                 adjustBox = boxes[i];
461                 if (adjustBox.stretched && adjustBox.type == 'left' || adjustBox.type == 'right') {
462                     adjustBox.height += box.height;
463                 }
464                 else if (adjustBox.type == 'bottom') {
465                     adjustBox.y += box.height;
466                 }
467             }
468         }
469
470         switch (pos) {
471             case 'top':
472                 box.y = bodyBox.y;
473                 if (!box.overlay) {
474                     bodyBox.y += box.height;
475                     if (owner.isFixedHeight()) {
476                         bodyBox.height -= box.height;
477                     } else {
478                         size.height += box.height;
479                     }
480                 }
481                 break;
482
483             case 'bottom':
484                 if (!box.overlay) {
485                     if (owner.isFixedHeight()) {
486                         bodyBox.height -= box.height;
487                     } else {
488                         size.height += box.height;
489                     }
490                 }
491                 box.y = (bodyBox.y + bodyBox.height);
492                 break;
493
494             case 'left':
495                 box.x = bodyBox.x;
496                 if (!box.overlay) {
497                     bodyBox.x += box.width;
498                     if (owner.isFixedWidth()) {
499                         bodyBox.width -= box.width;
500                     } else {
501                         size.width += box.width;
502                     }
503                 }
504                 break;
505
506             case 'right':
507                 if (!box.overlay) {
508                     if (owner.isFixedWidth()) {
509                         bodyBox.width -= box.width;
510                     } else {
511                         size.width += box.width;
512                     }
513                 }
514                 box.x = (bodyBox.x + bodyBox.width);
515                 break;
516         }
517
518         if (box.ignoreFrame) {
519             if (pos == 'bottom') {
520                 box.y += (frameSize.bottom + padding.bottom + border.bottom);
521             }
522             else {
523                 box.y -= (frameSize.top + padding.top + border.top);
524             }
525             if (pos == 'right') {
526                 box.x += (frameSize.right + padding.right + border.right);
527             }
528             else {
529                 box.x -= (frameSize.left + padding.left + border.left);
530             }
531         }
532         return box;
533     },
534
535     /**
536      * @protected
537      * This method will create a box object, with a reference to the item, the type of dock
538      * (top, left, bottom, right). It will also take care of stretching and aligning of the
539      * docked items.
540      * @param {Ext.Component} item The docked item we want to initialize the box for
541      * @return {Object} The initial box containing width and height and other useful information
542      */
543     initBox : function(item) {
544         var me = this,
545             bodyBox = me.info.bodyBox,
546             horizontal = (item.dock == 'top' || item.dock == 'bottom'),
547             owner = me.owner,
548             frameSize = me.frameSize,
549             info = me.info,
550             padding = info.padding,
551             border = info.border,
552             box = {
553                 item: item,
554                 overlay: item.overlay,
555                 type: item.dock,
556                 offsets: Ext.core.Element.parseBox(item.offsets || {}),
557                 ignoreFrame: item.ignoreParentFrame
558             };
559         // First we are going to take care of stretch and align properties for all four dock scenarios.
560         if (item.stretch !== false) {
561             box.stretched = true;
562             if (horizontal) {
563                 box.x = bodyBox.x + box.offsets.left;
564                 box.width = bodyBox.width - (box.offsets.left + box.offsets.right);
565                 if (box.ignoreFrame) {
566                     box.width += (frameSize.left + frameSize.right + border.left + border.right + padding.left + padding.right);
567                 }
568                 item.setCalculatedSize(box.width - item.el.getMargin('lr'), undefined, owner);
569             }
570             else {
571                 box.y = bodyBox.y + box.offsets.top;
572                 box.height = bodyBox.height - (box.offsets.bottom + box.offsets.top);
573                 if (box.ignoreFrame) {
574                     box.height += (frameSize.top + frameSize.bottom + border.top + border.bottom + padding.top + padding.bottom);
575                 }
576                 item.setCalculatedSize(undefined, box.height - item.el.getMargin('tb'), owner);
577
578                 // At this point IE will report the left/right-docked toolbar as having a width equal to the
579                 // container's full width. Forcing a repaint kicks it into shape so it reports the correct width.
580                 if (!Ext.supports.ComputedStyle) {
581                     item.el.repaint();
582                 }
583             }
584         }
585         else {
586             item.doComponentLayout();
587             box.width = item.getWidth() - (box.offsets.left + box.offsets.right);
588             box.height = item.getHeight() - (box.offsets.bottom + box.offsets.top);
589             box.y += box.offsets.top;
590             if (horizontal) {
591                 box.x = (item.align == 'right') ? bodyBox.width - box.width : bodyBox.x;
592                 box.x += box.offsets.left;
593             }
594         }
595
596         // If we haven't calculated the width or height of the docked item yet
597         // do so, since we need this for our upcoming calculations
598         if (box.width == undefined) {
599             box.width = item.getWidth() + item.el.getMargin('lr');
600         }
601         if (box.height == undefined) {
602             box.height = item.getHeight() + item.el.getMargin('tb');
603         }
604
605         return box;
606     },
607
608     /**
609      * @protected
610      * Returns an array containing all the <b>visible</b> docked items inside this layout's owner Panel
611      * @return {Array} An array containing all the <b>visible</b> docked items of the Panel
612      */
613     getLayoutItems : function() {
614         var it = this.owner.getDockedItems(),
615             ln = it.length,
616             i = 0,
617             result = [];
618         for (; i < ln; i++) {
619             if (it[i].isVisible(true)) {
620                 result.push(it[i]);
621             }
622         }
623         return result;
624     },
625
626     /**
627      * @protected
628      * Render the top and left docked items before any existing DOM nodes in our render target,
629      * and then render the right and bottom docked items after. This is important, for such things
630      * as tab stops and ARIA readers, that the DOM nodes are in a meaningful order.
631      * Our collection of docked items will already be ordered via Panel.getDockedItems().
632      */
633     renderItems: function(items, target) {
634         var cns = target.dom.childNodes,
635             cnsLn = cns.length,
636             ln = items.length,
637             domLn = 0,
638             i, j, cn, item;
639
640         // Calculate the number of DOM nodes in our target that are not our docked items
641         for (i = 0; i < cnsLn; i++) {
642             cn = Ext.get(cns[i]);
643             for (j = 0; j < ln; j++) {
644                 item = items[j];
645                 if (item.rendered && (cn.id == item.el.id || cn.down('#' + item.el.id))) {
646                     break;
647                 }
648             }
649
650             if (j === ln) {
651                 domLn++;
652             }
653         }
654
655         // Now we go through our docked items and render/move them
656         for (i = 0, j = 0; i < ln; i++, j++) {
657             item = items[i];
658
659             // If we're now at the right/bottom docked item, we jump ahead in our
660             // DOM position, just past the existing DOM nodes.
661             //
662             // TODO: This is affected if users provide custom weight values to their
663             // docked items, which puts it out of (t,l,r,b) order. Avoiding a second
664             // sort operation here, for now, in the name of performance. getDockedItems()
665             // needs the sort operation not just for this layout-time rendering, but
666             // also for getRefItems() to return a logical ordering (FocusManager, CQ, et al).
667             if (i === j && (item.dock === 'right' || item.dock === 'bottom')) {
668                 j += domLn;
669             }
670
671             // Same logic as Layout.renderItems()
672             if (item && !item.rendered) {
673                 this.renderItem(item, target, j);
674             }
675             else if (!this.isValidParent(item, target, j)) {
676                 this.moveItem(item, target, j);
677             }
678         }
679     },
680
681     /**
682      * @protected
683      * This function will be called by the dockItems method. Since the body is positioned absolute,
684      * we need to give it dimensions and a position so that it is in the middle surrounded by
685      * docked items
686      * @param {Object} box An object containing new x, y, width and height values for the
687      * Panel's body
688      */
689     setBodyBox : function(box) {
690         var me = this,
691             owner = me.owner,
692             body = owner.body,
693             info = me.info,
694             bodyMargin = info.bodyMargin,
695             padding = info.padding,
696             border = info.border,
697             frameSize = me.frameSize;
698         
699         // Panel collapse effectively hides the Panel's body, so this is a no-op.
700         if (owner.collapsed) {
701             return;
702         }
703         
704         if (Ext.isNumber(box.width)) {
705             box.width -= bodyMargin.left + bodyMargin.right;
706         }
707         
708         if (Ext.isNumber(box.height)) {
709             box.height -= bodyMargin.top + bodyMargin.bottom;
710         }
711         
712         me.setElementSize(body, box.width, box.height);
713         if (Ext.isNumber(box.x)) {
714             body.setLeft(box.x - padding.left - frameSize.left);
715         }
716         if (Ext.isNumber(box.y)) {
717             body.setTop(box.y - padding.top - frameSize.top);
718         }
719     },
720
721     /**
722      * @protected
723      * We are overriding the Ext.layout.Layout configureItem method to also add a class that
724      * indicates the position of the docked item. We use the itemCls (x-docked) as a prefix.
725      * An example of a class added to a dock: right item is x-docked-right
726      * @param {Ext.Component} item The item we are configuring
727      */
728     configureItem : function(item, pos) {
729         this.callParent(arguments);
730         if (item.dock == 'top' || item.dock == 'bottom') {
731             item.layoutManagedWidth = 1;
732             item.layoutManagedHeight = 2;
733         } else {
734             item.layoutManagedWidth = 2;
735             item.layoutManagedHeight = 1;
736         }
737         
738         item.addCls(Ext.baseCSSPrefix + 'docked');
739         item.addClsWithUI('docked-' + item.dock);
740     },
741
742     afterRemove : function(item) {
743         this.callParent(arguments);
744         if (this.itemCls) {
745             item.el.removeCls(this.itemCls + '-' + item.dock);
746         }
747         var dom = item.el.dom;
748
749         if (!item.destroying && dom) {
750             dom.parentNode.removeChild(dom);
751         }
752         this.childrenChanged = true;
753     }
754 });