fix javadoc header
[fanfix.git] / src / jexer / TMessageBox.java
1 /*
2 * Jexer - Java Text User Interface
3 *
4 * License: LGPLv3 or later
5 *
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.
9 *
10 * Copyright (C) 2015 Kevin Lamonte
11 *
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.
16 *
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.
21 *
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
26 * 02110-1301 USA
27 *
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 * @version 1
30 */
31 package jexer;
32
33 import java.util.ArrayList;
34 import java.util.List;
35
36 /**
37 * TMessageBox is a system-modal dialog with buttons for OK, Cancel, Yes, or
38 * No. Call it like:
39 *
40 * <p>
41 * <pre>
42 * {@code
43 * box = application.messageBox(title, caption,
44 * TMessageBox.Type.OK | TMessageBox.Type.CANCEL);
45 *
46 * if (box.getResult() == TMessageBox.OK) {
47 * ... the user pressed OK, do stuff ...
48 * }
49 * }
50 * </pre>
51 *
52 */
53 public class TMessageBox extends TWindow {
54
55 /**
56 * Message boxes have these supported types.
57 */
58 public enum Type {
59 /**
60 * Show an OK button.
61 */
62 OK,
63
64 /**
65 * Show both OK and Cancel buttons.
66 */
67 OKCANCEL,
68
69 /**
70 * Show both Yes and No buttons.
71 */
72 YESNO,
73
74 /**
75 * Show Yes, No, and Cancel buttons.
76 */
77 YESNOCANCEL
78 };
79
80 /**
81 * Message boxes have these possible results.
82 */
83 public enum Result {
84 /**
85 * User clicked "OK".
86 */
87 OK,
88
89 /**
90 * User clicked "Cancel".
91 */
92 CANCEL,
93
94 /**
95 * User clicked "Yes".
96 */
97 YES,
98
99 /**
100 * User clicked "No".
101 */
102 NO
103 };
104
105
106 /**
107 * Which button was clicked: OK, CANCEL, YES, or NO.
108 */
109 private Result result = Result.OK;
110
111 /**
112 * Get the result.
113 *
114 * @return the result: OK, CANCEL, YES, or NO.
115 */
116 public final Result getResult() {
117 return result;
118 }
119
120 /**
121 * Public constructor. The message box will be centered on screen.
122 *
123 * @param application TApplication that manages this window
124 * @param title window title, will be centered along the top border
125 * @param caption message to display. Use embedded newlines to get a
126 * multi-line box.
127 */
128 public TMessageBox(final TApplication application, final String title,
129 final String caption) {
130
131 this(application, title, caption, Type.OK, true);
132 }
133
134 /**
135 * Public constructor. The message box will be centered on screen.
136 *
137 * @param application TApplication that manages this window
138 * @param title window title, will be centered along the top border
139 * @param caption message to display. Use embedded newlines to get a
140 * multi-line box.
141 * @param type one of the Type constants. Default is Type.OK.
142 */
143 public TMessageBox(final TApplication application, final String title,
144 final String caption, final Type type) {
145
146 this(application, title, caption, type, true);
147 }
148
149 /**
150 * Public constructor. The message box will be centered on screen.
151 *
152 * @param application TApplication that manages this window
153 * @param title window title, will be centered along the top border
154 * @param caption message to display. Use embedded newlines to get a
155 * multi-line box.
156 * @param type one of the Type constants. Default is Type.OK.
157 * @param yield if true, yield this Thread. Subclasses need to set this
158 * to false and yield at their end of their constructor intead.
159 */
160 protected TMessageBox(final TApplication application, final String title,
161 final String caption, final Type type, final boolean yield) {
162
163 // Start as 50x50 at (1, 1). These will be changed later.
164 super(application, title, 1, 1, 100, 100, CENTERED | MODAL);
165
166 // Determine width and height
167 String [] lines = caption.split("\n");
168 int width = title.length() + 12;
169 setHeight(6 + lines.length);
170 for (String line: lines) {
171 if (line.length() + 4 > width) {
172 width = line.length() + 4;
173 }
174 }
175 setWidth(width);
176 if (getWidth() > getScreen().getWidth()) {
177 setWidth(getScreen().getWidth());
178 }
179 // Re-center window to get an appropriate (x, y)
180 center();
181
182 // Now add my elements
183 int lineI = 1;
184 for (String line: lines) {
185 addLabel(line, 1, lineI, "twindow.background.modal");
186 lineI++;
187 }
188
189 // The button line
190 lineI++;
191 List<TButton> buttons = new ArrayList<TButton>();
192
193 int buttonX = 0;
194
195 // Setup button actions
196 switch (type) {
197
198 case OK:
199 result = Result.OK;
200 if (getWidth() < 15) {
201 setWidth(15);
202 }
203 buttonX = (getWidth() - 11) / 2;
204 buttons.add(addButton(" &OK ", buttonX, lineI,
205 new TAction() {
206 public void DO() {
207 result = Result.OK;
208 getApplication().closeWindow(TMessageBox.this);
209 }
210 }
211 )
212 );
213 break;
214
215 case OKCANCEL:
216 result = Result.CANCEL;
217 if (getWidth() < 26) {
218 setWidth(26);
219 }
220 buttonX = (getWidth() - 22) / 2;
221 buttons.add(addButton(" &OK ", buttonX, lineI,
222 new TAction() {
223 public void DO() {
224 result = Result.OK;
225 getApplication().closeWindow(TMessageBox.this);
226 }
227 }
228 )
229 );
230 buttonX += 8 + 4;
231 buttons.add(addButton("&Cancel", buttonX, lineI,
232 new TAction() {
233 public void DO() {
234 result = Result.CANCEL;
235 getApplication().closeWindow(TMessageBox.this);
236 }
237 }
238 )
239 );
240 break;
241
242 case YESNO:
243 result = Result.NO;
244 if (getWidth() < 20) {
245 setWidth(20);
246 }
247 buttonX = (getWidth() - 16) / 2;
248 buttons.add(addButton("&Yes", buttonX, lineI,
249 new TAction() {
250 public void DO() {
251 result = Result.YES;
252 getApplication().closeWindow(TMessageBox.this);
253 }
254 }
255 )
256 );
257 buttonX += 5 + 4;
258 buttons.add(addButton("&No", buttonX, lineI,
259 new TAction() {
260 public void DO() {
261 result = Result.NO;
262 getApplication().closeWindow(TMessageBox.this);
263 }
264 }
265 )
266 );
267 break;
268
269 case YESNOCANCEL:
270 result = Result.CANCEL;
271 if (getWidth() < 31) {
272 setWidth(31);
273 }
274 buttonX = (getWidth() - 27) / 2;
275 buttons.add(addButton("&Yes", buttonX, lineI,
276 new TAction() {
277 public void DO() {
278 result = Result.YES;
279 getApplication().closeWindow(TMessageBox.this);
280 }
281 }
282 )
283 );
284 buttonX += 5 + 4;
285 buttons.add(addButton("&No", buttonX, lineI,
286 new TAction() {
287 public void DO() {
288 result = Result.NO;
289 getApplication().closeWindow(TMessageBox.this);
290 }
291 }
292 )
293 );
294 buttonX += 4 + 4;
295 buttons.add(addButton("&Cancel", buttonX, lineI,
296 new TAction() {
297 public void DO() {
298 result = Result.CANCEL;
299 getApplication().closeWindow(TMessageBox.this);
300 }
301 }
302 )
303 );
304 break;
305
306 default:
307 throw new IllegalArgumentException("Invalid message box type: " + type);
308 }
309
310 // Set the secondaryThread to run me
311 getApplication().enableSecondaryEventReceiver(this);
312
313 if (yield) {
314 // Yield to the secondary thread. When I come back from the
315 // constructor response will already be set.
316 getApplication().yield();
317 }
318 }
319
320 }