[Laszlo-checkins] r11314 - openlaszlo/trunk/WEB-INF/lps/lfc/helpers

bargull@openlaszlo.org bargull at openlaszlo.org
Thu Oct 2 02:40:54 PDT 2008


Author: bargull
Date: 2008-10-02 02:40:50 -0700 (Thu, 02 Oct 2008)
New Revision: 11314

Modified:
   openlaszlo/trunk/WEB-INF/lps/lfc/helpers/LzDataSelectionManager.lzs
   openlaszlo/trunk/WEB-INF/lps/lfc/helpers/LzSelectionManager.lzs
Log:
Change 20081001-bargull-c2C by bargull at dell--p4--2-53 on 2008-10-01 16:02:23
    in /home/Admin/src/svn/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: selection management fixes

New Features:

Bugs Fixed: LPP-7094, LPP-7095, LPP-7096, LPP-7097, LPP-7098

Technical Reviewer: ptw
QA Reviewer: (pending)
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:
LPP-7094: clearSelection() changed in Lz(Data)SelectionManager:
- store the previous selection and then create fresh variables to hold new selections
- this avoids a possible non-terminating state (see testcase at bugreport)
LPP-7095: fixed by LPP-7094 bugfix
LPP-7096: select() changed in LzSelectionManager:
- removed "if (s!=o)", which was meant as a speed-up (?), but turned out to be buggy and which was never true for LzDataSelectionManager, 
because s is a LzView, whereas o is a LzDataNode. 
LPP-7097: unselect() changed in LzDataSelectionManager:
- only call "setSelected(false)" when actually found a valid selection
LPP-7098: makeSelected() changed in LzDataSelectionManager:
- set first "singleClone" and then call "setSelected(true)"
- applied same fix in unselect() and __LZsetSelected()

Added indentation for LPP-2623.
Added typing for LPP-6049.
Used LzNode#__LZUID instead of LzNode#getUID() now that there is no longer the requirement to call the getter.
    

Tests:
a testcase for every bug is attached at the bugreports



