6 Replies Latest reply on Mar 25, 2010 11:00 AM by jfillman

    DataGroup Drag Enter Issue/Question (FB4)

    jfillman Level 1

      I'm working with Flash Builder 4, Flex 4 and I'm having difficulty in getting the drag events to fire, in particular the Drag Enter event. I have 2 dataGroups with a custom layout and itemRenderer. I'm attempting to drag an element from one DataGroup and drop it into the other DataGroup. In Flex 3, when I dragged something over a container, the event.CurrentTarget was the container, and I could then tell the container to accept the dragged item. In Flex 4, the dragEnter event isn't firing when I drag something over the DataGroup. It ONLY fires when I drag something over one of the rendered items in the DataGroup. Below is the code for the application, DataGroup, CustomLayout, and itemRenderer. If you debug the application and drag an item in the first DataGroup over the second DataGroup, note that you don't get the trace statements. If you drag the item so that the mouse passes over one of the elements in the second DataGroup, THEN the DragEnter events fires.

       

      Application:

       

      <?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" minWidth="955" minHeight="600" xmlns:ns1="*" >

       

       

       

      <fx:Script>

      <![CDATA[

       

       

      import mx.events.DragEvent;

       

       

      private function dragEnterHandler(event:DragEvent):void {

       

      trace ("Drag Enter");

       

      trace (" Target: "+event.target.id);

       

      trace (" Current Target: "+event.currentTarget.id);

      }

       

       

      private function dragDropHandler(event:DragEvent):void {

       

      trace (event.currentTarget.id);

      }

       

      ]]>

       

      </fx:Script>

       

       

      <s:SkinnableContainer top="0" left="0" right="0" bottom="0" id="dgContainer" >

       

       

      <ns1:myDataGroup left="5" id="dgOne" top="5" bottom="5" width="200" depth="1" dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)"/>

       

       

      <ns1:myDataGroup left="226" id="dgTwo" top="5" bottom="5" width="200" depth="1" dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)"/>

       

      <mx:VRule left="213" top="0" bottom="0"/>

       

       

      </s:SkinnableContainer>

      </s:Application>

       

      DataGroup:

       

      <?xml version="1.0" encoding="utf-8"?>

      <s:DataGroup

      xmlns:fx="http://ns.adobe.com/mxml/2009"

      xmlns:s="

      library://ns.adobe.com/flex/spark"

      xmlns:mx="

      library://ns.adobe.com/flex/mx" dataProvider="{myAC}"

      width="

      100%" height="100%" xmlns:myLayout="myLayout.*" itemRenderer="iRenderer"

      creationComplete="addEventListener(RESIZE_CLICK, resizeHandler,

      false, 0, true);"

      initialize="cLayout.setLayout();" name="

      myDGroup" >

       

      <fx:Declarations>

       

      <!-- Place non-visual elements (e.g., services, value objects) here -->

       

      </fx:Declarations>

       

       

      <fx:Script>

      <![CDATA[

       

      import mx.collections.ArrayCollection;

       

      import mx.events.DragEvent;

       

      [

      Bindable]

       

      public var myAC:ArrayCollection = new ArrayCollection([

      {Height: 100, Label:

      "Test # 1", xPos: 0},

      {Height: 200, Label:

      "Test # 2", xPos: 0}

      ]);

       

       

      public static const RESIZE_CLICK:String = "resizeClick";

       

      protected var resizingElement:iRenderer;

       

      protected var initX:Number;

       

      protected var initY:Number;

       

      public var itemID:Number;

       

      public function resizeHandler(event:MouseEvent):void {

       

      if (event.target.name == 'iRenderer') {

      resizingElement = iRenderer(event.target);

      initX = event.localX;

      initY = event.localY;

      itemID = Number(resizingElement.uid);

      systemManager.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler,

      true);

      systemManager.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler,

      true);

      }

      }

       

       

      protected function mouseMoveHandler(event:MouseEvent):void {

      event.stopImmediatePropagation();

       

      if (resizingElement.height + event.stageY - initY > 49) {

      myAC[itemID].Height = myAC[itemID].Height + event.stageY - initY;

      resizingElement.height = resizingElement.height + event.stageY - initY;

      initY = event.stageY;

      }

      }

       

       

      protected function mouseUpHandler(event:MouseEvent):void {

      cLayout.setLayout();

       

      this.invalidateDisplayList();

      systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler,

      true);

      systemManager.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler,

      true);

      }

       

      ]]>

       

      </fx:Script>

       

       

      <s:layout>

       

      <myLayout:customLayout id="cLayout" />

       

      </s:layout>

       

      </s:DataGroup>

       

      CustomLayout:

       

      package

       

      myLayout

      {

       

      import mx.collections.ArrayCollection;

       

      import mx.core.ILayoutElement;

       

       

      import spark.components.DataGroup;

       

      import spark.components.supportClasses.GroupBase;

       

      import spark.components.supportClasses.ItemRenderer;

       

      import spark.layouts.supportClasses.LayoutBase;

       

       

      public class customLayout extends LayoutBase {

       

      public var layoutTarget:GroupBase;

       

      public var count:int;

       

      public var dataProvider:ArrayCollection;

       

      public var maxHeight:Number = 0;

       

      public var maxWidth:Number;

       

      public var x:Number;

       

      public var y:Number;

       

       

      public function setLayout():void {

      layoutTarget =

      this.target;

      dataProvider = ArrayCollection(DataGroup(target).dataProvider);

      count = layoutTarget.numElements;

      dataProvider.source.sortOn([

      "Height"], [Array.NUMERIC | Array.DESCENDING]);

       

      if (dataProvider[0].Height > dataProvider[1].Height) {

      dataProvider[0].xPos = 0;

      dataProvider[1].xPos = 60;

      }

       

      else if (dataProvider[1].Height > dataProvider[0].Height) {

      dataProvider[1].xPos = 0;

      dataProvider[0].xPos = 60;

      }

      }

       

       

      override public function updateDisplayList(containerWidth:Number, containerHeight:Number):void {

       

      for (var ii:int = 0; ii < count; ii++) {

       

      // get the current element, we're going to work with the

       

      // ILayoutElement interface

       

       

      var element:ILayoutElement = layoutTarget.getElementAt(ii);

       

      var item:ItemRenderer = target.getElementAt(ii) as ItemRenderer;

       

       

      // Resize the element to its preferred size by passing

       

      // NaN for the width and height constraints

      element.setLayoutBoundsSize(NaN, NaN);

       

       

      // Find out the element's dimensions sizes.

       

      // We do this after the element has been already resized

       

      // to its preferred size.

       

      var elementWidth:Number = element.getLayoutBoundsWidth();

       

      var elementHeight:Number = element.getLayoutBoundsHeight();

      item.uid = String(ii);

       

      y = 0;

      x = dataProvider[ii].xPos;

       

      // Find maximum element extents. This is needed for

       

      // the scrolling support.

      maxWidth = 50;

      maxHeight = dataProvider[ii].Height;

       

       

      // Position the element

      element.setLayoutBoundsPosition(x, y);

      element.setLayoutBoundsSize(maxWidth, maxHeight);

      }

       

      // Scrolling support - update the content size

      layoutTarget.setContentSize(maxWidth, maxHeight);

      }

      }

      }

       

       

      ItemRenderer:

       

      <?xml version="1.0" encoding="utf-8"?>

      <s:ItemRenderer

      focusEnabled="false"

      xmlns:fx="

      http://ns.adobe.com/mxml/2009"

      xmlns:s="

      library://ns.adobe.com/flex/spark"

      height="

      100%" width="100%" alpha="1.0" buttonMode="true"

      useHandCursor="

      true" xmlns:mx="library://ns.adobe.com/flex/halo"

      mouseOut="mouseOutHandler(event)"

      mouseMove="mouseMoveHandler(event);"

      mouseDown="mouseDownHandler(event);"

      name="

      iRenderer" depth="1" xmlns:ns="library://ns.adobe.com/flex/mx">

       

      <s:states>

       

      <s:State name="State1"/>

       

      <s:State name="modify"/>

       

      </s:states>

       

       

      <fx:Script>

      <![CDATA[

       

      import mx.core.DragSource;

       

      import mx.managers.CursorManager;

       

      import mx.managers.DragManager;

       

      [

      Embed(source="images/reSize.gif")]

       

      public var reSize:Class;

       

       

      public static const RESIZE_CLICK:String = "resizeClick";

       

      private function mouseDownHandler(event:MouseEvent):void {

       

      if (event.localY >= (this.height - 10) && event.localY <= this.height && event.currentTarget.name == 'iRenderer') {

      CursorManager.setCursor(reSize, 0, 0, -8);

       

      var rbEvent:MouseEvent = new MouseEvent(RESIZE_CLICK, true);

      rbEvent.localX = event.stageX;

      rbEvent.localY = event.stageY;

      dispatchEvent(rbEvent);

      }

      }

       

       

      private function mouseOutHandler(event:MouseEvent):void {

       

      if (event.buttonDown == false) {

      CursorManager.removeAllCursors();

      }

      }

       

       

      private function mouseMoveHandler(event:MouseEvent):void {

       

      var target:String = event.currentTarget.toString();

       

      var target2:String = event.target.toString();

       

       

      if (event.buttonDown == true && event.currentTarget.name == 'iRenderer' && event.localY < (this.height - 10)) {

       

      var dragInitiator:ItemRenderer = ItemRenderer(event.currentTarget);

       

      var ds:DragSource = new DragSource();

      DragManager.doDrag(dragInitiator, ds, event);

      }

       

      else if (event.localY >= (this.height - 10) && event.localY <= this.height && event.currentTarget.name == 'iRenderer') {

      CursorManager.setCursor(reSize, 0, 0, -8);

      }

       

      else {

      CursorManager.removeAllCursors();

      }

      }

       

      ]]>

       

      </fx:Script>

       

       

      <s:SkinnableContainer id="apPanel" top="0" bottom="0" left="0" right="0" >

       

      <!-- layer 1: border -->

       

      <s:Rect left="0" right="0" top="0" bottom="0">

       

      <s:stroke>

       

      <s:SolidColorStroke color="#5E7788" alpha="1.0" weight="2" />

       

      </s:stroke>

       

      </s:Rect>

       

      <!-- layer 2: background fill -->

       

      <s:Rect id="background" left="1" top="1" right="1" bottom="1">

       

      <s:fill>

       

      <s:SolidColor color="0x5E7788" id="bgFill" alpha="1.0" />

       

      </s:fill>

       

      </s:Rect>

       

      <!-- layer 3: title bar fill -->

       

      <s:Rect left="2" right="2" top="2" height.State1="15" height.modify="30">

       

      <s:fill>

       

      <s:SolidColor color="white" alpha="1.0"/>

       

      </s:fill>

       

      </s:Rect>

       

      <s:Label id="titleDisplay" text="{data.Label}" top="3" left="2" right="2" height="15" verticalAlign="middle" fontWeight="bold" includeIn="State1" fontSize="10"/>

       

      </s:SkinnableContainer>

       

      </s:ItemRenderer>

       

        • 1. Re: DataGroup Drag Enter Issue/Question (FB4)
          Flex harUI Adobe Employee

          In Flex 3 List had some default behavior that I don't think is in DataGroup

          but is in s:List

          • 2. Re: DataGroup Drag Enter Issue/Question (FB4)
            jfillman Level 1

            I had wondered whether or not a DataGroup was drag & drop capable. So I tested the drag enter by replacing one of the DataGroups with a group and then with a skinnableDataContainer. The result was the exact same, the drag enter event only fires when the mouse moves over one of the itemRenderers in these containers. I can't use a list because I need control of each items x, y, height, and width.

             

            So my next question is should I be getting the itemRenderer to drag & drop, or is there an underlying element in the heirarchy that I need to get?? Maybe it's a bug?

            • 3. Re: DataGroup Drag Enter Issue/Question (FB4)
              Flex harUI Adobe Employee

              I doubt it is a bug.  The target must call acceptDragDrop and do other

              handshakes.  Maybe subclass DataGroup and start copying in code from List.

              • 4. Re: DataGroup Drag Enter Issue/Question (FB4)
                Shongrunden Adobe Employee

                DataGroup and SkinnableDataContainer are not drag and drop enabled.  You will need to use a spark List.  You can still position and size renderers of a spark List you just need to do it via the data using a BasicLayout (ensure useVirtualLayout="false" on the List).

                 

                Does the following sample application help?

                 

                <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                               xmlns:s="library://ns.adobe.com/flex/spark"
                               xmlns:local="*">
                
                    <fx:Declarations>
                        <fx:Component className="MyList">
                            <s:List useVirtualLayout="false" dragEnabled="true" dropEnabled="true" height="200" width="200">
                                <s:layout>
                                    <s:BasicLayout />
                                </s:layout>
                                <s:itemRenderer>
                                    <fx:Component>
                                        <s:ItemRenderer x="{data.x}" y="{data.y}" width="{data.width}" height="{data.height}">
                                            <s:Rect width="100%" height="100%">
                                                <s:fill><s:SolidColor color="0xff0000" /></s:fill>
                                            </s:Rect>
                                            <s:Label text="{data.text}" horizontalCenter="0" verticalCenter="0" />
                                        </s:ItemRenderer>
                                    </fx:Component>
                                </s:itemRenderer>
                            </s:List>
                        </fx:Component>
                    </fx:Declarations>
                    
                    <s:HGroup>
                        <local:MyList>
                            <local:dataProvider>
                                <s:ArrayList>
                                    <fx:Object text="0" x="0" y="0" width="20" height="20" />
                                    <fx:Object text="1" x="20" y="20" width="20" height="20" />
                                    <fx:Object text="2" x="40" y="40" width="20" height="20" />
                                </s:ArrayList>
                            </local:dataProvider>
                        </local:MyList>
                        
                        <local:MyList>
                            <local:dataProvider>
                                <s:ArrayList>
                                    <fx:Object text="A" x="0" y="30" width="20" height="20" />
                                    <fx:Object text="B" x="20" y="50" width="20" height="20" />
                                    <fx:Object text="C" x="40" y="70" width="20" height="20" />
                                </s:ArrayList>
                            </local:dataProvider>
                        </local:MyList>
                    </s:HGroup>
                        
                </s:Application>
                
                1 person found this helpful
                • 5. Re: DataGroup Drag Enter Issue/Question (FB4)
                  jfillman Level 1

                  Shongrunden, Thank you! Can I drag to resize an item in a list too? If so, I believe that I can work with this.

                  • 6. Re: DataGroup Drag Enter Issue/Question (FB4)
                    jfillman Level 1

                    DataGroup and SkinnableDataContainer do have all the necessary drag events, so I should be able to use them for manual drag & drop. I actually do think this could be a bug. However, I found an odd workaround. If I add a mouseOver event that does absolutely nothing, then it appears that I can drag and drop without issue. See following code:

                     

                    <?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"

                    height="100%" width="100%" xmlns:ns1="*">

                     

                     

                     

                     

                    <fx:Script>

                    <![CDATA[

                    import mx.events.DragEvent;

                    import mx.managers.DragManager;

                     

                    import spark.components.DataGroup;

                     

                    private function dragEnterHandler(event:Event):void {

                    trace ("Drag Enter");

                    trace (event.currentTarget.id);

                    DragManager.acceptDragDrop(DataGroup(event.currentTarget));

                    }

                     

                    private function mouseOverHandler(event:MouseEvent):void {

                    //Without this function added, drag & drop stops working.

                     

                     

                     

                     

                     

                     

                     

                    }

                     

                    private function dragDropHandler(event:DragEvent):void {

                    trace ("Drag Drop");

                    trace (" Target: "+event.currentTarget.id);

                    trace (" y: "+event.localY);

                    }

                    ]]>

                    </fx:Script>

                     

                     

                     

                     

                     

                    <ns1:myDataGroup id="dgOne" left="5" top="5" width="200" bottom="5" dragEnter="dragEnterHandler(event);" mouseOver="mouseOverHandler(event)" dragDrop="dragDropHandler(event)" />

                    <ns1:myDataGroup id="dgTwo" left="220" top="5" width="200" bottom="5" dragEnter="dragEnterHandler(event);" mouseOver="mouseOverHandler(event)" dragDrop="dragDropHandler(event)" />

                    <mx:VRule left="210" top="0" bottom="0" />

                    </s:Application>