You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cf...@apache.org on 2012/12/21 19:05:22 UTC
svn commit: r1425063 [3/13] - in /incubator/flex/sdk/branches/develop:
frameworks/ frameworks/projects/spark/ frameworks/projects/spark/src/
frameworks/projects/spark/src/spark/collections/
frameworks/projects/spark/src/spark/components/ frameworks/pro...
Modified: incubator/flex/sdk/branches/develop/frameworks/projects/spark/src/spark/components/Grid.as
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/frameworks/projects/spark/src/spark/components/Grid.as?rev=1425063&r1=1425062&r2=1425063&view=diff
==============================================================================
--- incubator/flex/sdk/branches/develop/frameworks/projects/spark/src/spark/components/Grid.as (original)
+++ incubator/flex/sdk/branches/develop/frameworks/projects/spark/src/spark/components/Grid.as Fri Dec 21 18:05:20 2012
@@ -29,24 +29,36 @@ import flash.utils.getTimer;
import mx.collections.ArrayList;
import mx.collections.IList;
import mx.core.IFactory;
+import mx.core.IVisualElement;
+import mx.core.UIComponent;
import mx.core.UIComponentGlobals;
import mx.core.mx_internal;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.FlexEvent;
import mx.events.PropertyChangeEvent;
+import mx.graphics.SolidColorStroke;
import mx.utils.ObjectUtil;
+import spark.collections.SubListView;
import spark.components.gridClasses.CellPosition;
import spark.components.gridClasses.GridColumn;
import spark.components.gridClasses.GridDimensions;
+import spark.components.gridClasses.GridDimensionsView;
import spark.components.gridClasses.GridLayout;
import spark.components.gridClasses.GridSelection;
import spark.components.gridClasses.GridSelectionMode;
+import spark.components.gridClasses.GridView;
+import spark.components.gridClasses.GridViewLayout;
import spark.components.gridClasses.IDataGridElement;
import spark.components.gridClasses.IGridItemRenderer;
+import spark.components.supportClasses.GroupBase;
import spark.events.GridCaretEvent;
import spark.events.GridEvent;
+import spark.layouts.VerticalLayout;
+import spark.layouts.supportClasses.LayoutBase;
+import spark.primitives.Line;
+import spark.primitives.Rect;
import spark.utils.MouseEventUtil;
use namespace mx_internal;
@@ -229,7 +241,7 @@ use namespace mx_internal;
public class Grid extends Group implements IDataGridElement
{
include "../core/Version.as";
-
+
//--------------------------------------------------------------------------
//
// Variables
@@ -288,6 +300,7 @@ public class Grid extends Group implemen
public function Grid()
{
super();
+
layout = new GridLayout();
MouseEventUtil.addDownDragUpListeners(this,
@@ -302,12 +315,30 @@ public class Grid extends Group implemen
/**
* @private
+ * Return the GridView which contains the specified cell. If rowIndex == -1,
+ * then return the topmost GridView that contains the specified column and
+ * if columnIndex == -1 then return the leftmost GridView that contains the specified row.
*/
- private function get gridLayout():GridLayout
+ private function getGridViewAt(rowIndex:int, columnIndex:int):GridView
{
- return layout as GridLayout;
+ if ((rowIndex < 0) && (columnIndex < 0))
+ return null;
+
+ const gridLayout:GridLayout = layout as GridLayout;
+
+ if ((rowIndex >= lockedRowCount) || (rowIndex == -1))
+ {
+ if ((columnIndex >= lockedColumnCount) || (columnIndex == -1))
+ return gridLayout.centerGridView;
+
+ return gridLayout.leftGridView;
+ }
+
+ return (columnIndex < lockedColumnCount) ? gridLayout.topLeftGridView : gridLayout.topGridView;
}
+
+
//--------------------------------------------------------------------------
//
// Properties
@@ -386,7 +417,7 @@ public class Grid extends Group implemen
return;
}
- _anchorColumnIndex = value;
+ _anchorColumnIndex = value;
anchorChanged = true;
invalidateProperties();
@@ -461,7 +492,7 @@ public class Grid extends Group implemen
* If <code>selectionMode</code> is
* <code>GridSelectionMode.SINGLE_CELL</code> or
* <code>GridSelectionMode.MULTIPLE_CELLS</code>, the
- * visual element displayted for the caret cell.
+ * visual element displayed for the caret cell.
*
* @default null
*
@@ -598,6 +629,167 @@ public class Grid extends Group implemen
invalidateDisplayListFor("caretIndicator");
dispatchChangeEvent("caretRowIndexChanged");
}
+
+ //----------------------------------
+ // clipAndEnableScrolling (private override)
+ //----------------------------------
+
+ private var _clipAndEnableScrolling:Boolean = false;
+
+ /**
+ * @private
+ */
+ override public function get clipAndEnableScrolling():Boolean
+ {
+ return _clipAndEnableScrolling;
+ }
+
+ /**
+ * @private
+ */
+ override public function set clipAndEnableScrolling(value:Boolean):void
+ {
+ if (value == _clipAndEnableScrolling)
+ return;
+
+ _clipAndEnableScrolling = value;
+
+ const gridLayout:GridLayout = layout as GridLayout;
+ const topGridView:GridView = gridLayout.topGridView;
+ const leftGridView:GridView = gridLayout.leftGridView;
+ const centerGridView:GridView = gridLayout.centerGridView;
+
+ if (topGridView) topGridView.clipAndEnableScrolling = value;
+ if (leftGridView) leftGridView.clipAndEnableScrolling = value;
+ if (centerGridView) centerGridView.clipAndEnableScrolling = value;
+ }
+
+
+ //----------------------------------
+ // contentHeight (private get override)
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ override public function get contentHeight():Number
+ {
+ return Math.ceil(gridDimensions.getContentHeight());
+ }
+
+ //----------------------------------
+ // contentWidth (private get override)
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ override public function get contentWidth():Number
+ {
+ return Math.ceil(gridDimensions.getContentWidth());
+ }
+
+ //----------------------------------
+ // horizontalScrollPosition (private override)
+ //----------------------------------
+
+ private var _horizontalScrollPosition:Number = 0;
+
+ [Bindable]
+ [Inspectable(minValue="0.0")]
+
+ /**
+ * @copy spark.core.IViewport#horizontalScrollPosition
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override public function get horizontalScrollPosition():Number
+ {
+ return _horizontalScrollPosition;
+ }
+
+ /**
+ * @private
+ */
+ override public function set horizontalScrollPosition(value:Number):void
+ {
+ if (_horizontalScrollPosition == value)
+ return;
+
+ const gridLayout:GridLayout = layout as GridLayout;
+ const topGridView:GridView = gridLayout.topGridView;
+ const centerGridView:GridView = gridLayout.centerGridView;
+
+ if (centerGridView)
+ {
+ const gridViewLayout:GridViewLayout = centerGridView.gridViewLayout;
+ const gridMaxHSP:Number = contentWidth - width;
+ const centerContentWidth:Number = Math.ceil(gridViewLayout.gridDimensionsView.getContentWidth());
+ const centerMaxHSP:Number = centerContentWidth - centerGridView.width;
+ const hsp:Number = (centerMaxHSP / gridMaxHSP) * value;
+
+ centerGridView.horizontalScrollPosition = hsp;
+
+ if (topGridView)
+ topGridView.horizontalScrollPosition = hsp;
+ }
+
+ _horizontalScrollPosition = value;
+ }
+
+ //----------------------------------
+ // verticalScrollPosition (private override)
+ //----------------------------------
+
+ private var _verticalScrollPosition:Number = 0;
+
+ [Bindable]
+ [Inspectable(minValue="0.0")]
+
+ /**
+ * @copy spark.core.IViewport#verticalScrollPosition
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4
+ */
+ override public function get verticalScrollPosition():Number
+ {
+ return _verticalScrollPosition;
+ }
+
+ /**
+ * @private
+ */
+ override public function set verticalScrollPosition(value:Number):void
+ {
+ if (_verticalScrollPosition == value)
+ return;
+
+ const gridLayout:GridLayout = layout as GridLayout;
+ const leftGridView:GridView = gridLayout.leftGridView;
+ const centerGridView:GridView = gridLayout.centerGridView;
+
+ if (centerGridView)
+ {
+ const gridViewLayout:GridViewLayout = centerGridView.gridViewLayout;
+ const gridMaxVSP:Number = contentHeight - height;
+ const centerContentHeight:Number = Math.ceil(gridViewLayout.gridDimensionsView.getContentHeight());
+ const centerMaxVSP:Number = centerContentHeight - centerGridView.height;
+ const vsp:Number = (centerMaxVSP / gridMaxVSP) * value;
+
+ centerGridView.verticalScrollPosition = vsp;
+
+ if (leftGridView)
+ leftGridView.verticalScrollPosition = vsp;
+ }
+
+ _verticalScrollPosition = value;
+ }
//----------------------------------
// hoverIndicator
@@ -994,6 +1186,20 @@ public class Grid extends Group implemen
}
//----------------------------------
+ // gridDimensions (mx_internal)
+ //----------------------------------
+
+ private var _gridDimensions:GridDimensions = null;
+
+ mx_internal function get gridDimensions():GridDimensions
+ {
+ if (!_gridDimensions)
+ _gridDimensions = new GridDimensions();
+
+ return _gridDimensions;
+ }
+
+ //----------------------------------
// itemRenderer
//----------------------------------
@@ -1134,6 +1340,184 @@ public class Grid extends Group implemen
_dataGrid = value;
dispatchChangeEvent("dataGridChanged");
}
+
+ //----------------------------------
+ // lockedColumnCount
+ //----------------------------------
+
+ private var _lockedColumnCount:int = 0;
+
+ [Bindable("lockedColumnCountChanged")]
+ [Inspectable(category="General", defaultValue="0", minValue="0")]
+
+ /**
+ * The first lockedColumnCount columns are "locked", i.e. they do not scroll horizontally.
+ * If lockedColumnCount is zero (the default) then changes to the horizontalScrollPosition
+ * affect all columns.
+ *
+ * <p>The locked columns are displayed in the topGridView and, if lockedRowCount is also
+ * greater than zero, the topLeftGridView. The locked columns are separated from the remaining
+ * columns by a lockedColumnSeparator.</p>
+ *
+ * @default 0
+ *
+ * @see spark.components.gridClasses.GridColumn#topGridView
+ * @see spark.components.gridClasses.GridColumn#topLeftGridView
+ * @see spark.components.gridClasses.GridColumn#lockedColumnSeparator
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 5.0
+ */
+ public function get lockedColumnCount():int
+ {
+ return _lockedColumnCount;
+ }
+
+ /**
+ * @private
+ */
+ public function set lockedColumnCount(value:int):void
+ {
+ if (_lockedColumnCount == value)
+ return;
+
+ invalidateProperties();
+ invalidateSize();
+ invalidateDisplayList();
+
+ _lockedColumnCount = value;
+ dispatchChangeEvent("lockedColumnCountChanged");
+ }
+
+ //----------------------------------
+ // lockedColumnsSeparator
+ //----------------------------------
+
+ private var _lockedColumnsSeparator:IFactory = null;
+
+ [Bindable("lockedColumnsSeparatorChanged")]
+
+ /**
+ * A visual element displayed between the locked and unlocked columns. The factory value of this
+ * property is used to create the lockedColumnsSeparatorElement.
+ *
+ * @see spark.components.Grid#lockedRowsSeparatorElement
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 5.0
+ *
+ * @default null
+ */
+ public function get lockedColumnsSeparator():IFactory
+ {
+ return _lockedColumnsSeparator;
+ }
+
+ /**
+ * @private
+ */
+ public function set lockedColumnsSeparator(value:IFactory):void
+ {
+ if (_lockedColumnsSeparator == value)
+ return;
+
+ _lockedColumnsSeparator = value;
+ invalidateDisplayList();
+ dispatchChangeEvent("lockedColumnsSeparatorChanged");
+ }
+
+ //----------------------------------
+ // lockedRowCount
+ //----------------------------------
+
+ private var _lockedRowCount:int = 0;
+
+ [Bindable("lockedRowCountChanged")]
+ [Inspectable(category="General", defaultValue="0", minValue="0")]
+
+ /**
+ * The first lockedRowCount rows are "locked", i.e. they do not scroll vertically.
+ * If lockedRowCount is zero (the default) then changes to the verticalScrollPosition
+ * affect all rows.
+ *
+ * <p>The locked rows are displayed in the leftGridView and, if lockedColumnCount is also
+ * greater than zero, the topLeftGridView. The locked rows are separated from the remaining
+ * rows by a lockedRowSeparator.</p>
+ *
+ * @default 0
+ *
+ * @see spark.components.gridClasses.GridColumn#leftGridView
+ * @see spark.components.gridClasses.GridColumn#topLeftGridView
+ * @see spark.components.gridClasses.GridColumn#lockedRowSeparator
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 5.0
+ */
+ public function get lockedRowCount():int
+ {
+ return _lockedRowCount;
+ }
+
+ /**
+ * @private
+ */
+ public function set lockedRowCount(value:int):void
+ {
+ if (_lockedRowCount == value)
+ return;
+
+ invalidateProperties();
+ invalidateSize();
+ invalidateDisplayList();
+
+ _lockedRowCount = value;
+ dispatchChangeEvent("lockedRowCountChanged");
+ }
+
+ //----------------------------------
+ // lockedRowsSeparator
+ //----------------------------------
+
+ private var _lockedRowsSeparator:IFactory = null;
+
+ [Bindable("lockedRowsSeparatorChanged")]
+
+ /**
+ * A visual element displayed between the locked and unlocked rows. The factory value of this
+ * property is used to create the lockedRowsSeparatorElement.
+ *
+ * @default null
+ *
+ * @see spark.components.Grid#lockedRowsSeparatorElement
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 5.0
+ */
+ public function get lockedRowsSeparator():IFactory
+ {
+ return _lockedRowsSeparator;
+ }
+
+ /**
+ * @private
+ */
+ public function set lockedRowsSeparator(value:IFactory):void
+ {
+ if (_lockedRowsSeparator == value)
+ return;
+
+ _lockedRowsSeparator = value;
+ invalidateDisplayList();
+ dispatchChangeEvent("lockedRowsSeparatorChanged");
+ }
//----------------------------------
// preserveSelection (delegates to gridSelection.preserveSelection)
@@ -1608,7 +1992,7 @@ public class Grid extends Group implemen
* event. When the user changes the selection programmatically, the
* control dispatches the <code>valueCommit</code> event.</p>
*
- * <p> This property is intended be used to initialize or bind to the
+ * <p> This property is intended to be used to initialize or bind to the
* selection in MXML markup. The <code>setSelectedCell()</code> method
* should be used for programatic selection updates, for example
* when writing a keyboard or mouse event handler. </p>
@@ -1681,7 +2065,7 @@ public class Grid extends Group implemen
* event. When the user changes the selection programmatically, the
* control dispatches the <code>valueCommit</code> event.</p>
*
- * <p> This property is intended be used to initialize or bind to the
+ * <p> This property is intended to be used to initialize or bind to the
* selection in MXML markup. The <code>setSelectedCell()</code> method
* should be used for programatic selection updates, for example when
* writing a keyboard or mouse event handler. </p>
@@ -1723,18 +2107,14 @@ public class Grid extends Group implemen
var f:Function = function():void
{
- clearSelection();
- for each (cell in valueCopy)
- addSelectedCell(cell.rowIndex, cell.columnIndex);
+ doSetSelectedCells(valueCopy);
}
deferredOperations.push(f); // function f() to be called by commitProperties()
invalidateProperties();
}
else
{
- clearSelection();
- for each (cell in valueCopy)
- addSelectedCell(cell.rowIndex, cell.columnIndex);
+ doSetSelectedCells(valueCopy);
}
}
@@ -1756,7 +2136,7 @@ public class Grid extends Group implemen
* event. When the user changes the selection programmatically, the
* control dispatches the <code>valueCommit</code> event.</p>
*
- * <p> This property is intended be used to initialize or bind to the
+ * <p> This property is intended to be used to initialize or bind to the
* selection in MXML markup. The <code>setSelectedCell()</code> method should be used
* for programatic selection updates, for example when writing a keyboard
* or mouse event handler. </p>
@@ -1826,7 +2206,7 @@ public class Grid extends Group implemen
* event. When the user changes the selection programmatically, the
* control dispatches the <code>valueCommit</code> event.</p>
*
- * <p> This property is intended be used to initialize or bind to the
+ * <p> This property is intended to be used to initialize or bind to the
* selection in MXML markup. The setSelectedCell() method should be used
* for programatic selection updates, for example when writing a keyboard
* or mouse event handler. </p> >
@@ -1865,18 +2245,14 @@ public class Grid extends Group implemen
var f:Function = function():void
{
- clearSelection();
- for each (var index:int in valueCopy)
- addSelectedIndex(index);
+ doSetSelectedIndices(valueCopy);
}
deferredOperations.push(f); // function f() to be called by commitProperties()
invalidateProperties();
}
else
{
- clearSelection();
- for each (var index:int in valueCopy)
- addSelectedIndex(index);
+ doSetSelectedIndices(valueCopy);
}
}
@@ -1899,7 +2275,7 @@ public class Grid extends Group implemen
* event. When the user changes the selection programmatically, the
* control dispatches the <code>valueCommit</code> event.</p>
*
- * <p> This property is intended be used to initialize or bind to the
+ * <p> This property is intended to be used to initialize or bind to the
* selection in MXML markup. The <code>setSelectedCell()</code> method should be used
* for programatic selection updates, for example when writing a keyboard
* or mouse event handler. </p>
@@ -1980,7 +2356,7 @@ public class Grid extends Group implemen
* event. When the user changes the selection programmatically, the
* control dispatches the <code>valueCommit</code> event.</p>
*
- * <p> This property is intended be used to initialize or bind to the
+ * <p> This property is intended to be used to initialize or bind to the
* selection in MXML markup. The setSelectedCell() method should be used
* for programatic selection updates, for example when writing a keyboard
* or mouse event handler. </p>
@@ -2027,24 +2403,14 @@ public class Grid extends Group implemen
var f:Function = function():void
{
- if (!dataProvider)
- return;
-
- clearSelection();
- for each (var item:Object in valueCopy)
- addSelectedIndex(dataProvider.getItemIndex(item));
+ doSetSelectedItems(valueCopy);
}
deferredOperations.push(f); // function f() to be called by commitProperties()
invalidateProperties();
}
else
{
- if (!dataProvider)
- return;
-
- clearSelection();
- for each (var item:Object in valueCopy)
- addSelectedIndex(dataProvider.getItemIndex(item))
+ doSetSelectedItems(valueCopy);
}
}
@@ -2171,6 +2537,39 @@ public class Grid extends Group implemen
}
//----------------------------------
+ // showCaret
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ private var _showCaret:Boolean = false;
+
+ [Bindable("showCaretChanged")]
+
+ /**
+ * Determines if the caret is visible.
+ * TBD: when is this property automatically set?
+ */
+ public function get showCaret():Boolean
+ {
+ return _showCaret;
+ }
+
+ /**
+ * @private
+ */
+ public function set showCaret(value:Boolean):void
+ {
+ if (_showCaret == value)
+ return;
+
+ _showCaret = value;
+ invalidateDisplayListFor("caretIndicator");
+ dispatchChangeEvent("showCaretChanged");
+ }
+
+ //----------------------------------
// showDataTips
//----------------------------------
@@ -2207,9 +2606,9 @@ public class Grid extends Group implemen
_showDataTips = value;
invalidateDisplayList();
- dispatchEvent(new Event("showDataTipsChanged"));
+ dispatchChangeEvent("showDataTipsChanged");
}
-
+
//----------------------------------
// typicalItem
//----------------------------------
@@ -2221,7 +2620,7 @@ public class Grid extends Group implemen
[Inspectable(category="Data")]
/**
- * The grid's layout ensures that columns whose width is not specified is wide
+ * The grid's layout ensures that columns whose width is not specified are wide
* enough to display an item renderer for this default data provider item.
* If a typical item is not specified, then the first data provider item is used.
*
@@ -2249,9 +2648,7 @@ public class Grid extends Group implemen
return;
_typicalItem = value;
-
invalidateTypicalItemRenderer();
-
dispatchChangeEvent("typicalItemChanged");
}
@@ -2304,26 +2701,66 @@ public class Grid extends Group implemen
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
- public function get variableRowHeight():Boolean
+ public function get variableRowHeight():Boolean
+ {
+ return _variableRowHeight;
+ }
+
+ /**
+ * @private
+ */
+ public function set variableRowHeight(value:Boolean):void
+ {
+ if (value == variableRowHeight)
+ return;
+
+ _variableRowHeight = value;
+ variableRowHeightChanged = true;
+ invalidateProperties();
+
+ dispatchChangeEvent("variableRowHeightChanged");
+ }
+
+ //----------------------------------
+ // gridView
+ //----------------------------------
+
+ private var _gridView:IFactory = null;
+
+ [Bindable("gridViewChanged")]
+
+ /**
+ * Used to initialize this grid's gridViews: centerGridView, leftGridView, topGridView, topLeftGridView.
+ * GridViews are created as needed, depending on the values of lockedRowCount and lockedColumnCount.
+ *
+ * @default null.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 5.0
+ */
+ public function get gridView():IFactory
{
- return _variableRowHeight;
+ return _gridView;
}
/**
* @private
*/
- public function set variableRowHeight(value:Boolean):void
+ public function set gridView(value:IFactory):void
{
- if (value == variableRowHeight)
+ if (value == _gridView)
return;
- _variableRowHeight = value;
- variableRowHeightChanged = true;
+ _gridView = value;
invalidateProperties();
- dispatchChangeEvent("variableRowHeightChanged");
+ // TBD clear everything
+
+ dispatchChangeEvent("gridViewChanged");
}
-
+
//--------------------------------------------------------------------------
//
// GridSelection Cover Methods
@@ -2736,7 +3173,7 @@ public class Grid extends Group implemen
*
* @param columnIndex The 0-based column index of the cell.
*
- * @return <code>true</code> if if no errors.
+ * @return <code>true</code> if no errors.
* <code>false</code> if <code>rowIndex</code>
* or <code>columnIndex</code> is invalid or the <code>selectionMode</code>
* is invalid.
@@ -2935,21 +3372,100 @@ public class Grid extends Group implemen
return selectionChanged;
}
-
+
//--------------------------------------------------------------------------
//
- // GridLayout Cover Methods, Properties
+ // Selection API Helper Methods
//
//--------------------------------------------------------------------------
+
+ /**
+ * For performance reasons, make sure validateClient, anchor and caret updates,
+ * and selectionIndicator and VALUE_COMMIT updates are only done once.
+ */
+ private function doSetSelectedCells(valueCopy:Vector.<CellPosition>):void
+ {
+ // Need to apply pending dataProvider and column changes so selection
+ // isn't reset after it is set here.
+ if (invalidatePropertiesFlag)
+ UIComponentGlobals.layoutManager.validateClient(this, false);
+
+ gridSelection.removeAll();
+ for each (var cell:CellPosition in valueCopy)
+ {
+ gridSelection.addCell(cell.rowIndex, cell.columnIndex);
+ }
+
+ doFinalizeSetSelection(cell ? cell.rowIndex : -1,
+ cell ? cell.columnIndex : -1);
+ }
/**
- * @private
+ * For performance reasons, make sure validateClient, anchor and caret updates,
+ * and selectionIndicator and VALUE_COMMIT updates are only done once.
+ */
+ private function doSetSelectedIndices(valueCopy:Vector.<int>):void
+ {
+ // Need to apply pending dataProvider and column changes so selection
+ // isn't reset after it is set here.
+ if (invalidatePropertiesFlag)
+ UIComponentGlobals.layoutManager.validateClient(this, false);
+
+ var newRowIndex:int = -1;
+ gridSelection.removeAll();
+ for each (newRowIndex in valueCopy)
+ {
+ gridSelection.addRow(newRowIndex);
+ }
+
+ doFinalizeSetSelection(newRowIndex, -1);
+ }
+
+ /**
+ * For performance reasons, make sure validateClient, anchor and caret updates,
+ * and selectionIndicator and VALUE_COMMIT updates are only done once.
+ */
+ private function doSetSelectedItems(valueCopy:Vector.<Object>):void
+ {
+ if (!dataProvider)
+ return;
+
+ // Need to apply pending dataProvider and column changes so selection
+ // isn't reset after it is set here.
+ if (invalidatePropertiesFlag)
+ UIComponentGlobals.layoutManager.validateClient(this, false);
+
+ var newRowIndex:int = -1;
+ gridSelection.removeAll();
+ for each (var item:Object in valueCopy)
+ {
+ newRowIndex = dataProvider.getItemIndex(item);
+ gridSelection.addRow(newRowIndex);
+ }
+
+ doFinalizeSetSelection(newRowIndex, -1);
+ }
+
+ /**
+ * Finished selection operations so update the anchor, caret, selection indicators and
+ * trigger the selection bindings.
*/
- private function get gridDimensions():GridDimensions
+ private function doFinalizeSetSelection(rowIndex:int, columnIndex:int):void
{
- return gridLayout.gridDimensions;
+ initializeAnchorPosition();
+ caretRowIndex = rowIndex
+ caretColumnIndex = columnIndex
+
+ invalidateDisplayListFor("selectionIndicator");
+ dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
}
+ //--------------------------------------------------------------------------
+ //
+ // GridViewLayout Cover Methods, Properties
+ //
+ //--------------------------------------------------------------------------
+
/**
* @private
* Update the scroll position so that the virtual Grid element at the specified
@@ -2959,13 +3475,24 @@ public class Grid extends Group implemen
*
* @returns True if either the horizontalScrollPosition or verticalScrollPosition changed.
*/
- private function scrollToIndex(elementIndex:int, scrollHorizontally:Boolean, scrollVertically:Boolean):Boolean
+ private function scrollToIndex(view:GridView, elementIndex:int, scrollHorizontally:Boolean, scrollVertically:Boolean):Boolean
{
- var spDelta:Point = gridLayout.getScrollPositionDeltaToElement(elementIndex);
+ var spDelta:Point = view.gridViewLayout.getScrollPositionDeltaToElement(elementIndex);
// The cell is completely visible or the specified index is no longer valid so punt.
+
if (!spDelta)
- return false;
+ return false;
+
+ // If the required scroll is locked then punt
+
+ if ((spDelta.y != 0) && view.gridViewLayout.verticalScrollingLocked)
+ return false;
+
+ if ((spDelta.x != 0) && view.gridViewLayout.horizontalScrollingLocked)
+ return false;
+
+ // Update the scroll positions
var scrollChanged:Boolean = false;
@@ -3019,9 +3546,19 @@ public class Grid extends Group implemen
(columnIndex != -1 && !(GridColumn(columns.getItemAt(columnIndex)).visible)))
return;
- const columnsLength:int = columns.length;
const scrollHorizontally:Boolean = columnIndex != -1;
const scrollVertically:Boolean = rowIndex != -1;
+
+ // If the row, column, or cell is locked, then there's nothing to do.
+
+ if ((columnIndex < lockedColumnCount) && (rowIndex < lockedRowCount))
+ return;
+
+ if (!scrollVertically && (columnIndex < lockedColumnCount))
+ return;
+
+ if (!scrollHorizontally && (rowIndex < lockedRowCount))
+ return;
// If called after the layout cache is cleared, need to rebuild the cache
// before accessing visible rows/columns and attempting to scroll.
@@ -3031,17 +3568,29 @@ public class Grid extends Group implemen
// When not scrolling horizontally, columnIndex can just be 0.
if (!scrollHorizontally)
columnIndex = 0;
-
+
+ // Find the GridView the specified cell is contained by and punt if it's not visible
+
+ const cellGridView:GridView = getGridViewAt(rowIndex, columnIndex);
+ if (!cellGridView ||
+ (cellGridView.getLayoutBoundsX() >= getLayoutBoundsWidth()) ||
+ (cellGridView.getLayoutBoundsY() >= getLayoutBoundsHeight()))
+ return;
+
// If the row index isn't specified, use the first one that's visible.
if (!scrollVertically)
{
- const visibleRowIndices:Vector.<int> = this.getVisibleRowIndices();
+ const visibleRowIndices:Vector.<int> = cellGridView.gridViewLayout.getVisibleRowIndices();
rowIndex = (visibleRowIndices.length > 0) ? visibleRowIndices[0] : 0;
}
// A cell's index as defined by LayoutBase it's just its position
// in the row-major linear ordering of the grid's cells.
- const elementIndex:int = (rowIndex * columnsLength) + columnIndex;
+
+ const gridViewLayout:GridViewLayout = cellGridView.gridViewLayout;
+ const cellViewRowIndex:int = rowIndex - gridViewLayout.viewRowIndex;
+ const cellViewColumnIndex:int = columnIndex - gridViewLayout.viewColumnIndex;
+ const cellElementIndex:int = (cellViewRowIndex * gridViewLayout.columnsView.length) + cellViewColumnIndex;
var scrollChanged:Boolean = false;
var firstScroll:Boolean = true;
@@ -3049,7 +3598,7 @@ public class Grid extends Group implemen
// Iterate until we've scrolled elementIndex at least partially into view.
do
{
- scrollChanged = scrollToIndex(elementIndex, scrollHorizontally, scrollVertically);
+ scrollChanged = scrollToIndex(cellGridView, cellElementIndex, scrollHorizontally, scrollVertically);
// Fixed row heights, and we're only scrolling vertically.
if (!variableRowHeight && !scrollHorizontally)
@@ -3070,7 +3619,7 @@ public class Grid extends Group implemen
// At this point we've only ensured that the requested cell is at least
// partially visible. Ensure that it's completely visible.
- scrollToIndex(elementIndex, scrollHorizontally, scrollVertically);
+ scrollToIndex(cellGridView, cellElementIndex, scrollHorizontally, scrollVertically);
}
/**
@@ -3091,7 +3640,19 @@ public class Grid extends Group implemen
*/
public function getVisibleRowIndices():Vector.<int>
{
- return gridLayout.getVisibleRowIndices();
+ const gridLayout:GridLayout = layout as GridLayout;
+ const topGridView:GridView = gridLayout.topGridView;
+ const centerGridView:GridView = gridLayout.centerGridView;
+
+ if (!centerGridView)
+ return new Vector.<int>(0);
+
+ const centerRowIndices:Vector.<int> = centerGridView.gridViewLayout.getVisibleRowIndices();
+ if (!topGridView)
+ return centerRowIndices;
+
+ const topRowIndices:Vector.<int> = topGridView.gridViewLayout.getVisibleRowIndices();
+ return topRowIndices.concat(centerRowIndices);
}
/**
@@ -3120,7 +3681,16 @@ public class Grid extends Group implemen
*/
public function getVisibleColumnIndices():Vector.<int>
{
- return gridLayout.getVisibleColumnIndices();
+ const gridLayout:GridLayout = layout as GridLayout;
+ const leftGridView:GridView = gridLayout.leftGridView;
+ const centerGridView:GridView = gridLayout.centerGridView;
+
+ const centerColumnIndices:Vector.<int> = centerGridView.gridViewLayout.getVisibleColumnIndices();
+ if (!leftGridView)
+ return centerColumnIndices;
+
+ const leftColumnIndices:Vector.<int> = leftGridView.gridViewLayout.getVisibleColumnIndices();
+ return leftColumnIndices.concat(centerColumnIndices);
}
/**
@@ -3144,7 +3714,7 @@ public class Grid extends Group implemen
*/
public function getCellBounds(rowIndex:int, columnIndex:int):Rectangle
{
- return gridLayout.getCellBounds(rowIndex, columnIndex);
+ return gridDimensions.getCellBounds(rowIndex, columnIndex);
}
/**
@@ -3166,7 +3736,7 @@ public class Grid extends Group implemen
*/
public function getRowBounds(rowIndex:int):Rectangle
{
- return gridLayout.getRowBounds(rowIndex);
+ return gridDimensions.getRowBounds(rowIndex);
}
/**
@@ -3187,13 +3757,12 @@ public class Grid extends Group implemen
*/
public function getColumnBounds(columnIndex:int):Rectangle
{
- return gridLayout.getColumnBounds(columnIndex);
+ return gridDimensions.getColumnBounds(columnIndex);
}
/**
- * Returns the row index corresponding to the specified coordinates,
+ * Returns the row index corresponding to the specified grid coordinates,
* or -1 if the coordinates are out of bounds.
- * The coordinates are resolved with respect to the grid.
*
* <p>If all of the columns or rows for the grid have not yet been scrolled
* into view, the returned index may only be an approximation,
@@ -3212,13 +3781,12 @@ public class Grid extends Group implemen
*/
public function getRowIndexAt(x:Number, y:Number):int
{
- return gridLayout.getRowIndexAt(x, y);
+ return gridDimensions.getRowIndexAt(x, y);
}
/**
- * Returns the column index corresponding to the specified coordinates,
- * or -1 if the coordinates are out of bounds. The coordinates are
- * resolved with respect to the grid.
+ * Returns the column index corresponding to the specified grid coordinates,
+ * or -1 if the coordinates are out of bounds.
*
* <p>If all of the columns or rows for the grid have not yet been scrolled
* into view, the returned index may only be an approximation,
@@ -3237,7 +3805,7 @@ public class Grid extends Group implemen
*/
public function getColumnIndexAt(x:Number, y:Number):int
{
- return gridLayout.getColumnIndexAt(x, y);
+ return gridDimensions.getColumnIndexAt(x, y);
}
/**
@@ -3293,7 +3861,11 @@ public class Grid extends Group implemen
*/
public function getCellAt(x:Number, y:Number):CellPosition
{
- return gridLayout.getCellAt(x, y);
+ const rowIndex:int = gridDimensions.getRowIndexAt(x, y);
+ const columnIndex:int = gridDimensions.getColumnIndexAt(x, y);
+ if ((rowIndex == -1) || (columnIndex == -1))
+ return null;
+ return new CellPosition(rowIndex, columnIndex);
}
/**
@@ -3319,7 +3891,28 @@ public class Grid extends Group implemen
*/
public function getCellsAt(x:Number, y:Number, w:Number, h:Number):Vector.<CellPosition>
{
- return gridLayout.getCellsAt(x, y, w, h);
+ var cells:Vector.<CellPosition> = new Vector.<CellPosition>;
+
+ if (w <= 0 || h <= 0)
+ return cells;
+
+ // Get the row/column indexes of the corners of the region.
+ var topLeft:CellPosition = getCellAt(x, y);
+ var bottomRight:CellPosition = getCellAt(x + w, y + h);
+ if (!topLeft || !bottomRight)
+ return cells;
+
+ for (var rowIndex:int = topLeft.rowIndex;
+ rowIndex <= bottomRight.rowIndex; rowIndex++)
+ {
+ for (var columnIndex:int = topLeft.columnIndex;
+ columnIndex <= bottomRight.columnIndex; columnIndex++)
+ {
+ cells.push(new CellPosition(rowIndex, columnIndex));
+ }
+ }
+
+ return cells;
}
/**
@@ -3402,8 +3995,12 @@ public class Grid extends Group implemen
*/
public function getItemRendererAt(rowIndex:int, columnIndex:int):IGridItemRenderer
{
- return gridLayout.getItemRendererAt(rowIndex, columnIndex);
- }
+ const view:GridView = getGridViewAt(rowIndex, columnIndex);
+ if (!view)
+ return null;
+
+ return view.gridViewLayout.getItemRendererAt(rowIndex, columnIndex);
+ }
/**
* Returns <code>true</code> if the specified cell is at least partially visible.
@@ -3427,7 +4024,8 @@ public class Grid extends Group implemen
*/
public function isCellVisible(rowIndex:int = -1, columnIndex:int = -1):Boolean
{
- return gridLayout.isCellVisible(rowIndex, columnIndex);
+ const view:GridView = getGridViewAt(rowIndex, columnIndex);
+ return view && view.gridViewLayout.isCellVisible(rowIndex, columnIndex);
}
//--------------------------------------------------------------------------
@@ -3435,6 +4033,7 @@ public class Grid extends Group implemen
// Tracking Grid invalidateDisplayList() "reasons", invalid cells
//
//--------------------------------------------------------------------------
+
/**
* @private
* Low cost "list" of invalidateDisplayList() reasons.
@@ -3443,6 +4042,16 @@ public class Grid extends Group implemen
/**
* @private
+ * This flag makes it possible to defer clearing the invalidateDisplayListReasonsMask
+ * until after the Grid's subtree has been redisplayed. It's set by updateDisplayList()
+ * and not cleared until the next invalidateDisplayListFor() call, on the assumption
+ * that the Grid subtree's updateDisplayList() methods will not reset any Grid properties
+ * (that call invalidateDisplayListFor()).
+ */
+ private var clearInvalidateDisplayListReasons:Boolean = false;
+
+ /**
+ * @private
* Table that maps from reason names to bit fields.
*/
private static const invalidateDisplayListReasonBits:Object = {
@@ -3452,7 +4061,7 @@ public class Grid extends Group implemen
hoverIndicator: uint(1 << 2),
caretIndicator: uint(1 << 3),
selectionIndicator: uint(1 << 4),
- editorIndicator: uint(1 << 5),
+ editorIndicator: uint(1 << 5),
none: uint(~0)
};
@@ -3462,6 +4071,12 @@ public class Grid extends Group implemen
*/
private function setInvalidateDisplayListReason(reason:String):void
{
+ if (clearInvalidateDisplayListReasons)
+ {
+ invalidateDisplayListReasonsMask = 0;
+ clearInvalidateDisplayListReasons = false;
+ }
+
invalidateDisplayListReasonsMask |= invalidateDisplayListReasonBits[reason];
}
@@ -3476,19 +4091,32 @@ public class Grid extends Group implemen
return (invalidateDisplayListReasonsMask & bit) == bit;
}
+ //--------------------------------------------------------------------------
+ //
+ // Method Overrides
+ //
+ //--------------------------------------------------------------------------
+
/**
* @private
*/
- mx_internal function clearInvalidateDisplayListReasons():void
+ override public function getHorizontalScrollPositionDelta(navigationUnit:uint):Number
{
- invalidateDisplayListReasonsMask = 0;
+ const gridLayout:GridLayout = layout as GridLayout;
+ const centerGridView:GridView = gridLayout.centerGridView;
+ return (centerGridView) ? centerGridView.getHorizontalScrollPositionDelta(navigationUnit) : 0;
}
- //--------------------------------------------------------------------------
- //
- // Method Overrides
- //
- //--------------------------------------------------------------------------
+ /**
+ * @private
+ */
+ override public function getVerticalScrollPositionDelta(navigationUnit:uint):Number
+ {
+ const gridLayout:GridLayout = layout as GridLayout;
+ const centerGridView:GridView = gridLayout.centerGridView;
+ return (centerGridView) ? centerGridView.getVerticalScrollPositionDelta(navigationUnit) : 0;
+ }
+
/**
* @private
@@ -3504,6 +4132,14 @@ public class Grid extends Group implemen
if (!inUpdateDisplayList)
{
super.invalidateSize();
+
+ for each (var view:GridView in allGridViews)
+ {
+ if (!view)
+ continue;
+ view.invalidateSize();
+ }
+
dispatchChangeEvent("invalidateSize");
}
}
@@ -3523,10 +4159,180 @@ public class Grid extends Group implemen
{
setInvalidateDisplayListReason("none");
super.invalidateDisplayList();
- dispatchChangeEvent("invalidateDisplayList");
+
+ for each (var view:GridView in allGridViews)
+ {
+ if (!view)
+ continue;
+ view.invalidateDisplayList();
+ }
+
+ dispatchChangeEvent("invalidateDisplayList");
}
}
+
+ private function get allGridViews():Array
+ {
+ const gridLayout:GridLayout = layout as GridLayout;
+ return gridLayout ? [gridLayout.topLeftGridView, gridLayout.topGridView, gridLayout.leftGridView, gridLayout.centerGridView] : [];
+ }
+
+ private function createGridView():GridView
+ {
+ const elt:GridView = gridView.newInstance() as GridView;
+ addElement(elt);
+ return elt;
+ }
+ private function configureGridView(gv:GridView, viewRowIndex:int, viewColumnIndex:int, viewRowCount:int, viewColumnCount:int):void
+ {
+ const gridViewLayout:GridViewLayout = gv.gridViewLayout;
+ gridViewLayout.grid = this;
+ gridViewLayout.viewRowIndex = viewRowIndex;
+ gridViewLayout.viewColumnIndex = viewColumnIndex;
+ gridViewLayout.viewRowCount = viewRowCount;
+ gridViewLayout.viewColumnCount = viewColumnCount;
+ }
+
+ /**
+ * Create and/or configure this Grid's GridViews. We're assuming that the
+ * Grid's viewFactory, columns and dataProvider are specified.
+ *
+ * If GridVeiws are added or removed, a "gridViewsChanged" event is dispatched.
+ */
+ private function configureGridViews():void
+ {
+ const columnCount:int = columns.length;
+ const rowCount:int = (dataProvider) ? dataProvider.length : 0;
+
+ lockedColumnCount = Math.min(lockedColumnCount, columnCount);
+ lockedRowCount = Math.min(lockedRowCount, rowCount);
+
+ const centerRowCount:int = Math.max(0, rowCount - lockedRowCount);
+ const centerColumnCount:int = Math.max(0, columnCount - lockedColumnCount);
+
+ const gridLayout:GridLayout = layout as GridLayout;
+ var topLeftGridView:GridView = gridLayout.topLeftGridView;
+ var topGridView:GridView = gridLayout.topGridView;
+ var leftGridView:GridView = gridLayout.leftGridView;
+ var centerGridView:GridView = gridLayout.centerGridView;
+ var lockedRowsSeparatorElement:IVisualElement = gridLayout.lockedRowsSeparatorElement;
+ var lockedColumnsSeparatorElement:IVisualElement = gridLayout.lockedColumnsSeparatorElement;
+
+ var gridViewsChanged:Boolean = false;
+
+ // Unconditionally create and configure the "center" GridView
+
+ if (centerGridView == null)
+ {
+ gridLayout.centerGridView = centerGridView = createGridView();
+ gridViewsChanged = true;
+ }
+
+ configureGridView(centerGridView, lockedRowCount, lockedColumnCount, -1, -1);
+
+ centerGridView.gridViewLayout.requestedRowCount = requestedRowCount - lockedRowCount;
+ centerGridView.gridViewLayout.requestedColumnCount = requestedColumnCount - lockedColumnCount;
+
+ // Remove or create/configure the topLeftGridView
+
+ if ((lockedRowCount > 0) && (lockedColumnCount > 0))
+ {
+ if (!topLeftGridView)
+ {
+ gridLayout.topLeftGridView = topLeftGridView = createGridView();
+ topLeftGridView.gridViewLayout.verticalScrollingLocked = true;
+ topLeftGridView.gridViewLayout.horizontalScrollingLocked = true;
+ gridViewsChanged = true;
+ }
+
+ }
+ else if (topLeftGridView)
+ {
+ removeElement(topLeftGridView);
+ gridLayout.topLeftGridView = topLeftGridView = null;
+ gridViewsChanged = true;
+ }
+
+ if (topLeftGridView)
+ configureGridView(topLeftGridView, 0, 0, lockedRowCount, lockedColumnCount);
+
+ // Remove or create/configure the topGridView
+
+ if (lockedRowCount > 0)
+ {
+ if (!topGridView)
+ {
+ gridLayout.topGridView = topGridView = createGridView();
+ topGridView.gridViewLayout.verticalScrollingLocked = true;
+ gridViewsChanged = true;
+ }
+
+ if (lockedRowsSeparator && !lockedRowsSeparatorElement)
+ {
+ gridLayout.lockedRowsSeparatorElement = lockedRowsSeparatorElement = lockedRowsSeparator.newInstance() as IVisualElement;
+ addElement(lockedRowsSeparatorElement);
+ }
+ }
+ else
+ {
+ if (topGridView)
+ {
+ removeElement(topGridView);
+ gridLayout.topGridView = topGridView = null;
+ gridViewsChanged = true;
+ }
+
+ if (lockedRowsSeparatorElement)
+ {
+ removeElement(lockedRowsSeparatorElement);
+ gridLayout.lockedRowsSeparatorElement = lockedRowsSeparatorElement = null;
+ }
+ }
+
+ if (topGridView)
+ configureGridView(topGridView, 0, lockedColumnCount, lockedRowCount, centerColumnCount);
+
+ // Remove or create/configure the leftGridView
+
+ if (lockedColumnCount > 0)
+ {
+ if (!leftGridView)
+ {
+ gridLayout.leftGridView = leftGridView = createGridView();
+ leftGridView.gridViewLayout.horizontalScrollingLocked = true;
+ gridViewsChanged = true;
+ }
+
+ if (lockedColumnsSeparator && !lockedColumnsSeparatorElement)
+ {
+ gridLayout.lockedColumnsSeparatorElement = lockedColumnsSeparatorElement = lockedColumnsSeparator.newInstance() as IVisualElement;
+ addElement(lockedColumnsSeparatorElement);
+ }
+ }
+ else
+ {
+ if (leftGridView)
+ {
+ removeElement(leftGridView);
+ gridLayout.leftGridView = leftGridView = null;
+ gridViewsChanged = true;
+ }
+
+ if (lockedColumnsSeparatorElement)
+ {
+ removeElement(lockedColumnsSeparatorElement);
+ gridLayout.lockedColumnsSeparatorElement = lockedColumnsSeparatorElement = null;
+ }
+ }
+
+ if (leftGridView)
+ configureGridView(leftGridView, lockedRowCount, 0, centerRowCount, lockedColumnCount);
+
+ if (gridViewsChanged)
+ dispatchChangeEvent("gridViewsChanged");
+ }
+
/**
* @private
*/
@@ -3578,6 +4384,7 @@ public class Grid extends Group implemen
if (dataProviderChanged || columnsChanged)
{
+
// Remove the current selection and, if requireSelection, make
// sure the selection is reset to row 0 or cell 0,0.
if (gridSelection)
@@ -3586,8 +4393,8 @@ public class Grid extends Group implemen
gridSelection.requireSelection = false;
gridSelection.removeAll();
gridSelection.requireSelection = savedRequireSelection;
- }
-
+ }
+
// make sure we have the right number of columns.
if (columnsChanged)
gridDimensions.columnCount = _columns ? _columns.length : 0;
@@ -3608,8 +4415,14 @@ public class Grid extends Group implemen
dataProviderChanged = false;
columnsChanged = false;
}
+
anchorChanged = false;
+ // Create or reconfigure the Grid's GridViews
+
+ if (gridView && columns)
+ configureGridViews();
+
// Deferred selection operations
if (dataProvider)
@@ -3619,8 +4432,8 @@ public class Grid extends Group implemen
deferredOperations.length = 0;
}
- // Only want one event if both caretRowIndex and caretColumnIndex
- // changed.
+ // Only want one event if both caretRowIndex and caretColumnIndex changed
+
if (caretChanged)
{
// Validate values now. Need to let caret be set in the same
@@ -3644,6 +4457,7 @@ public class Grid extends Group implemen
}
}
+
/**
* @private
*/
@@ -3653,7 +4467,7 @@ public class Grid extends Group implemen
super.updateDisplayList(unscaledWidth, unscaledHeight);
inUpdateDisplayList = false;
- clearInvalidateDisplayListReasons();
+ clearInvalidateDisplayListReasons = true;
if (!variableRowHeight)
setFixedRowHeight(gridDimensions.getRowHeight(0));
@@ -3686,8 +4500,34 @@ public class Grid extends Group implemen
{
if (!inUpdateDisplayList)
{
- setInvalidateDisplayListReason(reason);
+ setInvalidateDisplayListReason(reason);
super.invalidateDisplayList();
+
+ // Minor optimization: if the reason for this invalidation is a
+ // scroll, don't invalidate GridViews that can't change.
+
+ const vspReason:Boolean = reason == "verticalScrollPosition";
+ const hspReason:Boolean = reason == "horizontalScrollPosition";
+ const bothReason:Boolean = reason == "bothScrollPositions";
+
+ const gridLayout:GridLayout = layout as GridLayout;
+ const topLeftGridView:GridView = gridLayout.topLeftGridView;
+ const topGridView:GridView = gridLayout.topGridView;
+ const leftGridView:GridView = gridLayout.leftGridView;
+ const centerGridView:GridView = gridLayout.centerGridView;
+
+ if (topLeftGridView && !vspReason && !hspReason && !bothReason)
+ topLeftGridView.invalidateDisplayList();
+
+ if (topGridView && !vspReason)
+ topGridView.invalidateDisplayList();
+
+ if (leftGridView && !hspReason)
+ leftGridView.invalidateDisplayList();
+
+ if (centerGridView)
+ centerGridView.invalidateDisplayList();
+
dispatchChangeEvent("invalidateDisplayList");
}
}
@@ -3720,11 +4560,19 @@ public class Grid extends Group implemen
*/
public function invalidateCell(rowIndex:int, columnIndex:int):void
{
- if (!dataProvider)
+ if ((rowIndex == -1) && (columnIndex == -1))
+ {
+ invalidateDisplayList();
+ return;
+ }
+
+ const view:GridView = getGridViewAt(rowIndex, columnIndex);
+ if (!dataProvider || !view)
return;
+ const gridLayout:GridViewLayout = view.gridViewLayout;
const dataProviderLength:int = dataProvider.length;
- if (rowIndex >= dataProvider.length)
+ if (!gridLayout || (rowIndex >= dataProvider.length))
return;
if (!isCellVisible(rowIndex, columnIndex))
@@ -3819,11 +4667,14 @@ public class Grid extends Group implemen
*/
private function getVisibleItemRenderer(rowIndex:int, columnIndex:int):IGridItemRenderer
{
- const layout:GridLayout = layout as GridLayout;
- if (!layout)
- return null;
-
- return layout.getVisibleItemRenderer(rowIndex, columnIndex);
+ const view:GridView = getGridViewAt(rowIndex, columnIndex);
+ if (!view)
+ return null;
+
+ const gridViewLayout:GridViewLayout = view.gridViewLayout;
+ const viewRowIndex:int = rowIndex - gridViewLayout.viewRowIndex;
+ const viewColumnIndex:int = columnIndex - gridViewLayout.viewColumnIndex;
+ return gridViewLayout.getVisibleItemRenderer(viewRowIndex, viewColumnIndex);
}
//--------------------------------------------------------------------------
@@ -3837,9 +4688,71 @@ public class Grid extends Group implemen
private var mouseDownRowIndex:int = -1;
private var mouseDownColumnIndex:int = -1;
private var lastClickTime:Number;
+
// default max time between clicks for a double click is 480ms.
mx_internal var DOUBLE_CLICK_TIME:Number = 480;
+ /**
+ * @private
+ * Return the GridView whose bounds contain the MouseEvent, or null. Note that the
+ * comparison is based strictly on the event's location and the GridViews' bounds.
+ * The event's target can be anything.
+ */
+ private function mouseEventGridView(event:MouseEvent):GridView
+ {
+ const gridLayout:GridLayout = layout as GridLayout;
+
+ const centerGridView:GridView = gridLayout.centerGridView;
+ if (centerGridView && centerGridView.containsMouseEvent(event))
+ return centerGridView;
+
+ const leftGridView:GridView = gridLayout.leftGridView;
+ if (leftGridView && leftGridView.containsMouseEvent(event))
+ return leftGridView;
+
+ const topGridView:GridView = gridLayout.topGridView;
+ if (topGridView && topGridView.containsMouseEvent(event))
+ return topGridView;
+
+ const topLeftGridView:GridView = gridLayout.topLeftGridView;
+ if (topLeftGridView && topLeftGridView.containsMouseEvent(event))
+ return topLeftGridView;
+
+ return null;
+ }
+
+ /**
+ * @private
+ * Return the Grid-relative row,column (gridCP) and X,Y location (gridXY) of the MouseEvent.
+ */
+ private function eventToGridLocations(event:MouseEvent, gridCP:CellPosition, gridXY:Point):void
+ {
+ const stageXY:Point = new Point(event.stageX, event.stageY);
+ const localXY:Point = globalToLocal(stageXY);
+ gridXY.x = localXY.x; // event may not have targeted the Grid
+ gridXY.y = localXY.y;
+
+ const view:GridView = mouseEventGridView(event);
+ if (view)
+ {
+ const viewXY:Point = view.globalToLocal(stageXY);
+ const gridViewLayout:GridViewLayout = view.gridViewLayout;
+ const gdv:GridDimensionsView = gridViewLayout.gridDimensionsView;
+
+
+ gridCP.rowIndex = gdv.getRowIndexAt(viewXY.x, viewXY.y) + gridViewLayout.viewRowIndex;
+ gridCP.columnIndex = gdv.getColumnIndexAt(viewXY.x, viewXY.y) + gridViewLayout.viewColumnIndex;
+
+ gridXY.x = viewXY.x + gdv.viewOriginX;
+ gridXY.y = viewXY.y + gdv.viewOriginY;
+ }
+ else
+ {
+ gridCP.rowIndex = -1;
+ gridCP.columnIndex = -1;
+ }
+ }
+
/**
* @private
* This method is called when a MOUSE_DOWN event occurs within the grid and
@@ -3859,11 +4772,12 @@ public class Grid extends Group implemen
*/
protected function grid_mouseDownDragUpHandler(event:MouseEvent):void
{
- const eventStageXY:Point = new Point(event.stageX, event.stageY);
- const eventGridXY:Point = globalToLocal(eventStageXY);
- const gridDimensions:GridDimensions = this.gridDimensions;
- const eventRowIndex:int = gridDimensions.getRowIndexAt(eventGridXY.x, eventGridXY.y);
- const eventColumnIndex:int = gridDimensions.getColumnIndexAt(eventGridXY.x, eventGridXY.y);
+ const eventGridCP:CellPosition = new CellPosition();
+ const eventGridXY:Point = new Point();
+ eventToGridLocations(event, eventGridCP, eventGridXY);
+
+ const eventRowIndex:int = eventGridCP.rowIndex;
+ const eventColumnIndex:int = eventGridCP.columnIndex;
var gridEventType:String;
switch(event.type)
@@ -3890,7 +4804,7 @@ public class Grid extends Group implemen
dispatchGridEvent(event, gridEventType, eventGridXY, eventRowIndex, eventColumnIndex);
if (gridEventType == GridEvent.GRID_MOUSE_UP)
- dispatchGridClickEvents(event, eventGridXY, eventRowIndex, eventColumnIndex);
+ dispatchGridClickEvents(event, eventGridXY, eventRowIndex, eventColumnIndex);
}
/**
@@ -3910,12 +4824,13 @@ public class Grid extends Group implemen
*/
protected function grid_mouseMoveHandler(event:MouseEvent):void
{
- const eventStageXY:Point = new Point(event.stageX, event.stageY);
- const eventGridXY:Point = globalToLocal(eventStageXY);
- const gridDimensions:GridDimensions = this.gridDimensions;
- const eventRowIndex:int = gridDimensions.getRowIndexAt(eventGridXY.x, eventGridXY.y);
- const eventColumnIndex:int = gridDimensions.getColumnIndexAt(eventGridXY.x, eventGridXY.y);
-
+ const eventGridCP:CellPosition = new CellPosition();
+ const eventGridXY:Point = new Point();
+ eventToGridLocations(event, eventGridCP, eventGridXY);
+
+ const eventRowIndex:int = eventGridCP.rowIndex;
+ const eventColumnIndex:int = eventGridCP.columnIndex;
+
if ((eventRowIndex != rollRowIndex) || (eventColumnIndex != rollColumnIndex))
{
if ((rollRowIndex != -1) || (rollColumnIndex != -1))
@@ -3944,7 +4859,8 @@ public class Grid extends Group implemen
if ((rollRowIndex != -1) || (rollColumnIndex != -1))
{
const eventStageXY:Point = new Point(event.stageX, event.stageY);
- const eventGridXY:Point = globalToLocal(eventStageXY);
+ const eventGridXY:Point = globalToLocal(eventStageXY);
+
dispatchGridEvent(event, GridEvent.GRID_ROLL_OUT, eventGridXY, rollRowIndex, rollColumnIndex);
rollRowIndex = -1;
rollColumnIndex = -1;
@@ -3965,19 +4881,19 @@ public class Grid extends Group implemen
*/
protected function grid_mouseUpHandler(event:MouseEvent):void
{
- // If in a drag, the drag handler already dispatched a mouse up
- // event so don't do it again here.
if (dragInProgress)
{
+ // drag handler has already dispatched a mouse up event, don't do so again here
dragInProgress = false;
return;
}
- const eventStageXY:Point = new Point(event.stageX, event.stageY);
- const eventGridXY:Point = globalToLocal(eventStageXY);
- const gridDimensions:GridDimensions = this.gridDimensions;
- const eventRowIndex:int = gridDimensions.getRowIndexAt(eventGridXY.x, eventGridXY.y);
- const eventColumnIndex:int = gridDimensions.getColumnIndexAt(eventGridXY.x, eventGridXY.y);
+ const eventGridCP:CellPosition = new CellPosition();
+ const eventGridXY:Point = new Point();
+ eventToGridLocations(event, eventGridCP, eventGridXY);
+
+ const eventRowIndex:int = eventGridCP.rowIndex;
+ const eventColumnIndex:int = eventGridCP.columnIndex;
dispatchGridEvent(event, GridEvent.GRID_MOUSE_UP, eventGridXY, eventRowIndex, eventColumnIndex);
dispatchGridClickEvents(event, eventGridXY, eventRowIndex, eventColumnIndex);
@@ -3997,9 +4913,8 @@ public class Grid extends Group implemen
*/
private function dispatchGridClickEvents(mouseEvent:MouseEvent, gridXY:Point, rowIndex:int, columnIndex:int):void
{
- var dispatchGridClick:Boolean = (rowIndex == mouseDownRowIndex &&
- columnIndex == mouseDownColumnIndex);
- var newClickTime:Number = getTimer();
+ const dispatchGridClick:Boolean = ((rowIndex == mouseDownRowIndex) && (columnIndex == mouseDownColumnIndex));
+ const newClickTime:Number = getTimer();
// In the case that we dispatched a click last time, check if we
// should dispatch a double click this time.
@@ -4288,6 +5203,8 @@ public class Grid extends Group implemen
*/
private function dataProvider_collectionChangeHandler(event:CollectionEvent):void
{
+ var selectionChanged:Boolean = false;
+
// If no columns exist, we should try to generate them.
if (!columns && dataProvider.length > 0)
{
@@ -4303,11 +5220,15 @@ public class Grid extends Group implemen
gridDimensions.rowCount = dataProvider.length;
}
- if (gridLayout)
- gridLayout.dataProviderCollectionChanged(event);
+ for each (var view:GridView in allGridViews)
+ {
+ if (!view)
+ continue;
+ view.gridViewLayout.dataProviderCollectionChanged(event);
+ }
if (gridSelection)
- gridSelection.dataProviderCollectionChanged(event);
+ selectionChanged = gridSelection.dataProviderCollectionChanged(event);
if (gridDimensions && hoverRowIndex != -1)
updateHoverForDataProviderChange(event);
@@ -4319,7 +5240,10 @@ public class Grid extends Group implemen
if (caretRowIndex != -1)
updateCaretForDataProviderChange(event);
-
+
+ // Trigger bindings to selectedIndex/selectedCell/selectedItem and the plurals of those.
+ if (selectionChanged)
+ dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
}
/**
@@ -4330,6 +5254,7 @@ public class Grid extends Group implemen
var column:GridColumn;
var columnIndex:int = event.location;
var i:int;
+ var selectionChanged:Boolean = false;
switch (event.kind)
{
@@ -4436,11 +5361,16 @@ public class Grid extends Group implemen
if (gridDimensions)
gridDimensions.columnsCollectionChanged(event);
- if (gridLayout)
- gridLayout.columnsCollectionChanged(event);
+ for each (var view:GridView in allGridViews)
+ {
+ if (!view)
+ continue;
+ view.gridViewLayout.columnsCollectionChanged(event);
+ }
+
if (gridSelection)
- gridSelection.columnsCollectionChanged(event);
+ selectionChanged = gridSelection.columnsCollectionChanged(event);
if (caretColumnIndex != -1)
updateCaretForColumnsChange(event);
@@ -4449,7 +5379,12 @@ public class Grid extends Group implemen
updateHoverForColumnsChange(event);
invalidateSize();
- invalidateDisplayList();
+ invalidateDisplayList();
+
+ // Trigger bindings to selectedCell/selectedItem and the plurals of those.
+ if (selectionChanged)
+ dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
+
}
//--------------------------------------------------------------------------
@@ -4465,14 +5400,22 @@ public class Grid extends Group implemen
*/
mx_internal function clearGridLayoutCache(clearTypicalSizes:Boolean):void
{
- gridLayout.clearVirtualLayoutCache();
-
+ for each (var view:GridView in allGridViews)
+ {
+ if (!view)
+ continue;
+ view.gridViewLayout.clearVirtualLayoutCache();
+ }
+
const gridDimensions:GridDimensions = this.gridDimensions;
if (gridDimensions)
{
if (clearTypicalSizes)
+ {
gridDimensions.clearTypicalCellWidthsAndHeights();
-
+ gridDimensions.clearColumns(0, gridDimensions.columnCount);
+ }
+
gridDimensions.clearHeights();
// Reset row count because dataProvider length may have changed.