Add KeyShortcutHandler to every NAT UI, KeyShortcutSystem

This commit is contained in:
2022-07-01 23:36:28 +00:00
parent c21c323292
commit 215bc12692
14 changed files with 102 additions and 23 deletions

View File

@@ -9,7 +9,7 @@ typedef PrefixMapHandler<T> = (Map<String, ShortcutKey<T>>) -> Void;
typedef ItemHandler<T> = (T) -> Void;
typedef FinishHandler = () -> Void;
typedef BadKeyHandler<T> = (String, PrefixMap<T>) -> Void;
typedef BadShortcutHandler<T> = (String,ShortcutKey<T>) -> Void;
typedef BadShortcutHandler<T> = (String, ShortcutKey<T>) -> Void;
enum ShortcutKey<T> {
Final(item:T);

View File

@@ -82,5 +82,4 @@
(method :Void registerItem [description :T item]
(whenLet [keyboardShortcut (extractKeyboardShortcuts description)]
(registerShortcut (keyboardShortcut.split "") description item)))
(registerShortcut (keyboardShortcut.split "") description item)))

View File

@@ -11,6 +11,7 @@
"main": "nat.CLI",
"dependencies": {
"kiss": "",
"kiss-tools": "",
"tink_json": ""
}
}

View File

@@ -160,6 +160,8 @@
(archive.addSystem (new RemarkableAPISystem))
(archive.addSystem (new WikipediaImageSystem))
(archive.addSystem (new ImageAttachmentSystem))
(archive.addSystem (new KeyShortcutSystem this))
// Just for testing:
// (archive.addSystem (new AttachmentSystem ["jpg" "jpeg" "png"] ->[archive e files] ~files))
@@ -199,7 +201,7 @@
(defCommand CreateMediaEntries [medium (Text null) names (VarText null)]
// createEntry returns a list, so these lists must be flattened
(flatten (for name names
(CreateEntry name))))
(CreateMediaEntry medium name))))
// TODO use Tag and VarTag arg types for AddTags and RemoveTags
(defCommand AddTags [entries (SelectedEntries 1 null)
@@ -214,7 +216,15 @@
(removeTags archive e tagsToRemove))
entries) // TODO this includes entries that didn't have the tag in the changeset
(defCommand AddKeyShortcut [e SelectedEntry description (Text null)]
(addComponent archive e KeyShortcut description))
(defCommand AddNATCommand [e (SelectedEntries null null) command (Text null)]
(doFor e e (addComponent archive e NATCommand command)))
(defCommand AddNATCommands [e (SelectedEntries null null) commands (VarText null)]
(doFor e e (addComponent archive e NATCommands commands)))
(defCommand AddFiles [entries (SelectedEntries 1 null)
// TODO add File and Files as an argument type for commands, ArchiveUI
// TODO make tkinter file browser externs and use tkinter as the file picking mechanism for CLI

View File

@@ -1,6 +1,8 @@
package nat;
import nat.Entry;
import nat.ArchiveController;
import kiss_tools.KeyShortcutHandler;
interface ArchiveUI {
/**
@@ -8,6 +10,11 @@ interface ArchiveUI {
*/
var controller(default, default):ArchiveController;
/**
* A KeyShortcutHandler that will integrate with the KeyShortcutSystem if provided
*/
var shortcutHandler(default, null):Null<KeyShortcutHandler<Entry>>;
/**
* Prompt the user to enter text
*/

View File

@@ -13,6 +13,7 @@
(controller.tryRunCommand command))))
(prop &mut :ArchiveController controller)
(prop :KeyShortcutHandler<Entry> shortcutHandler null)
(defNew [])

View File

@@ -0,0 +1,3 @@
package nat.components;
typedef KeyShortcut = String;

View File

@@ -0,0 +1,3 @@
package nat.components;
typedef NATCommand = String;

View File

@@ -0,0 +1,3 @@
package nat.components;
typedef NATCommands = Array<NATCommand>;

View File

@@ -0,0 +1,7 @@
package nat.systems;
import kiss.Prelude;
import kiss.List;
@:build(kiss.Kiss.build())
class KeyShortcutSystem extends System {}

View File

