2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2017 Kevin Lamonte
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
31 import java
.util
.ArrayList
;
32 import java
.util
.List
;
34 import jexer
.event
.TKeypressEvent
;
35 import static jexer
.TKeypress
.*;
38 * TMessageBox is a system-modal dialog with buttons for OK, Cancel, Yes, or
44 * box = application.messageBox(title, caption,
45 * TMessageBox.Type.OK | TMessageBox.Type.CANCEL);
47 * if (box.getResult() == TMessageBox.OK) {
48 * ... the user pressed OK, do stuff ...
54 public class TMessageBox
extends TWindow
{
57 * Message boxes have these supported types.
66 * Show both OK and Cancel buttons.
71 * Show both Yes and No buttons.
76 * Show Yes, No, and Cancel buttons.
82 * The type of this message box.
89 private List
<TButton
> buttons
;
92 * Message boxes have these possible results.
101 * User clicked "Cancel".
106 * User clicked "Yes".
117 * Which button was clicked: OK, CANCEL, YES, or NO.
119 private Result result
= Result
.OK
;
124 * @return the result: OK, CANCEL, YES, or NO.
126 public final Result
getResult() {
131 * Public constructor. The message box will be centered on screen.
133 * @param application TApplication that manages this window
134 * @param title window title, will be centered along the top border
135 * @param caption message to display. Use embedded newlines to get a
138 public TMessageBox(final TApplication application
, final String title
,
139 final String caption
) {
141 this(application
, title
, caption
, Type
.OK
, true);
145 * Public constructor. The message box will be centered on screen.
147 * @param application TApplication that manages this window
148 * @param title window title, will be centered along the top border
149 * @param caption message to display. Use embedded newlines to get a
151 * @param type one of the Type constants. Default is Type.OK.
153 public TMessageBox(final TApplication application
, final String title
,
154 final String caption
, final Type type
) {
156 this(application
, title
, caption
, type
, true);
160 * Public constructor. The message box will be centered on screen.
162 * @param application TApplication that manages this window
163 * @param title window title, will be centered along the top border
164 * @param caption message to display. Use embedded newlines to get a
166 * @param type one of the Type constants. Default is Type.OK.
167 * @param yield if true, yield this Thread. Subclasses need to set this
168 * to false and yield at their end of their constructor intead.
170 protected TMessageBox(final TApplication application
, final String title
,
171 final String caption
, final Type type
, final boolean yield
) {
173 // Start as 50x50 at (1, 1). These will be changed later.
174 super(application
, title
, 1, 1, 100, 100, CENTERED
| MODAL
);
176 // Hang onto type so that we can provide more convenience in
180 // Determine width and height
181 String
[] lines
= caption
.split("\n");
182 int width
= title
.length() + 12;
183 setHeight(6 + lines
.length
);
184 for (String line
: lines
) {
185 if (line
.length() + 4 > width
) {
186 width
= line
.length() + 4;
190 if (getWidth() > getScreen().getWidth()) {
191 setWidth(getScreen().getWidth());
193 // Re-center window to get an appropriate (x, y)
196 // Now add my elements
198 for (String line
: lines
) {
199 addLabel(line
, 1, lineI
, "twindow.background.modal");
205 buttons
= new ArrayList
<TButton
>();
209 // Setup button actions
214 if (getWidth() < 15) {
217 buttonX
= (getWidth() - 11) / 2;
218 buttons
.add(addButton(" &OK ", buttonX
, lineI
,
222 getApplication().closeWindow(TMessageBox
.this);
230 result
= Result
.CANCEL
;
231 if (getWidth() < 26) {
234 buttonX
= (getWidth() - 22) / 2;
235 buttons
.add(addButton(" &OK ", buttonX
, lineI
,
239 getApplication().closeWindow(TMessageBox
.this);
245 buttons
.add(addButton("&Cancel", buttonX
, lineI
,
248 result
= Result
.CANCEL
;
249 getApplication().closeWindow(TMessageBox
.this);
258 if (getWidth() < 20) {
261 buttonX
= (getWidth() - 16) / 2;
262 buttons
.add(addButton("&Yes", buttonX
, lineI
,
266 getApplication().closeWindow(TMessageBox
.this);
272 buttons
.add(addButton("&No", buttonX
, lineI
,
276 getApplication().closeWindow(TMessageBox
.this);
284 result
= Result
.CANCEL
;
285 if (getWidth() < 31) {
288 buttonX
= (getWidth() - 27) / 2;
289 buttons
.add(addButton("&Yes", buttonX
, lineI
,
293 getApplication().closeWindow(TMessageBox
.this);
299 buttons
.add(addButton("&No", buttonX
, lineI
,
303 getApplication().closeWindow(TMessageBox
.this);
309 buttons
.add(addButton("&Cancel", buttonX
, lineI
,
312 result
= Result
.CANCEL
;
313 getApplication().closeWindow(TMessageBox
.this);
321 throw new IllegalArgumentException("Invalid message box type: " + type
);
324 // Set the secondaryThread to run me
325 getApplication().enableSecondaryEventReceiver(this);
328 // Yield to the secondary thread. When I come back from the
329 // constructor response will already be set.
330 getApplication().yield();
337 * @param keypress keystroke event
340 public void onKeypress(final TKeypressEvent keypress
) {
342 if (this instanceof TInputBox
) {
343 super.onKeypress(keypress
);
347 // Some convenience for message boxes: Alt won't be needed for the
352 if (keypress
.equals(kbO
)) {
353 buttons
.get(0).dispatch();
359 if (keypress
.equals(kbO
)) {
360 buttons
.get(0).dispatch();
362 } else if (keypress
.equals(kbC
)) {
363 buttons
.get(1).dispatch();
369 if (keypress
.equals(kbY
)) {
370 buttons
.get(0).dispatch();
372 } else if (keypress
.equals(kbN
)) {
373 buttons
.get(1).dispatch();
379 if (keypress
.equals(kbY
)) {
380 buttons
.get(0).dispatch();
382 } else if (keypress
.equals(kbN
)) {
383 buttons
.get(1).dispatch();
385 } else if (keypress
.equals(kbC
)) {
386 buttons
.get(2).dispatch();
392 throw new IllegalArgumentException("Invalid message box type: " + type
);
395 super.onKeypress(keypress
);