`
oncer_L
  • 浏览: 4362 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

flex4 spark DataGrid 拖放drag drop实现

阅读更多
转自:http://www.riafan.com/article/flex/spark-datagrid-with-support-for-drag-and-drop.html

上面的网址有源码,是在上面做了dragMove修复,修复了   drop到一个  button时  datagrid的 selecteditem数据会被移除的问题

和 新增 dragsouce 的 items属性 更像mx的DataGrid的drag特性呢

DNDragDataGrid.as

package com.dn.components.datagrid
{
 
 
 import flash.display.DisplayObject;
 import flash.geom.Point;
 
 import mx.collections.ArrayList;
 import mx.core.DragSource;
 import mx.core.IFactory;
 import mx.core.IFlexDisplayObject;
 import mx.events.DragEvent;
 import mx.managers.DragManager;
 
 
 import spark.components.DataGrid;
 import spark.components.Group;
 import spark.components.gridClasses.CellPosition;
 import spark.components.gridClasses.GridColumn;
 import spark.components.gridClasses.IGridItemRenderer;
 import spark.events.GridEvent;
 /**
  * 
  * @author Hugo.Wang
  * 2012-6-15 17:25:25
  */
 public class DNDragDataGrid extends DataGrid
 {
  public function DNDragDataGrid()
  {
   super();
   addEventListener(GridEvent.GRID_MOUSE_DRAG, startDragDrop);
  }
  
  private var dropIndex:int;
  
  private var dropIndicator:DisplayObject;
  
  private var _dragEnabled:Boolean = false;
  
  [Inspectable(defaultValue="false")]
  
  public function get dragEnabled():Boolean
  {
   return _dragEnabled;
  }
  
  public function set dragEnabled(value:Boolean):void
  {
   if (value == _dragEnabled)
    return;
   _dragEnabled = value;
   if(_dragEnabled)
   {
    addEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler); 
   }
   else
   {
    removeEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler); 
   }
  }
  
  private var _dragMoveEnabled:Boolean = false;
  
  [Inspectable(defaultValue="false")]
  
  public function get dragMoveEnabled():Boolean
  {
   return _dragMoveEnabled;
  }
  
  public function set dragMoveEnabled(value:Boolean):void
  {
   _dragMoveEnabled = value;
  }
  
  private var _dropEnabled:Boolean = false;
  
  [Inspectable(defaultValue="false")]
  
  public function get dropEnabled():Boolean
  {
   return _dropEnabled;
  }
  
  public function set dropEnabled(value:Boolean):void
  {
   if (value == _dropEnabled)
    return;
   _dropEnabled = value;
   if(_dropEnabled)
    addEventListener(DragEvent.DRAG_ENTER, dragEnterHandler);
   else
    removeEventListener(DragEvent.DRAG_ENTER, dragEnterHandler);
  }
  
  private var _draggableColumns:Boolean = false;
  
  [Inspectable(defaultValue="false")]
  
  public function get draggableColumns():Boolean
  {
   return _draggableColumns;
  }
  
  public function set draggableColumns(value:Boolean):void
  {
   _draggableColumns = value;
  }
  
  private function startDragDrop(event:GridEvent):void
  {
   if (DragManager.isDragging)
    return;
   
   if (event.rowIndex == -1 && event.itemRenderer)
    // dragging headers
    startColumnDragDrop(event);
   else
    startRowDragDrop(event);
  }
  
  private var dragColumn:GridColumn;
  
  protected function startColumnDragDrop(event:GridEvent):void
  {
   if(!(draggableColumns))
   {
    return;
   }
   
   dragColumn = event.column;
   var ds:DragSource = new DragSource();
   ds.addData(dragColumn, "spark.components.gridClasses.GridColumn");
   var factory:IFactory = dragColumn.headerRenderer;
   if (!factory)
    factory = columnHeaderGroup.headerRenderer;
   var renderer:IGridItemRenderer = IGridItemRenderer(factory.newInstance());
   renderer.visible = true;
   renderer.column = dragColumn;
   renderer.label = dragColumn.headerText;
   var currentRenderer:IGridItemRenderer = columnHeaderGroup.getHeaderRendererAt(event.columnIndex);
   renderer.width = currentRenderer.width;
   renderer.height = currentRenderer.height;
   renderer.x = currentRenderer.x;
   renderer.y = currentRenderer.y;
   renderer.prepare(false);
   DragManager.doDrag(this, ds, event, renderer as IFlexDisplayObject);
   renderer.owner = this;
   columnHeaderGroup.addEventListener(DragEvent.DRAG_ENTER, columnDragEnterHandler)
   columnHeaderGroup.addEventListener(DragEvent.DRAG_COMPLETE, columnDragCompleteHandler);
  }
  
  protected function columnDragEnterHandler(event:DragEvent):void
  {
   if (event.dragSource.hasFormat("spark.components.gridClasses.GridColumn"))
   {
    columnHeaderGroup.addEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
    columnHeaderGroup.addEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
    columnHeaderGroup.addEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
    showColumnDropFeedback(event);
    DragManager.acceptDragDrop(columnHeaderGroup);
   }
  }
  
  protected function columnDragOverHandler(event:DragEvent):void
  {
   if (event.dragSource.hasFormat("spark.components.gridClasses.GridColumn"))
   {
    showColumnDropFeedback(event);
    DragManager.acceptDragDrop(columnHeaderGroup);
   }
  }
  
  protected function columnDragExitHandler(event:DragEvent):void
  {
   columnHeaderGroup.removeEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
   columnHeaderGroup.removeEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
   columnHeaderGroup.removeEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
   cleanUpDropIndicator();
  }
  
  private function columnDragDropHandler(event:DragEvent):void
  {
   columnHeaderGroup.removeEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
   columnHeaderGroup.removeEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
   columnHeaderGroup.removeEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
   dropColumn(event);
  }
  
  private function columnDragCompleteHandler(event:DragEvent):void
  {
   columnHeaderGroup.removeEventListener(DragEvent.DRAG_ENTER, columnDragEnterHandler);
   cleanUpDropIndicator();
  }
  
  
  private function dropColumn(event:DragEvent):void
  {
   if (dropIndex != dragColumn.columnIndex)
   {
    var oldIndex:int = dragColumn.columnIndex;
    columns.removeItemAt(dragColumn.columnIndex);
    if (dropIndex > oldIndex)
     dropIndex--;
    columns.addItemAt(dragColumn, dropIndex);
   }
   cleanUpDropIndicator();
  }
  
  
  private function showColumnDropFeedback(event:DragEvent):void
  {
   var pt:Point = new Point(event.stageX, event.stageY);
   pt = columnHeaderGroup.globalToLocal(pt);
   var newDropIndex:int = columnHeaderGroup.getHeaderIndexAt(pt.x, pt.y);
   if (newDropIndex != -1)
   {
    var renderer:IGridItemRenderer = columnHeaderGroup.getHeaderRendererAt(newDropIndex);
    if (!dropIndicator)
    {
     dropIndicator = new ColumnDropIndicator();
     dropIndicator.height = renderer.height;
     columnHeaderGroup.overlay.addDisplayObject(dropIndicator);
    }
    if (pt.x < renderer.x + renderer.width / 2)
     dropIndicator.x = renderer.x - dropIndicator.width / 2; 
    else
    {
     dropIndicator.x = renderer.x + renderer.width - dropIndicator.width / 2;
     newDropIndex++;
    }
    dropIndex = newDropIndex;
   }
   else
   {
    cleanUpDropIndicator();
   }
  }
  
  
  protected function copySelectedItems(useDataField:Boolean = true):Array
  {
   var tmp:Array = [];
   
   var items:Vector.<Object> = selectedItems;
   for (var i:int = 0; i < items.length; i++) 
   {
    if(useDataField){
     tmp[i]=items[i];
    }else{
     tmp[i]=selectedIndices[i];
    }
   }
   
   return tmp;
  }
  /**
   *  @private
   */
  private function copySelectedItemsForDragDrop():Vector.<Object>
  {
   // Copy the vector so that we don't modify the original
   // since selectedIndices returns a reference.
   var draggedIndices:Vector.<int> = selectedIndices.slice(0, selectedIndices.length);
   var result:Vector.<Object> = new Vector.<Object>(draggedIndices.length);
   
   // Sort in the order of the data source
   draggedIndices.sort(compareValues);
   
   // Copy the items
   var count:int = draggedIndices.length;
   for (var i:int = 0; i < count; i++)
    result[i] = dataProvider.getItemAt(draggedIndices[i]);  
   return result;
  }
  
  protected function startRowDragDrop(event:GridEvent):void
  {
   if(!dragEnabled)
    return;
   
   var newIndex:int = event.rowIndex;
   
   var ds:DragSource = new DragSource();
   ds.addHandler(copySelectedItems, "items");
   ds.addHandler(copySelectedItemsForDragDrop, "itemsByIndex");
   
   // Calculate the index of the focus item within the vector
   // of ordered items returned for the "itemsByIndex" format.
   var caretIndex:int = 0;
   var draggedIndices:Vector.<int> = selectedIndices;
   var count:int = draggedIndices.length;
   for (var i:int = 0; i < count; i++)
   {
    if (newIndex > draggedIndices[i])
     caretIndex++;
   }
   ds.addData(caretIndex, "caretIndex");
   
   var proxy:Group = new Group();
   proxy.width = grid.width;
   DragManager.doDrag(this, ds, event, proxy as IFlexDisplayObject, 
    0, -rowHeight, 0.5, dragMoveEnabled);
   
   const visibleColumnIndices:Vector.<int> = grid.getVisibleColumnIndices();
   count = visibleColumnIndices.length;
   const visibleRowIndices:Vector.<int> = grid.getVisibleRowIndices();
   //for scrolled renderers
   var rIndex:int = grid.getVisibleRowIndices().indexOf(newIndex);
   for (i = 0; i < count; i++)
   {
    var currentRenderer:IGridItemRenderer = grid.getItemRendererAt(newIndex, visibleColumnIndices[i]);
    var factory:IFactory = columns.getItemAt(i).itemRenderer;
    if (!factory)
     factory = itemRenderer;
    var renderer:IGridItemRenderer = IGridItemRenderer(factory.newInstance());
    renderer.visible = true;
    if(currentRenderer)
    {
     renderer.column = currentRenderer.column;
     renderer.rowIndex = currentRenderer.rowIndex;
     renderer.label = currentRenderer.label;
     renderer.x = currentRenderer.x;
     renderer.y = rIndex  * rowHeight;
     renderer.width = currentRenderer.width;
     renderer.height = currentRenderer.height;
     renderer.prepare(false);
     proxy.addElement(renderer);
     renderer.owner = this;
    }
   }
   proxy.height = renderer.height;
   
  }
  
  protected function dragEnterHandler(event:DragEvent):void
  {
   if (event.dragSource.hasFormat("itemsByIndex"))
   {
    grid.addEventListener(DragEvent.DRAG_OVER, rowDragOverHandler);
    grid.addEventListener(DragEvent.DRAG_EXIT, rowDragExitHandler);
    grid.addEventListener(DragEvent.DRAG_DROP, rowDragDropHandler);
    showRowDropFeedback(event);
    DragManager.acceptDragDrop(grid);
   }
  }
  
  protected function rowDragOverHandler(event:DragEvent):void
  {
   if (event.dragSource.hasFormat("itemsByIndex"))
   {
    showRowDropFeedback(event);
    DragManager.acceptDragDrop(grid);
   }
  }
  
  protected function rowDragExitHandler(event:DragEvent):void
  {
   grid.removeEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
   grid.removeEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
   grid.removeEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
   cleanUpRowDropIndicator();
  }
  
  protected function rowDragDropHandler(event:DragEvent):void
  {
   grid.removeEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
   grid.removeEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
   grid.removeEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
   dropRow(event);
  }
  
  protected function dragCompleteHandler(event:DragEvent):void
  {
   if (event.isDefaultPrevented())
    return;
   // Remove the dragged items only if they were drag moved to
   // a different list. If the items were drag moved to this
   // list, the reordering was already handles in the 
   // DragEvent.DRAG_DROP listener.
   if (!dragMoveEnabled ||
    event.action != DragManager.MOVE || 
    event.relatedObject == this)
    return;
   
   // Clear the selection, but remember which items were moved
   var movedIndices:Vector.<int> = selectedIndices;
   selectedIndices = new Vector.<int>();
   validateProperties();
   // Remove the moved items
   movedIndices.sort(compareValues);
   var count:int = movedIndices.length;
   for (var i:int = count - 1; i >= 0; i--)
   {
    dataProvider.removeItemAt(movedIndices[i]);
   }  
   dropIndex = 0;
  }
  
  private function showRowDropFeedback(event:DragEvent):void
  {
   DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : DragManager.MOVE);
   var pt:Point = new Point(event.stageX, event.stageY);
   pt = grid.globalToLocal(pt);
   var pos:CellPosition = grid.getCellAt(pt.x, pt.y);
   var newDropIndex:int = pos ? pos.rowIndex : - 1;
   if (newDropIndex != -1)
   {
    var renderer:IGridItemRenderer = grid.getItemRendererAt(pos.rowIndex, pos.columnIndex);
    if (!dropIndicator)
    {
     dropIndicator = new RowDropIndicator();
     dropIndicator.width = width;
     grid.overlay.addDisplayObject(dropIndicator);
    }
    if (pt.y < renderer.y + renderer.height / 2)
     dropIndicator.y = renderer.y - dropIndicator.height / 2; 
    else
    {
     dropIndicator.y = renderer.y + renderer.height - dropIndicator.height / 2;
     newDropIndex++;
    }
    dropIndex = newDropIndex;
   }
   else
   {
    cleanUpRowDropIndicator();
   }
  }
  
  private function dropRow(event:DragEvent):void
  {
   if(event.dragSource.hasFormat("itemsByIndex"))
   {
    var data:Vector.<Object> = event.dragSource.dataForFormat("itemsByIndex") as Vector.<Object>;
    var count:int = data.length;
    var i:int;
    
    if (event.dragInitiator == this)
    {
     for (i = 0; i < count; i++)
     {
      var index:int = dataProvider.getItemIndex(data[i]);
      dataProvider.removeItemAt(index);
      if (index < dropIndex)
       dropIndex--;
     }
    }
    
    if(dataProvider == null)
    {
     dataProvider = new ArrayList();
    }
    
    for (i = 0; i < count; i++)
    {
     dataProvider.addItemAt(data[i], dropIndex++);
    }
   }
   cleanUpRowDropIndicator();
  }
  
  private function cleanUpDropIndicator():void
  {
   if (dropIndicator)
   {
    dropIndex == -1;
    if( columnHeaderGroup.overlay.numDisplayObjects > 0)
    {
     columnHeaderGroup.overlay.removeDisplayObject(dropIndicator);
     dropIndicator = null;
    }
   }
  }
  
  private function cleanUpRowDropIndicator():void
  {
   if (dropIndicator)
   {
    dropIndex == -1;
    if(grid.overlay.numDisplayObjects > 0)
    {
     grid.overlay.removeDisplayObject(dropIndicator);
     dropIndicator = null;
    }
   }
  }
  
  /**
   *  @private
   *  Used to sort the selected indices during drag and drop operations.
   */
  private function compareValues(a:int, b:int):int
  {
   return a - b;
  } 
 }
}


RowDropIndicator.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
 xmlns:s="library://ns.adobe.com/flex/spark" 
 xmlns:mx="library://ns.adobe.com/flex/mx"
 width="100%" height="3">
 <s:Rect left="1" right="1" top="1" bottom="1">
  <s:fill>
   <s:SolidColor color="0x2B333C"/>
  </s:fill>
 </s:Rect>
 <s:Rect left="0" right="0" top="0" bottom="0">
  <s:stroke>
   <s:SolidColorStroke weight="1"/>
  </s:stroke>
 </s:Rect>
</s:Group>


ColumnDropIndicator.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
 xmlns:s="library://ns.adobe.com/flex/spark" 
 xmlns:mx="library://ns.adobe.com/flex/mx">
 <s:Rect width="1" height="100%" right="1"> 
  <s:fill>
   <s:SolidColor color="0x0167FF"/>
  </s:fill>
 </s:Rect>
</s:Group>


app.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
 xmlns:s="library://ns.adobe.com/flex/spark"
 xmlns:mx="library://ns.adobe.com/flex/mx"
 xmlns:c="components.*"
 width="800" height="600">
 <s:layout>
  <s:VerticalLayout horizontalAlign="center" paddingTop="30"/>
 </s:layout>
 <fx:Script>
  <![CDATA[
   import mx.controls.Alert;
   import mx.core.IUIComponent;
   import mx.events.DragEvent;
   import mx.managers.DragManager;
   
   protected function addItemButton_dragDropHandler(event:DragEvent):void
   {
    // TODO Auto-generated method stub
     try{
       var obj:Object=event.dragSource.dataForFormat('items')[0];
      Alert.show(obj.birthday); 
     }catch(er:Error){}
   }
   
   protected function button1_dragEnterHandler(event:DragEvent):void
   {
    // TODO Auto-generated method stub
    DragManager.acceptDragDrop(IUIComponent(event.target));
   }
   
  ]]>
 </fx:Script>
 
 <fx:Declarations>
  <s:ArrayList id="al">
   <s:DataItem birthday="07/23/1987" salary="6000" userName="Jim"/>
   <s:DataItem birthday="06/12/1987" salary="5500" userName="Jane"/>
   <s:DataItem birthday="12/06/1988" salary="8000" userName="Tom"/>
   <s:DataItem birthday="01/12/1988" salary="6000" userName="Kite"/>
   <s:DataItem birthday="05/28/1987" salary="7000" userName="Mike"/>
  </s:ArrayList> 
 </fx:Declarations>
 <s:Button
  label="drop in"
  dragEnter="button1_dragEnterHandler(event)"
  dragDrop="addItemButton_dragDropHandler(event)"
  >
  
 </s:Button>
 <mx:DataGrid width="400"
  dataProvider="{new ArrayList(al.source.concat())}" 
  dragEnabled="true" dragDrop="true"
  draggableColumns="true" rowCount="5" 
  allowMultipleSelection="true">
  <mx:columns>
   <mx:DataGridColumn dataField="userName" headerText="Name"/>
   <mx:DataGridColumn dataField="birthday" headerText="Bithday"/>
   <mx:DataGridColumn dataField="salary" headerText="Salary"/>
  </mx:columns>
 </mx:DataGrid>
 
 <c:DataGridEx width="400" dataProvider="{al}" dragEnabled="true" draggableColumns="true"
  dragMoveEnabled="true" dropEnabled="true" requestedRowCount="5" selectionMode="multipleRows">
  <c:columns>
   <s:ArrayList>
    <s:GridColumn dataField="userName" headerText="Name"/>
    <s:GridColumn dataField="birthday" headerText="Bithday"/>
    <s:GridColumn dataField="salary" headerText="Salary"/>
   </s:ArrayList>
  </c:columns>
 </c:DataGridEx>
 
 <c:DataGridEx id="dgex" width="400" dragEnabled="true" dropEnabled="true" requestedRowCount="5">
  <c:columns>
   <s:ArrayList>
    <s:GridColumn dataField="userName" headerText="Name"/>
    <s:GridColumn dataField="birthday" headerText="Bithday"/>
    <s:GridColumn dataField="salary" headerText="Salary"/>
   </s:ArrayList>
  </c:columns>
 </c:DataGridEx>
 
 <s:List height="90" dragEnabled="true" dropEnabled="true" 
  labelField="userName"/>
</s:Application> 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics