Version 2.0.0: update sources
[jvcard.git] / src / be / nikiroo / jvcard / tui / MainWindow.java
CommitLineData
a3b510ab
NR
1package be.nikiroo.jvcard.tui;
2
5ad0e17e 3import java.io.IOException;
bcb54330 4import java.util.ArrayList;
a3b510ab
NR
5import java.util.Arrays;
6import java.util.LinkedList;
7import java.util.List;
8
7da41ecd 9import be.nikiroo.jvcard.launcher.Main;
f06c8100
NR
10import be.nikiroo.jvcard.resources.ColorOption;
11import be.nikiroo.jvcard.resources.StringId;
a3b510ab 12import be.nikiroo.jvcard.tui.KeyAction.Mode;
f04d8b1c 13import be.nikiroo.jvcard.tui.panes.ContactDetails;
296a0b75 14import be.nikiroo.jvcard.tui.panes.ContactDetailsRaw;
fae07ea7
NR
15import be.nikiroo.jvcard.tui.panes.ContactList;
16import be.nikiroo.jvcard.tui.panes.MainContent;
f06c8100
NR
17import be.nikiroo.utils.StringUtils;
18import be.nikiroo.utils.Version;
a3b510ab
NR
19
20import com.googlecode.lanterna.TerminalSize;
21import com.googlecode.lanterna.gui2.BasicWindow;
22import com.googlecode.lanterna.gui2.BorderLayout;
23import com.googlecode.lanterna.gui2.Direction;
24import com.googlecode.lanterna.gui2.Interactable;
25import com.googlecode.lanterna.gui2.Label;
26import com.googlecode.lanterna.gui2.LinearLayout;
27import com.googlecode.lanterna.gui2.Panel;
28import com.googlecode.lanterna.gui2.TextBox;
a3b510ab
NR
29import com.googlecode.lanterna.gui2.Window;
30import com.googlecode.lanterna.input.KeyStroke;
31import com.googlecode.lanterna.input.KeyType;
32
33/**
0b0b2b0f
NR
34 * This is the main "window" of the program. It can show up to one
35 * {@link MainContent} at any one time, but keeps a stack of contents.
a3b510ab
NR
36 *
37 * @author niki
38 *
39 */
f720df72 40
a3b510ab
NR
41public class MainWindow extends BasicWindow {
42 private List<KeyAction> defaultActions = new LinkedList<KeyAction>();
43 private List<KeyAction> actions = new LinkedList<KeyAction>();
0b0b2b0f 44 private List<MainContent> contentStack = new LinkedList<MainContent>();
f720df72 45 private UserQuestion userQuestion;
bcb54330 46 private String titleCache;
a3b510ab
NR
47 private Panel titlePanel;
48 private Panel mainPanel;
49 private Panel contentPanel;
50 private Panel actionPanel;
51 private Panel messagePanel;
52 private TextBox text;
53
f720df72
NR
54 /**
55 * Information about a question to ask the user and its answer.
56 *
57 * @author niki
f06c8100 58 *
f720df72
NR
59 */
60 private class UserQuestion {
61 private boolean oneKeyAnswer;
62 private KeyAction action;
63 private String answer;
64
65 /**
66 * Create a new {@link UserQuestion}.
67 *
68 * @param action
69 * the action that triggered the question
70 * @param oneKeyAnswer
71 * TRUE if we expect a one-key answer
72 */
73 public UserQuestion(KeyAction action, boolean oneKeyAnswer) {
74 this.action = action;
75 this.oneKeyAnswer = oneKeyAnswer;
76 }
77
78 /**
79 * Return the {@link KeyAction} that triggered the question.
80 *
81 * @return the {@link KeyAction}
82 */
83 public KeyAction getAction() {
84 return action;
85 }
86
87 /**
88 * Check if a one-key answer is expected.
89 *
90 * @return TRUE if a one-key answer is expected
91 */
92 public boolean isOneKeyAnswer() {
93 return oneKeyAnswer;
94 }
95
96 /**
97 * Return the user answer.
98 *
99 * @return the user answer
100 */
101 public String getAnswer() {
102 return answer;
103 }
104
105 /**
106 * Set the user answer.
107 *
108 * @param answer
109 * the new answer
110 */
111 public void setAnswer(String answer) {
112 this.answer = answer;
113 }
114 }
115
0b0b2b0f
NR
116 /**
117 * Create a new, empty window.
118 */
a3b510ab
NR
119 public MainWindow() {
120 this(null);
121 }
122
0b0b2b0f
NR
123 /**
124 * Create a new window hosting the given content.
125 *
126 * @param content
127 * the content to host
128 */
a3b510ab
NR
129 public MainWindow(MainContent content) {
130 super(content == null ? "" : content.getTitle());
131
132 setHints(Arrays.asList(Window.Hint.FULL_SCREEN,
133 Window.Hint.NO_DECORATIONS, Window.Hint.FIT_TERMINAL_WINDOW));
134
135 defaultActions.add(new KeyAction(Mode.BACK, 'q',
136 StringId.KEY_ACTION_BACK));
137 defaultActions.add(new KeyAction(Mode.BACK, KeyType.Escape,
138 StringId.NULL));
139 defaultActions.add(new KeyAction(Mode.HELP, 'h',
140 StringId.KEY_ACTION_HELP));
141 defaultActions.add(new KeyAction(Mode.HELP, KeyType.F1, StringId.NULL));
142
143 actionPanel = new Panel();
144 contentPanel = new Panel();
145 mainPanel = new Panel();
146 messagePanel = new Panel();
147 titlePanel = new Panel();
148
149 Panel actionMessagePanel = new Panel();
150
151 LinearLayout llayout = new LinearLayout(Direction.HORIZONTAL);
152 llayout.setSpacing(0);
153 actionPanel.setLayoutManager(llayout);
154
0b0b2b0f
NR
155 BorderLayout blayout = new BorderLayout();
156 titlePanel.setLayoutManager(blayout);
a3b510ab
NR
157
158 llayout = new LinearLayout(Direction.VERTICAL);
159 llayout.setSpacing(0);
160 messagePanel.setLayoutManager(llayout);
161
0b0b2b0f 162 blayout = new BorderLayout();
a3b510ab
NR
163 mainPanel.setLayoutManager(blayout);
164
165 blayout = new BorderLayout();
166 contentPanel.setLayoutManager(blayout);
167
168 blayout = new BorderLayout();
169 actionMessagePanel.setLayoutManager(blayout);
170
171 actionMessagePanel
172 .addComponent(messagePanel, BorderLayout.Location.TOP);
173 actionMessagePanel.addComponent(actionPanel,
174 BorderLayout.Location.CENTER);
175
176 mainPanel.addComponent(titlePanel, BorderLayout.Location.TOP);
177 mainPanel.addComponent(contentPanel, BorderLayout.Location.CENTER);
178 mainPanel
179 .addComponent(actionMessagePanel, BorderLayout.Location.BOTTOM);
180
181 pushContent(content);
182
183 setComponent(mainPanel);
184 }
185
0b0b2b0f
NR
186 /**
187 * "push" some content to the window stack.
188 *
189 * @param content
190 * the new top-of-the-stack content
191 */
a3b510ab
NR
192 public void pushContent(MainContent content) {
193 List<KeyAction> actions = null;
a3b510ab
NR
194
195 contentPanel.removeAllComponents();
196 if (content != null) {
a3b510ab
NR
197 actions = content.getKeyBindings();
198 contentPanel.addComponent(content, BorderLayout.Location.CENTER);
0b0b2b0f 199 this.contentStack.add(content);
9c8baf0c
NR
200
201 Interactable focus = content.nextFocus(null);
202 if (focus != null)
203 focus.takeFocus();
a3b510ab
NR
204 }
205
bcb54330 206 setTitle();
0b0b2b0f 207 setActions(actions, true);
a3b510ab
NR
208 }
209
0b0b2b0f
NR
210 /**
211 * "pop" the latest, top-of-the-stack content from the window stack.
212 *
213 * @return the removed content if any
214 */
9c8baf0c
NR
215 public MainContent popContent() {
216 MainContent removed = null;
217 MainContent prev = null;
9c8baf0c 218
0b0b2b0f
NR
219 MainContent content = getContent();
220 if (content != null)
221 removed = contentStack.remove(contentStack.size() - 1);
9c8baf0c 222
0b0b2b0f
NR
223 if (contentStack.size() > 0)
224 prev = contentStack.remove(contentStack.size() - 1);
a3b510ab 225
5ad0e17e
NR
226 if (prev != null) {
227 try {
228 String mess = prev.wakeup();
229 if (mess != null)
230 setMessage(mess, false);
231 } catch (IOException e) {
232 setMessage(e.getMessage(), true);
233 }
234 }
235
0b0b2b0f 236 pushContent(prev);
a3b510ab 237
0b0b2b0f 238 return removed;
a3b510ab
NR
239 }
240
9c8baf0c
NR
241 /**
242 * Show the given message on screen. It will disappear at the next action.
243 *
244 * @param mess
245 * the message to display
246 * @param error
247 * TRUE for an error message, FALSE for an information message
bcb54330
NR
248 *
249 * @return TRUE if changes were performed
9c8baf0c 250 */
bcb54330
NR
251 public boolean setMessage(String mess, boolean error) {
252 if (mess != null || messagePanel.getChildCount() > 0) {
253 messagePanel.removeAllComponents();
254 if (mess != null) {
e119a1c1
NR
255 ColorOption element = (error ? ColorOption.LINE_MESSAGE_ERR
256 : ColorOption.LINE_MESSAGE);
257 Label lbl = UiColors.createLabel(element, " " + mess + " ");
bcb54330
NR
258 messagePanel.addComponent(lbl, LinearLayout
259 .createLayoutData(LinearLayout.Alignment.Center));
260 }
261 return true;
262 }
263
264 return false;
265 }
266
267 /**
268 * Show a question to the user and switch to "ask for answer" mode see
269 * {@link MainWindow#handleQuestion}. The user will be asked to enter some
270 * answer and confirm with ENTER.
271 *
296a0b75
NR
272 * @param action
273 * the related action
bcb54330
NR
274 * @param question
275 * the question to ask
276 * @param initial
277 * the initial answer if any (to be edited by the user)
278 */
296a0b75
NR
279 public void setQuestion(KeyAction action, String question, String initial) {
280 setQuestion(action, question, initial, false);
bcb54330
NR
281 }
282
283 /**
284 * Show a question to the user and switch to "ask for answer" mode see
285 * {@link MainWindow#handleQuestion}. The user will be asked to hit one key
286 * as an answer.
287 *
296a0b75
NR
288 * @param action
289 * the related action
bcb54330
NR
290 * @param question
291 * the question to ask
292 */
296a0b75
NR
293 public void setQuestion(KeyAction action, String question) {
294 setQuestion(action, question, null, true);
9c8baf0c
NR
295 }
296
0b0b2b0f
NR
297 /**
298 * Show a question to the user and switch to "ask for answer" mode see
299 * {@link MainWindow#handleQuestion}.
300 *
296a0b75
NR
301 * @param action
302 * the related action
bcb54330
NR
303 * @param question
304 * the question to ask
305 * @param initial
306 * the initial answer if any (to be edited by the user)
0b0b2b0f
NR
307 * @param oneKey
308 * TRUE for a one-key answer, FALSE for a text answer validated
309 * by ENTER
310 */
296a0b75 311 private void setQuestion(KeyAction action, String question, String initial,
bcb54330 312 boolean oneKey) {
f720df72 313 userQuestion = new UserQuestion(action, oneKey);
0b0b2b0f 314
9c8baf0c 315 messagePanel.removeAllComponents();
9c8baf0c 316
0b0b2b0f
NR
317 Panel hpanel = new Panel();
318 LinearLayout llayout = new LinearLayout(Direction.HORIZONTAL);
319 llayout.setSpacing(0);
320 hpanel.setLayoutManager(llayout);
9c8baf0c 321
e119a1c1 322 Label lbl = UiColors.createLabel(ColorOption.LINE_MESSAGE_QUESTION, " "
bcb54330 323 + question + " ");
296a0b75
NR
324 text = new TextBox(new TerminalSize(getSize().getColumns()
325 - lbl.getSize().getColumns(), 1));
f720df72
NR
326
327 if (initial != null) {
328 // add all chars one by one so the caret is at the end
329 for (int index = 0; index < initial.length(); index++) {
330 text.handleInput(new KeyStroke(initial.charAt(index), false,
331 false));
332 }
333 }
9c8baf0c 334
bcb54330
NR
335 hpanel.addComponent(lbl,
336 LinearLayout.createLayoutData(LinearLayout.Alignment.Beginning));
337 hpanel.addComponent(text,
338 LinearLayout.createLayoutData(LinearLayout.Alignment.Fill));
9c8baf0c 339
bcb54330
NR
340 messagePanel
341 .addComponent(hpanel, LinearLayout
342 .createLayoutData(LinearLayout.Alignment.Beginning));
9c8baf0c 343
0b0b2b0f 344 text.takeFocus();
9c8baf0c
NR
345 }
346
296a0b75
NR
347 /**
348 * Refresh the window and the empty-space handling. You should call this
349 * method when the window size changed.
350 *
351 * @param size
352 * the new size of the window
353 */
354 public void refresh(TerminalSize size) {
355 if (size == null)
356 return;
357
358 if (getSize() == null || !getSize().equals(size))
359 setSize(size);
360
361 setTitle();
362
363 if (actions != null)
364 setActions(new ArrayList<KeyAction>(actions), false);
365
366 invalidate();
367 }
368
369 @Override
370 public void invalidate() {
371 super.invalidate();
372 for (MainContent content : contentStack) {
373 content.invalidate();
374 }
375 }
376
377 @Override
378 public boolean handleInput(KeyStroke key) {
379 boolean handled = false;
380
f720df72
NR
381 if (userQuestion != null) {
382 handled = handleQuestion(userQuestion, key);
383 if (handled) {
384 if (userQuestion.getAnswer() != null) {
385 handleAction(userQuestion.getAction(),
386 userQuestion.getAnswer());
296a0b75 387
f720df72
NR
388 userQuestion = null;
389 }
296a0b75
NR
390 }
391 } else {
392 handled = handleKey(key);
393 }
394
f720df72 395 if (!handled) {
296a0b75 396 handled = super.handleInput(key);
f720df72 397 }
296a0b75
NR
398
399 return handled;
400 }
401
bcb54330
NR
402 /**
403 * Actually set the title <b>inside</b> the window. Will also call
296a0b75 404 * {@link BasicWindow#setTitle} with the computed parameters.
bcb54330
NR
405 */
406 private void setTitle() {
0b0b2b0f 407 String prefix = " " + Main.APPLICATION_TITLE + " (version "
f06c8100 408 + Version.getCurrentVersion() + ")";
0b0b2b0f 409
bcb54330 410 String title = null;
0b0b2b0f 411 int count = -1;
bcb54330 412
0b0b2b0f 413 MainContent content = getContent();
bcb54330
NR
414 if (content != null) {
415 title = content.getTitle();
0b0b2b0f 416 count = content.getCount();
bcb54330
NR
417 }
418
419 if (title == null)
420 title = "";
0b0b2b0f 421
bcb54330 422 if (title.length() > 0) {
0b0b2b0f 423 prefix = prefix + ": ";
7da41ecd 424 title = StringUtils.sanitize(title, Main.isUnicode());
0b0b2b0f
NR
425 }
426
bcb54330
NR
427 String countStr = "";
428 if (count > -1) {
429 countStr = "[" + count + "]";
430 }
431
296a0b75
NR
432 int width = -1;
433 if (getSize() != null) {
434 width = getSize().getColumns();
435 }
436
bcb54330
NR
437 if (width > 0) {
438 int padding = width - prefix.length() - title.length()
439 - countStr.length();
440 if (padding > 0) {
441 if (title.length() > 0)
442 title = StringUtils.padString(title, title.length()
443 + padding);
444 else
445 prefix = StringUtils.padString(prefix, prefix.length()
446 + padding);
447 }
0b0b2b0f 448 }
0b0b2b0f 449
bcb54330
NR
450 String titleCache = prefix + title + count;
451 if (!titleCache.equals(this.titleCache)) {
452 super.setTitle(prefix);
0b0b2b0f
NR
453
454 Label lblPrefix = new Label(prefix);
e119a1c1 455 UiColors.themeLabel(ColorOption.TITLE_MAIN, lblPrefix);
0b0b2b0f
NR
456
457 Label lblTitle = null;
bcb54330 458 if (title.length() > 0) {
0b0b2b0f 459 lblTitle = new Label(title);
e119a1c1 460 UiColors.themeLabel(ColorOption.TITLE_VARIABLE, lblTitle);
0b0b2b0f
NR
461 }
462
463 Label lblCount = null;
bcb54330
NR
464 if (countStr != null) {
465 lblCount = new Label(countStr);
e119a1c1 466 UiColors.themeLabel(ColorOption.TITLE_COUNT, lblCount);
0b0b2b0f
NR
467 }
468
469 titlePanel.removeAllComponents();
a3b510ab 470
0b0b2b0f
NR
471 titlePanel.addComponent(lblPrefix, BorderLayout.Location.LEFT);
472 if (lblTitle != null)
473 titlePanel.addComponent(lblTitle, BorderLayout.Location.CENTER);
474 if (lblCount != null)
475 titlePanel.addComponent(lblCount, BorderLayout.Location.RIGHT);
0b0b2b0f
NR
476 }
477 }
478
479 /**
480 * Return the current {@link MainContent} from the stack if any.
481 *
482 * @return the current {@link MainContent}
483 */
484 private MainContent getContent() {
485 if (contentStack.size() > 0) {
486 return contentStack.get(contentStack.size() - 1);
487 }
488
489 return null;
490 }
491
492 /**
493 * Update the list of actions and refresh the action panel.
494 *
495 * @param actions
496 * the list of actions to support
497 * @param enableDefaultactions
498 * TRUE to enable the default actions
499 */
500 private void setActions(List<KeyAction> actions,
501 boolean enableDefaultactions) {
a3b510ab 502 this.actions.clear();
9c8baf0c 503
a3b510ab
NR
504 if (enableDefaultactions)
505 this.actions.addAll(defaultActions);
506
507 if (actions != null)
508 this.actions.addAll(actions);
509
510 actionPanel.removeAllComponents();
511 for (KeyAction action : this.actions) {
668268fc 512 String trans = " " + Main.trans(action.getStringId()) + " ";
a3b510ab
NR
513
514 if (" ".equals(trans))
515 continue;
516
7da41ecd 517 String keyTrans = KeyAction.trans(action.getKey());
a3b510ab
NR
518
519 Panel kPane = new Panel();
520 LinearLayout layout = new LinearLayout(Direction.HORIZONTAL);
521 layout.setSpacing(0);
522 kPane.setLayoutManager(layout);
523
e119a1c1
NR
524 kPane.addComponent(UiColors.createLabel(ColorOption.ACTION_KEY,
525 keyTrans));
59597d59
NR
526 kPane.addComponent(UiColors.createLabel(ColorOption.ACTION_DESC,
527 trans));
a3b510ab
NR
528
529 actionPanel.addComponent(kPane);
530 }
bcb54330
NR
531
532 // fill with "desc" colour
296a0b75
NR
533 int width = -1;
534 if (getSize() != null) {
535 width = getSize().getColumns();
536 }
537
bcb54330 538 if (width > 0) {
59597d59
NR
539 actionPanel.addComponent(UiColors.createLabel(
540 ColorOption.ACTION_DESC, StringUtils.padString("", width)));
bcb54330 541 }
a3b510ab
NR
542 }
543
0b0b2b0f
NR
544 /**
545 * Handle user input when in "ask for question" mode (see
f720df72 546 * {@link MainWindow#userQuestion}).
0b0b2b0f 547 *
f720df72
NR
548 * @param userQuestion
549 * the question data
0b0b2b0f
NR
550 * @param key
551 * the key that has been pressed by the user
552 *
f720df72 553 * @return TRUE if the {@link KeyStroke} was handled
0b0b2b0f 554 */
f720df72
NR
555 private boolean handleQuestion(UserQuestion userQuestion, KeyStroke key) {
556 userQuestion.setAnswer(null);
ae22c247 557
f720df72
NR
558 if (userQuestion.isOneKeyAnswer()) {
559 userQuestion.setAnswer("" + key.getCharacter());
a3b510ab 560 } else {
f720df72
NR
561 // ^h == Backspace
562 if (key.isCtrlDown() && key.getCharacter() == 'h') {
563 key = new KeyStroke(KeyType.Backspace);
564 }
565
566 switch (key.getKeyType()) {
567 case Enter:
a3b510ab 568 if (text != null)
f720df72 569 userQuestion.setAnswer(text.getText());
a3b510ab 570 else
f720df72
NR
571 userQuestion.setAnswer("");
572 break;
573 case Backspace:
574 int pos = text.getCaretPosition().getColumn();
575 if (pos > 0) {
576 String current = text.getText();
577 // force caret one space before:
578 text.setText(current.substring(0, pos - 1));
579 // re-add full text:
580 text.setText(current.substring(0, pos - 1)
581 + current.substring(pos));
582 }
583 return true;
584 default:
585 // Do nothing (continue entering text)
586 break;
a3b510ab
NR
587 }
588 }
589
f720df72 590 if (userQuestion.getAnswer() != null) {
a3b510ab 591 Interactable focus = null;
0b0b2b0f
NR
592 MainContent content = getContent();
593 if (content != null)
594 focus = content.nextFocus(null);
a3b510ab 595
fae07ea7 596 focus.takeFocus();
f720df72
NR
597
598 return true;
a3b510ab
NR
599 }
600
f720df72 601 return false;
a3b510ab
NR
602 }
603
0b0b2b0f
NR
604 /**
605 * Handle the input in case of "normal" (not "ask for answer") mode.
606 *
607 * @param key
608 * the key that was pressed
0b0b2b0f 609 *
bcb54330 610 * @return if the window handled the input
0b0b2b0f 611 */
296a0b75 612 private boolean handleKey(KeyStroke key) {
a3b510ab
NR
613 boolean handled = false;
614
296a0b75
NR
615 if (setMessage(null, false))
616 return true;
a3b510ab 617
0b0b2b0f
NR
618 for (KeyAction action : actions) {
619 if (!action.match(key))
620 continue;
a3b510ab 621
0b0b2b0f
NR
622 handled = true;
623
5ad0e17e
NR
624 action.getObject(); // see {@link KeyAction#getMessage()}
625 String mess = action.getMessage();
626 if (mess != null) {
627 setMessage(mess, action.isError());
628 }
629
59597d59 630 if (!action.isError() && action.onAction()) {
296a0b75
NR
631 handleAction(action, null);
632 }
0b0b2b0f 633
296a0b75
NR
634 break;
635 }
0b0b2b0f 636
296a0b75
NR
637 return handled;
638 }
639
640 /**
641 * Handle the input in case of "normal" (not "ask for answer") mode.
642 *
f06c8100
NR
643 * @param action
644 * the key that was pressed and the action to take
296a0b75
NR
645 * @param answer
646 * the answer given for this key
647 *
296a0b75
NR
648 */
649 private void handleAction(KeyAction action, String answer) {
650 MainContent content = getContent();
651
296a0b75
NR
652 switch (action.getMode()) {
653 case MOVE:
654 int x = 0;
655 int y = 0;
656
657 if (action.getKey().getKeyType() == KeyType.ArrowUp)
658 x = -1;
659 if (action.getKey().getKeyType() == KeyType.ArrowDown)
660 x = 1;
661 if (action.getKey().getKeyType() == KeyType.ArrowLeft)
662 y = -1;
663 if (action.getKey().getKeyType() == KeyType.ArrowRight)
664 y = 1;
665
666 if (content != null) {
667 String err = content.move(x, y);
668 if (err != null)
669 setMessage(err, true);
670 }
671
672 break;
673 // mode with windows:
674 case CONTACT_LIST:
ae22c247
NR
675 if (action.getCard() != null) {
676 pushContent(new ContactList(action.getCard()));
5ad0e17e
NR
677 } else if (action.getObject() != null
678 && action.getObject() instanceof MainContent) {
679 MainContent mergeContent = (MainContent) action.getObject();
680 pushContent(mergeContent);
296a0b75
NR
681 }
682 break;
683 case CONTACT_DETAILS:
ae22c247
NR
684 if (action.getContact() != null) {
685 pushContent(new ContactDetails(action.getContact()));
f04d8b1c
NR
686 }
687 break;
688 case CONTACT_DETAILS_RAW:
ae22c247
NR
689 if (action.getContact() != null) {
690 pushContent(new ContactDetailsRaw(action.getContact()));
296a0b75
NR
691 }
692 break;
693 // mode interpreted by MainWindow:
694 case HELP:
695 // TODO
f720df72 696 setMessage("Help! I need somebody! Help!", false);
296a0b75
NR
697
698 break;
699 case BACK:
700 String warning = content.getExitWarning();
701 if (warning != null) {
702 if (answer == null) {
703 setQuestion(action, warning);
704 } else {
705 setMessage(null, false);
706 if (answer.equalsIgnoreCase("y")) {
bcb54330 707 popContent();
a3b510ab 708 }
296a0b75
NR
709 }
710 } else {
711 popContent();
712 }
0b0b2b0f 713
296a0b75
NR
714 if (contentStack.size() == 0) {
715 close();
716 }
bcb54330 717
296a0b75
NR
718 break;
719 // action modes:
ae22c247 720 case ASK_USER:
296a0b75 721 if (answer == null) {
ae22c247
NR
722 setQuestion(action, action.getQuestion(),
723 action.getDefaultAnswer());
296a0b75 724 } else {
ae22c247
NR
725 setMessage(action.callback(answer), true);
726 content.refreshData();
727 invalidate();
728 setTitle();
296a0b75
NR
729 }
730 break;
ae22c247 731 case ASK_USER_KEY:
296a0b75 732 if (answer == null) {
ae22c247 733 setQuestion(action, action.getQuestion());
296a0b75 734 } else {
ae22c247
NR
735 setMessage(action.callback(answer), true);
736 content.refreshData();
737 invalidate();
738 setTitle();
0b0b2b0f 739 }
296a0b75
NR
740 break;
741 default:
742 case NONE:
0b0b2b0f
NR
743 break;
744 }
a3b510ab
NR
745 }
746}