[moodle] / contrib / plugins / grade / report / visual / flare_visualization / flare_visualization.as Repository:

Annotation of /contrib/plugins/grade/report/visual/flare_visualization/flare_visualization.as

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (view) (download)

1 : dservos 1.2 ///////////////////////////////////////////////////////////////////////////
2 :     // //
3 :     // NOTICE OF COPYRIGHT //
4 :     // //
5 :     // Moodle - Modular Object-Oriented Dynamic Learning Environment //
6 :     // http://moodle.org //
7 :     // //
8 :     // Copyright (C) 1999 onwards Martin Dougiamas http://moodle.com //
9 :     // //
10 :     // This program is free software; you can redistribute it and/or modify //
11 :     // it under the terms of the GNU General Public License as published by //
12 :     // the Free Software Foundation; either version 2 of the License, or //
13 :     // (at your option) any later version. //
14 :     // //
15 :     // This program is distributed in the hope that it will be useful, //
16 :     // but WITHOUT ANY WARRANTY; without even the implied warranty of //
17 :     // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
18 :     // GNU General Public License for more details: //
19 :     // //
20 :     // http://www.gnu.org/copyleft/gpl.html //
21 :     // //
22 :     ///////////////////////////////////////////////////////////////////////////
23 :    
24 :     /**
25 :     * This is the flex with flare based visualizer for the Moodle 2.x visual
26 :     * grade book plug-in. This should load the grade book data for a given
27 :     * visualization from the report/visual plug-in based on a set of flashvars
28 :     * passed to it from Moodle and display a visual repersenation.
29 :     */
30 : dservos 1.1 package {
31 : dservos 1.2 //Flare imports
32 : dservos 1.1 import flare.animate.Transitioner;
33 :     import flare.data.DataSet;
34 :     import flare.data.DataSource;
35 :     import flare.display.TextSprite;
36 :     import flare.vis.Visualization;
37 :     import flare.vis.controls.HoverControl;
38 :     import flare.vis.data.Data;
39 :     import flare.vis.data.DataSprite;
40 :     import flare.vis.legend.Legend;
41 : dservos 1.2 import flare.vis.legend.LegendItem;
42 : dservos 1.1 import flare.vis.operator.encoder.ColorEncoder;
43 :     import flare.vis.operator.encoder.ShapeEncoder;
44 :     import flare.vis.operator.layout.AxisLayout;
45 :     import flare.vis.scale.ScaleType;
46 :     import flare.vis.util.Filters;
47 :    
48 :     import flash.display.DisplayObject;
49 :     import flash.display.DisplayObjectContainer;
50 :     import flash.display.Sprite;
51 :     import flash.events.Event;
52 :     import flash.events.MouseEvent;
53 :     import flash.filters.GlowFilter;
54 :     import flash.geom.Rectangle;
55 :     import flash.net.URLLoader;
56 :     import flash.text.TextFormat;
57 :    
58 :     [SWF(width="800", height="600", backgroundColor="#ffffff", frameRate="30")]
59 : dservos 1.2 /**
60 :     * Main class for handling grade book data and greatating a visualization.
61 :     */
62 : dservos 1.1 public class flare_visualization extends Sprite
63 :     {
64 : dservos 1.2 /**
65 :     * The visualization object to be used in creating the visualization.
66 :     */
67 : dservos 1.1 private var vis:Visualization;
68 : dservos 1.2
69 :     /**
70 :     * A refernce to the currently displayed dialog box. If null no dialog
71 :     * box is currently being displayed.
72 :     */
73 : dservos 1.1 private var lastBox:Sprite = null;
74 : dservos 1.2
75 :     /**
76 :     * A refernce to the data sprite witch contains the data for witch the
77 :     * currently displayed dialog box is based on and a child of.
78 :     */
79 : dservos 1.1 private var lastBoxData:DataSprite = null;
80 : dservos 1.2
81 :     /**
82 :     * The data feild the X axis is based on.
83 :     * @default data.student
84 :     */
85 : dservos 1.1 private var axisX:String = "data.student";
86 : dservos 1.2
87 :     /**
88 :     * The data field the Y axis is based on.
89 :     * @default data.grade
90 :     */
91 : dservos 1.1 private var axisY:String = "data.grade";
92 : dservos 1.2
93 :     /**
94 :     * A container for the legends witch will be displayed on the righ hand
95 :     * side.
96 :     */
97 :     private var legends:Sprite;
98 :    
99 :     /**
100 :     * The hover control for the dialog box.
101 :     */
102 :     private var boxhc:HoverControl = new HoverControl();
103 :    
104 :     /**
105 :     * The constucter for the flare_visualization class.
106 :     * Calls on harvest_data and sets up the varibles from the flashvars.
107 :     */
108 : dservos 1.1 public function flare_visualization()
109 :     {
110 : dservos 1.2 // Call harvest_data, loading needed visualization data from moodle.
111 :     // The Moodle wwwroot, course id, users sessionid, users session cookie
112 :     // and session test data are needed to get the data from moodle are
113 :     // loaded threw flashvars.
114 :     harvest_data(loaderInfo.parameters['wwwroot'] + '/grade/report/visual/data.php?id=' + escape(loaderInfo.parameters['courseid']) + '&sessioncookie=' + escape(loaderInfo.parameters['sessioncookie']) + '&sessionid=' + escape(loaderInfo.parameters['sessionid']) + '&sessiontest=' + escape(loaderInfo.parameters['sessiontest']));
115 :     //harvest_data('http://localhost/moodle/grade/report/visual/data.php?id=3&sessioncookie=&sessionid=ebb79f5984c0fa4c9b0d85814c573a81&sessiontest=jHKFJhsOPf');
116 : dservos 1.1 }
117 :    
118 : dservos 1.2 /**
119 :     * Harvests the data from Moodle and calls on buildVis to build the
120 :     * visualization once the data has been loaded.
121 :     * TODO: Add a loading bar and more feed back about the loading process.
122 :     * @param url The url from witch to load the tab formated data for the visualization.
123 :     */
124 : dservos 1.1 public function harvest_data(url:String):void
125 :     {
126 :     var ds:DataSource = new DataSource(url, "tab");
127 :     var loader:URLLoader = ds.load();
128 :     loader.addEventListener(Event.COMPLETE, function(evt:Event):void {
129 :     var ds:DataSet = loader.data as DataSet;
130 :     buildVis(Data.fromDataSet(ds));
131 :     });
132 :     }
133 :    
134 : dservos 1.2 /**
135 :     * Find the max width between a container and all of it's decendence
136 :     * This dose not find the width of a container but the greatest width
137 :     * of an invdual component in it's decenedences.
138 :     * @param d The display container to find the max width of.
139 :     * @return the max width value of the display objects.
140 :     */
141 : dservos 1.1 private function getMaxWidth(d:DisplayObjectContainer):int {
142 :     var max:int = d.width;
143 :    
144 : dservos 1.2 for(var k:uint = 0; k < d.numChildren; k++ ) {
145 : dservos 1.1 var width:int = 0;
146 :    
147 :     if(d.getChildAt(k) is DisplayObjectContainer) {
148 :     width = getMaxWidth(DisplayObjectContainer(d.getChildAt(k)));
149 :     } else {
150 :     width = d.getChildAt(k).width;
151 :     }
152 :    
153 :     if(width > max) {
154 :     max = width;
155 :     }
156 :     }
157 :    
158 :     return max;
159 :     }
160 :    
161 : dservos 1.2 /**
162 :     * Simple function to retrun the greatest of two ints.
163 :     * @param num1 the first number to test
164 :     * @param num2 the second number to test
165 :     * @return the largest value between num1 and num2.
166 :     */
167 : dservos 1.1 private function max(num1:int, num2:int):int {
168 :     if(num1 > num2) {
169 :     return num1;
170 :     } else {
171 :     return num2;
172 :     }
173 :     }
174 :    
175 : dservos 1.2 /**
176 :     * Find the max height between a container and all of it's decendence
177 :     * This dose not find the width of a container but the greatest height
178 :     * of an invdual component in it's decenedences.
179 :     * @param d The display container to find the max height of.
180 :     * @return the max height value of the display objects.
181 :     */
182 : dservos 1.1 private function getMaxHeight(d:DisplayObjectContainer):int {
183 :     var max:int = d.height;
184 :    
185 : dservos 1.2 for(var k:uint = 0; k < d.numChildren; k++ ) {
186 : dservos 1.1 var height:int = 0;
187 :    
188 :     if(d.getChildAt(k) is DisplayObjectContainer) {
189 :     height = getMaxHeight(DisplayObjectContainer(d.getChildAt(k)));
190 :     } else {
191 :     height = d.getChildAt(k).height;
192 :     }
193 :    
194 :     if(height > max) {
195 :     max = height;
196 :     }
197 :     }
198 :    
199 :     return max;
200 :     }
201 :    
202 : dservos 1.2 /**
203 :     * Builds the visualization based on the loaded data.
204 :     * Also sets up the legends, buttons and controls.
205 :     * @param data The data that was loaded in from moodle.
206 :     */
207 : dservos 1.1 private function buildVis(data:Data):void
208 :     {
209 :     vis = new Visualization(data);
210 : dservos 1.2 legends = new Sprite();
211 :    
212 :     // Set the functions to be called when a dialog box is hovered over.
213 :     boxhc.onRollOver = boxRollOver;
214 :     boxhc.onRollOut = boxRollOut;
215 : dservos 1.1
216 : dservos 1.2 // Set up the encoders and layout
217 : dservos 1.1 var colorEncoder:ColorEncoder = new ColorEncoder("data.item", Data.NODES, "lineColor", ScaleType.CATEGORIES);
218 :     var shapeEncoder:ShapeEncoder = new ShapeEncoder("data.group");
219 :     var al:AxisLayout = new AxisLayout(axisX, axisY);
220 :    
221 : dservos 1.2 // Add the encoders and layout to the visualization.
222 : dservos 1.1 vis.operators.add(al);
223 :     vis.operators.add(colorEncoder);
224 :     vis.operators.add(shapeEncoder);
225 :    
226 : dservos 1.2 // Set up the layout of the axes.
227 : dservos 1.1 vis.xyAxes.xAxis.horizontalAnchor = TextSprite.LEFT;
228 :     vis.xyAxes.xAxis.verticalAnchor = TextSprite.MIDDLE;
229 :     vis.xyAxes.xAxis.labelAngle = Math.PI / 2;
230 :     vis.xyAxes.xAxis.fixLabelOverlap = false;
231 :     vis.xyAxes.yAxis.fixLabelOverlap = false;
232 :    
233 : dservos 1.2 // Update the visualization so the widths and other values are correct.
234 : dservos 1.1 vis.update();
235 :    
236 : dservos 1.2 // Initalize the X and Y axis labels and the visualizations title.
237 : dservos 1.1 var labelX:TextSprite = new TextSprite("Student", new TextFormat("mono", 20));
238 :     var labelY:TextSprite = new TextSprite("Grade", new TextFormat("mono", 20));
239 :     var title:TextSprite = new TextSprite("Normalized Grades vs Students", new TextFormat("mono", 25));
240 :    
241 : dservos 1.2 // Find the largest width out of the X axis labels so it can used for positing sprites.
242 :     var xLabelsHeight:int = getMaxHeight(vis.xyAxes.xAxis.labels);
243 :     var yLabelsWidth:int = getMaxWidth(vis.xyAxes.yAxis.labels);
244 :    
245 :     // Position the visualization.
246 : dservos 1.1 vis.y = title.height + 10;
247 : dservos 1.2 vis.x = labelY.height + -vis.xyAxes.yAxis.labelOffsetX + yLabelsWidth;
248 : dservos 1.1
249 : dservos 1.2 // Set up the legends.
250 : dservos 1.1 var itemLegend:Legend = new Legend("data.item", colorEncoder.scale, colorEncoder.colors, null, null);
251 :     var groupLegend:Legend = new Legend("data.group", shapeEncoder.scale, null, shapeEncoder.shapes, null);
252 :    
253 : dservos 1.2 // Set the bounds of the visualization based on the hieght and width of the flash application,
254 :     // and the other components so the visualization is takes up the unused space.
255 : dservos 1.1 vis.bounds = new Rectangle(0, 0, loaderInfo.width - (max(itemLegend.width, groupLegend.width) + 15 + vis.x), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
256 : dservos 1.2
257 :     // Add the visualization to the main sprite.
258 : dservos 1.1 addChild(vis);
259 :    
260 : dservos 1.2 // Set up the properitys of the data sprites and add a eventlistener to check for
261 :     // clicks on them.
262 : dservos 1.1 vis.data.visit(function(d:DataSprite):void {
263 :     d.fillColor = 0x018888ff;
264 :     d.fillAlpha = 0.2;
265 :     d.lineWidth = 2;
266 :     d.addEventListener(MouseEvent.CLICK, mouseClicked);
267 :     });
268 :    
269 : dservos 1.2 // Position the legends.
270 :     legends.x = vis.bounds.width + 10;
271 :     itemLegend.x = 0;
272 : dservos 1.1 itemLegend.y = 0;
273 : dservos 1.2 groupLegend.x = 0;
274 : dservos 1.1 groupLegend.y = itemLegend.y + itemLegend.height;
275 :    
276 : dservos 1.2 // Add a listener for mouse clicks on the legends.
277 :     itemLegend.items.addEventListener(MouseEvent.CLICK, legendClick);
278 :     groupLegend.items.addEventListener(MouseEvent.CLICK, legendClick);
279 :    
280 :     // Add the legends to the legends container.
281 :     legends.addChild(itemLegend);
282 :     legends.addChild(groupLegend);
283 :    
284 :     // Set up and add a hover control to each legend.
285 :     var itemHC:HoverControl = new HoverControl(itemLegend.items);
286 :     itemHC.onRollOver = legendRollOver;
287 :     itemHC.onRollOut = legendRollOut;
288 :     var groupHC:HoverControl = new HoverControl(groupLegend.items);
289 :     groupHC.onRollOver = legendRollOver;
290 :     groupHC.onRollOut = legendRollOut;
291 : dservos 1.1
292 : dservos 1.2
293 :     // Position and add the labels and title to the axes.
294 : dservos 1.1 labelX.x = vis.bounds.width/2 - labelX.width/2;
295 :     labelX.y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + xLabelsHeight;
296 :     vis.xyAxes.xAxis.addChild(labelX);
297 :    
298 :     labelY.x = -vis.x;
299 :     labelY.y = vis.bounds.height/2 - labelY.width/2;
300 :     labelY.rotation = -90;
301 :     vis.xyAxes.yAxis.addChild(labelY);
302 :    
303 :     title.x = vis.bounds.width/2 - title.width/2;
304 :     title.y = -vis.y;
305 :     vis.xyAxes.addChild(title);
306 :    
307 : dservos 1.2 // Add the legeneds container to the visualization.
308 :     vis.addChild(legends);
309 : dservos 1.1
310 : dservos 1.2 // Set up the hovercontrol for the marks on the chart
311 : dservos 1.1 var hc:HoverControl = new HoverControl(vis, Filters.isDataSprite);
312 :     hc.onRollOver = rollOver;
313 :     hc.onRollOut = rollOut;
314 :    
315 : dservos 1.2 // Set up the buttons and a container for them.
316 :     var controls:Sprite = new Sprite();
317 :     var bInvert:Button = new Button("Invert Axes");
318 :     var bHideAxis:Button = new Button("Hide Axes");
319 :     var bHideXLabel:Button = new Button("Hide X Labels");
320 :     var bHideYLabel:Button = new Button("Hide Y Labels");
321 :    
322 :     var hideXLabelTransitioner:Transitioner = new Transitioner(2);
323 :     bHideXLabel.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
324 :     if(!hideXLabelTransitioner.running) {
325 :     hideXLabelTransitioner.reset();
326 :    
327 :     if(bHideXLabel.text == "Show X Labels") {
328 :     bHideXLabel.text = "Hide X Labels";
329 :     vis.xyAxes.xAxis.showLabels = true;
330 :     vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + vis.x), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
331 :     } else {
332 :     bHideXLabel.text = "Show X Labels";
333 :     vis.xyAxes.xAxis.showLabels = false;
334 :     vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + vis.x), loaderInfo.height - (vis.y + labelX.height));
335 :     }
336 :    
337 :     hideXLabelTransitioner.$(labelY).x = -vis.x;
338 :     hideXLabelTransitioner.$(labelY).y = vis.bounds.height/2 - labelY.height/2;
339 :    
340 :     vis.update(hideXLabelTransitioner).play();
341 :     }
342 :     });
343 :    
344 :     var hideYLabelTransitioner:Transitioner = new Transitioner(2);
345 :     bHideYLabel.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
346 :     if(!hideYLabelTransitioner.running) {
347 :     var t:Transitioner = new Transitioner(2);
348 :     var newX:int;
349 :    
350 :     hideYLabelTransitioner.reset();
351 :    
352 :     if(bHideYLabel.text == "Show Y Labels") {
353 :     bHideYLabel.text = "Hide Y Labels";
354 :     vis.xyAxes.yAxis.showLabels = true;
355 :     newX = labelY.width + -vis.xyAxes.yAxis.labelOffsetX + yLabelsWidth;
356 :     } else {
357 :     bHideYLabel.text = "Show Y Labels";
358 :     vis.xyAxes.yAxis.showLabels = false;
359 :     newX = labelY.width;
360 :     }
361 :    
362 :     t.$(vis).x = newX;
363 :     vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + newX), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
364 :    
365 :     // Reposition the labels and title.
366 :     t.$(title).x = vis.bounds.width/2 - title.width/2;
367 :     t.$(labelX).x = vis.bounds.width/2 - labelX.width/2;
368 :     t.$(labelX).y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + xLabelsHeight;
369 :     t.$(labelY).x = -newX;
370 :     t.$(labelY).y = vis.bounds.height/2 - labelY.height/2;
371 :    
372 :     // Keep the legends in there place.
373 :     t.$(legends).x = vis.bounds.width + 10;
374 :    
375 :     t.play();
376 :     vis.update(hideYLabelTransitioner).play();
377 :     }
378 :     });
379 :    
380 :     // Set up the transitioner to be used when inverting the axes
381 :     var updateTransitioner:Transitioner = new Transitioner(2);
382 :     updateTransitioner.onEnd = function():void {
383 :     updateMarkVisiblity();
384 :     vis.xyAxes.xAxis.labels.visible = true;
385 :     vis.xyAxes.yAxis.labels.visible = true;
386 :     };
387 :     updateTransitioner.onStart = function():void {
388 :     updateMarkVisiblity();
389 :     vis.xyAxes.xAxis.labels.visible = false;
390 :     vis.xyAxes.yAxis.labels.visible = false;
391 :     }
392 :    
393 :     // The function to invert the axes.
394 : dservos 1.1 bInvert.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
395 : dservos 1.2 // If we are not allready in the process of inverting the axes.
396 :     if(!updateTransitioner.running) {
397 :     var t:Transitioner = new Transitioner(2);
398 :     var tempText:String = labelX.text;
399 :     var tempOffset:int = vis.xyAxes.xAxis.labelOffsetX;
400 :     var tempWidth:uint = vis.bounds.width;
401 :    
402 :     var tempLabels:int = xLabelsHeight;
403 :     var currentXLabelsHeight:int = getMaxWidth(vis.xyAxes.yAxis.labels);
404 :    
405 :     var tempShowLabels:Boolean = vis.xyAxes.xAxis.showLabels;
406 : dservos 1.1
407 : dservos 1.2 // Rest the transitioner for a clean transition.
408 :     updateTransitioner.reset();
409 :    
410 :     // Flip the axis feilds.
411 :     al.xField = axisY;
412 :     al.yField = axisX;
413 :     axisX = al.xField;
414 :     axisY = al.yField;
415 :    
416 :     xLabelsHeight = yLabelsWidth;
417 :     yLabelsWidth = tempLabels;
418 :    
419 :     vis.xyAxes.xAxis.showLabels = vis.xyAxes.yAxis.showLabels;
420 :     vis.xyAxes.yAxis.showLabels = tempShowLabels;
421 :    
422 :     if(vis.xyAxes.yAxis.showLabels) {
423 :     bHideYLabel.text = "Hide Y Labels";
424 :     } else {
425 :     bHideYLabel.text = "Show Y Labels";
426 :     }
427 :    
428 :     if(vis.xyAxes.xAxis.showLabels) {
429 :     bHideXLabel.text = "Hide X Labels";
430 :     } else {
431 :     bHideXLabel.text = "Show X Labels";
432 :     }
433 :    
434 :    
435 :     // Flip the labels
436 :     labelX.text = labelY.text;
437 :     labelY.text = tempText;
438 :    
439 :     // Find the new X value for the visualization.
440 :     var newX:int = labelY.width + vis.xyAxes.xAxis.labelOffsetY + getMaxHeight(vis.xyAxes.xAxis.labels);
441 :    
442 :     // Reposition and set the bounds of the visualization.
443 :     t.$(vis).x = newX;
444 :     vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + newX), loaderInfo.height - (vis.y + currentXLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
445 :    
446 :     // Reposition the labels and title.
447 :     t.$(title).x = vis.bounds.width/2 - title.width/2;
448 :     t.$(labelX).x = vis.bounds.width/2 - labelX.width/2;
449 :     t.$(labelX).y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + currentXLabelsHeight;
450 :     t.$(labelY).x = -newX;
451 :     t.$(labelY).y = vis.bounds.height/2 - labelY.width/2;
452 :    
453 :     // Keep the legends in there place.
454 :     t.$(legends).x = vis.bounds.width + 10;
455 :    
456 :     //Play the transition.
457 :     t.play();
458 :     vis.update(updateTransitioner).play();
459 :     }
460 :     });
461 :    
462 :     // Set up the transitioner for the hide axes button.
463 :     var hideAxisTrans:Transitioner = new Transitioner(1);
464 :    
465 :     // Function for hidding the axes.
466 :     bHideAxis.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
467 :     // If we are not allready in the process of hidding the axes
468 :     if(!hideAxisTrans.running) {
469 :     // Reset the transitoner for a clean transiton.
470 :     hideAxisTrans.reset();
471 :    
472 :     // Hide or show the axes.
473 :     if(bHideAxis.text == "Show Axes") {
474 :     hideAxisTrans.$(bHideAxis).text = "Hide Axes";
475 :     al.showAxes(hideAxisTrans).play();
476 :     } else {
477 :     hideAxisTrans.$(bHideAxis).text = "Show Axes";
478 :     al.hideAxes(hideAxisTrans).play();
479 :     }
480 :     }
481 : dservos 1.1 });
482 :    
483 : dservos 1.2 // Position the buttons inside there container.
484 :     bHideXLabel.x = 0;
485 :     bHideXLabel.y = 0;
486 :    
487 :     bHideAxis.x = legends.width - bHideAxis.width - 5;
488 :     bHideAxis.y = bHideXLabel.y;
489 :    
490 :     bInvert.x = legends.width - bInvert.width - 5;
491 :     bInvert.y = bHideXLabel.y + bHideXLabel.height + 2;
492 :    
493 :     bHideYLabel.x = 0;
494 :     bHideYLabel.y = bHideXLabel.y + bHideXLabel.height + 2;
495 :    
496 :     // Poistion the buttons container.
497 :     controls.x = legends.x + vis.x;
498 :     controls.y = legends.y + legends.height + vis.y + 20;
499 :    
500 :     // Add the buttons to the container and the container to the main sprite.
501 :     controls.addChild(bInvert);
502 :     controls.addChild(bHideAxis);
503 :     controls.addChild(bHideXLabel);
504 :     controls.addChild(bHideYLabel);
505 :     addChild(controls);
506 :    
507 :     // Set the marks on the chart to the higest deepth.
508 :     vis.setChildIndex(vis.marks, vis.numChildren - 1);
509 :    
510 :     // Update.
511 : dservos 1.1 vis.update();
512 : dservos 1.2 updateMarkVisiblity();
513 : dservos 1.1 }
514 :    
515 : dservos 1.2 /**
516 :     * Roll over function witch makes the object 0.5 units bigger and adds a glow filter.
517 :     * @param ob the object witch was rolled over.
518 :     */
519 : dservos 1.1 private function rollOver(ob:Object):void {
520 :     ob.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
521 : dservos 1.2 ob.size += 0.5;
522 : dservos 1.1 }
523 :    
524 : dservos 1.2 /**
525 :     * Roll out function witch removes the filters and makes the object 0.5 units smaller.
526 :     * @param ob the object witch was rolled out of.
527 :     */
528 : dservos 1.1 private function rollOut(ob:Object):void {
529 :     ob.filters = null;
530 : dservos 1.2 ob.size -= 0.5;
531 : dservos 1.1 }
532 :    
533 : dservos 1.2 /**
534 :     * Roll over function for the dialog box.
535 :     * Adds a glow filter to the curently active dialog box.
536 :     * @param ob a child of the dialog box.
537 :     */
538 : dservos 1.1 private function boxRollOver(ob:Object):void {
539 :     if(lastBoxData != null) {
540 :     lastBoxData.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
541 :     }
542 :     }
543 :    
544 : dservos 1.2 /**
545 :     * Roll out function for the dialog box.
546 :     * Removes filters on the curently active dialog box.
547 :     * @param ob a child of the dialog box.
548 :     */
549 : dservos 1.1 private function boxRollOut(ob:Object):void {
550 :     if(lastBoxData != null) {
551 :     lastBoxData.filters = null;
552 :     }
553 :     }
554 :    
555 : dservos 1.2 /**
556 :     * Finds the Legend belonging to the LegendItem passed.
557 :     * TODO: See if this can be replaced by a .parent call.
558 :     * @param item a LegendItem to find the Legend of.
559 :     * @return the Legend that contains the passed LegendItem.
560 :     */
561 :     private function findLegendByItem(item:LegendItem):Legend {
562 :     for(var i:uint = 0; i < legends.numChildren; i++ ) {
563 :     if(Legend(legends.getChildAt(i)).items.contains(item)) {
564 :     return Legend(legends.getChildAt(i));
565 :     }
566 :     }
567 :    
568 :     return null;
569 :     }
570 :    
571 :     /**
572 :     * Roll over function for legends.
573 :     * Adds a glow filter to the legend's item aswell as all the markers on the chart
574 :     * that are realted to the legend item and incrases there size by 1 unit.
575 :     * @param ob the LegendItem being rolled over.
576 :     */
577 :     private function legendRollOver(ob:LegendItem):void {
578 :     var legend:Legend = findLegendByItem(ob);
579 :     var dataName:String = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
580 :    
581 :     ob.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
582 :    
583 :     vis.data.visit(function(d:DataSprite):void {
584 :     if(d.data.hasOwnProperty(dataName) && ob.value == d.data[dataName]) {
585 :     d.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
586 :     d.size += 1;
587 :     }
588 :     }, 3, Filters.isDataSprite);
589 :     }
590 :    
591 :     /**
592 :     * Roll out function for legends.
593 :     * Removes filters to the legend's item aswell as all the markers on the chart
594 :     * that are realted to the legend item and decrases there size by 1 unit.
595 :     * @param ob the LegendItem being rolled out of.
596 :     */
597 :     private function legendRollOut(ob:LegendItem):void {
598 :     var legend:Legend = findLegendByItem(ob);
599 :     var dataName:String = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
600 :    
601 :     ob.filters = null;
602 :    
603 :     vis.data.visit(function(d:DataSprite):void {
604 :     if(d.data.hasOwnProperty(dataName) && ob.value == d.data[dataName]) {
605 :     d.filters = null;
606 :     d.size -= 1;
607 :     }
608 :     }, 3, Filters.isDataSprite);
609 :     }
610 :    
611 :     /**
612 :     * Creates and returns a dialog box containing information on the passed data sprite.
613 :     * @param data the DataSprite containing the information to display.
614 :     * @returns the Sprite containing the dialog box.
615 :     */
616 : dservos 1.1 private function dataDialogBox(data:DataSprite):Sprite {
617 :     var box:Sprite = new Sprite;
618 :    
619 :     var backGround:Sprite = new Sprite;
620 :     backGround.graphics.beginFill(0x7777ff, 0.60);
621 :     backGround.graphics.lineStyle(3, 0x0000ff, 0.3);
622 :    
623 :     var text:Sprite = new Sprite;
624 : dservos 1.2 var x:int = 5;
625 :     var y:int = 0;
626 :    
627 :     for(var property:Object in data.data) {
628 :     var temp:TextSprite = new TextSprite(property.toString() + ": " + data.data[property], new TextFormat("mono", 12, null, true));
629 :     temp.x = x;
630 :     temp.y = y;
631 :     text.addChild(temp);
632 :     y += temp.height;
633 :     }
634 :    
635 :     /*var name:TextSprite = new TextSprite(data.data.student, new TextFormat("mono", 20, null, true));
636 : dservos 1.1 var item:TextSprite = new TextSprite("Item: " + data.data.item, new TextFormat("mono", 12, null, true));
637 :     var grade:TextSprite = new TextSprite("Grade: " + data.data.grade + "%", new TextFormat("mono", 12, null, true));
638 :     var group:TextSprite = new TextSprite("Group: " + data.data.group, new TextFormat("mono", 12, null, true));
639 :     text.addChild(name);
640 :     text.addChild(item);
641 :     text.addChild(group);
642 :     text.addChild(grade);
643 :    
644 :     name.x = text.width/2 - name.width/2;
645 :     item.x = 5;
646 :     grade.x = 5;
647 :     group.x = 5;
648 :    
649 :     name.y = 0;
650 :     item.y = name.y + name.height;
651 :     group.y = item.y + item.height;
652 : dservos 1.2 grade.y = group.y + group.height;*/
653 : dservos 1.1
654 : dservos 1.2 backGround.graphics.drawRoundRect(0, 0, text.width + 10, text.height, 30, 30);
655 : dservos 1.1
656 :     box.addChild(backGround);
657 :     box.addChild(text);
658 :    
659 :     return box;
660 :     }
661 :    
662 : dservos 1.2 /**
663 :     * Check if a mark on the chart is visible based on the related LegendItems states.
664 :     * @param d the DataSprite to check the visiblility of.
665 :     * @returns true if the mark is visible.
666 :     */
667 :     private function markIsVisible(d:DataSprite):Boolean {
668 :     var items:Array = getLegendItems(d);
669 :    
670 :     for each(var item:LegendItem in items) {
671 :     if(item.alpha != 1) {
672 :     return false;
673 :     }
674 :     }
675 :    
676 :     return true;
677 :     }
678 :    
679 :     /**
680 :     * Gets all LegenedItems realted to a given DataSprite/mark.
681 :     * @params d the DataSprite on the chart.
682 :     * @returns Array of LegendItems that are realted to the given DataSprite.
683 :     */
684 :     private function getLegendItems(d:DataSprite):Array {
685 :     var items:Array = new Array();
686 :    
687 :     for(var i:uint = 0; i < legends.numChildren; i++) {
688 :     var legend:Legend = Legend(legends.getChildAt(i));
689 :    
690 :     for(var k:uint = 0; k < legend.items.numChildren; k++) {
691 :     var item:LegendItem = LegendItem(legend.items.getChildAt(k));
692 :    
693 :     if(d.data[legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1)] == item.value) {
694 :     items.push(item);
695 :     break;
696 :     }
697 :     }
698 :     }
699 :    
700 :     return items;
701 :     }
702 :    
703 :     /**
704 :     * Sets the visible atrubute of the marks/DataSprites based on the status of the LegendItems realted to it.
705 :     * @param item if set, only updates marks for that LegendItem. Otherwise updates all marks.
706 :     */
707 :     private function updateMarkVisiblity(item:LegendItem=null):void {
708 :     var legend:Legend;
709 :     var dataName:String;
710 :    
711 :     if(item != null) {
712 :     legend = findLegendByItem(item);
713 :     dataName = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
714 :     }
715 :    
716 :     vis.data.visit(function(d:DataSprite):void {
717 :     if(item == null || (d.data.hasOwnProperty(dataName) && item.value == d.data[dataName])) {
718 :     if(markIsVisible(d)) {
719 :     //d.alpha = 1.0;
720 :     d.visible = true;
721 :     } else {
722 :     //d.alpha = 0.0;
723 :     d.visible = false;
724 :     }
725 :     }
726 :     }, 3, Filters.isDataSprite);
727 :     }
728 :    
729 :     /**
730 :     * Function to be called when a LegendItem is clicked.
731 :     * Changes the legendItems alpah value and updates mark visiblity.
732 :     * @param evt the mouse event.
733 :     */
734 :     private function legendClick(evt:MouseEvent):void {
735 :     var item:LegendItem = LegendItem(evt.target);
736 :    
737 :     if(item.alpha == 1) {
738 :     item.alpha = 0.4;
739 :     } else {
740 :     item.alpha = 1.0;
741 :     }
742 :    
743 :     updateMarkVisiblity(item);
744 :     }
745 :    
746 :     /**
747 :     * Function called when a click happens on a mark on the chart.
748 :     * Creates and adds a dialog box for that mark/DataSprite when clicked or removes the dialog box if
749 :     * the mark allready has one.
750 :     * @param the mouse event.
751 :     */
752 : dservos 1.1 private function mouseClicked(evt:MouseEvent):void {
753 :     if(DisplayObject(evt.target).parent == vis.marks) {
754 :     if(lastBox != null && lastBoxData != null) {
755 :     lastBoxData.removeChild(lastBox);
756 : dservos 1.2 boxhc.detach();
757 : dservos 1.1 }
758 :    
759 :     if(evt.target != lastBoxData) {
760 :     lastBox = dataDialogBox(DataSprite(evt.target));
761 :     lastBoxData = DataSprite(evt.target);
762 :     Sprite(evt.target).addChild(lastBox);
763 :     vis.marks.setChildIndex(Sprite(evt.target), vis.marks.numChildren - 1);
764 : dservos 1.2 boxhc.attach(Sprite(evt.target));
765 : dservos 1.1 } else {
766 :     lastBoxData = null;
767 :     lastBox = null;
768 :     }
769 :     }
770 :     }
771 :     }
772 :     }

Moodle CVS Admin
ViewVC Help
Powered by ViewVC 1.0.7