1 package be
.nikiroo
.jvcard
.tui
;
3 import java
.util
.Arrays
;
4 import java
.util
.LinkedList
;
7 import be
.nikiroo
.jvcard
.Card
;
8 import be
.nikiroo
.jvcard
.Contact
;
9 import be
.nikiroo
.jvcard
.i18n
.Trans
;
10 import be
.nikiroo
.jvcard
.i18n
.Trans
.StringId
;
11 import be
.nikiroo
.jvcard
.tui
.KeyAction
.Mode
;
12 import be
.nikiroo
.jvcard
.tui
.UiColors
.Element
;
13 import be
.nikiroo
.jvcard
.tui
.panes
.ContactDetails
;
14 import be
.nikiroo
.jvcard
.tui
.panes
.ContactList
;
15 import be
.nikiroo
.jvcard
.tui
.panes
.MainContent
;
17 import com
.googlecode
.lanterna
.TerminalSize
;
18 import com
.googlecode
.lanterna
.gui2
.BasicWindow
;
19 import com
.googlecode
.lanterna
.gui2
.BorderLayout
;
20 import com
.googlecode
.lanterna
.gui2
.Direction
;
21 import com
.googlecode
.lanterna
.gui2
.Interactable
;
22 import com
.googlecode
.lanterna
.gui2
.Label
;
23 import com
.googlecode
.lanterna
.gui2
.LinearLayout
;
24 import com
.googlecode
.lanterna
.gui2
.Panel
;
25 import com
.googlecode
.lanterna
.gui2
.TextBox
;
26 import com
.googlecode
.lanterna
.gui2
.TextGUIGraphics
;
27 import com
.googlecode
.lanterna
.gui2
.Window
;
28 import com
.googlecode
.lanterna
.input
.KeyStroke
;
29 import com
.googlecode
.lanterna
.input
.KeyType
;
32 * This is the main "window" of the program. It will host one
33 * {@link MainContent} at any one time.
38 public class MainWindow
extends BasicWindow
{
39 private List
<KeyAction
> defaultActions
= new LinkedList
<KeyAction
>();
40 private List
<KeyAction
> actions
= new LinkedList
<KeyAction
>();
41 private List
<MainContent
> content
= new LinkedList
<MainContent
>();
42 private boolean actionsPadded
;
43 private Boolean waitForOneKeyAnswer
; // true, false, (null = do not wait for
46 private Panel titlePanel
;
47 private Panel mainPanel
;
48 private Panel contentPanel
;
49 private Panel actionPanel
;
50 private Panel messagePanel
;
57 public MainWindow(MainContent content
) {
58 super(content
== null ?
"" : content
.getTitle());
60 setHints(Arrays
.asList(Window
.Hint
.FULL_SCREEN
,
61 Window
.Hint
.NO_DECORATIONS
, Window
.Hint
.FIT_TERMINAL_WINDOW
));
63 defaultActions
.add(new KeyAction(Mode
.BACK
, 'q',
64 StringId
.KEY_ACTION_BACK
));
65 defaultActions
.add(new KeyAction(Mode
.BACK
, KeyType
.Escape
,
67 defaultActions
.add(new KeyAction(Mode
.HELP
, 'h',
68 StringId
.KEY_ACTION_HELP
));
69 defaultActions
.add(new KeyAction(Mode
.HELP
, KeyType
.F1
, StringId
.NULL
));
71 actionPanel
= new Panel();
72 contentPanel
= new Panel();
73 mainPanel
= new Panel();
74 messagePanel
= new Panel();
75 titlePanel
= new Panel();
77 Panel actionMessagePanel
= new Panel();
79 LinearLayout llayout
= new LinearLayout(Direction
.HORIZONTAL
);
80 llayout
.setSpacing(0);
81 actionPanel
.setLayoutManager(llayout
);
83 llayout
= new LinearLayout(Direction
.VERTICAL
);
84 llayout
.setSpacing(0);
85 titlePanel
.setLayoutManager(llayout
);
87 llayout
= new LinearLayout(Direction
.VERTICAL
);
88 llayout
.setSpacing(0);
89 messagePanel
.setLayoutManager(llayout
);
91 BorderLayout blayout
= new BorderLayout();
92 mainPanel
.setLayoutManager(blayout
);
94 blayout
= new BorderLayout();
95 contentPanel
.setLayoutManager(blayout
);
97 blayout
= new BorderLayout();
98 actionMessagePanel
.setLayoutManager(blayout
);
101 .addComponent(messagePanel
, BorderLayout
.Location
.TOP
);
102 actionMessagePanel
.addComponent(actionPanel
,
103 BorderLayout
.Location
.CENTER
);
105 mainPanel
.addComponent(titlePanel
, BorderLayout
.Location
.TOP
);
106 mainPanel
.addComponent(contentPanel
, BorderLayout
.Location
.CENTER
);
108 .addComponent(actionMessagePanel
, BorderLayout
.Location
.BOTTOM
);
110 pushContent(content
);
112 setComponent(mainPanel
);
115 public void pushContent(MainContent content
) {
116 List
<KeyAction
> actions
= null;
119 contentPanel
.removeAllComponents();
120 if (content
!= null) {
121 title
= content
.getTitle();
122 actions
= content
.getKeyBindings();
123 contentPanel
.addComponent(content
, BorderLayout
.Location
.CENTER
);
124 this.content
.add(content
);
128 setActions(actions
, true, true);
133 * Set the application title.
136 * the new title or NULL for the default title
138 public void setTitle(String title
) {
140 title
= Trans
.StringId
.TITLE
.trans();
143 if (!title
.equals(this.title
)) {
144 super.setTitle(title
);
148 Label lbl
= new Label(title
);
149 titlePanel
.removeAllComponents();
151 titlePanel
.addComponent(lbl
, LinearLayout
152 .createLayoutData(LinearLayout
.Alignment
.Center
));
156 public void draw(TextGUIGraphics graphics
) {
158 if (!actionsPadded
) {
159 // fill with "desc" colour
160 actionPanel
.addComponent(UiColors
.Element
.ACTION_DESC
161 .createLabel(StringUtils
.padString("", graphics
.getSize()
163 actionsPadded
= true;
165 super.draw(graphics
);
168 public MainContent
popContent() {
169 MainContent removed
= null;
170 MainContent prev
= null;
171 if (content
.size() > 0)
172 removed
= content
.remove(content
.size() - 1);
173 if (content
.size() > 0)
174 prev
= content
.remove(content
.size() - 1);
180 private void setActions(List
<KeyAction
> actions
, boolean allowKeys
,
181 boolean enableDefaultactions
) {
183 this.actions
.clear();
184 actionsPadded
= false;
186 if (enableDefaultactions
)
187 this.actions
.addAll(defaultActions
);
190 this.actions
.addAll(actions
);
192 actionPanel
.removeAllComponents();
193 for (KeyAction action
: this.actions
) {
194 String trans
= " " + action
.getStringId().trans() + " ";
196 if (" ".equals(trans
))
199 String keyTrans
= "";
200 switch (action
.getKey().getKeyType()) {
208 keyTrans
= " " + action
.getKey().getCharacter() + " ";
211 keyTrans
= "" + action
.getKey().getKeyType();
213 if (keyTrans
.length() > width
) {
214 keyTrans
= keyTrans
.substring(0, width
);
215 } else if (keyTrans
.length() < width
) {
217 + new String(new char[width
- keyTrans
.length()])
223 Panel kPane
= new Panel();
224 LinearLayout layout
= new LinearLayout(Direction
.HORIZONTAL
);
225 layout
.setSpacing(0);
226 kPane
.setLayoutManager(layout
);
228 kPane
.addComponent(UiColors
.Element
.ACTION_KEY
229 .createLabel(keyTrans
));
230 kPane
.addComponent(UiColors
.Element
.ACTION_DESC
.createLabel(trans
));
232 actionPanel
.addComponent(kPane
);
237 * Show the given message on screen. It will disappear at the next action.
240 * the message to display
242 * TRUE for an error message, FALSE for an information message
244 public void setMessage(String mess
, boolean error
) {
245 messagePanel
.removeAllComponents();
247 Element element
= (error ? UiColors
.Element
.LINE_MESSAGE_ERR
248 : UiColors
.Element
.LINE_MESSAGE
);
249 Label lbl
= element
.createLabel(" " + mess
+ " ");
250 messagePanel
.addComponent(lbl
, LinearLayout
251 .createLayoutData(LinearLayout
.Alignment
.Center
));
255 public void setQuestion(String mess
, boolean oneKey
) {
256 messagePanel
.removeAllComponents();
258 waitForOneKeyAnswer
= oneKey
;
260 Panel hpanel
= new Panel();
261 LinearLayout llayout
= new LinearLayout(Direction
.HORIZONTAL
);
262 llayout
.setSpacing(0);
263 hpanel
.setLayoutManager(llayout
);
265 Label lbl
= UiColors
.Element
.LINE_MESSAGE_QUESTION
.createLabel(" "
267 text
= new TextBox(new TerminalSize(getSize().getColumns()
268 - lbl
.getSize().getColumns(), 1));
270 hpanel
.addComponent(lbl
, LinearLayout
271 .createLayoutData(LinearLayout
.Alignment
.Beginning
));
272 hpanel
.addComponent(text
, LinearLayout
273 .createLayoutData(LinearLayout
.Alignment
.Fill
));
275 messagePanel
.addComponent(hpanel
, LinearLayout
276 .createLayoutData(LinearLayout
.Alignment
.Beginning
));
282 private String
handleQuestion(KeyStroke key
) {
283 String answer
= null;
285 if (waitForOneKeyAnswer
) {
286 answer
= "" + key
.getCharacter();
288 if (key
.getKeyType() == KeyType
.Enter
) {
290 answer
= text
.getText();
296 if (answer
!= null) {
297 Interactable focus
= null;
298 if (this.content
.size() > 0)
299 // focus = content.get(0).getDefaultFocusElement();
300 focus
= content
.get(0).nextFocus(null);
309 public boolean handleInput(KeyStroke key
) {
310 boolean handled
= false;
312 if (waitForOneKeyAnswer
!= null) {
313 String answer
= handleQuestion(key
);
314 if (answer
!= null) {
315 waitForOneKeyAnswer
= null;
316 setMessage("ANS: " + answer
, false);
321 setMessage(null, false);
323 for (KeyAction action
: actions
) {
324 if (!action
.match(key
))
329 if (action
.onAction()) {
330 switch (action
.getMode()) {
335 if (action
.getKey().getKeyType() == KeyType
.ArrowUp
)
337 if (action
.getKey().getKeyType() == KeyType
.ArrowDown
)
339 if (action
.getKey().getKeyType() == KeyType
.ArrowLeft
)
341 if (action
.getKey().getKeyType() == KeyType
.ArrowRight
)
344 if (content
.size() > 0) {
345 String err
= content
.get(content
.size() - 1).move(
348 setMessage(err
, true);
352 // mode with windows:
354 Card card
= action
.getCard();
356 pushContent(new ContactList(card
));
359 case CONTACT_DETAILS
:
360 Contact contact
= action
.getContact();
361 if (contact
!= null) {
362 pushContent(new ContactDetails(contact
));
365 // mode interpreted by MainWindow:
368 // setMessage("Help! I need somebody! Help!", false);
369 setQuestion("Test question?", false);
374 if (content
.size() == 0)
388 handled
= super.handleInput(key
);