Modified: openlaszlo/trunk/WEB-INF/lps/lfc/helpers/LzDataSelectionManager.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/helpers/LzDataSelectionManager.lzs	2008-10-02 09:30:34 UTC (rev 11313)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/helpers/LzDataSelectionManager.lzs	2008-10-02 09:40:50 UTC (rev 11314)
@@ -10,20 +10,20 @@
   */
 
 /**
-  * <p>If a datapath's <classname>datapath.replication</classname> attribute is set to "lazy", then a match to 
-  * multiple nodes will create an <sgmltag class="element" role="LzLazyReplicationManager">LzLazyReplicationManager</sgmltag> 
-    instead of an <sgmltag class="element" role="LzReplicationManager">LzReplicationManager</sgmltag>. 
-  * The lazy replication manager creates only enough replicated views in order to display the data, 
-  * so there is not a view for each data node. This enables the display of very large datasets. 
+  * <p>If a datapath's <classname>datapath.replication</classname> attribute is set to "lazy", then a match to
+  * multiple nodes will create an <sgmltag class="element" role="LzLazyReplicationManager">LzLazyReplicationManager</sgmltag>
+    instead of an <sgmltag class="element" role="LzReplicationManager">LzReplicationManager</sgmltag>.
+  * The lazy replication manager creates only enough replicated views in order to display the data,
+  * so there is not a view for each data node. This enables the display of very large datasets.
   * </p>
   * <p>
-  * With lazy replication you must use a <classname>LzDataSelectionManager </classname>instead of a <sgmltag class="element" role="LzSelectionManager">LzSelectionManager</sgmltag>. 
-  * The <classname>LzDataSelectionManager</classname> will operate on the data itself, instead of on the views (which 
-  * may not be present if the data has scrolled out of view). For each dataset you are controlling, 
-  * you can have only one <classname>LzDataSelectionManager</classname> operating on it. 
+  * With lazy replication you must use a <classname>LzDataSelectionManager </classname>instead of a <sgmltag class="element" role="LzSelectionManager">LzSelectionManager</sgmltag>.
+  * The <classname>LzDataSelectionManager</classname> will operate on the data itself, instead of on the views (which
+  * may not be present if the data has scrolled out of view). For each dataset you are controlling,
+  * you can have only one <classname>LzDataSelectionManager</classname> operating on it.
   * </p>
-  * <p>As with a LzSelectionManager, ctrl-click will select multiple items and shift-click will 
-  * select a range. To modify this behavior, you can extend the <classname>LzDataSelectionManager</classname> and implement 
+  * <p>As with a LzSelectionManager, ctrl-click will select multiple items and shift-click will
+  * select a range. To modify this behavior, you can extend the <classname>LzDataSelectionManager</classname> and implement
   * <method>isRangeSelect</method> and <method>isMultiSelect</method>.</p>
   * <example class="program" id="datasenectionmgr">
   * &lt;canvas width="200" height="200"&gt;
@@ -41,7 +41,7 @@
   *       &lt;item&gt;motorboat&lt;/item&gt;
   *     &lt;/list&gt;
   *   &lt;/dataset&gt;
-        
+
   *   &lt;class name="selectme" onclick="immediateparent.selector.select(this)"
         height="17" width="100" bgcolor="white"&gt;
   *     &lt;text datapath="text()"/&gt;
@@ -50,7 +50,7 @@
         else setAttribute('bgcolor', white);
   *     &lt;/method&gt;
   *   &lt;/class&gt;
-        
+
   *   &lt;view height="70" clip="true"&gt;
   *     &lt;view&gt;
   *       &lt;dataselectionmanager name="selector"/&gt;
@@ -66,193 +66,175 @@
   *
   * @shortdesc A selection manager for views generated by a lazily-replicated datapath
   * @lzxname dataselectionmanager
-  *
+  * @devnote: TODO: [20080930 anba] (LPP-6080) uncomment typing in method signatures
   */
