X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fcore%2FBox.java;h=b6dcdf57fabaadd1b064c84ba048ffd61bc0edd2;hp=7a332ea42957d429eab514a56260a55e45108a95;hb=281809f6b87f0abc7b944795c05b1131a4495895;hpb=586485c446bc6870e08cfca8675a41442cca2c54 diff --git a/src/org/ibex/core/Box.java b/src/org/ibex/core/Box.java index 7a332ea..b6dcdf5 100644 --- a/src/org/ibex/core/Box.java +++ b/src/org/ibex/core/Box.java @@ -41,7 +41,7 @@ import org.ibex.graphics.*; * 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 JS.Obj implements Task { +public final class Box extends JS.Obj implements Callable { private static final JS.Method METHOD = new JS.Method(); @@ -54,17 +54,13 @@ public final class Box extends JS.Obj implements Task { //#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_BOOLEAN.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.Hash(500, 3); - 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); } - } + public static final Font DEFAULT_FONT = Font.getFont(Main.vera, 10); // Flags ////////////////////////////////////////////////////////////////////// @@ -85,11 +81,6 @@ public final class Box extends JS.Obj implements Task { static final int RECONSTRAIN = 0x00000200; static final int REPLACE = 0x00000400; - static final int ALIGN_TOP = 0x00001000; - static final int ALIGN_BOTTOM = 0x00002000; - static final int ALIGN_LEFT = 0x00004000; - static final int ALIGN_RIGHT = 0x00008000; - static final int ALIGNS = 0x0000f000; static final int CURSOR = 0x00010000; // if true, this box has a cursor in the cursor hash; FEATURE: GC issues? static final int CLIP = 0x00020000; static final int STOP_UPWARD_PROPAGATION = 0x00040000; @@ -118,6 +109,10 @@ public final class Box extends JS.Obj implements 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; @@ -147,13 +142,14 @@ public final class Box extends JS.Obj implements Task { 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, 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 @@ -243,7 +239,8 @@ public final class Box extends JS.Obj implements Task { 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) && hasTrap(SIZECHANGE); + 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); @@ -259,7 +256,7 @@ public final class Box extends JS.Obj implements Task { this.width = width; this.height = height; this.x = x; this.y = y; dirty(); } - if (sizechange) putAndTriggerTrapsAndCatchExceptions(SIZECHANGE, T); + if (sizechange) putAndTriggerTrapsAndCatchExceptions(SIZECHANGE, JSU.T); } private float targetColumnSize = (float)0.0; @@ -367,13 +364,13 @@ public final class Box extends JS.Obj implements Task { 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); + child_x = child.ax + gap_x / 2; + child_y = child.ay + gap_y / 2; } else { int diff; //#repeat col/row colspan/rowspan contentwidth/contentheight width/height colMaxWidth/rowMaxHeight \ // child_x/child_y x/y HSHRINK/VSHRINK maxwidth/maxheight cols/rows minwidth/minheight x_slack/y_slack \ - // child_width/child_height ALIGN_RIGHT/ALIGN_BOTTOM ALIGN_LEFT/ALIGN_TOP lp_h/lp \ + // child_width/child_height lp_h/lp \ // numregions/numregions_v regions/regions_v targetColumnSize/targetRowSize sizes/sizes_v child_x = 0; if (cols == 1) { @@ -386,7 +383,7 @@ public final class Box extends JS.Obj implements Task { } } diff = (child_width - (child.test(HSHRINK) ? child.contentwidth : min(child_width, child.maxwidth))); - child_x += (child.test(ALIGN_RIGHT) ? diff : child.test(ALIGN_LEFT) ? 0 : diff / 2); + child_x += diff / 2; child_width -= diff; //#end } @@ -430,12 +427,12 @@ public final class Box extends JS.Obj implements Task { 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); + int text_x = globalx + gap_x/2; + int text_y = globaly + gap_y/2; font.rasterizeGlyphs(text, buf, strokecolor, text_x, text_y, cx1, cy1, cx2, cy2); } - if (path != null) path.realize(Affine.translate(globalx, globaly)).stroke(buf, 1, strokecolor); + 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); @@ -443,22 +440,20 @@ public final class Box extends JS.Obj implements Task { // Methods to implement org.ibex.js.JS ////////////////////////////////////// - - public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { - switch (nargs) { + public JS call(JS method, JS[] args) throws JSExn { + switch (args.length) { case 1: { //#switch(JSU.toString(method)) case "indexof": - Box b = (Box)a0; + Box b = (Box)args[0]; if (b.parent != this) return (redirect == null || redirect == this) ? - JSU.N(-1) : - redirect.callMethod(method, a0, a1, a2, rest, nargs); + JSU.N(-1) : redirect.call(method, args); return JSU.N(b.getIndexInParent()); case "distanceto": - Box b = (Box)a0; + 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))); @@ -467,7 +462,7 @@ public final class Box extends JS.Obj implements Task { //#end } } - return super.callMethod(method, a0, a1, a2, rest, nargs); + return super.call(method, args); } public JS get(JS name) throws JSExn { @@ -493,7 +488,6 @@ public final class Box extends JS.Obj implements Task { case "font": return font == null ? null : font.stream; case "fontsize": return font == null ? JSU.N(10) : JSU.N(font.pointsize); case "strokewidth": return JSU.N(strokewidth); - case "align": return JSU.S(alignToString()); case "thisbox": return this; case "shrink": return JSU.B(test(HSHRINK) || test(VSHRINK)); case "hshrink": return JSU.B(test(HSHRINK)); @@ -512,7 +506,7 @@ public final class Box extends JS.Obj implements Task { case "minheight": return JSU.N(minheight); case "maxheight": return JSU.N(maxheight); case "clip": return JSU.B(test(CLIP)); - case "visible": return JSU.B(test(VISIBLE) && (parent == null || (parent.get(JSU.S("visible")) == T))); + case "visible": return JSU.B(test(VISIBLE) && (parent == null || (parent.get(JSU.S("visible")) == JSU.T))); case "packed": return JSU.B(test(PACKED)); case "globalx": return JSU.N(localToGlobalX(0)); case "globaly": return JSU.N(localToGlobalY(0)); @@ -523,14 +517,14 @@ public final class Box extends JS.Obj implements Task { throw new JSExn("you cannot read from the box.mouse property in background thread context"); return new Mouse(); case "numchildren": return redirect == null ? JSU.N(0) : redirect == this ? JSU.N(treeSize()) : redirect.get(JSU.S("numchildren")); - case "redirect": return redirect == null ? null : redirect == this ? T : redirect.get(JSU.S("redirect")); + case "redirect": return redirect == null ? null : redirect == this ? JSU.T : redirect.get(JSU.S("redirect")); case "Minimized": if (parent == null && getSurface() != null) return JSU.B(getSurface().minimized); default: return super.get(name); //#end throw new Error("unreachable"); // unreachable } - private class Mouse extends JS implements JS.Cloneable { + private class Mouse extends JS.Immutable implements JS.Cloneable { public JS get(JS key) throws JSExn { //#switch(JSU.toString(key)) case "x": return JSU.N(globalToLocalX(getSurface()._mousex)); @@ -539,7 +533,7 @@ public final class Box extends JS.Obj implements Task { // this might not get recomputed if we change mousex/mousey... case "inside": return JSU.B(test(MOUSEINSIDE)); //#end - return null; + return super.get(key); } } @@ -569,7 +563,7 @@ public final class Box extends JS.Obj implements Task { case "shrink": CHECKSET_FLAG(HSHRINK | VSHRINK); RECONSTRAIN(); case "hshrink": CHECKSET_FLAG(HSHRINK); RECONSTRAIN(); case "vshrink": CHECKSET_FLAG(VSHRINK); RECONSTRAIN(); - case "path": path = Path.parse(JSU.toString(value)); 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)); @@ -580,7 +574,6 @@ public final class Box extends JS.Obj implements Task { 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); REPLACE(); case "cursor": setCursor(JSU.toString(value)); case "fill": setFill(value); case "clip": CHECKSET_FLAG(CLIP); if (parent == null) dirty(); else parent.dirty(); @@ -603,9 +596,9 @@ public final class Box extends JS.Obj implements Task { 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(!(value instanceof Fountain)) throw new JSExn("You can only put streams to the font property"); //FIXME: if (font == value) return; // FIXME: unclone() - font = value == null ? null : Font.getFont((Stream)value, font == null ? 10 : font.pointsize); + font = value == null ? null : Font.getFont((Fountain)value, font == null ? 10 : font.pointsize); RECONSTRAIN(); dirty(); case "x": if (parent==null && Surface.fromBox(this)!=null) { @@ -672,36 +665,6 @@ public final class Box extends JS.Obj implements Task { //#end } - private String alignToString() { - switch(flags & ALIGNS) { - case (ALIGN_TOP | ALIGN_LEFT): return "topleft"; - case (ALIGN_BOTTOM | ALIGN_LEFT): return "bottomleft"; - case (ALIGN_TOP | ALIGN_RIGHT): return "topright"; - case (ALIGN_BOTTOM | ALIGN_RIGHT): return "bottomright"; - case ALIGN_TOP: return "top"; - case ALIGN_BOTTOM: return "bottom"; - case ALIGN_LEFT: return "left"; - case ALIGN_RIGHT: return "right"; - case 0: return "center"; - default: throw new Error("invalid alignment flags: " + (flags & ALIGNS)); - } - } - - private void setAlign(JS value) throws JSExn { - clear(ALIGNS); - //#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); - case "bottomright": set(ALIGN_BOTTOM | ALIGN_RIGHT); - case "top": set(ALIGN_TOP); - case "bottom": set(ALIGN_BOTTOM); - case "left": set(ALIGN_LEFT); - case "right": set(ALIGN_RIGHT); - default: JSU.log("invalid alignment \"" + JSU.debugToString(value) + "\""); - //#end - } - private void setCursor(String value) throws JSExn { if (value == null) { clear(CURSOR); boxToCursor.remove(this); return; } if (value.equals(boxToCursor.get(this))) return; @@ -729,7 +692,7 @@ public final class Box extends JS.Obj implements Task { if (texture == newtex) return; texture = newtex; fillcolor = 0; - if (texture != null && texture.isLoaded) perform(); + if (texture != null && texture.isLoaded) run(null); } dirty(); } @@ -748,12 +711,12 @@ public final class Box extends JS.Obj implements Task { boolean isinside = test(VISIBLE) && inside(x, y) && !obscured; if (!wasinside && isinside) { set(MOUSEINSIDE); - putAndTriggerTrapsAndCatchExceptions(JSU.S("Enter"), T); + putAndTriggerTrapsAndCatchExceptions(JSU.S("Enter"), JSU.T); } if (isinside && test(CURSOR)) getSurface().cursor = (String)boxToCursor.get(this); if (wasinside && !isinside) { clear(MOUSEINSIDE); - putAndTriggerTrapsAndCatchExceptions(JSU.S("Leave"), T); + putAndTriggerTrapsAndCatchExceptions(JSU.S("Leave"), JSU.T); } boolean found = false; @@ -936,10 +899,10 @@ public final class Box extends JS.Obj implements Task { try { putAndTriggerTraps(name, val); } catch (JSExn e) { - JSU.log("caught js exception while putting to trap \""+ JSU.debugToString(name)+"\""); + JSU.log("caught js exception while putting to trap \""+ JSU.str(name)+"\""); JSU.log(e); } catch (Exception e) { - JSU.log("caught exception while putting to trap \""+ JSU.debugToString(name)+"\""); + JSU.log("caught exception while putting to trap \""+ JSU.str(name)+"\""); JSU.log(e); } }