/src/com/globalworks/lbs/tools/elements/axis/XAxis.as

https://github.com/fgontier/LBS_earnings_potential_calculator · ActionScript · 417 lines · 293 code · 65 blank · 59 comment · 49 complexity · 1f96eccbe9cfa78e00ea1b1e89836b6e MD5 · raw file

  1. package elements.axis {
  2. import flash.display.Sprite;
  3. import flash.geom.Matrix;
  4. import string.Utils;
  5. import charts.series.bars.Bar3D;
  6. import com.serialization.json.JSON;
  7. import Range;
  8. public class XAxis extends Sprite {
  9. private var steps:Number;
  10. private var alt_axis_colour:Number;
  11. private var alt_axis_step:Number;
  12. private var three_d:Boolean;
  13. private var three_d_height:Number;
  14. private var stroke:Number;
  15. private var tick_height:Number;
  16. private var colour:Number;
  17. public var offset:Boolean;
  18. private var grid_colour:Number;
  19. private var grid_visible:Boolean;
  20. private var user_ticks:Boolean;
  21. private var user_labels:Array;
  22. // make this private
  23. public var labels:XAxisLabels;
  24. private var style:Object;
  25. function XAxis( json:Object, min:Number, max:Number )
  26. {
  27. // default values
  28. this.style = {
  29. stroke: 2,
  30. 'tick-height': 3,
  31. colour: '#784016',
  32. offset: true,
  33. 'grid-colour': '#F5E1AA',
  34. 'grid-visible': true,
  35. '3d': 0,
  36. steps: 1,
  37. min: 0,
  38. max: null
  39. };
  40. if( json != null )
  41. object_helper.merge_2( json.x_axis, this.style );
  42. this.calcSteps();
  43. this.stroke = this.style.stroke;
  44. this.tick_height = this.style['tick-height'];
  45. this.colour = this.style.colour;
  46. // is the axis offset (see ScreenCoords)
  47. this.offset = this.style.offset;
  48. this.grid_visible = this.style['grid-visible'];
  49. this.colour = Utils.get_colour( this.style.colour );
  50. this.grid_colour = Utils.get_colour( this.style['grid-colour'] );
  51. if( style['3d'] > 0 )
  52. {
  53. this.three_d = true;
  54. this.three_d_height = int( this.style['3d'] );
  55. }
  56. else
  57. this.three_d = false;
  58. // Patch from Will Henry
  59. if( json )
  60. {
  61. if( json.x_label_style != undefined ) {
  62. if( json.x_label_style.alt_axis_step != undefined )
  63. this.alt_axis_step = json.x_label_style.alt_axis_step;
  64. if( json.x_label_style.alt_axis_colour != undefined )
  65. this.alt_axis_colour = Utils.get_colour(json.x_label_style.alt_axis_colour);
  66. }
  67. }
  68. this.labels = new XAxisLabels( json );
  69. this.addChild( this.labels );
  70. // the X Axis labels *may* require info from
  71. // this.obs
  72. if( !this.range_set() )
  73. {
  74. //
  75. // the user has not told us how long the X axis
  76. // is, so we figure it out:
  77. //
  78. if( this.labels.need_labels ) {
  79. //
  80. // No X Axis labels set:
  81. //
  82. // tr.aces( 'max x', this.obs.get_min_x(), this.obs.get_max_x() );
  83. this.set_range( min, max );
  84. }
  85. else
  86. {
  87. //
  88. // X Axis labels used, even so, make the chart
  89. // big enough to show all values
  90. //
  91. // tr.aces('x labels', this.obs.get_min_x(), this.x_axis.labels.count(), this.obs.get_max_x());
  92. if ( this.labels.count() > max ) {
  93. // Data and labesl are OK
  94. this.set_range( 0, this.labels.count() );
  95. } else {
  96. // There is more data than labels -- oops
  97. this.set_range( min, max );
  98. }
  99. }
  100. }
  101. else
  102. {
  103. //range set, but no labels...
  104. this.labels.auto_label( this.get_range(), this.get_steps() );
  105. }
  106. // custom ticks:
  107. this.make_user_ticks();
  108. }
  109. //
  110. // a little hacky, but we inspect the labels
  111. // to see if we need to display user custom ticks
  112. //
  113. private function make_user_ticks():void {
  114. if ((this.style.labels != null) &&
  115. (this.style.labels.labels != null) &&
  116. (this.style.labels.labels is Array) &&
  117. (this.style.labels.labels.length > 0))
  118. {
  119. this.user_labels = new Array();
  120. for each( var lbl:Object in this.style.labels.labels )
  121. {
  122. if (!(lbl is String)) {
  123. if (lbl.x != null)
  124. {
  125. var tmpObj:Object = { x: lbl.x };
  126. if (lbl["grid-colour"])
  127. {
  128. tmpObj["grid-colour"] = Utils.get_colour(lbl["grid-colour"]);
  129. }
  130. else
  131. {
  132. tmpObj["grid-colour"] = this.grid_colour;
  133. }
  134. this.user_ticks = true;
  135. this.user_labels.push(tmpObj);
  136. }
  137. }
  138. }
  139. }
  140. }
  141. private function calcSteps():void {
  142. if (this.style.max == null) {
  143. this.steps = 1;
  144. }
  145. else {
  146. var xRange:Number = this.style.max - this.style.min;
  147. var rev:Boolean = (this.style.min >= this.style.max); // min-max reversed?
  148. this.steps = ((this.style.steps != null) &&
  149. (this.style.steps != 0)) ? this.style.steps : 1;
  150. // force max of 250 labels and tick marks
  151. if ((Math.abs(xRange) / this.steps) > 250) this.steps = xRange / 250;
  152. // guarantee lblSteps is the proper sign
  153. this.steps = rev ? -Math.abs(this.steps) : Math.abs(this.steps);
  154. }
  155. }
  156. //
  157. // have we been passed a range? (min and max?)
  158. //
  159. public function range_set():Boolean {
  160. return this.style.max != null;
  161. }
  162. //
  163. // We don't have a range, so we need to calculate it.
  164. // grid lines, depends on number of values,
  165. // the X Axis labels and X min and X max
  166. //
  167. public function set_range( min:Number, max:Number ):void
  168. {
  169. this.style.min = min;
  170. this.style.max = max;
  171. // Calc new steps
  172. this.calcSteps();
  173. this.labels.auto_label( this.get_range(), this.get_steps() );
  174. }
  175. //
  176. // how many items in the X axis?
  177. //
  178. public function get_range():Range {
  179. return new Range( this.style.min, this.style.max, this.steps, this.offset );
  180. }
  181. public function get_steps():Number {
  182. return this.steps;
  183. }
  184. public function resize( sc:ScreenCoords, yPos:Number ):void
  185. {
  186. this.graphics.clear();
  187. //
  188. // Grid lines
  189. //
  190. if (this.user_ticks)
  191. {
  192. for each( var lbl:Object in this.user_labels )
  193. {
  194. this.graphics.beginFill(lbl["grid-colour"], 1);
  195. var xVal:Number = sc.get_x_from_val(lbl.x);
  196. this.graphics.drawRect( xVal, sc.top, 1, sc.height );
  197. this.graphics.endFill();
  198. }
  199. }
  200. else if(this.grid_visible)
  201. {
  202. var rev:Boolean = (this.style.min >= this.style.max); // min-max reversed?
  203. var tickMax:Number = /*(rev && this.style.offset) ? this.style.max-2 : */ this.style.max
  204. for( var i:Number=this.style.min; rev ? i >= tickMax : i <= tickMax; i+=this.steps )
  205. {
  206. if( ( this.alt_axis_step > 1 ) && ( i % this.alt_axis_step == 0 ) )
  207. this.graphics.beginFill(this.alt_axis_colour, 1);
  208. else
  209. this.graphics.beginFill(this.grid_colour, 1);
  210. xVal = sc.get_x_from_val(i);
  211. this.graphics.drawRect( xVal, sc.top, 1, sc.height );
  212. this.graphics.endFill();
  213. }
  214. }
  215. if( this.three_d )
  216. this.three_d_axis( sc );
  217. else
  218. this.two_d_axis( sc );
  219. this.labels.resize( sc, yPos );
  220. }
  221. public function three_d_axis( sc:ScreenCoords ):void
  222. {
  223. // for 3D
  224. var h:Number = this.three_d_height;
  225. var offset:Number = 12;
  226. var x_axis_height:Number = h+offset;
  227. //
  228. // ticks
  229. var item_width:Number = sc.width / this.style.max;
  230. // turn off out lines:
  231. this.graphics.lineStyle(0,0,0);
  232. var w:Number = 1;
  233. if (this.user_ticks)
  234. {
  235. for each( var lbl:Object in this.user_labels )
  236. {
  237. var xVal:Number = sc.get_x_from_val(lbl.x);
  238. this.graphics.beginFill(this.colour, 1);
  239. this.graphics.drawRect( xVal, sc.bottom + x_axis_height, w, this.tick_height );
  240. this.graphics.endFill();
  241. }
  242. }
  243. else
  244. {
  245. for( var i:Number=0; i < this.style.max; i+=this.steps )
  246. {
  247. var pos:Number = sc.get_x_tick_pos(i);
  248. this.graphics.beginFill(this.colour, 1);
  249. this.graphics.drawRect( pos, sc.bottom + x_axis_height, w, this.tick_height );
  250. this.graphics.endFill();
  251. }
  252. }
  253. var lighter:Number = Bar3D.Lighten( this.colour );
  254. // TOP
  255. var colors:Array = [this.colour,lighter];
  256. var alphas:Array = [100,100];
  257. var ratios:Array = [0,255];
  258. var matrix:Matrix = new Matrix();
  259. matrix.createGradientBox(sc.width_(), offset, (270 / 180) * Math.PI, sc.left-offset, sc.bottom );
  260. this.graphics.beginGradientFill('linear' /*GradientType.Linear*/, colors, alphas, ratios, matrix, 'pad'/*SpreadMethod.PAD*/ );
  261. this.graphics.moveTo(sc.left,sc.bottom);
  262. this.graphics.lineTo(sc.right,sc.bottom);
  263. this.graphics.lineTo(sc.right-offset,sc.bottom+offset);
  264. this.graphics.lineTo(sc.left-offset,sc.bottom+offset);
  265. this.graphics.endFill();
  266. // front
  267. colors = [this.colour,lighter];
  268. alphas = [100,100];
  269. ratios = [0, 255];
  270. matrix.createGradientBox( sc.width_(), h, (270 / 180) * Math.PI, sc.left - offset, sc.bottom + offset );
  271. this.graphics.beginGradientFill("linear", colors, alphas, ratios, matrix);
  272. this.graphics.moveTo(sc.left-offset,sc.bottom+offset);
  273. this.graphics.lineTo(sc.right-offset,sc.bottom+offset);
  274. this.graphics.lineTo(sc.right-offset,sc.bottom+offset+h);
  275. this.graphics.lineTo(sc.left-offset,sc.bottom+offset+h);
  276. this.graphics.endFill();
  277. // right side
  278. colors = [this.colour,lighter];
  279. alphas = [100,100];
  280. ratios = [0,255];
  281. // var matrix:Object = { matrixType:"box", x:box.left - offset, y:box.bottom + offset, w:box.width_(), h:h, r:(225 / 180) * Math.PI };
  282. matrix.createGradientBox( sc.width_(), h, (225 / 180) * Math.PI, sc.left - offset, sc.bottom + offset );
  283. this.graphics.beginGradientFill("linear", colors, alphas, ratios, matrix);
  284. this.graphics.moveTo(sc.right,sc.bottom);
  285. this.graphics.lineTo(sc.right,sc.bottom+h);
  286. this.graphics.lineTo(sc.right-offset,sc.bottom+offset+h);
  287. this.graphics.lineTo(sc.right-offset,sc.bottom+offset);
  288. this.graphics.endFill();
  289. }
  290. // 2D:
  291. public function two_d_axis( sc:ScreenCoords ):void
  292. {
  293. //
  294. // ticks
  295. var item_width:Number = sc.width / this.style.max;
  296. var left:Number = sc.left+(item_width/2);
  297. //this.graphics.clear();
  298. // Axis line:
  299. this.graphics.lineStyle( 0, 0, 0 );
  300. this.graphics.beginFill( this.colour );
  301. this.graphics.drawRect( sc.left, sc.bottom, sc.width, this.stroke );
  302. this.graphics.endFill();
  303. if (this.user_ticks)
  304. {
  305. for each( var lbl:Object in this.user_labels )
  306. {
  307. var xVal:Number = sc.get_x_from_val(lbl.x);
  308. this.graphics.beginFill(this.colour, 1);
  309. this.graphics.drawRect( xVal-(this.stroke/2), sc.bottom + this.stroke, this.stroke, this.tick_height );
  310. this.graphics.endFill();
  311. }
  312. }
  313. else
  314. {
  315. for( var i:Number=this.style.min; i <= this.style.max; i+=this.steps )
  316. {
  317. xVal = sc.get_x_from_val(i);
  318. this.graphics.beginFill(this.colour, 1);
  319. this.graphics.drawRect( xVal-(this.stroke/2), sc.bottom + this.stroke, this.stroke, this.tick_height );
  320. this.graphics.endFill();
  321. }
  322. }
  323. }
  324. public function get_height():Number {
  325. if( this.three_d )
  326. {
  327. // 12 is the size of the slanty
  328. // 3D part of the X axis
  329. return this.three_d_height+12+this.tick_height + this.labels.get_height();
  330. }
  331. else
  332. return this.stroke + this.tick_height + this.labels.get_height();
  333. }
  334. public function first_label_width() : Number
  335. {
  336. return this.labels.first_label_width();
  337. }
  338. public function last_label_width() : Number
  339. {
  340. return this.labels.last_label_width();
  341. }
  342. public function die(): void {
  343. this.style = null;
  344. this.graphics.clear();
  345. while ( this.numChildren > 0 )
  346. this.removeChildAt(0);
  347. if (this.labels != null)
  348. this.labels.die();
  349. this.labels = null;
  350. }
  351. }
  352. }