From 026feed5d3ffb670533197a4ec733d1d03578c63 Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 14 Feb 2005 04:23:25 +0000 Subject: [PATCH] massive reworking of Box.java darcs-hash:20050214042325-5007d-d9b736bacdf12b13c67904acad152d0390e08ddd.gz --- src/org/ibex/core/Box.java | 586 +++++++++++++----------------------- src/org/ibex/core/Template.java | 4 +- src/org/ibex/graphics/Affine.java | 1 + src/org/ibex/graphics/Path.java | 13 + src/org/ibex/graphics/Polygon.java | 6 +- src/org/ibex/graphics/Surface.java | 9 +- src/org/ibex/plat/AWT.java | 2 +- 7 files changed, 240 insertions(+), 381 deletions(-) diff --git a/src/org/ibex/core/Box.java b/src/org/ibex/core/Box.java index 089797f..76871cf 100644 --- a/src/org/ibex/core/Box.java +++ b/src/org/ibex/core/Box.java @@ -2,19 +2,11 @@ // Licensed under the GNU General Public License version 2 ("the License"). // You may not use this file except in compliance with the License. -// FIXME 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? -// FIXME: if we change min{width/height}, thereby forcing a change to max{min/height}, does a trap on those get triggered? -// FIXME: trap on numchildren? replaces ChildChanged? // FIXME: trap on visible, trigger when parent visibility changes - -// FIXME: ax/ay nonsense // FIXME: mouse move/release still needs to propagate to boxen in which the mouse was pressed and is still held down - -// FEATURE: mark to reflow starting with a certain child // FEATURE: reintroduce surface.abort import java.util.*; @@ -43,13 +35,10 @@ import org.ibex.graphics.*; */ public final class Box extends JS.Obj implements Callable { - private static final JS.Method METHOD = new JS.Method(); - // Macros ////////////////////////////////////////////////////////////////////// final void REPLACE() { for(Box b2 = this; b2 != null && !b2.test(REPLACE); b2 = b2.parent) b2.set(REPLACE); } 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)JSU.toInt(value); if (nu == prop) break; prop = nu; //#define CHECKSET_INT(prop) int nu = JSU.toInt(value); if (nu == prop) break; prop = nu; @@ -57,84 +46,39 @@ public final class Box extends JS.Obj implements Callable { //#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 Basket.Map boxToCursor = new Basket.Hash(500, 3); - - public static final Font DEFAULT_FONT = Font.getFont(Main.vera, 10); - - - // Flags ////////////////////////////////////////////////////////////////////// - - static final int MOUSEINSIDE = 0x00000001; - static final int VISIBLE = 0x00000002; - static final int PACKED = 0x00000004; - 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; - static final boolean ROWS = true; - static final boolean COLS = false; - - static final int ISROOT = 0x00000080; - static final int REPACK = 0x00000100; - static final int RECONSTRAIN = 0x00000200; - static final int REPLACE = 0x00000400; - - static final int CURSOR = 0x00010000; // if true, this box has cursor in the cursor hash; FEATURE: GC issues? - static final int CLIP = 0x00020000; - static final int STOP_UPWARD_PROPAGATION = 0x00040000; - static final int MOVED = 0x00080000; - - // Instance Data ////////////////////////////////////////////////////////////////////// - Box parent = null; - 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; - private short strokewidth = 1; - public int fillcolor = 0x00000000; - private int strokecolor = 0xFF000000; - - private int aspect = 0; + private Box parent = null; + private Box redirect = this; + private int flags = VISIBLE | RECONSTRAIN | REPLACE | STOP_UPWARD_PROPAGATION | CLIP | MOVED; + private BalancedTree bt = null; + private String text = null; + private Font font = DEFAULT_FONT; + private Picture texture = null; + public int fillcolor = 0x00000000; + private int strokecolor = 0xFF000000; + public float flex = 1; + private Path path = null; + private Affine transform = Affine.identity(); + + // FEATURE: polygon caching + private Polygon polygon = null; // specified directly by user public int minwidth = 0; public int maxwidth = Integer.MAX_VALUE; public int minheight = 0; public int maxheight = Integer.MAX_VALUE; - private short rows = 1; - private short cols = 0; - private short rowspan = 1; - private short colspan = 1; // computed during reflow - private short row = 0; - private short col = 0; - public int x = 0; - public int y = 0; public int width = 0; public int height = 0; public int contentwidth = 0; // == max(minwidth, textwidth, sum(child.contentwidth)) public int contentheight = 0; - private Path path = null; - /* - private Affine transform = null; - private VectorGraphics.RasterPath rpath = null; - private Affine rtransform = null; - */ // 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 Object run(Object o) throws JSExn { if (texture == null) { Log.warn(Box.class, "perform() called with null texture"); return null; } @@ -146,23 +90,19 @@ public final class Box extends JS.Obj implements Callable { return null; } - // FEATURE: use cx2/cy2 format /** Adds the intersection of (x,y,w,h) and the node's current actual geometry to the Surface's dirty list */ - public void dirty() { dirty(0, 0, width, height); } - public void dirty(int x, int y, int w, int h) { - for(Box cur = this; cur != null; cur = cur.parent) { - // x and y have a different meaning on the root box - if (cur.parent != null && cur.test(CLIP)) { - w = min(x + w, cur.width) - max(x, 0); - h = min(y + h, cur.height) - max(y, 0); - x = max(x, 0); - y = max(y, 0); - } - if (w <= 0 || h <= 0) return; - if (cur.parent == null && cur.getSurface() != null) cur.getSurface().dirty(x, y, w, h); - x += cur.x; - y += cur.y; - } + public void dirty() { if (path==null) dirty(0, 0, contentwidth, contentheight); else dirty(path); } + public void dirty(int x, int y, int w, int h) { } + public void dirty(Path p) { + Affine a = transform; + for(Box cur = this; cur != null; cur = cur.parent) a.premultiply(cur.transform); + long hbounds = p.horizontalBounds(a); + long vbounds = p.verticalBounds(a); + int x1 = (int)Encode.longToFloat2(hbounds); + int x2 = (int)Encode.longToFloat1(hbounds); + int y1 = (int)Encode.longToFloat2(vbounds); + int y2 = (int)Encode.longToFloat1(vbounds); + if (getSurface() != null) getSurface().dirty(x1, y1, x2-x1, y2-y1); } @@ -170,266 +110,136 @@ public final class Box extends JS.Obj implements Callable { /** should only be invoked on the root box */ public void reflow() { - pack(); - resize(x, y, - test(HSHRINK) ? contentwidth : maxwidth, - test(VSHRINK) ? contentheight : maxheight); + constrain(this, Affine.identity()); + width = maxwidth; + height = maxheight; + transform.e = 0; + transform.f = 0; place(); } - - private static Box[] frontier = new Box[65535]; - /** pack the boxes into rows and columns, compute contentwidth */ - 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(); } - 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 - if (test(FIXED) == COLS) { - rows = 0; + + void place() { + if (!packed()) { for(Box child = getChild(0); child != null; child = child.nextSibling()) { - if (!child.test(PACKED) || !child.test(VISIBLE)) continue; - if (cols == 1) { child.row = rows; rows += child.rowspan; child.col = 0; continue; } - child.col = (short)(frontier_size <= 0 ? 0 : (frontier[frontier_size-1].col + frontier[frontier_size-1].colspan)); - child.row = (short)(frontier_size <= 0 ? 0 : frontier[frontier_size-1].row); - if (child.col + min(cols,child.colspan) > cols) { child.col = 0; child.row++; } - for(int i=0; ichild.col) { - child.col = (short)(frontier[i].col + frontier[i].colspan); - if (child.col + min(cols,child.colspan) > cols) { - child.row = (short)(frontier[i].row + frontier[i].rowspan); - for(i--; i>0; i--) child.row = (short)min(row, frontier[i].row + frontier[i].rowspan); - child.col = (short)0; - } - i = -1; - } else break; - frontier[frontier_size++] = child; + child.width = max(child.minwidth, child.test(HSHRINK) ? child.contentwidth : child.maxwidth); + child.height = max(child.minheight, child.test(VSHRINK) ? child.contentheight : child.maxheight); + child.place(); } - for(int i=0; i 1) do { - - // FIXME: cache these? - // compute regions - numregions = 0; - for(Box c = firstPackedChild(); c != null; c = c.nextPackedSibling()) { - regions[numregions++] = c.col; - regions[numregions++] = min(cols, c.col+c.colspan); - } - Vec.sortInts(regions, 0, numregions); - int j = 0; - int newnumregions = numregions; - for(int i=1; i= 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.contentwidth - (float)0.5)) - sizes[r] = (float)Math.max(sizes[r], (regions[r+1]-regions[r])*(child.contentwidth/child.colspan)); - total += sizes[r]; - } - float save = targetColumnSize; - if (Math.abs(total - target) <= (float)1.0) break; - if (!first) { - if (Math.abs(total - last_total) <= (float)1.0) break; - } else { - last_columnsize = ((total - target) / (float)cols) + targetColumnSize; - } - if (total < target) targetColumnSize += Math.abs((last_columnsize - targetColumnSize) / (float)1.1); - else if (total > target) targetColumnSize -= Math.abs((last_columnsize - targetColumnSize) / (float)1.1); - last_columnsize = save; - last_total = total; - first = false; + while(slack > 0 && flex > 0 && oldslack!=slack) { + oldslack = slack; + slack = width; + for(Box child = getChild(0); child != null; child = child.nextSibling()) { + if (!child.test(VISIBLE)) continue; + if (child.width < child.maxwidth && !child.test(HSHRINK)) + child.width = bound(child.contentwidth, (int)(child.width + (slack/flex)), child.maxwidth); + newflex += child.width < child.maxwidth && !child.test(HSHRINK) ? child.flex : 0; + slack -= child.width; } - if (findMinimum) contentwidth = Math.round(total); - else this.targetColumnSize = targetColumnSize; - } while(false); - //#end - } - - void place() { - solve(false); + flex = newflex; + } + float pos = slack / 2; for(Box child = getChild(0); child != null; child = child.nextSibling()) { if (!child.test(VISIBLE)) continue; - if (!child.test(REPLACE)) continue; - int child_width, child_height, child_x, child_y; - if (!child.test(PACKED)) { - child_width = child.test(HSHRINK) ? child.contentwidth : min(child.maxwidth, width); - child_height = child.test(VSHRINK) ? child.contentheight : min(child.maxheight, height); - 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 = gap_x / 2; - child_y = 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 lp_h/lp \ - // numregions/numregions_v regions/regions_v targetColumnSize/targetRowSize sizes/sizes_v - child_x = 0; - if (cols == 1) { - child_width = width; - } else { - child_width = 0; - for(int r=0; r 0) - child.place(); - } + for(Box child = getChild(0); child != null; child = child.nextSibling()) { + xmin = Integer.MAX_VALUE; ymin = Integer.MAX_VALUE; + xmax = Integer.MIN_VALUE; ymax = Integer.MIN_VALUE; + child.constrain(this, Affine.identity()); + if (xmin==Integer.MAX_VALUE||xmax==Integer.MIN_VALUE||ymin==Integer.MAX_VALUE||ymax== Integer.MIN_VALUE) continue; + child.transform.e = -1 * xmin; + child.transform.f = -1 * ymin; + contentwidth += (xmax-xmin); + contentheight = max(ymax-ymin, contentheight); + } + xmin = save_xmin; + ymin = save_ymin; + xmax = save_xmax; + ymax = save_ymax; + contentwidth = bound(minwidth, contentwidth, maxwidth); + contentheight = bound(minheight, contentheight, maxheight); + int cw = bound(minwidth, contentwidth, maxwidth), ch = bound(minheight, contentheight, maxheight); + //#repeat contentwidth/contentheight contentheight/contentwidth minwidth/minheight row/col col/row \ + // textwidth/textheight maxwidth/maxheight bounds/boundsy x1/y1 x2/y2 z1/q1 z2/q2 z3/q3 z4/q4 \ + // horizontalBounds/verticalBounds e/f multiply_px/multiply_py xmin/ymin xmax/ymax + long bounds = path==null ? 0 : path.horizontalBounds(a); + float z1 = path==null ? a.multiply_px(0, 0) : Encode.longToFloat2(bounds); + float z2 = path==null ? a.multiply_px(cw, ch) : Encode.longToFloat1(bounds); + float z3 = path==null ? a.multiply_px(cw, 0) : Encode.longToFloat2(bounds); + float z4 = path==null ? a.multiply_px(0, ch) : Encode.longToFloat1(bounds); + xmin = min(xmin, (int)min(min(z1, z2), min(z3, z4))); + xmax = max(xmax, (int)max(max(z1, z2), max(z3, z4))); + //#end + } + // Rendering Pipeline ///////////////////////////////////////////////////////////////////// + private static final boolean OPTIMIZE = false; + /** Renders self and children within the specified region. All rendering operations are clipped to xIn,yIn,wIn,hIn */ - public void render(int parentx, int parenty, int cx1, int cy1, int cx2, int cy2, PixelBuffer buf, Affine a) { + public void render(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); - - // intersect the x,y,w,h rendering window with ourselves; quit if it's empty - if (test(CLIP)) { - cx1 = max(cx1, globalx); - cy1 = max(cy1, globaly); - cx2 = min(cx2, globalx + width); - cy2 = min(cy2, globaly + height); - if (cx2 <= cx1 || cy2 <= cy1) return; - } - - if ((fillcolor & 0xFF000000) != 0x00000000 || parent == null) - buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, (fillcolor & 0xFF000000) == 0 ? 0xffffffff : fillcolor); - - if (texture != null && texture.isLoaded) - 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) { - int gap_x = width - font.textwidth(text); - int gap_y = height - font.textheight(text); - 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); + a = a.copy().premultiply(transform); + + // FIXME: clipping + if (path == null) { + if (((fillcolor & 0xFF000000) != 0x00000000 || parent == null)) { + if (OPTIMIZE && a.doesNotRotate()) { + int x = (int)a.multiply_px(0, 0); + int y = (int)a.multiply_py(0, 0); + int x2 = (int)a.multiply_px(contentwidth, contentheight); + int y2 = (int)a.multiply_py(contentwidth, contentheight); + buf.fillTrapezoid(x, x, y, x2, x2, y2, (fillcolor & 0xFF000000) == 0 ? 0xffffffff : fillcolor); + } else { + new Polygon().addrect(0, 0, contentwidth, contentheight, a).fill(buf, new Paint.SingleColorPaint(fillcolor)); + } + } + // FIXME: text + // FIXME: texture + } else { + Polygon p = new Polygon(path, a); + p.fill(buf, new Paint.SingleColorPaint(fillcolor)); + p.stroke(buf, 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); + for(Box b = getChild(0); b != null; b = b.nextSibling()) b.render(cx1, cy1, cx2, cy2, buf, a); } @@ -481,18 +291,11 @@ public final class Box extends JS.Obj implements Callable { case "textcolor": return JSU.S(Color.colorToString(strokecolor)); 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 "thisbox": return this; case "shrink": return JSU.B(test(HSHRINK) || test(VSHRINK)); case "hshrink": return JSU.B(test(HSHRINK)); case "vshrink": return JSU.B(test(VSHRINK)); - case "aspect": return JSU.N(aspect); - case "x": return JSU.N(x); - case "y": return JSU.N(y); - case "cols": return test(FIXED) == COLS ? JSU.N(cols) : JSU.N(0); - case "rows": return test(FIXED) == ROWS ? JSU.N(rows) : JSU.N(0); - case "colspan": return JSU.N(colspan); - case "rowspan": return JSU.N(rowspan); + case "flex": return JSU.N(flex); case "width": getRoot().reflow(); return JSU.N(width); case "height": getRoot().reflow(); return JSU.N(height); case "minwidth": return JSU.N(minwidth); @@ -501,7 +304,7 @@ public final class Box extends JS.Obj implements Callable { 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")) == JSU.T))); - case "packed": return JSU.B(test(PACKED)); + case "axis": return test(XAXIS) ? JSU.S("x") : test(YAXIS) ? JSU.S("y") : JSU.S("z"); case "globalx": return JSU.N(localToGlobalX(0)); case "globaly": return JSU.N(localToGlobalY(0)); case "cursor": return test(CURSOR) ? JSU.S((String)boxToCursor.get(this)) : null; @@ -550,37 +353,53 @@ public final class Box extends JS.Obj implements Callable { if (JSU.isInt(name)) { put(JSU.toInt(name), value); return; } //#switch(JSU.toString(name)) case "thisbox": if (value == null) removeSelf(); - case "text": { String s = value == null ? "" : JSU.toString(value); CHECKSET_STRING(text); RECONSTRAIN(); dirty(); } + case "text": { String s = value==null ? "" : JSU.toString(value); CHECKSET_STRING(text); RECONSTRAIN(); dirty(); } case "strokecolor": value = JSU.N(Color.stringToColor(JSU.toString(value))); CHECKSET_INT(strokecolor); dirty(); case "textcolor": value = JSU.N(Color.stringToColor(JSU.toString(value))); CHECKSET_INT(strokecolor); dirty(); - case "strokewidth": CHECKSET_SHORT(strokewidth); dirty(); case "shrink": CHECKSET_FLAG(HSHRINK | VSHRINK); RECONSTRAIN(); case "hshrink": CHECKSET_FLAG(HSHRINK); RECONSTRAIN(); case "vshrink": CHECKSET_FLAG(VSHRINK); RECONSTRAIN(); - case "path": path = new Path(JSU.toString(value)); RECONSTRAIN(); dirty(); + case "path": { + path = new Path(JSU.toString(value)); + float tx = -1 * Encode.longToFloat2(path.horizontalBounds(Affine.identity())); + float ty = -1 * Encode.longToFloat2(path.verticalBounds(Affine.identity())); + path.transform(Affine.translate(tx, ty), true); + REPLACE(); + RECONSTRAIN(); + dirty(); + polygon = null; + } + case "transform": { + transform = Affine.parse(JSU.toString(value)); + transform.e = 0; + transform.f = 0; + if (getSurface() != null) getSurface().dirty(0, 0, 500, 500); // FIXME + REPLACE(); + RECONSTRAIN(); dirty(); polygon = null; + } case "width": setWidth(JSU.toInt(value), JSU.toInt(value)); case "height": setHeight(JSU.toInt(value), JSU.toInt(value)); + case "flex": flex = JSU.toFloat(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 "cursor": setCursor(JSU.toString(value)); case "fill": setFill(value); 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 = 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); - + getSurface()._mousex = (int)localToGlobalX(mousex); + getSurface()._mousey = (int)localToGlobalY(mousey); + case "axis": { + String s = JSU.toString(value); + if (s.equals("x")) { clear(YAXIS); set(XAXIS); } + else if (s.equals("y")) { clear(XAXIS); set(YAXIS); } + else if (s.equals("z")) { clear(XAXIS); clear(YAXIS); } + else JSU.warn("attempted to set axis property to invalid value: " + s); + } 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); @@ -595,8 +414,6 @@ public final class Box extends JS.Obj implements Callable { font = value == null ? null : Font.getFont((Fountain)value, font == null ? 10 : font.pointsize); RECONSTRAIN(); dirty(); - case "x": if (parent==null && Surface.fromBox(this)!=null) { CHECKSET_INT(x); } - case "y": if (parent==null && Surface.fromBox(this)!=null) { CHECKSET_INT(y); } case "titlebar": if (getSurface()!=null) getSurface().setTitleBarText(JSU.toString(value)); super.put(name,value); // FIXME: icon @@ -687,8 +504,8 @@ public final class Box extends JS.Obj implements Callable { String name = JSU.toString(name_); if (getSurface() == null) return; - int x = globalToLocalX(getSurface()._mousex); - int y = globalToLocalY(getSurface()._mousey); + int x = (int)globalToLocalX(getSurface()._mousex); + int y = (int)globalToLocalY(getSurface()._mousey); boolean wasinside = test(MOUSEINSIDE); boolean isinside = test(VISIBLE) && inside(x, y) && !obscured; if (!wasinside && isinside) { @@ -708,7 +525,7 @@ public final class Box extends JS.Obj implements Callable { JS value2 = value; if (name.equals("_HScroll") || name.equals("_VScroll")) value2 = JSU.N(JSU.toFloat(value) * ((float)child.fontSize()) / (float)fontSize()); - if (obscured || !child.inside(x - child.x, y - child.y)) { + if (obscured /*|| !child.inside(x - child.x, y - child.y) FIXME FIXME */) { child.propagateDownward(name_, value2, true); } else try { found = true; @@ -718,9 +535,11 @@ public final class Box extends JS.Obj implements Callable { } finally { if (save_stop) child.set(STOP_UPWARD_PROPAGATION); else child.clear(STOP_UPWARD_PROPAGATION); } + /* FIXME FIXME if (child.inside(x - child.x, y - child.y)) if (name != null && name.equals("_Move")) obscured = true; else break; + */ } if (!obscured && !found) @@ -745,11 +564,11 @@ public final class Box extends JS.Obj implements Callable { for(int i=cur.treeSize() - 1; i>=0; i--) { Box child = cur.getChild(i); if (child == null) continue; // since this method is unsynchronized, we have to double-check - globalx += child.x; - globaly += child.y; + globalx += child.transform.e; + globaly += child.transform.f; if (child.test(VISIBLE) && child.inside(x - globalx, y - globaly)) { cur = child; continue OUTER; } - globalx -= child.x; - globaly -= child.y; + globalx -= child.transform.e; + globaly -= child.transform.f; } break; } @@ -759,16 +578,17 @@ public final class Box extends JS.Obj implements Callable { // Trivial Helper Methods (should be inlined) ///////////////////////////////////////// - void mark_for_repack() { REPACK(); } + public final int fontSize() { return font == null ? DEFAULT_FONT.pointsize : font.pointsize; } public Enumeration keys() { throw new Error("you cannot apply for..in to a " + this.getClass().getName()); } public Box getRoot() { return parent == null ? this : parent.getRoot(); } public Surface getSurface() { return Surface.fromBox(getRoot()); } - 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(); } - public int globalToLocalX(int x) { return parent == null ? x : parent.globalToLocalX(x - this.x); } - public int globalToLocalY(int y) { return parent == null ? y : parent.globalToLocalY(y - this.y); } - public int localToGlobalX(int x) { return parent == null ? x : parent.globalToLocalX(x + this.x); } - public int localToGlobalY(int y) { return parent == null ? y : parent.globalToLocalY(y + this.y); } + private final boolean packed() { return test(YAXIS) || test(XAXIS); } + Box nextPackedSibling() { Box b = nextSibling(); return b == null || (b.packed() && b.test(VISIBLE))?b:b.nextPackedSibling(); } + Box firstPackedChild() { Box b = getChild(0); return b == null || (b.packed() && b.test(VISIBLE))?b:b.nextPackedSibling(); } + public float globalToLocalX(float x) { return parent == null ? x : parent.globalToLocalX(x - transform.e); } + public float globalToLocalY(float y) { return parent == null ? y : parent.globalToLocalY(y - transform.f); } + public float localToGlobalX(float x) { return parent == null ? x : parent.globalToLocalX(x + transform.e); } + public float localToGlobalY(float y) { return parent == null ? y : parent.globalToLocalY(y + transform.f); } static short min(short a, short b) { if (a maxy) maxy = y; if (y < miny) miny = y; } + return this; } public void stroke(PixelBuffer buf, int color) { diff --git a/src/org/ibex/graphics/Surface.java b/src/org/ibex/graphics/Surface.java index ebf4670..165207f 100644 --- a/src/org/ibex/graphics/Surface.java +++ b/src/org/ibex/graphics/Surface.java @@ -179,8 +179,9 @@ public abstract class Surface implements Callable { // FEATURE: can we avoid creating objects here? protected final void PosChange(final int x, final int y) { Platform.Scheduler.add(new Callable() { public Object run(Object o) throws JSExn { - root.x = x; - root.y = y; + // FIXME + //root.x = x; + //root.y = y; root.putAndTriggerTrapsAndCatchExceptions(JSU.S("PosChange"), T); return null; }}); @@ -258,7 +259,6 @@ public abstract class Surface implements Callable { // make sure the root is properly sized do { abort = false; - root.pack(); if (syncRootBoxToSurface) { root.setWidth(root.minwidth, pendingWidth); root.setHeight(root.minheight, pendingHeight); @@ -280,6 +280,7 @@ public abstract class Surface implements Callable { } while(abort); int[][] dirt = dirtyRegions.flush(); + for(int i = 0; dirt != null && i < dirt.length; i++) { if (dirt[i] == null) continue; int x = dirt[i][0], y = dirt[i][1], w = dirt[i][2], h = dirt[i][3]; @@ -289,7 +290,7 @@ public abstract class Surface implements Callable { if (y+h > root.height) h = root.height - y; if (w <= 0 || h <= 0) continue; - root.render(0, 0, x, y, x + w, y + h, this.getPixelBuffer(), identity); + root.render(x, y, x + w, y + h, this.getPixelBuffer(), identity); getPixelBuffer().drawPicture(scarImage, 0, root.height - scarImage.height, x, y, x+w, y+h); if (abort) { diff --git a/src/org/ibex/plat/AWT.java b/src/org/ibex/plat/AWT.java index 27d213b..fb31bd9 100644 --- a/src/org/ibex/plat/AWT.java +++ b/src/org/ibex/plat/AWT.java @@ -297,7 +297,7 @@ public class AWT extends JVM { public void setMinimumSize(int minx, int miny, boolean resizable) { if (frame != null) frame.setResizable(resizable); } public void toBack() { if (window != null) window.toBack(); } public void toFront() { if (window != null) window.toFront(); } - public void setLocation() { window.setLocation(root.x, root.y); } + public void setLocation() { /*window.setLocation(root.x, root.y); FIXME */ } public void setTitleBarText(String s) { if (frame != null) frame.setTitle(s); } public void setIcon(Picture i) { if (frame != null) frame.setIconImage(((AWTPicture)i).i); } public void _setSize(int width, int height) { -- 1.7.10.4