source: code/Website/open-flash-chart/elements/axis/XAxisLabels.as@ 7849

Last change on this file since 7849 was 7849, checked in by dennisw, 15 years ago
File size: 9.0 KB
Line 
1package elements.axis {
2 import flash.display.Sprite;
3 import flash.text.TextField;
4 import flash.text.TextFormat;
5 import flash.display.DisplayObject;
6 import flash.geom.Rectangle;
7 import elements.axis.AxisLabel;
8 import string.Utils;
9 import string.DateUtils;
10 import com.serialization.json.JSON;
11 // import DateUtils;
12
13 public class XAxisLabels extends Sprite {
14
15 public var need_labels:Boolean;
16 public var axis_labels:Array;
17 // JSON style:
18 private var style:Object;
19 private var userSpecifiedVisible:Object;
20
21 //
22 // Ugh, ugly code so we can rotate the text:
23 //
24 // [Embed(systemFont='Arial', fontName='spArial', mimeType='application/x-font', unicodeRange='U+0020-U+007E')]
25 [Embed(systemFont = 'Arial', fontName = 'spArial', mimeType = 'application/x-font')]
26
27 public static var ArialFont__:Class;
28
29 function XAxisLabels( json:Object ) {
30
31 this.need_labels = true;
32
33 // TODO: remove this and the class
34 // var style:XLabelStyle = new XLabelStyle( json.x_labels );
35
36 this.style = {
37 rotate: 0,
38 visible: null,
39 labels: null,
40 text: '#val#', // <-- default to display the position number or x value
41 steps: null, // <-- null for auto labels
42 size: 10,
43 align: 'auto',
44 colour: '#000000',
45 "visible-steps": null
46 };
47
48 // cache the text for tooltips
49 this.axis_labels = new Array();
50
51 if( ( json.x_axis != null ) && ( json.x_axis.labels != null ) )
52 object_helper.merge_2( json.x_axis.labels, this.style );
53
54 // save the user specified visible value foe use with auto_labels
55 this.userSpecifiedVisible = this.style.visible;
56 // for user provided labels, default to visible if not specified
57 if (this.style.visible == null) this.style.visible = true;
58
59 // Force rotation value if "rotate" is specified
60 if ( this.style.rotate is String )
61 {
62 if (this.style.rotate == "vertical")
63 {
64 this.style.rotate = 270;
65 }
66 else if (this.style.rotate == "diagonal")
67 {
68 this.style.rotate = -45;
69 }
70 }
71
72 this.style.colour = Utils.get_colour( this.style.colour );
73
74 if( ( this.style.labels is Array ) && ( this.style.labels.length > 0 ) )
75 {
76 //
77 // we WERE passed labels
78 //
79 this.need_labels = false;
80 if (this.style.steps == null)
81 this.style.steps = 1;
82
83 //
84 // BUG: this should start counting at X MIN, not zero
85 //
86 var x:Number = 0;
87 var lblCount:Number = 0;
88 // Allow for only displaying some of the labels
89 var visibleSteps:Number = (this.style["visible-steps"] == null) ? this.style.steps : this.style["visible-steps"];
90
91 for each( var s:Object in this.style.labels )
92 {
93 var tmpStyle:Object = { };
94 object_helper.merge_2( this.style, tmpStyle );
95
96 tmpStyle.visible = ((lblCount % visibleSteps) == 0);
97 tmpStyle.x = x;
98
99 // we need the x position for #x_label# tooltips
100 this.add( s, tmpStyle );
101 x++;
102 lblCount++;
103 }
104 }
105 }
106
107 //
108 // we were not passed labels and need to make
109 // them from the X Axis range
110 //
111 public function auto_label( range:Range, steps:Number ):void {
112
113 //
114 // if the user has passed labels we don't do this
115 //
116 if ( this.need_labels ) {
117 var rev:Boolean = (range.min >= range.max); // min-max reversed?
118
119 // Use the steps specific to labels if provided by user
120 var lblSteps:Number = 1;
121 if (this.style.steps != null) lblSteps = this.style.steps;
122
123 // force max of 250 labels
124 if (Math.abs(range.count() / lblSteps) > 250) lblSteps = range.count() / 250;
125
126 // guarantee lblSteps is the proper sign
127 lblSteps = rev ? -Math.abs(lblSteps) : Math.abs(lblSteps);
128
129 // Allow for only displaying some of the labels
130 var visibleSteps:Number = (this.style["visible-steps"] == null) ? steps : this.style["visible-steps"];
131
132 var tempStyle:Object = {};
133 object_helper.merge_2( this.style, tempStyle );
134 var lblCount:Number = 0;
135 for ( var i:Number = range.min; rev ? i >= range.max : i <= range.max; i += lblSteps ) {
136 tempStyle.x = i;
137 // restore the user specified visble value
138 if (this.userSpecifiedVisible == null)
139 {
140 tempStyle.visible = ((lblCount % visibleSteps) == 0);
141 lblCount++;
142 }
143 else
144 {
145 tempStyle.visible = this.userSpecifiedVisible;
146 }
147 this.add( null, tempStyle );
148 }
149 }
150 }
151
152 public function add( label:Object, style:Object ) : void
153 {
154
155 var label_style:Object = {
156 colour: style.colour,
157 text: style.text,
158 rotate: style.rotate,
159 size: style.size,
160 align: style.align,
161 visible: style.visible,
162 x: style.x
163 };
164
165 //
166 // inherit some properties from
167 // our parents 'globals'
168 //
169 if( label is String )
170 label_style.text = label as String;
171 else
172 object_helper.merge_2( label, label_style );
173
174 // Replace magic date variables in x label text
175 if (label_style.x != null) {
176 label_style.text = this.replace_magic_values(label_style.text, label_style.x);
177 }
178
179 var lines:Array = label_style.text.split( '<br>' );
180 label_style.text = lines.join( '\n' );
181
182 // Map X location to label string
183 this.axis_labels[label_style.x] = label_style.text;
184
185 // only create the label if necessary
186 if (label_style.visible) {
187 // our parent colour is a number, but
188 // we may have our own colour:
189 if( label_style.colour is String )
190 label_style.colour = Utils.get_colour( label_style.colour );
191
192 var l:TextField = this.make_label( label_style );
193
194 this.addChild( l );
195 }
196 }
197
198 public function get( i:Number ) : String
199 {
200 if( i<this.axis_labels.length )
201 return this.axis_labels[i];
202 else
203 return '';
204 }
205
206
207 public function make_label( label_style:Object ):TextField {
208 // we create the text in its own movie clip, so when
209 // we rotate it, we can move the regestration point
210
211 var title:AxisLabel = new AxisLabel();
212 title.x = 0;
213 title.y = 0;
214
215 //this.css.parseCSS(this.style);
216 //title.styleSheet = this.css;
217 title.text = label_style.text;
218
219 var fmt:TextFormat = new TextFormat();
220 fmt.color = label_style.colour;
221
222 // TODO: != null
223 if( label_style.rotate != 0 )
224 {
225 // so we can rotate the text
226 fmt.font = "spArial";
227 title.embedFonts = true;
228 }
229 else
230 {
231 fmt.font = "Verdana";
232 }
233
234 fmt.size = label_style.size;
235 fmt.align = "left";
236 title.setTextFormat(fmt);
237 title.autoSize = "left";
238 title.rotate_and_align( label_style.rotate, label_style.align, this );
239
240 // we don't know the x & y locations yet...
241
242 title.visible = label_style.visible;
243 if (label_style.x != null)
244 {
245 // store the x value for use in resize
246 title.xVal = label_style.x;
247 }
248
249 return title;
250 }
251
252
253 public function count() : Number
254 {
255 return this.axis_labels.length-1;
256 }
257
258 public function get_height() : Number
259 {
260 var height:Number = 0;
261 for( var pos:Number=0; pos < this.numChildren; pos++ )
262 {
263 var child:DisplayObject = this.getChildAt(pos);
264 height = Math.max( height, child.height );
265 }
266
267 return height;
268 }
269
270 public function resize( sc:ScreenCoords, yPos:Number ) : void
271 {
272
273 this.graphics.clear();
274 var i:Number = 0;
275
276 for( var pos:Number=0; pos < this.numChildren; pos++ )
277 {
278 var child:AxisLabel = this.getChildAt(pos) as AxisLabel;
279 if (isNaN(child.xVal))
280 {
281 child.x = sc.get_x_tick_pos(pos) + child.xAdj;
282 }
283 else
284 {
285 child.x = sc.get_x_from_val(child.xVal) + child.xAdj;
286 }
287 child.y = yPos + child.yAdj;
288 }
289 }
290
291 //
292 // to help Box calculate the correct width:
293 //
294 public function last_label_width() : Number
295 {
296 // is the last label shown?
297// if( ( (this.labels.length-1) % style.step ) != 0 )
298// return 0;
299
300 // get the width of the right most label
301 // because it may stick out past the end of the graph
302 // and we don't want to truncate it.
303// return this.mcs[(this.mcs.length-1)]._width;
304 if ( this.numChildren > 0 )
305 // this is a kludge compensating for ScreenCoords dividing the width by 2
306 return AxisLabel(this.getChildAt(this.numChildren - 1)).rightOverhang * 2;
307 else
308 return 0;
309 }
310
311 // see above comments
312 public function first_label_width() : Number
313 {
314 if( this.numChildren>0 )
315 // this is a kludge compensating for ScreenCoords dividing the width by 2
316 return AxisLabel(this.getChildAt(0)).leftOverhang * 2;
317 else
318 return 0;
319 }
320
321 public function die(): void {
322
323 this.axis_labels = null;
324 this.style = null;
325 this.graphics.clear();
326
327 while ( this.numChildren > 0 )
328 this.removeChildAt(0);
329 }
330
331 private function replace_magic_values(labelText:String, xVal:Number):String {
332 labelText = labelText.replace('#val#', NumberUtils.formatNumber(xVal));
333 labelText = DateUtils.replace_magic_values(labelText, xVal);
334 return labelText;
335 }
336
337 }
338}
Note: See TracBrowser for help on using the repository browser.