1/22/10

Tab Navigator with checkbox and close button on tab, allowing tab drag and drop and also child containers drag and drop

Hi guys... I hope this post will help so many people a lot. We have worked with tab navigator which has close button and where the tabs can be dragged. I have used that feature from the internet resource and modified to have new feature.

following are the action script classes...

package com
{

import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.MouseEvent;

import mx.controls.Button;
import mx.controls.CheckBox;
import mx.controls.tabBarClasses.*;
import mx.core.DragSource;
import mx.core.IFlexDisplayObject;
import mx.core.mx_internal;
import mx.events.DragEvent;
import mx.events.ItemClickEvent;
import mx.managers.DragManager;
import mx.utils.StringUtil;


use namespace mx_internal;

[Style(name="showCloseButton", type="Boolean")]
public class extended_Tab extends Tab
{

private var closeButton:Button;
private var chkBox:CheckBox;
private var dropIndicatorClass:Class = extended_TabDropIndicator;
private var tabDropIndicator:IFlexDisplayObject;
public var mystate:String="false"

public function extended_Tab()
{

super();

mouseChildren = true;

//use if text align is right
//setStyle("paddingRight",15);
//setStyle("textAlign","left");
//setStyle("labelPlacement","right");

addEventListener("creationComplete", handleCreationComplete);
addEventListener(MouseEvent.MOUSE_MOVE,handleMouseMove);

addEventListener(DragEvent.DRAG_ENTER,handleDragEnter);
addEventListener(DragEvent.DRAG_DROP,handleDragDrop);
addEventListener(DragEvent.DRAG_EXIT,handleDragExit);
addEventListener(DragEvent.DRAG_OVER,handleDragOver);



}

//add close button and drop indication 
override protected function createChildren():void{

super.createChildren();

if (this.getStyle("showCloseButton")==true){
chkBox=new CheckBox();
chkBox.selected=false;
chkBox.width = 10;
chkBox.height = 10;

chkBox.name="Check"
closeButton = new Button();
closeButton.width = 11;
closeButton.height = 11;
closeButton.name="CloseButton"
closeButton.styleName="CloseButton";
// closeButton.visible=false;
// closeButton.enabled=false
closeButton.mouseEnabled =true;
chkBox.mouseEnabled =true;
addChild(chkBox);
addChild(closeButton);
closeButton.move(width-18,textField.y+4);

//the tab gets focus on mouse down so the only event 
//we can use is mouse down on the button for close
closeButton.addEventListener(MouseEvent.MOUSE_DOWN,handleMouseDown);
chkBox.addEventListener(MouseEvent.CLICK,handleMouseDown1);
}

//create the drop indicator
tabDropIndicator = IFlexDisplayObject(new dropIndicatorClass());
addChildAt(DisplayObject(tabDropIndicator),numChildren-1)
tabDropIndicator.visible=false;

}

/**
* if the drag format is correct in form the user that
* the location is acceptable for the drop
**/ 
private function handleDragEnter(event:DragEvent):void{
if (event.dragSource.hasFormat('tabButton')) {
var dropTarget:extended_Tab=extended_Tab(event.currentTarget);
DragManager.acceptDragDrop(dropTarget);

//make sure it is topmost display object and show it
setChildIndex(DisplayObject(tabDropIndicator),numChildren-1)
tabDropIndicator.visible=true;   
}
}

/**
* basically draw an indicator to show user where the tab 
* will be inserted
**/
private function handleDragOver(event:DragEvent):void{
if (event.dragSource.hasFormat('tabButton')) {

}
}

/**
* clean up the drag drop indicator
**/
private function handleDragExit(event:DragEvent):void{
//hide it
tabDropIndicator.visible=false;
}

/**
* begin the drag operation
**/
private function handleMouseMove(event:MouseEvent):void{
if (event.buttonDown){
startTabDrag(event,"tabButton");
} 
}

/**
* dispatch the drop event to the parent tab navigator
**/
private function handleDragDrop(event:DragEvent):void {

var DragDropEvent:DragEvent = new DragEvent("TAB_DRAG_DROP",true
,true,event.dragInitiator,event.dragSource,event.action,event.ctrlKey
,event.altKey,event.shiftKey);

dispatchEvent(DragDropEvent);

//hide it
tabDropIndicator.visible=false;

}

/**
* set up a proxy and begin the drag operation
* */
private function startTabDrag(event:MouseEvent, format:String):void {
var dragInitiator:Button=Button(event.currentTarget);

var ds:DragSource = new DragSource();
ds.addData(this,format);

var dragProxy:extended_Tab = new extended_Tab();
dragProxy.label=label;
dragProxy.setStyle("icon",getStyle("icon"));
dragProxy.width = width;
dragProxy.height = height;

DragManager.doDrag(dragInitiator, ds, event, dragProxy);
}



/**
* handle the passing of an event to the parent
* Note: We have to unfortunately close on mouse down
* as I’ve yet to figure out how to stop the tab selecting
* and causing index problems
**/
private function handleMouseDown(event:MouseEvent):void{

event.stopPropagation();
event.preventDefault();

if (event.target is Button && event.target.name=="CloseButton"){
var closeEvent:ItemClickEvent = new ItemClickEvent("TAB_CLOSE_CLICK", true, true);
closeEvent.index = parent.getChildIndex(this)

closeButton.removeEventListener(MouseEvent.MOUSE_DOWN,handleMouseDown);

removeEventListener("creationComplete", handleCreationComplete);

dispatchEvent(closeEvent);

}

}
private function handleMouseDown1(event:MouseEvent):void{

event.stopPropagation();
event.preventDefault();

if (event.target is CheckBox && event.target.name=="Check"){

//var _dispatchObj:DatasEvent=new DatasEvent(countUsers, "getCount", false);
//dispatchEvent(_dispatchObj);

mystate=""+chkBox.selected;

var closeEvent:ItemClickEvent = new ItemClickEvent("Tab_Disable", true, true,StringUtil.trim(mystate));
closeEvent.index = parent.getChildIndex(this)

//chkBox.removeEventListener(MouseEvent.CLICK,handleMouseDown1);

removeEventListener("creationComplete", handleCreationComplete);

dispatchEvent(closeEvent);
/*if(chkBox.selected){
var _dispatchObj:DatasEvent=new DatasEvent("true~"+parent.getChildIndex(this), "Tab_Disable", false);
chkBox.removeEventListener(MouseEvent.MOUSE_DOWN,handleMouseDown1);

removeEventListener("creationComplete", handleCreationComplete);
dispatchEvent(_dispatchObj);
}
else{
var _dispatchObj:DatasEvent=new DatasEvent("false~"+parent.getChildIndex(this), "Tab_Disable", false);
chkBox.removeEventListener(MouseEvent.MOUSE_DOWN,handleMouseDown1);

removeEventListener("creationComplete", handleCreationComplete);
dispatchEvent(_dispatchObj);}*/

}

}

/**
* adjust position of button when creation is complete
**/
private function handleCreationComplete(event:Event):void{
if (this.getStyle("showCloseButton")==true){
closeButton.move(width-18,textField.y+4);
chkBox.move(1,textField.y+4);
}
}

/**
* swap the button to the top of the z/depth order
**/
override mx_internal function layoutContents(unscaledWidth:Number,unscaledHeight:Number, offset:Boolean):void{
super.layoutContents(unscaledWidth, unscaledHeight, offset);

//if (this.getStyle("showCloseButton")==true){
setChildIndex(getChildByName("Check") , numChildren-1);
chkBox.move(1,textField.y+4);
setChildIndex(getChildByName("CloseButton") , numChildren-1);
closeButton.move(width-18,textField.y+4);
//}

//make sure we set this otherwise the tabs are resized and 
//squished together using measured width to get a proper 
//tab size
explicitWidth = measuredWidth;
}
}
}


