суббота, 23 мая 2009 г.

DataGrid with selection by checkboxes

The DataGrid what change selection by clicking on checkboxes and accordingly change state of checkboxes by changing DataGrid selection. In addition select all by key "a" pressed.


view source enabled

CheckBoxSelectionDataGrid
package ua.org.enginer.controls {

import flash.events.Event;
import flash.events.KeyboardEvent;

import mx.collections.ArrayCollection;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.core.ClassFactory;
import mx.events.ListEvent;

import ua.org.enginer.controls.renderers.DataGridSelectionIndicator;
import ua.org.enginer.controls.renderers.DataGridSelectionIndicatorHeader;


/**
* [a] key for select all (like [Ctrl+a])
*
* Indicate selection by CheckBoxes
*/
public class CheckBoxSelectionDataGrid extends DataGrid {

public function CheckBoxSelectionDataGrid() {
super();
addEventListener(KeyboardEvent.KEY_DOWN, onKetDown)

function onKetDown(event:KeyboardEvent):void {
//if (event.ctrlKey && event.keyCode == 65) {
// My lovely IE do not pass [Ctrl+A]... so simply [a]
if (event.keyCode == 65) {
selectAll()
}
}
}

public function selectAll(value:Boolean=true):void {
selectedItems = value ? ArrayCollection(collection).source : []
}

// storage for seted columns
private var rawColumns:Array

override public function set columns(value:Array):void {
super.columns = value
rawColumns = value
}

private var _indicatorAlign:String = "right";

public function set indicatorAlign(value:String):void {
if (value != _indicatorAlign) {
_indicatorAlign = value;
invalidateProperties()
dispatchEvent (new Event("indicatorAlignChange"));
}
}

[Bindable(event="indicatorAlignChange")]
[Inspectable(category="General", enumeration="left,right", defaultValue="right")]
public function get indicatorAlign():String {
return _indicatorAlign;
}

private var _indicatorsColumn:DataGridColumn

public function get indicatorsColumn():DataGridColumn {
if (_indicatorsColumn) return _indicatorsColumn

var selectionIndicators:DataGridColumn = new DataGridColumn()
selectionIndicators.itemRenderer = new ClassFactory(DataGridSelectionIndicator)
selectionIndicators.headerRenderer = new ClassFactory(DataGridSelectionIndicatorHeader)
selectionIndicators.width = 20
selectionIndicators.sortable = false
selectionIndicators.resizable = false

return _indicatorsColumn = selectionIndicators
}

override protected function commitProperties():void {

// clone array
var newColumns:Array = rawColumns.concat()
indicatorAlign == "right" ? newColumns.push(indicatorsColumn) :
newColumns.unshift(indicatorsColumn)
super.columns = newColumns

super.commitProperties()
}

override public function set selectedItems(items:Array):void {
super.selectedItems = items
// for recalculation
dispatchEvent(new ListEvent(ListEvent.CHANGE))
}

override public function set selectedIndices(indices:Array):void {
super.selectedIndices = indices
dispatchEvent(new ListEvent(ListEvent.CHANGE))
}

override public function set dataProvider(value:Object):void {
super.dataProvider = value
dispatchEvent(new ListEvent(ListEvent.CHANGE))
}
}
}



DataGridSelectionIndicator
package ua.org.enginer.controls.renderers {

import flash.events.Event;

import mx.controls.CheckBox;
import mx.controls.DataGrid;
import mx.controls.listClasses.BaseListData;
import mx.events.FlexEvent;
import mx.events.ListEvent;

public class DataGridSelectionIndicator extends CheckBox {

public function DataGridSelectionIndicator() {
super();
addEventListener(Event.CHANGE, onChange)
setStyle("paddingLeft", 3)
}


private function onChange(event:Event):void {
var grid:DataGrid = DataGrid(listData.owner)
var myIndex:int = grid.itemRendererToIndex(this)

if (selected) {
if (grid.selectedIndices.indexOf(myIndex)>=0) return;
var indices:Array = grid.selectedIndices
indices.push(myIndex)
grid.selectedIndices = indices
}
else grid.selectedIndices = grid.selectedIndices.filter(function (...args):Boolean {
if (args[0] == myIndex) return false;
return true
})
}

private function onItemClick(event:Event):void {
var grid:DataGrid = DataGrid(listData.owner)
var myIndex:int = grid.itemRendererToIndex(this)
selected = grid.selectedIndices.indexOf(myIndex)>=0
}

override public function set listData(value:BaseListData):void {
super.listData = value

var grid:DataGrid = DataGrid(value.owner)

grid.addEventListener(FlexEvent.VALUE_COMMIT, onItemClick)
grid.addEventListener(ListEvent.ITEM_CLICK, onItemClick)
//grid.addEventListener(ListEvent.CHANGE, onItemClick)
selected = false
}

override public function set data(value:Object):void {
// prevent default behavior
}
}
}




DataGridSelectionIndicatorHeader
package ua.org.enginer.controls.renderers {

import flash.events.Event;

import mx.controls.CheckBox;
import mx.controls.DataGrid;
import mx.controls.listClasses.BaseListData;
import mx.events.FlexEvent;
import mx.events.ListEvent;

import ua.org.enginer.controls.CheckBoxSelectionDataGrid;

// fixme: do not change state on click
public class DataGridSelectionIndicatorHeader extends CheckBox {

private var grid:CheckBoxSelectionDataGrid

public function DataGridSelectionIndicatorHeader() {
super();
addEventListener(Event.CHANGE, onChange)
setStyle("paddingLeft", 3)
toolTip = "Отметить все"
}


private function onChange(event:Event):void {
grid.selectAll(selected)
}

override public function set listData(value:BaseListData):void {
//super.listData = value
grid = CheckBoxSelectionDataGrid(value.owner)
}

override public function set data(value:Object):void {
// prevent default behavior
}

}
}