+ public Object call(Object method, JSArray args) throws JS.Exn {
+ if (!"indexof".equals(method)) return null;
+ Box b = (Box)args.elementAt(0);
+ if (b.parent != this) return (redirect == null || redirect == this) ? N(-1) : redirect.call(method, args);
+ return N(b.getIndexInParent());
+ }
+
+ /** to be filled in by the Tree implementation */
+ abstract void put(int i, Object value);
+ public int numchildren = 0;
+ abstract public int getIndexInParent();
+ abstract public Box getChild(int i);
+ abstract public Box nextSibling();
+ abstract public Box prevSibling();
+ abstract public void remove();
+ abstract Box swapPosition(Box x, Box y);
+
+ public Object get(Object name) { return get(name, false); }
+ public Object get(Object name, boolean ignoretraps) {
+ if (name instanceof Number)
+ return redirect == null ? null : redirect == this ? getChild(toInt(name)) : redirect.get(name);
+
+ //#switch(name)
+ case "text": return text;
+ case "path": throw new JS.Exn("cannot read from the path property");
+ case "fill": return colorToString(fillcolor);
+ case "strokecolor": return colorToString(strokecolor);
+ case "textcolor": return colorToString(strokecolor);
+ case "font": return font == null ? null : font.res;
+ case "fontsize": return font == null ? N(10) : N(font.pointsize);
+ case "strokewidth": return N(strokewidth);
+ case "align": return alignToString();
+ case "thisbox": return this;
+ case "shrink": return B(test(HSHRINK) || test(VSHRINK));
+ case "hshrink": return B(test(HSHRINK));
+ case "vshrink": return B(test(VSHRINK));
+ case "x": return (parent == null || !test(VISIBLE)) ? N(0) : N(x);
+ case "y": return (parent == null || !test(VISIBLE)) ? N(0) : N(y);
+ case "width" return N(width);
+ case "height" return N(height);
+ case "cols": return test(FIXED) == COLS ? N(cols) : N(0);
+ case "rows": return test(FIXED) == ROWS ? N(rows) : N(0);
+ case "colspan": return N(colspan);
+ case "rowspan": return N(rowspan);
+ case "noclip": return B(test(NOCLIP));
+ case "visible": return B(test(VISIBLE) && (parent == null || (parent.get("visible") == T)));
+ case "packed": return B(test(PACKED));
+ case "globalx": return N(localToGlobalX(0));
+ case "globaly": return N(localToGlobalY(0));
+ case "cursor": return test(CURSOR) ? boxToCursor.get(this) : null;
+ case "mousex": { Surface s = getSurface(); return N(s == null ? 0 : globalToLocalX(s.mousex)); }
+ case "mousey": { Surface s = getSurface(); return N(s == null ? 0 : globalToLocalY(s.mousey)); }
+ case "mouseinside": return B(test(MOUSEINSIDE));
+ case "numchildren": return redirect == null ? N(0) : redirect == this ? N(numchildren) : redirect.get("numchildren");
+ case "minwidth": return N(minwidth);
+ case "maxwidth": return N(maxwidth);
+ case "minheight": return N(minheight);
+ case "maxheight": return N(maxheight);
+ case "redirect": return redirect == null ? null : redirect == this ? T : redirect.get("redirect");
+ case "Minimized": if (parent == null && getSurface() != null) return B(getSurface().minimized);
+ default: return super.get(name);
+ //#end
+ return null;
+ }
+
+ public void put(Object name, Object value) { put(name, value, false); }
+ public void put(Object name, Object value, boolean ignoretraps) {
+ if (name instanceof Number) { put(toInt(name), value); return; }
+
+ //#switch(name)
+ case "text": CHECKSET_STRING(text); MARK_RESIZE; dirty();
+ case "strokewidth": CHECKSET_SHORT(strokewidth); dirty();
+ case "thisbox": if (value == null) remove();
+ case "shrink": put("hshrink", value); put("vshrink", value);
+ case "hshrink": CHECKSET_FLAG(HSHRINK); MARK_RESIZE;
+ case "vshrink": CHECKSET_FLAG(VSHRINK); MARK_RESIZE;
+ case "width": CHECKSET_INT(width); MARK_RESIZE;
+ case "maxwidth": CHECKSET_INT(maxwidth); MARK_RESIZE;
+ case "minwidth": CHECKSET_INT(minwidth); MARK_RESIZE;
+ case "height": CHECKSET_INT(height); MARK_RESIZE;
+ case "maxheight": CHECKSET_INT(maxheight); MARK_RESIZE;
+ case "minheight": CHECKSET_INT(minheight); MARK_RESIZE;
+ case "colspan": CHECKSET_SHORT(colspan); MARK_REPACK_parent;
+ case "rowspan": CHECKSET_SHORT(colspan); MARK_REPACK_parent;
+ case "rows": CHECKSET_SHORT(rows); MARK_REPACK; // FEATURE: error checking
+ case "cols": CHECKSET_SHORT(cols); MARK_REPACK; // FEATURE: error checking
+ case "noclip": CHECKSET_FLAG(NOCLIP); if (parent == null) dirty(); else parent.dirty();
+ case "visible": CHECKSET_FLAG(VISIBLE); dirty(); MARK_RESIZE; dirty();
+ case "packed": CHECKSET_FLAG(PACKED); MARK_REPACK_parent;
+ case "globalx": put("x", N(globalToLocalX(toInt(value))));
+ case "globaly": put("y", N(globalToLocalY(toInt(value))));
+ case "align": clear(ALIGNS); setAlign(value == null ? "center" : value); MARK_RESIZE;
+ case "cursor": setCursor(value);
+ case "fill": setFill(value);
+ case "Press1": mouseEvent("Press1", value);
+ case "Press2": mouseEvent("Press2", value);
+ case "Press3": mouseEvent("Press3", value);
+ case "Release1": mouseEvent("Release1", value);
+ case "Release2": mouseEvent("Release2", value);
+ case "Release3": mouseEvent("Release3", value);
+ case "Click1": mouseEvent("Click1", value);
+ case "Click2": mouseEvent("Click2", value);
+ case "Click3": mouseEvent("Click3", value);
+ case "DoubleClick1": mouseEvent("DoubleClick1", value);
+ case "DoubleClick2": mouseEvent("DoubleClick2", value);
+ case "DoubleClick3": mouseEvent("DoubleClick3", value);
+ 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 "toback": if (parent == null && getSurface() != null && toBoolean(value)) { getSurface().toBack(); }
+ case "tofront": if (parent == null && getSurface() != null && toBoolean(value)) { getSurface().toFront(); }
+ case "redirect": if (redirect == this) redirect = (Box)value; else Log.log(this, "redirect can only be set once");
+ case "font": font = value == null ? null : Font.getFont((Res)value, font == null ? 10 : font.pointsize); MARK_RESIZE; dirty();
+ case "fontsize": font = Font.getFont(font == null ? null : font.res, toInt(value)); MARK_RESIZE; dirty();
+ case "x": if (test(PACKED) && parent != null) return; CHECKSET_INT(x); dirty(); MARK_RESIZE; dirty();
+ case "y": if (test(PACKED) && parent != null) return; CHECKSET_INT(y); dirty(); MARK_RESIZE; dirty();
+ case "KeyPressed": // prevent stuff from hitting the Hash
+ case "KeyReleased": // prevent stuff from hitting the Hash
+ case "PosChange": // prevent stuff from hitting the Hash
+ case "SizeChange": // prevent stuff from hitting the Hash
+ case "childadded": // prevent stuff from hitting the Hash
+ case "childremoved": // prevent stuff from hitting the Hash
+ //#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(Object value) {
+ //#switch(value)
+ case "center": clear(ALIGNS);
+ 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: Log.logJS("invalid alignment \"" + value + "\"");
+ //#end