diff options
author | Derrell Lipman <derrell@samba.org> | 2007-02-06 04:35:30 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:44:39 -0500 |
commit | a45ea9069c51b6f90d55a2c40346c3ee9becc263 (patch) | |
tree | 8208442a0ab9d655f9dbb6953c8db60872c7b7ad /webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js | |
parent | 0a5d888c24c925222dd94cdd80a29e09b235b795 (diff) | |
download | samba-a45ea9069c51b6f90d55a2c40346c3ee9becc263.tar.gz samba-a45ea9069c51b6f90d55a2c40346c3ee9becc263.tar.bz2 samba-a45ea9069c51b6f90d55a2c40346c3ee9becc263.zip |
r21169: - Step 3: Upgrade qooxdoo release code with latest qooxdoo svn's Table and
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)
Diffstat (limited to 'webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js')
-rw-r--r-- | webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js | 561 |
1 files changed, 365 insertions, 196 deletions
diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js index 215830c224..f9ff3a9758 100644 --- a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js @@ -30,33 +30,40 @@ * * 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; }; |