Pull demo into jar
[fanfix.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 private void openYNCMessageBox() {
158 application.messageBox("Yes/No/Cancel MessageBox",
159 q"EOS
160 This is an example of a Yes/No/Cancel MessageBox.
161
162 Note that the MessageBox text can span multiple
163 lines.
164
165 The default result (if someone hits the top-left
166 close button) is CANCEL.
167 EOS",
168 TMessageBox.Type.YESNOCANCEL);
169 }
170
171 private void openYNMessageBox() {
172 application.messageBox("Yes/No MessageBox",
173 q"EOS
174 This is an example of a Yes/No MessageBox.
175
176 Note that the MessageBox text can span multiple
177 lines.
178
179 The default result (if someone hits the top-left
180 close button) is NO.
181 EOS",
182 TMessageBox.Type.YESNO);
183 }
184
185 private void openOKCMessageBox() {
186 application.messageBox("OK/Cancel MessageBox",
187 q"EOS
188 This is an example of a OK/Cancel MessageBox.
189
190 Note that the MessageBox text can span multiple
191 lines.
192
193 The default result (if someone hits the top-left
194 close button) is CANCEL.
195 EOS",
196 TMessageBox.Type.OKCANCEL);
197 }
198
199 private void openOKMessageBox() {
200 application.messageBox("OK MessageBox",
201 q"EOS
202 This is an example of a OK MessageBox. This is the
203 default MessageBox.
204
205 Note that the MessageBox text can span multiple
206 lines.
207
208 The default result (if someone hits the top-left
209 close button) is OK.
210 EOS",
211 TMessageBox.Type.OK);
212 }
213
214 */
215
216 /**
217 * Constructor.
218 *
219 * @param parent the main application
220 */
221 DemoMsgBoxWindow(final TApplication parent) {
222 this(parent, TWindow.CENTERED | TWindow.RESIZABLE);
223 }
224
225 /**
226 * Constructor.
227 *
228 * @param parent the main application
229 * @param flags bitmask of MODAL, CENTERED, or RESIZABLE
230 */
231 DemoMsgBoxWindow(final TApplication parent, final int flags) {
232 // Construct a demo window. X and Y don't matter because it
233 // will be centered on screen.
234 super(parent, "Message Boxes", 0, 0, 60, 15, flags);
235 /*
236 uint row = 1;
237
238 // Add some widgets
239 addLabel("Default OK message box", 1, row);
240 addButton("Open O&K MB", 35, row, &openOKMessageBox);
241 row += 2;
242
243 addLabel("OK/Cancel message box", 1, row);
244 addButton("O&pen OKC MB", 35, row, &openOKCMessageBox);
245 row += 2;
246
247 addLabel("Yes/No message box", 1, row);
248 addButton("Open &YN MB", 35, row, &openYNMessageBox);
249 row += 2;
250
251 addLabel("Yes/No/Cancel message box", 1, row);
252 addButton("Ope&n YNC MB", 35, row, &openYNCMessageBox);
253 row += 2;
254
255 addLabel("Input box", 1, row);
256 addButton("Open &input box", 35, row,
257 {
258 application.inputBox("Input Box",
259 q"EOS
260 This is an example of an InputBox.
261
262 Note that the InputBox text can span multiple
263 lines.
264 EOS",
265 "some input text");
266 }
267 );
268
269 addButton("&Close Window", (width - 14) / 2, height - 4,
270 {
271 application.closeWindow(this);
272 }
273 );
274 */
275 }
276 }
277
278 /**
279 * This is the main "demo" application window. It makes use of the TTimer,
280 * TProgressBox, TLabel, TButton, and TField widgets.
281 */
282 class DemoMainWindow extends TWindow {
283
284 // Timer that increments a number.
285 private TTimer timer;
286
287 // Timer label is updated with timer ticks.
288 TLabel timerLabel;
289
290 /*
291 // The modal window is a more low-level example of controlling a window
292 // "from the outside". Most windows will probably subclass TWindow and
293 // do this kind of logic on their own.
294 private TWindow modalWindow;
295 private void openModalWindow() {
296 modalWindow = application.addWindow("Demo Modal Window", 0, 0,
297 58, 15, TWindow.Flag.MODAL);
298 modalWindow.addLabel("This is an example of a very braindead modal window.", 1, 1);
299 modalWindow.addLabel("Modal windows are centered by default.", 1, 2);
300 modalWindow.addButton("&Close", (modalWindow.width - 8)/2,
301 modalWindow.height - 4, &modalWindowClose);
302 }
303 private void modalWindowClose() {
304 application.closeWindow(modalWindow);
305 }
306 */
307
308 /**
309 * We need to override onClose so that the timer will no longer be called
310 * after we close the window. TTimers currently are completely unaware
311 * of the rest of the UI classes.
312 */
313 @Override
314 public void onClose() {
315 getApplication().removeTimer(timer);
316 }
317
318 /**
319 * Construct demo window. It will be centered on screen.
320 *
321 * @param parent the main application
322 */
323 public DemoMainWindow(final TApplication parent) {
324 this(parent, CENTERED | RESIZABLE);
325 }
326
327 // These are used by the timer loop. They have to be at class scope so
328 // that they can be accessed by the anonymous TAction class.
329 int timerI = 0;
330 TProgressBar progressBar;
331
332 /**
333 * Constructor.
334 *
335 * @param parent the main application
336 * @param flags bitmask of MODAL, CENTERED, or RESIZABLE
337 */
338 private DemoMainWindow(final TApplication parent, final int flags) {
339 // Construct a demo window. X and Y don't matter because it will be
340 // centered on screen.
341 super(parent, "Demo Window", 0, 0, 60, 23, flags);
342
343 int row = 1;
344
345 // Add some widgets
346 if (!isModal()) {
347 addLabel("Message Boxes", 1, row);
348 addButton("&MessageBoxes", 35, row,
349 new TAction() {
350 public void DO() {
351 new DemoMsgBoxWindow(getApplication());
352 }
353 }
354 );
355 }
356 row += 2;
357
358 addLabel("Open me as modal", 1, row);
359 addButton("W&indow", 35, row,
360 new TAction() {
361 public void DO() {
362 new DemoMainWindow(getApplication(), MODAL);
363 }
364 }
365 );
366
367 row += 2;
368
369 addLabel("Variable-width text field:", 1, row);
370 addField(35, row++, 15, false, "Field text");
371
372 addLabel("Fixed-width text field:", 1, row);
373 addField(35, row, 15, true);
374 row += 2;
375
376 if (!isModal()) {
377 addLabel("Radio buttons and checkboxes", 1, row);
378 addButton("&Checkboxes", 35, row,
379 new TAction() {
380 public void DO() {
381 new DemoCheckboxWindow(getApplication());
382 }
383 }
384 );
385 }
386 row += 2;
387
388 /*
389 if (!isModal()) {
390 addLabel("Editor window", 1, row);
391 addButton("Edito&r", 35, row,
392 {
393 new TEditor(application, 0, 0, 60, 15);
394 }
395 );
396 }
397 row += 2;
398 */
399
400 if (!isModal()) {
401 addLabel("Text areas", 1, row);
402 addButton("&Text", 35, row,
403 new TAction() {
404 public void DO() {
405 new DemoTextWindow(getApplication());
406 }
407 }
408 );
409 }
410 row += 2;
411
412 /*
413 if (!isModal()) {
414 addLabel("Tree views", 1, row);
415 addButton("Tree&View", 35, row,
416 {
417 new DemoTreeViewWindow(application);
418 }
419 );
420 }
421 row += 2;
422
423 if (!isModal()) {
424 addLabel("Terminal", 1, row);
425 addButton("Termi&nal", 35, row,
426 {
427 application.openTerminal(0, 0);
428 }
429 );
430 }
431 row += 2;
432 */
433
434 progressBar = addProgressBar(1, row, 22, 0);
435 row++;
436 timerLabel = addLabel("Timer", 1, row);
437 timer = getApplication().addTimer(100, true,
438 new TAction() {
439
440 public void DO() {
441 timerLabel.setText(String.format("Timer: %d", timerI));
442 timerLabel.setWidth(timerLabel.getText().length());
443 if (timerI < 100) {
444 timerI++;
445 }
446 progressBar.setValue(timerI);
447 DemoMainWindow.this.setRepaint();
448 }
449 }
450 );
451 }
452 }
453
454 /**
455 * The demo application itself.
456 */
457 class DemoApplication extends TApplication {
458
459 /**
460 * Public constructor.
461 *
462 * @throws Exception if TApplication can't instantiate the Backend.
463 */
464 public DemoApplication() throws Exception {
465 super(null, null);
466 new DemoMainWindow(this);
467
468 // Add the menus
469 addFileMenu();
470 addEditMenu();
471
472 TMenu demoMenu = addMenu("&Demo");
473 TMenuItem item = demoMenu.addItem(2000, "&Checkable");
474 item.setCheckable(true);
475 item = demoMenu.addItem(2001, "Disabled");
476 item.setEnabled(false);
477 item = demoMenu.addItem(2002, "&Normal");
478 TSubMenu subMenu = demoMenu.addSubMenu("Sub-&Menu");
479 item = demoMenu.addItem(2010, "N&ormal A&&D");
480
481 item = subMenu.addItem(2000, "&Checkable (sub)");
482 item.setCheckable(true);
483 item = subMenu.addItem(2001, "Disabled (sub)");
484 item.setEnabled(false);
485 item = subMenu.addItem(2002, "&Normal (sub)");
486
487 subMenu = subMenu.addSubMenu("Sub-&Menu");
488 item = subMenu.addItem(2000, "&Checkable (sub)");
489 item.setCheckable(true);
490 item = subMenu.addItem(2001, "Disabled (sub)");
491 item.setEnabled(false);
492 item = subMenu.addItem(2002, "&Normal (sub)");
493
494 addWindowMenu();
495
496 }
497 }
498
499 /**
500 * This class provides a simple demonstration of Jexer's capabilities.
501 */
502 public class Demo1 {
503 /**
504 * Main entry point.
505 *
506 * @param args Command line arguments
507 */
508 public static void main(final String [] args) {
509 try {
510 DemoApplication app = new DemoApplication();
511 app.run();
512 } catch (Exception e) {
513 e.printStackTrace();
514 }
515 }
516
517 }