-    
-class LzDataSelectionManager extends LzSelectionManager {
+public class LzDataSelectionManager extends LzSelectionManager {
 
-function LzDataSelectionManager ( parent:LzNode? = null , attrs:Object? = null , children:Array? = null, instcall:Boolean  = false) {
-    super(parent,attrs,children,instcall);
-}
+    /** @access private */
+    function LzDataSelectionManager (parent:LzNode? = null, attrs:Object? = null, children:Array? = null, instcall:Boolean = false) {
+        super(parent, attrs, children, instcall);
+    }
 
+    /** @access private
+      * @modifiers override
+      */
+    static var tagname :String = 'dataselectionmanager';
 
-/** @access private
-  * @modifiers override 
-  */
-static var tagname = 'dataselectionmanager';
-/** @access private */
-  static var attributes = new LzInheritedHash(LzSelectionManager.attributes);
+    /** @access private */
+    static var attributes :Object = new LzInheritedHash(LzSelectionManager.attributes);
 
-/** @access private
-  */
-var manager;
+    /** @access private */
+    var manager :LzReplicationManager;
 
-/** @access private
-  */
-var singleClone;
+    /** @access private */
+    var singleClone :LzView;
 
-/**
-  * Makes the given view selected
-  * @access private
-  * @param LzView o: The view to be selected
-  */
-override function makeSelected ( o ){
-    var so = o.datapath.p;
-    if ( this.manager == null ) this.manager = o.cloneManager; 
-    if ( so.sel ) return; 
-    so.sel = true;
-    this.selected.push( so );
-    o.datapath[ this.sel ]( true );    
-    
-    if ( this.manager == null ){
-        //just one "clone", mark it!
-        this.singleClone = o;
+    /**
+      * Makes the given view selected
+      * @access private
+      * @param LzView o: The view to be selected
+      */
+    override function makeSelected (o:LzView) :void {
+        if (this.manager == null) this.manager = o.cloneManager;//try to get a cloneManager
+
+        var so /*:LzDataNodeMixin*/ = o.datapath.p;
+        if (! so.sel) {
+            so.sel = true;
+            this.selected.push( so );
+            if (this.manager == null) {
+                //just one "clone", mark it!
+                this.singleClone = o;
+            }
+            o.datapath.setSelected( true );
+        }
     }
-}
 
-/**
-  * Unselect the given view
-  * @param LzView o: The view to be unselected
-  */
-override function unselect ( o ){
-    if ( this.manager == null ) this.manager = o.cloneManager;//try to get a cloneManager  
+    /**
+      * Unselect the given view
+      * @param LzView o: The view to be unselected
+      */
+    override function unselect (o /*:LzView*/) :void {
+        if (this.manager == null) this.manager = o.cloneManager;//try to get a cloneManager
 
-    var so = o.datapath.p;
-    so.sel = false;
-    for ( var i = this.selected.length-1 ; i >= 0; i-- ){
-        if ( this.selected[ i ] == so ) {
-            this.selected.splice( i , 1 );
-            break;
+        var sela:Array = this.selected;
+        var so /*:LzDataNodeMixin*/ = o.datapath.p;
+        for (var i:int = sela.length - 1; i >= 0; i--) {
+            if (sela[ i ] === so) {
+                so.sel = false;
+                sela.splice( i, 1 );
+                if (o == this.singleClone) this.singleClone = null;//clear "singleClone"
+                o.datapath.setSelected( false );
+                return;
+            }
         }
-    }      
-    o.datapath[ this.sel ]( false );
-    
-    if ( o == this.singleClone ) this.singleClone = null;//clear "singleClone"
-}
-
-/**
-  * Selects the range between the datapath that was lastselected and the newly
-  * selected view
-  * @access private
-  * @param LzDataPath s: The datapath that was at top of the selection stack
-  * @param LzView e: The newly selected view
-  */
-override function selectRange ( s , e ){
-    if ( this.manager == null ){        
-        this.manager = e.cloneManager;
-        
-        //maybe we've got now clones
-        if ( this.manager == null ){
-        //still no clones?          
-        //so it's nothing to do, just hope so...
-        if ( $debug ){
-            Debug.write( "selectRange failed, no clones" );
-        }
-        return;
-        }
     }
-    
-    var nodes = this.manager.nodes;
 
-    var st = -1;
-    var en = -1;
-    var i  = 0;
-    var ennode = e.datapath.p;
-    //find the start and end in the sort array of parents
+    /**
+      * Selects the range between the datapath that was lastselected and the newly
+      * selected view
+      * @access private
+      * @param LzDataNodeMixin s: The datanode that was at top of the selection stack
+      * @param LzView e: The newly selected view
+      */
+    override function selectRange (s:*, e:LzView) :void {
+        if (this.manager == null) {
+            this.manager = e.cloneManager;
 
-    while ( ( st == -1 || en == -1 ) && i < nodes.length ){
-        if ( nodes[ i ] == s ){
-            st = i;
-        } 
-        if ( nodes[ i ] == ennode ){
-            en = i;
-        } 
-        i++;
-    }
+            //maybe we've got now clones
+            if (this.manager == null) {
+                //still no clones - so it's nothing to do
+                return;
+            }
+        }
 
-        
-    var dir = st > en ? -1 : 1;
-    
-    this.clearSelection();
+        var nodes:Array = this.manager.nodes;
+        var st:int = -1;
+        var en:int = -1;
+        var ennode /*:LzDataNodeMixin*/ = e.datapath.p;
+        //find the start and end in the sort array of parents
+        for (var i:int = 0; i < nodes.length && (st == -1 || en == -1); i++) {
+            if (nodes[ i ] === s) st = i;
+            if (nodes[ i ] === ennode) en = i;
+        }
 
-    this.lastRange = s;
+        var dir:int = st > en ? -1 : 1;
+        this.clearSelection();
+        this.lastRangeStart = s;
 
-    //couldn't find -- wierd
-    if ( st == -1 || en == -1 ) return;
-    
-    for ( var i = st; i != en + dir; i += dir ) {
-        var p = nodes[ i ];
-        p.sel = true;
-        this.selected.push( p );
-        this.__LZsetSelected( p, true );
+        if (st != -1 && en != -1) {
+            for (var i:int = st; i != en + dir; i += dir) {
+                var p /*:LzDataNodeMixin*/ = nodes[ i ];
+                p.sel = true;
+                this.selected.push( p );
+                this.__LZsetSelected( p, true );
+            }
+        }
     }
-}
 
-/**
-  * Returns a list of datapointers, which point to the selected records
-  * @return Array: A list of datapointers
-  */
-override function getSelection (){
-    var r = [];
-    for ( var i = 0; i < this.selected.length ; i++ ){
-        r.push( new LzDatapointer( null , {pointer : this.selected[i] }));
+    /**
+      * Returns a list of datapointers, which point to the selected records
+      * @return Array: A list of datapointers
+      */
+    override function getSelection () :Array {
+        var sela:Array = this.selected;
+        var r:Array = [];
+        for (var i:int = 0; i < sela.length; i++) {
+            r.push( new LzDatapointer( null, {pointer : sela[i]} ) );
+        }
+        return r;
     }
-    return r;    
-}
 
-/**
-  * Unselects everything that is currently selected and clears the selection
-  * list
-  * 
-  */
-override function clearSelection ( ){
-    while ( this.selected.length ){
-        var p  = this.selected.pop();
-        p.sel = false;
-        this.__LZsetSelected( p , false );
+    /**
+      * Unselects everything that is currently selected and clears the selection
+      * list
+      */
+    override function clearSelection () :void {
+        var sela:Array = this.selected;
+        this.selected = [];
+        this.lastRangeStart = null;
+        var p /*:LzDataNodeMixin*/;
+        while (p = sela.pop()) {
+            p.sel = false;
+            this.__LZsetSelected( p, false );
+        }
     }
-    this.lastRange = null;
-}
-        
-/**
-  * Tests whether the given view is selected
-  * @param LzView o: The view to test for selectedness
-  * @return Boolean: The selectedness of the input object.
-  */
-override function isSelected ( o){
-    if ( this.manager == null ) this.manager = o.cloneManager;//try to get a cloneManager
 
-    return o.datapath.p.sel;
-}
+    /**
+      * Tests whether the given view is selected
+      * @param LzView o: The view to test for selectedness
+      * @return Boolean: The selectedness of the input object.
+      */
+    override function isSelected (o /*:LzView*/) :Boolean {
+        if (this.manager == null) this.manager = o.cloneManager;//try to get a cloneManager
 
-/**
-  * sets the selected attribute of the data, if there is a clone, it will
-  * call <method>setSelected(Boolean)</method> on the clone's datapath
-  * @param LzDataElement p: the node we want to set
-  * @param Boolean val: new value for selected
-  * @access private
-  */
-function __LZsetSelected ( p, val ){
-    if ( this.manager != null ){
-        var cl = this.manager.getCloneForNode( p, true );
-        if ( cl ){
-            cl.datapath[this.sel]( val );
-        } else { // no clone on screen
-            p.sel = val;
-        }
-    } else {//no clones
-        //if caller is selectRange, then "this.manager" won't be "null"
-        //but if caller is clearSelection, "this.manager" could be "null", but then "val" is definitely "false"
-        if ( !val ){
-            if ( this.singleClone != null && this.singleClone.datapath.p == p ){
-                this.singleClone.datapath[this.sel]( false );
+        return o.datapath.p.sel;
+    }
+
+    /**
+      * sets the selected attribute of the data, if there is a clone, it will
+      * call <method>setSelected(Boolean)</method> on the clone's datapath
+      * @param LzDataNodeMixin p: the node we want to set
+      * @param Boolean val: new value for selected
+      * @access private
+      */
+    function __LZsetSelected (p /*:LzDataNodeMixin*/, val:Boolean) :void {
+        if (this.manager != null) {
+            var cl:LzNode = this.manager.getCloneForNode( p, true );
+            if (cl) {
+                cl.datapath.setSelected( val );
+            } else {
+                // no clone on screen
+            }
+        } else if (! val) {//no clones
+            // the if-condition only yields true for clearSelection(), 
+            // in which case we need to check the singleClone property
+            var scl:LzView = this.singleClone;
+            if (scl != null && scl.datapath.p === p) {
                 this.singleClone = null;
-                return;//job is done...
+                scl.datapath.setSelected( val );
             }
         }
-        p.sel = val;//default action
     }
-}
 
 } // End of LzDataselectionmanager
 lz[LzDataSelectionManager.tagname] = LzDataSelectionManager;  // publish

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/helpers/LzSelectionManager.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/helpers/LzSelectionManager.lzs	2008-10-02 09:30:34 UTC (rev 11313)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/helpers/LzSelectionManager.lzs	2008-10-02 09:40:50 UTC (rev 11314)
@@ -15,41 +15,41 @@
   * enable standard control and shift click modifiers to aid range
   * selection. Selection managers provide methods to manipulate, add to
   * and clear the selection.  For example:</p>
-  * 
+  *
   * <example>
   * &lt;canvas&gt;
-  * 
+  *
   *   &lt;dataset name="fruits"&gt;
   *     &lt;fruit&gt;Oranges&lt;/fruit&gt;
   *     &lt;fruit&gt;Apples&lt;/fruit&gt;
   *     &lt;fruit&gt;Bananas&lt;/fruit&gt;
-  * 
+  *
   *     &lt;fruit&gt;Grapes&lt;/fruit&gt;
   *     &lt;fruit&gt;Kiwis&lt;/fruit&gt;
   *     &lt;fruit&gt;Papayas&lt;/fruit&gt;
   *     &lt;fruit&gt;Watermelon&lt;/fruit&gt;
-  * 
+  *
   *     &lt;fruit&gt;Strawberries&lt;/fruit&gt;
   *     &lt;fruit&gt;Cherries&lt;/fruit&gt;
   *   &lt;/dataset&gt;
-  *   
+  *
   *   &lt;simplelayout/&gt;
-  *   
-  *   &lt;text&gt;Select a series of items below. The control and shift-click modifiers 
+  *
+  *   &lt;text&gt;Select a series of items below. The control and shift-click modifiers
   *   help select ranges.&lt;/text&gt;
-  * 
-  *   
+  *
+  *
   *   &lt;view name="fruitlist"&gt;
   *     &lt;selectionmanager name="selector" toggle="true"/&gt;
   *     &lt;simplelayout/&gt;
-  *     
+  *
   *     &lt;view name ="listitem"
-  *           datapath="fruits:/fruit" 
+  *           datapath="fruits:/fruit"
   *           onclick="parent.selector.select(this);"&gt;
   *       &lt;text name="txt" datapath="text()"/&gt;
-  * 
+  *
   *       &lt;method name="setSelected" args="amselected"&gt;
-  * 
+  *
   *         if (amselected) {
   *           var txtColor = 0xFFFFFF;
   *           var bgcolor = 0x999999;
@@ -61,7 +61,7 @@
   *         this.txt.setAttribute('fgcolor', txtColor);
   *       &lt;/method&gt;
   *     &lt;/view&gt;
-  *     
+  *
   *     &lt;method name="deleteSelected"&gt;
   *     &lt;![CDATA[
   *       var csel = this.selector.getSelection();
@@ -71,12 +71,12 @@
   *       this.selector.clearSelection();
   *     ]]&gt;
   *     &lt;/method&gt;
-  * 
+  *
   *   &lt;/view&gt;
   *   &lt;button onclick="fruitlist.deleteSelected();"&gt;Delete selection&lt;/button&gt;
   * &lt;/canvas&gt;
   * </example>
-  * 
+  *
   * @shortdesc Manages selection among a series of objects.
   * @lzxname selectionmanager
   *
@@ -84,214 +84,213 @@
   * the selection.
   * @initarg Boolean sel: The name of the method to call (with true or
   * false to represent selectedness) when an element changes its selectedness
+  * @devnote: TODO: [20080930 anba] (LPP-6080) uncomment typing in method signatures
   */
-  
-class LzSelectionManager extends LzNode {
+public class LzSelectionManager extends LzNode {
 
-/** @access private */
-function LzSelectionManager ( parent:LzNode? = null , attrs:Object? = null , children:Array? = null, instcall:Boolean  = false) {
-    super(parent,attrs,children,instcall);
-}
+    /** @access private */
+    function LzSelectionManager (parent:LzNode? = null, attrs:Object? = null, children:Array? = null, instcall:Boolean = false) {
+        super(parent, attrs, children, instcall);
+    }
 
+    /** @access private
+      * @modifiers override
+      */
+    static var tagname :String = 'selectionmanager';
 
-/** @access private
-  * @modifiers override 
-  */
-static var tagname = 'selectionmanager';
-/** @access private */
-  static var attributes = new LzInheritedHash(LzNode.attributes);
+    /** @access private */
+    static var attributes :Object = new LzInheritedHash(LzNode.attributes);
 
-/** The name of the method to call on an object
-  * when an object's selectedness changes.  The method is called with a single Boolean argument.  The default value for this 
-  * field is <code>setSelected</code>.
-  * @type String
-  * @lzxtype string
-  */
-var sel = "setSelected";
+    /** The name of the method to call on an object when an object's selectedness changes.
+      * The method is called with a single Boolean argument. The default value for this
+      * field is <code>setSelected</code>. (This feature is not available for LzDataSelectionManager.)
+      * @type String
+      * @lzxtype string
+      */
+    var sel :String = "setSelected";
 
-/** A hash of currently selected objects (by UID)
-  * @access private
-  * @type Object
-  */
-var selectedHash;
+    /** A hash of currently selected objects (by UID)
+      * @access private
+      * @type Object
+      */
+    var selectedHash :Object;
 
-/** An array that represents the current selection
-  * @access private
-  * @type Array
-  */
-var selected;
+    /** An array that represents the current selection
+      * @access private
+      * @type Array
+      */
+    var selected :Array;
 
-/** If true, a re-selected element will lose the selection
-  * @type Boolean
-  * @lzxtype boolean
-  */
-var toggle;
+    /** If true, a re-selected element will lose the selection
+      * @type Boolean
+      * @lzxtype boolean
+      */
+    var toggle :Boolean;
 
-/** If true, a re-selected element will lose the selection
-  * @type Boolean
-  * @access private
-  */
-var lastRange;
+    /** @type *
+      * @access private
+      */
+    var lastRangeStart :*;
 
-/**
-  * @param LzView view: A view above this one in the hierarchy that will determine
-  * the placement of the selection manager.
-  * @param Object args: A hash of initialization arguments
-  * 
-  * @access private
-  */
-override function construct ( view , args ) {
-    super.construct.apply(this, arguments);
+    /**
+      * @param LzView view: A view above this one in the hierarchy that will determine
+      * the placement of the selection manager.
+      * @param Object args: A hash of initialization arguments
+      *
+      * @access private
+      */
+    override function construct (parent, args) {
+        super.construct(parent, args);
 
-    this.toggle = args.toggle == true;
+        this.toggle = args.toggle == true;
 
-    if (args.sel != null) {
-        this.sel = args.sel;
+        if (args.sel != null) {
+            this.sel = args.sel;
+        }
+
+        this.selected = [];
+        this.selectedHash = {};
+        this.lastRangeStart = null;
     }
-    
-    this.selected = new Array;
-    this.selectedHash = new Object;
-    this.lastRange = null;
-}
 
 
-/**
-  * Called with a new member to be selected.
-  * @param LzView o: The new element that got selected.
-  */
-function select ( o ){
-    if (  this.isSelected( o ) && ( this.toggle ||
-                                                this.isMultiSelect(o) ) ) {
-        this.unselect( o );
-        return;
+    /**
+      * Called with a new member to be selected.
+      * @param LzView o: The new element that got selected.
+      */
+    function select (o /*:LzView*/) :void {
+        if (this.isSelected( o ) && (this.toggle || this.isMultiSelect( o ))) {
+            this.unselect( o );
+        } else {
+            if (this.selected.length > 0 && this.isRangeSelect( o )) {
+                var s:* = this.lastRangeStart || this.selected[ 0 ];
+                this.selectRange( s, o );
+            } else {
+                if (! this.isMultiSelect( o )) {
+                    this.clearSelection();
+                }
+                this.makeSelected( o );
+            }
+        }
     }
 
-    if (this.selected.length > 0 && this.isRangeSelect(o) ){
-        var s = this.lastRange != null ? this.lastRange : this.selected[ 0 ];
-        if ( s != o ){
-            this.selectRange( s , o );
-        }
-        return;
+    /**
+      * Tests for selectedness of input.
+      * @param LzView o: The object to test for selectedness.
+      * @return Boolean: The selectedness of the input object.
+      */
+    function isSelected (o /*:LzView*/) :Boolean {
+        return this.selectedHash[ o.__LZUID ] == true;
     }
 
-    if ( ! this.isMultiSelect(o) ){
-        this.clearSelection();
+    /**
+      * Makes the given object selected.
+      * @access private
+      * @param LzView s: The object to make selected
+      */
+    function makeSelected (s:LzView) :void {
+        if (! this.selectedHash[ s.__LZUID ]) {
+            this.selectedHash[ s.__LZUID ] = true;
+            this.selected.push( s );
+            s[ this.sel ]( true );
+        }
     }
-    this.makeSelected( o );
-}
 
-/**
-  * Tests for selectedness of input.
-  * @param LzView o: The object to test for selectedness.
-  * @return Boolean: The selectedness of the input object.
-  */
-function isSelected ( o )  {
-    return this.selectedHash[ o.getUID() ];
-}
 
-/**
-  * Makes the given object selected.
-  * @access private
-  * @param LzView s: The object to make selected
-  */
-function makeSelected ( s )  {
-    if ( this.selectedHash[ s.getUID() ] ) return;
+    /**
+      * Unselects the given object.
+      * @param LzView o: The object to make unselected
+      */
+    function unselect (o /*:LzView*/) :void {
+        var selh:Object = this.selectedHash;
+        var sela:Array = this.selected;
+        if (selh[ o.__LZUID ]) {
+            for (var i:int = sela.length - 1; i >= 0; i--) {
+                if (sela[ i ] === o) {
+                    delete selh[ o.__LZUID ];
+                    sela.splice( i, 1 );
+                    o[ this.sel ]( false );
+                    return;
+                }
+            }
+        }
+    }
 
-    this.selectedHash[ s.getUID() ] = true;
-    this.selected.push( s );
-    s[ this.sel ] ( true );
-}
-
-
-/**
-  * Unselects the given object.
-  * @param LzView o: The object to make unselected
-  */
-function unselect ( o ){
-    for ( var i= this.selected.length-1 ; i >= 0; i-- ){
-        if ( this.selected[ i ] == o ) {
-            this.selectedHash[ o.getUID() ] = false;
-            o [ this.sel ] ( false );
-            this.selected.splice( i , 1 );
-            break;
+    /**
+      * Unselects any selected objects.
+      */
+    function clearSelection () :void {
+        var sela:Array = this.selected;
+        this.selected = [];
+        this.selectedHash = {};
+        this.lastRangeStart = null;
+        var s:LzView;
+        while (s = sela.pop()) {
+            s[ this.sel ]( false );
         }
     }
-}
 
-/**
-  * Unselects any selected objects.
-  */
-function clearSelection (){
-    var s;
-    while ( s =  this.selected.pop()){
-        s[ this.sel ] ( false );
+    /**
+      * Returns an array representing the current selection.
+      * @return Array: An array representing the current selection.
+      */
+    function getSelection () :Array {
+        return this.selected.concat();
     }
-    this.selected = new Array;
-    this.selectedHash = new Object;
-    this.lastRange = null;
-}
 
-/**
-  * Returns an array representing the current selection.
-  * @return Array: An array representing the current selection.
-  */
-function getSelection (){
-    return this.selected;
-}
+    /**
+      * @access private
+      * @param LzView s: The view that was at top of the selection stack
+      * @param LzView e: The newly selected view
+      */
+    function selectRange (s:*, e:LzView) :void {
+        var pview:LzView = (s cast LzView).immediateparent;
 
-/**
-  * @access private
-  * @param LzDataPath s: The datapath that was at top of the selection stack
-  * @param LzView e: The newly selected view
-  */
-function selectRange ( s , e ){
-    var pview = s.immediateparent;
+        var svs:Array = pview.subviews;
+        var st:int = -1;
+        var en:int = -1;
+        for (var i:int = 0; i < svs.length && (st == -1 || en == -1); i++) {
+            if (svs[ i ] === s) st = i;
+            if (svs[ i ] === e) en = i;
+        }
 
-    var svs = pview.subviews;
-    var st = null;
-    var en = null;
-    for ( var i = 0; i < svs.length; i++ ){
-        if ( svs[ i ] == s ) st = i;
-        if ( svs[ i ] == e ) en = i;
-        if ( null != st && null != en ) break;
+        var dir:int = st > en ? -1 : 1;
+        this.clearSelection();
+        this.lastRangeStart = s;
+
+        if (st != -1 && en != -1) {
+            for (var i:int = st; i != en + dir; i += dir) {
+                this.makeSelected( svs[ i ] );
+            }
+        }
     }
 
-    var dir = st > en ? -1 : 1;
-    this.clearSelection();
-    
-    this.lastRange = s;
-    for ( var i = st; i != en + dir; i += dir ) {
-        this.makeSelected( pview.subviews[ i ] );
+    /**
+      * Determines whether the an additional selection should be multi-selected or
+      * should replace the existing selection
+      * @param LzView o: The newly selected view
+      * @return Boolean:  If true, multi select. If false, don't multi select
+      */
+    function isMultiSelect (o /*:LzView*/) :Boolean {
+        return lz.Keys.isKeyDown( "control" );
     }
-    
-}
 
-/**
-  * Determines whether the an additional selection should be multi-selected or
-  * should replace the existing selection
-  * @param LzView o: The newly selected view
-  * @return Boolean:  If true, multi select. If false, don't multi select
-  */
-function isMultiSelect (o){
-    return lz.Keys.isKeyDown( "control" );
-}
+    /**
+      * Determines whether the an additional selection should be range-selected or
+      * should replace the existing selection
+      * @param LzView o: The newly selected view
+      * @return Boolean: If true, range select. If false, don't range select
+      */
+    function isRangeSelect (o /*:LzView*/) :Boolean {
+        return lz.Keys.isKeyDown( "shift" );
+    }
 
-/**
-  * Determines whether the an additional selection should be range-selected or
-  * should replace the existing selection
-  * @param LzView o: The newly selected view
-  * @return Boolean: If true, range select. If false, don't range select
-  */
-function isRangeSelect(o){
-    return lz.Keys.isKeyDown( "shift" );
-}
+    /**
+      * @access private
+      */
+    override function toString () {
+        return "LzSelectionManager";
+    }
 
-/**
-  * @access private
-  */
-override function toString (){
-    return "LzSelectionManager";
-}
-
 } // End of LzSelectionManager
 lz[LzSelectionManager.tagname] = LzSelectionManager;  // publish



More information about the Laszlo-checkins mailing list