// All windows share the same text size (var &mut textSize 16) (var :kiss.List windowStack []) (var &mut :flixel.FlxCamera defaultCamera null) (prop :FlxCamera controlCamera) (prop &mut keyboardEnabled true) // TODO tooltip support with left-click and right-click action // icons and explanations? (defNew [&opt :String _title :FlxColor bgColor :FlxColor _textColor :Float percentWidth :Float percentHeight] [:String title (or _title "") &mut :Float nextControlX 0 &mut :Float nextControlY 0 &mut :Int controlsPerColumn 0 :FlxColor titleColor (or _textColor FlxColor.WHITE) &mut :FlxColor textColor (or _textColor FlxColor.WHITE) :FlxTypedGroup controls (new FlxTypedGroup) :FlxKeyShortcutHandler keyHandler (new FlxKeyShortcutHandler)] (super 0 0) (when defaultCamera (set this.cameras [defaultCamera])) (makeGraphic (Std.int (* FlxG.width (or percentWidth 0.5))) (Std.int (* FlxG.height (or percentHeight 0.5))) (or bgColor FlxColor.BLACK)) (screenCenter) (set controlCamera (new FlxCamera (Std.int x) (Std.int y) (Std.int width) (Std.int height))) (set controlCamera.bgColor FlxColor.TRANSPARENT) // Top-left corner for controls is (0,0) because a camera displays them (set nextControlX 0) (set nextControlY 0) (let [textHeight .height (new FlxText 0 0 0 "a" textSize)] (set controlsPerColumn (Math.floor (/ height textHeight))) (when title (-= controlsPerColumn 1))) (when title (makeText title null)) (set keyHandler.onBadKey ->:Void [_ _] {}) // TODO do SOMETHING (set keyHandler.onSelectItem ->:Void [:ShortcutAction a] { (a) (keyHandler.start) }) // TODO show which shortcuts' prefixes are partially highlighted? ) // TODO could make a camera on the window so the controls are clipped by the camera (method addControl [:FlxSprite control] (set control.cameras [controlCamera]) (set control.x nextControlX) (set control.y nextControlY) (controls.add control) (+= nextControlY control.height) // TODO controls that aren't the same height as text will be able to vertically overflow (let [columnControls (controls.members.slice (if title 1 0))] (when (and columnControls (= 0 (% columnControls.length controlsPerColumn))) (set nextControlY 0) (when title (+= nextControlY control.height)) (+= nextControlX (apply max (for control (last (groups columnControls controlsPerColumn)) control.width)) textSize)))) (prop :Map _actions (new Map)) (prop :Map _colors (new Map)) (method makeText [:String text &opt :FlxColor color :Action onClick :Bool noShortcut] (let [ftext (new FlxText nextControlX nextControlY 0 text textSize)] (set ftext.color (or color textColor)) (dictSet _colors ftext ftext.color) (set ftext.cameras this.cameras) (addControl ftext) (when onClick (dictSet _actions ftext onClick) // TODO right click? (unless noShortcut (keyHandler.registerItem text ->:Void (onClick ftext)))) ftext)) // TODO makeButton // TODO make inputText (prop &mut _shown false) (method isShown [] _shown) (method clearControls [] (_actions.clear) (controls.clear) (keyHandler.clear) (set nextControlX x) (set nextControlY y) (makeText title titleColor)) (method :Void show [] (unless _shown (FlxG.cameras.add controlCamera) (FlxG.state.add this) (FlxG.state.add controls) (windowStack.push this) (keyHandler.start) (set _shown true))) (method :Void hide [] (when _shown (FlxG.cameras.remove controlCamera false) (FlxG.state.remove this) (FlxG.state.remove controls) (windowStack.remove this) (keyHandler.cancel) (set _shown false))) (function getHighlighted [:FlxColor color &opt :Float amount] (unless amount (set amount 0.2)) (cond ((> color.lightness amount) (color.getDarkened amount)) (true (color.getLightened amount)))) (prop &mut otherIsSelected false) (method &override update [:Float elapsed] (super.update elapsed) (set otherIsSelected false) (when (= (last windowStack) this) (when keyboardEnabled (keyHandler.update)) // Handle mouse input (let [mousePos (FlxG.mouse.getScreenPosition controlCamera)] (controls.forEach ->text (whenLet [onClick (dictGet _actions text)] (let [color (dictGet _colors text)] (if (and !otherIsSelected (.containsPoint (text.getScreenBounds controlCamera) mousePos)) { (when FlxG.mouse.justPressed (onClick text)) (set otherIsSelected true) (set text.color (getHighlighted color)) } { (set text.color color) }))))))) (function :SimpleWindow promptForChoice <>[T] [:String prompt :Array choices :T->Void onChoice &opt :FlxColor bgColor :FlxColor titleColor :FlxColor choiceColor :Float percentWidth :Float percentHeight :Bool noShortcuts] (let [window (new SimpleWindow prompt bgColor titleColor percentWidth percentHeight) choiceColor (or choiceColor titleColor FlxColor.WHITE)] (doFor choice choices (window.makeText (Std.string choice) choiceColor ->:Void s { (window.hide) (onChoice choice) } noShortcuts)) (window.show) window))