]> git.proxmox.com Git - sencha-touch.git/blob - src/src/layout/Default.js
import Sencha Touch 2.4.2 source
[sencha-touch.git] / src / src / layout / Default.js
1 /**
2 *
3 */
4 Ext.define('Ext.layout.Default', {
5 extend: 'Ext.layout.Abstract',
6
7 isAuto: true,
8
9 alias: ['layout.default', 'layout.auto'],
10
11 requires: [
12 'Ext.util.Wrapper',
13 'Ext.layout.wrapper.BoxDock',
14 'Ext.layout.wrapper.Inner'
15 ],
16
17 config: {
18 /**
19 * @cfg {Ext.fx.layout.Card} animation Layout animation configuration
20 * Controls how layout transitions are animated. Currently only available for
21 * Card Layouts.
22 *
23 * Possible values are:
24 *
25 * - cover
26 * - cube
27 * - fade
28 * - flip
29 * - pop
30 * - reveal
31 * - scroll
32 * - slide
33 * @accessor
34 */
35 animation: null
36 },
37
38 centerWrapperClass: 'x-center',
39
40 dockWrapperClass: 'x-dock',
41
42 positionMap: {
43 top: 'start',
44 left: 'start',
45 middle: 'center',
46 bottom: 'end',
47 right: 'end'
48 },
49
50 positionDirectionMap: {
51 top: 'vertical',
52 bottom: 'vertical',
53 left: 'horizontal',
54 right: 'horizontal'
55 },
56
57 setContainer: function(container) {
58 var options = {
59 delegate: '> component'
60 };
61
62 this.dockedItems = [];
63
64 this.callSuper(arguments);
65
66 container.on('centeredchange', 'onItemCenteredChange', this, options, 'before')
67 .on('floatingchange', 'onItemFloatingChange', this, options, 'before')
68 .on('dockedchange', 'onBeforeItemDockedChange', this, options, 'before')
69 .on('afterdockedchange', 'onAfterItemDockedChange', this, options);
70 },
71
72 monitorSizeStateChange: function() {
73 this.monitorSizeStateChange = Ext.emptyFn;
74 this.container.on('sizestatechange', 'onContainerSizeStateChange', this);
75 },
76
77 monitorSizeFlagsChange: function() {
78 this.monitorSizeFlagsChange = Ext.emptyFn;
79 this.container.on('sizeflagschange', 'onContainerSizeFlagsChange', this);
80 },
81
82 onItemAdd: function(item) {
83 var docked = item.getDocked();
84
85 if (docked !== null) {
86 this.dockItem(item);
87 }
88 else if (item.isCentered()) {
89 this.onItemCenteredChange(item, true);
90 }
91 else if (item.isFloating()) {
92 this.onItemFloatingChange(item, true);
93 }
94 else {
95 this.onItemInnerStateChange(item, true);
96 }
97 },
98
99 /**
100 * @param {Ext.Component} item
101 * @param {Boolean} isInner
102 * @param {Boolean} [destroying]
103 */
104 onItemInnerStateChange: function(item, isInner, destroying) {
105 if (isInner) {
106 this.insertInnerItem(item, this.container.innerIndexOf(item));
107 }
108 else {
109 this.removeInnerItem(item);
110 }
111 },
112
113 insertInnerItem: function(item, index) {
114 var container = this.container,
115 containerDom = container.innerElement.dom,
116 itemDom = item.element.dom,
117 nextSibling = index !== -1 ? container.getInnerAt(index + 1) : null,
118 nextSiblingDom = null,
119 translatable;
120
121 if (nextSibling) {
122 translatable = nextSibling.getTranslatable();
123 if (translatable && translatable.getUseWrapper()) {
124 nextSiblingDom = translatable.getWrapper().dom;
125 }
126 else {
127 nextSiblingDom = nextSibling ? nextSibling.element.dom : null;
128 }
129 }
130
131 containerDom.insertBefore(itemDom, nextSiblingDom);
132
133 return this;
134 },
135
136 insertBodyItem: function(item) {
137 var container = this.container.setUseBodyElement(true),
138 bodyDom = container.bodyElement.dom;
139
140 if (item.getZIndex() === null) {
141 item.setZIndex((container.indexOf(item) + 1) * 2);
142 }
143
144 bodyDom.insertBefore(item.element.dom, bodyDom.firstChild);
145
146 return this;
147 },
148
149 removeInnerItem: function(item) {
150 item.element.detach();
151 },
152
153 removeBodyItem: function(item) {
154 item.setZIndex(null);
155 item.element.detach();
156 },
157
158 onItemRemove: function(item, index, destroying) {
159 var docked = item.getDocked();
160
161 if (docked) {
162 this.undockItem(item);
163 }
164 else if (item.isCentered()) {
165 this.onItemCenteredChange(item, false);
166 }
167 else if (item.isFloating()) {
168 this.onItemFloatingChange(item, false);
169 }
170 else {
171 this.onItemInnerStateChange(item, false, destroying);
172 }
173 },
174
175 onItemMove: function(item, toIndex, fromIndex) {
176 if (item.isCentered() || item.isFloating()) {
177 item.setZIndex((toIndex + 1) * 2);
178 }
179 else if (item.isInnerItem()) {
180 this.insertInnerItem(item, this.container.innerIndexOf(item));
181 }
182 else {
183 this.undockItem(item);
184 this.dockItem(item);
185 }
186 },
187
188 onItemCenteredChange: function(item, centered) {
189 var wrapperName = '$centerWrapper';
190
191 if (centered) {
192 this.insertBodyItem(item);
193 item.link(wrapperName, new Ext.util.Wrapper({
194 className: this.centerWrapperClass
195 }, item.element));
196 }
197 else {
198 item.unlink(wrapperName);
199 this.removeBodyItem(item);
200 }
201 },
202
203 onItemFloatingChange: function(item, floating) {
204 if (floating) {
205 this.insertBodyItem(item);
206 }
207 else {
208 this.removeBodyItem(item);
209 }
210 },
211
212 onBeforeItemDockedChange: function(item, docked, oldDocked) {
213 if (oldDocked) {
214 this.undockItem(item);
215 }
216 },
217
218 onAfterItemDockedChange: function(item, docked, oldDocked) {
219 if (docked) {
220 this.dockItem(item);
221 }
222 },
223
224 onContainerSizeStateChange: function() {
225 var dockWrapper = this.getDockWrapper();
226
227 if (dockWrapper) {
228 dockWrapper.setSizeState(this.container.getSizeState());
229 }
230 },
231
232 onContainerSizeFlagsChange: function() {
233 var items = this.dockedItems,
234 i, ln, item;
235
236 for (i = 0, ln = items.length; i < ln; i++) {
237 item = items[i];
238 this.refreshDockedItemLayoutSizeFlags(item);
239 }
240 },
241
242 refreshDockedItemLayoutSizeFlags: function(item) {
243 var container = this.container,
244 dockedDirection = this.positionDirectionMap[item.getDocked()],
245 binaryMask = (dockedDirection === 'horizontal') ? container.LAYOUT_HEIGHT : container.LAYOUT_WIDTH,
246 flags = (container.getSizeFlags() & binaryMask);
247
248 item.setLayoutSizeFlags(flags);
249 },
250
251 dockItem: function(item) {
252 var DockClass = Ext.layout.wrapper.BoxDock,
253 dockedItems = this.dockedItems,
254 ln = dockedItems.length,
255 container = this.container,
256 itemIndex = container.indexOf(item),
257 positionDirectionMap = this.positionDirectionMap,
258 direction = positionDirectionMap[item.getDocked()],
259 dockInnerWrapper = this.dockInnerWrapper,
260 referenceDirection, i, dockedItem, index, previousItem, slice,
261 referenceItem, referenceDocked, referenceWrapper, newWrapper, nestedWrapper, oldInnerWrapper;
262
263 this.monitorSizeStateChange();
264 this.monitorSizeFlagsChange();
265
266 if (!dockInnerWrapper) {
267 dockInnerWrapper = this.link('dockInnerWrapper', new Ext.layout.wrapper.Inner({
268 container: this.container
269 }));
270 }
271
272 if (ln === 0) {
273 dockedItems.push(item);
274
275 newWrapper = new DockClass({
276 container: this.container,
277 direction: direction
278 });
279
280 newWrapper.addItem(item);
281 newWrapper.getElement().replace(dockInnerWrapper.getElement());
282 newWrapper.setInnerWrapper(dockInnerWrapper);
283 container.onInitialized('onContainerSizeStateChange', this);
284 }
285 else {
286 for (i = 0; i < ln; i++) {
287 dockedItem = dockedItems[i];
288 index = container.indexOf(dockedItem);
289
290 if (index > itemIndex) {
291 referenceItem = previousItem || dockedItems[0];
292 dockedItems.splice(i, 0, item);
293 break;
294 }
295
296 previousItem = dockedItem;
297 }
298
299 if (!referenceItem) {
300 referenceItem = dockedItems[ln - 1];
301 dockedItems.push(item);
302 }
303
304 referenceDocked = referenceItem.getDocked();
305 referenceWrapper = referenceItem.$dockWrapper;
306 referenceDirection = positionDirectionMap[referenceDocked];
307
308 if (direction === referenceDirection) {
309 referenceWrapper.addItem(item);
310 }
311 else {
312 slice = referenceWrapper.getItemsSlice(itemIndex);
313
314 newWrapper = new DockClass({
315 container: this.container,
316 direction: direction
317 });
318
319 if (slice.length > 0) {
320 if (slice.length === referenceWrapper.itemsCount) {
321 nestedWrapper = referenceWrapper;
322 newWrapper.setSizeState(nestedWrapper.getSizeState());
323 newWrapper.getElement().replace(nestedWrapper.getElement());
324 }
325 else {
326 nestedWrapper = new DockClass({
327 container: this.container,
328 direction: referenceDirection
329 });
330 nestedWrapper.setInnerWrapper(referenceWrapper.getInnerWrapper());
331 nestedWrapper.addItems(slice);
332 referenceWrapper.setInnerWrapper(newWrapper);
333 }
334
335 newWrapper.setInnerWrapper(nestedWrapper);
336 }
337 else {
338 oldInnerWrapper = referenceWrapper.getInnerWrapper();
339 referenceWrapper.setInnerWrapper(null);
340 newWrapper.setInnerWrapper(oldInnerWrapper);
341 referenceWrapper.setInnerWrapper(newWrapper);
342 }
343
344 newWrapper.addItem(item);
345 }
346 }
347
348 container.onInitialized('refreshDockedItemLayoutSizeFlags', this, [item]);
349 },
350
351 getDockWrapper: function() {
352 var dockedItems = this.dockedItems;
353
354 if (dockedItems.length > 0) {
355 return dockedItems[0].$dockWrapper;
356 }
357
358 return null;
359 },
360
361 undockItem: function(item) {
362 var dockedItems = this.dockedItems;
363
364 if (item.$dockWrapper) {
365 item.$dockWrapper.removeItem(item);
366 }
367
368 Ext.Array.remove(dockedItems, item);
369
370 item.setLayoutSizeFlags(0);
371 },
372
373 destroy: function() {
374 this.dockedItems.length = 0;
375
376 delete this.dockedItems;
377
378 this.callSuper();
379 }
380 });