Flow now respects each Child's alignY setting. :-)
Not sure if __rebuildCache() would apply or not to Flow.
I'm going to take a break from trying to put any more functionality into
this, as I'd rather get feedback from the devs on this, as how it could
be improved and/or cleaned up, before I go making it more convoluted.
Might also be cool to get this into the SVN contrib as a next step?
Here's a simple use case again for anyone who's curious:
-----------------------------------------------------------------
/*
-------------------------------------------------------------------------
Below is your actual application code...
-------------------------------------------------------------------------
*/
var container = new qx.ui.container.Composite( new
qx.ui.layout.Flow(0, "center") );
var button1 = new qx.ui.form.Button("First Button is long!
Overflow should ¬
stay centered (and a wee bit of margin too...)",
"custom/test.png");
button1.setMargin(3);
button1.setAlignY("middle");
container.add(button1);
... Add more buttons here to see Flow in action!..
this.getRoot().add(container, {edge: 0});
-----------------------------------------------------------------
The first parameter to Flow is for eventual Child spacing, but I haven't
implemented that yet. I've also placed the Flow.js file in with the
other qooxdoo ui.layout files...
Hope this Flow class can be of use someday. Our current YUI-based tools
implement an Image Library, so we'd need to be able to build a 'flowing'
thumbnail container. This Flow would work for that already -- kinda cool
that qooxdoo is so usable that I could get a crude version of such a
layout object working in just a couple of days from scratch.
Its a glorious day here, at the foot of the Matterhorn, and I'm off for
a fantastic, long bike ride through the Swiss alps! (
http://bergbahnen.zermatt.ch/e/web-cam/ )
Have a great day!
-Chris
Like so until monday we're going to have a FlowLayout 1.0 full :)
2008/8/23 Chris Banford <[EMAIL PROTECTED]>
Me again,
I've managed to get a working implementation of a flow layout that
now handles
alignX : ["left". "center", "right"] and to boot it respects
margins. Turned out to be a tricky little bugger.
It also keeps it in grip if the elements are wider than the
available space.
Need to start to figure out what is up with Gaps and Spacers.
AlignY shouldn't too bad to get working as well.
-Chris
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
http://www.dihedrals.com
Copyright:
2008 Dihedrals.com
License:
LGPL: http://www.gnu.org/licenses/lgpl.html
EPL: http://www.eclipse.org/org/documents/epl-v10.php
See the LICENSE file in the project's top-level directory for details.
Authors:
* Chris Banford [chris at dihedrals dot com]
* Borrowed liberally from Basic.js and HBox.js
************************************************************************ */
/**
* A basic layout, which supports positioning of child widgets in a 'flowing'
* manner, starting at the container's top/left position, placing children left
to right
* (like a HBox) until the there's no remaining room for the next child. When
* out of room on the current line of elements, a new line is started, cleared
* below the tallest child of the preceeding line -- a bit like using 'float'
* in CSS, except that a new line wraps all the way back to the left.
*
* *Example*
*
* Here is a little example of how to use the grid layout.
*
* <pre class="javascript">
* var flow = new qx.ui.layout.Flow("center") // defaults to
"left"
*
* var container = new qx.ui.container.Composite( new qx.ui.layout.Flow( flow )
);
*
* var button1 = new qx.ui.form.Button("First Button is long! Overflow should
stay centered (and a wee bit of margin too...)", "custom/test.png");
* button1.setMargin(3);
* container.add(button1);
*
* var button2 = new qx.ui.form.Button("2. Button", "custom/test.png");
* container.add(button2);
*
* var button3 = new qx.ui.form.Button("3rd TALL & really, really, really long
Button", "custom/test.png");
* button3.setHeight(100); // tall button
* container.add(button3);
*
* var button4 = new qx.ui.form.Button("Number 4", "custom/test.png");
* container.add(button4);
*
* this.getRoot().add(container, {edge: 0});
*
* </pre>
*
* *External Documentation*
*
*/
qx.Class.define("qx.ui.layout.Flow",
{
extend : qx.ui.layout.Abstract,
/*
*****************************************************************************
CONSTRUCTOR
*****************************************************************************
*/
/**
* @param spacing {Integer?0} The spacing between child widgets [EMAIL
PROTECTED] #spacing}.
* @param alignX {String?"left"} Horizontal alignment of the whole children
* block [EMAIL PROTECTED] #alignX}.
*/
construct : function(spacing, alignX)
{
this.base(arguments);
if (spacing) {
this.setSpacing(spacing);
}
if (alignX) {
this.setAlignX(alignX);
}
},
/*
*****************************************************************************
PROPERTIES
*****************************************************************************
*/
properties :
{
/**
* Horizontal alignment of the whole children block. The horizontal
* alignment of the child is completely ignored in HBoxes (
* [EMAIL PROTECTED] qx.ui.core.LayoutItem#alignX}).
*/
alignX :
{
check : [ "left", "center", "right" ],
init : "left",
apply : "_applyLayoutChange"
},
/**
* Vertical alignment of each child. Can be overridden through
* [EMAIL PROTECTED] qx.ui.core.LayoutItem#alignY}.
*/
alignY :
{
check : [ "top", "middle", "bottom", "baseline" ],
init : "top",
apply : "_applyLayoutChange"
},
/** Horizontal spacing between two children */
spacing :
{
check : "Integer",
init : 0,
apply : "_applyLayoutChange"
}
},
/*
*****************************************************************************
MEMBERS
*****************************************************************************
*/
members :
{
__currLinesTotalChildWidth : 0,
__currLinesTallestChild : 0,
/*
---------------------------------------------------------------------------
LAYOUT INTERFACE
---------------------------------------------------------------------------
*/
// overridden
verifyLayoutProperty : qx.core.Variant.select("qx.debug",
{
"on" : function(item, name, value)
{
this.assert( false, "The property '"+name+"' is not supported
by the flow layout!" );
},
"off" : null
}),
//-------------------------------------------------------------------
// overridden
renderLayout : function( availWidth, availHeight )
{
var util = qx.ui.layout.Util;
var children = this._getLayoutChildren();
var child, size, left, top, childW;
var marginL, marginR, marginT, marginB;
var linesChildrenIndexes =[];
var newLineFlag = false;
var lineLeft = 0, lineTop = 0;
var tallestChildInLine = 0;
// Compute gaps
var spacing = this.getSpacing();
//var separator = this.getSeparator();
//if (separator) {
// var gaps =
util.computeHorizontalSeparatorGaps(children, spacing, separator);
//} else {
//var gaps = util.computeHorizontalGaps(children, spacing,
true);
//}
this.info( " >> Layout spacing: " + spacing );
// Flow Render children
//if ( qx.core.Variant.get("qx.debug") == "on" ){ this.info(
"*** Render Start ***" ); }
var lineCounter = 0;
var currChildIndex = 0
while ( currChildIndex < children.length )
{
lineCounter++;
tallestChildInLine = 0;
linesChildrenIndexes =
this._getIndexesOfChildrenOnALine(children, currChildIndex, availWidth);
/*
// Debug msgs
if ( qx.core.Variant.get("qx.debug") == "on" ){
if ( linesChildrenIndexes.length > 0 ) {
this.info( "Line #"+ (lineCounter) +"
is "+this.getAlignX()+" aligned and has " + linesChildrenIndexes.length + "x
children" );
} else {
this.info( "Line #"+ (lineCounter) +"
is "+this.getAlignX()+" aligned and has 1 child" );
}
}
*/
// Alignment X support
var thisLineCurrLeft = 0;
// AlignX -> "left"
if (this.getAlignX() != "left") {
thisLineCurrLeft = availWidth -
this.__currLinesTotalChildWidth; // AlignX -> "right"
if (this.getAlignX() == "center") {
thisLineCurrLeft =
Math.round(thisLineCurrLeft / 2); // AlignX -> "center"
}
// reverse this Line's children, so the Flow
starts from the
// right edge of the container, with the proper
child order (I think)
if (this.getAlignX() == "right") {
linesChildrenIndexes =
linesChildrenIndexes.concat().reverse();
}
}
// If there are multiple children that have place on
this Line,
// then loop through them and render each one after
calculating
// the correct left starting position due to alignX.
var thisLineNr;
var len = linesChildrenIndexes.length;
for ( var x=0; x<len; x++ ) {
thisLineNr = linesChildrenIndexes[x];
child = children[thisLineNr];
//this.info( " >> Render child: " +
child.getLabel() );
size = child.getSizeHint();
// Keep track of the tallest child on this Line.
marginT = child.getMarginTop();
marginB = child.getMarginBottom();
if ( (marginT + size.height + marginB) >
tallestChildInLine ) {
tallestChildInLine = (marginT +
size.height + marginB);
}
marginL = child.getMarginLeft();
marginR = child.getMarginRight();
// Respect vertical alignment - alignY
top =
util.computeVerticalAlignOffset(child.getAlignY()||this.getAlignY(), (marginT +
size.height + marginB), this.__currLinesTallestChild, marginT, marginB);
child.renderLayout( (thisLineCurrLeft +
marginL), (lineTop + top), size.width, size.height);
thisLineCurrLeft += (marginL + size.width +
marginR);
currChildIndex++;
}
// Single child on Line
// If this line contain's a single element that is
wider than then
// available space, then it still needs to be rendered
to this Line,
// and the line counter increased to the next line
(otherwise any
// element wider than availWidth wouldn't be shown...)
// AlignX will have special meaning here! Will prob
mean negative left pos...
if ( len < 1 ) {
child = children[currChildIndex];
//this.info( " >> Render child wider than
window on its own line: " + child.getLabel() );
size = child.getSizeHint();
// Only a single child on this line, so its
automatically the tallest.
marginT = child.getMarginTop();
marginB = child.getMarginBottom();
tallestChildInLine = (marginT + size.height +
marginB);
marginL = child.getMarginLeft();
marginR = child.getMarginRight();
// Adjust this single, possibly overflowing
child for alignX.
if ( (marginL + size.width + marginR) >
availWidth ) {
// Child is overflowing.
if (this.getAlignX() == "center") {
var centeredLeft =
Math.round((availWidth - (marginL + size.width + marginR)) / 2)
//this.info( ">> Single
centered overflow: " + centeredLeft );
thisLineCurrLeft =
centeredLeft; // AlignX -> "center"
}
if (this.getAlignX() == "right") {
var rightLeft =
Math.round(availWidth - (marginL + size.width + marginR))
//this.info( ">> Single
centered overflow: " + centeredLeft );
thisLineCurrLeft = rightLeft;
// AlignX -> "right"
}
}
// alignY -> When a single child is displayed
alone on a line,
// there is no alignY applied, as this child's
hieght is the Line's height.
child.renderLayout( (thisLineCurrLeft +
marginL), (lineTop + marginT), size.width, size.height);
currChildIndex++;
}
// update the next line's top starting point.
lineTop += tallestChildInLine;
}
},
//-------------------------------------------------------------------
// Take a list of children and a starting index and see how
// many of the buggers will fit on a line of availWidth space.
_getIndexesOfChildrenOnALine : function(children, startIndex,
availWidth)
{
var childIndexList = [];
var child, size, childW;
var marginL, marginR, marginT, marginB;
var currLeft = 0;
var tallestChildInLine = 0;
for ( var i=startIndex, l=children.length; i<l; i++ )
{
// Add children indexes, until their accumulated widths
// won't fit on a single line anymore.
child = children[i];
size = child.getSizeHint();
marginL = child.getMarginLeft();
marginR = child.getMarginRight();
marginT = child.getMarginTop();
marginB = child.getMarginBottom();
childW = marginL + size.width + marginR;
if ( currLeft + childW > availWidth ) {
// Don't save this child and return this lines
list of Child index numbers.
break;
}
// Calc Tallest child on line.
if ( (marginT + size.height + marginB) >
tallestChildInLine ) {
tallestChildInLine = (marginT + size.height +
marginB);
}
childIndexList.push(i);
currLeft += childW;
}
// keep track of the total width of all this line's children, so
// renderLayout() can calculate the starting left position of
the first child,
// so that alignX works.
this.__currLinesTotalChildWidth = currLeft;
// Same for alignY
this.__currLinesTallestChild = tallestChildInLine;
return childIndexList;
},
// overridden
// Don't need hints for a Flow box (I think)
// Sebastian's tip is to return null, but that's yakking, so returning
0 instead.
_computeSizeHint : function()
{
return {
width : 0,
height : 0
};
}
}
});
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
qooxdoo-devel mailing list
qooxdoo-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel