diff --git a/bin/Console.swc b/bin/Console.swc index 9385da5..7232140 100644 Binary files a/bin/Console.swc and b/bin/Console.swc differ diff --git a/bin/ConsoleRemote.air b/bin/ConsoleRemote.air index d1d1bb0..8dc8167 100644 Binary files a/bin/ConsoleRemote.air and b/bin/ConsoleRemote.air differ diff --git a/bin/SampleBasic.swf b/bin/SampleBasic.swf index c3b8437..f22cf3a 100644 Binary files a/bin/SampleBasic.swf and b/bin/SampleBasic.swf differ diff --git a/bin/consoleRemote.swf b/bin/consoleRemote.swf index b344af5..9c9e823 100644 Binary files a/bin/consoleRemote.swf and b/bin/consoleRemote.swf differ diff --git a/bin/sampleAdvanced.swf b/bin/sampleAdvanced.swf index a6fb1cb..96f6452 100644 Binary files a/bin/sampleAdvanced.swf and b/bin/sampleAdvanced.swf differ diff --git a/bin/sampleStyle.swf b/bin/sampleStyle.swf index b7f513a..c45946c 100644 Binary files a/bin/sampleStyle.swf and b/bin/sampleStyle.swf differ diff --git a/build/build.xml b/build/build.xml index 5c0e06c..4868482 100644 --- a/build/build.xml +++ b/build/build.xml @@ -28,7 +28,7 @@ - + @@ -89,11 +89,30 @@ - + + + + + + + + + + + + + + + + + + + + @@ -102,7 +121,13 @@ - + + + + + + + @@ -147,20 +172,29 @@ - + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + diff --git a/build/project.properties b/build/project.properties index f0b11c5..1bd91e3 100644 --- a/build/project.properties +++ b/build/project.properties @@ -1,5 +1,6 @@ -#Wed Feb 22 00:11:41 GMT 2012 -build.number=611 -build.date=2012/02/22 00\:11 -build.version=2.6 -build.stage= +#Mon, 01 Oct 2012 00:46:18 +0100 +#Thu Mar 01 01:08:19 GMT 2012 +build.number=614 +build.date=2012/10/01 00\:46 +build.version=2.7 +build.stage=BETA diff --git a/doc/Addons.txt b/doc/Addons.txt index 2d9d4d9..a3658ab 100644 --- a/doc/Addons.txt +++ b/doc/Addons.txt @@ -17,16 +17,26 @@ They are not compiled as part of SWC package at the moment as some may require a * Export console logs to a HTML file. preserves channels and priorities. * It also have all those filtering features in HTML page. * Add to menu: `ConsoleHtmlExportAddon.addToMenu();` + * sample: http://console.junkbyte.com/addons/htmlexport/export.html * blog: http://junkbyte.com/wp/as3/console/console-logs-to-html-export-addon/ - * Requires com.adobe.serialization.json.JSON. (May replace in your own code with flash player 11's native JSON) + * Requires flash player 11 OR com.adobe.serialization.json.JSON. + * If you are using com.adobe.serialization.json.JSON, make sure you reference the class somewhere so that it get compiled. ==Command Prompt== * Simulates 'command prompt' style user input. * Ask to choose from a selection of input, user enter into command line to choose a selection. * Could be useful for 'utility' sort of app where there is no GUI to represent user options. - * Currently undocumented. see source code of `CommandPrompt.as`. + * Demo: http://console.junkbyte.com/addons/commandprompt/ + * Blog with demo source: http://junkbyte.com/wp/as3/console/console-command-prompt-addon-demo/ + + + +==`CommandLine` Auto focus== + * Sets focus to commandLine input field whenever Console becomes visible, e.g after entering password key. -==CommandLine Auto focus== - * Sets focus to commandLine input field whenever Console becomes visible, e.g after entering password key. \ No newline at end of file +==Ruler addon== + * Ruler addon let you measure the distance and angle between two points on screen + * Add to menu: `RulerAddon.addToMenu();` + * Start ruler tool by pressing on 'ruler' at the top menu \ No newline at end of file diff --git a/doc/GettingStarted.txt b/doc/GettingStarted.txt index e369ab1..63c4a6a 100644 --- a/doc/GettingStarted.txt +++ b/doc/GettingStarted.txt @@ -1,272 +1,266 @@ -#summary for v2.6 -#labels Featured,Phase-Deploy,Phase-Implementation - - - -=Introduction= - - * The main class you need to use for console is `Cc`, (`com.junkbyte.console.Cc`). - * `Cc` stands for Console controller which acts as singleton adapter for `Console` (`com.junkbyte.console.Console`). - * Asdoc: http://console.junkbyte.com/2.6/asdoc/com/junkbyte/console/Cc.html - - * When you no longer need console in your project, you can remove `Cc.startOnStage(..)` and all other calls through Cc will stop working silently. - -=Basics= - -For easy reference, please see `samples/flash/SampleBasic.as` for working sample. - -==Start on stage== -{{{ -import com.junkbyte.console.Cc; -Cc.startOnStage(this, ""); -}}} - # First parameter is any `DisplayObject` which is already on stage or to be added. - # If you want to set a keyword for console to start, assign at second parameter. - * You will need to type the keyword in correct sequence to show the console. - * Recommended keyword: ``` or ~ or debug. Use letters and numbers only. - * Console will start hidden if you set a password (you can set `Cc.visible = true;` to force display console). - * Entering the keyword while console is visible will hide it - * Password will not trigger if user have focus on an input `TextField` - -==Logging== -{{{ - -Cc.log("Hello world."); -Cc.info("An info message.", "Optionally there", "can be", "multiple arguments."); -Cc.debug("A debug level log.", "You can also pass an object and it'll become a link to inspect:", this); -Cc.warn("This is a warning log.", "Lets try the object linking again:", stage, " <- click it! (press 'exit' when done)"); -Cc.error("This is an error log.", "This link might not work because it can get garbage collected:", new Sprite()); -Cc.fatal("This is a fatal error log with high visibility.", "You will get a short stack trace of where it's called from (configurable)"); -// -// Basic channel logging -// -Cc.infoch("myChannel", "Hello myChannel."); -Cc.debugch("myChannel", "A debug level log.", "There is also Cc.errorch() and Cc.fatalch(). Skipping that for demo."); -// You can also use Cc.errorch() and Cc.fatalch(). -// -// Instanced channel -// -var ch:ConsoleChannel = new ConsoleChannel('myCh'); -ch.info("Hello!", "Works just like other logging methods but this way you keep the channel as an instance."); -}}} - -==UI== - -[http://console.junkbyte.com/2.6/console_controls.png] - -see: doc/console_controls.png - -==Configuration== -You will need to use `Cc.config` to enable or disable some features. -It is recommended to set them before starting console. -Example: -{{{ -Cc.config.commandLineAllowed = true // Enables full commandLine features -Cc.config.tracing = true; // also send traces to flash's normal trace() -Cc.config.maxLines = 2000; // change maximum log lines to 2000, default is 1000 - -Cc.startOnStage(this); // finally start with these config -}}} - -Asdoc: http://console.junkbyte.com/2.6/asdoc/com/junkbyte/console/ConsoleConfig.html - ----- - -=Useful Features (Advanced)= - -For easy reference, please see samples/flash/SampleAdvanced.as for working sample. - -==Object inspection== - * When you log an object in console, it will keep a weak reference to the object - * Example: `Cc.info("Stage is:", stage)` will show up in console as `Stage is: {Stage}` - * Clicking on the link {Stage} will reveal detailed info about stage - * Details shows up in an 'inspection' channel. When you are done, click 'Exit' to return to normal logging view - * As references are stored as weak link, some objects may get garbage collected before you click - * To avoid early garbage collection issue, see Cc.config.objectHardReferenceTimer. - * asdoc: http://console.junkbyte.com/asdoc/com/junkbyte/console/ConsoleConfig.html#objectHardReferenceTimer - * You can click on `[set scope]` to set scope in commandLine (explained later) - * You can manually print detailed info about an object by calling Cc.inspect(...); - -==Keyboard Binding== - * Key binding lets you bind keyboard keys to your own function - * Example usages: open a specific panel, give special items/cheats in a game - * The function you pass get STRONG referenced - * Key Binding will not trigger if user have focus on an input `TextField` - * If triggering something by keyboard is part of the actual project behaviour, it is recommended you write your own to avoid depending on console - * Example below logs "Hello!" in console when user press the key H in keyboard. -{{{ -import com.junkbyte.console.Cc; -import com.junkbyte.console.KeyBind; -Cc.bindKey(new KeyBind("h"), Cc.log, ["Hello!"]); -}}} - -==Command line== - * `CommandLine` let you execute actionscript 3 code at run time - * You must set `Cc.config.commandLineAllowed = true;` to be able to run full features. - * Command line appears at the bottom of main panel (press CL at top menu) - - * *Slash commands* run special functions on demand - * An example of built-in slash command: '/filter log' - * Typing this will filter to logs that match the string 'log' - * You will also get underline under the exact match - * When you are done, change the channel at top OR type '/filter' - - * You can also add your own custom slash commands -{{{ -// Slash command example 1 -Cc.addSlashCommand("test", function():void{ Cc.log("Do the test!");} ); -//When user type "/test" in commandLine, it will call function with no params. - -// Slash command example 2 -Cc.addSlashCommand("test2", function(param:String = ""):void{Cc.log("Do the test2 with param string:", param);} ); -//User type "/test2 abc 123" in commandLine to call Cc.log with one param: "abc 123". -}}} - * If you need multiple params, you will need to do the conversion inside your call back function. -{{{ -// Slash command example 3 (multiple arguments trick) -Cc.addSlashCommand("test3", function(param:String = ""):void{ - var args:Array = param.split(/\s+/); - Cc.log.apply(null, args); // This is where you call a function that accept multiple arguments - }); -//User type "/test3 abc 123" in commandLine to call Cc.log with param 1: "abc", param 2: "123" -}}} - * Functions and arguments you pass get STRONG referenced - * If you are planning to use complex params, consider using `Cc.store` instead - - * You can *store references* for use in commandline -{{{ -//Example 1 (storing functions) -Cc.store("load", function(id:uint){Cc.log("Do some loading with id", id)}); -//User call this function by typing '$load(123);' to load with id 123. -// -//Example 2 (storing anything) -Cc.store("mc", myMC); // assuming myMC is a MovieClip somewhere or could be anything, class, object, etc... -//User manipulate the mc by typing `$mc.x = 100;`, `$mc.alpha = 0.5`, `$mc.parent.removeChild($mc);` etc... -}}} - * NOTE: Cc.store(...) use weak reference by default but you can specify to be strong - * You can go crazy with commandline. Example: - * `stage.getChildByName("Console").filters = new Array(new flash.filters.GlowFilter());` - * Adds glow filter on Console. - * CommandLine have limitations. For better understanding, see CommandLineHelp - -==Display Roller== - * Display roller shows the display tree of objects under your mouse - * Start Display roller by pressing RL at the top menu - * You can capture the display map to console for use in commandLine or for detail inspection - * To do this, click on 'Capture key: *unassigned*' in the RL panel - * Press C on keyboard to bind the capture key to that key - * Roll over to anything you want to capture and press the keyboard C key - * You will get the display map printed on console - * Clicking on the name will set that display (`Sprite/MovieClip` etc) as commandLine's scope - * Clicking on the link inside the {..} will inspect the object showing you the detailed info - * NOTE: You can also use Cc.setRollerCaptureKey(...) to assign the capture key - * Example use: You got an item thats behaving weirdly on screen... - * Use the Roller tool to get reference to that object - * Use link inspection to find out whats wrong with the values - * Use commandline to change and experiment with different property values on the fly - -==Advanced Logging== -Yes, lets go back to logging... here are some extra features: - - * *Cc.stack()* Gives you a stack trace under your string to show where this method is called from (requires debug player) - * Example if you need to clearify from which call to a specific function is causing the bug - -{{{ -Cc.stack("Stack trace called from..."); -/* //If you have debug player, it'll show up in console as: - Stack trace called from... - @ Sample/demoBasics() - @ Sample() -*/ -}}} - * Use `Cc.stackch(ch:String, str:*, depth:int = -1, priority:int = 5)` to have channel name. - - * *Cc.explode()* is similar to JSON where it explodes an object's value to bits so that you can see all in one line -{{{ -Cc.explode(stage); -// logs: {Stage quality:"HIGH", fullScreenWidth:1920, alpha:1, numChildren:2, width:700, height:303, etc... -}}} - * The explosion also give you links to the sub objects - - * *Non-repetitive logging* - * Keeps replacing the previous line that has repeat turned on until certain count is passed - * For example, if you are tracing download progress and you don't want to flood console with it - -{{{ -Cc.add("My advanced log in priority 2, 1st call", 2, true); -Cc.add("My advanced log in priority 2, 2nd call", 2, true); -Cc.add("My advanced log in priority 2, 3rd call", 2, true); -Cc.add("My advanced log in priority 2, 4th call", 2, true); -Cc.add("My advanced log in priority 2, 5th call", 2, true); -// You will only see the last line in console. -// If you want to specify the channel, use: -// Cc.ch(channel:*, str:*, priority:int, isRepeating:Boolean) -}}} - -==Graphing== - * Graphing lets you view number graphs similar to the FPS and memory monitor. (F and M buttons on top menu) - * Example as seen in `samples/SampleAdvanced.as`: -{{{ -//Graph the current mouseX and mouseY values -Cc.addGraph("mouse", this, "mouseX", 0xff3333,"X", new Rectangle(380,180,80,80), true); -Cc.addGraph("mouse", this, "mouseY", 0x3333ff,"Y"); -// Sine wave graph generated by commandline execution, very expensive way to graph but it works :) -Cc.addGraph("mouse", this, "(Math.sin(flash.utils.getTimer()/1000)*300)+300", 0x119911, "sine"); -}}} - -==Extra menu links== - * You can add your own menu link at the top along with other console built-in links. -{{{ -Cc.addMenu("hi", Cc.log, ["Hello from top menu"], "Says hello!"); -}}} - * This adds a link 'hi' on top menu. Rolling over the link will show the tooltip "Says hello!" - * Clicking on the link will print in console "Hello from top menu". - -==Ruler tool== - * Start ruler tool by pressing on RL at the top menu - * Ruler tool let you measure the distance and angle between two points - -==Garbage collection monitor== -{{{ -import flash.display.Sprite; -var aSprite = new Sprite(); -Cc.watch(aSprite, "aSprite"); -aSprite = null; -}}} - * Above example creates a Sprite and then remove its reference. - * This marks the Sprite to be garbage collected, but it might not get collected straight away. - * If you have a debugger version of flash player installed, you can open memory monitor (press M in console menu) and then press G in that panel to force garbage collect. - * You will see that objects you are watching will get notified in console when they are garbage collected. - -==Remoting== - * Remoting sends log data for a remote console to use - * The advantages are: - * You dont need to keep console open in your working flash project - * Logs stays in remote afer closing your working flash project - * You can use commandline, view FPS and memory from remote - * SWF version of remote is in `bin/consoleRemote.swf` - * AIR version of remote is in `bin/ConsoleRemote.air` - * EXE and APP version can be published using `samples/flash/ConsoleRemote.as` - * NOTE: There can be confusion with FPS and memory monitor if you have more than one flash client sending to remote -{{{ -Cc.remoting = true; // turns on remoting -}}} - ----- - -==Custom Style== -You *must* set them before starting console. Example: -{{{ -Cc.config.style.big(); // BIGGER text. -Cc.config.style.whiteBase(); // Black on white. - NOT the way for stealth coders! -Cc.config.style.backgroundAlpha = 1; // opaque background. - -Cc.startOnStage(this); // finally start with these styles -}}} - -example: bin/sampleStyle.swf for demo. (src: `samples/flash/SampleStyle.as`). - -Asdoc: http://console.junkbyte.com/2.6/asdoc/com/junkbyte/console/ConsoleStyle.html - -=Addons= -There are a few addons available for console. See [Addons] +#summary for v2.6 +#labels Featured,Phase-Deploy,Phase-Implementation + + + +=Introduction= + + * The main class you need to use for console is `Cc`, (`com.junkbyte.console.Cc`). + * `Cc` stands for Console controller which acts as singleton adapter for `Console` (`com.junkbyte.console.Console`). + * Asdoc: http://console.junkbyte.com/2.6/asdoc/com/junkbyte/console/Cc.html + + * When you no longer need console in your project, you can remove `Cc.startOnStage(..)` and all other calls through Cc will stop working silently. + +=Basics= + +For easy reference, please see `samples/flash/SampleBasic.as` for working sample. + +==Start on stage== +{{{ +import com.junkbyte.console.Cc; +Cc.startOnStage(this, ""); +}}} + # First parameter is any `DisplayObject` which is already on stage or to be added. + # If you want to set a keyword for console to start, assign at second parameter. + * You will need to type the keyword in correct sequence to show the console. + * Recommended keyword: ``` or ~ or debug. Use letters and numbers only. + * Console will start hidden if you set a password (you can set `Cc.visible = true;` to force display console). + * Entering the keyword while console is visible will hide it + * Password will not trigger if user have focus on an input `TextField` + +==Logging== +{{{ + +Cc.log("Hello world."); +Cc.info("An info message.", "Optionally there", "can be", "multiple arguments."); +Cc.debug("A debug level log.", "You can also pass an object and it'll become a link to inspect:", this); +Cc.warn("This is a warning log.", "Lets try the object linking again:", stage, " <- click it! (press 'exit' when done)"); +Cc.error("This is an error log.", "This link might not work because it can get garbage collected:", new Sprite()); +Cc.fatal("This is a fatal error log with high visibility.", "You will get a short stack trace of where it's called from (configurable)"); +// +// Basic channel logging +// +Cc.infoch("myChannel", "Hello myChannel."); +Cc.debugch("myChannel", "A debug level log.", "There is also Cc.errorch() and Cc.fatalch(). Skipping that for demo."); +// You can also use Cc.errorch() and Cc.fatalch(). +// +// Instanced channel +// +var ch:ConsoleChannel = new ConsoleChannel('myCh'); +ch.info("Hello!", "Works just like other logging methods but this way you keep the channel as an instance."); +}}} + +==UI== + +[http://console.junkbyte.com/2.6/console_controls.png] + +see: doc/console_controls.png + +==Configuration== +You will need to use `Cc.config` to enable or disable some features. +It is recommended to set them before starting console. +Example: +{{{ +Cc.config.commandLineAllowed = true // Enables full commandLine features +Cc.config.tracing = true; // also send traces to flash's normal trace() +Cc.config.maxLines = 2000; // change maximum log lines to 2000, default is 1000 + +Cc.startOnStage(this); // finally start with these config +}}} + +Asdoc: http://console.junkbyte.com/2.6/asdoc/com/junkbyte/console/ConsoleConfig.html + +---- + +=Useful Features (Advanced)= + +For easy reference, please see samples/flash/SampleAdvanced.as for working sample. + +==Object inspection== + * When you log an object in console, it will keep a weak reference to the object + * Example: `Cc.info("Stage is:", stage)` will show up in console as `Stage is: {Stage}` + * Clicking on the link {Stage} will reveal detailed info about stage + * Details shows up in an 'inspection' channel. When you are done, click 'Exit' to return to normal logging view + * As references are stored as weak link, some objects may get garbage collected before you click + * To avoid early garbage collection issue, see Cc.config.objectHardReferenceTimer. + * asdoc: http://console.junkbyte.com/asdoc/com/junkbyte/console/ConsoleConfig.html#objectHardReferenceTimer + * You can click on `[set scope]` to set scope in commandLine (explained later) + * You can manually print detailed info about an object by calling Cc.inspect(...); + +==Keyboard Binding== + * Key binding lets you bind keyboard keys to your own function + * Example usages: open a specific panel, give special items/cheats in a game + * The function you pass get STRONG referenced + * Key Binding will not trigger if user have focus on an input `TextField` + * If triggering something by keyboard is part of the actual project behaviour, it is recommended you write your own to avoid depending on console + * Example below logs "Hello!" in console when user press the key H in keyboard. +{{{ +import com.junkbyte.console.Cc; +import com.junkbyte.console.KeyBind; +Cc.bindKey(new KeyBind("h"), Cc.log, ["Hello!"]); +}}} + +==Command line== + * `CommandLine` let you execute actionscript 3 code at run time + * You must set `Cc.config.commandLineAllowed = true;` to be able to run full features. + * Command line appears at the bottom of main panel (press CL at top menu) + + * *Slash commands* run special functions on demand + * An example of built-in slash command: '/filter log' + * Typing this will filter to logs that match the string 'log' + * You will also get underline under the exact match + * When you are done, change the channel at top OR type '/filter' + + * You can also add your own custom slash commands +{{{ +// Slash command example 1 +Cc.addSlashCommand("test", function():void{ Cc.log("Do the test!");} ); +//When user type "/test" in commandLine, it will call function with no params. + +// Slash command example 2 +Cc.addSlashCommand("test2", function(param:String = ""):void{Cc.log("Do the test2 with param string:", param);} ); +//User type "/test2 abc 123" in commandLine to call Cc.log with one param: "abc 123". +}}} + * If you need multiple params, you will need to do the conversion inside your call back function. +{{{ +// Slash command example 3 (multiple arguments trick) +Cc.addSlashCommand("test3", function(param:String = ""):void{ + var args:Array = param.split(/\s+/); + Cc.log.apply(null, args); // This is where you call a function that accept multiple arguments + }); +//User type "/test3 abc 123" in commandLine to call Cc.log with param 1: "abc", param 2: "123" +}}} + * Functions and arguments you pass get STRONG referenced + * If you are planning to use complex params, consider using `Cc.store` instead + + * You can *store references* for use in commandline +{{{ +//Example 1 (storing functions) +Cc.store("load", function(id:uint){Cc.log("Do some loading with id", id)}); +//User call this function by typing '$load(123);' to load with id 123. +// +//Example 2 (storing anything) +Cc.store("mc", myMC); // assuming myMC is a MovieClip somewhere or could be anything, class, object, etc... +//User manipulate the mc by typing `$mc.x = 100;`, `$mc.alpha = 0.5`, `$mc.parent.removeChild($mc);` etc... +}}} + * NOTE: Cc.store(...) use weak reference by default but you can specify to be strong + * You can go crazy with commandline. Example: + * `stage.getChildByName("Console").filters = new Array(new flash.filters.GlowFilter());` + * Adds glow filter on Console. + * CommandLine have limitations. For better understanding, see CommandLineHelp + +==Display Roller== + * Display roller shows the display tree of objects under your mouse + * Start Display roller by pressing RL at the top menu + * You can capture the display map to console for use in commandLine or for detail inspection + * To do this, click on 'Capture key: *unassigned*' in the RL panel + * Press C on keyboard to bind the capture key to that key + * Roll over to anything you want to capture and press the keyboard C key + * You will get the display map printed on console + * Clicking on the name will set that display (`Sprite/MovieClip` etc) as commandLine's scope + * Clicking on the link inside the {..} will inspect the object showing you the detailed info + * NOTE: You can also use Cc.setRollerCaptureKey(...) to assign the capture key + * Example use: You got an item thats behaving weirdly on screen... + * Use the Roller tool to get reference to that object + * Use link inspection to find out whats wrong with the values + * Use commandline to change and experiment with different property values on the fly + +==Advanced Logging== +Yes, lets go back to logging... here are some extra features: + + * *Cc.stack()* Gives you a stack trace under your string to show where this method is called from (requires debug player) + * Example if you need to clearify from which call to a specific function is causing the bug + +{{{ +Cc.stack("Stack trace called from..."); +/* //If you have debug player, it'll show up in console as: + Stack trace called from... + @ Sample/demoBasics() + @ Sample() +*/ +}}} + * Use `Cc.stackch(ch:String, str:*, depth:int = -1, priority:int = 5)` to have channel name. + + * *Cc.explode()* is similar to JSON where it explodes an object's value to bits so that you can see all in one line +{{{ +Cc.explode(stage); +// logs: {Stage quality:"HIGH", fullScreenWidth:1920, alpha:1, numChildren:2, width:700, height:303, etc... +}}} + * The explosion also give you links to the sub objects + + * *Non-repetitive logging* + * Keeps replacing the previous line that has repeat turned on until certain count is passed + * For example, if you are tracing download progress and you don't want to flood console with it + +{{{ +Cc.add("My advanced log in priority 2, 1st call", 2, true); +Cc.add("My advanced log in priority 2, 2nd call", 2, true); +Cc.add("My advanced log in priority 2, 3rd call", 2, true); +Cc.add("My advanced log in priority 2, 4th call", 2, true); +Cc.add("My advanced log in priority 2, 5th call", 2, true); +// You will only see the last line in console. +// If you want to specify the channel, use: +// Cc.ch(channel:*, str:*, priority:int, isRepeating:Boolean) +}}} + +==Graphing== + * Graphing lets you view number graphs similar to the FPS and memory monitor. (F and M buttons on top menu) + * Example as seen in `samples/SampleAdvanced.as`: +{{{ +//Graph the current mouseX and mouseY values +Cc.addGraph("mouse", this, "mouseX", 0xff3333,"X", new Rectangle(380,180,80,80), true); +Cc.addGraph("mouse", this, "mouseY", 0x3333ff,"Y"); +// Sine wave graph generated by commandline execution, very expensive way to graph but it works :) +Cc.addGraph("mouse", this, "(Math.sin(flash.utils.getTimer()/1000)*300)+300", 0x119911, "sine"); +}}} + +==Extra menu links== + * You can add your own menu link at the top along with other console built-in links. +{{{ +Cc.addMenu("hi", Cc.log, ["Hello from top menu"], "Says hello!"); +}}} + * This adds a link 'hi' on top menu. Rolling over the link will show the tooltip "Says hello!" + * Clicking on the link will print in console "Hello from top menu". + +==Garbage collection monitor== +{{{ +import flash.display.Sprite; +var aSprite = new Sprite(); +Cc.watch(aSprite, "aSprite"); +aSprite = null; +}}} + * Above example creates a Sprite and then remove its reference. + * This marks the Sprite to be garbage collected, but it might not get collected straight away. + * If you have a debugger version of flash player installed, you can open memory monitor (press M in console menu) and then press G in that panel to force garbage collect. + * You will see that objects you are watching will get notified in console when they are garbage collected. + +==Remoting== + * Remoting sends log data for a remote console to use + * The advantages are: + * You dont need to keep console open in your working flash project + * Logs stays in remote afer closing your working flash project + * You can use commandline, view FPS and memory from remote + * AIR version of remote is in `bin/ConsoleRemote.air` +{{{ +Cc.remoting = true; // turns on remoting +}}} +For more information see: [Remoting] + +---- + +==Custom Style== +You *must* set them before starting console. Example: +{{{ +Cc.config.style.big(); // BIGGER text. +Cc.config.style.whiteBase(); // Black on white. - NOT the way for stealth coders! +Cc.config.style.backgroundAlpha = 1; // opaque background. + +Cc.startOnStage(this); // finally start with these styles +}}} + +example: bin/sampleStyle.swf for demo. (src: `samples/flash/SampleStyle.as`). + +Asdoc: http://console.junkbyte.com/2.6/asdoc/com/junkbyte/console/ConsoleStyle.html + +=Addons= +There are a few addons available for console. See [Addons] \ No newline at end of file diff --git a/doc/ReadMe.txt b/doc/ReadMe.txt index e75aedb..2d74ba2 100644 --- a/doc/ReadMe.txt +++ b/doc/ReadMe.txt @@ -6,7 +6,7 @@ ==Flash Console== - * Version 2.6 (Feb 2012) + * Version 2.7 (Sept 2012) * Project home page: http://code.google.com/p/flash-console/ * Author: Lu Aye Oo, http://www.junkbyte.com * Required: `ActionScript 3.0`, Flash player 9 or above @@ -32,6 +32,15 @@ http://code.google.com/p/flash-console/issues/ == Change Log == +===2.7 BETA === + + * Graphing uses bitmap draw for faster performance. + * Allows slash commands with space and any other characters. + * Ruler becomes an addon that you have to add to console menu. + * Clears logs in remote air app on new connections. Can be toggled by clicking on 'auto-clear' top menu. + * ASDOC included in SWC for help text in IDE. + * Remote version is now split from normal version. See ConsoleRemote.as for example. + ===2.6 === * Addons are now included in Console.swc * DisplayMap addon, Allows inspecting of display tree diff --git a/doc/Remoting.txt b/doc/Remoting.txt new file mode 100644 index 0000000..0b90f97 --- /dev/null +++ b/doc/Remoting.txt @@ -0,0 +1,54 @@ +#summary Remoting lets you connect to an external FlashConsole. +#labels Phase-Implementation + += Introduction = + + * Remoting sends log data for a remote console to use + * The advantages are: + * You dont need to keep console open in your working flash project + * Logs stays in remote afer closing your working flash project + * You can use commandline, view FPS and memory from remote + * AIR version of remote is in [http://flash-console.googlecode.com/svn/trunk/bin/ConsoleRemote.air bin/ConsoleRemote.air] + * EXE and APP version can be published using `samples/remote_air/ConsoleRemoteAIR.as` + +==DEMO== + * Client (sender): http://console.junkbyte.com/sample.html + * Remote (receiver): http://console.junkbyte.com/remote.html + +Remote may prompt for password if you have password set up on client. + +You may disable this by setting `Cc.config.remotingPassword = "";`. - *Must be set before* starting remoting. + +There can be confusion with FPS and memory monitor if you have more than one flash client sending to remote + +=Communication options= + +==Local Connection== +Default option. +It can connects to another flash instance on the same machine. + +====How to==== +Start from client code: +`Cc.remoting = true;` + +Start from commandLine: +`$C.remoting = true` + +==Socket== +Can connect using Socket connection to another FlashConsole on another computer. + +Data is in simple binaries, so you can even write your own remote on any platform. + +====How to==== + # Must use ConsoleRemote.air AIR app for receiving (remote). _This is because socket server is only supported in AIR and there is no way to do p2p connection otherwise._ + # In the remote air app, type in command line: `/listen `. Example `/listen 192.168.1.2 99`, do not use localhost or 127.0.0.1 + # Run client (sender) flash file (may not work on HTML page). + # Make sure that swf file is inside local trusted files list. Right click > Global Settings > Advanced > Trusted Location Settings… > add your dev folder where your swf files live. Restart swf after setting this up for first time. + # Type in commandline: `/remotingSocket `. Example `/remotingSocket 192.168.1.2 99` Alternatively set up in code Cc.remotingSocket()… + # Remote should now show logs from client. Due to a few variables involved in the setup, you may not get it working straight away. + +====Known problems==== +If you have flash security issues, you will get a ton of “Remoting sync error: Error: Error #2030″ on AIR app and ‘SecurityErrorEvent’ on client side after several seconds. +This happens if you haven’t set up trusted local files settings or connecting from inaccessible security sandbox. + +Does not work from HTML embed clients, tho it may depend on sandbox security. \ No newline at end of file diff --git a/samples/flash/ConsoleRemote.as b/samples/flash/ConsoleRemote.as index bb32bb1..8548196 100644 --- a/samples/flash/ConsoleRemote.as +++ b/samples/flash/ConsoleRemote.as @@ -25,8 +25,8 @@ package { import com.junkbyte.console.Cc; - import com.junkbyte.console.core.Remoting; - + import com.junkbyte.console.remote.ConsoleRe; + import flash.display.*; import flash.events.*; @@ -38,19 +38,23 @@ package public class ConsoleRemote extends Sprite { + private var console:ConsoleRe; public function ConsoleRemote() { - Cc.start(this); - Cc.commandLine = true; - Cc.config.maxLines = 2000; - Cc.config.maxRepeats = 200; - Cc.config.commandLineAllowed = true; + console = new ConsoleRe(); + + addChild(console); + + console.commandLine = true; + console.config.maxLines = 2000; + console.config.maxRepeats = 200; + console.config.commandLineAllowed = true; // Start remote service. - Cc.instance.remoter.remoting = Remoting.RECIEVER; + console.remoter.remoting = true; // Disable scaling and moving - Cc.instance.panels.mainPanel.moveable = false; - Cc.instance.panels.mainPanel.scalable = false; + console.panels.mainPanel.moveable = false; + console.panels.mainPanel.scalable = false; // stage.scaleMode = StageScaleMode.NO_SCALE; @@ -59,8 +63,8 @@ package onStageResize(); } private function onStageResize(e : Event = null) : void { - Cc.width = stage.stageWidth; - Cc.height = stage.stageHeight; + console.width = stage.stageWidth; + console.height = stage.stageHeight; } } } \ No newline at end of file diff --git a/samples/flash/SampleAdvanced.as b/samples/flash/SampleAdvanced.as index 090f2ae..1ec0f1a 100644 --- a/samples/flash/SampleAdvanced.as +++ b/samples/flash/SampleAdvanced.as @@ -28,14 +28,15 @@ package import com.junkbyte.console.addons.autoFocus.CommandLineAutoFocusAddon; import com.junkbyte.console.addons.displaymap.DisplayMapAddon; import com.junkbyte.console.addons.htmlexport.ConsoleHtmlExportAddon; + import com.junkbyte.console.addons.ruler.RulerAddon; import flash.display.*; import flash.geom.Rectangle; - [SWF(width='700',height='300',backgroundColor='0xFFFFFF',frameRate='30')] + [SWF(width='700',height='300',backgroundColor='0xFFFFFF',frameRate='60')] // Might want to add compile argument: -use-network=false -debug=true - public dynamic class SampleAdvanced extends MovieClip{ + public dynamic class SampleAdvanced extends Sprite{ private var temp:Object = {object1:{subObj:{text:"Some randome text", number:123}, subArr:[2,3,4,5]}, object2:{arr:[3,4,5]}}; @@ -55,7 +56,7 @@ package Cc.config.commandLineAllowed = true; Cc.width = 700; Cc.height = 300; - Cc.config.remotingPassword = ""; // Just so that remote don't ask for password + //Cc.config.remotingPassword = ""; // Just so that remote don't ask for password Cc.remoting = true; Cc.addMenu("T1", Cc.log, ["Greetings 1"], "This is a test menu 1"); @@ -109,6 +110,8 @@ package // requires JSON: com.adobe.serialization.json.JSON ConsoleHtmlExportAddon.addToMenu(); + RulerAddon.addToMenu(); + DisplayMapAddon.registerCommand(); DisplayMapAddon.addToMenu("DM"); // DisplayMapper. click on DM button at top menu to start. diff --git a/samples/remote_air/ConsoleRemoteAIR-app.xml b/samples/remote_air/ConsoleRemoteAIR-app.xml index a187da0..4fa512a 100644 --- a/samples/remote_air/ConsoleRemoteAIR-app.xml +++ b/samples/remote_air/ConsoleRemoteAIR-app.xml @@ -1,7 +1,7 @@ - + com.junkbyte.console.ConsoleRemoteAIR - 2.6 + 2.7 Console Remote Console Remote diff --git a/samples/remote_air/ConsoleRemoteAIR.as b/samples/remote_air/ConsoleRemoteAIR.as index d7500b5..7b0ce2c 100644 --- a/samples/remote_air/ConsoleRemoteAIR.as +++ b/samples/remote_air/ConsoleRemoteAIR.as @@ -23,74 +23,100 @@ * */ package { - import flash.events.ProgressEvent; - import flash.net.Socket; - import com.junkbyte.console.Console; import com.junkbyte.console.ConsoleConfig; + import com.junkbyte.console.addons.htmlexport.ConsoleHtmlExportAddon; import com.junkbyte.console.core.Remoting; + import com.junkbyte.console.remote.ConsoleRe; import com.junkbyte.console.view.ConsolePanel; - + import com.junkbyte.console.view.PanelsManager; + import flash.display.MovieClip; + import flash.display.NativeWindowDisplayState; + import flash.display.NativeWindowResize; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.MouseEvent; - import flash.filters.GlowFilter; - import flash.text.TextField; + import flash.events.ProgressEvent; import flash.events.ServerSocketConnectEvent; - import flash.net.ServerSocket; import flash.filesystem.File; - import flash.filesystem.FileStream; import flash.filesystem.FileMode; - import flash.display.NativeWindowDisplayState; - import flash.display.NativeWindowResize; + import flash.filesystem.FileStream; + import flash.filters.GlowFilter; + import flash.net.ServerSocket; + import flash.net.Socket; + import flash.text.TextField; public class ConsoleRemoteAIR extends MovieClip { - private var _c : Console; + + private var console:Console; + private var _serverSocket : ServerSocket; + + private var _autoClear:Boolean = true; public function ConsoleRemoteAIR() { - var config : ConsoleConfig = new ConsoleConfig(); - config.maxLines = 2000; - config.style.backgroundAlpha = 0.55; - config.commandLineAllowed = true; - _c = new Console(null, config); - addChild(_c); - _c.visible = true; - _c.remoter.remoting = Remoting.RECIEVER; - _c.commandLine = true; - _c.x = 10; - _c.y = 10; - _c.addMenu("top", toggleOnTop, null, "Toggle always in front"); - _c.addMenu("save", saveToFile, null, "Save to file"); - var menu : TextField = _c.panels.mainPanel.getChildByName("menuField") as TextField; + + console = new ConsoleRe(); + addChild(console); + + console.config.maxLines = 2000; + console.config.style.backgroundAlpha = 0.55; + console.config.commandLineAllowed = true; + + var panels:PanelsManager = console.panels; + + console.remoter.addEventListener(Event.CONNECT, onRemotingConnect); + console.remoter.remoting = true; + console.commandLine = true; + console.x = 10; + console.y = 10; + console.addMenu("top", toggleOnTop, null, "Toggle always in front"); + console.addMenu("auto-clear", toggleAutoClear, null, "Toggle auto clear on new connection"); + + ConsoleHtmlExportAddon.addToMenu("save"); + + var menu : TextField = panels.mainPanel.getChildByName("menuField") as TextField; menu.doubleClickEnabled = true; menu.addEventListener(MouseEvent.DOUBLE_CLICK, ondouble); - _c.panels.mainPanel.addEventListener(ConsolePanel.DRAGGING_STARTED, moveHandle); - _c.panels.mainPanel.addEventListener(ConsolePanel.SCALING_STARTED, scaleHandle); + panels.mainPanel.addEventListener(ConsolePanel.DRAGGING_STARTED, moveHandle); + panels.mainPanel.addEventListener(ConsolePanel.SCALING_STARTED, scaleHandle); - _c.filters = new Array(new GlowFilter(0, 0.7, 5, 5)); + console.filters = new Array(new GlowFilter(0, 0.7, 5, 5)); - _c.panels.mainPanel.addEventListener(Event.CLOSE, onMainPanelClose); + panels.mainPanel.addEventListener(Event.CLOSE, onMainPanelClose); stage.frameRate = 60; stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.addEventListener(Event.RESIZE, onStageResize); onStageResize(); - _c.addSlashCommand("listen", function (params:String = ""):void{ + console.addSlashCommand("listen", function (params:String = ""):void{ var parts:Array = params.split(/\s+/); bindServer(parts[0], parts[1]); }); - _c.cl.localCommands.push("listen"); - _c.report("Use /listen ip port command to listen to socket connection.", -2); - _c.report("Example /listen 127.0.0.1 200 command to listen to socket connection.", -1); + console.cl.localCommands.push("listen"); + console.report("Use /listen ip port command to listen to socket connection.", -2); + console.report("Example /listen 127.0.0.1 200 command to listen to socket connection.", -1); } + private function onRemotingConnect(event:Event):void + { + if(_autoClear) + { + console.clear(); + } + } + private function toggleOnTop() : void { stage.nativeWindow.alwaysInFront = !stage.nativeWindow.alwaysInFront; - _c.report("Always in front " + (stage.nativeWindow.alwaysInFront ? "enabled." : "disabled"), -1); + console.report("Always in front " + (stage.nativeWindow.alwaysInFront ? "enabled." : "disabled"), -1); + } + + private function toggleAutoClear() : void { + _autoClear = !_autoClear; + console.report("Auto clear on new connection " + (_autoClear ? "enabled." : "disabled"), -1); } private function onMainPanelClose(e : Event) : void { @@ -103,7 +129,7 @@ package { docsDir.browseForSave("Save Log As"); docsDir.addEventListener(Event.SELECT, saveData); } catch (err : Error) { - _c.error("Failed:", err.message); + console.error("Failed:", err.message); } } @@ -117,16 +143,16 @@ package { file.nativePath = path + ".txt"; } } - var str : String = _c.getAllLog(File.lineEnding); + var str : String = console.getAllLog(File.lineEnding); var stream : FileStream = new FileStream(); try { stream.open(file, FileMode.WRITE); stream.writeUTFBytes(str); stream.close(); - _c.report("Saved log to " + file.nativePath, -1); + console.report("Saved log to " + file.nativePath, -1); } catch(e : Error) { // maybe read-only , etc - _c.report("There was a problem saving the log to " + file.nativePath + "\n" + e, 10); + console.report("There was a problem saving the log to " + file.nativePath + "\n" + e, 10); } } @@ -143,13 +169,13 @@ package { } private function scaleHandle(e : Event) : void { - _c.panels.mainPanel.stopScaling(); + console.panels.mainPanel.stopScaling(); stage.nativeWindow.startResize(NativeWindowResize.BOTTOM_RIGHT); } private function onStageResize(e : Event = null) : void { - _c.width = stage.stageWidth - 20; - _c.height = stage.stageHeight - 20; + console.width = stage.stageWidth - 20; + console.height = stage.stageHeight - 20; } public function bindServer(host : String, port : int) : void { @@ -160,18 +186,18 @@ package { _serverSocket.bind(port, host); _serverSocket.addEventListener(ServerSocketConnectEvent.CONNECT, onConnect); _serverSocket.listen(); - _c.report("Listening to: " + _serverSocket.localAddress + ":" + _serverSocket.localPort, -1); + console.report("Listening to: " + _serverSocket.localAddress + ":" + _serverSocket.localPort, -1); } private function onConnect(event : ServerSocketConnectEvent) : void { var clientSocket : Socket = event.socket; clientSocket.addEventListener(ProgressEvent.SOCKET_DATA, onClientSocketData); - _c.report("Connection from " + clientSocket.remoteAddress + ":" + clientSocket.remotePort); + console.report("Connection from " + clientSocket.remoteAddress + ":" + clientSocket.remotePort); } private function onClientSocketData(event : ProgressEvent) : void { var clientSocket : Socket = event.currentTarget as Socket; - _c.remoter.handleSocket(clientSocket); + console.remoter.handleSocket(clientSocket); } } } \ No newline at end of file diff --git a/src-tests/TestRunner.as b/src-tests/TestRunner.as new file mode 100644 index 0000000..c9e42ab --- /dev/null +++ b/src-tests/TestRunner.as @@ -0,0 +1,21 @@ +package +{ + import com.junkbyte.console.ConsoleTestSuite; + + import org.flexunit.internals.TraceListener; + import org.flexunit.runner.FlexUnitCore; + + import flash.display.Sprite; + + public class TestRunner extends Sprite + { + public function TestRunner() + { + var core : FlexUnitCore = new FlexUnitCore(); + + core.addListener(new TraceListener()); + + core.run(ConsoleTestSuite); + } + } +} diff --git a/src-tests/com/junkbyte/console/ConsoleTestSuite.as b/src-tests/com/junkbyte/console/ConsoleTestSuite.as new file mode 100644 index 0000000..e9821bf --- /dev/null +++ b/src-tests/com/junkbyte/console/ConsoleTestSuite.as @@ -0,0 +1,11 @@ +package com.junkbyte.console +{ + import com.junkbyte.console.core.CommandLineTests; + + [Suite] + [RunWith("org.flexunit.runners.Suite")] + public class ConsoleTestSuite + { + public var commandLineTests : CommandLineTests; + } +} diff --git a/src-tests/com/junkbyte/console/core/CommandLineTests.as b/src-tests/com/junkbyte/console/core/CommandLineTests.as new file mode 100644 index 0000000..c85878e --- /dev/null +++ b/src-tests/com/junkbyte/console/core/CommandLineTests.as @@ -0,0 +1,219 @@ +package com.junkbyte.console.core +{ + import com.junkbyte.console.Cc; + import com.junkbyte.console.Console; + + import flash.display.DisplayObject; + import flash.display.DisplayObjectContainer; + import flash.display.Sprite; + + import org.flexunit.asserts.assertEquals; + import org.flexunit.asserts.assertStrictlyEquals; + import org.flexunit.asserts.assertTrue; + + public class CommandLineTests + { + public var container:Sprite; + public var console:Console; + private var commandLine:CommandLine; + private var saves:Object; + + [Before] + public function setUp():void + { + console = new Console(); + console.config.commandLineAllowed = true; + + container = new Sprite(); + container.addChild(console); + + commandLine = console.cl; + commandLine.base = this; + + saves = null; + } + + private function run(str:String):* + { + return commandLine.run(str, saves, true); + } + + [Test] + public function testBasicCommands():void + { + // assertStrictlyEquals don't seem to pick up === cases. + assertTrue(null === run("null")); + assertTrue(undefined === run("undefined")); + assertTrue(true === run("true")); + assertTrue(false === run("false")); + + assertEquals(123, run("123")); + assertEquals(-123, run("-123")); + assertEquals(123.456, run("123.456")); + assertEquals(-123.456, run("-123.456")); + assertTrue(isNaN(run("NaN"))); + assertTrue(Infinity === run("Infinity")); + + var text:String = "Abcd \"EFG\" hijk"; + assertEquals(text, run("'"+text+"'")); + text = "Abcd 'EFG' hijk"; + assertEquals(text, run("\""+text+"\"")); + + assertEquals(this, run("this")); + + assertEquals(int, run("int")); + assertEquals(Array, run("Array")); + assertEquals(Function, run("Function")); + assertEquals(XML, run("XML")); + assertEquals(Sprite, run("flash.display.Sprite")); + assertEquals(Cc, run("com.junkbyte.console.Cc")); + assertEquals(console, run("$C")); + } + + [Test] + public function testChangecope():void + { + assertEquals(this, run("this")); + run("$C"); + run("/"); + assertEquals(console, run("this")); + } + + [Test] + public function testBasicMultilineCommands():void + { + assertEquals(this, run("this;$C ; $base ")); // just tests that it returns the last value + assertEquals(console, run("$C; /; this")); + //assertEquals(this, run("$C; /; /base")); // tests mixing slash commands in multiline // FAILING + } + + [Test] + public function testChangePreviousScope():void + { + run("$C;/;"); + run("//"); + assertEquals(this, run("this")); + } + + [Test] + public function testSaveSlashCommand():void + { + run("$C;/;"); + run("/save console"); + assertEquals(console, run("$console")); + } + + [Test] + public function testSlashCommandMatching():void + { + console.addSlashCommand("test", function (param:String = ""):String{return "test:"+param;}); + console.addSlashCommand("test 2", function (param:String = ""):String{return "test 2:"+param;}); + console.addSlashCommand("test 23", function (param:String = ""):String{return "test 23:"+param;}); + console.addSlashCommand("test 3", function (param:String = ""):String{return "test 3:"+param;}); + + assertEquals(undefined, run("/doNotExist")); + + assertEquals("test:", run("/test")); + assertEquals("test:", run("/test ")); + + assertEquals("test:abcd", run("/test abcd")); + assertEquals("test: abcd", run("/test abcd")); + + assertEquals("test 2:", run("/test 2")); + assertEquals("test 2:", run("/test 2 ")); + assertEquals("test 2:abcd", run("/test 2 abcd")); + assertEquals("test 23:", run("/test 23 ")); + assertEquals("test 23:abcd", run("/test 23 abcd")); + assertEquals("test 3:abcd", run("/test 3 abcd")); + } + + [Test] + public function testDot():void + { + assertEquals(this.console, run("this.console")); + assertEquals(console.name, run("$C.name;")); + + console.alpha = 0.5; + assertEquals(console.alpha, run("$C.alpha;")); + assertEquals(console.config.maxLines, run("$C.config.maxLines;")); + + + assertEquals(22, run("new Array(11,22,33).1")); + assertEquals(1, run("new Array(11,22,33);/;1")); + assertEquals(22, run("new Array(11,22,33);/;this.1")); + } + + [Test] + public function testNewObject():void + { + assertTrue(run("new String()") is String); + assertEquals("ABCD", run("new String('ABCD')")); + assertTrue(run("new flash.display.Sprite()") is Sprite); + + var array:Array = run("new Array(11, 22, 33, 44);"); + assertTrue(array is Array); + assertEquals(4, array.length); + assertEquals(11, array[0]); + assertEquals(22, array[1]); + assertEquals(33, array[2]); + assertEquals(44, array[3]); + + var xml:XML = run('new XML("B")'); + assertTrue(xml is XML); + assertEquals("t", xml.name()); + assertEquals("A", xml.attribute("a").toString()); + assertEquals("B", xml.b.toString()); + + assertEquals("A", run('new XML("").attribute("a")')); + } + + [Test] + public function testCallFunction():void + { + assertEquals(String(this), run("toString()")); + assertEquals(console.getChildAt(0), run("$C.getChildAt(0)")); + var result:DisplayObject = DisplayObjectContainer(container.getChildByName("Console")).getChildAt(0); + assertEquals(result, run("container.getChildByName(\"Console\").getChildAt(0)")); + } + + [Test] + public function testNestedCallFunction():void + { + var result:DisplayObject = container.getChildByName(new String(console.name) + ""); + assertEquals(result, run("container.getChildByName(new String(console.name) + \"\")")); + } + + [Test] + public function testBasicOperators():void + { + assertEquals(11, run("5 + 6")); + assertEquals(-1, run("5 - 6")); + assertEquals(15, run("3 * 5")); + assertEquals(3/5, run("3 / 5")); + assertEquals(3.44/5.22, run("3.44 / 5.22")); + + assertEquals("abcdefg", run("'abcd' + \"efg\"")); + } + + [Test] + public function testAssignmentOperators():void + { + run("$C.alpha = 0.5"); + assertEquals(0.5, console.alpha); + run("$C.alpha += 0.25"); + assertEquals(0.75, console.alpha); + run("$C.alpha -= 0.5"); + assertEquals(0.25, console.alpha); + } + + [Test] + public function testMixedOperators():void + { + assertEquals(5 + 6 - 30, run("5 + 6 - 30")); + assertEquals(5 * 3 + 2, run("5 * 3 + 2")); + //assertEquals(2 + 5 * 3, run("2 + 5 * 3")); // FAILING + assertEquals(5 * 3 / 2, run("5 * 3 / 2")); + assertEquals(2 / 5 * 3, run(" 2 / 5 * 3")); + } + } +} \ No newline at end of file diff --git a/src/com/junkbyte/console/Cc.as b/src/com/junkbyte/console/Cc.as index 09c80cf..b29cb0e 100644 --- a/src/com/junkbyte/console/Cc.as +++ b/src/com/junkbyte/console/Cc.as @@ -23,9 +23,11 @@ * */ package com.junkbyte.console { - import flash.display.LoaderInfo; + import com.junkbyte.console.vos.GraphGroup; + import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; + import flash.display.LoaderInfo; import flash.events.Event; import flash.geom.Rectangle; @@ -37,8 +39,9 @@ package com.junkbyte.console { * and all other calls through Cc will stop working silently. *

