summaryrefslogtreecommitdiff
path: root/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js
diff options
context:
space:
mode:
Diffstat (limited to 'webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js')
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js1062
1 files changed, 1062 insertions, 0 deletions
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js
new file mode 100644
index 0000000000..360662e718
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js
@@ -0,0 +1,1062 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+#require(qx.ui.table.DefaultDataRowRenderer)
+
+************************************************************************ */
+
+/**
+ * A table.
+ *
+ * @param tableModel {qx.ui.table.TableModel} The table
+ * model to read the data from.
+ */
+qx.OO.defineClass("qx.ui.table.Table", qx.ui.layout.VerticalBoxLayout,
+function(tableModel) {
+ qx.ui.layout.VerticalBoxLayout.call(this);
+
+ // Create the child widgets
+ this._scrollerParent = new qx.ui.layout.HorizontalBoxLayout;
+ this._scrollerParent.setDimension("100%", "1*");
+ this._scrollerParent.setSpacing(1);
+
+ this._statusBar = new qx.ui.basic.Label;
+ this._statusBar.setAppearance("table-focus-statusbar");
+ this._statusBar.setDimension("100%", "auto");
+
+ this.add(this._scrollerParent, this._statusBar);
+
+ this._columnVisibilityBt = new qx.ui.toolbar.Button(null, "widget/table/selectColumnOrder.png");
+ this._columnVisibilityBt.addEventListener("execute", this._onColumnVisibilityBtExecuted, this);
+
+ // Create the models
+ this._selectionManager = new qx.ui.table.SelectionManager;
+
+ this.setSelectionModel(new qx.ui.table.SelectionModel);
+ this.setTableColumnModel(new qx.ui.table.TableColumnModel);
+ this.setTableModel(tableModel);
+
+ // Update the status bar
+ this._updateStatusBar();
+
+ // create the main meta column
+ this.setMetaColumnCounts([ -1 ]);
+
+ // Make focusable
+ this.setTabIndex(1);
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+ this.addEventListener("changeFocused", this._onFocusChanged);
+
+ this._focusedCol = 0;
+ this._focusedRow = 0;
+});
+
+
+/** The default row renderer to use when {@link #dataRowRenderer} is null. */
+qx.Class.DEFAULT_DATA_ROW_RENDERER = new qx.ui.table.DefaultDataRowRenderer();
+
+
+/** The selection model. */
+qx.OO.addProperty({ name:"selectionModel", type:"object", instance : "qx.ui.table.SelectionModel" });
+
+/** The table model. */
+qx.OO.addProperty({ name:"tableModel", type:"object", instance : "qx.ui.table.TableModel" });
+
+/** The table column model. */
+qx.OO.addProperty({ name:"tableColumnModel", type:"object", instance : "qx.ui.table.TableColumnModel" });
+
+/** The height of the table rows. */
+qx.OO.addProperty({ name:"rowHeight", type:"number", defaultValue:15 });
+
+/** Whether to show the status bar */
+qx.OO.addProperty({ name:"statusBarVisible", type:"boolean", defaultValue:true });
+
+/** Whether to show the column visibility button */
+qx.OO.addProperty({ name:"columnVisibilityButtonVisible", type:"boolean", defaultValue:true });
+
+/**
+ * {int[]} The number of columns per meta column. If the last array entry is -1,
+ * this meta column will get the remaining columns.
+ */
+qx.OO.addProperty({ name:"metaColumnCounts", type:"object" });
+
+/**
+ * Whether the focus should moved when the mouse is moved over a cell. If false
+ * the focus is only moved on mouse clicks.
+ */
+qx.OO.addProperty({ name:"focusCellOnMouseMove", type:"boolean", defaultValue:false });
+
+/**
+ * Whether the table should keep the first visible row complete. If set to false,
+ * the first row may be rendered partial, depending on the vertical scroll value.
+ */
+qx.OO.addProperty({ name:"keepFirstVisibleRowComplete", type:"boolean", defaultValue:true });
+
+/**
+ * Whether the table cells should be updated when only the selection or the
+ * focus changed. This slows down the table update but allows to react on a
+ * changed selection or a changed focus in a cell renderer.
+ */
+qx.OO.addProperty({ name:"alwaysUpdateCells", type:"boolean", defaultValue:false });
+
+/** The height of the header cells. */
+qx.OO.addProperty({ name:"headerCellHeight", type:"number", defaultValue:16, allowNull:false });
+
+/** 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 });
+
+
+// property modifier
+qx.Proto._modifySelectionModel = function(propValue, propOldValue, propData) {
+ this._selectionManager.setSelectionModel(propValue);
+
+ if (propOldValue != null) {
+ propOldValue.removeEventListener("changeSelection", this._onSelectionChanged, this);
+ }
+ propValue.addEventListener("changeSelection", this._onSelectionChanged, this);
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyTableModel = function(propValue, propOldValue, propData) {
+ this.getTableColumnModel().init(propValue.getColumnCount());
+
+ if (propOldValue != null) {
+ propOldValue.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
+ propOldValue.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, this._onTableModelDataChanged, this);
+ }
+ propValue.addEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
+ propValue.addEventListener(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, this._onTableModelDataChanged, this);
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyTableColumnModel = function(propValue, propOldValue, propData) {
+ if (propOldValue != null) {
+ propOldValue.removeEventListener("visibilityChanged", this._onColVisibilityChanged, this);
+ propOldValue.removeEventListener("widthChanged", this._onColWidthChanged, this);
+ propOldValue.removeEventListener("orderChanged", this._onColOrderChanged, this);
+ }
+ propValue.addEventListener("visibilityChanged", this._onColVisibilityChanged, this);
+ propValue.addEventListener("widthChanged", this._onColWidthChanged, this);
+ propValue.addEventListener("orderChanged", this._onColOrderChanged, this);
+
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyStatusBarVisible = function(propValue, propOldValue, propData) {
+ this._statusBar.setDisplay(propValue);
+
+ if (propValue) {
+ this._updateStatusBar();
+ }
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyColumnVisibilityButtonVisible = function(propValue, propOldValue, propData) {
+ this._columnVisibilityBt.setDisplay(propValue);
+
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyMetaColumnCounts = function(propValue, propOldValue, propData) {
+ var metaColumnCounts = propValue;
+ var scrollerArr = this._getPaneScrollerArr();
+
+ // Remove the panes not needed any more
+ this._cleanUpMetaColumns(metaColumnCounts.length);
+
+ // Update the old panes
+ var leftX = 0;
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var paneScroller = scrollerArr[i];
+ var paneModel = paneScroller.getTablePaneModel();
+ paneModel.setFirstColumnX(leftX);
+ paneModel.setMaxColumnCount(metaColumnCounts[i]);
+ leftX += metaColumnCounts[i];
+ }
+
+ // Add the new panes
+ if (metaColumnCounts.length > scrollerArr.length) {
+ var selectionModel = this.getSelectionModel();
+ var tableModel = this.getTableModel();
+ var columnModel = this.getTableColumnModel();
+
+ for (var i = scrollerArr.length; i < metaColumnCounts.length; i++) {
+ var paneModel = new qx.ui.table.TablePaneModel(columnModel);
+ paneModel.setFirstColumnX(leftX);
+ paneModel.setMaxColumnCount(metaColumnCounts[i]);
+ leftX += metaColumnCounts[i];
+
+ var paneScroller = new qx.ui.table.TablePaneScroller(this);
+ paneScroller.setTablePaneModel(paneModel);
+
+ // Register event listener for vertical scrolling
+ paneScroller.addEventListener("changeScrollY", this._onScrollY, this);
+
+ this._scrollerParent.add(paneScroller);
+ }
+ }
+
+ // Update all meta columns
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var paneScroller = scrollerArr[i];
+ var isLast = (i == (scrollerArr.length - 1));
+
+ // Set the right header height
+ paneScroller.getHeader().setHeight(this.getHeaderCellHeight());
+
+ // Put the _columnVisibilityBt in the top right corner of the last meta column
+ paneScroller.setTopRightWidget(isLast ? this._columnVisibilityBt : null);
+ }
+
+ this._updateScrollerWidths();
+ this._updateScrollBarVisibility();
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyFocusCellOnMouseMove = function(propValue, propOldValue, propData) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i].setFocusCellOnMouseMove(propValue);
+ }
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyKeepFirstVisibleRowComplete = function(propValue, propOldValue, propData) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onKeepFirstVisibleRowCompleteChanged();
+ }
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyHeaderCellHeight = function(propValue, propOldValue, propData) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i].getHeader().setHeight(propValue);
+ }
+ return true;
+};
+
+
+/**
+ * Returns the selection manager.
+ *
+ * @return {SelectionManager} the selection manager.
+ */
+qx.Proto._getSelectionManager = function() {
+ return this._selectionManager;
+};
+
+
+/**
+ * Returns an array containing all TablePaneScrollers in this table.
+ *
+ * @return {TablePaneScroller[]} all TablePaneScrollers in this table.
+ */
+qx.Proto._getPaneScrollerArr = function() {
+ return this._scrollerParent.getChildren();
+}
+
+
+/**
+ * Returns a TablePaneScroller of this table.
+ *
+ * @param metaColumn {int} the meta column to get the TablePaneScroller for.
+ * @return {TablePaneScroller} the TablePaneScroller.
+ */
+qx.Proto.getPaneScroller = function(metaColumn) {
+ return this._getPaneScrollerArr()[metaColumn];
+}
+
+
+/**
+ * Cleans up the meta columns.
+ *
+ * @param fromMetaColumn {int} the first meta column to clean up. All following
+ * meta columns will be cleaned up, too. All previous meta columns will
+ * stay unchanged. If 0 all meta columns will be cleaned up.
+ */
+qx.Proto._cleanUpMetaColumns = function(fromMetaColumn) {
+ var scrollerArr = this._getPaneScrollerArr();
+ if (scrollerArr != null) {
+ for (var i = scrollerArr.length - 1; i >= fromMetaColumn; i--) {
+ var paneScroller = scrollerArr[i];
+ paneScroller.removeEventListener("changeScrollY", this._onScrollY, this);
+ this._scrollerParent.remove(paneScroller);
+ paneScroller.dispose();
+ }
+ }
+}
+
+
+/**
+ * Event handler. Called when the selection has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onSelectionChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onSelectionChanged(evt);
+ }
+
+ this._updateStatusBar();
+}
+
+
+/**
+ * Event handler. Called when the table model meta data has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelMetaDataChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onTableModelMetaDataChanged(evt);
+ }
+
+ this._updateStatusBar();
+}
+
+
+/**
+ * Event handler. Called when the table model data has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelDataChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onTableModelDataChanged(evt);
+ }
+
+ var rowCount = this.getTableModel().getRowCount();
+ if (rowCount != this._lastRowCount) {
+ this._lastRowCount = rowCount;
+
+ this._updateScrollBarVisibility();
+ this._updateStatusBar();
+ }
+};
+
+
+/**
+ * Event handler. Called when a TablePaneScroller has been scrolled vertically.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onScrollY = function(evt) {
+ if (! this._internalChange) {
+ this._internalChange = true;
+
+ // Set the same scroll position to all meta columns
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i].setScrollY(evt.getData());
+ }
+
+ this._internalChange = false;
+ }
+}
+
+
+/**
+ * Event handler. Called when a key was pressed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onkeydown = function(evt) {
+ var identifier = evt.getKeyIdentifier();
+
+ var consumed = false;
+ var oldFocusedRow = this._focusedRow;
+ if (this.isEditing()) {
+ // Editing mode
+ if (evt.getModifiers() == 0) {
+ consumed = true;
+ switch (identifier) {
+ case "Enter":
+ this.stopEditing();
+ var oldFocusedRow = this._focusedRow;
+ this.moveFocusedCell(0, 1);
+ if (this._focusedRow != oldFocusedRow) {
+ this.startEditing();
+ }
+ break;
+ case "Escape":
+ this.cancelEditing();
+ this.focus();
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+ }
+ } else {
+ // No editing mode
+
+ // Handle keys that are independant from the modifiers
+ consumed = true;
+ switch (identifier) {
+ case "Home":
+ this.setFocusedCell(this._focusedCol, 0, true);
+ break;
+ case "End":
+ var rowCount = this.getTableModel().getRowCount();
+ this.setFocusedCell(this._focusedCol, rowCount - 1, true);
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+
+ // Handle keys that depend on modifiers
+ if (evt.getModifiers() == 0) {
+ consumed = true;
+ switch (identifier) {
+ case "F2":
+ case "Enter":
+ this.startEditing();
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+ } else if (evt.getCtrlKey()) {
+ consumed = true;
+ switch (identifier) {
+ case "A": // Ctrl + A
+ var rowCount = this.getTableModel().getRowCount();
+ if (rowCount > 0) {
+ this.getSelectionModel().setSelectionInterval(0, rowCount - 1);
+ }
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+ }
+ }
+
+ if (oldFocusedRow != this._focusedRow) {
+ // The focus moved -> Let the selection manager handle this event
+ this._selectionManager.handleMoveKeyDown(this._focusedRow, evt);
+ }
+
+ if (consumed) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+};
+
+
+qx.Proto._onkeypress = function(evt)
+{
+ if (this.isEditing()) { return }
+ // No editing mode
+ var oldFocusedRow = this._focusedRow;
+ var consumed = true;
+
+ // Handle keys that are independant from the modifiers
+ var identifier = evt.getKeyIdentifier();
+ switch (identifier) {
+ case "Space":
+ this._selectionManager.handleSelectKeyDown(this._focusedRow, evt);
+ break;
+
+ case "Left":
+ this.moveFocusedCell(-1, 0);
+ break;
+
+ case "Right":
+ this.moveFocusedCell(1, 0);
+ break;
+
+ case "Up":
+ this.moveFocusedCell(0, -1);
+ break;
+
+ case "Down":
+ this.moveFocusedCell(0, 1);
+ break;
+
+ case "PageUp":
+ case "PageDown":
+ var scroller = this.getPaneScroller(0);
+ var pane = scroller.getTablePane();
+ var rowCount = pane.getVisibleRowCount() - 1;
+ var rowHeight = this.getRowHeight();
+ var direction = (identifier == "PageUp") ? -1 : 1;
+ scroller.setScrollY(scroller.getScrollY() + direction * rowCount * rowHeight);
+ this.moveFocusedCell(0, direction * rowCount);
+ break;
+
+ default:
+ consumed = false;
+ }
+ if (oldFocusedRow != this._focusedRow) {
+ // The focus moved -> Let the selection manager handle this event
+ this._selectionManager.handleMoveKeyDown(this._focusedRow, evt);
+ }
+
+ if (consumed) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+};
+
+
+/**
+ * Event handler. Called when the table gets the focus.
+ */
+qx.Proto._onFocusChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onFocusChanged(evt);
+ }
+};
+
+
+/**
+ * Event handler. Called when the visibility of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColVisibilityChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onColVisibilityChanged(evt);
+ }
+
+ this._updateScrollerWidths();
+ this._updateScrollBarVisibility();
+}
+
+
+/**
+ * Event handler. Called when the width of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColWidthChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onColWidthChanged(evt);
+ }
+
+ this._updateScrollerWidths();
+ this._updateScrollBarVisibility();
+}
+
+
+/**
+ * Event handler. Called when the column order has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColOrderChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onColOrderChanged(evt);
+ }
+
+ // A column may have been moved between meta columns
+ this._updateScrollerWidths();
+ this._updateScrollBarVisibility();
+}
+
+
+/**
+ * Gets the TablePaneScroller at a certain x position in the page. If there is
+ * no TablePaneScroller at this postion, null is returned.
+ *
+ * @param pageX {int} the position in the page to check (in pixels).
+ * @return {TablePaneScroller} the TablePaneScroller or null.
+ *
+ * @see TablePaneScrollerPool
+ */
+qx.Proto.getTablePaneScrollerAtPageX = function(pageX) {
+ var metaCol = this._getMetaColumnAtPageX(pageX);
+ return (metaCol != -1) ? this.getPaneScroller(metaCol) : null;
+}
+
+
+/**
+ * Sets the currently focused cell.
+ *
+ * @param col {int} the model index of the focused cell's column.
+ * @param row {int} the model index of the focused cell's row.
+ * @param scrollVisible {boolean ? false} whether to scroll the new focused cell
+ * visible.
+ *
+ * @see TablePaneScrollerPool
+ */
+qx.Proto.setFocusedCell = function(col, row, scrollVisible) {
+ if (!this.isEditing() && (col != this._focusedCol || row != this._focusedRow)) {
+ this._focusedCol = col;
+ this._focusedRow = row;
+
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i].setFocusedCell(col, row);
+ }
+
+ if (scrollVisible) {
+ this.scrollCellVisible(col, row);
+ }
+ }
+}
+
+
+/**
+ * Returns the column of the currently focused cell.
+ *
+ * @return {int} the model index of the focused cell's column.
+ */
+qx.Proto.getFocusedColumn = function() {
+ return this._focusedCol;
+};
+
+
+/**
+ * Returns the row of the currently focused cell.
+ *
+ * @return {int} the model index of the focused cell's column.
+ */
+qx.Proto.getFocusedRow = function() {
+ return this._focusedRow;
+};
+
+
+/**
+ * Moves the focus.
+ *
+ * @param deltaX {int} The delta by which the focus should be moved on the x axis.
+ * @param deltaY {int} The delta by which the focus should be moved on the y axis.
+ */
+qx.Proto.moveFocusedCell = function(deltaX, deltaY) {
+ var col = this._focusedCol;
+ var row = this._focusedRow;
+
+ if (deltaX != 0) {
+ var columnModel = this.getTableColumnModel();
+ var x = columnModel.getVisibleX(col);
+ var colCount = columnModel.getVisibleColumnCount();
+ x = qx.lang.Number.limit(x + deltaX, 0, colCount - 1);
+ col = columnModel.getVisibleColumnAtX(x);
+ }
+
+ if (deltaY != 0) {
+ var tableModel = this.getTableModel();
+ row = qx.lang.Number.limit(row + deltaY, 0, tableModel.getRowCount() - 1);
+ }
+
+ this.setFocusedCell(col, row, true);
+}
+
+
+/**
+ * Scrolls a cell visible.
+ *
+ * @param col {int} the model index of the column the cell belongs to.
+ * @param row {int} the model index of the row the cell belongs to.
+ */
+qx.Proto.scrollCellVisible = function(col, row) {
+ var columnModel = this.getTableColumnModel();
+ var x = columnModel.getVisibleX(col);
+
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ if (metaColumn != -1) {
+ this.getPaneScroller(metaColumn).scrollCellVisible(col, row);
+ }
+}
+
+
+/**
+ * Returns whether currently a cell is editing.
+ *
+ * @return whether currently a cell is editing.
+ */
+qx.Proto.isEditing = function() {
+ if (this._focusedCol != null) {
+ var x = this.getTableColumnModel().getVisibleX(this._focusedCol);
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ return this.getPaneScroller(metaColumn).isEditing();
+ }
+}
+
+
+/**
+ * Starts editing the currently focused cell. Does nothing if already editing
+ * or if the column is not editable.
+ *
+ * @return {boolean} whether editing was started
+ */
+qx.Proto.startEditing = function() {
+ if (this._focusedCol != null) {
+ var x = this.getTableColumnModel().getVisibleX(this._focusedCol);
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ return this.getPaneScroller(metaColumn).startEditing();
+ }
+ return false;
+}
+
+
+/**
+ * Stops editing and writes the editor's value to the model.
+ */
+qx.Proto.stopEditing = function() {
+ if (this._focusedCol != null) {
+ var x = this.getTableColumnModel().getVisibleX(this._focusedCol);
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ this.getPaneScroller(metaColumn).stopEditing();
+ }
+}
+
+
+/**
+ * Stops editing without writing the editor's value to the model.
+ */
+qx.Proto.cancelEditing = function() {
+ if (this._focusedCol != null) {
+ var x = this.getTableColumnModel().getVisibleX(this._focusedCol);
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ this.getPaneScroller(metaColumn).cancelEditing();
+ }
+}
+
+
+/**
+ * Gets the meta column at a certain x position in the page. If there is no
+ * meta column at this postion, -1 is returned.
+ *
+ * @param pageX {int} the position in the page to check (in pixels).
+ * @return {int} the index of the meta column or -1.
+ */
+qx.Proto._getMetaColumnAtPageX = function(pageX) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var elem = scrollerArr[i].getElement();
+ if (pageX >= qx.dom.Location.getPageBoxLeft(elem)
+ && pageX <= qx.dom.Location.getPageBoxRight(elem))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/**
+ * Returns the meta column a column is shown in. If the column is not shown at
+ * all, -1 is returned.
+ *
+ * @param visXPos {int} the visible x position of the column.
+ * @return {int} the meta column the column is shown in.
+ */
+qx.Proto._getMetaColumnAtColumnX = function(visXPos) {
+ var metaColumnCounts = this.getMetaColumnCounts();
+ var rightXPos = 0;
+ for (var i = 0; i < metaColumnCounts.length; i++) {
+ var counts = metaColumnCounts[i];
+ rightXPos += counts;
+
+ if (counts == -1 || visXPos < rightXPos) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/**
+ * Updates the text shown in the status bar.
+ */
+qx.Proto._updateStatusBar = function() {
+ if (this.getStatusBarVisible()) {
+ var selectedRowCount = this.getSelectionModel().getSelectedCount();
+ var rowCount = this.getTableModel().getRowCount();
+
+ var text;
+ if (selectedRowCount == 0) {
+ text = rowCount + ((rowCount == 1) ? " row" : " rows");
+ } else {
+ text = selectedRowCount + " of " + rowCount
+ + ((rowCount == 1) ? " row" : " rows") + " selected";
+ }
+ this._statusBar.setHtml(text);
+ }
+}
+
+
+/**
+ * Updates the widths of all scrollers.
+ */
+qx.Proto._updateScrollerWidths = function() {
+/* no longer needed, per Til, and removing it does not appear to add problems.
+ * qx.ui.core.Widget.flushGlobalQueues();
+ */
+
+ // Give all scrollers except for the last one the wanted width
+ // (The last one has a flex with)
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var isLast = (i == (scrollerArr.length - 1));
+ var width = isLast ? "1*" : scrollerArr[i].getTablePaneModel().getTotalWidth();
+ scrollerArr[i].setWidth(width);
+ }
+}
+
+
+/**
+ * Updates the visibility of the scrollbars in the meta columns.
+ */
+qx.Proto._updateScrollBarVisibility = function() {
+ if (this.isSeeable()) {
+ var horBar = qx.ui.table.TablePaneScroller.HORIZONTAL_SCROLLBAR;
+ var verBar = qx.ui.table.TablePaneScroller.VERTICAL_SCROLLBAR;
+ var scrollerArr = this._getPaneScrollerArr();
+
+ // Check which scroll bars are needed
+ var horNeeded = false;
+ var verNeeded = false;
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var isLast = (i == (scrollerArr.length - 1));
+
+ // Only show the last vertical scrollbar
+ var bars = scrollerArr[i].getNeededScrollBars(horNeeded, !isLast);
+
+ if (bars & horBar) {
+ horNeeded = true;
+ }
+ if (isLast && (bars & verBar)) {
+ verNeeded = true;
+ }
+ }
+
+ // Set the needed scrollbars
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var isLast = (i == (scrollerArr.length - 1));
+
+ // Only show the last vertical scrollbar
+ scrollerArr[i].setHorizontalScrollBarVisible(horNeeded);
+ scrollerArr[i].setVerticalScrollBarVisible(isLast && verNeeded);
+ }
+ }
+}
+
+
+/**
+ * Event handler. Called when the column visibiliy button was executed.
+ */
+qx.Proto._onColumnVisibilityBtExecuted = function() {
+ if ((this._columnVisibilityMenuCloseTime == null)
+ || (new Date().getTime() > this._columnVisibilityMenuCloseTime + 200))
+ {
+ this._toggleColumnVisibilityMenu();
+ }
+}
+
+
+/**
+ * Toggels the visibility of the menu used to change the visibility of columns.
+ */
+qx.Proto._toggleColumnVisibilityMenu = function() {
+ if (this._columnVisibilityMenu == null || !this._columnVisibilityMenu.isSeeable()) {
+ // Show the menu
+
+ // Create the new menu
+ var menu = new qx.ui.menu.Menu;
+
+ menu.addEventListener("disappear", function(evt) {
+ this._columnVisibilityMenuCloseTime = new Date().getTime();
+ }, this);
+
+ var tableModel = this.getTableModel();
+ var columnModel = this.getTableColumnModel();
+ for (var x = 0; x < columnModel.getOverallColumnCount(); x++) {
+ var col = columnModel.getOverallColumnAtX(x);
+ var visible = columnModel.isColumnVisible(col);
+ var cmd = { col:col }
+ var bt = new qx.ui.menu.CheckBox(tableModel.getColumnName(col), null, visible);
+
+ var handler = this._createColumnVisibilityCheckBoxHandler(col);
+ bt._handler = handler;
+ bt.addEventListener("execute", handler, this);
+
+ menu.add(bt);
+ }
+
+ menu.setParent(this.getTopLevelWidget());
+
+ this._columnVisibilityMenu = menu;
+
+ // Show the menu
+ var btElem = this._columnVisibilityBt.getElement();
+ menu.setRestrictToPageOnOpen(false);
+ menu.setTop(qx.dom.Location.getClientBoxBottom(btElem));
+ menu.setLeft(-1000);
+
+ // NOTE: We have to show the menu in a timeout, otherwise it won't be shown
+ // at all.
+ window.setTimeout(function() {
+ menu.show();
+ qx.ui.core.Widget.flushGlobalQueues();
+
+ menu.setLeft(qx.dom.Location.getClientBoxRight(btElem) - menu.getOffsetWidth());
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, 0);
+ } else {
+ // hide the menu
+ menu.hide();
+ this._cleanupColumnVisibilityMenu();
+ }
+}
+
+
+/**
+ * Cleans up the column visibility menu.
+ */
+qx.Proto._cleanupColumnVisibilityMenu = function() {
+ if (this._columnVisibilityMenu != null && ! this._columnVisibilityMenu.getDisposed()) {
+ this._columnVisibilityMenu.dispose();
+ this._columnVisibilityMenu = null;
+ }
+}
+
+
+/**
+ * Creates a handler for a check box of the column visibility menu.
+ *
+ * @param col {int} the model index of column to create the handler for.
+ */
+qx.Proto._createColumnVisibilityCheckBoxHandler = function(col) {
+ return function(evt) {
+ var columnModel = this.getTableColumnModel();
+ columnModel.setColumnVisible(col, !columnModel.isColumnVisible(col));
+ }
+}
+
+
+/**
+ * Sets the width of a column.
+ *
+ * @param col {int} the model index of column.
+ * @param width {int} the new width in pixels.
+ */
+qx.Proto.setColumnWidth = function(col, width) {
+ this.getTableColumnModel().setColumnWidth(col, width);
+}
+
+
+// overridden
+qx.Proto._changeInnerWidth = function(newValue, oldValue) {
+ var self = this;
+ window.setTimeout(function() {
+ self._updateScrollBarVisibility();
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, 0);
+
+ return qx.ui.layout.VerticalBoxLayout.prototype._changeInnerWidth.call(this, newValue, oldValue);
+}
+
+
+// overridden
+qx.Proto._changeInnerHeight = function(newValue, oldValue) {
+ var self = this;
+ window.setTimeout(function() {
+ self._updateScrollBarVisibility();
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, 0);
+
+ return qx.ui.layout.VerticalBoxLayout.prototype._changeInnerHeight.call(this, newValue, oldValue);
+}
+
+
+// overridden
+qx.Proto._afterAppear = function() {
+ qx.ui.layout.VerticalBoxLayout.prototype._afterAppear.call(this);
+
+ this._updateScrollBarVisibility();
+}
+
+
+// overridden
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._tableModel) {
+ this._tableModel.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
+ }
+
+ this._columnVisibilityBt.removeEventListener("execute", this._onColumnVisibilityBtExecuted, this);
+ this._columnVisibilityBt.dispose();
+
+ this._cleanupColumnVisibilityMenu();
+
+ this._cleanUpMetaColumns(0);
+
+ var selectionModel = this.getSelectionModel();
+ if (selectionModel != null) {
+ selectionModel.removeEventListener("changeSelection", this._onSelectionChanged, this);
+ }
+
+ var tableModel = this.getTableModel();
+ if (tableModel != null) {
+ tableModel.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
+ tableModel.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, this._onTableModelDataChanged, this);
+ }
+
+ var tableColumnModel = this.getTableColumnModel();
+ if (tableColumnModel) {
+ tableColumnModel.removeEventListener("visibilityChanged", this._onColVisibilityChanged, this);
+ tableColumnModel.removeEventListener("widthChanged", this._onColWidthChanged, this);
+ tableColumnModel.removeEventListener("orderChanged", this._onColOrderChanged, this);
+ }
+
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+
+ return qx.ui.layout.VerticalBoxLayout.prototype.dispose.call(this);
+}