Add default selection to MultiItemSelector
- Added default selection to items - Added correct styling for disabled but default selected item - Added missing license header - Added missing javadoc - Added default selection to sample/doc code
This commit is contained in:
committed by
Janne Valkealahti
parent
329c7eb559
commit
2862cc855e
@@ -32,6 +32,7 @@ import org.springframework.shell.component.support.Enableable;
|
||||
import org.springframework.shell.component.support.Itemable;
|
||||
import org.springframework.shell.component.support.Matchable;
|
||||
import org.springframework.shell.component.support.Nameable;
|
||||
import org.springframework.shell.component.support.Selectable;
|
||||
import org.springframework.shell.component.support.AbstractSelectorComponent.SelectorComponentContext;
|
||||
import org.springframework.shell.component.MultiItemSelector.MultiItemSelectorContext;
|
||||
|
||||
@@ -40,7 +41,7 @@ import org.springframework.shell.component.MultiItemSelector.MultiItemSelectorCo
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public class MultiItemSelector<T, I extends Nameable & Matchable & Enableable & Itemable<T>>
|
||||
public class MultiItemSelector<T, I extends Nameable & Matchable & Enableable & Selectable & Itemable<T>>
|
||||
extends AbstractSelectorComponent<T, MultiItemSelectorContext<T, I>, I> {
|
||||
|
||||
private MultiItemSelectorContext<T, I> currentContext;
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.shell.component.support.Enableable;
|
||||
import org.springframework.shell.component.support.Itemable;
|
||||
import org.springframework.shell.component.support.Matchable;
|
||||
import org.springframework.shell.component.support.Nameable;
|
||||
import org.springframework.shell.component.support.Selectable;
|
||||
import org.springframework.shell.component.support.AbstractSelectorComponent.SelectorComponentContext;
|
||||
import org.springframework.shell.component.SingleItemSelector.SingleItemSelectorContext;
|
||||
|
||||
@@ -40,7 +41,7 @@ import org.springframework.shell.component.SingleItemSelector.SingleItemSelector
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public class SingleItemSelector<T, I extends Nameable & Matchable & Enableable & Itemable<T>>
|
||||
public class SingleItemSelector<T, I extends Nameable & Matchable & Enableable & Selectable & Itemable<T>>
|
||||
extends AbstractSelectorComponent<T, SingleItemSelectorContext<T, I>, I> {
|
||||
|
||||
private SingleItemSelectorContext<T, I> currentContext;
|
||||
|
||||
@@ -617,7 +617,7 @@ public interface ComponentFlow {
|
||||
private Stream<OrderedInputOperation> multiItemSelectorsStream() {
|
||||
return multiInputs.stream().map(input -> {
|
||||
List<SelectorItem<String>> selectorItems = input.getSelectItems().stream()
|
||||
.map(si -> SelectorItem.of(si.name(), si.item(), si.enabled()))
|
||||
.map(si -> SelectorItem.of(si.name(), si.item(), si.enabled(), si.selected()))
|
||||
.collect(Collectors.toList());
|
||||
MultiItemSelector<String, SelectorItem<String>> selector = new MultiItemSelector<>(terminal,
|
||||
selectorItems, input.getName(), input.getComparator());
|
||||
|
||||
@@ -25,11 +25,13 @@ public class DefaultSelectItem implements SelectItem {
|
||||
private String name;
|
||||
private String item;
|
||||
private boolean enabled;
|
||||
private boolean selected;
|
||||
|
||||
public DefaultSelectItem(String name, String item, boolean enabled) {
|
||||
public DefaultSelectItem(String name, String item, boolean enabled, boolean selected) {
|
||||
this.name = name;
|
||||
this.item = item;
|
||||
this.enabled = enabled;
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,4 +48,9 @@ public class DefaultSelectItem implements SelectItem {
|
||||
public boolean enabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selected() {
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
@@ -43,11 +43,18 @@ public interface SelectItem {
|
||||
*/
|
||||
boolean enabled();
|
||||
|
||||
/**
|
||||
* Return if the item is selected.
|
||||
*
|
||||
* @return if item is selected
|
||||
*/
|
||||
boolean selected();
|
||||
|
||||
public static SelectItem of(String name, String item) {
|
||||
return of(name, item, true);
|
||||
return of(name, item, true, false);
|
||||
}
|
||||
|
||||
public static SelectItem of(String name, String item, boolean enabled) {
|
||||
return new DefaultSelectItem(name, item, enabled);
|
||||
public static SelectItem of(String name, String item, boolean enabled, boolean selected) {
|
||||
return new DefaultSelectItem(name, item, enabled, selected);
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ import static org.jline.keymap.KeyMap.key;
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public abstract class AbstractSelectorComponent<T, C extends SelectorComponentContext<T, I, C>, I extends Nameable & Matchable & Enableable & Itemable<T>>
|
||||
public abstract class AbstractSelectorComponent<T, C extends SelectorComponentContext<T, I, C>, I extends Nameable & Matchable & Enableable & Selectable & Itemable<T>>
|
||||
extends AbstractComponent<C> {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger(AbstractSelectorComponent.class);
|
||||
@@ -257,7 +257,7 @@ public abstract class AbstractSelectorComponent<T, C extends SelectorComponentCo
|
||||
AtomicInteger index = new AtomicInteger(0);
|
||||
itemStates = context.getItems().stream()
|
||||
.sorted(comparator)
|
||||
.map(item -> ItemState.of(item, item.getName(), index.getAndIncrement(), item.isEnabled()))
|
||||
.map(item -> ItemState.of(item, item.getName(), index.getAndIncrement(), item.isEnabled(), item.isSelected()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
for (int i = 0; i < itemStates.size(); i++) {
|
||||
@@ -280,7 +280,7 @@ public abstract class AbstractSelectorComponent<T, C extends SelectorComponentCo
|
||||
AtomicInteger index = new AtomicInteger(0);
|
||||
itemStates = context.getItems().stream()
|
||||
.sorted(comparator)
|
||||
.map(item -> ItemState.of(item, item.getName(), index.getAndIncrement(), item.isEnabled()))
|
||||
.map(item -> ItemState.of(item, item.getName(), index.getAndIncrement(), item.isEnabled(), item.isSelected()))
|
||||
.collect(Collectors.toList());
|
||||
context.setItemStates(itemStates);
|
||||
}
|
||||
@@ -547,11 +547,12 @@ public abstract class AbstractSelectorComponent<T, C extends SelectorComponentCo
|
||||
boolean enabled;
|
||||
int index;
|
||||
|
||||
ItemState(I item, String name, int index, boolean enabled) {
|
||||
ItemState(I item, String name, int index, boolean enabled, boolean selected) {
|
||||
this.item = item;
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.enabled = enabled;
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
public boolean matches(String match) {
|
||||
@@ -574,8 +575,8 @@ public abstract class AbstractSelectorComponent<T, C extends SelectorComponentCo
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static <I extends Matchable> ItemState<I> of(I item, String name, int index, boolean enabled) {
|
||||
return new ItemState<I>(item, name, index, enabled);
|
||||
static <I extends Matchable> ItemState<I> of(I item, String name, int index, boolean enabled, boolean selected) {
|
||||
return new ItemState<I>(item, name, index, enabled, selected);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2022 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.component.support;
|
||||
|
||||
public interface Selectable {
|
||||
|
||||
boolean isSelected();
|
||||
}
|
||||
@@ -17,29 +17,31 @@ package org.springframework.shell.component.support;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public interface SelectorItem<T> extends Nameable, Matchable, Enableable, Itemable<T> {
|
||||
public interface SelectorItem<T> extends Nameable, Matchable, Enableable, Selectable, Itemable<T> {
|
||||
|
||||
static <T> SelectorItem<T> of(String name, T item) {
|
||||
return of(name, item, true);
|
||||
return of(name, item, true, false);
|
||||
}
|
||||
|
||||
static <T> SelectorItem<T> of(String name, T item, boolean enabled) {
|
||||
return new SelectorItemWrapper<T>(name, item, enabled);
|
||||
static <T> SelectorItem<T> of(String name, T item, boolean enabled, boolean selected) {
|
||||
return new SelectorItemWrapper<T>(name, item, enabled, selected);
|
||||
}
|
||||
|
||||
public static class SelectorItemWrapper<T> implements SelectorItem<T> {
|
||||
private String name;
|
||||
private boolean enabled;
|
||||
private T item;
|
||||
private boolean selected;
|
||||
|
||||
public SelectorItemWrapper(String name, T item) {
|
||||
this(name, item, true);
|
||||
this(name, item, true, false);
|
||||
}
|
||||
|
||||
public SelectorItemWrapper(String name, T item, boolean enabled) {
|
||||
public SelectorItemWrapper(String name, T item, boolean enabled, boolean selected) {
|
||||
this.name = name;
|
||||
this.item = item;
|
||||
this.enabled = enabled;
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,7 +53,7 @@ public interface SelectorItem<T> extends Nameable, Matchable, Enableable, Itemab
|
||||
public boolean matches(String match) {
|
||||
if (!StringUtils.hasText(match)) {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
return name.toLowerCase().contains(match.toLowerCase());
|
||||
}
|
||||
|
||||
@@ -60,8 +62,14 @@ public interface SelectorItem<T> extends Nameable, Matchable, Enableable, Itemab
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@ select_item(item) ::= <%
|
||||
<({<figures.checkboxOff> }); format=selected_style(item.selected)> <item.name>
|
||||
<endif>
|
||||
<else>
|
||||
<({<figures.checkboxOff> }); format="style-item-disabled"> <item.name; format="style-item-disabled">
|
||||
<if(item.selected)>
|
||||
<({<figures.checkboxOn> }); format="style-item-disabled"> <item.name; format="style-item-disabled">
|
||||
<else>
|
||||
<({<figures.checkboxOff> }); format="style-item-disabled"> <item.name; format="style-item-disabled">
|
||||
<endif>
|
||||
<endif>
|
||||
%>
|
||||
|
||||
|
||||
@@ -51,13 +51,15 @@ public class MultiItemSelectorTests extends AbstractShellTests {
|
||||
private static SimplePojo SIMPLE_POJO_5 = SimplePojo.of("data5");
|
||||
private static SimplePojo SIMPLE_POJO_6 = SimplePojo.of("data6");
|
||||
private static SimplePojo SIMPLE_POJO_7 = SimplePojo.of("data7");
|
||||
private static SimplePojo SIMPLE_POJO_8 = SimplePojo.of("data8");
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_1 = SelectorItem.of("simplePojo1", SIMPLE_POJO_1);
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_2 = SelectorItem.of("simplePojo2", SIMPLE_POJO_2);
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_3 = SelectorItem.of("simplePojo3", SIMPLE_POJO_3);
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_4 = SelectorItem.of("simplePojo4", SIMPLE_POJO_4);
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_5 = SelectorItem.of("simplePojo5", SIMPLE_POJO_5);
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_6 = SelectorItem.of("simplePojo6", SIMPLE_POJO_6);
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_7 = SelectorItem.of("simplePojo7", SIMPLE_POJO_7, false);
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_7 = SelectorItem.of("simplePojo7", SIMPLE_POJO_7, false, false);
|
||||
private static SelectorItem<SimplePojo> SELECTOR_ITEM_8 = SelectorItem.of("simplePojo8", SIMPLE_POJO_8, false, true);
|
||||
|
||||
private ExecutorService service;
|
||||
private CountDownLatch latch;
|
||||
@@ -204,6 +206,22 @@ public class MultiItemSelectorTests extends AbstractShellTests {
|
||||
Stream<String> datas = selected.stream().map(SelectorItem::getItem).map(SimplePojo::getData);
|
||||
assertThat(datas).containsExactlyInAnyOrder("data4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultSelection() throws InterruptedException {
|
||||
scheduleSelect(Arrays.asList(SELECTOR_ITEM_1, SELECTOR_ITEM_2, SELECTOR_ITEM_7, SELECTOR_ITEM_8));
|
||||
|
||||
TestBuffer testBuffer = new TestBuffer().cr();
|
||||
write(testBuffer.getBytes());
|
||||
|
||||
awaitLatch();
|
||||
|
||||
List<SelectorItem<SimplePojo>> selected = result.get();
|
||||
assertThat(selected).hasSize(1);
|
||||
Stream<String> datas = selected.stream().map(SelectorItem::getItem).map(SimplePojo::getData);
|
||||
assertThat(datas).containsExactlyInAnyOrder("data8");
|
||||
assertThat(consoleOut()).contains("testSimple data8");
|
||||
}
|
||||
|
||||
private void scheduleSelect() {
|
||||
scheduleSelect(Arrays.asList(SELECTOR_ITEM_1, SELECTOR_ITEM_2, SELECTOR_ITEM_3,
|
||||
|
||||
@@ -170,7 +170,7 @@ public class UiComponentSnippets {
|
||||
public String multiSelector() {
|
||||
List<SelectorItem<String>> items = new ArrayList<>();
|
||||
items.add(SelectorItem.of("key1", "value1"));
|
||||
items.add(SelectorItem.of("key2", "value2", false));
|
||||
items.add(SelectorItem.of("key2", "value2", false, true));
|
||||
items.add(SelectorItem.of("key3", "value3"));
|
||||
MultiItemSelector<String, SelectorItem<String>> component = new MultiItemSelector<>(getTerminal(),
|
||||
items, "testSimple", null);
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ComponentCommands extends AbstractShellComponent {
|
||||
public String multiSelector() {
|
||||
List<SelectorItem<String>> items = new ArrayList<>();
|
||||
items.add(SelectorItem.of("key1", "value1"));
|
||||
items.add(SelectorItem.of("key2", "value2", false));
|
||||
items.add(SelectorItem.of("key2", "value2", false, true));
|
||||
items.add(SelectorItem.of("key3", "value3"));
|
||||
MultiItemSelector<String, SelectorItem<String>> component = new MultiItemSelector<>(getTerminal(),
|
||||
items, "testSimple", null);
|
||||
|
||||
Reference in New Issue
Block a user