1 /* ************************************************************************
3 qooxdoo - the new era of web development
8 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
11 LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
14 * Sebastian Werner (wpbasti)
15 * Andreas Ecker (ecker)
17 ************************************************************************ */
19 /* ************************************************************************
23 ************************************************************************ */
25 qx.OO.defineClass("qx.renderer.layout.FlowLayoutImpl", qx.renderer.layout.LayoutImpl,
27 qx.renderer.layout.LayoutImpl.call(this, vWidget);
30 qx.renderer.layout.FlowLayoutImpl.STR_FIRST = "getFirstVisibleChild";
31 qx.renderer.layout.FlowLayoutImpl.STR_LAST = "getLastVisibleChild";
32 qx.renderer.layout.FlowLayoutImpl.STR_NEXT = "getNextSibling";
33 qx.renderer.layout.FlowLayoutImpl.STR_PREVIOUS = "getPreviousSibling";
39 [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
40 [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
41 [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
42 [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
43 [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
44 [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
45 [08] CHILDREN ADD/REMOVE/MOVE HANDLING
46 [09] FLUSH LAYOUT QUEUES OF CHILDREN
50 Inherits from qx.renderer.layout.LayoutImpl:
52 [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
53 [02] COMPUTE NEEDED DIMENSIONS FOR AN INDIVIDUAL CHILD
54 [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
64 ---------------------------------------------------------------------------
65 [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
66 ---------------------------------------------------------------------------
70 Compute and return the width needed by all children of this widget
72 qx.Proto.computeChildrenNeededWidth = function()
74 var w = this.getWidget();
75 return qx.renderer.layout.LayoutImpl.prototype.computeChildrenNeededWidth_sum.call(this) + ((w.getVisibleChildrenLength()-1) * w.getHorizontalSpacing());
79 Calculate the layout to get the needed height of the children
81 qx.Proto.computeChildrenNeededHeight = function()
83 var vWidget = this.getWidget();
85 var vInnerWidth = vWidget.getInnerWidth();
87 var vHorizontalSpacing = vWidget.getHorizontalSpacing();
88 var vVerticalSpacing = vWidget.getVerticalSpacing();
89 var vReversed = vWidget.getReverseChildrenOrder();
94 var vRowHeightSum = 0;
96 for (var i=0, ch=vWidget.getVisibleChildren(), chl=ch.length, chc; i<chl; i++)
98 chc = vReversed ? ch[chl-1-i] : ch[i];
100 vRowWidth += chc.getNeededWidth();
102 if (vRowWidth > vInnerWidth)
104 vRowHeightSum += vRowHeight + vVerticalSpacing;
105 vRowWidth = chc.getNeededWidth();
106 vRowHeight = chc.getNeededHeight();
110 vRowHeight = Math.max(vRowHeight, chc.getNeededHeight());
113 vRowWidth += vHorizontalSpacing;
116 return vRowHeightSum + vRowHeight;
126 ---------------------------------------------------------------------------
127 [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
128 ---------------------------------------------------------------------------
132 Things to do and layout when any of the childs changes it's outer width.
133 Needed by layouts where the children depends on each-other, like flow- or box-layouts.
135 qx.Proto.updateSelfOnChildOuterWidthChange = function(vChild)
137 // If a child only change it's width also recompute the height
138 // as the layout flows around here
139 //this.getWidget()._recomputeNeededHeightHelper();
140 this.getWidget()._invalidatePreferredInnerHeight();
149 ---------------------------------------------------------------------------
150 [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
151 ---------------------------------------------------------------------------
155 Actions that should be done if the inner width of the widget was changed.
156 Normally this includes update to percent values and ranges.
158 qx.Proto.updateChildOnInnerWidthChange = function(vChild)
160 vChild._recomputePercentX();
161 vChild.addToLayoutChanges("location");
167 Actions that should be done if the inner height of the widget was changed.
168 Normally this includes update to percent values and ranges.
170 qx.Proto.updateChildOnInnerHeightChange = function(vChild)
172 vChild._recomputePercentY();
173 vChild.addToLayoutChanges("location");
185 ---------------------------------------------------------------------------
186 [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
187 ---------------------------------------------------------------------------
191 Updates children on special jobs
193 qx.Proto.updateChildrenOnJobQueueFlush = function(vQueue)
195 if (vQueue.horizontalSpacing || vQueue.verticalSpacing || vQueue.reverseChildrenOrder || vQueue.horizontalChildrenAlign || vQueue.verticalChildrenAlign) {
196 this.getWidget()._addChildrenToLayoutQueue("location");
206 ---------------------------------------------------------------------------
207 [08] CHILDREN ADD/REMOVE/MOVE HANDLING
208 ---------------------------------------------------------------------------
212 This method combines calls of methods which should be done if a widget should be removed from the current layout.
213 Needed by layouts where the children depends on each-other, like flow- or box-layouts.
215 qx.Proto.updateChildrenOnRemoveChild = function(vChild, vIndex)
217 var w=this.getWidget(), ch=w.getVisibleChildren(), chl=ch.length, chc, i=-1;
219 if (w.getReverseChildrenOrder())
221 while((chc=ch[++i]) && i<vIndex) {
222 chc.addToLayoutChanges("location");
229 chc.addToLayoutChanges("location");
235 This method combines calls of methods which should be done if a child should be moved
236 inside the same parent to a new positions.
237 Needed by layouts where the children depends on each-other, like flow- or box-layouts.
239 qx.Proto.updateChildrenOnMoveChild = function(vChild, vIndex, vOldIndex)
241 for (var i=Math.min(vIndex, vOldIndex), ch=this.getWidget().getVisibleChildren(), l=ch.length; i<l; i++) {
242 ch[i].addToLayoutChanges("location");
252 ---------------------------------------------------------------------------
253 [09] FLUSH LAYOUT QUEUES OF CHILDREN
254 ---------------------------------------------------------------------------
258 This method have full control of the order in which the
259 registered (or also non-registered) children should be
260 layouted on the horizontal axis.
263 qx.Proto.flushChildrenQueue = function(vChildrenQueue)
265 var w=this.getWidget(), ch=w.getVisibleChildren(), chl=ch.length, chc, chh;
267 if (w.getReverseChildrenOrder())
269 // layout all childs from the first child
270 // with an own layout request to the end
271 var i=chl, changed=false;
274 chh = chc.toHashCode();
276 if (changed || vChildrenQueue[chh])
285 // layout all childs from the first child
286 // with an own layout request to the end
287 var i=-1, changed=false;
290 chh = chc.toHashCode();
292 if (changed || vChildrenQueue[chh])
307 ---------------------------------------------------------------------------
309 ---------------------------------------------------------------------------
312 qx.Proto.layoutChild = function(vChild, vJobs)
314 this.layoutChild_sizeX_essentialWrapper(vChild, vJobs);
315 this.layoutChild_sizeY_essentialWrapper(vChild, vJobs);
317 this.layoutChild_sizeLimitX(vChild, vJobs);
318 this.layoutChild_sizeLimitY(vChild, vJobs);
320 this.layoutChild_marginX(vChild, vJobs);
321 this.layoutChild_marginY(vChild, vJobs);
323 this.layoutChild_location(vChild, vJobs);
326 if (qx.sys.Client.getInstance().isMshtml() || qx.sys.Client.getInstance().isOpera())
329 We need to respect all dimension properties on the horizontal axis in
330 internet explorer to set the 'width' style
332 qx.Proto.layoutChild_sizeX = function(vChild, vJobs)
334 if (vJobs.initial || vJobs.width || vJobs.minWidth || vJobs.maxWidth) {
335 vChild._computedWidthTypeNull && vChild._computedMinWidthTypeNull && vChild._computedMaxWidthTypeNull ? vChild._resetRuntimeWidth() : vChild._applyRuntimeWidth(vChild.getBoxWidth());
340 We need to respect all dimension properties on the vertical axis in
341 internet explorer to set the 'height' style
343 qx.Proto.layoutChild_sizeY = function(vChild, vJobs)
345 if (vJobs.initial || vJobs.height || vJobs.minHeight || vJobs.maxHeight) {
346 vChild._computedHeightTypeNull && vChild._computedMinHeightTypeNull && vChild._computedMaxHeightTypeNull ? vChild._resetRuntimeHeight() : vChild._applyRuntimeHeight(vChild.getBoxHeight());
352 qx.Proto.layoutChild_sizeX = function(vChild, vJobs)
354 if (vJobs.initial || vJobs.width) {
355 vChild._computedWidthTypeNull ? vChild._resetRuntimeWidth() : vChild._applyRuntimeWidth(vChild.getWidthValue());
359 qx.Proto.layoutChild_sizeY = function(vChild, vJobs)
361 if (vJobs.initial || vJobs.height) {
362 vChild._computedHeightTypeNull ? vChild._resetRuntimeHeight() : vChild._applyRuntimeHeight(vChild.getHeightValue());
367 qx.Proto.layoutChild_location = function(vChild, vJobs)
369 var vWidget = this.getWidget();
370 var vReverse = vWidget.getReverseChildrenOrder();
372 var vMethodBegin = vReverse ? qx.renderer.layout.FlowLayoutImpl.STR_LAST : qx.renderer.layout.FlowLayoutImpl.STR_FIRST;
373 var vMethodContinue = vReverse ? qx.renderer.layout.FlowLayoutImpl.STR_NEXT : qx.renderer.layout.FlowLayoutImpl.STR_PREVIOUS;
375 if (vChild == vWidget[vMethodBegin]())
377 vChild._cachedLocationHorizontal = vChild._cachedLocationVertical = vChild._cachedRow = 0;
381 var vTempChild = vChild[vMethodContinue]();
383 // stupidly update cache value (check them later)
384 vChild._cachedLocationHorizontal = vTempChild._cachedLocationHorizontal + vTempChild.getOuterWidth() + vWidget.getHorizontalSpacing();
385 vChild._cachedLocationVertical = vTempChild._cachedLocationVertical;
386 vChild._cachedRow = vTempChild._cachedRow;
389 if ((vChild._cachedLocationHorizontal + vChild.getOuterWidth()) > vWidget.getInnerWidth())
391 // evaluate width of previous row
392 vRowMax = vTempChild.getOuterHeight();
393 while((vTempChild = vTempChild[vMethodContinue]()) && vTempChild._cachedRow == vChild._cachedRow) {
394 vRowMax = Math.max(vRowMax, vTempChild.getOuterHeight());
398 vChild._cachedLocationHorizontal = 0;
399 vChild._cachedLocationVertical += vWidget.getVerticalSpacing() + vRowMax;
404 // add margins and parent padding
405 if (vWidget.getHorizontalChildrenAlign() == "right")
407 vChild._resetRuntimeLeft();
408 vChild._applyRuntimeRight(vWidget.getPaddingRight() + vChild._cachedLocationHorizontal);
412 vChild._resetRuntimeRight();
413 vChild._applyRuntimeLeft(vWidget.getPaddingLeft() + vChild._cachedLocationHorizontal);
416 if (vWidget.getVerticalChildrenAlign() == "bottom")
418 vChild._resetRuntimeTop();
419 vChild._applyRuntimeBottom(vWidget.getPaddingBottom() + vChild._cachedLocationVertical);
423 vChild._resetRuntimeBottom();
424 vChild._applyRuntimeTop(vWidget.getPaddingTop() + vChild._cachedLocationVertical);