package com
{
 
import flash.display.DisplayObject;

import mx.containers.TabNavigator;
import mx.controls.Alert;
import mx.core.IFlexDisplayObject;
import mx.core.mx_internal;
import mx.events.DragEvent;
import mx.events.ItemClickEvent;
import mx.managers.DragManager;

use namespace mx_internal;


[Event(name="CloseClick",type="mx.events.ItemClickEvent")]
[Event(name="checkClick",type="mx.events.ItemClickEvent")]
public class extended_TabNavigator extends TabNavigator
{

private var dropIndicatorClass:Class = extended_TabDropIndicator;
private var tabDropIndicator:IFlexDisplayObject;

public function extended_TabNavigator()
{
super();
addEventListener("TAB_CLOSE_CLICK",handleTabCloseClick, false,0,true);
addEventListener("Tab_Disable",handleTabDisableClick, false,0,true);
addEventListener("TAB_DRAG_DROP",handleTabDragDrop, false,0,true);

addEventListener(DragEvent.DRAG_ENTER,handleDragEnter, false,0,true);
addEventListener(DragEvent.DRAG_DROP,handleTabDragDrop, false,0,true);
addEventListener(DragEvent.DRAG_EXIT,handleDragExit, false,0,true);
addEventListener(DragEvent.DRAG_OVER,handleDragOver, false,0,true);

}


/**
* make sure that the tabbar is our extended version of the adobe tabbar
**/
override protected function createChildren():void{
tabBar = new extended_TabBar();
tabBar.name = "tabBar";
tabBar.focusEnabled = false;
tabBar.styleName = this;

tabBar.setStyle("borderStyle", "none");
tabBar.setStyle("paddingTop", 0);
tabBar.setStyle("paddingBottom", 0);

rawChildren.addChild(tabBar);

//create the drop indicator
tabDropIndicator = IFlexDisplayObject(new dropIndicatorClass());
rawChildren.addChildAt(DisplayObject(tabDropIndicator),rawChildren.numChildren-1)
tabDropIndicator.visible=false;

super.createChildren();

}


/**
* accept drag and drop on the navigator as well,
* for when there are no tabs present
**/
private function handleDragEnter(event:DragEvent):void{
if (event.dragSource.hasFormat('tabButton')) {
var dropTarget:extended_TabNavigator=extended_TabNavigator(event.currentTarget);
DragManager.acceptDragDrop(dropTarget);

//make sure it is topmost display object and show it
rawChildren.setChildIndex(DisplayObject(tabDropIndicator),rawChildren.numChildren-1)
tabDropIndicator.visible=true; 

}
}

/**
* draw indicator to show user where the tab 
* will be inserted
**/
private function handleDragOver(event:DragEvent):void{
if (event.dragSource.hasFormat('tabButton')) {

}
}

/**
* clean up the drag drop indicator
**/
private function handleDragExit(event:DragEvent):void{
//hide it
tabDropIndicator.visible=false;
}


/**
* when dragged (even between navigators) if the format is correct
* move the tab to the new parent and location if the target is the 
* navigator then the new tab is inserted at location 0.
**/
private function handleTabDragDrop(event:DragEvent):void{

if(event.dragInitiator.parent.parent is extended_TabNavigator){ 
if (event.dragSource.hasFormat('tabButton')) {
var oldIndex:int = event.dragInitiator.parent.getChildIndex(DisplayObject(event.dragInitiator));
var newIndex:int 

if (event.target is extended_Tab){
newIndex= event.target.parent.getChildIndex(event.target);
}
else{
newIndex=0;
tabDropIndicator.visible=false;
}

var obj:DisplayObject = extended_TabNavigator(event.dragInitiator.parent.parent).removeChildAt(oldIndex);
addChildAt(obj,newIndex);

//validate the visible items for the tab bar.
extended_TabBar(tabBar).validateVisibleTabs();

}
}


}

/**
* handle removal of container when close button is clicked
**/
private function handleTabCloseClick(event:ItemClickEvent):void{
event.stopPropagation();
event.preventDefault();

var obj:DisplayObject = removeChildAt(event.index);
obj = null;


var dispEvent:ItemClickEvent = new ItemClickEvent("CloseClick");
dispEvent.index =event.index;
dispEvent.item = event.item;
dispEvent.label = event.label;
dispEvent.relatedObject = event.relatedObject;
dispatchEvent(dispEvent);


}
/**
* handle removal of container when checkbox is clicked
**/
private function handleTabDisableClick(event:ItemClickEvent):void{
event.stopPropagation();
event.preventDefault();

var dispEvent:ItemClickEvent = new ItemClickEvent("checkClick");
dispEvent.index =event.index;
dispEvent.item = event.item;
dispEvent.label = event.label;
dispEvent.relatedObject = event.relatedObject;

dispatchEvent(dispEvent);


}

}
}


