2 Replies Latest reply on Mar 23, 2010 9:27 PM by jfillman

    Drag to ResizeElements in DataGroup

    jfillman Level 1

      Am I able to drag to resize items in a DataGroup, and if so, can someone post an example? I guess my first question is, am I modifying the itemRenderer directly and then updating the dataProvider for the group once I release the mouse, or am I updating the dataProvider as I size the element? Since the itemRenderer is bound to the dataProvider, it seems like I would update the dataProvider, but I've not been successful in attempting this.

        • 1. Re: Drag to ResizeElements in DataGroup
          jfillman Level 1

          I've been able to successfully drag-resize an item in my DataGroup, HOWEVER, if I sort the DataGroup DataProvider, it does not update the display correctly. To duplicate this, use the code below. Move your cursor near the bottom of the 2nd element, click and drag it so that it is longer than the first element. Note how the itemRenderer element moves, but the text field, that is part of the itemRenderer, does not stay with the correct item.

           

          Take the following DataGroup, custom layout, and itemRenderer. If I remove the dataProvider sort, then the display updates correctly. If I sort the dataProvider, the text display item on the itemRenderer do not change.

           

          This is working sample code. The sort is irrelevant to this example, but is used to demonstrate the issue.

           

          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();"

          >

           

           

          <fx:Declarations>

           

           

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

           

           

          </fx:Declarations>

           

           

           

          <fx:Script>

          <![CDATA[

           

           

          import mx.collections.ArrayCollection;

           

          [

          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>

           

           

          Custom Layout (Try both ways, with the sort enabled, and then remove it):

           

          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);

          }

          }

          }

           

           

          Item Renderer:

           

          <?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.managers.CursorManager;

           

          [

          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') {

           

          trace ("True");

          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 mouseMoveHandler(event:MouseEvent):void {

           

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

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

          }

           

          else {

          CursorManager.removeAllCursors();

          }

          }

           

           

          private function mouseOutHandler(event:MouseEvent):void {

           

          if (event.buttonDown == false) {

          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>

          • 2. Re: Drag to ResizeElements in DataGroup
            jfillman Level 1

            So, if I loop through the arrayCollection at application startup and set value in the array to track the original position, I can then sort the arrayCollection source back to it's original order before updateDisplayList. This can't be the right way to do it, but, it works!

             

            The setOrder function in the myLayout package is called only once when the DataGroup is initialized, before it starts the layout:

             

            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 setOrder():void {

            layoutTarget =

            this.target;

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

            count = layoutTarget.numElements;

             

            for (var a:int = 1; a < dataProvider.length; a++) {

            dataProvider[a].Orig = a;

            }

            setLayout();

            }

             

             

             

            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 {

            dataProvider.source.sortOn([

            "Orig"], [Array.NUMERIC]);

             

            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);

            }

            }

            }