// Copyright 2007. Adobe Systems Incorporated. All Rights Reserved. package fl.controls { import fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn; import fl.controls.dataGridClasses.HeaderRenderer; import fl.controls.listClasses.CellRenderer; import fl.controls.listClasses.ICellRenderer; import fl.controls.listClasses.ListData; import fl.controls.ScrollPolicy; import fl.controls.SelectableList; import fl.controls.TextInput; import fl.core.UIComponent; import fl.core.InvalidationType; import fl.data.DataProvider; import fl.events.ScrollEvent; import fl.events.ListEvent; import fl.events.student_ar_fl_controls_DataGridEvent; import fl.events.student_ar_fl_controls_DataGridEventReason; import fl.events.DataChangeType; import fl.events.DataChangeEvent; import fl.managers.IFocusManager; import fl.managers.IFocusManagerComponent; import flash.display.Sprite; import flash.display.Graphics; import flash.display.InteractiveObject; import flash.display.DisplayObjectContainer import flash.events.MouseEvent; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.FocusEvent; import flash.ui.Keyboard; import flash.ui.Mouse; import flash.display.DisplayObject; import flash.utils.Dictionary; import flash.utils.describeType; import flash.geom.Point; import flash.system.IME; /** * Dispatched after the user clicks a header cell. * * @includeExample examples/student_ar_fl_controls_DataGrid.headerRelease.1.as -noswf * * @eventType fl.events.student_ar_fl_controls_DataGridEvent.HEADER_RELEASE * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="headerRelease", type="fl.events.student_ar_fl_controls_DataGridEvent")] /** * Dispatched after a user expands a column horizontally. * * @includeExample examples/student_ar_fl_controls_DataGrid.columnStretch.1.as -noswf * * @eventType fl.events.student_ar_fl_controls_DataGridEvent.COLUMN_STRETCH * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="columnStretch", type="fl.events.student_ar_fl_controls_DataGridEvent")] /** * Dispatched after a user prepares to edit an item, for example, * by releasing the mouse button over the item. * * @eventType fl.events.student_ar_fl_controls_DataGridEvent.ITEM_EDIT_BEGINNING * * @see #event:itemEditBegin * @see #event:itemEditEnd * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="itemEditBeginning", type="fl.events.student_ar_fl_controls_DataGridEvent")] /** * Dispatched after the editedItemPosition property is set * and the item can be edited. * * @eventType fl.events.student_ar_fl_controls_DataGridEvent.ITEM_EDIT_BEGIN * * @see #event:itemEditBeginning * @see #event:itemEditEnd * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="itemEditBegin", type="fl.events.student_ar_fl_controls_DataGridEvent")] /** * Dispatched when an item editing session ends for any reason. * * @eventType fl.events.student_ar_fl_controls_DataGridEvent.ITEM_EDIT_END * * @see #event:itemEditBegin * @see #event:itemEditBeginning * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="itemEditEnd", type="fl.events.student_ar_fl_controls_DataGridEvent")] /** * Dispatched after an item receives focus. * * @eventType fl.events.student_ar_fl_controls_DataGridEvent.ITEM_FOCUS_IN * * @see #event:itemFocusOut * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="itemFocusIn", type="fl.events.student_ar_fl_controls_DataGridEvent")] /** * Dispatched after an item loses focus. * * @eventType fl.events.student_ar_fl_controls_DataGridEvent.ITEM_FOCUS_OUT * * @see #event:itemFocusIn * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="itemFocusOut", type="fl.events.student_ar_fl_controls_DataGridEvent")] //-------------------------------------- // Styles //-------------------------------------- /** * The name of the class that provides the cursor that is used when * the mouse is between two column headers and the resizableColumns * property is set to true. * * @default student_ar_fl_controls_DataGrid_columnStretchCursorSkin * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="columnStretchCursorSkin", type="Class")] /** * The name of the class that provides the divider that appears * between columns. * * @default student_ar_fl_controls_DataGrid_columnDividerSkin * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="columnDividerSkin", type="Class")] /** * The name of the class that provides the background for each column header. * * @default HeaderRenderer_upSkin * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerUpSkin", type="Class")] /** * The name of the class that provides the background for each column header * when the mouse is over it. * * @default HeaderRenderer_overSkin * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerOverSkin", type="Class")] /** * The name of the class that provides the background for each column header * when the mouse is down. * * @default HeaderRenderer_downSkin * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerDownSkin", type="Class")] /** * The name of the class that provides the background for each column header * when the component is disabled. * * @default HeaderRenderer_disabledSkin * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerDisabledSkin", type="Class")] /** * The name of the class that provides the sort arrow when the sorted * column is in descending order. * * @default HeaderSortArrow_descIcon * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerSortArrowDescSkin", type="Class")] /** * The name of the class that provides the sort arrow when the sorted * column is in ascending order. * * @default HeaderSortArrow_ascIcon * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerSortArrowAscSkin", type="Class")] /** * The format to be applied to the text contained in each column header. * * @default null * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerTextFormat", type="flash.text.TextFormat")] /** * The format to be applied to the text contained in each column header * when the component is disabled. * * @default null * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerDisabledTextFormat", type="flash.text.TextFormat")] /** * The padding that separates the column header border from the column header * text, in pixels. * * @default 5 * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerTextPadding", type="Number", format="Length")] /** * The name of the class that provides each column header. * * @default fl.controls.dataGridClasses.HeaderRenderer * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Style(name="headerRenderer", type="Class")] [InspectableList("allowMultipleSelection","editable","headerHeight","horizontalLineScrollSize","horizontalPageScrollSize","horizontalScrollPolicy","resizableColumns","rowHeight","showHeaders","sortableColumns","verticalLineScrollSize","verticalPageScrollSize","verticalScrollPolicy")] //-------------------------------------- // Class description //-------------------------------------- /** * The student_ar_fl_controls_DataGrid class is a list-based component that provides a grid of * rows and columns. You can specify an optional header row at the top * of the component that shows all the property names. Each row consists * of one or more columns, each of which represents a property that belongs * to the specified data object. The student_ar_fl_controls_DataGrid component is used to view data; * it is not intended to be used as a layout tool like an HTML table. * *

A student_ar_fl_controls_DataGrid component is well suited for the display of objects that contain * multiple properties. The data that a student_ar_fl_controls_DataGrid component displays can * be contained in a DataProvider object or as an array of objects. The columns of a student_ar_fl_controls_DataGrid * component can be represented by a list of student_ar_fl_controls_DataGridColumn objects, * each of which contains information that is specific to the column.

* *

The student_ar_fl_controls_DataGrid component provides the following features:

* * *

The student_ar_fl_controls_DataGrid component is composed of subcomponents including ScrollBar, * HeaderRenderer, CellRenderer, student_ar_fl_controls_DataGridCellEditor, and ColumnDivider components, all of which * can be skinned during authoring or at run time.

* *

The student_ar_fl_controls_DataGrid component uses the following classes that can be found in the dataGridClasses package:

