Revision: 3608
          http://vexi.svn.sourceforge.net/vexi/?rev=3608&view=rev
Author:   clrg
Date:     2009-08-18 10:10:29 +0000 (Tue, 18 Aug 2009)

Log Message:
-----------
- Only fire Leave/Enter when necessary during assignToParent
- Fix add/clear not working on redirects
- Throw exceptions when calling child control methods on a box with a null 
redirect
- Documentation updates and trivial code changes

Modified Paths:
--------------
    trunk/core/org.vexi.core/src/org/vexi/core/Box.jpp

Modified: trunk/core/org.vexi.core/src/org/vexi/core/Box.jpp
===================================================================
--- trunk/core/org.vexi.core/src/org/vexi/core/Box.jpp  2009-08-18 00:56:54 UTC 
(rev 3607)
+++ trunk/core/org.vexi.core/src/org/vexi/core/Box.jpp  2009-08-18 10:10:29 UTC 
(rev 3608)
@@ -90,12 +90,13 @@
  * </dl>
  * 
  * <h4>Placing</h4>
- * <p>The width of a box is assigned width according to the following 
rules:</p>
+ * <p>The width of a box is assigned width according to the 3 following rules, 
in strict order of priority:</p>
  * <ol><li>It's width is never greater than its maxwidth</li>
- *     <li>It's width is never less than its contentwidth, with the exception 
of #4</li>
- *     <li>If a box is shrunk, the will always be set to contentwidth, with 
the exception of #4</li>
- *     <li>If a box's maxwidth is less than it's contentwidth, the maxwidth is 
used</li></ol>
+ *     <li>It's width will not be less than its contentwidth</li>
+ *     <li>If a box is shrunk, the width be set to contentwidth</li></ol>
  * 
+ * <p><b>NB:</b> <em>if a box's maxwidth is less than it's contentwidth, the 
maxwidth is used</em></p>
+ * 
  * <p>Boxes are placed in order in the space allocated to them by the parent 
box:</p>
  * <dl>
  *   <dt><code>"place"</code> or <code>"layer"</code></dt>
