Make Catalog browsers focusable with shortcuts
- 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
This commit is contained in:
@@ -190,6 +190,7 @@ public class TerminalUI implements ViewService {
|
||||
* @param view the view to configure
|
||||
*/
|
||||
public void configure(View view) {
|
||||
view.init();
|
||||
view.setEventLoop(eventLoop);
|
||||
view.setThemeResolver(themeResolver);
|
||||
view.setThemeName(themeName);
|
||||
|
||||
@@ -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.
|
||||
@@ -88,8 +85,20 @@ public abstract class AbstractView extends AbstractControl implements View {
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,6 +106,9 @@ public abstract class AbstractView extends AbstractControl implements View {
|
||||
* usefull. Typically key and mousebindings are registered from this method.
|
||||
*/
|
||||
protected void initInternal() {
|
||||
if (shortcutKey != null && shortcutAction != null) {
|
||||
registerHotKeyBinding(shortcutKey, shortcutAction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -261,6 +261,28 @@ public class GridView extends BoxView {
|
||||
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() {
|
||||
|
||||
@@ -100,6 +100,7 @@ public class ListView<T> extends BoxView {
|
||||
|
||||
@Override
|
||||
protected void initInternal() {
|
||||
super.initInternal();
|
||||
registerViewCommand(ViewCommand.LINE_UP, () -> up());
|
||||
registerViewCommand(ViewCommand.LINE_DOWN, () -> down());
|
||||
|
||||
|
||||
@@ -247,9 +247,11 @@ public class MenuBarView extends BoxView {
|
||||
|
||||
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();
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.springframework.shell.component.view.event.MouseHandler;
|
||||
*/
|
||||
public interface View extends Control {
|
||||
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Sets a layer index this {@code View} operates on.
|
||||
*
|
||||
|
||||
@@ -47,6 +47,7 @@ public class KeyBinder {
|
||||
|
||||
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'));
|
||||
|
||||
@@ -66,6 +66,7 @@ public class AbstractViewTests {
|
||||
}
|
||||
|
||||
protected void configure(View view) {
|
||||
view.init();
|
||||
if (eventLoop != null) {
|
||||
if (view instanceof AbstractView v) {
|
||||
v.setEventLoop(eventLoop);
|
||||
|
||||
@@ -38,6 +38,7 @@ class TerminalUiSnippets {
|
||||
void sample() {
|
||||
TerminalUI ui = builder.build();
|
||||
BoxView view = new BoxView();
|
||||
ui.configure(view);
|
||||
view.setDrawFunction((screen, rect) -> {
|
||||
screen.writerBuilder()
|
||||
.build()
|
||||
@@ -59,6 +60,7 @@ class TerminalUiSnippets {
|
||||
void sample() {
|
||||
TerminalUI ui = new TerminalUI(terminal);
|
||||
BoxView view = new BoxView();
|
||||
ui.configure(view);
|
||||
ui.setRoot(view, true);
|
||||
EventLoop eventLoop = ui.getEventLoop();
|
||||
eventLoop.keyEvents()
|
||||
|
||||
@@ -207,11 +207,12 @@ public class Catalog {
|
||||
|
||||
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;
|
||||
@@ -242,8 +243,9 @@ public class Catalog {
|
||||
|
||||
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));
|
||||
|
||||
Reference in New Issue
Block a user