* @author Lu Aye Oo - * @version 2.4 + * @version 2.7 * @see http://code.google.com/p/flash-console/ + * @see http://junkbyte.com * @see #start() * @see #startOnStage() */ @@ -197,7 +200,7 @@ package com.junkbyte.console { * @param ...strings Strings to be logged, any type can be passed and will be converted to string or a link if it is an object/class. */ public static function logch(channel:*, ...strings):void{ - if(_console) _console.addCh(channel, strings, Console.LOG); + if(_console) _console.addCh(channel, strings, ConsoleLevel.LOG); } /** * Add log line with priority 3 to channel @@ -207,7 +210,7 @@ package com.junkbyte.console { * @param ...strings Strings to be logged, any type can be passed and will be converted to string or a link if it is an object/class. */ public static function infoch(channel:*, ...strings):void{ - if(_console) _console.addCh(channel, strings, Console.INFO); + if(_console) _console.addCh(channel, strings, ConsoleLevel.INFO); } /** * Add log line with priority 5 to channel @@ -217,7 +220,7 @@ package com.junkbyte.console { * @param ...strings Strings to be logged, any type can be passed and will be converted to string or a link if it is an object/class. */ public static function debugch(channel:*, ...strings):void{ - if(_console) _console.addCh(channel, strings, Console.DEBUG); + if(_console) _console.addCh(channel, strings, ConsoleLevel.DEBUG); } /** * Add log line with priority 7 to channel @@ -227,7 +230,7 @@ package com.junkbyte.console { * @param ...strings Strings to be logged, any type can be passed and will be converted to string or a link if it is an object/class. */ public static function warnch(channel:*, ...strings):void{ - if(_console) _console.addCh(channel, strings, Console.WARN); + if(_console) _console.addCh(channel, strings, ConsoleLevel.WARN); } /** * Add log line with priority 9 to channel @@ -237,7 +240,7 @@ package com.junkbyte.console { * @param ...strings Strings to be logged, any type can be passed and will be converted to string or a link if it is an object/class. */ public static function errorch(channel:*, ...strings):void{ - if(_console) _console.addCh(channel, strings, Console.ERROR); + if(_console) _console.addCh(channel, strings, ConsoleLevel.ERROR); } /** * Add log line with priority 10 to channel @@ -247,7 +250,7 @@ package com.junkbyte.console { * @param ...strings Strings to be logged, any type can be passed and will be converted to string or a link if it is an object/class. */ public static function fatalch(channel:*, ...strings):void{ - if(_console) _console.addCh(channel, strings, Console.FATAL); + if(_console) _console.addCh(channel, strings, ConsoleLevel.FATAL); } /** * Add a stack trace of where it is called from at the end of the line. Requires debug player. @@ -526,8 +529,15 @@ package com.junkbyte.console { * @param inverse (optional) invert the graph, meaning the highest value at the bottom and lowest at the top. * */ - public static function addGraph(panelName:String, obj:Object, property:String, color:Number = -1, idKey:String = null, rectArea:Rectangle = null, inverse:Boolean = false):void{ - if(_console) _console.addGraph(panelName, obj, property, color, idKey, rectArea, inverse); + public static function addGraph(panelName:String, obj:Object, property:String, color:Number = -1, idKey:String = null, rectArea:Rectangle = null, inverse:Boolean = false):GraphGroup{ + if(_console) return _console.addGraph(panelName, obj, property, color, idKey, rectArea, inverse); + return null; + } + /** + * Add graph group + */ + public static function addGraphGroup(group:GraphGroup):void{ + if(_console) _console.addGraphGroup(group); } /** * Fix graph's range. @@ -762,8 +772,8 @@ package com.junkbyte.console { else return ""; } /** - * Get instance to Console - * This is for debugging of console. + * Get instance of Console + * This is for debugging console. * PLEASE avoid using it! * * @return Console class instance diff --git a/src/com/junkbyte/console/Console.as b/src/com/junkbyte/console/Console.as index 625bb0e..3ed9838 100644 --- a/src/com/junkbyte/console/Console.as +++ b/src/com/junkbyte/console/Console.as @@ -24,8 +24,6 @@ */ package com.junkbyte.console { - import flash.utils.getTimer; - import flash.system.Capabilities; import com.junkbyte.console.core.CommandLine; import com.junkbyte.console.core.ConsoleTools; import com.junkbyte.console.core.Graphing; @@ -36,8 +34,9 @@ package com.junkbyte.console import com.junkbyte.console.core.Remoting; import com.junkbyte.console.view.PanelsManager; import com.junkbyte.console.view.RollerPanel; + import com.junkbyte.console.vos.GraphGroup; import com.junkbyte.console.vos.Log; - + import flash.display.DisplayObjectContainer; import flash.display.LoaderInfo; import flash.display.Sprite; @@ -47,6 +46,11 @@ package com.junkbyte.console import flash.events.KeyboardEvent; import flash.geom.Rectangle; import flash.net.SharedObject; + import flash.system.Capabilities; + import flash.utils.getTimer; + + use namespace console_internal; + /** * Console is the main class. * Please see com.junkbyte.console.Cc for documentation as it shares the same properties and methods structure. @@ -55,41 +59,32 @@ package com.junkbyte.console */ public class Console extends Sprite { - public static const VERSION:Number = 2.6; - public static const VERSION_STAGE:String = ""; - public static const BUILD:int = 611; - public static const BUILD_DATE:String = "2012/02/22 00:11"; - // - public static const LOG:uint = 1; - public static const INFO:uint = 3; - public static const DEBUG:uint = 6; - public static const WARN:uint = 8; - public static const ERROR:uint = 9; - public static const FATAL:uint = 10; - // - public static const GLOBAL_CHANNEL:String = " * "; - public static const DEFAULT_CHANNEL:String = "-"; - public static const CONSOLE_CHANNEL:String = "C"; - public static const FILTER_CHANNEL:String = "~"; + public static const VERSION:Number = 2.7; + public static const VERSION_STAGE:String = "BETA"; + public static const BUILD:int = 614; + public static const BUILD_DATE:String = "2012/10/01 00:46"; + // - private var _config:ConsoleConfig; - private var _panels:PanelsManager; - private var _cl:CommandLine; - private var _kb:KeyBinder; - private var _refs:LogReferences; - private var _mm:MemoryMonitor; - private var _graphing:Graphing; - private var _remoter:Remoting; - private var _tools:ConsoleTools; + protected var _config:ConsoleConfig; + protected var _panels:PanelsManager; + protected var _cl:CommandLine; + protected var _kb:KeyBinder; + protected var _refs:LogReferences; + protected var _mm:MemoryMonitor; + protected var _graphing:Graphing; + protected var _remoter:Remoting; + protected var _tools:ConsoleTools; + protected var _logs:Logs; // private var _topTries:int = 50; private var _paused:Boolean; private var _rollerKey:KeyBind; - private var _logs:Logs; private var _so:SharedObject; private var _soData:Object = {}; + private var _lastTime:uint; + /** * Console is the main class. However please use Cc for singleton Console adapter. * Using Console through Cc will also make sure you can remove console in a later date @@ -106,15 +101,9 @@ package com.junkbyte.console if (password) { _config.keystrokePassword = password; } + _config.style.updateStyleSheet(); // - _remoter = new Remoting(this); - _logs = new Logs(this); - _refs = new LogReferences(this); - _cl = new CommandLine(this); - _tools = new ConsoleTools(this); - _graphing = new Graphing(this); - _mm = new MemoryMonitor(this); - _kb = new KeyBinder(this); + initModules(); cl.addCLCmd("remotingSocket", function(str:String = ""):void{ var args:Array = str.split(/\s+|\:/); @@ -130,17 +119,34 @@ package com.junkbyte.console } } - _config.style.updateStyleSheet(); - _panels = new PanelsManager(this); if(password) visible = false; //report("Console v"+VERSION+VERSION_STAGE+" b"+BUILD+". Happy coding!", -2); report("Console v"+VERSION+VERSION_STAGE+" build "+BUILD+". "+Capabilities.playerType+" "+Capabilities.version+".", -2); + + _lastTime = getTimer(); + // must have enterFrame here because user can start without a parent display and use remoting. addEventListener(Event.ENTER_FRAME, _onEnterFrame); addEventListener(Event.ADDED_TO_STAGE, stageAddedHandle); } + + protected function initModules():void + { + _remoter = new Remoting(this); + _logs = new Logs(this); + _refs = new LogReferences(this); + _cl = new CommandLine(this); + _tools = new ConsoleTools(this); + _graphing = new Graphing(this); + _mm = new MemoryMonitor(this); + _kb = new KeyBinder(this); + + _panels = new PanelsManager(this); + } + + private function stageAddedHandle(e:Event=null):void{ if(_cl.base == null) _cl.base = parent; if(loaderInfo){ @@ -188,24 +194,28 @@ package com.junkbyte.console if(!str){ str = String(error); } - report(str, FATAL, false); + report(str, ConsoleLevel.FATAL, false); } /** * @copy com.junkbyte.console.Cc#addGraph() */ - public function addGraph(name:String, obj:Object, property:String, color:Number = -1, key:String = null, rect:Rectangle = null, inverse:Boolean = false):void{ - _graphing.add(name, obj, property, color, key, rect, inverse); + public function addGraph(name:String, obj:Object, property:String, color:Number = -1, key:String = null, rect:Rectangle = null, inverse:Boolean = false):GraphGroup{ + return _graphing.add(name, obj, property, color, key, rect, inverse); + } + + public function addGraphGroup(group:GraphGroup):void{ + return _graphing.addGroup(group); } /** - * @copy com.junkbyte.console.Cc#fixGraphRange() - */ + * @copy com.junkbyte.console.Cc#fixGraphRange() + */ public function fixGraphRange(name:String, min:Number = NaN, max:Number = NaN):void{ _graphing.fixRange(name, min, max); } - + /** * @copy com.junkbyte.console.Cc#removeGraph() */ @@ -313,7 +323,7 @@ package com.junkbyte.console * @copy com.junkbyte.console.Cc#map() */ public function map(container:DisplayObjectContainer, maxstep:uint = 0):void{ - _tools.map(container, maxstep, DEFAULT_CHANNEL); + _tools.map(container, maxstep, ConsoleChannel.DEFAULT_CHANNEL); } /** @@ -327,7 +337,7 @@ package com.junkbyte.console * @copy com.junkbyte.console.Cc#inspect() */ public function inspect(obj:Object, showInherit:Boolean = true):void{ - _refs.inspect(obj, showInherit, DEFAULT_CHANNEL); + _refs.inspect(obj, showInherit, ConsoleChannel.DEFAULT_CHANNEL); } /** @@ -396,26 +406,27 @@ package com.junkbyte.console // // private function _onEnterFrame(e:Event):void{ + var time:int = getTimer(); - var hasNewLog:Boolean = _logs.update(time); + _logs.update(time); + var timeDelta:uint = time - _lastTime; + _lastTime = time; _refs.update(time); + _mm.update(); - var graphsList:Array; - if(remoter.remoting != Remoting.RECIEVER) - { - graphsList = _graphing.update(stage?stage.frameRate:0); - } + _graphing.update(timeDelta); _remoter.update(); // VIEW UPDATES ONLY if(visible && parent){ - if(config.alwaysOnTop && parent.getChildAt(parent.numChildren-1) != this && _topTries>0){ + if(config.alwaysOnTop && _topTries > 0 && parent.numChildren > parent.getChildIndex(this) + 1) + { _topTries--; parent.addChild(this); report("Moved console on top (alwaysOnTop enabled), "+_topTries+" attempts left.",-1); } - _panels.update(_paused, hasNewLog); - if(graphsList) _panels.updateGraphs(graphsList); + _panels.update(_paused, _logs.hasNewLog); + _logs.hasNewLog = false; } } // @@ -426,10 +437,10 @@ package com.junkbyte.console * @copy com.junkbyte.console.Cc#remoting */ public function get remoting():Boolean{ - return _remoter.remoting == Remoting.SENDER; + return _remoter.remoting; } public function set remoting(b:Boolean):void{ - _remoter.remoting = b?Remoting.SENDER:Remoting.NONE; + _remoter.remoting = b; } /** @@ -510,14 +521,14 @@ package com.junkbyte.console * @copy com.junkbyte.console.Cc#add() */ public function add(string:*, priority:int = 2, isRepeating:Boolean = false):void{ - addLine([string], priority, DEFAULT_CHANNEL, isRepeating); + addLine([string], priority, ConsoleChannel.DEFAULT_CHANNEL, isRepeating); } /** * @copy com.junkbyte.console.Cc#stack() */ public function stack(string:*, depth:int = -1, priority:int = 5):void{ - addLine([string], priority, DEFAULT_CHANNEL, false, false, depth>=0?depth:_config.defaultStackDepth); + addLine([string], priority, ConsoleChannel.DEFAULT_CHANNEL, false, false, depth>=0?depth:_config.defaultStackDepth); } /** @@ -534,42 +545,42 @@ package com.junkbyte.console * @copy com.junkbyte.console.Cc#log() */ public function log(...strings):void{ - addLine(strings, LOG); + addLine(strings, ConsoleLevel.LOG); } /** * @copy com.junkbyte.console.Cc#info() */ public function info(...strings):void{ - addLine(strings, INFO); + addLine(strings, ConsoleLevel.INFO); } /** * @copy com.junkbyte.console.Cc#debug() */ public function debug(...strings):void{ - addLine(strings, DEBUG); + addLine(strings, ConsoleLevel.DEBUG); } /** * @copy com.junkbyte.console.Cc#warn() */ public function warn(...strings):void{ - addLine(strings, WARN); + addLine(strings, ConsoleLevel.WARN); } /** * @copy com.junkbyte.console.Cc#error() */ public function error(...strings):void{ - addLine(strings, ERROR); + addLine(strings, ConsoleLevel.ERROR); } /** * @copy com.junkbyte.console.Cc#fatal() */ public function fatal(...strings):void{ - addLine(strings, FATAL); + addLine(strings, ConsoleLevel.FATAL); } /** @@ -583,42 +594,42 @@ package com.junkbyte.console * @copy com.junkbyte.console.Cc#logch() */ public function logch(channel:*, ...strings):void{ - addLine(strings, LOG, channel); + addLine(strings, ConsoleLevel.LOG, channel); } /** * @copy com.junkbyte.console.Cc#infoch() */ public function infoch(channel:*, ...strings):void{ - addLine(strings, INFO, channel); + addLine(strings, ConsoleLevel.INFO, channel); } /** * @copy com.junkbyte.console.Cc#debugch() */ public function debugch(channel:*, ...strings):void{ - addLine(strings, DEBUG, channel); + addLine(strings, ConsoleLevel.DEBUG, channel); } /** * @copy com.junkbyte.console.Cc#warnch() */ public function warnch(channel:*, ...strings):void{ - addLine(strings, WARN, channel); + addLine(strings, ConsoleLevel.WARN, channel); } /** * @copy com.junkbyte.console.Cc#errorch() */ public function errorch(channel:*, ...strings):void{ - addLine(strings, ERROR, channel); + addLine(strings, ConsoleLevel.ERROR, channel); } /** * @copy com.junkbyte.console.Cc#fatalch() */ public function fatalch(channel:*, ...strings):void{ - addLine(strings, FATAL, channel); + addLine(strings, ConsoleLevel.FATAL, channel); } /** @@ -632,7 +643,7 @@ package com.junkbyte.console * @copy com.junkbyte.console.Cc#addHTML() */ public function addHTML(...strings):void{ - addLine(strings, 2, DEFAULT_CHANNEL, false, testHTML(strings)); + addLine(strings, 2, ConsoleChannel.DEFAULT_CHANNEL, false, testHTML(strings)); } /** @@ -699,10 +710,6 @@ package com.junkbyte.console * @private */ public function get logs():Logs{return _logs;} - /** - * @private - */ - public function get mapper():ConsoleTools{return _tools;} /** * @private @@ -723,7 +730,7 @@ package com.junkbyte.console public static function MakeChannelName(obj:*):String{ if(obj is String) return obj as String; else if(obj) return LogReferences.ShortClassName(obj); - return DEFAULT_CHANNEL; + return ConsoleChannel.DEFAULT_CHANNEL; } } } \ No newline at end of file diff --git a/src/com/junkbyte/console/ConsoleChannel.as b/src/com/junkbyte/console/ConsoleChannel.as index f256286..8b65f6d 100644 --- a/src/com/junkbyte/console/ConsoleChannel.as +++ b/src/com/junkbyte/console/ConsoleChannel.as @@ -27,6 +27,12 @@ package com.junkbyte.console { public class ConsoleChannel { + public static const GLOBAL_CHANNEL:String = " * "; + public static const DEFAULT_CHANNEL:String = "-"; + public static const CONSOLE_CHANNEL:String = "C"; + public static const FILTER_CHANNEL:String = "~"; + + private var _c:*; // because it could be Console or Cc. This is the cheapest way I think... private var _name:String; @@ -40,7 +46,7 @@ package com.junkbyte.console { */ public function ConsoleChannel(n:*, c:Console = null){ _name = Console.MakeChannelName(n); - if (_name == Console.GLOBAL_CHANNEL) _name = Console.DEFAULT_CHANNEL; + if (_name == ConsoleChannel.GLOBAL_CHANNEL) _name = ConsoleChannel.DEFAULT_CHANNEL; // allowed to pass in Console here incase you want to use a different console instance from whats used in Cc _c = c?c:Cc; } diff --git a/src/com/junkbyte/console/ConsoleConfig.as b/src/com/junkbyte/console/ConsoleConfig.as index da59ac1..d71ebdc 100644 --- a/src/com/junkbyte/console/ConsoleConfig.as +++ b/src/com/junkbyte/console/ConsoleConfig.as @@ -1,11 +1,11 @@ /* -* +* * Copyright (c) 2008-2010 Lu Aye Oo -* +* * @author Lu Aye Oo -* +* * http://code.google.com/p/flash-console/ -* +* * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -20,19 +20,22 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. -* +* */ -package com.junkbyte.console { +package com.junkbyte.console +{ + import flash.utils.getQualifiedClassName; + + public class ConsoleConfig + { - public class ConsoleConfig { - /** * Password sequence to toggle console's visibility. If password is set, console will start hidden. Set Cc.visible = ture to unhide at start. * Must be ASCII chars. Example passwords: ` OR debug. * Password will not trigger if you have focus on an input TextField. */ public var keystrokePassword:String; - + /** * Set Password required to connect from remote. *