@@ -344,9 +345,9 @@
     // 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 */
     private final void dirtyInPlace(boolean clean) { if (clean) { dirty(); 
clear(PLACE_CLEAN); } }
-    private final void dirty() { dirty(0, 0, width, height); }
-    private final void dirty(int x, int y, int w, int h) {
-        for (Box cur = this; cur != null; cur = cur.parent) {
+    private final void dirty() { dirty(this, 0, 0, width, height); }
+    private static final void dirty(Box b, int x, int y, int w, int h) {
+        for (Box cur = b; cur != null; cur = cur.parent) {
             if (!cur.test(DISPLAY)) return;
             // get around sub-sampling of enlarged textures
             if (cur.texture != null && !cur.test(TILE_IMAGE)) {
@@ -886,7 +887,9 @@
                 buf.drawPicture(texture, cx1, cy1, cx2, cy2, sx1, sy1, sx2, 
sy2);
             }
         }
- 
+        
+        // REMARK: text.font may still be null at this point so
+        // cannot use text.isEmpty() but instead use text.width
         if (text.width != 0) {
             int gap_x = width - text.width;
             int gap_y = height - text.height;
@@ -1167,7 +1170,6 @@
         
         // REMARK: anything from here on in is a partial interruption relative
         // to this box so we can not call propagateLeave() directly upon it
-        
         int i;
         boolean interrupted = false;
         
@@ -1376,17 +1378,27 @@
             switch (args.length) {
             case 0:
                 //#switch(JSU.toString(method))
-                case "forcereflow": reflow(); return null;
+                case "forcereflow":
+                    reflow();
+                    return null;
                 case "clear":
-                    for (int i = JSU.toInt(get(SC_numchildren))-1; i>=0; i--)
+                    if (redirect==null) {
+                        throw new JSExn("Can not call Box."+method+"() on a 
box with a null redirect");
+                    }
+                    for (int i = JSU.toInt(get(SC_numchildren))-1; i>=0; i--) {
                         put(i, null);
+                    }
                     return null;
                 //#end
                 break;
             case 1:
                 //#switch(JSU.toString(method))
                 case "add":
-                    put(treeSize(), args[0]); return null;
+                    if (redirect==null) {
+                        throw new JSExn("Can not call Box."+method+"() on a 
box with a null redirect");
+                    }
+                    put(getAndTriggerTraps(SC_numchildren), args[0]);
+                    return null;
                 case "distanceto":
                     try {
                         return new DistanceTo(this, (Box)args[0]);
@@ -1394,8 +1406,10 @@
                         throw new JSExn("Cannot call Box."+method+"() with 
non-box argument");
                     }
                 case "indexof":
+                    if (redirect==null) {
+                        throw new JSExn("Can not call Box."+method+"() on a 
box with a null redirect");
+                    }
                     try {
-                        // FIXME: test for numchildren trap on redirects
                         Box b = (Box)args[0];
                         Box p = this;
                         while (b.parent != p) {
@@ -1431,16 +1445,18 @@
         }
         boolean isBoxMethod = false;
         //#switch(JSU.toString(method))
+        case "add":         isBoxMethod = true;
         case "clear":       isBoxMethod = true;
+        case "distanceto":  isBoxMethod = true;
         case "forcereflow": isBoxMethod = true;
-        case "add":         isBoxMethod = true;
-        case "distanceto":  isBoxMethod = true;
         case "indexof":     isBoxMethod = true;
         case "sendEvent":   isBoxMethod = true;
         //#end
-        if (isBoxMethod)
+        if (isBoxMethod) {
             throw new JSExn("Incorrect number of arguments for Box method 
"+method+"()");
-        else throw new JSExn("Box method not found: "+method+"()");
+        } else {
+            throw new JSExn("Box method not found: "+method+"()");
+        }
     }
 
     /** implements reading from box properties in JS */
@@ -1448,7 +1464,7 @@
         // integer properties translate to box children
         if (JSU.isInt(name)) return get(JSU.toInt(name));
 
-        /*
+        /* FEATURE: paths
         case "path":
             if (path != null) return JSU.S(path.toString());
             String ret = "";
@@ -1464,23 +1480,50 @@
          * <p>The vexi box is a fundamental component from which
          * user interfaces are composed.</p>
          * */
+        
         
/*****************************************************************************************/
+        
         /*...@section(Rendering) The rendering properties affect what the box 
looks like visually.*/
+
+        /* <p>A box will draw itself on-screen filled with the color or 
imagespecified by this
+         * property.</p>
+         * 
+         * <p>If the value is a stream, Vexi will try to load the stream as an 
image with one of
+         * the supported file extensions.  The image will then be rendered in 
the on-screen area
+         * represented by the box according to it's <code>tile</code> 
property.  If the image
+         * fails to load, the error will be re-put to the <code>fill</code> 
property.</p>
+         * 
+         * <p>If the value is a 5-character hex string (#RGB), 7-character hex 
string (#RRGGBB),
+         * 9-character hex string (#AARRGGBB), a box's fill color will be set 
to that color.</p>
+         * 
+         * <p>If the value is one of the <a 
href="http://www.color.org/ICC-1A_1999-04.PDF"; 
+         * target="_top">ICC</a> colors (the same set of color names supported 
by SVG), the box's
+         * fill color is set to that color.</p>
+         * 
+         * <p>If the value is null, the fill color will be set to clear 
(#00000000).</p>
+         * 
+         * @initial_value(null)
+         * @type(String<br/>Stream)
+         * */
         case "fill": if (texture == null) return 
JSU.S(Color.colorToString(fillcolor)); return texture.stream;
+        
         /* <p>When an object is written to this property, its stream is read 
using the 
          * <a href="http://www.freetype.org/"; target="_top">freetype2 
library</a>, and the
          * resulting font is used to render the box's text.</p>
          * 
          * @type(Stream)
          * @initial_value(vexi.ui.font.vera)
-         * @nofollow */
+         * @nofollow
+         * */
         case "font": return text.font.stream;
+        
         /* <p>The size (in points) to render the text.</p>
          * 
          * @type(Number)
          * @initial_value(10)
          * */
         case "fontsize": return Text.sizeToJS(text.pointsize);
+        
         /* 
          * The text of a box. Visually null renders the same as the text to "" 
(i.e as nothing).
          * 
@@ -1488,7 +1531,8 @@
          * @type(String)
          * @nofollow
          * */
-        case "text": return text.str; 
+        case "text": return text.str;
+        
         /* <p>If the value is a 5-character hex string (#RGB), 7-character hex 
string (#RRGGBB),
          * 9-character hex string (#AARRGGBB), a box's text color will be set 
to that color.</p>
          * 
@@ -1502,6 +1546,7 @@
          * @type(String)
          * */
         case "textcolor": return JSU.S(Color.colorToString(text.color));
+        
         /* <p>This property can be set to any of the values specified for 
textcolor. If the value
          * written is a stream then it will interpreted as a PNG, GIF, or JPEG 
image, which will
          * become the texture for the box. The box's minwidth and minheight 
properties will be
@@ -1553,12 +1598,14 @@
          * @initial_value("pack")
          * */
         case "layout": return test(PACK) ? SC_pack : (test(CLIP) ? SC_place : 
SC_layer);
-        /* The number of children a box has. 
+        
+        /* <p><em>Read only</em> reflecting the number of children a box 
has.</p>
          * 
          * @initial_value(varies,code=false)
          * @type(Number)
          * */
         case "numchildren": return redirect == null ? NC_0 : redirect == this 
? JSU.N(treeSize()) : redirect.getAndTriggerTraps(SC_numchildren);
+        
         /* <p>The direction the children are layed out in the box when 
<code>layout="pack"</code>.
          * Valid values are <code>"horizontal"</code> or 
<code>"vertical"</code>.</p>
          * 
@@ -1566,13 +1613,21 @@
          * @initial_value("horizontal")
          * */
         case "orient": return test(ORIENT) ? SC_horizontal : SC_vertical;
-        /* <p>Writing to this property sets a box's redirect target. This 
property cannot be read
-         * from, and can only be written to once.</p>
+        
+        /* <p>Writing to this property sets a box's redirect target. Reading 
from this property
+         * will return a boolean instead of the redirect target - 
<code>true</code> if redirect
+         * target is a box, <code>false</code> if it is <code>null</code>.</p>
          * 
+         * <p>A box's redirect target must be a descendent of the box.  An 
error will be thrown
+         * if it is not.</p> 
+         * 
          * @initial_value(thisbox)
          * @type(Box)
          * */
-        case "redirect": return redirect == null ? null : redirect == this ? 
JSU.T : redirect.getAndTriggerTraps(SC_redirect);
+        case "redirect":
+            return redirect == null ? null :
+                redirect == this ? JSU.T : 
redirect.getAndTriggerTraps(SC_redirect);
+        
         /* <p>Add a new child to the end of the box's children It is the 
equivalent of the
          * following VexiScript:</p>
          * <pre>box[box.numchildren] = child;</pre>
@@ -1581,15 +1636,25 @@
          * @param(b)
          * @return(null)
          * */
-        case "add": return METHOD;
-        /* <p>Clears a box of its children:</p>
+        case "add":
+            if (redirect==null) {
+                throw new JSExn("Can not call Box."+JSU.toString(name)+"() on 
a box with a null redirect");
+            }
+            return redirect == this ? METHOD : 
redirect.getAndTriggerTraps(SC_add);
+        
+        /* <p>Clear a box of its children:</p>
          * <pre>while (box.numchildren) box[0] = null;</pre>
          * 
          * @method
          * @param()
          * @return(null)
          * */
-        case "clear": return METHOD;
+        case "clear":
+            if (redirect==null) {
+                throw new JSExn("Can not call Box."+JSU.toString(name)+"() on 
a box with a null redirect");
+            }
+            return redirect == this ? METHOD : 
redirect.getAndTriggerTraps(SC_clear);
+        
         /* <p>Returns the index of childbox within a box. If childbox is not 
an immediate child of
          * the box, or an immediate child of the box's redirect, then the 
function returns -1.</p>
          * 
@@ -1597,7 +1662,12 @@
          * @param(b)
          * @return(Number)
          * */
-        case "indexof": return redirect == this ? METHOD : 
redirect.getAndTriggerTraps(SC_indexof);
+        case "indexof":
+            if (redirect==null) {
+                throw new JSExn("Can not call Box."+JSU.toString(name)+"() on 
a box with a null redirect");
+            }
+            return redirect == this ? METHOD : 
redirect.getAndTriggerTraps(SC_indexof);
+        
         /* <p>The Children property is a <em>meta-property</em>  representing 
a gateway for
          * accessing the children of a box.</p>
          * 
@@ -1632,6 +1702,7 @@
         
         
/*****************************************************************************************/
         /*...@section(Layout)*/
+        
         /* <p>If set to true this box will shrink to the smallest size allowed 
by its packed
          * children and <span>minwidth</span> and <span>minheight</span> 
properties.</p>
          * 
@@ -1646,21 +1717,18 @@
          * 
          * */
         case "shrink": return JSU.B(test(HSHRINK) || test(VSHRINK));
-        /* <p>Affects how a box is shrunk in the horizontal dimension only. A 
horizontally shrunk
-         * box will decline any horizontal slack available to it within a 
parent box if the parent
-         * box has a packed layout strategy and a horizontal orient.</p>
+        
+        /* <p>Affects how a box is shrunk in the horizontal and vertical 
dimensions.</p>
          * 
+         * <p>A <em>horizontally</em> shrunk (<code>hshrink</code) box will 
decline any horizontal
+         * slack available to it within a parent box, and a 
<em>vertically</em> shrunk
+         * (<code>vshrink</code) box will decline vertical slack.</p>
+         *  
+         * @group(vshrink)
          * @type(Boolean)
          * @initial_value(false)
          * */
         case "hshrink": return JSU.B(test(HSHRINK));
-        /* <p>Affects how a box is shrunk in the vertical dimension only. A 
vertically shrunk box
-         * will decline any vertical slack available to it within a parent box 
if the parent box
-         * has a packed layout strategy and a vertical orient.</p>
-         * 
-         * @type(Boolean)
-         * @initial_value(false)
-         * */
         case "vshrink": return JSU.B(test(VSHRINK));
         
         /* <p>If a box is a surface, this is the (x, y) coordinates of the 
surface.</p>
@@ -1712,6 +1780,19 @@
         case "maxwidth": return JSU.N(maxwidth);
         case "maxheight": return JSU.N(maxheight);
         
+        /* <p><em>Read only</em> property describing the <em>minimum</em> size 
a box may be in
+         * pixels when constrained by its contents and dimension restricting 
properties.</p>
+         * 
+         * <p>That is, <em>considering width</em>, the maximum of a box's 
minwidth property and the
+         * constrained size of it's children, and the minimum of this value 
and the boxes maxwidth
+         * property.</p>
+         * 
+         * <p>See the layout section of Box Model for more details on 
constraining.</p>
+         * 
+         * @group(contentheight) 
+         * @type(Number)
+         * @initial_value(0)
+         * */
         case "contentwidth": return JSU.N(contentwidth);
         case "contentheight": return JSU.N(contentheight);
         
@@ -1727,12 +1808,14 @@
          * @initial_value("center")
          * */
         case "align": return alignToJS();
-        /* Whether to display a box and it's contents.
+        
+        /* <p>Whether to display a box and it's contents.</p>
          * 
          * @type(Boolean)
          * @initial_value(true)
          * */
         case "display": return JSU.B(test(DISPLAY));
+        
         /* <p><em>Read only</em> property describing the visible status of 
this box.</p>
          * 
          * <p>Reads <code>false</code> if an ascendent box has its 
<code>display</code> property
@@ -1745,10 +1828,10 @@
         case "visible": return JSU.B(test(DISPLAY) && (parent!=null ? 
parent.isVisible() : Surface.fromBox(this)!=null));
         
         
+        
/*****************************************************************************************/
+        /*...@section(Other) Miscellaneous*/
         
-        
/*****************************************************************************************/
-        /*...@section(Other) Miscellany*/   
-        case "__treedepth": return JSU.N(depth(this)); // FIXME: this is for 
debugging - move to devl?
+        //case "__treedepth": return JSU.N(depth(this)); // FIXME: this is for 
debugging - move to devl?
         //case "props": return mirror();
         
         /* <p>The shape that the cursor should take when inside this box.</p>
@@ -1767,28 +1850,57 @@
          * @initial_value(null)
          * @type(String) */
         case "cursor": return test(CURSOR) ? super.get(name) : null;
+        
         /* @constructor @jpp(Box) */
         case "distanceto": return METHOD;
+        
+        /* <p><em>Read only</em> function that forces reflow to happen on a 
box and it's contents.
+         * Useful because reflow is normally deferred until a box becomes 
visible on screen, but
+         * sometimes it is desirable to have reflow occur and boxes learn 
their size before this
+         * occurs or if it never happens.</p>
+         * 
+         * @method
+         * @param()
+         * @return(null)
+         * */
         case "forcereflow": return METHOD;
+        
         /* @constructor @notmethod @jpp(Box) */
         case "mouse": return getSurface() == null ? null : new Mouse();
-        case "sendEvent": return METHOD; 
-        /* <p>If a box has a parent, this property returns parent.surface; 
otherwise it returns 
+        
+        /* <p><em>Read only</em> function that can be used to induce an event 
on a box and it's
+         * contents.</p>
+         * 
+         * @method
+         * @param(event, x, y)
+         * @return(null)
+         * */
+        case "sendEvent": return METHOD;
+        
+        /* <p>This special property is read only - alter it by placing a read 
trap.  Puts to this
+         * property will have no effect and do not throw an error.</p>
+         * 
+         * <p>If a box has a parent, this property returns parent.surface; 
otherwise it returns 
          * null. This property is a simple building block that the widget 
library uses to implement
          * more complex functionality such as focus control and popups.</p>
          * 
+         * <p>For more details see Surfaces.</p>
+         * 
          * @initial_value(null)
          * @type(<em>varies</em>)
          */
         case "surface": return getSurfaceObject(parent);
-        /* Returns a reference of a box to itself. If <code>null</code> is 
written to this
-         * property, and this box is the root box of a surface, the box will 
be detached and the
-         * surface destroyed. If this box has a parent, it will be detached 
from its parent.
+        
+        /* <p>Returns a reference of a box to itself. If <code>null</code> is 
written to this
+         * property, and this box has a parent, it will be detached from its 
parent. If this box is
+         * the root box of a surface, the box will be detached and the surface 
destroyed.</p>
+         * 
          * @type(Box)*/
         case "thisbox": return this;
         
         
/*****************************************************************************************/
-        /*...@section(Frame)*/ 
+        /*...@section(Frame)*/
+        
         // see put() for jsdoc
         case "Minimized": if (parent == null && getSurface() != null) return 
JSU.B(getSurface().minimized);
         case "Maximized": if (parent == null && getSurface() != null) return 
JSU.B(getSurface().maximized);
@@ -1855,7 +1967,7 @@
         // integer properties translate to box children
         if (JSU.isInt(name)) { put(JSU.toInt(name), value); return; }
         
-        /*
+        /* FEATURE: paths
         case "path":
             path = new Path(JSU.toString(value));
             float tx = -1 * 
Encode.longToFloat2(path.horizontalBounds(Affine.identity()));
@@ -2372,8 +2484,6 @@
         if (newparent != null) {
             if (i<0) throw new JSExn("Illegal attempt to set the parent of a 
box");
         }
-        // FIXME: test for Enter (but put where? in place()?)
-        propagateLeave();
         final boolean wasvisible = isVisible();
         final JS oldsurface = getSurfaceObject(oldparent);
         final JS newsurface = getSurfaceObject(newparent);
@@ -2388,9 +2498,12 @@
             if (newparent != null) {
                 // invoke null put to Children trap on oldparent
                 oldparent.put(oldparent.indexNode(this), null, false, false);
+                // FIXME: test for Enter (but put where? in place()?)
+                if (!newparent.test(MOUSEINSIDE)) propagateLeave();
             } else {
                 // newparent==null => null put has already occurred
                 removeFromParent();
+                propagateLeave();
             }
         }
         // assign new parent


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Vexi-svn mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/vexi-svn

Reply via email to