174 lines
6.5 KiB
Plaintext
174 lines
6.5 KiB
Plaintext
// All windows share the same text size
|
|
(var &mut textSize 16)
|
|
(var :kiss.List<SimpleWindow> 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<FlxSprite> controls (new FlxTypedGroup)
|
|
:FlxKeyShortcutHandler<ShortcutAction> 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<FlxSprite,Action> _actions (new Map))
|
|
(prop :Map<FlxSprite,FlxColor> _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<T> 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)) |