// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
package org.ibex;
-// FEATURE: reflow before allowing js to read from width/height
-// FEATURE: fastpath for rows=1/cols=1
// FEATURE: mark to reflow starting with a certain child
-// FEATURE: separate mark_for_reflow and mark_for_resize
-// FEATURE: make all methods final
-// FEATURE: use a linked list for the "frontier" when packing
-// FEATURE: or else have a way to mark a column "same as last one"?
// FEATURE: reintroduce surface.abort
import java.util.*;
public void perform() throws JSExn {
if (texture == null) { Log.warn(Box.class, "perform() called with null texture"); return; }
if (texture.isLoaded) {
- setMinWidth(max(texture.width, maxwidth));
- setMinHeight(max(texture.height, maxheight));
+ setMinWidth(max(texture.width, minwidth));
+ setMinHeight(max(texture.height, minheight));
DIRTY; }
else { JS res = texture.stream; texture = null; throw new JSExn("image not found: "+res.unclone()); }
}
// Reflow ////////////////////////////////////////////////////////////////////////////////////////
+ /** should only be invoked on the root box */
+ void reflow() { pack(); resize(x, y, maxwidth, maxheight); place(); }
+
private static Box[] frontier = new Box[65535];
/** pack the boxes into rows and columns, compute contentwidth */
void pack() {
if (!test(REPACK)) { constrain(); return; }
boolean haskid = false;
for(Box child = getChild(0); child != null; child = child.nextSibling()) { haskid = true; child.pack(); }
- if (!haskid) { clear(REPACK); return; }
+ if (!haskid) { clear(REPACK); constrain(); return; }
int frontier_size = 0;
//#repeat COLS/ROWS rows/cols cols/rows col/row row/col colspan/rowspan rowspan/colspan \
// contentheight/contentwidth contentwidth/contentheight
void resize(LENGTH x, LENGTH y, LENGTH width, LENGTH height) {
if (x == this.x && y == this.y && width == this.width && height == this.height) return;
boolean sizechange = (this.width != width || this.height != height) && getTrap("SizeChange") != null;
- try {
- int thisx = parent == null ? 0 : this.x;
- int thisy = parent == null ? 0 : this.y;
- if (this.x != x || this.y != y) set(MOVED);
- if (texture == null && (text == null || text.equals("")) && !test(MOVED)) {
- if ((fillcolor & 0xff000000) != 0) {
- Box who = (parent == null ? this : parent);
- who.dirty(thisx+min(this.width,width), thisy, Math.abs(width-this.width), max(this.height, height));
- who.dirty(thisx, thisy+min(this.height,height), min(this.width, width), Math.abs(height-this.height));
- }
- //return;
+ int thisx = parent == null ? 0 : this.x;
+ int thisy = parent == null ? 0 : this.y;
+ Box who = (parent == null ? this : parent);
+ if (this.x != x || this.y != y) set(MOVED);
+ if (texture == null && (text == null || text.equals("")) && !test(MOVED)) {
+ if ((fillcolor & 0xff000000) != 0 || parent == null) {
+ who.dirty(thisx+min(this.width,width), thisy, Math.abs(width-this.width), max(this.height, height));
+ who.dirty(thisx, thisy+min(this.height,height), max(this.width, width), Math.abs(height-this.height));
}
- (parent == null ? this : parent).dirty(thisx, thisy, this.width, this.height);
this.width = width; this.height = height; this.x = x; this.y = y;
- DIRTY;
- } finally {
+ } else {
+ who.dirty(thisx, thisy, this.width, this.height);
this.width = width; this.height = height; this.x = x; this.y = y;
- if (sizechange) putAndTriggerTrapsAndCatchExceptions("SizeChange", T);
+ DIRTY;
}
+ if (sizechange) putAndTriggerTrapsAndCatchExceptions("SizeChange", T);
}
private float targetColumnSize = (float)0.0;
void solve(boolean findMinimum) {
int numkids = 0; for(Box c = firstPackedChild(); c != null; c = c.nextPackedSibling()) numkids++;
//#repeat col/row colspan/rowspan contentwidth/contentheight width/height HSHRINK/VSHRINK numregions/numregions_v \
- // maxwidth/maxheight cols/rows minwidth/minheight regions/regions_v targetColumnSize/targetRowSize sizes/sizes_v
+ // maxwidth/maxheight cols/rows minwidth/minheight regions/regions_v targetColumnSize/targetRowSize sizes/sizes_v \
+ // HSHRINK/VSHRINK
if (numkids == 0) {
if (findMinimum) contentwidth = 0;
else targetColumnSize = 0;
if (regions[r+1] < child.col) continue;
if (regions[r] >= min(child.col+child.colspan,cols)) { minregion = r; break; }
total -= sizes[r];
+ int child_maxwidth = child.test(HSHRINK)?child.contentwidth:child.maxwidth;
if (sizes[r] <= (float)(targetColumnSize*(regions[r+1]-regions[r])))
- if ((child.colspan * targetColumnSize) > (child.maxwidth + (float)0.5))
- sizes[r] = (float)Math.min(sizes[r], (regions[r+1]-regions[r])*(child.maxwidth/child.colspan));
+ if ((child.colspan * targetColumnSize) > (child_maxwidth + (float)0.5))
+ sizes[r] = (float)Math.min(sizes[r], (regions[r+1]-regions[r])*(child_maxwidth/child.colspan));
if ((child.colspan * targetColumnSize) < (child.contentwidth - (float)0.5))
sizes[r] = (float)Math.max(sizes[r], (regions[r+1]-regions[r])*(child.contentwidth/child.colspan));
total += sizes[r];
case "rows": return test(FIXED) == ROWS ? N(rows) : N(0);
case "colspan": return N(colspan);
case "rowspan": return N(rowspan);
- case "width": return N(width);
- case "height": return N(height);
+ case "width": getRoot().reflow(); return N(width);
+ case "height": getRoot().reflow(); return N(height);
case "minwidth": return N(minwidth);
case "maxwidth": return N(maxwidth);
case "minheight": return N(minheight);
public void put(Object name, Object value) throws JSExn {
if (name instanceof Number) { put(toInt(name), value); return; }
//#switch(name)
- case "text": CHECKSET_STRING(text); RECONSTRAIN(); DIRTY;
+ case "text": if (value == null) value = ""; CHECKSET_STRING(text); RECONSTRAIN(); DIRTY;
case "strokecolor": value = N(stringToColor((String)value)); CHECKSET_INT(strokecolor); DIRTY;
case "textcolor": value = N(stringToColor((String)value)); CHECKSET_INT(strokecolor); DIRTY;
case "strokewidth": CHECKSET_SHORT(strokewidth); DIRTY;