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
;
14 import com
.googlecode
.lanterna
.TerminalSize
;
15 import com
.googlecode
.lanterna
.gui2
.BasicWindow
;
16 import com
.googlecode
.lanterna
.gui2
.BorderLayout
;
17 import com
.googlecode
.lanterna
.gui2
.Direction
;
18 import com
.googlecode
.lanterna
.gui2
.Interactable
;
19 import com
.googlecode
.lanterna
.gui2
.Label
;
20 import com
.googlecode
.lanterna
.gui2
.LinearLayout
;
21 import com
.googlecode
.lanterna
.gui2
.Panel
;
22 import com
.googlecode
.lanterna
.gui2
.TextBox
;
23 import com
.googlecode
.lanterna
.gui2
.TextGUIGraphics
;
24 import com
.googlecode
.lanterna
.gui2
.Window
;
25 import com
.googlecode
.lanterna
.input
.KeyStroke
;
26 import com
.googlecode
.lanterna
.input
.KeyType
;
29 * This is the main "window" of the program. It will host one
30 * {@link MainContent} at any one time.
35 public class MainWindow
extends BasicWindow
{
36 private List
<KeyAction
> defaultActions
= new LinkedList
<KeyAction
>();
37 private List
<KeyAction
> actions
= new LinkedList
<KeyAction
>();
38 private List
<MainContent
> content
= new LinkedList
<MainContent
>();
39 private boolean actionsPadded
;
40 private Boolean waitForOneKeyAnswer
; // true, false, (null = do not wait for
43 private Panel titlePanel
;
44 private Panel mainPanel
;
45 private Panel contentPanel
;
46 private Panel actionPanel
;
47 private Panel messagePanel
;
54 public MainWindow(MainContent content
) {
55 super(content
== null ?
"" : content
.getTitle());
57 setHints(Arrays
.asList(Window
.Hint
.FULL_SCREEN
,
58 Window
.Hint
.NO_DECORATIONS
, Window
.Hint
.FIT_TERMINAL_WINDOW
));
60 defaultActions
.add(new KeyAction(Mode
.BACK
, 'q',
61 StringId
.KEY_ACTION_BACK
));
62 defaultActions
.add(new KeyAction(Mode
.BACK
, KeyType
.Escape
,
64 defaultActions
.add(new KeyAction(Mode
.HELP
, 'h',
65 StringId
.KEY_ACTION_HELP
));
66 defaultActions
.add(new KeyAction(Mode
.HELP
, KeyType
.F1
, StringId
.NULL
));
68 actionPanel
= new Panel();
69 contentPanel
= new Panel();
70 mainPanel
= new Panel();
71 messagePanel
= new Panel();
72 titlePanel
= new Panel();
74 Panel actionMessagePanel
= new Panel();
76 LinearLayout llayout
= new LinearLayout(Direction
.HORIZONTAL
);
77 llayout
.setSpacing(0);
78 actionPanel
.setLayoutManager(llayout
);
80 llayout
= new LinearLayout(Direction
.VERTICAL
);
81 llayout
.setSpacing(0);
82 titlePanel
.setLayoutManager(llayout
);
84 llayout
= new LinearLayout(Direction
.VERTICAL
);
85 llayout
.setSpacing(0);
86 messagePanel
.setLayoutManager(llayout
);
88 BorderLayout blayout
= new BorderLayout();
89 mainPanel
.setLayoutManager(blayout
);
91 blayout
= new BorderLayout();
92 contentPanel
.setLayoutManager(blayout
);
94 blayout
= new BorderLayout();
95 actionMessagePanel
.setLayoutManager(blayout
);
98 .addComponent(messagePanel
, BorderLayout
.Location
.TOP
);
99 actionMessagePanel
.addComponent(actionPanel
,
100 BorderLayout
.Location
.CENTER
);
102 mainPanel
.addComponent(titlePanel
, BorderLayout
.Location
.TOP
);
103 mainPanel
.addComponent(contentPanel
, BorderLayout
.Location
.CENTER
);
105 .addComponent(actionMessagePanel
, BorderLayout
.Location
.BOTTOM
);
107 pushContent(content
);
109 setComponent(mainPanel
);
112 public void pushContent(MainContent content
) {
113 List
<KeyAction
> actions
= null;
116 contentPanel
.removeAllComponents();
117 if (content
!= null) {
118 title
= content
.getTitle();
119 actions
= content
.getKeyBindings();
120 contentPanel
.addComponent(content
, BorderLayout
.Location
.CENTER
);
121 this.content
.add(content
);
125 setActions(actions
, true, true);
130 * Set the application title.
133 * the new title or NULL for the default title
135 public void setTitle(String title
) {
137 title
= Trans
.StringId
.TITLE
.trans();
140 if (!title
.equals(this.title
)) {
141 super.setTitle(title
);
145 Label lbl
= new Label(title
);
146 titlePanel
.removeAllComponents();
148 titlePanel
.addComponent(lbl
, LinearLayout
149 .createLayoutData(LinearLayout
.Alignment
.Center
));
153 public void draw(TextGUIGraphics graphics
) {
155 if (!actionsPadded
) {
156 // fill with "desc" colour
157 actionPanel
.addComponent(UiColors
.Element
.ACTION_DESC
158 .createLabel(StringUtils
.padString("", graphics
.getSize()
160 actionsPadded
= true;
162 super.draw(graphics
);
165 public MainContent
popContent() {
166 MainContent removed
= null;
167 MainContent prev
= null;
168 if (content
.size() > 0)
169 removed
= content
.remove(content
.size() - 1);
170 if (content
.size() > 0)
171 prev
= content
.remove(content
.size() - 1);
177 private void setActions(List
<KeyAction
> actions
, boolean allowKeys
,
178 boolean enableDefaultactions
) {
180 this.actions
.clear();
181 actionsPadded
= false;
183 if (enableDefaultactions
)
184 this.actions
.addAll(defaultActions
);
187 this.actions
.addAll(actions
);
189 actionPanel
.removeAllComponents();
190 for (KeyAction action
: this.actions
) {
191 String trans
= " " + action
.getStringId().trans() + " ";
193 if (" ".equals(trans
))
196 String keyTrans
= "";
197 switch (action
.getKey().getKeyType()) {
205 keyTrans
= " " + action
.getKey().getCharacter() + " ";
208 keyTrans
= "" + action
.getKey().getKeyType();
210 if (keyTrans
.length() > width
) {
211 keyTrans
= keyTrans
.substring(0, width
);
212 } else if (keyTrans
.length() < width
) {
214 + new String(new char[width
- keyTrans
.length()])
220 Panel kPane
= new Panel();
221 LinearLayout layout
= new LinearLayout(Direction
.HORIZONTAL
);
222 layout
.setSpacing(0);
223 kPane
.setLayoutManager(layout
);
225 kPane
.addComponent(UiColors
.Element
.ACTION_KEY
226 .createLabel(keyTrans
));
227 kPane
.addComponent(UiColors
.Element
.ACTION_DESC
.createLabel(trans
));
229 actionPanel
.addComponent(kPane
);
234 * Show the given message on screen. It will disappear at the next action.
237 * the message to display
239 * TRUE for an error message, FALSE for an information message
241 public void setMessage(String mess
, boolean error
) {
242 messagePanel
.removeAllComponents();
244 Element element
= (error ? UiColors
.Element
.LINE_MESSAGE_ERR
245 : UiColors
.Element
.LINE_MESSAGE
);
246 Label lbl
= element
.createLabel(" " + mess
+ " ");
247 messagePanel
.addComponent(lbl
, LinearLayout
248 .createLayoutData(LinearLayout
.Alignment
.Center
));
252 public void setQuestion(String mess
, boolean oneKey
) {
253 messagePanel
.removeAllComponents();
255 waitForOneKeyAnswer
= oneKey
;
257 Panel hpanel
= new Panel();
258 LinearLayout llayout
= new LinearLayout(Direction
.HORIZONTAL
);
259 llayout
.setSpacing(0);
260 hpanel
.setLayoutManager(llayout
);
262 Label lbl
= UiColors
.Element
.LINE_MESSAGE_QUESTION
.createLabel(" "
264 text
= new TextBox(new TerminalSize(getSize().getColumns()
265 - lbl
.getSize().getColumns(), 1));
267 hpanel
.addComponent(lbl
, LinearLayout
268 .createLayoutData(LinearLayout
.Alignment
.Beginning
));
269 hpanel
.addComponent(text
, LinearLayout
270 .createLayoutData(LinearLayout
.Alignment
.Fill
));
272 messagePanel
.addComponent(hpanel
, LinearLayout
273 .createLayoutData(LinearLayout
.Alignment
.Beginning
));
275 this.setFocusedInteractable(text
);
279 private String
handleQuestion(KeyStroke key
) {
280 String answer
= null;
282 if (waitForOneKeyAnswer
) {
283 answer
= "" + key
.getCharacter();
285 if (key
.getKeyType() == KeyType
.Enter
) {
287 answer
= text
.getText();
293 if (answer
!= null) {
294 Interactable focus
= null;
295 if (this.content
.size() > 0)
296 // focus = content.get(0).getDefaultFocusElement();
297 focus
= content
.get(0).nextFocus(null);
299 this.setFocusedInteractable(focus
);
306 public boolean handleInput(KeyStroke key
) {
307 boolean handled
= false;
309 if (waitForOneKeyAnswer
!= null) {
310 String answer
= handleQuestion(key
);
311 if (answer
!= null) {
312 waitForOneKeyAnswer
= null;
313 setMessage("ANS: " + answer
, false);
318 setMessage(null, false);
320 for (KeyAction action
: actions
) {
321 if (!action
.match(key
))
326 if (action
.onAction()) {
327 switch (action
.getMode()) {
332 if (action
.getKey().getKeyType() == KeyType
.ArrowUp
)
334 if (action
.getKey().getKeyType() == KeyType
.ArrowDown
)
336 if (action
.getKey().getKeyType() == KeyType
.ArrowLeft
)
338 if (action
.getKey().getKeyType() == KeyType
.ArrowRight
)
341 if (content
.size() > 0) {
342 String err
= content
.get(content
.size() - 1).move(
345 setMessage(err
, true);
349 // mode with windows:
351 Card card
= action
.getCard();
353 pushContent(new ContactList(card
));
356 case CONTACT_DETAILS
:
357 Contact contact
= action
.getContact();
358 if (contact
!= null) {
359 pushContent(new ContactDetails(contact
));
362 // mode interpreted by MainWindow:
365 // setMessage("Help! I need somebody! Help!", false);
366 setQuestion("Test question?", false);
371 if (content
.size() == 0)
385 handled
= super.handleInput(key
);