@@ -42,19 +45,19 @@ package com.junkbyte.console { *

*/ public var remotingPassword:String; - + ////////////////////// // // // LOGGING CONIFG // // // ////////////////////// - + /** * Maximum number of logs Console should remember. * 0 = unlimited. Setting to very high will take up more memory and potentially slow down. */ public var maxLines:uint = 1000; - + /** * Frames before repeating line is forced to print to next line. *

@@ -63,35 +66,35 @@ package com.junkbyte.console { *

*/ public var maxRepeats:int = 75; - + /** * Auto stack trace logs for this priority and above * default priortiy = 10; fatal level */ - public var autoStackPriority:int = Console.FATAL; - + public var autoStackPriority:int = ConsoleLevel.FATAL; + /** * Default stack trace depth */ public var defaultStackDepth:int = 2; - - /** + + /** * Object linking allows you click on individual objects you have logged to inspect the detials in a specific view. * The down side is that it will take a little more memory to keep a WEAK reference to all objects pass for logging. * Potentially a security risk as users will be able to explore your code interface. */ public var useObjectLinking:Boolean = true; - + /** * Seconds in which object links should be hard referenced for. - * If you logged a temp object (object that is not referenced anywhere else), it will become a link in console. - * However it will get garbage collected almost straight away which prevents you from clicking on the object link. + * If you logged a temp object (object that is not referenced anywhere else), it will become a link in console. + * However it will get garbage collected almost straight away which prevents you from clicking on the object link. * (You will normally get this message: "Reference no longer exists") * This feature allow you to set how many seconds console should hard reference object logs. * Example, if you set 120, you will get 2 mins guaranteed time that any object link will work since it first appeared. * Default is 0, meaning everything is weak linked straight away. * Recommend not to use too high numbers. possibly 120 (2 minutes) is max you should set. - * + * * Example: * * Cc.log("This is a temp object:", new Object()); @@ -100,7 +103,7 @@ package com.junkbyte.console { * */ public var objectHardReferenceTimer:uint = 0; - + /** * Use flash's build in (or external) trace(). *

@@ -112,7 +115,7 @@ package com.junkbyte.console { * @see traceCall */ public var tracing:Boolean; - + /** * Assign custom trace function. *

@@ -131,17 +134,15 @@ package com.junkbyte.console { *

* @see tracing */ - public var traceCall:Function = function (ch:String, line:String, ...args):void{ - trace("["+ch+"] "+line); + public var traceCall:Function = function(ch:String, line:String, ... args):void { + trace("[" + ch + "] " + line); }; - - + /** * Specifies whether to show timestamps in Console. */ public var showTimestamp:Boolean = false; - - + /** * Time stamp formatter. *

@@ -153,61 +154,106 @@ package com.junkbyte.console { */ public var timeStampFormatter:Function = function(timer:uint):String { - var s:uint = timer*0.001; - return makeTimeDigit(s/60)+":"+makeTimeDigit(s%60); + var s:uint = timer * 0.001; + return makeTimeDigit(s / 60) + ":" + makeTimeDigit(s % 60); }; - - private function makeTimeDigit(v:uint):String{ - if(v < 10) return "0"+v; + + private function makeTimeDigit(v:uint):String + { + if (v < 10) + { + return "0" + v; + } return String(v); } - + /** * Specifies whether to show line numbers in console. */ public var showLineNumber:Boolean = false; - - // Work in progress - //public var rolloverStackToolTip:Boolean = false; - + + private var _stackIgnoredExp:RegExp = new RegExp("Function|" + addDotSlash(getQualifiedClassName(Console)) + "|" + addDotSlash(getQualifiedClassName(Cc))); + + /** + * @private + * Use internally by console to ignore certain classes in stack traces. + */ + public function get stackTraceIgnoreExpression():RegExp + { + return _stackIgnoredExp; + } + + /** + * Add class to ignore in stack trace. + *

    + *
  • This stops the stack from going down further when it reaches this class.
  • + *
  • By default the stack stops when reaching Console or Cc.
  • + *
  • Useful to ignore if you have many pass backs and wrappers before reaching the log calls to Console.
  • + *
  • Currently no way to remove once added.
  • + *
+ * + * @param classToIgnore Class to ignore. + * + */ + public function addStackTraceIgnoreClass(classToIgnore:Class):void + { + var stringToAdd:String = "|" + addDotSlash(getQualifiedClassName(classToIgnore)); + + var expressionStr:String = _stackIgnoredExp.source; + + var index:int = expressionStr.indexOf(stringToAdd); + var end:int = index + stringToAdd.length; + if (index < 0 || (end < expressionStr.length && expressionStr.charAt(end) != "|")) + { + expressionStr += stringToAdd; + + _stackIgnoredExp = new RegExp(expressionStr + stringToAdd); + } + } + + private function addDotSlash(string:String):String + { + return string.replace(/\./g, "\\.") + } + /////////////////////// // // // REMOTING CONFIG // // // /////////////////////// - - /** - * Shared connection name used for remoting + + /** + * Shared connection name used for remoting * You can change this if you don't want to use default channel * Other remotes with different remoting channel won't be able to connect your flash. * Start with _ to work in any domain + platform (air/swf - local / network) * Note that local to network sandbox still apply. */ public var remotingConnectionName:String = "_Console"; - + /** * allowDomain and allowInsecureDomain of remoting LocalConnection. * Default: "*" * see LocalConnection -> allowDomain for info. */ public var allowedRemoteDomain:String = "*"; - + /////////////////// // // // MISC CONFIG // // // /////////////////// - + /** * Full Command line features usage allowance. *

- * CommandLine is a big security risk for your code and flash. + * CommandLine is a big security risk for your code and flash. * It is a very good practice to disable it after development phase. * On the other hand having it on full access will let you debug the code easier. *

*/ public var commandLineAllowed:Boolean; - + /** * CommandLine autoscoping *

@@ -215,7 +261,7 @@ package com.junkbyte.console { *

*/ public var commandLineAutoScope:Boolean; - + /** * CommandLine input pass through function *

@@ -232,25 +278,25 @@ package com.junkbyte.console { *

*/ public var commandLineInputPassThrough:Function; - + /** * Commandline auto hinting and auto-completion *

- * When using config.commandLineInputPassThrough feature, + * When using config.commandLineInputPassThrough feature, * it maybe be convenient to turn off commandLineAutoCompleteEnabled. *

*/ public var commandLineAutoCompleteEnabled:Boolean = true; - + /** * Key binding availability *

- * While turned off, you can still bind keys. + * While turned off, you can still bind keys. * Just that it will not trigger so long as the keyBindsEnabled is set to false. *

*/ public var keyBindsEnabled:Boolean = true; - + /** * Display Roller availability *

@@ -258,30 +304,16 @@ package com.junkbyte.console { *

*/ public var displayRollerEnabled:Boolean = true; - - /** - * Ruler tool availability - */ - public var rulerToolEnabled:Boolean = true; - + /** - * Determine if Console should hide mouse cursor when using Ruler tool. - *

- * You may want to turn it off if your app/game don't use system mouse. - * Default: true - *

- */ - public var rulerHidesMouse:Boolean = true; - - /** * Local shared object used for storing user data such as command line history * Set to null to disable storing to local shared object. */ public var sharedObjectName:String = "com.junkbyte/Console/UserData"; - + /** Local shared object path */ public var sharedObjectPath:String = "/"; - + /** * Remembers viewing filters such as channels and priority level over different sessions. *
    @@ -292,49 +324,51 @@ package com.junkbyte.console { *
*/ public var rememberFilterSettings:Boolean; - + /** * Keeping Console on top of display list. *

* When turned on (by default), console will always try to put it self on top of the parent's display list. - * For example, if console is started in root, when a child display is added in root, console will move it self to the + * For example, if console is started in root, when a child display is added in root, console will move it self to the * top of root's display list to try to overlay the new child display. - making sure that console don't get covered. *

*

- * However, if Console's parent display (root in example) is covered by another display (example: adding a child directly to stage), + * However, if Console's parent display (root in example) is covered by another display (example: adding a child directly to stage), * console will not be able to pull it self above it as it is in root, not stage. * If console is added on stage in the first place, there won't be an issue as described above. Use Cc.startOnStage(...). *

*

- * Keeping it turned on may have other side effects if another display is also trying to put it self on top, + * Keeping it turned on may have other side effects if another display is also trying to put it self on top, * they could be jumping layers as they fight for the top layer. *

*/ public var alwaysOnTop:Boolean = true; - + //////////////////// // // // STYLE CONFIG // // // //////////////////// - + /** * Get style configuration used. */ - public function get style():ConsoleStyle{ + public function get style():ConsoleStyle + { return _style; } - + ///////////////////// // // // END OF CONFIG // // // ///////////////////// - + private var _style:ConsoleStyle; - - public function ConsoleConfig(){ + + public function ConsoleConfig() + { _style = new ConsoleStyle(); } } -} \ No newline at end of file +} diff --git a/src/com/junkbyte/console/ConsoleLevel.as b/src/com/junkbyte/console/ConsoleLevel.as new file mode 100644 index 0000000..a8ec1a7 --- /dev/null +++ b/src/com/junkbyte/console/ConsoleLevel.as @@ -0,0 +1,12 @@ +package com.junkbyte.console +{ + public class ConsoleLevel + { + public static const LOG:uint = 2; + public static const INFO:uint = 4; + public static const DEBUG:uint = 7; + public static const WARN:uint = 8; + public static const ERROR:uint = 9; + public static const FATAL:uint = 10; + } +} \ No newline at end of file diff --git a/src/com/junkbyte/console/ConsoleStyle.as b/src/com/junkbyte/console/ConsoleStyle.as index 191c648..64dc78a 100644 --- a/src/com/junkbyte/console/ConsoleStyle.as +++ b/src/com/junkbyte/console/ConsoleStyle.as @@ -28,13 +28,16 @@ package com.junkbyte.console { public class ConsoleStyle { /** Font for menus and almost all others */ - public var menuFont:String = "Arial"; + public var menuFont:String = "Arial, Verdana"; /** Default font size */ public var menuFontSize:int = 12; /** Font for trace field */ - public var traceFont:String = "Verdana"; + public var traceFont:String = "Verdana, Arial"; + + /** Font for non-string trace */ + public var traceTypedFont:String = "Courier New, Arial"; /** Font size for trace field */ public var traceFontSize:int = 11; @@ -200,6 +203,7 @@ package com.junkbyte.console { _css.setStyle("p-1",{color:hesh(priorityC1), display:'inline'}); _css.setStyle("p-2",{color:hesh(priorityC2), display:'inline'}); _css.setStyle("logs",{color:hesh(logHeaderColor), display:'inline'}); + _css.setStyle("type",{fontFamily:traceTypedFont, fontSize:traceFontSize+1, display:'inline'}); } /** * Style sheet used by Console. diff --git a/src/com/junkbyte/console/addons/autoFocus/CommandLineAutoFocusAddon.as b/src/com/junkbyte/console/addons/autoFocus/CommandLineAutoFocusAddon.as index 75a38bf..a69e797 100644 --- a/src/com/junkbyte/console/addons/autoFocus/CommandLineAutoFocusAddon.as +++ b/src/com/junkbyte/console/addons/autoFocus/CommandLineAutoFocusAddon.as @@ -38,7 +38,7 @@ package com.junkbyte.console.addons.autoFocus var commandField:TextField = mainPanel.getChildByName("commandField") as TextField; - if (commandField && commandField.stage) + if (commandField && commandField.visible && commandField.stage) { commandField.stage.focus = commandField; var textLen:uint = commandField.text.length; diff --git a/src/com/junkbyte/console/addons/commandprompt/CommandPrompt.as b/src/com/junkbyte/console/addons/commandprompt/CommandPrompt.as index 23d1122..d38930c 100644 --- a/src/com/junkbyte/console/addons/commandprompt/CommandPrompt.as +++ b/src/com/junkbyte/console/addons/commandprompt/CommandPrompt.as @@ -25,6 +25,7 @@ package com.junkbyte.console.addons.commandprompt { import com.junkbyte.console.Cc; import com.junkbyte.console.Console; + import com.junkbyte.console.ConsoleChannel; /** * Command prompt addon. @@ -36,7 +37,7 @@ package com.junkbyte.console.addons.commandprompt { */ public class CommandPrompt { - public var ch : String = Console.CONSOLE_CHANNEL; + public var ch : String = ConsoleChannel.CONSOLE_CHANNEL; public var headerQuestion:String; public var footerText:String; public var defaultCallback:Function; diff --git a/src/com/junkbyte/console/addons/displaymap/DisplayMapAddon.as b/src/com/junkbyte/console/addons/displaymap/DisplayMapAddon.as index 09a333a..300169d 100644 --- a/src/com/junkbyte/console/addons/displaymap/DisplayMapAddon.as +++ b/src/com/junkbyte/console/addons/displaymap/DisplayMapAddon.as @@ -133,7 +133,7 @@ package com.junkbyte.console.addons.displaymap panel.y = console.mouseY + 10; } } - console.addMenu(menuName, callbackFunction); + console.addMenu(menuName, callbackFunction, null, "Display map"); } } } diff --git a/src/com/junkbyte/console/addons/htmlexport/ConsoleHtmlExportAddon.as b/src/com/junkbyte/console/addons/htmlexport/ConsoleHtmlExportAddon.as index 75a883e..bd2f0e6 100644 --- a/src/com/junkbyte/console/addons/htmlexport/ConsoleHtmlExportAddon.as +++ b/src/com/junkbyte/console/addons/htmlexport/ConsoleHtmlExportAddon.as @@ -21,7 +21,6 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * -* REQUIRES Flash Player 11.0 OR com.adobe.serialization.json.JSON */ package com.junkbyte.console.addons.htmlexport { @@ -47,6 +46,7 @@ package com.junkbyte.console.addons.htmlexport * * * REQUIRES Flash Player 11.0 OR com.adobe.serialization.json.JSON library. + * If you are using com.adobe.serialization.json.JSON, make sure you reference the class somewhere so that it get compiled. */ public class ConsoleHtmlExportAddon { diff --git a/src/com/junkbyte/console/addons/htmlexport/template.html b/src/com/junkbyte/console/addons/htmlexport/template.html index e0f57a8..eb77742 100644 --- a/src/com/junkbyte/console/addons/htmlexport/template.html +++ b/src/com/junkbyte/console/addons/htmlexport/template.html @@ -73,6 +73,10 @@ function convertChannelsListToMap(channels) { + if(channels == null || channels.length == 0) + { + return null; + } var object = {}; for (var X in channels) { diff --git a/src/com/junkbyte/console/addons/ruler/RulerAddon.as b/src/com/junkbyte/console/addons/ruler/RulerAddon.as new file mode 100644 index 0000000..f8d4f28 --- /dev/null +++ b/src/com/junkbyte/console/addons/ruler/RulerAddon.as @@ -0,0 +1,371 @@ +/* +* +* Copyright (c) 2008-2010 Lu Aye Oo +* +* @author Lu Aye Oo +* +* http://code.google.com/p/flash-console/ +* +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +* +*/ +package com.junkbyte.console.addons.ruler +{ + import com.junkbyte.console.Cc; + import com.junkbyte.console.Console; + import com.junkbyte.console.ConsoleConfig; + import com.junkbyte.console.ConsoleStyle; + + import flash.display.Bitmap; + import flash.display.BitmapData; + import flash.display.BlendMode; + import flash.display.Graphics; + import flash.display.Shape; + import flash.display.Sprite; + import flash.events.Event; + import flash.events.MouseEvent; + import flash.geom.Matrix; + import flash.geom.Point; + import flash.geom.Rectangle; + import flash.text.TextField; + import flash.text.TextFieldAutoSize; + import flash.text.TextFormat; + import flash.text.TextFormatAlign; + import flash.ui.Mouse; + + /** + * Screen ruler addon. + *

+ * Measure the distance and angle between two points on screen. + *

+ *

+ * Register to console using RulerAddon.addToMenu(); + *

+ */ + public class RulerAddon extends Sprite + { + + /** + * Determine if Console should hide mouse cursor when using Ruler tool. + *

+ * You may want to turn it off if your app/game don't use system mouse. + * Default: true + *

+ */ + public static var hideMouseWhenActive:Boolean = true; + + /** + * Add screen ruler addon to console menu. + * + * @param menuName Name of menu. Default = 'ruler' + * @param console Instance to Console. You do not need to pass this param if you use Cc. + */ + public static function addToMenu(menuName:String = "ruler", console:Console = null):void + { + if (console == null) + { + console = Cc.instance; + } + if (console) + { + console.addMenu(menuName, startRuler, new Array(console), "Screen Ruler::Measure the distance and angle between two points on screen."); + } + } + + private static function startRuler(console:Console):void + { + var ruler:RulerAddon = new RulerAddon(console); + ruler.start(); + } + + private var _console:Console; + + private var _area:Rectangle; + private var _pointer:Shape; + + private var _posTxt:TextField; + private var _zoom:Bitmap; + + private var _points:Array; + + public function RulerAddon(console:Console) + { + _console = console; + buttonMode = true; + _points = new Array(); + _pointer = new Shape(); + addChild(_pointer); + var p:Point = new Point(); + p = globalToLocal(p); + _area = new Rectangle(-console.stage.stageWidth * 1.5 + p.x, -console.stage.stageHeight * 1.5 + p.y, console.stage.stageWidth * 3, console.stage.stageHeight * 3); + graphics.beginFill(config.style.backgroundColor, 0.2); + graphics.drawRect(_area.x, _area.y, _area.width, _area.height); + graphics.endFill(); + // + _posTxt = _console.panels.mainPanel.makeTF("positionText", true); + _posTxt.autoSize = TextFieldAutoSize.LEFT; + addChild(_posTxt); + // + _zoom = new Bitmap(); + _zoom.scaleY = _zoom.scaleX = 2; + addChild(_zoom); + // + addEventListener(MouseEvent.CLICK, onMouseClick, false, 0, true); + addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true); + onMouseMove(); + if (hideMouseWhenActive) + { + Mouse.hide(); + } + _console.report("Ruler started. Click on two locations to measure.", -1); + } + + public function start():void + { + _console.addChild(this); + } + + private function get config():ConsoleConfig + { + return _console.config; + } + + private function onMouseMove(e:MouseEvent = null):void + { + _pointer.graphics.clear(); + _pointer.graphics.lineStyle(1, 0xAACC00, 1); + _pointer.graphics.moveTo(_area.x, mouseY); + _pointer.graphics.lineTo(_area.x + _area.width, mouseY); + _pointer.graphics.moveTo(mouseX, _area.y); + _pointer.graphics.lineTo(mouseX, _area.y + _area.height); + _pointer.blendMode = BlendMode.INVERT; + _posTxt.text = "" + mouseX + "," + mouseY + ""; + // + var bmd:BitmapData = new BitmapData(30, 30); + try + { + var m:Matrix = new Matrix(); + m.tx = -stage.mouseX + 15; + m.ty = -stage.mouseY + 15; + bmd.draw(stage, m); + } + catch (err:Error) + { + bmd = null; + } + _zoom.bitmapData = bmd; + // + var d:int = 10; + _posTxt.x = mouseX - _posTxt.width - d; + _posTxt.y = mouseY - _posTxt.height - d; + _zoom.x = _posTxt.x + _posTxt.width - _zoom.width; + _zoom.y = _posTxt.y - _zoom.height; + if (_posTxt.x < 16) + { + _posTxt.x = mouseX + d; + _zoom.x = _posTxt.x; + } + if (_posTxt.y < 38) + { + _posTxt.y = mouseY + d; + _zoom.y = _posTxt.y + _posTxt.height; + } + } + + private function onMouseClick(e:MouseEvent):void + { + e.stopPropagation(); + var p:Point; + var style:ConsoleStyle = config.style; + if (_points.length == 0) + { + p = new Point(e.localX, e.localY); + graphics.lineStyle(1, 0xFF0000); + graphics.drawCircle(p.x, p.y, 3); + _points.push(p); + } + else if (_points.length == 1) + { + _zoom.bitmapData = null; + if (hideMouseWhenActive) + { + Mouse.show(); + } + removeChild(_pointer); + removeChild(_posTxt); + removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + p = _points[0]; + var p2:Point = new Point(e.localX, e.localY); + _points.push(p2); + graphics.clear(); + graphics.beginFill(style.backgroundColor, 0.4); + graphics.drawRect(_area.x, _area.y, _area.width, _area.height); + graphics.endFill(); + graphics.lineStyle(1.5, 0xFF0000); + graphics.drawCircle(p.x, p.y, 4); + graphics.lineStyle(1.5, 0xFF9900); + graphics.drawCircle(p2.x, p2.y, 4); + var mp:Point = Point.interpolate(p, p2, 0.5); + graphics.lineStyle(1, 0xAAAAAA); + graphics.drawCircle(mp.x, mp.y, 4); + // + var xmin:Point = p; + var xmax:Point = p2; + if (p.x > p2.x) + { + xmin = p2; + xmax = p; + } + var ymin:Point = p; + var ymax:Point = p2; + if (p.y > p2.y) + { + ymin = p2; + ymax = p; + } + // + var w:Number = xmax.x - xmin.x; + var h:Number = ymax.y - ymin.y; + var d:Number = Point.distance(p, p2); + // + var txt:TextField = makeTxtField(style.highColor); + txt.text = round(p.x) + "," + round(p.y); + txt.x = p.x; + txt.y = p.y - (ymin == p ? 14 : 0); + addChild(txt); + // + txt = makeTxtField(style.highColor); + txt.text = round(p2.x) + "," + round(p2.y); + txt.x = p2.x; + txt.y = p2.y - (ymin == p2 ? 14 : 0); + ; + addChild(txt); + // + if (w > 40 || h > 25) + { + txt = makeTxtField(style.lowColor); + txt.text = round(mp.x) + "," + round(mp.y); + txt.x = mp.x; + txt.y = mp.y; + addChild(txt); + } + // + graphics.lineStyle(1, 0xAACC00, 0.5); + graphics.moveTo(_area.x, ymin.y); + graphics.lineTo(_area.x + _area.width, ymin.y); + graphics.moveTo(_area.x, ymax.y); + graphics.lineTo(_area.x + _area.width, ymax.y); + graphics.moveTo(xmin.x, _area.y); + graphics.lineTo(xmin.x, _area.y + _area.height); + graphics.moveTo(xmax.x, _area.y); + graphics.lineTo(xmax.x, _area.y + _area.height); + // + var a1:Number = round(angle(p, p2), 100); + var a2:Number = round(angle(p2, p), 100); + graphics.lineStyle(1, 0xAA0000, 0.8); + drawCircleSegment(graphics, 10, p, a1, -90); + graphics.lineStyle(1, 0xCC8800, 0.8); + drawCircleSegment(graphics, 10, p2, a2, -90); + // + graphics.lineStyle(2, 0x00FF00, 0.7); + graphics.moveTo(p.x, p.y); + graphics.lineTo(p2.x, p2.y); + // + _console.report("Ruler results: (red) [" + p.x + "," + p.y + "] to (orange) [" + p2.x + "," + p2.y + "]", -2); + _console.report("Distance: " + round(d, 100) + "", -2); + _console.report("Mid point: [" + mp.x + "," + mp.y + "]", -2); + _console.report("Width:" + w + ", Height: " + h + "", -2); + _console.report("Angle from first point (red): " + a1 + "°", -2); + _console.report("Angle from second point (orange): " + a2 + "°", -2); + } + else + { + exit(); + } + } + + public function exit():void + { + _console = null; + if (parent) + { + parent.removeChild(this); + } + dispatchEvent(new Event(Event.COMPLETE)); + } + + private function makeTxtField(col:Number, b:Boolean = true):TextField + { + var format:TextFormat = new TextFormat(config.style.menuFont, config.style.menuFontSize, col, b, true, null, null, TextFormatAlign.RIGHT); + var txt:TextField = new TextField(); + txt.autoSize = TextFieldAutoSize.RIGHT; + txt.selectable = false; + txt.defaultTextFormat = format; + return txt; + } + + private function round(n:Number, d:uint = 10):Number + { + return Math.round(n * d) / d; + } + + private function angle(srcP:Point, point:Point):Number + { + var a:Number = Math.atan2(point.y - srcP.y, point.x - srcP.x) / Math.PI * 180; + a += 90; + if (a > 180) + { + a -= 360; + } + return a; + } + + private function drawCircleSegment(g:Graphics, radius:Number, pos:Point, deg:Number = 180, startDeg:Number = 0):Point + { + var reversed:Boolean = false; + if (deg < 0) + { + reversed = true; + deg = Math.abs(deg); + } + var rad:Number = (deg * Math.PI) / 180; + var rad2:Number = (startDeg * Math.PI) / 180; + var p:Point = getPointOnCircle(radius, rad2); + p.offset(pos.x, pos.y); + g.moveTo(p.x, p.y); + var pra:Number = 0; + for (var i:int = 1; i <= (rad + 1); i++) + { + var ra:Number = i <= rad ? i : rad; + var diffr:Number = ra - pra; + var offr:Number = 1 + (0.12 * diffr * diffr); + var ap:Point = getPointOnCircle(radius * offr, ((ra - (diffr / 2)) * (reversed ? -1 : 1)) + rad2); + ap.offset(pos.x, pos.y); + p = getPointOnCircle(radius, (ra * (reversed ? -1 : 1)) + rad2); + p.offset(pos.x, pos.y); + g.curveTo(ap.x, ap.y, p.x, p.y); + pra = ra; + } + return p; + } + + private function getPointOnCircle(radius:Number, rad:Number):Point + { + return new Point(radius * Math.cos(rad), radius * Math.sin(rad)); + } + + } +} diff --git a/src/com/junkbyte/console/console_internal.as b/src/com/junkbyte/console/console_internal.as new file mode 100644 index 0000000..e89faff --- /dev/null +++ b/src/com/junkbyte/console/console_internal.as @@ -0,0 +1,4 @@ +package com.junkbyte.console +{ + public namespace console_internal; +} \ No newline at end of file diff --git a/src/com/junkbyte/console/core/CcCallbackDispatcher.as b/src/com/junkbyte/console/core/CcCallbackDispatcher.as new file mode 100644 index 0000000..6098200 --- /dev/null +++ b/src/com/junkbyte/console/core/CcCallbackDispatcher.as @@ -0,0 +1,38 @@ +package com.junkbyte.console.core +{ + + public class CcCallbackDispatcher + { + + private var _list:Array = new Array(); + + public function add(callback:Function):void + { + remove(callback); + _list.push(callback); + } + + public function remove(callback:Function):void + { + var index:int = _list.indexOf(callback); + if (index >= 0) + { + _list.splice(index, 1); + } + } + + public function apply(param:Object):void + { + var len:uint = _list.length; + for (var i:uint = 0; i < len; i++) + { + _list[i](param); + } + } + + public function clear():void + { + _list.splice(0, _list.length); + } + } +} diff --git a/src/com/junkbyte/console/core/CommandLine.as b/src/com/junkbyte/console/core/CommandLine.as index 09acba2..b6d9cae 100644 --- a/src/com/junkbyte/console/core/CommandLine.as +++ b/src/com/junkbyte/console/core/CommandLine.as @@ -24,14 +24,14 @@ */ package com.junkbyte.console.core { - import flash.utils.ByteArray; - import flash.utils.getQualifiedClassName; import com.junkbyte.console.Console; import com.junkbyte.console.vos.WeakObject; import com.junkbyte.console.vos.WeakRef; - + import flash.display.DisplayObjectContainer; import flash.events.Event; + import flash.utils.ByteArray; + import flash.utils.getQualifiedClassName; /** * @private @@ -46,8 +46,8 @@ package com.junkbyte.console.core private var _scope:*; private var _prevScope:WeakRef; - private var _scopeStr:String = ""; - private var _slashCmds:Object; + protected var _scopeStr:String = ""; + private var _slashCmds:Array; public var localCommands:Array = new Array("filter", "filterexp"); @@ -55,7 +55,7 @@ package com.junkbyte.console.core super(m); _saved = new WeakObject(); _scope = m; - _slashCmds = new Object(); + _slashCmds = new Array(); _prevScope = new WeakRef(m); _saved.set("C", m); @@ -65,13 +65,12 @@ package com.junkbyte.console.core remoter.registerCallback("scope", function(bytes:ByteArray):void{ handleScopeEvent(bytes.readUnsignedInt()); }); - remoter.registerCallback("cls", handleScopeString); remoter.addEventListener(Event.CONNECT, sendCmdScope2Remote); addCLCmd("help", printHelp, "How to use command line"); - addCLCmd("save|store", saveCmd, "Save current scope as weak reference. (same as Cc.store(...))"); - addCLCmd("savestrong|storestrong", saveStrongCmd, "Save current scope as strong reference"); - addCLCmd("saved|stored", savedCmd, "Show a list of all saved references"); + addCLCmd("save", saveCmd, "Save current scope as weak reference. (same as Cc.store(...))"); + addCLCmd("savestrong", saveStrongCmd, "Save current scope as strong reference"); + addCLCmd("saved", savedCmd, "Show a list of all saved references"); addCLCmd("string", stringCmd, "Create String, useful to paste complex strings without worrying about \" or \'", false, null); addCLCmd("commands", cmdsCmd, "Show a list of all slash commands", true); addCLCmd("inspect", inspectCmd, "Inspect current scope"); @@ -84,7 +83,7 @@ package com.junkbyte.console.core } public function set base(obj:Object):void { - if (base) { + if (this.base) { report("Set new commandLine base from "+base+ " to "+ obj, 10); }else{ _prevScope.reference = _scope; @@ -96,19 +95,10 @@ package com.junkbyte.console.core public function get base():Object { return _saved.get("base"); } - public function handleScopeString(bytes:ByteArray):void{ - _scopeStr = bytes.readUTF(); - } public function handleScopeEvent(id:uint):void{ - if(remoter.remoting == Remoting.RECIEVER){ - var bytes:ByteArray = new ByteArray(); - bytes.writeUnsignedInt(id); - remoter.send("scope", bytes); - }else{ - var v:* = console.refs.getRefById(id); - if(v) console.cl.setReturned(v, true, false); - else console.report("Reference no longer exist.", -2); - } + var v:* = console.refs.getRefById(id); + if(v) console.cl.setReturned(v, true, false); + else console.report("Reference no longer exist.", -2); } public function store(n:String, obj:Object, strong:Boolean = false):void { if(!n) { @@ -132,10 +122,9 @@ package com.junkbyte.console.core } public function getHintsFor(str:String, max:uint):Array{ var all:Array = new Array(); - for (var X:String in _slashCmds){ - var cmd:Object = _slashCmds[X]; + for each(var cmd:SlashCommand in _slashCmds){ if(config.commandLineAllowed || cmd.allow) - all.push(["/"+X+" ", cmd.d?cmd.d:null]); + all.push(["/"+cmd.n+" ", cmd.d?cmd.d:null]); } if(config.commandLineAllowed){ for (var Y:String in _saved){ @@ -168,46 +157,27 @@ package com.junkbyte.console.core return config.commandLineAllowed?_scopeStr:""; } public function addCLCmd(n:String, callback:Function, desc:String, allow:Boolean = false, endOfArgsMarker:String = ";"):void{ - var split:Array = n.split("|"); - for(var i:int = 0; i0) _slashCmds.setPropertyIsEnumerable(n, false); - } + _slashCmds.push(new SlashCommand(n, callback, desc, false, allow, endOfArgsMarker)); } public function addSlashCommand(n:String, callback:Function, desc:String = "", alwaysAvailable:Boolean = true, endOfArgsMarker:String = ";"):void{ - n = n.replace(/[^\w]*/g, ""); - if(_slashCmds[n] != null){ - var prev:SlashCommand = _slashCmds[n]; + //n = n.replace(/[^\w]*/g, ""); + var prev:SlashCommand = getSlashCommandWithName(n); + if(prev != null){ if(!prev.user) { throw new Error("Can not alter build-in slash command ["+n+"]"); } + removeSlashCommand(prev); } - if(callback == null) delete _slashCmds[n]; - else _slashCmds[n] = new SlashCommand(n, callback, LogReferences.EscHTML(desc), true, alwaysAvailable, endOfArgsMarker); + _slashCmds.push(new SlashCommand(n, callback, LogReferences.EscHTML(desc), true, alwaysAvailable, endOfArgsMarker)); } - public function run(str:String, saves:Object = null):* { + public function run(str:String, saves:Object = null, canThrowError:Boolean = false):* { if(!str) return; str = str.replace(/\s*/,""); - if(remoter.remoting == Remoting.RECIEVER){ - if(str.charAt(0) == "~"){ - str = str.substring(1); - }else if(str.search(new RegExp("\/"+localCommands.join("|\/"))) != 0){ - report("Run command at remote: "+str,-2); - - var bytes:ByteArray = new ByteArray(); - bytes.writeUTF(str); - if(!console.remoter.send("cmd", bytes)){ - report("Command could not be sent to client.", 10); - } - return null; - } - } report("> "+str, 4, false); var v:* = null; try{ if(str.charAt(0) == "/"){ - execCommand(str.substring(1)); + v = execCommand(str.substring(1)); }else{ if(!config.commandLineAllowed) { report(DISABLED, 9); @@ -229,6 +199,10 @@ package com.junkbyte.console.core } }catch(e:Error){ reportError(e); + if(canThrowError) + { + throw e; + } } return v; } @@ -241,21 +215,31 @@ package com.junkbyte.console.core setReturned(exe.scope, true); } } - private function execCommand(str:String):void{ - var brk:int = str.search(/[^\w]/); - var cmd:String = str.substring(0, brk>0?brk:str.length); - if(cmd == ""){ - setReturned(_saved.get(Executer.RETURNED), true); - return; + private function execCommand(str:String):*{ + if(str.search(/[^\s]/) < 0){ + var returned:* = _saved.get(Executer.RETURNED); + setReturned(returned, true); + return returned; } - var param:String = brk>0?str.substring(brk+1):""; - if(_slashCmds[cmd] != null){ + var result:*; + var slashcmd:SlashCommand; + for each(var cmd:SlashCommand in _slashCmds) + { + if(str.indexOf(cmd.n) == 0 && (str.length == cmd.n.length || str.charAt(cmd.n.length) == " ")) + { + if(slashcmd == null || slashcmd.n.length < cmd.n.length) // make sure newly found match has longer match. + { + slashcmd = cmd; + } + } + } + if(slashcmd != null){ try{ - var slashcmd:SlashCommand = _slashCmds[cmd]; + var param:String = str.substring(slashcmd.n.length+1); if(!config.commandLineAllowed && !slashcmd.allow) { report(DISABLED, 9); - return; + return result; } var restStr:String; if(slashcmd.endMarker){ @@ -266,12 +250,13 @@ package com.junkbyte.console.core } } if(param.length == 0){ - slashcmd.f(); + result = slashcmd.f(); } else { - slashcmd.f(param); + result = slashcmd.f(param); } - if(restStr){ - run(restStr); + if(restStr) + { + result = run(restStr); } }catch(err:Error){ reportError(err); @@ -279,6 +264,7 @@ package com.junkbyte.console.core } else{ report("Undefined command /commands for list of all commands.",10); } + return result; } public function setReturned(returned:*, changeScope:Boolean = false, say:Boolean = true):void{ if(!config.commandLineAllowed) { @@ -292,10 +278,8 @@ package com.junkbyte.console.core // scope changed _prevScope.reference = _scope; _scope = returned; - if(remoter.remoting != Remoting.RECIEVER){ - _scopeStr = LogReferences.ShortClassName(_scope, false); - sendCmdScope2Remote(); - } + _scopeStr = LogReferences.ShortClassName(_scope, false); + sendCmdScope2Remote(); report("Changed to "+console.refs.makeRefTyped(returned), -1); }else{ if(say) report("Returned "+console.refs.makeString(returned), -1); @@ -305,9 +289,12 @@ package com.junkbyte.console.core } } public function sendCmdScope2Remote(e:Event = null):void{ - var bytes:ByteArray = new ByteArray(); - bytes.writeUTF(_scopeStr); - console.remoter.send("cls", bytes); + if(remoter.connected) + { + var bytes:ByteArray = new ByteArray(); + bytes.writeUTF(_scopeStr); + console.remoter.send("cls", bytes); + } } private function reportError(e:Error):void{ var str:String = console.refs.makeString(e); @@ -331,6 +318,26 @@ package com.junkbyte.console.core } report(parts.join("\n"), 9); } + + private function getSlashCommandWithName(name:String):SlashCommand + { + for each(var cmd:SlashCommand in _slashCmds) + { + if(cmd.n.indexOf(name) == 0) + { + return cmd; + } + } + return null; + } + private function removeSlashCommand(cmd:SlashCommand):void + { + var index:int = _slashCmds.indexOf(cmd); + if(index >= 0) + { + _slashCmds.splice(index, 1); + } + } private function saveCmd(param:String = null):void{ store(param, _scope, false); } diff --git a/src/com/junkbyte/console/core/ConsoleTools.as b/src/com/junkbyte/console/core/ConsoleTools.as index 0bb2d1c..f7a6fd6 100644 --- a/src/com/junkbyte/console/core/ConsoleTools.as +++ b/src/com/junkbyte/console/core/ConsoleTools.as @@ -162,7 +162,7 @@ package com.junkbyte.console.core var txt:String = ""; var lines:Array = str.split(/\n\sat\s/); var len:int = lines.length; - var reg:RegExp = new RegExp("Function|"+getQualifiedClassName(Console)+"|"+getQualifiedClassName(Cc)); + var reg:RegExp = config.stackTraceIgnoreExpression; var found:Boolean = false; for (var i:int = 2; i < len; i++){ if(!found && (lines[i].search(reg) != 0)){ diff --git a/src/com/junkbyte/console/core/Graphing.as b/src/com/junkbyte/console/core/Graphing.as index 21ffb27..92f4996 100644 --- a/src/com/junkbyte/console/core/Graphing.as +++ b/src/com/junkbyte/console/core/Graphing.as @@ -1,11 +1,11 @@ /* -* +* * Copyright (c) 2008-2010 Lu Aye Oo -* +* * @author Lu Aye Oo -* +* * http://code.google.com/p/flash-console/ -* +* * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -20,259 +20,346 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. -* +* */ -package com.junkbyte.console.core { - import flash.utils.ByteArray; +package com.junkbyte.console.core +{ import com.junkbyte.console.Console; - import flash.system.System; - import flash.utils.getTimer; - - import com.junkbyte.console.vos.GraphInterest; + import com.junkbyte.console.vos.GraphFPSGroup; import com.junkbyte.console.vos.GraphGroup; - - import flash.geom.Rectangle; + import com.junkbyte.console.vos.GraphInterest; + import com.junkbyte.console.vos.GraphMemoryGroup; + import flash.events.Event; + import flash.geom.Rectangle; + import flash.utils.ByteArray; + /** * @private */ - public class Graphing extends ConsoleCore{ - - private var _groups:Array = []; - private var _map:Object = {}; - - private var _fpsGroup:GraphGroup; - private var _memGroup:GraphGroup; - - private var _hadGraph:Boolean; - private var _previousTime:Number = -1; - - public function Graphing(m:Console){ + public class Graphing extends ConsoleCore + { + + protected var _groups:Array = []; + protected var _map:Object = {}; + + protected var _fpsGroup:GraphGroup; + protected var _memGroup:GraphGroup; + + protected var _groupAddedDispatcher:CcCallbackDispatcher = new CcCallbackDispatcher(); + + public function Graphing(m:Console) + { super(m); - remoter.registerCallback("fps", function(bytes:ByteArray):void{ - fpsMonitor = bytes.readBoolean(); - }); - remoter.registerCallback("mem", function(bytes:ByteArray):void{ - memoryMonitor = bytes.readBoolean(); + + remoter.addEventListener(Event.CONNECT, onRemoteConnection); + + remoter.registerCallback("fps", function(bytes:ByteArray):void + { + fpsMonitor = !fpsMonitor; }); - remoter.registerCallback("removeGroup", function(bytes:ByteArray):void{ - removeGroup(bytes.readUTF()); + remoter.registerCallback("mem", function(bytes:ByteArray):void + { + memoryMonitor = !memoryMonitor; }); - remoter.registerCallback("graph", handleRemoteGraph, true); - + remoter.registerCallback("removeGraphGroup", onRemotingRemoveGraphGroup); + remoter.registerCallback("menuGraphGroup", onRemotingMenuGraphGroup); } - public function add(n:String, obj:Object, prop:String, col:Number = -1, key:String = null, rect:Rectangle = null, inverse:Boolean = false):void{ - if(obj == null) { - report("ERROR: Graph ["+n+"] received a null object to graph property ["+prop+"].", 10); - return; + + public function add(n:String, obj:Object, prop:String, col:Number = -1, key:String = null, rect:Rectangle = null, inverse:Boolean = false):GraphGroup + { + if (obj == null) + { + report("ERROR: Graph [" + n + "] received a null object to graph property [" + prop + "].", 10); + return null; } var group:GraphGroup = _map[n]; var newGroup:Boolean; - if(!group) { + if (!group) + { newGroup = true; group = new GraphGroup(n); } var interests:Array = group.interests; - if (isNaN(col) || col < 0) { - if (interests.length <= 5) col = config.style["priority"+ (10-interests.length*2)]; - else col = Math.random()*0xFFFFFF; + if (isNaN(col) || col < 0) + { + if (interests.length <= 5) + { + col = config.style["priority" + (10 - interests.length * 2)]; + } + else + { + col = Math.random() * 0xFFFFFF; + } } - if(key == null) key = prop; - for each(var i:GraphInterest in interests){ - if(i.key == key){ - report("Graph with key ["+key+"] already exists in ["+n+"]", 10); - return; + if (key == null) + { + key = prop; + } + for each (var i:GraphInterest in interests) + { + if (i.key == key) + { + report("Graph with key [" + key + "] already exists in [" + n + "]", 10); + return null; } } - if(rect) group.rect = rect; - if(inverse) group.inv = inverse; + if (rect) + { + group.rect = rect; + } + if (inverse) + { + group.inverted = inverse; + } var interest:GraphInterest = new GraphInterest(key, col); var v:Number = NaN; - try{ + try + { v = interest.setObject(obj, prop); - }catch (e:Error){ - report("Error with graph value for ["+key+"] in ["+n+"]. "+e, 10); - return; } - if(isNaN(v)){ - report("Graph value for key ["+key+"] in ["+n+"] is not a number (NaN).", 10); - }else{ + catch (e:Error) + { + report("Error with graph value for [" + key + "] in [" + n + "]. " + e, 10); + return null; + } + if (isNaN(v)) + { + report("Graph value for key [" + key + "] in [" + n + "] is not a number (NaN).", 10); + } + else + { group.interests.push(interest); - if(newGroup){ + if (newGroup) + { _map[n] = group; - _groups.push(group); + addGroup(group); } } + return group; } - public function fixRange(n:String, low:Number = NaN, high:Number = NaN):void{ + public function remove(n:String, obj:Object = null, prop:String = null):void + { var group:GraphGroup = _map[n]; - if(!group) return; - group.low = low; - group.hi = high; - group.fixed = !(isNaN(low)||isNaN(high)); - } - public function remove(n:String, obj:Object = null, prop:String = null):void{ - if(obj==null&&prop==null){ - removeGroup(n); - }else if(_map[n]){ - var interests:Array = _map[n].interests; - for(var i:int = interests.length-1;i>=0;i--){ - var interest:GraphInterest = interests[i]; - if((obj == null || interest.obj == obj) && (prop == null || interest.prop == prop)){ - interests.splice(i, 1); - } + if(group) + { + if (obj == null && prop == null) + { + group.close(); } - if(interests.length==0){ - removeGroup(n); + else + { + var interests:Array = group.interests; + for (var i:int = interests.length - 1; i >= 0; i--) + { + var interest:GraphInterest = interests[i]; + if ((obj == null || interest.obj == obj) && (prop == null || interest.prop == prop)) + { + interests.splice(i, 1); + } + } + if (interests.length == 0) + { + group.close(); + } } } } - private function removeGroup(n:String):void{ - if(remoter.remoting == Remoting.RECIEVER) { - var bytes:ByteArray = new ByteArray(); - bytes.writeUTF(n); - remoter.send("removeGroup", bytes); - }else{ - var g:GraphGroup = _map[n]; - var index:int = _groups.indexOf(g); - if(index>=0) _groups.splice(index, 1); - delete _map[n]; + + public function fixRange(name:String, min:Number = NaN, max:Number = NaN):void + { + var group:GraphGroup = _map[name]; + if(group) + { + group.fixedMin = min; + group.fixedMax = max; } } - public function get fpsMonitor():Boolean{ - if(remoter.remoting == Remoting.RECIEVER) return console.panels.fpsMonitor; - return _fpsGroup!=null; + + public function get onGroupAdded():CcCallbackDispatcher + { + return _groupAddedDispatcher; } - public function set fpsMonitor(b:Boolean):void{ - if(remoter.remoting == Remoting.RECIEVER) { - var bytes:ByteArray = new ByteArray(); - bytes.writeBoolean(b); - remoter.send("fps", bytes); - }else if(b != fpsMonitor){ - if(b) { - _fpsGroup = addSpecialGroup(GraphGroup.FPS); - _fpsGroup.low = 0; - _fpsGroup.fixed = true; - _fpsGroup.averaging = 30; - } else{ - _previousTime = -1; - var index:int = _groups.indexOf(_fpsGroup); - if(index>=0) _groups.splice(index, 1); - _fpsGroup = null; + + public function get fpsMonitor():Boolean + { + return _fpsGroup != null; + } + + public function set fpsMonitor(b:Boolean):void + { + if (b) + { + if (_fpsGroup) + { + return; } + _fpsGroup = new GraphFPSGroup(console); + _fpsGroup.onClose.add(onFPSGroupClose); + addGroup(_fpsGroup); + console.panels.mainPanel.updateMenu(); } + else if (_fpsGroup) + { + _fpsGroup.close(); + } } + + private function onFPSGroupClose(group:GraphGroup):void + { + _fpsGroup = null; + + console.panels.mainPanel.updateMenu(); + } + // - public function get memoryMonitor():Boolean{ - if(remoter.remoting == Remoting.RECIEVER) return console.panels.memoryMonitor; - return _memGroup!=null; + public function get memoryMonitor():Boolean + { + return _memGroup != null; } - public function set memoryMonitor(b:Boolean):void{ - if(remoter.remoting == Remoting.RECIEVER) { - var bytes:ByteArray = new ByteArray(); - bytes.writeBoolean(b); - remoter.send("mem", bytes); - }else if(b != memoryMonitor){ - if(b) { - _memGroup = addSpecialGroup(GraphGroup.MEM); - _memGroup.freq = 20; - } else{ - var index:int = _groups.indexOf(_memGroup); - if(index>=0) _groups.splice(index, 1); - _memGroup = null; + + public function set memoryMonitor(b:Boolean):void + { + if (b) + { + if (_memGroup) + { + return; } + _memGroup = new GraphMemoryGroup(console); + _memGroup.onClose.add(onMemGroupClose); + addGroup(_memGroup); + console.panels.mainPanel.updateMenu(); } + else if (_memGroup) + { + _memGroup.close(); + } } - private function addSpecialGroup(type:int):GraphGroup{ - var group:GraphGroup = new GraphGroup("special"); - group.type = type; - _groups.push(group); - var graph:GraphInterest = new GraphInterest("special"); - if(type == GraphGroup.FPS) { - graph.col = 0xFF3333; - }else{ - graph.col = 0x5060FF; + + private function onMemGroupClose(group:GraphGroup):void + { + _memGroup = null; + + console.panels.mainPanel.updateMenu(); + } + + public function addGroup(group:GraphGroup):void + { + if (_groups.indexOf(group) < 0) + { + _groups.push(group); + group.onClose.add(onGroupClose); + + _groupAddedDispatcher.apply(group); + + syncAddGroup(group); } - group.interests.push(graph); - return group; } - public function update(fps:Number = 0):Array{ - var interest:GraphInterest; - var v:Number; - for each(var group:GraphGroup in _groups){ - var ok:Boolean = true; - if(group.freq>1){ - group.idle++; - if(group.idle= 0){ - var mspf:Number = time-_previousTime; - v = 1000/mspf; - interest.setValue(v, averaging); - } - _previousTime = time; - }else if(typ == GraphGroup.MEM){ - interest = interests[0]; - v = Math.round(System.totalMemory/10485.76)/100; - group.updateMinMax(v); - interest.setValue(v, averaging); - }else{ - updateExternalGraphGroup(group); - } - } + + protected function onGroupClose(group:GraphGroup):void + { + var index:int = _groups.indexOf(group); + if (index >= 0) + { + _groups.splice(index, 1); + + syncRemoveGroup(index); } - if(remoter.canSend && (_hadGraph || _groups.length)){ - var len:uint = _groups.length; - var ga:ByteArray = new ByteArray(); - for(var j:uint = 0; j0; + } + + public function update(timeDelta:uint):void + { + for each (var group:GraphGroup in _groups) + { + group.tick(timeDelta); + } + } + + protected function onRemoteConnection(event:Event):void + { + var bytes:ByteArray = new ByteArray(); + bytes.writeShort(_groups.length); + for each (var group:GraphGroup in _groups) + { + group.writeToBytes(bytes); + setupSyncGroupUpdate(group); + } + remoter.send("graphGroups", bytes); + } + + protected function onRemotingRemoveGraphGroup(bytes:ByteArray):void + { + var index:uint = bytes.readShort(); + var group:GraphGroup = _groups[index]; + if (group) + { + group.close(); } - return _groups; } - private function updateExternalGraphGroup(group:GraphGroup):void + protected function onRemotingMenuGraphGroup(bytes:ByteArray):void { - for each(var i:GraphInterest in group.interests){ - try{ - var v:Number = i.getCurrentValue(); - i.setValue(v, group.averaging); - }catch(e:Error){ - report("Error with graph value for key ["+i.key+"] in ["+group.name+"]. "+e, 10); - remove(group.name, i.obj, i.prop); - } - group.updateMinMax(v); + var index:uint = bytes.readShort(); + var menuKey:String = bytes.readUTF(); + var group:GraphGroup = _groups[index]; + if (group) + { + group.onMenu.apply(menuKey); + } + } + + protected function syncAddGroup(group:GraphGroup):void + { + if (remoter.connected) + { + var bytes:ByteArray = new ByteArray(); + group.writeToBytes(bytes); + remoter.send("addGraphGroup", bytes); + setupSyncGroupUpdate(group); } } + + protected function syncRemoveGroup(index:int):void + { + if (remoter.connected) + { + var bytes:ByteArray = new ByteArray(); + bytes.writeShort(index); + remoter.send("removeGraphGroup", bytes); + } + } + - private function handleRemoteGraph(bytes:ByteArray = null):void{ - if(bytes && bytes.length){ - bytes.position = 0; - var a:Array = new Array(); - while(bytes.bytesAvailable){ - a.push(GraphGroup.FromBytes(bytes)); + protected function setupSyncGroupUpdate(group:GraphGroup):void + { + group.onUpdate.add(function (values:Array):void + { + syncGroupUpdate(group, values); + }); + } + + protected function syncGroupUpdate(group:GraphGroup, values:Array):void + { + if (remoter.connected) + { + var index:int = _groups.indexOf(group); + if (index < 0) + { + return; + } + + var bytes:ByteArray = new ByteArray(); + bytes.writeShort(index); + for each(var value:Number in values) + { + bytes.writeDouble(value); } - console.panels.updateGraphs(a); - }else{ - console.panels.updateGraphs(new Array()); + remoter.send("updateGraphGroup", bytes); } } } -} \ No newline at end of file +} diff --git a/src/com/junkbyte/console/core/LogReferences.as b/src/com/junkbyte/console/core/LogReferences.as index e5953a8..3375da0 100644 --- a/src/com/junkbyte/console/core/LogReferences.as +++ b/src/com/junkbyte/console/core/LogReferences.as @@ -121,13 +121,13 @@ package com.junkbyte.console.core // err.getStackTrace() is not supported in non-debugger players... var stackstr:String = err.hasOwnProperty("getStackTrace")?err.getStackTrace():err.toString(); if(stackstr){ - return stackstr; + txt = stackstr; } - return err.toString(); + txt = err.toString(); }else if(v is XML || v is XMLList){ - return shortenString(EscHTML(v.toXMLString()), maxlen, o, prop); + txt = shortenString(EscHTML(v.toXMLString()), maxlen, o, prop); }else if(v is QName){ - return String(v); + txt = String(v); }else if(v is Array || getQualifiedClassName(v).indexOf("__AS3__.vec::Vector.") == 0){ // note: using getQualifiedClassName for vector for backward compatibility // Need to specifically cast to string in array to produce correct results @@ -152,12 +152,20 @@ package com.junkbyte.console.core else if(v is DisplayObject && v.name) add = " "+v.name; txt = "{"+genLinkString(o, prop, ShortClassName(v))+EscHTML(add)+"}"; }else{ - if(v is ByteArray) txt = "[ByteArray position:"+ByteArray(v).position+" length:"+ByteArray(v).length+"]"; - else txt = String(v); - if(!html){ - return shortenString(EscHTML(txt), maxlen, o, prop); + if(v is ByteArray) + { + txt = "[ByteArray position:"+ByteArray(v).position+" length:"+ByteArray(v).length+"]"; + } + txt = String(v); + if(!html) + { + txt = shortenString(EscHTML(txt), maxlen, o, prop); } } + if(!(v is String)) + { + txt = ""+txt+""; + } return txt; } public function makeRefTyped(v:*):String{ @@ -193,13 +201,7 @@ package com.junkbyte.console.core } } public function handleRefEvent(str:String):void{ - if(remoter.remoting == Remoting.RECIEVER){ - var bytes:ByteArray = new ByteArray(); - bytes.writeUTF(str); - remoter.send("ref", bytes); - }else{ - handleString(str); - } + handleString(str); } private function handleString(str:String):void{ if(str == "refexit"){ @@ -238,7 +240,10 @@ package com.junkbyte.console.core } } public function focus(o:*, full:Boolean = false):void{ - remoter.send("focus"); + if(remoter.connected) + { + remoter.send("focus"); + } console.clear(LogReferences.INSPECTING_CHANNEL); console.setViewingChannels(LogReferences.INSPECTING_CHANNEL); @@ -262,11 +267,14 @@ package com.junkbyte.console.core _dofull = false; _history = null; _hisIndex = 0; - if(remoter.remoting == Remoting.SENDER){ + + if(remoter.connected) + { var bytes:ByteArray = new ByteArray(); bytes.writeUTF("refexit"); remoter.send("ref", bytes); } + console.clear(LogReferences.INSPECTING_CHANNEL); } diff --git a/src/com/junkbyte/console/core/Logs.as b/src/com/junkbyte/console/core/Logs.as index 70b7913..a3b6cad 100644 --- a/src/com/junkbyte/console/core/Logs.as +++ b/src/com/junkbyte/console/core/Logs.as @@ -24,11 +24,13 @@ */ package com.junkbyte.console.core { - import flash.utils.ByteArray; - import flash.events.Event; import com.junkbyte.console.Console; + import com.junkbyte.console.ConsoleChannel; import com.junkbyte.console.vos.Log; + import flash.events.Event; + import flash.utils.ByteArray; + /** * @private */ @@ -38,9 +40,9 @@ package com.junkbyte.console.core private var _repeating:uint; private var _lastRepeat:Log; private var _newRepeat:Log; - private var _hasNewLog:Boolean; private var _timer:uint; + public var hasNewLog:Boolean; public var first:Log; public var last:Log; @@ -51,9 +53,6 @@ package com.junkbyte.console.core super(console); _channels = new Object(); remoter.addEventListener(Event.CONNECT, onRemoteConnection); - remoter.registerCallback("log", function(bytes:ByteArray):void{ - registerLog(Log.FromBytes(bytes)); - }); } private function onRemoteConnection(e:Event):void{ @@ -64,15 +63,15 @@ package com.junkbyte.console.core } } - private function send2Remote(line:Log):void{ - if(remoter.canSend) { + protected function send2Remote(line:Log):void{ + if(remoter.connected) { var bytes:ByteArray = new ByteArray(); - line.toBytes(bytes); + line.writeToBytes(bytes); remoter.send("log", bytes); } } - public function update(time:uint):Boolean{ + public function update(time:uint):void{ _timer = time; if(_repeating > 0) _repeating--; if(_newRepeat){ @@ -81,9 +80,6 @@ package com.junkbyte.console.core _newRepeat = null; push(_lastRepeat); } - var b:Boolean = _hasNewLog; - _hasNewLog = false; - return b; } public function add(line:Log):void{ @@ -94,8 +90,8 @@ package com.junkbyte.console.core registerLog(line); } - private function registerLog(line:Log):void{ - _hasNewLog = true; + protected function registerLog(line:Log):void{ + hasNewLog = true; addChannel(line.ch); line.lineStr = line.line +" "; @@ -156,11 +152,11 @@ package com.junkbyte.console.core } public function getChannels():Array{ - var arr:Array = new Array(Console.GLOBAL_CHANNEL); - addIfexist(Console.DEFAULT_CHANNEL, arr); - addIfexist(Console.FILTER_CHANNEL, arr); + var arr:Array = new Array(ConsoleChannel.GLOBAL_CHANNEL); + addIfexist(ConsoleChannel.DEFAULT_CHANNEL, arr); + addIfexist(ConsoleChannel.FILTER_CHANNEL, arr); addIfexist(LogReferences.INSPECTING_CHANNEL, arr); - addIfexist(Console.CONSOLE_CHANNEL, arr); + addIfexist(ConsoleChannel.CONSOLE_CHANNEL, arr); var others:Array = new Array(); for(var X:String in _channels){ if(arr.indexOf(X)<0) others.push(X); diff --git a/src/com/junkbyte/console/core/MemoryMonitor.as b/src/com/junkbyte/console/core/MemoryMonitor.as index 30563a8..cd1791c 100644 --- a/src/com/junkbyte/console/core/MemoryMonitor.as +++ b/src/com/junkbyte/console/core/MemoryMonitor.as @@ -25,7 +25,7 @@ package com.junkbyte.console.core { import com.junkbyte.console.Console; - + import flash.system.System; import flash.utils.Dictionary; import flash.utils.getQualifiedClassName; @@ -107,26 +107,17 @@ package com.junkbyte.console.core } public function gc():void { - if(remoter.remoting == Remoting.RECIEVER){ - try{ - //report("Sending garbage collection request to client",-1); - remoter.send("gc"); - }catch(e:Error){ - report(e,10); + var ok:Boolean; + try{ + // have to put in brackes cause some compilers will complain. + if(System["gc"] != null){ + System["gc"](); + ok = true; } - }else{ - var ok:Boolean; - try{ - // have to put in brackes cause some compilers will complain. - if(System["gc"] != null){ - System["gc"](); - ok = true; - } - }catch(e:Error){ } - - var str:String = "Manual garbage collection "+(ok?"successful.":"FAILED. You need debugger version of flash player."); - report(str,(ok?-1:10)); - } + }catch(e:Error){ } + + var str:String = "Manual garbage collection "+(ok?"successful.":"FAILED. You need debugger version of flash player."); + report(str,(ok?-1:10)); } } } \ No newline at end of file diff --git a/src/com/junkbyte/console/core/Remoting.as b/src/com/junkbyte/console/core/Remoting.as index b9beda6..d4876be 100644 --- a/src/com/junkbyte/console/core/Remoting.as +++ b/src/com/junkbyte/console/core/Remoting.as @@ -1,11 +1,11 @@ /* -* +* * Copyright (c) 2008-2010 Lu Aye Oo -* +* * @author Lu Aye Oo -* +* * http://code.google.com/p/flash-console/ -* +* * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -20,11 +20,12 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. -* +* */ -package com.junkbyte.console.core +package com.junkbyte.console.core { import com.junkbyte.console.Console; + import com.junkbyte.console.ConsoleLevel; import flash.events.AsyncErrorEvent; import flash.events.Event; @@ -38,229 +39,308 @@ package com.junkbyte.console.core import flash.utils.ByteArray; import flash.utils.Dictionary; - [Event(name="CONNECT", type="flash.events.Event")] + [Event(name = "connect", type = "flash.events.Event")] /** * @private */ - public class Remoting extends ConsoleCore{ - - public static const NONE:uint = 0; - public static const SENDER:uint = 1; - public static const RECIEVER:uint = 2; - - private var _callbacks:Object = new Object(); - private var _mode:uint; - private var _local:LocalConnection; - private var _socket:Socket; - private var _sendBuffer:ByteArray = new ByteArray(); - private var _recBuffers:Object = new Object(); - private var _senders:Dictionary = new Dictionary(); - - private var _lastLogin:String = ""; - private var _loggedIn:Boolean; - - private var _sendID:String; - private var _lastReciever:String; - - public function Remoting(m:Console) { + public class Remoting extends ConsoleCore + { + + protected var _callbacks:Object = new Object(); + protected var _remoting:Boolean; + protected var _local:LocalConnection; + protected var _socket:Socket; + protected var _sendBuffer:ByteArray = new ByteArray(); + protected var _recBuffers:Object = new Object(); + protected var _senders:Dictionary = new Dictionary(); + + protected var _loggedIn:Boolean; + + protected var _selfId:String; + protected var _lastRecieverId:String; + + public function Remoting(m:Console) + { super(m); - registerCallback("login", function(bytes:ByteArray):void{ + registerCallback("login", function(bytes:ByteArray):void { login(bytes.readUTF()); }); - registerCallback("requestLogin", requestLogin); - registerCallback("loginFail", loginFail); - registerCallback("loginSuccess", loginSuccess); } - public function update():void{ - if(_sendBuffer.length){ - if(_socket && _socket.connected){ + + public function update():void + { + if (_sendBuffer.length) + { + if (_socket && _socket.connected) + { _socket.writeBytes(_sendBuffer); //_socket.flush(); _sendBuffer = new ByteArray(); - }else if(_local){ + } + else if (_local) + { var packet:ByteArray; - _sendBuffer.position = 0; - if(_sendBuffer.bytesAvailable < 38000){ + _sendBuffer.position = 0; + if (_sendBuffer.bytesAvailable < 38000) + { packet = _sendBuffer; _sendBuffer = new ByteArray(); - }else{ + } + else + { packet = new ByteArray(); _sendBuffer.readBytes(packet, 0, Math.min(38000, _sendBuffer.bytesAvailable)); var newbuffer:ByteArray = new ByteArray(); _sendBuffer.readBytes(newbuffer); _sendBuffer = newbuffer; } - var target:String = config.remotingConnectionName+(remoting == Remoting.RECIEVER?SENDER:RECIEVER); - _local.send(target, "synchronize", _sendID, packet); - }else{ + _local.send(remoteLocalConnectionName, "synchronize", _selfId, packet); + } + else + { _sendBuffer = new ByteArray(); } } - for (var id:String in _recBuffers){ + for (var id:String in _recBuffers) + { processRecBuffer(id); } } + protected function get selfLlocalConnectionName():String + { + return config.remotingConnectionName + "Sender"; + } + + protected function get remoteLocalConnectionName():String + { + return config.remotingConnectionName + "Receiver"; + } + private function processRecBuffer(id:String):void { - if(!_senders[id]){ + if (!_senders[id]) + { _senders[id] = true; - if(_lastReciever){ - report("Remote switched to new sender ["+id+"] as primary.", -2); + if (_lastRecieverId) + { + report("Switched to [" + id + "] as primary remote.", -2); } - _lastReciever = id; + _lastRecieverId = id; } - + var buffer:ByteArray = _recBuffers[id]; - try{ + try + { var pointer:uint = buffer.position = 0; - while(buffer.bytesAvailable){ - var cmd:String = buffer.readUTF(); + while (buffer.bytesAvailable) + { + var cmdlen:uint = buffer.readByte(); + if (buffer.bytesAvailable == 0) + { + break; + } + var cmd:String = buffer.readUTFBytes(cmdlen); var arg:ByteArray = null; - if(buffer.bytesAvailable == 0) break; - if(buffer.readBoolean()){ - if(buffer.bytesAvailable == 0) break; + if (buffer.bytesAvailable == 0) + { + break; + } + if (buffer.readBoolean()) + { + if (buffer.bytesAvailable == 0) + { + break; + } var blen:uint = buffer.readUnsignedInt(); - if(buffer.bytesAvailable < blen) break; + if (buffer.bytesAvailable < blen) + { + break; + } arg = new ByteArray(); buffer.readBytes(arg, 0, blen); } var callbackData:Object = _callbacks[cmd]; - if(!callbackData.latest || id == _lastReciever){ - if(arg) callbackData.fun(arg); - else callbackData.fun(); + if (callbackData == null) + { + report("Unknown remote commmand received [" + cmd + "].", ConsoleLevel.ERROR); + } + else if (!callbackData.latest || id == _lastRecieverId) + { + if (arg) + { + callbackData.fun(arg); + } + else + { + callbackData.fun(); + } } pointer = buffer.position; } - if(pointer < buffer.length){ + if (pointer < buffer.length) + { var recbuffer:ByteArray = new ByteArray(); recbuffer.writeBytes(buffer, pointer); _recBuffers[id] = buffer = recbuffer; - }else{ + } + else + { delete _recBuffers[id]; } - }catch(err:Error){ - report("Remoting sync error: "+err, 9); + } + catch (err:Error) + { + report("Remoting sync error: " + err, 9); } } - - private function synchronize(id:String, obj:Object):void{ - if(!(obj is ByteArray)){ - report("Remoting sync error. Recieved non-ByteArray:"+obj, 9); + private function synchronize(id:String, obj:Object):void + { + var packet:ByteArray = obj as ByteArray; + if (packet == null) + { + report("Remoting sync error. Recieved non-ByteArray:" + obj, 9); return; } - var packet:ByteArray = obj as ByteArray; var buffer:ByteArray = _recBuffers[id]; - if(buffer){ + if (buffer) + { buffer.position = buffer.length; buffer.writeBytes(packet); - }else{ + } + else + { _recBuffers[id] = packet; } } - public function send(command:String, arg:ByteArray = null):Boolean{ - if(_mode == NONE) return false; + + public function send(command:String, arg:ByteArray = null):Boolean + { + if (!_remoting) + { + return false; + } _sendBuffer.position = _sendBuffer.length; - _sendBuffer.writeUTF(command); - if(arg){ + _sendBuffer.writeByte(command.length); + _sendBuffer.writeUTFBytes(command); + if (arg) + { _sendBuffer.writeBoolean(true); _sendBuffer.writeUnsignedInt(arg.length); _sendBuffer.writeBytes(arg); - }else{ + } + else + { _sendBuffer.writeBoolean(false); } return true; } - public function get remoting():uint{ - return _mode; + + public function get connected():Boolean + { + return _remoting && _loggedIn; } - public function get canSend():Boolean{ - return _mode == SENDER && _loggedIn; + + public function get remoting():Boolean + { + return _remoting; } - public function set remoting(newMode:uint):void{ - if(newMode == _mode) return; - _sendID = generateId(); - if(newMode == SENDER){ - if(!startSharedConnection(SENDER)){ - report("Could not create remoting client service. You will not be able to control this console with remote.", 10); - } - _sendBuffer = new ByteArray(); - _local.addEventListener(StatusEvent.STATUS, onSenderStatus, false, 0, true); - report("Remoting started. "+getInfo(),-1); - _loggedIn = checkLogin(""); - if(_loggedIn){ - sendLoginSuccess(); - }else{ - send("requestLogin"); - } - }else if(newMode == RECIEVER){ - if(startSharedConnection(RECIEVER)){ - _sendBuffer = new ByteArray(); - _local.addEventListener(AsyncErrorEvent.ASYNC_ERROR , onRemoteAsyncError, false, 0, true); - _local.addEventListener(StatusEvent.STATUS, onRecieverStatus, false, 0, true); - report("Remote started. "+getInfo(),-1); - var sdt:String = Security.sandboxType; - if(sdt == Security.LOCAL_WITH_FILE || sdt == Security.LOCAL_WITH_NETWORK){ - report("Untrusted local sandbox. You may not be able to listen for logs properly.", 10); - printHowToGlobalSetting(); - } - login(_lastLogin); - }else{ - report("Could not create remote service. You might have a console remote already running.", 10); - } - }else{ + + public function set remoting(newMode:Boolean):void + { + if (newMode == _remoting) + { + return; + } + _selfId = generateId(); + if (newMode) + { + startRemoting(); + } + else + { close(); } console.panels.updateMenu(); } - public function remotingSocket(host:String, port:int = 0):void{ - if(_socket && _socket.connected){ + + protected function startRemoting():void + { + if (!startLocalConnection()) + { + report("Could not create remoting client service.", 10); + return; + } + _sendBuffer = new ByteArray(); + report("Remoting started. " + getInfo(), -1); + send("started"); + } + + public function remotingSocket(host:String, port:int = 0):void + { + if (_socket && _socket.connected) + { _socket.close(); _socket = null; } - if(host && port) + if (host && port) { - remoting = SENDER; + remoting = true; report("Connecting to socket " + host + ":" + port); _socket = new Socket(); - _socket.addEventListener(Event.CLOSE, socketCloseHandler); - _socket.addEventListener(Event.CONNECT, socketConnectHandler); - _socket.addEventListener(IOErrorEvent.IO_ERROR, socketIOErrorHandler); - _socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socketSecurityErrorHandler); - _socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler); - _socket.connect(host, port); + _socket.addEventListener(Event.CLOSE, socketCloseHandler); + _socket.addEventListener(Event.CONNECT, socketConnectHandler); + _socket.addEventListener(IOErrorEvent.IO_ERROR, socketIOErrorHandler); + _socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socketSecurityErrorHandler); + _socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler); + _socket.connect(host, port); } } - private function socketCloseHandler(e:Event) : void { - if(e.currentTarget == _socket){ + private function socketCloseHandler(e:Event):void + { + if (e.currentTarget == _socket) + { _socket = null; } } - private function socketConnectHandler(e:Event) : void { + + private function socketConnectHandler(e:Event):void + { report("Remoting socket connected.", -1); _sendBuffer = new ByteArray(); - if(_loggedIn || checkLogin("")){ + if (_loggedIn || checkLogin("")) + { sendLoginSuccess(); - }else{ - send("requestLogin"); } - // not needed yet + else + { + send("loginRequest"); + } } - private function socketIOErrorHandler(e:Event) : void { + + private function socketIOErrorHandler(e:Event):void + { report("Remoting socket error." + e, 9); remotingSocket(null); } - private function socketSecurityErrorHandler(e:Event) : void { + + private function socketSecurityErrorHandler(e:Event):void + { report("Remoting security error." + e, 9); remotingSocket(null); } - private function socketDataHandler(e:Event) : void { + + private function socketDataHandler(e:Event):void + { handleSocket(e.currentTarget as Socket); } - public function handleSocket(socket:Socket):void{ - if(!_senders[socket]){ + + public function handleSocket(socket:Socket):void + { + if (!_senders[socket]) + { _senders[socket] = generateId(); _socket = socket; } @@ -268,115 +348,120 @@ package com.junkbyte.console.core socket.readBytes(bytes); synchronize(_senders[socket], bytes); } - private function onSenderStatus(e:StatusEvent):void{ - if(e.level == "error" && !(_socket && _socket.connected)) { + + protected function onLocalConnectionStatus(e:StatusEvent):void + { + if (e.level == "error" && _loggedIn && !(_socket && _socket.connected)) + { + report("Remote connection lost.", ConsoleLevel.ERROR); _loggedIn = false; } } - private function onRecieverStatus(e:StatusEvent):void{ - if(remoting == Remoting.RECIEVER && e.level=="error"){ - report("Problem communicating to client.", 10); - } + + protected function onRemoteAsyncError(e:AsyncErrorEvent):void + { + report("Problem with remote sync. [Click here] to restart.", 10); + remoting = false; } - private function onRemotingSecurityError(e:SecurityErrorEvent):void{ + + protected function onRemotingSecurityError(e:SecurityErrorEvent):void + { report("Remoting security error.", 9); printHowToGlobalSetting(); } - private function onRemoteAsyncError(e:AsyncErrorEvent):void{ - report("Problem with remote sync. [Click here] to restart.", 10); - remoting = NONE; - } - - private function getInfo():String{ - return "channel:"+config.remotingConnectionName+" ("+Security.sandboxType+")"; + + protected function getInfo():String + { + return "channel:" + config.remotingConnectionName + " (" + Security.sandboxType + ")"; } - - private function printHowToGlobalSetting():void{ + + protected function printHowToGlobalSetting():void + { report("Make sure your flash file is 'trusted' in Global Security Settings.", -2); - report("Go to Settings Manager [click here] > 'Global Security Settings Panel' (on left) > add the location of the local flash (swf) file.", -2); + report("Go to Settings Manager [click here] > 'Global Security Settings Panel' > add the location of the local flash (swf) file.", -2); } - - private function generateId():String{ - return new Date().time+"."+Math.floor(Math.random()*100000); + + protected function generateId():String + { + return new Date().time + "." + Math.floor(Math.random() * 100000); } - private function startSharedConnection(targetmode:uint):Boolean{ + + protected function startLocalConnection():Boolean + { close(); - _mode = targetmode; + _remoting = true; _local = new LocalConnection(); - _local.client = {synchronize:synchronize}; - if(config.allowedRemoteDomain){ + _local.client = {synchronize: synchronize}; + if (config.allowedRemoteDomain) + { _local.allowDomain(config.allowedRemoteDomain); _local.allowInsecureDomain(config.allowedRemoteDomain); } - _local.addEventListener(SecurityErrorEvent.SECURITY_ERROR , onRemotingSecurityError, false, 0, true); - - try{ - _local.connect(config.remotingConnectionName+_mode); - }catch(err:Error){ + _local.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onRemotingSecurityError, false, 0, true); + _local.addEventListener(StatusEvent.STATUS, onLocalConnectionStatus, false, 0, true); + _local.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onRemoteAsyncError, false, 0, true); + + try + { + _local.connect(selfLlocalConnectionName); + } + catch (err:Error) + { + _remoting = false; + _local = null; return false; } return true; } - public function registerCallback(key:String, fun:Function, latestOnly:Boolean = false):void{ - _callbacks[key] = {fun:fun, latest:latestOnly}; - } - private function loginFail():void{ - if(remoting != Remoting.RECIEVER) return; - report("Login Failed", 10); - console.panels.mainPanel.requestLogin(); + + public function registerCallback(key:String, fun:Function, lastestSenderOnly:Boolean = false):void + { + _callbacks[key] = {fun: fun, latest: lastestSenderOnly}; } - private function sendLoginSuccess():void{ + + private function sendLoginSuccess():void + { _loggedIn = true; send("loginSuccess"); dispatchEvent(new Event(Event.CONNECT)); } - private function loginSuccess():void{ - console.setViewingChannels(); - report("Login Successful", -1); - } - private function requestLogin():void{ - if(remoting != Remoting.RECIEVER) return; - _sendBuffer = new ByteArray(); - if(_lastLogin){ - login(_lastLogin); - }else{ - console.panels.mainPanel.requestLogin(); + + public function login(pass:String = ""):void + { + if (_loggedIn || checkLogin(pass)) + { + sendLoginSuccess(); } - } - public function login(pass:String = ""):void{ - if(remoting == Remoting.RECIEVER){ - _lastLogin = pass; - report("Attempting to login...", -1); - var bytes:ByteArray = new ByteArray(); - bytes.writeUTF(pass); - send("login", bytes); - }else{ - // once logged in, next login attempts will always be success - if(_loggedIn || checkLogin(pass)){ - sendLoginSuccess(); - }else{ - send("loginFail"); - } + else + { + send("loginFail"); } } - private function checkLogin(pass : String) : Boolean { - return ((config.remotingPassword === null && config.keystrokePassword == pass) - || config.remotingPassword === "" - || config.remotingPassword == pass + private function checkLogin(pass:String):Boolean + { + return ((config.remotingPassword === null && config.keystrokePassword == pass) + || config.remotingPassword === "" + || config.remotingPassword == pass ); } - public function close():void{ - if(_local){ - try{ + + public function close():void + { + if (_local) + { + try + { _local.close(); - }catch(error:Error){ - report("Remote.close: "+error, 10); + } + catch (error:Error) + { + report("Remote.close: " + error, 10); } } - _mode = NONE; + _remoting = false; _sendBuffer = new ByteArray(); _local = null; } } -} \ No newline at end of file +} diff --git a/src/com/junkbyte/console/remote/CommandLineRemote.as b/src/com/junkbyte/console/remote/CommandLineRemote.as new file mode 100644 index 0000000..1c5bfbf --- /dev/null +++ b/src/com/junkbyte/console/remote/CommandLineRemote.as @@ -0,0 +1,54 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.core.CommandLine; + + import flash.events.Event; + import flash.utils.ByteArray; + + public class CommandLineRemote extends CommandLine + { + public function CommandLineRemote(m:Console) + { + super(m); + remoter.registerCallback("cls", handleScopeString); + } + + override public function sendCmdScope2Remote(e:Event = null):void{ + } + override public function run(str:String, saves:Object = null, canThrowError:Boolean = false):* + { + if (!str) + { + return; + } + str = str.replace(/\s*/, ""); + + if (str.charAt(0) == "~") + { + str = str.substring(1); + super.run(str, saves); + } + else if (str.search(new RegExp("\/" + localCommands.join("|\/"))) != 0) + { + report("Run command at remote: " + str, -2); + + var bytes:ByteArray = new ByteArray(); + bytes.writeUTF(str); + if (!console.remoter.send("cmd", bytes)) + { + report("Command could not be sent to client.", 10); + } + } + } + public function handleScopeString(bytes:ByteArray):void{ + _scopeStr = bytes.readUTF(); + } + + override public function handleScopeEvent(id:uint):void{ + var bytes:ByteArray = new ByteArray(); + bytes.writeUnsignedInt(id); + remoter.send("scope", bytes); + } + } +} diff --git a/src/com/junkbyte/console/remote/ConsoleRe.as b/src/com/junkbyte/console/remote/ConsoleRe.as new file mode 100644 index 0000000..acda4bb --- /dev/null +++ b/src/com/junkbyte/console/remote/ConsoleRe.as @@ -0,0 +1,36 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.ConsoleConfig; + import com.junkbyte.console.core.CommandLine; + import com.junkbyte.console.core.ConsoleTools; + import com.junkbyte.console.core.KeyBinder; + import com.junkbyte.console.core.LogReferences; + import com.junkbyte.console.core.Logs; + import com.junkbyte.console.core.MemoryMonitor; + import com.junkbyte.console.core.Remoting; + + public class ConsoleRe extends Console + { + public function ConsoleRe(password:String = "", config:ConsoleConfig = null) + { + super(password, config); + + _config.displayRollerEnabled = false; + } + + override protected function initModules():void + { + _remoter = new RemotingRemote(this); + _logs = new LogsRemote(this); + _refs = new LogReferencesRemote(this); + _cl = new CommandLineRemote(this); + _tools = new ConsoleTools(this); + _graphing = new GraphingRemote(this); + _mm = new MemoryMonitorRemote(this); + _kb = new KeyBinder(this); + + _panels = new PanelsManagerRemote(this); + } + } +} diff --git a/src/com/junkbyte/console/remote/GraphingRemote.as b/src/com/junkbyte/console/remote/GraphingRemote.as new file mode 100644 index 0000000..8150e01 --- /dev/null +++ b/src/com/junkbyte/console/remote/GraphingRemote.as @@ -0,0 +1,136 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.console_internal; + import com.junkbyte.console.core.Graphing; + import com.junkbyte.console.vos.GraphGroup; + + import flash.events.Event; + import flash.utils.ByteArray; + + use namespace console_internal; + + public class GraphingRemote extends Graphing + { + + private var _closingFromRemoter:Boolean; + + public function GraphingRemote(m:Console) + { + super(m); + + remoter.registerCallback("graphGroups", onRemotingGraphGroups, true); + remoter.registerCallback("addGraphGroup", onRemotingAddGraphGroup, true); + remoter.registerCallback("removeGraphGroup", onRemotingRemoveGraphGroup, true); + remoter.registerCallback("updateGraphGroup", onRemotingUpdateGraphGroup, true); + } + + override protected function onRemoteConnection(event:Event):void + { + _closingFromRemoter = true; + while (_groups.length) + { + GraphGroup(_groups[0]).close(); + } + _closingFromRemoter = false; + } + + override public function update(timeDelta:uint):void + { + + } + + override protected function syncRemoveGroup(index:int):void + { + if (!_closingFromRemoter) + { + super.syncRemoveGroup(index); + } + } + + override protected function syncAddGroup(group:GraphGroup):void + { + + } + + override protected function syncGroupUpdate(group:GraphGroup, values:Array):void + { + + } + + override protected function onRemotingRemoveGraphGroup(bytes:ByteArray):void + { + _closingFromRemoter = true; + super.onRemotingRemoveGraphGroup(bytes); + _closingFromRemoter = false; + } + + private function onRemotingGraphGroups(bytes:ByteArray):void + { + var count:uint = bytes.readShort(); + _groups = new Array(); + for (var i:uint = 0; i < count; i++) + { + addGroup(GraphGroup.FromBytes(bytes)); + } + } + + private function onRemotingAddGraphGroup(bytes:ByteArray):void + { + var group:GraphGroup = GraphGroup.FromBytes(bytes); + + addGroup(group); + + group.onMenu.add(function (menukey:String):void + { + var index:int = _groups.indexOf(group); + if (index >= 0) + { + syncMenuGroup(index, menukey); + } + } + ); + } + + private function onRemotingUpdateGraphGroup(bytes:ByteArray):void + { + var index:uint = bytes.readShort(); + var group:GraphGroup = _groups[index]; + if (group) + { + var values:Array = new Array(); + while (bytes.bytesAvailable) + { + values.push(bytes.readDouble()); + } + group.applyUpdateDispather(values); + } + } + + override public function set fpsMonitor(b:Boolean):void + { + var bytes:ByteArray = new ByteArray(); + bytes.writeBoolean(b); + remoter.send("fps", bytes); + } + + override public function set memoryMonitor(b:Boolean):void + { + var bytes:ByteArray = new ByteArray(); + bytes.writeBoolean(b); + remoter.send("mem", bytes); + } + + + protected function syncMenuGroup(groupIndex:int, menuKey:String):void + { + if (remoter.connected) + { + var bytes:ByteArray = new ByteArray(); + bytes.writeShort(groupIndex); + bytes.writeUTF(menuKey); + remoter.send("menuGraphGroup", bytes); + } + } + } +} diff --git a/src/com/junkbyte/console/remote/LogReferencesRemote.as b/src/com/junkbyte/console/remote/LogReferencesRemote.as new file mode 100644 index 0000000..7b989db --- /dev/null +++ b/src/com/junkbyte/console/remote/LogReferencesRemote.as @@ -0,0 +1,23 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.core.LogReferences; + + import flash.utils.ByteArray; + + public class LogReferencesRemote extends LogReferences + { + public function LogReferencesRemote(console:Console) + { + super(console); + } + override public function handleRefEvent(str:String):void{ + var bytes:ByteArray = new ByteArray(); + bytes.writeUTF(str); + remoter.send("ref", bytes); + } + override public function exitFocus():void{ + + } + } +} \ No newline at end of file diff --git a/src/com/junkbyte/console/remote/LogsRemote.as b/src/com/junkbyte/console/remote/LogsRemote.as new file mode 100644 index 0000000..5d34e5c --- /dev/null +++ b/src/com/junkbyte/console/remote/LogsRemote.as @@ -0,0 +1,25 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.core.Logs; + import com.junkbyte.console.vos.Log; + + import flash.utils.ByteArray; + + public class LogsRemote extends Logs + { + public function LogsRemote(console:Console) + { + super(console); + remoter.registerCallback("log", onRemotingLog); + } + + private function onRemotingLog(bytes:ByteArray):void + { + registerLog(Log.FromBytes(bytes)); + } + override protected function send2Remote(line:Log):void{ + + } + } +} diff --git a/src/com/junkbyte/console/remote/MainPanelRemote.as b/src/com/junkbyte/console/remote/MainPanelRemote.as new file mode 100644 index 0000000..8a93ced --- /dev/null +++ b/src/com/junkbyte/console/remote/MainPanelRemote.as @@ -0,0 +1,30 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.core.Remoting; + import com.junkbyte.console.view.MainPanel; + + import flash.events.Event; + import flash.events.TextEvent; + + public class MainPanelRemote extends MainPanel + { + public function MainPanelRemote(m:Console) + { + super(m); + } + + override protected function updateCmdHint(e:Event = null):void{ + + + } + + override protected function linkHandler(e:TextEvent):void{ + super.linkHandler(e); + if(e.text == "remote") + { + console.remoter.remoting = true; + } + } + } +} \ No newline at end of file diff --git a/src/com/junkbyte/console/remote/MemoryMonitorRemote.as b/src/com/junkbyte/console/remote/MemoryMonitorRemote.as new file mode 100644 index 0000000..804eb1e --- /dev/null +++ b/src/com/junkbyte/console/remote/MemoryMonitorRemote.as @@ -0,0 +1,22 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.core.MemoryMonitor; + + public class MemoryMonitorRemote extends MemoryMonitor + { + public function MemoryMonitorRemote(m:Console) + { + super(m); + } + + override public function gc():void { + try{ + report("Sending garbage collection request to client",-1); + remoter.send("gc"); + }catch(e:Error){ + report(e,10); + } + } + } +} \ No newline at end of file diff --git a/src/com/junkbyte/console/remote/PanelsManagerRemote.as b/src/com/junkbyte/console/remote/PanelsManagerRemote.as new file mode 100644 index 0000000..877b9c1 --- /dev/null +++ b/src/com/junkbyte/console/remote/PanelsManagerRemote.as @@ -0,0 +1,19 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.view.MainPanel; + import com.junkbyte.console.view.PanelsManager; + + public class PanelsManagerRemote extends PanelsManager + { + public function PanelsManagerRemote(master:Console) + { + super(master); + } + + override protected function createMainPanel():MainPanel + { + return new MainPanelRemote(console); + } + } +} \ No newline at end of file diff --git a/src/com/junkbyte/console/remote/RemotingRemote.as b/src/com/junkbyte/console/remote/RemotingRemote.as new file mode 100644 index 0000000..9449306 --- /dev/null +++ b/src/com/junkbyte/console/remote/RemotingRemote.as @@ -0,0 +1,107 @@ +package com.junkbyte.console.remote +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.core.Remoting; + + import flash.events.AsyncErrorEvent; + import flash.events.Event; + import flash.events.StatusEvent; + import flash.system.Security; + import flash.utils.ByteArray; + + public class RemotingRemote extends Remoting + { + + protected var _lastLogin:String = ""; + + public function RemotingRemote(m:Console) + { + super(m); + registerCallback("started", clientStarted); + registerCallback("loginRequest", requestLogin); + registerCallback("loginFail", loginFail); + registerCallback("loginSuccess", loginSuccess); + } + + private function loginFail():void + { + report("Login Failed", 10); + + console.panels.mainPanel.requestLogin(); + } + + private function loginSuccess():void + { + _loggedIn = true; + console.setViewingChannels(); + report("Login Successful", -1); + dispatchEvent(new Event(Event.CONNECT)); + } + + private function clientStarted():void + { + login(_lastLogin); + } + + private function requestLogin():void + { + _sendBuffer = new ByteArray(); + if (_lastLogin) + { + login(_lastLogin); + } + else + { + console.panels.mainPanel.requestLogin(); + } + } + + override public function login(pass:String = ""):void + { + _lastLogin = pass; + report("Attempting to login...", -1); + var bytes:ByteArray = new ByteArray(); + bytes.writeUTF(pass); + send("login", bytes); + } + + override protected function startRemoting():void + { + if (startLocalConnection()) + { + _sendBuffer = new ByteArray(); + _local.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onRemoteAsyncError, false, 0, true); + report("Remote started. " + getInfo(), -1); + var sdt:String = Security.sandboxType; + if (sdt == Security.LOCAL_WITH_FILE || sdt == Security.LOCAL_WITH_NETWORK) + { + report("Untrusted local sandbox. You may not be able to listen for logs properly.", 10); + printHowToGlobalSetting(); + } + login(_lastLogin); + } + else + { + report("Could not create remote service. You might have a console remote already running.", 10); + } + } + + override protected function get selfLlocalConnectionName():String + { + return super.remoteLocalConnectionName; + } + + override protected function get remoteLocalConnectionName():String + { + return super.selfLlocalConnectionName; + } + + override protected function onLocalConnectionStatus(e:StatusEvent):void + { + if (e.level == "error") + { + report("Problem communicating to client.", 10); + } + } + } +} diff --git a/src/com/junkbyte/console/view/ConsolePanel.as b/src/com/junkbyte/console/view/ConsolePanel.as index 6118566..48fc86c 100644 --- a/src/com/junkbyte/console/view/ConsolePanel.as +++ b/src/com/junkbyte/console/view/ConsolePanel.as @@ -63,7 +63,7 @@ package com.junkbyte.console.view { [Event(name="visibilityChanged", type="flash.events.Event")] /** - * Dispatched when started dragging + * Dispatched when closed */ [Event(name="close", type="flash.events.Event")] diff --git a/src/com/junkbyte/console/view/GraphingPanel.as b/src/com/junkbyte/console/view/GraphingPanel.as index 4f6ca9a..51a2df3 100644 --- a/src/com/junkbyte/console/view/GraphingPanel.as +++ b/src/com/junkbyte/console/view/GraphingPanel.as @@ -1,11 +1,11 @@ /* -* +* * Copyright (c) 2008-2010 Lu Aye Oo -* +* * @author Lu Aye Oo -* +* * http://code.google.com/p/flash-console/ -* +* * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -20,47 +20,51 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. -* +* */ -package com.junkbyte.console.view { +package com.junkbyte.console.view +{ import com.junkbyte.console.Console; import com.junkbyte.console.vos.GraphGroup; import com.junkbyte.console.vos.GraphInterest; - import flash.display.Graphics; - import flash.display.Shape; + import flash.display.Bitmap; + import flash.display.BitmapData; + import flash.display.StageAlign; import flash.events.TextEvent; + import flash.geom.Matrix; + import flash.geom.Rectangle; import flash.text.TextField; import flash.text.TextFormat; - + /** * @private */ - public class GraphingPanel extends ConsolePanel { - // - public static const FPS:String = "fpsPanel"; - public static const MEM:String = "memoryPanel"; + public class GraphingPanel extends ConsolePanel + { // private var _group:GraphGroup; private var _interest:GraphInterest; - private var _infoMap:Object = new Object(); - + private var _menuString:String; // - private var _type:String; - // - private var _needRedraw:Boolean; - // - private var underlay:Shape; - private var graph:Shape; + protected var _bm:Bitmap; + protected var _bmd:BitmapData; + + protected var lowestValue:Number; + protected var highestValue:Number; + protected var lastValues:Object = new Object(); + private var lowTxt:TextField; private var highTxt:TextField; + private var lineRect:Rectangle = new Rectangle(0, 0, 1); + // - public var startOffset:int = 5; - // - public function GraphingPanel(m:Console, W:int, H:int, type:String = null) { + public function GraphingPanel(m:Console, group:GraphGroup) + { super(m); - _type = type; + _group = group; + name = group.name; registerDragger(bg); minWidth = 32; minHeight = 26; @@ -71,240 +75,340 @@ package com.junkbyte.console.view { textFormat.size = lowStyle.fontSize; textFormat.color = style.lowColor; + _bm = new Bitmap(); + _bm.name = "graph"; + _bm.y = style.menuFontSize - 2; + addChild(_bm); + lowTxt = new TextField(); lowTxt.name = "lowestField"; lowTxt.defaultTextFormat = textFormat; lowTxt.mouseEnabled = false; - lowTxt.height = style.menuFontSize+2; + lowTxt.height = style.menuFontSize + 2; addChild(lowTxt); - + highTxt = new TextField(); highTxt.name = "highestField"; highTxt.defaultTextFormat = textFormat; highTxt.mouseEnabled = false; - highTxt.height = style.menuFontSize+2; - highTxt.y = style.menuFontSize-4; + highTxt.height = style.menuFontSize + 2; + highTxt.y = style.menuFontSize - 4; addChild(highTxt); // txtField = makeTF("menuField"); - txtField.height = style.menuFontSize+4; + txtField.height = style.menuFontSize + 4; txtField.y = -3; registerTFRoller(txtField, onMenuRollOver, linkHandler); registerDragger(txtField); // so that we can still drag from textfield addChild(txtField); // - underlay = new Shape(); - addChild(underlay); - // - graph = new Shape(); - graph.name = "graph"; - graph.y = style.menuFontSize; - addChild(graph); - // - _menuString = ""; - if(_type == MEM){ - _menuString += " G "; - } - _menuString += "R X"; + setMenuString(); + _group.onUpdate.add(onGroupUpdate); // - init(W,H,true); - } - private function stop():void { - if(_group) console.graphing.remove(_group.name); - } - public function get group():GraphGroup{ - return _group; - } - public function reset():void{ - _infoMap = {}; - graph.graphics.clear(); - if(!_group.fixed) + var rect:Rectangle = group.rect; + var w:Number = Math.max(minWidth, rect.width); + var h:Number = Math.max(minHeight, rect.height); + var mainPanel:MainPanel = console.panels.mainPanel; + x = mainPanel.x+rect.x; + y = mainPanel.y+rect.y; + if(group.alignRight) { - _group.low = NaN; - _group.hi = NaN; + x = mainPanel.x+mainPanel.width-x; } + + init(w, h, true); } - /*public function set showKeyText(b:Boolean):void{ - keyTxt.visible = b; + + public function get group():GraphGroup + { + return _group; } - public function get showKeyText():Boolean{ - return keyTxt.visible; + + public function reset():void + { + lowestValue = highestValue = NaN; + lastValues = new Object(); } - public function set showBoundsText(b:Boolean):void{ - lowTxt.visible = b; - highTxt.visible = b; + + protected function setMenuString():void + { + _menuString = ""; + var menus:Array = _group.menus.concat("R", "X"); + for each(var menu:String in menus) + { + _menuString += " "+menu+""; + } + _menuString += ""; } - public function get showBoundsText():Boolean{ - return lowTxt.visible; - }*/ - override public function set height(n:Number):void{ + + override public function set height(n:Number):void + { super.height = n; - lowTxt.y = n-style.menuFontSize; - _needRedraw = true; - - var g:Graphics = underlay.graphics; - g.clear(); - g.lineStyle(1,style.controlColor, 0.6); - g.moveTo(0, graph.y); - g.lineTo(width-startOffset, graph.y); - g.lineTo(width-startOffset, n); + lowTxt.y = n - style.menuFontSize; + + resizeBMD(); } - override public function set width(n:Number):void{ + + override public function set width(n:Number):void + { super.width = n; lowTxt.width = n; highTxt.width = n; txtField.width = n; txtField.scrollH = txtField.maxScrollH; - graph.graphics.clear(); - _needRedraw = true; + + resizeBMD(); } - // - // - // - public function update(group:GraphGroup, draw:Boolean):void{ - _group = group; - var push:int = 1; // 0 = no push, 1 = 1 push, 2 = push all - if(group.idle>0){ - push = 0; - if(!_needRedraw) return; + + private function resizeBMD():void + { + var w:Number = width; + var h:Number = height - style.menuFontSize + 2; + if (_bmd != null && _bmd.width == w && _bmd.height == h) + { + return; } - if(_needRedraw) draw = true; - _needRedraw = false; - var interests:Array = group.interests; - var W:int = width-startOffset; - var H:int = height-graph.y; - var lowest:Number = group.low; - var highest:Number = group.hi; - var diffGraph:Number = highest-lowest; - var listchanged:Boolean = false; - if(draw) { - TextField(group.inv?highTxt:lowTxt).text = String(group.low); - TextField(group.inv?lowTxt:highTxt).text = String(group.hi); - graph.graphics.clear(); + var prevBMD:BitmapData = _bmd; + _bmd = new BitmapData(w, h, true, 0); + if (prevBMD != null) + { + var matrix:Matrix = new Matrix(1, 0, 0, _bmd.height / prevBMD.height); + matrix.tx = _bmd.width - prevBMD.width; + _bmd.draw(prevBMD, matrix, null, null, null, true); + prevBMD.dispose(); } + _bm.bitmapData = _bmd; + } + + protected function onGroupUpdate(values:Array):void + { + var interests:Array = _group.interests; + var listchanged:Boolean = false; var interest:GraphInterest; - for each(interest in interests){ - _interest = interest; - var n:String = _interest.key; - var info:Array = _infoMap[n]; - if(info == null){ - listchanged = true; - // used to use InterestInfo - info = new Array(_interest.col.toString(16), new Array()); - _infoMap[n] = info; + + var lowest:Number = isNaN(_group.fixedMin) ? lowestValue : _group.fixedMin; + var highest:Number = isNaN(_group.fixedMax) ? highestValue : _group.fixedMax; + var numInterests:uint = interests.length; + for (var i:uint = 0; i30) frames = 30; // Don't add too many lagged frames - while(frames>0){ - history.push(_interest.v); - frames--; - } - }else{ - history.push(_interest.v); - } + if (isNaN(_group.fixedMax) && (isNaN(highest) || v > highest)) + { + highest = v; } - var maxLen:int = Math.floor(W)+10; - while(history.length > maxLen) + } + + updateKeyText(values); + + if(lowestValue != lowest || highestValue != highest) + { + scaleBitmapData(lowest, highest); + if(group.inverted) { - history.shift(); + highTxt.text = makeValueString(lowest); + lowTxt.text = makeValueString(highest); } - if(draw) { - var len:int = history.length; - graph.graphics.lineStyle(1, _interest.col); - var maxi:int = W>len?len:W; - for(var i:int = 1; iH)Y=H; - if(i==1){ - graph.graphics.moveTo(width, Y); - } - graph.graphics.lineTo((W-i), Y); - } - if(isNaN(_interest.avg) && diffGraph){ - Y = ((_interest.avg-lowest)/diffGraph)*H; - if(!group.inv) Y = H-Y; - if(Y<0)Y=0; - if(Y>H)Y=H; - graph.graphics.lineStyle(1,_interest.col, 0.3); - graph.graphics.moveTo(0, Y); - graph.graphics.lineTo(W, Y); - } + else + { + lowTxt.text = makeValueString(lowest); + highTxt.text = makeValueString(highest); } } - for(var X:String in _infoMap){ - var found:Boolean; - for each(interest in interests){ - if(interest.key == X) + + pushBMD(values); + } + + protected function pushBMD(values:Array):void + { + var diffValue:Number = highestValue - lowestValue; + var pixX:uint = _bmd.width - 1; + + var bmdHeight:int = _bmd.height; + + _bmd.lock(); + + _bmd.scroll(-1, 0); + _bmd.fillRect(new Rectangle(pixX, 0, 1, _bmd.height), 0); + + var interests:Array = _group.interests; + for (var i:int = interests.length - 1; i >= 0; i--) + { + var interest:GraphInterest = interests[i]; + var value:Number = values[i]; + var pixY:int = getPixelValue(value); + + var lastValue:Number = lastValues[i]; + + var connectionColor:uint = interest.col + 0xFF000000; + + if (isNaN(lastValue) == false) + { + lineRect.x = pixX; + var prevPixY:int = getPixelValue(lastValue); + var half:Number; + if (pixY < prevPixY) { - found = true; + half = (prevPixY - pixY) * 0.5; + lineRect.y = pixY; + lineRect.height = half; + + _bmd.fillRect(lineRect, connectionColor); + lineRect.x--; + lineRect.y = pixY + half; + _bmd.fillRect(lineRect, connectionColor); + } + else (pixY > prevPixY) + { + half = (pixY - prevPixY) * 0.5; + lineRect.y = prevPixY + half; + lineRect.height = half; + + _bmd.fillRect(lineRect, connectionColor); + lineRect.x--; + lineRect.y = prevPixY; + _bmd.fillRect(lineRect, connectionColor); } } - if(!found){ - listchanged = true; - delete _infoMap[X]; - } + _bmd.setPixel32(pixX, pixY, connectionColor); + + lastValues[i] = value; } - if(draw && (listchanged || _type)) updateKeyText(); + _bmd.unlock(); } - - public function updateKeyText():void{ + + protected function getPixelValue(value:Number):Number + { + if(highestValue == lowestValue) + { + return _bmd.height * 0.5; + } + value = ((value - lowestValue) / (highestValue - lowestValue)) * _bmd.height; + if (!_group.inverted) + { + value = _bmd.height - value; + } + if (value < 0) + { + value = 0; + } + if (value >= _bmd.height) + { + value = _bmd.height - 1; + } + return value; + } + + protected function scaleBitmapData(newLow:Number, newHigh:Number):void + { + var scaleBMD:BitmapData = _bmd.clone(); + _bmd.fillRect(_bmd.rect, 0); + + var newDiff:Number = newHigh - newLow; + + if(newDiff == 0) + { + lowestValue = newLow; + highestValue = newHigh; + return; + } + // + // Try to pixel round outside given value so that it reduces the need to rescale. + var valuePerPixel:Number = newDiff / _bmd.height; + var valuePerHalfPixel:Number = valuePerPixel * 0.5; + newHigh += valuePerPixel; + newLow -= valuePerPixel; + if (!isNaN(_group.fixedMax) && newHigh > _group.fixedMax) + { + newHigh = _group.fixedMax; + } + if (!isNaN(_group.fixedMin) && newLow < _group.fixedMin) + { + newLow = _group.fixedMin; + } + // + + newDiff = newHigh - newLow; + + var oldDiff:Number = highestValue - lowestValue; + + var matrix:Matrix = new Matrix(); + if(_group.inverted) + { + matrix.ty = (lowestValue - newLow) / oldDiff * _bmd.height; + } + else + { + matrix.ty = ( newHigh - highestValue) / oldDiff * _bmd.height; + } + matrix.scale(1, oldDiff / newDiff); + _bmd.draw(scaleBMD, matrix, null, null, null, true); + + scaleBMD.dispose(); + + lowestValue = newLow; + highestValue = newHigh; + } + + public function updateKeyText(values:Array):void + { var str:String = ""; - if(_type){ - if(isNaN(_interest.v)){ - str += "no input"; - }else if(_type == FPS){ - str += _interest.avg.toFixed(1); - }else{ - str += _interest.v+"mb"; - } - }else{ - for(var X:String in _infoMap){ - str += " "+X+""; - } - str += " |"; + + var numInterests:uint = _group.interests.length; + for (var i:uint = 0; i" + makeValueString(values[i]) + interest.key+" "; } - txtField.htmlText = str+_menuString; + txtField.htmlText = str + _menuString; txtField.scrollH = txtField.maxScrollH; } - - protected function linkHandler(e:TextEvent):void{ + private function makeValueString(value:Number):String + { + var precision:uint = _group.numberDisplayPrecision; + if(precision == 0 || value == 0) + { + return String(value); + } + return value.toPrecision(precision); + } + + protected function linkHandler(e:TextEvent):void + { TextField(e.currentTarget).setSelection(0, 0); - if(e.text == "reset"){ + if (e.text == "R") + { reset(); - }else if(e.text == "close"){ - if(_type == FPS) console.fpsMonitor = false; - else if(_type == MEM) console.memoryMonitor = false; - else stop(); - console.panels.removeGraph(_group); - }else if(e.text == "gc"){ - console.gc(); - } + } + else if (e.text == "X") + { + _group.close(); + } + _group.onMenu.apply(e.text); e.stopPropagation(); } - protected function onMenuRollOver(e:TextEvent):void{ - var txt:String = e.text?e.text.replace("event:",""):null; - if(txt == "gc"){ + + protected function onMenuRollOver(e:TextEvent):void + { + var txt:String = e.text ? e.text.replace("event:", "") : null; + // TODO use shared menu system. + if (txt == "G") + { txt = "Garbage collect::Requires debugger version of flash player"; } + else + { + txt = null; + } console.panels.tooltip(txt, this); } } } -/* -Stopped using this to save 0.5kb! - wow -class InterestInfo{ - public var col:Number; - public var history:Array = []; - public function InterestInfo(c:Number){ - col = c; - } -}*/ \ No newline at end of file diff --git a/src/com/junkbyte/console/view/MainPanel.as b/src/com/junkbyte/console/view/MainPanel.as index 7914a1d..9d81ebd 100644 --- a/src/com/junkbyte/console/view/MainPanel.as +++ b/src/com/junkbyte/console/view/MainPanel.as @@ -25,6 +25,7 @@ package com.junkbyte.console.view { import com.junkbyte.console.Console; + import com.junkbyte.console.ConsoleChannel; import com.junkbyte.console.core.LogReferences; import com.junkbyte.console.core.Remoting; import com.junkbyte.console.vos.Log; @@ -231,7 +232,7 @@ package com.junkbyte.console.view */ public function addMenu(key:String, f:Function, args:Array, rollover:String):void{ if(key){ - key = key.replace(/[^\w]*/g, ""); + key = key.replace(/[^\w\-]*/g, ""); if(f == null){ delete _extraMenus[key]; }else{ @@ -446,8 +447,8 @@ package com.junkbyte.console.view && ( chShouldShow(line.ch) - || (_filterText && _viewingChannels.indexOf(Console.FILTER_CHANNEL) >= 0 && line.text.toLowerCase().indexOf(_filterText)>=0 ) - || (_filterRegExp && _viewingChannels.indexOf(Console.FILTER_CHANNEL)>=0 && line.text.search(_filterRegExp)>=0 ) + || (_filterText && _viewingChannels.indexOf(ConsoleChannel.FILTER_CHANNEL) >= 0 && line.text.toLowerCase().indexOf(_filterText)>=0 ) + || (_filterRegExp && _viewingChannels.indexOf(ConsoleChannel.FILTER_CHANNEL)>=0 && line.text.search(_filterRegExp)>=0 ) ) ); } @@ -461,7 +462,7 @@ package com.junkbyte.console.view * @private */ public function get reportChannel():String{ - return _viewingChannels.length == 1?_viewingChannels[0]:Console.CONSOLE_CHANNEL; + return _viewingChannels.length == 1?_viewingChannels[0]:ConsoleChannel.CONSOLE_CHANNEL; } /*public function get viewingChannels():Array{ return _viewingChannels; @@ -479,7 +480,7 @@ package com.junkbyte.console.view } _ignoredChannels.splice(0); _viewingChannels.splice(0); - if(a.indexOf(Console.GLOBAL_CHANNEL) < 0 && a.indexOf(null) < 0){ + if(a.indexOf(ConsoleChannel.GLOBAL_CHANNEL) < 0 && a.indexOf(null) < 0){ for each(var ch:String in a) { if(ch) _viewingChannels.push(ch); @@ -512,7 +513,7 @@ package com.junkbyte.console.view _ignoredChannels.splice(0); _viewingChannels.splice(0); - if(a.indexOf(Console.GLOBAL_CHANNEL) < 0 && a.indexOf(null) < 0){ + if(a.indexOf(ConsoleChannel.GLOBAL_CHANNEL) < 0 && a.indexOf(null) < 0){ for each(var ch:String in a) { if(ch) _ignoredChannels.push(ch); @@ -550,15 +551,15 @@ package com.junkbyte.console.view } } private function startFilter():void{ - console.clear(Console.FILTER_CHANNEL); - console.logs.addChannel(Console.FILTER_CHANNEL); - setViewingChannels(Console.FILTER_CHANNEL); + console.clear(ConsoleChannel.FILTER_CHANNEL); + console.logs.addChannel(ConsoleChannel.FILTER_CHANNEL); + setViewingChannels(ConsoleChannel.FILTER_CHANNEL); } private function endFilter():void{ _filterRegExp = null; _filterText = null; - if(_viewingChannels.length == 1 && _viewingChannels[0] == Console.FILTER_CHANNEL){ - setViewingChannels(Console.GLOBAL_CHANNEL); + if(_viewingChannels.length == 1 && _viewingChannels[0] == ConsoleChannel.FILTER_CHANNEL){ + setViewingChannels(ConsoleChannel.GLOBAL_CHANNEL); } } private function makeLine(line:Log, showch:Boolean):String{ @@ -794,11 +795,9 @@ package com.junkbyte.console.view str += doActive(" CL", commandLine); - if(console.remoter.remoting != Remoting.RECIEVER){ - if(config.displayRollerEnabled) + if(config.displayRollerEnabled) + { str += doActive(" Ro", console.displayRoller); - if(config.rulerToolEnabled) - str += doActive(" RL", console.panels.rulerActive); } str += " ¦"; str += " Sv"; @@ -841,13 +840,13 @@ package com.junkbyte.console.view public function onMenuRollOver(e:TextEvent, src:ConsolePanel = null):void{ if(src==null) src = this; var txt:String = e.text?e.text.replace("event:",""):""; - if(txt == "channel_"+Console.GLOBAL_CHANNEL){ + if(txt == "channel_"+ConsoleChannel.GLOBAL_CHANNEL){ txt = "View all channels"; - }else if(txt == "channel_"+Console.DEFAULT_CHANNEL) { + }else if(txt == "channel_"+ConsoleChannel.DEFAULT_CHANNEL) { txt = "Default channel::Logs with no channel"; - }else if(txt == "channel_"+ Console.CONSOLE_CHANNEL) { + }else if(txt == "channel_"+ ConsoleChannel.CONSOLE_CHANNEL) { txt = "Console's channel::Logs generated from Console"; - }else if(txt == "channel_"+ Console.FILTER_CHANNEL) { + }else if(txt == "channel_"+ ConsoleChannel.FILTER_CHANNEL) { txt = _filterRegExp?String(_filterRegExp):_filterText; txt = "Filtering channel"+"::*"+txt+"*"; }else if(txt == "channel_"+LogReferences.INSPECTING_CHANNEL) { @@ -867,7 +866,6 @@ package com.junkbyte.console.view fps:"Frames Per Second", mm:"Memory Monitor", roller:"Display Roller::Map the display list under your mouse", - ruler:"Screen Ruler::Measure the distance and angle between two points on screen.", command:"Command Line", copy:"Save to clipboard::shift: no channel name\nctrl: use viewing filters\nalt: save to file", clear:"Clear log", @@ -879,7 +877,7 @@ package com.junkbyte.console.view } console.panels.tooltip(txt, src); } - private function linkHandler(e:TextEvent):void{ + protected function linkHandler(e:TextEvent):void{ txtField.setSelection(0, 0); stopDrag(); var t:String = e.text; @@ -916,9 +914,6 @@ package com.junkbyte.console.view console.memoryMonitor = !console.memoryMonitor; }else if(t == "roller"){ console.displayRoller = !console.displayRoller; - }else if(t == "ruler"){ - console.panels.tooltip(); - console.panels.startRuler(); }else if(t == "command"){ commandLine = !commandLine; } else if (t == "copy") { @@ -939,8 +934,6 @@ package com.junkbyte.console.view }else if(t == "settings"){ console.report("A new window should open in browser. If not, try searching for 'Flash Player Global Security Settings panel' online :)", -1); Security.showSettings(SecurityPanel.SETTINGS_MANAGER); - }else if(t == "remote"){ - console.remoter.remoting = Remoting.RECIEVER; }else if(t.indexOf("ref")==0){ console.refs.handleRefEvent(t); }else if(t.indexOf("channel_")==0){ @@ -964,11 +957,11 @@ package com.junkbyte.console.view */ public function onChannelPressed(chn:String):void{ var current:Array; - if(_ctrl && chn != Console.GLOBAL_CHANNEL){ + if(_ctrl && chn != ConsoleChannel.GLOBAL_CHANNEL){ current = toggleCHList(_ignoredChannels, chn); setIgnoredChannels.apply(this, current); } - else if(_shift && chn != Console.GLOBAL_CHANNEL && _viewingChannels[0] != LogReferences.INSPECTING_CHANNEL){ + else if(_shift && chn != ConsoleChannel.GLOBAL_CHANNEL && _viewingChannels[0] != LogReferences.INSPECTING_CHANNEL){ current = toggleCHList(_viewingChannels, chn); setViewingChannels.apply(this, current); }else{ @@ -981,7 +974,7 @@ package com.junkbyte.console.view if(ind>=0){ current.splice(ind,1); if(current.length == 0){ - current.push(Console.GLOBAL_CHANNEL); + current.push(ConsoleChannel.GLOBAL_CHANNEL); } }else{ current.push(chn); @@ -1113,9 +1106,10 @@ package com.junkbyte.console.view private function setCLSelectionAtEnd():void{ _cmdField.setSelection(_cmdField.text.length, _cmdField.text.length); } - private function updateCmdHint(e:Event = null):void{ + + protected function updateCmdHint(e:Event = null):void{ var str:String = _cmdField.text; - if(str && config.commandLineAutoCompleteEnabled && console.remoter.remoting != Remoting.RECIEVER){ + if(str && config.commandLineAutoCompleteEnabled){ try{ setHints(console.cl.getHintsFor(str, 5)); return; @@ -1123,10 +1117,12 @@ package com.junkbyte.console.view } setHints(); } + private function onCmdFocusOut(e:Event):void{ setHints(); } private function setHints(hints:Array = null):void{ + var cmdText:String = _cmdField.text; if(hints && hints.length){ _hint = hints[0][0]; if(hints.length > 1){ @@ -1136,16 +1132,22 @@ package com.junkbyte.console.view if(next.charAt(i) == _hint.charAt(i)){ matched = true; }else{ - if(matched && _cmdField.text.length < i) _hint = _hint.substring(0, i); + if(matched && cmdText.length < i) + { + _hint = _hint.substring(0, i); + } break; } } } var strs:Array = new Array(); - for each(var hint:Array in hints) strs.push(""+hint[0]+" "+(hint[1]?hint[1]:"")+""); + for each(var hint:Array in hints) + { + strs.push(""+hint[0]+" "+(hint[1]?hint[1]:"")+""); + } _hintField.htmlText = "

"+strs.reverse().join("\n")+"

"; _hintField.visible = true; - var r:Rectangle = _cmdField.getCharBoundaries(_cmdField.text.length-1); + var r:Rectangle = _cmdField.getCharBoundaries(cmdText.length-1); if(!r) r = new Rectangle(); _hintField.x = _cmdField.x + r.x + r.width+ 30; _hintField.y = height-_hintField.height; diff --git a/src/com/junkbyte/console/view/PanelsManager.as b/src/com/junkbyte/console/view/PanelsManager.as index befb328..050f4bf 100644 --- a/src/com/junkbyte/console/view/PanelsManager.as +++ b/src/com/junkbyte/console/view/PanelsManager.as @@ -25,37 +25,44 @@ package com.junkbyte.console.view { import com.junkbyte.console.Console; + import com.junkbyte.console.console_internal; import com.junkbyte.console.vos.GraphGroup; - + import flash.events.Event; import flash.geom.Rectangle; import flash.text.TextField; import flash.text.TextFieldAutoSize; + import flash.utils.Dictionary; public class PanelsManager{ - private var console:Console; - private var _mainPanel:MainPanel; - private var _ruler:Ruler; + protected var console:Console; + protected var _mainPanel:MainPanel; private var _chsPanel:ChannelsPanel; - private var _fpsPanel:GraphingPanel; - private var _memPanel:GraphingPanel; - private var _graphsMap:Object = {}; - private var _graphPlaced:uint = 0; + private var _graphsMap:Dictionary = new Dictionary(); private var _tooltipField:TextField; private var _canDraw:Boolean; public function PanelsManager(master:Console) { console = master; - _mainPanel = new MainPanel(console); + _mainPanel = createMainPanel(); _tooltipField = mainPanel.makeTF("tooltip", true); _tooltipField.mouseEnabled = false; _tooltipField.autoSize = TextFieldAutoSize.CENTER; _tooltipField.multiline = true; addPanel(_mainPanel); + + + console.graphing.onGroupAdded.add(onGraphingGroupAdded); } + + protected function createMainPanel():MainPanel + { + return new MainPanel(console); + } + public function addPanel(panel:ConsolePanel):void{ if(console.contains(_tooltipField)){ console.addChildAt(panel, console.getChildIndex(_tooltipField)); @@ -111,7 +118,7 @@ package com.junkbyte.console.view /** * @private */ - public function update(paused:Boolean, lineAdded:Boolean):void{ + console_internal function update(paused:Boolean, lineAdded:Boolean):void{ _canDraw = !paused; _mainPanel.update(!paused && lineAdded); if(!paused) { @@ -120,115 +127,30 @@ package com.junkbyte.console.view } } } - /** - * @private - */ - public function updateGraphs(graphs:Array):void{ - var usedMap:Object; - var fpsGroup:GraphGroup; - var memGroup:GraphGroup; - _graphPlaced = 0; - for each(var group:GraphGroup in graphs){ - if(group.type == GraphGroup.FPS) { - fpsGroup = group; - }else if(group.type == GraphGroup.MEM) { - memGroup = group; - }else{ - var n:String = group.name; - var panel:GraphingPanel = _graphsMap[n] as GraphingPanel; - if(!panel){ - var rect:Rectangle = group.rect; - if(rect == null) rect = new Rectangle(NaN,NaN, 0, 0); - var size:Number = 100; - if(isNaN(rect.x) || isNaN(rect.y)){ - if(_mainPanel.width < 150){ - size = 50; - } - var maxX:Number = Math.floor(_mainPanel.width/size)-1; - if(maxX <=1) maxX = 2; - var ix:int = _graphPlaced%maxX; - var iy:int = Math.floor(_graphPlaced/maxX); - rect.x = _mainPanel.x+size+(ix*size); - rect.y = _mainPanel.y+(size*0.6)+(iy*size); - _graphPlaced++; - } - if(rect.width<=0 || isNaN(rect.width)) rect.width = size; - if(rect.height<=0 || isNaN(rect.height)) rect.height = size; - panel = new GraphingPanel(console, rect.width,rect.height); - panel.x = rect.x; - panel.y = rect.y; - panel.name = "graph_"+n; - _graphsMap[n] = panel; - addPanel(panel); - } - if(usedMap == null) - { - usedMap = {}; - } - usedMap[n] = true; - panel.update(group, _canDraw); - } - } + + private function onGraphingGroupAdded(group:GraphGroup):void + { + group.onClose.add(onGraphGroupClose); - for(var X:String in _graphsMap){ - if(usedMap == null || !usedMap[X]){ - _graphsMap[X].close(); - delete _graphsMap[X]; - } - } - // - // - if(fpsGroup != null){ - if (_fpsPanel == null) { - _fpsPanel = new GraphingPanel(console, 80 ,40, GraphingPanel.FPS); - _fpsPanel.name = GraphingPanel.FPS; - _fpsPanel.x = _mainPanel.x+_mainPanel.width-160; - _fpsPanel.y = _mainPanel.y+15; - addPanel(_fpsPanel); - _mainPanel.updateMenu(); - } - _fpsPanel.update(fpsGroup, _canDraw); - }else if(_fpsPanel!=null){ - removePanel(GraphingPanel.FPS); - _fpsPanel = null; - } - // - // - if(memGroup != null){ - if(_memPanel == null){ - _memPanel = new GraphingPanel(console, 80 ,40, GraphingPanel.MEM); - _memPanel.name = GraphingPanel.MEM; - _memPanel.x = _mainPanel.x+_mainPanel.width-80; - _memPanel.y = _mainPanel.y+15; - addPanel(_memPanel); - _mainPanel.updateMenu(); - } - _memPanel.update(memGroup, _canDraw); - }else if(_memPanel!=null){ - removePanel(GraphingPanel.MEM); - _memPanel = null; - } - _canDraw = false; + var graph:GraphingPanel = new GraphingPanel(console, group); + _graphsMap[group] = graph; + addPanel(graph); } - /** - * @private - */ - public function removeGraph(group:GraphGroup):void + + private function onGraphGroupClose(group:GraphGroup):void { - if(_fpsPanel && group == _fpsPanel.group){ - _fpsPanel.close(); - _fpsPanel = null; - }else if(_memPanel && group == _memPanel.group){ - _memPanel.close(); - _memPanel = null; - }else{ - var graph:GraphingPanel = _graphsMap[group.name]; - if(graph){ - graph.close(); - delete _graphsMap[group.name]; - } + var graph:GraphingPanel = getGraphByGroup(group); + if(graph) + { + delete _graphsMap[group]; + graph.close(); } } + + public function getGraphByGroup(group:GraphGroup):GraphingPanel + { + return _graphsMap[group]; + } // // // @@ -281,26 +203,11 @@ package com.junkbyte.console.view // // // - /** - * @private - */ - public function get memoryMonitor():Boolean{ - return _memPanel!=null; - } - /** - * @private - */ - public function get fpsMonitor():Boolean{ - return _fpsPanel!=null; - } - // - // - // /** * @private */ public function tooltip(str:String = null, panel:ConsolePanel = null):void{ - if(str && !rulerActive){ + if(str){ var split:Array = str.split("::"); str = split[0]; if(split.length > 1) str += "
"+split[1]+""; @@ -339,28 +246,6 @@ package com.junkbyte.console.view // // // - public function startRuler():void{ - if(rulerActive){ - return; - } - _ruler = new Ruler(console); - _ruler.addEventListener(Event.COMPLETE, onRulerExit, false, 0, true); - console.addChild(_ruler); - _mainPanel.updateMenu(); - } - public function get rulerActive():Boolean{ - return (_ruler && console.contains(_ruler))?true:false; - } - private function onRulerExit(e:Event):void{ - if(_ruler && console.contains(_ruler)){ - console.removeChild(_ruler); - } - _ruler = null; - _mainPanel.updateMenu(); - } - // - // - // private function onPanelStartDragScale(e:Event):void{ var target:ConsolePanel = e.currentTarget as ConsolePanel; if(console.config.style.panelSnapping) { diff --git a/src/com/junkbyte/console/view/Ruler.as b/src/com/junkbyte/console/view/Ruler.as deleted file mode 100644 index e4a5d81..0000000 --- a/src/com/junkbyte/console/view/Ruler.as +++ /dev/null @@ -1,280 +0,0 @@ -/* -* -* Copyright (c) 2008-2010 Lu Aye Oo -* -* @author Lu Aye Oo -* -* http://code.google.com/p/flash-console/ -* -* -* This software is provided 'as-is', without any express or implied -* warranty. In no event will the authors be held liable for any damages -* arising from the use of this software. -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software -* in a product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* 3. This notice may not be removed or altered from any source distribution. -* -*/ -package com.junkbyte.console.view { - import flash.geom.Matrix; - import flash.display.BitmapData; - import flash.display.Bitmap; - import com.junkbyte.console.ConsoleConfig; - import com.junkbyte.console.ConsoleStyle; - import com.junkbyte.console.Console; - - import flash.display.BlendMode; - import flash.display.Graphics; - import flash.display.Shape; - import flash.display.Sprite; - import flash.events.Event; - import flash.events.MouseEvent; - import flash.geom.Point; - import flash.geom.Rectangle; - import flash.text.TextField; - import flash.text.TextFieldAutoSize; - import flash.text.TextFormat; - import flash.text.TextFormatAlign; - import flash.ui.Mouse; - - /** - * @private - */ - public class Ruler extends Sprite{ - - private var _master:Console; - private var _config : ConsoleConfig; - - private var _area:Rectangle; - private var _pointer:Shape; - - private var _posTxt:TextField; - private var _zoom:Bitmap; - - private var _points:Array; - - public function Ruler(console:Console) { - _master = console; - _config = console.config; - buttonMode = true; - _points = new Array(); - _pointer = new Shape(); - addChild(_pointer); - var p:Point = new Point(); - p = globalToLocal(p); - _area = new Rectangle(-console.stage.stageWidth*1.5+p.x, -console.stage.stageHeight*1.5+p.y, console.stage.stageWidth*3, console.stage.stageHeight*3); - graphics.beginFill(_config.style.backgroundColor, 0.2); - graphics.drawRect(_area.x, _area.y, _area.width, _area.height); - graphics.endFill(); - // - _posTxt = _master.panels.mainPanel.makeTF("positionText", true); - _posTxt.autoSize = TextFieldAutoSize.LEFT; - addChild(_posTxt); - // - _zoom = new Bitmap(); - _zoom.scaleY = _zoom.scaleX = 2; - addChild(_zoom); - // - addEventListener(MouseEvent.CLICK, onMouseClick, false, 0, true); - addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true); - onMouseMove(); - if(_config.rulerHidesMouse) Mouse.hide(); - _master.report("Ruler started. Click on two locations to measure.", -1); - } - private function onMouseMove(e:MouseEvent = null):void{ - _pointer.graphics.clear(); - _pointer.graphics.lineStyle(1, 0xAACC00, 1); - _pointer.graphics.moveTo(_area.x, mouseY); - _pointer.graphics.lineTo(_area.x+_area.width, mouseY); - _pointer.graphics.moveTo(mouseX, _area.y); - _pointer.graphics.lineTo(mouseX, _area.y+_area.height); - _pointer.blendMode = BlendMode.INVERT; - _posTxt.text = ""+mouseX+","+mouseY+""; - // - var bmd:BitmapData = new BitmapData(30, 30); - try{ - var m:Matrix = new Matrix(); - m.tx = -stage.mouseX+15; - m.ty = -stage.mouseY+15; - bmd.draw(stage, m); - }catch(err:Error){ - bmd = null; - } - _zoom.bitmapData = bmd; - // - var d:int = 10; - _posTxt.x = mouseX-_posTxt.width-d; - _posTxt.y = mouseY-_posTxt.height-d; - _zoom.x = _posTxt.x+_posTxt.width-_zoom.width; - _zoom.y = _posTxt.y-_zoom.height; - if(_posTxt.x < 16){ - _posTxt.x = mouseX+d; - _zoom.x = _posTxt.x; - } - if(_posTxt.y < 38){ - _posTxt.y = mouseY+d; - _zoom.y = _posTxt.y+_posTxt.height; - } - } - private function onMouseClick(e:MouseEvent):void{ - e.stopPropagation(); - var p:Point; - var style : ConsoleStyle = _config.style; - if(_points.length==0){ - p = new Point(e.localX, e.localY); - graphics.lineStyle(1, 0xFF0000); - graphics.drawCircle(p.x, p.y, 3); - _points.push(p); - }else if(_points.length==1){ - _zoom.bitmapData = null; - if(_config.rulerHidesMouse) Mouse.show(); - removeChild(_pointer); - removeChild(_posTxt); - removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); - p = _points[0]; - var p2:Point = new Point(e.localX, e.localY); - _points.push(p2); - graphics.clear(); - graphics.beginFill(style.backgroundColor, 0.4); - graphics.drawRect(_area.x, _area.y, _area.width, _area.height); - graphics.endFill(); - graphics.lineStyle(1.5, 0xFF0000); - graphics.drawCircle(p.x, p.y, 4); - graphics.lineStyle(1.5, 0xFF9900); - graphics.drawCircle(p2.x, p2.y, 4); - var mp:Point = Point.interpolate(p, p2, 0.5); - graphics.lineStyle(1, 0xAAAAAA); - graphics.drawCircle(mp.x, mp.y, 4); - // - var xmin:Point = p; - var xmax:Point = p2; - if(p.x>p2.x){ - xmin = p2; - xmax = p; - } - var ymin:Point = p; - var ymax:Point = p2; - if(p.y>p2.y){ - ymin = p2; - ymax = p; - } - // - var w:Number = xmax.x-xmin.x; - var h:Number = ymax.y-ymin.y; - var d:Number = Point.distance(p, p2); - // - var txt:TextField = makeTxtField(style.highColor); - txt.text = round(p.x)+","+ round(p.y); - txt.x = p.x; - txt.y = p.y-(ymin==p?14:0); - addChild(txt); - // - txt = makeTxtField(style.highColor); - txt.text = round(p2.x)+","+ round(p2.y); - txt.x = p2.x; - txt.y = p2.y-(ymin==p2?14:0);; - addChild(txt); - // - if(w>40 || h>25){ - txt = makeTxtField(style.lowColor); - txt.text = round(mp.x)+","+ round(mp.y); - txt.x = mp.x; - txt.y = mp.y; - addChild(txt); - } - // - graphics.lineStyle(1, 0xAACC00, 0.5); - graphics.moveTo(_area.x, ymin.y); - graphics.lineTo(_area.x+_area.width, ymin.y); - graphics.moveTo(_area.x, ymax.y); - graphics.lineTo(_area.x+_area.width, ymax.y); - graphics.moveTo(xmin.x, _area.y); - graphics.lineTo(xmin.x, _area.y+_area.height); - graphics.moveTo(xmax.x, _area.y); - graphics.lineTo(xmax.x, _area.y+_area.height); - // - var a1:Number = round(angle(p,p2),100); - var a2:Number = round(angle(p2,p),100); - graphics.lineStyle(1, 0xAA0000, 0.8); - drawCircleSegment(graphics, 10,p, a1, -90); - graphics.lineStyle(1, 0xCC8800, 0.8); - drawCircleSegment(graphics, 10,p2, a2, -90); - // - graphics.lineStyle(2, 0x00FF00, 0.7); - graphics.moveTo(p.x, p.y); - graphics.lineTo(p2.x, p2.y); - // - _master.report("Ruler results: (red) ["+p.x+","+p.y+"] to (orange) ["+p2.x+","+p2.y+"]", -2); - _master.report("Distance: "+round(d,100) +"", -2); - _master.report("Mid point: ["+mp.x+","+mp.y+"]", -2); - _master.report("Width:"+w+", Height: "+h+"", -2); - _master.report("Angle from first point (red): "+a1+"°", -2); - _master.report("Angle from second point (orange): "+a2+"°", -2); - }else{ - exit(); - } - } - public function exit():void{ - _master = null; - dispatchEvent(new Event(Event.COMPLETE)); - } - private function makeTxtField(col:Number, b:Boolean = true):TextField{ - var format:TextFormat = new TextFormat(_config.style.menuFont, _config.style.menuFontSize, col, b, true, null, null, TextFormatAlign.RIGHT); - var txt:TextField = new TextField(); - txt.autoSize = TextFieldAutoSize.RIGHT; - txt.selectable = false; - txt.defaultTextFormat = format; - return txt; - } - - - private function round(n:Number, d:uint = 10):Number{ - return Math.round(n*d)/d; - } - private function angle(srcP:Point, point:Point):Number { - var a:Number = Math.atan2(point.y - srcP.y , point.x - srcP.x)/Math.PI * 180; - a +=90; - if(a>180) a -= 360; - return a; - } - private function drawCircleSegment(g : Graphics,radius :Number,pos:Point, deg:Number = 180, startDeg:Number = 0):Point - { - var reversed:Boolean = false; - if(deg<0){ - reversed = true; - deg = Math.abs(deg); - } - var rad:Number = (deg*Math.PI)/180; - var rad2:Number = (startDeg*Math.PI)/180; - var p:Point = getPointOnCircle(radius, rad2); - p.offset(pos.x,pos.y); - g.moveTo(p.x,p.y); - var pra:Number = 0; - for (var i:int = 1; i<=(rad+1); i++) { - var ra:Number = i<=rad?i:rad; - var diffr:Number = ra-pra; - var offr:Number = 1+(0.12*diffr*diffr); - var ap:Point = getPointOnCircle(radius*offr, ((ra-(diffr/2))*(reversed?-1:1))+rad2); - ap.offset(pos.x,pos.y); - p = getPointOnCircle(radius, (ra*(reversed?-1:1))+rad2); - p.offset(pos.x,pos.y); - g.curveTo(ap.x,ap.y, p.x,p.y); - pra = ra; - } - return p; - } - private function getPointOnCircle(radius:Number, rad:Number):Point { - return new Point(radius * Math.cos(rad),radius * Math.sin(rad)); - } - - - - } -} \ No newline at end of file diff --git a/src/com/junkbyte/console/vos/GraphFPSGroup.as b/src/com/junkbyte/console/vos/GraphFPSGroup.as new file mode 100644 index 0000000..3937e96 --- /dev/null +++ b/src/com/junkbyte/console/vos/GraphFPSGroup.as @@ -0,0 +1,103 @@ +package com.junkbyte.console.vos +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.console_internal; + + use namespace console_internal; + + public class GraphFPSGroup extends GraphGroup + { + public static const NAME:String = "consoleFPSGraph"; + + public var maxLag:uint = 60; + + private var _console:Console; + + private var _historyLength:uint; + private var _history:Array = new Array(); + private var _historyIndex:uint; + private var _historyTotal:Number = 0; + + public function GraphFPSGroup(console:Console, historyLength:uint = 5) + { + _console = console; + _historyLength = historyLength; + + super(NAME); + + for (var i:uint = 0; i < historyLength; i++) + { + _history.push(0); + } + + rect.x = 170; + rect.y = 15; + alignRight = true; + + var graph:GraphInterest = new GraphInterest("fps"); + graph.col = 0xFF3333; + + interests.push(graph); + + _updateArgs.length = 1; + + freq = 200; + fixedMin = 0; + numberDisplayPrecision = 2; + } + + override public function tick(timeDelta:uint):void + { + if(timeDelta == 0) + { + return; + } + var fps:Number = 1000 / timeDelta; + + var frames:uint; + if (_console.stage) + { + fixedMax = _console.stage.frameRate; + + frames = fixedMax / fps / _historyLength; + if (frames > maxLag) + { + frames = maxLag; + } + } + if (frames == 0) + { + frames = 1 + } + + while (frames > 0) + { + dispatchFPS(fps); + frames--; + } + } + + private function dispatchFPS(fps:Number):void + { + _historyTotal -= _history[_historyIndex]; + + _historyTotal += fps; + _history[_historyIndex] = fps; + + _historyIndex++; + if (_historyIndex >= _historyLength) + { + _historyIndex = 0; + } + + fps = _historyTotal / _historyLength; + if (fps > fixedMax) + { + fps = fixedMax; + } + _updateArgs[0] = Math.round(fps); + + applyUpdateDispather(_updateArgs); + } + } +} diff --git a/src/com/junkbyte/console/vos/GraphGroup.as b/src/com/junkbyte/console/vos/GraphGroup.as index 50adf3d..bc9154c 100644 --- a/src/com/junkbyte/console/vos/GraphGroup.as +++ b/src/com/junkbyte/console/vos/GraphGroup.as @@ -1,11 +1,11 @@ /* -* +* * Copyright (c) 2008-2010 Lu Aye Oo -* +* * @author Lu Aye Oo -* +* * http://code.google.com/p/flash-console/ -* +* * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -20,73 +20,184 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. -* +* */ -package com.junkbyte.console.vos { - import flash.utils.ByteArray; +package com.junkbyte.console.vos +{ + import com.junkbyte.console.console_internal; + import com.junkbyte.console.core.CcCallbackDispatcher; + + import flash.display.StageAlign; + import flash.events.Event; + import flash.events.EventDispatcher; import flash.geom.Rectangle; - - /** - * @private - */ - public class GraphGroup { - - public static const FPS:uint = 1; - public static const MEM:uint = 2; + import flash.utils.ByteArray; - public var type:uint; + use namespace console_internal; + + [Event(name = "close", type = "flash.events.Event")] + public class GraphGroup + { public var name:String; - public var freq:int = 1; // update every n number of frames. - public var low:Number; - public var hi:Number; - public var fixed:Boolean; - public var averaging:uint; - public var inv:Boolean; + + public var freq:int = 0; // 0 = every frame, 500 = twice per second, 1000 = once every second + + /** + * Fix graph's range. + * When fixed, graph will only show within the fixed value however offset the real values may be. + *

+ * For example: if the graph is fixed between 100 and 200, and the graph value at one point is 300, + * graph will not expand to accompany up to value 10, but remain fixed to 100 - 200 range. + * Pass NaN to min or max to unfix graph. + * No effect if no graph of the name exists. + *

+ */ + public var fixedMin:Number; + public var fixedMax:Number; + + public var inverted:Boolean; public var interests:Array = []; - public var rect:Rectangle; - // + public var menus:Array = []; + + public var numberDisplayPrecision:uint = 4; + + public var alignRight:Boolean; + public var rect:Rectangle = new Rectangle(0, 0, 80, 40); // - public var idle:int; + protected var _updateArgs:Array = new Array(); + protected var sinceLastUpdate:uint; - public function GraphGroup(n:String){ + protected var _onUpdate:CcCallbackDispatcher = new CcCallbackDispatcher(); + protected var _onClose:CcCallbackDispatcher = new CcCallbackDispatcher(); + protected var _onMenu:CcCallbackDispatcher = new CcCallbackDispatcher(); + + // + // + + public function GraphGroup(n:String) + { name = n; } - public function updateMinMax(v:Number):void{ - if(!isNaN(v) && !fixed){ - if(isNaN(low)) { - low = v; - hi = v; - } - if(v > hi) hi = v; - if(v < low) low = v; + + public function tick(timeDelta:uint):void + { + sinceLastUpdate += timeDelta; + + if (sinceLastUpdate >= freq) + { + update(); } } + + public function update():void + { + sinceLastUpdate = 0; + dispatchUpdates(); + } + + protected function dispatchUpdates():void + { + for (var i:int = interests.length - 1; i >= 0; i--) + { + var graph:GraphInterest = interests[i]; + var v:Number = graph.getCurrentValue(); + _updateArgs[i] = v; + } + applyUpdateDispather(_updateArgs); + } + + console_internal function applyUpdateDispather(args:Array):void + { + _onUpdate.apply(args); + } + + public function close():void + { + _onClose.apply(this); + _onUpdate.clear(); + _onClose.clear(); + _onMenu.clear(); + } + + public function get onUpdate():CcCallbackDispatcher + { + return _onUpdate; + } + + public function get onClose():CcCallbackDispatcher + { + return _onClose; + } + + public function get onMenu():CcCallbackDispatcher + { + return _onMenu; + } + // // // - public function toBytes(bytes:ByteArray):void{ + public function writeToBytes(bytes:ByteArray):void + { bytes.writeUTF(name); - bytes.writeUnsignedInt(type); - bytes.writeUnsignedInt(idle); - bytes.writeDouble(low); - bytes.writeDouble(hi); - bytes.writeBoolean(inv); - bytes.writeUnsignedInt(interests.length); - for each(var gi:GraphInterest in interests) gi.toBytes(bytes); + bytes.writeDouble(fixedMin); + bytes.writeDouble(fixedMax); + bytes.writeBoolean(inverted); + + bytes.writeBoolean(alignRight); + + bytes.writeFloat(rect.x); + bytes.writeFloat(rect.y); + bytes.writeFloat(rect.width); + bytes.writeFloat(rect.height); + + bytes.writeShort(numberDisplayPrecision); + + bytes.writeShort(interests.length); + for each (var gi:GraphInterest in interests) + { + gi.writeToBytes(bytes); + } + + bytes.writeShort(menus.length); + for each (var menu:String in menus) + { + bytes.writeUTF(menu); + } } - public static function FromBytes(bytes:ByteArray):GraphGroup{ + + public static function FromBytes(bytes:ByteArray):GraphGroup + { var g:GraphGroup = new GraphGroup(bytes.readUTF()); - g.type = bytes.readUnsignedInt(); - g.idle = bytes.readUnsignedInt(); - g.low = bytes.readDouble(); - g.hi = bytes.readDouble(); - g.inv = bytes.readBoolean(); - var len:uint = bytes.readUnsignedInt(); - while(len){ + g.fixedMin = bytes.readDouble(); + g.fixedMax = bytes.readDouble(); + g.inverted = bytes.readBoolean(); + + g.alignRight = bytes.readBoolean(); + + var rect:Rectangle = g.rect; + rect.x = bytes.readFloat(); + rect.y = bytes.readFloat(); + rect.width = bytes.readFloat(); + rect.height = bytes.readFloat(); + + g.numberDisplayPrecision = bytes.readShort(); + + var len:uint = bytes.readShort(); + while (len > 0) + { g.interests.push(GraphInterest.FromBytes(bytes)); len--; } + + len = bytes.readShort(); + while (len > 0) + { + g.menus.push(bytes.readUTF()); + len--; + } + return g; } } -} \ No newline at end of file +} diff --git a/src/com/junkbyte/console/vos/GraphInterest.as b/src/com/junkbyte/console/vos/GraphInterest.as index 213dc4e..3743676 100644 --- a/src/com/junkbyte/console/vos/GraphInterest.as +++ b/src/com/junkbyte/console/vos/GraphInterest.as @@ -1,11 +1,11 @@ /* -* +* * Copyright (c) 2008-2010 Lu Aye Oo -* +* * @author Lu Aye Oo -* +* * http://code.google.com/p/flash-console/ -* +* * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -20,77 +20,102 @@ * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. -* -*/package com.junkbyte.console.vos { - import flash.utils.ByteArray; +* +*/ +package com.junkbyte.console.vos +{ import com.junkbyte.console.core.Executer; - import com.junkbyte.console.vos.WeakRef; - + + import flash.utils.ByteArray; + /** * @private */ - public class GraphInterest { - + public class GraphInterest + { + private var _ref:WeakRef; public var _prop:String; + + private var _getValueMethod:Function; + private var useExec:Boolean; public var key:String; public var col:Number; - public var v:Number; - public var avg:Number; - - public function GraphInterest(keystr:String ="", color:Number = 0):void{ + + public function GraphInterest(keystr:String = "", color:Number = 0):void + { col = color; key = keystr; } - public function setObject(object:Object, property:String):Number{ + + public function setObject(object:Object, property:String):Number + { _ref = new WeakRef(object); _prop = property; - useExec = _prop.search(/[^\w\d]/) >= 0; - // - v = getCurrentValue(); - avg = v; - return v; + _getValueMethod = getAppropriateGetValueMethod(); + + return getCurrentValue(); } - public function get obj():Object{ - return _ref!=null?_ref.reference:undefined; + + public function setGetValueCallback(callback:Function):void + { + if (callback == null) + { + _getValueMethod = getAppropriateGetValueMethod(); + } + else + { + _getValueMethod = callback; + } + } + + public function get obj():Object + { + return _ref != null ? _ref.reference : undefined; } - public function get prop():String{ + + public function get prop():String + { return _prop; } - // - // - // - public function getCurrentValue():Number{ - return useExec?Executer.Exec(obj, _prop):obj[_prop]; + + public function getCurrentValue():Number + { + return _getValueMethod(this); } - public function setValue(val:Number, averaging:uint = 0):void{ - v = val; - if(averaging>0) + + private function getAppropriateGetValueMethod():Function + { + if(_prop.search(/[^\w\d]/) >= 0) { - if(isNaN(avg)) - { - avg = v; - } - else - { - avg += ((v-avg)/averaging); - } + return executerValueCallback; } + return defaultValueCallback; + } + + private function defaultValueCallback(graph:GraphInterest):Number + { + return obj[_prop]; + } + + private function executerValueCallback(graph:GraphInterest):Number + { + return Executer.Exec(obj, _prop); } + // // // - public function toBytes(bytes:ByteArray):void{ + public function writeToBytes(bytes:ByteArray):void + { bytes.writeUTF(key); bytes.writeUnsignedInt(col); - bytes.writeDouble(v); - bytes.writeDouble(avg); } - public static function FromBytes(bytes:ByteArray):GraphInterest{ + + public static function FromBytes(bytes:ByteArray):GraphInterest + { var interest:GraphInterest = new GraphInterest(bytes.readUTF(), bytes.readUnsignedInt()); - interest.v = bytes.readDouble(); - interest.avg = bytes.readDouble(); return interest; } } diff --git a/src/com/junkbyte/console/vos/GraphMemoryGroup.as b/src/com/junkbyte/console/vos/GraphMemoryGroup.as new file mode 100644 index 0000000..86d8552 --- /dev/null +++ b/src/com/junkbyte/console/vos/GraphMemoryGroup.as @@ -0,0 +1,53 @@ +package com.junkbyte.console.vos +{ + import com.junkbyte.console.Console; + import com.junkbyte.console.console_internal; + + import flash.display.StageAlign; + import flash.system.System; + + use namespace console_internal; + + public class GraphMemoryGroup extends GraphGroup + { + public static const NAME:String = "consoleMemoryGraph"; + + private var console:Console; + + public function GraphMemoryGroup(console:Console) + { + super(NAME); + this.console = console; + + rect.x = 90; + rect.y = 15; + alignRight = true; + + var graph:GraphInterest = new GraphInterest("mb"); + graph.col = 0x6090FF; + + _updateArgs.length = 1; + + interests.push(graph); + freq = 1000; + + menus.push("G"); + + onMenu.add(onMenuClick); + } + + protected function onMenuClick(key:String):void + { + if(key == "G") + { + console.gc(); + } + } + + override protected function dispatchUpdates():void + { + _updateArgs[0] = Math.round(System.totalMemory / 10485.76) / 100; + applyUpdateDispather(_updateArgs); + } + } +} diff --git a/src/com/junkbyte/console/vos/Log.as b/src/com/junkbyte/console/vos/Log.as index fae5ce2..9c8e12b 100644 --- a/src/com/junkbyte/console/vos/Log.as +++ b/src/com/junkbyte/console/vos/Log.as @@ -52,7 +52,7 @@ package com.junkbyte.console.vos { repeat = repeating; html = ishtml; } - public function toBytes(bytes:ByteArray):void{ + public function writeToBytes(bytes:ByteArray):void{ var t:ByteArray = new ByteArray(); t.writeUTFBytes(text);// because writeUTF can't accept more than 65535 bytes.writeUnsignedInt(t.length);