package com
{
 import mx.skins.halo.HaloBorder;
  
 public class extended_TabListToolButtonSkin extends HaloBorder
 {
  private var offset:Number=0;
  
  public function extended_TabListToolButtonSkin()
  {
   super();
      
  }
    
  override protected function updateDisplayList(w:Number, h:Number):void{
   var alpha:Number =getStyle("alpha");
   var borderColor:uint =getStyle("borderColor");
   graphics.beginFill(borderColor,alpha);
   graphics.drawRect(0,0,w-offset,h);
   drawArrow(w,h);
  }
  
  private function drawArrow(w:Number, h:Number):void{
   if (this.parent is extendedPopUpMenuButton){
   
    //draw the drop down arrow taking into account the right padding
             //and use the text color for the arrow color
    var PaddingRight:Number = getStyle("paddingRight");
    var arrowColor:uint = getStyle("color");
     
    graphics.lineStyle(1,arrowColor,0);
    graphics.beginFill(arrowColor,1);
    graphics.moveTo((w-PaddingRight)-7/2, h/2+3);
    graphics.lineTo(w-PaddingRight, 9);
    graphics.lineTo((w-PaddingRight)-7, 9);
    graphics.lineTo((w-PaddingRight)-7/2,h/2+3);
    graphics.endFill();
   
   }
   
  }
   
  
 }
}


