private short col = 0;
public LENGTH x = 0;
public LENGTH y = 0;
+ public LENGTH ax = 0; // FEATURE: roll these into x/y; requires lots of changes
+ public LENGTH ay = 0; // FEATURE: roll these into x/y; requires lots of changes; perhaps y()?
public LENGTH width = 0;
public LENGTH height = 0;
private LENGTH contentwidth = 0; // == max(minwidth, textwidth, sum(child.contentwidth))
// as external events have occured, check the state of box
if (texture != null) {
if (texture.isLoaded) { minwidth = min(texture.width, maxwidth); minheight = min(texture.height, maxheight); }
- else { JS res = texture.stream; texture = null; throw new JSExn("image not found: "+res); }
+ else { JS res = texture.stream; texture = null; throw new JSExn("image not found: "+res.unclone()); }
+ } else {
+ Log.warn(Box.class, "perform() called with null texture");
}
-
MARK_REPACK;
MARK_REFLOW;
MARK_RESIZE;
private static LENGTH[] colMaxWidth = new LENGTH[65535];
private static LENGTH[] rowHeight = new LENGTH[65535];
private static LENGTH[] rowMaxHeight = new LENGTH[65535];
- static { for(int i=0; i<rowMaxHeight.length; i++) { rowMaxHeight[i] = MAX_LENGTH; colMaxWidth[i] = MAX_LENGTH; } }
+ static { for(int i=0; i<rowMaxHeight.length; i++) { rowMaxHeight[i] = 0; colMaxWidth[i] = 0; } }
Box nextPackedSibling() { Box b = nextSibling(); return b == null || (b.test(PACKED | VISIBLE)) ? b : b.nextPackedSibling(); }
Box firstPackedChild() { Box b = getChild(0); return b == null || (b.test(PACKED | VISIBLE)) ? b : b.nextPackedSibling(); }
x_slack += colWidth[i];
colWidth[i] = max(colWidth[i], child.contentwidth / child.colspan);
x_slack -= colWidth[i];
- colMaxWidth[i] = min(colMaxWidth[i], child.test(HSHRINK) ? child.contentwidth : child.maxwidth) / child.colspan;
+ colMaxWidth[i] = max(colMaxWidth[i], (child.test(HSHRINK) ? child.contentwidth : child.maxwidth) / child.colspan);
}
// PHASE 2: hand out slack
if (!child.test(VISIBLE)) continue;
int child_width, child_height, child_x, child_y;
if (!child.test(PACKED)) {
- child_x = child.x;
- child_y = child.y;
- child_width = child.test(HSHRINK) ? child.contentwidth : min(child.maxwidth, width - child_x);
- child_height = child.test(VSHRINK) ? child.contentheight : min(child.maxheight, height - child_y);
+ child_width = child.test(HSHRINK) ? child.contentwidth : min(child.maxwidth, width - Math.abs(child.ax));
+ child_height = child.test(VSHRINK) ? child.contentheight : min(child.maxheight, height - Math.abs(child.ay));
child_width = max(child.minwidth, child_width);
child_height = max(child.minheight, child_height);
+ int gap_x = width - child_width;
+ int gap_y = height - child_height;
+ child_x = child.ax + (child.test(ALIGN_RIGHT) ? gap_x : !child.test(ALIGN_LEFT) ? gap_x / 2 : 0);
+ child_y = child.ay + (child.test(ALIGN_BOTTOM) ? gap_y : !child.test(ALIGN_TOP) ? gap_y / 2 : 0);
} else {
int unbounded;
//#repeat col/row colspan/rowspan contentwidth/contentheight width/height colMaxWidth/rowMaxHeight \
}
// cleanup
- for(int i=0; i<cols; i++) { colWidth[i] = 0; colMaxWidth[i] = MAX_LENGTH; }
- for(int i=0; i<rows; i++) { rowHeight[i] = 0; rowMaxHeight[i] = MAX_LENGTH; }
+ for(int i=0; i<cols; i++) { colWidth[i] = 0; colMaxWidth[i] = 0; }
+ for(int i=0; i<rows; i++) { rowHeight[i] = 0; rowMaxHeight[i] = 0; }
for(Box child = getChild(0); child != null; child = child.nextSibling())
if (test(VISIBLE))
int globaly = parenty + (parent == null ? 0 : y);
// intersect the x,y,w,h rendering window with ourselves; quit if it's empty
-
if (test(CLIP)) {
- cx1 = max(cx1, parent == null ? 0 : globalx);
- cy1 = max(cy1, parent == null ? 0 : globaly);
+ cx1 = max(cx1, globalx);
+ cy1 = max(cy1, globaly);
cx2 = min(cx2, globalx + width);
cy2 = min(cy2, globaly + height);
if (cx2 <= cx1 || cy2 <= cy1) return;
for(int x = globalx; x < cx2; x += texture.width)
for(int y = globaly; y < cy2; y += texture.height)
buf.drawPicture(texture, x, y, cx1, cy1, cx2, cy2);
-
- if (text != null && !text.equals("") && font != null)
- if (font.rasterizeGlyphs(text, buf, strokecolor, globalx, globaly, cx1, cy1, cx2, cy2, null) == -1)
- font.rasterizeGlyphs(text, buf, strokecolor, globalx, globaly, cx1, cy1, cx2, cy2, this);
+
+ if (text != null && !text.equals("") && font != null) {
+ int gap_x = width - font.textwidth(text);
+ int gap_y = height - font.textheight(text);
+ int text_x = globalx + (test(ALIGN_RIGHT) ? gap_x : !test(ALIGN_LEFT) ? gap_x/2 : 0);
+ int text_y = globaly + (test(ALIGN_BOTTOM) ? gap_y : !test(ALIGN_TOP) ? gap_y/2 : 0);
+ if (font.rasterizeGlyphs(text, buf, strokecolor, text_x, text_y, cx1, cy1, cx2, cy2, null) == -1)
+ font.rasterizeGlyphs(text, buf, strokecolor, text_x, text_y, cx1, cy1, cx2, cy2, this);
+ }
for(Box b = getChild(0); b != null; b = b.nextSibling())
b.render(globalx, globaly, cx1, cy1, cx2, cy2, buf, null);
case "Minimized": if (parent == null && getSurface() != null) getSurface().minimized = toBoolean(value); // FEATURE
case "Maximized": if (parent == null && getSurface() != null) getSurface().maximized = toBoolean(value); // FEATURE
case "Close": if (parent == null && getSurface() != null) getSurface().dispose(true);
- case "redirect": if (redirect == this) redirect = (Box)value; else Log.info(this, "redirect can only be set once");
+ case "redirect":
+ for(Box cur = (Box)value; cur != null; cur = cur.parent)
+ if (cur == redirect) {
+ redirect = (Box)value;
+ return;
+ }
+ JS.error("redirect can only be set to a descendant of its current value");
case "font":
if(!(value instanceof Stream)) throw new JSExn("You can only put streams to the font property");
font = value == null ? null : Font.getFont((Stream)value, font == null ? 10 : font.pointsize);
MARK_RESIZE;
dirty();
case "fontsize": font = Font.getFont(font == null ? null : font.stream, toInt(value)); MARK_RESIZE; dirty();
- case "x": if (parent==null && Surface.fromBox(this)!=null) { CHECKSET_INT(x); } else { if (test(PACKED) && parent != null) return; dirty(); CHECKSET_INT(x); dirty(); MARK_RESIZE; dirty(); }
- case "y": if (parent==null && Surface.fromBox(this)!=null) { CHECKSET_INT(y); } else { if (test(PACKED) && parent != null) return; dirty(); CHECKSET_INT(y); dirty(); MARK_RESIZE; dirty(); }
+ case "x": if (parent==null && Surface.fromBox(this)!=null) {
+ CHECKSET_INT(x);
+ } else {
+ if (test(PACKED) && parent != null) return;
+ dirty(); CHECKSET_INT(ax);
+ dirty(); MARK_RESIZE;
+ dirty();
+ }
+ case "y": if (parent==null && Surface.fromBox(this)!=null) {
+ CHECKSET_INT(y);
+ } else {
+ if (test(PACKED) && parent != null) return;
+ dirty(); CHECKSET_INT(ay);
+ dirty(); MARK_RESIZE;
+ dirty();
+ }
case "titlebar":
if (getSurface() != null && value != null) getSurface().setTitleBarText(JS.toString(value));
super.put(name,value);
case "KeyPressed": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
case "KeyReleased": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
case "Move": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
- case "Enter": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
- case "Leave": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
case "HScroll": if (!test(STOP_UPWARD_PROPAGATION) && parent != null)
parent.putAndTriggerTraps(name, N(((Number)value).floatValue() * ((float)parent.fontSize()) / ((float)fontSize())));
case "SizeChange": return;
case "childadded": return;
case "childremoved": return;
+ case "Enter": return;
+ case "Leave": return;
case "thisbox": if (value == null) removeSelf();