I have a bubble chart with a custom renderer which is a pie chart.  I
bind the chart to data which is an array of complex objects which
themselves contain references to other data objects in my application.  

The data displayed on the chart does not come from the bound object
but from the object that it contains.  

So the main chart looks like this

<mx:BubbleChart xmlns:mx="http://www.adobe.com/2006/mxml";
xmlns:graphs="pmco.graphs.*">
....<mx:series>
........<graphs:LinearAreaBubbleSeries
............dataProvider="{fBubbles.bubbles}" 
............xField="x" 
............yField="y" 
............radiusField="radius" 
............itemRenderer="pmco.tv.tv_RSPPiePoint"
............minRadius="5"
............maxRadius="100"
............ showDataEffect="rearrangeData"
............id="bubbleSeries"/>
....</mx:series>
</mx:BubbleChart>

LinearAreaBubbleSeries is just an overloaded BubbleSeries which scales
areas rather than radii with bubble  value.

The item renderer is a canvas with a pie chart on it (I have omitted
script code for brevity).

<mx:Canvas 
....xmlns:mx="http://www.adobe.com/2006/mxml"; 
....width="400" height="300" 
....horizontalScrollPolicy="off" verticalScrollPolicy="off" 
....implements="pmco.graphs.IPiePoint">

....<mx:PieChart id="chart" height="100%" width="100%"
            paddingRight="0" paddingLeft="0"
            showDataTips="false" 
            added="init_Pie()"
             left="0" top="0">
........<mx:series>
............<mx:PieSeries 
................dataProvider="{RSPBubble(data.item).Slices}" 
................nameField="name" field="size" 
................labelPosition="none" 
................id="pieSeries" 
................fills="{data.item.fillColours}">
............</mx:PieSeries>
........</mx:series>

....</mx:PieChart>

</mx:Canvas>

the data items are complex objects (RSPBubble) which refer to an
underlying object which contains the real data (Competitor) (silly is
there because I can't figure out how to make the bubble chart show a
single series, it only shows anything when there are two bubbles, so I
add a silly one by default, a hack for another message...)

package pmco.graphs
{
....import pmco.pojos.Competitor;
....import mx.collections.ArrayCollection;
....import pmco.utils.PieSegment;
....import pmco.pojos.States;
....import mx.graphics.SolidColor;
....import pmco.pojos.User;
....
....[Bindable]
....public class RSPBubble
....{
........public var competitor:Competitor;
........public var silly:Boolean;
........public function toString():String
........{
............return competitor.name;
........}
........public function get y():Number
........{
............if (silly) return -99.99;
............return competitor.market_attractiveness;
........}
........public function set y(_y:Number):void
........{
............if (!silly) competitor.market_attractiveness = _y;
........}
........public function get x():Number
........{
............if (silly) return -99.99;
............return competitor.competitive_position;
........}
........public function set x(_x:Number):void
........{
............if (!silly) competitor.competitive_position = _x;
........}
........public function get total():Number
........{
............if (silly) return 0;
............return competitor.potential;
........}
........
........public function get fillColours():Array
........{
............if (silly) return null;
............return competitor.fillColours
........}
........
........// Artificially create pie slices
........public function get Slices():ArrayCollection
........{
............if (silly) return pieSegments;
............return competitor.Slices;
........}
....}
}

The point of the RSPBubble object is to abstract the chart rendering
from the underlying data and to be able to switch which data gets
displayed by adjusting the properties of the bubble, not the
underlying value object.  I haven't quite managed to do this cleanly
so the value object still has some remnants of chart knowledge (again,
snipped for brevity):

package pmco.pojos
{
....import mx.collections.ArrayCollection;
....import mx.graphics.SolidColor;
....import mx.formatters.CurrencyFormatter;
....import pmco.utils.PieSegment;
....import pmco.interfaces.IAssumptionOwner;
....import pmco.interfaces.INotesOwner;
....import pmco.interfaces.IPojo;
....
....[Managed]
....[RemoteClass(alias="pmco.pojos.Competitor")]
....public class Competitor implements IPojo
....{........  

........private var arrFillColours:Array;
........public function get fillColours():Array
........{
............if (arrFillColours == null)
............{
................arrFillColours = new Array();
................arrFillColours.push(new
SolidColor(States.STATUS_COLOUR[state],States.ALPHA_VALUE));
................if (isus)
................{
....................arrFillColours.push(new
SolidColor(States.COLOUR_BUBBLE_BACKGROUND,States.ALPHA_VALUE));
................}
................else
................{
....................arrFillColours.push(new
SolidColor(States.COLOUR_BUBBLE_BACKGROUND_C,States.ALPHA_VALUE));
................}
............}
............return arrFillColours;
........}

........private var pieSegments:ArrayCollection;
........public function get Slices():ArrayCollection
........{
............if (pieSegments == null)
............{
................//var c:int = States.STATUS_COLOUR[state];
................pieSegments = new ArrayCollection();
................// take care of the case when the target and potential
are 0
................if (target == 0 && potential == 0)
................{
....................pieSegments.addItem(new PieSegment(target, name,
state));
....................pieSegments.addItem(new PieSegment(1, "Remaining
Potential", -1));
................}
................else
................{
....................pieSegments.addItem(new PieSegment(target, name,
state));
....................pieSegments.addItem(new PieSegment(potential -
target, "Remaining Potential", -1));
................}
............}
............return pieSegments;
........}
....}
}

and to complete the picture the pieSegment object is as follows:

package pmco.utils
{
....import mx.graphics.SolidColor;
....import pmco.pojos.Competitor;
....import pmco.pojos.States;
....import mx.charts.series.items.BubbleSeriesItem;
....
....public class PieSegment extends BubbleSeriesItem
....{
........public var size:Number;
........public var name:String;
........public var state:int;
........public function PieSegment(sz:Number, nm:String, st:int)
........{
............size = sz;
............name = nm;
............state = st;
............
........}
....}
}

The real issue is with fillColours which controls which colour my pie
slices are, and Slices which controls how big the slices are.

When I run this code I get trace messages as follows:

warning: unable to bind to property 'item' on class
'mx.charts.series.items::BubbleSeriesItem'
warning: unable to bind to property 'fillColours' on class
'pmco.graphs::RSPBubble'
warning: unable to bind to property 'Slices' on class
'pmco.graphs::RSPBubble'

Perhaps predictably when I adjust the underlying value object
(competitor on a RSPBubble instance) nothing happens to the chart, but
I can force the chart to re-bind and thereby get the data again, so
one way or another I can get some interactivity.  Specifically I want
to be able to change the colours and sizes of the slices dynamically
on a user interaction.

So I have a couple of questions:
1) what is causing the trace messages?
2) can I bind to a getter?
3) is there a better/nicer/cleaner way to do this?

Any clues?

SP

P.S. I know I spell colour properly.



Reply via email to