rulururu

post Select multiple List items like in desktop application with selection rectangle(FLEX/AIR)

February 14th, 2010

Filed under: Flash/Flex — Alex Bylim @ 5:29 pm

Hi, guys. In Flex we often should use different kind of list and selection of multiple items little bit complex there, you should press CTRL(win) or COMMAND(mac os) button and then select items one by one. But what if you want select multiple items from list like you select icons on your desktop ?

For this we need our list, in this example i will use TileList and we need Canvas(we can customize it in whatever way we want). Canvas and TileList should be in one container.

Before starting i should admit that we can use two ways of items selection: first one is select all items that are inside our selection rectangle, second is select items when they intersects with selection rectangle. From experience for first one way, we should to reduce bounds of item to make it selection little bit easier, it will looks like on the picture below

But in demo you can see using of second way.

So every selection should start with mouse button down:

private function mouseDownS(event:MouseEvent):void{
	// start selection only if we clicked on our List(not outside or it's items)
	if(event.target.parent != tileList)
	  return;
 
	//storing point from where we will start selection
	selectionRectRightBottom = new Point(event.localX, event.localY);
 
	// disable interactions with all childrens(items) of list
	tileList.mouseChildren = false;
 
	// show our canvas rect
	selectRectCanvas.visible = true;
	selectRectCanvas.width = 0;
	selectRectCanvas.height = 0;
 
	// this is array for storing rectangles(bounds) of items for further comparing them and selection
	// but we will make them little bit smaller to make their selection easier
	animatedGridItemsRect = new Array();
 
	// we should use this value if we will select items when they whole inside selection rectangle
	// if we will select items that will be selected just while intersection with selection rectangle this value should be 0
	var RECT_PADDING_DELTA:Number = 0;
 
	var count:int = tileList.dataProvider.length; 
 
	for(var i:int = 0; i < count; i++){
	  var data:Object = new Object();
	  var rendererRect:Rectangle = tileList.indexToItemRenderer(i).getRect(tileList);
	  rendererRect.x 		+= RECT_PADDING_DELTA;
	  rendererRect.y 		+= RECT_PADDING_DELTA;
	  rendererRect.width	-= RECT_PADDING_DELTA * 2;
	  rendererRect.height 	-= RECT_PADDING_DELTA * 2;
	  // here is we storing item data + item reducedd bounds
	  data.rect = rendererRect;
	  data.item = tileList.indexToItemRenderer(i).data;
	  animatedGridItemsRect.push(data);
	}
}

then continue selection when mouse moving:

private function mouseMoveS(e:MouseEvent):void{
       if(!selectionRectRightBottom)
          return;
 
        // end-poing of our selection rectangle
       selectionRectLeftTop = new Point(tileList.mouseX, tileList.mouseY);
 
	// calculating selection rectangle height and width
	var selectionRectWidth:Number = -selectionRectRightBottom.x + selectionRectLeftTop.x;
	var selectionRectHeight:Number = -selectionRectRightBottom.y + selectionRectLeftTop.y;
 
	// set selection rect canvas size and position
	selectRectCanvas.width = selectionRectWidth;
	selectRectCanvas.height = selectionRectHeight;
 
	selectRectCanvas.x = selectionRectRightBottom.x + tileList.x;
	selectRectCanvas.y = selectionRectRightBottom.y + tileList.y;
 
	// getting Rectangle instance of selection canvas
	var selectRect:Rectangle = selectRectCanvas.getRect(tileList);
 
	// actually array that will contain indecies of newly selected items
	var newSelectedIndicies:Array = new Array();
	var i:int = 0;
	for each(var itemData:Object in animatedGridItemsRect){
	        // we should use this line if we will select items when they whole inside selection rectangle
		//if(selectRect.containsRect(Rectangle(itemData.rect)))
		// we should use this line if we will select items that will be selected just while intersection with selection rectangle
		if(selectRect.intersects(Rectangle(itemData.rect)))
			  newSelectedIndicies.push(i);
			i++;
		}
		tileList.selectedIndices = newSelectedIndicies;
		// force list to refresh
		tileList.invalidateDisplayList();
		// call this for forcing flash to handle all stuff above after every mouse move
		e.updateAfterEvent();
 
}

and ends when mouse up:

private function mouseUpS():void{
        // if mouse up, then restore all states
	selectionRectRightBottom = null;
	selectionRectLeftTop = null;
	tileList.mouseChildren = true;
	selectRectCanvas.visible = false;
	animatedGridItemsRect = null;
}

Source code and  demo

  • http://binhpm.wordpress.com Binhpm

    nice article!
    But if tileList has very much item and tilelist display a Vscrollbar then this solution has bug.

    You can move line code “selectRectCanvas.visible = true;” to mouseMoveS function (after line “if(event.target.parent != tileList) return; “) to prevent display dot blue when you click mouse down.

ruldrurd
Powered by WordPress, Web Design by Laurentiu Piron
Entries (RSS) and Comments (RSS)