Revision: 4631 http://sourceforge.net/p/vexi/code/4631 Author: clrg Date: 2013-12-23 03:16:07 +0000 (Mon, 23 Dec 2013) Log Message: ----------- Layout fixes
Modified Paths: -------------- branches/vexi4c/org.vexi-core.main/src/main/jpp/org/vexi/ui/Box.jpp Modified: branches/vexi4c/org.vexi-core.main/src/main/jpp/org/vexi/ui/Box.jpp =================================================================== --- branches/vexi4c/org.vexi-core.main/src/main/jpp/org/vexi/ui/Box.jpp 2013-12-22 19:32:32 UTC (rev 4630) +++ branches/vexi4c/org.vexi-core.main/src/main/jpp/org/vexi/ui/Box.jpp 2013-12-23 03:16:07 UTC (rev 4631) @@ -44,7 +44,7 @@ * property on the box.</p> * * <h4>Packed Layout</h4> - * <p>In packed layout boxes are positioned next to eachother in the direction of the parents + * <p>In packed layout boxes are positioned next to each other in the direction of the parents * orient property. The parent is constrained to the combined size of the packed children in the * orient direction and to the maximum size of its children in the non-orient direction.</p> * @@ -205,17 +205,18 @@ } } - private static final Box getRoot(Box b) { return b.parent == null ? b : getRoot(b.parent); } + private final Box getRoot() { return parent == null ? this : parent.getRoot(); } - private static final int getXInParent(Box b) { Box p = b.parent; return p==null ? 0 : ((p.test(PACK) || p.test(ALIGN_LEFT)) ? b.x : b.x+((p.width-b.width)/(p.test(ALIGN_RIGHT)?1:2))); } - private static final int getYInParent(Box b) { Box p = b.parent; return p==null ? 0 : ((p.test(PACK) || p.test(ALIGN_TOP)) ? b.y : b.y+((p.height-b.height)/(p.test(ALIGN_BOTTOM)?1:2))); } - private static final int globalToLocalX(Box b, int x) { return b.parent==null ? x : globalToLocalX(b.parent, x - getXInParent(b)); } - private static final int globalToLocalY(Box b, int y) { return b.parent==null ? y : globalToLocalY(b.parent, y - getYInParent(b)); } - private static final int localToGlobalX(Box b, int x) { return b.parent==null ? x : localToGlobalX(b.parent, x + getXInParent(b)); } - private static final int localToGlobalY(Box b, int y) { return b.parent==null ? y : localToGlobalY(b.parent, y + getYInParent(b)); } + private final int getXInParent() { return parent==null ? 0 : ((parent.test(PACK) || parent.test(ALIGN_LEFT)) ? x : x+((parent.width-width)/(parent.test(ALIGN_RIGHT)?1:2))); } + private final int getYInParent() { return parent==null ? 0 : ((parent.test(PACK) || parent.test(ALIGN_TOP)) ? y : y+((parent.height-height)/(parent.test(ALIGN_BOTTOM)?1:2))); } + private final int globalToLocalX(int x) { return parent==null ? x : parent.globalToLocalX(x - getXInParent()); } + private final int globalToLocalY(int y) { return parent==null ? y : parent.globalToLocalY(y - getYInParent()); } + private final int localToGlobalX(int x) { return parent==null ? x : parent.localToGlobalX(x + getXInParent()); } + private final int localToGlobalY(int y) { return parent==null ? y : parent.localToGlobalY(y + getYInParent()); } - // useful debugging reflow problems - //private static final int depth(Box b) { return b.parent==null ? 0 : depth(b.parent)+1; } + // useful debugging + //private final int depth() { return parent==null ? 0 : parent.depth()+1; } + private final String name() { try { return get(JSU.S("name")).toString(); } catch (JSExn e) { throw new Error(); } } private static final int min(int a, int b) { return (a<b) ? a : b; } private static final int max(int a, int b) { return (a>b) ? a : b; } @@ -223,7 +224,6 @@ private final boolean inside(int x, int y) { return test(DISPLAY) && x >= 0 && y >= 0 && x < width && y < height; } // TRAPFLAGS helper functions - private final void setclear(short mask, boolean set) { if (set) set(mask); else clear(mask); } private final void set(short mask) { trapflags |= mask; } private final void clear(short mask) { trapflags &= ~mask; } private final boolean test(short mask) { return ((trapflags & mask) == mask); } @@ -235,7 +235,7 @@ private final boolean test(int mask) { return ((flags & mask) == mask); } public final int getIntFillcolor() { return visual.fillcolor; } - public final Surface getSurface() { return Surface.fromBox(getRoot(this)); } + public final Surface getSurface() { return Surface.fromBox(getRoot()); } /** for Surface to set the x/y properties of the root box */ public final void setRootPosition(int x, int y) throws JSExn { @@ -374,6 +374,10 @@ protected int contentheight = 0; private Insets margin = Insets.ZERO; private Insets padding = Insets.ZERO; + + // this is a calculated total of the gaps between packed children + // TODO: put into a place() loop or another alternative mechanism + private int box_spacing = 0; // Instance Methods ///////////////////////////////////////////////////////////////////// @@ -419,8 +423,8 @@ return; } // go again relative to parent - x += getXInParent(cur); - y += getYInParent(cur); + x += cur.getXInParent(); + y += cur.getYInParent(); } } @@ -620,7 +624,7 @@ // clear first, because it is possible // that reflow may lead to more reflow clear(CONSTRAIN_DESCENDENT); - // reconstrain any children + // re-constrain any children for (Box c = getChild(i=0); c != null; c = getChild(++i)) { if (!c.test(DISPLAY)) { continue; @@ -635,7 +639,7 @@ justTriggerTrapsAndCatchExceptions(SC_Resize, JSU.T); } - // no reconstrain necessary + // no re-constrain necessary if (!test(CONSTRAIN)) { return; } @@ -647,11 +651,14 @@ if (test(ORIENT) == HORIZONTAL) { // accumulate child contentwidth int prior_margin = 0; + box_spacing = 0; for (Box c = getChild(i=0); c != null; c = getChild(++i)) { if (!c.test(DISPLAY)) { continue; } - new_contentwidth += c.nominalWidth() + max(prior_margin, c.margin.left); + int spacing = max(prior_margin, c.margin.left); + box_spacing += spacing; + new_contentwidth += c.nominalWidth() + spacing; prior_margin = c.margin.right; } new_contentwidth += prior_margin; @@ -722,7 +729,7 @@ set(PLACE_CLEAN); } - //#repeat Width/Height getTargetX/getTargetY x/y width/height left/top right/bottom + //#repeat HSHRINK/VSHRINK Width/Height getTargetX/getTargetY x/y tx/ty width/height left/top right/bottom private final int getTargetWidth(final int availableWidth) { return test(HSHRINK) ? nominalWidth() : max(contentwidth, min(maxwidth, availableWidth - x - margin.left - margin.right)); @@ -768,7 +775,7 @@ if (test(ORIENT) == HORIZONTAL) { // horizontal stacking if (contentwidth >= width) { - // simple case - no slack, place children next to eachother + // simple case - no slack, place children next to each other int i = 0; int prior_margin = padding.left; for (Box child = getChild(i=0); child != null; child = getChild(++i)) { @@ -791,7 +798,7 @@ // our layout lies somewhere between the min and max size, // loop over the children attempting to set their width to // targetsize and adjust until it meets the parent width - float targetsize = (float)width/(float)treeSize(); + float targetsize = (float)(width - box_spacing) / (float)treeSize(); float totalsize = 0; for (int j=0; j<100; j++) { totalsize = 0; @@ -802,7 +809,6 @@ int num_maxsize = 0; int num_nolimit = 0; int num_passive = 0; - int prior_margin = padding.left; int i = 0; for (Box child = getChild(i=0); child != null; child = getChild(++i)) { if (!child.test(DISPLAY)) { @@ -812,9 +818,9 @@ num_active++; if (child.test(HSHRINK) || child.maxwidth==child_nomwidth) { num_passive++; - totalsize += child.contentwidth; + totalsize += child_nomwidth; } else if (child_nomwidth>targetsize) { - min_minsize = min(min_minsize, child.contentwidth); + min_minsize = min(min_minsize, child_nomwidth); num_minsize++; totalsize += (float)child_nomwidth; } else if (child.maxwidth<targetsize) { @@ -825,10 +831,7 @@ num_nolimit++; totalsize += targetsize; } - totalsize += (float)max(prior_margin, child.margin.left); - prior_margin = child.margin.right; } - totalsize += (float)max(prior_margin, padding.right); if (num_active==0) { // no active children - nothing to do @@ -836,25 +839,25 @@ } // test to see if targetsize produces a solution that rounds - // to match the width, adjusting appropriatly if it does not + // to match the width, adjusting appropriately if it does not int totalsize_int = (int)(totalsize+0.5); - if (totalsize_int > width) { + if (totalsize_int - box_spacing > width) { if (num_nolimit>0) { targetsize -= (totalsize-(float)width)/(float)num_nolimit; } else { if (num_minsize+num_passive==num_active) { - // no solution required - avaiable min-sizes over-consume width + // no solution required - available min-sizes over-consume width targetsize = width; break; } targetsize = (float)max_maxsize - (totalsize-(float)width)/(float)num_maxsize; } - } else if (totalsize_int < width) { + } else if (totalsize_int - box_spacing < width) { if (num_nolimit>0) { targetsize += ((float)width-totalsize)/(float)num_nolimit; } else { if (num_maxsize+num_passive==num_active) { - // no solution required - avaiable max-sizes do not consume width + // no solution required - available max-sizes do not consume width targetsize = width; break; } @@ -880,7 +883,7 @@ // if there is 'slack' (child boxes do not consume parent width) then // align determines whether we pack boxes to left, centre, or right - int offset_x = (int)(totalsize+0.5)>=width || left ? 0 : (int)(((float)width-totalsize)/(float)(right?1:2)); + int offset_x = left ? 0 : (int)(((float)width-totalsize)/(float)(right?1:2)); // we use total (a float) to keep tabs on final layout totals // so we do not get stray pixel sized gaps caused by rounding @@ -920,7 +923,7 @@ if (0 >= height - contentheight) { // simple case - no slack int i = 0; - int prior_margin = padding.left; + int prior_margin = padding.top; for (Box child = getChild(i=0); child != null; child = getChild(++i)) { if (!child.test(DISPLAY)) { continue; @@ -929,8 +932,11 @@ child_width = child.getTargetWidth(width); child_x = child.getTargetX(width, child_width, left, right); // height, y - child.tryMoveAndResize(child_x, child_y, child_width, child.contentheight, clean); + child_height = child.nominalHeight(); + child_y += max(prior_margin, child.margin.top); + child.tryMoveAndResize(child_x, child_y, child_width, child_height, clean); child_y += child.contentheight; + prior_margin = child.margin.bottom; } } else { @@ -938,7 +944,7 @@ // our layout lies somewhere between the min and max size, // loop over the children attempting to set their width to // targetsize and adjust until it meets the parent width - float targetsize = (float)height/(float)treeSize(); + float targetsize = (float)(height - box_spacing) / (float)treeSize(); float totalsize = 0; for (int j=0; j<100; j++) { totalsize = 0; @@ -949,20 +955,20 @@ int num_maxsize = 0; int num_nolimit = 0; int num_passive = 0; - int prior_margin = padding.left; int i = 0; for (Box child = getChild(i=0); child != null; child = getChild(++i)) { if (!child.test(DISPLAY)) { continue; } + final int child_nomheight = child.nominalHeight(); num_active++; - if (child.test(VSHRINK) || child.maxheight==child.contentheight) { + if (child.test(VSHRINK) || child.maxheight==child_nomheight) { num_passive++; - totalsize += child.contentheight; - } else if (child.contentheight>targetsize) { - min_minsize = min(min_minsize, child.contentheight); + totalsize += child_nomheight; + } else if (child_nomheight>targetsize) { + min_minsize = min(min_minsize, child_nomheight); num_minsize++; - totalsize += (float)child.contentheight; + totalsize += (float)child_nomheight; } else if (child.maxheight<targetsize) { max_maxsize = max(max_maxsize, child.maxheight); num_maxsize++; @@ -979,25 +985,25 @@ } // test to see if targetsize produces a solution that rounds - // to match the height, adjusting appropriatly if it does not + // to match the height, adjusting appropriately if it does not int totalsize_int = (int)(totalsize+0.5); - if (totalsize_int > height) { + if (totalsize_int - box_spacing > height) { if (num_nolimit>0) { targetsize -= (totalsize-(float)height)/(float)num_nolimit; } else { if (num_minsize+num_passive==num_active) { - // no solution required - avaiable min-sizes over-consume height + // no solution required - available min-sizes over-consume height targetsize = height; break; } targetsize = (float)max_maxsize - (totalsize-(float)height)/(float)num_maxsize; } - } else if (totalsize_int < height) { + } else if (totalsize_int - box_spacing < height) { if (num_nolimit>0) { targetsize += ((float)height-totalsize)/(float)num_nolimit; } else { if (num_maxsize+num_passive==num_active) { - // no solution required - avaiable max-sizes do not consume height + // no solution required - available max-sizes do not consume height targetsize = height; break; } @@ -1023,12 +1029,12 @@ // if there is 'slack' (child boxes do not consume parent width) then // align determines whether we pack boxes to left, centre, or right - int offset_y = (int)(totalsize+0.5)>=height || top ? 0 : (int)(((float)height-totalsize)/(float)(bottom?1:2)); + int offset_y = top ? 0 : (int)(((float)height-totalsize)/(float)(bottom?1:2)); // we use total (a float) to keep tabs on final layout totals // so we do not get stray pixel sized gaps caused by rounding totalsize = 0; - int prior_margin = padding.left; + int prior_margin = padding.top; int i = 0; for (Box child = getChild(i); child != null; child = getChild(++i)) { if (!child.test(DISPLAY)) { @@ -1038,6 +1044,7 @@ child_width = child.getTargetWidth(width); child_x = child.getTargetX(width, child_width, left, right); // height, y + totalsize += (float)max(prior_margin, child.margin.left); child_y = offset_y + (int)(totalsize+0.5); if (child.test(VSHRINK) || child.contentheight > targetsize) { child_height = child.contentheight; @@ -1051,6 +1058,7 @@ totalsize += targetsize; } child.tryMoveAndResize(child_x, child_y, child_width, child_height, clean); + prior_margin = child.margin.right; } } } @@ -1063,8 +1071,8 @@ /** renders self and children within the specified region; all rendering operations are clipped to xIn,yIn,wIn,hIn */ public void render(int parentx, int parenty, int cx1, int cy1, int cx2, int cy2, PixelBuffer buf) { - int globalx = parentx + getXInParent(this); - int globaly = parenty + getYInParent(this); + int globalx = parentx + getXInParent(); + int globaly = parenty + getYInParent(); // intersect the x,y,w,h rendering window with ourselves; quit if it's empty cx1 = max(cx1, globalx); @@ -1438,8 +1446,8 @@ b.propagateLeave(); continue; } - int b_mx = mousex-getXInParent(b); - int b_my = mousey-getYInParent(b); + int b_mx = mousex-b.getXInParent(); + int b_my = mousey-b.getYInParent(); if (b.inside(b_mx, b_my)) { if (b.propagateMove(b_mx, b_my)) { interrupted = true; @@ -1459,8 +1467,8 @@ b.propagateLeave(); continue; } - int b_mx = mousex-getXInParent(b); - int b_my = mousey-getYInParent(b); + int b_mx = mousex-b.getXInParent(); + int b_my = mousey-b.getYInParent(); if (b.inside(b_mx, b_my)) { packedhit = true; if (b.propagateMove(b_mx, b_my)) { @@ -1548,8 +1556,8 @@ if (!test(PACK)) { // absolute layout - check all children for (Box b = getChild(i=treeSize()-1); b != null; b = getChild(--i)) { - int b_mx = mousex-getXInParent(b); - int b_my = mousey-getYInParent(b); + int b_mx = mousex-b.getXInParent(); + int b_my = mousey-b.getYInParent(); if (b.inside(b_mx, b_my)) { if (b.propagateEvent(event, _event, value, b_mx, b_my)) { return true; @@ -1593,6 +1601,7 @@ /** the mouse object of a box */ private class Mouse extends JS.Immutable implements JS.Cloneable { + @SuppressWarnings("unused") public JS get(JS key) throws JSExn { //#switch (JSU.toString(key)) /*@PAGE(varname=mouse,humanname=Mouse Object) @@ -1623,10 +1632,10 @@ * @group(y) */ case "x": Surface s = getSurface(); - return JSU.N(globalToLocalX(Box.this, s==null ? 0 : getSurface().getMouseX())); + return JSU.N(Box.this.globalToLocalX(s==null ? 0 : getSurface().getMouseX())); case "y": Surface s = getSurface(); - return JSU.N(globalToLocalY(Box.this, s==null ? 0 : getSurface().getMouseY())); + return JSU.N(Box.this.globalToLocalY(s==null ? 0 : getSurface().getMouseY())); //#end return super.get(key); } @@ -1638,6 +1647,7 @@ private Box from; private Box to; DistanceTo(Box from, Box to) { this.from = from; this.to = to; } + @SuppressWarnings("unused") public JS get(JS key) throws JSExn { //#switch (JSU.toString(key)) /*@PAGE(varname=distanceto,humanname=DistanceTo Object) @@ -1665,11 +1675,12 @@ * * @group(y) * @type(Number) */ - case "x": return JSU.N(localToGlobalX(to, 0) - localToGlobalX(from, 0)); - case "y": return JSU.N(localToGlobalY(to, 0) - localToGlobalY(from, 0)); + case "x": return JSU.N(to.localToGlobalX(0) - from.localToGlobalX(0)); + case "y": return JSU.N(to.localToGlobalY(0) - from.localToGlobalY(0)); //#end return super.get(key); } + @SuppressWarnings("unused") public void put(JS key, JS value) throws JSExn { try { //#switch (JSU.toString(key)) @@ -1689,7 +1700,7 @@ public Box toImage(int x, int y, int w, int h) { PixelBuffer pb = Platform.createPixelBuffer(w, h, null); // FIXME: hack - // this bizzare bit of parent manipulation is to get around + // this bizarre bit of parent manipulation is to get around // the 'getX/YInParent()' look ups in render() for this box Box p = parent; parent = null; @@ -1704,6 +1715,7 @@ } /** implements functions that can be invoked on a box in JS */ + @SuppressWarnings("unused") public JS callMethod(JS this_, JS method, JS[] args) throws JSExn { try { switch (args.length) { @@ -1829,6 +1841,7 @@ } /** implements reading from box properties in JS */ + @SuppressWarnings("unused") public JS get(JS name) throws JSExn { // integer properties translate to box children if (JSU.isInt(name)) { @@ -2496,6 +2509,7 @@ } /** implements the writing of box properties from JS */ + @SuppressWarnings("unused") public void put(JS name, JS value) throws JSExn { // integer properties translate to box children if (JSU.isInt(name)) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Rapidly troubleshoot problems before they affect your business. Most IT organizations don't have a clear picture of how application performance affects their revenue. With AppDynamics, you get 100% visibility into your Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro! http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk _______________________________________________ Vexi-svn mailing list Vexi-svn@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vexi-svn