From 72b2c418c09f6b81418bba2a328397b54bf6ed6b Mon Sep 17 00:00:00 2001
From: alfongj
Date: Wed, 3 Aug 2011 19:51:27 +0100
Subject: [PATCH] This commit closes Issues #27, #29, #36.1, #36.2, #37; opens
#41, #42, #43, #44, updates #41 and closes #42 and #43
---
gui-builder/assets/icons/pan_tool.png | Bin 212 -> 704 bytes
.../lse/math/games/builder/io/FileManager.as | 14 +-
.../src/lse/math/games/builder/model/Iset.as | 6 +-
.../builder/presenter/TreeGridPresenter.as | 14 +-
.../games/builder/settings/UserSettings.as | 20 +-
.../src/lse/math/games/builder/view/Main.mxml | 107 +++++++---
.../games/builder/viewmodel/DepthAdjuster.as | 190 +++++++++---------
gui-builder/src/util/EvCodes.as | 14 ++
gui-builder/src/util/EventManager.as | 51 +++++
gui-builder/src/util/Log.as | 63 ++++--
web-service/war/builder/index.jsp | 67 +-----
11 files changed, 333 insertions(+), 213 deletions(-)
create mode 100644 gui-builder/src/util/EvCodes.as
create mode 100644 gui-builder/src/util/EventManager.as
diff --git a/gui-builder/assets/icons/pan_tool.png b/gui-builder/assets/icons/pan_tool.png
index 2413c903a456b66588d42adbb4c80588baf97d58..dad3606d67a8207aef1d98fc318fb2f0fd3be42a 100644
GIT binary patch
delta 691
zcmV;k0!;nX0l)>28Gi-<001BJ|6u?C010qNS#tmY4c7nw4c7reD4Tcy001CkNK#Dz
z0D2_=0Dyx40Qvs_0D$NK08$750ToyP06Lcd02go9S|5-A00KryL_t(|+N4uGYa2ln
zoVR;YZco?P!32zi?_{tD7*eG(fwXB1NoN~UBtfoR`zN??ntv3*ij&TE7lZ#m0)hMk
zS0+B)apoF%d$KvWqUXr
zQkteFO;a-*4u45X*|sdp6XF)-T7a1WU`a}OX^dHo<9IvEGLdDOh~s$M7_%y+yacc`
z#$F3BGl*!Dh>nV)$NUrLNtJP9jmcjS^
zx98{Qm%U!^zLYWnfYE4lZ*FexU~zGAMkxiQlx2+B55q7M_|LJ3=s1d^S3-!+c!e$7
zwxepbnvX`K`N<0Xet#oLl7)J`{>F9PA5j#wiRhSC*0!!plv2Jl#ykR$GV|lv+1UdC
z==b{@M1S-dfFp$XqP2d{%zH%iD@a5HX5M4wPnAkV6-9A3&-3MGvpEj{Ns=rprM^`v
zm9#9&HD*4Wr1Hvx@xz(cdPWFw(r7exlu|}1Wg3mfju7HRYdr(t>}I5InP`kbS(c&J
zx>Kvw*l`@;IF6{*YOJ;Hlw}zjWB%L)A}X1=6D$P5z!)C=u{g-xiDBJ2nU_EgOS+@4BLl<6e(pbstUx|zfk$L9
z0|Vb-5N14{zaj-FnCa=_7-Hc+H|R7Ug968=|Mj={%u0Sl#YU-GIJ&rmn9lpQMPBRY
z`l}5FOcpV3FU$=7-tniV{_%!Q3%6H0%qx+3(P$%o{m9G*FD@OtwRir+4d+6?%w9gP
txiUCdZ-M$Q$G2T8%S!wzVuV%yFqF*I{wTad<0;Tq22WQ%mvv4FO#oQdP7DA5
diff --git a/gui-builder/src/lse/math/games/builder/io/FileManager.as b/gui-builder/src/lse/math/games/builder/io/FileManager.as
index 060b07e..3843278 100644
--- a/gui-builder/src/lse/math/games/builder/io/FileManager.as
+++ b/gui-builder/src/lse/math/games/builder/io/FileManager.as
@@ -1,9 +1,7 @@
package lse.math.games.builder.io
{
- import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.IOErrorEvent;
- import flash.events.TimerEvent;
import flash.external.ExternalInterface;
import flash.net.FileFilter;
import flash.net.FileReference;
@@ -14,8 +12,6 @@ package lse.math.games.builder.io
import lse.math.games.builder.presenter.TreeGridPresenter;
import lse.math.games.builder.settings.UserSettings;
- import mx.core.FlexGlobals;
-
import util.Log;
import util.PromptTwoButtons;
@@ -86,8 +82,10 @@ package lse.math.games.builder.io
if(settings.cookiesStorable /*&& autosave_on */)
{
- //Have to get a new instance of the shared object because it might have not existed previously
- SharedObject.getLocal( "autosave", "/" ).setProperty("treeXML", value);
+ if(treeStorage == null)
+ treeStorage = SharedObject.getLocal( "autosave", "/" );
+
+ treeStorage.setProperty("treeXML", value);
unsavedChanges = false;
}
}
@@ -287,6 +285,10 @@ package lse.math.games.builder.io
filename = getNameFromFile(fr);
unsavedChanges = false;
+ //As the user has its tree saved as a .xml, he wouldn't like to have it also as a SharedObject
+ if(treeStorage != null)
+ treeStorage.clear();
+
fr = null;
}
diff --git a/gui-builder/src/lse/math/games/builder/model/Iset.as b/gui-builder/src/lse/math/games/builder/model/Iset.as
index b7ecb84..afb32e0 100644
--- a/gui-builder/src/lse/math/games/builder/model/Iset.as
+++ b/gui-builder/src/lse/math/games/builder/model/Iset.as
@@ -305,7 +305,7 @@ package lse.math.games.builder.model
{
if (this == h)
{
- log.add(Log.ERROR, "Couldn't merge the Isets: please select two different ones");
+ log.add(Log.HINT, "Couldn't merge the Isets: please select two different ones");
return false;
}
if (this.player != h.player)
@@ -318,6 +318,10 @@ package lse.math.games.builder.model
log.add(Log.ERROR, "Couldn't merge the Isets: please select two with the same number of moves");
return false;
}
+ if (this.player == Player.CHANCE)
+ {
+ log.add(Log.HINT, "Chance nodes aren't mergeable into an Iset");
+ }
return true;
}
diff --git a/gui-builder/src/lse/math/games/builder/presenter/TreeGridPresenter.as b/gui-builder/src/lse/math/games/builder/presenter/TreeGridPresenter.as
index f80086c..b1c6a55 100644
--- a/gui-builder/src/lse/math/games/builder/presenter/TreeGridPresenter.as
+++ b/gui-builder/src/lse/math/games/builder/presenter/TreeGridPresenter.as
@@ -569,9 +569,10 @@ package lse.math.games.builder.presenter
// URL Request Handler below here...
public function runAlgorithm(algo:Object, seed:String):void
- {
- if (algo != null && algo.service == undefined || algo.url == undefined) {
- Alert.show("Algorithm not configured");
+ {
+ if (algo == null || algo.service == null || algo.service == undefined
+ || algo.url == null || algo.url == undefined) {
+ log.add(Log.ERROR, "Algorithm not configured");
return;
}
@@ -594,8 +595,13 @@ package lse.math.games.builder.presenter
} else if (algo.type == "xf") {
params.g = getTreeParam();
} else {
- Alert.show("type was not recognized: " + algo.type);
+ log.add(Log.ERROR, "type was not recognized: " + algo.type);
}
+
+ log.add(Log.HINT, "You don't see the output? It is shown in a PopUp window " +
+ "in your browser, so you'll have to configure it previously. Don't forget to " +
+ "save your changes before.");
+
srv.send(params);
}
diff --git a/gui-builder/src/lse/math/games/builder/settings/UserSettings.as b/gui-builder/src/lse/math/games/builder/settings/UserSettings.as
index 2e561f2..c91c56b 100644
--- a/gui-builder/src/lse/math/games/builder/settings/UserSettings.as
+++ b/gui-builder/src/lse/math/games/builder/settings/UserSettings.as
@@ -23,11 +23,8 @@ package lse.math.games.builder.settings
* @author alfongj based on Ian Serlin's work
*/
public class UserSettings
- {
- /**
- * The Singleton instance of the Settings to use when accessing properties and methods of the Settings.
- */
- public static const instance:UserSettings = new UserSettings( SettingsSingletonLock );
+ {
+ private static var _instance:UserSettings = null;
private const FILENAME:String = "settings";
@@ -52,6 +49,19 @@ package lse.math.games.builder.settings
}
}
+ /**
+ * The Singleton instance of the Settings to use when accessing properties and methods of the Settings.
+ */
+ public static function get instance():UserSettings
+ {
+ if(_instance == null)
+ {
+ _instance = new UserSettings(SettingsSingletonLock);
+ }
+
+ return _instance;
+ }
+
/** If the settings have been loaded from local storage */
public function get loaded():Boolean
{
diff --git a/gui-builder/src/lse/math/games/builder/view/Main.mxml b/gui-builder/src/lse/math/games/builder/view/Main.mxml
index c45c156..eb3259e 100644
--- a/gui-builder/src/lse/math/games/builder/view/Main.mxml
+++ b/gui-builder/src/lse/math/games/builder/view/Main.mxml
@@ -7,6 +7,10 @@
[Bindable]
- public var log:Log = Log.instance;
+ private var log:Log = Log.instance;
[Bindable]
- public var fileManager:FileManager;
//if moved to declarations, erase the 'added' property in 'filename' textbox
+ private var fileManager:FileManager;
+
+ private var eventManager:EventManager = EventManager.instance;
private function initVars():void
{
@@ -76,6 +84,19 @@
}
}
+ // Handles click on the canvas
+ private function handleClickOnCanvas():void
+ {
+ if(opModeBar2.selectedIndex <= 7)
+ controller.doActionAt(canvas.mouseX, canvas.mouseY);
+ else
+ treePainter.selectAndEdit(controller, canvas.mouseX, canvas.mouseY);
+ }
+
+
+
+ /* <--- --- TOOLBARS-RELATED FUNCTIONS --- ---> */
+
//Pops up a settings dialog
private function showSettings():void
{
@@ -107,15 +128,6 @@
throw new Error("callback for index " + idx + " not found");
}
- // Handles click on the canvas
- private function handleClickOnCanvas():void
- {
- if(opModeBar2.selectedIndex <= 7)
- controller.doActionAt(canvas.mouseX, canvas.mouseY);
- else
- treePainter.selectAndEdit(controller, canvas.mouseX, canvas.mouseY);
- }
-
// Changes orientation of the tree
private function changeOrientation(orientation:int):void
{
@@ -136,8 +148,53 @@
}
}
- //*** Keyboard shortcut handlers ***
+ //Executes the clear() function from the TreeGridController, epending on the button pressed as a result of the prompt
+ private function clearDependingOnPromptResult():void
+ {
+ if(PromptTwoButtons.buttonPressed == PromptTwoButtons.OK)
+ controller.clear();
+ }
+
+
+
+ /* <--- --- LOGLINE-RELATED FUNCTIONS --- ---> */
+
+ //Registers a listener for HINTs added to Log, which will call updateHint
+ private function initLogLineListener():void
+ {
+ eventManager.addEventListener(EvCodes.HINT_ADDED, updateLogLine);
+ }
+
+ private var lastLogLineTimeoutId:int = -1;
+
+ //Updates the LogLine with the text from
+ private function updateLogLine(evt:TextEvent):void
+ {
+ logLine.text = evt.text;
+ if(lastLogLineTimeoutId != -1)
+ clearTimeout(lastLogLineTimeoutId);
+
+ var optimalMsForReading:int = Math.max(3000, 1000+evt.text.length*67);
+ //These ms are calculated from average lowest reading speed in english (200 wpm)
+ //and average of letters per word in english (4.5), plus two extra sources of extra
+ //time: counting the non-letter characters as letters, and giving one sec at the start for noticing
+ //there is something written.
+
+ lastLogLineTimeoutId = setTimeout(clearLogLine, optimalMsForReading);
+ }
+
+ //Erases the logLine text
+ private function clearLogLine():void {
+ lastLogLineTimeoutId = -1;
+ logLine.text = "";
+ }
+
+
+
+ /* <--- --- KEYBOARD EVENT HANDLERS --- ---> */
private var opModeBar2lastSelectedIdx:int = 0;
+
+ //Shortcuts when key is pressed
protected function sc_keyDownHandler(event:KeyboardEvent):void
{
var ctrl:Boolean = event.ctrlKey;
@@ -146,10 +203,11 @@
switch(event.keyCode)
{
case Keyboard.SPACE:
+ //TODO: DEBUG, it is not working properly
if(tab == "Extensive Form")
{
scrollbar.enableMouseScrolling();
- opModeBar2lastSelectedIdx = opModeBar2.selectedIndex;
+ opModeBar2lastSelectedIdx = opModeBar2.selectedIndex;
opModeBar2.selectedIndex = 7;
}
else if(tab == "Strategic Form")
@@ -158,6 +216,7 @@
}
}
+ //Shortcuts when key is released
protected function sc_keyUpHandler(event:KeyboardEvent):void
{
var ctrl:Boolean = event.ctrlKey;
@@ -169,11 +228,11 @@
case Keyboard.SPACE:
if(tab == "Extensive Form" && opModeBar2lastSelectedIdx != 7)
{
+ //Although we've released spacebar, we need to check this
scrollbar.disableMouseScrolling();
opModeBar2.selectedIndex = opModeBar2lastSelectedIdx;
}
else if(tab == "Strategic Form")
- //Although we've released spacebar, we need to check this
scrollbarNF.disableMouseScrolling();
break;
case 67: //'c'
@@ -208,13 +267,6 @@
break;
}
}
-
- //Executes the clear() function from the TreeGridController, epending on the button pressed as a result of the prompt
- private function clearDependingOnPromptResult():void
- {
- if(PromptTwoButtons.buttonPressed == PromptTwoButtons.OK)
- controller.clear();
- }
]]>
@@ -253,11 +305,10 @@
-
-
+
@@ -267,8 +318,6 @@
-
-
@@ -333,14 +382,16 @@
-
+
-
+
+
+
@@ -354,7 +405,7 @@
text="{fileManager.filename}" keyUp="if(event.keyCode == Keyboard.ENTER) controller.canvas.setFocus(); event.stopPropagation()" keyDown="event.stopPropagation()"
borderVisible="false" color="#EEEEEE" contentBackgroundColor="#B6BABD" disabledColor="#000000"/>
-
+
diff --git a/gui-builder/src/lse/math/games/builder/viewmodel/DepthAdjuster.as b/gui-builder/src/lse/math/games/builder/viewmodel/DepthAdjuster.as
index 06d427f..ac95163 100644
--- a/gui-builder/src/lse/math/games/builder/viewmodel/DepthAdjuster.as
+++ b/gui-builder/src/lse/math/games/builder/viewmodel/DepthAdjuster.as
@@ -18,10 +18,18 @@ package lse.math.games.builder.viewmodel
private var _timeElapsed:int = 0;
+
+ public function DepthAdjuster() {}
public function get timeElapsed():int {return _timeElapsed; }
- public function DepthAdjuster() {}
+ public function get changesData():Boolean { return true; }
+
+ public function get changesSize():Boolean { return true; }
+
+ public function get changesDisplay():Boolean { return true; }
+
+
public function doAction(grid:TreeGrid):void
{
@@ -33,16 +41,91 @@ package lse.math.games.builder.viewmodel
_timeElapsed = getTimer() - prevTime;
}
- public function get changesData():Boolean {
- return true;
- }
-
- public function get changesSize():Boolean {
- return true;
- }
+ //Aligns the 'adjusted' depths of all nodes to be the equal if they belong to the same Iset, taking the maximum possible
+ private function alignDepths(grid:TreeGrid):void
+ {
+ // sort nodes with (1) lowest BASE depth first and (2) left Of first
+ // so, we should clear depth delta before insertion into the pqueue
+ var queue:NodePriorityQueue = new NodePriorityQueue();
+ recAddToQueue(grid.root, queue);
+
+ while (!queue.isEmpty) {
+ var node:Node = queue.shift();
+
+ // nothing to do for nodes with no isets or singleton isets
+ if (node.iset == null || node.iset.numNodes == 1) {
+ continue;
+ }
+
+ // record current depth
+ var below:int = node.depth;
+ var above:int = -1;
+ var potentialPulls:Vector. = new Vector.();
+
+ // find the next lower (closest to the root) depth in the iset
+ // while we are at it remove all items in the iset at the same depth from the queue
+ for (var isetNode:Node = node.iset.firstNode; isetNode != null; isetNode = isetNode.nextInIset) {
+ if (isetNode != node) {
+ if (isetNode.depth < below) {
+ if (isetNode.depth > above) {
+ above = isetNode.depth;
+ }
+ } else if (isetNode.depth == below) {
+ var removeIdx:int = queue.remove(isetNode);
+ if (removeIdx == -1) throw new Error("Node was not found in queue");
+ }
+ }
+ }
+
+ // if the next lower depth == the current depth, this iset is finished and we move on
+ if (above == -1) {
+ continue;
+ }
+
+ // add all the potential pulls
+ for (var potentialPull:Node = node.iset.firstNode; potentialPull != null; potentialPull = potentialPull.nextInIset) {
+ if (potentialPull.depth == above) {
+ potentialPulls.push(potentialPull);
+ }
+ }
+
+ // ignore nodes in iset with greater depth
+ // otherwise for all nodes <= currentDepth and > lowestDepth
+ // recursively add all nodes in ancestor isets smaller than the currentDepth
+ var nodeSet:Vector. = new Vector.();
+ recAddAncestorIsetNodes(below, above, node.iset, nodeSet);
+
+ // once we have that set complete, we can go through the nodes in the starting iset that are less than the current depth
+ // on a node-by-node basis, check to see if it has descendants in the set (only need to check descendants up to the current depth)
+ // if there are no descendants, move to current depth and remove from queue... otherwise stay put
+ while (potentialPulls.length > 0) {
+ var toPull:TreeGridNode = potentialPulls.pop() as TreeGridNode;
+ if (!recHasDecendantsInNodeSet(toPull, below, nodeSet)) {
+ toPull.assignDepth(below);
+
+ // any depth change of a node requires removal from the queue to keep sort order consistent
+ queue.remove(toPull);
+
+ // we need to add children back to queue if they were already processed
+ for (var pulledChild:Node = toPull.firstChild; pulledChild != null; pulledChild = pulledChild.sibling) {
+ if (!queue.contains(pulledChild)) {
+ queue.push(pulledChild);
+ }
+ }
+ }
+ }
+ }
+ }
- public function get changesDisplay():Boolean {
- return true;
+ // Adds node and children to a queue ordered by depth, with their adjusted depth cleared
+ // TODO: add children from right to left to optimize queueing time... need a new pointer to prevSibling or use a DEQueue as NodePriorityQueue
+ private function recAddToQueue(node:Node, queue:NodePriorityQueue):void
+ {
+ for (var child:Node = node.firstChild; child != null; child = child.sibling) {
+ recAddToQueue(child, queue);
+ }
+ (node as TreeGridNode).resetDepth();
+ queue.push(node);
}
private function sortOutCollisions(grid:TreeGrid):void
@@ -145,93 +228,6 @@ package lse.math.games.builder.viewmodel
return didAdjustments;
}
- //Aligns the 'adjusted' depths of all nodes to be the equal if they belong to the same Iset, taking the maximum possible
- private function alignDepths(grid:TreeGrid):void
- {
- // sort nodes with (1) lowest BASE depth first and (2) left Of first
- // so, we should clear depth delta before insertion into the pqueue
- var queue:NodePriorityQueue = new NodePriorityQueue();
- recAddToQueue(grid.root, queue);
-
- while (!queue.isEmpty) {
- var node:Node = queue.shift();
-
- // nothing to do for nodes with no isets or singleton isets
- if (node.iset == null || node.iset.numNodes == 1) {
- continue;
- }
-
- // record current depth
- var below:int = node.depth;
- var above:int = -1;
- var potentialPulls:Vector. = new Vector.();
-
- // find the next lower (closest to the root) depth in the iset
- // while we are at it remove all items in the iset at the same depth from the queue
- for (var isetNode:Node = node.iset.firstNode; isetNode != null; isetNode = isetNode.nextInIset) {
- if (isetNode != node) {
- if (isetNode.depth < below) {
- if (isetNode.depth > above) {
- above = isetNode.depth;
- }
- } else if (isetNode.depth == below) {
- var removeIdx:int = queue.remove(isetNode);
- if (removeIdx == -1) throw new Error("Node was not found in queue");
- }
- }
- }
-
- // if the next lower depth == the current depth, this iset is finished and we move on
- if (above == -1) {
- continue;
- }
-
- // add all the potential pulls
- for (var potentialPull:Node = node.iset.firstNode; potentialPull != null; potentialPull = potentialPull.nextInIset) {
- if (potentialPull.depth == above) {
- potentialPulls.push(potentialPull);
- }
- }
-
- // ignore nodes in iset with greater depth
- // otherwise for all nodes <= currentDepth and > lowestDepth
- // recursively add all nodes in ancestor isets smaller than the currentDepth
- var nodeSet:Vector. = new Vector.();
- recAddAncestorIsetNodes(below, above, node.iset, nodeSet);
-
- // once we have that set complete, we can go through the nodes in the starting iset that are less than the current depth
- // on a node-by-node basis, check to see if it has descendants in the set (only need to check descendants up to the current depth)
- // if there are no descendants, move to current depth and remove from queue... otherwise stay put
- while (potentialPulls.length > 0) {
- var toPull:TreeGridNode = potentialPulls.pop() as TreeGridNode;
- if (!recHasDecendantsInNodeSet(toPull, below, nodeSet)) {
- toPull.assignDepth(below);
-
- // any depth change of a node requires removal from the queue to keep sort order consistent
- queue.remove(toPull);
-
- // we need to add children back to queue if they were already processed
- for (var pulledChild:Node = toPull.firstChild; pulledChild != null; pulledChild = pulledChild.sibling) {
- if (!queue.contains(pulledChild)) {
- queue.push(pulledChild);
- }
- }
- }
- }
- }
- }
-
- // Adds node and children to a queue ordered by depth, with their adjusted depth cleared
- // TODO: add children from right to left to optimize queueing time... need a new pointer to prevSibling or use a DEQueue as NodePriorityQueue
- private function recAddToQueue(node:Node, queue:NodePriorityQueue):void
- {
- for (var child:Node = node.firstChild; child != null; child = child.sibling) {
- recAddToQueue(child, queue);
- }
- (node as TreeGridNode).resetDepth();
- queue.push(node);
- }
-
//Adds to nodeSet all nodes with a depth higher than 'top' but lower or equal than 'bottom', starting from the ones inside
//the 'bottom' level inside the 'iset', and looking at their parents Iset's nodes, recursively (its easier to understand
//just by reading the code :) )
diff --git a/gui-builder/src/util/EvCodes.as b/gui-builder/src/util/EvCodes.as
new file mode 100644
index 0000000..56a1f65
--- /dev/null
+++ b/gui-builder/src/util/EvCodes.as
@@ -0,0 +1,14 @@
+package util
+{
+ /**
+ * Enum containing each custom Event name, with a brief description
+ * of when its thrown and what it means.
+ *
+ * @author alfongj
+ */
+ public final class EvCodes
+ {
+ /** Dispatched when a Hint is added to Log, to show it on the Main class */
+ public static const HINT_ADDED:String = "HINT_ADDED";
+ }
+}
\ No newline at end of file
diff --git a/gui-builder/src/util/EventManager.as b/gui-builder/src/util/EventManager.as
new file mode 100644
index 0000000..b89731b
--- /dev/null
+++ b/gui-builder/src/util/EventManager.as
@@ -0,0 +1,51 @@
+package util
+{
+ import flash.errors.IllegalOperationError;
+ import flash.events.EventDispatcher;
+
+ /**
+ * EventManager is a singleton class that can act as Event Dispatcher
+ * and listener for any class, without them having to be related.
+ *
+ * Use this class by calling EventManager.instance, and not by calling
+ * the constructor.
+ *
+ * Call this.dispatchEvent() to dispatch a new event, addEventListener()
+ * to add a listener, and removeEventListener for removing it.
+ *
+ * @author alfongj
+ */
+ public class EventManager extends EventDispatcher
+ {
+ private static var _instance:EventManager = null;
+
+
+
+ /**
+ * DO NOT CALL THE CONSTRUCTOR DIRECTLY, INSTEAD USE EventManager.instance
+ * This acts like a private constructor
+ */
+ public function EventManager( lock:Class ){
+ if( lock != EventManagerSingletonLock ){
+ throw new IllegalOperationError( "Settings is a Singleton, please use the static instance method instead." );
+ }
+ }
+
+ /**
+ * The Singleton instance of the Settings to use when accessing properties and methods of the Settings.
+ */
+ public static function get instance():EventManager
+ {
+ if(_instance == null)
+ {
+ _instance = new EventManager(EventManagerSingletonLock);
+ }
+
+ return _instance;
+ }
+ }
+
+}
+
+//Dummy private class for making the constructor artificially private
+class EventManagerSingletonLock {}
\ No newline at end of file
diff --git a/gui-builder/src/util/Log.as b/gui-builder/src/util/Log.as
index 8237d72..d143803 100644
--- a/gui-builder/src/util/Log.as
+++ b/gui-builder/src/util/Log.as
@@ -1,5 +1,9 @@
package util
{
+ import flash.errors.IllegalOperationError;
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.TextEvent;
import flash.net.FileReference;
import mx.collections.ArrayList;
@@ -15,28 +19,35 @@ package util
{
private static var _instance : Log = null; //Instance of the class for making it a singleton (needed for binding lastMessage)
+ private var dispatcher:EventManager = EventManager.instance;
+
+
+
public static function get instance():Log
{
if(_instance == null)
{
- _instance = new Log();
+ _instance = new Log(LogSingletonLock);
}
return _instance;
}
- //TODO: Control it has not been instantiated, as in UserSettings
- public function Log() {}
+ public function Log(lock:Class) {
+ if( lock != LogSingletonLock ){
+ throw new IllegalOperationError( "Settings is a Singleton, please use the static instance method instead." );
+ } else {
+ }
+ }
private var lines : ArrayList = new ArrayList();
private const LOG_MAX_LENGTH : int = 100;
[Bindable]
- private var _lastMessage : String = ""; //TODO: This isnt binding
+ private var _lastMessage : String = ""; //TODO: Possibly remove, better throw events
public function get lastMessage():String
{
- //TODO: Depending on the type of the last message, it should show or not, here
if(lines.length==0)
return "";
@@ -44,23 +55,42 @@ package util
var type:String = getStringFromType(entry.type as int);
- return (entry.time as Date).toLocaleTimeString() + " " + type + ": " + entry.line + (entry.origin==null ? "" : " - " + entry.origin);
+ return (entry.time as Date).toLocaleTimeString() + " " + type
+ + ": " + entry.line + (entry.origin==null ? "" : " - " + entry.origin);
}
- /** An ERROR occurred possibly by user interaction, which displays an alert to the user */
+ /**
+ * An ERROR occurred possibly by user interaction, which displays an
+ * alert to the user
+ */
public static const ERROR : int = 1;
- /** An ERROR so important that it must interrupt the workflow, so therefore it is thrown, apart from logged */
+ /**
+ * An ERROR so important that it must interrupt the workflow, so
+ * therefore it is thrown, apart from logged
+ */
public static const ERROR_THROW : int = 2;
- /** A minor ERROR from which the user doesn't have to know anything and therefore isn't shown to him, but that is logged*/
- public static const ERROR_HIDDEN : int = 3; //TODO: Functionality
+ /**
+ * A minor ERROR from which the user doesn't need to know anything
+ * and therefore isn't shown to him. It is treated the same as DEBUG,
+ * the only difference being that this one is marked as an ERROR (something
+ * bad), and DEBUG can just be anything that the debugger would want to track,
+ * not necessarily somethign bad.
+ */
+ public static const ERROR_HIDDEN : int = 3;
/** A substitution of trace(), just debugging info for dev use */
public static const DEBUG : int = 4;
- /** A message sent to the user as to recommmend him doing something */
- public static const HINT : int = 5; //TODO: Fucntionality
+ /**
+ * A message sent to the user as to recommmend him doing something. Not
+ * as invasive as ERROR, because it doesn't show in a PopUp,it shows in the
+ * logLine instead (the space below the canvas).
+ */
+ public static const HINT : int = 5;
+
+
/**
* Traces one line, storing it in the log. Depending on the type of statement you select, it does the following:
@@ -90,13 +120,13 @@ package util
throw new Error(line);
break;
case ERROR_HIDDEN:
- //Do something
+ trace("Error: "+line+(origin==null ? "" : " - "+origin));
break;
case DEBUG:
trace("Debug: "+line+(origin==null ? "" : " - "+origin));
break;
case HINT:
- //Do something: it should be something the user must see
+ dispatcher.dispatchEvent(new TextEvent(EvCodes.HINT_ADDED, false, false, line));
break;
default:
@@ -167,4 +197,7 @@ package util
}
}
}
-}
\ No newline at end of file
+}
+
+//Dummy private class for making the constructor artificially private
+class LogSingletonLock {}
\ No newline at end of file
diff --git a/web-service/war/builder/index.jsp b/web-service/war/builder/index.jsp
index b3d55a3..6e23fa1 100644
--- a/web-service/war/builder/index.jsp
+++ b/web-service/war/builder/index.jsp
@@ -32,6 +32,7 @@
var attributes = {
id:"GuiBuilder"
};
+ attributes.align = "middle";
var fullwindow = true;
@@ -53,7 +54,6 @@
document.title = 'GTE - '+value;
}
- var inThisWindowOutput = false;
var outputWindow = null;
function writeSolution(data)
@@ -70,51 +70,12 @@
outputWindow=window.open("", "Output", "height=500, width=500, toolbar=yes, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes");
- if(!isPopupBlocked(outputWindow))
- {
- outputWindow.document.write("Output");
- outputWindow.document.write("
");
- outputWindow.document.write("
"+data+"
");
- outputWindow.document.close();
- var desiredHeight = Math.min(outputWindow.document.getElementById("solutionHeader").offsetHeight + outputWindow.document.getElementById("solution").offsetHeight + 100 , 750);
- outputWindow.resizeTo(500,desiredHeight);
- } else {
- if(!inThisWindowOutput)
- {
- inThisWindowOutput = confirm("Your browser is blocking popups, you should change that setting. Meanwhile, do you want to use in-window output?");
- alert("ALERT: If you are going to enable popups in your browser, please save the current file in advance, as the window might restart");
- }
-
- if(inThisWindowOutput)
- {
- document.getElementById("solutionContainer").style.display="";
- document.getElementById("solutionHeader").style.backgroundColor = headerBackgroundColor;
- document.getElementById("solution").innerHTML = "