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/TreeVirtual.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/TreeVirtual.js')
-rw-r--r-- | webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/TreeVirtual.js | 430 |
1 files changed, 311 insertions, 119 deletions
diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/TreeVirtual.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/TreeVirtual.js index 0acf87f56f..2ffae79436 100644 --- a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/TreeVirtual.js +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/treevirtual/TreeVirtual.js @@ -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(); }; @@ -420,6 +438,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. * * We handle the Enter key to toggle opened/closed tree state. All @@ -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} * |