1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

r21285: - Add the new ResizeTableColumnModel and make use of it in TreeVirtual. This

allows the Ldb Browser tree to properly size itself upon initially appearing
  and upon window resizes.  There are still a few problems with it that I need
  to resolve, including an occasional set of double scrollbars, and making it
  resize the tree column when the splitter is resized.
This commit is contained in:
Derrell Lipman 2007-02-11 20:22:45 +00:00 committed by Gerald (Jerry) Carter
parent 181b3a031f
commit c3c93ad36a
7 changed files with 1131 additions and 31 deletions

View File

@ -0,0 +1,166 @@
/* ************************************************************************
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)
************************************************************************ */
/**
* An abstract resize behavior. All resize behaviors should extend this
* class.
*/
qx.OO.defineClass("qx.ui.table.AbstractResizeBehavior",
qx.core.Object,
function()
{
qx.core.Object.call(this);
this._resizeColumnData = [ ];
});
/**
* Called when the ResizeTableColumnModel is initialized, and upon loading of
* a new TableModel, to allow the Resize Behaviors to know how many columns
* are in use.
*
* @param numColumns {Integer}
* The numbrer of columns in use.
*/
qx.Proto._setNumColumns = function(numColumns)
{
throw new Error("_setNumColumns is abstract");
};
/**
* Called when the table has first been rendered.
*
* @param tableColumnModel {qx.ui.table.ResizeTableColumnModel}
* The table column model in use. Of particular interest is the property
* <i>_table</i> which is a reference to the table widget. This allows
* access to any other features of the table, for use in calculating widths
* of columns.
*
* @param event
* The <i>onappear</i> event object.
*/
qx.Proto.onAppear = function(tableColumnModel, event)
{
throw new Error("onAppear is abstract");
};
/**
* Called when the window is resized.
*
* @param tableColumnModel {qx.ui.table.ResizeTableColumnModel}
* The table column model in use. Of particular interest is the property
* <i>_table</i> which is a reference to the table widget. This allows
* access to any other features of the table, for use in calculating widths
* of columns.
*
* @param event
* The <i>onwindowresize</i> event object.
*/
qx.Proto.onWindowResize = function(tableColumnModel, event)
{
throw new Error("onWindowResize is abstract");
};
/**
* Called when a column width is changed.
*
* @param tableColumnModel {qx.ui.table.ResizeTableColumnModel}
* The table column model in use. Of particular interest is the property
* <i>_table</i> which is a reference to the table widget. This allows
* access to any other features of the table, for use in calculating widths
* of columns.
*
* @param event
* The <i>widthChanged</i> event object. This event has data, obtained via
* event.getData(), which is an object with three properties: the column
* which changed width (data.col), the old width (data.oldWidth) and the new
* width (data.newWidth).
*/
qx.Proto.onColumnWidthChanged = function(tableColumnModel, event)
{
throw new Error("onColumnWidthChanged is abstract");
};
/**
* Called when a column visibility is changed.
*
* @param tableColumnModel {qx.ui.table.ResizeTableColumnModel}
* The table column model in use. Of particular interest is the property
* <i>_table</i> which is a reference to the table widget. This allows
* access to any other features of the table, for use in calculating widths
* of columns.
*
* @param event
* The <i>visibilityChanged</i> event object. This event has data, obtained
* via event.getData(), which is an object with two properties: the column
* which changed width (data.col) and the new visibility of the column
* (data.visible).
*/
qx.Proto.onVisibilityChanged = function(tableColumnModel, event)
{
throw new Error("onVisibilityChanged is abstract");
};
/*
* Determine the inner width available to columns in the table.
*
* @param tableColumnModel {qx.ui.table.ResizeTableColumnModel}
* The table column model in use.
*
*/
qx.Proto._getAvailableWidth = function(tableColumnModel)
{
// Get the inner width off the table
var el = tableColumnModel._table.getElement();
var width = qx.html.Dimension.getInnerWidth(el) - 2;
// Get the last meta column scroller
var scrollers = tableColumnModel._table._getPaneScrollerArr();
var lastScroller = scrollers[scrollers.length - 1];
// Update the scroll bar visibility so we can determine if the vertical bar
// is displayed. If it is, we'll need to reduce available space by its
// width.
tableColumnModel._table._updateScrollBarVisibility();
// If the column visibility button is displayed or a verticalscroll bar is
// being displayed, then reduce the available width by the width of those.
if (tableColumnModel._table.getColumnVisibilityButtonVisible() ||
(lastScroller._verScrollBar.getVisibility() &&
lastScroller._verScrollBar.getWidth() == "auto"))
{
width -= 16;
}
return width;
};

