From 2b18de0ffb9eb33635781455852b4975db88f4f8 Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Tue, 7 May 2024 08:05:45 +0100 Subject: [PATCH] Fix fg and bg styling - In ListView and MenuView fix how styling for background and foreground are used. - In Catalog app fix same issue in ScenarioListCell - Fixes #1063 --- .../component/view/control/ListView.java | 7 +- .../component/view/control/MenuView.java | 20 ++++-- .../component/view/control/ListViewTests.java | 66 ++++++++++++++++- .../component/view/control/MenuViewTests.java | 71 ++++++++++++++++++- .../shell/samples/catalog/Catalog.java | 2 +- 5 files changed, 155 insertions(+), 11 deletions(-) diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ListView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ListView.java index fa83b53e..8b239e4f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ListView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ListView.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 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. @@ -169,6 +169,8 @@ public class ListView extends BoxView { Rectangle rect = getInnerRect(); int y = rect.y(); int selectedStyle = resolveThemeStyle(StyleSettings.TAG_HIGHLIGHT, ScreenItem.STYLE_BOLD); + int selectedForegroundColor = resolveThemeForeground(StyleSettings.TAG_HIGHLIGHT, -1, -1); + int selectedBackgroundColor = resolveThemeBackground(StyleSettings.TAG_HIGHLIGHT, -1, -1); int i = 0; for (ListCell c : cells) { @@ -178,10 +180,13 @@ public class ListView extends BoxView { } c.setRect(rect.x(), y++, rect.width(), 1); if (i == start + pos) { + c.setForegroundColor(selectedForegroundColor); + c.setBackgroundColor(selectedBackgroundColor); c.setStyle(selectedStyle); } else { c.setBackgroundColor(-1); + c.setForegroundColor(-1); c.setStyle(-1); } c.draw(screen); diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuView.java index fe06723f..b41fc09e 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuView.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 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. @@ -143,9 +143,15 @@ public class MenuView extends BoxView { protected void drawInternal(Screen screen) { Rectangle rect = getInnerRect(); int y = rect.y(); - Writer writer = screen.writerBuilder().layer(getLayer()).build(); - int themeStyle = resolveThemeStyle(StyleSettings.TAG_HIGHLIGHT, ScreenItem.STYLE_BOLD); - Writer writer2 = screen.writerBuilder().layer(getLayer()).style(themeStyle).build(); + int selectedStyle = resolveThemeStyle(StyleSettings.TAG_HIGHLIGHT, ScreenItem.STYLE_BOLD); + int selectedForegroundColor = resolveThemeForeground(StyleSettings.TAG_HIGHLIGHT, -1, -1); + int selectedBackgroundColor = resolveThemeBackground(StyleSettings.TAG_HIGHLIGHT, -1, -1); + Writer writer = screen.writerBuilder() + .layer(getLayer()).build(); + Writer selectedWriter = screen.writerBuilder() + .layer(getLayer()) + .color(selectedForegroundColor) + .style(selectedStyle).build(); int i = 0; boolean hasCheck = false; for (MenuItem item : items) { @@ -174,7 +180,11 @@ public class MenuView extends BoxView { } String text = prefix + item.getTitle(); if (activeItemIndex == i) { - writer2.text(text, rect.x(), y); + selectedWriter.text(text, rect.x(), y); + if (selectedBackgroundColor > -1) { + Rectangle itemRect = new Rectangle(rect.x(), y, rect.width(), 1); + selectedWriter.background(itemRect, selectedBackgroundColor); + } } else { writer.text(text, rect.x(), y); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ListViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ListViewTests.java index 40d53483..bcd6ab04 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ListViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ListViewTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 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. @@ -35,9 +35,15 @@ import org.springframework.shell.component.view.event.KeyHandler.KeyHandlerResul 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; +import org.springframework.shell.component.view.screen.Color; import org.springframework.shell.component.view.screen.Screen; import org.springframework.shell.component.view.screen.Screen.Writer; import org.springframework.shell.geom.Rectangle; +import org.springframework.shell.style.StyleSettings; +import org.springframework.shell.style.Theme; +import org.springframework.shell.style.ThemeRegistry; +import org.springframework.shell.style.ThemeResolver; +import org.springframework.shell.style.ThemeSettings; import static org.assertj.core.api.Assertions.assertThat; @@ -52,6 +58,38 @@ class ListViewTests extends AbstractViewTests { private static final String SCROLL_METHOD = "scrollIndex"; ListView view; + ThemeResolver themeResolver; + + @BeforeEach + public void setupListView() { + ThemeRegistry themeRegistry = new ThemeRegistry(); + themeRegistry.register(new Theme() { + @Override + public String getName() { + return "default"; + } + + @Override + public ThemeSettings getSettings() { + + return new ThemeSettings() { + @Override + public StyleSettings styles() { + return new StyleSettings() { + @Override + public String highlight() { + return "bold,italic,bg-rgb:#0000FF,fg-rgb:#FF0000"; + } + }; + } + }; + } + }); + + themeResolver = new ThemeResolver(themeRegistry, "default"); + } + + @Nested class Events { @@ -189,6 +227,32 @@ class ListViewTests extends AbstractViewTests { assertThat(forScreen(screen24x80)).hasBorder(0, 0, 80, 24); } + @Test + void selectedHighlightNoTheme() { + view = new ListView<>(); + view.setShowBorder(true); + view.setRect(0, 0, 10, 7); + view.setItems(Arrays.asList("item1", "item2", "item3")); + view.draw(screen7x10); + assertThat(forScreen(screen7x10)).hasStyle(1, 1, 1); + assertThat(forScreen(screen7x10)).hasForegroundColor(1, 1, -1); + assertThat(forScreen(screen7x10)).hasBackgroundColor(1, 1, -1); + } + + @Test + void selectedHighlightThemeSet() { + view = new ListView<>(); + view.setThemeResolver(themeResolver); + view.setThemeName("default"); + view.setShowBorder(true); + view.setRect(0, 0, 10, 7); + view.setItems(Arrays.asList("item1", "item2", "item3")); + view.draw(screen7x10); + assertThat(forScreen(screen7x10)).hasStyle(1, 1, 5); + assertThat(forScreen(screen7x10)).hasForegroundColor(1, 1, Color.RED); + assertThat(forScreen(screen7x10)).hasBackgroundColor(1, 1, Color.BLUE); + } + @Test void showingAllCells() { view = new ListView<>(); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuViewTests.java index 5681b8ea..295ea823 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuViewTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 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. @@ -32,6 +32,12 @@ import org.springframework.shell.component.view.control.MenuView.MenuViewSelecte import org.springframework.shell.component.view.event.KeyEvent.Key; import org.springframework.shell.component.view.event.MouseEvent; import org.springframework.shell.component.view.event.MouseHandler.MouseHandlerResult; +import org.springframework.shell.component.view.screen.Color; +import org.springframework.shell.style.StyleSettings; +import org.springframework.shell.style.Theme; +import org.springframework.shell.style.ThemeRegistry; +import org.springframework.shell.style.ThemeResolver; +import org.springframework.shell.style.ThemeSettings; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -42,6 +48,37 @@ class MenuViewTests extends AbstractViewTests { private static final String RADIO_ACTIVE_FIELD = "radioActive"; private static final String CHECKED_ACTIVE_FIELD = "checkedActive"; + ThemeResolver themeResolver; + + @BeforeEach + public void setupMenuView() { + ThemeRegistry themeRegistry = new ThemeRegistry(); + themeRegistry.register(new Theme() { + @Override + public String getName() { + return "default"; + } + + @Override + public ThemeSettings getSettings() { + + return new ThemeSettings() { + @Override + public StyleSettings styles() { + return new StyleSettings() { + @Override + public String highlight() { + return "bold,italic,bg-rgb:#0000FF,fg-rgb:#FF0000"; + } + }; + } + }; + } + }); + + themeResolver = new ThemeResolver(themeRegistry, "default"); + } + @Nested class Construction { @@ -127,20 +164,48 @@ class MenuViewTests extends AbstractViewTests { @Nested class Styling { + MenuView view; + @Test void hasBorder() { MenuItem menuItem = new MenuView.MenuItem("sub1"); - MenuView view = new MenuView(Arrays.asList(menuItem)); + view = new MenuView(Arrays.asList(menuItem)); view.setShowBorder(true); view.setRect(0, 0, 80, 24); view.draw(screen24x80); assertThat(forScreen(screen24x80)).hasBorder(0, 0, 80, 24); } + @Test + void selectedHighlightNoTheme() { + MenuItem menuItem = new MenuView.MenuItem("sub1"); + view = new MenuView(Arrays.asList(menuItem)); + view.setShowBorder(true); + view.setRect(0, 0, 10, 7); + view.draw(screen7x10); + assertThat(forScreen(screen7x10)).hasStyle(1, 1, 1); + assertThat(forScreen(screen7x10)).hasForegroundColor(1, 1, -1); + assertThat(forScreen(screen7x10)).hasBackgroundColor(1, 1, -1); + } + + @Test + void selectedHighlightThemeSet() { + MenuItem menuItem = new MenuView.MenuItem("sub1"); + view = new MenuView(Arrays.asList(menuItem)); + view.setThemeResolver(themeResolver); + view.setThemeName("default"); + view.setShowBorder(true); + view.setRect(0, 0, 10, 7); + view.draw(screen7x10); + assertThat(forScreen(screen7x10)).hasStyle(1, 1, 5); + assertThat(forScreen(screen7x10)).hasForegroundColor(1, 1, Color.RED); + assertThat(forScreen(screen7x10)).hasBackgroundColor(1, 1, Color.BLUE); + } + @Test void defaultItemCheckStyleIsNoCheck() { MenuItem menuItem = new MenuView.MenuItem("sub1"); - MenuView view = new MenuView(Arrays.asList(menuItem)); + view = new MenuView(Arrays.asList(menuItem)); assertThat(view.getItems()).allSatisfy(item -> { assertThat(item.getCheckStyle()).isEqualTo(MenuItemCheckStyle.NOCHECK); }); diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/Catalog.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/Catalog.java index 8d8c2eb4..347e75c6 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/Catalog.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/Catalog.java @@ -235,7 +235,7 @@ public class Catalog { @Override protected void drawContent(Screen screen) { Rectangle rect = getRect(); - Writer writer = screen.writerBuilder().style(getStyle()).build(); + Writer writer = screen.writerBuilder().style(getStyle()).color(getForegroundColor()).build(); writer.text(String.format("%-20s %s", getItem().name(), getItem().description()), rect.x(), rect.y()); } }