package com
{
 import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.MouseEvent;

import mx.controls.Button;
import mx.controls.Menu;
import mx.controls.TabBar;
import mx.core.ClassFactory;
import mx.core.DragSource;
import mx.core.IFlexDisplayObject;
import mx.core.mx_internal;
import mx.events.DragEvent;
import mx.events.MenuEvent;
import mx.managers.DragManager;

use namespace mx_internal;

public class extended_TabBar extends TabBar
{

private var listPopup:extendedPopUpMenuButton; 

public function extended_TabBar()
{
super();

//set the factory to our specific tab
navItemFactory = new ClassFactory(extended_Tab);
addEventListener("creationComplete", handleCreationComplete , false,0,true); 

}

//store an internal array of tabs to work with 
private var _itemData:Array = [];
private function set itemData(value:Array):void{
_itemData = value;
}
private function get itemData():Array{
return _itemData 
}


private function handleCreationComplete (event:Event):void{
//make sure we get informed on the parent resize for the 
//popup positioning
parent.addEventListener("resize", handleParentReSize, false,0,true); 
listPopup.addEventListener(MenuEvent.ITEM_CLICK,handleListDataItemClick, false,0,true);
}

private function handleListDataCreationComplete(event:Event):void{
Menu(listPopup.popUp).dragEnabled = true;
Menu(listPopup.popUp).dragMoveEnabled = true;
Menu(listPopup.popUp).addEventListener(MouseEvent.MOUSE_MOVE,handleListDataMouseMove, false,0,true);
}

private function handleListDataMouseMove(event:MouseEvent):void{
if (event.buttonDown && !DragManager.isDragging){
DragFromItemList(event,"tabButton");
}
}

/**
* Set up a proxy and begin the drag operation.
**/
private function DragFromItemList(event:MouseEvent, format:String):void {


var dragInitiator:Button=Button(getChildAt(event.currentTarget.selectedIndex));

var ds:DragSource = new DragSource();
ds.addData(dragInitiator,format);

//create a proxy drag image based on current dragged tab
var dragProxy:extended_Tab = new extended_Tab();
dragProxy.label=dragInitiator.label;
dragProxy.setStyle("icon",dragInitiator.getStyle("icon"));
dragProxy.width = dragInitiator.width;
dragProxy.height = dragInitiator.height;

//get X position 
var proxyPointX:int =(dragInitiator.x+(dragInitiator.width/2))-event.stageX;

//get Y position
var proxyPointY:int;
if(dragInitiator.contentMouseY > 0){
//popup below 
proxyPointY=(dragInitiator.y - (event.currentTarget.contentMouseY+(dragInitiator.height/2)));
}
else{
//popup above
proxyPointY= event.currentTarget.height-(event.currentTarget.contentMouseY-(dragInitiator.height/2));
}

//start the drag operation
DragManager.doDrag(dragInitiator, ds, event, dragProxy,proxyPointX,proxyPointY); 

}

//on the menu click update both the tab bar and the parent (when tab not visible) 
private function handleListDataItemClick(event:MenuEvent):void{

selectedIndex = event.index;

if (getChildAt(event.index).visible==true){
selectedIndex = event.index;
}
else{

setChildIndex(getChildAt(event.index),0);
selectedIndex = 0;

validateVisibleTabs();

if (owner is extended_TabNavigator){
extended_TabNavigator(owner).setChildIndex(owner.getChildAt(event.index),0);
extended_TabNavigator(owner).selectedIndex = 0;
} 
}
}




override protected function createNavItem( label:String, icon:Class = null):IFlexDisplayObject{

var navItem:IFlexDisplayObject = super.createNavItem(label,icon);
reBuildItemData();


return navItem; 

}

public override function addChild(child:DisplayObject):DisplayObject{
return super.addChild(child);
}

public override function setChildIndex(child:DisplayObject, newIndex:int):void{
super.setChildIndex(child,newIndex);
reBuildItemData();
}

public override function removeChildAt(index:int):DisplayObject{

itemData.splice(index,1); 
listPopup.dataProvider = itemData;

return super.removeChildAt(index);


}

//update the item data array
private function reBuildItemData():void{

itemData = new Array();
for (var i:int;i= parent.width-listPopup.width){
currTab.visible=false;
listPopup.visible = true;
}
else{
currTab.visible=true;
listPopup.visible = false;
listPopup.close();
}
}*/
}

//validate on display updates
override protected function updateDisplayList(w:Number, h:Number):void{
super.updateDisplayList(w,h);
validateVisibleTabs();
}

}
}



