r21169: - Step 3: Upgrade qooxdoo release code with latest qooxdoo svn's Table and
authorDerrell Lipman <derrell@samba.org>
Tue, 6 Feb 2007 04:35:30 +0000 (04:35 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:44:39 +0000 (14:44 -0500)
  TreeVirtual.  The TreeVirtual that was in the release was a very early
  pre-release, and had a number of problems and missing features.  This brings
  it up-to-date and provides what seems to be a pretty well-working and highly
  useful widget.
(This used to be commit 194880f1ffde7f01997c120136854acd145189e9)

15 files changed:
webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/example/TreeVirtual_1.html [moved from webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/test/TreeVirtual_3.html with 100% similarity]
webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/example/TreeVirtual_2.html [moved from webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/test/TreeVirtual_4.html with 95% similarity]
webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/example/TreeVirtual_3.html [moved from webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/test/TreeVirtual_5.html with 72% similarity]
webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/example/TreeVirtual_4.html [moved from webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/test/TreeVirtual_6.html with 100% similarity]
webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/test/TreeVirtual_1.html
webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/test/TreeVirtual_2.html
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/theme/appearance/Classic.js
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/table/Table.js
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/table/TablePaneScroller.js
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/DefaultDataCellRenderer.js
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SelectionManager.js [new file with mode: 0644]
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataCellRenderer.js
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/TreeVirtual.js
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/translation/C.po

similarity index 95%
rename from webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/test/TreeVirtual_4.html
rename to webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/example/TreeVirtual_2.html
index 3b150f52baa34843b3f5ada6efe3f61e812ca762..843de574777df8a77b7aea856c3e657661074f6b 100644 (file)
@@ -83,9 +83,7 @@
                           {
                             alert('treeOpenWithContent ');
                             var node = e.getData();
-                            dataModel.addLeaf(node.nodeId,
-                                              newItem.toString(),
-                                              false);
+                            dataModel.addLeaf(node.nodeId, newItem.toString());
                             newItem++;
                           });
 
                           {
                             alert('treeOpenWhileEmpty');
                             var node = e.getData();
-                            tree.setState(node.nodeId, { opened : null });
+                            tree.setState(node.nodeId,
+                                          { bHideOpenClose : true });
                           });
 
 
similarity index 72%
rename from webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/test/TreeVirtual_5.html
rename to webapps/qooxdoo-0.6.5-sdk/frontend/application/sample/source/html/example/TreeVirtual_3.html
index 08c73e12ea2880b873e5e317dcfa1135afd70680..70391adf8908f17fd389c9f9d1937709695eab28 100644 (file)
   <script type="text/javascript" src="../../script/layout.js"></script>
 
   <div id="demoDescription">
-    <p>Demonstrate use of multiple columns in a tree.</p>
+    <p>
+      Demonstrate use of multiple columns in a tree, and the use of the
+      getHierarchy() method to retrieve the entire tree path of a node.
+      Allows various options to be manipulated.
+    </p>
   </div>
 
   <script type="text/javascript">
   qx.core.Init.getInstance().defineMain(function()
   {
     // tree
-    var tree = new qx.ui.treevirtual.TreeVirtual([ "Tree", "Permissions" ]);
+    var tree = new qx.ui.treevirtual.TreeVirtual(
+        [
+          "Tree",
+          "Permissions",
+          "Last Accessed"
+        ]);
     with (tree)
     {
       set({
@@ -30,8 +39,9 @@
             border : qx.renderer.border.BorderPresets.getInstance().thinInset
           });
       setAlwaysShowOpenCloseSymbol(true);
-      setColumnWidth(0, 400);
-      setColumnWidth(1, 100);
+      setColumnWidth(0, 200);
+      setColumnWidth(1, 80);
+      setColumnWidth(2, 200);
     };
 
     tree.addToDocument();
     te1_1 = dataModel.addBranch(te1, "Workspace", true);
     te = dataModel.addLeaf(te1_1, "Windows (C:)");
     dataModel.setColumnData(te, 1, "-rwxr-xr-x");
+    dataModel.setColumnData(te, 2, "2007-01-30 22:54:03");
     te = dataModel.addLeaf(te1_1, "Documents (D:)");
     dataModel.setColumnData(te, 1, "-rwxr-xr-x");
+    dataModel.setColumnData(te, 2, "2007-01-30 22:54:03");
 
     dataModel.addBranch(te1, "Network", true);
 
                          tree.setUseTreeLines(e.getData());
                        });
 
-    o = new qx.ui.form.CheckBox("Jens Lautenbacher mode?");
+    o = new qx.ui.form.CheckBox("Exclude first-level tree lines?");
     o.set({ top: 100, left: 0, checked: false });
     commandFrame.add(o);
     o.addEventListener("changeChecked",
                        function(e)
                        {
-                         tree.setJensLautenbacherMode(e.getData());
+                         tree.setExcludeFirstLevelTreeLines(e.getData());
                        });
 
     o = new qx.ui.form.CheckBox("Always show open/close symbol?");
                             if (this.getChecked())
                             {
                               var node = e.getData();
-                              tree.setState(node.nodeId, { opened : null });
+                              tree.setState(node.nodeId,
+                                            { bHideOpenClose : true });
                             }
                           },
                           o);
                        {
                          tree.setOpenCloseClickSelectsRow(e.getData());
                        });
+
+    o = new qx.ui.form.CheckBox("Disable the tree?");
+    o.set({ top: 180, left: 0, checked: false });
+    commandFrame.add(o);
+    o.addEventListener("changeChecked",
+                       function(e)
+                       {
+                         tree.setEnabled(! e.getData());
+                       });
+
+    o = new qx.ui.form.CheckBox("Display a cell focus indicator?");
+    o.set({ top: 200, left: 0, checked: true });
+    commandFrame.add(o);
+    o.addEventListener("changeChecked",
+                       function(e)
+                       {
+                         if (e.getData())
+                         {
+                           tree.setCellFocusAttributes(
+                             {
+                               backgroundColor : "lightblue"
+                             });
+                         }
+                         else
+                         {
+                           tree.setCellFocusAttributes(
+                             {
+                               backgroundColor : "transparent"
+                             });
+                         }
+                       });
+
+
   });
   </script>
 </body>
index e419453600afb3aa880859d68a18df55bed54aa4..089aa0f5829d51200562ff58f3f80f6ee2653469 100644 (file)
   {
     var d = qx.ui.core.ClientDocument.getInstance();
 
-    // tree
-    var tree = new qx.ui.treevirtual.TreeVirtual("Tree");
-    with (tree)
-    {
-      set({
-            left   : 10,
-            top    : 30,
-            width  : 400,
-            bottom : 30,
-            border : qx.renderer.border.BorderPresets.getInstance().thinInset
-          });
-      setColumnWidth(0, 400);
-    };
-
-    d.add(tree);
-
-    // tree data model
-    var dataModel = tree.getDataModel();
 
-    var te;
+    var horiz =  new qx.ui.layout.HorizontalBoxLayout;
+    
+    horiz.setPadding(10);
+    horiz.set({
+        left:20, right:10, height:"100%", spacing:20
+    });
 
-    var te1 = dataModel.addBranch(null, "Desktop", true);
-
-    dataModel.addBranch(te1, "Files", true);
+    var tree = new qx.ui.treevirtual.TreeVirtual(["Objects", "Date", "ID"]);
+    with (tree){
+       setHeight ("100%");
+        setWidth(900);
+        setColumnWidth(0, 400)
+        setColumnWidth(1, 200);
+        setColumnWidth(2, 50);
+    };
 
-    te = dataModel.addBranch(te1, "Workspace", true);
-    dataModel.addLeaf(te, "Windows (C:)");
-    dataModel.addLeaf(te, "Documents (D:)");
+    var data_model = tree.getDataModel ();
 
-    dataModel.addBranch(te1, "Network", true);
-    dataModel.addBranch(te1, "Trash", true);
+    var object_folder =
+       data_model.addBranch (null, 
+                             "Test", 
+                             false);
 
-    var te2 = dataModel.addBranch(null, "Inbox", true);
+    data_model.addLeaf (object_folder, 
+                       "Test") ;
+    
+    data_model.setData();      
 
-    dataModel.addBranch(te2, "Presets", true);
-    dataModel.addBranch(te2, "Sent", true);
-    dataModel.addBranch(te2, "Trash", true);
-    dataModel.addBranch(te2, "Data", true);
-    dataModel.addBranch(te2, "Edit", true);
+    if (false)
+    {
+       d.add (tree);
+    }
+    else
+    {
+       horiz.add (tree);
+       d.add (horiz);
+    }
 
-    dataModel.setData();
   });
   </script>
 </body>
index 8c965f93dec222ae38c2c5855e3d9bf68a9bc5a4..7c44daf98bf0ec2bfc8b6c1798d29402ee0880e6 100644 (file)
@@ -45,7 +45,7 @@
 
     var node =                  // the root node (not displayed)
       {
-        opened        : true,
+        bOpened       : true,
         children      : [ 1 ]
       };
     treeData.push(node);
@@ -56,7 +56,7 @@
         parentNodeId  : 0,
         label         : "My Root",
         bSelected     : false,
-        opened        : true,
+        bOpened       : true,
         icon          : "icon/16/places/folder.png",
         iconSelected  : "icon/16/folder_open.png",
         labelStyle    : "background-color:red;color:white",
@@ -70,7 +70,8 @@
         parentNodeId  : 1,
         label         : "A sub-folder",
         bSelected     : false,
-        opened        : true,
+        bOpened       : true,
+        bHideOpenClose: true,
         icon          : "icon/16/places/folder.png",
         iconSelected  : "icon/16/folder_open.png",
         cellStyle     : "background-color:cyan",
@@ -84,7 +85,7 @@
         parentNodeId  : 2,
         label         : "Third-level leaf",
         bSelected     : false,
-        opened        : false,
+        bOpened       : false,
         icon          : "icon/16/actions/document-new.png",
         iconSelected  : "icon/16/actions/document-open.png",
         children      : [ ]