View File

@ -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;

View File

@ -0,0 +1,37 @@
/* ************************************************************************
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)
************************************************************************ */
/**
* All of the resizing information about a column.
*/
qx.OO.defineClass("qx.ui.table.ResizeBehaviorColumnData",
qx.ui.core.Widget,
function()
{
qx.ui.core.Widget.call(this);
// Assume equal flex width for all columns
this.setWidth("1*");
});

View File

@ -0,0 +1,228 @@
/* ************************************************************************
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)
#require(qx.ui.table.DefaultResizeBehavior)
************************************************************************ */
/**
* A table column model that automagically resizes columns based on a
* selected behavior.
*
* @see qx.ui.table.TableColumnModel
*/
qx.OO.defineClass("qx.ui.table.ResizeTableColumnModel",
qx.ui.table.TableColumnModel,
function()
{
qx.ui.table.TableColumnModel.call(this);
// We don't want to recursively call ourself based on our resetting of
// column sizes. Track when we're resizing.
this._bInProgress = false;
// Track when the table has appeared. We want to ignore resize events until
// then since we won't be able to determine the available width anyway.
this._bAppeared = false;
});
/*
* The behavior to use.
*
* The provided behavior must extend {link @AbstractResizeBehavior} and
* implement the <i>onAppear</i>, <i>onWindowResize</i>,
* <i>onColumnWidthChanged</i> and <i>onVisibilityChanged</i>methods.
*/
qx.OO.addProperty(
{
name : "behavior",
type : "object",
defaultValue : new qx.ui.table.DefaultResizeBehavior()
});
// Behavior modifier
qx.Proto._modifyBehavior = function(propValue, propOldValue, propData)
{
// Tell the new behavior how many columns there are
this.getBehavior()._setNumColumns(this._columnDataArr.length);
return true;
};
/**
* Initializes the column model.
*
* @param colCount {Integer}
* The number of columns the model should have.
*
* @param table {qx.ui.table.Table}
* The table which this model is used for. This allows us access to other
* aspects of the table, as the <i>behavior</i> sees fit.
*/
qx.Proto.init = function(numColumns, table)
{
// Call our superclass
qx.ui.table.TableColumnModel.prototype.init.call(this, numColumns);
// Save the table so we can get at its features, as necessary.
this._table = table;
// We'll do our column resizing when the table appears, ...
table.addEventListener("appear", this._onappear, this);
// ... when the window is resized, ...
var d = qx.ui.core.ClientDocument.getInstance();
d.addEventListener("windowresize", this._onwindowresize, this);
// ... when columns are resized, ...
this.addEventListener("widthChanged", this._oncolumnwidthchanged, this);
// ... and when a column visibility changes.
this.addEventListener("visibilityChanged", this._onvisibilitychanged, this);
// We want to manipulate the button visibility menu
this._table.addEventListener("columnVisibilityMenuCreateEnd",
this._addResetColumnWidthButton,
this);
// Tell the behavior how many columns there are
this.getBehavior()._setNumColumns(numColumns);
};
/**
* Reset the column widths to their "onappear" defaults.
*
* @param event {qx.event.type.DataEvent}
* The "columnVisibilityMenuCreateEnd" event indicating that the menu is
* being generated. The data is a map containing propeties <i>table</i> and
* <i>menu</i>.
*/
qx.Proto._addResetColumnWidthButton = function(event)
{
var data = event.getData();
var menu = data.menu;
var o;
var Am = qx.manager.object.AliasManager;
var icon = Am.getInstance().resolvePath("icon/16/actions/view-refresh.png");
// Add a separator between the column names and our reset button
o= new qx.ui.menu.Separator();
menu.add(o);
// Add a button to reset the column widths
o = new qx.ui.menu.Button("Reset column widths", icon);
menu.add(o);
o.addEventListener("execute", this._onappear, this);
};
/**
* Event handler for the "onappear" event.
*
* @param event {qx.event.type.Event}
* The "onappear" event object.
*/
qx.Proto._onappear = function(event)
{
// Is this a recursive call?
if (this._bInProgress)
{
// Yup. Ignore it.
return;
}
this._bInProgress = true;
this.debug("onappear");
this.getBehavior().onAppear(this, event);
this._bInProgress = false;
this._bAppeared = true;
};
/**
* Event handler for the "onwindowresize" event.
*
* @param event {qx.event.type.Event}
* The "onwidowresize" event object.
*/
qx.Proto._onwindowresize = function(event)
{
// Is this a recursive call or has the table not yet been rendered?
if (this._bInProgress || ! this._bAppeared)
{
// Yup. Ignore it.
return;
}
this._bInProgress = true;
this.debug("onwindowresize");
this.getBehavior().onWindowResize(this, event);
this._bInProgress = false;
};
/**
* Event handler for the "oncolumnwidthchanged" event.
*
* @param event {qx.event.type.DataEvent}
* The "oncolumnwidthchanged" event object.
*/
qx.Proto._oncolumnwidthchanged = function(event)
{
// Is this a recursive call or has the table not yet been rendered?
if (this._bInProgress || ! this._bAppeared)
{
// Yup. Ignore it.
return;
}
this._bInProgress = true;
this.debug("oncolumnwidthchanged");
this.getBehavior().onColumnWidthChanged(this, event);
this._bInProgress = false;
};
/**
* Event handler for the "onvisibilitychangned" event.
*
* @param event {qx.event.type.DataEvent}
* The "onvisibilitychanged" event object.
*/
qx.Proto._onvisibilitychanged = function(event)
{
// Is this a recursive call or has the table not yet been rendered?
if (this._bInProgress || ! this._bAppeared)
{
// Yup. Ignore it.
return;
}
this._bInProgress = true;
this.debug("onvisibilitychanged");
this.getBehavior().onVisibilityChanged(this, event);
this._bInProgress = false;
};