package com
{
 import mx.skins.ProgrammaticSkin;
 import flash.display.Graphics;
 import mx.utils.ColorUtil;
 
 
 public class extended_TabDropIndicator extends ProgrammaticSkin
 {
  public function extended_TabDropIndicator()
  {
   super();
   
  }
  
  override protected function updateDisplayList(w:Number, h:Number):void{ 
   super.updateDisplayList(w, h);
   
   //eventually use a style setting
   var dropIndicatorColor:uint =0x000000;
   
   graphics.lineStyle(0, 0, 0);
   graphics.beginFill(dropIndicatorColor);
      
   graphics.moveTo (4, 0); 
   graphics.lineTo (0, 4); 
   graphics.lineTo (-4, 0); 
   graphics.lineTo (4,0);
   graphics.endFill();
 
 
 
  }
 }
}


package com
{ 
 import flash.events.MouseEvent;
 import mx.controls.PopUpMenuButton;
 import mx.core.mx_internal;
 import mx.controls.Menu;
 import mx.core.ClassFactory;
 import mx.events.MenuEvent;
 import flash.events.Event;
 
 [Event(name="menuItemClick", type="mx.events.MenuEvent")]
 public class extendedPopUpMenuButton extends PopUpMenuButton
 {
  
  public function extendedPopUpMenuButton():void{
   super();
   openAlways=true;
   
   addEventListener("open",handleOpenClose, false,0,true);
   addEventListener("close",handleOpenClose, false,0,true);
      
  }
  
  public var isOpen:Boolean;
  
  private function handleOpenClose(event:Event):void{
   
   switch (event.type){
    case "open":
     isOpen=true;
     break;
    case "close":
     isOpen=false;
     this.styleChanged("upSkin");
     break;
   }

  }
  
  override public function close():void{
   super.close();
   
  }  
  override public function open():void{
   super.open();
   
  }
    
  [Inspectable]
  public var iconField:String;
  
  override protected function clickHandler(event:MouseEvent):void
     {
      super.clickHandler(event);
     }
     
     
  override public function set dataProvider(value:Object):void{
      
   super.dataProvider = value;
   
  } 
  
  private function handelItemClick(event:MenuEvent):void{
   //dispatch a specific menu event
   //bubble this so the parent navigator can receive it
   var menuEvent:MenuEvent = new MenuEvent("menuItemClick");
   menuEvent.menu = Menu(popUp);
   menuEvent.menu.selectedIndex = Menu(popUp).selectedIndex;
   menuEvent.item =  Menu(popUp).selectedItem
   menuEvent.itemRenderer = Menu(popUp).itemToItemRenderer(Menu(popUp).selectedItem);
   menuEvent.index = Menu(popUp).selectedIndex;
   dispatchEvent(menuEvent);
   
  }
      
  //override to block the default    
  override public function setStyle(styleProp:String, newValue:*):void{}
  
  
 }
}