* * * @includeExample examples/student_ar_fl_controls_DataGridExample.as * * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridCellEditor student_ar_fl_controls_DataGridCellEditor * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn student_ar_fl_controls_DataGridColumn * @see fl.controls.dataGridClasses.HeaderRenderer HeaderRenderer * @see fl.controls.listClasses.CellRenderer CellRenderer * @see fl.events.student_ar_fl_controls_DataGridEvent student_ar_fl_controls_DataGridEvent * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public class student_ar_fl_controls_DataGrid extends SelectableList implements IFocusManagerComponent { /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _rowHeight:Number = 20; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _headerHeight:Number = 25; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _showHeaders:Boolean = true; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _columns:Array; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _minColumnWidth:Number; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var header:Sprite; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var headerMask:Sprite; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var headerSortArrow:Sprite; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _cellRenderer:Object; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _headerRenderer:Object; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _labelFunction:Function; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var visibleColumns:Array; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var displayableColumns:Array; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var columnsInvalid:Boolean = true; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var minColumnWidthInvalid:Boolean = false; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var activeCellRenderersMap:Dictionary; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var availableCellRenderersMap:Dictionary; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var dragHandlesMap:Dictionary; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var columnStretchIndex:Number = -1; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var columnStretchStartX:Number; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var columnStretchStartWidth:Number; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var columnStretchCursor:Sprite; /** * @private (protected) * The index of the column being sorted. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _sortIndex:int = -1; /** * @private (protected) * The index of the last column being sorted on. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var lastSortIndex:int = -1; /** * @private (protected) * The direction of the current sort. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _sortDescending:Boolean = false; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var _editedItemPosition:Object; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var editedItemPositionChanged:Boolean = false; /** * @private (protected) * undefined means we've processed it, null means don't put up an editor * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var proposedEditedItemPosition:*; /** * @private (protected) * Last known position of item editor instance * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var actualRowIndex:int; /** * @private (protected) * Last known position of item editor instance * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var actualColIndex:int; /** * @private (protected) * Whether the mouse button is pressed. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var isPressed:Boolean = false; /** * @private (protected) * True if we want to block editing on mouseUp. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var losingFocus:Boolean = false; /** * @private (protected) * Stores the user set headerheight (we modify header height when dg is resized down) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var maxHeaderHeight:Number = 25; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected var currentHoveredRow:int = -1; /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ private static var defaultStyles:Object = { headerUpSkin: "HeaderRenderer_upSkin", headerDownSkin: "HeaderRenderer_downSkin", headerOverSkin: "HeaderRenderer_overSkin", headerDisabledSkin: "HeaderRenderer_disabledSkin", headerSortArrowDescSkin:"HeaderSortArrow_descIcon", headerSortArrowAscSkin:"HeaderSortArrow_ascIcon", columnStretchCursorSkin:"ColumnStretch_cursor", columnDividerSkin:null, headerTextFormat:null, headerDisabledTextFormat:null, headerTextPadding:5, headerRenderer:HeaderRenderer, focusRectSkin:null, focusRectPadding:null, skin:"student_ar_fl_controls_DataGrid_skin" }; /** * @copy fl.core.UIComponent#getStyleDefinition() * * @includeExample ../core/examples/UIComponent.getStyleDefinition.1.as -noswf * * @see fl.core.UIComponent#getStyle() UIComponent.getStyle() * @see fl.core.UIComponent#setStyle() UIComponent.setStyle() * @see fl.managers.StyleManager StyleManager * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public static function getStyleDefinition():Object { return mergeStyles(defaultStyles, SelectableList.getStyleDefinition(), ScrollBar.getStyleDefinition()); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected static const HEADER_STYLES:Object = { disabledSkin:"headerDisabledSkin", downSkin:"headerDownSkin", overSkin:"headerOverSkin", upSkin:"headerUpSkin", textFormat: "headerTextFormat", disabledTextFormat: "headerDisabledTextFormat", textPadding: "headerTextPadding" }; /** * @private * Creates the Accessibility class. * This method is called from UIComponent. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public static var createAccessibilityImplementation:Function; /** * Creates a new student_ar_fl_controls_DataGrid component instance. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function student_ar_fl_controls_DataGrid() { super(); if (_columns == null) { _columns = []; } _horizontalScrollPolicy = ScrollPolicy.OFF; activeCellRenderersMap = new Dictionary(true); availableCellRenderersMap = new Dictionary(true); addEventListener(student_ar_fl_controls_DataGridEvent.ITEM_EDIT_BEGINNING, itemEditorItemEditBeginningHandler, false, -50); addEventListener(student_ar_fl_controls_DataGridEvent.ITEM_EDIT_BEGIN, itemEditorItemEditBeginHandler, false, -50); addEventListener(student_ar_fl_controls_DataGridEvent.ITEM_EDIT_END, itemEditorItemEditEndHandler, false, -50); addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override public function set dataProvider(dataSource:DataProvider):void { super.dataProvider = dataSource; // if not already created, create columns from dataprovider if (_columns == null) { _columns = []; } if (_columns.length == 0) { createColumnsFromDataProvider(); } // remove all existing cellrenderers removeCellRenderers(); } [Inspectable(defaultValue=true, verbose=1)] /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override public function set enabled(value:Boolean):void { super.enabled = value; header.mouseChildren = _enabled; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override public function setSize(w:Number, h:Number):void { super.setSize(w, h); columnsInvalid = true; } [Inspectable(defaultValue="off",enumeration="on,off,auto")] /** * Gets or sets a Boolean value that indicates whether the * horizontal scroll bar is always on. The following list describes * the valid values: * * * *

Note: If the combined width of the visible columns in the student_ar_fl_controls_DataGrid * component is smaller than the available width of the student_ar_fl_controls_DataGrid component, the columns may not expand to fill * the available space of the student_ar_fl_controls_DataGrid component, depending on the value of the * horizontalScrollPolicy property. The following list describes * these values and their effects:

* * * * @default ScrollPolicy.OFF * * @see fl.containers.BaseScrollPane#verticalScrollPolicy BaseScrollPane.verticalScrollPolicy * @see ScrollPolicy * * @includeExample examples/student_ar_fl_controls_DataGrid.horizontalScrollPolicy.1.as -noswf * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override public function get horizontalScrollPolicy():String { return _horizontalScrollPolicy; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override public function set horizontalScrollPolicy(policy:String):void { super.horizontalScrollPolicy = policy; columnsInvalid = true; } /** * Gets or sets an array of student_ar_fl_controls_DataGridColumn objects, one for each column that can be displayed. * If not explicitly set, the student_ar_fl_controls_DataGrid component examines the first item in the * data provider, locates its properties, and then displays those properties * in alphabetic order. * *

You can make changes to the columns and to their order in this student_ar_fl_controls_DataGridColumn * array. After the changes are made, however, you must explicitly assign the * changed array to the columns property. If an explicit assignment * is not made, the set of columns that was used before will continue to be used.

* * @default [] * * @includeExample examples/student_ar_fl_controls_DataGrid.columns.1.as -noswf * @includeExample examples/student_ar_fl_controls_DataGrid.columns.2.as -noswf * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get columns():Array { return _columns.slice(0); } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set columns(value:Array):void { // remove all existing cellrenderers removeCellRenderers(); // add columns _columns = []; for (var i:uint = 0; i < value.length; i++) { addColumn(value[i]); } } /** * Gets or sets the minimum width of a student_ar_fl_controls_DataGrid column, in pixels. * If this value is set to NaN, the minimum column * width can be individually set for each column of the student_ar_fl_controls_DataGrid component. * * @default NaN * * @includeExample examples/student_ar_fl_controls_DataGrid.minColumnWidth.1.as -noswf * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get minColumnWidth():Number { return _minColumnWidth; } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set minColumnWidth(value:Number):void { _minColumnWidth = value; columnsInvalid = true; minColumnWidthInvalid = true; invalidate(InvalidationType.SIZE); } /** * Gets or sets a function that determines which fields of each * item to use for the label text. * * @default null * * @includeExample examples/student_ar_fl_controls_DataGrid.labelFunction.1.as -noswf * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get labelFunction():Function { return _labelFunction; } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set labelFunction(value:Function):void { if (_labelFunction == value) { return; } _labelFunction = value; invalidate(InvalidationType.DATA); } /** * Gets or sets the number of rows that are at least partially visible in the * list. * * @includeExample examples/student_ar_fl_controls_DataGrid.rowCount.1.as -noswf * * @see SelectableList#length SelectableList.length * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override public function get rowCount():uint { // This is low right now (ie. doesn't count two half items as a whole): return Math.ceil(calculateAvailableHeight() / rowHeight); } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set rowCount(value:uint):void { var pad:Number = Number(getStyleValue("contentPadding")); var scrollBarHeight:Number = (_horizontalScrollPolicy == ScrollPolicy.ON || (_horizontalScrollPolicy == ScrollPolicy.AUTO && hScrollBar)) ? 15 : 0; height = rowHeight * value + 2 * pad + scrollBarHeight + (showHeaders ? headerHeight : 0); } [Inspectable(defaultValue=20)] /** * Gets or sets the height of each row in the student_ar_fl_controls_DataGrid component, in pixels. * * @default 20 * * @includeExample examples/student_ar_fl_controls_DataGrid.rowHeight.1.as -noswf * * @see #headerHeight * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get rowHeight():Number { return _rowHeight; } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set rowHeight(value:Number):void { _rowHeight = Math.max(0, value); invalidate(InvalidationType.SIZE); } [Inspectable(defaultValue=25)] /** * Gets or sets the height of the student_ar_fl_controls_DataGrid header, in pixels. * * @default 25 * * @includeExample examples/student_ar_fl_controls_DataGrid.headerHeight.1.as -noswf * * @see #rowHeight * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get headerHeight():Number { return _headerHeight; } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set headerHeight(value:Number):void { maxHeaderHeight = value; _headerHeight = Math.max(0, value); invalidate(InvalidationType.SIZE); } [Inspectable(defaultValue=true)] /** * Gets or sets a Boolean value that indicates whether the student_ar_fl_controls_DataGrid component shows column headers. * A value of true indicates that the student_ar_fl_controls_DataGrid component shows column headers; a value * of false indicates that it does not. * * @default true * * @includeExample examples/student_ar_fl_controls_DataGrid.showHeaders.1.as -noswf * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get showHeaders():Boolean { return _showHeaders; } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set showHeaders(value:Boolean):void { _showHeaders = value; invalidate(InvalidationType.SIZE); } /** * Gets the index of the column to be sorted. * * @default -1 * * @see #sortDescending * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get sortIndex():int { return _sortIndex; } /** * Gets the order in which a column is sorted when * the user clicks its header. A value of true * indicates that the column is sorted in descending order; a * value of false indicates that the column is * sorted in ascending order. * *

The sortDescending property does not affect * how the sort method completes the sort operation. By default, * the sort operation involves a case-sensitive string sort. * To change this behavior, modify the sortOptions * and sortCompareFunction properties of the student_ar_fl_controls_DataGridColumn * class.

* *

Note: If you query this property from an event * listener for the headerRelease event, the property value * identifies the sort order for the previous sort operation. This * is because the next sort has not yet occurred.

* * * * @default false * * @includeExample examples/student_ar_fl_controls_DataGrid.sortDescending.1.as -noswf * * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn#sortOptions student_ar_fl_controls_DataGridColumn.sortOptions * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn#sortCompareFunction student_ar_fl_controls_DataGridColumn.sortCompareFunction * @see Array#sort() Array.sort() * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get sortDescending():Boolean { return _sortDescending; } /** * @copy fl.controls.TextArea#imeMode * * @see flash.system.IMEConversionMode IMEConversionMode * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get imeMode():String { return _imeMode; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set imeMode(value:String):void { _imeMode = value; } [Inspectable(defaultValue=false)] /** * Indicates whether or not the user can edit items in the data provider. * A value of true indicates that the user can edit items in the * data provider; a value of false indicates that the user cannot. * *

If this value is true, the item renderers in the component * are editable. The user can click on an item renderer to open an editor.

* *

You can turn off editing for individual columns of the student_ar_fl_controls_DataGrid component * by using the student_ar_fl_controls_DataGridColumn.editable property, or by handling * the itemEditBeginning and itemEditBegin events.

* * @default false * * @see #event:itemEditBegin * @see #event:itemEditBeginning * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn#editable student_ar_fl_controls_DataGridColumn.editable * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public var editable:Boolean = false; [Inspectable(defaultValue=true)] /** * Indicates whether the user can change the size of the * columns. A value of true indicates that the user can * change the column size; a value of false indicates that * column size is fixed. * *

If this value is true, the user can stretch or shrink * the columns of the student_ar_fl_controls_DataGrid component by dragging the grid lines between * the header cells. Additionally, if this value is true, * the user can change the size of the columns unless the resizeable * properties of individual columns are set to false.

* * @default true * * @includeExample examples/student_ar_fl_controls_DataGrid.resizableColumns.1.as -noswf * * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn#resizable student_ar_fl_controls_DataGridColumn.resizable * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public var resizableColumns:Boolean = true; [Inspectable(defaultValue=true)] /** * Indicates whether the user can sort the items in the data provider * by clicking on a column header cell. If this value is true, * the user can sort the data provider items by clicking on a column header cell; * if this value is false, the user cannot. * *

If this value is true, to prevent an individual column * from responding to a user mouse click on a header cell, set the * sortable property of that column to false.

* *

The sort field of a column is either the dataField or * sortCompareFunction property of the student_ar_fl_controls_DataGridColumn component. * If the user clicks a column more than one time, the sort operation * alternates between ascending and descending order.

* *

If both this property and the sortable property of a * column are set to true, the student_ar_fl_controls_DataGrid component dispatches * a headerRelease event after the user releases the mouse * button of the column header cell. If a call is not made to the preventDefault() * method from a handler method of the headerRelease event, * the student_ar_fl_controls_DataGrid component performs a sort based on the values of the dataField * or sortCompareFunction properties.

* * @default true * * @includeExample examples/student_ar_fl_controls_DataGrid.sortableColumns.1.as -noswf * * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn#sortable student_ar_fl_controls_DataGridColumn.sortable * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public var sortableColumns:Boolean = true; /** * A reference to the currently active instance of the item editor, * if one exists. * *

To access the item editor instance and the new item value when an * item is being edited, use the itemEditorInstance * property. The itemEditorInstance property is not valid * until after the event listener for the itemEditBegin * event executes. For this reason, the itemEditorInstance property * is typically accessed from the event listener for the itemEditEnd * event.

* *

The student_ar_fl_controls_DataGridColumn.itemEditor property defines the * class of the item editor, and therefore, the data type of the * item editor instance.

* * @includeExample examples/student_ar_fl_controls_DataGrid.itemEditorInstance.1.as -noswf * * @see #event:itemEditBegin * @see #event:itemEditEnd * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn#itemEditor student_ar_fl_controls_DataGridColumn.itemEditor * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public var itemEditorInstance:Object; /** * Gets a reference to the item renderer in the student_ar_fl_controls_DataGrid component whose item is currently being * edited. If no item is being edited, this property contains a value of null. * *

You can obtain the current value of the item that is being edited by using the * editedItemRenderer.data property from an event listener for the * itemEditBegin event or the itemEditEnd event.

* *

This is a read-only property. To set a custom item editor, use the itemEditor * property of the class that represents the relevant column.

* * @see fl.controls.dataGridClasses.student_ar_fl_controls_DataGridColumn#itemEditor student_ar_fl_controls_DataGridColumn.itemEditor * * @includeExample examples/student_ar_fl_controls_DataGrid.editedItemPosition.1.as -noswf * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get editedItemRenderer():ICellRenderer { if (!itemEditorInstance) { return null; } return getCellRendererAt(actualRowIndex, actualColIndex); } /** * Gets or sets the column and row index of the item renderer for * the data provider item that is being edited. If no item is being * edited, this property is null. * *

This object has two fields:

* * * *

For example: { columnIndex:2, rowIndex:3 }

* *

Setting this property scrolls the item into view and dispatches the * itemEditBegin event to open an item editor on the specified * item renderer.

* * @default null * * @includeExample examples/student_ar_fl_controls_DataGrid.editedItemPosition.1.as -noswf * * @see #event:itemEditBegin * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function get editedItemPosition():Object { if (_editedItemPosition) { return { rowIndex: _editedItemPosition.rowIndex, columnIndex: _editedItemPosition.columnIndex }; } else { return _editedItemPosition; } } /** * @private (setter) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function set editedItemPosition(value:Object):void { var newValue:Object = { rowIndex: value.rowIndex, columnIndex: value.columnIndex }; setEditedItemPosition(newValue); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function calculateAvailableHeight():Number { var pad:Number = Number(getStyleValue("contentPadding")); var scrollBarHeight:Number = (_horizontalScrollPolicy == ScrollPolicy.ON || (_horizontalScrollPolicy == ScrollPolicy.AUTO && _maxHorizontalScrollPosition > 0)) ? 15 : 0; return height - pad * 2 - scrollBarHeight - (showHeaders ? headerHeight : 0); } /** * Adds a column to the end of the columns array. * * @param column A String or a student_ar_fl_controls_DataGridColumn object. * * @return The student_ar_fl_controls_DataGridColumn object that was added. * * @see #addColumnAt() * * @includeExample examples/student_ar_fl_controls_DataGrid.addColumn.2.as -noswf * @includeExample examples/student_ar_fl_controls_DataGrid.addColumn.3.as -noswf * @includeExample examples/student_ar_fl_controls_DataGrid.addColumn.1.as -noswf * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function addColumn(column:*):student_ar_fl_controls_DataGridColumn { return addColumnAt(column, _columns.length); } /** * Inserts a column at the specified index in the columns array. * * @param column The string or student_ar_fl_controls_DataGridColumn object that represents the column to be inserted. * @param index The array index that identifies the location at which the column is to be inserted. * * @return The student_ar_fl_controls_DataGridColumn object that was inserted into the array of columns. * * @see #addColumn() * * @includeExample examples/student_ar_fl_controls_DataGrid.addColumn.1.as -noswf * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function addColumnAt(column:*, index:uint):student_ar_fl_controls_DataGridColumn { var dataGridColumn:student_ar_fl_controls_DataGridColumn; if (index < _columns.length) { // insert placeholder for new column _columns.splice(index, 0, ""); // adjust colNums for(var i:uint = index + 1; i < _columns.length; i++) { dataGridColumn = _columns[i] as student_ar_fl_controls_DataGridColumn; dataGridColumn.colNum = i; } } var col:* = column; if(!(col is student_ar_fl_controls_DataGridColumn)) { if (col is String) { col = new student_ar_fl_controls_DataGridColumn(col); } else { col = new student_ar_fl_controls_DataGridColumn(); } } dataGridColumn = col as student_ar_fl_controls_DataGridColumn; dataGridColumn.owner = this; dataGridColumn.colNum = index; _columns[index] = dataGridColumn; invalidate(InvalidationType.SIZE); columnsInvalid = true; return dataGridColumn; } /** * Removes the column that is located at the specified index of the columns array. * * @param index The index of the column to be removed. * * @return The student_ar_fl_controls_DataGridColumn object that was removed. This method returns null * if a column is not found at the specified index. * * @see #removeAllColumns() * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function removeColumnAt(index:uint):student_ar_fl_controls_DataGridColumn { var col:student_ar_fl_controls_DataGridColumn = _columns[index] as student_ar_fl_controls_DataGridColumn; if(col != null) { removeCellRenderersByColumn(col); _columns.splice(index, 1); for(var i:uint = index; i < _columns.length; i++) { col = _columns[i] as student_ar_fl_controls_DataGridColumn; if(col) { col.colNum = i; } } invalidate(InvalidationType.SIZE); columnsInvalid = true; } return col; } /** * Removes all columns from the student_ar_fl_controls_DataGrid component. * * @see #removeColumnAt() * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function removeAllColumns():void { if(_columns.length > 0) { removeCellRenderers(); _columns = []; invalidate(InvalidationType.SIZE); columnsInvalid = true; } } /** * Retrieves the column that is located at the specified index of the columns array. * * @param index The index of the column to be retrieved, or null * if a column is not found. * * @return The student_ar_fl_controls_DataGridColumn object that was found at the specified index. * * @see #getColumnIndex() * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function getColumnAt(index:uint):student_ar_fl_controls_DataGridColumn { return _columns[index] as student_ar_fl_controls_DataGridColumn; } /** * Retrieves the index of the column of the specified name, * or -1 if no match is found. * * @param name The data field of the column to be located. * * @return The index of the location at which the column of the * specified name is found. * * @see #getColumnAt() * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function getColumnIndex(name:String):int { for (var i:uint = 0; i < _columns.length; i++) { var column:student_ar_fl_controls_DataGridColumn = _columns[i] as student_ar_fl_controls_DataGridColumn; if(column.dataField == name) { return i; } } return -1; } /** * Retrieves the number of columns in the student_ar_fl_controls_DataGrid component. * * @return The number of columns contained in the student_ar_fl_controls_DataGrid component. * * @includeExample examples/student_ar_fl_controls_DataGrid.columns.2.as -noswf * @includeExample examples/student_ar_fl_controls_DataGrid.columns.3.as -noswf * * @see #rowCount * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function getColumnCount():uint { return _columns.length; } /** * Resets the widths of the visible columns to the same size. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function spaceColumnsEqually():void { drawNow(); // Force a redraw in case this is called before validation. if(displayableColumns.length > 0) { var newWidth:Number = availableWidth / displayableColumns.length; for (var i:int = 0; i < displayableColumns.length; i++) { var displayableColumn:student_ar_fl_controls_DataGridColumn = displayableColumns[i] as student_ar_fl_controls_DataGridColumn; displayableColumn.width = newWidth; } invalidate(InvalidationType.SIZE); columnsInvalid = true; } } /** * Edits a given field or property in the student_ar_fl_controls_DataGrid component. * * @param index The index of the data provider item to be edited. * * @param dataField The name of the field or property in the data provider item to be edited. * * @param data The new data value. * * @throws RangeError The specified index is less than 0 or greater than or equal to the * length of the data provider. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function editField(index:uint, dataField:String, data:Object):void { var item:Object = getItemAt(index); item[dataField] = data; replaceItemAt(item, index); } /** * The student_ar_fl_controls_DataGrid component has multiple cells for any given item, so the itemToCellRenderer * method always returns null. * * @param item The item in the data provider. * * @return null. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override public function itemToCellRenderer(item:Object):ICellRenderer { return null; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function configUI():void { useFixedHorizontalScrolling = false; super.configUI(); headerMask = new Sprite(); var g:Graphics = headerMask.graphics; g.beginFill(0, 0.3); g.drawRect(0, 0, 100, 100); g.endFill(); headerMask.visible = false; addChild(headerMask); header = new Sprite(); addChild(header); header.mask = headerMask; _horizontalScrollPolicy = ScrollPolicy.OFF; _verticalScrollPolicy = ScrollPolicy.AUTO; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function draw():void { var contentHeightChanged:Boolean = (contentHeight != rowHeight * length); contentHeight = rowHeight * length; if (isInvalid(InvalidationType.STYLES)) { setStyles(); drawBackground(); // drawLayout is expensive, so only do it if padding has changed: if (contentPadding != getStyleValue("contentPadding")) { invalidate(InvalidationType.SIZE, false); } // redrawing all the cell renderers is even more expensive, so we really only want to do it if necessary: if (_cellRenderer != getStyleValue("cellRenderer") || _headerRenderer != getStyleValue("headerRenderer")) { // remove all the existing renderers: _invalidateList(); _cellRenderer = getStyleValue("cellRenderer"); _headerRenderer = getStyleValue("headerRenderer"); } } if (isInvalid(InvalidationType.SIZE)) { columnsInvalid = true; } if (isInvalid(InvalidationType.SIZE, InvalidationType.STATE) || contentHeightChanged) { drawLayout(); drawDisabledOverlay(); } if (isInvalid(InvalidationType.RENDERER_STYLES)) { updateRendererStyles(); } if (isInvalid(InvalidationType.STYLES,InvalidationType.SIZE,InvalidationType.DATA,InvalidationType.SCROLL,InvalidationType.SELECTED)) { drawList(); } updateChildren(); // not calling super.draw, because we're handling everything here. Instead we'll just call validate(); validate(); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function drawLayout():void { vOffset = showHeaders ? headerHeight : 0; super.drawLayout(); // if header is present, adjust masks contentScrollRect = listHolder.scrollRect; if(showHeaders) { headerHeight = maxHeaderHeight; if(Math.floor(availableHeight - headerHeight) <= 0) { _headerHeight = availableHeight; } list.y = headerHeight; // adjust the content mask to take header into account contentScrollRect = listHolder.scrollRect; contentScrollRect.y = contentPadding + headerHeight; contentScrollRect.height = availableHeight-headerHeight; listHolder.y = contentPadding + headerHeight; // position and size the header mask headerMask.x = contentPadding; headerMask.y = contentPadding; headerMask.width = availableWidth; headerMask.height = headerHeight; } else { contentScrollRect.y = contentPadding; listHolder.y = 0; } listHolder.scrollRect = contentScrollRect } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function drawList():void { if(showHeaders) { header.visible = true; header.x = contentPadding - _horizontalScrollPosition; header.y = contentPadding; listHolder.y = contentPadding + headerHeight; // adjust vertical scroller parameters to take header into account var availHeight:Number = Math.floor(availableHeight - headerHeight); _verticalScrollBar.setScrollProperties(availHeight, 0, contentHeight - availHeight, _verticalScrollBar.pageScrollSize); } else { header.visible = false; listHolder.y = contentPadding; } listHolder.x = contentPadding; contentScrollRect = listHolder.scrollRect; contentScrollRect.x = _horizontalScrollPosition; contentScrollRect.y = vOffset + Math.floor(_verticalScrollPosition) % rowHeight; listHolder.scrollRect = contentScrollRect; listHolder.cacheAsBitmap = useBitmapScrolling; // figure out which rows we have to render: var rowStartIndex:uint = Math.min(Math.max(length - 1, 0), Math.floor(_verticalScrollPosition / rowHeight)); var rowEndIndex:uint = Math.min(Math.max(length - 1, 0), rowStartIndex + rowCount + 1); var x:Number; var lastColWidth:Number; var i:uint; var item:Object; var renderer:ICellRenderer; var activeRenderers:Array; var col:student_ar_fl_controls_DataGridColumn; var listHovered:Boolean = list.hitTestPoint(stage.mouseX, stage.mouseY); calculateColumnSizes(); // create a dictionary for looking up the new "displayed" items: var itemHash:Dictionary = renderedItems = new Dictionary(true); if(length > 0) { for (i = rowStartIndex; i <= rowEndIndex; i++) { itemHash[_dataProvider.getItemAt(i)] = true; } } // calculate x coordinate of first visible column x = 0; var firstVisibleColumn:student_ar_fl_controls_DataGridColumn = visibleColumns[0] as student_ar_fl_controls_DataGridColumn; for(i = 0; i < displayableColumns.length; i++) { var displayableColumn:student_ar_fl_controls_DataGridColumn = displayableColumns[i] as student_ar_fl_controls_DataGridColumn; if(displayableColumn != firstVisibleColumn) { x += displayableColumn.width; } else { break; } } while(header.numChildren > 0) { header.removeChildAt(0); } dragHandlesMap = new Dictionary(true); var rendererSprite:Sprite; var rendererUIC:UIComponent; var visibleColumnsIndices:Array = []; var visibleColumnsLen:uint = visibleColumns.length; for (var ci:uint = 0; ci < visibleColumnsLen; ci++) { col = visibleColumns[ci] as student_ar_fl_controls_DataGridColumn; visibleColumnsIndices.push(col.colNum); if(showHeaders) { var headerRendererSkin:Object = (col.headerRenderer != null) ? col.headerRenderer : _headerRenderer; var headerRenderer:HeaderRenderer = getDisplayObjectInstance(headerRendererSkin) as HeaderRenderer; if (headerRenderer != null) { headerRenderer.addEventListener(MouseEvent.CLICK, handleHeaderRendererClick, false, 0, true); headerRenderer.x = x; headerRenderer.y = 0; headerRenderer.setSize(col.width, headerHeight); headerRenderer.column = col.colNum; headerRenderer.label = col.headerText; header.addChildAt(headerRenderer, ci); // set styles copyStylesToChild(headerRenderer, HEADER_STYLES); // set sort arrow if((sortIndex == -1 && lastSortIndex == -1) || (col.colNum != sortIndex)) { headerRenderer.setStyle("icon", null); } else { headerRenderer.setStyle("icon", sortDescending ? getStyleValue("headerSortArrowAscSkin") : getStyleValue("headerSortArrowDescSkin")); } // add resize drag handles if(ci < visibleColumnsLen - 1 && resizableColumns && col.resizable) { var dragHandle:Sprite = new Sprite(); var g:Graphics = dragHandle.graphics; g.beginFill(0, 0); g.drawRect(0, 0, 3, headerHeight); g.endFill(); dragHandle.x = x + col.width - 2; dragHandle.y = 0; dragHandle.alpha = 0; dragHandle.addEventListener(MouseEvent.MOUSE_OVER, handleHeaderResizeOver, false, 0, true); dragHandle.addEventListener(MouseEvent.MOUSE_OUT, handleHeaderResizeOut, false, 0, true); dragHandle.addEventListener(MouseEvent.MOUSE_DOWN, handleHeaderResizeDown, false, 0, true); header.addChild(dragHandle); dragHandlesMap[dragHandle] = col.colNum; } if(ci == visibleColumnsLen - 1 && _horizontalScrollPosition == 0 && availableWidth > x + col.width) { // adjust width of rightmost column in case it doesn't // fill the available width of the grid lastColWidth = Math.floor(availableWidth - x); headerRenderer.setSize(lastColWidth, headerHeight); } else { lastColWidth = col.width; } // force an immediate draw (because render event will not be called on the renderer): headerRenderer.drawNow(); } } var colCellRenderer:Object = (col.cellRenderer != null) ? col.cellRenderer : _cellRenderer; var availableRenderers:Array = availableCellRenderersMap[col]; activeRenderers = activeCellRenderersMap[col]; if(activeRenderers == null) { activeCellRenderersMap[col] = activeRenderers = []; } if(availableRenderers == null) { availableCellRenderersMap[col] = availableRenderers = []; } // find cell renderers that are still active, and make those that aren't active available: var itemToRendererHash:Dictionary = new Dictionary(true); while (activeRenderers.length > 0) { renderer = activeRenderers.pop(); item = renderer.data; if (itemHash[item] == null || invalidItems[item] == true) { availableRenderers.push(renderer); } else { itemToRendererHash[item] = renderer; // prevent problems with duplicate objects: invalidItems[item] = true; } list.removeChild(renderer as DisplayObject); } // draw cell renderers: if(length > 0) { for (i = rowStartIndex; i <= rowEndIndex; i++) { var reused:Boolean = false; item = _dataProvider.getItemAt(i); if (itemToRendererHash[item] != null) { // existing renderer for this item we can reuse: reused = true; renderer = itemToRendererHash[item]; delete(itemToRendererHash[item]); } else if (availableRenderers.length > 0) { // recycle an old renderer: renderer = availableRenderers.pop() as ICellRenderer; } else { // out of renderers, create a new one: renderer = getDisplayObjectInstance(colCellRenderer) as ICellRenderer; rendererSprite = renderer as Sprite; if (rendererSprite != null) { rendererSprite.addEventListener(MouseEvent.CLICK,handleCellRendererClick,false,0,true); rendererSprite.addEventListener(MouseEvent.ROLL_OVER,handleCellRendererMouseEvent,false,0,true); rendererSprite.addEventListener(MouseEvent.ROLL_OUT,handleCellRendererMouseEvent,false,0,true); rendererSprite.addEventListener(Event.CHANGE,handleCellRendererChange,false,0,true); rendererSprite.doubleClickEnabled = true; rendererSprite.addEventListener(MouseEvent.DOUBLE_CLICK,handleCellRendererDoubleClick,false,0,true); if (rendererSprite["setStyle"] != null) { for (var n:String in rendererStyles) { rendererSprite["setStyle"](n, rendererStyles[n]); } } } } list.addChild(renderer as Sprite); activeRenderers.push(renderer); renderer.x = x; renderer.y = rowHeight * (i - rowStartIndex); renderer.setSize((ci == visibleColumnsLen - 1) ? lastColWidth : col.width, rowHeight); if (!reused) { renderer.data = item; } renderer.listData = new ListData(columnItemToLabel(col.colNum, item), null, this, i, i, ci); if(listHovered && isHovered(renderer)) { renderer.setMouseState("over"); currentHoveredRow = i; } else { renderer.setMouseState("up"); } renderer.selected = (_selectedIndices.indexOf(i) != -1); // force an immediate draw (because render event will not be called on the renderer): if (renderer is UIComponent) { rendererUIC = renderer as UIComponent; rendererUIC.drawNow(); } } } x += col.width; } // remove renderers for columns that are no longer visible for (i = 0; i < _columns.length; i++) { if(visibleColumnsIndices.indexOf(i) == -1) { removeCellRenderersByColumn(_columns[i] as student_ar_fl_controls_DataGridColumn); } } if (editedItemPositionChanged) { editedItemPositionChanged = false; commitEditedItemPosition(proposedEditedItemPosition); proposedEditedItemPosition = undefined; } invalidItems = new Dictionary(true); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function updateRendererStyles():void { var renderers:Array = []; for (var n:Object in availableCellRenderersMap) { renderers = renderers.concat(availableCellRenderersMap[n]); } for (n in activeCellRenderersMap) { renderers = renderers.concat(activeCellRenderersMap[n]); } var l:uint = renderers.length; for (var i:uint=0; i 0) { list.removeChild(activeRenderers.pop() as DisplayObject); } } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function handleCellRendererMouseEvent(event:MouseEvent):void { var renderer:ICellRenderer = event.target as ICellRenderer; if(renderer) { var row:int = renderer.listData.row; var mouseMode:String; if(event.type == MouseEvent.ROLL_OVER) { mouseMode = "over"; } else if(event.type == MouseEvent.ROLL_OUT) { mouseMode = "up"; } if(mouseMode) { for(var i:uint = 0; i < visibleColumns.length; i++) { var col:student_ar_fl_controls_DataGridColumn = visibleColumns[i] as student_ar_fl_controls_DataGridColumn; var cellRenderer:ICellRenderer = getCellRendererAt(row, col.colNum); if(cellRenderer) { cellRenderer.setMouseState(mouseMode); } if(row != currentHoveredRow) { cellRenderer = getCellRendererAt(currentHoveredRow, col.colNum); if(cellRenderer) { cellRenderer.setMouseState("up"); } } } } } super.handleCellRendererMouseEvent(event); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function isHovered(renderer:ICellRenderer):Boolean { var rowStartIndex:uint = Math.min(Math.max(length - 1, 0), Math.floor(_verticalScrollPosition / rowHeight)); var rowYPos:Number = (renderer.listData.row - rowStartIndex) * rowHeight; var pt:Point = list.globalToLocal(new Point(0, stage.mouseY)); return (pt.y > rowYPos) && (pt.y < rowYPos + rowHeight); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function setHorizontalScrollPosition(scroll:Number, fireEvent:Boolean = false):void { if (scroll == _horizontalScrollPosition) { return; } contentScrollRect = listHolder.scrollRect; contentScrollRect.x = scroll; listHolder.scrollRect = contentScrollRect; list.x = 0; header.x = -scroll; super.setHorizontalScrollPosition(scroll, true); invalidate(InvalidationType.SCROLL); columnsInvalid = true; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function setVerticalScrollPosition(scroll:Number,fireEvent:Boolean=false):void { if (itemEditorInstance) { endEdit(student_ar_fl_controls_DataGridEventReason.OTHER); } invalidate(InvalidationType.SCROLL); super.setVerticalScrollPosition(scroll, true); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function columnItemToLabel(columnIndex:uint, item:Object):String { var col:student_ar_fl_controls_DataGridColumn = _columns[columnIndex] as student_ar_fl_controls_DataGridColumn; if(col != null) { return col.itemToLabel(item); } return " "; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function calculateColumnSizes():void { var delta:Number; var n:int; var i:int; var totalWidth:Number = 0; var col:student_ar_fl_controls_DataGridColumn; if (_columns.length == 0) { visibleColumns = []; displayableColumns = []; return; } if (columnsInvalid) { columnsInvalid = false; visibleColumns = []; if (minColumnWidthInvalid) { n = _columns.length; for (i = 0; i < n; i++) { _columns[i].minWidth = minColumnWidth; } minColumnWidthInvalid = false; } displayableColumns = null; n = _columns.length; for (i = 0; i < n; i++) { if (displayableColumns && _columns[i].visible) { displayableColumns.push(_columns[i]); } else if (!displayableColumns && !_columns[i].visible) { displayableColumns = new Array(i); for (var k:int = 0; k < i; k++) { displayableColumns[k] = _columns[k]; } } } // If there are no hidden columns, displayableColumns points to // _columns (we don't need a duplicate copy of _columns). if (!displayableColumns) { displayableColumns = _columns; } if (horizontalScrollPolicy == ScrollPolicy.OFF) { // if no hscroll, then pack all columns in available space n = displayableColumns.length; for (i = 0; i < n; i++) { visibleColumns.push(displayableColumns[i]); } } else { // check which of the displayable columns are actually visible n = displayableColumns.length; var xCol:Number = 0; for (i = 0; i < n; i++) { col = displayableColumns[i] as student_ar_fl_controls_DataGridColumn; if(xCol + col.width > _horizontalScrollPosition && xCol < _horizontalScrollPosition + availableWidth) { visibleColumns.push(col); } xCol += col.width; } } } var lastColumn:student_ar_fl_controls_DataGridColumn; var newSize:Number; if (horizontalScrollPolicy == ScrollPolicy.OFF) { // if no hscroll, then pack all columns in available space var numResizable:int = 0; var fixedWidth:Number = 0; // count how many resizable columns and how wide they are n = visibleColumns.length; for (i = 0; i < n; i++) { col = visibleColumns[i] as student_ar_fl_controls_DataGridColumn; if (col.resizable) { if (!isNaN(col.explicitWidth)) { // explicit width fixedWidth += col.width; } else { // implicitly resizable numResizable++; fixedWidth += col.minWidth; } } else { // not resizable fixedWidth += col.width; } totalWidth += col.width; } var ratio:Number; var newTotal:Number = availableWidth; var minWidth:Number; if ((availableWidth > fixedWidth) && numResizable) { // we have flexible columns and room to honor minwidths and non-resizable // divide and distribute the excess among the resizable n = visibleColumns.length; for (i = 0; i < n; i++) { col = visibleColumns[i] as student_ar_fl_controls_DataGridColumn; if (col.resizable && isNaN(col.explicitWidth)) { lastColumn = col; if (totalWidth > availableWidth) { ratio = (lastColumn.width - lastColumn.minWidth) / (totalWidth - fixedWidth); } else { ratio = lastColumn.width / totalWidth; } newSize = lastColumn.width - (totalWidth - availableWidth) * ratio; minWidth = col.minWidth; col.setWidth(Math.max(newSize, minWidth)); } newTotal -= col.width; } if (newTotal && lastColumn) { lastColumn.setWidth(lastColumn.width + newTotal); } } else { // can't honor minwidth and non-resizables so just scale everybody n = visibleColumns.length; for (i = 0; i < n; i++) { lastColumn = visibleColumns[i] as student_ar_fl_controls_DataGridColumn; ratio = lastColumn.width / totalWidth; newSize = availableWidth * ratio; lastColumn.setWidth(newSize); lastColumn.explicitWidth = NaN; newTotal -= newSize; } if (newTotal && lastColumn) { lastColumn.setWidth(lastColumn.width + newTotal); } } } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function calculateContentWidth():void { var n:int; var i:int; var col:student_ar_fl_controls_DataGridColumn; if (_columns.length == 0) { contentWidth = 0; return; } if (minColumnWidthInvalid) { n = _columns.length; for (i = 0; i < n; i++) { col = _columns[i] as student_ar_fl_controls_DataGridColumn; col.minWidth = minColumnWidth; } minColumnWidthInvalid = false; } if(horizontalScrollPolicy == ScrollPolicy.OFF) { contentWidth = availableWidth; } else { contentWidth = 0; n = _columns.length; for (i = 0; i < n; i++) { col = _columns[i] as student_ar_fl_controls_DataGridColumn; if (col.visible) { contentWidth += col.width; } } if(!isNaN(_horizontalScrollPosition) && _horizontalScrollPosition + availableWidth > contentWidth) { setHorizontalScrollPosition(contentWidth - availableWidth); } } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function handleHeaderRendererClick(event:MouseEvent):void { if (!_enabled) { return; } var headerRenderer:HeaderRenderer = event.currentTarget as HeaderRenderer; var columnIndex:uint = headerRenderer.column; var column:student_ar_fl_controls_DataGridColumn = _columns[columnIndex] as student_ar_fl_controls_DataGridColumn; if(sortableColumns && column.sortable) { var lastSortIndexTmp:uint = _sortIndex; _sortIndex = columnIndex; // this event is cancellable: var dataGridEvent:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.HEADER_RELEASE, false, true, columnIndex, -1, headerRenderer, column ? column.dataField : null ); if (!dispatchEvent(dataGridEvent) || !_selectable) { _sortIndex = lastSortIndex; return; } lastSortIndex = lastSortIndexTmp; // sort sortByColumn(columnIndex); invalidate(InvalidationType.DATA); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function resizeColumn(columnIndex:int, w:Number):void { if(_columns.length == 0) { return; } var column:student_ar_fl_controls_DataGridColumn = _columns[columnIndex] as student_ar_fl_controls_DataGridColumn; if(!column) { return; } if (!visibleColumns || visibleColumns.length == 0) { column.setWidth(w); return; } if (w < column.minWidth) { w = column.minWidth; } if (_horizontalScrollPolicy == ScrollPolicy.ON || _horizontalScrollPolicy == ScrollPolicy.AUTO) { // hScrollBar is present, adjust the column's width column.setWidth(w); column.explicitWidth = w; } else { var index:int = getVisibleColumnIndex(column); if(index != -1) { // we want all cols's new widths to the right of this to be in proportion // to what they were before the stretch. // get the original space to the right not taken up by the column var totalSpace:Number = 0; var n:int = visibleColumns.length; var visibleColumn:student_ar_fl_controls_DataGridColumn; var lastColumn:student_ar_fl_controls_DataGridColumn; var i:int; var newWidth:Number; // non-resizable columns don't count though for (i = index + 1; i < n; i++) { visibleColumn = visibleColumns[i] as student_ar_fl_controls_DataGridColumn; if (visibleColumn && visibleColumn.resizable) { totalSpace += visibleColumn.width; } } var newTotalSpace:Number = column.width - w + totalSpace; if (totalSpace) { column.setWidth(w); column.explicitWidth = w; } var totX:Number = 0; // resize the columns to the right proportionally to what they were for (i = index + 1; i < n; i++) { visibleColumn = visibleColumns[i] as student_ar_fl_controls_DataGridColumn; if (visibleColumn.resizable) { newWidth = visibleColumn.width * newTotalSpace / totalSpace; if (newWidth < visibleColumn.minWidth) { newWidth = visibleColumn.minWidth; } visibleColumn.setWidth(newWidth); totX += visibleColumn.width; lastColumn = visibleColumn; } } if (totX > newTotalSpace) { // if excess then should be taken out only from changing column // cause others would have already gone to their minimum newWidth = column.width - totX + newTotalSpace; if (newWidth < column.minWidth) { newWidth = column.minWidth; } column.setWidth(newWidth); } else if (lastColumn) { // if less then should be added in last column // dont need to check for minWidth as we are adding lastColumn.setWidth(lastColumn.width - totX + newTotalSpace); } } else { column.setWidth(w); column.explicitWidth = w; } } columnsInvalid = true; invalidate(InvalidationType.SIZE); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function sortByColumn(index:int):void { var col:student_ar_fl_controls_DataGridColumn = columns[index] as student_ar_fl_controls_DataGridColumn; if (!enabled || !col || !col.sortable) { return }; var desc:Boolean = col.sortDescending; // prepare sort options var sortOptions:uint = col.sortOptions; if(desc) { sortOptions |= Array.DESCENDING; } else { sortOptions &= ~Array.DESCENDING; } // do the sort if(col.sortCompareFunction != null) { sortItems(col.sortCompareFunction, sortOptions); } else { sortItemsOn(col.dataField, sortOptions); } // inverse the sort order for next sort _sortDescending = col.sortDescending = !desc; // reset the sort order for last sorted column if(lastSortIndex >= 0 && lastSortIndex != sortIndex) { col = columns[lastSortIndex] as student_ar_fl_controls_DataGridColumn; if(col != null) { col.sortDescending = false; } } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function createColumnsFromDataProvider():void { _columns = []; if(length > 0) { var item:Object = _dataProvider.getItemAt(0); for(var dataField:String in item) { addColumn(dataField); } } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function getVisibleColumnIndex(column:student_ar_fl_controls_DataGridColumn):int { for(var i:uint = 0; i < visibleColumns.length; i++) { if(column == visibleColumns[i]) { return i; } } return -1; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function handleHeaderResizeOver(event:MouseEvent):void { if(columnStretchIndex == -1) { showColumnStretchCursor(); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function handleHeaderResizeOut(event:MouseEvent):void { if(columnStretchIndex == -1) { showColumnStretchCursor(false); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function handleHeaderResizeDown(event:MouseEvent):void { var dragHandle:Sprite = event.currentTarget as Sprite; var colNum:Number = dragHandlesMap[dragHandle]; var col:student_ar_fl_controls_DataGridColumn = getColumnAt(colNum); columnStretchIndex = colNum; columnStretchStartX = event.stageX; columnStretchStartWidth = col.width; stage.addEventListener(MouseEvent.MOUSE_MOVE, handleHeaderResizeMove, false, 0, true); stage.addEventListener(MouseEvent.MOUSE_UP, handleHeaderResizeUp, false, 0, true); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function handleHeaderResizeMove(event:MouseEvent):void { var delta:Number = event.stageX - columnStretchStartX; var newWidth:Number = columnStretchStartWidth + delta; resizeColumn(columnStretchIndex, newWidth); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function handleHeaderResizeUp(event:MouseEvent):void { var dragHandle:Sprite = event.currentTarget as Sprite; var column:student_ar_fl_controls_DataGridColumn = _columns[columnStretchIndex] as student_ar_fl_controls_DataGridColumn; var headerRenderer:HeaderRenderer; for(var i:uint = 0; i < header.numChildren; i++) { headerRenderer = header.getChildAt(i) as HeaderRenderer; if(headerRenderer && headerRenderer.column == columnStretchIndex) { break; } } var dataGridEvent:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.COLUMN_STRETCH, false, true, columnStretchIndex, -1, headerRenderer, column ? column.dataField : null ); dispatchEvent(dataGridEvent); columnStretchIndex = -1; showColumnStretchCursor(false); stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleHeaderResizeMove, false); stage.removeEventListener(MouseEvent.MOUSE_UP, handleHeaderResizeUp, false); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function showColumnStretchCursor(show:Boolean = true):void { if(columnStretchCursor == null) { // create custom cursor columnStretchCursor = getDisplayObjectInstance(getStyleValue("columnStretchCursorSkin")) as Sprite; columnStretchCursor.mouseEnabled = false; } if(show) { Mouse.hide(); stage.addChild(columnStretchCursor); stage.addEventListener(MouseEvent.MOUSE_MOVE, positionColumnStretchCursor, false, 0, true); columnStretchCursor.x = stage.mouseX; columnStretchCursor.y = stage.mouseY; } else { stage.removeEventListener(MouseEvent.MOUSE_MOVE, positionColumnStretchCursor, false); if(stage.contains(columnStretchCursor)) { stage.removeChild(columnStretchCursor); } Mouse.show(); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function positionColumnStretchCursor(event:MouseEvent):void { columnStretchCursor.x = event.stageX; columnStretchCursor.y = event.stageY; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function setEditedItemPosition(coord:Object):void { editedItemPositionChanged = true; proposedEditedItemPosition = coord; if (coord && coord.rowIndex != selectedIndex) { selectedIndex = coord.rowIndex; } invalidate(InvalidationType.DATA); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function commitEditedItemPosition(coord:Object):void { if (!enabled || !editable) { return; } // check if there already is an itemEditorInstance for this position if (itemEditorInstance && coord && itemEditorInstance is IFocusManagerComponent && _editedItemPosition.rowIndex == coord.rowIndex && _editedItemPosition.columnIndex == coord.columnIndex) { // just give focus back to the itemEditorInstance IFocusManagerComponent(itemEditorInstance).setFocus(); return; } // dispose of any existing editor, saving away its data first if (itemEditorInstance) { var reason:String; if (!coord) { reason = student_ar_fl_controls_DataGridEventReason.OTHER; } else { if(!editedItemPosition || coord.rowIndex == editedItemPosition.rowIndex) { reason = student_ar_fl_controls_DataGridEventReason.NEW_COLUMN; } else { reason = student_ar_fl_controls_DataGridEventReason.NEW_ROW; } } if (!endEdit(reason) && reason != student_ar_fl_controls_DataGridEventReason.OTHER) { return; } } // store the value _editedItemPosition = coord; // allow setting of undefined to dispose item editor instance if (!coord) { return; } actualRowIndex = coord.rowIndex; actualColIndex = coord.columnIndex; if (displayableColumns.length != _columns.length) { for (var i:int = 0; i < displayableColumns.length; i++) { if (displayableColumns[i].colNum >= actualColIndex) { actualColIndex = displayableColumns[i].colNum; break; } } if (i == displayableColumns.length) { actualColIndex = 0; } } // scroll item into view scrollToPosition(actualRowIndex, actualColIndex); // get the actual references for the column, row, and item var renderer:ICellRenderer = getCellRendererAt(actualRowIndex, actualColIndex); var event:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.ITEM_EDIT_BEGIN, false, true, actualColIndex, actualRowIndex, renderer); dispatchEvent(event); // user may be trying to change the focused item renderer if (editedItemPositionChanged) { editedItemPositionChanged = false; commitEditedItemPosition(proposedEditedItemPosition); proposedEditedItemPosition = undefined; } if (!itemEditorInstance) { // assume that editing was cancelled commitEditedItemPosition(null); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function itemEditorItemEditBeginningHandler(event:student_ar_fl_controls_DataGridEvent):void { if (!event.isDefaultPrevented()) { setEditedItemPosition( {columnIndex: event.columnIndex, rowIndex: uint(event.rowIndex) } ); } else if (!itemEditorInstance) { _editedItemPosition = null; // return focus to the grid w/o selecting an item editable = false; setFocus(); editable = true; } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function itemEditorItemEditBeginHandler(event:student_ar_fl_controls_DataGridEvent):void { if (stage) { // weak reference for deactivation stage.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true); } if (!event.isDefaultPrevented()) { createItemEditor(event.columnIndex, uint(event.rowIndex)); ICellRenderer(itemEditorInstance).listData = ICellRenderer(editedItemRenderer).listData; ICellRenderer(itemEditorInstance).data = editedItemRenderer.data; itemEditorInstance.imeMode = (columns[event.columnIndex].imeMode == null) ? _imeMode : columns[event.columnIndex].imeMode; var fm:IFocusManager = focusManager; if (itemEditorInstance is IFocusManagerComponent) { fm.setFocus(InteractiveObject(itemEditorInstance)); } fm.defaultButtonEnabled = false; var event:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.ITEM_FOCUS_IN, false, false, _editedItemPosition.columnIndex, _editedItemPosition.rowIndex, itemEditorInstance); dispatchEvent(event); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function itemEditorItemEditEndHandler(event:student_ar_fl_controls_DataGridEvent):void { if (!event.isDefaultPrevented()) { var bChanged:Boolean = false; if (itemEditorInstance && event.reason != student_ar_fl_controls_DataGridEventReason.CANCELLED) { var newData:Object = itemEditorInstance[_columns[event.columnIndex].editorDataField]; var property:String = _columns[event.columnIndex].dataField; var data:Object = event.itemRenderer.data; var typeInfo:String = ""; for each(var variable:XML in describeType(data).variable) { if (property == variable.@name.toString()) { typeInfo = variable.@type.toString(); break; } } switch(typeInfo) { case "String": if (!(newData is String)) { newData = newData.toString(); } break; case "uint": if (!(newData is uint)) { newData = uint(newData); } break; case "int": if (!(newData is int)) { newData = int(newData); } break; case "Number": if (!(newData is Number)) { newData = Number(newData); } break; } if (data[property] != newData) { bChanged = true; data[property] = newData; } event.itemRenderer.data = data; } } else { if (event.reason != student_ar_fl_controls_DataGridEventReason.OTHER) { if (itemEditorInstance && _editedItemPosition) { // edit session is continued so restore focus and selection if (selectedIndex != _editedItemPosition.rowIndex) { selectedIndex = _editedItemPosition.rowIndex; } var fm:IFocusManager = focusManager; if (itemEditorInstance is IFocusManagerComponent) { fm.setFocus(InteractiveObject(itemEditorInstance)); } } } } if (event.reason == student_ar_fl_controls_DataGridEventReason.OTHER || !event.isDefaultPrevented()) { destroyItemEditor(); } } /** * @private (protected) * When we get focus, focus an item renderer. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function focusInHandler(event:FocusEvent):void { if (event.target != this) { return; } if (losingFocus) { losingFocus = false; return; } setIMEMode(true); super.focusInHandler(event); // don't do this if we're mouse focused if (editable && !isPressed) { var foundOne:Boolean = (editedItemPosition != null); // start somewhere if (!_editedItemPosition) { _editedItemPosition = { rowIndex: 0, columnIndex: 0 }; for (; _editedItemPosition.columnIndex < _columns.length; _editedItemPosition.columnIndex++) { // If the editedItemPosition is valid, focus it, otherwise find one. var col:student_ar_fl_controls_DataGridColumn = _columns[_editedItemPosition.columnIndex] as student_ar_fl_controls_DataGridColumn; if (col.editable && col.visible) { foundOne = true; break; } } } if (foundOne) { setEditedItemPosition(_editedItemPosition); } } if (editable) { addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler); addEventListener(MouseEvent.MOUSE_DOWN, mouseFocusChangeHandler); } } /** * @private (protected) * When we lose focus, close the editor. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function focusOutHandler(event:FocusEvent):void { setIMEMode(false); if (event.target == this) { super.focusOutHandler(event); } // just leave if item editor is losing focus back to grid. Usually happens // when someone clicks out of the editor onto a new item renderer. if (event.relatedObject == this && itemRendererContains(itemEditorInstance, DisplayObject(event.target))) { return; } // just leave if the cell renderer is losing focus to nothing while its editor exists. // this happens when we make the cell renderer invisible as we put up the editor // if the renderer can have focus. if (event.relatedObject == null && itemRendererContains(editedItemRenderer, DisplayObject(event.target))) { return; } // just leave if item editor is losing focus to nothing. Usually happens // when someone clicks out of the textfield if (event.relatedObject == null && itemRendererContains(itemEditorInstance, DisplayObject(event.target))) { return; } // however, if we're losing focus to anything other than the editor or the grid // hide the editor; if (itemEditorInstance && (!event.relatedObject || !itemRendererContains(itemEditorInstance, event.relatedObject))) { endEdit(student_ar_fl_controls_DataGridEventReason.OTHER); removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler); removeEventListener(MouseEvent.MOUSE_DOWN, mouseFocusChangeHandler); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function editorMouseDownHandler(event:MouseEvent):void { if (!itemRendererContains(itemEditorInstance, DisplayObject(event.target))) { if(event.target is ICellRenderer && contains(DisplayObject(event.target))) { var cr:ICellRenderer = event.target as ICellRenderer; var row:uint = cr.listData.row; if(_editedItemPosition.rowIndex == row) { endEdit(student_ar_fl_controls_DataGridEventReason.NEW_COLUMN); } else { endEdit(student_ar_fl_controls_DataGridEventReason.NEW_ROW); } } else { endEdit(student_ar_fl_controls_DataGridEventReason.OTHER); } } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function editorKeyDownHandler(event:KeyboardEvent):void { // ESC just kills the editor, no new data if (event.keyCode == Keyboard.ESCAPE) { endEdit(student_ar_fl_controls_DataGridEventReason.CANCELLED); } else if (event.ctrlKey && event.charCode == 46) { // Check for Ctrl-. endEdit(student_ar_fl_controls_DataGridEventReason.CANCELLED); } else if (event.charCode == Keyboard.ENTER && event.keyCode != 229) { // Enter edits the item, moves down a row // The 229 keyCode is for IME compatability. When entering an IME expression, // the enter key is down, but the keyCode is 229 instead of the enter key code. if (endEdit(student_ar_fl_controls_DataGridEventReason.NEW_ROW)) { findNextEnterItemRenderer(event); } } } /** * @private (protected) * Determines the next item renderer to navigate to using the Tab key. * If the item renderer to be focused falls out of range (the end or beginning * of the grid) then move focus outside the grid. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function findNextItemRenderer(shiftKey:Boolean):Boolean { if (!_editedItemPosition) { return false; } // some other thing like a collection change has changed the // position, so bail and wait for commit to reset the editor. if (proposedEditedItemPosition !== undefined) { return false; } var rowIndex:int = _editedItemPosition.rowIndex; var colIndex:int = _editedItemPosition.columnIndex; var found:Boolean = false; var incr:int = shiftKey ? -1 : 1; var maxIndex:int = length - 1; // cycle till we find something worth focusing, or the end of the grid while (!found) { // go to next column colIndex += incr; if (colIndex < 0 || colIndex >= _columns.length) { // if we fall off the end of the columns, wrap around colIndex = (colIndex < 0) ? _columns.length - 1 : 0; // and increment/decrement the row index rowIndex += incr; if (rowIndex < 0 || rowIndex > maxIndex) { // if we've fallen off the rows, we need to leave the grid. get rid of the editor setEditedItemPosition(null); // set focus back to the grid so default handler will move it to the next component losingFocus = true; setFocus(); return false; } } // if we find a visible and editable column, move to it if (_columns[colIndex].editable && _columns[colIndex].visible) { found = true; // kill the old edit session var reason:String; if(rowIndex == _editedItemPosition.rowIndex) { reason = student_ar_fl_controls_DataGridEventReason.NEW_COLUMN } else { reason = student_ar_fl_controls_DataGridEventReason.NEW_ROW } if (!itemEditorInstance || endEdit(reason)) { // send event to create the new one var dataGridEvent:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.ITEM_EDIT_BEGINNING, false, true, colIndex, rowIndex); dataGridEvent.dataField = _columns[colIndex].dataField; dispatchEvent(dataGridEvent); } } } return found; } /** * @private (protected) * Find the next item renderer down from the currently edited item renderer, and focus it. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function findNextEnterItemRenderer(event:KeyboardEvent):void { if (proposedEditedItemPosition !== undefined) { // some other thing has changed the position, so bail // and wait for commit to reset the editor. return; } var rowIndex:int = _editedItemPosition.rowIndex; var colIndex:int = _editedItemPosition.columnIndex; // modify direction with SHIFT (up or down) var newIndex:int = _editedItemPosition.rowIndex + (event.shiftKey ? -1 : 1); // only move if we're within range if (newIndex >= 0 && newIndex < length) { rowIndex = newIndex; } // send event to create the new one var dataGridEvent:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.ITEM_EDIT_BEGINNING, false, true, colIndex, rowIndex); dataGridEvent.dataField = _columns[colIndex].dataField; dispatchEvent(dataGridEvent); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function mouseFocusChangeHandler(event:MouseEvent):void { if (itemEditorInstance && !event.isDefaultPrevented() && itemRendererContains(itemEditorInstance, DisplayObject(event.target))) { event.preventDefault(); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function keyFocusChangeHandler(event:FocusEvent):void { if (event.keyCode == Keyboard.TAB && !event.isDefaultPrevented() && findNextItemRenderer(event.shiftKey)) { event.preventDefault(); } } /** * @private * Hides the itemEditorInstance. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ private function itemEditorFocusOutHandler(event:FocusEvent):void { if (event.relatedObject && contains(event.relatedObject)) { return; } // ignore textfields losing focus on mousedowns if (!event.relatedObject) { return; } if (itemEditorInstance) { endEdit(student_ar_fl_controls_DataGridEventReason.OTHER); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function deactivateHandler(event:Event):void { // if stage losing activation, set focus to DG so when we get it back // we popup an editor again if (itemEditorInstance) { endEdit(student_ar_fl_controls_DataGridEventReason.OTHER); losingFocus = true; setFocus(); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function mouseDownHandler(event:MouseEvent):void { if (!enabled || !selectable) { return; } isPressed = true; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function mouseUpHandler(event:MouseEvent):void { if (!enabled || !selectable) { return; } isPressed = false; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function handleCellRendererClick(event:MouseEvent):void { super.handleCellRendererClick(event); var renderer:ICellRenderer = event.currentTarget as ICellRenderer; if (renderer && renderer.data && renderer != itemEditorInstance /*&& lastItemDown == r*/) { var col:student_ar_fl_controls_DataGridColumn = _columns[renderer.listData.column] as student_ar_fl_controls_DataGridColumn; if (editable && col && col.editable /*&& !dontEdit*/) { var dgEvent:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.ITEM_EDIT_BEGINNING, false, true, renderer.listData.column, renderer.listData.row, renderer, col.dataField); dispatchEvent(dgEvent); } } } /** * Uses the editor specified by the itemEditor property to * create an item editor for the item renderer at the column and row index * identified by the editedItemPosition property. * *

This method sets the editor instance as the itemEditorInstance * property.

* *

You can call this method from the event listener for the itemEditBegin * event. To create an editor from other code, set the editedItemPosition * property to generate the itemEditBegin event.

* * @param colIndex The column index of the item to be edited in the data provider. * @param rowIndex The row index of the item to be edited in the data provider. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function createItemEditor(colIndex:uint, rowIndex:uint):void { if (displayableColumns.length != _columns.length) { for (var i:int = 0; i < displayableColumns.length; i++) { if (displayableColumns[i].colNum >= colIndex) { colIndex = displayableColumns[i].colNum; break; } } if (i == displayableColumns.length) { colIndex = 0; } } var col:student_ar_fl_controls_DataGridColumn = _columns[colIndex] as student_ar_fl_controls_DataGridColumn; var renderer:ICellRenderer = getCellRendererAt(rowIndex, colIndex); // if this isn't implemented, use an input control as editor if (!itemEditorInstance) { itemEditorInstance = getDisplayObjectInstance(col.itemEditor); itemEditorInstance.tabEnabled = false; list.addChild(DisplayObject(itemEditorInstance)); } list.setChildIndex(DisplayObject(itemEditorInstance), list.numChildren - 1); // give it the right size, look and placement var rendererSprite:Sprite = renderer as Sprite; itemEditorInstance.visible = true; itemEditorInstance.move(rendererSprite.x, rendererSprite.y); itemEditorInstance.setSize(col.width, rowHeight); itemEditorInstance.drawNow(); DisplayObject(itemEditorInstance).addEventListener(FocusEvent.FOCUS_OUT, itemEditorFocusOutHandler); rendererSprite.visible = false; // listen for keyStrokes on the itemEditorInstance (which lets the grid supervise for ESC/ENTER) DisplayObject(itemEditorInstance).addEventListener(KeyboardEvent.KEY_DOWN, editorKeyDownHandler); // we disappear on any mouse down outside the editor stage.addEventListener(MouseEvent.MOUSE_DOWN, editorMouseDownHandler, true, 0, true); } /** * Closes an item editor that is currently open on an item renderer. This method is * typically called from the event listener for the itemEditEnd event, * after a call is made to the preventDefault() method to prevent the * default event listener from executing. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function destroyItemEditor():void { if (itemEditorInstance) { DisplayObject(itemEditorInstance).removeEventListener(KeyboardEvent.KEY_DOWN, editorKeyDownHandler); stage.removeEventListener(MouseEvent.MOUSE_DOWN, editorMouseDownHandler, true); var event:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.ITEM_FOCUS_OUT, false, false, _editedItemPosition.columnIndex, _editedItemPosition.rowIndex, itemEditorInstance); dispatchEvent(event); // FocusManager.removeHandler() does not find // itemEditors in focusableObjects[] array // and hence does not remove the focusRectangle if (itemEditorInstance && itemEditorInstance is UIComponent) { UIComponent(itemEditorInstance).drawFocus(false); } // must call removeChild() so FocusManager.lastFocus becomes null list.removeChild(DisplayObject(itemEditorInstance)); DisplayObject(editedItemRenderer).visible = true; itemEditorInstance = null; } } /** * @private (protected) * This method is called after the user finishes editing an item. * It dispatches the itemEditEnd event to start the process * of copying the edited data from * the itemEditorInstance to the data provider and hiding the itemEditorInstance. * returns true if nobody called the preventDefault() method. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function endEdit(reason:String):Boolean { if (!editedItemRenderer) { return true; } //inEndEdit = true; var event:student_ar_fl_controls_DataGridEvent = new student_ar_fl_controls_DataGridEvent( student_ar_fl_controls_DataGridEvent.ITEM_EDIT_END, false, true, editedItemPosition.columnIndex, editedItemPosition.rowIndex, editedItemRenderer, _columns[editedItemPosition.columnIndex].dataField, reason ); dispatchEvent(event); return !event.isDefaultPrevented(); } /** * Get the instance of a cell renderer at the specified position * in the student_ar_fl_controls_DataGrid. * *

Note: This method returns null * for positions that are not visible (i.e. scrolled out of the * view).

* * @param row A row index. * @param column A column index. * * @return The ICellRenderer object at the specified position, or * null if no cell renderer exists at that position. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ public function getCellRendererAt(row:uint, column:uint):ICellRenderer { // get the column var col:student_ar_fl_controls_DataGridColumn = _columns[column] as student_ar_fl_controls_DataGridColumn; if(col != null) { // get the active renderers for that column var activeRenderers:Array = activeCellRenderersMap[col] as Array; if(activeRenderers != null) { for(var i:uint = 0; i < activeRenderers.length; i++) { var renderer:ICellRenderer = activeRenderers[i] as ICellRenderer; // if the row matches, return the renderer if(renderer.listData.row == row) { return renderer; } } } } return null; } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function itemRendererContains(renderer:Object, object:DisplayObject):Boolean { if (!object || !renderer || !(renderer is DisplayObjectContainer)) { return false; } return DisplayObjectContainer(renderer).contains(object); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function handleDataChange(event:DataChangeEvent):void { super.handleDataChange(event); // if not already created, create columns from dataprovider if (_columns == null) { _columns = []; } if (_columns.length == 0) { createColumnsFromDataProvider(); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function keyDownHandler(event:KeyboardEvent):void { if (!selectable || itemEditorInstance) { return; } switch (event.keyCode) { case Keyboard.UP: case Keyboard.DOWN: case Keyboard.END: case Keyboard.HOME: case Keyboard.PAGE_UP: case Keyboard.PAGE_DOWN: moveSelectionVertically(event.keyCode, event.shiftKey && _allowMultipleSelection, event.ctrlKey && _allowMultipleSelection); break; case Keyboard.LEFT: case Keyboard.RIGHT: moveSelectionHorizontally(event.keyCode, event.shiftKey && _allowMultipleSelection, event.ctrlKey && _allowMultipleSelection); break; case Keyboard.SPACE: if(caretIndex == -1) { caretIndex = 0; } scrollToIndex(caretIndex); doKeySelection(caretIndex, event.shiftKey, event.ctrlKey); break; default: break; } event.stopPropagation(); } /** * @private (protected) * Moves the selection in a horizontal direction in response * to the user selecting items using the left-arrow or right-arrow * keys and modifiers such as the Shift and Ctrl keys. * *

Not implemented in List because the default list * is single column and therefore doesn't scroll horizontally.

* * @param code The key that was pressed (e.g. Keyboard.LEFT) * @param shiftKey true if the shift key was held down when * the keyboard key was pressed. * @param ctrlKey true if the ctrl key was held down when * the keyboard key was pressed. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function moveSelectionHorizontally(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void {} /** * @private (protected) * Moves the selection in a vertical direction in response * to the user selecting items using the up-arrow or down-arrow * Keys and modifiers such as the Shift and Ctrl keys. * * @param code The key that was pressed (e.g. Keyboard.DOWN) * @param shiftKey true if the shift key was held down when * the keyboard key was pressed. * @param ctrlKey true if the ctrl key was held down when * the keyboard key was pressed. * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void { var pageSize:int = Math.max(Math.floor(calculateAvailableHeight() / rowHeight), 1); var newCaretIndex:int = -1; var dir:int = 0; switch(code) { case Keyboard.UP: if (caretIndex > 0) { newCaretIndex = caretIndex - 1; } break; case Keyboard.DOWN: if (caretIndex < length - 1) { newCaretIndex = caretIndex + 1; } break; case Keyboard.PAGE_UP: if (caretIndex > 0) { newCaretIndex = Math.max(caretIndex - pageSize, 0); } break; case Keyboard.PAGE_DOWN: if (caretIndex < length - 1) { newCaretIndex = Math.min(caretIndex + pageSize, length - 1); } break; case Keyboard.HOME: if (caretIndex > 0) { newCaretIndex = 0; } break; case Keyboard.END: if (caretIndex < length - 1) { newCaretIndex = length - 1; } break; } if(newCaretIndex >= 0) { doKeySelection(newCaretIndex, shiftKey, ctrlKey); scrollToSelected(); } } /** * @copy fl.controls.SelectableList#scrollToIndex() * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override public function scrollToIndex(newCaretIndex:int):void { drawNow(); var lastVisibleItemIndex:int = Math.floor((_verticalScrollPosition + availableHeight) / rowHeight) - 1; var firstVisibleItemIndex:int = Math.ceil(_verticalScrollPosition / rowHeight); if(newCaretIndex < firstVisibleItemIndex) { verticalScrollPosition = newCaretIndex * rowHeight; } else if(newCaretIndex >= lastVisibleItemIndex) { var scrollBarHeight:Number = (_horizontalScrollPolicy == ScrollPolicy.ON || (_horizontalScrollPolicy == ScrollPolicy.AUTO && hScrollBar)) ? 15 : 0; verticalScrollPosition = (newCaretIndex + 1) * rowHeight - availableHeight + scrollBarHeight + (showHeaders ? headerHeight : 0); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function scrollToPosition(rowIndex:int, columnIndex:int):void { var oldVerticalScrollPos:Number = verticalScrollPosition; var oldHorizontalScrollPos:Number = horizontalScrollPosition; // adjust vertical scroll if necessary scrollToIndex(rowIndex); // adjust horizontal scroll if necessary var i:uint; var x:Number = 0; var col:student_ar_fl_controls_DataGridColumn = _columns[columnIndex] as student_ar_fl_controls_DataGridColumn; for(i = 0; i < displayableColumns.length; i++) { var displayableColumn:student_ar_fl_controls_DataGridColumn = displayableColumns[i] as student_ar_fl_controls_DataGridColumn; if(displayableColumn != col) { x += displayableColumn.width; } else { break; } } if(horizontalScrollPosition > x) { horizontalScrollPosition = x; } else if(horizontalScrollPosition + availableWidth < x + col.width) { horizontalScrollPosition = -(availableWidth - (x + col.width)); } if(oldVerticalScrollPos != verticalScrollPosition || oldHorizontalScrollPos != horizontalScrollPosition) { drawNow(); } } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ protected function doKeySelection(newCaretIndex:int, shiftKey:Boolean, ctrlKey:Boolean):void { var selChanged:Boolean = false; if(shiftKey) { var i:int; var selIndices:Array = []; var startIndex:int = lastCaretIndex; var endIndex:int = newCaretIndex; if(startIndex == -1) { startIndex = caretIndex != -1 ? caretIndex : newCaretIndex; } if(startIndex > endIndex) { endIndex = startIndex; startIndex = newCaretIndex; } for(i = startIndex; i <= endIndex; i++) { selIndices.push(i); } selectedIndices = selIndices; caretIndex = newCaretIndex; selChanged = true; } else if(ctrlKey) { // only moves the caret caretIndex = newCaretIndex; } else { selectedIndex = newCaretIndex; caretIndex = lastCaretIndex = newCaretIndex; selChanged = true; } if(selChanged) { dispatchEvent(new Event(Event.CHANGE)); } invalidate(InvalidationType.DATA); } /** * @private (protected) * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ override protected function initializeAccessibility():void { if (student_ar_fl_controls_DataGrid.createAccessibilityImplementation != null) { student_ar_fl_controls_DataGrid.createAccessibilityImplementation(this); } } } }