diff --git a/flixel/system/debug/completion/CompletionList.hx b/flixel/system/debug/completion/CompletionList.hx index 97d964c13f..f8f4284a65 100644 --- a/flixel/system/debug/completion/CompletionList.hx +++ b/flixel/system/debug/completion/CompletionList.hx @@ -4,19 +4,20 @@ import flixel.math.FlxMath; import openfl.display.Sprite; import openfl.events.KeyboardEvent; import openfl.ui.Keyboard; -using StringTools; + using flixel.util.FlxStringUtil; +using StringTools; class CompletionList extends Sprite { public var completed:String->Void; public var selectionChanged:String->Void; public var closed:Void->Void; - + public var filter(default, set):String; - + public var items(default, null):Array; - + var entries:Array = []; var originalItems:Array; var selectedIndex:Int = 0; @@ -24,44 +25,44 @@ class CompletionList extends Sprite var upperVisibleIndex:Int = 0; var scrollBar:CompletionListScrollBar; var actualHeight:Int; - + public function new(capacity:Int) { super(); - + visible = false; upperVisibleIndex = capacity - 1; actualHeight = capacity * CompletionListEntry.HEIGHT; - + createPopupEntries(capacity); createScrollBar(); updateSelectedItem(); } - + public function show(x:Float, items:Array) { visible = true; this.x = x; this.originalItems = items; filter = ""; - + updateEntries(); } - + public function setY(y:Float) { this.y = y - actualHeight; } - + public function close() { visible = false; filter = null; - + if (closed != null) closed(); } - + function createPopupEntries(amount:Int) { for (i in 0...amount) @@ -72,73 +73,73 @@ class CompletionList extends Sprite entry.y = CompletionListEntry.HEIGHT * i; } } - + function createScrollBar() { scrollBar = new CompletionListScrollBar(CompletionListEntry.WIDTH, 0, 5, actualHeight); addChild(scrollBar); } - + public function onKeyDown(e:KeyboardEvent) { if (!visible) return; - + switch (e.keyCode) { case Keyboard.DOWN: updateIndices(1); - + case Keyboard.UP: updateIndices(-1); - + case Keyboard.ENTER | Keyboard.TAB: if (completed != null) completed(items[selectedIndex]); close(); return; - + case Keyboard.ESCAPE: close(); return; } - + updateEntries(); } - + function updateIndices(modifier:Int) { selectedIndex = bound(selectedIndex + modifier); if (FlxMath.inBounds(selectedIndex, lowerVisibleIndex, upperVisibleIndex)) return; - + // scroll visible area lowerVisibleIndex = bound(lowerVisibleIndex + modifier); upperVisibleIndex = bound(upperVisibleIndex + modifier); var range = upperVisibleIndex - lowerVisibleIndex; - + if (range == items.length) return; - + // hit lower or upper end if (lowerVisibleIndex == 0) upperVisibleIndex = entries.length - 1; else if (upperVisibleIndex == items.length - 1) lowerVisibleIndex = items.length - entries.length; } - + function bound(index:Int) { return Std.int(FlxMath.bound(index, 0, items.length - 1)); } - + function updateEntries() { updateLabels(); updateSelectedItem(); scrollBar.updateHandle(lowerVisibleIndex, items.length, entries.length); } - + function updateLabels() { for (i in 0...entries.length) @@ -149,43 +150,43 @@ class CompletionList extends Sprite entries[i].setItem(selectedItem); } } - + function updateSelectedItem() { for (entry in entries) entry.selected = false; entries[selectedIndex - lowerVisibleIndex].selected = true; - + if (selectionChanged != null) selectionChanged(items[selectedIndex]); } - + function setItems(items:Array) { if (items == null) return; if (items.length == 0) close(); - + this.items = items; - + selectedIndex = 0; lowerVisibleIndex = 0; upperVisibleIndex = entries.length - 1; updateEntries(); } - + function filterItems(filter:String):Array { if (filter == null) filter = ""; - + return sortItems(filter, originalItems.filter(function(item) { return item.toLowerCase().contains(filter.toLowerCase()); })); } - + /** * sort items so that: * - strings starting with the filter have a higher priority than those only containing it @@ -195,7 +196,7 @@ class CompletionList extends Sprite { if (filter == "") return items; - + items.sort(function(a, b) { var valueA = startsWithExt(a, filter); @@ -204,14 +205,14 @@ class CompletionList extends Sprite return -valueA; if (valueB > valueA) return valueB; - + if (valueA == valueB) return Std.int(a.length - b.length); return 0; }); return items; } - + /** * Custom startsWith() that ignores leading underscores. */ @@ -223,12 +224,12 @@ class CompletionList extends Sprite return 1; return 0; } - + function set_filter(filter:String):String { if (filter == this.filter) return filter; - + setItems(filterItems(filter)); return this.filter = filter; } diff --git a/flixel/system/debug/console/Console.hx b/flixel/system/debug/console/Console.hx index 26fdd978c6..251f757a8b 100644 --- a/flixel/system/debug/console/Console.hx +++ b/flixel/system/debug/console/Console.hx @@ -1,14 +1,14 @@ package flixel.system.debug.console; #if FLX_DEBUG +import openfl.text.TextField; +import openfl.text.TextFormat; import flixel.FlxG; import flixel.FlxObject; import flixel.system.debug.FlxDebugger.GraphicConsole; -import flixel.system.debug.completion.CompletionHandler; import flixel.system.debug.completion.CompletionList; +import flixel.system.debug.completion.CompletionHandler; import flixel.util.FlxStringUtil; -import openfl.text.TextField; -import openfl.text.TextFormat; #if (!next && sys) import openfl.events.MouseEvent; #end @@ -17,6 +17,7 @@ import openfl.events.FocusEvent; import openfl.events.KeyboardEvent; import openfl.text.TextFieldType; import openfl.ui.Keyboard; + using StringTools; #end @@ -31,41 +32,41 @@ class Console extends Window * The text that is displayed in the console's input field by default. */ static inline var DEFAULT_TEXT:String = #if hscript "(Click here / press [Tab] to enter command. Type 'help' for help.)" #else "Using the console requires hscript - please run 'haxelib install hscript'." #end; - + /** * Map containing all registered Objects. You can use registerObject() or add them directly to this map. */ public var registeredObjects:Map = new Map(); - + /** * Map containing all registered Functions. You can use registerFunction() or add them directly to this map. */ public var registeredFunctions:Map = new Map(); - + /** * Map containing all registered help text. Set these values from registerObject() or registerFunction(). */ public var registeredHelp:Map = new Map(); - + /** * Internal helper var containing all the FlxObjects created via the create command. */ public var objectStack:Array = []; - + /** * The input textfield used to enter commands. */ var input:TextField; - + #if (!next && sys) var inputMouseDown:Bool = false; var stageMouseDown:Bool = false; #end - + public var history:ConsoleHistory; - + var completionList:CompletionList; - + /** * Creates a new console window object. */ @@ -74,22 +75,22 @@ class Console extends Window super("Console", new GraphicConsole(0, 0), 0, 0, false); this.completionList = completionList; completionList.setY(y + Window.HEADER_HEIGHT); - + #if hscript ConsoleUtil.init(); #end - + history = new ConsoleHistory(); createInputTextField(); new CompletionHandler(completionList, input); registerEventListeners(); - + // Install commands #if FLX_DEBUG new ConsoleCommands(this); #end } - + function createInputTextField() { // Create the input textfield @@ -103,7 +104,7 @@ class Console extends Window input.y = 15; addChild(input); } - + function registerEventListeners() { #if hscript @@ -111,7 +112,7 @@ class Console extends Window input.addEventListener(FocusEvent.FOCUS_IN, onFocus); input.addEventListener(FocusEvent.FOCUS_OUT, onFocusLost); input.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); - + #if !flash // openfl/openfl#1856 FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent) @@ -121,7 +122,7 @@ class Console extends Window }); #end #end - + #if (!next && sys) // workaround for broken TextField focus on native input.addEventListener(MouseEvent.MOUSE_DOWN, function(_) { @@ -133,25 +134,25 @@ class Console extends Window }); #end } - + #if (!next && sys) @:access(flixel.FlxGame.onFocus) override public function update() { super.update(); - + if (FlxG.stage.focus == input && stageMouseDown && !inputMouseDown) { FlxG.stage.focus = null; // setting focus to null will trigger a focus lost event, let's undo that FlxG.game.onFocus(null); } - + stageMouseDown = false; inputMouseDown = false; } #end - + @:access(flixel.FlxGame) function onFocus(_) { @@ -159,17 +160,17 @@ class Console extends Window // Pause game if (FlxG.console.autoPause) FlxG.vcr.pause(); - + // Block keyboard input #if FLX_KEYBOARD FlxG.keys.enabled = false; #end - + if (input.text == Console.DEFAULT_TEXT) input.text = ""; #end } - + @:access(flixel.FlxGame) function onFocusLost(_) { @@ -177,83 +178,82 @@ class Console extends Window // Unpause game if (FlxG.console.autoPause && !FlxG.game.debugger.vcr.manualPause) FlxG.vcr.resume(); - + // Unblock keyboard input #if FLX_KEYBOARD FlxG.keys.enabled = true; #end - + if (input.text == "") input.text = Console.DEFAULT_TEXT; #end - + completionList.close(); FlxG.game.debugger.onMouseFocusLost(); } - + #if hscript function onKeyDown(e:KeyboardEvent) { - if (completionList.visible) { completionList.onKeyDown(e); return; } - + switch (e.keyCode) { case Keyboard.ENTER: if (input.text != "") processCommand(); - + case Keyboard.ESCAPE: FlxG.stage.focus = null; - + case Keyboard.DELETE: input.text = ""; - + case Keyboard.UP: if (!history.isEmpty) setText(history.getPreviousCommand()); - + case Keyboard.DOWN: if (!history.isEmpty) setText(history.getNextCommand()); } } - + function setText(text:String) { input.text = text; // Set caret to the end of the command input.setSelection(text.length, text.length); } - + function processCommand() { try { var text = input.text.trim(); - + // Force registered functions to have "()" if the command doesn't already include them // so when the user types "help" or "resetGame", something useful happens if (registeredFunctions.get(text) != null) text += "()"; - + // Attempt to parse, run, and output the command var output = ConsoleUtil.runCommand(text); if (output != null) ConsoleUtil.log(output); - + history.addCommand(input.text); - + // Step forward one frame to see the results of the command #if FLX_DEBUG if (FlxG.vcr.paused && FlxG.console.stepAfterCommand) FlxG.game.debugger.vcr.onStep(); #end - + input.text = ""; } catch (e:Dynamic) @@ -262,7 +262,7 @@ class Console extends Window FlxG.log.error("Console: Invalid syntax: '" + e + "'"); } } - + override public function reposition(x:Float, y:Float) { super.reposition(x, y); @@ -270,7 +270,7 @@ class Console extends Window completionList.close(); } #end - + /** * Register a new function to use in any command. * @@ -284,11 +284,11 @@ class Console extends Window #if hscript ConsoleUtil.registerFunction(alias, func); #end - + if (helpText != null) registeredHelp.set(alias, helpText); } - + /** * Register a new object to use in any command. * @@ -302,7 +302,7 @@ class Console extends Window ConsoleUtil.registerObject(alias, object); #end } - + /** * Removes an object or function from the command registry. * @@ -317,7 +317,7 @@ class Console extends Window ConsoleUtil.removeByAlias(alias); #end } - + /** * Removes an object from the command registry by searching through the list. * @@ -340,7 +340,7 @@ class Console extends Window } } } - + /** * Removes a function from the command registry by searching through the list. * @@ -363,7 +363,7 @@ class Console extends Window } } } - + /** * Register a new class to use in any command. * @@ -373,7 +373,7 @@ class Console extends Window { registerObject(FlxStringUtil.getClassName(c, true), c); } - + /** * Removes a class from the command registry. * @@ -384,7 +384,7 @@ class Console extends Window { removeByAlias(FlxStringUtil.getClassName(c, true)); } - + /** * Register a new enum to use in any command. * @@ -395,7 +395,7 @@ class Console extends Window { registerObject(FlxStringUtil.getEnumName(e, true), e); } - + /** * Removes an enum from the command registry. * @@ -406,37 +406,37 @@ class Console extends Window { removeByAlias(FlxStringUtil.getEnumName(e, true)); } - + override public function destroy() { super.destroy(); - + #if hscript input.removeEventListener(FocusEvent.FOCUS_IN, onFocus); input.removeEventListener(FocusEvent.FOCUS_OUT, onFocusLost); input.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); #end - + if (input != null) { removeChild(input); input = null; } - + registeredObjects = null; registeredFunctions = null; registeredHelp = null; - + objectStack = null; } - + /** * Adjusts the width and height of the text field accordingly. */ override function updateSize() { super.updateSize(); - + input.width = _width - 4; input.height = _height - 15; }