2 * Jexer - Java Text User Interface
4 * License: LGPLv3 or later
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
10 * Copyright (C) 2015 Kevin Lamonte
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
33 import java
.util
.ArrayList
;
34 import java
.util
.List
;
36 import jexer
.event
.TKeypressEvent
;
37 import static jexer
.TKeypress
.*;
40 * TMessageBox is a system-modal dialog with buttons for OK, Cancel, Yes, or
46 * box = application.messageBox(title, caption,
47 * TMessageBox.Type.OK | TMessageBox.Type.CANCEL);
49 * if (box.getResult() == TMessageBox.OK) {
50 * ... the user pressed OK, do stuff ...
56 public class TMessageBox
extends TWindow
{
59 * Message boxes have these supported types.
68 * Show both OK and Cancel buttons.
73 * Show both Yes and No buttons.
78 * Show Yes, No, and Cancel buttons.
84 * The type of this message box.
91 List
<TButton
> buttons
;
94 * Message boxes have these possible results.
103 * User clicked "Cancel".
108 * User clicked "Yes".
119 * Which button was clicked: OK, CANCEL, YES, or NO.
121 private Result result
= Result
.OK
;
126 * @return the result: OK, CANCEL, YES, or NO.
128 public final Result
getResult() {
133 * Public constructor. The message box will be centered on screen.
135 * @param application TApplication that manages this window
136 * @param title window title, will be centered along the top border
137 * @param caption message to display. Use embedded newlines to get a
140 public TMessageBox(final TApplication application
, final String title
,
141 final String caption
) {
143 this(application
, title
, caption
, Type
.OK
, true);
147 * Public constructor. The message box will be centered on screen.
149 * @param application TApplication that manages this window
150 * @param title window title, will be centered along the top border
151 * @param caption message to display. Use embedded newlines to get a
153 * @param type one of the Type constants. Default is Type.OK.
155 public TMessageBox(final TApplication application
, final String title
,
156 final String caption
, final Type type
) {
158 this(application
, title
, caption
, type
, true);
162 * Public constructor. The message box will be centered on screen.
164 * @param application TApplication that manages this window
165 * @param title window title, will be centered along the top border
166 * @param caption message to display. Use embedded newlines to get a
168 * @param type one of the Type constants. Default is Type.OK.
169 * @param yield if true, yield this Thread. Subclasses need to set this
170 * to false and yield at their end of their constructor intead.
172 protected TMessageBox(final TApplication application
, final String title
,
173 final String caption
, final Type type
, final boolean yield
) {
175 // Start as 50x50 at (1, 1). These will be changed later.
176 super(application
, title
, 1, 1, 100, 100, CENTERED
| MODAL
);
178 // Hang onto type so that we can provide more convenience in
182 // Determine width and height
183 String
[] lines
= caption
.split("\n");
184 int width
= title
.length() + 12;
185 setHeight(6 + lines
.length
);
186 for (String line
: lines
) {
187 if (line
.length() + 4 > width
) {
188 width
= line
.length() + 4;
192 if (getWidth() > getScreen().getWidth()) {
193 setWidth(getScreen().getWidth());
195 // Re-center window to get an appropriate (x, y)
198 // Now add my elements
200 for (String line
: lines
) {
201 addLabel(line
, 1, lineI
, "twindow.background.modal");
207 buttons
= new ArrayList
<TButton
>();
211 // Setup button actions
216 if (getWidth() < 15) {
219 buttonX
= (getWidth() - 11) / 2;
220 buttons
.add(addButton(" &OK ", buttonX
, lineI
,
224 getApplication().closeWindow(TMessageBox
.this);
232 result
= Result
.CANCEL
;
233 if (getWidth() < 26) {
236 buttonX
= (getWidth() - 22) / 2;
237 buttons
.add(addButton(" &OK ", buttonX
, lineI
,
241 getApplication().closeWindow(TMessageBox
.this);
247 buttons
.add(addButton("&Cancel", buttonX
, lineI
,
250 result
= Result
.CANCEL
;
251 getApplication().closeWindow(TMessageBox
.this);
260 if (getWidth() < 20) {
263 buttonX
= (getWidth() - 16) / 2;
264 buttons
.add(addButton("&Yes", buttonX
, lineI
,
268 getApplication().closeWindow(TMessageBox
.this);
274 buttons
.add(addButton("&No", buttonX
, lineI
,
278 getApplication().closeWindow(TMessageBox
.this);
286 result
= Result
.CANCEL
;
287 if (getWidth() < 31) {
290 buttonX
= (getWidth() - 27) / 2;
291 buttons
.add(addButton("&Yes", buttonX
, lineI
,
295 getApplication().closeWindow(TMessageBox
.this);
301 buttons
.add(addButton("&No", buttonX
, lineI
,
305 getApplication().closeWindow(TMessageBox
.this);
311 buttons
.add(addButton("&Cancel", buttonX
, lineI
,
314 result
= Result
.CANCEL
;
315 getApplication().closeWindow(TMessageBox
.this);
323 throw new IllegalArgumentException("Invalid message box type: " + type
);
326 // Set the secondaryThread to run me
327 getApplication().enableSecondaryEventReceiver(this);
330 // Yield to the secondary thread. When I come back from the
331 // constructor response will already be set.
332 getApplication().yield();
339 * @param keypress keystroke event
342 public void onKeypress(final TKeypressEvent keypress
) {
344 if (this instanceof TInputBox
) {
345 super.onKeypress(keypress
);
349 // Some convenience for message boxes: Alt won't be needed for the
354 if (keypress
.equals(kbO
)) {
355 buttons
.get(0).dispatch();
361 if (keypress
.equals(kbO
)) {
362 buttons
.get(0).dispatch();
364 } else if (keypress
.equals(kbC
)) {
365 buttons
.get(1).dispatch();
371 if (keypress
.equals(kbY
)) {
372 buttons
.get(0).dispatch();
374 } else if (keypress
.equals(kbN
)) {
375 buttons
.get(1).dispatch();
381 if (keypress
.equals(kbY
)) {
382 buttons
.get(0).dispatch();
384 } else if (keypress
.equals(kbN
)) {
385 buttons
.get(1).dispatch();
387 } else if (keypress
.equals(kbC
)) {
388 buttons
.get(2).dispatch();
394 throw new IllegalArgumentException("Invalid message box type: " + type
);
397 super.onKeypress(keypress
);