cleanup
[fanfix.git] / src / jexer / TWidget.java
CommitLineData
daa4106c 1/*
48e27807
KL
2 * Jexer - Java Text User Interface
3 *
e16dda65 4 * The MIT License (MIT)
48e27807 5 *
a69ed767 6 * Copyright (C) 2019 Kevin Lamonte
48e27807 7 *
e16dda65
KL
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:
48e27807 14 *
e16dda65
KL
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
48e27807 17 *
e16dda65
KL
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.
48e27807
KL
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29package jexer;
30
0d47c546 31import java.io.IOException;
48e27807 32import java.util.List;
2ce6dab2 33import java.util.ArrayList;
48e27807 34
42873e30 35import jexer.backend.Screen;
a69ed767
KL
36import jexer.bits.Cell;
37import jexer.bits.CellAttributes;
928811d8 38import jexer.bits.ColorTheme;
48e27807
KL
39import jexer.event.TCommandEvent;
40import jexer.event.TInputEvent;
41import jexer.event.TKeypressEvent;
42import jexer.event.TMenuEvent;
43import jexer.event.TMouseEvent;
44import jexer.event.TResizeEvent;
928811d8 45import jexer.menu.TMenu;
d36057df
KL
46import jexer.ttree.TTreeItem;
47import jexer.ttree.TTreeView;
48import jexer.ttree.TTreeViewWidget;
48e27807
KL
49import static jexer.TKeypress.*;
50
51/**
52 * TWidget is the base class of all objects that can be drawn on screen or
53 * handle user input events.
54 */
2b9c27db 55public abstract class TWidget implements Comparable<TWidget> {
48e27807 56
2ce6dab2 57 // ------------------------------------------------------------------------
d36057df 58 // Variables --------------------------------------------------------------
2ce6dab2
KL
59 // ------------------------------------------------------------------------
60
48e27807
KL
61 /**
62 * Every widget has a parent widget that it may be "contained" in. For
051e2913
KL
63 * example, a TWindow might contain several TFields, or a TComboBox may
64 * contain a TList that itself contains a TVScroller.
48e27807 65 */
fca67db0
KL
66 private TWidget parent = null;
67
48e27807
KL
68 /**
69 * Child widgets that this widget contains.
70 */
71 private List<TWidget> children;
72
73 /**
74 * The currently active child widget that will receive keypress events.
75 */
76 private TWidget activeChild = null;
77
78 /**
79 * If true, this widget will receive events.
80 */
fca67db0
KL
81 private boolean active = false;
82
48e27807
KL
83 /**
84 * The window that this widget draws to.
85 */
fca67db0 86 private TWindow window = null;
48e27807
KL
87
88 /**
89 * Absolute X position of the top-left corner.
90 */
fca67db0
KL
91 private int x = 0;
92
93 /**
d36057df 94 * Absolute Y position of the top-left corner.
fca67db0 95 */
d36057df 96 private int y = 0;
fca67db0
KL
97
98 /**
d36057df 99 * Width.
fca67db0 100 */
d36057df 101 private int width = 0;
48e27807
KL
102
103 /**
d36057df 104 * Height.
48e27807 105 */
d36057df 106 private int height = 0;
fca67db0
KL
107
108 /**
d36057df 109 * My tab order inside a window or containing widget.
fca67db0 110 */
d36057df 111 private int tabOrder = 0;
fca67db0
KL
112
113 /**
d36057df 114 * If true, this widget can be tabbed to or receive events.
fca67db0 115 */
d36057df 116 private boolean enabled = true;
48e27807 117
051e2913
KL
118 /**
119 * If true, this widget will be rendered.
120 */
121 private boolean visible = true;
122
48e27807 123 /**
d36057df 124 * If true, this widget has a cursor.
48e27807 125 */
d36057df 126 private boolean cursorVisible = false;
fca67db0
KL
127
128 /**
d36057df 129 * Cursor column position in relative coordinates.
fca67db0 130 */
d36057df 131 private int cursorX = 0;
fca67db0
KL
132
133 /**
d36057df 134 * Cursor row position in relative coordinates.
fca67db0 135 */
d36057df 136 private int cursorY = 0;
48e27807 137
d36057df
KL
138 // ------------------------------------------------------------------------
139 // Constructors -----------------------------------------------------------
140 // ------------------------------------------------------------------------
fca67db0
KL
141
142 /**
d36057df 143 * Default constructor for subclasses.
fca67db0 144 */
d36057df
KL
145 protected TWidget() {
146 children = new ArrayList<TWidget>();
fca67db0
KL
147 }
148
149 /**
d36057df 150 * Protected constructor.
fca67db0 151 *
d36057df 152 * @param parent parent widget
fca67db0 153 */
d36057df
KL
154 protected TWidget(final TWidget parent) {
155 this(parent, true);
fca67db0 156 }
48e27807 157
0ee88b6d 158 /**
d36057df 159 * Protected constructor.
0ee88b6d 160 *
d36057df
KL
161 * @param parent parent widget
162 * @param x column relative to parent
163 * @param y row relative to parent
164 * @param width width of widget
165 * @param height height of widget
0ee88b6d 166 */
d36057df
KL
167 protected TWidget(final TWidget parent, final int x, final int y,
168 final int width, final int height) {
0ee88b6d 169
d36057df 170 this(parent, true, x, y, width, height);
0ee88b6d
KL
171 }
172
48e27807 173 /**
d36057df 174 * Protected constructor used by subclasses that are disabled by default.
48e27807 175 *
d36057df
KL
176 * @param parent parent widget
177 * @param enabled if true assume enabled
48e27807 178 */
d36057df
KL
179 protected TWidget(final TWidget parent, final boolean enabled) {
180 this.enabled = enabled;
181 this.parent = parent;
182 this.window = parent.window;
183 children = new ArrayList<TWidget>();
184
a69ed767 185 // Do not add TStatusBars, they are drawn by TApplication.
d36057df 186 if (this instanceof TStatusBar) {
a69ed767 187 // NOP
d36057df
KL
188 } else {
189 parent.addChild(this);
190 }
48e27807
KL
191 }
192
193 /**
d36057df 194 * Protected constructor used by subclasses that are disabled by default.
48e27807 195 *
d36057df
KL
196 * @param parent parent widget
197 * @param enabled if true assume enabled
198 * @param x column relative to parent
199 * @param y row relative to parent
200 * @param width width of widget
201 * @param height height of widget
48e27807 202 */
d36057df
KL
203 protected TWidget(final TWidget parent, final boolean enabled,
204 final int x, final int y, final int width, final int height) {
205
48e27807 206 this.enabled = enabled;
d36057df
KL
207 this.parent = parent;
208 this.window = parent.window;
209 children = new ArrayList<TWidget>();
210
a69ed767 211 // Do not add TStatusBars, they are drawn by TApplication.
d36057df 212 if (this instanceof TStatusBar) {
a69ed767 213 // NOP
d36057df
KL
214 } else {
215 parent.addChild(this);
48e27807 216 }
48e27807 217
d36057df
KL
218 this.x = x;
219 this.y = y;
220 this.width = width;
221 this.height = height;
222 }
48e27807 223
7272e49f 224 /**
d36057df 225 * Backdoor access for TWindow's constructor. ONLY TWindow USES THIS.
7272e49f 226 *
d36057df
KL
227 * @param window the top-level window
228 * @param x column relative to parent
229 * @param y row relative to parent
230 * @param width width of window
231 * @param height height of window
7272e49f 232 */
d36057df
KL
233 protected final void setupForTWindow(final TWindow window,
234 final int x, final int y, final int width, final int height) {
235
236 this.parent = window;
237 this.window = window;
238 this.x = x;
239 this.y = y;
240 this.width = width;
241 this.height = height;
7272e49f
KL
242 }
243
d36057df
KL
244 // ------------------------------------------------------------------------
245 // Event handlers ---------------------------------------------------------
246 // ------------------------------------------------------------------------
247
a69ed767
KL
248 /**
249 * Subclasses should override this method to cleanup resources. This is
250 * called by TWindow.onClose().
251 */
252 protected void close() {
253 // Default: call close() on children.
254 for (TWidget w: getChildren()) {
255 w.close();
256 }
257 }
258
a06459bd 259 /**
d36057df
KL
260 * Check if a mouse press/release event coordinate is contained in this
261 * widget.
a06459bd 262 *
d36057df
KL
263 * @param mouse a mouse-based event
264 * @return whether or not a mouse click would be sent to this widget
a06459bd 265 */
d36057df
KL
266 public final boolean mouseWouldHit(final TMouseEvent mouse) {
267
268 if (!enabled) {
24489803
KL
269 return false;
270 }
271
d36057df
KL
272 if ((this instanceof TTreeItem)
273 && ((y < 0) || (y > parent.getHeight() - 1))
24489803
KL
274 ) {
275 return false;
276 }
a06459bd 277
d36057df
KL
278 if ((mouse.getAbsoluteX() >= getAbsoluteX())
279 && (mouse.getAbsoluteX() < getAbsoluteX() + width)
280 && (mouse.getAbsoluteY() >= getAbsoluteY())
281 && (mouse.getAbsoluteY() < getAbsoluteY() + height)
282 ) {
283 return true;
284 }
285 return false;
286 }
48e27807 287
7272e49f 288 /**
d36057df 289 * Method that subclasses can override to handle keystrokes.
7272e49f 290 *
d36057df 291 * @param keypress keystroke event
7272e49f 292 */
d36057df
KL
293 public void onKeypress(final TKeypressEvent keypress) {
294
295 if ((children.size() == 0)
296 || (this instanceof TTreeView)
297 || (this instanceof TText)
a69ed767 298 || (this instanceof TComboBox)
d36057df
KL
299 ) {
300
301 // Defaults:
302 // tab / shift-tab - switch to next/previous widget
303 // left-arrow or up-arrow: same as shift-tab
304 if ((keypress.equals(kbTab))
a69ed767 305 || (keypress.equals(kbDown) && !(this instanceof TComboBox))
d36057df
KL
306 ) {
307 parent.switchWidget(true);
308 return;
309 } else if ((keypress.equals(kbShiftTab))
310 || (keypress.equals(kbBackTab))
a69ed767 311 || (keypress.equals(kbUp) && !(this instanceof TComboBox))
d36057df
KL
312 ) {
313 parent.switchWidget(false);
314 return;
315 }
316 }
317
318 if ((children.size() == 0)
319 && !(this instanceof TTreeView)
320 ) {
321
322 // Defaults:
323 // right-arrow or down-arrow: same as tab
324 if (keypress.equals(kbRight)) {
325 parent.switchWidget(true);
326 return;
327 } else if (keypress.equals(kbLeft)) {
328 parent.switchWidget(false);
329 return;
330 }
331 }
332
333 // If I have any buttons on me AND this is an Alt-key that matches
334 // its mnemonic, send it an Enter keystroke
335 for (TWidget widget: children) {
336 if (widget instanceof TButton) {
337 TButton button = (TButton) widget;
338 if (button.isEnabled()
339 && !keypress.getKey().isFnKey()
340 && keypress.getKey().isAlt()
341 && !keypress.getKey().isCtrl()
342 && (Character.toLowerCase(button.getMnemonic().getShortcut())
343 == Character.toLowerCase(keypress.getKey().getChar()))
344 ) {
345
346 widget.onKeypress(new TKeypressEvent(kbEnter));
347 return;
348 }
349 }
350 }
351
352 // Dispatch the keypress to an active widget
353 for (TWidget widget: children) {
354 if (widget.active) {
355 widget.onKeypress(keypress);
356 return;
357 }
358 }
7272e49f
KL
359 }
360
361 /**
d36057df 362 * Method that subclasses can override to handle mouse button presses.
7272e49f 363 *
d36057df 364 * @param mouse mouse button event
7272e49f 365 */
d36057df
KL
366 public void onMouseDown(final TMouseEvent mouse) {
367 // Default: do nothing, pass to children instead
a69ed767
KL
368 if (activeChild != null) {
369 if (activeChild.mouseWouldHit(mouse)) {
370 // Dispatch to the active child
371
372 // Set x and y relative to the child's coordinates
373 mouse.setX(mouse.getAbsoluteX() - activeChild.getAbsoluteX());
374 mouse.setY(mouse.getAbsoluteY() - activeChild.getAbsoluteY());
375 activeChild.onMouseDown(mouse);
376 return;
377 }
378 }
d36057df
KL
379 for (int i = children.size() - 1 ; i >= 0 ; i--) {
380 TWidget widget = children.get(i);
381 if (widget.mouseWouldHit(mouse)) {
382 // Dispatch to this child, also activate it
383 activate(widget);
7272e49f 384
d36057df
KL
385 // Set x and y relative to the child's coordinates
386 mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX());
387 mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY());
388 widget.onMouseDown(mouse);
389 return;
390 }
391 }
392 }
48e27807 393
7272e49f 394 /**
d36057df 395 * Method that subclasses can override to handle mouse button releases.
7272e49f 396 *
d36057df 397 * @param mouse mouse button event
7272e49f 398 */
d36057df
KL
399 public void onMouseUp(final TMouseEvent mouse) {
400 // Default: do nothing, pass to children instead
a69ed767
KL
401 if (activeChild != null) {
402 if (activeChild.mouseWouldHit(mouse)) {
403 // Dispatch to the active child
404
405 // Set x and y relative to the child's coordinates
406 mouse.setX(mouse.getAbsoluteX() - activeChild.getAbsoluteX());
407 mouse.setY(mouse.getAbsoluteY() - activeChild.getAbsoluteY());
408 activeChild.onMouseUp(mouse);
409 return;
410 }
411 }
d36057df
KL
412 for (int i = children.size() - 1 ; i >= 0 ; i--) {
413 TWidget widget = children.get(i);
414 if (widget.mouseWouldHit(mouse)) {
415 // Dispatch to this child, also activate it
416 activate(widget);
417
418 // Set x and y relative to the child's coordinates
419 mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX());
420 mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY());
421 widget.onMouseUp(mouse);
422 return;
423 }
424 }
7272e49f
KL
425 }
426
427 /**
d36057df 428 * Method that subclasses can override to handle mouse movements.
7272e49f 429 *
d36057df 430 * @param mouse mouse motion event
7272e49f 431 */
d36057df
KL
432 public void onMouseMotion(final TMouseEvent mouse) {
433 // Default: do nothing, pass it on to ALL of my children. This way
434 // the children can see the mouse "leaving" their area.
435 for (TWidget widget: children) {
436 // Set x and y relative to the child's coordinates
437 mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX());
438 mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY());
439 widget.onMouseMotion(mouse);
440 }
7272e49f
KL
441 }
442
2ce6dab2 443 /**
d36057df
KL
444 * Method that subclasses can override to handle mouse button
445 * double-clicks.
2ce6dab2 446 *
d36057df 447 * @param mouse mouse button event
2ce6dab2 448 */
d36057df
KL
449 public void onMouseDoubleClick(final TMouseEvent mouse) {
450 // Default: do nothing, pass to children instead
a69ed767
KL
451 if (activeChild != null) {
452 if (activeChild.mouseWouldHit(mouse)) {
453 // Dispatch to the active child
454
455 // Set x and y relative to the child's coordinates
456 mouse.setX(mouse.getAbsoluteX() - activeChild.getAbsoluteX());
457 mouse.setY(mouse.getAbsoluteY() - activeChild.getAbsoluteY());
458 activeChild.onMouseDoubleClick(mouse);
459 return;
460 }
461 }
d36057df
KL
462 for (int i = children.size() - 1 ; i >= 0 ; i--) {
463 TWidget widget = children.get(i);
464 if (widget.mouseWouldHit(mouse)) {
465 // Dispatch to this child, also activate it
466 activate(widget);
467
468 // Set x and y relative to the child's coordinates
469 mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX());
470 mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY());
471 widget.onMouseDoubleClick(mouse);
472 return;
473 }
474 }
2ce6dab2
KL
475 }
476
477 /**
d36057df
KL
478 * Method that subclasses can override to handle window/screen resize
479 * events.
2ce6dab2 480 *
d36057df 481 * @param resize resize event
2ce6dab2 482 */
d36057df
KL
483 public void onResize(final TResizeEvent resize) {
484 // Default: change my width/height.
485 if (resize.getType() == TResizeEvent.Type.WIDGET) {
486 width = resize.getWidth();
487 height = resize.getHeight();
488 } else {
489 // Let children see the screen resize
490 for (TWidget widget: children) {
491 widget.onResize(resize);
492 }
493 }
2ce6dab2
KL
494 }
495
48e27807 496 /**
d36057df 497 * Method that subclasses can override to handle posted command events.
7668cb45 498 *
d36057df 499 * @param command command event
2b9c27db 500 */
d36057df
KL
501 public void onCommand(final TCommandEvent command) {
502 // Default: do nothing, pass to children instead
503 for (TWidget widget: children) {
504 widget.onCommand(command);
7668cb45 505 }
48e27807
KL
506 }
507
508 /**
d36057df
KL
509 * Method that subclasses can override to handle menu or posted menu
510 * events.
48e27807 511 *
d36057df 512 * @param menu menu event
48e27807 513 */
d36057df
KL
514 public void onMenu(final TMenuEvent menu) {
515 // Default: do nothing, pass to children instead
516 for (TWidget widget: children) {
517 widget.onMenu(menu);
48e27807 518 }
48e27807
KL
519 }
520
521 /**
d36057df
KL
522 * Method that subclasses can override to do processing when the UI is
523 * idle. Note that repainting is NOT assumed. To get a refresh after
524 * onIdle, call doRepaint().
48e27807 525 */
d36057df
KL
526 public void onIdle() {
527 // Default: do nothing, pass to children instead
528 for (TWidget widget: children) {
529 widget.onIdle();
530 }
48e27807
KL
531 }
532
533 /**
d36057df
KL
534 * Consume event. Subclasses that want to intercept all events in one go
535 * can override this method.
48e27807 536 *
d36057df 537 * @param event keyboard, mouse, resize, command, or menu event
48e27807 538 */
d36057df
KL
539 public void handleEvent(final TInputEvent event) {
540 /*
541 System.err.printf("TWidget (%s) event: %s\n", this.getClass().getName(),
542 event);
543 */
544
545 if (!enabled) {
546 // Discard event
547 // System.err.println(" -- discard --");
548 return;
549 }
550
551 if (event instanceof TKeypressEvent) {
552 onKeypress((TKeypressEvent) event);
553 } else if (event instanceof TMouseEvent) {
554
555 TMouseEvent mouse = (TMouseEvent) event;
556
557 switch (mouse.getType()) {
558
559 case MOUSE_DOWN:
560 onMouseDown(mouse);
561 break;
562
563 case MOUSE_UP:
564 onMouseUp(mouse);
565 break;
566
567 case MOUSE_MOTION:
568 onMouseMotion(mouse);
569 break;
570
571 case MOUSE_DOUBLE_CLICK:
572 onMouseDoubleClick(mouse);
573 break;
574
575 default:
576 throw new IllegalArgumentException("Invalid mouse event type: "
577 + mouse.getType());
578 }
579 } else if (event instanceof TResizeEvent) {
580 onResize((TResizeEvent) event);
581 } else if (event instanceof TCommandEvent) {
582 onCommand((TCommandEvent) event);
583 } else if (event instanceof TMenuEvent) {
584 onMenu((TMenuEvent) event);
585 }
586
587 // Do nothing else
588 return;
48e27807
KL
589 }
590
d36057df
KL
591 // ------------------------------------------------------------------------
592 // TWidget ----------------------------------------------------------------
593 // ------------------------------------------------------------------------
594
48e27807 595 /**
d36057df 596 * Get parent widget.
48e27807 597 *
d36057df 598 * @return parent widget
48e27807 599 */
d36057df
KL
600 public final TWidget getParent() {
601 return parent;
48e27807
KL
602 }
603
604 /**
d36057df 605 * Get the list of child widgets that this widget contains.
48e27807 606 *
d36057df 607 * @return the list of child widgets
48e27807 608 */
d36057df
KL
609 public List<TWidget> getChildren() {
610 return children;
48e27807
KL
611 }
612
928811d8 613 /**
d36057df 614 * Get active flag.
928811d8 615 *
d36057df 616 * @return if true, this widget will receive events
928811d8 617 */
d36057df
KL
618 public final boolean isActive() {
619 return active;
928811d8
KL
620 }
621
48e27807 622 /**
d36057df
KL
623 * Set active flag.
624 *
625 * @param active if true, this widget will receive events
48e27807 626 */
d36057df
KL
627 public final void setActive(final boolean active) {
628 this.active = active;
48e27807
KL
629 }
630
631 /**
d36057df
KL
632 * Get the window this widget is on.
633 *
634 * @return the window
48e27807 635 */
d36057df
KL
636 public final TWindow getWindow() {
637 return window;
48e27807
KL
638 }
639
be72cb5c 640 /**
d36057df
KL
641 * Get X position.
642 *
643 * @return absolute X position of the top-left corner
be72cb5c 644 */
d36057df
KL
645 public final int getX() {
646 return x;
be72cb5c
KL
647 }
648
48e27807 649 /**
d36057df
KL
650 * Set X position.
651 *
652 * @param x absolute X position of the top-left corner
48e27807 653 */
d36057df
KL
654 public final void setX(final int x) {
655 this.x = x;
48e27807
KL
656 }
657
658 /**
d36057df 659 * Get Y position.
48e27807 660 *
d36057df 661 * @return absolute Y position of the top-left corner
48e27807 662 */
d36057df
KL
663 public final int getY() {
664 return y;
30d336cc
KL
665 }
666
a83fea2b 667 /**
d36057df 668 * Set Y position.
a83fea2b 669 *
d36057df 670 * @param y absolute Y position of the top-left corner
a83fea2b 671 */
d36057df
KL
672 public final void setY(final int y) {
673 this.y = y;
a83fea2b
KL
674 }
675
30d336cc 676 /**
d36057df 677 * Get the width.
30d336cc 678 *
d36057df 679 * @return widget width
30d336cc 680 */
d36057df
KL
681 public final int getWidth() {
682 return this.width;
48e27807
KL
683 }
684
a83fea2b 685 /**
d36057df 686 * Change the width.
a83fea2b 687 *
d36057df 688 * @param width new widget width
a83fea2b 689 */
d36057df 690 public final void setWidth(final int width) {
a83fea2b 691 this.width = width;
a83fea2b
KL
692 }
693
2ce6dab2 694 /**
d36057df 695 * Get the height.
2ce6dab2 696 *
d36057df 697 * @return widget height
2ce6dab2 698 */
d36057df
KL
699 public final int getHeight() {
700 return this.height;
701 }
2ce6dab2 702
d36057df
KL
703 /**
704 * Change the height.
705 *
706 * @param height new widget height
707 */
708 public final void setHeight(final int height) {
2ce6dab2
KL
709 this.height = height;
710 }
711
48e27807 712 /**
d36057df 713 * Change the dimensions.
48e27807 714 *
d36057df
KL
715 * @param x absolute X position of the top-left corner
716 * @param y absolute Y position of the top-left corner
717 * @param width new widget width
718 * @param height new widget height
48e27807 719 */
d36057df
KL
720 public final void setDimensions(final int x, final int y, final int width,
721 final int height) {
48e27807 722
d36057df
KL
723 setX(x);
724 setY(y);
725 setWidth(width);
726 setHeight(height);
48e27807
KL
727 }
728
729 /**
d36057df 730 * Get enabled flag.
48e27807 731 *
d36057df 732 * @return if true, this widget can be tabbed to or receive events
48e27807 733 */
d36057df
KL
734 public final boolean isEnabled() {
735 return enabled;
736 }
48e27807 737
d36057df
KL
738 /**
739 * Set enabled flag.
740 *
741 * @param enabled if true, this widget can be tabbed to or receive events
742 */
743 public final void setEnabled(final boolean enabled) {
744 this.enabled = enabled;
745 if (!enabled) {
746 active = false;
747 // See if there are any active siblings to switch to
748 boolean foundSibling = false;
749 if (parent != null) {
750 for (TWidget w: parent.children) {
751 if ((w.enabled)
752 && !(this instanceof THScroller)
753 && !(this instanceof TVScroller)
754 ) {
755 parent.activate(w);
756 foundSibling = true;
757 break;
758 }
759 }
760 if (!foundSibling) {
761 parent.activeChild = null;
762 }
48e27807 763 }
48e27807
KL
764 }
765 }
766
051e2913
KL
767 /**
768 * Set visible flag.
769 *
770 * @param visible if true, this widget will be drawn
771 */
772 public final void setVisible(final boolean visible) {
773 this.visible = visible;
774 }
775
776 /**
777 * See if this widget is visible.
778 *
779 * @return if true, this widget will be drawn
780 */
781 public final boolean isVisible() {
782 return visible;
783 }
784
48e27807 785 /**
d36057df 786 * Set visible cursor flag.
48e27807 787 *
d36057df 788 * @param cursorVisible if true, this widget has a cursor
48e27807 789 */
d36057df
KL
790 public final void setCursorVisible(final boolean cursorVisible) {
791 this.cursorVisible = cursorVisible;
48e27807
KL
792 }
793
794 /**
d36057df 795 * See if this widget has a visible cursor.
48e27807 796 *
d36057df 797 * @return if true, this widget has a visible cursor
48e27807 798 */
d36057df
KL
799 public final boolean isCursorVisible() {
800 // If cursor is out of my bounds, it is not visible.
801 if ((cursorX >= width)
802 || (cursorX < 0)
803 || (cursorY >= height)
804 || (cursorY < 0)
805 ) {
806 return false;
807 }
48e27807 808
d36057df
KL
809 // If cursor is out of my window's bounds, it is not visible.
810 if ((getCursorAbsoluteX() >= window.getAbsoluteX()
811 + window.getWidth() - 1)
812 || (getCursorAbsoluteX() < 0)
813 || (getCursorAbsoluteY() >= window.getAbsoluteY()
814 + window.getHeight() - 1)
815 || (getCursorAbsoluteY() < 0)
816 ) {
817 return false;
48e27807 818 }
d36057df
KL
819 return cursorVisible;
820 }
48e27807 821
d36057df
KL
822 /**
823 * Get cursor X value.
824 *
825 * @return cursor column position in relative coordinates
826 */
827 public final int getCursorX() {
828 return cursorX;
829 }
48e27807 830
d36057df
KL
831 /**
832 * Set cursor X value.
833 *
834 * @param cursorX column position in relative coordinates
835 */
836 public final void setCursorX(final int cursorX) {
837 this.cursorX = cursorX;
838 }
48e27807 839
d36057df
KL
840 /**
841 * Get cursor Y value.
842 *
843 * @return cursor row position in relative coordinates
844 */
845 public final int getCursorY() {
846 return cursorY;
847 }
48e27807 848
d36057df
KL
849 /**
850 * Set cursor Y value.
851 *
852 * @param cursorY row position in relative coordinates
853 */
854 public final void setCursorY(final int cursorY) {
855 this.cursorY = cursorY;
856 }
48e27807 857
d36057df
KL
858 /**
859 * Get this TWidget's parent TApplication.
860 *
861 * @return the parent TApplication
862 */
863 public TApplication getApplication() {
864 return window.getApplication();
865 }
48e27807 866
d36057df
KL
867 /**
868 * Get the Screen.
869 *
870 * @return the Screen
871 */
872 public Screen getScreen() {
873 return window.getScreen();
48e27807
KL
874 }
875
876 /**
d36057df
KL
877 * Comparison operator. For various subclasses it sorts on:
878 * <ul>
879 * <li>tabOrder for TWidgets</li>
880 * <li>z for TWindows</li>
881 * <li>text for TTreeItems</li>
882 * </ul>
48e27807 883 *
d36057df
KL
884 * @param that another TWidget, TWindow, or TTreeItem instance
885 * @return difference between this.tabOrder and that.tabOrder, or
886 * difference between this.z and that.z, or String.compareTo(text)
48e27807 887 */
d36057df
KL
888 public final int compareTo(final TWidget that) {
889 if ((this instanceof TWindow)
890 && (that instanceof TWindow)
48e27807 891 ) {
d36057df
KL
892 return (((TWindow) this).getZ() - ((TWindow) that).getZ());
893 }
894 if ((this instanceof TTreeItem)
895 && (that instanceof TTreeItem)
896 ) {
897 return (((TTreeItem) this).getText().compareTo(
898 ((TTreeItem) that).getText()));
48e27807 899 }
d36057df
KL
900 return (this.tabOrder - that.tabOrder);
901 }
48e27807 902
d36057df
KL
903 /**
904 * See if this widget should render with the active color.
905 *
906 * @return true if this widget is active and all of its parents are
907 * active.
908 */
909 public final boolean isAbsoluteActive() {
910 if (parent == this) {
911 return active;
48e27807 912 }
d36057df 913 return (active && parent.isAbsoluteActive());
48e27807
KL
914 }
915
d36057df
KL
916 /**
917 * Returns the cursor X position.
918 *
919 * @return absolute screen column number for the cursor's X position
920 */
921 public final int getCursorAbsoluteX() {
922 return getAbsoluteX() + cursorX;
923 }
2ce6dab2
KL
924
925 /**
d36057df 926 * Returns the cursor Y position.
2ce6dab2 927 *
d36057df 928 * @return absolute screen row number for the cursor's Y position
2ce6dab2 929 */
d36057df
KL
930 public final int getCursorAbsoluteY() {
931 return getAbsoluteY() + cursorY;
932 }
2ce6dab2 933
d36057df
KL
934 /**
935 * Compute my absolute X position as the sum of my X plus all my parent's
936 * X's.
937 *
938 * @return absolute screen column number for my X position
939 */
940 public final int getAbsoluteX() {
941 assert (parent != null);
942 if (parent == this) {
943 return x;
2ce6dab2 944 }
d36057df
KL
945 if ((parent instanceof TWindow)
946 && !(parent instanceof TMenu)
947 && !(parent instanceof TDesktop)
948 ) {
949 // Widgets on a TWindow have (0,0) as their top-left, but this is
950 // actually the TWindow's (1,1).
951 return parent.getAbsoluteX() + x + 1;
952 }
953 return parent.getAbsoluteX() + x;
954 }
2ce6dab2 955
d36057df
KL
956 /**
957 * Compute my absolute Y position as the sum of my Y plus all my parent's
958 * Y's.
959 *
960 * @return absolute screen row number for my Y position
961 */
962 public final int getAbsoluteY() {
963 assert (parent != null);
964 if (parent == this) {
965 return y;
966 }
967 if ((parent instanceof TWindow)
968 && !(parent instanceof TMenu)
969 && !(parent instanceof TDesktop)
2ce6dab2 970 ) {
d36057df
KL
971 // Widgets on a TWindow have (0,0) as their top-left, but this is
972 // actually the TWindow's (1,1).
973 return parent.getAbsoluteY() + y + 1;
2ce6dab2 974 }
d36057df 975 return parent.getAbsoluteY() + y;
2ce6dab2
KL
976 }
977
48e27807 978 /**
d36057df 979 * Get the global color theme.
48e27807 980 *
d36057df 981 * @return the ColorTheme
48e27807 982 */
a69ed767 983 protected final ColorTheme getTheme() {
d36057df
KL
984 return window.getApplication().getTheme();
985 }
48e27807 986
d36057df
KL
987 /**
988 * Draw my specific widget. When called, the screen rectangle I draw
989 * into is already setup (offset and clipping).
990 */
991 public void draw() {
992 // Default widget draws nothing.
993 }
48e27807 994
d36057df 995 /**
a69ed767 996 * Called by parent to render to TWindow. Note package private access.
d36057df 997 */
a69ed767 998 final void drawChildren() {
d36057df
KL
999 // Set my clipping rectangle
1000 assert (window != null);
1001 assert (getScreen() != null);
1002 Screen screen = getScreen();
1003
1004 // Special case: TStatusBar is drawn by TApplication, not anything
1005 // else.
1006 if (this instanceof TStatusBar) {
1007 return;
48e27807
KL
1008 }
1009
d36057df
KL
1010 screen.setClipRight(width);
1011 screen.setClipBottom(height);
92554d64 1012
d36057df
KL
1013 int absoluteRightEdge = window.getAbsoluteX() + window.getWidth();
1014 int absoluteBottomEdge = window.getAbsoluteY() + window.getHeight();
1015 if (!(this instanceof TWindow) && !(this instanceof TVScroller)) {
1016 absoluteRightEdge -= 1;
1017 }
1018 if (!(this instanceof TWindow) && !(this instanceof THScroller)) {
1019 absoluteBottomEdge -= 1;
48e27807 1020 }
d36057df
KL
1021 int myRightEdge = getAbsoluteX() + width;
1022 int myBottomEdge = getAbsoluteY() + height;
1023 if (getAbsoluteX() > absoluteRightEdge) {
1024 // I am offscreen
1025 screen.setClipRight(0);
1026 } else if (myRightEdge > absoluteRightEdge) {
1027 screen.setClipRight(screen.getClipRight()
1028 - (myRightEdge - absoluteRightEdge));
1029 }
1030 if (getAbsoluteY() > absoluteBottomEdge) {
1031 // I am offscreen
1032 screen.setClipBottom(0);
1033 } else if (myBottomEdge > absoluteBottomEdge) {
1034 screen.setClipBottom(screen.getClipBottom()
1035 - (myBottomEdge - absoluteBottomEdge));
1036 }
1037
1038 // Set my offset
1039 screen.setOffsetX(getAbsoluteX());
1040 screen.setOffsetY(getAbsoluteY());
48e27807 1041
d36057df
KL
1042 // Draw me
1043 draw();
1044
a69ed767
KL
1045 // Continue down the chain. Draw the active child last so that it
1046 // is on top.
48e27807 1047 for (TWidget widget: children) {
a69ed767 1048 if (widget.isVisible() && (widget != activeChild)) {
051e2913
KL
1049 widget.drawChildren();
1050 }
48e27807 1051 }
a69ed767
KL
1052 if (activeChild != null) {
1053 activeChild.drawChildren();
1054 }
48e27807
KL
1055 }
1056
1057 /**
d36057df 1058 * Repaint the screen on the next update.
48e27807 1059 */
a69ed767 1060 protected final void doRepaint() {
d36057df 1061 window.getApplication().doRepaint();
48e27807
KL
1062 }
1063
1064 /**
d36057df
KL
1065 * Add a child widget to my list of children. We set its tabOrder to 0
1066 * and increment the tabOrder of all other children.
48e27807 1067 *
d36057df 1068 * @param child TWidget to add
48e27807 1069 */
d36057df
KL
1070 private void addChild(final TWidget child) {
1071 children.add(child);
48e27807 1072
d36057df
KL
1073 if ((child.enabled)
1074 && !(child instanceof THScroller)
1075 && !(child instanceof TVScroller)
1076 ) {
1077 for (TWidget widget: children) {
1078 widget.active = false;
48e27807 1079 }
d36057df
KL
1080 child.active = true;
1081 activeChild = child;
48e27807 1082 }
d36057df
KL
1083 for (int i = 0; i < children.size(); i++) {
1084 children.get(i).tabOrder = i;
48e27807
KL
1085 }
1086 }
1087
b6faeac0 1088 /**
d36057df 1089 * Switch the active child.
b6faeac0 1090 *
d36057df 1091 * @param child TWidget to activate
b6faeac0 1092 */
d36057df
KL
1093 public final void activate(final TWidget child) {
1094 assert (child.enabled);
1095 if ((child instanceof THScroller)
1096 || (child instanceof TVScroller)
1097 ) {
1098 return;
b6faeac0 1099 }
b6faeac0 1100
d36057df
KL
1101 if (child != activeChild) {
1102 if (activeChild != null) {
1103 activeChild.active = false;
12b55d76 1104 }
d36057df
KL
1105 child.active = true;
1106 activeChild = child;
48e27807
KL
1107 }
1108 }
1109
1110 /**
d36057df 1111 * Switch the active child.
48e27807 1112 *
d36057df
KL
1113 * @param tabOrder tabOrder of the child to activate. If that child
1114 * isn't enabled, then the next enabled child will be activated.
48e27807 1115 */
d36057df
KL
1116 public final void activate(final int tabOrder) {
1117 if (activeChild == null) {
1118 return;
48e27807 1119 }
d36057df 1120 TWidget child = null;
48e27807 1121 for (TWidget widget: children) {
d36057df
KL
1122 if ((widget.enabled)
1123 && !(widget instanceof THScroller)
1124 && !(widget instanceof TVScroller)
1125 && (widget.tabOrder >= tabOrder)
1126 ) {
1127 child = widget;
1128 break;
1129 }
48e27807 1130 }
d36057df
KL
1131 if ((child != null) && (child != activeChild)) {
1132 activeChild.active = false;
1133 assert (child.enabled);
1134 child.active = true;
1135 activeChild = child;
48e27807
KL
1136 }
1137 }
1138
1139 /**
d36057df 1140 * Switch the active widget with the next in the tab order.
48e27807 1141 *
d36057df
KL
1142 * @param forward if true, then switch to the next enabled widget in the
1143 * list, otherwise switch to the previous enabled widget in the list
48e27807 1144 */
d36057df 1145 public final void switchWidget(final boolean forward) {
48e27807 1146
d36057df
KL
1147 // Only switch if there are multiple enabled widgets
1148 if ((children.size() < 2) || (activeChild == null)) {
48e27807
KL
1149 return;
1150 }
1151
d36057df
KL
1152 int tabOrder = activeChild.tabOrder;
1153 do {
1154 if (forward) {
1155 tabOrder++;
1156 } else {
1157 tabOrder--;
1158 }
1159 if (tabOrder < 0) {
48e27807 1160
d36057df
KL
1161 // If at the end, pass the switch to my parent.
1162 if ((!forward) && (parent != this)) {
1163 parent.switchWidget(forward);
1164 return;
1165 }
48e27807 1166
d36057df
KL
1167 tabOrder = children.size() - 1;
1168 } else if (tabOrder == children.size()) {
1169 // If at the end, pass the switch to my parent.
1170 if ((forward) && (parent != this)) {
1171 parent.switchWidget(forward);
1172 return;
1173 }
48e27807 1174
d36057df
KL
1175 tabOrder = 0;
1176 }
1177 if (activeChild.tabOrder == tabOrder) {
1178 // We wrapped around
48e27807 1179 break;
d36057df
KL
1180 }
1181 } while ((!children.get(tabOrder).enabled)
1182 && !(children.get(tabOrder) instanceof THScroller)
1183 && !(children.get(tabOrder) instanceof TVScroller));
48e27807 1184
d36057df 1185 assert (children.get(tabOrder).enabled);
48e27807 1186
d36057df
KL
1187 activeChild.active = false;
1188 children.get(tabOrder).active = true;
1189 activeChild = children.get(tabOrder);
1190 }
48e27807 1191
d36057df
KL
1192 /**
1193 * Returns my active widget.
1194 *
1195 * @return widget that is active, or this if no children
1196 */
1197 public TWidget getActiveChild() {
1198 if ((this instanceof THScroller)
1199 || (this instanceof TVScroller)
1200 ) {
1201 return parent;
1202 }
b6faeac0 1203
d36057df
KL
1204 for (TWidget widget: children) {
1205 if (widget.active) {
1206 return widget.getActiveChild();
48e27807 1207 }
48e27807 1208 }
d36057df
KL
1209 // No active children, return me
1210 return this;
48e27807
KL
1211 }
1212
a69ed767
KL
1213 // ------------------------------------------------------------------------
1214 // Passthru for Screen functions ------------------------------------------
1215 // ------------------------------------------------------------------------
1216
1217 /**
1218 * Get the attributes at one location.
1219 *
1220 * @param x column coordinate. 0 is the left-most column.
1221 * @param y row coordinate. 0 is the top-most row.
1222 * @return attributes at (x, y)
1223 */
1224 protected final CellAttributes getAttrXY(final int x, final int y) {
1225 return getScreen().getAttrXY(x, y);
1226 }
1227
1228 /**
1229 * Set the attributes at one location.
1230 *
1231 * @param x column coordinate. 0 is the left-most column.
1232 * @param y row coordinate. 0 is the top-most row.
1233 * @param attr attributes to use (bold, foreColor, backColor)
1234 */
1235 protected final void putAttrXY(final int x, final int y,
1236 final CellAttributes attr) {
1237
1238 getScreen().putAttrXY(x, y, attr);
1239 }
1240
1241 /**
1242 * Set the attributes at one location.
1243 *
1244 * @param x column coordinate. 0 is the left-most column.
1245 * @param y row coordinate. 0 is the top-most row.
1246 * @param attr attributes to use (bold, foreColor, backColor)
1247 * @param clip if true, honor clipping/offset
1248 */
1249 protected final void putAttrXY(final int x, final int y,
1250 final CellAttributes attr, final boolean clip) {
1251
1252 getScreen().putAttrXY(x, y, attr, clip);
1253 }
1254
1255 /**
1256 * Fill the entire screen with one character with attributes.
1257 *
1258 * @param ch character to draw
1259 * @param attr attributes to use (bold, foreColor, backColor)
1260 */
1261 protected final void putAll(final char ch, final CellAttributes attr) {
1262 getScreen().putAll(ch, attr);
1263 }
1264
1265 /**
1266 * Render one character with attributes.
1267 *
1268 * @param x column coordinate. 0 is the left-most column.
1269 * @param y row coordinate. 0 is the top-most row.
1270 * @param ch character + attributes to draw
1271 */
1272 protected final void putCharXY(final int x, final int y, final Cell ch) {
1273 getScreen().putCharXY(x, y, ch);
1274 }
1275
1276 /**
1277 * Render one character with attributes.
1278 *
1279 * @param x column coordinate. 0 is the left-most column.
1280 * @param y row coordinate. 0 is the top-most row.
1281 * @param ch character to draw
1282 * @param attr attributes to use (bold, foreColor, backColor)
1283 */
1284 protected final void putCharXY(final int x, final int y, final char ch,
1285 final CellAttributes attr) {
1286
1287 getScreen().putCharXY(x, y, ch, attr);
1288 }
1289
1290 /**
1291 * Render one character without changing the underlying attributes.
1292 *
1293 * @param x column coordinate. 0 is the left-most column.
1294 * @param y row coordinate. 0 is the top-most row.
1295 * @param ch character to draw
1296 */
1297 protected final void putCharXY(final int x, final int y, final char ch) {
1298 getScreen().putCharXY(x, y, ch);
1299 }
1300
1301 /**
1302 * Render a string. Does not wrap if the string exceeds the line.
1303 *
1304 * @param x column coordinate. 0 is the left-most column.
1305 * @param y row coordinate. 0 is the top-most row.
1306 * @param str string to draw
1307 * @param attr attributes to use (bold, foreColor, backColor)
1308 */
1309 protected final void putStringXY(final int x, final int y, final String str,
1310 final CellAttributes attr) {
1311
1312 getScreen().putStringXY(x, y, str, attr);
1313 }
1314
1315 /**
1316 * Render a string without changing the underlying attribute. Does not
1317 * wrap if the string exceeds the line.
1318 *
1319 * @param x column coordinate. 0 is the left-most column.
1320 * @param y row coordinate. 0 is the top-most row.
1321 * @param str string to draw
1322 */
1323 protected final void putStringXY(final int x, final int y, final String str) {
1324 getScreen().putStringXY(x, y, str);
1325 }
1326
1327 /**
1328 * Draw a vertical line from (x, y) to (x, y + n).
1329 *
1330 * @param x column coordinate. 0 is the left-most column.
1331 * @param y row coordinate. 0 is the top-most row.
1332 * @param n number of characters to draw
1333 * @param ch character to draw
1334 * @param attr attributes to use (bold, foreColor, backColor)
1335 */
1336 protected final void vLineXY(final int x, final int y, final int n,
1337 final char ch, final CellAttributes attr) {
1338
1339 getScreen().vLineXY(x, y, n, ch, attr);
1340 }
1341
1342 /**
1343 * Draw a horizontal line from (x, y) to (x + n, y).
1344 *
1345 * @param x column coordinate. 0 is the left-most column.
1346 * @param y row coordinate. 0 is the top-most row.
1347 * @param n number of characters to draw
1348 * @param ch character to draw
1349 * @param attr attributes to use (bold, foreColor, backColor)
1350 */
1351 protected final void hLineXY(final int x, final int y, final int n,
1352 final char ch, final CellAttributes attr) {
1353
1354 getScreen().hLineXY(x, y, n, ch, attr);
1355 }
1356
1357 /**
1358 * Draw a box with a border and empty background.
1359 *
1360 * @param left left column of box. 0 is the left-most row.
1361 * @param top top row of the box. 0 is the top-most row.
1362 * @param right right column of box
1363 * @param bottom bottom row of the box
1364 * @param border attributes to use for the border
1365 * @param background attributes to use for the background
1366 */
1367 protected final void drawBox(final int left, final int top,
1368 final int right, final int bottom,
1369 final CellAttributes border, final CellAttributes background) {
1370
1371 getScreen().drawBox(left, top, right, bottom, border, background);
1372 }
1373
1374 /**
1375 * Draw a box with a border and empty background.
1376 *
1377 * @param left left column of box. 0 is the left-most row.
1378 * @param top top row of the box. 0 is the top-most row.
1379 * @param right right column of box
1380 * @param bottom bottom row of the box
1381 * @param border attributes to use for the border
1382 * @param background attributes to use for the background
1383 * @param borderType if 1, draw a single-line border; if 2, draw a
1384 * double-line border; if 3, draw double-line top/bottom edges and
1385 * single-line left/right edges (like Qmodem)
1386 * @param shadow if true, draw a "shadow" on the box
1387 */
1388 protected final void drawBox(final int left, final int top,
1389 final int right, final int bottom,
1390 final CellAttributes border, final CellAttributes background,
1391 final int borderType, final boolean shadow) {
1392
1393 getScreen().drawBox(left, top, right, bottom, border, background,
1394 borderType, shadow);
1395 }
1396
1397 /**
1398 * Draw a box shadow.
1399 *
1400 * @param left left column of box. 0 is the left-most row.
1401 * @param top top row of the box. 0 is the top-most row.
1402 * @param right right column of box
1403 * @param bottom bottom row of the box
1404 */
1405 protected final void drawBoxShadow(final int left, final int top,
1406 final int right, final int bottom) {
1407
1408 getScreen().drawBoxShadow(left, top, right, bottom);
1409 }
1410
2ce6dab2
KL
1411 // ------------------------------------------------------------------------
1412 // Other TWidget constructors ---------------------------------------------
1413 // ------------------------------------------------------------------------
48e27807 1414
30d336cc
KL
1415 /**
1416 * Convenience function to add a label to this container/window.
1417 *
1418 * @param text label
1419 * @param x column relative to parent
1420 * @param y row relative to parent
1421 * @return the new label
1422 */
1423 public final TLabel addLabel(final String text, final int x, final int y) {
1424 return addLabel(text, x, y, "tlabel");
1425 }
1426
1427 /**
1428 * Convenience function to add a label to this container/window.
1429 *
1430 * @param text label
1431 * @param x column relative to parent
1432 * @param y row relative to parent
1433 * @param colorKey ColorTheme key color to use for foreground text.
1434 * Default is "tlabel"
1435 * @return the new label
1436 */
1437 public final TLabel addLabel(final String text, final int x, final int y,
1438 final String colorKey) {
1439
1440 return new TLabel(this, text, x, y, colorKey);
1441 }
1442
051e2913
KL
1443 /**
1444 * Convenience function to add a label to this container/window.
1445 *
1446 * @param text label
1447 * @param x column relative to parent
1448 * @param y row relative to parent
1449 * @param colorKey ColorTheme key color to use for foreground text.
1450 * Default is "tlabel"
1451 * @param useWindowBackground if true, use the window's background color
1452 * @return the new label
1453 */
1454 public final TLabel addLabel(final String text, final int x, final int y,
1455 final String colorKey, final boolean useWindowBackground) {
1456
1457 return new TLabel(this, text, x, y, colorKey, useWindowBackground);
1458 }
1459
30d336cc
KL
1460 /**
1461 * Convenience function to add a button to this container/window.
1462 *
1463 * @param text label on the button
1464 * @param x column relative to parent
1465 * @param y row relative to parent
051e2913 1466 * @param action action to call when button is pressed
30d336cc
KL
1467 * @return the new button
1468 */
1469 public final TButton addButton(final String text, final int x, final int y,
1470 final TAction action) {
1471
1472 return new TButton(this, text, x, y, action);
1473 }
1474
7272e49f
KL
1475 /**
1476 * Convenience function to add a checkbox to this container/window.
1477 *
1478 * @param x column relative to parent
1479 * @param y row relative to parent
1480 * @param label label to display next to (right of) the checkbox
1481 * @param checked initial check state
1482 * @return the new checkbox
1483 */
051e2913 1484 public final TCheckBox addCheckBox(final int x, final int y,
7272e49f
KL
1485 final String label, final boolean checked) {
1486
051e2913
KL
1487 return new TCheckBox(this, x, y, label, checked);
1488 }
1489
1490 /**
1491 * Convenience function to add a combobox to this container/window.
1492 *
1493 * @param x column relative to parent
1494 * @param y row relative to parent
1495 * @param width visible combobox width, including the down-arrow
1496 * @param values the possible values for the box, shown in the drop-down
1497 * @param valuesIndex the initial index in values, or -1 for no default
1498 * value
1499 * @param valuesHeight the height of the values drop-down when it is
1500 * visible
1501 * @param updateAction action to call when a new value is selected from
1502 * the list or enter is pressed in the edit field
1503 * @return the new combobox
1504 */
1505 public final TComboBox addComboBox(final int x, final int y,
1506 final int width, final List<String> values, final int valuesIndex,
1507 final int valuesHeight, final TAction updateAction) {
1508
1509 return new TComboBox(this, x, y, width, values, valuesIndex,
1510 valuesHeight, updateAction);
1511 }
1512
1513 /**
1514 * Convenience function to add a spinner to this container/window.
1515 *
1516 * @param x column relative to parent
1517 * @param y row relative to parent
1518 * @param upAction action to call when the up arrow is clicked or pressed
1519 * @param downAction action to call when the down arrow is clicked or
1520 * pressed
1521 * @return the new spinner
1522 */
1523 public final TSpinner addSpinner(final int x, final int y,
1524 final TAction upAction, final TAction downAction) {
1525
1526 return new TSpinner(this, x, y, upAction, downAction);
1527 }
1528
1529 /**
1530 * Convenience function to add a calendar to this container/window.
1531 *
1532 * @param x column relative to parent
1533 * @param y row relative to parent
1534 * @param updateAction action to call when the user changes the value of
1535 * the calendar
1536 * @return the new calendar
1537 */
1538 public final TCalendar addCalendar(final int x, final int y,
1539 final TAction updateAction) {
1540
1541 return new TCalendar(this, x, y, updateAction);
7272e49f 1542 }
30d336cc 1543
d502a0e9
KL
1544 /**
1545 * Convenience function to add a progress bar to this container/window.
1546 *
1547 * @param x column relative to parent
1548 * @param y row relative to parent
1549 * @param width width of progress bar
1550 * @param value initial value of percent complete
00d2622b 1551 * @return the new progress bar
d502a0e9
KL
1552 */
1553 public final TProgressBar addProgressBar(final int x, final int y,
1554 final int width, final int value) {
1555
1556 return new TProgressBar(this, x, y, width, value);
1557 }
1558
00d2622b
KL
1559 /**
1560 * Convenience function to add a radio button group to this
1561 * container/window.
1562 *
1563 * @param x column relative to parent
1564 * @param y row relative to parent
1565 * @param label label to display on the group box
1566 * @return the new radio button group
1567 */
1568 public final TRadioGroup addRadioGroup(final int x, final int y,
1569 final String label) {
1570
1571 return new TRadioGroup(this, x, y, label);
1572 }
1573
128e5be1
KL
1574 /**
1575 * Convenience function to add a text field to this container/window.
1576 *
1577 * @param x column relative to parent
1578 * @param y row relative to parent
1579 * @param width visible text width
1580 * @param fixed if true, the text cannot exceed the display width
1581 * @return the new text field
1582 */
1583 public final TField addField(final int x, final int y,
1584 final int width, final boolean fixed) {
1585
1586 return new TField(this, x, y, width, fixed);
1587 }
1588
1589 /**
1590 * Convenience function to add a text field to this container/window.
1591 *
1592 * @param x column relative to parent
1593 * @param y row relative to parent
1594 * @param width visible text width
1595 * @param fixed if true, the text cannot exceed the display width
1596 * @param text initial text, default is empty string
1597 * @return the new text field
1598 */
1599 public final TField addField(final int x, final int y,
1600 final int width, final boolean fixed, final String text) {
1601
1602 return new TField(this, x, y, width, fixed, text);
1603 }
1604
1605 /**
1606 * Convenience function to add a text field to this container/window.
1607 *
1608 * @param x column relative to parent
1609 * @param y row relative to parent
1610 * @param width visible text width
1611 * @param fixed if true, the text cannot exceed the display width
1612 * @param text initial text, default is empty string
1613 * @param enterAction function to call when enter key is pressed
1614 * @param updateAction function to call when the text is updated
1615 * @return the new text field
1616 */
1617 public final TField addField(final int x, final int y,
1618 final int width, final boolean fixed, final String text,
1619 final TAction enterAction, final TAction updateAction) {
1620
1621 return new TField(this, x, y, width, fixed, text, enterAction,
1622 updateAction);
1623 }
00d2622b 1624
cc99cba8
KL
1625 /**
1626 * Convenience function to add a scrollable text box to this
1627 * container/window.
1628 *
1629 * @param text text on the screen
1630 * @param x column relative to parent
1631 * @param y row relative to parent
1632 * @param width width of text area
1633 * @param height height of text area
1634 * @param colorKey ColorTheme key color to use for foreground text
1635 * @return the new text box
1636 */
c6940ed9 1637 public final TText addText(final String text, final int x,
cc99cba8
KL
1638 final int y, final int width, final int height, final String colorKey) {
1639
1640 return new TText(this, text, x, y, width, height, colorKey);
1641 }
1642
1643 /**
1644 * Convenience function to add a scrollable text box to this
1645 * container/window.
1646 *
1647 * @param text text on the screen
1648 * @param x column relative to parent
1649 * @param y row relative to parent
1650 * @param width width of text area
1651 * @param height height of text area
1652 * @return the new text box
1653 */
c6940ed9 1654 public final TText addText(final String text, final int x, final int y,
cc99cba8
KL
1655 final int width, final int height) {
1656
1657 return new TText(this, text, x, y, width, height, "ttext");
1658 }
1659
12b55d76
KL
1660 /**
1661 * Convenience function to add an editable text area box to this
1662 * container/window.
1663 *
1664 * @param text text on the screen
1665 * @param x column relative to parent
1666 * @param y row relative to parent
1667 * @param width width of text area
1668 * @param height height of text area
1669 * @return the new text box
1670 */
1671 public final TEditorWidget addEditor(final String text, final int x,
1672 final int y, final int width, final int height) {
1673
1674 return new TEditorWidget(this, text, x, y, width, height);
1675 }
1676
c6940ed9
KL
1677 /**
1678 * Convenience function to spawn a message box.
1679 *
1680 * @param title window title, will be centered along the top border
1681 * @param caption message to display. Use embedded newlines to get a
1682 * multi-line box.
1683 * @return the new message box
1684 */
1685 public final TMessageBox messageBox(final String title,
1686 final String caption) {
1687
1688 return getApplication().messageBox(title, caption, TMessageBox.Type.OK);
1689 }
1690
1691 /**
1692 * Convenience function to spawn a message box.
1693 *
1694 * @param title window title, will be centered along the top border
1695 * @param caption message to display. Use embedded newlines to get a
1696 * multi-line box.
1697 * @param type one of the TMessageBox.Type constants. Default is
1698 * Type.OK.
1699 * @return the new message box
1700 */
1701 public final TMessageBox messageBox(final String title,
1702 final String caption, final TMessageBox.Type type) {
1703
1704 return getApplication().messageBox(title, caption, type);
1705 }
1706
1707 /**
1708 * Convenience function to spawn an input box.
1709 *
1710 * @param title window title, will be centered along the top border
1711 * @param caption message to display. Use embedded newlines to get a
1712 * multi-line box.
1713 * @return the new input box
1714 */
1715 public final TInputBox inputBox(final String title, final String caption) {
1716
1717 return getApplication().inputBox(title, caption);
1718 }
1719
1720 /**
1721 * Convenience function to spawn an input box.
1722 *
1723 * @param title window title, will be centered along the top border
1724 * @param caption message to display. Use embedded newlines to get a
1725 * multi-line box.
1726 * @param text initial text to seed the field with
1727 * @return the new input box
1728 */
1729 public final TInputBox inputBox(final String title, final String caption,
1730 final String text) {
1731
1732 return getApplication().inputBox(title, caption, text);
1733 }
cc99cba8 1734
87a17f3c
KL
1735 /**
1736 * Convenience function to add a password text field to this
1737 * container/window.
1738 *
1739 * @param x column relative to parent
1740 * @param y row relative to parent
1741 * @param width visible text width
1742 * @param fixed if true, the text cannot exceed the display width
1743 * @return the new text field
1744 */
1745 public final TPasswordField addPasswordField(final int x, final int y,
1746 final int width, final boolean fixed) {
1747
1748 return new TPasswordField(this, x, y, width, fixed);
1749 }
1750
1751 /**
1752 * Convenience function to add a password text field to this
1753 * container/window.
1754 *
1755 * @param x column relative to parent
1756 * @param y row relative to parent
1757 * @param width visible text width
1758 * @param fixed if true, the text cannot exceed the display width
1759 * @param text initial text, default is empty string
1760 * @return the new text field
1761 */
1762 public final TPasswordField addPasswordField(final int x, final int y,
1763 final int width, final boolean fixed, final String text) {
1764
1765 return new TPasswordField(this, x, y, width, fixed, text);
1766 }
1767
1768 /**
1769 * Convenience function to add a password text field to this
1770 * container/window.
1771 *
1772 * @param x column relative to parent
1773 * @param y row relative to parent
1774 * @param width visible text width
1775 * @param fixed if true, the text cannot exceed the display width
1776 * @param text initial text, default is empty string
1777 * @param enterAction function to call when enter key is pressed
1778 * @param updateAction function to call when the text is updated
1779 * @return the new text field
1780 */
1781 public final TPasswordField addPasswordField(final int x, final int y,
1782 final int width, final boolean fixed, final String text,
1783 final TAction enterAction, final TAction updateAction) {
1784
1785 return new TPasswordField(this, x, y, width, fixed, text, enterAction,
1786 updateAction);
1787 }
1788
7668cb45 1789 /**
d36057df
KL
1790 * Convenience function to add a scrollable tree view to this
1791 * container/window.
7668cb45
KL
1792 *
1793 * @param x column relative to parent
1794 * @param y row relative to parent
1795 * @param width width of tree view
1796 * @param height height of tree view
329fd62e 1797 * @return the new tree view
7668cb45 1798 */
d36057df 1799 public final TTreeViewWidget addTreeViewWidget(final int x, final int y,
7668cb45
KL
1800 final int width, final int height) {
1801
d36057df 1802 return new TTreeViewWidget(this, x, y, width, height);
7668cb45
KL
1803 }
1804
1805 /**
d36057df
KL
1806 * Convenience function to add a scrollable tree view to this
1807 * container/window.
7668cb45
KL
1808 *
1809 * @param x column relative to parent
1810 * @param y row relative to parent
1811 * @param width width of tree view
1812 * @param height height of tree view
1813 * @param action action to perform when an item is selected
329fd62e 1814 * @return the new tree view
7668cb45 1815 */
d36057df 1816 public final TTreeViewWidget addTreeViewWidget(final int x, final int y,
7668cb45
KL
1817 final int width, final int height, final TAction action) {
1818
d36057df 1819 return new TTreeViewWidget(this, x, y, width, height, action);
7668cb45
KL
1820 }
1821
0d47c546
KL
1822 /**
1823 * Convenience function to spawn a file open box.
1824 *
1825 * @param path path of selected file
1826 * @return the result of the new file open box
329fd62e 1827 * @throws IOException if a java.io operation throws
0d47c546
KL
1828 */
1829 public final String fileOpenBox(final String path) throws IOException {
1830 return getApplication().fileOpenBox(path);
1831 }
1832
a69ed767
KL
1833 /**
1834 * Convenience function to spawn a file save box.
1835 *
1836 * @param path path of selected file
1837 * @return the result of the new file open box
1838 * @throws IOException if a java.io operation throws
1839 */
1840 public final String fileSaveBox(final String path) throws IOException {
1841 return getApplication().fileOpenBox(path, TFileOpenBox.Type.SAVE);
1842 }
1843
0d47c546
KL
1844 /**
1845 * Convenience function to spawn a file open box.
1846 *
1847 * @param path path of selected file
1848 * @param type one of the Type constants
1849 * @return the result of the new file open box
329fd62e 1850 * @throws IOException if a java.io operation throws
0d47c546
KL
1851 */
1852 public final String fileOpenBox(final String path,
1853 final TFileOpenBox.Type type) throws IOException {
1854
1855 return getApplication().fileOpenBox(path, type);
1856 }
a69ed767
KL
1857
1858 /**
1859 * Convenience function to spawn a file open box.
1860 *
1861 * @param path path of selected file
1862 * @param type one of the Type constants
1863 * @param filter a string that files must match to be displayed
1864 * @return the result of the new file open box
1865 * @throws IOException of a java.io operation throws
1866 */
1867 public final String fileOpenBox(final String path,
1868 final TFileOpenBox.Type type, final String filter) throws IOException {
1869
1870 ArrayList<String> filters = new ArrayList<String>();
1871 filters.add(filter);
1872
1873 return getApplication().fileOpenBox(path, type, filters);
1874 }
1875
1876 /**
1877 * Convenience function to spawn a file open box.
1878 *
1879 * @param path path of selected file
1880 * @param type one of the Type constants
1881 * @param filters a list of strings that files must match to be displayed
1882 * @return the result of the new file open box
1883 * @throws IOException of a java.io operation throws
1884 */
1885 public final String fileOpenBox(final String path,
1886 final TFileOpenBox.Type type,
1887 final List<String> filters) throws IOException {
1888
1889 return getApplication().fileOpenBox(path, type, filters);
1890 }
1891
0d47c546
KL
1892 /**
1893 * Convenience function to add a directory list to this container/window.
1894 *
1895 * @param path directory path, must be a directory
1896 * @param x column relative to parent
1897 * @param y row relative to parent
1898 * @param width width of text area
1899 * @param height height of text area
329fd62e 1900 * @return the new directory list
0d47c546
KL
1901 */
1902 public final TDirectoryList addDirectoryList(final String path, final int x,
1903 final int y, final int width, final int height) {
1904
1905 return new TDirectoryList(this, path, x, y, width, height, null);
1906 }
1907
1908 /**
1909 * Convenience function to add a directory list to this container/window.
1910 *
1911 * @param path directory path, must be a directory
1912 * @param x column relative to parent
1913 * @param y row relative to parent
1914 * @param width width of text area
1915 * @param height height of text area
a69ed767
KL
1916 * @param action action to perform when an item is selected (enter or
1917 * double-click)
329fd62e 1918 * @return the new directory list
0d47c546
KL
1919 */
1920 public final TDirectoryList addDirectoryList(final String path, final int x,
1921 final int y, final int width, final int height, final TAction action) {
1922
1923 return new TDirectoryList(this, path, x, y, width, height, action);
1924 }
7668cb45 1925
3649b921
KL
1926 /**
1927 * Convenience function to add a directory list to this container/window.
1928 *
a69ed767
KL
1929 * @param path directory path, must be a directory
1930 * @param x column relative to parent
1931 * @param y row relative to parent
1932 * @param width width of text area
1933 * @param height height of text area
1934 * @param action action to perform when an item is selected (enter or
1935 * double-click)
1936 * @param singleClickAction action to perform when an item is selected
1937 * (single-click)
1938 * @return the new directory list
1939 */
1940 public final TDirectoryList addDirectoryList(final String path, final int x,
1941 final int y, final int width, final int height, final TAction action,
1942 final TAction singleClickAction) {
1943
1944 return new TDirectoryList(this, path, x, y, width, height, action,
1945 singleClickAction);
1946 }
1947
1948 /**
1949 * Convenience function to add a directory list to this container/window.
1950 *
1951 * @param path directory path, must be a directory
1952 * @param x column relative to parent
1953 * @param y row relative to parent
1954 * @param width width of text area
1955 * @param height height of text area
1956 * @param action action to perform when an item is selected (enter or
1957 * double-click)
1958 * @param singleClickAction action to perform when an item is selected
1959 * (single-click)
1960 * @param filters a list of strings that files must match to be displayed
1961 * @return the new directory list
1962 */
1963 public final TDirectoryList addDirectoryList(final String path, final int x,
1964 final int y, final int width, final int height, final TAction action,
1965 final TAction singleClickAction, final List<String> filters) {
1966
1967 return new TDirectoryList(this, path, x, y, width, height, action,
1968 singleClickAction, filters);
1969 }
1970
1971 /**
1972 * Convenience function to add a list to this container/window.
1973 *
3649b921
KL
1974 * @param strings list of strings to show
1975 * @param x column relative to parent
1976 * @param y row relative to parent
1977 * @param width width of text area
1978 * @param height height of text area
1979 * @return the new directory list
1980 */
1981 public final TList addList(final List<String> strings, final int x,
1982 final int y, final int width, final int height) {
1983
1984 return new TList(this, strings, x, y, width, height, null);
1985 }
1986
1987 /**
a69ed767 1988 * Convenience function to add a list to this container/window.
3649b921
KL
1989 *
1990 * @param strings list of strings to show
1991 * @param x column relative to parent
1992 * @param y row relative to parent
1993 * @param width width of text area
1994 * @param height height of text area
1995 * @param enterAction action to perform when an item is selected
1996 * @return the new directory list
1997 */
1998 public final TList addList(final List<String> strings, final int x,
1999 final int y, final int width, final int height,
2000 final TAction enterAction) {
2001
2002 return new TList(this, strings, x, y, width, height, enterAction);
2003 }
2004
2005 /**
a69ed767 2006 * Convenience function to add a list to this container/window.
3649b921
KL
2007 *
2008 * @param strings list of strings to show
2009 * @param x column relative to parent
2010 * @param y row relative to parent
2011 * @param width width of text area
2012 * @param height height of text area
2013 * @param enterAction action to perform when an item is selected
2014 * @param moveAction action to perform when the user navigates to a new
2015 * item with arrow/page keys
2016 * @return the new directory list
2017 */
2018 public final TList addList(final List<String> strings, final int x,
2019 final int y, final int width, final int height,
2020 final TAction enterAction, final TAction moveAction) {
2021
2022 return new TList(this, strings, x, y, width, height, enterAction,
2023 moveAction);
2024 }
2025
48e27807 2026}