diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUI.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUI.java index eb98f59d..54719890 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUI.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUI.java @@ -273,6 +273,9 @@ public class TerminalUI implements ViewService { if (handler != null) { KeyHandlerResult result = handler.handle(KeyHandler.argsOf(event)); if (result.consumed()) { + if (result.focus() != null) { + setFocus(result.focus()); + } return; } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractView.java index 092345ef..c7d2142f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractView.java @@ -189,16 +189,18 @@ public abstract class AbstractView extends AbstractControl implements View { log.trace("getHotKeyHandler() {}", this); KeyHandler handler = args -> { KeyEvent event = args.event(); + View view = null; boolean consumed = false; Integer key = event.key(); if (key != null) { KeyBindingValue keyBindingValue = getHotKeyBindings().get(key); if (keyBindingValue != null) { + view = this; consumed = dispatchKeyRunCommand(event, keyBindingValue); } } - return KeyHandler.resultOf(event, consumed, null); + return KeyHandler.resultOf(event, consumed, view); }; return handler; } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java index 9f9f02ab..175715dd 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java @@ -106,6 +106,14 @@ public class AbstractViewTests { return view.getKeyHandler().handle(KeyHandler.argsOf(key)); } + protected KeyHandlerResult handleHotKey(View view, Integer key) { + return handleHotKeyEvent(view, KeyEvent.of(key)); + } + + protected KeyHandlerResult handleHotKeyEvent(View view, KeyEvent key) { + return view.getHotKeyHandler().handle(KeyHandler.argsOf(key)); + } + protected MouseEvent mouseClick(int x, int y) { return MouseEvent.of(x, y, MouseEvent.Type.Released | MouseEvent.Button.Button1); } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuBarViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuBarViewTests.java index 4b78a98f..1cb8f706 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuBarViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuBarViewTests.java @@ -15,12 +15,15 @@ */ package org.springframework.shell.component.view.control; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.shell.component.view.control.MenuBarView.MenuBarItem; import org.springframework.shell.component.view.control.MenuView.MenuItem; +import org.springframework.shell.component.view.event.KeyEvent; import org.springframework.shell.component.view.event.KeyEvent.Key; +import org.springframework.shell.component.view.event.KeyHandler.KeyHandlerResult; import org.springframework.shell.component.view.event.MouseEvent; import org.springframework.shell.component.view.event.MouseHandler; import org.springframework.shell.component.view.event.MouseHandler.MouseHandlerResult; @@ -58,6 +61,46 @@ class MenuBarViewTests extends AbstractViewTests { } } + @Nested + class Events { + + MenuBarView view; + + @BeforeEach + void setup() { + MenuItem menuItem = new MenuView.MenuItem("sub1"); + MenuBarItem menuBarItem = new MenuBarView.MenuBarItem("menu1", new MenuView.MenuItem[] { menuItem }); + menuBarItem.setHotKey(Key.q); + view = new MenuBarView(new MenuBarView.MenuBarItem[] { menuBarItem }); + view.setRect(0, 0, 10, 10); + configure(view); + } + + @Test + void mouseClickGetsFocus() { + MouseEvent click = mouseClick(0, 0); + MouseHandlerResult result = view.getMouseHandler().handle(MouseHandler.argsOf(click)); + assertThat(result).isNotNull().satisfies(r -> { + assertThat(r.event()).isEqualTo(click); + assertThat(r.consumed()).isTrue(); + assertThat(r.focus()).isEqualTo(view); + assertThat(r.capture()).isEqualTo(view); + }); + } + + @Test + void hotKeyGetsFocus() { + KeyHandlerResult result = handleHotKey(view, KeyEvent.Key.q); + + assertThat(result).isNotNull().satisfies(r -> { + assertThat(r.event()).isNotNull(); + assertThat(r.consumed()).isTrue(); + assertThat(r.focus()).isEqualTo(view); + }); + } + + } + @Nested class Styling {