Wednesday, February 22, 2012

Spark Spreadsheet Datagrid, locked columns

I was recently tasked with providing spreadsheet like functionality in a Flex 4 application where you can lock columns on the left side of the grid to keep them in view while scrolling as well as allowing single cell editing while highlighting entire rows on mouse overs.  This is somewhat the same as you would expect in an Excel spreadsheet.  Anyway, I was able to put his together really quick to satisfy our needs based on a blog I came across giving me the idea to put 2 grids side by side. Here's a link LockedGrid.
Anyway, I needed a lot more functionality so I expanded on this idea and created a custom component.  It's pretty rough and not everything is wired in yet but you can feel free to use it and call me on any hiccups.  I put this together really quickly but wanted to share.


	[SkinState("lockedMode")]
	[SkinState("nonLockedMode")]

	[Event(name = "gridDoubleClick", type = "spark.events.GridEvent")]
	[Event(name = "gridClick", type = "spark.events.GridEvent")]
	[Event(name = "gridItemEditorSessionStarting", type = "spark.events.GridItemEditorEvent")]
	[Event(name = "gridItemEditorSessionStart", type = "spark.events.GridItemEditorEvent")]
	[Event(name = "gridItemEditorSessionSave", type = "spark.events.GridItemEditorEvent")]
	[Event(name = "gridItemEditorSessionCancel", type = "spark.events.GridItemEditorEvent")]
	[Event(name = "selectionChange", type = "spark.events.GridSelectionEvent")]


	public class SparkLockedColumnGrid extends SkinnableComponent
	{
		public static const LOCKEDMODE:String = "lockedMode";
		public static const NONLOCKEDMODE:String = "nonLockedMode";
		private static const MIN_ROWHEIGHT:Number = 30;

		[SkinPart(required = "true")]
		public var lockedGrid:DataGrid;

		[SkinPart(required = "true")]
		public var dataGrid:DataGrid;

		private var _columnsChanged:Boolean;
		private var _gridsLocked:Boolean;
		private var _dataProviderChanged:Boolean;
		private var _selectionModeChanged:Boolean;
		private var lockedCols:ArrayList = new ArrayList();
		private var gridCols:ArrayList = new ArrayList();
		private var _rowHeightChanged:Boolean;
		private var _selectedCellsChanged:Boolean;
		private var _selectedItemChanged:Boolean;
		private var _selectedIndexChanged:Boolean;
		private var _selectedItemsChanged:Boolean;
		private var _selectedIndicesChanged:Boolean;
		private var _selectedCellChanged:Boolean;
		private var _doubleClickEnabledChanged:Boolean;
		private var _spreadsheetModeChanged:Boolean;
		private var _lockedGridSelectionMode:String;
		private var selectedChildDatagrid:DataGrid;
		private var _editableChanged:Boolean;
		private var freezeGrid:Boolean;

		//----------------------------------
		//  selectedItem
		//----------------------------------
		private var _selectedItem:Object;

		public function get selectedItem():Object
		{
			return _selectedItem;
		}

		public function set selectedItem(value:Object):void
		{
			_selectedItem = value;
			_selectedItemChanged = true;
			invalidateProperties();
		}

		//----------------------------------
		//  selectedIndex
		//----------------------------------
		private var _selectedIndex:int;

		public function get selectedIndex():int
		{
			return _selectedIndex;
		}

		public function set selectedIndex(value:int):void
		{
			_selectedIndex = value;
			_selectedIndexChanged = true;
			invalidateProperties();
		}

		//----------------------------------
		//  selectedItems
		//----------------------------------
		private var _selectedItems:Vector.(Object);

		public function get selectedItems():Vector.(Object){
			return _selectedItems;
		}

		public function set selectedItems(value:Vector.(Object)):void
		{
			_selectedItems = value;
			_selectedItemsChanged = true;
			invalidateProperties();
		}


		//----------------------------------
		//  selectedIndices
		//----------------------------------
		private var _selectedIndices:Vector.(int);

		public function get selectedIndices():Vector.(int)
		{
			return _selectedIndices;
		}

		public function set selectedIndices(value:Vector.(int)):void
		{
			_selectedIndices = value;
			_selectedIndicesChanged = true;
			invalidateProperties();
		}


		//----------------------------------
		//  selectedCell
		//----------------------------------
		private var _selectedCell:CellPosition;

		public function get selectedCell():CellPosition
		{
			return _selectedCell;
		}

		public function set selectedCell(value:CellPosition):void
		{
			_selectedCell = value;
			_selectedCellChanged = true;
			invalidateProperties();
		}


		//----------------------------------
		//  selectedCells
		//----------------------------------
		private var _selectedCells:Vector.(cellposition);

		public function get selectedCells():Vector.(cellposition)
		{
			return _selectedCells;
		}

		public function set selectedCells(value:Vector.(cellposition)):void
		{
			_selectedCells = value;
			_selectedCellsChanged = true;
			invalidateProperties();
		}

		//----------------------------------
		//  Editable
		//----------------------------------
		private var _editable:Boolean;

		public function get editable():Boolean
		{
			return _editable;
		}

		/**
		 *  @private
		 */
		public function set editable(value:Boolean):void
		{
			if (_editable != value)
			{
				_editable = value;
				_editableChanged = true;
				invalidateProperties();
			}
		}

		/**
		 *  SPREADSHEET MODE
		 * this feature will change the selection mode on mouseover of the
		 * two grids to select a row on the locked grid and cell mode on the regular
		 * grid. On double click of a locked row will change to cell mode and an edit mode.
		 *
		**/
		private var _spreadsheetMode:Boolean;

		public function get spreadsheetMode():Boolean
		{
			return _spreadsheetMode;
		}

		public function set spreadsheetMode(value:Boolean):void
		{
			_spreadsheetMode = value;
			_spreadsheetModeChanged = true;
			invalidateProperties();
		}

		//----------------------------------
		//  Columns
		//----------------------------------
		private var _columns:IList;

		public function get columns():IList
		{
			return _columns;
		}

		/**
		 *  @private
		 */
		public function set columns(value:IList):void
		{
			if (_columns != value)
			{
				_columns = value;
				_columnsChanged = true;
				invalidateProperties();
			}
		}

		//----------------------------------
		//  dataProvider
		//----------------------------------

		//----------------------------------
		//  dataProvider
		//----------------------------------

		private var _dataProvider:IList;

		[Bindable("dataProviderChanged")]
		[Inspectable(category = "Data")]
		public function get dataProvider():IList
		{
			return _dataProvider;
		}

		/**
		 *  @private
		 */
		public function set dataProvider(value:IList):void
		{
			if (_dataProvider != value)
			{
				if (_dataProvider && _dataProvider.hasEventListener(CollectionEvent.COLLECTION_CHANGE))
					_dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, updateDataProvider);

				_dataProvider = value;

				dispatchChangeEvent("dataProviderChanged");
				_dataProviderChanged = true;
				invalidateDisplayList();
				invalidateProperties();

				if (dataProvider)
					_dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, updateDataProvider, false, 0, true);
			}
		}

		private function updateDataProvider(event:CollectionEvent):void
		{
			_dataProviderChanged = true;
			invalidateDisplayList();
		}

		//----------------------------------
		//  selectionMode
		//----------------------------------

		private var _selectionMode:String;

		public function get selectionMode():String
		{
			return _selectionMode;
		}

		public function set selectionMode(value:String):void
		{
			_selectionMode = value;
			_selectionModeChanged = true;
			invalidateProperties();
		}

		//----------------------------------
		//  Row Height
		//----------------------------------
		private var _rowHeight:Number = 20;

		public function get rowHeight():Number
		{
			return _rowHeight;
		}

		public function set rowHeight(value:Number):void
		{
			_rowHeight = value;
			_rowHeightChanged = true;
			invalidateProperties();
		}

		//----------------------------------
		//  doubleClickEnabled
		//----------------------------------

		override public function set doubleClickEnabled(value:Boolean):void
		{
			super.doubleClickEnabled = value;

			_doubleClickEnabledChanged = true;
			invalidateProperties();
		}


		//----------------------------------
		//  commitProperties
		//----------------------------------

		override protected function commitProperties():void
		{
			if (dataGrid && _columnsChanged)
			{
				updateGridColumns();
				_columnsChanged = false;
			}

			if (_dataProviderChanged)
			{
				if (lockedGrid)
					lockedGrid.dataProvider = dataProvider;

				if (dataGrid)
					dataGrid.dataProvider = dataProvider;

				_gridsLocked = false;
				_dataProviderChanged = false;
			}

			if (_rowHeightChanged)
			{
				if (isNaN(rowHeight))
				{
					_rowHeight = MIN_ROWHEIGHT;
				}

				if (lockedGrid)
				{
					lockedGrid.rowHeight = _rowHeight;
				}

				if (dataGrid)
				{
					dataGrid.rowHeight = _rowHeight;
				}

				_rowHeightChanged = false;
			}

			if (dataGrid && lockedGrid && !_gridsLocked)
			{
				if (selectedChildDatagrid == dataGrid)
				{
					lockedGrid.grid.hoverRowIndex = dataGrid.grid.hoverRowIndex;
				}
				else
				{
					dataGrid.grid.hoverRowIndex = lockedGrid.grid.hoverRowIndex;
				}

				_gridsLocked = true;
			}

			if (_selectedCellsChanged)
			{

				if (dataGrid == selectedChildDatagrid)
				{
					dataGrid.selectedCells = selectedCells;

					if (lockedGrid)
						lockedGrid.selectedCells = null;
				}
				else if (lockedGrid == selectedChildDatagrid)
				{
					lockedGrid.selectedCells = selectedCells;

					if (dataGrid)
						dataGrid.selectedCells = null;
				}

				_selectedCellsChanged = false;
			}

			if (_selectedItemChanged)
			{
				if (lockedGrid)
					lockedGrid.selectedItem = selectedItem;

				if (dataGrid)
					dataGrid.selectedItem = selectedItem;

				_selectedItemChanged = false;
			}

			if (_selectedIndexChanged)
			{
				if (lockedGrid)
					lockedGrid.selectedIndex = selectedIndex;

				if (dataGrid)
					dataGrid.selectedIndex = selectedIndex;

				_selectedIndexChanged = false;
			}

			if (_selectedItemsChanged)
			{
				if (lockedGrid)
					lockedGrid.selectedItems = selectedItems;

				if (dataGrid)
					dataGrid.selectedItems = selectedItems;

				_selectedItemsChanged = false;
			}

			if (_selectedIndicesChanged)
			{
				if (lockedGrid)
					lockedGrid.selectedIndices = selectedIndices;

				if (dataGrid)
					dataGrid.selectedIndices = selectedIndices;

				_selectedIndicesChanged = false;
			}

			if (_selectedCellChanged)
			{
				if (dataGrid == selectedChildDatagrid)
				{
					dataGrid.selectedCell = selectedCell;

					if (lockedGrid)
						lockedGrid.selectedCell = null;
				}
				else if (lockedGrid == selectedChildDatagrid)
				{
					lockedGrid.selectedCell = selectedCell;

					if (dataGrid)
						if (spreadsheetMode)
						{
							dataGrid.selectedIndex = selectedCell.rowIndex;
						}
						else
						{
							dataGrid.selectedCell = null;
						}
				}
				_selectedCellChanged = false;
			}

			if (_doubleClickEnabledChanged)
			{
				if (lockedGrid)
					lockedGrid.doubleClickEnabled = doubleClickEnabled;

				if (dataGrid)
					dataGrid.doubleClickEnabled = doubleClickEnabled;

				_doubleClickEnabledChanged = false;
			}

			if (_editableChanged)
			{
				if (lockedGrid)
					lockedGrid.editable = editable;

				if (dataGrid)
					dataGrid.editable = editable;

				_editableChanged = false;
			}

			if (_spreadsheetModeChanged)
			{
				if (lockedGrid)
				{
					if (spreadsheetMode)
					{
						lockedGrid.editable = true;
					}
					else
					{
						lockedGrid.editable = editable;
					}
				}

				if (dataGrid)
				{
					if (spreadsheetMode)
					{
						dataGrid.editable = true;
					}
					else
					{
						dataGrid.editable = editable;
					}
				}
			}

			super.commitProperties();

		}

		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);

			if (_selectionModeChanged)
			{
				if (lockedGrid)
				{
					if (selectionMode == GridSelectionMode.SINGLE_CELL || selectionMode == GridSelectionMode.MULTIPLE_CELLS)
					{
						_lockedGridSelectionMode = lockedGrid.selectionMode = GridSelectionMode.NONE;
					}
					else
					{
						_lockedGridSelectionMode = lockedGrid.selectionMode = selectionMode;
					}
				}

				if (dataGrid)
				{
					dataGrid.selectionMode = selectionMode;
				}
			}

		}

		private function updateGridColumns():void
		{
			if (!columns)
				return;

			lockedCols = new ArrayList();
			gridCols = new ArrayList();

			for (var x:int = 0; x < columns.length; x++)
			{
				if (columns.getItemAt(x) is LockedGridColumn && (columns.getItemAt(x) as LockedGridColumn).lockColumn)
				{
					lockedCols.addItem(columns.getItemAt(x));
				}
				else
				{
					gridCols.addItem(columns.getItemAt(x));
				}
			}

			lockedGrid.columns = lockedCols;
			dataGrid.columns = gridCols;

			invalidateSkinState();
		}

		override protected function getCurrentSkinState():String
		{
			var returnState:String = NONLOCKEDMODE;

			// Use information in the class to determine the new view state of the skin class. 
			if (lockedCols.length > 0)
			{
				returnState = LOCKEDMODE;
			}

			return returnState;
		}

		override protected function partAdded(partName:String, instance:Object):void
		{
			super.partAdded(partName, instance);

			if (instance == lockedGrid)
			{
				lockedGrid.addEventListener(GridEvent.GRID_ROLL_OVER, lockedGridRollOverEvent, false, 0, true);
				lockedGrid.addEventListener(GridEvent.GRID_ROLL_OUT, lockedGridRollOutEvent, false, 0, true);
				lockedGrid.addEventListener(GridSelectionEvent.SELECTION_CHANGE, lockedGridSelectEvent, false, 0, true);
				lockedGrid.addEventListener(GridEvent.GRID_DOUBLE_CLICK, dataGrid_itemDoubleClickHandler, false, 0, true);
				lockedGrid.addEventListener(GridEvent.GRID_CLICK, dataGrid_itemClickHandler, false, 0, true);
				lockedGrid.addEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE, gridItemEditorSaveHandler, false, 0, true);
				lockedGrid.addEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_START, gridItemEditorStartHandler, false, 0, true);
				lockedGrid.addEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_CANCEL, gridItemEditorCancelHandler, false, 0, true);
				lockedGrid.setStyle("horizontalScrollPolicy", "off");
				lockedGrid.setStyle("verticalScrollPolicy", "off");
				_gridsLocked = false;
				lockedGrid.hasFocusableChildren = false;
				lockedGrid.rowHeight = MIN_ROWHEIGHT;
				lockedGrid.columns = new ArrayList();
				lockedGrid.sortableColumns = false;
			}
			else if (instance == dataGrid)
			{
				dataGrid.addEventListener(GridEvent.GRID_ROLL_OVER, gridRollOverEvent, false, 0, true);
				dataGrid.addEventListener(GridEvent.GRID_ROLL_OUT, gridRollOutEvent, false, 0, true);
				dataGrid.addEventListener(GridSelectionEvent.SELECTION_CHANGE, gridSelectEvent, false, 0, true);
				dataGrid.scroller.verticalScrollBar.addEventListener(Event.CHANGE, verticalScrollChange, false, 0, true);
				dataGrid.addEventListener(GridEvent.GRID_DOUBLE_CLICK, dataGrid_itemDoubleClickHandler, false, 0, true);
				dataGrid.addEventListener(GridEvent.GRID_CLICK, dataGrid_itemClickHandler, false, 0, true);
				dataGrid.scroller.verticalScrollBar.addEventListener(ResizeEvent.RESIZE, onAddHandler, false, 0, true);
				dataGrid.scroller.horizontalScrollBar.addEventListener(ResizeEvent.RESIZE, onAddHandler, false, 0, true);
				dataGrid.addEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_START, gridItemEditorStartHandler, false, 0, true);
				dataGrid.addEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE, gridItemEditorSaveHandler, false, 0, true);
				dataGrid.addEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_CANCEL, gridItemEditorCancelHandler, false, 0, true);
				_gridsLocked = false;
				setNonLockedGridAsSelected();
				dataGrid.hasFocusableChildren = false;
				dataGrid.rowHeight = MIN_ROWHEIGHT;
				dataGrid.columns = new ArrayList();
				dataGrid.sortableColumns = false;
			}
		}

		override protected function partRemoved(partName:String, instance:Object):void
		{
			super.partRemoved(partName, instance);

			if (instance == lockedGrid)
			{
				lockedGrid.removeEventListener(GridEvent.GRID_ROLL_OVER, lockedGridRollOverEvent);
				lockedGrid.removeEventListener(GridEvent.GRID_ROLL_OUT, lockedGridRollOutEvent);
				lockedGrid.removeEventListener(GridSelectionEvent.SELECTION_CHANGE, lockedGridSelectEvent);
				lockedGrid.removeEventListener(GridEvent.GRID_DOUBLE_CLICK, dataGrid_itemDoubleClickHandler);
				lockedGrid.removeEventListener(GridEvent.GRID_CLICK, dataGrid_itemClickHandler);
				lockedGrid.removeEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE, gridItemEditorSaveHandler);
				lockedGrid.removeEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_START, gridItemEditorStartHandler);
			}
			else if (instance == dataGrid)
			{
				dataGrid.removeEventListener(GridEvent.GRID_ROLL_OVER, gridRollOverEvent);
				dataGrid.removeEventListener(GridEvent.GRID_ROLL_OUT, gridRollOutEvent);
				dataGrid.removeEventListener(GridSelectionEvent.SELECTION_CHANGE, gridSelectEvent);
				dataGrid.scroller.verticalScrollBar.removeEventListener(Event.CHANGE, verticalScrollChange);
				dataGrid.scroller.verticalScrollBar.removeEventListener(ResizeEvent.RESIZE, onAddHandler);
				dataGrid.scroller.horizontalScrollBar.removeEventListener(ResizeEvent.RESIZE, onAddHandler);
				dataGrid.removeEventListener(GridEvent.GRID_DOUBLE_CLICK, dataGrid_itemDoubleClickHandler);
				dataGrid.removeEventListener(GridEvent.GRID_CLICK, dataGrid_itemClickHandler);
				dataGrid.removeEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE, gridItemEditorSaveHandler);
				dataGrid.removeEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_START, gridItemEditorStartHandler);
			}
		}


		private function updateDatagridSpreadsheetSelectionMode():void
		{
			if (spreadsheetMode)
			{
				if (lockedGrid)
					lockedGrid.selectionMode = GridSelectionMode.NONE;

				if (dataGrid)
					dataGrid.selectionMode = GridSelectionMode.SINGLE_CELL;

				dispatchEvent(new GridSelectionEvent(GridSelectionEvent.SELECTION_CHANGE));
			}
			else
			{
				if (lockedGrid)
					lockedGrid.selectionMode = _lockedGridSelectionMode;

				if (dataGrid)
					dataGrid.selectionMode = selectionMode;
			}
		}

		private function updateLockedgridSpreadsheetSelectionMode():void
		{
			if (spreadsheetMode)
			{
				if (lockedGrid)
					lockedGrid.selectionMode = GridSelectionMode.SINGLE_CELL;

				if (dataGrid)
					dataGrid.selectionMode = GridSelectionMode.SINGLE_ROW;

				dispatchEvent(new GridSelectionEvent(GridSelectionEvent.SELECTION_CHANGE));
			}
			else
			{
				if (lockedGrid)
					lockedGrid.selectionMode = _lockedGridSelectionMode;

				if (dataGrid)
					dataGrid.selectionMode = selectionMode;
			}
		}

		//Scrolls the locked datagrid when the scrollable datagrid scrolls vertically
		private function verticalScrollChange(evt:Event):void
		{
			dataGrid.validateNow();
			lockedGrid.grid.verticalScrollPosition = dataGrid.grid.verticalScrollPosition;
		}

		private function gridRollOutEvent(event:GridEvent):void
		{
			if (dataGrid.editorRowIndex != -1 || dataGrid.editorColumnIndex != -1)
				dataGrid.dispatchEvent(new GridItemEditorEvent(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE));

			dataGrid.grid.hoverRowIndex = -1;

		}

		private function gridRollOverEvent(event:GridEvent):void
		{
			if (freezeGrid)
				return;

			updateDatagridSpreadsheetSelectionMode();
			lockedGrid.validateNow();
			setNonLockedGridAsSelected();
			_gridsLocked = false;
			invalidateProperties();
		}

		private function lockedGridRollOutEvent(event:GridEvent):void
		{
			if (lockedGrid.editorRowIndex != -1 || lockedGrid.editorColumnIndex != -1)
				lockedGrid.dispatchEvent(new GridItemEditorEvent(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE));

			lockedGrid.grid.hoverRowIndex = -1;
		}

		private function lockedGridRollOverEvent(event:GridEvent):void
		{
			if (freezeGrid)
				return;

			updateLockedgridSpreadsheetSelectionMode();
			dataGrid.validateNow();
			setLockedGridAsSelected();
			_gridsLocked = false;
			invalidateProperties();
		}

		protected function dataGrid_itemDoubleClickHandler(event:GridEvent):void
		{
			if ((event.currentTarget as DataGrid).selectionMode == GridSelectionMode.NONE)
			{
				event.stopPropagation();
			}
			else if ((event.currentTarget as DataGrid).selectionMode == GridSelectionMode.SINGLE_CELL && (event.currentTarget as DataGrid).editable)
			{
				(event.currentTarget as DataGrid).startItemEditorSession(event.rowIndex, event.columnIndex);
			}
		}

		protected function dataGrid_itemClickHandler(event:GridEvent):void
		{
			if ((event.currentTarget as DataGrid).selectionMode == GridSelectionMode.NONE)
			{
				event.stopPropagation();
			}
		}

		protected function lockedGridSelectEvent(event:GridSelectionEvent):void
		{
			event.stopPropagation();

			if (!lockedGrid)
			{
				return;
			}

			if (lockedGrid.selectionMode == GridSelectionMode.MULTIPLE_CELLS || lockedGrid.selectionMode == GridSelectionMode.SINGLE_CELL || spreadsheetMode)
			{
				setLockedGridAsSelected();
				selectedCell = (event.currentTarget as DataGrid).selectedCell;
				selectedCells = (event.currentTarget as DataGrid).selectedCells;

				if (dataGrid)
				{
					dataGrid.selectedCell = null;
					dataGrid.selectedCells = null;
				}
			}
			else
			{
				selectedItem = lockedGrid.selectedItem = (event.currentTarget as DataGrid).selectedItem;
				selectedIndex = lockedGrid.selectedIndex = (event.currentTarget as DataGrid).selectedIndex;
				selectedItems = lockedGrid.selectedItems = (event.currentTarget as DataGrid).selectedItems;
				selectedIndices = lockedGrid.selectedIndices = (event.currentTarget as DataGrid).selectedIndices;
			}

			var e:GridSelectionEvent = event.clone() as GridSelectionEvent;
			dispatchEvent(e);
		}

		protected function gridSelectEvent(event:GridSelectionEvent):void
		{
			event.stopPropagation();

			if (!dataGrid)
			{
				return;
			}

			if (dataGrid.selectionMode == GridSelectionMode.MULTIPLE_CELLS || dataGrid.selectionMode == GridSelectionMode.SINGLE_CELL || spreadsheetMode)
			{
				setNonLockedGridAsSelected();
				selectedCell = (event.currentTarget as DataGrid).selectedCell;
				selectedCells = (event.currentTarget as DataGrid).selectedCells;

				if (lockedGrid)
				{
					lockedGrid.selectedCell = null;
					lockedGrid.selectedCells = null;
				}
			}
			else
			{
				selectedItem = dataGrid.selectedItem = (event.currentTarget as DataGrid).selectedItem;
				selectedIndex = dataGrid.selectedIndex = (event.currentTarget as DataGrid).selectedIndex;
				selectedItems = dataGrid.selectedItems = (event.currentTarget as DataGrid).selectedItems;
				selectedIndices = dataGrid.selectedIndices = (event.currentTarget as DataGrid).selectedIndices;
			}

			var e:GridSelectionEvent = event.clone() as GridSelectionEvent;
			dispatchEvent(e);
		}

		private function gridItemEditorStartHandler(event:GridItemEditorEvent):void
		{
			freezeGrid = true;
			event.stopPropagation();

			var e:GridItemEditorEvent = event.clone() as GridItemEditorEvent;
			dispatchEvent(e);
		}

		private function gridItemEditorSaveHandler(event:GridItemEditorEvent):void
		{
			freezeGrid = false;
			event.stopPropagation();

			var e:GridItemEditorEvent = event.clone() as GridItemEditorEvent;
			dispatchEvent(e);
		}

		protected function gridItemEditorCancelHandler(event:GridItemEditorEvent):void
		{
			freezeGrid = false;
			event.stopPropagation();

			var e:GridItemEditorEvent = event.clone() as GridItemEditorEvent;
			dispatchEvent(e);
		}

		private function onAddHandler(event:ResizeEvent):void
		{
			if (lockedGrid)
			{
				if (dataGrid && dataGrid.scroller.horizontalScrollBar.visible)
				{
					lockedGrid.height = dataGrid.height - dataGrid.scroller.horizontalScrollBar.height;
				}
				else
				{
					lockedGrid.height = dataGrid.height;
				}

				lockedGrid.invalidateSize();
				lockedGrid.invalidateProperties();
				invalidateSize();
				invalidateProperties();
				invalidateDisplayList();
			}
		}

		public function SparkLockedColumnGrid()
		{
			this.addEventListener(MouseEvent.ROLL_OUT, handleComponentMouseOut);
		}

		private function handleComponentMouseOut(event:MouseEvent):void
		{
			if (event.currentTarget != lockedGrid && event.currentTarget != dataGrid)
			{
				if (lockedGrid)
				{
					lockedGrid.grid.hoverRowIndex = -1;
					lockedGrid.invalidateProperties();
					lockedGrid.invalidateDisplayList();
				}

				if (dataGrid)
				{
					dataGrid.grid.hoverRowIndex = -1;
					dataGrid.invalidateProperties();
					dataGrid.invalidateDisplayList();
				}
			}
		}

		public function setLockedGridAsSelected():void
		{
			selectedChildDatagrid = lockedGrid;
		}

		public function setNonLockedGridAsSelected():void
		{
			selectedChildDatagrid = dataGrid;
		}

		public function selectedGridIsLocked():Boolean
		{
			return selectedChildDatagrid == lockedGrid ? true : false;
		}

		public function startItemEditorSession(rowIndex:int, columnIndex:int):Boolean
		{
			var ret:Boolean;

			if (selectedGridIsLocked())
			{
				ret = lockedGrid.startItemEditorSession(rowIndex, columnIndex);
				lockedGrid.validateNow();
				dataGrid.grid.verticalScrollPosition = lockedGrid.grid.verticalScrollPosition;
			}
			else
			{
				ret = dataGrid.startItemEditorSession(rowIndex, columnIndex);
				dataGrid.validateNow();
				lockedGrid.grid.verticalScrollPosition = dataGrid.grid.verticalScrollPosition;
			}

			return ret;
		}

		//----------------------------------
		//  dataProviderLength
		//---------------------------------- 
		public function get dataProviderLength():int
		{
			const dataProvider:IList = dataProvider;
			return (dataProvider) ? dataProvider.length : 0;
		}

		private function dispatchChangeEvent(type:String):void
		{
			if (hasEventListener(type))
				dispatchEvent(new Event(type));
		}
	}

And an example skin:





	
		[HostComponent("components.datagrid.SparkLockedColumnGrid")]
	

	
		
		
		
		
	

	
		
			
			
		
	
	
	
		
		
	


No comments:

Post a Comment