Overhaul StatusBar for better text use
- Can change item text - Can position items by priority(true left, false right) and primary(sort for draw attempt) - Fixes #1112
This commit is contained in:
@@ -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.
|
||||
@@ -17,12 +17,14 @@ package org.springframework.shell.component.view.control;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.shell.component.message.ShellMessageBuilder;
|
||||
import org.springframework.shell.component.view.event.MouseEvent;
|
||||
import org.springframework.shell.component.view.event.MouseHandler;
|
||||
@@ -30,17 +32,24 @@ 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.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link StatusBarView} shows {@link StatusItem items} horizontally and is
|
||||
* typically used in layouts which builds complete terminal UI's.
|
||||
*
|
||||
* {@link StatusItem item} {@code primary} denotes if item is drawn to left
|
||||
* or right, {@code priority} on which order items are drawn until bar runs
|
||||
* out of space. Default {@code primary} is {@code true} and {@code priority}
|
||||
* is {@code 0}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public class StatusBarView extends BoxView {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(StatusBarView.class);
|
||||
private final List<StatusItem> items = new ArrayList<>();
|
||||
private String itemSeparator = " | ";
|
||||
|
||||
public StatusBarView() {
|
||||
this(new StatusItem[0]);
|
||||
@@ -59,18 +68,64 @@ public class StatusBarView extends BoxView {
|
||||
return StyleSettings.TAG_STATUSBAR_BACKGROUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item separator.
|
||||
*
|
||||
* @return a separator
|
||||
*/
|
||||
@Nullable
|
||||
public String getItemSeparator() {
|
||||
return itemSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item separator. Separator can be {@code null} or empty which
|
||||
* essentially disables it.
|
||||
*
|
||||
* @param itemSeparator the item separator
|
||||
*/
|
||||
public void setItemSeparator(@Nullable String itemSeparator) {
|
||||
this.itemSeparator = itemSeparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawInternal(Screen screen) {
|
||||
Rectangle rect = getInnerRect();
|
||||
log.debug("Drawing status bar to {}", rect);
|
||||
Writer writer = screen.writerBuilder().build();
|
||||
int x = rect.x();
|
||||
|
||||
int primaryX = rect.x();
|
||||
int nonprimaryX = rect.x() + rect.width();
|
||||
boolean primaryWritten = false;
|
||||
boolean nonprimaryWritten = false;
|
||||
|
||||
ListIterator<StatusItem> iter = items.listIterator();
|
||||
while (iter.hasNext()) {
|
||||
StatusItem item = iter.next();
|
||||
String text = String.format(" %s%s", item.getTitle(), iter.hasNext() ? " |" : "");
|
||||
writer.text(text, x, rect.y());
|
||||
x += text.length();
|
||||
String text = item.getTitle();
|
||||
if (text == null) {
|
||||
continue;
|
||||
}
|
||||
String sep = getItemSeparator();
|
||||
if (nonprimaryX - primaryX < (text.length() + (sep != null ? sep.length() : 0))) {
|
||||
break;
|
||||
}
|
||||
if (item.primary) {
|
||||
if (primaryWritten && StringUtils.hasText(sep)) {
|
||||
text = sep + text;
|
||||
}
|
||||
writer.text(text, primaryX, rect.y());
|
||||
primaryX += text.length();
|
||||
primaryWritten = true;
|
||||
}
|
||||
else {
|
||||
if (nonprimaryWritten && StringUtils.hasText(sep)) {
|
||||
text = text + sep;
|
||||
}
|
||||
writer.text(text, nonprimaryX - text.length(), rect.y());
|
||||
nonprimaryX -= text.length();
|
||||
nonprimaryWritten = true;
|
||||
}
|
||||
}
|
||||
super.drawInternal(screen);
|
||||
}
|
||||
@@ -121,6 +176,19 @@ public class StatusBarView extends BoxView {
|
||||
public void setItems(List<StatusItem> items) {
|
||||
this.items.clear();
|
||||
this.items.addAll(items);
|
||||
Collections.sort(this.items, (o1, o2) -> {
|
||||
int ret = o1.priority - o2.priority;
|
||||
if (ret == 0) {
|
||||
if (o1.primary && !o2.primary) {
|
||||
ret = -1;
|
||||
}
|
||||
else if (!o1.primary && o2.primary) {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
// this.items.sort(null);
|
||||
registerHotKeys();
|
||||
}
|
||||
|
||||
@@ -152,6 +220,8 @@ public class StatusBarView extends BoxView {
|
||||
private String title;
|
||||
private Runnable action;
|
||||
private Integer hotKey;
|
||||
private boolean primary = true;
|
||||
private int priority = 0;
|
||||
|
||||
public StatusItem(String title) {
|
||||
this(title, null);
|
||||
@@ -167,6 +237,14 @@ public class StatusBarView extends BoxView {
|
||||
this.hotKey = hotKey;
|
||||
}
|
||||
|
||||
public StatusItem(String title, Runnable action, Integer hotKey, boolean primary, int priority) {
|
||||
this.title = title;
|
||||
this.action = action;
|
||||
this.hotKey = hotKey;
|
||||
this.primary = primary;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public static StatusItem of(String title) {
|
||||
return new StatusItem(title);
|
||||
}
|
||||
@@ -179,10 +257,18 @@ public class StatusBarView extends BoxView {
|
||||
return new StatusItem(title, action, hotKey);
|
||||
}
|
||||
|
||||
public static StatusItem of(String title, Runnable action, Integer hotKey, boolean primary, int priority) {
|
||||
return new StatusItem(title, action, hotKey, primary, priority);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Runnable getAction() {
|
||||
return action;
|
||||
}
|
||||
@@ -201,6 +287,22 @@ public class StatusBarView extends BoxView {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public boolean isPrimary() {
|
||||
return primary;
|
||||
}
|
||||
|
||||
public void setPrimary(boolean primary) {
|
||||
this.primary = primary;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user