PageRenderTime 5266ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/yui/as-src/charts/Charts.as

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