index 9e8d0e702b32079b05caaebdf0a65c817fa117e1..324a3950b4cd750cf4bf27f135e60f45546ca739 100644 (file)
@@ -1171,6 +1171,17 @@ qx.Proto._appearances = qx.lang.Object.carefullyMergeWith( {
 
 
 
+  /*
+  ---------------------------------------------------------------------------
+    TREEVIRTUAL
+  ---------------------------------------------------------------------------
+  */
+
+  "treevirtual-focus-indicator" : {
+  },
+
+
+
   /*
   ---------------------------------------------------------------------------
     TREE
index 1fda3f52f214aec0dd6cf21d91b17dd43af78df0..d0950211bf69745de7058948d37fb27b9f1438d1 100644 (file)
@@ -50,11 +50,13 @@ function(tableModel) {
   this._columnVisibilityBt.addEventListener("execute", this._onColumnVisibilityBtExecuted, this);
 
   // Create the models
-  this._selectionManager = new qx.ui.table.SelectionManager;
+  this._selectionManager = this.getNewSelectionManager()(this);
+  this.setSelectionModel(this.getNewSelectionModel()(this));
+  this.setTableColumnModel(this.getNewTableColumnModel()(this));
 
-  this.setSelectionModel(new qx.ui.table.SelectionModel);
-  this.setTableColumnModel(new qx.ui.table.TableColumnModel);
+  // If a table model was provided...
   if (tableModel != null) {
+    // ... then save it.
     this.setTableModel(tableModel);
   }
 
@@ -125,6 +127,145 @@ qx.OO.addProperty({ name:"headerCellHeight", type:"number", defaultValue:16, all
 /** The renderer to use for styling the rows. */
 qx.OO.addProperty({ name:"dataRowRenderer", type:"object", instance:"qx.ui.table.DataRowRenderer", defaultValue:qx.Class.DEFAULT_DATA_ROW_RENDERER, allowNull:false });
 
+/**
+ * A function to instantiate a selection manager.  this allows subclasses of
+ * Table to subclass this internal class.  To take effect, this property must
+ * be set before calling the Table constructor.
+ */
+qx.OO.addProperty(
+  {
+    name :
+      "newSelectionManager",
+    type :
+      "function",
+    setOnlyOnce :
+      true,
+    defaultValue:
+      function(obj)
+      {
+        return new qx.ui.table.SelectionManager(obj);
+      }
+  });
+
+/**
+ * A function to instantiate a selection model.  this allows subclasses of
+ * Table to subclass this internal class.  To take effect, this property must
+ * be set before calling the Table constructor.
+ */
+qx.OO.addProperty(
+  {
+    name :
+      "newSelectionModel",
+    type :
+      "function",
+    setOnlyOnce :
+      true,
+    defaultValue:
+      function(obj)
+      {
+        return new qx.ui.table.SelectionModel(obj);
+      }
+  });
+
+/**
+ * A function to instantiate a selection model.  this allows subclasses of
+ * Table to subclass this internal class.  To take effect, this property must
+ * be set before calling the Table constructor.
+ */
+qx.OO.addProperty(
+  {
+    name :
+      "newTableColumnModel",
+    type :
+      "function",
+    setOnlyOnce :
+      true,
+    defaultValue:
+      function(obj)
+      {
+        return new qx.ui.table.TableColumnModel(obj);
+      }
+  });
+
+/**
+ * A function to instantiate a table pane.  this allows subclasses of Table to
+ * subclass this internal class.  To take effect, this property must be set
+ * before calling the Table constructor.
+ */
+qx.OO.addProperty(
+  {
+    name :
+      "newTablePane",
+    type :
+      "function",
+    setOnlyOnce :
+      true,
+    defaultValue:
+      function(obj)
+      {
+        return new qx.ui.table.TablePane(obj);
+      }
+  });
+
+/**
+ * A function to instantiate a table pane.  this allows subclasses of Table to
+ * subclass this internal class.  To take effect, this property must be set
+ * before calling the Table constructor.
+ */
+qx.OO.addProperty(
+  {
+    name :
+      "newTablePaneHeader",
+    type :
+      "function",
+    setOnlyOnce :
+      true,
+    defaultValue:
+      function(obj)
+      {
+        return new qx.ui.table.TablePaneHeader(obj);
+      }
+  });
+
+/**
+ * A function to instantiate a table pane scroller.  this allows subclasses of
+ * Table to subclass this internal class.  To take effect, this property must
+ * be set before calling the Table constructor.
+ */
+qx.OO.addProperty(
+  {
+    name :
+      "newTablePaneScroller",
+    type :
+      "function",
+    setOnlyOnce :
+      true,
+    defaultValue:
+      function(obj)
+      {
+        return new qx.ui.table.TablePaneScroller(obj);
+      }
+  });
+
+/**
+ * A function to instantiate a table pane model.  this allows subclasses of
+ * Table to subclass this internal class.  To take effect, this property must
+ * be set before calling the Table constructor.
+ */
+qx.OO.addProperty(
+  {
+    name :
+      "newTablePaneModel",
+    type :
+      "function",
+    setOnlyOnce :
+      true,
+    defaultValue:
+      function(columnModel)
+      {
+        return new qx.ui.table.TablePaneModel(columnModel);
+      }
+  });
 
 // property modifier
 qx.Proto._modifySelectionModel = function(propValue, propOldValue, propData) {
@@ -216,12 +357,12 @@ qx.Proto._modifyMetaColumnCounts = function(propValue, propOldValue, propData) {
     var columnModel = this.getTableColumnModel();
 
     for (var i = scrollerArr.length; i < metaColumnCounts.length; i++) {
-      var paneModel = new qx.ui.table.TablePaneModel(columnModel);
+      var paneModel = this.getNewTablePaneModel()(columnModel);
       paneModel.setFirstColumnX(leftX);
       paneModel.setMaxColumnCount(metaColumnCounts[i]);
       leftX += metaColumnCounts[i];
 
-      var paneScroller = new qx.ui.table.TablePaneScroller(this);
+      var paneScroller = this.getNewTablePaneScroller()(this);
       paneScroller.setTablePaneModel(paneModel);
 
       // Register event listener for vertical scrolling
@@ -279,7 +420,6 @@ qx.Proto._modifyHeaderCellHeight = function(propValue, propOldValue, propData) {
   return true;
 };
 
-
 /**
  * Returns the selection manager.
  *
@@ -408,6 +548,10 @@ qx.Proto._onScrollY = function(evt) {
  * @param evt {Map} the event.
  */
 qx.Proto._onkeydown = function(evt) {
+  if (! this.getEnabled()) {
+    return;
+  }
+
   var identifier = evt.getKeyIdentifier();
 
   var consumed = false;
@@ -494,6 +638,10 @@ qx.Proto._onkeydown = function(evt) {
 
 qx.Proto._onkeypress = function(evt)
 {
+  if (! this.getEnabled()) {
+    return;
+  }
+
   if (this.isEditing()) { return }
   // No editing mode
   var oldFocusedRow = this._focusedRow;
@@ -907,6 +1055,10 @@ qx.Proto._onColumnVisibilityBtExecuted = function() {
  */
 qx.Proto._toggleColumnVisibilityMenu = function() {
   if (this._columnVisibilityMenu == null || !this._columnVisibilityMenu.isSeeable()) {
+    if (! this.getEnabled()) {
+      return;
+    }
+
     // Show the menu
 
     // Create the new menu
index 8629be1fc0e5813bed96b96302d34554bd58c828..9b60a9eec7786c0705b7ce8c3e63e76def590bf3 100644 (file)
@@ -51,7 +51,7 @@ function(table) {
   this._verScrollBar.addEventListener("changeValue", this._onScrollY, this);
 
   // init header
-  this._header = new qx.ui.table.TablePaneHeader(this);
+  this._header = this.getTable().getNewTablePaneHeader()(this);
   this._header.set({ width:"auto", height:"auto" });
 
   this._headerClipper = new qx.ui.layout.CanvasLayout;
@@ -67,7 +67,7 @@ function(table) {
   this._top.add(this._headerClipper, this._spacer);
 
   // init pane
-  this._tablePane = new qx.ui.table.TablePane(this);
+  this._tablePane = this.getTable().getNewTablePane()(this);
   this._tablePane.set({ width:"auto", height:"auto" });
 
   this._focusIndicator = new qx.ui.layout.HorizontalBoxLayout;
@@ -415,8 +415,14 @@ qx.Proto._onScrollY = function(evt) {
  * @param evt {Map} the event.
  */
 qx.Proto._onmousewheel = function(evt) {
+  var table = this.getTable();
+
+  if (! table.getEnabled()) {
+    return;
+  }
+
   this._verScrollBar.setValue(this._verScrollBar.getValue()
-    - evt.getWheelDelta() * this.getTable().getRowHeight());
+    - evt.getWheelDelta() * table.getRowHeight());
 
   // Update the focus
   if (this._lastMousePageX && this.getFocusCellOnMouseMove()) {
@@ -431,8 +437,14 @@ qx.Proto._onmousewheel = function(evt) {
  * @param evt {Map} the event.
  */
 qx.Proto._onmousemove = function(evt) {
-  var tableModel = this.getTable().getTableModel();
-  var columnModel = this.getTable().getTableColumnModel();
+  var table = this.getTable();
+
+  if (! table.getEnabled()) {
+    return;
+  }
+
+  var tableModel = table.getTableModel();
+  var columnModel = table.getTableColumnModel();
 
   var useResizeCursor = false;
   var mouseOverColumn = null;
@@ -528,8 +540,14 @@ qx.Proto._onmousemove = function(evt) {
  * @param evt {Map} the event.
  */
 qx.Proto._onmousedown = function(evt) {
-  var tableModel = this.getTable().getTableModel();
-  var columnModel = this.getTable().getTableColumnModel();
+  var table = this.getTable();
+
+  if (! table.getEnabled()) {
+    return;
+  }
+
+  var tableModel = table.getTableModel();
+  var columnModel = table.getTableColumnModel();
 
   var pageX = evt.getPageX();
   var pageY = evt.getPageY();
@@ -558,7 +576,7 @@ qx.Proto._onmousedown = function(evt) {
     var selectBeforeFocus = this.getSelectBeforeFocus();
 
     if (selectBeforeFocus) {
-      this.getTable()._getSelectionManager().handleMouseDown(row, evt);
+      table._getSelectionManager().handleMouseDown(row, evt);
     }
 
     // The mouse is over the data -> update the focus
@@ -567,7 +585,7 @@ qx.Proto._onmousedown = function(evt) {
     }
 
     if (! selectBeforeFocus) {
-      this.getTable()._getSelectionManager().handleMouseDown(row, evt);
+      table._getSelectionManager().handleMouseDown(row, evt);
     }
   }
 }
@@ -579,7 +597,13 @@ qx.Proto._onmousedown = function(evt) {
  * @param evt {Map} the event.
  */
 qx.Proto._onmouseup = function(evt) {
-  var columnModel = this.getTable().getTableColumnModel();
+  var table = this.getTable();
+
+  if (! table.getEnabled()) {
+    return;
+  }
+
+  var columnModel = table.getTableColumnModel();
   var paneModel = this.getTablePaneModel();
 
   if (this._resizeColumn != null) {
@@ -630,7 +654,7 @@ qx.Proto._onmouseup = function(evt) {
     // This is a normal mouse up
     var row = this._getRowForPagePos(evt.getPageX(), evt.getPageY());
     if (row != -1 && row != null) {
-      this.getTable()._getSelectionManager().handleMouseUp(row, evt);
+      table._getSelectionManager().handleMouseUp(row, evt);
     }
   }
 }
@@ -642,7 +666,13 @@ qx.Proto._onmouseup = function(evt) {
  * @param evt {Map} the event.
  */
 qx.Proto._onclick = function(evt) {
-  var tableModel = this.getTable().getTableModel();
+  var table = this.getTable();
+
+  if (! table.getEnabled()) {
+    return;
+  }
+
+  var tableModel = table.getTableModel();
 
   var pageX = evt.getPageX();
   var pageY = evt.getPageY();
@@ -659,11 +689,11 @@ qx.Proto._onclick = function(evt) {
         var ascending = (col != sortCol) ? true : !tableModel.isSortAscending();
 
         tableModel.sortByColumn(col, ascending);
-        this.getTable().getSelectionModel().clearSelection();
+        table.getSelectionModel().clearSelection();
       }
     }
   } else if (row != null) {
-    this.getTable()._getSelectionManager().handleClick(row, evt);
+    table._getSelectionManager().handleClick(row, evt);
   }
 }
 
@@ -687,6 +717,12 @@ qx.Proto._ondblclick = function(evt) {
  * @param evt {Map} the event.
  */
 qx.Proto._onmouseout = function(evt) {
+  var table = this.getTable();
+
+  if (! table.getEnabled()) {
+    return;
+  }
+
   /*
   // Workaround: See _onmousemove
   this._lastMousePageX = null;
@@ -1248,6 +1284,12 @@ qx.Proto._updateContent = function() {
  * Updates the location and the visibility of the focus indicator.
  */
 qx.Proto._updateFocusIndicator = function() {
+  var table = this.getTable();
+
+  if (! table.getEnabled()) {
+    return;
+  }
+
   if (this._focusedCol == null) {
     this._focusIndicator.hide();
   } else {
@@ -1255,11 +1297,11 @@ qx.Proto._updateFocusIndicator = function() {
     if (xPos == -1) {
       this._focusIndicator.hide();
     } else {
-      var columnModel = this.getTable().getTableColumnModel();
+      var columnModel = table.getTableColumnModel();
       var paneModel = this.getTablePaneModel();
 
       var firstRow = this._tablePane.getFirstVisibleRow();
-      var rowHeight = this.getTable().getRowHeight();
+      var rowHeight = table.getRowHeight();
 
       this._focusIndicator.setHeight(rowHeight + 3);
       this._focusIndicator.setWidth(columnModel.getColumnWidth(this._focusedCol) + 3);
@@ -1267,6 +1309,11 @@ qx.Proto._updateFocusIndicator = function() {
       this._focusIndicator.setLeft(paneModel.getColumnLeft(this._focusedCol) - 2);
 
       this._focusIndicator.show();
+
+      // Force redisplay of the focus indicator right away.  Without this, it
+      // waits until the mouse stops moving for a while before updating, and
+      // appears as if it is slow to respond.
+      qx.ui.core.Widget.flushGlobalQueues();
     }
   }
 }
index adedd829a98ddf3cd03f50405e5d0221fa7848fe..d089fdd643a99bf5622e06fb0daad9ad0a843a0d 100644 (file)
@@ -40,6 +40,8 @@ qx.Proto._getCellStyle = function(cellInfo)
 {
   // Return the style for the div for the cell.  If there's cell-specific
   // style information provided, append it.
-  var html = qx.ui.treevirtual.SimpleTreeDataCellRenderer.MAIN_DIV_STYLE;
+  var html =
+    cellInfo.style +
+    qx.ui.treevirtual.SimpleTreeDataCellRenderer.MAIN_DIV_STYLE;
   return html;
 };
diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SelectionManager.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SelectionManager.js
new file mode 100644 (file)
index 0000000..94e5154
--- /dev/null
@@ -0,0 +1,165 @@
+/* ************************************************************************
+
+   qooxdoo - the new era of web development
+
+   http://qooxdoo.org
+
+   Copyright:
+     2007 Derrell Lipman
+
+   License:
+     LGPL: http://www.gnu.org/licenses/lgpl.html
+     EPL: http://www.eclipse.org/org/documents/epl-v10.php
+     See the LICENSE file in the project's top-level directory for details.
+
+   Authors:
+     * Derrell Lipman (derrell)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(treevirtual)
+
+************************************************************************ */
+
+/**
+ * A selection manager. This is a helper class that handles all selection
+ * related events and updates a SelectionModel.
+ * <p>
+ * This Selection Manager differs from its superclass in that we do not want
+ * rows to be selected when moving around with the keyboard.
+ */
+qx.OO.defineClass("qx.ui.treevirtual.SelectionManager",
+                  qx.ui.table.SelectionManager,
+function(table)
+{
+  qx.ui.table.SelectionManager.call(this);
+
+  this._table = table;
+});
+
+
+/**
+ * Handles a key down event that moved the focus (E.g. up, down, home, end, ...).
+ *
+ * @param index {Integer} the index that is currently focused.
+ * @param evt {Map} the key event.
+ */
+qx.Proto.handleMoveKeyDown = function(index, evt)
+{
+  var selectionModel = this.getSelectionModel();
+
+  switch (evt.getModifiers())
+  {
+  case 0:
+    break;
+
+  case qx.event.type.DomEvent.SHIFT_MASK:
+    var anchor = selectionModel.getAnchorSelectionIndex();
+    
+    if (anchor == -1)
+    {
+      selectionModel.setSelectionInterval(index, index);
+    }
+    else
+    {
+      selectionModel.setSelectionInterval(anchor, index);
+    }
+    break;
+  }
+};
+
+
+/**
+ * Handles a select event.  First we determine if the click was on the
+ * open/close button and toggle the opened/closed state as necessary.  Then,
+ * if the click was not on the open/close button or if the table's
+ * "openCloseClickSelectsRow" property so indicates, call our superclass to
+ * handle the actual row selection.
+ *
+ * @param index {Integer} the index the event is pointing at.
+ * @param evt {Map} the mouse event.
+ */
+qx.Proto._handleSelectEvent = function(index, evt)
+{
+  function handleOpenCloseClick(table, index, evt)
+  {
+    // Get the node to which this event applies
+    var node = table.getTableModel().getValue(table.getFocusedColumn(),
+                                              table.getFocusedRow());
+    if (! node)
+    {
+      return false;
+    }
+
+    // Was this a mouse event?
+    if (evt instanceof qx.event.type.MouseEvent)
+    {
+      // Yup.  Get the order of the columns
+      var tcm = table.getTableColumnModel();
+      var columnPositions = tcm._getColToXPosMap();
+
+      // Calculate the position of the beginning of the tree column
+      var treeCol = table.getTableModel().getTreeColumn();
+      var left = qx.html.Location.getClientBoxLeft(table.getElement());
+      for (i = 0; i < columnPositions[treeCol].visX; i++)
+      {
+        left += tcm.getColumnWidth(columnPositions[i].visX);
+      }
+
+      // Was the click on the open/close button?  That button begins at
+      // (node.level - 1) * 19 + 2 (the latter for padding), and has width 19.
+      // We add a bit of latitude to that.
+      var x = evt.getClientX();
+      var latitude = 2;
+
+      var buttonPos = left + (node.level - 1) * 19 + 2;
+
+      if (x >= buttonPos - latitude && x <= buttonPos + 19 + latitude)
+      {
+        // Yup.  Toggle the opened state for this node.
+        table.toggleOpened(node);
+        return table.openCloseClickSelectsRow() ? false : true;
+      }
+      else
+      {
+        return false;
+      }
+    }
+    else
+    {
+      // See which key generated the event
+      var identifier = evt.getKeyIdentifier();
+      switch (identifier)
+      {
+      case "Space":
+        // This should only select the row, not toggle the opened state
+        return false;
+
+      case "Enter":
+        // Toggle the open state if open/close is allowed
+        if (! node.bHideOpenClose)
+        {
+          table.toggleOpened(node);
+        }
+        return table.openCloseClickSelectsRow() ? false : true;
+
+      default:
+        // Unrecognized key.  Ignore it.
+        return true;
+      }
+    }
+  }
+
+  // Call our local method to toggle the open/close state, if necessary
+  var bNoSelect = handleOpenCloseClick(this._table, index, evt);
+
+  // If we haven't been told not to do the selection...
+  if (! bNoSelect)
+  {
+    // then call the Selection Manager's method to do it.
+    var Sm = qx.ui.table.SelectionManager;
+    Sm.prototype._handleSelectEvent.call(this, index, evt);
+  }
+};
index 71abc0eb3faf5615a382381c6ea1545b18878bd7..7ae55277feb5deed904d503a5133b51996db0a2a 100644 (file)
 /* ************************************************************************
 
 #module(treevirtual)
+#embed(qx.icontheme/16/status/folder-open.png)
+#embed(qx.icontheme/16/places/folder.png)
+#embed(qx.icontheme/16/actions/document-open.png)
+#embed(qx.icontheme/16/actions/document-new.png)
+#embed(qx.widgettheme/tree/*)
+#embed(qx.static/blank.gif)
 
 ************************************************************************ */
 
@@ -49,22 +55,23 @@ qx.OO.addProperty({
                     getAlias     : "useTreeLines"
                   });
 
-/**
- * Set whether the open/close button should be displayed on a branch, even if
- * the branch has no children.
+/*
+ * When true, exclude only the first-level tree lines, creating, effectively,
+ * multiple unrelated root nodes.
  */
 qx.OO.addProperty({
-                    name         : "alwaysShowOpenCloseSymbol",
+                    name         : "excludeFirstLevelTreeLines",
                     type         : "boolean",
                     defaultValue : false
                   });
 
+
 /**
- * When true, exclude only the first-level tree lines, creating, effectively,
- * multiple unrelated root nodes.
+ * Set whether the open/close button should be displayed on a branch, even if
+ * the branch has no children.
  */
 qx.OO.addProperty({
-                    name         : "jensLautenbacherMode",
+                    name         : "alwaysShowOpenCloseSymbol",
                     type         : "boolean",
                     defaultValue : false
                   });
@@ -80,6 +87,7 @@ qx.Proto._getCellStyle = function(cellInfo)
   // Return the style for the div for the cell.  If there's cell-specific
   // style information provided, append it.
   var html =
+    cellInfo.style +
     qx.ui.treevirtual.SimpleTreeDataCellRenderer.MAIN_DIV_STYLE +
     (node.cellStyle ? node.cellStyle + ";" : "");
   return html;
@@ -135,7 +143,7 @@ qx.Proto._getContentHtml = function(cellInfo)
   // Generate the indentation.  Obtain icon determination values once rather
   // than each time through the loop.
   var bUseTreeLines = this.getUseTreeLines();
-  var bJensLautenbacherMode = this.getJensLautenbacherMode();
+  var bExcludeFirstLevelTreeLines = this.getExcludeFirstLevelTreeLines();
   var bAlwaysShowOpenCloseSymbol = this.getAlwaysShowOpenCloseSymbol();
 
   for (var i = 0; i < node.level; i++)
@@ -144,7 +152,7 @@ qx.Proto._getContentHtml = function(cellInfo)
                                      node,
                                      bUseTreeLines,
                                      bAlwaysShowOpenCloseSymbol,
-                                     bJensLautenbacherMode);
+                                     bExcludeFirstLevelTreeLines);
     html += addImage({
                        url         : imageUrl,
                        imageWidth  : 19,
@@ -188,15 +196,43 @@ qx.Proto._getContentHtml = function(cellInfo)
 };
 
 
+/**
+ * Determine the symbol to use for indentation of a tree row, at a particular
+ * column.  The indentation to use may be just white space or may be a tree
+ * line.  Tree lines come in numerous varieties, so the appropriate one is
+ * selected.
+ *
+ * @param column {Integer}
+ *   The column of indentation being requested, zero-relative
+ *
+ * @param node
+ *   The node being displayed in the row.  The properties of a node are
+ *   described in {@link qx.ui.treevirtual.SimpleTreeDataModel}
+ *
+ * @param bUseTreeLines {Boolean}
+ *   Whether to find an appropriate tree line icon, or simply provide white
+ *   space.
+ *
+ * @param bAlwaysShowOpenCloseSymbol {Boolean}
+ *   Whether to display the open/close icon for a node even if it has no
+ *   children.
+ *
+ * @param bExcludeFirstLevelTreeLines {Boolean}
+ *   If bUseTreeLines is enabled, then further filtering of the left-most tree
+ *   line may be specified here.  If <i>true</i> then the left-most tree line,
+ *   between top-level siblings, will not be displayed.  If <i>false</i>, then
+ *   the left-most tree line wiill be displayed just like all of the other
+ *   tree lines.
+ */
 qx.Proto._getIndentSymbol = function(column,
                                      node,
                                      bUseTreeLines,
                                      bAlwaysShowOpenCloseSymbol,
-                                     bJensLautenbacherMode)
+                                     bExcludeFirstLevelTreeLines)
 {
-  // If we're in column 0 and jensLautenbacherMode is enabled, then we treat
-  // this as if no tree lines were requested.
-  if (column == 0 && bJensLautenbacherMode)
+  // If we're in column 0 and excludeFirstLevelTreeLines is enabled, then
+  // we treat this as if no tree lines were requested.
+  if (column == 0 && bExcludeFirstLevelTreeLines)
   {
     bUseTreeLines = false;
   }
@@ -212,11 +248,11 @@ qx.Proto._getIndentSymbol = function(column,
 
   var bLastChild = node.lastChild[node.lastChild.length - 1];
 
-  // Is this a branch node?
+  // Is this a branch node that does not have the open/close button hidden?
   if (node.type == qx.ui.treevirtual.SimpleTreeDataModel.Type.BRANCH &&
-      (node.opened === true || node.opened === false))
+      ! node.bHideOpenClose)
   {
-    // Determine if this node has any children
+    // Yup.  Determine if this node has any children
     var child = null;
     for (child in node.children)
     {
@@ -232,7 +268,7 @@ qx.Proto._getIndentSymbol = function(column,
       if (! bUseTreeLines)
       {
         // ... then just use a plus or minus
-        return (node.opened
+        return (node.bOpened
                 ? this.WIDGET_TREE_URI + "minus.gif"
                 : this.WIDGET_TREE_URI + "plus.gif");
       }
@@ -244,14 +280,14 @@ qx.Proto._getIndentSymbol = function(column,
         if (bLastChild)
         {
           // ... then use no tree lines.
-          return (node.opened
+          return (node.bOpened
                   ? this.WIDGET_TREE_URI + "only_minus.gif"
                   : this.WIDGET_TREE_URI + "only_plus.gif");
         }
         else
         {
           // otherwise, use descender lines but no ascender.
-          return (node.opened
+          return (node.bOpened
                   ? this.WIDGET_TREE_URI + "start_minus.gif"
                   : this.WIDGET_TREE_URI + "start_plus.gif");
         }
@@ -261,16 +297,16 @@ qx.Proto._getIndentSymbol = function(column,
       // parent?
       if (bLastChild)
       {
-        // Yup.   Return an ending plus or minus, or blank if node.opened so
+        // Yup.   Return an ending plus or minus, or blank if node.bOpened so
         // indicates.
-        return (node.opened
+        return (node.bOpened
                 ? this.WIDGET_TREE_URI + "end_minus.gif"
                 : this.WIDGET_TREE_URI + "end_plus.gif");
       }
 
       // Otherwise, return a crossing plus or minus, or a blank if
-      // node.opened so indicates.
-      return (node.opened
+      // node.bOpened so indicates.
+      return (node.bOpened
               ? this.WIDGET_TREE_URI + "cross_minus.gif"
               : this.WIDGET_TREE_URI + "cross_plus.gif");
     }
@@ -287,22 +323,9 @@ qx.Proto._getIndentSymbol = function(column,
   }
 
   return this.STATIC_IMAGE_URI + "blank.gif";
-}
-
-
-// overridden
-qx.Proto._createCellStyle_array_join = function(cellInfo, htmlArr)
-{
-  throw new Error("USE_ARRAY_JOIN not supported");
 };
 
 
-
-qx.Proto._createContentHtml_array_join = function(cellInfo, htmlArr)
-{
-  throw new Error("USE_ARRAY_JOIN not supported");
-};
-
 qx.Class.MAIN_DIV_STYLE =
   ';overflow:hidden;white-space:nowrap;border-right:1px solid #eeeeee;' +
   'padding-left:2px;padding-right:2px;cursor:default' +
index 215830c224763bb130741f47ce121ff219321f79..f9ff3a97581393f1b6e99bf9523f76c144536176 100644 (file)
  *
  * The object structure of a single node of the tree is:
  *
+ * <pre>
  * {
- *   type          : qx.ui.treevirtual.Type.LEAF,
- *   parentNodeId  : 23,   // index in _nodeArr of the parent node
- *   label         : "My Documents",
- *   bSelected     : true, // true if node is selected; false otherwise
- *   opened        : null, // true (-), false (+), or null (no +/-)
- *   icon          : "images/folder.gif",
- *   iconSelected  : "images/folder_selected.gif",
- *   children      : [ ],  // each value is an index into _nodeArr
- *
- *   cellStyle     : "background-color:cyan"
- *   labelStyle    : "background-color:red;color:white"
+ *   // USER-PROVIDED ATTRIBUTES
+ *   // ------------------------
+ *   type           : qx.ui.treevirtual.Type.LEAF,
+ *   parentNodeId   : 23,    // index in _nodeArr of the parent node
+ *   label          : "My Documents",
+ *   bSelected      : true,  // true if node is selected; false otherwise
+ *   bOpened        : true,  // true (-), false (+)
+ *   bHideOpenClose : false, // whether to hide the open/close button
+ *   icon           : "images/folder.gif",
+ *   iconSelected   : "images/folder_selected.gif",
+ *   children       : [ ],   // each value is an index into _nodeArr
  *
+ *   cellStyle      : "background-color:cyan"
+ *   labelStyle     : "background-color:red;color:white"
+ *
+ *   // INTERNALLY-CALCULATED ATTRIBUTES
+ *   // --------------------------------
  *   // The following properties need not (and should not) be set by the
  *   // caller, but are automatically calculated.  Some are used internally,
  *   // while others may be of use to event listeners.
  *
- *   nodeId        : 42,   // The index in _nodeArr, useful to event listeners
+ *   nodeId         : 42,   // The index in _nodeArr, useful to event listeners
  *
- *   level         : 2,    // The indentation level of this tree node
+ *   level          : 2,    // The indentation level of this tree node
  *
- *   bFirstChild   : true,
- *   lastChild     : [ false ],  // Array where the index is the column of
- *                               // indentation, and the value is a boolean.
- *                               // These are used to locate the
- *                               // appropriate "tree line" icon.
+ *   bFirstChild    : true,
+ *   lastChild      : [ false ],  // Array where the index is the column of
+ *                                // indentation, and the value is a boolean.
+ *                                // These are used to locate the
+ *                                // appropriate "tree line" icon.
  * }
+ * </pre>
  */
 qx.OO.defineClass("qx.ui.treevirtual.SimpleTreeDataModel",
                   qx.ui.table.AbstractTableModel,
@@ -80,7 +87,7 @@ function()
   this._nodeArr.push(           // the root node, needed to store its children
     {
       label     : "<virtual root>",
-      opened    : true,
+      bOpened   : true,
       children  : [ ]
     });
 });
@@ -121,42 +128,60 @@ qx.Proto.sortByColumn = function(columnIndex, ascending)
 };
 
 
+/**
+ * Returns the column index the model is sorted by. This model is never
+ * sorted, so -1 is returned.
+ *
+ * @return {Integer}
+ *   -1, to indicate that the model is not sorted.
+ */
 qx.Proto.getSortColumnIndex = function()
 {
   return -1;
 };
 
 
-qx.Proto.isSortAscending = function()
+/**
+ * Specifies which column the tree is to be displayed in.  The tree is
+ * displayed using the SimpleTreeDataCellRenderer.  Other columns may be
+ * provided which use different cell renderers.
+ *
+ * @param columnIndex {Integer}
+ *   The index of the column in which the tree should be displayed.
+ */
+qx.Proto.setTreeColumn = function(columnIndex)
 {
-  return true;
+  this._treeColumn = columnIndex;
 };
 
 
-qx.Proto.getRowCount = function()
+/**
+ * Get the column in which the tree is to be displayed.
+ *
+ * @return {Integer}
+ *   The column in whcih the tree is to be displayed
+ */
+qx.Proto.getTreeColumn = function()
 {
-  return this._rowArr.length;
+  return this._treeColumn;
 };
 
 
-qx.Proto.setTreeColumn = function(columnIndex)
-{
-  this._treeColumn = columnIndex;
-}
-
-
-qx.Proto.getTreeColumn = function()
+// overridden
+qx.Proto.getRowCount = function()
 {
-  return this._treeColumn;
-}
+  return this._rowArr.length;
+};
 
 
+// overridden
 qx.Proto.getRowData = function(rowIndex)
 {
   return this._rowArr[rowIndex];
-}
+};
 
 
+// overridden
 qx.Proto.getValue = function(columnIndex, rowIndex)
 {
   if (rowIndex < 0 || rowIndex >= this._rowArr.length)
@@ -181,9 +206,58 @@ qx.Proto.getValue = function(columnIndex, rowIndex)
 };
 
 
+/**
+ * Add a node to the tree.
+ *
+ * NOTE: This method is for <b>internal use</b> and should not be called by
+ *       users of this class.  Instead, call {@link #addBranch} or {@link
+ *       #addLeaf}.  There is no guarantee that the interface to this method
+ *       will remain unchanged over time.
+ *
+ * @param parentNodeId {Integer}
+ *   The node id of the parent of the node being added
+ *
+ * @param label {String}
+ *   The string to display as the label for this node
+ *
+ * @param bOpened {Integer}
+ *   <i>true</i> if the tree should be rendered in its opened state;
+ *   <i>false</i> otherwise.
+ *
+ * @param bHideOpenCloseButton
+ *   <i>true</i> if the open/close button should be hidden (not displayed);
+ *   </i>false</i> to display the open/close button for this node.
+ *
+ * @param type {Integer}
+ *   The type of node being added.  The type determines whether children may
+ *   be added, and determines the default icons to use.  This parameter must
+ *   be one of the following values:
+ *   <dl>
+ *     <dt>qx.ui.treevirtual.SimpleTreeDataModel.Type.BRANCH</dt>
+ *     <dd>
+ *       This node is a branch.  A branch node may have children.
+ *     </dd>
+ *     <dt>qx.ui.treevirtual.SimpleTreeDataModel.Type.LEAF</dt>
+ *     <dd>
+ *       This node is a leaf, and may not have children
+ *     </dd>
+ *   </dl>
+ *
+ * @param icon {String}
+ *   The relative (subject to alias expansion) or full path of the icon to
+ *   display for this node when it is not a selected node.
+ *
+ * @param iconSelected {String}
+ *   The relative (subject to alias expansion) or full path of the icon to
+ *   display for this node when it is a selected node.
+ *
+ * @return {Integer}
+ *   The node id of the newly-added node.
+ */
 qx.Proto._addNode = function(parentNodeId,
                              label,
-                             opened,
+                             bOpened,
+                             bHideOpenCloseButton,
                              type,
                              icon,
                              iconSelected)
@@ -212,10 +286,12 @@ qx.Proto._addNode = function(parentNodeId,
     parentNodeId = 0;
   }
 
-  // If this is a file, we don't present open/close icon
-  if (type == qx.ui.treevirtual.SimpleTreeDataModel.Type.LEAF && opened)
+  // If this is a leaf, we don't present open/close icon
+  if (type == qx.ui.treevirtual.SimpleTreeDataModel.Type.LEAF)
   {
-    throw new Error("Attempt to display a LEAF opened [" + label + "]");
+    // mask off the opened bit but retain the hide open/close button bit
+    bOpened = false;
+    bHideOpenClose = false;
   }
 
   // Determine the node id of this new node
@@ -224,15 +300,16 @@ qx.Proto._addNode = function(parentNodeId,
   // Set the data for this node.
   var node =
     {
-      type         : type,
-      parentNodeId : parentNodeId,
-      label        : label,
-      bSelected    : false,
-      opened       : opened,
-      icon         : icon,
-      iconSelected : iconSelected,
-      children     : [ ],
-      columnData   : [ ]
+      type           : type,
+      parentNodeId   : parentNodeId,
+      label          : label,
+      bSelected      : false,
+      bOpened        : bOpened,
+      bHideOpenClose : bHideOpenCloseButton,
+      icon           : icon,
+      iconSelected   : iconSelected,
+      children       : [ ],
+      columnData     : [ ]
     };
 
   // Add this node to the array
@@ -247,21 +324,71 @@ qx.Proto._addNode = function(parentNodeId,
 
 
 
+/**
+ * Add a branch to the tree.
+ *
+ * @param parentNodeId {Integer}
+ *   The node id of the parent of the node being added
+ *
+ * @param label {String}
+ *   The string to display as the label for this node
+ *
+ * @param bOpened {Boolean}
+ *   <i>True</i> if the branch should be rendered in its opened state;
+ *   <i>false</i> otherwise.
+ *
+ * @param bHideOpenCloseButton {Boolean}
+ *   <i>True</i> if the open/close button should not be displayed;
+ *   <i>false</i> if the open/close button should be displayed
+ *
+ * @param icon {String}
+ *   The relative (subject to alias expansion) or full path of the icon to
+ *   display for this node when it is not a selected node.
+ *
+ * @param iconSelected {String}
+ *   The relative (subject to alias expansion) or full path of the icon to
+ *   display for this node when it is a selected node.
+ *
+ * @return {Integer}
+ *   The node id of the newly-added branch.
+ */
 qx.Proto.addBranch = function(parentNodeId,
                               label,
-                              opened,
+                              bOpened,
+                              bHideOpenCloseButton,
                               icon,
                               iconSelected)
 {
   return this._addNode(parentNodeId,
                        label,
-                       opened,
+                       bOpened,
+                       bHideOpenCloseButton,
                        qx.ui.treevirtual.SimpleTreeDataModel.Type.BRANCH,
                        icon,
                        iconSelected);
 };
 
 
+/**
+ * Add a leaf to the tree.
+ *
+ * @param parentNodeId {Integer}
+ *   The node id of the parent of the node being added
+ *
+ * @param label {String}
+ *   The string to display as the label for this node
+ *
+ * @param icon {String}
+ *   The relative (subject to alias expansion) or full path of the icon to
+ *   display for this node when it is not a selected node.
+ *
+ * @param iconSelected {String}
+ *   The relative (subject to alias expansion) or full path of the icon to
+ *   display for this node when it is a selected node.
+ *
+ * @return {Integer}
+ *   The node id of the newly-added leaf.
+ */
 qx.Proto.addLeaf = function(parentNodeId,
                             label,
                             icon,
@@ -270,12 +397,21 @@ qx.Proto.addLeaf = function(parentNodeId,
   return this._addNode(parentNodeId,
                        label,
                        false,
+                       false,
                        qx.ui.treevirtual.SimpleTreeDataModel.Type.LEAF,
                        icon,
                        iconSelected);
 };
 
 
+/**
+ * Prune the tree by removing the specified node, and, if the node has
+ * children, recursively all of its children.
+ *
+ * @param nodeId {Integer}
+ *   The node id, previously returned by {@link #addLeaf} or {@link
+ *   #addBranch}, of the node (and its children) to be pruned from the tree.
+ */
 qx.Proto.prune = function(nodeId)
 {
   // First, recursively remove all children
@@ -308,18 +444,155 @@ qx.Proto.prune = function(nodeId)
  *
  * @param nodeArr {Array | null}
  *   Pass either an Array of node objects, or null.
- *
+ *   </p><p>
  *   If non-null, nodeArr is an array of node objects containing the entire
  *   tree to be displayed.  If loading the whole data en bulk in this way, it
  *   is assumed that the data is correct!  No error checking or validation is
  *   done.  You'd better know what you're doing!  Caveat emptor.
- *
+ *   </p><p>
  *   If nodeArr is null, then this call is a notification that the user has
  *   completed building or modifying a tree by issuing a series of calls to
- *   addNode().
+ *   {@link #addBranch} and/or {@link #addLeaf}.
+ *   <p>
  */
 qx.Proto.setData = function(nodeArr)
 {
+  var _this = this;
+
+  function render()
+  {
+    var inorder = function(nodeId, level)
+    {
+      var child = null;
+      var childNodeId;
+
+      // For each child of the specified node...
+      var numChildren = _this._nodeArr[nodeId].children.length;
+      for (var i = 0; i < numChildren; i++)
+      {
+        // Determine the node id of this child
+        childNodeId = _this._nodeArr[nodeId].children[i];
+
+        // Get the child node
+        child = _this._nodeArr[childNodeId];
+
+        // Skip deleted nodes
+        if (child == null)
+        {
+          continue;
+        }
+
+        // Listeners will need to know a node's id when they receive an event
+        child.nodeId = childNodeId;
+
+        // (Re-)assign this node's level
+        child.level = level;
+
+        // Determine if we're the first child of our parent
+        child.bFirstChild = (i == 0);
+
+        // Determine if we're the last child of our parent
+        child.lastChild = [ i == numChildren - 1 ];
+
+        // Get our parent.
+        var parent = _this._nodeArr[child.parentNodeId];
+
+        // For each parent node, determine if it is a last child
+        while (parent.nodeId)
+        {
+          var bLast = parent.lastChild[parent.lastChild.length - 1];
+          child.lastChild.unshift(bLast);
+          parent = _this._nodeArr[parent.parentNodeId];
+        }
+
+        // Ensure there's an entry in the columnData array for each column
+        if (! child.columnData)
+        {
+          child.columnData = [ ];
+        }
+
+        if (child.columnData.length < _this.getColumnCount())
+        {
+          child.columnData[_this.getColumnCount() - 1] = null;
+        }
+
+        // Add this node to the row array.  Initialize a row data array.
+        var rowData = [ ];
+
+        // If additional column data is provided...
+        if (child.columnData)
+        {
+          // ... then add each column data.
+          for (var j = 0; j < child.columnData.length; j++)
+          {
+            // Is this the tree column?
+            if (j == _this._treeColumn)
+            {
+              // Yup.  Add the tree node data
+              rowData.push(child);
+            }
+            else
+            {
+              // Otherwise, add the column data verbatim.
+              rowData.push(child.columnData[j]);
+            }
+          }
+        }
+        else
+        {
+          // No column data.  Just add the tree node.
+          rowData.push(child);
+        }
+
+        // If this node is selected, ...
+        if (child.bSelected)
+        {
+          // ... indicate so for the row.
+          rowData.selected = true;
+        }
+
+        // Track the _rowArr index for each node so we can handle selections
+        _this._nodeRowMap[child.nodeId] = _this._rowArr.length;
+
+        // Add the row data to the row array
+        _this._rowArr.push(rowData)
+
+        // If this child is opened, ...
+        if (child.bOpened)
+        {
+          // ... then add its children too.
+          inorder(childNodeId, level + 1);
+        }
+      }
+    }
+
+    // Reset the row array
+    _this._rowArr = [];
+
+    // Reset the _nodeArr -> _rowArr map
+    _this._nodeRowMap = [ ];
+
+    // Begin in-order traversal of the tree from the root to regenerate _rowArr
+    inorder(0, 1);
+
+    // Inform the listeners
+    if (_this.hasEventListeners(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED))
+    {
+      var data =
+        {
+          firstRow        : 0,
+          lastRow         : _this._rowArr.length - 1,
+          firstColumn     : 0,
+          lastColumn      : _this.getColumnCount() - 1
+        };
+
+      _this.dispatchEvent(new qx.event.type.DataEvent(
+                            qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED,
+                            data),
+                          true);
+    }
+  }
+
   if (nodeArr instanceof Array)
   {
     // Determine the set of selected nodes
@@ -341,7 +614,7 @@ qx.Proto.setData = function(nodeArr)
   }
 
   // Re-render the row array
-  this._render();
+  render();
 };
 
 
@@ -350,7 +623,7 @@ qx.Proto.setData = function(nodeArr)
  *
  * @return {Array}
  *   Array of node objects.  See {@link qx.ui.treevirtual.SimpleTreeDataModel}
- *   for a description of each node.
+ *   for a description nodes in this array.
  */
 qx.Proto.getData = function()
 {
@@ -360,10 +633,12 @@ qx.Proto.getData = function()
 
 
 /**
- * Add data to an additional column of the tree.
+ * Add data to an additional column (a column other than the tree column) of
+ * the tree.
  *
  * @param nodeId
- *   A node identifier, as previously returned by addBranch() or addLeaf().
+ *   A node identifier, as previously returned by {@link #addBranch} or {@link
+ *   addLeaf}.
  *
  * @param columnIndex
  *   The column number to which the provided data applies
@@ -377,6 +652,19 @@ qx.Proto.setColumnData = function(nodeId, columnIndex, data)
 }
 
 
+/**
+ * Set state attributes of a node.
+ *
+ * @param nodeId {Integer}
+ *   A node identifier, as previously returned by {@link #addBranch} or {@link
+ *   addLeaf}.
+ *
+ * @param attributes {Map}
+ *   Each property name in the map may correspond to the property names of a
+ *   node which are specified as <i>USER-PROVIDED ATTRIBUTES</i> in {@link
+ *   #SimpleTreeDataModel}.  Each property value will be assigned to the
+ *   corresponding property of the node specified by nodeId.
+ */
 qx.Proto.setState = function(nodeId, attributes)
 {
   for (var attribute in attributes)
@@ -400,13 +688,25 @@ qx.Proto.setState = function(nodeId, attributes)
 };
 
 
+/**
+ * Return the mapping of nodes to rendered rows.  This function is intended
+ * for use by the cell renderer, not by users of this class.
+ *
+ * @return {Array}
+ *   The array containing mappings of nodes to rendered rows.
+ */
 qx.Proto.getNodeRowMap = function()
 {
   return this._nodeRowMap;
 };
 
 
-qx.Proto.clearSelections = function()
+/*
+ * Clear all selections in the data model.  This method does not clear
+ * selections displayed in the widget, and is intended for internal use, not
+ * by users of this class.
+ */
+qx.Proto._clearSelections = function()
 {
   // Clear selected state for any selected nodes.
   for (var selection in this._selections)
@@ -419,153 +719,22 @@ qx.Proto.clearSelections = function()
 };
 
 
-qx.Proto.getSelections = function()
-{
-  return this._selections;
-};
-
-
 /**
- * Render (or re-render) the tree.  Call this function after having added
- * and/or deleted tree nodes (Files or Folders), or after having made changes
- * to tree (or tree node) options that will cause the tree to be rendered
- * differently.  This function should typically be called after a set of
- * concurrent changes, not after each change.
+ * Return the nodes that are currently selected.
+ *
+ * @return {Array}
+ *   An array containing the nodes that are currently selected.
  */
-qx.Proto._render = function()
+qx.Proto.getSelectedNodes = function()
 {
-  var _this = this;
+  var nodes = [ ];
 
-  var inorder = function(nodeId, level)
+  for (var nodeId in this._selections)
   {
-    var child = null;
-    var childNodeId;
-
-    // For each child of the specified node...
-    var numChildren = _this._nodeArr[nodeId].children.length;
-    for (var i = 0; i < numChildren; i++)
-    {
-      // Determine the node id of this child
-      childNodeId = _this._nodeArr[nodeId].children[i];
-
-      // Get the child node
-      child = _this._nodeArr[childNodeId];
-
-      // Skip deleted nodes
-      if (child == null)
-      {
-        continue;
-      }
-
-      // Listeners will need to know a node's id when they receive an event
-      child.nodeId = childNodeId;
-
-      // (Re-)assign this node's level
-      child.level = level;
-
-      // Determine if we're the first child of our parent
-      child.bFirstChild = (i == 0);
-
-      // Determine if we're the last child of our parent
-      child.lastChild = [ i == numChildren - 1 ];
-
-      // Get our parent.
-      var parent = _this._nodeArr[child.parentNodeId];
-
-      // For each parent node, determine if it is a last child
-      while (parent.nodeId)
-      {
-        var bLast = parent.lastChild[parent.lastChild.length - 1];
-        child.lastChild.unshift(bLast);
-        parent = _this._nodeArr[parent.parentNodeId];
-      }
-
-      // Ensure there's an entry in the columnData array for each column
-      if (! child.columnData)
-      {
-        child.columnData = [ ];
-      }
-
-      if (child.columnData.length < _this.getColumnCount())
-      {
-        child.columnData[_this.getColumnCount() - 1] = null;
-      }
-
-      // Add this node to the row array.  Initialize a row data array.
-      var rowData = [ ];
-
-      // If additional column data is provided...
-      if (child.columnData)
-      {
-        // ... then add each column data.
-        for (var j = 0; j < child.columnData.length; j++)
-        {
-          // Is this the tree column?
-          if (j == _this._treeColumn)
-          {
-            // Yup.  Add the tree node data
-            rowData.push(child);
-          }
-          else
-          {
-            // Otherwise, add the column data verbatim.
-            rowData.push(child.columnData[j]);
-          }
-        }
-      }
-      else
-      {
-        // No column data.  Just add the tree node.
-        rowData.push(child);
-      }
-
-      // If this node is selected, ...
-      if (child.bSelected)
-      {
-        // ... indicate so for the row.
-        rowData.selected = true;
-      }
-
-      // Track the _rowArr index for each node so we can handle selections
-      _this._nodeRowMap[child.nodeId] = _this._rowArr.length;
-
-      // Add the row data to the row array
-      _this._rowArr.push(rowData)
-
-      // If this child is opened, ...
-      if (child.opened)
-      {
-        // ... then add its children too.
-        inorder(childNodeId, level + 1);
-      }
-    }
+    nodes.push(this._nodeArr[nodeId]);
   }
 
-  // Reset the row array
-  this._rowArr = [];
-
-  // Reset the _nodeArr -> _rowArr map
-  this._nodeRowMap = [ ];
-
-  // Begin in-order traversal of the tree from the root to regenerate _rowArr
-  inorder(0, 1);
-
-  // Inform the listeners
-  if (this.hasEventListeners(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED))
-  {
-    var data =
-      {
-        firstRow        : 0,
-        lastRow         : this._rowArr.length - 1,
-        firstColumn     : 0,
-        lastColumn      : this.getColumnCount() - 1
-      };
-
-    this.dispatchEvent(new qx.event.type.DataEvent(
-                         qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED,
-                         data),
-                       true);
-  }
+  return nodes;
 };
 
 
index 0acf87f56f5f242fbbc75f473dd619a10851bed0..2ffae79436cfd0e808bb284a680a225c10fdbfdc 100644 (file)
@@ -50,6 +50,12 @@ function(headings)
   }
   tableModel.setColumns(headings);
 
+  this.setNewSelectionManager(
+      function(obj)
+      {
+        return new qx.ui.treevirtual.SelectionManager(obj);
+      });
+
   // Call our superclass constructor
   qx.ui.table.Table.call(this, tableModel);
 
@@ -84,6 +90,9 @@ function(headings)
       bgcolFocusedBlur         : "#f0f0f0"
     });
 
+  // Set the cell focus color
+  this.setCellFocusAttributes({ backgroundColor : "lightblue" });
+
 /*
   // Use this instead, to help determine which does what
   this.setRowColors(
@@ -97,44 +106,19 @@ function(headings)
     });
 */
 
-  // Remove the outline on focus.
-  //
-  // KLUDGE ALERT: I really want to remove the old appearance, but I don't
-  // know how to do that.  Instead, for the moment, I'll just use an existing
-  // appearance that won't affect the focus indicator, making the appearance
-  // effectively a no-op.
-  var scrollerArr = this._getPaneScrollerArr();
-  for (var i = 0; i < scrollerArr.length; i++)
-  {
-    scrollerArr[i]._focusIndicator.setAppearance("image");
+  // Get the list of pane scrollers
+  var scrollers = this._getPaneScrollerArr();
 
-    // Set the pane scrollers to handle the selection before displaying the
-    // focus, so we can manipulate the selected icon.
-    scrollerArr[i].setSelectBeforeFocus(true);
-  }
-
-  // Arrange to select events locally. Replace the selection manager's method
-  // with one that calls our _handleSelectEvent method first, and it it
-  // indicates we should actually select the row, then call the selection
-  // manager's method.  Our method handles deciding if the click was on the
-  // open/close button, and toggling the opened/closed state as necessary.
-  // The selection manager's method handles marking the selected row.
-  var _this = this;
-  this._getSelectionManager()._handleSelectEvent = function(index, evt)
+  // For each scroller...
+  for (var i = 0; i < scrollers.length; i++)
   {
-    var Sm = qx.ui.table.SelectionManager;
-    var Tv = qx.ui.treevirtual.TreeVirtual;
+    // ... remove the outline on focus, 
+    scrollers[i]._focusIndicator.setAppearance("treevirtual-focus-indicator");
 
-    // Call our local method to toggle the open/close state, if necessary
-    var bNoSelect = Tv.prototype._handleSelectEvent.call(_this, index, evt);
-
-    // If we haven't been told not to do the selection...
-    if (! bNoSelect)
-    {
-      // then call the Selection Manager's method to do it.
-      Sm.prototype._handleSelectEvent.call(_this, index, evt);
-    }
-  };
+    // ... and set the pane scrollers to handle the selection before
+    // displaying the focus, so we can manipulate the selected icon.
+    scrollers[i].setSelectBeforeFocus(true);
+  }
 });
 
 
@@ -241,18 +225,19 @@ qx.Proto.setAlwaysShowOpenCloseSymbol = function(b)
 
 
 /**
- * Set whether drawing of first-level tree-node lines are disabled.
+ * Set whether drawing of first-level tree-node lines are disabled even if
+ * drawing of tree lines is enabled.  (See also @link {#setUseTreeLines})
  *
  * @param b {Boolean}
  *   <i>true</i> if first-level tree lines should be disabled;
  *   <i>false</i> for normal operation.
  */
-qx.Proto.setJensLautenbacherMode = function(b)
+qx.Proto.setExcludeFirstLevelTreeLines = function(b)
 {
   var stdcm = this.getTableModel();
   var treeCol = stdcm.getTreeColumn();
   var dcr = this.getTableColumnModel().getDataCellRenderer(treeCol);
-  dcr.setJensLautenbacherMode(b);
+  dcr.setExcludeFirstLevelTreeLines(b);
 
   // Inform the listeners
   if (stdcm.hasEventListeners(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED))
@@ -274,16 +259,17 @@ qx.Proto.setJensLautenbacherMode = function(b)
 
 
 /**
- * Get whether drawing of first-level tree lines should be disabled
+ * Get whether drawing of first-level tree lines should be disabled even if
+ * drawing of tree lines is enabled.  (See also {@link #getUseTreeLines})
  *
  * @return {Boolean}
  *   <i>true</i> if tree lines are in use; <i>false</i> otherwise.
  */
-qx.Proto.getJensLautenbacherMode = function()
+qx.Proto.getExcludeFirstLevelTreeLines = function()
 {
   var treeCol = this.getTableModel().getTreeColumn();
   var dcr = this.getTableColumnModel().getDataCellRenderer(treeCol);
-  return dcr.getJensLautenbacherMode();
+  return dcr.getExcludeFirstLevelTreeLines();
 }
 
 
@@ -302,12 +288,36 @@ qx.Proto.getAlwaysShowOpenCloseSymbol = function()
 };
 
 
+/**
+ * Set the selection mode.
+ *
+ * @param mode {Integer}
+ *   The selection mode to be used.  It may be any of:
+ *   <pre>
+ *     qx.ui.treevirtual.SelectionMode.NONE:
+ *        Nothing can ever be selected.
+ *
+ *     qx.ui.treevirtual.SelectionMode.SINGLE
+ *        Allow only one selected item.
+ *
+ *     qx.ui.treevirtual.SelectionMode.SINGLE_INTERVAL
+ *        Allow one contiguous interval of selected items.
+ *
+ *     qx.ui.treevirtual.SelectionMode.MULTIPLE_INTERVAL
+ *        Allow any selected items, whether contiguous or not.
+ *   </pre>
+ */
 qx.Proto.setSelectionMode = function(mode)
 {
   this.getSelectionModel().setSelectionMode(mode);
 }
 
-
+/**
+ * Get the selection mode currently in use.
+ *
+ * @return {Integer}
+ *   One of the values documented in {@link #setSelectionMode}
+ */
 qx.Proto.getSelectionMode = function(mode)
 {
   return this.getSelectionModel().getSelectionMode();
@@ -324,15 +334,8 @@ qx.Proto.getSelectionMode = function(mode)
  */
 qx.Proto.toggleOpened = function(node)
 {
-  // Ignore toggle request if 'opened' is not a boolean (i.e. we've been
-  // told explicitely not to display the open/close button).
-  if (node.opened !== true && node.opened !== false)
-  {
-    return;
-  }
-
   // Are we opening or closing?
-  if (node.opened)
+  if (node.bOpened)
   {
     // We're closing.  If there are listeners, generate a treeClose event.
     this.createDispatchDataEvent("treeClose", node);
@@ -354,24 +357,39 @@ qx.Proto.toggleOpened = function(node)
   }
 
   // Event handler may have modified the opened state.  Check before toggling.
-  if (node.opened === true || node.opened === false)
+  if (! node.bHideOpenClose)
   {
     // It's still boolean.  Toggle the state
-    node.opened = ! node.opened;
+    node.bOpened = ! node.bOpened;
 
     // Get the selection model
     var sm = this.getSelectionModel();
 
+    // Get the data model
+    var dm = this.getTableModel();
+
+    // Determine if this node was selected
+    var rowIndex = dm.getNodeRowMap()[node.nodeId];
+
+    // Is this row already selected?
+    var bSelected = sm.isSelectedIndex(rowIndex);
+
     // Clear the old selections in the tree
     this.getSelectionModel()._clearSelection();
 
     // Clear the old selections in the data model
-    this.getTableModel().clearSelections();
+    dm._clearSelections();
+
+    // If this row was selected, re-select it
+    if (bSelected)
+    {
+      this.setState(node.nodeId, { bSelected : true });
+    }
   }
 
   // Re-render the row data since formerly visible rows may now be invisible,
   // or vice versa.
-  this.getTableModel()._render();
+  this.getTableModel().setData();
 };
 
 
@@ -419,6 +437,41 @@ qx.Proto.setRowColors = function(colors)
 };
 
 
+/**
+ * Set the attributes used to indicate the cell that has the focus.
+ *
+ * @param attributes {Map}
+ *   The set of attributes that the cell focus indicator should have.  This is
+ *   in the format required to call the <i>set()</i> method of a widget, e.g.
+ *   <p>
+ *   { backgroundColor: blue }
+ *   <p>
+ *   If not otherwise specified, the opacity is set to 0.2 so that the cell
+ *   data can be seen "through" the cell focus indicator which overlays it.
+ *   <p>
+ *   For no visible focus indicator, use { backgroundColor : "transparent" }
+ *   <p>
+ *   The focus indicator is a box the size of the cell, which overlays the
+ *   cell itself.  There is no text in the focus indicator itself, so it makes
+ *   no sense to set the color attribute or any other attribute that affects
+ *   fonts.
+ */
+qx.Proto.setCellFocusAttributes = function(attributes)
+{
+  // Add an opacity attribute so what's below the focus can be seen
+  if (! attributes.opacity)
+  {
+    attributes.opacity = 0.2;
+  }
+
+  var scrollers = this._getPaneScrollerArr();
+  for (var i = 0; i < scrollers.length; i++)
+  {
+    scrollers[i]._focusIndicator.set(attributes);
+  }  
+};
+
+
 /**
  * Event handler. Called when a key was pressed.
  *
@@ -429,18 +482,149 @@ qx.Proto.setRowColors = function(colors)
  */
 qx.Proto._onkeydown = function(evt)
 {
+  if (! this.getEnabled()) {
+    return;
+  }
+
   var identifier = evt.getKeyIdentifier();
 
   var consumed = false;
-  if (evt.getModifiers() == 0)
+  var modifiers = evt.getModifiers();
+  if (modifiers == 0)
   {
     switch (identifier)
     {
     case "Enter":
-      var node = this.getTableModel().getValue(this.getFocusedColumn(),
-                                               this.getFocusedRow());
+      // Get the data model
+      var dm = this.getTableModel();
+
+      // Get the focused node
+      var focusedRow = this.getFocusedRow();
+      var treeCol = dm.getTreeColumn();
+      var node = dm.getValue(treeCol, focusedRow);
 
-      this.toggleOpened(node);
+      if (! node.bHideOpenClose)
+      {
+        this.toggleOpened(node);
+      }
+      consumed = true;
+      break;
+
+    case "Left":
+      this.moveFocusedCell(-1, 0);
+      break;
+
+    case "Right":
+      this.moveFocusedCell(1, 0);
+      break;
+    }
+  }
+  else if (modifiers == qx.event.type.DomEvent.CTRL_MASK)
+  {
+    switch (identifier)
+    {
+    case "Left":
+      // Get the data model
+      var dm = this.getTableModel();
+
+      // Get the focused node
+      var focusedRow = this.getFocusedRow();
+      var treeCol = dm.getTreeColumn();
+      var node = dm.getValue(treeCol, focusedRow);
+
+      // If it's an open branch and open/close is allowed...
+      if (node.type == qx.ui.treevirtual.SimpleTreeDataModel.Type.BRANCH &&
+          ! node.bHideOpenClose &&
+          node.bOpened)
+      {
+        // ... then close it
+        this.toggleOpened(node);
+      }
+    
+      // Reset the focus to the current node
+      this.setFocusedCell(treeCol, focusedRow, true);
+
+      consumed = true;
+      break;
+
+    case "Right":
+      // Get the data model
+      var dm = this.getTableModel();
+
+      // Get the focused node
+      var focusedRow = this.getFocusedRow();
+      var treeCol = dm.getTreeColumn();
+      var node = dm.getValue(treeCol, focusedRow);
+
+      // If it's a closed branch and open/close is allowed...
+      if (node.type == qx.ui.treevirtual.SimpleTreeDataModel.Type.BRANCH &&
+          ! node.bHideOpenClose &&
+          ! node.bOpened)
+      {
+        // ... then open it
+        this.toggleOpened(node);
+      }
+
+      // Reset the focus to the current node
+      this.setFocusedCell(treeCol, focusedRow, true);
+    
+      consumed = true;
+      break;
+    }
+  }
+  else if (modifiers == qx.event.type.DomEvent.SHIFT_MASK)
+  {
+    switch (identifier)
+    {
+      case "Left":
+      // Get the data model
+      var dm = this.getTableModel();
+
+      // Get the focused node
+      var focusedRow = this.getFocusedRow();
+      var treeCol = dm.getTreeColumn();
+      var node = dm.getValue(treeCol, focusedRow);
+
+      // If we're not at the top-level already...
+      if (node.parentNodeId)
+      {
+        // Find out what rendered row our parent node is at
+        var rowIndex = dm.getNodeRowMap()[node.parentNodeId];
+      
+        // Set the focus to our parent
+        this.setFocusedCell(this._focusedCol, rowIndex, true);
+      }
+      
+      consumed = true;
+      break;
+
+      case "Right":
+      // Get the data model
+      var dm = this.getTableModel();
+
+      // Get the focused node
+      var focusedRow = this.getFocusedRow();
+      var treeCol = dm.getTreeColumn();
+      var node = dm.getValue(treeCol, focusedRow);
+
+      // If we're on a branch and open/close is allowed...
+      if (node.type == qx.ui.treevirtual.SimpleTreeDataModel.Type.BRANCH &&
+          ! node.bHideOpenClose)
+      {
+        // ... then first ensure the branch is open
+        if (! node.bOpened)
+        {
+          this.toggleOpened(node);
+        }
+
+        // If this node has children...
+        if (node.children.length > 0)
+        {
+          // ... then move the focus to the first child
+          this.moveFocusedCell(0, 1);
+        }
+      }
+      
       consumed = true;
       break;
     }
@@ -461,6 +645,39 @@ qx.Proto._onkeydown = function(evt)
 };
 
 
+qx.Proto._onkeypress = function(evt)
+{
+  if (! this.getEnabled()) {
+    return;
+  }
+
+  var consumed = false;
+
+  // Handle keys that are independant from the modifiers
+  var identifier = evt.getKeyIdentifier();
+  switch (identifier)
+  {
+    // Ignore events we already handled in _onkeydown
+    case "Left":
+    case "Right":
+      consumed = true;
+      break;
+  }
+
+  if (consumed)
+  {
+    evt.preventDefault();
+    evt.stopPropagation();
+  }
+  else
+  {
+    // Let our superclass handle this event
+    qx.ui.table.Table.prototype._onkeypress.call(this, evt);
+  }
+};
+
+
+
 /**
  * Event handler. Called when the selection has changed.
  *
@@ -469,7 +686,7 @@ qx.Proto._onkeydown = function(evt)
 qx.Proto._onSelectionChanged = function(evt)
 {
   // Clear the old list of selected nodes
-  this.getTableModel().clearSelections();
+  this.getTableModel()._clearSelections();
 
   // If selections are allowed, pass an event to our listeners
   if (this.getSelectionMode() !=
@@ -487,69 +704,20 @@ qx.Proto._onSelectionChanged = function(evt)
 
 
 /**
- * Handles the a selection event
- *
- * @param index {Integer}
- *   The row index the mouse is pointing at.
+ * Obtain the entire hierarchy of labels from the root down to the specified
+ * node.
  *
- * @param evt {Map}
- *   The mouse event.
+ * @param nodeId {Integer}
+ *   The node id of the node for which the hierarchy is desired.
  *
- * @return {Boolean}
- *   Returns <i>true</i> if the event was a click on the open/close button,
- *   <i>false</i> otherwise.
+ * @return {Array}
+ *   The returned array contains one string for each label in the hierarchy of
+ *   the node specified by the parameter.  Element 0 of the array contains the
+ *   label of the root node, element 1 contains the label of the node
+ *   immediately below root in the specified node's hierarchy, etc., down to
+ *   the last element in the array contain the label of the node referenced by
+ *   the parameter.
  */
-qx.Proto._handleSelectEvent = function(index, evt)
-{
-  // Get the node to which this event applies
-  var node = this.getTableModel().getValue(this.getFocusedColumn(),
-                                           this.getFocusedRow());
-  if (! node)
-  {
-    return false;
-  }
-
-  // Was this a mouse event?
-  if (evt instanceof qx.event.type.MouseEvent)
-  {
-    // Yup.  Get the order of the columns
-    var tcm = this.getTableColumnModel();
-    var columnPositions = tcm._getColToXPosMap();
-
-    // Calculate the position of the beginning of the tree column
-    var treeCol = this.getTableModel().getTreeColumn();
-    var left = 0;
-    for (i = 0; i < columnPositions[treeCol].visX; i++)
-    {
-      left += tcm.getColumnWidth(columnPositions[i].visX);
-    }
-
-    // Was the click on the open/close button?  That button begins at
-    // (node.level - 1) * 19 + 2 (the latter for padding), and has width 19.
-    // We add a bit of latitude to that.
-    var x = evt.getClientX();
-    var latitude = 2;
-
-    var buttonPos = left + (node.level - 1) * 19 + 2;
-
-    if (x >= buttonPos - latitude && x <= buttonPos + 19 + latitude)
-    {
-      // Yup.  Toggle the opened state for this node.
-      this.toggleOpened(node);
-      return true;
-    }
-  }
-  else
-  {
-    // Key event.  Toggle the open state
-    this.toggleOpened(node);
-    return true;
-  }
-
-  return this.openCloseClickSelectsRow() ? true : false;
-};
-
-
 qx.Proto.getHierarchy = function(nodeId)
 {
   var _this = this;
@@ -579,6 +747,18 @@ qx.Proto.getHierarchy = function(nodeId)
 }
 
 
+/**
+ * Calculate and return the set of nodes which are currently selected by the
+ * user, on the screen.  In the process of calculating which nodes are
+ * selected, the nodes corresponding to the selected rows on the screen are
+ * marked as selected by setting their <i>bSelected</i> property to true, and
+ * all previously-selected nodes have their <i>bSelected</i> property reset to
+ * false.
+ *
+ * @return {Array}
+ *   An array of nodes matching the set of rows which are selected on the
+ *   screen. 
+ */
 qx.Proto._calculateSelectedNodes = function()
 {
   // Create an array of nodes that are now selected
@@ -603,6 +783,18 @@ qx.Proto._calculateSelectedNodes = function()
 };
 
 
+/**
+ * Return the nodes that are currently selected.
+ *
+ * @return {Array}
+ *   An array containing the nodes that are currently selected.
+ */
+qx.Proto.getSelectedNodes = function()
+{
+  return this.getTableModel().getSelectedNodes();
+};
+
+
 /*
  * Selection Modes {int}
  *
index 4a4e1263f8423276366b151a1e7b71870629a92b..bb5586ec79aa092ba4b87966867860f283dd3103 100644 (file)
@@ -4,7 +4,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: qooxdoo framework\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-02-05 13:42-0500\n"
+"POT-Creation-Date: 2007-02-05 23:17-0500\n"
 "PO-Revision-Date: 2006-12-19 15:52+0100\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -14,296 +14,296 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
 #. TRANSLATION: short representation of key names
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:61
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:61
 msgid "key_short_Backspace"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:62
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:62
 msgid "key_short_Tab"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:63
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:63
 msgid "key_short_Space"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:64
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:64
 msgid "key_short_Enter"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:65
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:65
 msgid "key_short_Shift"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:66
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:66
 msgid "key_short_Control"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:67
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:67
 msgid "key_short_Alt"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:68
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:68
 msgid "key_short_CapsLock"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:69
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:69
 msgid "key_short_Meta"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:70
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:70
 msgid "key_short_Escape"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:71
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:71
 msgid "key_short_Left"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:72
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:72
 msgid "key_short_Up"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:73
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:73
 msgid "key_short_Right"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:74
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:74
 msgid "key_short_Down"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:75
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:75
 msgid "key_short_PageUp"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:76
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:76
 msgid "key_short_PageDown"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:77
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:77
 msgid "key_short_End"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:78
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:78
 msgid "key_short_Home"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:79
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:79
 msgid "key_short_Insert"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:80
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:80
 msgid "key_short_Delete"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:81
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:81
 msgid "key_short_NumLock"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:82
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:82
 msgid "key_short_PrintScreen"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:83
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:83
 msgid "key_short_Scroll"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:84
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:84
 msgid "key_short_Pause"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:85
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:85
 msgid "key_short_Win"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:86
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:86
 msgid "key_short_Apps"
 msgstr ""
 
 #. TRANSLATION: full/long representation of key names
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:89
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:89
 msgid "key_full_Backspace"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:90
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:90
 msgid "key_full_Tab"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:91
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:91
 msgid "key_full_Space"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:92
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:92
 msgid "key_full_Enter"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:93
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:93
 msgid "key_full_Shift"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:94
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:94
 msgid "key_full_Control"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:95
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:95
 msgid "key_full_Alt"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:96
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:96
 msgid "key_full_CapsLock"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:97
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:97
 msgid "key_full_Meta"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:98
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:98
 msgid "key_full_Escape"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:99
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:99
 msgid "key_full_Left"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:100
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:100
 msgid "key_full_Up"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:101
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:101
 msgid "key_full_Right"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:102
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:102
 msgid "key_full_Down"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:103
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:103
 msgid "key_full_PageUp"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:104
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:104
 msgid "key_full_PageDown"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:105
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:105
 msgid "key_full_End"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:106
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:106
 msgid "key_full_Home"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:107
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:107
 msgid "key_full_Insert"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:108
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:108
 msgid "key_full_Delete"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:109
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:109
 msgid "key_full_NumLock"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:110
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:110
 msgid "key_full_PrintScreen"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:111
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:111
 msgid "key_full_Scroll"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:112
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:112
 msgid "key_full_Pause"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:113
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:113
 msgid "key_full_Win"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/Key.js:114
+#: ../../../frontend/framework/source/class/qx/locale/Key.js:114
 msgid "key_full_Apps"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorPopup.js:81
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorPopup.js:81
 msgid "Automatic"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorPopup.js:135
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js:292
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorPopup.js:135
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorSelector.js:292
 msgid "Preview (Old/New)"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorPopup.js:161
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorPopup.js:161
 msgid "Open ColorSelector"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorPopup.js:175
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorPopup.js:175
 msgid "Color Selector"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js:143
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorSelector.js:143
 msgid "Cancel"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js:144
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorSelector.js:144
 msgid "OK"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js:236
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorSelector.js:236
 msgid "Presets"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js:280
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorSelector.js:280
 msgid "Details"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js:325
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorSelector.js:325
 msgid "Hex"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js:348
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorSelector.js:348
 msgid "RGB"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js:376
+#: ../../../frontend/framework/source/class/qx/ui/component/ColorSelector.js:376
 msgid "HSB"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/DateChooser.js:52
+#: ../../../frontend/framework/source/class/qx/ui/component/DateChooser.js:52
 msgid "Last year"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/DateChooser.js:53
+#: ../../../frontend/framework/source/class/qx/ui/component/DateChooser.js:53
 msgid "Last month"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/DateChooser.js:54
+#: ../../../frontend/framework/source/class/qx/ui/component/DateChooser.js:54
 msgid "Next month"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/DateChooser.js:55
+#: ../../../frontend/framework/source/class/qx/ui/component/DateChooser.js:55
 msgid "Next year"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/component/DateChooserButton.js:91
+#: ../../../frontend/framework/source/class/qx/ui/component/DateChooserButton.js:91
 msgid "Choose a date"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:67
+#: ../../../frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:67
 msgid "Description"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:67
+#: ../../../frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:67
 msgid "ID"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:620
+#: ../../../frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:620
 msgid "Case sensitive"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:657
+#: ../../../frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:657
 msgid "Search next occurrence"
 msgstr ""
 
-#: ../qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:694
+#: ../../../frontend/framework/source/class/qx/ui/form/ComboBoxEx.js:694
 msgid "Search items in list"
 msgstr ""