View File

@ -28,8 +28,20 @@
/**
* A table.
*
* @param tableModel {qx.ui.table.TableModel, null} The table model to read the
* data from.
* @param tableModel {qx.ui.table.TableModel, null}
* The table model to read the data from.
*
* @event columnVisibilityMenuCreateStart {qx.event.type.DataEvent}
* Dispatched before adding the column list to the column visibility menu.
* The event data is a map with two properties: table and menu. Listeners
* may add additional items to the menu, which appear at the top of the
* menu.
*
* @event columnVisibilityMenuCreateEnd {qx.event.type.DataEvent}
* Dispatched after adding the column list to the column visibility menu.
* The event data is a map with two properties: table and menu. Listeners
* may add additional items to the menu, which appear at the bottom of the
* menu.
*/
qx.OO.defineClass("qx.ui.table.Table", qx.ui.layout.VerticalBoxLayout,
function(tableModel) {
@ -282,7 +294,7 @@ qx.Proto._modifySelectionModel = function(propValue, propOldValue, propData) {
// property modifier
qx.Proto._modifyTableModel = function(propValue, propOldValue, propData) {
this.getTableColumnModel().init(propValue.getColumnCount());
this.getTableColumnModel().init(propValue.getColumnCount(), this);
if (propOldValue != null) {
propOldValue.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
@ -309,6 +321,25 @@ qx.Proto._modifyTableColumnModel = function(propValue, propOldValue, propData) {
propValue.addEventListener("widthChanged", this._onColWidthChanged, this);
propValue.addEventListener("orderChanged", this._onColOrderChanged, this);
// Get the current table model
var tm = this.getTableModel();
// If one is already in effect...
if (tm)
{
// ... then initialize this new table column model now.
propValue.init(tm.getColumnCount(), this);
}
// Reset the table column model in each table pane model
var scrollerArr = this._getPaneScrollerArr();
for (var i = 0; i < scrollerArr.length; i++)
{
var paneScroller = scrollerArr[i];
var paneModel = paneScroller.getTablePaneModel();
paneModel._tableColumnModel = propValue;
}
return true;
};
@ -1070,6 +1101,20 @@ qx.Proto._toggleColumnVisibilityMenu = function() {
var tableModel = this.getTableModel();
var columnModel = this.getTableColumnModel();
// Inform listeners who may want to insert menu items at the beginning
if (this.hasEventListeners("columnVisibilityMenuCreateStart"))
{
var data =
{
table : this,
menu : menu
};
var event =
new qx.event.type.DataEvent("columnVisibilityMenuCreateStart", data);
this.dispatchEvent(event, true);
}
for (var x = 0; x < columnModel.getOverallColumnCount(); x++) {
var col = columnModel.getOverallColumnAtX(x);
var visible = columnModel.isColumnVisible(col);
@ -1083,6 +1128,19 @@ qx.Proto._toggleColumnVisibilityMenu = function() {
menu.add(bt);
}
// Inform listeners who may want to insert menu items at the end
if (this.hasEventListeners("columnVisibilityMenuCreateEnd"))
{
var data =
{
table : this,
menu : menu
};
var event =
new qx.event.type.DataEvent("columnVisibilityMenuCreateEnd", data);
this.dispatchEvent(event, true);
}
menu.setParent(this.getTopLevelWidget());
this._columnVisibilityMenu = menu;

View File

@ -56,9 +56,19 @@ function(headings)
return new qx.ui.treevirtual.SelectionManager(obj);
});
this.setNewTableColumnModel(
function(obj)
{
return new qx.ui.table.ResizeTableColumnModel(obj);
});
// Call our superclass constructor
qx.ui.table.Table.call(this, tableModel);
// By default, present the column visibility button only if there are
// multiple columns.
this.setColumnVisibilityButtonVisible(headings.length > 1);
// Set sizes
this.setRowHeight(16);
this.setMetaColumnCounts([1, -1]);
@ -112,7 +122,7 @@ function(headings)
// For each scroller...
for (var i = 0; i < scrollers.length; i++)
{
// ... remove the outline on focus,
// ... remove the outline on focus,
scrollers[i]._focusIndicator.setAppearance("treevirtual-focus-indicator");
// ... and set the pane scrollers to handle the selection before
@ -371,22 +381,8 @@ qx.Proto.toggleOpened = function(node)
// 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
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,
@ -470,7 +466,7 @@ qx.Proto.setCellFocusAttributes = function(attributes)
for (var i = 0; i < scrollers.length; i++)
{
scrollers[i]._focusIndicator.set(attributes);
}
}
};
@ -542,7 +538,7 @@ qx.Proto._onkeydown = function(evt)
// ... then close it
this.toggleOpened(node);
}
// Reset the focus to the current node
this.setFocusedCell(treeCol, focusedRow, true);
@ -569,7 +565,7 @@ qx.Proto._onkeydown = function(evt)
// Reset the focus to the current node
this.setFocusedCell(treeCol, focusedRow, true);
consumed = true;
break;
}
@ -592,11 +588,11 @@ qx.Proto._onkeydown = function(evt)
{
// 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;
@ -626,7 +622,7 @@ qx.Proto._onkeydown = function(evt)
this.moveFocusedCell(0, 1);
}
}
consumed = true;
break;
}
@ -759,7 +755,7 @@ qx.Proto.getHierarchy = function(nodeId)
*
* @return {Array}
* An array of nodes matching the set of rows which are selected on the
* screen.
* screen.
*/
qx.Proto._calculateSelectedNodes = function()
{

View File

@ -339,12 +339,6 @@ qx.Proto._buildPageBrowse = function(module, page)
// We've only got one column, so we don't need cell focus indication.
tree.setCellFocusAttributes({ backgroundColor : "transparent" });
// This needs to become automatic!
tree.setColumnWidth(0, 200);
// We only have one column. We don't need the column visibility button
tree.setColumnVisibilityButtonVisible(false);
// Get the data model
var dataModel = tree.getDataModel();