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