Skip to content

Commit

Permalink
Make Catalog browsers focusable with shortcuts
Browse files Browse the repository at this point in the history
- Category and scenario list views can now be focused with
  ctrl+a/ctrl+s.
- Bind all keys with ctrl modifier
- Add "shortcut" concept to views which currently hooks to
  hot keys.
- In a catalog app by using a "shortcut" then takes the key
  event as a hot key, as it consumes resulting behaviour
  is to focus.
- Move view initInternal away from constructor call to
  require user to call init() which is not in a
  View interface
- Relates #826
  • Loading branch information
jvalkeal committed Nov 12, 2023
1 parent a9b1675 commit 2d29050
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public ViewService getViewService() {
* @param view the view to configure
*/
public void configure(View view) {
view.init();
view.setEventLoop(eventLoop);
view.setThemeResolver(themeResolver);
view.setThemeName(themeName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ public abstract class AbstractView extends AbstractControl implements View {
private Map<Integer, KeyBindingValue> keyBindings = new HashMap<>();
private Map<Integer, KeyBindingValue> hotKeyBindings = new HashMap<>();
private Map<Integer, MouseBindingValue> mouseBindings = new HashMap<>();

public AbstractView() {
init();
}
private boolean init = false;

/**
* Register {@link Disposable} to get disposed when view terminates.
Expand All @@ -88,15 +85,30 @@ public void destroy() {
*
* @see #initInternal()
*/
protected final void init() {
@Override
public final void init() {
if (init) {
return;
}
initInternal();
init = true;
}

private Integer shortcutKey;
private Runnable shortcutAction;
public void shortcut(Integer key, Runnable runnable) {
this.shortcutKey = key;
this.shortcutAction = runnable;
}

/**
* Internal init method called from {@link #init()}. Override to do something
* usefull. Typically key and mousebindings are registered from this method.
*/
protected void initInternal() {
if (shortcutKey != null && shortcutAction != null) {
registerHotKeyBinding(shortcutKey, shortcutAction);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,28 @@ public KeyHandler getKeyHandler() {
return super.getKeyHandler();
}

@Override
public KeyHandler getHotKeyHandler() {
log.trace("getHotKeyHandler()");
KeyHandler handler = null;
for (GridItem i : gridItems) {
if (handler == null) {
handler = i.view.getHotKeyHandler();
}
else {
handler = handler.thenIfNotConsumed(i.view.getHotKeyHandler());
}
// handler = i.view.getHotKeyHandler();
// if (i.view.hasFocus()) {
// handler = i.view.getHotKeyHandler();
// break;
// }
}
if (handler != null) {
return handler.thenIfNotConsumed(super.getHotKeyHandler());
}
return super.getHotKeyHandler();
}

@Override
public boolean hasFocus() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public ListView(@Nullable List<T> items, ItemStyle itemStyle) {

@Override
protected void initInternal() {
super.initInternal();
registerViewCommand(ViewCommand.LINE_UP, () -> up());
registerViewCommand(ViewCommand.LINE_DOWN, () -> down());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,11 @@ private void closeCurrentMenuView() {

private MenuView buildMenuView(MenuBarItem item) {
MenuView menuView = new MenuView(item.getItems());
menuView.init();
menuView.setEventLoop(getEventLoop());
menuView.setThemeResolver(getThemeResolver());
menuView.setThemeName(getThemeName());
menuView.setViewService(getViewService());
menuView.setShowBorder(true);
menuView.setLayer(1);
Rectangle rect = getInnerRect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
*/
public interface View extends Control {

void init();

/**
* Sets a layer index this {@code View} operates on.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public void bindAll(KeyMap<Integer> keyMap) {

for (char i = KeyEvent.Key.a; i <= KeyEvent.Key.z; i++) {
keyMap.bind(i | KeyEvent.KeyMask.AltMask, alt(i));
keyMap.bind(i | KeyEvent.KeyMask.CtrlMask, ctrl(i));
}

keyMap.bind(KeyEvent.Key.q | KeyEvent.KeyMask.CtrlMask, ctrl('q'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ protected void clearScreens() {
}

protected void configure(View view) {
view.init();
if (eventLoop != null) {
if (view instanceof AbstractView v) {
v.setEventLoop(eventLoop);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SampleIntro {
void sample() {
TerminalUI ui = builder.build();
BoxView view = new BoxView();
ui.configure(view);
view.setDrawFunction((screen, rect) -> {
screen.writerBuilder()
.build()
Expand All @@ -59,6 +60,7 @@ class Sample3 {
void sample() {
TerminalUI ui = new TerminalUI(terminal);
BoxView view = new BoxView();
ui.configure(view);
ui.setRoot(view, true);
EventLoop eventLoop = ui.getEventLoop();
eventLoop.keyEvents()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,12 @@ private AppView buildScenarioBrowser(EventLoop eventLoop, TerminalUI component)

private ListView<String> buildCategorySelector() {
ListView<String> categories = new ListView<>();
categories.shortcut(Key.a | KeyMask.CtrlMask, () -> {});
ui.configure(categories);

List<String> items = List.copyOf(categoryMap.keySet());
categories.setItems(items);
categories.setTitle("Categories");
categories.setTitle("Categories (CTRL+A)");
categories.setFocusedTitleStyle(ScreenItem.STYLE_BOLD);
categories.setShowBorder(true);
return categories;
Expand Down Expand Up @@ -242,8 +243,9 @@ protected void drawContent(Screen screen) {

private ListView<ScenarioData> buildScenarioSelector() {
ListView<ScenarioData> scenarios = new ListView<>();
scenarios.shortcut(Key.s | KeyMask.CtrlMask, () -> {});
ui.configure(scenarios);
scenarios.setTitle("Scenarios");
scenarios.setTitle("Scenarios (CTRL+S)");
scenarios.setFocusedTitleStyle(ScreenItem.STYLE_BOLD);
scenarios.setShowBorder(true);
scenarios.setCellFactory((list, item) -> new ScenarioListCell(item));
Expand Down

0 comments on commit 2d29050

Please sign in to comment.