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