From: megacz Date: Fri, 30 Jan 2004 07:42:10 +0000 (+0000) Subject: 2003/11/27 05:05:09 X-Git-Tag: RC3~310 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=0f94de16d032aa04fcfa50056f7964de2fcd2d58;p=org.ibex.core.git 2003/11/27 05:05:09 darcs-hash:20040130074210-2ba56-26bac58446febbedfdb454cc331ade435c22a120.gz --- diff --git a/src/org/xwt/Box.java b/src/org/xwt/Box.java index 280924c..ebd3d85 100644 --- a/src/org/xwt/Box.java +++ b/src/org/xwt/Box.java @@ -165,7 +165,7 @@ public final class Box extends JSScope { else if (wasinside && !isinside && getTrap("Leave") != null) putAndTriggerTraps("Leave", T); else if (wasinside && isinside && (mousex != oldmousex || mousey != oldmousey) && getTrap("Move")!= null) putAndTriggerTraps("Move", T); - for(Box b = getChild(numchildren - 1); b != null; b = b.prevSibling()) { + for(Box b = getChild(treeSize() - 1); b != null; b = b.prevSibling()) { 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; } @@ -363,9 +363,6 @@ public final class Box extends JSScope { public Enumeration keys() { throw new Error("you cannot apply for..in to a " + this.getClass().getName()); } - /** to be filled in by the Tree implementation */ - public int numchildren = 0; - protected boolean isTrappable() { return true; } public Object get(Object name) { if (name instanceof Number) @@ -403,7 +400,7 @@ public final class Box extends JSScope { 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 "numchildren": return redirect == null ? N(0) : redirect == this ? N(treeSize()) : redirect.get("numchildren"); case "minwidth": return N(minwidth); case "maxwidth": return N(maxwidth); case "minheight": return N(minheight); @@ -423,7 +420,6 @@ public final class Box extends JSScope { case "textcolor": value = N(stringToColor((String)value)); CHECKSET_INT(strokecolor); MARK_RESIZE; dirty(); 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; @@ -473,6 +469,12 @@ public final class Box extends JSScope { case "SizeChange": return; // prevent stuff from hitting the Hash case "childadded": return; // prevent stuff from hitting the Hash case "childremoved": return; // prevent stuff from hitting the Hash + case "thisbox": { + if (value != null) break; + if (parent != null) { parent.removeChild(parent.indexNode(this)); return; } + Surface surface = Surface.fromBox(this); + if (surface != null) surface.dispose(true); + } default: super.put(name, value); //#end } @@ -595,7 +597,7 @@ public final class Box extends JSScope { if (!cur.test(VISIBLE)) return 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--) { + 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; @@ -630,347 +632,44 @@ public final class Box extends JSScope { void clear(int mask) { flags &= ~mask; } boolean test(int mask) { return ((flags & mask) == mask); } - protected Box left = null; - protected Box right = null; - protected Box rootChild = null; - protected Box peerTree_parent = null; - // Tree Handling ////////////////////////////////////////////////////////////////////// - - private static boolean REDbool = false; - private static boolean BLACKbool = true; - - public final Box peerTree_leftmost() { for (Box p = this; ; p = p.left) if (p.left == null) return p; } - public final Box peerTree_rightmost() { for (Box p = this; ; p = p.right) if (p.right == null) return p; } - static Box peerTree_parent(Box p) { return (p == null)? null: p.peerTree_parent; } - - public void insertBeforeMe(Box cell) { left = cell; cell.peerTree_parent = this; cell.fixAfterInsertion(); } - public void insertAfterMe(Box cell) { right = cell; cell.peerTree_parent = this; cell.fixAfterInsertion(); } - - static boolean colorOf(Box p) { return (p == null) ? BLACKbool : p.test(BLACK); } - static void setColor(Box p, boolean c) { if (p != null) { if (c) p.set(BLACK); else p.clear(BLACK); } } - static Box leftOf(Box p) { return (p == null)? null: p.left; } - static Box rightOf(Box p) { return (p == null)? null: p.right; } - + // FIXME inefficient public final Box nextSibling() { - if (right != null) - return right.peerTree_leftmost(); - else { - Box p = peerTree_parent; - Box ch = this; - while (p != null && ch == p.right) { ch = p; p = p.peerTree_parent; } - return p; - } + int index = parent.indexNode(this); + if (index >= parent.treeSize() - 1) return null; + return parent.getChild(index + 1); } + // FIXME inefficient public final Box prevSibling() { - if (left != null) - return left.peerTree_rightmost(); - else { - Box p = peerTree_parent; - Box ch = this; - while (p != null && ch == p.left) { ch = p; p = p.peerTree_parent; } - return p; - } - } - - public void removeNode() { - - // handle case where we are only node - if (left == null && right == null && peerTree_parent == null) return; - - // if strictly internal, swap places with a successor - if (left != null && right != null) { - Box s = nextSibling(); - // To work nicely with arbitrary subclasses of Box, we don't want to - // just copy successor's fields. since we don't know what - // they are. Instead we swap positions in the tree. - swapPosition(this, s); - } - - // Start fixup at replacement node (normally a child). - // But if no children, fake it by using self - - if (left == null && right == null) { - - if (test(BLACK)) fixAfterDeletion(); - - // Unlink (Couldn't before since fixAfterDeletion needs peerTree_parent ptr) - - if (peerTree_parent != null) { - if (this == peerTree_parent.left) - peerTree_parent.left = null; - else if (this == peerTree_parent.right) - peerTree_parent.right = null; - peerTree_parent = null; - } - - } - else { - Box replacement = left; - if (replacement == null) replacement = right; - - // link replacement to peerTree_parent - replacement.peerTree_parent = peerTree_parent; - - if (peerTree_parent == null) parent.rootChild = replacement; - else if (this == peerTree_parent.left) peerTree_parent.left = replacement; - else peerTree_parent.right = replacement; - - left = null; - right = null; - peerTree_parent = null; - - // fix replacement - if (test(BLACK)) replacement.fixAfterDeletion(); - - } - } - - /** - * Swap the linkages of two nodes in a tree. - * Return new root, in case it changed. - **/ - void swapPosition(Box x, Box y) { - - /* Too messy. TODO: find sequence of assigments that are always OK */ - - Box px = x.peerTree_parent; - boolean xpl = px != null && x == px.left; - Box lx = x.left; - Box rx = x.right; - - Box py = y.peerTree_parent; - boolean ypl = py != null && y == py.left; - Box ly = y.left; - Box ry = y.right; - - if (x == py) { - y.peerTree_parent = px; - if (px != null) if (xpl) px.left = y; else px.right = y; - x.peerTree_parent = y; - if (ypl) { - y.left = x; - y.right = rx; if (rx != null) rx.peerTree_parent = y; - } - else { - y.right = x; - y.left = lx; if (lx != null) lx.peerTree_parent = y; - } - x.left = ly; if (ly != null) ly.peerTree_parent = x; - x.right = ry; if (ry != null) ry.peerTree_parent = x; - } - else if (y == px) { - x.peerTree_parent = py; - if (py != null) if (ypl) py.left = x; else py.right = x; - y.peerTree_parent = x; - if (xpl) { - x.left = y; - x.right = ry; if (ry != null) ry.peerTree_parent = x; - } - else { - x.right = y; - x.left = ly; if (ly != null) ly.peerTree_parent = x; - } - y.left = lx; if (lx != null) lx.peerTree_parent = y; - y.right = rx; if (rx != null) rx.peerTree_parent = y; - } - else { - x.peerTree_parent = py; if (py != null) if (ypl) py.left = x; else py.right = x; - x.left = ly; if (ly != null) ly.peerTree_parent = x; - x.right = ry; if (ry != null) ry.peerTree_parent = x; - - y.peerTree_parent = px; if (px != null) if (xpl) px.left = y; else px.right = y; - y.left = lx; if (lx != null) lx.peerTree_parent = y; - y.right = rx; if (rx != null) rx.peerTree_parent = y; - } - - boolean c = x.test(BLACK); - if (y.test(BLACK)) x.set(BLACK); else x.clear(BLACK); - if (c) y.set(BLACK); else y.clear(BLACK); - - if (parent.rootChild == x) parent.rootChild = y; - else if (parent.rootChild == y) parent.rootChild = x; + int index = parent.indexNode(this); + if (index <= 0) return null; + return parent.getChild(index - 1); } - void rotateLeft() { - Box r = right; - right = r.left; - if (r.left != null) r.left.peerTree_parent = this; - r.peerTree_parent = peerTree_parent; - if (peerTree_parent == null) parent.rootChild = r; - else if (peerTree_parent.left == this) peerTree_parent.left = r; - else peerTree_parent.right = r; - r.left = this; - peerTree_parent = r; - } - - void rotateRight() { - Box l = left; - left = l.right; - if (l.right != null) l.right.peerTree_parent = this; - l.peerTree_parent = peerTree_parent; - if (peerTree_parent == null) parent.rootChild = l; - else if (peerTree_parent.right == this) peerTree_parent.right = l; - else peerTree_parent.left = l; - l.right = this; - peerTree_parent = l; - } - - void fixAfterInsertion() { - clear(BLACK); - Box x = this; - - while (x != null && x != parent.rootChild && !x.peerTree_parent.test(BLACK)) { - if (peerTree_parent(x) == leftOf(peerTree_parent(peerTree_parent(x)))) { - Box y = rightOf(peerTree_parent(peerTree_parent(x))); - if (colorOf(y) == REDbool) { - setColor(peerTree_parent(x), BLACKbool); - setColor(y, BLACKbool); - setColor(peerTree_parent(peerTree_parent(x)), REDbool); - x = peerTree_parent(peerTree_parent(x)); - } - else { - if (x == rightOf(peerTree_parent(x))) { - x = peerTree_parent(x); - x.rotateLeft(); - } - setColor(peerTree_parent(x), BLACKbool); - setColor(peerTree_parent(peerTree_parent(x)), REDbool); - if (peerTree_parent(peerTree_parent(x)) != null) - peerTree_parent(peerTree_parent(x)).rotateRight(); - } - } - else { - Box y = leftOf(peerTree_parent(peerTree_parent(x))); - if (colorOf(y) == REDbool) { - setColor(peerTree_parent(x), BLACKbool); - setColor(y, BLACKbool); - setColor(peerTree_parent(peerTree_parent(x)), REDbool); - x = peerTree_parent(peerTree_parent(x)); - } - else { - if (x == leftOf(peerTree_parent(x))) { - x = peerTree_parent(x); - x.rotateRight(); - } - setColor(peerTree_parent(x), BLACKbool); - setColor(peerTree_parent(peerTree_parent(x)), REDbool); - if (peerTree_parent(peerTree_parent(x)) != null) - peerTree_parent(peerTree_parent(x)).rotateLeft(); - } - } - } - parent.rootChild.set(BLACK); - } - - /** From CLR **/ - void fixAfterDeletion() { - Box x = this; - while (x != parent.rootChild && colorOf(x) == BLACKbool) { - if (x == leftOf(peerTree_parent(x))) { - Box sib = rightOf(peerTree_parent(x)); - if (colorOf(sib) == REDbool) { - setColor(sib, BLACKbool); - setColor(peerTree_parent(x), REDbool); - peerTree_parent(x).rotateLeft(); - sib = rightOf(peerTree_parent(x)); - } - if (colorOf(leftOf(sib)) == BLACKbool && colorOf(rightOf(sib)) == BLACKbool) { - setColor(sib, REDbool); - x = peerTree_parent(x); - } - else { - if (colorOf(rightOf(sib)) == BLACKbool) { - setColor(leftOf(sib), BLACKbool); - setColor(sib, REDbool); - sib.rotateRight(); - sib = rightOf(peerTree_parent(x)); - } - setColor(sib, colorOf(peerTree_parent(x))); - setColor(peerTree_parent(x), BLACKbool); - setColor(rightOf(sib), BLACKbool); - peerTree_parent(x).rotateLeft(); - x = parent.rootChild; - } - } - else { - Box sib = leftOf(peerTree_parent(x)); - if (colorOf(sib) == REDbool) { - setColor(sib, BLACKbool); - setColor(peerTree_parent(x), REDbool); - peerTree_parent(x).rotateRight(); - sib = leftOf(peerTree_parent(x)); - } - if (colorOf(rightOf(sib)) == BLACKbool && colorOf(leftOf(sib)) == BLACKbool) { - setColor(sib, REDbool); - x = peerTree_parent(x); - } - else { - if (colorOf(leftOf(sib)) == BLACKbool) { - setColor(rightOf(sib), BLACKbool); - setColor(sib, REDbool); - sib.rotateLeft(); - sib = leftOf(peerTree_parent(x)); - } - setColor(sib, colorOf(peerTree_parent(x))); - setColor(peerTree_parent(x), BLACKbool); - setColor(leftOf(sib), BLACKbool); - peerTree_parent(x).rotateRight(); - x = parent.rootChild; - } - } - } - setColor(x, BLACKbool); + public final Box getChild(int i) { + if (i < 0) return null; + if (i >= treeSize()) return null; + return (Box)getNode(i); } + public final int getIndexInParent() { return parent == null ? 0 : parent.indexNode(this); } // Tree Manipulation ///////////////////////////////////////////////////////////////////// - /** remove this node from its parent; INVARIANT: whenever the parent of a node is changed, remove() gets called. */ - public void remove() { - if (parent == null) { - Surface surface = Surface.fromBox(this); - if (surface != null) surface.dispose(true); - return; - } else { - parent.numchildren--; - } - Box oldparent = parent; - if (oldparent == null) return; + /** remove the i^th child */ + public void removeChild(int i) { + Box b = getChild(i); + MARK_REFLOW_b; + b.dirty(); + b.clear(MOUSEINSIDE); + deleteNode(i); + b.parent = null; MARK_REFLOW; - dirty(); - clear(MOUSEINSIDE); - removeNode(); - parent = null; - if (oldparent != null) { Box b = oldparent; MARK_REFLOW_b; } - if (oldparent != null) oldparent.putAndTriggerTraps("childremoved", this); - } - - /** Returns ith child */ - public Box getChild(int i) { - // FIXME: store numleft and numright in the tree - Box left = rootChild; - if (left == null) return null; - while (left.left != null) left = left.left; - for(; i > 0; i--) left = left.nextSibling(); - return left; + putAndTriggerTraps("childremoved", b); } - /** Returns our index in our parent */ - public int getIndexInParent() { - // FIXME: store numleft and numright in the tree - if (peerTree_parent == null) return left == null ? 0 : left.numPeerChildren() + 1; - else if (peerTree_parent.left == this) return peerTree_parent.getIndexInParent() - 1; - else if (peerTree_parent.right == this) return peerTree_parent.getIndexInParent() + 1; - else throw new Error("we're not a child of our parent!"); - } - - public int numPeerChildren() { - return (left == null ? 0 : left.numPeerChildren() + 1) + (right == null ? 0 : right.numPeerChildren() + 1); - } - public void put(int i, Object value) { if (i < 0) return; @@ -992,9 +691,9 @@ public final class Box extends JSScope { } } else if (value == null) { - if (i < 0 || i > numchildren) return; + if (i < 0 || i > treeSize()) return; Box b = getChild(i); - b.remove(); + removeChild(i); putAndTriggerTraps("childremoved", b); } else { @@ -1015,16 +714,9 @@ public final class Box extends JSScope { return; } - b.remove(); + if (b.parent != null) b.parent.removeChild(b.parent.indexNode(b)); + insertNode(i, b); b.parent = this; - numchildren++; - - Box before = getChild(i); - if (before == null) { - if (rootChild == null) rootChild = b; - else rootChild.peerTree_rightmost().insertAfterMe(b); - } - else before.insertBeforeMe(b); // need both of these in case child was already uncalc'ed MARK_REFLOW_b; diff --git a/src/org/xwt/Surface.java b/src/org/xwt/Surface.java index fb9585a..ac2a837 100644 --- a/src/org/xwt/Surface.java +++ b/src/org/xwt/Surface.java @@ -298,7 +298,7 @@ public abstract class Surface extends PixelBuffer { this.root = root; Surface old = fromBox(root); if (old != null) old.dispose(false); - else root.remove(); + else root.put("thisbox", null); // make sure the root is properly sized do { abort = false; root.reflow(root.width, root.height); } while(abort); diff --git a/src/org/xwt/Template.java b/src/org/xwt/Template.java index 2921cde..2dbaa3b 100644 --- a/src/org/xwt/Template.java +++ b/src/org/xwt/Template.java @@ -126,7 +126,7 @@ public class Template { for (int i=0; children != null && i