summaryrefslogtreecommitdiff
path: root/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/table/DefaultResizeBehavior.js
diff options
context:
space:
mode:
Diffstat (limited to 'webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/table/DefaultResizeBehavior.js')
-rw-r--r--webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/table/DefaultResizeBehavior.js621
1 files changed, 621 insertions, 0 deletions
diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/table/DefaultResizeBehavior.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/table/DefaultResizeBehavior.js
new file mode 100644
index 0000000000..39ab740f82
--- /dev/null
+++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/ui/table/DefaultResizeBehavior.js
@@ -0,0 +1,621 @@
+/* ************************************************************************
+
+ 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(table)
+
+************************************************************************ */
+
+/**
+ * The default resize behavior. Until a resize model is loaded, the default
+ * behavior is to:
+ * <ol>
+ * <li>
+ * Upon the table initially appearing, and upon any window resize, divide
+ * the table space equally between the visible columns.
+ * </li>
+ * <li>
+ * When a column is increased in width, all columns to its right are
+ * pushed to the right with no change to their widths. This may push some
+ * columns off the right edge of the table, causing a horizontal scroll
+ * bar to appear.
+ * </li>
+ * <li>
+ * When a column is decreased in width, if the total width of all columns
+ * is <i>greater than</i> the table width, no additional column wiidth
+ * changes are made.
+ * </li>
+ * <li>
+ * When a column is decreased in width, if the total width of all columns
+ * is <i>less than</i> the width of the table, the visible column
+ * immediately to the right of the column which decreased in width has its
+ * width increased to fill the remaining space.
+ * </li>
+ * </ol>
+ *
+ * A resize model may be loaded to provide more guidance on how to adjust
+ * column width upon each of the events: initial appear, window resize, and
+ * column resize. *** TO BE FILLED IN ***
+ */
+qx.OO.defineClass("qx.ui.table.DefaultResizeBehavior",
+ qx.ui.table.AbstractResizeBehavior,
+function()
+{
+ qx.ui.table.AbstractResizeBehavior.call(this);
+});
+
+
+/*
+ * A function to instantiate a resize behavior column data object.
+ */
+qx.OO.addProperty(
+ {
+ name :
+ "newResizeBehaviorColumnData",
+ type :
+ "function",
+ setOnlyOnce :
+ true,
+ defaultValue:
+ function(obj)
+ {
+ return new qx.ui.table.ResizeBehaviorColumnData();
+ }
+ });
+
+
+/**
+ * Set the width of a column.
+ *
+ * @param col {Integer}
+ * The column whose width is to be set
+ *
+ * @param width {Integer, String}
+ * The width of the specified column. The width may be specified as integer
+ * number of pixels (e.g. 100), a string representing percentage of the
+ * inner width of the Table (e.g. "25%"), or a string representing a flex
+ * width (e.g. "1*").
+ */
+qx.Proto.setWidth = function(col, width)
+{
+ // Ensure the column is within range
+ if (col >= this._resizeColumnData.length)
+ {
+ throw new Error("Column number out of range");
+ }
+
+ // Set the new width
+ this._resizeColumnData[col].setWidth(width);
+};
+
+
+/**
+ * Set the minimum width of a column.
+ *
+ * @param col {Integer}
+ * The column whose minimum width is to be set
+ *
+ * @param width {Integer}
+ * The minimum width of the specified column.
+ */
+qx.Proto.setMinWidth = function(col, width)
+{
+ // Ensure the column is within range
+ if (col >= this._resizeColumnData.length)
+ {
+ throw new Error("Column number out of range");
+ }
+
+ // Set the new width
+ this._resizeColumnData[col].setMinWidth(width);
+};
+
+
+/**
+ * Set the maximum width of a column.
+ *
+ * @param col {Integer}
+ * The column whose maximum width is to be set
+ *
+ * @param width {Integer}
+ * The maximum width of the specified column.
+ */
+qx.Proto.setMaxWidth = function(col, width)
+{
+ // Ensure the column is within range
+ if (col >= this._resizeColumnData.length)
+ {
+ throw new Error("Column number out of range");
+ }
+
+ // Set the new width
+ this._resizeColumnData[col].setMaxWidth(width);
+};
+
+
+/**
+ * Set any or all of the width, minimum width, and maximum width of a column
+ * in a single call.
+ *
+ * @param map {Map}
+ * A map containing any or all of the property names "width", "minWidth",
+ * and "maxWidth". The property values are as described for
+ * {@link #setWidth}, {@link #setMinWidth} and {@link #setMaxWidth}
+ * respectively.
+ */
+qx.Proto.set = function(col, map)
+{
+ for (var prop in map)
+ {
+ switch(prop)
+ {
+ case "width":
+ this.setWidth(col, map[prop]);
+ break;
+
+ case "minWidth":
+ this.setMinWidth(col, map[prop]);
+ break;
+
+ case "maxWidth":
+ this.setMaxWidth(col, map[prop]);
+ break;
+
+ default:
+ throw new Error("Unknown property: " + prop);
+ }
+ }
+};
+
+
+// overloaded
+qx.Proto.onAppear = function(tableColumnModel, event)
+{
+ // Get the initial available width so we know whether a resize caused an
+ // increase or decrease in the available space.
+ this._width = this._getAvailableWidth(tableColumnModel);
+
+ // Calculate column widths
+ this._computeColumnsFlexWidth(tableColumnModel, event);
+};
+
+
+// overloaded
+qx.Proto.onWindowResize = function(tableColumnModel, event)
+{
+ // Calculate column widths
+ this._computeColumnsFlexWidth(tableColumnModel, event);
+};
+
+
+// overloaded
+qx.Proto.onColumnWidthChanged = function(tableColumnModel, event)
+{
+ // Extend the next column to fill blank space
+ this._extendNextColumn(tableColumnModel, event);
+};
+
+
+// overloaded
+qx.Proto.onVisibilityChanged = function(tableColumnModel, event)
+{
+ // Extend the last column to fill blank space
+ this._extendLastColumn(tableColumnModel, event);
+};
+
+
+// overloaded
+qx.Proto._setNumColumns = function(numColumns)
+{
+ // Are there now fewer (or the same number of) columns than there were
+ // previously?
+ if (numColumns <= this._resizeColumnData.length)
+ {
+ // Yup. Delete the extras.
+ this._resizeColumnData.splice(numColumns);
+ return;
+ }
+
+ // There are more columns than there were previously. Allocate more.
+ for (var i = this._resizeColumnData.length; i < numColumns; i++)
+ {
+ this._resizeColumnData[i] = this.getNewResizeBehaviorColumnData()();
+ this._resizeColumnData[i]._columnNumber = i;
+ }
+};
+
+
+/**
+ * Computes the width of all flexible children (based loosely on the method of
+ * the same name in HorizontalBoxLayoutImpl).
+ *
+ * @param tableColumnModel {qx.ui.table.ResizeTableColumnModel}
+ * The table column model in use.
+ *
+ * @param event
+ * The event object.
+ */
+qx.Proto._computeColumnsFlexWidth = function(tableColumnModel, event)
+{
+ // Semi-permanent configuration settings
+ var debug = true;
+
+ if (debug)
+ {
+ this.debug("computeColumnsFlexWidth");
+ }
+
+ var visibleColumns = tableColumnModel._visibleColumnArr;
+ var visibleColumnsLength = visibleColumns.length;
+ var columnData;
+ var flexibleColumns = [ ];
+ var widthUsed = 0;
+ var i;
+
+ // Determine the available width
+ var width = this._getAvailableWidth(tableColumnModel);
+
+
+ // *************************************************************
+ // 1. Compute the sum of all static sized columns and find
+ // all flexible columns.
+ // *************************************************************
+ for (i = 0; i < visibleColumnsLength; i++)
+ {
+ // Get the current column's column data
+ columnData = this._resizeColumnData[visibleColumns[i]];
+
+ // Is this column width type "auto"?
+ if (columnData._computedWidthTypeAuto)
+ {
+ // Yup. Convert it to a Flex "1*"
+ columnData._computedWidthTypeAuto = false;
+ columnData._computedWidthTypeFlex = true;
+ columnData._computedWidthParsed = 1;
+ }
+
+ // Is this column a flex width?
+ if (columnData._computedWidthTypeFlex)
+ {
+ // Yup. Save it for future processing.
+ flexibleColumns.push(columnData);
+ }
+ else if (columnData._computedWidthTypePercent)
+ {
+ // We can calculate the width of a Percent type right now. Convert it
+ // to a Flex type that's already calculated (no further calculation
+ // required).
+ columnData._computedWidthPercentValue =
+ Math.round(width * (columnData._computedWidthParsed / 100));
+ widthUsed += columnData._computedWidthPercentValue;
+ }
+ else
+ {
+ // We have a fixed width. Track width already allocated.
+ widthUsed += columnData.getWidth();
+ }
+ }
+
+ if (debug)
+ {
+ this.debug("Width: " + widthUsed + "/" + width);
+ this.debug("Flexible Count: " + flexibleColumns.length);
+ }
+
+
+ // *************************************************************
+ // 2. Compute the sum of all flexible column widths
+ // *************************************************************
+ var widthRemaining = width - widthUsed;
+ var flexibleColumnsLength = flexibleColumns.length;
+ var prioritySum = 0;
+
+ for (i = 0; i < flexibleColumnsLength; i++)
+ {
+ prioritySum += flexibleColumns[i]._computedWidthParsed;
+ }
+
+
+ // *************************************************************
+ // 3. Calculating the size of each 'part'.
+ // *************************************************************
+ var partWidth = widthRemaining / prioritySum;
+
+ // *************************************************************
+ // 4. Adjust flexible columns, taking min/max values into account
+ // *************************************************************
+
+ bSomethingChanged = true;
+ for (flexibleColumnsLength = flexibleColumns.length;
+ bSomethingChanged && flexibleColumnsLength > 0;
+ flexibleColumnsLength = flexibleColumns.length)
+ {
+ // Assume nothing will change
+ bSomethingChanged = false;
+
+ for (i = flexibleColumnsLength - 1; i >= 0; i--)
+ {
+ columnData = flexibleColumns[i];
+
+ computedFlexibleWidth =
+ columnData._computedWidthFlexValue =
+ columnData._computedWidthParsed * partWidth;
+
+ // If the part is not within its specified min/max range, adjust it.
+ var min = columnData.getMinWidthValue();
+ var max = columnData.getMaxWidthValue();
+ if (min && computedFlexibleWidth < min)
+ {
+ columnData._computedWidthFlexValue = Math.round(min);
+ widthUsed += columnData._computedWidthFlexValue;
+ qx.lang.Array.removeAt(flexibleColumns, i);
+ bSomethingChanged = true;
+
+ // Don't round fixed-width columns (in step 5)
+ columnData = null;
+ }
+ else if (max && computedFlexibleWidth > max)
+ {
+ columnData._computedWidthFlexValue = Math.round(max);
+ widthUsed += columnData._computedWidthFlexValue;
+ qx.lang.Array.removeAt(flexibleColumns, i);
+ bSomethingChanged = true;
+
+ // Don't round fixed-width columns (in step 5)
+ columnData = null;
+ }
+ }
+ }
+
+ // If any flexible columns remain, then allocate the remaining space to them
+ if (flexibleColumns.length > 0)
+ {
+ // Recalculate the priority sum of the remaining flexible columns
+ prioritySum = 0;
+ for (i = 0; i < flexibleColumnsLength; i++)
+ {
+ prioritySum += flexibleColumns[i]._computedWidthParsed;
+ }
+
+ // Recalculate the width remaining and part width
+ widthRemaining = width - widthUsed;
+ partWidth = widthRemaining / prioritySum;
+
+ // If there's no width remaining...
+ if (widthRemaining <= 0)
+ {
+ // ... then use minimum width * priority for all remaining columns
+ for (i = 0; i < flexibleColumnsLength; i++)
+ {
+ columnData = flexibleColumns[i];
+
+ computedFlexibleWidth =
+ columnData._computedWidthFlexValue =
+ (qx.ui.table.DefaultResizeBehavior.MIN_WIDTH *
+ flexibleColumns[i]._computedWidthParsed);
+ columnData._computedWidthFlexValue = Math.round(computedFlexibleWidth);
+ widthUsed += columnData._computedWidthFlexValue;
+ }
+ }
+ else
+ {
+ // Assign widths of remaining flexible columns
+ for (i = 0; i < flexibleColumnsLength; i++)
+ {
+ columnData = flexibleColumns[i];
+
+ computedFlexibleWidth =
+ columnData._computedWidthFlexValue =
+ columnData._computedWidthParsed * partWidth;
+
+ // If the computed width is less than our hard-coded minimum...
+ if (computedFlexibleWidth <
+ qx.ui.table.DefaultResizeBehavior.MIN_WIDTH)
+ {
+ // ... then use the hard-coded minimum
+ computedFlexibleWidth = qx.ui.table.DefaultResizeBehavior.MIN_WIDTH;
+ }
+
+ columnData._computedWidthFlexValue = Math.round(computedFlexibleWidth);
+ widthUsed += columnData._computedWidthFlexValue;
+ }
+ }
+ }
+
+ // *************************************************************
+ // 5. Fix rounding errors
+ // *************************************************************
+ if (columnData != null && widthRemaining > 0)
+ {
+ columnData._computedWidthFlexValue += width - widthUsed;
+ }
+
+ // *************************************************************
+ // 6. Set the column widths to what we have calculated
+ // *************************************************************
+ for (i = 0; i < visibleColumnsLength; i++)
+ {
+ var colWidth;
+
+ // Get the current column's column data
+ columnData = this._resizeColumnData[visibleColumns[i]];
+
+ // Is this column a flex width?
+ if (columnData._computedWidthTypeFlex)
+ {
+ // Yup. Set the width to the calculated width value based on flex
+ colWidth = columnData._computedWidthFlexValue;
+ }
+ else if (columnData._computedWidthTypePercent)
+ {
+ // Set the width to the calculated width value based on percent
+ colWidth = columnData._computedWidthPercentValue;
+ }
+ else
+ {
+ colWidth = columnData.getWidth();
+ }
+
+ // Now that we've calculated the width, set it.
+ tableColumnModel.setColumnWidth(visibleColumns[i], colWidth);
+
+ if (debug)
+ {
+ this.debug("col " + columnData._columnNumber + ": width=" + colWidth);
+ }
+ }
+};
+
+
+/**
+ * Extend the visible column to right of the column which just changed width,
+ * to fill any available space within the inner width of the table. This
+ * means that if the sum of the widths of all columns exceeds the inner width
+ * of the table, no change is made. If, on the other hand, the sum of the
+ * widths of all columns is less than the inner width of the table, the
+ * visible column to the right of the column which just changed width is
+ * extended to take up the width available within the inner width of the
+ * table.
+ *
+ * @param tableColumnModel {qx.ui.table.ResizeTableColumnModel}
+ * The table column model in use.
+ *
+ * @param event
+ * The event object.
+ */
+qx.Proto._extendNextColumn = function(tableColumnModel, event)
+{
+ // Event data properties: col, oldWidth, newWidth
+ var data = event.getData();
+
+ var visibleColumns = tableColumnModel._visibleColumnArr;
+
+ // Determine the available width
+ var width = this._getAvailableWidth(tableColumnModel);
+
+ // Determine the number of visible columns
+ var numColumns = visibleColumns.length;
+
+ // Did this column become longer than it was?
+ if (data.newWidth > data.oldWidth)
+ {
+ // Yup. Don't resize anything else. The other columns will just get
+ // pushed off and require scrollbars be added (if not already there).
+ return;
+ }
+
+ // This column became shorter. See if we no longer take up the full space
+ // that's available to us.
+ var i;
+ var nextCol;
+ var widthUsed = 0;
+ for (i = 0; i < numColumns; i++)
+ {
+ widthUsed +=
+ tableColumnModel.getColumnWidth(visibleColumns[i]);
+ }
+
+ // If the used width is less than the available width...
+ if (widthUsed < width)
+ {
+ // ... then determine the next visible column
+ for (i = 0; i < visibleColumns.length; i++)
+ {
+ if (visibleColumns[i] == data.col)
+ {
+ nextCol = visibleColumns[i + 1];
+ break;
+ }
+ }
+
+ if (nextCol)
+ {
+ // Make the next column take up the available space.
+ var oldWidth = tableColumnModel.getColumnWidth(nextCol);
+ var newWidth = (width - (widthUsed -
+ tableColumnModel.getColumnWidth(nextCol)));
+ tableColumnModel.setColumnWidth(nextCol, newWidth);
+ }
+ }
+};
+
+
+/**
+ * If a column was just made invisible, extend the last column to fill any
+ * available space within the inner width of the table. This means that if
+ * the sum of the widths of all columns exceeds the inner width of the table,
+ * no change is made. If, on the other hand, the sum of the widths of all
+ * columns is less than the inner width of the table, the last column is
+ * extended to take up the width available within the inner width of the
+ * table.
+ *
+ * @param tableColumnModel {qx.ui.table.ResizeTableColumnModel}
+ * The table column model in use.
+ *
+ * @param event
+ * The event object.
+ */
+qx.Proto._extendLastColumn = function(tableColumnModel, event)
+{
+ // Event data properties: col, visible
+ var data = event.getData();
+
+ // If the column just became visible, don't make any width changes
+ if (data.visible)
+ {
+ return;
+ }
+
+ // Get the array of visible columns
+ var visibleColumns = tableColumnModel._visibleColumnArr;
+
+ // Determine the available width
+ var width = this._getAvailableWidth(tableColumnModel);
+
+ // Determine the number of visible columns
+ var numColumns = visibleColumns.length;
+
+ // See if we no longer take up the full space that's available to us.
+ var i;
+ var lastCol;
+ var widthUsed = 0;
+ for (i = 0; i < numColumns; i++)
+ {
+ widthUsed +=
+ tableColumnModel.getColumnWidth(visibleColumns[i]);
+ }
+
+ // If the used width is less than the available width...
+ if (widthUsed < width)
+ {
+ // ... then get the last visible column
+ lastCol = visibleColumns[visibleColumns.length - 1];
+
+ // Make the last column take up the available space.
+ var oldWidth = tableColumnModel.getColumnWidth(lastCol);
+ var newWidth = (width - (widthUsed -
+ tableColumnModel.getColumnWidth(lastCol)));
+ tableColumnModel.setColumnWidth(lastCol, newWidth);
+ }
+};
+
+
+
+qx.Class.MIN_WIDTH = 10;