sixel in README
[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
e23ea538
KL
1101 if (children.size() == 1) {
1102 if (children.get(0).enabled == true) {
1103 child.active = true;
1104 activeChild = child;
1105 }
1106 } else {
1107 if (child != activeChild) {
1108 if (activeChild != null) {
1109 activeChild.active = false;
1110 }
1111 child.active = true;
1112 activeChild = child;
12b55d76 1113 }
48e27807
KL
1114 }
1115 }
1116
1117 /**
d36057df 1118 * Switch the active child.
48e27807 1119 *
d36057df
KL
1120 * @param tabOrder tabOrder of the child to activate. If that child
1121 * isn't enabled, then the next enabled child will be activated.
48e27807 1122 */
d36057df 1123 public final void activate(final int tabOrder) {
e23ea538
KL
1124 if (children.size() == 1) {
1125 if (children.get(0).enabled == true) {
1126 children.get(0).active = true;
1127 activeChild = children.get(0);
1128 }
1129 return;
1130 }
1131
d36057df
KL
1132 if (activeChild == null) {
1133 return;
48e27807 1134 }
d36057df 1135 TWidget child = null;
48e27807 1136 for (TWidget widget: children) {
d36057df
KL
1137 if ((widget.enabled)
1138 && !(widget instanceof THScroller)
1139 && !(widget instanceof TVScroller)
1140 && (widget.tabOrder >= tabOrder)
1141 ) {
1142 child = widget;
1143 break;
1144 }
48e27807 1145 }
d36057df
KL
1146 if ((child != null) && (child != activeChild)) {
1147 activeChild.active = false;
1148 assert (child.enabled);
1149 child.active = true;
1150 activeChild = child;
48e27807
KL
1151 }
1152 }
1153
1154 /**
d36057df 1155 * Switch the active widget with the next in the tab order.
48e27807 1156 *
d36057df
KL
1157 * @param forward if true, then switch to the next enabled widget in the
1158 * list, otherwise switch to the previous enabled widget in the list
48e27807 1159 */
d36057df 1160 public final void switchWidget(final boolean forward) {
48e27807 1161
e23ea538 1162 // No children: do nothing.
978a5d8f 1163 if ((children.size() == 0) || (activeChild == null)) {
e23ea538
KL
1164 return;
1165 }
1166
1167 // If there is only one child, make it active if it is enabled.
1168 if (children.size() == 1) {
1169 if (children.get(0).enabled == true) {
1170 activeChild = children.get(0);
1171 activeChild.active = true;
1172 } else {
1173 children.get(0).active = false;
1174 activeChild = null;
1175 }
48e27807
KL
1176 return;
1177 }
1178
e23ea538
KL
1179 // Two or more children: go forward or backward to the next enabled
1180 // child.
d36057df
KL
1181 int tabOrder = activeChild.tabOrder;
1182 do {
1183 if (forward) {
1184 tabOrder++;
1185 } else {
1186 tabOrder--;
1187 }
1188 if (tabOrder < 0) {
48e27807 1189
d36057df
KL
1190 // If at the end, pass the switch to my parent.
1191 if ((!forward) && (parent != this)) {
1192 parent.switchWidget(forward);
1193 return;
1194 }
48e27807 1195
d36057df
KL
1196 tabOrder = children.size() - 1;
1197 } else if (tabOrder == children.size()) {
1198 // If at the end, pass the switch to my parent.
1199 if ((forward) && (parent != this)) {
1200 parent.switchWidget(forward);
1201 return;
1202 }
48e27807 1203
d36057df
KL
1204 tabOrder = 0;
1205 }
1206 if (activeChild.tabOrder == tabOrder) {
1207 // We wrapped around
48e27807 1208 break;
d36057df
KL
1209 }
1210 } while ((!children.get(tabOrder).enabled)
1211 && !(children.get(tabOrder) instanceof THScroller)
1212 && !(children.get(tabOrder) instanceof TVScroller));
48e27807 1213
d36057df 1214 assert (children.get(tabOrder).enabled);
48e27807 1215
d36057df
KL
1216 activeChild.active = false;
1217 children.get(tabOrder).active = true;
1218 activeChild = children.get(tabOrder);
1219 }
48e27807 1220
d36057df
KL
1221 /**
1222 * Returns my active widget.
1223 *
1224 * @return widget that is active, or this if no children
1225 */
1226 public TWidget getActiveChild() {
1227 if ((this instanceof THScroller)
1228 || (this instanceof TVScroller)
1229 ) {
1230 return parent;
1231 }
b6faeac0 1232
d36057df
KL
1233 for (TWidget widget: children) {
1234 if (widget.active) {
1235 return widget.getActiveChild();
48e27807 1236 }
48e27807 1237 }
d36057df
KL
1238 // No active children, return me
1239 return this;
48e27807
KL
1240 }
1241
a69ed767
KL
1242 // ------------------------------------------------------------------------
1243 // Passthru for Screen functions ------------------------------------------
1244 // ------------------------------------------------------------------------
1245
1246 /**
1247 * Get the attributes at one location.
1248 *
1249 * @param x column coordinate. 0 is the left-most column.
1250 * @param y row coordinate. 0 is the top-most row.
1251 * @return attributes at (x, y)
1252 */
1253 protected final CellAttributes getAttrXY(final int x, final int y) {
1254 return getScreen().getAttrXY(x, y);
1255 }
1256
1257 /**
1258 * Set the attributes at one location.
1259 *
1260 * @param x column coordinate. 0 is the left-most column.
1261 * @param y row coordinate. 0 is the top-most row.
1262 * @param attr attributes to use (bold, foreColor, backColor)
1263 */
1264 protected final void putAttrXY(final int x, final int y,
1265 final CellAttributes attr) {
1266
1267 getScreen().putAttrXY(x, y, attr);
1268 }
1269
1270 /**
1271 * Set the attributes at one location.
1272 *
1273 * @param x column coordinate. 0 is the left-most column.
1274 * @param y row coordinate. 0 is the top-most row.
1275 * @param attr attributes to use (bold, foreColor, backColor)
1276 * @param clip if true, honor clipping/offset
1277 */
1278 protected final void putAttrXY(final int x, final int y,
1279 final CellAttributes attr, final boolean clip) {
1280
1281 getScreen().putAttrXY(x, y, attr, clip);
1282 }
1283
1284 /**
1285 * Fill the entire screen with one character with attributes.
1286 *
1287 * @param ch character to draw
1288 * @param attr attributes to use (bold, foreColor, backColor)
1289 */
1290 protected final void putAll(final char ch, final CellAttributes attr) {
1291 getScreen().putAll(ch, attr);
1292 }
1293
1294 /**
1295 * Render one character with attributes.
1296 *
1297 * @param x column coordinate. 0 is the left-most column.
1298 * @param y row coordinate. 0 is the top-most row.
1299 * @param ch character + attributes to draw
1300 */
1301 protected final void putCharXY(final int x, final int y, final Cell ch) {
1302 getScreen().putCharXY(x, y, ch);
1303 }
1304
1305 /**
1306 * Render one character with attributes.
1307 *
1308 * @param x column coordinate. 0 is the left-most column.
1309 * @param y row coordinate. 0 is the top-most row.
1310 * @param ch character to draw
1311 * @param attr attributes to use (bold, foreColor, backColor)
1312 */
1313 protected final void putCharXY(final int x, final int y, final char ch,
1314 final CellAttributes attr) {
1315
1316 getScreen().putCharXY(x, y, ch, attr);
1317 }
1318
1319 /**
1320 * Render one character without changing the underlying attributes.
1321 *
1322 * @param x column coordinate. 0 is the left-most column.
1323 * @param y row coordinate. 0 is the top-most row.
1324 * @param ch character to draw
1325 */
1326 protected final void putCharXY(final int x, final int y, final char ch) {
1327 getScreen().putCharXY(x, y, ch);
1328 }
1329
1330 /**
1331 * Render a string. Does not wrap if the string exceeds the line.
1332 *
1333 * @param x column coordinate. 0 is the left-most column.
1334 * @param y row coordinate. 0 is the top-most row.
1335 * @param str string to draw
1336 * @param attr attributes to use (bold, foreColor, backColor)
1337 */
1338 protected final void putStringXY(final int x, final int y, final String str,
1339 final CellAttributes attr) {
1340
1341 getScreen().putStringXY(x, y, str, attr);
1342 }
1343
1344 /**
1345 * Render a string without changing the underlying attribute. Does not
1346 * wrap if the string exceeds the line.
1347 *
1348 * @param x column coordinate. 0 is the left-most column.
1349 * @param y row coordinate. 0 is the top-most row.
1350 * @param str string to draw
1351 */
1352 protected final void putStringXY(final int x, final int y, final String str) {
1353 getScreen().putStringXY(x, y, str);
1354 }
1355
1356 /**
1357 * Draw a vertical line from (x, y) to (x, y + n).
1358 *
1359 * @param x column coordinate. 0 is the left-most column.
1360 * @param y row coordinate. 0 is the top-most row.
1361 * @param n number of characters to draw
1362 * @param ch character to draw
1363 * @param attr attributes to use (bold, foreColor, backColor)
1364 */
1365 protected final void vLineXY(final int x, final int y, final int n,
1366 final char ch, final CellAttributes attr) {
1367
1368 getScreen().vLineXY(x, y, n, ch, attr);
1369 }
1370
1371 /**
1372 * Draw a horizontal line from (x, y) to (x + n, y).
1373 *
1374 * @param x column coordinate. 0 is the left-most column.
1375 * @param y row coordinate. 0 is the top-most row.
1376 * @param n number of characters to draw
1377 * @param ch character to draw
1378 * @param attr attributes to use (bold, foreColor, backColor)
1379 */
1380 protected final void hLineXY(final int x, final int y, final int n,
1381 final char ch, final CellAttributes attr) {
1382
1383 getScreen().hLineXY(x, y, n, ch, attr);
1384 }
1385
1386 /**
1387 * Draw a box with a border and empty background.
1388 *
1389 * @param left left column of box. 0 is the left-most row.
1390 * @param top top row of the box. 0 is the top-most row.
1391 * @param right right column of box
1392 * @param bottom bottom row of the box
1393 * @param border attributes to use for the border
1394 * @param background attributes to use for the background
1395 */
1396 protected final void drawBox(final int left, final int top,
1397 final int right, final int bottom,
1398 final CellAttributes border, final CellAttributes background) {
1399
1400 getScreen().drawBox(left, top, right, bottom, border, background);
1401 }
1402
1403 /**
1404 * Draw a box with a border and empty background.
1405 *
1406 * @param left left column of box. 0 is the left-most row.
1407 * @param top top row of the box. 0 is the top-most row.
1408 * @param right right column of box
1409 * @param bottom bottom row of the box
1410 * @param border attributes to use for the border
1411 * @param background attributes to use for the background
1412 * @param borderType if 1, draw a single-line border; if 2, draw a
1413 * double-line border; if 3, draw double-line top/bottom edges and
1414 * single-line left/right edges (like Qmodem)
1415 * @param shadow if true, draw a "shadow" on the box
1416 */
1417 protected final void drawBox(final int left, final int top,
1418 final int right, final int bottom,
1419 final CellAttributes border, final CellAttributes background,
1420 final int borderType, final boolean shadow) {
1421
1422 getScreen().drawBox(left, top, right, bottom, border, background,
1423 borderType, shadow);
1424 }
1425
1426 /**
1427 * Draw a box shadow.
1428 *
1429 * @param left left column of box. 0 is the left-most row.
1430 * @param top top row of the box. 0 is the top-most row.
1431 * @param right right column of box
1432 * @param bottom bottom row of the box
1433 */
1434 protected final void drawBoxShadow(final int left, final int top,
1435 final int right, final int bottom) {
1436
1437 getScreen().drawBoxShadow(left, top, right, bottom);
1438 }
1439
2ce6dab2
KL
1440 // ------------------------------------------------------------------------
1441 // Other TWidget constructors ---------------------------------------------
1442 // ------------------------------------------------------------------------
48e27807 1443
30d336cc
KL
1444 /**
1445 * Convenience function to add a label to this container/window.
1446 *
1447 * @param text label
1448 * @param x column relative to parent
1449 * @param y row relative to parent
1450 * @return the new label
1451 */
1452 public final TLabel addLabel(final String text, final int x, final int y) {
1453 return addLabel(text, x, y, "tlabel");
1454 }
1455
1456 /**
1457 * Convenience function to add a label to this container/window.
1458 *
1459 * @param text label
1460 * @param x column relative to parent
1461 * @param y row relative to parent
1462 * @param colorKey ColorTheme key color to use for foreground text.
1463 * Default is "tlabel"
1464 * @return the new label
1465 */
1466 public final TLabel addLabel(final String text, final int x, final int y,
1467 final String colorKey) {
1468
1469 return new TLabel(this, text, x, y, colorKey);
1470 }
1471
051e2913
KL
1472 /**
1473 * Convenience function to add a label to this container/window.
1474 *
1475 * @param text label
1476 * @param x column relative to parent
1477 * @param y row relative to parent
1478 * @param colorKey ColorTheme key color to use for foreground text.
1479 * Default is "tlabel"
1480 * @param useWindowBackground if true, use the window's background color
1481 * @return the new label
1482 */
1483 public final TLabel addLabel(final String text, final int x, final int y,
1484 final String colorKey, final boolean useWindowBackground) {
1485
1486 return new TLabel(this, text, x, y, colorKey, useWindowBackground);
1487 }
1488
30d336cc
KL
1489 /**
1490 * Convenience function to add a button to this container/window.
1491 *
1492 * @param text label on the button
1493 * @param x column relative to parent
1494 * @param y row relative to parent
051e2913 1495 * @param action action to call when button is pressed
30d336cc
KL
1496 * @return the new button
1497 */
1498 public final TButton addButton(final String text, final int x, final int y,
1499 final TAction action) {
1500
1501 return new TButton(this, text, x, y, action);
1502 }
1503
7272e49f
KL
1504 /**
1505 * Convenience function to add a checkbox to this container/window.
1506 *
1507 * @param x column relative to parent
1508 * @param y row relative to parent
1509 * @param label label to display next to (right of) the checkbox
1510 * @param checked initial check state
1511 * @return the new checkbox
1512 */
051e2913 1513 public final TCheckBox addCheckBox(final int x, final int y,
7272e49f
KL
1514 final String label, final boolean checked) {
1515
051e2913
KL
1516 return new TCheckBox(this, x, y, label, checked);
1517 }
1518
1519 /**
1520 * Convenience function to add a combobox to this container/window.
1521 *
1522 * @param x column relative to parent
1523 * @param y row relative to parent
1524 * @param width visible combobox width, including the down-arrow
1525 * @param values the possible values for the box, shown in the drop-down
1526 * @param valuesIndex the initial index in values, or -1 for no default
1527 * value
1528 * @param valuesHeight the height of the values drop-down when it is
1529 * visible
1530 * @param updateAction action to call when a new value is selected from
1531 * the list or enter is pressed in the edit field
1532 * @return the new combobox
1533 */
1534 public final TComboBox addComboBox(final int x, final int y,
1535 final int width, final List<String> values, final int valuesIndex,
1536 final int valuesHeight, final TAction updateAction) {
1537
1538 return new TComboBox(this, x, y, width, values, valuesIndex,
1539 valuesHeight, updateAction);
1540 }
1541
1542 /**
1543 * Convenience function to add a spinner to this container/window.
1544 *
1545 * @param x column relative to parent
1546 * @param y row relative to parent
1547 * @param upAction action to call when the up arrow is clicked or pressed
1548 * @param downAction action to call when the down arrow is clicked or
1549 * pressed
1550 * @return the new spinner
1551 */
1552 public final TSpinner addSpinner(final int x, final int y,
1553 final TAction upAction, final TAction downAction) {
1554
1555 return new TSpinner(this, x, y, upAction, downAction);
1556 }
1557
1558 /**
1559 * Convenience function to add a calendar to this container/window.
1560 *
1561 * @param x column relative to parent
1562 * @param y row relative to parent
1563 * @param updateAction action to call when the user changes the value of
1564 * the calendar
1565 * @return the new calendar
1566 */
1567 public final TCalendar addCalendar(final int x, final int y,
1568 final TAction updateAction) {
1569
1570 return new TCalendar(this, x, y, updateAction);
7272e49f 1571 }
30d336cc 1572
d502a0e9
KL
1573 /**
1574 * Convenience function to add a progress bar to this container/window.
1575 *
1576 * @param x column relative to parent
1577 * @param y row relative to parent
1578 * @param width width of progress bar
1579 * @param value initial value of percent complete
00d2622b 1580 * @return the new progress bar
d502a0e9
KL
1581 */
1582 public final TProgressBar addProgressBar(final int x, final int y,
1583 final int width, final int value) {
1584
1585 return new TProgressBar(this, x, y, width, value);
1586 }
1587
00d2622b
KL
1588 /**
1589 * Convenience function to add a radio button group to this
1590 * container/window.
1591 *
1592 * @param x column relative to parent
1593 * @param y row relative to parent
1594 * @param label label to display on the group box
1595 * @return the new radio button group
1596 */
1597 public final TRadioGroup addRadioGroup(final int x, final int y,
1598 final String label) {
1599
1600 return new TRadioGroup(this, x, y, label);
1601 }
1602
128e5be1
KL
1603 /**
1604 * Convenience function to add a text field to this container/window.
1605 *
1606 * @param x column relative to parent
1607 * @param y row relative to parent
1608 * @param width visible text width
1609 * @param fixed if true, the text cannot exceed the display width
1610 * @return the new text field
1611 */
1612 public final TField addField(final int x, final int y,
1613 final int width, final boolean fixed) {
1614
1615 return new TField(this, x, y, width, fixed);
1616 }
1617
1618 /**
1619 * Convenience function to add a text field to this container/window.
1620 *
1621 * @param x column relative to parent
1622 * @param y row relative to parent
1623 * @param width visible text width
1624 * @param fixed if true, the text cannot exceed the display width
1625 * @param text initial text, default is empty string
1626 * @return the new text field
1627 */
1628 public final TField addField(final int x, final int y,
1629 final int width, final boolean fixed, final String text) {
1630
1631 return new TField(this, x, y, width, fixed, text);
1632 }
1633
1634 /**
1635 * Convenience function to add a text field to this container/window.
1636 *
1637 * @param x column relative to parent
1638 * @param y row relative to parent
1639 * @param width visible text width
1640 * @param fixed if true, the text cannot exceed the display width
1641 * @param text initial text, default is empty string
1642 * @param enterAction function to call when enter key is pressed
1643 * @param updateAction function to call when the text is updated
1644 * @return the new text field
1645 */
1646 public final TField addField(final int x, final int y,
1647 final int width, final boolean fixed, final String text,
1648 final TAction enterAction, final TAction updateAction) {
1649
1650 return new TField(this, x, y, width, fixed, text, enterAction,
1651 updateAction);
1652 }
00d2622b 1653
cc99cba8
KL
1654 /**
1655 * Convenience function to add a scrollable text box to this
1656 * container/window.
1657 *
1658 * @param text text on the screen
1659 * @param x column relative to parent
1660 * @param y row relative to parent
1661 * @param width width of text area
1662 * @param height height of text area
1663 * @param colorKey ColorTheme key color to use for foreground text
1664 * @return the new text box
1665 */
c6940ed9 1666 public final TText addText(final String text, final int x,
cc99cba8
KL
1667 final int y, final int width, final int height, final String colorKey) {
1668
1669 return new TText(this, text, x, y, width, height, colorKey);
1670 }
1671
1672 /**
1673 * Convenience function to add a scrollable text box to this
1674 * container/window.
1675 *
1676 * @param text text on the screen
1677 * @param x column relative to parent
1678 * @param y row relative to parent
1679 * @param width width of text area
1680 * @param height height of text area
1681 * @return the new text box
1682 */
c6940ed9 1683 public final TText addText(final String text, final int x, final int y,
cc99cba8
KL
1684 final int width, final int height) {
1685
1686 return new TText(this, text, x, y, width, height, "ttext");
1687 }
1688
12b55d76
KL
1689 /**
1690 * Convenience function to add an editable text area box to this
1691 * container/window.
1692 *
1693 * @param text text on the screen
1694 * @param x column relative to parent
1695 * @param y row relative to parent
1696 * @param width width of text area
1697 * @param height height of text area
1698 * @return the new text box
1699 */
1700 public final TEditorWidget addEditor(final String text, final int x,
1701 final int y, final int width, final int height) {
1702
1703 return new TEditorWidget(this, text, x, y, width, height);
1704 }
1705
c6940ed9
KL
1706 /**
1707 * Convenience function to spawn a message box.
1708 *
1709 * @param title window title, will be centered along the top border
1710 * @param caption message to display. Use embedded newlines to get a
1711 * multi-line box.
1712 * @return the new message box
1713 */
1714 public final TMessageBox messageBox(final String title,
1715 final String caption) {
1716
1717 return getApplication().messageBox(title, caption, TMessageBox.Type.OK);
1718 }
1719
1720 /**
1721 * Convenience function to spawn a message 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 type one of the TMessageBox.Type constants. Default is
1727 * Type.OK.
1728 * @return the new message box
1729 */
1730 public final TMessageBox messageBox(final String title,
1731 final String caption, final TMessageBox.Type type) {
1732
1733 return getApplication().messageBox(title, caption, type);
1734 }
1735
1736 /**
1737 * Convenience function to spawn an input box.
1738 *
1739 * @param title window title, will be centered along the top border
1740 * @param caption message to display. Use embedded newlines to get a
1741 * multi-line box.
1742 * @return the new input box
1743 */
1744 public final TInputBox inputBox(final String title, final String caption) {
1745
1746 return getApplication().inputBox(title, caption);
1747 }
1748
1749 /**
1750 * Convenience function to spawn an input box.
1751 *
1752 * @param title window title, will be centered along the top border
1753 * @param caption message to display. Use embedded newlines to get a
1754 * multi-line box.
1755 * @param text initial text to seed the field with
1756 * @return the new input box
1757 */
1758 public final TInputBox inputBox(final String title, final String caption,
1759 final String text) {
1760
1761 return getApplication().inputBox(title, caption, text);
1762 }
cc99cba8 1763
87a17f3c
KL
1764 /**
1765 * Convenience function to add a password text field to this
1766 * container/window.
1767 *
1768 * @param x column relative to parent
1769 * @param y row relative to parent
1770 * @param width visible text width
1771 * @param fixed if true, the text cannot exceed the display width
1772 * @return the new text field
1773 */
1774 public final TPasswordField addPasswordField(final int x, final int y,
1775 final int width, final boolean fixed) {
1776
1777 return new TPasswordField(this, x, y, width, fixed);
1778 }
1779
1780 /**
1781 * Convenience function to add a password text field to this
1782 * container/window.
1783 *
1784 * @param x column relative to parent
1785 * @param y row relative to parent
1786 * @param width visible text width
1787 * @param fixed if true, the text cannot exceed the display width
1788 * @param text initial text, default is empty string
1789 * @return the new text field
1790 */
1791 public final TPasswordField addPasswordField(final int x, final int y,
1792 final int width, final boolean fixed, final String text) {
1793
1794 return new TPasswordField(this, x, y, width, fixed, text);
1795 }
1796
1797 /**
1798 * Convenience function to add a password text field to this
1799 * container/window.
1800 *
1801 * @param x column relative to parent
1802 * @param y row relative to parent
1803 * @param width visible text width
1804 * @param fixed if true, the text cannot exceed the display width
1805 * @param text initial text, default is empty string
1806 * @param enterAction function to call when enter key is pressed
1807 * @param updateAction function to call when the text is updated
1808 * @return the new text field
1809 */
1810 public final TPasswordField addPasswordField(final int x, final int y,
1811 final int width, final boolean fixed, final String text,
1812 final TAction enterAction, final TAction updateAction) {
1813
1814 return new TPasswordField(this, x, y, width, fixed, text, enterAction,
1815 updateAction);
1816 }
1817
7668cb45 1818 /**
d36057df
KL
1819 * Convenience function to add a scrollable tree view to this
1820 * container/window.
7668cb45
KL
1821 *
1822 * @param x column relative to parent
1823 * @param y row relative to parent
1824 * @param width width of tree view
1825 * @param height height of tree view
329fd62e 1826 * @return the new tree view
7668cb45 1827 */
d36057df 1828 public final TTreeViewWidget addTreeViewWidget(final int x, final int y,
7668cb45
KL
1829 final int width, final int height) {
1830
d36057df 1831 return new TTreeViewWidget(this, x, y, width, height);
7668cb45
KL
1832 }
1833
1834 /**
d36057df
KL
1835 * Convenience function to add a scrollable tree view to this
1836 * container/window.
7668cb45
KL
1837 *
1838 * @param x column relative to parent
1839 * @param y row relative to parent
1840 * @param width width of tree view
1841 * @param height height of tree view
1842 * @param action action to perform when an item is selected
329fd62e 1843 * @return the new tree view
7668cb45 1844 */
d36057df 1845 public final TTreeViewWidget addTreeViewWidget(final int x, final int y,
7668cb45
KL
1846 final int width, final int height, final TAction action) {
1847
d36057df 1848 return new TTreeViewWidget(this, x, y, width, height, action);
7668cb45
KL
1849 }
1850
0d47c546
KL
1851 /**
1852 * Convenience function to spawn a file open box.
1853 *
1854 * @param path path of selected file
1855 * @return the result of the new file open box
329fd62e 1856 * @throws IOException if a java.io operation throws
0d47c546
KL
1857 */
1858 public final String fileOpenBox(final String path) throws IOException {
1859 return getApplication().fileOpenBox(path);
1860 }
1861
a69ed767
KL
1862 /**
1863 * Convenience function to spawn a file save box.
1864 *
1865 * @param path path of selected file
1866 * @return the result of the new file open box
1867 * @throws IOException if a java.io operation throws
1868 */
1869 public final String fileSaveBox(final String path) throws IOException {
1870 return getApplication().fileOpenBox(path, TFileOpenBox.Type.SAVE);
1871 }
1872
0d47c546
KL
1873 /**
1874 * Convenience function to spawn a file open box.
1875 *
1876 * @param path path of selected file
1877 * @param type one of the Type constants
1878 * @return the result of the new file open box
329fd62e 1879 * @throws IOException if a java.io operation throws
0d47c546
KL
1880 */
1881 public final String fileOpenBox(final String path,
1882 final TFileOpenBox.Type type) throws IOException {
1883
1884 return getApplication().fileOpenBox(path, type);
1885 }
a69ed767
KL
1886
1887 /**
1888 * Convenience function to spawn a file open box.
1889 *
1890 * @param path path of selected file
1891 * @param type one of the Type constants
1892 * @param filter a string that files must match to be displayed
1893 * @return the result of the new file open box
1894 * @throws IOException of a java.io operation throws
1895 */
1896 public final String fileOpenBox(final String path,
1897 final TFileOpenBox.Type type, final String filter) throws IOException {
1898
1899 ArrayList<String> filters = new ArrayList<String>();
1900 filters.add(filter);
1901
1902 return getApplication().fileOpenBox(path, type, filters);
1903 }
1904
1905 /**
1906 * Convenience function to spawn a file open box.
1907 *
1908 * @param path path of selected file
1909 * @param type one of the Type constants
1910 * @param filters a list of strings that files must match to be displayed
1911 * @return the result of the new file open box
1912 * @throws IOException of a java.io operation throws
1913 */
1914 public final String fileOpenBox(final String path,
1915 final TFileOpenBox.Type type,
1916 final List<String> filters) throws IOException {
1917
1918 return getApplication().fileOpenBox(path, type, filters);
1919 }
1920
0d47c546
KL
1921 /**
1922 * Convenience function to add a directory list to this container/window.
1923 *
1924 * @param path directory path, must be a directory
1925 * @param x column relative to parent
1926 * @param y row relative to parent
1927 * @param width width of text area
1928 * @param height height of text area
329fd62e 1929 * @return the new directory list
0d47c546
KL
1930 */
1931 public final TDirectoryList addDirectoryList(final String path, final int x,
1932 final int y, final int width, final int height) {
1933
1934 return new TDirectoryList(this, path, x, y, width, height, null);
1935 }
1936
1937 /**
1938 * Convenience function to add a directory list to this container/window.
1939 *
1940 * @param path directory path, must be a directory
1941 * @param x column relative to parent
1942 * @param y row relative to parent
1943 * @param width width of text area
1944 * @param height height of text area
a69ed767
KL
1945 * @param action action to perform when an item is selected (enter or
1946 * double-click)
329fd62e 1947 * @return the new directory list
0d47c546
KL
1948 */
1949 public final TDirectoryList addDirectoryList(final String path, final int x,
1950 final int y, final int width, final int height, final TAction action) {
1951
1952 return new TDirectoryList(this, path, x, y, width, height, action);
1953 }
7668cb45 1954
3649b921
KL
1955 /**
1956 * Convenience function to add a directory list to this container/window.
1957 *
a69ed767
KL
1958 * @param path directory path, must be a directory
1959 * @param x column relative to parent
1960 * @param y row relative to parent
1961 * @param width width of text area
1962 * @param height height of text area
1963 * @param action action to perform when an item is selected (enter or
1964 * double-click)
1965 * @param singleClickAction action to perform when an item is selected
1966 * (single-click)
1967 * @return the new directory list
1968 */
1969 public final TDirectoryList addDirectoryList(final String path, final int x,
1970 final int y, final int width, final int height, final TAction action,
1971 final TAction singleClickAction) {
1972
1973 return new TDirectoryList(this, path, x, y, width, height, action,
1974 singleClickAction);
1975 }
1976
1977 /**
1978 * Convenience function to add a directory list to this container/window.
1979 *
1980 * @param path directory path, must be a directory
1981 * @param x column relative to parent
1982 * @param y row relative to parent
1983 * @param width width of text area
1984 * @param height height of text area
1985 * @param action action to perform when an item is selected (enter or
1986 * double-click)
1987 * @param singleClickAction action to perform when an item is selected
1988 * (single-click)
1989 * @param filters a list of strings that files must match to be displayed
1990 * @return the new directory list
1991 */
1992 public final TDirectoryList addDirectoryList(final String path, final int x,
1993 final int y, final int width, final int height, final TAction action,
1994 final TAction singleClickAction, final List<String> filters) {
1995
1996 return new TDirectoryList(this, path, x, y, width, height, action,
1997 singleClickAction, filters);
1998 }
1999
2000 /**
2001 * Convenience function to add a list to this container/window.
2002 *
3649b921
KL
2003 * @param strings list of strings to show
2004 * @param x column relative to parent
2005 * @param y row relative to parent
2006 * @param width width of text area
2007 * @param height height of text area
2008 * @return the new directory list
2009 */
2010 public final TList addList(final List<String> strings, final int x,
2011 final int y, final int width, final int height) {
2012
2013 return new TList(this, strings, x, y, width, height, null);
2014 }
2015
2016 /**
a69ed767 2017 * Convenience function to add a list to this container/window.
3649b921
KL
2018 *
2019 * @param strings list of strings to show
2020 * @param x column relative to parent
2021 * @param y row relative to parent
2022 * @param width width of text area
2023 * @param height height of text area
2024 * @param enterAction action to perform when an item is selected
2025 * @return the new directory list
2026 */
2027 public final TList addList(final List<String> strings, final int x,
2028 final int y, final int width, final int height,
2029 final TAction enterAction) {
2030
2031 return new TList(this, strings, x, y, width, height, enterAction);
2032 }
2033
2034 /**
a69ed767 2035 * Convenience function to add a list to this container/window.
3649b921
KL
2036 *
2037 * @param strings list of strings to show
2038 * @param x column relative to parent
2039 * @param y row relative to parent
2040 * @param width width of text area
2041 * @param height height of text area
2042 * @param enterAction action to perform when an item is selected
2043 * @param moveAction action to perform when the user navigates to a new
2044 * item with arrow/page keys
2045 * @return the new directory list
2046 */
2047 public final TList addList(final List<String> strings, final int x,
2048 final int y, final int width, final int height,
2049 final TAction enterAction, final TAction moveAction) {
2050
2051 return new TList(this, strings, x, y, width, height, enterAction,
2052 moveAction);
2053 }
2054
48e27807 2055}