Initial modal integration

- Integrate TerminalUI to ViewService and modals
- New Dialog scenario
- Relates #825
This commit is contained in:
Janne Valkealahti
2023-08-21 09:37:05 +03:00
parent f9283ae83b
commit 29417d495b
5 changed files with 99 additions and 11 deletions

View File

@@ -35,6 +35,7 @@ import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.shell.component.view.control.View;
import org.springframework.shell.component.view.control.ViewService;
import org.springframework.shell.component.view.event.DefaultEventLoop;
import org.springframework.shell.component.view.event.EventLoop;
import org.springframework.shell.component.view.event.KeyBinder;
@@ -60,7 +61,7 @@ import org.springframework.util.StringUtils;
*
* @author Janne Valkealahti
*/
public class TerminalUI {
public class TerminalUI implements ViewService {
private final static Logger log = LoggerFactory.getLogger(TerminalUI.class);
private final Terminal terminal;
@@ -70,6 +71,7 @@ public class TerminalUI {
private Display display;
private Size size;
private View rootView;
private View modalView;
private boolean fullScreen;
private final KeyBinder keyBinder;
private DefaultEventLoop eventLoop = new DefaultEventLoop();
@@ -87,6 +89,16 @@ public class TerminalUI {
this.keyBinder = new KeyBinder(terminal);
}
@Override
public View getModal() {
return modalView;
}
@Override
public void setModal(View view) {
this.modalView = view;
}
/**
* Sets a root view.
*
@@ -137,11 +149,15 @@ public class TerminalUI {
}
private void render(int rows, int columns) {
if (rootView == null) {
return;
if (rootView != null) {
rootView.setRect(0, 0, columns, rows);
rootView.draw(virtualDisplay);
}
if (modalView != null) {
modalView.setLayer(1);
modalView.setRect(0, 0, columns, rows);
modalView.draw(virtualDisplay);
}
rootView.setRect(0, 0, columns, rows);
rootView.draw(virtualDisplay);
}
private void display() {
@@ -254,8 +270,9 @@ public class TerminalUI {
private void handleMouseEvent(MouseEvent event) {
log.trace("handleMouseEvent {}", event);
if (rootView != null) {
MouseHandler handler = rootView.getMouseHandler();
View view = modalView != null ? modalView : rootView;
if (view != null) {
MouseHandler handler = view.getMouseHandler();
if (handler != null) {
MouseHandlerResult result = handler.handle(MouseHandler.argsOf(event));
if (result.focus() != null) {

View File

@@ -180,7 +180,7 @@ public class Catalog {
eventLoop.onDestroy(eventLoop.viewEvents(LISTVIEW_SCENARIO_TYPEREF, scenarios)
.subscribe(event -> {
View view = event.args().item().scenario()
.configure(eventLoop, themeResolver, activeThemeName)
.configure(ui, eventLoop, themeResolver, activeThemeName)
.build();
component.setRoot(view, true);
currentScenarioView = view;
@@ -273,8 +273,12 @@ public class Catalog {
return () -> setStyle(style);
}
private void about() {
}
private MenuBarView buildMenuBar(EventLoop eventLoop) {
Runnable quitAction = () -> requestQuit();
Runnable aboutAction = () -> about();
MenuItem[] themeItems = themeResolver.themeNames().stream()
.map(tn -> {
return MenuItem.of(tn, MenuItemCheckStyle.RADIO, styleAction(tn), "default".equals(tn));
@@ -288,7 +292,7 @@ public class Catalog {
themeItems)
.setHotKey(Key.t | KeyMask.AltMask),
MenuBarItem.of("Help",
MenuItem.of("About"))
MenuItem.of("About", MenuItemCheckStyle.NOCHECK, aboutAction))
);
menuBar.setThemeResolver(themeResolver);

View File

@@ -16,6 +16,7 @@
package org.springframework.shell.samples.catalog.scenario;
import org.springframework.shell.component.view.control.AbstractView;
import org.springframework.shell.component.view.control.ViewService;
import org.springframework.shell.component.view.event.EventLoop;
import org.springframework.shell.style.ThemeResolver;
@@ -26,18 +27,24 @@ import org.springframework.shell.style.ThemeResolver;
*/
public abstract class AbstractScenario implements Scenario {
private ViewService viewService;
private EventLoop eventloop;
private ThemeResolver themeResolver;
private String themeName;
@Override
public Scenario configure(EventLoop eventloop, ThemeResolver themeResolver, String themeName) {
public Scenario configure(ViewService viewService, EventLoop eventloop, ThemeResolver themeResolver, String themeName) {
this.viewService = viewService;
this.eventloop = eventloop;
this.themeResolver = themeResolver;
this.themeName = themeName;
return this;
}
protected ViewService getViewService() {
return viewService;
}
protected EventLoop getEventloop() {
return eventloop;
}

View File

@@ -16,6 +16,7 @@
package org.springframework.shell.samples.catalog.scenario;
import org.springframework.shell.component.view.control.View;
import org.springframework.shell.component.view.control.ViewService;
import org.springframework.shell.component.view.event.EventLoop;
import org.springframework.shell.style.ThemeResolver;
@@ -48,6 +49,6 @@ public interface Scenario {
* @param themeName theme name for scenario
* @return scenario for chaining
*/
Scenario configure(EventLoop eventloop, ThemeResolver themeResolver, String themeName);
Scenario configure(ViewService viewService, EventLoop eventloop, ThemeResolver themeResolver, String themeName);
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.shell.samples.catalog.scenario.other;
import org.springframework.shell.component.view.control.BoxView;
import org.springframework.shell.component.view.control.ButtonView;
import org.springframework.shell.component.view.control.DialogView;
import org.springframework.shell.component.view.control.View;
import org.springframework.shell.component.view.geom.HorizontalAlign;
import org.springframework.shell.component.view.geom.VerticalAlign;
import org.springframework.shell.samples.catalog.scenario.AbstractScenario;
import org.springframework.shell.samples.catalog.scenario.Scenario;
import org.springframework.shell.samples.catalog.scenario.ScenarioComponent;
@ScenarioComponent(name = "Dialog", description = "Modal dialog", category = {
Scenario.CATEGORY_OTHER })
public class DialogScenario extends AbstractScenario {
private Runnable dialogAction = () -> {
DialogView dialog = buildDialog();
getViewService().setModal(dialog);
};
@Override
public View build() {
ButtonView button = new ButtonView("Open Dialog", dialogAction);
configure(button);
return button;
}
private DialogView buildDialog() {
ButtonView button = new ButtonView("OK");
configure(button);
BoxView content = new BoxView();
content.setDrawFunction((screen, rect) -> {
screen.writerBuilder().layer(1).build().text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER);
return rect;
});
DialogView dialog = new DialogView(content, button);
configure(dialog);
dialog.setTransparent(false);
dialog.setViewService(getViewService());
return dialog;
}
}