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 = "
" + data + "
"; - } - } - } - - function isPopupBlocked(testPopup) - { - var popupBlocked = false; - if (testPopup==null || typeof(testPopup) == "undefined" || testPopup.outerWidth == 0 || testPopup.outerHeight == 0 || testPopup.test == "undefined") - { - //Test for most browsers - popupBlocked = true; - } - else - { - //Test for chrome - testPopup.onload = function() { - setTimeout(function() { - if (testPopup.screenX === 0) { - popupsBlocked = true; - } - }, 0); - }; - } - - return popupBlocked; + 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); } function expand() @@ -129,7 +90,6 @@ document.getElementById("GTEContainer").style.height = "580px"; document.getElementById("GTEContainer").style.width = "85%"; - document.getElementById("solutionContainer").style.width = "85%"; document.getElementById("expandButton").innerHTML = "Expand"; } @@ -141,12 +101,11 @@ //Remove borders document.getElementById("GTEContainer").style.padding = ""; - document.getElementById("GTEContainer").style.border =""; + document.getElementById("GTEContainer").style.border ="0px"; //Maximize GTEContainer & solutionContainer document.getElementById("GTEContainer").style.height = "100%"; document.getElementById("GTEContainer").style.width = "100%"; - document.getElementById("solutionContainer").style.width = "100%"; //Change button text document.getElementById("expandButton").innerHTML = "Contract"; @@ -187,14 +146,14 @@ - + - + @@ -215,12 +174,6 @@
- -