@@ -0,0 +1,32 @@
(load "../Lib.kiss")
(prop :Map<String,Bool> descriptions (new Map))
(defNew [&prop :ArchiveController controller]
[&mut :Bool setup false]
(super
->[archive e]
(hasComponent e KeyShortcut)
->[archive e &opt ui]
{
(when (and ui ui.shortcutHandler)
(unless setup
(set ui.shortcutHandler.onSelectItem (invokeEntry.bind archive ui))
(set ui.shortcutHandler.onBadKey ->[key map] (ui.displayMessage "$key is not mapped to a shortcut in this context: $map"))
(set setup true))
(unless (descriptions.exists (readComponent e KeyShortcut))
(ui.shortcutHandler.registerItem (readComponent e KeyShortcut) e)
(dictSet descriptions (readComponent e KeyShortcut) true)))
0
}))
(method invokeEntry [archive ui :Entry e]
// TODO make this doCond
(cond
((hasComponent e NATCommand)
(controller.tryRunCommand (readComponent e NATCommand)) 0)
((hasComponent e NATCommands)
// TODO chain them together asynchronously (they may be partial)
0)
(true (ui.displayMessage "tried to invoke ${e.id} but it has no available actions"))) 0)

View File

@@ -38,6 +38,7 @@
<haxelib name="flixel" />
<haxelib name="kiss" />
<haxelib name="kiss-tools" />
<haxeflag name="--macro" value="kiss.Kiss.setup()" />
<haxelib name="kiss-flixel" />

View File

@@ -19,6 +19,8 @@ import flixel.addons.plugin.FlxMouseControl;
import flixel.input.mouse.FlxMouseEventManager;
using StringTools;
using kiss_flixel.CameraTools;
import kiss_tools.KeyShortcutHandler;
import kiss_tools.FlxKeyShortcutHandler;
@:build(kiss.Kiss.build())
class PlayState extends FlxState implements ArchiveUI {}

View File

@@ -21,6 +21,7 @@
archive
this)))
(prop :KeyShortcutHandler<Entry> shortcutHandler (new FlxKeyShortcutHandler<Entry>))
(prop &mut :FlxGroup uiGroup (new FlxGroup))
(add uiGroup)
@@ -105,9 +106,13 @@
(archive.processSystems this)
(FlxG.camera.calculateScrollBounds entryGroup SCROLL_BOUND_MARGIN))
(defAlias &ident sh (cast shortcutHandler FlxKeyShortcutHandler<Dynamic>))
(method &override :Void update [:Float elapsed]
(super.update elapsed)
(when sh.currentMap
(sh.update))
(spriteDepthSystem.process archive)
(when FlxG.keys.justPressed.ESCAPE
@@ -142,26 +147,31 @@
(FlxG.camera.updateScrollWheelZoom elapsed 1)
// +/- keys to change an entry's z
(doFor e (controller.getSelectedEntries)
(when FlxG.keys.justPressed.MINUS
(withWritableComponents archive e [positions Positions]
(-= .z (dictGet positions spriteSystem.positionKey) 1)))
(when FlxG.keys.justPressed.PLUS
(withWritableComponents archive e [positions Positions]
(+= .z (dictGet positions spriteSystem.positionKey) 1))))
// Don't check keys that can be used in shortcuts outside this block:
(unless sh.currentMap
(when FlxG.keys.justPressed.SEMICOLON
(sh.start)
(return))
// +/- keys to change an entry's z
(doFor e (controller.getSelectedEntries)
(when FlxG.keys.justPressed.MINUS
(withWritableComponents archive e [positions Positions]
(-= .z (dictGet positions spriteSystem.positionKey) 1)))
(when FlxG.keys.justPressed.PLUS
(withWritableComponents archive e [positions Positions]
(+= .z (dictGet positions spriteSystem.positionKey) 1))))
// don't move the ui camera before ui has been placed -- new UI elements could appear offscreen
(when (> uiGroup.length 0)
(unless (and textInput textInput.hasFocus)
(uiCamera.updateKeyControl
elapsed
KEYBOARD_SCROLL_SPEED
// TODO support dvorak
->{FlxG.keys.pressed.A}
->{FlxG.keys.pressed.D}
->{FlxG.keys.pressed.W}
->{FlxG.keys.pressed.S}))))
// don't move the ui camera before ui has been placed -- new UI elements could appear offscreen
(when (> uiGroup.length 0)
(unless (and textInput textInput.hasFocus)
(uiCamera.updateKeyControl
elapsed
KEYBOARD_SCROLL_SPEED
// TODO support dvorak
->{FlxG.keys.pressed.A}
->{FlxG.keys.pressed.D}
->{FlxG.keys.pressed.W}
->{FlxG.keys.pressed.S})))))
(method :Void typeCommand []
(enterText