/ext-4.0.7/src/layout/component/Component.js
JavaScript | 289 lines | 184 code | 39 blank | 66 comment | 60 complexity | 471fd859f781d4459c81a5eed6097a86 MD5 | raw file
1/*
2
3This file is part of Ext JS 4
4
5Copyright (c) 2011 Sencha Inc
6
7Contact: http://www.sencha.com/contact
8
9GNU General Public License Usage
10This 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
12If 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.Component
17 * @extends Ext.layout.Layout
18 *
19 * This class is intended to be extended or created via the {@link Ext.Component#componentLayout layout}
20 * configuration property. See {@link Ext.Component#componentLayout} for additional details.
21 *
22 * @private
23 */
24Ext.define('Ext.layout.component.Component', {
25
26 /* Begin Definitions */
27
28 extend: 'Ext.layout.Layout',
29
30 /* End Definitions */
31
32 type: 'component',
33
34 monitorChildren: true,
35
36 initLayout : function() {
37 var me = this,
38 owner = me.owner,
39 ownerEl = owner.el;
40
41 if (!me.initialized) {
42 if (owner.frameSize) {
43 me.frameSize = owner.frameSize;
44 }
45 else {
46 owner.frameSize = me.frameSize = {
47 top: 0,
48 left: 0,
49 bottom: 0,
50 right: 0
51 };
52 }
53 }
54 me.callParent(arguments);
55 },
56
57 beforeLayout : function(width, height, isSetSize, callingContainer) {
58 this.callParent(arguments);
59
60 var me = this,
61 owner = me.owner,
62 ownerCt = owner.ownerCt,
63 layout = owner.layout,
64 isVisible = owner.isVisible(true),
65 ownerElChild = owner.el.child,
66 layoutCollection;
67
68 // Cache the size we began with so we can see if there has been any effect.
69 me.previousComponentSize = me.lastComponentSize;
70
71 // Do not allow autoing of any dimensions which are fixed
72 if (!isSetSize
73 && ((!Ext.isNumber(width) && owner.isFixedWidth()) ||
74 (!Ext.isNumber(height) && owner.isFixedHeight()))
75 // unless we are being told to do so by the ownerCt's layout
76 && callingContainer && callingContainer !== ownerCt) {
77
78 me.doContainerLayout();
79 return false;
80 }
81
82 // If an ownerCt is hidden, add my reference onto the layoutOnShow stack. Set the needsLayout flag.
83 // If the owner itself is a directly hidden floater, set the needsLayout object on that for when it is shown.
84 if (!isVisible && (owner.hiddenAncestor || owner.floating)) {
85 if (owner.hiddenAncestor) {
86 layoutCollection = owner.hiddenAncestor.layoutOnShow;
87 layoutCollection.remove(owner);
88 layoutCollection.add(owner);
89 }
90 owner.needsLayout = {
91 width: width,
92 height: height,
93 isSetSize: false
94 };
95 }
96
97 if (isVisible && this.needsLayout(width, height)) {
98 return owner.beforeComponentLayout(width, height, isSetSize, callingContainer);
99 }
100 else {
101 return false;
102 }
103 },
104
105 /**
106 * Check if the new size is different from the current size and only
107 * trigger a layout if it is necessary.
108 * @param {Number} width The new width to set.
109 * @param {Number} height The new height to set.
110 */
111 needsLayout : function(width, height) {
112 var me = this,
113 widthBeingChanged,
114 heightBeingChanged;
115 me.lastComponentSize = me.lastComponentSize || {
116 width: -Infinity,
117 height: -Infinity
118 };
119
120 // If autoWidthing, or an explicitly different width is passed, then the width is being changed.
121 widthBeingChanged = !Ext.isDefined(width) || me.lastComponentSize.width !== width;
122
123 // If autoHeighting, or an explicitly different height is passed, then the height is being changed.
124 heightBeingChanged = !Ext.isDefined(height) || me.lastComponentSize.height !== height;
125
126
127 // isSizing flag added to prevent redundant layouts when going up the layout chain
128 return !me.isSizing && (me.childrenChanged || widthBeingChanged || heightBeingChanged);
129 },
130
131 /**
132 * Set the size of any element supporting undefined, null, and values.
133 * @param {Number} width The new width to set.
134 * @param {Number} height The new height to set.
135 */
136 setElementSize: function(el, width, height) {
137 if (width !== undefined && height !== undefined) {
138 el.setSize(width, height);
139 }
140 else if (height !== undefined) {
141 el.setHeight(height);
142 }
143 else if (width !== undefined) {
144 el.setWidth(width);
145 }
146 },
147
148 /**
149 * Returns the owner component's resize element.
150 * @return {Ext.Element}
151 */
152 getTarget : function() {
153 return this.owner.el;
154 },
155
156 /**
157 * <p>Returns the element into which rendering must take place. Defaults to the owner Component's encapsulating element.</p>
158 * May be overridden in Component layout managers which implement an inner element.
159 * @return {Ext.Element}
160 */
161 getRenderTarget : function() {
162 return this.owner.el;
163 },
164
165 /**
166 * Set the size of the target element.
167 * @param {Number} width The new width to set.
168 * @param {Number} height The new height to set.
169 */
170 setTargetSize : function(width, height) {
171 var me = this;
172 me.setElementSize(me.owner.el, width, height);
173
174 if (me.owner.frameBody) {
175 var targetInfo = me.getTargetInfo(),
176 padding = targetInfo.padding,
177 border = targetInfo.border,
178 frameSize = me.frameSize;
179
180 me.setElementSize(me.owner.frameBody,
181 Ext.isNumber(width) ? (width - frameSize.left - frameSize.right - padding.left - padding.right - border.left - border.right) : width,
182 Ext.isNumber(height) ? (height - frameSize.top - frameSize.bottom - padding.top - padding.bottom - border.top - border.bottom) : height
183 );
184 }
185
186 me.autoSized = {
187 width: !Ext.isNumber(width),
188 height: !Ext.isNumber(height)
189 };
190
191 me.lastComponentSize = {
192 width: width,
193 height: height
194 };
195 },
196
197 getTargetInfo : function() {
198 if (!this.targetInfo) {
199 var target = this.getTarget(),
200 body = this.owner.getTargetEl();
201
202 this.targetInfo = {
203 padding: {
204 top: target.getPadding('t'),
205 right: target.getPadding('r'),
206 bottom: target.getPadding('b'),
207 left: target.getPadding('l')
208 },
209 border: {
210 top: target.getBorderWidth('t'),
211 right: target.getBorderWidth('r'),
212 bottom: target.getBorderWidth('b'),
213 left: target.getBorderWidth('l')
214 },
215 bodyMargin: {
216 top: body.getMargin('t'),
217 right: body.getMargin('r'),
218 bottom: body.getMargin('b'),
219 left: body.getMargin('l')
220 }
221 };
222 }
223 return this.targetInfo;
224 },
225
226 // Start laying out UP the ownerCt's layout when flagged to do so.
227 doOwnerCtLayouts: function() {
228 var owner = this.owner,
229 ownerCt = owner.ownerCt,
230 ownerCtComponentLayout, ownerCtContainerLayout,
231 curSize = this.lastComponentSize,
232 prevSize = this.previousComponentSize,
233 widthChange = (prevSize && curSize && Ext.isNumber(curSize.width )) ? curSize.width !== prevSize.width : true,
234 heightChange = (prevSize && curSize && Ext.isNumber(curSize.height)) ? curSize.height !== prevSize.height : true;
235
236 // If size has not changed, do not inform upstream layouts
237 if (!ownerCt || (!widthChange && !heightChange)) {
238 return;
239 }
240
241 ownerCtComponentLayout = ownerCt.componentLayout;
242 ownerCtContainerLayout = ownerCt.layout;
243
244 if (!owner.floating && ownerCtComponentLayout && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
245 if (!ownerCt.suspendLayout && ownerCtContainerLayout && !ownerCtContainerLayout.layoutBusy) {
246
247 // If the owning Container may be adjusted in any of the the dimension which have changed, perform its Component layout
248 if (((widthChange && !ownerCt.isFixedWidth()) || (heightChange && !ownerCt.isFixedHeight()))) {
249 // Set the isSizing flag so that the upstream Container layout (called after a Component layout) can omit this component from sizing operations
250 this.isSizing = true;
251 ownerCt.doComponentLayout();
252 this.isSizing = false;
253 }
254 // Execute upstream Container layout
255 else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
256 ownerCtContainerLayout.layout();
257 }
258 }
259 }
260 },
261
262 doContainerLayout: function() {
263 var me = this,
264 owner = me.owner,
265 ownerCt = owner.ownerCt,
266 layout = owner.layout,
267 ownerCtComponentLayout;
268
269 // Run the container layout if it exists (layout for child items)
270 // **Unless automatic laying out is suspended, or the layout is currently running**
271 if (!owner.suspendLayout && layout && layout.isLayout && !layout.layoutBusy && !layout.isAutoDock) {
272 layout.layout();
273 }
274
275 // Tell the ownerCt that it's child has changed and can be re-layed by ignoring the lastComponentSize cache.
276 if (ownerCt && ownerCt.componentLayout) {
277 ownerCtComponentLayout = ownerCt.componentLayout;
278 if (!owner.floating && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
279 ownerCtComponentLayout.childrenChanged = true;
280 }
281 }
282 },
283
284 afterLayout : function(width, height, isSetSize, layoutOwner) {
285 this.doContainerLayout();
286 this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
287 }
288});
289