1
1
/*
2
- * Copyright 2023 the original author or authors.
2
+ * Copyright 2023-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
18
18
import java .util .ArrayList ;
19
19
import java .util .Arrays ;
20
+ import java .util .Collections ;
20
21
import java .util .List ;
21
22
import java .util .ListIterator ;
22
23
23
24
import org .slf4j .Logger ;
24
25
import org .slf4j .LoggerFactory ;
25
26
27
+ import org .springframework .lang .Nullable ;
26
28
import org .springframework .shell .component .message .ShellMessageBuilder ;
27
29
import org .springframework .shell .component .view .event .MouseEvent ;
28
30
import org .springframework .shell .component .view .event .MouseHandler ;
29
31
import org .springframework .shell .component .view .screen .Screen ;
30
32
import org .springframework .shell .component .view .screen .Screen .Writer ;
31
33
import org .springframework .shell .geom .Rectangle ;
32
34
import org .springframework .shell .style .StyleSettings ;
35
+ import org .springframework .util .StringUtils ;
33
36
34
37
/**
35
38
* {@link StatusBarView} shows {@link StatusItem items} horizontally and is
36
39
* typically used in layouts which builds complete terminal UI's.
37
40
*
41
+ * {@link StatusItem item} {@code primary} denotes if item is drawn to left
42
+ * or right, {@code priority} on which order items are drawn until bar runs
43
+ * out of space. Default {@code primary} is {@code true} and {@code priority}
44
+ * is {@code 0}.
45
+ *
38
46
* @author Janne Valkealahti
39
47
*/
40
48
public class StatusBarView extends BoxView {
41
49
42
50
private final Logger log = LoggerFactory .getLogger (StatusBarView .class );
43
51
private final List <StatusItem > items = new ArrayList <>();
52
+ private String itemSeparator = " | " ;
44
53
45
54
public StatusBarView () {
46
55
this (new StatusItem [0 ]);
@@ -59,18 +68,64 @@ protected String getBackgroundStyle() {
59
68
return StyleSettings .TAG_STATUSBAR_BACKGROUND ;
60
69
}
61
70
71
+ /**
72
+ * Gets the item separator.
73
+ *
74
+ * @return a separator
75
+ */
76
+ @ Nullable
77
+ public String getItemSeparator () {
78
+ return itemSeparator ;
79
+ }
80
+
81
+ /**
82
+ * Sets the item separator. Separator can be {@code null} or empty which
83
+ * essentially disables it.
84
+ *
85
+ * @param itemSeparator the item separator
86
+ */
87
+ public void setItemSeparator (@ Nullable String itemSeparator ) {
88
+ this .itemSeparator = itemSeparator ;
89
+ }
90
+
62
91
@ Override
63
92
protected void drawInternal (Screen screen ) {
64
93
Rectangle rect = getInnerRect ();
65
94
log .debug ("Drawing status bar to {}" , rect );
66
95
Writer writer = screen .writerBuilder ().build ();
67
- int x = rect .x ();
96
+
97
+ int primaryX = rect .x ();
98
+ int nonprimaryX = rect .x () + rect .width ();
99
+ boolean primaryWritten = false ;
100
+ boolean nonprimaryWritten = false ;
101
+
68
102
ListIterator <StatusItem > iter = items .listIterator ();
69
103
while (iter .hasNext ()) {
70
104
StatusItem item = iter .next ();
71
- String text = String .format (" %s%s" , item .getTitle (), iter .hasNext () ? " |" : "" );
72
- writer .text (text , x , rect .y ());
73
- x += text .length ();
105
+ String text = item .getTitle ();
106
+ if (text == null ) {
107
+ continue ;
108
+ }
109
+ String sep = getItemSeparator ();
110
+ if (nonprimaryX - primaryX < (text .length () + (sep != null ? sep .length () : 0 ))) {
111
+ break ;
112
+ }
113
+ if (item .primary ) {
114
+ if (primaryWritten && StringUtils .hasText (sep )) {
115
+ text = sep + text ;
116
+ }
117
+ writer .text (text , primaryX , rect .y ());
118
+ primaryX += text .length ();
119
+ primaryWritten = true ;
120
+ }
121
+ else {
122
+ if (nonprimaryWritten && StringUtils .hasText (sep )) {
123
+ text = text + sep ;
124
+ }
125
+ writer .text (text , nonprimaryX - text .length (), rect .y ());
126
+ nonprimaryX -= text .length ();
127
+ nonprimaryWritten = true ;
128
+ }
74
129
}
75
130
super .drawInternal (screen );
76
131
}
@@ -121,6 +176,19 @@ private StatusItem itemAt(int x, int y) {
121
176
public void setItems (List <StatusItem > items ) {
122
177
this .items .clear ();
123
178
this .items .addAll (items );
179
+ Collections .sort (this .items , (o1 , o2 ) -> {
180
+ int ret = o1 .priority - o2 .priority ;
181
+ if (ret == 0 ) {
182
+ if (o1 .primary && !o2 .primary ) {
183
+ ret = -1 ;
184
+ }
185
+ else if (!o1 .primary && o2 .primary ) {
186
+ ret = 1 ;
187
+ }
188
+ }
189
+ return ret ;
190
+ });
191
+ // this.items.sort(null);
124
192
registerHotKeys ();
125
193
}
126
194
@@ -152,6 +220,8 @@ public static class StatusItem {
152
220
private String title ;
153
221
private Runnable action ;
154
222
private Integer hotKey ;
223
+ private boolean primary = true ;
224
+ private int priority = 0 ;
155
225
156
226
public StatusItem (String title ) {
157
227
this (title , null );
@@ -167,6 +237,14 @@ public StatusItem(String title, Runnable action, Integer hotKey) {
167
237
this .hotKey = hotKey ;
168
238
}
169
239
240
+ public StatusItem (String title , Runnable action , Integer hotKey , boolean primary , int priority ) {
241
+ this .title = title ;
242
+ this .action = action ;
243
+ this .hotKey = hotKey ;
244
+ this .primary = primary ;
245
+ this .priority = priority ;
246
+ }
247
+
170
248
public static StatusItem of (String title ) {
171
249
return new StatusItem (title );
172
250
}
@@ -179,10 +257,18 @@ public static StatusItem of(String title, Runnable action, Integer hotKey) {
179
257
return new StatusItem (title , action , hotKey );
180
258
}
181
259
260
+ public static StatusItem of (String title , Runnable action , Integer hotKey , boolean primary , int priority ) {
261
+ return new StatusItem (title , action , hotKey , primary , priority );
262
+ }
263
+
182
264
public String getTitle () {
183
265
return title ;
184
266
}
185
267
268
+ public void setTitle (String title ) {
269
+ this .title = title ;
270
+ }
271
+
186
272
public Runnable getAction () {
187
273
return action ;
188
274
}
@@ -201,6 +287,22 @@ public StatusItem setHotKey(Integer hotKey) {
201
287
return this ;
202
288
}
203
289
290
+ public int getPriority () {
291
+ return priority ;
292
+ }
293
+
294
+ public void setPriority (int priority ) {
295
+ this .priority = priority ;
296
+ }
297
+
298
+ public boolean isPrimary () {
299
+ return primary ;
300
+ }
301
+
302
+ public void setPrimary (boolean primary ) {
303
+ this .primary = primary ;
304
+ }
305
+
204
306
}
205
307
206
308
/**
0 commit comments