fujaba / fulibFx

A framework for JavaFX applications that is designed for MVC pattern projects.
https://fujaba.github.io/fulibFx/
MIT License
2 stars 0 forks source link

Annotation for global key handlers #48

Closed Clashsoft closed 8 months ago

Clashsoft commented 8 months ago

Is your feature request related to a problem? Please describe. Some apps require keyboard shortcuts that cannot be reasonably attached to a node. Usually that is because the node in question is not focusable. An annotation to create global key listeners (as implemented below) would be helpful.

Describe the solution you'd like

class MyController {
  private final BooleanProperty paused = new SimpleBooleanProperty(false);

  @OnKey(code = KeyCode.ESCAPE)
  void onEscape() {
    paused.set(true);
  }
}

Describe alternatives you've considered

class MyController {
    private final BooleanProperty paused = new SimpleBooleanProperty(false);
    private final EventHandler<KeyEvent> onKeyReleased = event -> {
        if (event.getCode() == KeyCode.ESCAPE) {
            paused.set(true);
        }
    };

    @onRender
    void addKeyReleased() {
        app.stage().addEventFilter(KeyEvent.KEY_RELEASED, onKeyReleased);
    }

    @onDestroy
    void removeKeyReleased() {
        app.stage().removeEventFilter(KeyEvent.KEY_RELEASED, onKeyReleased);
    }
}

Detailed description The @OnKey annotation could be defined like this:

@interface OnKey {
  KeyCode code() = KeyCode.UNDEFINED;
  EventType type() = KeyEvent.KEY_PRESSED; // see https://docs.oracle.com/javase/8/javafx/api/javafx/scene/input/KeyEvent.html
  String character() = "";
  String text() = "";
  boolean shiftDown, boolean controlDown, boolean altDown, boolean metaDown
}

The method should optionally allow a KeyEvent parameter (just like methods called from FXML). It could be used to inspect the event in case the KeyCode is dynamic/configurable.

@OnKey
void onKey(KeyEvent event) {
  if (event.getCode() == keyMappings.getCode(KeyMapping.WALK_FORWARD) {
    // ...
  }
}
LeStegii commented 8 months ago

I like the idea, this would certainly remove a lot of boilerplate code. However, I got a few questions:

Clashsoft commented 8 months ago

I changed it to @OnKey everywhere. The different key event types would need to be an enum. But there are only a few cases so it should be ok. Example:

@interface OnKey {
  enum Type { ANY, PRESSED, RELEASED, TYPED };
  Type type() = PRESSED;
}