PageRenderTime 75ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Main.hx

http://openhaxechart.googlecode.com/
Haxe | 862 lines | 482 code | 175 blank | 205 comment | 70 complexity | c58c1e02d6051e37bf6d5d08dbe531ee MD5 | raw file
Possible License(s): LGPL-3.0
  1. import charts.Factory;
  2. import charts.ObjectCollection;
  3. import charts.series.Element;
  4. import charts.series.HasTooltip;
  5. import com.adobe.images.JPGEncoder;
  6. import com.adobe.images.PNGEncoder;
  7. import elements.Background;
  8. import elements.axis.RadarAxis;
  9. import elements.axis.XAxis;
  10. import elements.axis.XAxisLabels;
  11. import elements.axis.YAxisBase;
  12. import elements.axis.YAxisLeft;
  13. import elements.axis.YAxisRight;
  14. import elements.labels.Keys;
  15. import elements.labels.Title;
  16. import elements.labels.XLegend;
  17. import elements.labels.YLegendBase;
  18. import elements.labels.YLegendLeft;
  19. import elements.labels.YLegendRight;
  20. import elements.menu.Menu;
  21. import flash.display.BitmapData;
  22. import flash.display.LoaderInfo;
  23. import flash.display.Sprite;
  24. import flash.display.StageAlign;
  25. import flash.display.StageScaleMode;
  26. import flash.events.ContextMenuEvent;
  27. import flash.events.Event;
  28. import flash.events.IOErrorEvent;
  29. import flash.events.MouseEvent;
  30. import flash.events.ProgressEvent;
  31. import flash.external.ExternalInterface;
  32. import flash.net.URLLoader;
  33. import flash.net.URLLoaderDataFormat;
  34. import flash.net.URLRequest;
  35. import flash.net.URLRequestHeader;
  36. import flash.net.URLRequestMethod;
  37. import flash.net.URLVariables;
  38. import flash.system.System;
  39. import flash.ui.ContextMenu;
  40. import flash.ui.ContextMenuItem;
  41. import flash.utils.ByteArray;
  42. import global.Global;
  43. import hxjson2.JSON;
  44. import mx.utils.Base64Encoder;
  45. import string.Utils;
  46. class Main extends Sprite {
  47. public var VERSION:String ;
  48. public var tool_tip_wrapper:String;
  49. var URL:String; // ugh, vile. The IOError doesn't report the URL
  50. var background:Background;
  51. var chart_parameters:Dynamic;
  52. var id:String;
  53. var keys:Keys;
  54. var menu:Menu;
  55. var obs:ObjectCollection;
  56. var ok:Bool;
  57. var radar_axis:RadarAxis;
  58. var sc:ScreenCoords;
  59. var title:Title ;
  60. var tooltip:Tooltip;
  61. var x_axis:XAxis;
  62. var x_legend:XLegend;
  63. var y_axis:YAxisBase;
  64. var y_axis_right:YAxisBase;
  65. var y_legend:YLegendBase;
  66. var y_legend_2:YLegendBase;
  67. public function new() {
  68. super();
  69. VERSION = "2 Ichor";
  70. title = null;
  71. _main();
  72. }
  73. public static function main() {
  74. Main();
  75. }
  76. public function _main() {
  77. var loaderInfo = LoaderInfo(this.loaderInfo);
  78. this.chart_parameters = loaderInfo.parameters;
  79. if( this.chart_parameters['loading'] == null )
  80. this.chart_parameters['loading'] = 'Loading data...';
  81. var l:Loading = new Loading(this.chart_parameters['loading']);
  82. this.addChild( l );
  83. this.build_right_click_menu();
  84. this.ok = false;
  85. if( !this.find_data() )
  86. {
  87. // no data found -- debug mode?
  88. try {
  89. var file:String = "../../data-files/menu.txt";
  90. //var file:String = "../../data-files/radar-2.txt";
  91. //var file:String = "../../../test-data-files/stack.txt";
  92. this.load_external_file( file );
  93. /*
  94. // test AJAX calls like this:
  95. var file:String = "../data-files/bar-2.txt";
  96. this.load_external_file( file );
  97. file = "../data-files/radar-area.txt";
  98. this.load_external_file( file );
  99. */
  100. }
  101. catch (e:Error) {
  102. this.show_error( 'Loading test data\n'+file+'\n'+e.message );
  103. }
  104. }
  105. // inform javascript that it can call our reload method
  106. ExternalInterface.addCallback("reload", reload); // mf 18nov08, line 110 of original 'main.as'
  107. // inform javascript that it can call our load method
  108. ExternalInterface.addCallback("load", load);
  109. // inform javascript that it can call our post_image method
  110. ExternalInterface.addCallback("post_image", post_image); // test, undo comment after
  111. //
  112. ExternalInterface.addCallback("get_img_binary", getImgBinary);
  113. // more Interface
  114. ExternalInterface.addCallback("get_version", getVersion);
  115. // tell the web page that we are ready
  116. if( this.chart_parameters['id'] != null )
  117. ExternalInterface.call("ofc_ready", this.chart_parameters['id']);
  118. else
  119. ExternalInterface.call("ofc_ready");
  120. this.set_the_stage();
  121. }
  122. public function getVersion():String {return VERSION;}
  123. // public function getImgBinary():String { return Base64.encodeByteArray(image_binary()); }
  124. public function getImgBinary():String {
  125. trace('Saving image :: image_binary()');
  126. var bmp:BitmapData = new BitmapData(this.stage.stageWidth, this.stage.stageHeight);
  127. bmp.draw(this);
  128. var b64:Base64Encoder = new Base64Encoder();
  129. var b:ByteArray = PNGEncoder.encode(bmp);
  130. // var encoder:JPGEncoder = new JPGEncoder(80);
  131. // var q:ByteArray = encoder.encode(bmp);
  132. // b64.encodeBytes(q);
  133. //
  134. //
  135. //
  136. b64.encodeBytes(b);
  137. return b64.toString();
  138. //
  139. // commented out by J vander? why?
  140. // return b64.flush();
  141. //
  142. //
  143. /*
  144. var b64:Base64Encoder = new Base64Encoder();
  145. b64.encodeBytes(image_binary());
  146. trace( b64 as String );
  147. return b64 as String;
  148. */
  149. }
  150. /**
  151. * Called from the context menu:
  152. */
  153. public function saveImage(e:ContextMenuEvent):Void {
  154. // ExternalInterface.call("save_image", this.chart_parameters['id']);// , getImgBinary());
  155. // ExternalInterface.call("save_image", getImgBinary());
  156. // this just calls the javascript function which will grab an image from use
  157. // an do something with it.
  158. ExternalInterface.call("save_image", this.chart_parameters['id']);
  159. }
  160. function image_binary() : ByteArray {
  161. trace('Saving image :: image_binary()');
  162. var pngSource:BitmapData = new BitmapData(this.width, this.height);
  163. pngSource.draw(this);
  164. return PNGEncoder.encode(pngSource);
  165. }
  166. //
  167. // External Interface called by Javascript to
  168. // save the flash as an image, then POST it to a URL
  169. //
  170. /*public function post_image(url:String, post_params:Object, callback_str:String, debug:Bool):Void {*/
  171. public function post_image(url:String, callback_str:String, debug:Bool):Void {
  172. var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
  173. //Make sure to use the correct path to jpg_encoder_download.php
  174. var request:URLRequest = new URLRequest(url);
  175. request.requestHeaders.push(header);
  176. request.method = URLRequestMethod.POST;
  177. //
  178. request.data = image_binary();
  179. var loader:URLLoader = new URLLoader();
  180. loader.dataFormat = URLLoaderDataFormat.VARIABLES;
  181. /*
  182. * i can't figure out how to make these work
  183. *
  184. var urlVars:URLVariables = new URLVariables();
  185. for (key in post_params) {
  186. urlVars[key] = post_params[key];
  187. }
  188. */
  189. // base64:
  190. // urlVars.b64_image_data = getImgBinary();
  191. // RAW:
  192. // urlVars.b64_image_data = image_binary();
  193. // request.data = urlVars;
  194. var id:String = '';
  195. // TODO - test if this comparison is valid
  196. if ( this.chart_parameters['id'] != null)
  197. id = this.chart_parameters['id'];
  198. if( debug )
  199. {
  200. // debug the PHP:
  201. flash.net.navigateToURL(request, "_blank");
  202. }
  203. else
  204. {
  205. //we have to use the PROGRESS event instead of the COMPLETE event due to a bug in flash
  206. loader.addEventListener(ProgressEvent.PROGRESS, function (e:ProgressEvent):Void {
  207. trace("progress:" + e.bytesLoaded + ", total: " + e.bytesTotal);
  208. if (e.bytesLoaded == e.bytesTotal && callback_str != null) {
  209. trace('Calling: ', callback_str + '(' + id + ')');
  210. ExternalInterface.call(callback_str, id);
  211. }
  212. });
  213. try {
  214. loader.load( request );
  215. } catch (error:Error) {
  216. trace("unable to load:" + error);
  217. }
  218. /*
  219. var loader:URLLoader = new URLLoader();
  220. loader.dataFormat = URLLoaderDataFormat.BINARY;
  221. loader.addEventListener(Event.COMPLETE, function(e:Event):Void {
  222. trace('Saved image to:');
  223. trace( url );
  224. //
  225. // when the upload has finished call the user
  226. // defined javascript function/method
  227. //
  228. ExternalInterface.call(callback_str);
  229. });
  230. loader.load( jpgURLRequest );
  231. */
  232. }
  233. }
  234. function onContextMenuHandler(event:ContextMenuEvent):Void
  235. {
  236. }
  237. //
  238. // try to find some data to load,
  239. // check the URL for a file name,
  240. //
  241. //
  242. public function find_data(): Bool {
  243. // var all:String = ExternalInterface.call("window.location.href.toString");
  244. var vars:String = ExternalInterface.call("window.location.search.substring", 1);
  245. if( vars != null )
  246. {
  247. var p:Array<Dynamic> = vars.split( '&' );
  248. for ( v in p )
  249. {
  250. if( v.indexOf( 'ofc=' ) > -1 ) // TODO - translate indexOf to haxe
  251. {
  252. var tmp:Array<Dynamic> = v.split('=');
  253. trace( 'Found external file:' + tmp[1] );
  254. this.load_external_file( tmp[1] );
  255. //
  256. // LOOK:
  257. //
  258. return true;
  259. }
  260. }
  261. }
  262. if( this.chart_parameters['data-file'] != null)
  263. {
  264. // trace( 'Found parameter:' + parameters['data-file'] );
  265. this.load_external_file( this.chart_parameters['data-file'] );
  266. //
  267. // LOOK:
  268. //
  269. return true;
  270. }
  271. var get_data:String = 'open_flash_chart_data';
  272. if( this.chart_parameters['get-data'] != null )
  273. get_data = this.chart_parameters['get-data'];
  274. var json_string:Dynamic;
  275. if( this.chart_parameters['id'] != null)
  276. json_string = ExternalInterface.call( get_data , this.chart_parameters['id']);
  277. else
  278. json_string = ExternalInterface.call( get_data );
  279. if( json_string != null )
  280. {
  281. if( Std.is( json_string, String) )
  282. {
  283. this.parse_json( json_string );
  284. //
  285. // We have loaded the data, so this.ok = true
  286. //
  287. this.ok = true;
  288. //
  289. // LOOK:
  290. //
  291. return true;
  292. }
  293. }
  294. return false;
  295. }
  296. //
  297. // an external Interface, used by javascript to
  298. // reload JSON from a URL :: mf 18nov08
  299. //
  300. public function reload( url:String ):Void {
  301. var l:Loading = new Loading(this.chart_parameters['loading']);
  302. this.addChild( l );
  303. this.load_external_file( url );
  304. }
  305. function load_external_file( file:String ):Void {
  306. this.URL = file;
  307. //
  308. // LOAD THE DATA
  309. //
  310. var loader:URLLoader = new URLLoader();
  311. loader.addEventListener( IOErrorEvent.IO_ERROR, this.io_error );
  312. loader.addEventListener( Event.COMPLETE, xmlLoaded );
  313. var request:URLRequest = new URLRequest(file);
  314. loader.load(request);
  315. }
  316. function io_error( e:IOErrorEvent ):Void {
  317. // remove the 'loading data...' msg:
  318. this.removeChildAt(0);
  319. var msg:ErrorMsg = new ErrorMsg( 'Open Haxe Chart\nIO ERROR\nLoading test data\n' + e.text );
  320. msg.add_html( 'This is the URL that I tried to open:<br><a href="'+this.URL+'">'+this.URL+'</a>' );
  321. this.addChild( msg );
  322. }
  323. function show_error( msg:String ):Void {
  324. // remove the 'loading data...' msg:
  325. this.removeChildAt(0);
  326. var m:ErrorMsg = new ErrorMsg( msg );
  327. //m.add_html( 'Click here to open your JSON file: <a href="http://a.com">asd</a>' );
  328. this.addChild(m);
  329. }
  330. public function get_x_legend() : XLegend {
  331. return this.x_legend;
  332. }
  333. function set_the_stage():Void {
  334. // tell flash to align top left, and not to scale
  335. // anything (we do that in the code)
  336. this.stage.align = StageAlign.TOP_LEFT;
  337. //
  338. // ----- RESIZE ----
  339. //
  340. // noScale: now we can pick up resize events
  341. this.stage.scaleMode = StageScaleMode.NO_SCALE;
  342. this.stage.addEventListener(Event.ACTIVATE, this.activateHandler);
  343. this.stage.addEventListener(Event.RESIZE, this.resizeHandler);
  344. this.stage.addEventListener(Event.MOUSE_LEAVE, this.mouseOut);
  345. this.addEventListener( MouseEvent.MOUSE_OVER, this.mouseMove );
  346. }
  347. function mouseMove( event:Event ):Void {
  348. // trace( 'over ' + event.target );
  349. // trace('move ' + Math.random().toString());
  350. // trace( this.tooltip.get_tip_style() );
  351. switch( this.tooltip.get_tip_style() ) {
  352. case Tooltip.CLOSEST:
  353. this.mouse_move_closest( event );
  354. case Tooltip.PROXIMITY:
  355. this.mouse_move_proximity( cast( event, MouseEvent) );
  356. case Tooltip.NORMAL:
  357. this.mouse_move_follow( cast( event, MouseEvent) );
  358. }
  359. }
  360. function mouse_move_follow( event:MouseEvent ):Void {
  361. // trace( event.currentTarget );
  362. // trace( event.target );
  363. if ( Std.is( event.target, HasTooltip) )
  364. this.tooltip.draw( cast( event.target, HasTooltip) );
  365. else
  366. this.tooltip.hide();
  367. }
  368. function mouse_move_proximity( event:MouseEvent ):Void {
  369. //trace( event.currentTarget );
  370. //trace( event.target );
  371. var elements:Array<Dynamic> = this.obs.mouse_move_proximity( this.mouseX, this.mouseY );
  372. this.tooltip.closest( elements );
  373. }
  374. function mouse_move_closest( event:Event ):Void {
  375. var elements:Array<Dynamic> = this.obs.closest_2( this.mouseX, this.mouseY );
  376. this.tooltip.closest( elements );
  377. }
  378. function activateHandler(event:Event):Void {
  379. trace("activateHandler: " + event);
  380. }
  381. function resizeHandler(event:Event):Void {
  382. // FlashConnect.trace("resizeHandler: " + event);
  383. this.resize();
  384. }
  385. //
  386. // pie charts are simpler to resize, they don't
  387. // have all the extras (X,Y axis, legends etc..)
  388. //
  389. function resize_pie(): ScreenCoordsBase {
  390. // should this be here?
  391. this.addEventListener(MouseEvent.MOUSE_MOVE, this.mouseMove);
  392. this.background.resize();
  393. this.title.resize();
  394. // this object is used in the mouseMove method
  395. this.sc = new ScreenCoords(
  396. this.title.get_height(), 0, this.stage.stageWidth, this.stage.stageHeight,
  397. null, null, null, 0, 0, false );
  398. this.obs.resize( sc );
  399. return sc;
  400. }
  401. //
  402. //
  403. function resize_radar(): ScreenCoordsBase {
  404. this.addEventListener(MouseEvent.MOUSE_MOVE, this.mouseMove);
  405. this.background.resize();
  406. this.title.resize();
  407. this.keys.resize( 0, this.title.get_height() );
  408. var top:Int = this.title.get_height() + this.keys.get_height();
  409. // this object is used in the mouseMove method
  410. var sc:ScreenCoordsRadar = new ScreenCoordsRadar(top, 0, this.stage.stageWidth, this.stage.stageHeight);
  411. sc.set_range( this.radar_axis.get_range() );
  412. // 0-4 = 5 spokes
  413. sc.set_angles( this.obs.get_max_x()-this.obs.get_min_x()+1 );
  414. // resize the axis first because they may
  415. // change the radius (to fit the labels on screen)
  416. this.radar_axis.resize( sc );
  417. this.obs.resize( sc );
  418. return sc;
  419. }
  420. function resize():Void {
  421. //
  422. // the chart is async, so we may get this
  423. // event before the chart has loaded, or has
  424. // partly loaded
  425. //
  426. if ( !this.ok )
  427. return; // <-- something is wrong
  428. var sc:ScreenCoordsBase;
  429. if ( this.radar_axis != null )
  430. sc = this.resize_radar();
  431. else if ( this.obs.has_pie() )
  432. sc = this.resize_pie();
  433. else
  434. sc = this.resize_chart();
  435. if( this.menu )
  436. this.menu.resize();
  437. // tell the web page that we have resized our content
  438. if( this.chart_parameters['id'] )
  439. ExternalInterface.call("ofc_resize", sc.left, sc.width, sc.top, sc.height, this.chart_parameters['id']);
  440. else
  441. ExternalInterface.call("ofc_resize", sc.left, sc.width, sc.top, sc.height);
  442. sc = null;
  443. }
  444. function resize_chart(): ScreenCoordsBase {
  445. //
  446. // we want to show the tooltip closest to
  447. // items near the mouse, so hook Into the
  448. // mouse move event:
  449. //
  450. this.addEventListener(MouseEvent.MOUSE_MOVE, this.mouseMove);
  451. // FlashConnect.trace("stageWidth: " + stage.stageWidth + " stageHeight: " + stage.stageHeight);
  452. this.background.resize();
  453. this.title.resize();
  454. var left:Int = this.y_legend.get_width() /*+ this.y_labels.get_width()*/ + this.y_axis.get_width();
  455. this.keys.resize( left, this.title.get_height() );
  456. var top:Int = this.title.get_height() + this.keys.get_height();
  457. var bottom:Int = this.stage.stageHeight;
  458. bottom -= (this.x_legend.get_height() + this.x_axis.get_height());
  459. var right:Int = this.stage.stageWidth;
  460. right -= this.y_legend_2.get_width();
  461. //right -= this.y_labels_right.get_width();
  462. right -= this.y_axis_right.get_width();
  463. // this object is used in the mouseMove method
  464. this.sc = new ScreenCoords(
  465. top, left, right, bottom,
  466. this.y_axis.get_range(),
  467. this.y_axis_right.get_range(),
  468. this.x_axis.get_range(),
  469. this.x_axis.first_label_width(),
  470. this.x_axis.last_label_width(),
  471. false );
  472. this.sc.set_bar_groups(this.obs.groups);
  473. this.x_axis.resize( sc,
  474. // can we remove this:
  475. this.stage.stageHeight-(this.x_legend.get_height()+this.x_axis.labels.get_height()) // <-- up from the bottom
  476. );
  477. this.y_axis.resize( this.y_legend.get_width(), sc );
  478. this.y_axis_right.resize( 0, sc );
  479. this.x_legend.resize( sc );
  480. this.y_legend.resize();
  481. this.y_legend_2.resize();
  482. this.obs.resize( sc );
  483. return sc;
  484. }
  485. function mouseOut(event:Event):Void {
  486. if( this.tooltip != null )
  487. this.tooltip.hide();
  488. if( this.obs != null )
  489. this.obs.mouse_out();
  490. }
  491. //
  492. // an external Interface, used by javascript to
  493. // pass in a JSON string
  494. //
  495. public function load( s:String ):Void {
  496. this.parse_json( s );
  497. }
  498. //
  499. // JSON is loaded from an external URL
  500. //
  501. function xmlLoaded(event:Event):Void {
  502. var loader:URLLoader = URLLoader(event.target);
  503. this.parse_json( loader.data );
  504. }
  505. //
  506. // we have data! parse it and make the chart
  507. //
  508. function parse_json( json_string:String ):Void {
  509. // trace(json_string);
  510. var ok:Bool = false;
  511. try {
  512. var json:Dynamic = JSON.decode( json_string );
  513. ok = true;
  514. }
  515. catch (e:Error) {
  516. // remove the 'loading data...' msg:
  517. this.removeChildAt(0);
  518. this.addChild( new JsonErrorMsg( cast( json_string, String), e ) );
  519. }
  520. //
  521. // don't catch these errors:
  522. //
  523. if( ok )
  524. {
  525. // remove 'loading data...' msg:
  526. this.removeChildAt(0);
  527. this.build_chart( json );
  528. // force this to be garbage collected
  529. json = null;
  530. }
  531. json_string = '';
  532. }
  533. function build_chart( json:Dynamic ):Void {
  534. trace('----');
  535. trace(JSON.encode(json));
  536. trace('----');
  537. if ( this.obs != null )
  538. this.die();
  539. // init singletons:
  540. NumberFormat.getInstance( json );
  541. NumberFormat.getInstanceY2( json );
  542. this.tooltip = new Tooltip( json.tooltip );
  543. var g:Global = Global.getInstance();
  544. g.set_tooltip_string( this.tooltip.tip_text );
  545. //
  546. // these are common to both X Y charts and PIE charts:
  547. this.background = new Background( json );
  548. this.title = new Title( json.title );
  549. //
  550. this.addChild( this.background );
  551. //
  552. if ( JsonInspector.is_radar( json ) ) {
  553. this.obs = Factory.make_chart( json );
  554. this.radar_axis = new RadarAxis( json.radar_axis );
  555. this.keys = new Keys( this.obs );
  556. this.addChild( this.radar_axis );
  557. this.addChild( this.keys );
  558. }
  559. else if ( !JsonInspector.has_pie_chart( json ) )
  560. {
  561. this.build_chart_background( json );
  562. }
  563. else
  564. {
  565. // this is a PIE chart
  566. this.obs = Factory.make_chart( json );
  567. // PIE charts default to FOLLOW tooltips
  568. this.tooltip.set_tip_style( Tooltip.NORMAL );
  569. }
  570. // these are added in the Flash Z Axis order
  571. this.addChild( this.title );
  572. for (set in this.obs.sets )
  573. this.addChild( set );
  574. this.addChild( this.tooltip );
  575. if (json.menu != null) {
  576. this.menu = new Menu('99', json['menu']);
  577. this.addChild(this.menu);
  578. }
  579. this.ok = true;
  580. this.resize();
  581. }
  582. //
  583. // PIE charts don't have this.
  584. // build grid, axis, legends and key
  585. //
  586. function build_chart_background( json:Dynamic ):Void {
  587. //
  588. // This reads all the 'elements' of the chart
  589. // e.g. bars and lines, then creates them as sprites
  590. //
  591. this.obs = Factory.make_chart( json );
  592. //
  593. this.x_legend = new XLegend( json.x_legend );
  594. this.y_legend = new YLegendLeft( json );
  595. this.y_legend_2 = new YLegendRight( json );
  596. this.x_axis = new XAxis( json, this.obs.get_min_x(), this.obs.get_max_x() );
  597. this.y_axis = new YAxisLeft( json );
  598. this.y_axis_right = new YAxisRight( json );
  599. // access all our globals through this:
  600. var g:Global = Global.getInstance();
  601. // this is needed by all the elements tooltip
  602. g.x_labels = this.x_axis.labels;
  603. g.x_legend = this.x_legend;
  604. // can pick up X Axis labels for the
  605. // tooltips
  606. this.obs.tooltip_replace_labels( this.x_axis.labels );
  607. //
  608. //
  609. //
  610. this.keys = new Keys( this.obs );
  611. this.addChild( this.x_legend );
  612. this.addChild( this.y_legend );
  613. this.addChild( this.y_legend_2 );
  614. this.addChild( this.y_axis );
  615. this.addChild( this.y_axis_right );
  616. this.addChild( this.x_axis );
  617. this.addChild( this.keys );
  618. }
  619. /**
  620. * Remove all our referenced objects
  621. */
  622. function die():Void {
  623. this.obs.die();
  624. this.obs = null;
  625. if ( this.tooltip != null ) this.tooltip.die();
  626. if ( this.x_legend != null ) this.x_legend.die();
  627. if ( this.y_legend != null ) this.y_legend.die();
  628. if ( this.y_legend_2 != null ) this.y_legend_2.die();
  629. if ( this.y_axis != null ) this.y_axis.die();
  630. if ( this.y_axis_right != null ) this.y_axis_right.die();
  631. if ( this.x_axis != null ) this.x_axis.die();
  632. if ( this.keys != null ) this.keys.die();
  633. if ( this.title != null ) this.title.die();
  634. if ( this.radar_axis != null ) this.radar_axis.die();
  635. if ( this.background != null ) this.background.die();
  636. this.tooltip = null;
  637. this.x_legend = null;
  638. this.y_legend = null;
  639. this.y_legend_2 = null;
  640. this.y_axis = null;
  641. this.y_axis_right = null;
  642. this.x_axis = null;
  643. this.keys = null;
  644. this.title = null;
  645. this.radar_axis = null;
  646. this.background = null;
  647. while ( this.numChildren > 0 )
  648. this.removeChildAt(0);
  649. if ( this.hasEventListener(MouseEvent.MOUSE_MOVE))
  650. this.removeEventListener(MouseEvent.MOUSE_MOVE, this.mouseMove);
  651. // do not force a garbage collection, it is not supported:
  652. // http://stackoverflow.com/questions/192373/force-garbage-collection-in-as3
  653. }
  654. function build_right_click_menu(): Void {
  655. var cm:ContextMenu = new ContextMenu();
  656. cm.addEventListener(ContextMenuEvent.MENU_SELECT, onContextMenuHandler);
  657. cm.hideBuiltInItems();
  658. // OFC CREDITS
  659. var fs:ContextMenuItem = new ContextMenuItem("Charts by Open Haxe Chart [Version "+VERSION+"]" );
  660. fs.addEventListener(
  661. ContextMenuEvent.MENU_ITEM_SELECT,
  662. function (e:ContextMenuEvent):Void {
  663. var url:String = "http://teethgrinder.co.uk/open-flash-chart-2/";
  664. var request:URLRequest = new URLRequest(url);
  665. flash.net.navigateToURL(request, '_blank');
  666. });
  667. cm.customItems.push( fs );
  668. var save_image_message:String = ( this.chart_parameters['save_image_message'] ) ? this.chart_parameters['save_image_message'] : 'Save Image Locally';
  669. var dl:ContextMenuItem = new ContextMenuItem(save_image_message);
  670. dl.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, this.saveImage);
  671. cm.customItems.push( dl );
  672. this.contextMenu = cm;
  673. }
  674. public function format_y_axis_label( val:Float ): String {
  675. // if( this._y_format != undefined )
  676. // {
  677. // var tmp:String = StringTools.replace(_root._y_format,'#val#',_root.format(val));
  678. // tmp = StringTools.replace(tmp,'#val:time#',_root.formatTime(val));
  679. // tmp = StringTools.replace(tmp,'#val:none#',String(val));
  680. // tmp = StringTools.replace(tmp,'#val:number#', NumberUtils.formatFloat (Float(val)));
  681. // return tmp;
  682. // }
  683. // else
  684. return NumberUtils.format(val,2,true,true,false);
  685. }
  686. }