package raghu  {  
import flash.events.Event;  
import flash.events.MouseEvent;
import mx.containers.Canvas; 
import mx.containers.VBox;
import mx.controls.TextInput;
import mx.events.DragEvent;
import mx.managers.DragManager;
public class DragCanvas extends Canvas  
{  
public function DragCanvas() 
{  
 super();  
 this.doubleClickEnabled=true;
 addEventListener(MouseEvent.DOUBLE_CLICK,test);
 addEventListener(DragEvent.DRAG_ENTER,candragEnterHandler);
 addEventListener(DragEvent.DRAG_OVER,candragOverHandler);
 addEventListener(DragEvent.DRAG_DROP,candragDropHandler);
 } 
private function test(e:Event):void{
}  
private function candragEnterHandler(event:DragEvent):void  
{
// Accept the drop.
if (event.dragSource.hasFormat("items"))
{   
var dropTarget:Canvas=Canvas(event.currentTarget); 
//var txt:TextInput=new TextInput();  
//dropTarget.addChild(txt);  
DragManager.acceptDragDrop(dropTarget);
}  
//DragManager.acceptDragDrop(TextInput(event.currentTarget));  
} 
private function candragOverHandler(event:DragEvent):void  
{
if (event.dragSource.hasFormat("items"))
DragManager.showFeedback(DragManager.COPY);
}
private var count:int=0;  
private function candragDropHandler(event:DragEvent):void
{     
event.preventDefault();
var itemsArray:Array=event.dragSource.dataForFormat("items") as Array;
var dropCanvas:Canvas = event.currentTarget as Canvas;
var box:VBox=new VBox();  
var txt:TextInput=new TextInput(); 
//if (TextInput(event.currentTarget).text == "")
//{  txt.text=itemsArray[0].label;  // }  
// else  
// {  
// TextInput(event.currentTarget).text="";  
// TextInput(event.currentTarget).text=itemsArray[0].label;  
//}  
box.x=0;
box.y=count*20;
box.addChild(txt);
dropCanvas.addChildAt(box,count);
count++; 
}
}
}  



following are the mxml  


following snapshots are the newly added features....
     

No comments:

Post a Comment

Popular Posts