More PMD warnings
[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 *
a2018e99 6 * Copyright (C) 2017 Kevin Lamonte
48e27807 7 *
e16dda65
KL
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
48e27807 14 *
e16dda65
KL
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
48e27807 17 *
e16dda65
KL
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
48e27807
KL
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29package jexer;
30
0d47c546 31import java.io.IOException;
48e27807 32import java.util.List;
2ce6dab2 33import java.util.ArrayList;
48e27807 34
42873e30 35import jexer.backend.Screen;
928811d8 36import jexer.bits.ColorTheme;
48e27807
KL
37import jexer.event.TCommandEvent;
38import jexer.event.TInputEvent;
39import jexer.event.TKeypressEvent;
40import jexer.event.TMenuEvent;
41import jexer.event.TMouseEvent;
42import jexer.event.TResizeEvent;
928811d8 43import jexer.menu.TMenu;
d36057df
KL
44import jexer.ttree.TTreeItem;
45import jexer.ttree.TTreeView;
46import jexer.ttree.TTreeViewWidget;
48e27807
KL
47import static jexer.TKeypress.*;
48
49/**
50 * TWidget is the base class of all objects that can be drawn on screen or
51 * handle user input events.
52 */
2b9c27db 53public abstract class TWidget implements Comparable<TWidget> {
48e27807 54
2ce6dab2 55 // ------------------------------------------------------------------------
d36057df 56 // Variables --------------------------------------------------------------
2ce6dab2
KL
57 // ------------------------------------------------------------------------
58
48e27807
KL
59 /**
60 * Every widget has a parent widget that it may be "contained" in. For
61 * example, a TWindow might contain several TTextFields, or a TComboBox
62 * may contain a TScrollBar.
63 */
fca67db0
KL
64 private TWidget parent = null;
65
48e27807
KL
66 /**
67 * Child widgets that this widget contains.
68 */
69 private List<TWidget> children;
70
71 /**
72 * The currently active child widget that will receive keypress events.
73 */
74 private TWidget activeChild = null;
75
76 /**
77 * If true, this widget will receive events.
78 */
fca67db0
KL
79 private boolean active = false;
80
48e27807
KL
81 /**
82 * The window that this widget draws to.
83 */
fca67db0 84 private TWindow window = null;
48e27807
KL
85
86 /**
87 * Absolute X position of the top-left corner.
88 */
fca67db0
KL
89 private int x = 0;
90
91 /**
d36057df 92 * Absolute Y position of the top-left corner.
fca67db0 93 */
d36057df 94 private int y = 0;
fca67db0
KL
95
96 /**
d36057df 97 * Width.
fca67db0 98 */
d36057df 99 private int width = 0;
48e27807
KL
100
101 /**
d36057df 102 * Height.
48e27807 103 */
d36057df 104 private int height = 0;
fca67db0
KL
105
106 /**
d36057df 107 * My tab order inside a window or containing widget.
fca67db0 108 */
d36057df 109 private int tabOrder = 0;
fca67db0
KL
110
111 /**
d36057df 112 * If true, this widget can be tabbed to or receive events.
fca67db0 113 */
d36057df 114 private boolean enabled = true;
48e27807
KL
115
116 /**
d36057df 117 * If true, this widget has a cursor.
48e27807 118 */
d36057df 119 private boolean cursorVisible = false;
fca67db0
KL
120
121 /**
d36057df 122 * Cursor column position in relative coordinates.
fca67db0 123 */
d36057df 124 private int cursorX = 0;
fca67db0
KL
125
126 /**
d36057df 127 * Cursor row position in relative coordinates.
fca67db0 128 */
d36057df 129 private int cursorY = 0;
48e27807 130
d36057df
KL
131 // ------------------------------------------------------------------------
132 // Constructors -----------------------------------------------------------
133 // ------------------------------------------------------------------------
fca67db0
KL
134
135 /**
d36057df 136 * Default constructor for subclasses.
fca67db0 137 */
d36057df
KL
138 protected TWidget() {
139 children = new ArrayList<TWidget>();
fca67db0
KL
140 }
141
142 /**
d36057df 143 * Protected constructor.
fca67db0 144 *
d36057df 145 * @param parent parent widget
fca67db0 146 */
d36057df
KL
147 protected TWidget(final TWidget parent) {
148 this(parent, true);
fca67db0 149 }
48e27807 150
0ee88b6d 151 /**
d36057df 152 * Protected constructor.
0ee88b6d 153 *
d36057df
KL
154 * @param parent parent widget
155 * @param x column relative to parent
156 * @param y row relative to parent
157 * @param width width of widget
158 * @param height height of widget
0ee88b6d 159 */
d36057df
KL
160 protected TWidget(final TWidget parent, final int x, final int y,
161 final int width, final int height) {
0ee88b6d 162
d36057df 163 this(parent, true, x, y, width, height);
0ee88b6d
KL
164 }
165
48e27807 166 /**
d36057df 167 * Protected constructor used by subclasses that are disabled by default.
48e27807 168 *
d36057df
KL
169 * @param parent parent widget
170 * @param enabled if true assume enabled
48e27807 171 */
d36057df
KL
172 protected TWidget(final TWidget parent, final boolean enabled) {
173 this.enabled = enabled;
174 this.parent = parent;
175 this.window = parent.window;
176 children = new ArrayList<TWidget>();
177
178 // Do not add TStatusBars, they are drawn by TApplication
179 if (this instanceof TStatusBar) {
180 } else {
181 parent.addChild(this);
182 }
48e27807
KL
183 }
184
185 /**
d36057df 186 * Protected constructor used by subclasses that are disabled by default.
48e27807 187 *
d36057df
KL
188 * @param parent parent widget
189 * @param enabled if true assume enabled
190 * @param x column relative to parent
191 * @param y row relative to parent
192 * @param width width of widget
193 * @param height height of widget
48e27807 194 */
d36057df
KL
195 protected TWidget(final TWidget parent, final boolean enabled,
196 final int x, final int y, final int width, final int height) {
197
48e27807 198 this.enabled = enabled;
d36057df
KL
199 this.parent = parent;
200 this.window = parent.window;
201 children = new ArrayList<TWidget>();
202
203 // Do not add TStatusBars, they are drawn by TApplication
204 if (this instanceof TStatusBar) {
205 } else {
206 parent.addChild(this);
48e27807 207 }
48e27807 208
d36057df
KL
209 this.x = x;
210 this.y = y;
211 this.width = width;
212 this.height = height;
213 }
48e27807 214
7272e49f 215 /**
d36057df 216 * Backdoor access for TWindow's constructor. ONLY TWindow USES THIS.
7272e49f 217 *
d36057df
KL
218 * @param window the top-level window
219 * @param x column relative to parent
220 * @param y row relative to parent
221 * @param width width of window
222 * @param height height of window
7272e49f 223 */
d36057df
KL
224 protected final void setupForTWindow(final TWindow window,
225 final int x, final int y, final int width, final int height) {
226
227 this.parent = window;
228 this.window = window;
229 this.x = x;
230 this.y = y;
231 this.width = width;
232 this.height = height;
7272e49f
KL
233 }
234
d36057df
KL
235 // ------------------------------------------------------------------------
236 // Event handlers ---------------------------------------------------------
237 // ------------------------------------------------------------------------
238
a06459bd 239 /**
d36057df
KL
240 * Check if a mouse press/release event coordinate is contained in this
241 * widget.
a06459bd 242 *
d36057df
KL
243 * @param mouse a mouse-based event
244 * @return whether or not a mouse click would be sent to this widget
a06459bd 245 */
d36057df
KL
246 public final boolean mouseWouldHit(final TMouseEvent mouse) {
247
248 if (!enabled) {
24489803
KL
249 return false;
250 }
251
d36057df
KL
252 if ((this instanceof TTreeItem)
253 && ((y < 0) || (y > parent.getHeight() - 1))
24489803
KL
254 ) {
255 return false;
256 }
a06459bd 257
d36057df
KL
258 if ((mouse.getAbsoluteX() >= getAbsoluteX())
259 && (mouse.getAbsoluteX() < getAbsoluteX() + width)
260 && (mouse.getAbsoluteY() >= getAbsoluteY())
261 && (mouse.getAbsoluteY() < getAbsoluteY() + height)
262 ) {
263 return true;
264 }
265 return false;
266 }
48e27807 267
7272e49f 268 /**
d36057df 269 * Method that subclasses can override to handle keystrokes.
7272e49f 270 *
d36057df 271 * @param keypress keystroke event
7272e49f 272 */
d36057df
KL
273 public void onKeypress(final TKeypressEvent keypress) {
274
275 if ((children.size() == 0)
276 || (this instanceof TTreeView)
277 || (this instanceof TText)
278 ) {
279
280 // Defaults:
281 // tab / shift-tab - switch to next/previous widget
282 // left-arrow or up-arrow: same as shift-tab
283 if ((keypress.equals(kbTab))
284 || (keypress.equals(kbDown))
285 ) {
286 parent.switchWidget(true);
287 return;
288 } else if ((keypress.equals(kbShiftTab))
289 || (keypress.equals(kbBackTab))
290 || (keypress.equals(kbUp))
291 ) {
292 parent.switchWidget(false);
293 return;
294 }
295 }
296
297 if ((children.size() == 0)
298 && !(this instanceof TTreeView)
299 ) {
300
301 // Defaults:
302 // right-arrow or down-arrow: same as tab
303 if (keypress.equals(kbRight)) {
304 parent.switchWidget(true);
305 return;
306 } else if (keypress.equals(kbLeft)) {
307 parent.switchWidget(false);
308 return;
309 }
310 }
311
312 // If I have any buttons on me AND this is an Alt-key that matches
313 // its mnemonic, send it an Enter keystroke
314 for (TWidget widget: children) {
315 if (widget instanceof TButton) {
316 TButton button = (TButton) widget;
317 if (button.isEnabled()
318 && !keypress.getKey().isFnKey()
319 && keypress.getKey().isAlt()
320 && !keypress.getKey().isCtrl()
321 && (Character.toLowerCase(button.getMnemonic().getShortcut())
322 == Character.toLowerCase(keypress.getKey().getChar()))
323 ) {
324
325 widget.onKeypress(new TKeypressEvent(kbEnter));
326 return;
327 }
328 }
329 }
330
331 // Dispatch the keypress to an active widget
332 for (TWidget widget: children) {
333 if (widget.active) {
334 widget.onKeypress(keypress);
335 return;
336 }
337 }
7272e49f
KL
338 }
339
340 /**
d36057df 341 * Method that subclasses can override to handle mouse button presses.
7272e49f 342 *
d36057df 343 * @param mouse mouse button event
7272e49f 344 */
d36057df
KL
345 public void onMouseDown(final TMouseEvent mouse) {
346 // Default: do nothing, pass to children instead
347 for (int i = children.size() - 1 ; i >= 0 ; i--) {
348 TWidget widget = children.get(i);
349 if (widget.mouseWouldHit(mouse)) {
350 // Dispatch to this child, also activate it
351 activate(widget);
7272e49f 352
d36057df
KL
353 // Set x and y relative to the child's coordinates
354 mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX());
355 mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY());
356 widget.onMouseDown(mouse);
357 return;
358 }
359 }
360 }
48e27807 361
7272e49f 362 /**
d36057df 363 * Method that subclasses can override to handle mouse button releases.
7272e49f 364 *
d36057df 365 * @param mouse mouse button event
7272e49f 366 */
d36057df
KL
367 public void onMouseUp(final TMouseEvent mouse) {
368 // Default: do nothing, pass to children instead
369 for (int i = children.size() - 1 ; i >= 0 ; i--) {
370 TWidget widget = children.get(i);
371 if (widget.mouseWouldHit(mouse)) {
372 // Dispatch to this child, also activate it
373 activate(widget);
374
375 // Set x and y relative to the child's coordinates
376 mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX());
377 mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY());
378 widget.onMouseUp(mouse);
379 return;
380 }
381 }
7272e49f
KL
382 }
383
384 /**
d36057df 385 * Method that subclasses can override to handle mouse movements.
7272e49f 386 *
d36057df 387 * @param mouse mouse motion event
7272e49f 388 */
d36057df
KL
389 public void onMouseMotion(final TMouseEvent mouse) {
390 // Default: do nothing, pass it on to ALL of my children. This way
391 // the children can see the mouse "leaving" their area.
392 for (TWidget widget: children) {
393 // Set x and y relative to the child's coordinates
394 mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX());
395 mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY());
396 widget.onMouseMotion(mouse);
397 }
7272e49f
KL
398 }
399
2ce6dab2 400 /**
d36057df
KL
401 * Method that subclasses can override to handle mouse button
402 * double-clicks.
2ce6dab2 403 *
d36057df 404 * @param mouse mouse button event
2ce6dab2 405 */
d36057df
KL
406 public void onMouseDoubleClick(final TMouseEvent mouse) {
407 // Default: do nothing, pass to children instead
408 for (int i = children.size() - 1 ; i >= 0 ; i--) {
409 TWidget widget = children.get(i);
410 if (widget.mouseWouldHit(mouse)) {
411 // Dispatch to this child, also activate it
412 activate(widget);
413
414 // Set x and y relative to the child's coordinates
415 mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX());
416 mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY());
417 widget.onMouseDoubleClick(mouse);
418 return;
419 }
420 }
2ce6dab2
KL
421 }
422
423 /**
d36057df
KL
424 * Method that subclasses can override to handle window/screen resize
425 * events.
2ce6dab2 426 *
d36057df 427 * @param resize resize event
2ce6dab2 428 */
d36057df
KL
429 public void onResize(final TResizeEvent resize) {
430 // Default: change my width/height.
431 if (resize.getType() == TResizeEvent.Type.WIDGET) {
432 width = resize.getWidth();
433 height = resize.getHeight();
434 } else {
435 // Let children see the screen resize
436 for (TWidget widget: children) {
437 widget.onResize(resize);
438 }
439 }
2ce6dab2
KL
440 }
441
48e27807 442 /**
d36057df 443 * Method that subclasses can override to handle posted command events.
7668cb45 444 *
d36057df 445 * @param command command event
2b9c27db 446 */
d36057df
KL
447 public void onCommand(final TCommandEvent command) {
448 // Default: do nothing, pass to children instead
449 for (TWidget widget: children) {
450 widget.onCommand(command);
7668cb45 451 }
48e27807
KL
452 }
453
454 /**
d36057df
KL
455 * Method that subclasses can override to handle menu or posted menu
456 * events.
48e27807 457 *
d36057df 458 * @param menu menu event
48e27807 459 */
d36057df
KL
460 public void onMenu(final TMenuEvent menu) {
461 // Default: do nothing, pass to children instead
462 for (TWidget widget: children) {
463 widget.onMenu(menu);
48e27807 464 }
48e27807
KL
465 }
466
467 /**
d36057df
KL
468 * Method that subclasses can override to do processing when the UI is
469 * idle. Note that repainting is NOT assumed. To get a refresh after
470 * onIdle, call doRepaint().
48e27807 471 */
d36057df
KL
472 public void onIdle() {
473 // Default: do nothing, pass to children instead
474 for (TWidget widget: children) {
475 widget.onIdle();
476 }
48e27807
KL
477 }
478
479 /**
d36057df
KL
480 * Consume event. Subclasses that want to intercept all events in one go
481 * can override this method.
48e27807 482 *
d36057df 483 * @param event keyboard, mouse, resize, command, or menu event
48e27807 484 */
d36057df
KL
485 public void handleEvent(final TInputEvent event) {
486 /*
487 System.err.printf("TWidget (%s) event: %s\n", this.getClass().getName(),
488 event);
489 */
490
491 if (!enabled) {
492 // Discard event
493 // System.err.println(" -- discard --");
494 return;
495 }
496
497 if (event instanceof TKeypressEvent) {
498 onKeypress((TKeypressEvent) event);
499 } else if (event instanceof TMouseEvent) {
500
501 TMouseEvent mouse = (TMouseEvent) event;
502
503 switch (mouse.getType()) {
504
505 case MOUSE_DOWN:
506 onMouseDown(mouse);
507 break;
508
509 case MOUSE_UP:
510 onMouseUp(mouse);
511 break;
512
513 case MOUSE_MOTION:
514 onMouseMotion(mouse);
515 break;
516
517 case MOUSE_DOUBLE_CLICK:
518 onMouseDoubleClick(mouse);
519 break;
520
521 default:
522 throw new IllegalArgumentException("Invalid mouse event type: "
523 + mouse.getType());
524 }
525 } else if (event instanceof TResizeEvent) {
526 onResize((TResizeEvent) event);
527 } else if (event instanceof TCommandEvent) {
528 onCommand((TCommandEvent) event);
529 } else if (event instanceof TMenuEvent) {
530 onMenu((TMenuEvent) event);
531 }
532
533 // Do nothing else
534 return;
48e27807
KL
535 }
536
d36057df
KL
537 // ------------------------------------------------------------------------
538 // TWidget ----------------------------------------------------------------
539 // ------------------------------------------------------------------------
540
48e27807 541 /**
d36057df 542 * Get parent widget.
48e27807 543 *
d36057df 544 * @return parent widget
48e27807 545 */
d36057df
KL
546 public final TWidget getParent() {
547 return parent;
48e27807
KL
548 }
549
550 /**
d36057df 551 * Get the list of child widgets that this widget contains.
48e27807 552 *
d36057df 553 * @return the list of child widgets
48e27807 554 */
d36057df
KL
555 public List<TWidget> getChildren() {
556 return children;
48e27807
KL
557 }
558
928811d8 559 /**
d36057df 560 * Get active flag.
928811d8 561 *
d36057df 562 * @return if true, this widget will receive events
928811d8 563 */
d36057df
KL
564 public final boolean isActive() {
565 return active;
928811d8
KL
566 }
567
48e27807 568 /**
d36057df
KL
569 * Set active flag.
570 *
571 * @param active if true, this widget will receive events
48e27807 572 */
d36057df
KL
573 public final void setActive(final boolean active) {
574 this.active = active;
48e27807
KL
575 }
576
577 /**
d36057df
KL
578 * Get the window this widget is on.
579 *
580 * @return the window
48e27807 581 */
d36057df
KL
582 public final TWindow getWindow() {
583 return window;
48e27807
KL
584 }
585
be72cb5c 586 /**
d36057df
KL
587 * Get X position.
588 *
589 * @return absolute X position of the top-left corner
be72cb5c 590 */
d36057df
KL
591 public final int getX() {
592 return x;
be72cb5c
KL
593 }
594
48e27807 595 /**
d36057df
KL
596 * Set X position.
597 *
598 * @param x absolute X position of the top-left corner
48e27807 599 */
d36057df
KL
600 public final void setX(final int x) {
601 this.x = x;
48e27807
KL
602 }
603
604 /**
d36057df 605 * Get Y position.
48e27807 606 *
d36057df 607 * @return absolute Y position of the top-left corner
48e27807 608 */
d36057df
KL
609 public final int getY() {
610 return y;
30d336cc
KL
611 }
612
a83fea2b 613 /**
d36057df 614 * Set Y position.
a83fea2b 615 *
d36057df 616 * @param y absolute Y position of the top-left corner
a83fea2b 617 */
d36057df
KL
618 public final void setY(final int y) {
619 this.y = y;
a83fea2b
KL
620 }
621
30d336cc 622 /**
d36057df 623 * Get the width.
30d336cc 624 *
d36057df 625 * @return widget width
30d336cc 626 */
d36057df
KL
627 public final int getWidth() {
628 return this.width;
48e27807
KL
629 }
630
a83fea2b 631 /**
d36057df 632 * Change the width.
a83fea2b 633 *
d36057df 634 * @param width new widget width
a83fea2b 635 */
d36057df 636 public final void setWidth(final int width) {
a83fea2b 637 this.width = width;
a83fea2b
KL
638 }
639
2ce6dab2 640 /**
d36057df 641 * Get the height.
2ce6dab2 642 *
d36057df 643 * @return widget height
2ce6dab2 644 */
d36057df
KL
645 public final int getHeight() {
646 return this.height;
647 }
2ce6dab2 648
d36057df
KL
649 /**
650 * Change the height.
651 *
652 * @param height new widget height
653 */
654 public final void setHeight(final int height) {
2ce6dab2
KL
655 this.height = height;
656 }
657
48e27807 658 /**
d36057df 659 * Change the dimensions.
48e27807 660 *
d36057df
KL
661 * @param x absolute X position of the top-left corner
662 * @param y absolute Y position of the top-left corner
663 * @param width new widget width
664 * @param height new widget height
48e27807 665 */
d36057df
KL
666 public final void setDimensions(final int x, final int y, final int width,
667 final int height) {
48e27807 668
d36057df
KL
669 setX(x);
670 setY(y);
671 setWidth(width);
672 setHeight(height);
48e27807
KL
673 }
674
675 /**
d36057df 676 * Get enabled flag.
48e27807 677 *
d36057df 678 * @return if true, this widget can be tabbed to or receive events
48e27807 679 */
d36057df
KL
680 public final boolean isEnabled() {
681 return enabled;
682 }
48e27807 683
d36057df
KL
684 /**
685 * Set enabled flag.
686 *
687 * @param enabled if true, this widget can be tabbed to or receive events
688 */
689 public final void setEnabled(final boolean enabled) {
690 this.enabled = enabled;
691 if (!enabled) {
692 active = false;
693 // See if there are any active siblings to switch to
694 boolean foundSibling = false;
695 if (parent != null) {
696 for (TWidget w: parent.children) {
697 if ((w.enabled)
698 && !(this instanceof THScroller)
699 && !(this instanceof TVScroller)
700 ) {
701 parent.activate(w);
702 foundSibling = true;
703 break;
704 }
705 }
706 if (!foundSibling) {
707 parent.activeChild = null;
708 }
48e27807 709 }
48e27807
KL
710 }
711 }
712
713 /**
d36057df 714 * Set visible cursor flag.
48e27807 715 *
d36057df 716 * @param cursorVisible if true, this widget has a cursor
48e27807 717 */
d36057df
KL
718 public final void setCursorVisible(final boolean cursorVisible) {
719 this.cursorVisible = cursorVisible;
48e27807
KL
720 }
721
722 /**
d36057df 723 * See if this widget has a visible cursor.
48e27807 724 *
d36057df 725 * @return if true, this widget has a visible cursor
48e27807 726 */
d36057df
KL
727 public final boolean isCursorVisible() {
728 // If cursor is out of my bounds, it is not visible.
729 if ((cursorX >= width)
730 || (cursorX < 0)
731 || (cursorY >= height)
732 || (cursorY < 0)
733 ) {
734 return false;
735 }
48e27807 736
d36057df
KL
737 // If cursor is out of my window's bounds, it is not visible.
738 if ((getCursorAbsoluteX() >= window.getAbsoluteX()
739 + window.getWidth() - 1)
740 || (getCursorAbsoluteX() < 0)
741 || (getCursorAbsoluteY() >= window.getAbsoluteY()
742 + window.getHeight() - 1)
743 || (getCursorAbsoluteY() < 0)
744 ) {
745 return false;
48e27807 746 }
d36057df
KL
747 return cursorVisible;
748 }
48e27807 749
d36057df
KL
750 /**
751 * Get cursor X value.
752 *
753 * @return cursor column position in relative coordinates
754 */
755 public final int getCursorX() {
756 return cursorX;
757 }
48e27807 758
d36057df
KL
759 /**
760 * Set cursor X value.
761 *
762 * @param cursorX column position in relative coordinates
763 */
764 public final void setCursorX(final int cursorX) {
765 this.cursorX = cursorX;
766 }
48e27807 767
d36057df
KL
768 /**
769 * Get cursor Y value.
770 *
771 * @return cursor row position in relative coordinates
772 */
773 public final int getCursorY() {
774 return cursorY;
775 }
48e27807 776
d36057df
KL
777 /**
778 * Set cursor Y value.
779 *
780 * @param cursorY row position in relative coordinates
781 */
782 public final void setCursorY(final int cursorY) {
783 this.cursorY = cursorY;
784 }
48e27807 785
d36057df
KL
786 /**
787 * Get this TWidget's parent TApplication.
788 *
789 * @return the parent TApplication
790 */
791 public TApplication getApplication() {
792 return window.getApplication();
793 }
48e27807 794
d36057df
KL
795 /**
796 * Get the Screen.
797 *
798 * @return the Screen
799 */
800 public Screen getScreen() {
801 return window.getScreen();
48e27807
KL
802 }
803
804 /**
d36057df
KL
805 * Comparison operator. For various subclasses it sorts on:
806 * <ul>
807 * <li>tabOrder for TWidgets</li>
808 * <li>z for TWindows</li>
809 * <li>text for TTreeItems</li>
810 * </ul>
48e27807 811 *
d36057df
KL
812 * @param that another TWidget, TWindow, or TTreeItem instance
813 * @return difference between this.tabOrder and that.tabOrder, or
814 * difference between this.z and that.z, or String.compareTo(text)
48e27807 815 */
d36057df
KL
816 public final int compareTo(final TWidget that) {
817 if ((this instanceof TWindow)
818 && (that instanceof TWindow)
48e27807 819 ) {
d36057df
KL
820 return (((TWindow) this).getZ() - ((TWindow) that).getZ());
821 }
822 if ((this instanceof TTreeItem)
823 && (that instanceof TTreeItem)
824 ) {
825 return (((TTreeItem) this).getText().compareTo(
826 ((TTreeItem) that).getText()));
48e27807 827 }
d36057df
KL
828 return (this.tabOrder - that.tabOrder);
829 }
48e27807 830
d36057df
KL
831 /**
832 * See if this widget should render with the active color.
833 *
834 * @return true if this widget is active and all of its parents are
835 * active.
836 */
837 public final boolean isAbsoluteActive() {
838 if (parent == this) {
839 return active;
48e27807 840 }
d36057df 841 return (active && parent.isAbsoluteActive());
48e27807
KL
842 }
843
d36057df
KL
844 /**
845 * Returns the cursor X position.
846 *
847 * @return absolute screen column number for the cursor's X position
848 */
849 public final int getCursorAbsoluteX() {
850 return getAbsoluteX() + cursorX;
851 }
2ce6dab2
KL
852
853 /**
d36057df 854 * Returns the cursor Y position.
2ce6dab2 855 *
d36057df 856 * @return absolute screen row number for the cursor's Y position
2ce6dab2 857 */
d36057df
KL
858 public final int getCursorAbsoluteY() {
859 return getAbsoluteY() + cursorY;
860 }
2ce6dab2 861
d36057df
KL
862 /**
863 * Compute my absolute X position as the sum of my X plus all my parent's
864 * X's.
865 *
866 * @return absolute screen column number for my X position
867 */
868 public final int getAbsoluteX() {
869 assert (parent != null);
870 if (parent == this) {
871 return x;
2ce6dab2 872 }
d36057df
KL
873 if ((parent instanceof TWindow)
874 && !(parent instanceof TMenu)
875 && !(parent instanceof TDesktop)
876 ) {
877 // Widgets on a TWindow have (0,0) as their top-left, but this is
878 // actually the TWindow's (1,1).
879 return parent.getAbsoluteX() + x + 1;
880 }
881 return parent.getAbsoluteX() + x;
882 }
2ce6dab2 883
d36057df
KL
884 /**
885 * Compute my absolute Y position as the sum of my Y plus all my parent's
886 * Y's.
887 *
888 * @return absolute screen row number for my Y position
889 */
890 public final int getAbsoluteY() {
891 assert (parent != null);
892 if (parent == this) {
893 return y;
894 }
895 if ((parent instanceof TWindow)
896 && !(parent instanceof TMenu)
897 && !(parent instanceof TDesktop)
2ce6dab2 898 ) {
d36057df
KL
899 // Widgets on a TWindow have (0,0) as their top-left, but this is
900 // actually the TWindow's (1,1).
901 return parent.getAbsoluteY() + y + 1;
2ce6dab2 902 }
d36057df 903 return parent.getAbsoluteY() + y;
2ce6dab2
KL
904 }
905
48e27807 906 /**
d36057df 907 * Get the global color theme.
48e27807 908 *
d36057df 909 * @return the ColorTheme
48e27807 910 */
d36057df
KL
911 public final ColorTheme getTheme() {
912 return window.getApplication().getTheme();
913 }
48e27807 914
d36057df
KL
915 /**
916 * Draw my specific widget. When called, the screen rectangle I draw
917 * into is already setup (offset and clipping).
918 */
919 public void draw() {
920 // Default widget draws nothing.
921 }
48e27807 922
d36057df
KL
923 /**
924 * Called by parent to render to TWindow.
925 */
926 public final void drawChildren() {
927 // Set my clipping rectangle
928 assert (window != null);
929 assert (getScreen() != null);
930 Screen screen = getScreen();
931
932 // Special case: TStatusBar is drawn by TApplication, not anything
933 // else.
934 if (this instanceof TStatusBar) {
935 return;
48e27807
KL
936 }
937
d36057df
KL
938 screen.setClipRight(width);
939 screen.setClipBottom(height);
92554d64 940
d36057df
KL
941 int absoluteRightEdge = window.getAbsoluteX() + window.getWidth();
942 int absoluteBottomEdge = window.getAbsoluteY() + window.getHeight();
943 if (!(this instanceof TWindow) && !(this instanceof TVScroller)) {
944 absoluteRightEdge -= 1;
945 }
946 if (!(this instanceof TWindow) && !(this instanceof THScroller)) {
947 absoluteBottomEdge -= 1;
48e27807 948 }
d36057df
KL
949 int myRightEdge = getAbsoluteX() + width;
950 int myBottomEdge = getAbsoluteY() + height;
951 if (getAbsoluteX() > absoluteRightEdge) {
952 // I am offscreen
953 screen.setClipRight(0);
954 } else if (myRightEdge > absoluteRightEdge) {
955 screen.setClipRight(screen.getClipRight()
956 - (myRightEdge - absoluteRightEdge));
957 }
958 if (getAbsoluteY() > absoluteBottomEdge) {
959 // I am offscreen
960 screen.setClipBottom(0);
961 } else if (myBottomEdge > absoluteBottomEdge) {
962 screen.setClipBottom(screen.getClipBottom()
963 - (myBottomEdge - absoluteBottomEdge));
964 }
965
966 // Set my offset
967 screen.setOffsetX(getAbsoluteX());
968 screen.setOffsetY(getAbsoluteY());
48e27807 969
d36057df
KL
970 // Draw me
971 draw();
972
973 // Continue down the chain
48e27807 974 for (TWidget widget: children) {
d36057df 975 widget.drawChildren();
48e27807
KL
976 }
977 }
978
979 /**
d36057df 980 * Repaint the screen on the next update.
48e27807 981 */
d36057df
KL
982 public void doRepaint() {
983 window.getApplication().doRepaint();
48e27807
KL
984 }
985
986 /**
d36057df
KL
987 * Add a child widget to my list of children. We set its tabOrder to 0
988 * and increment the tabOrder of all other children.
48e27807 989 *
d36057df 990 * @param child TWidget to add
48e27807 991 */
d36057df
KL
992 private void addChild(final TWidget child) {
993 children.add(child);
48e27807 994
d36057df
KL
995 if ((child.enabled)
996 && !(child instanceof THScroller)
997 && !(child instanceof TVScroller)
998 ) {
999 for (TWidget widget: children) {
1000 widget.active = false;
48e27807 1001 }
d36057df
KL
1002 child.active = true;
1003 activeChild = child;
48e27807 1004 }
d36057df
KL
1005 for (int i = 0; i < children.size(); i++) {
1006 children.get(i).tabOrder = i;
48e27807
KL
1007 }
1008 }
1009
b6faeac0 1010 /**
d36057df 1011 * Switch the active child.
b6faeac0 1012 *
d36057df 1013 * @param child TWidget to activate
b6faeac0 1014 */
d36057df
KL
1015 public final void activate(final TWidget child) {
1016 assert (child.enabled);
1017 if ((child instanceof THScroller)
1018 || (child instanceof TVScroller)
1019 ) {
1020 return;
b6faeac0 1021 }
b6faeac0 1022
d36057df
KL
1023 if (child != activeChild) {
1024 if (activeChild != null) {
1025 activeChild.active = false;
12b55d76 1026 }
d36057df
KL
1027 child.active = true;
1028 activeChild = child;
48e27807
KL
1029 }
1030 }
1031
1032 /**
d36057df 1033 * Switch the active child.
48e27807 1034 *
d36057df
KL
1035 * @param tabOrder tabOrder of the child to activate. If that child
1036 * isn't enabled, then the next enabled child will be activated.
48e27807 1037 */
d36057df
KL
1038 public final void activate(final int tabOrder) {
1039 if (activeChild == null) {
1040 return;
48e27807 1041 }
d36057df 1042 TWidget child = null;
48e27807 1043 for (TWidget widget: children) {
d36057df
KL
1044 if ((widget.enabled)
1045 && !(widget instanceof THScroller)
1046 && !(widget instanceof TVScroller)
1047 && (widget.tabOrder >= tabOrder)
1048 ) {
1049 child = widget;
1050 break;
1051 }
48e27807 1052 }
d36057df
KL
1053 if ((child != null) && (child != activeChild)) {
1054 activeChild.active = false;
1055 assert (child.enabled);
1056 child.active = true;
1057 activeChild = child;
48e27807
KL
1058 }
1059 }
1060
1061 /**
d36057df 1062 * Switch the active widget with the next in the tab order.
48e27807 1063 *
d36057df
KL
1064 * @param forward if true, then switch to the next enabled widget in the
1065 * list, otherwise switch to the previous enabled widget in the list
48e27807 1066 */
d36057df 1067 public final void switchWidget(final boolean forward) {
48e27807 1068
d36057df
KL
1069 // Only switch if there are multiple enabled widgets
1070 if ((children.size() < 2) || (activeChild == null)) {
48e27807
KL
1071 return;
1072 }
1073
d36057df
KL
1074 int tabOrder = activeChild.tabOrder;
1075 do {
1076 if (forward) {
1077 tabOrder++;
1078 } else {
1079 tabOrder--;
1080 }
1081 if (tabOrder < 0) {
48e27807 1082
d36057df
KL
1083 // If at the end, pass the switch to my parent.
1084 if ((!forward) && (parent != this)) {
1085 parent.switchWidget(forward);
1086 return;
1087 }
48e27807 1088
d36057df
KL
1089 tabOrder = children.size() - 1;
1090 } else if (tabOrder == children.size()) {
1091 // If at the end, pass the switch to my parent.
1092 if ((forward) && (parent != this)) {
1093 parent.switchWidget(forward);
1094 return;
1095 }
48e27807 1096
d36057df
KL
1097 tabOrder = 0;
1098 }
1099 if (activeChild.tabOrder == tabOrder) {
1100 // We wrapped around
48e27807 1101 break;
d36057df
KL
1102 }
1103 } while ((!children.get(tabOrder).enabled)
1104 && !(children.get(tabOrder) instanceof THScroller)
1105 && !(children.get(tabOrder) instanceof TVScroller));
48e27807 1106
d36057df 1107 assert (children.get(tabOrder).enabled);
48e27807 1108
d36057df
KL
1109 activeChild.active = false;
1110 children.get(tabOrder).active = true;
1111 activeChild = children.get(tabOrder);
1112 }
48e27807 1113
d36057df
KL
1114 /**
1115 * Returns my active widget.
1116 *
1117 * @return widget that is active, or this if no children
1118 */
1119 public TWidget getActiveChild() {
1120 if ((this instanceof THScroller)
1121 || (this instanceof TVScroller)
1122 ) {
1123 return parent;
1124 }
b6faeac0 1125
d36057df
KL
1126 for (TWidget widget: children) {
1127 if (widget.active) {
1128 return widget.getActiveChild();
48e27807 1129 }
48e27807 1130 }
d36057df
KL
1131 // No active children, return me
1132 return this;
48e27807
KL
1133 }
1134
2ce6dab2
KL
1135 // ------------------------------------------------------------------------
1136 // Other TWidget constructors ---------------------------------------------
1137 // ------------------------------------------------------------------------
48e27807 1138
30d336cc
KL
1139 /**
1140 * Convenience function to add a label to this container/window.
1141 *
1142 * @param text label
1143 * @param x column relative to parent
1144 * @param y row relative to parent
1145 * @return the new label
1146 */
1147 public final TLabel addLabel(final String text, final int x, final int y) {
1148 return addLabel(text, x, y, "tlabel");
1149 }
1150
1151 /**
1152 * Convenience function to add a label to this container/window.
1153 *
1154 * @param text label
1155 * @param x column relative to parent
1156 * @param y row relative to parent
1157 * @param colorKey ColorTheme key color to use for foreground text.
1158 * Default is "tlabel"
1159 * @return the new label
1160 */
1161 public final TLabel addLabel(final String text, final int x, final int y,
1162 final String colorKey) {
1163
1164 return new TLabel(this, text, x, y, colorKey);
1165 }
1166
1167 /**
1168 * Convenience function to add a button to this container/window.
1169 *
1170 * @param text label on the button
1171 * @param x column relative to parent
1172 * @param y row relative to parent
1173 * @param action to call when button is pressed
1174 * @return the new button
1175 */
1176 public final TButton addButton(final String text, final int x, final int y,
1177 final TAction action) {
1178
1179 return new TButton(this, text, x, y, action);
1180 }
1181
7272e49f
KL
1182 /**
1183 * Convenience function to add a checkbox to this container/window.
1184 *
1185 * @param x column relative to parent
1186 * @param y row relative to parent
1187 * @param label label to display next to (right of) the checkbox
1188 * @param checked initial check state
1189 * @return the new checkbox
1190 */
1191 public final TCheckbox addCheckbox(final int x, final int y,
1192 final String label, final boolean checked) {
1193
1194 return new TCheckbox(this, x, y, label, checked);
1195 }
30d336cc 1196
d502a0e9
KL
1197 /**
1198 * Convenience function to add a progress bar to this container/window.
1199 *
1200 * @param x column relative to parent
1201 * @param y row relative to parent
1202 * @param width width of progress bar
1203 * @param value initial value of percent complete
00d2622b 1204 * @return the new progress bar
d502a0e9
KL
1205 */
1206 public final TProgressBar addProgressBar(final int x, final int y,
1207 final int width, final int value) {
1208
1209 return new TProgressBar(this, x, y, width, value);
1210 }
1211
00d2622b
KL
1212 /**
1213 * Convenience function to add a radio button group to this
1214 * container/window.
1215 *
1216 * @param x column relative to parent
1217 * @param y row relative to parent
1218 * @param label label to display on the group box
1219 * @return the new radio button group
1220 */
1221 public final TRadioGroup addRadioGroup(final int x, final int y,
1222 final String label) {
1223
1224 return new TRadioGroup(this, x, y, label);
1225 }
1226
128e5be1
KL
1227 /**
1228 * Convenience function to add a text field to this container/window.
1229 *
1230 * @param x column relative to parent
1231 * @param y row relative to parent
1232 * @param width visible text width
1233 * @param fixed if true, the text cannot exceed the display width
1234 * @return the new text field
1235 */
1236 public final TField addField(final int x, final int y,
1237 final int width, final boolean fixed) {
1238
1239 return new TField(this, x, y, width, fixed);
1240 }
1241
1242 /**
1243 * Convenience function to add a text field to this container/window.
1244 *
1245 * @param x column relative to parent
1246 * @param y row relative to parent
1247 * @param width visible text width
1248 * @param fixed if true, the text cannot exceed the display width
1249 * @param text initial text, default is empty string
1250 * @return the new text field
1251 */
1252 public final TField addField(final int x, final int y,
1253 final int width, final boolean fixed, final String text) {
1254
1255 return new TField(this, x, y, width, fixed, text);
1256 }
1257
1258 /**
1259 * Convenience function to add a text field to this container/window.
1260 *
1261 * @param x column relative to parent
1262 * @param y row relative to parent
1263 * @param width visible text width
1264 * @param fixed if true, the text cannot exceed the display width
1265 * @param text initial text, default is empty string
1266 * @param enterAction function to call when enter key is pressed
1267 * @param updateAction function to call when the text is updated
1268 * @return the new text field
1269 */
1270 public final TField addField(final int x, final int y,
1271 final int width, final boolean fixed, final String text,
1272 final TAction enterAction, final TAction updateAction) {
1273
1274 return new TField(this, x, y, width, fixed, text, enterAction,
1275 updateAction);
1276 }
00d2622b 1277
cc99cba8
KL
1278 /**
1279 * Convenience function to add a scrollable text box to this
1280 * container/window.
1281 *
1282 * @param text text on the screen
1283 * @param x column relative to parent
1284 * @param y row relative to parent
1285 * @param width width of text area
1286 * @param height height of text area
1287 * @param colorKey ColorTheme key color to use for foreground text
1288 * @return the new text box
1289 */
c6940ed9 1290 public final TText addText(final String text, final int x,
cc99cba8
KL
1291 final int y, final int width, final int height, final String colorKey) {
1292
1293 return new TText(this, text, x, y, width, height, colorKey);
1294 }
1295
1296 /**
1297 * Convenience function to add a scrollable text box to this
1298 * container/window.
1299 *
1300 * @param text text on the screen
1301 * @param x column relative to parent
1302 * @param y row relative to parent
1303 * @param width width of text area
1304 * @param height height of text area
1305 * @return the new text box
1306 */
c6940ed9 1307 public final TText addText(final String text, final int x, final int y,
cc99cba8
KL
1308 final int width, final int height) {
1309
1310 return new TText(this, text, x, y, width, height, "ttext");
1311 }
1312
12b55d76
KL
1313 /**
1314 * Convenience function to add an editable text area box to this
1315 * container/window.
1316 *
1317 * @param text text on the screen
1318 * @param x column relative to parent
1319 * @param y row relative to parent
1320 * @param width width of text area
1321 * @param height height of text area
1322 * @return the new text box
1323 */
1324 public final TEditorWidget addEditor(final String text, final int x,
1325 final int y, final int width, final int height) {
1326
1327 return new TEditorWidget(this, text, x, y, width, height);
1328 }
1329
c6940ed9
KL
1330 /**
1331 * Convenience function to spawn a message box.
1332 *
1333 * @param title window title, will be centered along the top border
1334 * @param caption message to display. Use embedded newlines to get a
1335 * multi-line box.
1336 * @return the new message box
1337 */
1338 public final TMessageBox messageBox(final String title,
1339 final String caption) {
1340
1341 return getApplication().messageBox(title, caption, TMessageBox.Type.OK);
1342 }
1343
1344 /**
1345 * Convenience function to spawn a message box.
1346 *
1347 * @param title window title, will be centered along the top border
1348 * @param caption message to display. Use embedded newlines to get a
1349 * multi-line box.
1350 * @param type one of the TMessageBox.Type constants. Default is
1351 * Type.OK.
1352 * @return the new message box
1353 */
1354 public final TMessageBox messageBox(final String title,
1355 final String caption, final TMessageBox.Type type) {
1356
1357 return getApplication().messageBox(title, caption, type);
1358 }
1359
1360 /**
1361 * Convenience function to spawn an input box.
1362 *
1363 * @param title window title, will be centered along the top border
1364 * @param caption message to display. Use embedded newlines to get a
1365 * multi-line box.
1366 * @return the new input box
1367 */
1368 public final TInputBox inputBox(final String title, final String caption) {
1369
1370 return getApplication().inputBox(title, caption);
1371 }
1372
1373 /**
1374 * Convenience function to spawn an input box.
1375 *
1376 * @param title window title, will be centered along the top border
1377 * @param caption message to display. Use embedded newlines to get a
1378 * multi-line box.
1379 * @param text initial text to seed the field with
1380 * @return the new input box
1381 */
1382 public final TInputBox inputBox(final String title, final String caption,
1383 final String text) {
1384
1385 return getApplication().inputBox(title, caption, text);
1386 }
cc99cba8 1387
87a17f3c
KL
1388 /**
1389 * Convenience function to add a password text field to this
1390 * container/window.
1391 *
1392 * @param x column relative to parent
1393 * @param y row relative to parent
1394 * @param width visible text width
1395 * @param fixed if true, the text cannot exceed the display width
1396 * @return the new text field
1397 */
1398 public final TPasswordField addPasswordField(final int x, final int y,
1399 final int width, final boolean fixed) {
1400
1401 return new TPasswordField(this, x, y, width, fixed);
1402 }
1403
1404 /**
1405 * Convenience function to add a password text field to this
1406 * container/window.
1407 *
1408 * @param x column relative to parent
1409 * @param y row relative to parent
1410 * @param width visible text width
1411 * @param fixed if true, the text cannot exceed the display width
1412 * @param text initial text, default is empty string
1413 * @return the new text field
1414 */
1415 public final TPasswordField addPasswordField(final int x, final int y,
1416 final int width, final boolean fixed, final String text) {
1417
1418 return new TPasswordField(this, x, y, width, fixed, text);
1419 }
1420
1421 /**
1422 * Convenience function to add a password text field to this
1423 * container/window.
1424 *
1425 * @param x column relative to parent
1426 * @param y row relative to parent
1427 * @param width visible text width
1428 * @param fixed if true, the text cannot exceed the display width
1429 * @param text initial text, default is empty string
1430 * @param enterAction function to call when enter key is pressed
1431 * @param updateAction function to call when the text is updated
1432 * @return the new text field
1433 */
1434 public final TPasswordField addPasswordField(final int x, final int y,
1435 final int width, final boolean fixed, final String text,
1436 final TAction enterAction, final TAction updateAction) {
1437
1438 return new TPasswordField(this, x, y, width, fixed, text, enterAction,
1439 updateAction);
1440 }
1441
7668cb45 1442 /**
d36057df
KL
1443 * Convenience function to add a scrollable tree view to this
1444 * container/window.
7668cb45
KL
1445 *
1446 * @param x column relative to parent
1447 * @param y row relative to parent
1448 * @param width width of tree view
1449 * @param height height of tree view
329fd62e 1450 * @return the new tree view
7668cb45 1451 */
d36057df 1452 public final TTreeViewWidget addTreeViewWidget(final int x, final int y,
7668cb45
KL
1453 final int width, final int height) {
1454
d36057df 1455 return new TTreeViewWidget(this, x, y, width, height);
7668cb45
KL
1456 }
1457
1458 /**
d36057df
KL
1459 * Convenience function to add a scrollable tree view to this
1460 * container/window.
7668cb45
KL
1461 *
1462 * @param x column relative to parent
1463 * @param y row relative to parent
1464 * @param width width of tree view
1465 * @param height height of tree view
1466 * @param action action to perform when an item is selected
329fd62e 1467 * @return the new tree view
7668cb45 1468 */
d36057df 1469 public final TTreeViewWidget addTreeViewWidget(final int x, final int y,
7668cb45
KL
1470 final int width, final int height, final TAction action) {
1471
d36057df 1472 return new TTreeViewWidget(this, x, y, width, height, action);
7668cb45
KL
1473 }
1474
0d47c546
KL
1475 /**
1476 * Convenience function to spawn a file open box.
1477 *
1478 * @param path path of selected file
1479 * @return the result of the new file open box
329fd62e 1480 * @throws IOException if a java.io operation throws
0d47c546
KL
1481 */
1482 public final String fileOpenBox(final String path) throws IOException {
1483 return getApplication().fileOpenBox(path);
1484 }
1485
1486 /**
1487 * Convenience function to spawn a file open box.
1488 *
1489 * @param path path of selected file
1490 * @param type one of the Type constants
1491 * @return the result of the new file open box
329fd62e 1492 * @throws IOException if a java.io operation throws
0d47c546
KL
1493 */
1494 public final String fileOpenBox(final String path,
1495 final TFileOpenBox.Type type) throws IOException {
1496
1497 return getApplication().fileOpenBox(path, type);
1498 }
1499 /**
1500 * Convenience function to add a directory list to this container/window.
1501 *
1502 * @param path directory path, must be a directory
1503 * @param x column relative to parent
1504 * @param y row relative to parent
1505 * @param width width of text area
1506 * @param height height of text area
329fd62e 1507 * @return the new directory list
0d47c546
KL
1508 */
1509 public final TDirectoryList addDirectoryList(final String path, final int x,
1510 final int y, final int width, final int height) {
1511
1512 return new TDirectoryList(this, path, x, y, width, height, null);
1513 }
1514
1515 /**
1516 * Convenience function to add a directory list to this container/window.
1517 *
1518 * @param path directory path, must be a directory
1519 * @param x column relative to parent
1520 * @param y row relative to parent
1521 * @param width width of text area
1522 * @param height height of text area
1523 * @param action action to perform when an item is selected
329fd62e 1524 * @return the new directory list
0d47c546
KL
1525 */
1526 public final TDirectoryList addDirectoryList(final String path, final int x,
1527 final int y, final int width, final int height, final TAction action) {
1528
1529 return new TDirectoryList(this, path, x, y, width, height, action);
1530 }
7668cb45 1531
3649b921
KL
1532 /**
1533 * Convenience function to add a directory list to this container/window.
1534 *
1535 * @param strings list of strings to show
1536 * @param x column relative to parent
1537 * @param y row relative to parent
1538 * @param width width of text area
1539 * @param height height of text area
1540 * @return the new directory list
1541 */
1542 public final TList addList(final List<String> strings, final int x,
1543 final int y, final int width, final int height) {
1544
1545 return new TList(this, strings, x, y, width, height, null);
1546 }
1547
1548 /**
1549 * Convenience function to add a directory list to this container/window.
1550 *
1551 * @param strings list of strings to show
1552 * @param x column relative to parent
1553 * @param y row relative to parent
1554 * @param width width of text area
1555 * @param height height of text area
1556 * @param enterAction action to perform when an item is selected
1557 * @return the new directory list
1558 */
1559 public final TList addList(final List<String> strings, final int x,
1560 final int y, final int width, final int height,
1561 final TAction enterAction) {
1562
1563 return new TList(this, strings, x, y, width, height, enterAction);
1564 }
1565
1566 /**
1567 * Convenience function to add a directory list to this container/window.
1568 *
1569 * @param strings list of strings to show
1570 * @param x column relative to parent
1571 * @param y row relative to parent
1572 * @param width width of text area
1573 * @param height height of text area
1574 * @param enterAction action to perform when an item is selected
1575 * @param moveAction action to perform when the user navigates to a new
1576 * item with arrow/page keys
1577 * @return the new directory list
1578 */
1579 public final TList addList(final List<String> strings, final int x,
1580 final int y, final int width, final int height,
1581 final TAction enterAction, final TAction moveAction) {
1582
1583 return new TList(this, strings, x, y, width, height, enterAction,
1584 moveAction);
1585 }
1586
48e27807 1587}