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