clean up threads and timers
[nikiroo-utils.git] / src / jexer / demos / Demo1.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.demos;
32
33 import jexer.*;
34 import jexer.event.*;
35 import jexer.menu.*;
36
37 /**
38 * This window demonstates the TText, THScroller, and TVScroller widgets.
39 */
40 class DemoTextWindow extends TWindow {
41
42 /**
43 * Hang onto my TText so I can resize it with the window.
44 */
45 private TText textField;
46
47 /**
48 * Public constructor.
49 *
50 * @param parent the main application
51 */
52 public DemoTextWindow(final TApplication parent) {
53 super(parent, "Text Areas", 0, 0, 44, 20, RESIZABLE);
54
55 textField = addText(
56 "This is an example of a reflowable text field. Some example text follows.\n" +
57 "\n" +
58 "This library implements a text-based windowing system loosely\n" +
59 "reminiscient of Borland's [Turbo\n" +
60 "Vision](http://en.wikipedia.org/wiki/Turbo_Vision) library. For those\n" +
61 "wishing to use the actual C++ Turbo Vision library, see [Sergio\n" +
62 "Sigala's updated version](http://tvision.sourceforge.net/) that runs\n" +
63 "on many more platforms.\n" +
64 "\n" +
65 "Currently the only console platform supported is Posix (tested on\n" +
66 "Linux). Input/output is handled through terminal escape sequences\n" +
67 "generated by the library itself: ncurses is not required or linked to. \n" +
68 "xterm mouse tracking using UTF8 coordinates is supported.\n" +
69 "\n" +
70 "This library is licensed LGPL (\"GNU Lesser General Public License\")\n" +
71 "version 3 or greater. See the file COPYING for the full license text,\n" +
72 "which includes both the GPL v3 and the LGPL supplemental terms.\n" +
73 "\n",
74 1, 1, 40, 16);
75 }
76
77 /**
78 * Handle window/screen resize events.
79 *
80 * @param event resize event
81 */
82 @Override
83 public void onResize(final TResizeEvent event) {
84 if (event.getType() == TResizeEvent.Type.WIDGET) {
85 // Resize the text field
86 textField.setWidth(event.getWidth() - 4);
87 textField.setHeight(event.getHeight() - 4);
88 textField.reflow();
89 return;
90 }
91
92 // Pass to children instead
93 for (TWidget widget: getChildren()) {
94 widget.onResize(event);
95 }
96 }
97 }
98
99 /**
100 * This window demonstates the TRadioGroup, TRadioButton, and TCheckbox
101 * widgets.
102 */
103 class DemoCheckboxWindow extends TWindow {
104
105 /**
106 * Constructor.
107 *
108 * @param parent the main application
109 */
110 DemoCheckboxWindow(final TApplication parent) {
111 this(parent, CENTERED | RESIZABLE);
112 }
113
114 /**
115 * Constructor.
116 *
117 * @param parent the main application
118 * @param flags bitmask of MODAL, CENTERED, or RESIZABLE
119 */
120 DemoCheckboxWindow(final TApplication parent, final int flags) {
121 // Construct a demo window. X and Y don't matter because it will be
122 // centered on screen.
123 super(parent, "Radiobuttons and Checkboxes", 0, 0, 60, 15, flags);
124
125 int row = 1;
126
127 // Add some widgets
128 addLabel("Check box example 1", 1, row);
129 addCheckbox(35, row++, "Checkbox 1", false);
130 addLabel("Check box example 2", 1, row);
131 addCheckbox(35, row++, "Checkbox 2", true);
132 row += 2;
133
134 TRadioGroup group = addRadioGroup(1, row, "Group 1");
135 group.addRadioButton("Radio option 1");
136 group.addRadioButton("Radio option 2");
137 group.addRadioButton("Radio option 3");
138
139 addButton("&Close Window", (getWidth() - 14) / 2, getHeight() - 4,
140 new TAction() {
141 public void DO() {
142 DemoCheckboxWindow.this.getApplication()
143 .closeWindow(DemoCheckboxWindow.this);
144 }
145 }
146 );
147 }
148
149 }
150
151
152 /**
153 * This window demonstates the TMessageBox and TInputBox widgets.
154 */
155 class DemoMsgBoxWindow extends TWindow {
156
157 /**
158 * Constructor.
159 *
160 * @param parent the main application
161 */
162 DemoMsgBoxWindow(final TApplication parent) {
163 this(parent, TWindow.CENTERED | TWindow.RESIZABLE);
164 }
165
166 /**
167 * Constructor.
168 *
169 * @param parent the main application
170 * @param flags bitmask of MODAL, CENTERED, or RESIZABLE
171 */
172 DemoMsgBoxWindow(final TApplication parent, final int flags) {
173 // Construct a demo window. X and Y don't matter because it
174 // will be centered on screen.
175 super(parent, "Message Boxes", 0, 0, 60, 15, flags);
176
177 int row = 1;
178
179 // Add some widgets
180 addLabel("Default OK message box", 1, row);
181 addButton("Open O&K MB", 35, row,
182 new TAction() {
183 public void DO() {
184 getApplication().messageBox("OK MessageBox",
185 "This is an example of a OK MessageBox. This is the\n" +
186 "default MessageBox.\n" +
187 "\n" +
188 "Note that the MessageBox text can span multiple\n" +
189 "lines.\n" +
190 "\n" +
191 "The default result (if someone hits the top-left\n" +
192 "close button) is OK.\n",
193 TMessageBox.Type.OK);
194 }
195 }
196 );
197 row += 2;
198
199 addLabel("OK/Cancel message box", 1, row);
200 addButton("O&pen OKC MB", 35, row,
201 new TAction() {
202 public void DO() {
203 getApplication().messageBox("OK/Cancel MessageBox",
204 "This is an example of a OK/Cancel MessageBox.\n" +
205 "\n" +
206 "Note that the MessageBox text can span multiple\n" +
207 "lines.\n" +
208 "\n" +
209 "The default result (if someone hits the top-left\n" +
210 "close button) is CANCEL.\n",
211 TMessageBox.Type.OKCANCEL);
212 }
213 }
214 );
215 row += 2;
216
217 addLabel("Yes/No message box", 1, row);
218 addButton("Open &YN MB", 35, row,
219 new TAction() {
220 public void DO() {
221 getApplication().messageBox("Yes/No MessageBox",
222 "This is an example of a Yes/No MessageBox.\n" +
223 "\n" +
224 "Note that the MessageBox text can span multiple\n" +
225 "lines.\n" +
226 "\n" +
227 "The default result (if someone hits the top-left\n" +
228 "close button) is NO.\n",
229 TMessageBox.Type.YESNO);
230 }
231 }
232 );
233 row += 2;
234
235 addLabel("Yes/No/Cancel message box", 1, row);
236 addButton("Ope&n YNC MB", 35, row,
237 new TAction() {
238 public void DO() {
239 getApplication().messageBox("Yes/No/Cancel MessageBox",
240 "This is an example of a Yes/No/Cancel MessageBox.\n" +
241 "\n" +
242 "Note that the MessageBox text can span multiple\n" +
243 "lines.\n" +
244 "\n" +
245 "The default result (if someone hits the top-left\n" +
246 "close button) is CANCEL.\n",
247 TMessageBox.Type.YESNOCANCEL);
248 }
249 }
250 );
251 row += 2;
252
253 addLabel("Input box", 1, row);
254 addButton("Open &input box", 35, row,
255 new TAction() {
256 public void DO() {
257 TInputBox in = getApplication().inputBox("Input Box",
258 "This is an example of an InputBox.\n" +
259 "\n" +
260 "Note that the InputBox text can span multiple\n" +
261 "lines.\n",
262 "some input text");
263 getApplication().messageBox("Your InputBox Answer",
264 "You entered: " + in.getText());
265 }
266 }
267 );
268
269 addButton("&Close Window", (getWidth() - 14) / 2, getHeight() - 4,
270 new TAction() {
271 public void DO() {
272 getApplication().closeWindow(DemoMsgBoxWindow.this);
273 }
274 }
275 );
276 }
277 }
278
279 /**
280 * This is the main "demo" application window. It makes use of the TTimer,
281 * TProgressBox, TLabel, TButton, and TField widgets.
282 */
283 class DemoMainWindow extends TWindow {
284
285 // Timer that increments a number.
286 private TTimer timer;
287
288 // Timer label is updated with timer ticks.
289 TLabel timerLabel;
290
291 /**
292 * We need to override onClose so that the timer will no longer be called
293 * after we close the window. TTimers currently are completely unaware
294 * of the rest of the UI classes.
295 */
296 @Override
297 public void onClose() {
298 getApplication().removeTimer(timer);
299 }
300
301 /**
302 * Construct demo window. It will be centered on screen.
303 *
304 * @param parent the main application
305 */
306 public DemoMainWindow(final TApplication parent) {
307 this(parent, CENTERED | RESIZABLE);
308 }
309
310 // These are used by the timer loop. They have to be at class scope so
311 // that they can be accessed by the anonymous TAction class.
312 int timerI = 0;
313 TProgressBar progressBar;
314
315 /**
316 * Constructor.
317 *
318 * @param parent the main application
319 * @param flags bitmask of MODAL, CENTERED, or RESIZABLE
320 */
321 private DemoMainWindow(final TApplication parent, final int flags) {
322 // Construct a demo window. X and Y don't matter because it will be
323 // centered on screen.
324 super(parent, "Demo Window", 0, 0, 60, 23, flags);
325
326 int row = 1;
327
328 // Add some widgets
329 if (!isModal()) {
330 addLabel("Message Boxes", 1, row);
331 addButton("&MessageBoxes", 35, row,
332 new TAction() {
333 public void DO() {
334 new DemoMsgBoxWindow(getApplication());
335 }
336 }
337 );
338 }
339 row += 2;
340
341 addLabel("Open me as modal", 1, row);
342 addButton("W&indow", 35, row,
343 new TAction() {
344 public void DO() {
345 new DemoMainWindow(getApplication(), MODAL);
346 }
347 }
348 );
349
350 row += 2;
351
352 addLabel("Variable-width text field:", 1, row);
353 addField(35, row++, 15, false, "Field text");
354 addLabel("Fixed-width text field:", 1, row);
355 addField(35, row++, 15, true);
356 addLabel("Variable-width password:", 1, row);
357 addPasswordField(35, row++, 15, false);
358 addLabel("Fixed-width password:", 1, row);
359 addPasswordField(35, row++, 15, true, "hunter2");
360 row += 2;
361
362 if (!isModal()) {
363 addLabel("Radio buttons and checkboxes", 1, row);
364 addButton("&Checkboxes", 35, row,
365 new TAction() {
366 public void DO() {
367 new DemoCheckboxWindow(getApplication());
368 }
369 }
370 );
371 }
372 row += 2;
373
374 /*
375 if (!isModal()) {
376 addLabel("Editor window", 1, row);
377 addButton("Edito&r", 35, row,
378 {
379 new TEditor(application, 0, 0, 60, 15);
380 }
381 );
382 }
383 row += 2;
384 */
385
386 if (!isModal()) {
387 addLabel("Text areas", 1, row);
388 addButton("&Text", 35, row,
389 new TAction() {
390 public void DO() {
391 new DemoTextWindow(getApplication());
392 }
393 }
394 );
395 }
396 row += 2;
397
398 /*
399 if (!isModal()) {
400 addLabel("Tree views", 1, row);
401 addButton("Tree&View", 35, row,
402 {
403 new DemoTreeViewWindow(application);
404 }
405 );
406 }
407 row += 2;
408 */
409
410 if (!isModal()) {
411 addLabel("Terminal", 1, row);
412 addButton("Termi&nal", 35, row,
413 new TAction() {
414 public void DO() {
415 getApplication().openTerminal(0, 0);
416 }
417 }
418 );
419 }
420 row += 2;
421
422 progressBar = addProgressBar(1, row, 22, 0);
423 row++;
424 timerLabel = addLabel("Timer", 1, row);
425 timer = getApplication().addTimer(250, true,
426 new TAction() {
427
428 public void DO() {
429 timerLabel.setText(String.format("Timer: %d", timerI));
430 timerLabel.setWidth(timerLabel.getText().length());
431 if (timerI < 100) {
432 timerI++;
433 }
434 progressBar.setValue(timerI);
435 }
436 }
437 );
438 }
439 }
440
441 /**
442 * The demo application itself.
443 */
444 class DemoApplication extends TApplication {
445
446 /**
447 * Public constructor.
448 *
449 * @throws Exception if TApplication can't instantiate the Backend.
450 */
451 public DemoApplication() throws Exception {
452 super(null, null);
453 new DemoMainWindow(this);
454
455 // Add the menus
456 addFileMenu();
457 addEditMenu();
458
459 TMenu demoMenu = addMenu("&Demo");
460 TMenuItem item = demoMenu.addItem(2000, "&Checkable");
461 item.setCheckable(true);
462 item = demoMenu.addItem(2001, "Disabled");
463 item.setEnabled(false);
464 item = demoMenu.addItem(2002, "&Normal");
465 TSubMenu subMenu = demoMenu.addSubMenu("Sub-&Menu");
466 item = demoMenu.addItem(2010, "N&ormal A&&D");
467
468 item = subMenu.addItem(2000, "&Checkable (sub)");
469 item.setCheckable(true);
470 item = subMenu.addItem(2001, "Disabled (sub)");
471 item.setEnabled(false);
472 item = subMenu.addItem(2002, "&Normal (sub)");
473
474 subMenu = subMenu.addSubMenu("Sub-&Menu");
475 item = subMenu.addItem(2000, "&Checkable (sub)");
476 item.setCheckable(true);
477 item = subMenu.addItem(2001, "Disabled (sub)");
478 item.setEnabled(false);
479 item = subMenu.addItem(2002, "&Normal (sub)");
480
481 addWindowMenu();
482
483 }
484 }
485
486 /**
487 * This class provides a simple demonstration of Jexer's capabilities.
488 */
489 public class Demo1 {
490 /**
491 * Main entry point.
492 *
493 * @param args Command line arguments
494 */
495 public static void main(final String [] args) {
496 try {
497 DemoApplication app = new DemoApplication();
498 app.run();
499 } catch (Exception e) {
500 e.printStackTrace();
501 }
502 }
503
504 }