X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fcore%2FBox.java;h=16bae8585e0443d36ae11e1e0b62b8bd05532daa;hp=c898d8e1cfb502749b2aa88234e56013cedfa506;hb=297fdbde87e6db4732448a0950d1141c7265c169;hpb=4daeeb4119b901d53b44913c86f8af3ce67db925
diff --git a/src/org/ibex/core/Box.java b/src/org/ibex/core/Box.java
index c898d8e..16bae85 100644
--- a/src/org/ibex/core/Box.java
+++ b/src/org/ibex/core/Box.java
@@ -1,6 +1,9 @@
+// Copyright 2000-2005 the Contributors, as shown in the revision logs.
+// Licensed under the GNU General Public License version 2 ("the License").
+// You may not use this file except in compliance with the License.
+
// FIXME
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.core;
// FIXME: are traps on x/y meaningful?
// FIXME: if we trap on cols, then set rows to 0 (forcing cols to 1), does the cols trap get triggered?
@@ -17,7 +20,7 @@ package org.ibex;
import java.util.*;
import org.ibex.js.*;
import org.ibex.util.*;
-import org.ibex.translators.*;
+import org.ibex.graphics.*;
/**
*
@@ -38,7 +41,9 @@ import org.ibex.translators.*;
* trigger a Surface.abort; if rendering were done in the same pass,
* rendering work done prior to the Surface.abort would be wasted.
*/
-public final class Box extends JSScope implements Scheduler.Task {
+public final class Box extends JS.Obj implements Callable {
+
+ private static final JS.Method METHOD = new JS.Method();
// Macros //////////////////////////////////////////////////////////////////////
@@ -46,18 +51,20 @@ public final class Box extends JSScope implements Scheduler.Task {
final void RECONSTRAIN() { for(Box b2 = this; b2 != null && !b2.test(RECONSTRAIN); b2 = b2.parent) b2.set(RECONSTRAIN); }
final void REPACK() { for(Box b2 = this; b2 != null && !b2.test(REPACK); b2 = b2.parent) b2.set(REPACK); }
- //#define CHECKSET_SHORT(prop) short nu = (short)toInt(value); if (nu == prop) break; prop = nu;
- //#define CHECKSET_INT(prop) int nu = toInt(value); if (nu == prop) break; prop = nu;
- //#define CHECKSET_FLAG(flag) boolean nu = toBoolean(value); if (nu == test(flag)) break; if (nu) set(flag); else clear(flag);
- //#define CHECKSET_BOOLEAN(prop) boolean nu = toBoolean(value); if (nu == prop) break; prop = nu;
- //#define CHECKSET_STRING(prop) if ((value==null&&prop==null)||(value!=null&&JS.toString(value).equals(prop))) break; prop=JS.toString(value);
-
- protected Box() { super(null); }
+ //#define CHECKSET_SHORT(prop) short nu = (short)JSU.toInt(value); if (nu == prop) break; prop = nu;
+ //#define CHECKSET_INT(prop) int nu = JSU.toInt(value); if (nu == prop) break; prop = nu;
+ //#define CHECKSET_FLAG(flag) boolean nu = JSU.toBoolean(value); if (nu == test(flag)) break; if (nu) set(flag); else clear(flag);
+ //#define CHECKSET_BOOLEAJSU.N(prop) boolean nu = JSU.toBoolean(value); if (nu == prop) break; prop = nu;
+ //#define CHECKSET_STRING(prop) if ((value==null&&prop==null)||(value!=null&&JSU.toString(value).equals(prop))) break; prop=JSU.toString(value);
// FIXME memory leak
- static Hash boxToCursor = new Hash(500, 3);
+ static Basket.Map boxToCursor = new Basket.HashMap(500, 3);
- static final Font DEFAULT_FONT = Font.getFont((Stream)Main.builtin.get("fonts/vera/Vera.ttf"), 10);
+ static final Font DEFAULT_FONT;
+ static {
+ try { DEFAULT_FONT = Font.getFont((JS)Main.builtin.get(JSU.S("fonts/vera/Vera.ttf")), 10); }
+ catch(JSExn e) { throw new Error("Error loading default font: " + e); }
+ }
// Flags //////////////////////////////////////////////////////////////////////
@@ -65,8 +72,8 @@ public final class Box extends JSScope implements Scheduler.Task {
static final int MOUSEINSIDE = 0x00000001;
static final int VISIBLE = 0x00000002;
static final int PACKED = 0x00000004;
- static final int HSHRINK = 0x00000008;
- static final int VSHRINK = 0x00000010;
+ public static final int HSHRINK = 0x00000008;
+ public static final int VSHRINK = 0x00000010;
static final int BLACK = 0x00000020; // for red-black code
static final int FIXED = 0x00000040;
@@ -95,6 +102,8 @@ public final class Box extends JSScope implements Scheduler.Task {
Box redirect = this;
int flags = VISIBLE | PACKED | REPACK | RECONSTRAIN | REPLACE | FIXED | STOP_UPWARD_PROPAGATION | CLIP | MOVED;
+ private BalancedTree bt;
+
private String text = null;
private Font font = DEFAULT_FONT;
private Picture texture = null;
@@ -109,6 +118,10 @@ public final class Box extends JSScope implements Scheduler.Task {
public int maxwidth = Integer.MAX_VALUE;
public int minheight = 0;
public int maxheight = Integer.MAX_VALUE;
+ public int minwidth() { return minwidth; }
+ public int minheight() { return minheight; }
+ public int maxwidth() { return maxwidth; }
+ public int maxheight() { return maxheight; }
private short rows = 1;
private short cols = 0;
private short rowspan = 1;
@@ -123,30 +136,29 @@ public final class Box extends JSScope implements Scheduler.Task {
public int ay = 0; // FEATURE: roll these into x/y; requires lots of changes; perhaps y()?
public int width = 0;
public int height = 0;
- private int contentwidth = 0; // == max(minwidth, textwidth, sum(child.contentwidth))
- private int contentheight = 0;
+ public int contentwidth = 0; // == max(minwidth, textwidth, sum(child.contentwidth))
+ public int contentheight = 0;
+ private Path path = null;
/*
- private VectorGraphics.VectorPath path = null;
- private VectorGraphics.Affine transform = null;
+ private Affine transform = null;
private VectorGraphics.RasterPath rpath = null;
- private VectorGraphics.Affine rtransform = null;
+ private Affine rtransform = null;
*/
- //#define DIRTY dirty()
-
// Instance Methods /////////////////////////////////////////////////////////////////////
public final int fontSize() { return font == null ? DEFAULT_FONT.pointsize : font.pointsize; }
/** invoked when a resource needed to render ourselves finishes loading */
- public void perform() throws JSExn {
- if (texture == null) { Log.warn(Box.class, "perform() called with null texture"); return; }
+ public Object run(Object o) throws JSExn {
+ if (texture == null) { Log.warn(Box.class, "perform() called with null texture"); return null; }
if (texture.isLoaded) {
- setWidth(max(texture.width, maxwidth), maxwidth);
- setHeight(max(texture.height, maxheight), maxheight);
- DIRTY; }
+ setWidth(max(texture.width, minwidth), maxwidth);
+ setHeight(max(texture.height, minheight), maxheight);
+ dirty(); }
else { JS res = texture.stream; texture = null; throw new JSExn("image not found: "+res.unclone()); }
+ return null;
}
// FEATURE: use cx2/cy2 format
@@ -172,11 +184,17 @@ public final class Box extends JSScope implements Scheduler.Task {
// Reflow ////////////////////////////////////////////////////////////////////////////////////////
/** should only be invoked on the root box */
- void reflow() { pack(); resize(x, y, maxwidth, maxheight); place(); }
-
+ public void reflow() {
+ pack();
+ resize(x, y,
+ test(HSHRINK) ? contentwidth : maxwidth,
+ test(VSHRINK) ? contentheight : maxheight);
+ place();
+ }
+
private static Box[] frontier = new Box[65535];
/** pack the boxes into rows and columns, compute contentwidth */
- void pack() {
+ public void pack() {
if (!test(REPACK)) { constrain(); return; }
boolean haskid = false;
for(Box child = getChild(0); child != null; child = child.nextSibling()) { haskid = true; child.pack(); }
@@ -226,9 +244,12 @@ public final class Box extends JSScope implements Scheduler.Task {
set(REPLACE); // FIXME: be smarter / more incremental
}
+ private final static JS SIZECHANGE = JSU.S("SizeChange");
+
void resize(int x, int y, int width, int 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;
+ boolean sizechange = (this.width != width || this.height != height);
+ try { sizechange = sizechange && getTrap(SIZECHANGE) != null; } catch (JSExn e) {}
int thisx = parent == null ? 0 : this.x;
int thisy = parent == null ? 0 : this.y;
Box who = (parent == null ? this : parent);
@@ -242,9 +263,9 @@ public final class Box extends JSScope implements Scheduler.Task {
} else {
who.dirty(thisx, thisy, this.width, this.height);
this.width = width; this.height = height; this.x = x; this.y = y;
- DIRTY;
+ dirty();
}
- if (sizechange) putAndTriggerTrapsAndCatchExceptions("SizeChange", T);
+ if (sizechange) putAndTriggerTrapsAndCatchExceptions(SIZECHANGE, JSU.T);
}
private float targetColumnSize = (float)0.0;
@@ -390,7 +411,7 @@ public final class Box extends JSScope implements Scheduler.Task {
// Rendering Pipeline /////////////////////////////////////////////////////////////////////
/** Renders self and children within the specified region. All rendering operations are clipped to xIn,yIn,wIn,hIn */
- void render(int parentx, int parenty, int cx1, int cy1, int cx2, int cy2, PixelBuffer buf, VectorGraphics.Affine a) {
+ public void render(int parentx, int parenty, int cx1, int cy1, int cx2, int cy2, PixelBuffer buf, Affine a) {
if (!test(VISIBLE)) return;
int globalx = parentx + (parent == null ? 0 : x);
int globaly = parenty + (parent == null ? 0 : y);
@@ -420,6 +441,8 @@ public final class Box extends JSScope implements Scheduler.Task {
font.rasterizeGlyphs(text, buf, strokecolor, text_x, text_y, cx1, cy1, cx2, cy2);
}
+ if (path != null) new Polygon(path, Affine.translate(globalx, globaly)).stroke(buf, strokecolor);
+
for(Box b = getChild(0); b != null; b = b.nextSibling())
b.render(globalx, globaly, cx1, cy1, cx2, cy2, buf, null);
}
@@ -428,94 +451,100 @@ public final class Box extends JSScope implements Scheduler.Task {
// Methods to implement org.ibex.js.JS //////////////////////////////////////
- public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
- switch (nargs) {
+ public JS call(JS method, JS[] args) throws JSExn {
+ switch (args.length) {
case 1: {
- //#switch(method)
+ //#switch(JSU.toString(method))
case "indexof":
- Box b = (Box)a0;
+ Box b = (Box)args[0];
if (b.parent != this)
return (redirect == null || redirect == this) ?
- N(-1) :
- redirect.callMethod(method, a0, a1, a2, rest, nargs);
- return N(b.getIndexInParent());
+ JSU.N(-1) : redirect.call(method, args);
+ return JSU.N(b.getIndexInParent());
case "distanceto":
- Box b = (Box)a0;
- JS ret = new JS();
- ret.put("x", N(b.localToGlobalX(0) - localToGlobalX(0)));
- ret.put("y", N(b.localToGlobalY(0) - localToGlobalY(0)));
+ Box b = (Box)args[0];
+ JS ret = new JS.Obj();
+ ret.put(JSU.S("x"), JSU.N(b.localToGlobalX(0) - localToGlobalX(0)));
+ ret.put(JSU.S("y"), JSU.N(b.localToGlobalY(0) - localToGlobalY(0)));
return ret;
//#end
}
}
- return super.callMethod(method, a0, a1, a2, rest, nargs);
+ return super.call(method, args);
}
- public Object get(Object name) throws JSExn {
- if (name instanceof Number)
- return redirect == null ? null : redirect == this ? getChild(toInt(name)) : redirect.get(name);
+ public JS get(JS name) throws JSExn {
+ if (JSU.isInt(name))
+ return redirect == null ? null : redirect == this ? getChild(JSU.toInt(name)) : redirect.get(name);
- //#switch(name)
- case "surface": return parent == null ? null : parent.getAndTriggerTraps("surface");
+ //#switch(JSU.toString(name))
+ case "surface": return parent == null ? null : parent.getAndTriggerTraps(name);
case "indexof": return METHOD;
case "distanceto": return METHOD;
- case "text": return text;
- case "path": throw new JSExn("cannot read from the path property");
- case "fill": return colorToString(fillcolor);
- case "strokecolor": return colorToString(strokecolor);
- case "textcolor": return colorToString(strokecolor);
+ case "text": return JSU.S(text);
+ case "path": {
+ if (path != null) return JSU.S(path.toString());
+ if (text == null) return null;
+ if (font == null) return null;
+ String ret = "";
+ for(int i=0; i 0) { CHECKSET_SHORT(colspan); if (parent != null) parent.REPACK(); }
- case "rowspan": if (toInt(value) > 0) { CHECKSET_SHORT(rowspan); if (parent != null) parent.REPACK(); }
- case "visible": CHECKSET_FLAG(VISIBLE); RECONSTRAIN(); DIRTY;
+ case "path": path = new Path(JSU.toString(value)); RECONSTRAIN(); dirty();
+ case "width": setWidth(JSU.toInt(value), JSU.toInt(value));
+ case "height": setHeight(JSU.toInt(value), JSU.toInt(value));
+ case "maxwidth": setWidth(minwidth, JSU.toInt(value));
+ case "minwidth": setWidth(JSU.toInt(value), maxwidth);
+ case "maxheight": setHeight(minheight, JSU.toInt(value));
+ case "minheight": setHeight(JSU.toInt(value), maxheight);
+ case "colspan": if (JSU.toInt(value) > 0) { CHECKSET_SHORT(colspan); if (parent != null) parent.REPACK(); }
+ case "rowspan": if (JSU.toInt(value) > 0) { CHECKSET_SHORT(rowspan); if (parent != null) parent.REPACK(); }
+ case "visible": CHECKSET_FLAG(VISIBLE); RECONSTRAIN(); dirty();
case "packed": CHECKSET_FLAG(PACKED); if (parent != null) { parent.REPACK(); } else { REPACK(); }
- case "align": clear(ALIGNS); setAlign(value == null ? "center" : value); REPLACE();
- case "cursor": setCursor(value);
+ case "align": clear(ALIGNS); setAlign(value); REPLACE();
+ case "cursor": setCursor(JSU.toString(value));
case "fill": setFill(value);
- case "clip": CHECKSET_FLAG(CLIP); if (parent == null) DIRTY; else parent.DIRTY;
+ case "clip": CHECKSET_FLAG(CLIP); if (parent == null) dirty(); else parent.dirty();
case "rows": CHECKSET_SHORT(rows); if (rows==0){set(FIXED, COLS);if(cols==0)cols=1;} else set(FIXED, ROWS); REPACK();
case "cols": CHECKSET_SHORT(cols); if (cols==0){set(FIXED, ROWS);if(rows==0)rows=1;} else set(FIXED, COLS); REPACK();
// FIXME: remove
case "mouse":
- int mousex = toInt(((JS)value).get("x"));
- int mousey = toInt(((JS)value).get("y"));
+ int mousex = JSU.toInt(((JS)value).get(JSU.S("x")));
+ int mousey = JSU.toInt(((JS)value).get(JSU.S("y")));
getSurface()._mousex = localToGlobalX(mousex);
getSurface()._mousey = localToGlobalY(mousey);
- 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 "Minimized": if (parent == null && getSurface() != null) getSurface().minimized = JSU.toBoolean(value); // FEATURE
+ case "Maximized": if (parent == null && getSurface() != null) getSurface().maximized = JSU.toBoolean(value); // FEATURE
case "Close": if (parent == null && getSurface() != null) getSurface().dispose(true);
case "redirect":
for(Box cur = (Box)value; cur != null || cur == redirect; 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 "fontsize": font = Font.getFont(font == null ? null : font.stream, toInt(value)); RECONSTRAIN(); DIRTY;
+ JSU.error("redirect can only be set to a descendant of its current value");
+ case "fontsize": font = Font.getFont(font == null ? null : font.stream, JSU.toInt(value)); RECONSTRAIN(); dirty();
case "font":
if(!(value instanceof Stream)) throw new JSExn("You can only put streams to the font property");
- if (font == value) return; // FIXME: unclone()
+ //FIXME: if (font == value) return; // FIXME: unclone()
font = value == null ? null : Font.getFont((Stream)value, font == null ? 10 : font.pointsize);
RECONSTRAIN();
- DIRTY;
+ dirty();
case "x": if (parent==null && Surface.fromBox(this)!=null) {
CHECKSET_INT(x);
} else {
@@ -597,7 +627,7 @@ public final class Box extends JSScope implements Scheduler.Task {
CHECKSET_INT(ay);
REPLACE();
}
- case "titlebar": if (getSurface()!=null) getSurface().setTitleBarText(toString(value)); super.put(name,value);
+ case "titlebar": if (getSurface()!=null) getSurface().setTitleBarText(JSU.toString(value)); super.put(name,value);
// FIXME: icon
case "Press1": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
@@ -616,9 +646,9 @@ public final class Box extends JSScope implements Scheduler.Task {
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 "HScroll": if (!test(STOP_UPWARD_PROPAGATION) && parent != null)
- parent.putAndTriggerTraps(name, N(((Number)value).floatValue() * ((float)parent.fontSize()) / ((float)fontSize())));
+ parent.putAndTriggerTraps(name, JSU.N(JSU.toFloat(value) * ((float)parent.fontSize()) / ((float)fontSize())));
case "VScroll": if (!test(STOP_UPWARD_PROPAGATION) && parent != null)
- parent.putAndTriggerTraps(name, N(((Number)value).floatValue() * ((float)parent.fontSize()) / ((float)fontSize())));
+ parent.putAndTriggerTraps(name, JSU.N(JSU.toFloat(value) * ((float)parent.fontSize()) / ((float)fontSize())));
case "_Move": propagateDownward(name, value, false);
case "_Press1": propagateDownward(name, value, false);
@@ -662,9 +692,9 @@ public final class Box extends JSScope implements Scheduler.Task {
}
}
- private void setAlign(Object value) {
+ private void setAlign(JS value) throws JSExn {
clear(ALIGNS);
- //#switch(value)
+ //#switch(JSU.toString(value))
case "topleft": set(ALIGN_TOP | ALIGN_LEFT);
case "bottomleft": set(ALIGN_BOTTOM | ALIGN_LEFT);
case "topright": set(ALIGN_TOP | ALIGN_RIGHT);
@@ -673,11 +703,11 @@ public final class Box extends JSScope implements Scheduler.Task {
case "bottom": set(ALIGN_BOTTOM);
case "left": set(ALIGN_LEFT);
case "right": set(ALIGN_RIGHT);
- default: JS.log("invalid alignment \"" + value + "\"");
+ default: JSU.log("invalid alignment \"" + JSU.str(value) + "\"");
//#end
}
- private void setCursor(Object value) {
+ private void setCursor(String value) throws JSExn {
if (value == null) { clear(CURSOR); boxToCursor.remove(this); return; }
if (value.equals(boxToCursor.get(this))) return;
set(CURSOR);
@@ -689,35 +719,33 @@ public final class Box extends JSScope implements Scheduler.Task {
if (surface.cursor != tempcursor) surface.syncCursor();
}
- private void setFill(Object value) throws JSExn {
+ private void setFill(JS value) throws JSExn {
if (value == null) {
if (texture == null && fillcolor == 0) return;
texture = null;
fillcolor = 0;
- } else if (value instanceof String) {
- int newfillcolor = stringToColor((String)value);
+ } else if (JSU.isString(value)) {
+ int newfillcolor = Color.stringToColor(JSU.toString(value));
if (newfillcolor == fillcolor) return;
fillcolor = newfillcolor;
texture = null;
- } else if (value instanceof JS) {
+ } else {
Picture newtex = Picture.load((JS)value, this);
if (texture == newtex) return;
texture = newtex;
fillcolor = 0;
- if (texture != null && texture.isLoaded) perform();
- } else {
- throw new JSExn("fill must be null, a String, or a stream, not a " + value.getClass());
+ if (texture != null && texture.isLoaded) run(null);
}
- DIRTY;
+ dirty();
}
/**
* Handles events which propagate down the box tree. If obscured
* is set, then we merely check for Enter/Leave.
*/
- private void propagateDownward(Object name_, Object value, boolean obscured) {
+ private void propagateDownward(JS name_, JS value, boolean obscured) throws JSExn {
- String name = (String)name_;
+ String name = JSU.toString(name_);
if (getSurface() == null) return;
int x = globalToLocalX(getSurface()._mousex);
int y = globalToLocalY(getSurface()._mousey);
@@ -725,28 +753,28 @@ public final class Box extends JSScope implements Scheduler.Task {
boolean isinside = test(VISIBLE) && inside(x, y) && !obscured;
if (!wasinside && isinside) {
set(MOUSEINSIDE);
- putAndTriggerTrapsAndCatchExceptions("Enter", T);
+ putAndTriggerTrapsAndCatchExceptions(JSU.S("Enter"), JSU.T);
}
if (isinside && test(CURSOR)) getSurface().cursor = (String)boxToCursor.get(this);
if (wasinside && !isinside) {
clear(MOUSEINSIDE);
- putAndTriggerTrapsAndCatchExceptions("Leave", T);
+ putAndTriggerTrapsAndCatchExceptions(JSU.S("Leave"), JSU.T);
}
boolean found = false;
if (wasinside || isinside)
for(Box child = getChild(treeSize() - 1); child != null; child = child.prevSibling()) {
boolean save_stop = child.test(STOP_UPWARD_PROPAGATION);
- Object value2 = value;
+ JS value2 = value;
if (name.equals("_HScroll") || name.equals("_VScroll"))
- value2 = N(((Number)value).floatValue() * ((float)child.fontSize()) / (float)fontSize());
+ value2 = JSU.N(JSU.toFloat(value) * ((float)child.fontSize()) / (float)fontSize());
if (obscured || !child.inside(x - child.x, y - child.y)) {
- child.propagateDownward(name, value2, true);
+ child.propagateDownward(name_, value2, true);
} else try {
found = true;
child.clear(STOP_UPWARD_PROPAGATION);
- if (name != null) child.putAndTriggerTrapsAndCatchExceptions(name, value2);
- else child.propagateDownward(name, value2, obscured);
+ if (name != null) child.putAndTriggerTrapsAndCatchExceptions(name_, value2);
+ else child.propagateDownward(name_, value2, obscured);
} finally {
if (save_stop) child.set(STOP_UPWARD_PROPAGATION); else child.clear(STOP_UPWARD_PROPAGATION);
}
@@ -758,35 +786,7 @@ public final class Box extends JSScope implements Scheduler.Task {
if (!obscured && !found)
if ("_Move".equals(name) || name.startsWith("_Release") || wasinside)
if (name != null)
- putAndTriggerTrapsAndCatchExceptions(name.substring(1), value);
- }
-
- private static int stringToColor(String s) {
- // FIXME support three-char strings by doubling digits
- if (s == null) return 0x00000000;
- else if (SVG.colors.get(s) != null) return 0xFF000000 | toInt(SVG.colors.get(s));
- else if (s.length() == 7 && s.charAt(0) == '#') try {
- // FEATURE alpha
- return 0xFF000000 |
- (Integer.parseInt(s.substring(1, 3), 16) << 16) |
- (Integer.parseInt(s.substring(3, 5), 16) << 8) |
- Integer.parseInt(s.substring(5, 7), 16);
- } catch (NumberFormatException e) {
- Log.info(Box.class, "invalid color " + s);
- return 0;
- }
- else return 0; // FEATURE: error?
- }
-
- private static String colorToString(int argb) {
- if ((argb & 0xFF000000) == 0) return null;
- String red = Integer.toHexString((argb & 0x00FF0000) >> 16);
- String green = Integer.toHexString((argb & 0x0000FF00) >> 8);
- String blue = Integer.toHexString(argb & 0x000000FF);
- if (red.length() < 2) red = "0" + red;
- if (blue.length() < 2) blue = "0" + blue;
- if (green.length() < 2) green = "0" + green;
- return "#" + red + green + blue;
+ putAndTriggerTrapsAndCatchExceptions(JSU.S(name.substring(1)), value);
}
/** figures out what box in this subtree of the Box owns the pixel at x,y relitave to the Surface */
@@ -846,7 +846,7 @@ public final class Box extends JSScope implements Scheduler.Task {
void set(int mask) { flags |= mask; }
void set(int mask, boolean setclear) { if (setclear) set(mask); else clear(mask); }
void clear(int mask) { flags &= ~mask; }
- boolean test(int mask) { return ((flags & mask) == mask); }
+ public boolean test(int mask) { return ((flags & mask) == mask); }
// Tree Handling //////////////////////////////////////////////////////////////////////
@@ -862,7 +862,7 @@ public final class Box extends JSScope implements Scheduler.Task {
// Tree Manipulation /////////////////////////////////////////////////////////////////////
- void removeSelf() {
+ public void removeSelf() {
if (parent != null) { parent.removeChild(parent.indexNode(this)); return; }
Surface surface = Surface.fromBox(this);
if (surface != null) surface.dispose(true);
@@ -872,39 +872,39 @@ public final class Box extends JSScope implements Scheduler.Task {
public void removeChild(int i) {
Box b = getChild(i);
b.RECONSTRAIN();
- b.DIRTY;
+ b.dirty();
b.clear(MOUSEINSIDE);
deleteNode(i);
b.parent = null;
- RECONSTRAIN();
- putAndTriggerTrapsAndCatchExceptions("ChildChange", b);
+ REPACK();
+ putAndTriggerTrapsAndCatchExceptions(JSU.S("ChildChange"), b);
}
- public void put(int i, Object value) throws JSExn {
+ public void put(int i, JS value) throws JSExn {
if (i < 0) return;
if (value != null && !(value instanceof Box)) {
- if (Log.on) JS.warn("attempt to set a numerical property on a box to a non-box");
+ if (Log.on) JSU.warn("attempt to set a numerical property on a box to a non-box");
return;
}
if (redirect == null) {
- if (value == null) putAndTriggerTrapsAndCatchExceptions("ChildChange", getChild(i));
- else JS.warn("attempt to add/remove children to/from a node with a null redirect");
+ if (value == null) putAndTriggerTrapsAndCatchExceptions(JSU.S("ChildChange"), getChild(i));
+ else JSU.warn("attempt to add/remove children to/from a node with a null redirect");
} else if (redirect != this) {
- if (value != null) putAndTriggerTrapsAndCatchExceptions("ChildChange", value);
+ if (value != null) putAndTriggerTrapsAndCatchExceptions(JSU.S("ChildChange"), value);
redirect.put(i, value);
if (value == null) {
- Box b = (Box)redirect.get(new Integer(i));
- if (b != null) putAndTriggerTrapsAndCatchExceptions("ChildChange", b);
+ Box b = (Box)redirect.get(JSU.N(i));
+ if (b != null) putAndTriggerTrapsAndCatchExceptions(JSU.S("ChildChange"), b);
}
} else if (value == null) {
if (i < 0 || i > treeSize()) return;
Box b = getChild(i);
removeChild(i);
- putAndTriggerTrapsAndCatchExceptions("ChildChange", b);
+ putAndTriggerTrapsAndCatchExceptions(JSU.S("ChildChange"), b);
} else {
Box b = (Box)value;
@@ -912,14 +912,14 @@ public final class Box extends JSScope implements Scheduler.Task {
// check if box being moved is currently target of a redirect
for(Box cur = b.parent; cur != null; cur = cur.parent)
if (cur.redirect == b) {
- if (Log.on) JS.warn("attempt to move a box that is the target of a redirect");
+ if (Log.on) JSU.warn("attempt to move a box that is the target of a redirect");
return;
}
// check for recursive ancestor violation
for(Box cur = this; cur != null; cur = cur.parent)
if (cur == b) {
- if (Log.on) JS.warn("attempt to make a node a parent of its own ancestor");
+ if (Log.on) JSU.warn("attempt to make a node a parent of its own ancestor");
if (Log.on) Log.info(this, "box == " + this + " ancestor == " + b);
return;
}
@@ -929,30 +929,34 @@ public final class Box extends JSScope implements Scheduler.Task {
b.parent = this;
// need both of these in case child was already uncalc'ed
- b.RECONSTRAIN();
- RECONSTRAIN();
+ b.REPACK();
+ REPACK();
- b.DIRTY;
- putAndTriggerTrapsAndCatchExceptions("ChildChange", b);
+ b.dirty();
+ putAndTriggerTrapsAndCatchExceptions(JSU.S("ChildChange"), b);
}
}
-
- void putAndTriggerTrapsAndCatchExceptions(Object name, Object val) {
+
+ public void putAndTriggerTrapsAndCatchExceptions(JS name, JS val) {
try {
putAndTriggerTraps(name, val);
} catch (JSExn e) {
- JS.log("caught js exception while putting to trap \""+name+"\"");
- JS.log(e);
+ JSU.log("caught js exception while putting to trap \""+ JSU.str(name)+"\"");
+ JSU.log(e);
} catch (Exception e) {
- JS.log("caught exception while putting to trap \""+name+"\"");
- JS.log(e);
+ JSU.log("caught exception while putting to trap \""+ JSU.str(name)+"\"");
+ JSU.log(e);
}
}
-
+
+ // BalancedTree functions
+ private void insertNode(int p, Box b) {
+ if(bt == null) bt = new BalancedTree();
+ bt.insertNode(p,b);
+ }
+
+ private int treeSize() { return bt == null ? 0 : bt.treeSize(); }
+ private int indexNode(Box b) { return bt == null ? -1 : bt.indexNode(b); }
+ private void deleteNode(int p) { bt.deleteNode(p); }
+ private Box getNode(int p) { return (Box)bt.getNode(p); }
}
-
-
-
-
-
-