From 3d8c42500631568e2eda5a869403f72c8a0e361a Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 07:04:24 +0000 Subject: [PATCH] 2003/08/12 10:03:22 darcs-hash:20040130070424-2ba56-57f66f13441fdde8203aae4c47c7614bdf570bd7.gz --- src/org/xwt/Box.java.pp | 218 ++++++++++++++++++++++++++++++----------------- 1 file changed, 140 insertions(+), 78 deletions(-) diff --git a/src/org/xwt/Box.java.pp b/src/org/xwt/Box.java.pp index affcbb0..822f7a0 100644 --- a/src/org/xwt/Box.java.pp +++ b/src/org/xwt/Box.java.pp @@ -3,6 +3,9 @@ package org.xwt; // **** This file must be preprocessed before compilation **** +// RULE: coordinates on non-static methods are ALWAYS relative to the +// upper-left hand corner of this + // FIXME: align // FIXME use bitfields // FIXME fixedaspect @@ -143,15 +146,17 @@ public final class Box extends JS.Scope { // FIXME: rethink /** Adds the intersection of (x,y,w,h) and the node's current actual geometry to the Surface's dirty list */ - public final void dirty() { dirty(x, y, width, height); } + public final void dirty() { dirty(0, 0, width, height); } public final void dirty(int x, int y, int w, int h) { for(Box cur = this; cur != null; cur = cur.parent) { - w = min(x + w, this.x + this.width) - max(x, this.x); - h = min(y + h, this.y + this.height) - max(y, this.y); - x = max(x, this.x); - y = max(y, this.y); + 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.surface != null) cur.surface.dirty(x, y, w, h); + x += cur.x; + y += cur.y; } } @@ -172,19 +177,18 @@ public final class Box extends JS.Scope { if (!wasinside && !isinside) return; if (traps == null) { } - else if (!wasinside && isinside && traps.get("Enter") != null) put("Enter", this); - else if (wasinside && !isinside && traps.get("Leave") != null) put("Leave", this); - else if (wasinside && isinside && (mousex != oldmousex || mousey != oldmousey) && traps.get("Move") != null) put("Move", this); + else if (!wasinside && isinside && traps.get("Enter") != null) put("Enter", Boolean.TRUE); + else if (wasinside && !isinside && traps.get("Leave") != null) put("Leave", Boolean.TRUE); + else if (wasinside && isinside && (mousex != oldmousex || mousey != oldmousey) && traps.get("Move") != null) put("Move", Boolean.TRUE); if (isinside && cursor != null) getRoot().cursor = cursor; // if the mouse has moved into our padding region, it is considered 'outside' all our children - if (!(mousex >= x + hpad && mousey >= y + vpad && - mousex < x + width - hpad && mousey < y + height + vpad)) forceleave = true; + if (!(mousex >= hpad && mousey >= vpad && mousex < width - hpad && mousey < height + vpad)) forceleave = true; for(Box b = getChild(numChildren() - 1); b != null; b = b.prevSibling()) { - b.Move(oldmousex, oldmousey, mousex, mousey, forceleave); - if (b.inside(mousex, mousey)) forceleave = true; + b.Move(oldmousex - b.x, oldmousey - b.y, mousex - b.x, mousey - b.y, forceleave); + if (b.inside(mousex - b.x, mousey - b.y)) forceleave = true; } } @@ -199,7 +203,8 @@ public final class Box extends JS.Scope { /** Checks if the Box's size has changed, dirties it if necessary, and makes sure childrens' sizes are up to date */ void repack() { - if (!needs_reflow || numChildren() == 0) return; + if (!needs_reflow) return; + if (numChildren() == 0) { contentwidth = minwidth; contentheight = minheight; return; } // --- Phase 0 ---------------------------------------------------------------------- // recurse @@ -211,25 +216,26 @@ public final class Box extends JS.Scope { // --- Phase 1 ---------------------------------------------------------------------- // assign children to their row/column positions (assuming constrained columns) if ((rows == 0 && cols == 0) || (rows != 0 && cols != 0)) throw new Error("rows == " + rows + " cols == " + cols); - //#repeat x/y y/x width/height col/row row/col cols/rows colspan/rowspan colWidth/rowHeight numRowsInCol/numColsInRow INNER/INNER2 maxwidth/maxheight minwidth/minheight contentwidth/contentheight colMaxWidth/rowMaxHeight OUTER/OUTER2 INNER/INNER2 + //#repeat x/y y/x width/height col/row row/col cols/rows rows/cols colspan/rowspan rowspan/colspan colWidth/rowHeight numRowsInCol/numColsInRow INNER/INNER2 maxwidth/maxheight minwidth/minheight contentwidth/contentheight colMaxWidth/rowMaxHeight OUTER/OUTER2 INNER/INNER2 if (rows == 0) { int[] numRowsInCol = new int[cols]; // the number of cells occupied in each column Box child = getChild(0); - for(child = child.nextSibling(); child != null && (child.absolute || child.invisible); child = child.nextSibling()); + for(; child != null && (child.absolute || child.invisible); child = child.nextSibling()); OUTER: for(int row=0; child != null; row++) { for(int col=0; child != null && col < cols;) { INNER: while(true) { // scan across the row, looking for an unoccupied gap at least as wide as the child while(col < cols && numRowsInCol[col] > row) col++; - for(int i=col; i < cols && i < col + child.colspan; i++) + for(int i=col; i < cols && i < col + min(cols, child.colspan); i++) if (numRowsInCol[col] > row) { col = i + 1; continue INNER; } break; } - if (col + child.colspan >= cols) break; - for(int i=col; i < col + child.colspan; i++) numRowsInCol[i] += child.rowspan; + if (col + min(cols, child.colspan) > cols) break; + for(int i=col; i < col + min(cols, child.colspan); i++) numRowsInCol[i] += child.rowspan; child.col = col; child.row = row; - col += child.colspan; - for(child = child.nextSibling(); child != null && (child.absolute || child.invisible); child = child.nextSibling()); + col += min(cols, child.colspan); + child = child.nextSibling(); + for(; child != null && (child.absolute || child.invisible); child = child.nextSibling()); } } } @@ -237,14 +243,18 @@ public final class Box extends JS.Scope { // --- Phase 2 ---------------------------------------------------------------------- // compute the min/max sizes of the columns and rows and set our contentwidth - //#repeat x/y y/x width/height col/row cols/rows colspan/rowspan colWidth/rowHeight maxwidth/maxheight minwidth/minheight contentwidth/contentheight colMaxWidth/rowMaxHeight - contentwidth = 0; - LENGTH[] colWidth = new LENGTH[(cols == 0 ? (getChild(numChildren() - 1).col + 1) : cols)]; + //#repeat x/y y/x width/height col/row cols/rows colspan/rowspan colWidth/rowHeight maxwidth/maxheight minwidth/minheight contentwidth/contentheight colMaxWidth/rowMaxHeight numCols/numRows hpad/vpad + contentwidth = 2 * hpad; + int numCols = cols; + if (numCols == 0) + for(Box child = getChild(0); child != null; child = child.nextSibling()) + numCols = max(numCols, child.col + child.colspan); + LENGTH[] colWidth = new LENGTH[numCols]; for(Box child = getChild(0); child != null; child = child.nextSibling()) if (!(child.absolute || child.invisible)) colWidth[child.col] = max(colWidth[child.col], child.contentwidth / child.colspan); - for(int col=0; col 0) while(slack > 0) { // FEATURE: inefficient int startslack = slack; - int increment = max(1, slack / (cols == 0 ? (getChild(numChildren() - 1).col + 1) : cols)); - for(int col=0; col < (cols == 0 ? (getChild(numChildren() - 1).col + 1) : cols) && slack > 0; col++) { + int increment = max(1, slack / numCols); + for(int col=0; col < numCols && slack > 0; col++) { slack += colWidth[col]; colWidth[col] = min(colMaxWidth[col], colWidth[col] + increment); slack -= colWidth[col]; @@ -330,17 +347,24 @@ public final class Box extends JS.Scope { // --- Phase 4 ---------------------------------------------------------------------- // assign children's new sizes and positions and recurse for(Box child = getChild(0); child != null; child = child.nextSibling()) { - if (child.absolute || child.invisible) continue; - int diff; - - //#repeat x/y y/x width/height col/row cols/rows colspan/rowspan colWidth/rowHeight maxwidth/maxheight minwidth/minheight contentwidth/contentheight colMaxWidth/rowMaxHeight hshrink/vshrink marginWidth/marginHeight - child.width = 0; for(int i=child.col; i=b && a>=c) return a; else if (b>=c && b>=a) return b; else return c; } static final int bound(int a, int b, int c) { if (c < b) return c; if (a > b) return a; return b; } - final boolean inside(int x, int y) { return (!invisible && x >= this.x && y >= this.y && x < this.x + width && y < this.y + height); } + final boolean inside(int x, int y) { return (!invisible && x >= 0 && y >= 0 && x < width && y < height); } /** figures out what box in this subtree of the Box owns the pixel at x,y relitave to the Surface */ public static Box whoIs(Box cur, int x, int y) { + if (cur.parent != null) throw new Error("whoIs may only be invoked on the root box of a surface"); + int globalx = 0; + int globaly = 0; + // WARNING: this method is called from the event-queueing // thread -- it may run concurrently with ANY part of XWT, and // is UNSYNCHRONIZED for performance reasons. BE CAREFUL // HERE. if (cur.invisible) return null; - if (!cur.inside(x,y)) return cur.parent == null ? cur : null; + if (!cur.inside(x - globalx, y - globaly)) return cur.parent == null ? cur : null; OUTER: while(true) { for(int i=cur.numChildren() - 1; i>=0; i--) { Box child = cur.getChild(i); if (child == null) continue; // since this method is unsynchronized, we have to double-check - if (!child.invisible && child.inside(x,y)) { cur = child; continue OUTER; } + globalx += child.x; + globaly += child.y; + if (!child.invisible && child.inside(x - globalx, y - globaly)) { cur = child; continue OUTER; } + globalx -= child.x; + globaly -= child.y; } break; } @@ -913,6 +944,8 @@ public final class Box extends JS.Scope { Log.log(this, "invalid color " + s); return; } + else if (SVG.colors.get(s) != null) + newcolor = 0xFF000000 | ((Integer)SVG.colors.get(s)).intValue(); // FIXME put named colors back in if (newcolor == b.fillcolor) return; b.fillcolor = newcolor; @@ -921,6 +954,15 @@ public final class Box extends JS.Scope { }); //#end + specialBoxProperties.put("color", new SpecialBoxProperty() { + public Object get(Box b) { return b.get("fillcolor"); } + public void put(Box b, Object value) { b.put("fillcolor", value); } + }); + specialBoxProperties.put("textcolor", new SpecialBoxProperty() { + public Object get(Box b) { return b.get("strokecolor"); } + public void put(Box b, Object value) { b.put("strokecolor", value); } + }); + specialBoxProperties.put("text", new SpecialBoxProperty() { public Object get(Box b) { return b.text; } public void put(Box b, Object value) { @@ -1006,12 +1048,18 @@ public final class Box extends JS.Scope { return new Integer(b.x); } public void put(Box b, Object value) { - b.x = stoi(value); + if (!b.absolute) return; + int x = stoi(value); + if (x == b.x) return; + b.dirty(); + b.x = x; if (b.parent == null && b.surface != null) { // FIXME this gets hosed by the #repeat //b.surface.setLocation(b.x, b.y); b.surface.centerSurfaceOnRender = false; } + MARK_FOR_REFLOW_b; + b.dirty(); } }); //#end @@ -1084,6 +1132,7 @@ public final class Box extends JS.Scope { boolean newabsolute = stob(value); if (newabsolute == b.absolute) return; b.absolute = newabsolute; + if (b.absolute) { b.x = 0; b.y = 0; } if (b.parent != null) MARK_FOR_REFLOW_b_parent; } }); @@ -1100,6 +1149,7 @@ public final class Box extends JS.Scope { } else { b.minwidth = b.maxwidth = b.image.getWidth(); b.minheight = b.maxheight = b.image.getHeight(); + MARK_FOR_REFLOW_b; } } b.dirty(); @@ -1112,6 +1162,7 @@ public final class Box extends JS.Scope { public void put(Box b, Object value) { if (b.surface == null || b.parent == null) return; b.put("x", new Integer(stoi(value) - stoi(get(b.parent)))); + MARK_FOR_REFLOW_b; } }); //#end @@ -1132,7 +1183,13 @@ public final class Box extends JS.Scope { //#repeat mousex/mousey x/y specialBoxProperties.put("mousex", new SpecialBoxProperty() { - public Object get(Box b) { return new Integer(b.getRoot().surface == null ? 0 : b.getRoot().surface.mousex - b.x); } + public Object get(Box b) { + Surface surface = b.getRoot().surface; + if (surface == null) return new Integer(0); + int mousex = surface.mousex; + for(Box cur = b; cur != null && cur.parent != null; cur = cur.parent) mousex -= cur.x; + return new Integer(mousex); + } }); //#end @@ -1155,10 +1212,15 @@ public final class Box extends JS.Scope { public void put(String name, Box b, Object value) { Surface surface = b.getRoot().surface; if (surface == null) return; + int mousex = surface.mousex; + int mousey = surface.mousey; + for(Box c = b.parent; c != null && c.parent != null; c = c.parent) { + mousex -= c.x; + mousey -= c.y; + } for(Box c = b.prevSibling(); c != null; c = c.prevSibling()) { - Box siblingChild = whoIs(c, surface.mousex, surface.mousey); - if (siblingChild != null) { - siblingChild.put(name, value); + if (c.inside(mousex - c.x, mousey - c.y)) { + c.put(name, value); return; } } -- 1.7.10.4