Wow,
Chris, this is really cool.
I have now 0.7 code, but very early I will be porting it and I really
need flow layout. So very thank for your work!
Cheers
- Petr
2008/8/24 Chris Banford <[EMAIL PROTECTED]>:
>
> 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
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>
>
-------------------------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel