source: code/Website/open-flash-chart/Tooltip.as@ 7878

Last change on this file since 7878 was 7849, checked in by dennisw, 15 years ago
File size: 8.5 KB
Line 
1package {
2
3 import caurina.transitions.Tweener;
4 import caurina.transitions.Equations;
5 import flash.display.Sprite;
6 import flash.geom.Point;
7 import flash.geom.Rectangle;
8 import flash.text.TextField;
9 import flash.text.TextFormat;
10 import flash.filters.DropShadowFilter;
11 // import charts.Elements.Element;
12 import com.serialization.json.JSON;
13 import string.Utils;
14 import string.Css;
15 import object_helper;
16 import charts.series.has_tooltip;
17
18 public class Tooltip extends Sprite {
19 // JSON style:
20 private var style:Object;
21
22 private var tip_style:Number;
23 private var cached_elements:Array;
24 private var tip_showing:Boolean;
25
26 public var tip_text:String;
27
28 public static const CLOSEST:Number = 0;
29 public static const PROXIMITY:Number = 1;
30 public static const NORMAL:Number = 2; // normal tooltip (ugh -- boring!!)
31
32 public function Tooltip( json:Object )
33 {
34 //
35 // we don't want mouseOver events for the
36 // tooltip or any children (the text fields)
37 //
38 this.mouseEnabled = false;
39 this.tip_showing = false;
40
41 this.style = {
42 shadow: true,
43 rounded: 6,
44 stroke: 2,
45 colour: '#808080',
46 background: '#f0f0f0',
47 title: "color: #0000F0; font-weight: bold; font-size: 12;",
48 body: "color: #000000; font-weight: normal; font-size: 12;",
49 mouse: Tooltip.CLOSEST,
50 text: "_default"
51 };
52
53 if( json )
54 {
55 this.style = object_helper.merge( json, this.style );
56 }
57
58
59 this.style.colour = Utils.get_colour( this.style.colour );
60 this.style.background = Utils.get_colour( this.style.background );
61 this.style.title = new Css( this.style.title );
62 this.style.body = new Css( this.style.body );
63
64 this.tip_style = this.style.mouse;
65 this.tip_text = this.style.text;
66 this.cached_elements = [];
67
68 if( this.style.shadow==1 )
69 {
70 var dropShadow:DropShadowFilter = new flash.filters.DropShadowFilter();
71 dropShadow.blurX = 4;
72 dropShadow.blurY = 4;
73 dropShadow.distance = 4;
74 dropShadow.angle = 45;
75 dropShadow.quality = 2;
76 dropShadow.alpha = 0.5;
77 // apply shadow filter
78 this.filters = [dropShadow];
79 }
80 }
81
82 public function make_tip( elements:Array ):void {
83
84 this.graphics.clear();
85
86 while( this.numChildren > 0 )
87 this.removeChildAt(0);
88
89 var height:Number = 0;
90 var x:Number = 5;
91
92 for each ( var e:has_tooltip in elements ) {
93
94 var o:Object = this.make_one_tip(e, x);
95 height = Math.max(height, o.height);
96 x += o.width + 2;
97 }
98
99 this.graphics.lineStyle(this.style.stroke, this.style.colour, 1);
100 this.graphics.beginFill(this.style.background, 1);
101
102 this.graphics.drawRoundRect(
103 0,0,
104 width+10, height + 5,
105 this.style.rounded, this.style.rounded );
106 }
107
108 private function make_one_tip( e:has_tooltip, x:Number ):Object {
109
110 var tt:String = e.get_tooltip();
111 var lines:Array = tt.split( '<br>' );
112
113 var top:Number = 5;
114 var width:Number = 0;
115
116 if ( lines.length > 1 ) {
117
118 var title:TextField = this.make_title(lines.shift());
119 title.mouseEnabled = false;
120 title.x = x;
121 title.y = top;
122 top += title.height;
123 width = title.width;
124
125 this.addChild( title );
126 }
127
128 var text:TextField = this.make_body(lines.join( '\n' ));
129 text.mouseEnabled = false;
130 text.x = x;
131 text.y = top;
132 width = Math.max( width, text.width );
133 this.addChild( text );
134
135 top += text.height;
136 return {width:width, height:top};
137 }
138
139 private function make_title( text:String ):TextField {
140
141 var title:TextField = new TextField();
142 title.mouseEnabled = false;
143
144 title.htmlText = text;
145 /*
146 *
147 * Start thinking about just using html formatting
148 * instead of text format below. We could do away
149 * with the title textbox entirely and let the user
150 * use:
151 * <b>title stuff</b><br>Here is the value
152 *
153 */
154 var fmt:TextFormat = new TextFormat();
155 fmt.color = this.style.title.color;
156 fmt.font = "Verdana";
157 fmt.bold = (this.style.title.font_weight=="bold");
158 fmt.size = this.style.title.font_size;
159 fmt.align = "right";
160 title.setTextFormat(fmt);
161 title.autoSize = "left";
162
163 return title;
164 }
165
166 private function make_body( body:String ):TextField {
167
168 var text:TextField = new TextField();
169 text.mouseEnabled = false;
170
171 text.htmlText = body;
172 var fmt2:TextFormat = new TextFormat();
173 fmt2.color = this.style.body.color;
174 fmt2.font = "Verdana";
175 fmt2.bold = (this.style.body.font_weight=="bold");
176 fmt2.size = this.style.body.font_size;
177 fmt2.align = "left";
178 text.setTextFormat(fmt2);
179 text.autoSize="left";
180
181 return text;
182 }
183
184 private function get_pos( e:has_tooltip ):flash.geom.Point {
185
186 var pos:Object = e.get_tip_pos();
187
188 var x:Number = (pos.x + this.width + 16) > this.stage.stageWidth ? (this.stage.stageWidth - this.width - 16) : pos.x;
189
190 var y:Number = pos.y;
191 y -= 4;
192 y -= (this.height + 10 ); // 10 == border size
193
194 if( y < 0 )
195 {
196 // the tooltip has drifted off the top of the screen, move it down:
197 y = 0;
198 }
199 return new flash.geom.Point(x, y);
200 }
201
202 private function show_tip( e:has_tooltip ):void {
203
204 // remove the 'hide' tween
205 Tweener.removeTweens( this );
206 var p:flash.geom.Point = this.get_pos( e );
207
208 if ( this.style.mouse == Tooltip.CLOSEST )
209 {
210 //
211 // make the tooltip appear (if invisible)
212 // and shoot to the correct position
213 //
214 this.visible = true;
215 this.alpha = 1
216 this.x = p.x;
217 this.y = p.y;
218 }
219 else
220 {
221 // make the tooltip fade in gently
222 this.tip_showing = true;
223
224 tr.ace('show');
225 this.alpha = 0
226 this.visible = true;
227 this.x = p.x;
228 this.y = p.y;
229 Tweener.addTween(
230 this,
231 {
232 alpha:1,
233 time:0.4,
234 transition:Equations.easeOutExpo
235 } );
236 }
237 }
238
239 public function draw( e:has_tooltip ):void {
240
241 if ( this.cached_elements[0] == e )
242 {
243 // if the tip is showing, don't make it
244 // show again because this makes it flicker
245 if( !this.tip_showing )
246 this.show_tip(e);
247 }
248 else
249 {
250
251 // this is a new tooltip, tell
252 // the old highlighted item to
253 // return to ground state
254 this.untip();
255
256 // get the new text and recreate it
257 this.cached_elements = [e];
258
259 this.make_tip( [e] );
260 this.show_tip(e);
261 }
262 }
263
264 public function closest( elements:Array ):void {
265
266 if( elements.length == 0 )
267 return;
268
269 if( this.is_cached( elements ) )
270 return;
271
272 this.untip();
273 this.cached_elements = elements;
274 this.tip();
275
276 //
277 //tr.ace( 'make new tooltip' );
278 //tr.ace( Math.random() );
279 //
280
281 this.make_tip( elements );
282
283 var p:flash.geom.Point = this.get_pos( elements[0] );
284
285 this.visible = true;
286
287 Tweener.addTween(this, { x:p.x, time:0.3, transition:Equations.easeOutExpo } );
288 Tweener.addTween(this, { y:p.y, time:0.3, transition:Equations.easeOutExpo } );
289 }
290
291 //
292 // TODO: if elements has 1 item and cached_elements has 2
293 // one of which is in elements, this function
294 // returns true which is wrong
295 //
296 private function is_cached( elements:Array ):Boolean {
297
298 if ( this.cached_elements.length == 0 )
299 return false;
300
301 for each( var e:has_tooltip in elements )
302 if ( this.cached_elements.indexOf(e) == -1 )
303 return false;
304
305 return true;
306 }
307
308 private function untip():void {
309 for each( var e:has_tooltip in this.cached_elements )
310 e.set_tip( false );
311 }
312
313 private function tip():void {
314 for each( var e:has_tooltip in this.cached_elements )
315 e.set_tip( true );
316 }
317
318 private function hideAway() : void {
319 this.visible = false;
320 this.untip();
321 this.cached_elements = new Array();
322 this.alpha = 1;
323 }
324
325 public function hide():void {
326 this.tip_showing = false;
327 tr.ace('hide tooltip');
328 Tweener.addTween(this, { alpha:0, time:0.6, transition:Equations.easeOutExpo, onComplete:hideAway } );
329 }
330
331 public function get_tip_style():Number {
332 return this.tip_style;
333 }
334
335 public function set_tip_style( i:Number ):void {
336 this.tip_style = i;
337 }
338
339 public function die():void {
340
341 this.filters = [];
342 this.graphics.clear();
343
344 while( this.numChildren > 0 )
345 this.removeChildAt(0);
346
347 this.style = null;
348 this.cached_elements = null;
349 }
350 }
351}
Note: See TracBrowser for help on using the repository browser.