7 Replies Latest reply on Feb 5, 2010 8:29 AM by reidabel

    Guidance on approach - ad hoc barcharts

    reidabel

      I'm not sure how to go about this - maybe somebody can give me an overview of how best to approach it? Here's the idea:

       

      Three barcharts on the left, one each for Canada, US, and Mexico, each with the 12 months on the x axis, and a number of series of data, say 2007, 2008, and 2009. So, 12 groups of three bars in each of these three barcharts.

       

      Then, a single ad-hoc bar chart on the right, where the user can drag an entire series from one of the three barcharts on the left. So, for example, the user could drag and drop the series: Canada 2007 and 2009, Mexico 2008, and US 2009, ONTO the barchart on the right, and it would then have these as four individual series. So, 12 groups of four bars.

       

      Should I code the drag-and-drop operations to manipulate an array (or is it arrayCollection?) that is used as a dataprovider for the ad-hoc barchart?

       

      Should I do something inside the barchart instead? Like, adding a series on the fly and populating it with the data coded into the dragSource? How do I get at the data values within an individual series?

       

      Is there a different (and better?) way to do it?

       

      Also, a co-worker and I attended a Flash User's Group meeting a year ago where we thought we saw the Adobe presenter drag and drop series from one barchart into a piechart, and we got the impression that that capability was built into Flex. If so, it doesn't seem that I can find it. Does anyone know if this should be built-in and automatic? I found that mx:BarChart has dragEnabled, dragMoveEnabled, and dropEnabled, but that setting them to true

      doesn't allow me to drag and drop. I had to code the barchart's mouseDown and the list's dragEnterHandler manually to get the list to accept a drop of data from the barchart. Is that the only way to do it?

       

      Thanks for any help you can provide,

       

      Reid

        • 1. Re: Guidance on approach - ad hoc barcharts
          SunilAdobe Adobe Employee

          First things first

           

          Charts support only dragging, but they do not handle the drop, similar to datagrid.

          The items when dragged have the format "chartitems", so that one could figure out that it was dragged from a chart

          You can access the items of a series using the items property available in the series

          You can access the dataprovider for the series, using the dataprovider property (in chartelement) from which series derives

           

          I have attached a basic example which illustrate the various events, this might be useful to understand the capabilities of drag and drop.

          Also this blog entry illustrates some examples for line series http://sunban.wordpress.com/2007/12/03/drag-and-drop-line-series-segments/

           

          With these examples, hopefully you should be able to solve the issues that you are facing.

           

          Hope this helps.

           

          Thanks

          -Sunil

          1 person found this helpful
          • 2. Re: Guidance on approach - ad hoc barcharts
            reidabel Level 1

            Wonderful! Thanks for the quick response - I'll start reading these things and try to figure things out. It takes a long time for a newbie to figure this stuff out, even with a lot of education and experience. I just started on this stuff a few weeks ago ...

             

            Reid

            • 3. Re: Guidance on approach - ad hoc barcharts
              SunilAdobe Adobe Employee

                    

              Looks like the attachments did not come through.

              I'm pasting the code here, hopefully it should get formatted correctly

               

              <?xml version="1.0"?>
              <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" borderStyle="solid" >
              
                  <mx:Script>  
                        
                       <![CDATA[  
                          
                      import mx.collections.ArrayCollection;
                  
                      [Bindable]
                      private var medalsAC:ArrayCollection = new ArrayCollection( [
                         { Country: "USA", Gold: 35, Silver:39, Bronze: 29 },
                         { Country: "China", Gold: 32, Silver:17, Bronze: 14 }, 
                         { Country: "Russia", Gold: 27, Silver:27, Bronze: 38 } ]);
                         
                       [Bindable]
                      private var medalsAC1:ArrayCollection = new ArrayCollection( [ 
                         { Country: "Russia", Gold: 27, Silver:27, Bronze: 38 } ]);
                           
                             import mx.events.DragEvent;
                          import mx.controls.List;
                          import mx.managers.DragManager;
                          import mx.core.DragSource;
                          import mx.charts.chartClasses.ChartBase;
              
                  
                          private function doDragEnter(event:DragEvent):void {
                              var dragInitiator:ChartBase=ChartBase(event.currentTarget);
                              tiEnter.text += "dragEnter triggered" + "\n";
                              DragManager.acceptDragDrop(dragInitiator);
                          }
              
                          private function doDragOver(event:DragEvent):void {
                              tiOver.text += "dragOver triggered" + "\n";
                              if (event.ctrlKey)
                                  DragManager.showFeedback(DragManager.COPY);
                              else if (event.shiftKey)
                                  DragManager.showFeedback(DragManager.LINK);
                              else
                                  DragManager.showFeedback(DragManager.MOVE);
                          }
              
                          private function doDragDrop(event:DragEvent):void {
                              // Get drop target.
                              var dropTarget:ChartBase=ChartBase(event.currentTarget);
                              
                              // Write message to TextArea control.
                              tiDrop.text += "dragDrop triggered" + "\n";
              
                              // Hide drop feedback.
                              doDragExit(event);
                              
                              // Get the dragged items from the drag initiator.
                              var items:Array = event.dragSource.dataForFormat("chartitems") as Array;
                              
                              // Write status message to TextArea control.
                              tiDrop.text += "length: " + String(items.length) + "\n" + "format: " +
                                  String(event.dragSource.formats[0])+ "\n";
                                     
                              // Add each item to the drop target.
                              for(var i:uint=0; i < items.length; i++)
                              {
                                dropTarget.dataProvider.addItem(items[i].item);
                              }
                          }
              
                          private function doDragComplete(event:DragEvent):void {
                              tiComplete.text += "dragComplete triggered" + "\n";
                          }
                      
                          private function doDragExit(event:DragEvent):void {
                              var dropTarget:ChartBase=ChartBase(event.currentTarget);
                              tiExit.text += "dragExit triggered" + "\n";
                              dropTarget.hideDropFeedback(event);
                          }          
                      ]]>
                  </mx:Script>
                   
                  <mx:Panel title="Drag and Drop Example" 
                      height="603" width="743" layout="absolute">
                      <mx:HBox width="687" height="269">
                          <mx:ColumnChart id="column" height="100%" width="45%" 
                              paddingLeft="5" paddingRight="5" 
                              showDataTips="true" dataProvider="{medalsAC1}" selectionMode="multiple" description="mychart" dragEnabled="true" dropEnabled="true"
                              dragEnter="doDragEnter(event);"
                               dragExit="doDragExit(event);" 
                               dragOver="doDragOver(event);"
                               dragDrop="doDragDrop(event);">
                                  
                              <mx:horizontalAxis>
                                  <mx:CategoryAxis categoryField="Country"/>
                              </mx:horizontalAxis> 
                                      
                              <mx:series>
                                 <mx:ColumnSeries xField="Country" yField="Gold" displayName="Gold" selectable = "false" itemRenderer="mx.charts.renderers.ShadowBoxItemRenderer" labelPosition="inside"/>                
                              </mx:series>
                                
                          </mx:ColumnChart>
                          <mx:Legend dataProvider="{column}"/>
                          <mx:BarChart id="bar" height="100%" width="45%" 
                          paddingLeft="5" paddingRight="5" 
                          showDataTips="true" dataProvider="{medalsAC}" selectionMode="multiple" dropEnabled="true" dragEnabled="true"
                                      dragComplete="doDragComplete(event);" >
                                 
                          <mx:verticalAxis> 
                              <mx:CategoryAxis categoryField="Country"/>
                          </mx:verticalAxis>
                              
                          <mx:series> 
                              <mx:BarSeries yField="Country" xField="Gold" displayName="Gold" selectable = "true" />
                              <mx:BarSeries yField="Country" xField="Silver" displayName="Silver" selectable = "false"/>
                              <mx:BarSeries yField="Country" xField="Bronze" displayName="Bronze" selectable = "false"/>
                          </mx:series>
                          </mx:BarChart>
                          <mx:Legend dataProvider="{bar}"/>
                      </mx:HBox>
                      <mx:Canvas width="677" height="244" x="10" y="277">
                          <mx:HBox height="60" y="9" x="4">
                              <mx:Label text="dragDrop: "/>
                              <mx:TextArea id="tiDrop" width="182" height="60"/>
                          </mx:HBox>
                          <mx:HBox x="268" y="9" height="60">
                              <mx:Label text="dragEnter: "/>
                              <mx:TextArea id="tiEnter" width="182" height="60"/>
                          </mx:HBox>
                          <mx:HBox x="5" y="91" height="60">
                              <mx:Label text="dragOver: "/>
                              <mx:TextArea id="tiOver" width="182" height="60"/>
                          </mx:HBox>
                          <mx:HBox x="266" y="91" height="60">
                              <mx:Label text="dragExit: "/>
                              <mx:TextArea id="tiExit" width="182" height="60"/>
                          </mx:HBox>
                          <mx:HBox x="5" y="168" height="60">
                              <mx:Label text="dragComplete: "/>
                              <mx:TextArea id="tiComplete" width="182" height="60"/>
                          </mx:HBox>
                      </mx:Canvas>
                  </mx:Panel>
              </mx:Application>
              

               

              1 person found this helpful
              • 4. Re: Guidance on approach - ad hoc barcharts
                reidabel Level 1

                Thanks again. Just a comment as I get started here.

                 

                It appears that the code tips are not helping me out much. I searched the list that popped up when I typed the dot at the end of:

                 

                barchart1.series[0].

                 

                ... and "items" was not in the list. Same with "barchart1.series." However, since you specifically mentioned it, I tried (in my barchart's mouseDownHandler where var ds:DragSource = new DragSource():

                 

                ds.addData(barchart1.series[1].items,

                'items');

                 

                ... and it actually compiled and let me drop onto the list! I will need an item renderer to handle the [Object] stuff, but it took the drop.

                 

                So the lesson for me here is that I can't count on the IDE giving an accurate list of the properties that are available for use.

                 

                Or am I doing something wrong? Is it because series[] is an array?

                • 5. Re: Guidance on approach - ad hoc barcharts
                  Deeptika Gottipati Adobe Employee

                  barchart1.series is an Array and barchart1.series[1] is an Object. So we should cast the object series[i] to Series (or BarSeries in this case) before accessing its properties. That would show the appropriate properties in code-hinting.

                  • 6. Re: Guidance on approach - ad hoc barcharts
                    reidabel Level 1

                    Thanks Deeptika, I tried it and ...

                     

                    BarSeries(barchart1.series[1]).

                     

                    ... does indeed provide "items" in the list that code hinting pops up. However,

                     

                    Series(barchart1.series[1]).

                     

                    ... does not. So I know which one to use now!

                    • 7. Re: Guidance on approach - ad hoc barcharts
                      reidabel Level 1

                      Sunil, thanks for pointing me in the right direction. It seems that the answer to my question is that I should:

                       

                      manipulate the ArrayCollections that serve as the dataProviders

                       

                      for the bar/column charts being used. The charts then take care of themselves (display). I was able to extend your code out so that I can now drag and drop series (Countries) from the bar chart into the column chart and vice versa (add the drag-and-drop events to both charts, not just the one). With the Control key held (or not), I can have it copy or move the series from one chart into the other. I can also prevent it from receiving the same series twice, which was an issue with the example code. Here is the doDragDrop function that will help if anybody else wants to do this. The other drag-and-drop functions worked fine as you had them.

                       

                      I hope the formatting works out here:

                       

                      private function doDragDrop(event:DragEvent):void {

                        // Get a reference to both the source and target charts

                        var dropTarget:ChartBase=ChartBase(event.currentTarget);

                       

                        var dragFrom:ChartBase=ChartBase(event.dragInitiator);

                       

                        // Hide drop feedback.

                        doDragExit(event);

                       

                       

                        // Get the dragged items from the drag initiator - a Country

                       

                        var items:Array = event.dragSource.dataForFormat("chartitems") as Array;

                       

                        //Find out if this item is already in the chart we are dropping on

                       

                        var Found:Boolean = false;

                       

                       

                       

                        for (var x:int=0; x < dropTarget.dataProvider.length; x++)

                        {

                       

                          if ((items[0].item.Country) == (dropTarget.dataProvider.getItemAt(x).Country))

                          {

                            Found = true;

                       

                            //I don't yet know the command to break out of a for loop in the middle of the iteration. Anybody?

                          }

                       

                        }

                       

                       

                      if (!Found)

                        {

                          //Drop the country onto the target, at the front of it (for now, I want to find out how to drop it in between existing series)

                          dropTarget.dataProvider.addItemAt(items[0].item, 0);

                       

                       

                       

                          //Remove the item from the chart that it is coming from, unless the user

                          //has the Control key pressed

                          if (!event.ctrlKey)

                          {

                       

                            var dragFromIndex:int = -1;

                       

                       

                            for (var df_cnt:int = 0; df_cnt < dragFrom.dataProvider.length; df_cnt++)

                            {

                       

                              if (dragFrom.dataProvider.getItemAt(df_cnt).Country == items[0].item.Country)

                              {

                                dragFromIndex = df_cnt;

                                //Again, add code here to break out of the for loop since we have found what we're looking for

                              }

                            }

                       

                       

                            if (dragFromIndex > -1)

                            {

                              //Remove the item (country) from the chart it came from

                             

                      dragFrom.dataProvider.removeItemAt(dragFromIndex);

                            }

                          }

                        }

                       

                      Thanks,

                       

                      Reid

                      }