PageRenderTime 60ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/charts/as/Charts.as

https://github.com/sdesai/yui2
ActionScript | 1614 lines | 1259 code | 139 blank | 216 comment | 232 complexity | fac34910cd6d9154ff815831ea81dea6 MD5 | raw file
  1. package
  2. {
  3. import com.adobe.serialization.json.JSON;
  4. import com.yahoo.astra.fl.charts.*;
  5. import com.yahoo.astra.fl.charts.events.ChartEvent;
  6. import com.yahoo.astra.fl.charts.legend.Legend;
  7. import com.yahoo.astra.fl.charts.series.*;
  8. import com.yahoo.astra.fl.charts.skins.*;
  9. import com.yahoo.astra.fl.utils.UIComponentUtil;
  10. import com.yahoo.astra.utils.InstanceFactory;
  11. import com.yahoo.astra.utils.JavaScriptUtil;
  12. import com.yahoo.yui.LoggerCategory;
  13. import com.yahoo.yui.YUIAdapter;
  14. import com.yahoo.yui.charts.*;
  15. import com.yahoo.util.ImageExport;
  16. import fl.core.UIComponent;
  17. import flash.display.DisplayObject;
  18. import flash.display.Shape;
  19. import flash.display.Sprite;
  20. import flash.events.ErrorEvent;
  21. import flash.events.MouseEvent;
  22. import flash.external.ExternalInterface;
  23. import flash.text.TextFormat;
  24. import flash.utils.getDefinitionByName;
  25. import flash.utils.getQualifiedClassName;
  26. import flash.system.Capabilities;
  27. [SWF(backgroundColor=0xffffff)]
  28. /**
  29. * A wrapper for the Astra Charts components to allow them to be used by the YUI library.
  30. *
  31. * @author Josh Tynjala
  32. */
  33. public class Charts extends YUIAdapter
  34. {
  35. /**
  36. * @private
  37. * Path for all skin classes
  38. */
  39. private static const SKIN_NAMESPACE:String = "com.yahoo.astra.fl.charts.skins::";
  40. //--------------------------------------
  41. // Constructor
  42. //--------------------------------------
  43. /**
  44. * Constructor.
  45. */
  46. public function Charts()
  47. {
  48. super();
  49. this.setImageExport();
  50. }
  51. //--------------------------------------
  52. // Properties
  53. //--------------------------------------
  54. /**
  55. * @private
  56. * A reference to the chart instance.
  57. */
  58. protected var chart:Chart;
  59. /**
  60. * @private
  61. * The type of the chart specified by setType().
  62. */
  63. protected var type:String;
  64. /**
  65. * @private
  66. * A reference to the legend instance.
  67. */
  68. protected var legend:Legend;
  69. /**
  70. * @private
  71. * Storage for the legendDisplay property.
  72. */
  73. protected var _legendDisplay:String = "none";
  74. /**
  75. * @private
  76. * Specifies the location of the legend, or "none" if the legend
  77. * is not to be displayed.
  78. */
  79. public function get legendDisplay():String
  80. {
  81. return this._legendDisplay;
  82. }
  83. /**
  84. * @private
  85. */
  86. public function set legendDisplay(value:String):void
  87. {
  88. this._legendDisplay = value;
  89. this.refreshComponentSize();
  90. }
  91. /**
  92. * @private
  93. * Storage for the spacing property.
  94. */
  95. protected var _spacing:Number = 6;
  96. /**
  97. * @private
  98. * The spacing between the chart and other objects, such as the legend.
  99. */
  100. public function get spacing():Number
  101. {
  102. return this._spacing;
  103. }
  104. /**
  105. * @private
  106. */
  107. public function set spacing(value:Number):void
  108. {
  109. this._spacing = value;
  110. this.refreshComponentSize();
  111. }
  112. /**
  113. * @private
  114. * Storage for the padding property.
  115. */
  116. protected var _padding:Number = 10;
  117. /**
  118. * @private
  119. * The padding around the chart, in pixels.
  120. */
  121. public function get padding():Number
  122. {
  123. return this._padding;
  124. }
  125. /**
  126. * @private
  127. */
  128. public function set padding(value:Number):void
  129. {
  130. this._padding = value;
  131. }
  132. /**
  133. * @private
  134. */
  135. protected var backgroundAndBorder:BackgroundAndBorder;
  136. /**
  137. * @private
  138. */
  139. override protected function get component():DisplayObject
  140. {
  141. //why do I have to do this? it's not ambiguous!
  142. return super.component;
  143. }
  144. /**
  145. * @private
  146. */
  147. override protected function set component(value:DisplayObject):void
  148. {
  149. this.chart = Chart(value);
  150. this.chart.addEventListener(ErrorEvent.ERROR, chartErrorHandler);
  151. super.component = value;
  152. }
  153. //--------------------------------------
  154. // Public Methods
  155. //--------------------------------------
  156. /**
  157. * Creates a chart instance based on the specified type.
  158. */
  159. public function setType(value:String):void
  160. {
  161. if(this.chart)
  162. {
  163. this.removeChild(this.chart);
  164. this.chart.removeEventListener(ChartEvent.ITEM_CLICK, chartItemEventHandler);
  165. this.chart.removeEventListener(ChartEvent.ITEM_DOUBLE_CLICK, chartItemEventHandler);
  166. this.chart.removeEventListener(ChartEvent.ITEM_ROLL_OUT, chartItemEventHandler);
  167. this.chart.removeEventListener(ChartEvent.ITEM_ROLL_OVER, chartItemEventHandler);
  168. this.chart.removeEventListener(MouseEvent.MOUSE_DOWN, chartItemExtraEventHandler);
  169. }
  170. this.type = value;
  171. var ChartType:Class = ChartSerializer.getType(this.type);
  172. var chart:Chart = new ChartType();
  173. chart.setStyle("contentPadding", 0);
  174. chart.setStyle("backgroundSkin", Sprite);
  175. var backgroundFactory:InstanceFactory = this.createBorderBackgroundFactory();
  176. backgroundFactory.properties.fillColor = 0xffffff;
  177. backgroundFactory.properties.fillAlpha = 0.9;
  178. backgroundFactory.properties.borderWeight = 1;
  179. backgroundFactory.properties.borderColor = 0x000000;
  180. chart.setStyle("dataTipBackgroundSkin", backgroundFactory);
  181. chart.setStyle("seriesMarkerSkins", []);
  182. this.addChildAt(chart, 1);
  183. this.component = chart;
  184. this.chart.addEventListener(ChartEvent.ITEM_CLICK, chartItemEventHandler, false, 0, true);
  185. this.chart.addEventListener(ChartEvent.ITEM_DOUBLE_CLICK, chartItemEventHandler, false, 0, true);
  186. this.chart.addEventListener(ChartEvent.ITEM_ROLL_OUT, chartItemEventHandler, false, 0, true);
  187. this.chart.addEventListener(ChartEvent.ITEM_ROLL_OVER, chartItemEventHandler, false, 0, true);
  188. this.chart.addEventListener(MouseEvent.MOUSE_DOWN, chartItemExtraEventHandler, false, 0, true);
  189. this.chart.legend = this.legend;
  190. this.log("Type set to \"" + this.type + "\"");
  191. }
  192. public function setDataProvider(value:Array):void
  193. {
  194. var dataProvider:Array = [];
  195. var seriesCount:int = value.length;
  196. var seriesStyles:Array = [];
  197. for(var i:int = 0; i < seriesCount; i++)
  198. {
  199. var dataFromJavaScript:Object = value[i];
  200. var currentData:ISeries = this.chart.dataProvider[i] as ISeries;
  201. var seriesType:Class = SeriesSerializer.shortNameToSeriesType(dataFromJavaScript.type ? dataFromJavaScript.type : this.type);
  202. var series:ISeries;
  203. if(currentData && getDefinitionByName(getQualifiedClassName(currentData)) == seriesType)
  204. {
  205. //reuse the series if possible because we want animation
  206. series = SeriesSerializer.readSeries(dataFromJavaScript, currentData);
  207. }
  208. else
  209. {
  210. series = SeriesSerializer.readSeries(dataFromJavaScript);
  211. }
  212. dataProvider[i] = series;
  213. //this is where we parse the individual series styles, and we convert them
  214. //to the format the chart actually expects.
  215. //we fill in with defaults for styles that have not been specified
  216. if(dataFromJavaScript.style)
  217. {
  218. seriesStyles.push(dataFromJavaScript.style);
  219. }
  220. else seriesStyles.push(null);
  221. }
  222. this.log("Displaying " + seriesCount + " series.");
  223. //set data provider and new styles
  224. this.chart.dataProvider = dataProvider;
  225. //make sures the series are created!
  226. this.chart.drawNow();
  227. //set the styles for the series
  228. this.setSeriesStyles(seriesStyles);
  229. this.refreshComponentSize();
  230. }
  231. /**
  232. * Returns the category names.
  233. */
  234. public function getCategoryNames():Array
  235. {
  236. var categoryChart:ICategoryChart = this.chart as ICategoryChart;
  237. if(categoryChart)
  238. {
  239. return categoryChart.categoryNames;
  240. }
  241. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  242. this.log("Cannot find categoryNames on a chart of type " + shortName, LoggerCategory.WARN);
  243. return null;
  244. }
  245. /**
  246. * Sets the category names used if the data requires a category axis.
  247. * This field should be used if the data does not define the category
  248. * values directly.
  249. */
  250. public function setCategoryNames(value:Array):void
  251. {
  252. var categoryChart:ICategoryChart = this.chart as ICategoryChart;
  253. if(categoryChart)
  254. {
  255. categoryChart.categoryNames = value;
  256. }
  257. else
  258. {
  259. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  260. this.log("Unable to set categoryNames on a chart of type " + shortName, LoggerCategory.WARN);
  261. }
  262. }
  263. /**
  264. * Returns the field used in complex objects to access data to be
  265. * displayed on the PieChart.
  266. */
  267. public function getDataField():String
  268. {
  269. var pieChart:PieChart = this.chart as PieChart;
  270. if(pieChart)
  271. {
  272. return pieChart.dataField;
  273. }
  274. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  275. this.log("Unable to find dataField on a chart of type " + shortName, LoggerCategory.WARN);
  276. return null;
  277. }
  278. /**
  279. * Sets the field used in complex objects to access data to be displayed
  280. * on the PieChart.
  281. */
  282. public function setDataField(value:String):void
  283. {
  284. var pieChart:PieChart = this.chart as PieChart;
  285. if(pieChart)
  286. {
  287. pieChart.dataField = value;
  288. }
  289. else
  290. {
  291. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  292. this.log("Unable to set dataField on a chart of type " + shortName, LoggerCategory.WARN);
  293. }
  294. }
  295. /**
  296. * Returns the field used in complex objects to access categories to be
  297. * displayed on the PieChart.
  298. */
  299. public function getCategoryField():String
  300. {
  301. var pieChart:PieChart = this.chart as PieChart;
  302. if(pieChart)
  303. {
  304. return pieChart.categoryField;
  305. }
  306. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  307. this.log("Unable to find categoryField on a chart of type " + shortName, LoggerCategory.WARN);
  308. return null;
  309. }
  310. /**
  311. * Sets the field used in complex objects to access categories to be displayed
  312. * on the PieChart.
  313. */
  314. public function setCategoryField(value:String):void
  315. {
  316. var pieChart:PieChart = this.chart as PieChart;
  317. if(pieChart)
  318. {
  319. pieChart.categoryField = value;
  320. }
  321. else
  322. {
  323. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  324. this.log("Unable to set categoryField on a chart of type " + shortName, LoggerCategory.WARN);
  325. }
  326. }
  327. /**
  328. * Returns the field used in complex objects to access data to be
  329. * displayed on the horizontal axis.
  330. */
  331. public function getHorizontalField():String
  332. {
  333. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  334. if(cartesianChart)
  335. {
  336. return cartesianChart.horizontalField;
  337. }
  338. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  339. this.log("Unable to find horizontalField on a chart of type " + shortName, LoggerCategory.WARN);
  340. return null;
  341. }
  342. /**
  343. * Sets the field used in complex objects to access data to be displayed
  344. * on the horizontal axis. If the input data is XML, and the field is an
  345. * attribute, be sure to include the "@" symbol at the beginning of the
  346. * field name.
  347. */
  348. public function setHorizontalField(value:String):void
  349. {
  350. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  351. if(cartesianChart)
  352. {
  353. cartesianChart.horizontalField = value;
  354. }
  355. else
  356. {
  357. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  358. this.log("Unable to set horizontalField on a chart of type " + shortName, LoggerCategory.WARN);
  359. }
  360. }
  361. /**
  362. * Returns the field used in complex objects to access data to be
  363. * displayed on the vertical axis.
  364. */
  365. public function getVerticalField():String
  366. {
  367. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  368. if(cartesianChart)
  369. {
  370. return cartesianChart.verticalField;
  371. }
  372. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  373. this.log("Unable to find verticalField on a chart of type " + shortName, LoggerCategory.WARN);
  374. return null;
  375. }
  376. /**
  377. * Sets the field used in complex objects to access data to be displayed
  378. * on the vertical axis. If the input data is XML, and the field is an
  379. * attribute, be sure to include the "@" symbol at the beginning of the
  380. * field name.
  381. */
  382. public function setVerticalField(value:String):void
  383. {
  384. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  385. if(cartesianChart)
  386. {
  387. cartesianChart.verticalField = value;
  388. }
  389. else
  390. {
  391. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  392. this.log("Unable to set verticalField on a chart of type " + shortName, LoggerCategory.WARN);
  393. }
  394. }
  395. /**
  396. * Returns the title displayed next to the vertical axis.
  397. */
  398. public function getHorizontalAxisTitle():String
  399. {
  400. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  401. if(cartesianChart)
  402. {
  403. return cartesianChart.horizontalAxisTitle;
  404. }
  405. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  406. this.log("Unable to find horizontalAxisTitle on a chart of type " + shortName, LoggerCategory.WARN);
  407. return null;
  408. }
  409. /**
  410. * Sets the title displayed next to the horizontal axis.
  411. */
  412. public function setHorizontalAxisTitle(value:String):void
  413. {
  414. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  415. if(cartesianChart)
  416. {
  417. cartesianChart.horizontalAxisTitle = value;
  418. }
  419. else
  420. {
  421. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  422. this.log("Unable to set horizontalAxisTitle on a chart of type " + shortName, LoggerCategory.WARN);
  423. }
  424. }
  425. /**
  426. * Returns the title displayed next to the vertical axis.
  427. */
  428. public function getVerticalAxisTitle():String
  429. {
  430. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  431. if(cartesianChart)
  432. {
  433. return cartesianChart.verticalAxisTitle;
  434. }
  435. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  436. this.log("Unable to find verticalAxisTitle on a chart of type " + shortName, LoggerCategory.WARN);
  437. return null;
  438. }
  439. /**
  440. * Sets the title displayed next to the vertical axis.
  441. */
  442. public function setVerticalAxisTitle(value:String):void
  443. {
  444. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  445. if(cartesianChart)
  446. {
  447. cartesianChart.verticalAxisTitle = value;
  448. }
  449. else
  450. {
  451. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  452. this.log("Unable to set verticalAxisTitle on a chart of type " + shortName, LoggerCategory.WARN);
  453. }
  454. }
  455. /**
  456. * Updates the horizontal axis with a new type.
  457. */
  458. public function setHorizontalAxis(value:Object):void
  459. {
  460. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  461. if(cartesianChart)
  462. {
  463. cartesianChart.horizontalAxis = AxisSerializer.readAxis(value);
  464. }
  465. else
  466. {
  467. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  468. this.log("Unable to set horizontalAxis on a chart of type " + shortName, LoggerCategory.WARN);
  469. }
  470. }
  471. /**
  472. * Updates the vertical axis with a new type.
  473. */
  474. public function setVerticalAxis(value:Object):void
  475. {
  476. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  477. if(cartesianChart)
  478. {
  479. cartesianChart.verticalAxis = AxisSerializer.readAxis(value);
  480. }
  481. else
  482. {
  483. var shortName:String = ChartSerializer.getShortName(getQualifiedClassName(this.chart));
  484. this.log("Unable to set verticalAxis on a chart of type " + shortName, LoggerCategory.WARN);
  485. }
  486. }
  487. /**
  488. * Sets the JavaScript function to call to generate the chart's data tip.
  489. */
  490. public function setDataTipFunction(value:String):void
  491. {
  492. var delegate:Object = {dataTipFunction: JavaScriptUtil.createCallbackFunction(value).callback};
  493. delegate.callback = function(item:Object, index:int, series:ISeries):String
  494. {
  495. return delegate.dataTipFunction(item, index, SeriesSerializer.writeSeries(series));
  496. }
  497. this.chart.dataTipFunction = delegate.callback;
  498. }
  499. /**
  500. * Sets the JavaScript function to call to format legend labels
  501. */
  502. public function setLegendLabelFunction(value:String):void
  503. {
  504. var delegate:Object = {legendLabelFunction: JavaScriptUtil.createCallbackFunction(value).callback};
  505. delegate.callback = function(value:String):String
  506. {
  507. return delegate.legendLabelFunction(value);
  508. }
  509. this.chart.legendLabelFunction = delegate.callback;
  510. }
  511. /**
  512. * Determines whether the viewport is constrained
  513. */
  514. public function setConstrainViewport(value:Boolean):void
  515. {
  516. if(this.chart is CartesianChart) (this.chart as CartesianChart).constrainViewport = value;
  517. }
  518. /**
  519. * Accepts a JSON-encoded set of styles for the chart itself.
  520. * Flash Player versions below 9.0.60 don't encode ExternalInterface
  521. * calls correctly!
  522. */
  523. public function setStyles(styles:String):void
  524. {
  525. if(!styles) return;
  526. var parsedStyles:Object = JSON.decode(styles);
  527. for(var styleName:String in parsedStyles)
  528. {
  529. this.setStyle(styleName, parsedStyles[styleName], false);
  530. }
  531. }
  532. public function setStyle(name:String, value:Object, json:Boolean = true):void
  533. {
  534. if(json && value)
  535. {
  536. //by default, we assume it's json data, only setStyles will send false
  537. value = JSON.decode(value as String);
  538. }
  539. var needsSizingRefresh:Boolean = false;
  540. switch(name)
  541. {
  542. case "padding":
  543. this.padding = value as Number;
  544. needsSizingRefresh = true;
  545. break;
  546. case "spacing":
  547. this.spacing = value as Number;
  548. needsSizingRefresh = true;
  549. break;
  550. case "animationEnabled":
  551. this.chart.setStyle("animationEnabled", value);
  552. break;
  553. case "border":
  554. if(value.color != null)
  555. {
  556. this.backgroundAndBorder.borderColor = this.parseColor(value.color);
  557. }
  558. if(value.size != null)
  559. {
  560. this.backgroundAndBorder.borderWeight = value.size;
  561. needsSizingRefresh = true;
  562. }
  563. break;
  564. case "background":
  565. if(value.color != null)
  566. {
  567. this.backgroundAndBorder.fillColor = this.parseColor(value.color);
  568. }
  569. if(value.image)
  570. {
  571. this.backgroundAndBorder.image = value.image;
  572. }
  573. if(value.alpha != null)
  574. {
  575. this.backgroundAndBorder.fillAlpha = value.alpha;
  576. }
  577. if(value.mode)
  578. {
  579. this.backgroundAndBorder.imageMode = value.mode;
  580. }
  581. break;
  582. case "font":
  583. if(value.color) value.color = this.parseColor(value.color);
  584. var textFormat:TextFormat = TextFormatSerializer.readTextFormat(value);
  585. this.chart.setStyle("textFormat", textFormat);
  586. break;
  587. case "dataTip":
  588. this.setDataTipStyles(value);
  589. break;
  590. case "xAxis":
  591. this.setAxisStyles(value, "horizontal");
  592. break;
  593. case "yAxis":
  594. this.setAxisStyles(value, "vertical");
  595. break;
  596. case "secondaryXAxis" :
  597. this.setAxisStyles(value, "secondaryHorizontal");
  598. break;
  599. case "secondaryYAxis" :
  600. this.setAxisStyles(value, "secondaryVertical");
  601. case "legend":
  602. this.setLegendStyles(value);
  603. break;
  604. case "seriesItemSpacing":
  605. if(this.chart is BarChart || this.chart is ColumnChart)
  606. {
  607. this.chart.setStyle("seriesItemSpacing", Number(value));
  608. }
  609. else
  610. {
  611. this.log("The " + name + " style is only supported by Column and Bar Charts.");
  612. }
  613. break;
  614. default:
  615. this.log("Unknown style: " + name, LoggerCategory.WARN);
  616. }
  617. if(needsSizingRefresh)
  618. {
  619. this.refreshComponentSize();
  620. }
  621. }
  622. public function setSeriesStyles(styles:Array):void
  623. {
  624. var defaultSeriesColors:Array =
  625. [0x00b8bf, 0x8dd5e7, 0xedff9f, 0xffa928, 0xc0fff6, 0xd00050,
  626. 0xc6c6c6, 0xc3eafb, 0xfcffad, 0xcfff83, 0x444444, 0x4d95dd,
  627. 0xb8ebff, 0x60558f, 0x737d7e, 0xa64d9a, 0x8e9a9b, 0x803e77];
  628. //will be filled based on the defaults or the series style definition, if present.
  629. var seriesColors:Array = [];
  630. var seriesBorderColors:Array = [];
  631. var seriesFillColors:Array = [];
  632. var seriesLineColors:Array = [];
  633. var seriesBorderAlphas:Array = [];
  634. var seriesFillAlphas:Array = [];
  635. var seriesLineAlphas:Array = [];
  636. var seriesCount:int = Math.min(this.chart.dataProvider.length, styles.length);
  637. for(var i:int = 0; i < seriesCount; i++)
  638. {
  639. var series:ISeries = ISeries(this.chart.dataProvider[i]);
  640. var style:Object = styles[i];
  641. if(style)
  642. {
  643. style = JSON.decode(style as String);
  644. }
  645. //defaults
  646. var defaultColors:Array = defaultSeriesColors.concat();
  647. if(series is PieSeries)
  648. {
  649. defaultColors = [defaultColors];
  650. }
  651. var defaultSize:Number = 10;
  652. if(series is ColumnSeries || series is BarSeries)
  653. {
  654. defaultSize = 20;
  655. }
  656. var defaultSkin:Object = RectangleSkin;
  657. if(series is LineSeries)
  658. {
  659. defaultSkin = CircleSkin;
  660. }
  661. else if(series is PieSeries)
  662. {
  663. defaultSkin = [defaultSkin];
  664. }
  665. //initialize styles with defaults
  666. var color:Object = defaultColors[i % defaultColors.length];
  667. var borderColor:Object = null;
  668. var fillColor:Object= null;
  669. var lineColor:Object = null;
  670. var lineAlpha:Number = 1;
  671. var borderAlpha:Number = 1;
  672. var fillAlpha:Number = 1;
  673. var skin:Object = defaultSkin;
  674. var mode:Object = "repeat";
  675. if(style)
  676. {
  677. for(var styleName:String in style)
  678. {
  679. switch(styleName)
  680. {
  681. case "images":
  682. if(!(series is PieSeries))
  683. {
  684. this.log(styleName + " style is only supported by series of type 'pie'.", LoggerCategory.WARN);
  685. break;
  686. }
  687. var images:Array = style.images as Array;
  688. var imageCount:int = images.length;
  689. for(var j:int = 0; j < imageCount; j++)
  690. {
  691. images[j] = this.createMarkerSkin(String(images[j]), series);
  692. }
  693. skin = images;
  694. break;
  695. case "image":
  696. skin = this.createMarkerSkin(style.image, series);
  697. if(!(series is LineSeries))
  698. {
  699. skin.properties.fillColor = color;
  700. skin.properties.fillAlpha = 1;
  701. }
  702. break;
  703. case "mode":
  704. mode = style.mode;
  705. break;
  706. case "colors":
  707. if(!(series is PieSeries))
  708. {
  709. this.log(styleName + " style is only supported by series of type 'pie'.", LoggerCategory.WARN);
  710. break;
  711. }
  712. var colors:Array = style.colors;
  713. var colorCount:int = colors.length;
  714. for(j = 0; j < colorCount; j++)
  715. {
  716. colors[j] = this.parseColor(colors[j]);
  717. }
  718. color = colors;
  719. break;
  720. case "color":
  721. color = this.parseColor(style.color);
  722. if(skin is InstanceFactory && !(series is LineSeries))
  723. {
  724. skin.properties.fillColor = color;
  725. skin.properties.fillAlpha = 1;
  726. }
  727. break;
  728. case "borderColor":
  729. borderColor = this.parseColor(style.borderColor);
  730. break;
  731. case "borderAlpha":
  732. borderAlpha = style.borderAlpha;
  733. break;
  734. case "fillColor":
  735. fillColor = this.parseColor(style.fillColor);
  736. break;
  737. case "fillAlpha":
  738. fillAlpha = style.fillAlpha;
  739. case "size":
  740. UIComponent(series).setStyle("markerSize", style.size);
  741. break;
  742. case "lineColor": //LineSeries only
  743. if(!(series is LineSeries))
  744. {
  745. this.log("The style " + styleName + " is only supported by series of type 'line'.", LoggerCategory.WARN);
  746. }
  747. lineColor = this.parseColor(style.lineColor);
  748. break;
  749. case "lineAlpha":
  750. if(!(series is LineSeries))
  751. {
  752. this.log("The style " + styleName + " is only supported by series of type 'line'.", LoggerCategory.WARN);
  753. }
  754. lineAlpha = style.lineAlpha;
  755. break;
  756. case "alpha":
  757. UIComponent(series).setStyle("markerAlpha", style.alpha);
  758. break;
  759. case "showAreaFill": //LineSeries only
  760. if(!(series is LineSeries))
  761. {
  762. this.log("The style " + styleName + " is only supported by series of type 'line'.", LoggerCategory.WARN);
  763. }
  764. UIComponent(series).setStyle("showAreaFill", style.showAreaFill);
  765. break;
  766. case "areaFillAlpha": //LineSeries only
  767. if(!(series is LineSeries))
  768. {
  769. this.log("The style " + styleName + " is only supported by series of type 'line'.", LoggerCategory.WARN);
  770. }
  771. UIComponent(series).setStyle("areaFillAlpha", style.areaFillAlpha);
  772. break;
  773. case "lineSize": //LineSeries only
  774. if(!(series is LineSeries))
  775. {
  776. this.log("The style " + styleName + " is only supported by series of type 'line'.", LoggerCategory.WARN);
  777. }
  778. UIComponent(series).setStyle("lineWeight", style.lineSize);
  779. break;
  780. case "connectPoints": //LineSeries only
  781. if(!(series is LineSeries))
  782. {
  783. this.log("The style " + styleName + " is only supported by series of type 'line'.", LoggerCategory.WARN);
  784. }
  785. UIComponent(series).setStyle("connectPoints", style.connectPoints);
  786. break;
  787. case "connectDiscontinuousPoints": //LineSeries only
  788. if(!(series is LineSeries))
  789. {
  790. this.log("The style " + styleName + " is only supported by series of type 'line'.", LoggerCategory.WARN);
  791. }
  792. UIComponent(series).setStyle("connectDiscontinuousPoints", style.connectDiscontinuousPoints);
  793. break;
  794. case "discontinuousDashLength": //LineSeries only
  795. if(!(series is LineSeries))
  796. {
  797. this.log("The style " + styleName + " is only supported by series of type 'line'.", LoggerCategory.WARN);
  798. }
  799. UIComponent(series).setStyle("discontinuousDashLength", style.discontinuousDashLength);
  800. break;
  801. case "showLabels": //PieSeries only
  802. if(!(series is PieSeries))
  803. {
  804. this.log("The style " + styleName + " is only supported by series of type 'pie'.", LoggerCategory.WARN);
  805. }
  806. UIComponent(series).setStyle("showLabels", style.showLabels);
  807. break;
  808. case "hideOverlappingLabels": //PieSeries only
  809. if(!(series is PieSeries))
  810. {
  811. this.log("The style " + styleName + " is only supported by series of type 'pie'.", LoggerCategory.WARN);
  812. }
  813. UIComponent(series).setStyle("hideOverlappingLabels", style.showLabels);
  814. break;
  815. case "font": //PieSeries only
  816. if(!(series is PieSeries))
  817. {
  818. this.log("The style " + styleName + " is only supported by series of type 'pie'.", LoggerCategory.WARN);
  819. }
  820. if(style.font.color) style.font.color = this.parseColor(style.font.color);
  821. UIComponent(series).setStyle("textFormat", TextFormatSerializer.readTextFormat(style.font))
  822. break;
  823. case "visibility":
  824. if(!(series is PieSeries))
  825. {
  826. UIComponent(series).setStyle("visibility", style.visibility);
  827. }
  828. break;
  829. case "skin":
  830. if(series is LineSeries)
  831. {
  832. try
  833. {
  834. skin = getDefinitionByName(SKIN_NAMESPACE + style.skin) as Class;
  835. }
  836. catch(e:Error)
  837. {
  838. this.log(style.skin + " is not a valid skin class", LoggerCategory.WARN);
  839. }
  840. }
  841. break;
  842. default:
  843. this.log("Unknown series style: " + styleName, LoggerCategory.WARN);
  844. }
  845. }
  846. }
  847. if(mode)
  848. {
  849. if(skin is InstanceFactory)
  850. {
  851. skin.properties.imageMode = mode;
  852. }
  853. else if(skin is Array)
  854. {
  855. var skinCount:int = (skin as Array).length;
  856. for(j = 0; j < skinCount; j++)
  857. {
  858. var subSkin:InstanceFactory = skin[j] as InstanceFactory;
  859. if(subSkin)
  860. {
  861. subSkin.properties.imageMode = mode;
  862. }
  863. }
  864. }
  865. }
  866. if(series is PieSeries)
  867. {
  868. PieSeries(series).setStyle("markerSkins", skin);
  869. }
  870. else UIComponent(series).setStyle("markerSkin", skin);
  871. seriesColors[i] = color;
  872. seriesBorderColors[i] = borderColor!=null?borderColor:color;
  873. seriesFillColors[i] = fillColor!=null?fillColor:color;
  874. seriesLineColors[i] = lineColor!=null?lineColor:color;
  875. seriesBorderAlphas[i] = borderAlpha;
  876. seriesFillAlphas[i] = fillAlpha;
  877. seriesLineAlphas[i] = lineAlpha;
  878. }
  879. this.chart.setStyle("seriesColors", seriesColors);
  880. this.chart.setStyle("seriesBorderColors", seriesBorderColors);
  881. this.chart.setStyle("seriesFillColors", seriesFillColors);
  882. this.chart.setStyle("seriesBorderAlphas", seriesBorderAlphas);
  883. this.chart.setStyle("seriesFillAlphas", seriesFillAlphas);
  884. if(series is LineSeries)
  885. {
  886. this.chart.setStyle("seriesLineColors", seriesLineColors);
  887. this.chart.setStyle("seriesLineAlphas", seriesLineAlphas);
  888. }
  889. this.chart.drawNow();
  890. }
  891. //--------------------------------------
  892. // Protected Methods
  893. //--------------------------------------
  894. /**
  895. * @private (protected)
  896. * Initialize the functions that may be called by JavaScript through ExternalInterface.
  897. */
  898. override protected function initializeComponent():void
  899. {
  900. super.initializeComponent();
  901. try
  902. {
  903. ExternalInterface.addCallback("setType", setType);
  904. ExternalInterface.addCallback("setStyle", setStyle);
  905. ExternalInterface.addCallback("setStyles", setStyles);
  906. ExternalInterface.addCallback("setSeriesStyles", setSeriesStyles);
  907. ExternalInterface.addCallback("setDataProvider", setDataProvider);
  908. ExternalInterface.addCallback("getCategoryNames", getCategoryNames);
  909. ExternalInterface.addCallback("setCategoryNames", setCategoryNames);
  910. ExternalInterface.addCallback("setDataTipFunction", setDataTipFunction);
  911. ExternalInterface.addCallback("getCategoryNames", getCategoryNames);
  912. ExternalInterface.addCallback("setCategoryNames", setCategoryNames);
  913. ExternalInterface.addCallback("setLegendLabelFunction", setLegendLabelFunction);
  914. //CartesianChart
  915. ExternalInterface.addCallback("getHorizontalField", getHorizontalField);
  916. ExternalInterface.addCallback("setHorizontalField", setHorizontalField);
  917. ExternalInterface.addCallback("getVerticalField", getVerticalField);
  918. ExternalInterface.addCallback("setVerticalField", setVerticalField);
  919. ExternalInterface.addCallback("setHorizontalAxis", setHorizontalAxis);
  920. ExternalInterface.addCallback("setVerticalAxis", setVerticalAxis);
  921. ExternalInterface.addCallback("setConstrainViewport", setConstrainViewport);
  922. ExternalInterface.addCallback("setSeriesStylesByIndex", setSeriesStylesByIndex);
  923. //PieChart
  924. ExternalInterface.addCallback("getDataField", getDataField);
  925. ExternalInterface.addCallback("setDataField", setDataField);
  926. ExternalInterface.addCallback("getCategoryField", getCategoryField);
  927. ExternalInterface.addCallback("setCategoryField", setCategoryField);
  928. }
  929. catch(error:SecurityError)
  930. {
  931. //do nothing. it will be caught by the YUIAdapter.
  932. }
  933. this.backgroundAndBorder = new BackgroundAndBorder();
  934. this.backgroundAndBorder.width = this.stage.stageWidth;
  935. this.backgroundAndBorder.height = this.stage.stageHeight;
  936. this.backgroundAndBorder.addEventListener(ErrorEvent.ERROR, chartErrorHandler);
  937. this.addChild(this.backgroundAndBorder);
  938. this.legend = new Legend();
  939. this.legend.setStyle("backgroundSkin", Shape);
  940. this.addChild(this.legend);
  941. }
  942. /**
  943. * @private (protected)
  944. * Since Chart is a Flash CS3 component, we should call drawNow() to be sure it updates properly.
  945. */
  946. override protected function refreshComponentSize():void
  947. {
  948. super.refreshComponentSize();
  949. if(this.backgroundAndBorder)
  950. {
  951. this.backgroundAndBorder.width = this.stage.stageWidth;
  952. this.backgroundAndBorder.height = this.stage.stageHeight;
  953. this.backgroundAndBorder.drawNow();
  954. }
  955. if(this.chart)
  956. {
  957. this.chart.x = this.chart.y = this.backgroundAndBorder.borderWeight + this.padding;
  958. this.chart.width -= 2 * (this.backgroundAndBorder.borderWeight + this.padding);
  959. this.chart.height -= 2 * (this.backgroundAndBorder.borderWeight + this.padding);
  960. if(this.legend && this.legendDisplay != "none")
  961. {
  962. this.legend.visible = true;
  963. if(this.legendDisplay == "left" || this.legendDisplay == "right")
  964. {
  965. this.legend.maxHeight = this.component.height;
  966. this.legend.drawNow();
  967. if(this.legendDisplay == "left")
  968. {
  969. this.legend.x = this.backgroundAndBorder.borderWeight + this.padding;
  970. this.chart.x = this.legend.x + this.legend.width + this.spacing;
  971. }
  972. else //right
  973. {
  974. this.legend.x = this.stage.stageWidth - this.backgroundAndBorder.borderWeight - this.legend.width - padding;
  975. }
  976. //center vertically
  977. this.legend.y = Math.max(0, (this.stage.stageHeight - this.legend.height) / 2);
  978. this.chart.width -= (this.legend.width + this.spacing);
  979. }
  980. else //top or bottom
  981. {
  982. this.legend.maxWidth = this.component.width;
  983. this.legend.drawNow();
  984. if(this.legendDisplay == "top")
  985. {
  986. this.legend.y = this.backgroundAndBorder.borderWeight + this.padding;
  987. this.chart.y = this.legend.y + this.legend.height + this.spacing;
  988. }
  989. else //bottom
  990. {
  991. this.legend.y = this.stage.stageHeight - this.backgroundAndBorder.borderWeight - this.legend.height - padding;
  992. }
  993. //center horizontally
  994. this.legend.x = Math.max(0, (this.stage.stageWidth - this.legend.width) / 2);
  995. this.chart.height -= (this.legend.height + this.spacing);
  996. }
  997. //we disable animation temporarily because we don't want the markers
  998. //sliding around because the legend resized
  999. if(this.legend && this.legendDisplay != "none")
  1000. {
  1001. var oldAnimationEnabled:Boolean = UIComponentUtil.getStyleValue(this.chart, "animationEnabled");
  1002. this.chart.setStyle("animationEnabled", false);
  1003. this.chart.drawNow();
  1004. this.chart.setStyle("animationEnabled", oldAnimationEnabled);
  1005. }
  1006. }
  1007. else
  1008. {
  1009. this.legend.visible = false;
  1010. }
  1011. this.chart.drawNow();
  1012. }
  1013. }
  1014. /**
  1015. * @private (protected)
  1016. * Logs errors.
  1017. */
  1018. protected function chartErrorHandler(event:ErrorEvent):void
  1019. {
  1020. this.log(event.text, LoggerCategory.ERROR);
  1021. }
  1022. /**
  1023. * @private (protected)
  1024. *
  1025. * Receives chart item mouse events and passes them out to JavaScript.
  1026. */
  1027. protected function chartItemEventHandler(event:ChartEvent):void
  1028. {
  1029. var type:String = event.type.replace("Roll", "Mouse");
  1030. type += "Event";
  1031. var seriesIndex:int = (this.chart.dataProvider as Array).indexOf(event.series);
  1032. var itemEvent:Object = {type: type, seriesIndex: seriesIndex, index: event.index, item: event.item, x: this.mouseX, y: this.mouseY};
  1033. this.dispatchEventToJavaScript(itemEvent);
  1034. }
  1035. private var _lastMouseItem:ISeriesItemRenderer;
  1036. protected function chartItemExtraEventHandler(event:MouseEvent):void
  1037. {
  1038. var dragEventType:String = "itemDragEvent";
  1039. var renderer:ISeriesItemRenderer = this._lastMouseItem;
  1040. this._lastMouseItem = null;
  1041. if(event.type == MouseEvent.MOUSE_DOWN)
  1042. {
  1043. //crawl up until we get to the chart or an item renderer
  1044. var displayObject:DisplayObject = event.target as DisplayObject;
  1045. while(!(displayObject is ISeriesItemRenderer) && !(displayObject is Chart))
  1046. {
  1047. displayObject = displayObject.parent;
  1048. }
  1049. if(displayObject is ISeriesItemRenderer)
  1050. {
  1051. renderer = ISeriesItemRenderer(displayObject);
  1052. this.stage.addEventListener(MouseEvent.MOUSE_MOVE, chartItemExtraEventHandler);
  1053. this.stage.addEventListener(MouseEvent.MOUSE_UP, chartItemExtraEventHandler);
  1054. }
  1055. else
  1056. {
  1057. renderer = null;
  1058. }
  1059. dragEventType = "itemDragStartEvent";
  1060. }
  1061. else if(event.type == MouseEvent.MOUSE_UP)
  1062. {
  1063. dragEventType = "itemDragEndEvent";
  1064. this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, chartItemExtraEventHandler);
  1065. this.stage.removeEventListener(MouseEvent.MOUSE_UP, chartItemExtraEventHandler);
  1066. }
  1067. //if we've found an item renderer, dispatch the event
  1068. if(renderer is ISeriesItemRenderer)
  1069. {
  1070. var seriesIndex:int = (this.chart.dataProvider as Array).indexOf(renderer.series);
  1071. var itemIndex:int = renderer.series.dataProvider.indexOf(renderer.data)
  1072. var itemEvent:Object = {type: dragEventType, seriesIndex: seriesIndex, index: itemIndex, item: renderer.data, x: this.mouseX, y: this.mouseY};
  1073. this.dispatchEventToJavaScript(itemEvent);
  1074. this._lastMouseItem = renderer;
  1075. }
  1076. }
  1077. protected function setDataTipStyles(styles:Object):void
  1078. {
  1079. var contentPadding:Number = 6;
  1080. if(styles.padding >= 0)
  1081. {
  1082. contentPadding = styles.padding;
  1083. }
  1084. if(styles.border || styles.background)
  1085. {
  1086. //defaults
  1087. var backgroundFactory:InstanceFactory = this.createBorderBackgroundFactory();
  1088. backgroundFactory.properties.fillColor = 0xffffff;
  1089. backgroundFactory.properties.fillAlpha = 0.9;
  1090. backgroundFactory.properties.borderWeight = 1;
  1091. backgroundFactory.properties.borderColor = 0x000000;
  1092. var border:Object = styles.border;
  1093. if(border)
  1094. {
  1095. if(border.color != null)
  1096. {
  1097. backgroundFactory.properties.borderColor = this.parseColor(border.color)
  1098. }
  1099. if(border.size != null)
  1100. {
  1101. backgroundFactory.properties.borderWeight = border.size;
  1102. contentPadding += border.size;
  1103. }
  1104. }
  1105. var background:Object = styles.background;
  1106. if(background)
  1107. {
  1108. if(background.color != null)
  1109. {
  1110. backgroundFactory.properties.fillColor = this.parseColor(background.color);
  1111. }
  1112. if(background.image)
  1113. {
  1114. backgroundFactory.properties.image = background.image;
  1115. }
  1116. if(background.alpha != null)
  1117. {
  1118. backgroundFactory.properties.fillAlpha = background.alpha;
  1119. }
  1120. if(background.mode)
  1121. {
  1122. backgroundFactory.properties.imageMode = background.mode;
  1123. }
  1124. }
  1125. this.chart.setStyle("dataTipBackgroundSkin", backgroundFactory);
  1126. }
  1127. this.chart.setStyle("dataTipContentPadding", contentPadding);
  1128. if(styles.font)
  1129. {
  1130. if(styles.font.color) styles.font.color = this.parseColor(styles.font.color);
  1131. var textFormat:TextFormat = TextFormatSerializer.readTextFormat(styles.font);
  1132. this.chart.setStyle("dataTipTextFormat", textFormat);
  1133. }
  1134. }
  1135. protected function setAxisStyles(styles:Object, axisName:String):void
  1136. {
  1137. var cartesianChart:CartesianChart = this.chart as CartesianChart;
  1138. var axisStyle:String = axisName + "AxisStyles";
  1139. var gridLineStyle:String = axisName + "AxisGridLinesStyles";
  1140. if(styles.color != null)
  1141. {
  1142. cartesianChart.setComplexStyle(axisStyle, "axisColor", this.parseColor(styles.color));
  1143. }
  1144. if(styles.size != null)
  1145. {
  1146. cartesianChart.setComplexStyle(axisStyle, "axisWeight", Number(styles.size));
  1147. cartesianChart.setComplexStyle(axisStyle, "showAxis", styles.size > 0);
  1148. }
  1149. if(styles.showLabels != null)
  1150. {
  1151. cartesianChart.setComplexStyle(axisStyle, "showLabels", styles.showLabels);
  1152. }
  1153. if(styles.hideOverlappingLabels != null)
  1154. {
  1155. cartesianChart.setComplexStyle(axisStyle, "hideOverlappingLabels", styles.hideOverlappingLabels);
  1156. }
  1157. if(styles.labelRotation != null)
  1158. {
  1159. if(!isNaN(Number(styles.labelRotation)))
  1160. {
  1161. cartesianChart.setComplexStyle(axisStyle, "labelRotation", Number(styles.labelRotation));
  1162. }
  1163. else
  1164. {
  1165. this.log("The " + axisName + " labelRotation style must be of type Number.", LoggerCategory.WARN);
  1166. }
  1167. }
  1168. if(styles.labelSpacing != null)
  1169. {
  1170. cartesianChart.setComplexStyle(axisStyle, "labelSpacing", Number(styles.labelSpacing));
  1171. }
  1172. if(styles.labelDistance != null)
  1173. {
  1174. cartesianChart.setComplexStyle(axisStyle, "labelDistance", Number(styles.labelDistance));
  1175. }
  1176. if(styles.titleRotation != null)
  1177. {
  1178. cartesianChart.setComplexStyle(axisStyle, "titleRotation", Number(styles.titleRotation));
  1179. }
  1180. if(styles.titleDistance != null)
  1181. {
  1182. cartesianChart.setComplexStyle(axisStyle, "titleDistance", Number(styles.titleDistance));
  1183. }
  1184. if(styles.titleFont != null)
  1185. {
  1186. if(styles.titleFont.color) styles.titleFont.color = this.parseColor(styles.titleFont.color);
  1187. var titleTextFormat:TextFormat = TextFormatSerializer.readTextFormat(styles.titleFont);
  1188. cartesianChart.setComplexStyle(axisStyle, "titleTextFormat", titleTextFormat);
  1189. }
  1190. if(styles.majorGridLines)
  1191. {
  1192. var majorGridLines:Object = styles.majorGridLines;
  1193. if(majorGridLines.color != null)
  1194. {
  1195. cartesianChart.setComplexStyle(gridLineStyle, "lineColor", this.parseColor(majorGridLines.color));
  1196. }
  1197. if(majorGridLines.size != null)
  1198. {
  1199. cartesianChart.setComplexStyle(gridLineStyle, "lineWeight", majorGridLines.size);
  1200. cartesianChart.setComplexStyle(gridLineStyle, "showLines", majorGridLines.size > 0);
  1201. }
  1202. }
  1203. if(styles.minorGridLines)
  1204. {
  1205. var minorGridLines:Object = styles.minorGridLines;
  1206. if(minorGridLines.color != null)
  1207. {
  1208. cartesianChart.setComplexStyle(gridLineStyle, "minorLineColor", this.parseColor(minorGridLines.color));
  1209. }
  1210. if(minorGridLines.size != null)
  1211. {
  1212. cartesianChart.setComplexStyle(gridLineStyle, "minorLineWeight", minorGridLines.size);
  1213. cartesianChart.setComplexStyle(gridLineStyle, "showMinorLines", minorGridLines.size > 0);
  1214. }
  1215. }
  1216. if(styles.zeroGridLine)
  1217. {
  1218. var zeroGridLine:Object = styles.zeroGridLine;
  1219. if(zeroGridLine.color != null)
  1220. {
  1221. cartesianChart.setComplexStyle(gridLineStyle, "zeroGridLineColor", zeroGridLine.color);
  1222. }
  1223. if(zeroGridLine.size != null)
  1224. {
  1225. cartesianChart.setComplexStyle(gridLineStyle, "zeroGridLineWeight", zeroGridLine.size);
  1226. cartesianChart.setComplexStyle(gridLineStyle, "showZeroGridLine", zeroGridLine.size > 0);
  1227. }
  1228. }
  1229. if(styles.majorTicks)
  1230. {
  1231. var majorTicks:Object = styles.majorTicks;
  1232. if(majorTicks.color != null)
  1233. {
  1234. cartesianChart.setComplexStyle(axisStyle, "tickColor", this.parseColor(majorTicks.color));
  1235. }
  1236. if(majorTicks.size != null)
  1237. {
  1238. cartesianChart.setComplexStyle(axisStyle, "tickWeight", majorTicks.size);
  1239. }
  1240. if(majorTicks.length != null)
  1241. {
  1242. cartesianChart.setComplexStyle(axisStyle, "tickLength", majorTicks.length);
  1243. }
  1244. if(majorTicks.display)
  1245. {
  1246. cartesianChart.setComplexStyle(axisStyle, "showTicks", majorTicks.display != "none" && majorTicks.size != 0);
  1247. if(majorTicks.display != "none")
  1248. {
  1249. cartesianChart.setComplexStyle(axisStyle, "tickPosition", majorTicks.display);
  1250. }
  1251. }
  1252. }
  1253. if(styles.minorTicks)
  1254. {
  1255. var minorTicks:Object = styles.minorTicks;
  1256. if(minorTicks.color != null)
  1257. {
  1258. cartesianChart.setComplexStyle(axisStyle, "minorTickColor", this.parseColor(minorTicks.color));
  1259. }
  1260. if(minorTicks.size != null)
  1261. {
  1262. cartesianChart.setComplexStyle(axisStyle, "minorTickWeight", minorTicks.size);
  1263. }
  1264. if(minorTicks.length != null)
  1265. {
  1266. cartesianChart.setComplexStyle(axisStyle, "minorTickLength", minorTicks.length);
  1267. }
  1268. if(minorTicks.display)
  1269. {
  1270. cartesianChart.setComplexStyle(axisStyle, "showMinorTicks", minorTicks.display != "none" && minorTicks.size != 0);
  1271. if(minorTicks.display != "none")
  1272. {
  1273. cartesianChart.setComplexStyle(axisStyle, "minorTickPosition", minorTicks.display);
  1274. }
  1275. }
  1276. }
  1277. }
  1278. protected function setLegendStyles(styles:Object):void
  1279. {
  1280. if(styles.font)
  1281. {
  1282. if(styles.font.color) styles.font.color = this.parseColor(styles.font.color);
  1283. var textFormat:TextFormat = TextFormatSerializer.readTextFormat(styles.font);
  1284. this.legend.setStyle("textFormat", textFormat);
  1285. }
  1286. if(styles.spacing != null)
  1287. {
  1288. this.legend.setStyle("gap", styles.spacing);
  1289. }
  1290. if(styles.display)
  1291. {
  1292. switch(styles.display)
  1293. {
  1294. case "left":
  1295. case "right":
  1296. this.legend.setStyle("direction", "vertical");
  1297. break;
  1298. default: //top, bottom
  1299. this.legend.setStyle("direction", "horizontal");
  1300. }
  1301. this.legendDisplay = styles.display;
  1302. }
  1303. var contentPadding:Number = 6;
  1304. if(styles.padding != null)
  1305. {
  1306. contentPadding = styles.padding;
  1307. }
  1308. if(styles.border || styles.background)
  1309. {
  1310. var backgroundFactory:InstanceFactory = this.createBorderBackgroundFactory();
  1311. var border:Object = styles.border;
  1312. if(border)
  1313. {
  1314. if(border.color != null)
  1315. {
  1316. backgroundFactory.properties.borderColor = this.parseColor(border.color)
  1317. }
  1318. if(border.size != null)
  1319. {
  1320. backgroundFactory.properties.borderWeight = border.size;
  1321. contentPadding += border.size;
  1322. }
  1323. }
  1324. var background:Object = styles.background;
  1325. if(background)
  1326. {
  1327. if(background.color != null)
  1328. {
  1329. backgroundFactory.properties.fillColor = this.parseColor(background.color);
  1330. }
  1331. if(background.image)
  1332. {
  1333. backgroundFactory.properties.image = background.image;
  1334. }
  1335. if(background.alpha != null)
  1336. {
  1337. backgroundFactory.properties.fillAlpha = background.alpha;
  1338. }
  1339. if(background.mode)
  1340. {
  1341. backgroundFactory.properties.imageMode = background.mode;
  1342. }
  1343. }
  1344. this.legend.setStyle("backgroundSkin", backgroundFactory);
  1345. }
  1346. this.legend.setStyle("contentPadding", contentPadding);
  1347. }
  1348. public function setSeriesStylesByIndex(index:int, style:Object):void
  1349. {
  1350. var series:ISeries = this.chart.indexToSeries(index) as ISeries;
  1351. var seriesComponent:UIComponent = UIComponent(series);
  1352. if(style)
  1353. {
  1354. style = JSON.decode(style as String);
  1355. }
  1356. //parse color styles
  1357. if(style.borderColor) seriesComponent.setStyle("borderColor", this.parseColor(style.borderColor));
  1358. if(style.fillColor) seriesComponent.setStyle("fillColor", this.parseColor(style.fillColor));
  1359. if(series is LineSeries && style.lineColor) seriesComponent.setStyle("lineColor", this.parseColor(style.lineColor));
  1360. //cascade color styles by setting the color style to more specific styles when the specific styles are not present
  1361. if(style.color)
  1362. {
  1363. style.color = this.parseColor(style.color);
  1364. seriesComponent.setStyle("color", style.color);
  1365. if(!style.borderColor) seriesComponent.setStyle("borderColor", style.color);
  1366. if(!style.fillColor) seriesComponent.setStyle("fillColor", style.color);
  1367. if(series is LineSeries && !style.lineColor) seriesComponent.setStyle("lineColor", style.color);
  1368. }
  1369. //parse external image skin
  1370. if(style.image)
  1371. {
  1372. var skin:Object = this.createMarkerSkin(style.image, series);
  1373. if(!(series is LineSeries))
  1374. {
  1375. skin.properties.fillColor = style.color ? style.color : UIComponentUtil.getStyleValue(seriesComponent, "color");
  1376. skin.properties.fillAlpha = 1;
  1377. }
  1378. if(style.mode) skin.properties.imageMode = style.mode;
  1379. seriesComponent.setStyle("markerSkin", skin);
  1380. }
  1381. else if(style.mode)
  1382. {
  1383. var oldSkin:Object = UIComponentUtil.getStyleValue(seriesComponent, "markerSkin");
  1384. if(oldSkin is InstanceFactory)
  1385. {
  1386. skin = this.createMarkerSkin(oldSkin.properties.image, series);
  1387. if(!(series is LineSeries))
  1388. {
  1389. skin.properties.fillColor = style.color ? style.color : UIComponentUtil.getStyleValue(seriesComponent, "color");
  1390. skin.properties.fillAlpha = 1;
  1391. }
  1392. skin.properties.imageMode = style.mode;
  1393. seriesComponent.setStyle("markerSkin", skin);
  1394. }
  1395. }
  1396. //map external styles to the series equivalent
  1397. var availableStyles:Object =
  1398. {
  1399. alpha:"markerAlpha",
  1400. size:"markerSize",
  1401. borderAlpha:"borderAlpha",
  1402. fillAlpha:"fillAlpha",
  1403. visibility:"visibility"
  1404. }
  1405. if(series is LineSeries)
  1406. {
  1407. //add line only style mappings
  1408. availableStyles.lineAlpha = "lineAlpha";
  1409. availableStyles.connectPoints = "connectPoints";
  1410. availableStyles.connectDiscontinuousPoints = "connectDiscontinuousPoints";
  1411. availableStyles.discontinuousDashLength = "discontinuousDashLength";
  1412. availableStyles.showAreaFill = "showAreaFill";
  1413. availableStyles.areaFillAlpha = "areaFillAlpha";
  1414. availableStyles.lineSize = "lineWeight";
  1415. //handle specified marker class
  1416. if(style.skin)
  1417. {
  1418. try
  1419. {
  1420. skin = getDefinitionByName(SKIN_NAMESPACE + style.skin) as Class;
  1421. seriesComponent.setStyle("markerSkin", skin);
  1422. }
  1423. catch(e:Error)
  1424. {
  1425. this.log(style.skin + " is not a valid skin class", LoggerCategory.WARN);
  1426. }
  1427. }
  1428. }
  1429. var len:int = availableStyles.length;
  1430. //set mapped styles
  1431. for(var i:String in availableStyles)
  1432. {
  1433. if(style[i] != null) seriesComponent.setStyle(availableStyles[i], style[i]);
  1434. }
  1435. seriesComponent.drawNow();
  1436. }
  1437. //--------------------------------------
  1438. // Private Methods
  1439. //--------------------------------------
  1440. /**
  1441. * @private
  1442. * Creates a pseudo-class to instantiate a BackgroundAndBorder object.
  1443. */
  1444. private function createBorderBackgroundFactory():InstanceFactory
  1445. {
  1446. var factory:InstanceFactory = new InstanceFactory(BackgroundAndBorder);
  1447. factory.properties =
  1448. {
  1449. fillColor: 0xffffff,
  1450. fillAlpha: 1,
  1451. borderColor: 0x000000,
  1452. borderWeight: 0,
  1453. image: null,
  1454. imageMode: BackgroundImageMode.REPEAT
  1455. };
  1456. factory.methods =
  1457. {
  1458. addEventListener: [ErrorEvent.ERROR, backgroundLoadErrorHandler, false, 0, true]
  1459. };
  1460. return factory;
  1461. }
  1462. private function backgroundLoadErrorHandler(event:ErrorEvent):void
  1463. {
  1464. this.log(event.text, LoggerCategory.ERROR);
  1465. }
  1466. private function createMarkerSkin(imagePath:String, series:ISeries):InstanceFactory
  1467. {
  1468. //a simple UILoader would be enough, but we want tiling
  1469. var skin:InstanceFactory = this.createBorderBackgroundFactory();
  1470. //turn off the border
  1471. skin.properties.borderWeight = 0;
  1472. //turn off the fill
  1473. skin.prope