2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2019 Kevin Lamonte
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
31 import java
.awt
.image
.BufferedImage
;
32 import java
.io
.IOException
;
33 import java
.util
.List
;
34 import java
.util
.ArrayList
;
36 import jexer
.backend
.Screen
;
37 import jexer
.bits
.Cell
;
38 import jexer
.bits
.CellAttributes
;
39 import jexer
.bits
.Clipboard
;
40 import jexer
.bits
.ColorTheme
;
41 import jexer
.event
.TCommandEvent
;
42 import jexer
.event
.TInputEvent
;
43 import jexer
.event
.TKeypressEvent
;
44 import jexer
.event
.TMenuEvent
;
45 import jexer
.event
.TMouseEvent
;
46 import jexer
.event
.TResizeEvent
;
47 import jexer
.layout
.LayoutManager
;
48 import jexer
.menu
.TMenu
;
49 import jexer
.ttree
.TTreeItem
;
50 import jexer
.ttree
.TTreeView
;
51 import jexer
.ttree
.TTreeViewWidget
;
52 import static jexer
.TKeypress
.*;
55 * TWidget is the base class of all objects that can be drawn on screen or
56 * handle user input events.
58 public abstract class TWidget
implements Comparable
<TWidget
> {
60 // ------------------------------------------------------------------------
61 // Variables --------------------------------------------------------------
62 // ------------------------------------------------------------------------
65 * Every widget has a parent widget that it may be "contained" in. For
66 * example, a TWindow might contain several TFields, or a TComboBox may
67 * contain a TList that itself contains a TVScroller.
69 private TWidget parent
= null;
72 * Child widgets that this widget contains.
74 private List
<TWidget
> children
;
77 * The currently active child widget that will receive keypress events.
79 private TWidget activeChild
= null;
82 * If true, this widget will receive events.
84 private boolean active
= false;
87 * The window that this widget draws to.
89 private TWindow window
= null;
92 * Absolute X position of the top-left corner.
97 * Absolute Y position of the top-left corner.
104 private int width
= 0;
109 private int height
= 0;
112 * My tab order inside a window or containing widget.
114 private int tabOrder
= 0;
117 * If true, this widget can be tabbed to or receive events.
119 private boolean enabled
= true;
122 * If true, this widget will be rendered.
124 private boolean visible
= true;
127 * If true, this widget has a cursor.
129 private boolean cursorVisible
= false;
132 * Cursor column position in relative coordinates.
134 private int cursorX
= 0;
137 * Cursor row position in relative coordinates.
139 private int cursorY
= 0;
144 private LayoutManager layout
= null;
146 // ------------------------------------------------------------------------
147 // Constructors -----------------------------------------------------------
148 // ------------------------------------------------------------------------
151 * Default constructor for subclasses.
153 protected TWidget() {
154 children
= new ArrayList
<TWidget
>();
158 * Protected constructor.
160 * @param parent parent widget
162 protected TWidget(final TWidget parent
) {
167 * Protected constructor.
169 * @param parent parent widget
170 * @param x column relative to parent
171 * @param y row relative to parent
172 * @param width width of widget
173 * @param height height of widget
175 protected TWidget(final TWidget parent
, final int x
, final int y
,
176 final int width
, final int height
) {
178 this(parent
, true, x
, y
, width
, height
);
182 * Protected constructor used by subclasses that are disabled by default.
184 * @param parent parent widget
185 * @param enabled if true assume enabled
187 protected TWidget(final TWidget parent
, final boolean enabled
) {
188 this(parent
, enabled
, 0, 0, 0, 0);
192 * Protected constructor used by subclasses that are disabled by default.
194 * @param parent parent widget
195 * @param enabled if true assume enabled
196 * @param x column relative to parent
197 * @param y row relative to parent
198 * @param width width of widget
199 * @param height height of widget
201 protected TWidget(final TWidget parent
, final boolean enabled
,
202 final int x
, final int y
, final int width
, final int height
) {
205 throw new IllegalArgumentException("width cannot be negative");
208 throw new IllegalArgumentException("height cannot be negative");
211 this.enabled
= enabled
;
212 this.parent
= parent
;
213 children
= new ArrayList
<TWidget
>();
218 this.height
= height
;
220 if (parent
!= null) {
221 this.window
= parent
.window
;
222 parent
.addChild(this);
227 * Backdoor access for TWindow's constructor. ONLY TWindow USES THIS.
229 * @param window the top-level window
230 * @param x column relative to parent
231 * @param y row relative to parent
232 * @param width width of window
233 * @param height height of window
235 protected final void setupForTWindow(final TWindow window
,
236 final int x
, final int y
, final int width
, final int height
) {
239 throw new IllegalArgumentException("width cannot be negative");
242 throw new IllegalArgumentException("height cannot be negative");
245 this.parent
= window
;
246 this.window
= window
;
250 this.height
= height
;
253 // ------------------------------------------------------------------------
254 // Event handlers ---------------------------------------------------------
255 // ------------------------------------------------------------------------
258 * Subclasses should override this method to cleanup resources. This is
259 * called by TWindow.onClose().
261 protected void close() {
262 // Default: call close() on children.
263 for (TWidget w
: getChildren()) {
269 * Check if a mouse press/release event coordinate is contained in this
272 * @param mouse a mouse-based event
273 * @return whether or not a mouse click would be sent to this widget
275 public final boolean mouseWouldHit(final TMouseEvent mouse
) {
281 if ((this instanceof TTreeItem
)
282 && ((y
< 0) || (y
> parent
.getHeight() - 1))
287 if ((mouse
.getAbsoluteX() >= getAbsoluteX())
288 && (mouse
.getAbsoluteX() < getAbsoluteX() + width
)
289 && (mouse
.getAbsoluteY() >= getAbsoluteY())
290 && (mouse
.getAbsoluteY() < getAbsoluteY() + height
)
298 * Method that subclasses can override to handle keystrokes.
300 * @param keypress keystroke event
302 public void onKeypress(final TKeypressEvent keypress
) {
303 assert (parent
!= null);
305 if ((children
.size() == 0)
306 || (this instanceof TTreeView
)
307 || (this instanceof TText
)
308 || (this instanceof TComboBox
)
312 // tab / shift-tab - switch to next/previous widget
313 // left-arrow or up-arrow: same as shift-tab
314 if ((keypress
.equals(kbTab
))
315 || (keypress
.equals(kbDown
) && !(this instanceof TComboBox
))
317 parent
.switchWidget(true);
319 } else if ((keypress
.equals(kbShiftTab
))
320 || (keypress
.equals(kbBackTab
))
321 || (keypress
.equals(kbUp
) && !(this instanceof TComboBox
))
323 parent
.switchWidget(false);
328 if ((children
.size() == 0)
329 && !(this instanceof TTreeView
)
333 // right-arrow or down-arrow: same as tab
334 if (keypress
.equals(kbRight
)) {
335 parent
.switchWidget(true);
337 } else if (keypress
.equals(kbLeft
)) {
338 parent
.switchWidget(false);
343 // If I have any buttons on me AND this is an Alt-key that matches
344 // its mnemonic, send it an Enter keystroke.
345 for (TWidget widget
: children
) {
346 if (widget
instanceof TButton
) {
347 TButton button
= (TButton
) widget
;
348 if (button
.isEnabled()
349 && !keypress
.getKey().isFnKey()
350 && keypress
.getKey().isAlt()
351 && !keypress
.getKey().isCtrl()
352 && (Character
.toLowerCase(button
.getMnemonic().getShortcut())
353 == Character
.toLowerCase(keypress
.getKey().getChar()))
356 widget
.onKeypress(new TKeypressEvent(kbEnter
));
362 // If I have any labels on me AND this is an Alt-key that matches
363 // its mnemonic, call its action.
364 for (TWidget widget
: children
) {
365 if (widget
instanceof TLabel
) {
366 TLabel label
= (TLabel
) widget
;
367 if (!keypress
.getKey().isFnKey()
368 && keypress
.getKey().isAlt()
369 && !keypress
.getKey().isCtrl()
370 && (Character
.toLowerCase(label
.getMnemonic().getShortcut())
371 == Character
.toLowerCase(keypress
.getKey().getChar()))
380 // If I have any radiobuttons on me AND this is an Alt-key that
381 // matches its mnemonic, select it and send a Space to it.
382 for (TWidget widget
: children
) {
383 if (widget
instanceof TRadioButton
) {
384 TRadioButton button
= (TRadioButton
) widget
;
385 if (button
.isEnabled()
386 && !keypress
.getKey().isFnKey()
387 && keypress
.getKey().isAlt()
388 && !keypress
.getKey().isCtrl()
389 && (Character
.toLowerCase(button
.getMnemonic().getShortcut())
390 == Character
.toLowerCase(keypress
.getKey().getChar()))
393 widget
.onKeypress(new TKeypressEvent(kbSpace
));
397 if (widget
instanceof TRadioGroup
) {
398 for (TWidget child
: widget
.getChildren()) {
399 if (child
instanceof TRadioButton
) {
400 TRadioButton button
= (TRadioButton
) child
;
401 if (button
.isEnabled()
402 && !keypress
.getKey().isFnKey()
403 && keypress
.getKey().isAlt()
404 && !keypress
.getKey().isCtrl()
405 && (Character
.toLowerCase(button
.getMnemonic().getShortcut())
406 == Character
.toLowerCase(keypress
.getKey().getChar()))
409 widget
.activate(child
);
410 child
.onKeypress(new TKeypressEvent(kbSpace
));
418 // If I have any checkboxes on me AND this is an Alt-key that matches
419 // its mnemonic, select it and set it to checked.
420 for (TWidget widget
: children
) {
421 if (widget
instanceof TCheckBox
) {
422 TCheckBox checkBox
= (TCheckBox
) widget
;
423 if (checkBox
.isEnabled()
424 && !keypress
.getKey().isFnKey()
425 && keypress
.getKey().isAlt()
426 && !keypress
.getKey().isCtrl()
427 && (Character
.toLowerCase(checkBox
.getMnemonic().getShortcut())
428 == Character
.toLowerCase(keypress
.getKey().getChar()))
431 checkBox
.setChecked(true);
437 // Dispatch the keypress to an active widget
438 for (TWidget widget
: children
) {
440 widget
.onKeypress(keypress
);
447 * Method that subclasses can override to handle mouse button presses.
449 * @param mouse mouse button event
451 public void onMouseDown(final TMouseEvent mouse
) {
452 // Default: do nothing, pass to children instead
453 if (activeChild
!= null) {
454 if (activeChild
.mouseWouldHit(mouse
)) {
455 // Dispatch to the active child
457 // Set x and y relative to the child's coordinates
458 mouse
.setX(mouse
.getAbsoluteX() - activeChild
.getAbsoluteX());
459 mouse
.setY(mouse
.getAbsoluteY() - activeChild
.getAbsoluteY());
460 activeChild
.onMouseDown(mouse
);
464 for (int i
= children
.size() - 1 ; i
>= 0 ; i
--) {
465 TWidget widget
= children
.get(i
);
466 if (widget
.mouseWouldHit(mouse
)) {
467 // Dispatch to this child, also activate it
470 // Set x and y relative to the child's coordinates
471 mouse
.setX(mouse
.getAbsoluteX() - widget
.getAbsoluteX());
472 mouse
.setY(mouse
.getAbsoluteY() - widget
.getAbsoluteY());
473 widget
.onMouseDown(mouse
);
480 * Method that subclasses can override to handle mouse button releases.
482 * @param mouse mouse button event
484 public void onMouseUp(final TMouseEvent mouse
) {
485 // Default: do nothing, pass to children instead
486 if (activeChild
!= null) {
487 if (activeChild
.mouseWouldHit(mouse
)) {
488 // Dispatch to the active child
490 // Set x and y relative to the child's coordinates
491 mouse
.setX(mouse
.getAbsoluteX() - activeChild
.getAbsoluteX());
492 mouse
.setY(mouse
.getAbsoluteY() - activeChild
.getAbsoluteY());
493 activeChild
.onMouseUp(mouse
);
497 for (int i
= children
.size() - 1 ; i
>= 0 ; i
--) {
498 TWidget widget
= children
.get(i
);
499 if (widget
.mouseWouldHit(mouse
)) {
500 // Dispatch to this child, also activate it
503 // Set x and y relative to the child's coordinates
504 mouse
.setX(mouse
.getAbsoluteX() - widget
.getAbsoluteX());
505 mouse
.setY(mouse
.getAbsoluteY() - widget
.getAbsoluteY());
506 widget
.onMouseUp(mouse
);
513 * Method that subclasses can override to handle mouse movements.
515 * @param mouse mouse motion event
517 public void onMouseMotion(final TMouseEvent mouse
) {
518 // Default: do nothing, pass it on to ALL of my children. This way
519 // the children can see the mouse "leaving" their area.
520 for (TWidget widget
: children
) {
521 // Set x and y relative to the child's coordinates
522 mouse
.setX(mouse
.getAbsoluteX() - widget
.getAbsoluteX());
523 mouse
.setY(mouse
.getAbsoluteY() - widget
.getAbsoluteY());
524 widget
.onMouseMotion(mouse
);
529 * Method that subclasses can override to handle mouse button
532 * @param mouse mouse button event
534 public void onMouseDoubleClick(final TMouseEvent mouse
) {
535 // Default: do nothing, pass to children instead
536 if (activeChild
!= null) {
537 if (activeChild
.mouseWouldHit(mouse
)) {
538 // Dispatch to the active child
540 // Set x and y relative to the child's coordinates
541 mouse
.setX(mouse
.getAbsoluteX() - activeChild
.getAbsoluteX());
542 mouse
.setY(mouse
.getAbsoluteY() - activeChild
.getAbsoluteY());
543 activeChild
.onMouseDoubleClick(mouse
);
547 for (int i
= children
.size() - 1 ; i
>= 0 ; i
--) {
548 TWidget widget
= children
.get(i
);
549 if (widget
.mouseWouldHit(mouse
)) {
550 // Dispatch to this child, also activate it
553 // Set x and y relative to the child's coordinates
554 mouse
.setX(mouse
.getAbsoluteX() - widget
.getAbsoluteX());
555 mouse
.setY(mouse
.getAbsoluteY() - widget
.getAbsoluteY());
556 widget
.onMouseDoubleClick(mouse
);
563 * Method that subclasses can override to handle window/screen resize
566 * @param resize resize event
568 public void onResize(final TResizeEvent resize
) {
569 // Default: change my width/height.
570 if (resize
.getType() == TResizeEvent
.Type
.WIDGET
) {
571 width
= resize
.getWidth();
572 height
= resize
.getHeight();
573 if (layout
!= null) {
574 if (this instanceof TWindow
) {
575 layout
.onResize(new TResizeEvent(TResizeEvent
.Type
.WIDGET
,
576 width
- 2, height
- 2));
578 layout
.onResize(resize
);
582 // Let children see the screen resize
583 for (TWidget widget
: children
) {
584 widget
.onResize(resize
);
590 * Method that subclasses can override to handle posted command events.
592 * @param command command event
594 public void onCommand(final TCommandEvent command
) {
595 if (activeChild
!= null) {
596 activeChild
.onCommand(command
);
601 * Method that subclasses can override to handle menu or posted menu
604 * @param menu menu event
606 public void onMenu(final TMenuEvent menu
) {
607 // Default: do nothing, pass to children instead
608 for (TWidget widget
: children
) {
614 * Method that subclasses can override to do processing when the UI is
615 * idle. Note that repainting is NOT assumed. To get a refresh after
616 * onIdle, call doRepaint().
618 public void onIdle() {
619 // Default: do nothing, pass to children instead
620 for (TWidget widget
: children
) {
626 * Consume event. Subclasses that want to intercept all events in one go
627 * can override this method.
629 * @param event keyboard, mouse, resize, command, or menu event
631 public void handleEvent(final TInputEvent event
) {
633 System.err.printf("TWidget (%s) event: %s\n", this.getClass().getName(),
639 // System.err.println(" -- discard --");
643 if (event
instanceof TKeypressEvent
) {
644 onKeypress((TKeypressEvent
) event
);
645 } else if (event
instanceof TMouseEvent
) {
647 TMouseEvent mouse
= (TMouseEvent
) event
;
649 switch (mouse
.getType()) {
660 onMouseMotion(mouse
);
663 case MOUSE_DOUBLE_CLICK
:
664 onMouseDoubleClick(mouse
);
668 throw new IllegalArgumentException("Invalid mouse event type: "
671 } else if (event
instanceof TResizeEvent
) {
672 onResize((TResizeEvent
) event
);
673 } else if (event
instanceof TCommandEvent
) {
674 onCommand((TCommandEvent
) event
);
675 } else if (event
instanceof TMenuEvent
) {
676 onMenu((TMenuEvent
) event
);
683 // ------------------------------------------------------------------------
684 // TWidget ----------------------------------------------------------------
685 // ------------------------------------------------------------------------
690 * @return parent widget
692 public final TWidget
getParent() {
697 * Get the list of child widgets that this widget contains.
699 * @return the list of child widgets
701 public List
<TWidget
> getChildren() {
706 * Remove this widget from its parent container. close() will be called
707 * before it is removed.
709 public final void remove() {
714 * Remove this widget from its parent container.
716 * @param doClose if true, call the close() method before removing the
719 public final void remove(final boolean doClose
) {
720 if (parent
!= null) {
721 parent
.remove(this, doClose
);
726 * Remove a child widget from this container.
728 * @param child the child widget to remove
730 public final void remove(final TWidget child
) {
735 * Remove a child widget from this container.
737 * @param child the child widget to remove
738 * @param doClose if true, call the close() method before removing the
741 public final void remove(final TWidget child
, final boolean doClose
) {
742 if (!children
.contains(child
)) {
743 throw new IndexOutOfBoundsException("child widget is not in " +
744 "list of children of this parent");
749 children
.remove(child
);
752 if (layout
!= null) {
758 * Set this widget's parent to a different widget.
760 * @param newParent new parent widget
761 * @param doClose if true, call the close() method before removing the
762 * child from its existing parent widget
764 public final void setParent(final TWidget newParent
,
765 final boolean doClose
) {
767 if (parent
!= null) {
768 parent
.remove(this, doClose
);
771 assert (parent
== null);
772 assert (window
== null);
774 setWindow(parent
.window
);
775 parent
.addChild(this);
779 * Set this widget's window to a specific window.
781 * Having a null parent with a specified window is only used within Jexer
782 * by TStatusBar because TApplication routes events directly to it and
783 * calls its draw() method. Any other non-parented widgets will require
784 * similar special case functionality to receive events or be drawn to
787 * @param window the window to use
789 public final void setWindow(final TWindow window
) {
790 this.window
= window
;
791 for (TWidget child
: getChildren()) {
792 child
.setWindow(window
);
797 * Remove a child widget from this container, and all of its children
798 * recursively from their parent containers.
800 * @param child the child widget to remove
801 * @param doClose if true, call the close() method before removing each
804 public final void removeAll(final TWidget child
, final boolean doClose
) {
805 remove(child
, doClose
);
806 for (TWidget w
: child
.children
) {
807 child
.removeAll(w
, doClose
);
814 * @return if true, this widget will receive events
816 public final boolean isActive() {
823 * @param active if true, this widget will receive events
825 public final void setActive(final boolean active
) {
826 this.active
= active
;
830 * Get the window this widget is on.
834 public final TWindow
getWindow() {
841 * @return absolute X position of the top-left corner
843 public final int getX() {
850 * @param x absolute X position of the top-left corner
852 public final void setX(final int x
) {
859 * @return absolute Y position of the top-left corner
861 public final int getY() {
868 * @param y absolute Y position of the top-left corner
870 public final void setY(final int y
) {
877 * @return widget width
879 public int getWidth() {
886 * @param width new widget width
888 public void setWidth(final int width
) {
890 if (layout
!= null) {
891 layout
.onResize(new TResizeEvent(TResizeEvent
.Type
.WIDGET
,
899 * @return widget height
901 public int getHeight() {
908 * @param height new widget height
910 public void setHeight(final int height
) {
911 this.height
= height
;
912 if (layout
!= null) {
913 layout
.onResize(new TResizeEvent(TResizeEvent
.Type
.WIDGET
,
919 * Change the dimensions.
921 * @param x absolute X position of the top-left corner
922 * @param y absolute Y position of the top-left corner
923 * @param width new widget width
924 * @param height new widget height
926 public final void setDimensions(final int x
, final int y
, final int width
,
931 // Call the functions so that subclasses can choose how to handle it.
934 if (layout
!= null) {
935 layout
.onResize(new TResizeEvent(TResizeEvent
.Type
.WIDGET
,
941 * Get the layout manager.
943 * @return the layout manager, or null if not set
945 public LayoutManager
getLayoutManager() {
950 * Set the layout manager.
952 * @param layout the new layout manager
954 public void setLayoutManager(LayoutManager layout
) {
955 if (this.layout
!= null) {
956 for (TWidget w
: children
) {
957 this.layout
.remove(w
);
961 this.layout
= layout
;
962 if (this.layout
!= null) {
963 for (TWidget w
: children
) {
972 * @return if true, this widget can be tabbed to or receive events
974 public final boolean isEnabled() {
981 * @param enabled if true, this widget can be tabbed to or receive events
983 public final void setEnabled(final boolean enabled
) {
984 this.enabled
= enabled
;
987 // See if there are any active siblings to switch to
988 boolean foundSibling
= false;
989 if (parent
!= null) {
990 for (TWidget w
: parent
.children
) {
992 && !(this instanceof THScroller
)
993 && !(this instanceof TVScroller
)
1000 if (!foundSibling
) {
1001 parent
.activeChild
= null;
1010 * @param visible if true, this widget will be drawn
1012 public final void setVisible(final boolean visible
) {
1013 this.visible
= visible
;
1017 * See if this widget is visible.
1019 * @return if true, this widget will be drawn
1021 public final boolean isVisible() {
1026 * Set visible cursor flag.
1028 * @param cursorVisible if true, this widget has a cursor
1030 public final void setCursorVisible(final boolean cursorVisible
) {
1031 this.cursorVisible
= cursorVisible
;
1035 * See if this widget has a visible cursor.
1037 * @return if true, this widget has a visible cursor
1039 public final boolean isCursorVisible() {
1040 // If cursor is out of my bounds, it is not visible.
1041 if ((cursorX
>= width
)
1043 || (cursorY
>= height
)
1049 assert (window
!= null);
1051 if (window
instanceof TDesktop
) {
1052 // Desktop doesn't have a window border.
1053 return cursorVisible
;
1056 // If cursor is out of my window's bounds, it is not visible.
1057 if ((getCursorAbsoluteX() >= window
.getAbsoluteX()
1058 + window
.getWidth() - 1)
1059 || (getCursorAbsoluteX() < 0)
1060 || (getCursorAbsoluteY() >= window
.getAbsoluteY()
1061 + window
.getHeight() - 1)
1062 || (getCursorAbsoluteY() < 0)
1066 return cursorVisible
;
1070 * Get cursor X value.
1072 * @return cursor column position in relative coordinates
1074 public final int getCursorX() {
1079 * Set cursor X value.
1081 * @param cursorX column position in relative coordinates
1083 public final void setCursorX(final int cursorX
) {
1084 this.cursorX
= cursorX
;
1088 * Get cursor Y value.
1090 * @return cursor row position in relative coordinates
1092 public final int getCursorY() {
1097 * Set cursor Y value.
1099 * @param cursorY row position in relative coordinates
1101 public final void setCursorY(final int cursorY
) {
1102 this.cursorY
= cursorY
;
1106 * Get this TWidget's parent TApplication.
1108 * @return the parent TApplication, or null if not assigned
1110 public TApplication
getApplication() {
1111 if (window
!= null) {
1112 return window
.getApplication();
1120 * @return the Screen, or null if not assigned
1122 public Screen
getScreen() {
1123 if (window
!= null) {
1124 return window
.getScreen();
1130 * Get the Clipboard.
1132 * @return the Clipboard, or null if not assigned
1134 public Clipboard
getClipboard() {
1135 if (window
!= null) {
1136 return window
.getApplication().getClipboard();
1142 * Comparison operator. For various subclasses it sorts on:
1144 * <li>tabOrder for TWidgets</li>
1145 * <li>z for TWindows</li>
1146 * <li>text for TTreeItems</li>
1149 * @param that another TWidget, TWindow, or TTreeItem instance
1150 * @return difference between this.tabOrder and that.tabOrder, or
1151 * difference between this.z and that.z, or String.compareTo(text)
1154 public int compareTo(final TWidget that
) {
1155 if ((this instanceof TWindow
)
1156 && (that
instanceof TWindow
)
1158 return (((TWindow
) this).getZ() - ((TWindow
) that
).getZ());
1160 if ((this instanceof TTreeItem
)
1161 && (that
instanceof TTreeItem
)
1163 return (((TTreeItem
) this).getText().compareTo(
1164 ((TTreeItem
) that
).getText()));
1166 return (this.tabOrder
- that
.tabOrder
);
1170 * See if this widget should render with the active color.
1172 * @return true if this widget is active and all of its parents are
1175 public final boolean isAbsoluteActive() {
1176 if (parent
== this) {
1179 return (active
&& (parent
== null ?
true : parent
.isAbsoluteActive()));
1183 * Returns the cursor X position.
1185 * @return absolute screen column number for the cursor's X position
1187 public final int getCursorAbsoluteX() {
1188 return getAbsoluteX() + cursorX
;
1192 * Returns the cursor Y position.
1194 * @return absolute screen row number for the cursor's Y position
1196 public final int getCursorAbsoluteY() {
1197 return getAbsoluteY() + cursorY
;
1201 * Compute my absolute X position as the sum of my X plus all my parent's
1204 * @return absolute screen column number for my X position
1206 public final int getAbsoluteX() {
1207 assert (parent
!= null);
1208 if (parent
== this) {
1211 if ((parent
instanceof TWindow
)
1212 && !(parent
instanceof TMenu
)
1213 && !(parent
instanceof TDesktop
)
1215 // Widgets on a TWindow have (0,0) as their top-left, but this is
1216 // actually the TWindow's (1,1).
1217 return parent
.getAbsoluteX() + x
+ 1;
1219 return parent
.getAbsoluteX() + x
;
1223 * Compute my absolute Y position as the sum of my Y plus all my parent's
1226 * @return absolute screen row number for my Y position
1228 public final int getAbsoluteY() {
1229 assert (parent
!= null);
1230 if (parent
== this) {
1233 if ((parent
instanceof TWindow
)
1234 && !(parent
instanceof TMenu
)
1235 && !(parent
instanceof TDesktop
)
1237 // Widgets on a TWindow have (0,0) as their top-left, but this is
1238 // actually the TWindow's (1,1).
1239 return parent
.getAbsoluteY() + y
+ 1;
1241 return parent
.getAbsoluteY() + y
;
1245 * Get the global color theme.
1247 * @return the ColorTheme
1249 protected final ColorTheme
getTheme() {
1250 return window
.getApplication().getTheme();
1254 * See if this widget can be drawn onto a screen.
1256 * @return true if this widget is part of the hierarchy that can draw to
1259 public final boolean isDrawable() {
1260 if ((window
== null)
1261 || (window
.getScreen() == null)
1266 if (parent
== this) {
1269 return (parent
.isDrawable());
1273 * Draw my specific widget. When called, the screen rectangle I draw
1274 * into is already setup (offset and clipping).
1276 public void draw() {
1277 // Default widget draws nothing.
1281 * Called by parent to render to TWindow. Note package private access.
1283 final void drawChildren() {
1284 if (!isDrawable()) {
1288 // Set my clipping rectangle
1289 assert (window
!= null);
1290 assert (getScreen() != null);
1291 Screen screen
= getScreen();
1293 // Special case: TStatusBar is drawn by TApplication, not anything
1295 if (this instanceof TStatusBar
) {
1299 screen
.setClipRight(width
);
1300 screen
.setClipBottom(height
);
1302 int absoluteRightEdge
= window
.getAbsoluteX() + window
.getWidth();
1303 int absoluteBottomEdge
= window
.getAbsoluteY() + window
.getHeight();
1304 if (!(this instanceof TWindow
)
1305 && !(this instanceof TVScroller
)
1306 && !(window
instanceof TDesktop
)
1308 absoluteRightEdge
-= 1;
1310 if (!(this instanceof TWindow
)
1311 && !(this instanceof THScroller
)
1312 && !(window
instanceof TDesktop
)
1314 absoluteBottomEdge
-= 1;
1316 int myRightEdge
= getAbsoluteX() + width
;
1317 int myBottomEdge
= getAbsoluteY() + height
;
1318 if (getAbsoluteX() > absoluteRightEdge
) {
1320 screen
.setClipRight(0);
1321 } else if (myRightEdge
> absoluteRightEdge
) {
1322 screen
.setClipRight(screen
.getClipRight()
1323 - (myRightEdge
- absoluteRightEdge
));
1325 if (getAbsoluteY() > absoluteBottomEdge
) {
1327 screen
.setClipBottom(0);
1328 } else if (myBottomEdge
> absoluteBottomEdge
) {
1329 screen
.setClipBottom(screen
.getClipBottom()
1330 - (myBottomEdge
- absoluteBottomEdge
));
1334 screen
.setOffsetX(getAbsoluteX());
1335 screen
.setOffsetY(getAbsoluteY());
1339 if (!isDrawable()) {
1340 // An action taken by a draw method unhooked me from the UI.
1345 assert (visible
== true);
1347 // Continue down the chain. Draw the active child last so that it
1349 for (TWidget widget
: children
) {
1350 if (widget
.isVisible() && (widget
!= activeChild
)) {
1351 widget
.drawChildren();
1352 if (!isDrawable()) {
1353 // An action taken by a draw method unhooked me from the UI.
1359 if (activeChild
!= null) {
1360 activeChild
.drawChildren();
1365 * Repaint the screen on the next update.
1367 protected final void doRepaint() {
1368 window
.getApplication().doRepaint();
1372 * Add a child widget to my list of children. We set its tabOrder to 0
1373 * and increment the tabOrder of all other children.
1375 * @param child TWidget to add
1377 public void addChild(final TWidget child
) {
1378 children
.add(child
);
1381 && !(child
instanceof THScroller
)
1382 && !(child
instanceof TVScroller
)
1384 for (TWidget widget
: children
) {
1385 widget
.active
= false;
1387 child
.active
= true;
1388 activeChild
= child
;
1390 for (int i
= 0; i
< children
.size(); i
++) {
1391 children
.get(i
).tabOrder
= i
;
1393 if (layout
!= null) {
1399 * Reset the tab order of children to match their position in the list.
1400 * Available so that subclasses can re-order their widgets if needed.
1402 protected void resetTabOrder() {
1403 for (int i
= 0; i
< children
.size(); i
++) {
1404 children
.get(i
).tabOrder
= i
;
1409 * Remove and {@link TWidget#close()} the given child from this {@link TWidget}.
1411 * Will also reorder the tab values of the remaining children.
1413 * @param child the child to remove
1415 * @return TRUE if the child was removed, FALSE if it was not found
1417 public boolean removeChild(final TWidget child
) {
1418 <<<<<<< HEAD
:TWidget
.java
1419 if (children
.remove(child
)) {
1421 child
.parent
= null;
1422 child
.window
= null;
1431 if (children
.remove(child
)) {
1433 child
.parent
= null;
1434 child
.window
= null;
1442 >>>>>>> upstream
-sep2019
-tcombo
:src
/jexer
/TWidget
.java
1446 * Switch the active child.
1448 * @param child TWidget to activate
1450 public final void activate(final TWidget child
) {
1451 assert (child
.enabled
);
1452 if ((child
instanceof THScroller
)
1453 || (child
instanceof TVScroller
)
1458 if (children
.size() == 1) {
1459 if (children
.get(0).enabled
== true) {
1460 child
.active
= true;
1461 activeChild
= child
;
1464 if (child
!= activeChild
) {
1465 if (activeChild
!= null) {
1466 activeChild
.active
= false;
1469 child
.active
= true;
1470 activeChild
= child
;
1475 * Switch the active child.
1477 * @param tabOrder tabOrder of the child to activate. If that child
1478 * isn't enabled, then the next enabled child will be activated.
1480 public final void activate(final int tabOrder
) {
1481 if (children
.size() == 1) {
1482 if (children
.get(0).enabled
== true) {
1483 children
.get(0).active
= true;
1484 activeChild
= children
.get(0);
1489 TWidget child
= null;
1490 for (TWidget widget
: children
) {
1491 if ((widget
.enabled
)
1492 && !(widget
instanceof THScroller
)
1493 && !(widget
instanceof TVScroller
)
1494 && (widget
.tabOrder
>= tabOrder
)
1500 if ((child
!= null) && (child
!= activeChild
)) {
1501 if (activeChild
!= null) {
1502 activeChild
.active
= false;
1504 assert (child
.enabled
);
1505 child
.active
= true;
1506 activeChild
= child
;
1511 * Make this widget the active child of its parent. Note that this is
1512 * not final since TWindow overrides activate().
1514 public void activate() {
1516 if (parent
!= null) {
1517 parent
.activate(this);
1523 * Make this widget, all of its parents, the active child.
1525 public final void activateAll() {
1527 if (parent
== this) {
1530 if (parent
!= null) {
1531 parent
.activateAll();
1536 * Switch the active widget with the next in the tab order.
1538 * @param forward if true, then switch to the next enabled widget in the
1539 * list, otherwise switch to the previous enabled widget in the list
1541 public final void switchWidget(final boolean forward
) {
1543 // No children: do nothing.
1544 if (children
.size() == 0) {
1548 assert (parent
!= null);
1550 // If there is only one child, make it active if it is enabled.
1551 if (children
.size() == 1) {
1552 if (children
.get(0).enabled
== true) {
1553 activeChild
= children
.get(0);
1554 activeChild
.active
= true;
1556 children
.get(0).active
= false;
1562 // Two or more children: go forward or backward to the next enabled
1565 if (activeChild
!= null) {
1566 tabOrder
= activeChild
.tabOrder
;
1576 // If at the end, pass the switch to my parent.
1577 if ((!forward
) && (parent
!= this)) {
1578 parent
.switchWidget(forward
);
1582 tabOrder
= children
.size() - 1;
1583 } else if (tabOrder
== children
.size()) {
1584 // If at the end, pass the switch to my parent.
1585 if ((forward
) && (parent
!= this)) {
1586 parent
.switchWidget(forward
);
1592 if (activeChild
== null) {
1593 if (tabOrder
== 0) {
1594 // We wrapped around
1597 } else if (activeChild
.tabOrder
== tabOrder
) {
1598 // We wrapped around
1601 } while ((!children
.get(tabOrder
).enabled
)
1602 && !(children
.get(tabOrder
) instanceof THScroller
)
1603 && !(children
.get(tabOrder
) instanceof TVScroller
));
1605 if (activeChild
!= null) {
1606 assert (children
.get(tabOrder
).enabled
);
1608 activeChild
.active
= false;
1610 if (children
.get(tabOrder
).enabled
== true) {
1611 children
.get(tabOrder
).active
= true;
1612 activeChild
= children
.get(tabOrder
);
1617 * Returns my active widget.
1619 * @return widget that is active, or this if no children
1621 public TWidget
getActiveChild() {
1622 if ((this instanceof THScroller
)
1623 || (this instanceof TVScroller
)
1628 for (TWidget widget
: children
) {
1629 if (widget
.active
) {
1630 return widget
.getActiveChild();
1633 // No active children, return me
1638 * Insert a vertical split between this widget and parent, and optionally
1639 * put another widget in the other side of the split.
1641 * @param newWidgetOnLeft if true, the new widget (if specified) will be
1642 * on the left pane, and this widget will be placed on the right pane
1643 * @param newWidget the new widget to add to the other pane, or null
1644 * @return the new split pane widget
1646 public TSplitPane
splitVertical(final boolean newWidgetOnLeft
,
1647 final TWidget newWidget
) {
1649 TSplitPane splitPane
= new TSplitPane(null, x
, y
, width
, height
, true);
1650 TWidget myParent
= parent
;
1652 if (myParent
instanceof TSplitPane
) {
1653 // TSplitPane has a left/right/top/bottom link to me somewhere,
1654 // replace it with a link to splitPane.
1655 ((TSplitPane
) myParent
).replaceWidget(this, splitPane
);
1657 splitPane
.setParent(myParent
, false);
1658 if (newWidgetOnLeft
) {
1659 splitPane
.setLeft(newWidget
);
1660 splitPane
.setRight(this);
1662 splitPane
.setLeft(this);
1663 splitPane
.setRight(newWidget
);
1665 if (newWidget
!= null) {
1666 newWidget
.activateAll();
1671 assert (parent
!= null);
1672 assert (window
!= null);
1673 assert (splitPane
.getWindow() != null);
1674 assert (splitPane
.getParent() != null);
1675 assert (splitPane
.isActive() == true);
1676 assert (parent
== splitPane
);
1677 if (newWidget
!= null) {
1678 assert (newWidget
.parent
== parent
);
1679 assert (newWidget
.active
== true);
1680 assert (active
== false);
1682 assert (active
== true);
1688 * Insert a horizontal split between this widget and parent, and
1689 * optionally put another widget in the other side of the split.
1691 * @param newWidgetOnTop if true, the new widget (if specified) will be
1692 * on the top pane, and this widget's children will be placed on the
1694 * @param newWidget the new widget to add to the other pane, or null
1695 * @return the new split pane widget
1697 public TSplitPane
splitHorizontal(final boolean newWidgetOnTop
,
1698 final TWidget newWidget
) {
1700 TSplitPane splitPane
= new TSplitPane(null, x
, y
, width
, height
, false);
1701 TWidget myParent
= parent
;
1703 if (myParent
instanceof TSplitPane
) {
1704 // TSplitPane has a left/right/top/bottom link to me somewhere,
1705 // replace it with a link to splitPane.
1706 ((TSplitPane
) myParent
).replaceWidget(this, splitPane
);
1708 splitPane
.setParent(myParent
, false);
1709 if (newWidgetOnTop
) {
1710 splitPane
.setTop(newWidget
);
1711 splitPane
.setBottom(this);
1713 splitPane
.setTop(this);
1714 splitPane
.setBottom(newWidget
);
1716 if (newWidget
!= null) {
1717 newWidget
.activateAll();
1722 assert (parent
!= null);
1723 assert (window
!= null);
1724 assert (splitPane
.getWindow() != null);
1725 assert (splitPane
.getParent() != null);
1726 assert (splitPane
.isActive() == true);
1727 assert (parent
== splitPane
);
1728 if (newWidget
!= null) {
1729 assert (newWidget
.parent
== parent
);
1730 assert (newWidget
.active
== true);
1731 assert (active
== false);
1733 assert (active
== true);
1739 * Generate a human-readable string for this widget.
1741 * @return a human-readable string
1744 public String
toString() {
1745 return String
.format("%s(%8x) position (%d, %d) geometry %dx%d " +
1746 "active %s enabled %s visible %s", getClass().getName(),
1747 hashCode(), x
, y
, width
, height
, active
, enabled
, visible
);
1751 * Generate a string for this widget's hierarchy.
1753 * @param prefix a prefix to use for this widget's place in the hierarchy
1754 * @return a pretty-printable string of this hierarchy
1756 protected String
toPrettyString(final String prefix
) {
1757 StringBuilder sb
= new StringBuilder(prefix
);
1758 sb
.append(toString());
1759 String newPrefix
= "";
1760 for (int i
= 0; i
< prefix
.length(); i
++) {
1763 for (int i
= 0; i
< children
.size(); i
++) {
1764 TWidget child
= children
.get(i
);
1766 if (i
== children
.size() - 1) {
1767 sb
.append(child
.toPrettyString(newPrefix
+ " \u2514\u2500"));
1769 sb
.append(child
.toPrettyString(newPrefix
+ " \u251c\u2500"));
1772 return sb
.toString();
1776 * Generate a string for this widget's hierarchy.
1778 * @return a pretty-printable string of this hierarchy
1780 public String
toPrettyString() {
1781 return toPrettyString("");
1784 // ------------------------------------------------------------------------
1785 // Passthru for Screen functions ------------------------------------------
1786 // ------------------------------------------------------------------------
1789 * Get the attributes at one location.
1791 * @param x column coordinate. 0 is the left-most column.
1792 * @param y row coordinate. 0 is the top-most row.
1793 * @return attributes at (x, y)
1795 protected final CellAttributes
getAttrXY(final int x
, final int y
) {
1796 return getScreen().getAttrXY(x
, y
);
1800 * Set the attributes at one location.
1802 * @param x column coordinate. 0 is the left-most column.
1803 * @param y row coordinate. 0 is the top-most row.
1804 * @param attr attributes to use (bold, foreColor, backColor)
1806 protected final void putAttrXY(final int x
, final int y
,
1807 final CellAttributes attr
) {
1809 getScreen().putAttrXY(x
, y
, attr
);
1813 * Set the attributes at one location.
1815 * @param x column coordinate. 0 is the left-most column.
1816 * @param y row coordinate. 0 is the top-most row.
1817 * @param attr attributes to use (bold, foreColor, backColor)
1818 * @param clip if true, honor clipping/offset
1820 protected final void putAttrXY(final int x
, final int y
,
1821 final CellAttributes attr
, final boolean clip
) {
1823 getScreen().putAttrXY(x
, y
, attr
, clip
);
1827 * Fill the entire screen with one character with attributes.
1829 * @param ch character to draw
1830 * @param attr attributes to use (bold, foreColor, backColor)
1832 protected final void putAll(final int ch
, final CellAttributes attr
) {
1833 getScreen().putAll(ch
, attr
);
1837 * Render one character with attributes.
1839 * @param x column coordinate. 0 is the left-most column.
1840 * @param y row coordinate. 0 is the top-most row.
1841 * @param ch character + attributes to draw
1843 protected final void putCharXY(final int x
, final int y
, final Cell ch
) {
1844 getScreen().putCharXY(x
, y
, ch
);
1848 * Render one character with attributes.
1850 * @param x column coordinate. 0 is the left-most column.
1851 * @param y row coordinate. 0 is the top-most row.
1852 * @param ch character to draw
1853 * @param attr attributes to use (bold, foreColor, backColor)
1855 protected final void putCharXY(final int x
, final int y
, final int ch
,
1856 final CellAttributes attr
) {
1858 getScreen().putCharXY(x
, y
, ch
, attr
);
1862 * Render one character without changing the underlying attributes.
1864 * @param x column coordinate. 0 is the left-most column.
1865 * @param y row coordinate. 0 is the top-most row.
1866 * @param ch character to draw
1868 protected final void putCharXY(final int x
, final int y
, final int ch
) {
1869 getScreen().putCharXY(x
, y
, ch
);
1873 * Render a string. Does not wrap if the string exceeds the line.
1875 * @param x column coordinate. 0 is the left-most column.
1876 * @param y row coordinate. 0 is the top-most row.
1877 * @param str string to draw
1878 * @param attr attributes to use (bold, foreColor, backColor)
1880 protected final void putStringXY(final int x
, final int y
, final String str
,
1881 final CellAttributes attr
) {
1883 getScreen().putStringXY(x
, y
, str
, attr
);
1887 * Render a string without changing the underlying attribute. Does not
1888 * wrap if the string exceeds the line.
1890 * @param x column coordinate. 0 is the left-most column.
1891 * @param y row coordinate. 0 is the top-most row.
1892 * @param str string to draw
1894 protected final void putStringXY(final int x
, final int y
, final String str
) {
1895 getScreen().putStringXY(x
, y
, str
);
1899 * Draw a vertical line from (x, y) to (x, y + n).
1901 * @param x column coordinate. 0 is the left-most column.
1902 * @param y row coordinate. 0 is the top-most row.
1903 * @param n number of characters to draw
1904 * @param ch character to draw
1905 * @param attr attributes to use (bold, foreColor, backColor)
1907 protected final void vLineXY(final int x
, final int y
, final int n
,
1908 final int ch
, final CellAttributes attr
) {
1910 getScreen().vLineXY(x
, y
, n
, ch
, attr
);
1914 * Draw a horizontal line from (x, y) to (x + n, y).
1916 * @param x column coordinate. 0 is the left-most column.
1917 * @param y row coordinate. 0 is the top-most row.
1918 * @param n number of characters to draw
1919 * @param ch character to draw
1920 * @param attr attributes to use (bold, foreColor, backColor)
1922 protected final void hLineXY(final int x
, final int y
, final int n
,
1923 final int ch
, final CellAttributes attr
) {
1925 getScreen().hLineXY(x
, y
, n
, ch
, attr
);
1929 * Draw a box with a border and empty background.
1931 * @param left left column of box. 0 is the left-most row.
1932 * @param top top row of the box. 0 is the top-most row.
1933 * @param right right column of box
1934 * @param bottom bottom row of the box
1935 * @param border attributes to use for the border
1936 * @param background attributes to use for the background
1938 protected final void drawBox(final int left
, final int top
,
1939 final int right
, final int bottom
,
1940 final CellAttributes border
, final CellAttributes background
) {
1942 getScreen().drawBox(left
, top
, right
, bottom
, border
, background
);
1946 * Draw a box with a border and empty background.
1948 * @param left left column of box. 0 is the left-most row.
1949 * @param top top row of the box. 0 is the top-most row.
1950 * @param right right column of box
1951 * @param bottom bottom row of the box
1952 * @param border attributes to use for the border
1953 * @param background attributes to use for the background
1954 * @param borderType if 1, draw a single-line border; if 2, draw a
1955 * double-line border; if 3, draw double-line top/bottom edges and
1956 * single-line left/right edges (like Qmodem)
1957 * @param shadow if true, draw a "shadow" on the box
1959 protected final void drawBox(final int left
, final int top
,
1960 final int right
, final int bottom
,
1961 final CellAttributes border
, final CellAttributes background
,
1962 final int borderType
, final boolean shadow
) {
1964 getScreen().drawBox(left
, top
, right
, bottom
, border
, background
,
1965 borderType
, shadow
);
1969 * Draw a box shadow.
1971 * @param left left column of box. 0 is the left-most row.
1972 * @param top top row of the box. 0 is the top-most row.
1973 * @param right right column of box
1974 * @param bottom bottom row of the box
1976 protected final void drawBoxShadow(final int left
, final int top
,
1977 final int right
, final int bottom
) {
1979 getScreen().drawBoxShadow(left
, top
, right
, bottom
);
1982 // ------------------------------------------------------------------------
1983 // Other TWidget constructors ---------------------------------------------
1984 // ------------------------------------------------------------------------
1987 * Convenience function to add a label to this container/window.
1990 * @param x column relative to parent
1991 * @param y row relative to parent
1992 * @return the new label
1994 public final TLabel
addLabel(final String text
, final int x
, final int y
) {
1995 return addLabel(text
, x
, y
, "tlabel");
1999 * Convenience function to add a label to this container/window.
2002 * @param x column relative to parent
2003 * @param y row relative to parent
2004 * @param action to call when shortcut is pressed
2005 * @return the new label
2007 public final TLabel
addLabel(final String text
, final int x
, final int y
,
2008 final TAction action
) {
2010 return addLabel(text
, x
, y
, "tlabel", action
);
2014 * Convenience function to add a label to this container/window.
2017 * @param x column relative to parent
2018 * @param y row relative to parent
2019 * @param colorKey ColorTheme key color to use for foreground text.
2020 * Default is "tlabel"
2021 * @return the new label
2023 public final TLabel
addLabel(final String text
, final int x
, final int y
,
2024 final String colorKey
) {
2026 return new TLabel(this, text
, x
, y
, colorKey
);
2030 * Convenience function to add a label to this container/window.
2033 * @param x column relative to parent
2034 * @param y row relative to parent
2035 * @param colorKey ColorTheme key color to use for foreground text.
2036 * Default is "tlabel"
2037 * @param action to call when shortcut is pressed
2038 * @return the new label
2040 public final TLabel
addLabel(final String text
, final int x
, final int y
,
2041 final String colorKey
, final TAction action
) {
2043 return new TLabel(this, text
, x
, y
, colorKey
, action
);
2047 * Convenience function to add a label to this container/window.
2050 * @param x column relative to parent
2051 * @param y row relative to parent
2052 * @param colorKey ColorTheme key color to use for foreground text.
2053 * Default is "tlabel"
2054 * @param useWindowBackground if true, use the window's background color
2055 * @return the new label
2057 public final TLabel
addLabel(final String text
, final int x
, final int y
,
2058 final String colorKey
, final boolean useWindowBackground
) {
2060 return new TLabel(this, text
, x
, y
, colorKey
, useWindowBackground
);
2064 * Convenience function to add a label to this container/window.
2067 * @param x column relative to parent
2068 * @param y row relative to parent
2069 * @param colorKey ColorTheme key color to use for foreground text.
2070 * Default is "tlabel"
2071 * @param useWindowBackground if true, use the window's background color
2072 * @param action to call when shortcut is pressed
2073 * @return the new label
2075 public final TLabel
addLabel(final String text
, final int x
, final int y
,
2076 final String colorKey
, final boolean useWindowBackground
,
2077 final TAction action
) {
2079 return new TLabel(this, text
, x
, y
, colorKey
, useWindowBackground
,
2084 * Convenience function to add a button to this container/window.
2086 * @param text label on the button
2087 * @param x column relative to parent
2088 * @param y row relative to parent
2089 * @param action action to call when button is pressed
2090 * @return the new button
2092 public final TButton
addButton(final String text
, final int x
, final int y
,
2093 final TAction action
) {
2095 return new TButton(this, text
, x
, y
, action
);
2099 * Convenience function to add a checkbox to this container/window.
2101 * @param x column relative to parent
2102 * @param y row relative to parent
2103 * @param label label to display next to (right of) the checkbox
2104 * @param checked initial check state
2105 * @return the new checkbox
2107 public final TCheckBox
addCheckBox(final int x
, final int y
,
2108 final String label
, final boolean checked
) {
2110 return new TCheckBox(this, x
, y
, label
, checked
);
2114 * Convenience function to add a combobox to this container/window.
2116 * @param x column relative to parent
2117 * @param y row relative to parent
2118 * @param width visible combobox width, including the down-arrow
2119 * @param values the possible values for the box, shown in the drop-down
2120 * @param valuesIndex the initial index in values, or -1 for no default
2122 * @param maxValuesHeight the maximum height of the values drop-down when
2124 * @param updateAction action to call when a new value is selected from
2125 * the list or enter is pressed in the edit field
2126 * @return the new combobox
2128 public final TComboBox
addComboBox(final int x
, final int y
,
2129 final int width
, final List
<String
> values
, final int valuesIndex
,
2130 final int maxValuesHeight
, final TAction updateAction
) {
2132 return new TComboBox(this, x
, y
, width
, values
, valuesIndex
,
2133 maxValuesHeight
, updateAction
);
2137 * Convenience function to add a spinner to this container/window.
2139 * @param x column relative to parent
2140 * @param y row relative to parent
2141 * @param upAction action to call when the up arrow is clicked or pressed
2142 * @param downAction action to call when the down arrow is clicked or
2144 * @return the new spinner
2146 public final TSpinner
addSpinner(final int x
, final int y
,
2147 final TAction upAction
, final TAction downAction
) {
2149 return new TSpinner(this, x
, y
, upAction
, downAction
);
2153 * Convenience function to add a calendar to this container/window.
2155 * @param x column relative to parent
2156 * @param y row relative to parent
2157 * @param updateAction action to call when the user changes the value of
2159 * @return the new calendar
2161 public final TCalendar
addCalendar(final int x
, final int y
,
2162 final TAction updateAction
) {
2164 return new TCalendar(this, x
, y
, updateAction
);
2168 * Convenience function to add a progress bar to this container/window.
2170 * @param x column relative to parent
2171 * @param y row relative to parent
2172 * @param width width of progress bar
2173 * @param value initial value of percent complete
2174 * @return the new progress bar
2176 public final TProgressBar
addProgressBar(final int x
, final int y
,
2177 final int width
, final int value
) {
2179 return new TProgressBar(this, x
, y
, width
, value
);
2183 * Convenience function to add a radio button group to this
2186 * @param x column relative to parent
2187 * @param y row relative to parent
2188 * @param label label to display on the group box
2189 * @return the new radio button group
2191 public final TRadioGroup
addRadioGroup(final int x
, final int y
,
2192 final String label
) {
2194 return new TRadioGroup(this, x
, y
, label
);
2198 * Convenience function to add a radio button group to this
2201 * @param x column relative to parent
2202 * @param y row relative to parent
2203 * @param width width of group
2204 * @param label label to display on the group box
2206 public final TRadioGroup
addRadioGroup(final int x
, final int y
,
2207 final int width
, final String label
) {
2209 return new TRadioGroup(this, x
, y
, width
, label
);
2213 * Convenience function to add a text field to this container/window.
2215 * @param x column relative to parent
2216 * @param y row relative to parent
2217 * @param width visible text width
2218 * @param fixed if true, the text cannot exceed the display width
2219 * @return the new text field
2221 public final TField
addField(final int x
, final int y
,
2222 final int width
, final boolean fixed
) {
2224 return new TField(this, x
, y
, width
, fixed
);
2228 * Convenience function to add a text field to this container/window.
2230 * @param x column relative to parent
2231 * @param y row relative to parent
2232 * @param width visible text width
2233 * @param fixed if true, the text cannot exceed the display width
2234 * @param text initial text, default is empty string
2235 * @return the new text field
2237 public final TField
addField(final int x
, final int y
,
2238 final int width
, final boolean fixed
, final String text
) {
2240 return new TField(this, x
, y
, width
, fixed
, text
);
2244 * Convenience function to add a text field to this container/window.
2246 * @param x column relative to parent
2247 * @param y row relative to parent
2248 * @param width visible text width
2249 * @param fixed if true, the text cannot exceed the display width
2250 * @param text initial text, default is empty string
2251 * @param enterAction function to call when enter key is pressed
2252 * @param updateAction function to call when the text is updated
2253 * @return the new text field
2255 public final TField
addField(final int x
, final int y
,
2256 final int width
, final boolean fixed
, final String text
,
2257 final TAction enterAction
, final TAction updateAction
) {
2259 return new TField(this, x
, y
, width
, fixed
, text
, enterAction
,
2264 * Convenience function to add a scrollable text box to this
2267 * @param text text on the screen
2268 * @param x column relative to parent
2269 * @param y row relative to parent
2270 * @param width width of text area
2271 * @param height height of text area
2272 * @param colorKey ColorTheme key color to use for foreground text
2273 * @return the new text box
2275 public final TText
addText(final String text
, final int x
,
2276 final int y
, final int width
, final int height
, final String colorKey
) {
2278 return new TText(this, text
, x
, y
, width
, height
, colorKey
);
2282 * Convenience function to add a scrollable text box to this
2285 * @param text text on the screen
2286 * @param x column relative to parent
2287 * @param y row relative to parent
2288 * @param width width of text area
2289 * @param height height of text area
2290 * @return the new text box
2292 public final TText
addText(final String text
, final int x
, final int y
,
2293 final int width
, final int height
) {
2295 return new TText(this, text
, x
, y
, width
, height
, "ttext");
2299 * Convenience function to add an editable text area box to this
2302 * @param text text on the screen
2303 * @param x column relative to parent
2304 * @param y row relative to parent
2305 * @param width width of text area
2306 * @param height height of text area
2307 * @return the new text box
2309 public final TEditorWidget
addEditor(final String text
, final int x
,
2310 final int y
, final int width
, final int height
) {
2312 return new TEditorWidget(this, text
, x
, y
, width
, height
);
2316 * Convenience function to spawn a message box.
2318 * @param title window title, will be centered along the top border
2319 * @param caption message to display. Use embedded newlines to get a
2321 * @return the new message box
2323 public final TMessageBox
messageBox(final String title
,
2324 final String caption
) {
2326 return getApplication().messageBox(title
, caption
, TMessageBox
.Type
.OK
);
2330 * Convenience function to spawn a message box.
2332 * @param title window title, will be centered along the top border
2333 * @param caption message to display. Use embedded newlines to get a
2335 * @param type one of the TMessageBox.Type constants. Default is
2337 * @return the new message box
2339 public final TMessageBox
messageBox(final String title
,
2340 final String caption
, final TMessageBox
.Type type
) {
2342 return getApplication().messageBox(title
, caption
, type
);
2346 * Convenience function to spawn an input box.
2348 * @param title window title, will be centered along the top border
2349 * @param caption message to display. Use embedded newlines to get a
2351 * @return the new input box
2353 public final TInputBox
inputBox(final String title
, final String caption
) {
2355 return getApplication().inputBox(title
, caption
);
2359 * Convenience function to spawn an input box.
2361 * @param title window title, will be centered along the top border
2362 * @param caption message to display. Use embedded newlines to get a
2364 * @param text initial text to seed the field with
2365 * @return the new input box
2367 public final TInputBox
inputBox(final String title
, final String caption
,
2368 final String text
) {
2370 return getApplication().inputBox(title
, caption
, text
);
2374 * Convenience function to spawn an input box.
2376 * @param title window title, will be centered along the top border
2377 * @param caption message to display. Use embedded newlines to get a
2379 * @param text initial text to seed the field with
2380 * @param type one of the Type constants. Default is Type.OK.
2381 * @return the new input box
2383 public final TInputBox
inputBox(final String title
, final String caption
,
2384 final String text
, final TInputBox
.Type type
) {
2386 return getApplication().inputBox(title
, caption
, text
, type
);
2390 * Convenience function to add a password text field to this
2393 * @param x column relative to parent
2394 * @param y row relative to parent
2395 * @param width visible text width
2396 * @param fixed if true, the text cannot exceed the display width
2397 * @return the new text field
2399 public final TPasswordField
addPasswordField(final int x
, final int y
,
2400 final int width
, final boolean fixed
) {
2402 return new TPasswordField(this, x
, y
, width
, fixed
);
2406 * Convenience function to add a password text field to this
2409 * @param x column relative to parent
2410 * @param y row relative to parent
2411 * @param width visible text width
2412 * @param fixed if true, the text cannot exceed the display width
2413 * @param text initial text, default is empty string
2414 * @return the new text field
2416 public final TPasswordField
addPasswordField(final int x
, final int y
,
2417 final int width
, final boolean fixed
, final String text
) {
2419 return new TPasswordField(this, x
, y
, width
, fixed
, text
);
2423 * Convenience function to add a password text field to this
2426 * @param x column relative to parent
2427 * @param y row relative to parent
2428 * @param width visible text width
2429 * @param fixed if true, the text cannot exceed the display width
2430 * @param text initial text, default is empty string
2431 * @param enterAction function to call when enter key is pressed
2432 * @param updateAction function to call when the text is updated
2433 * @return the new text field
2435 public final TPasswordField
addPasswordField(final int x
, final int y
,
2436 final int width
, final boolean fixed
, final String text
,
2437 final TAction enterAction
, final TAction updateAction
) {
2439 return new TPasswordField(this, x
, y
, width
, fixed
, text
, enterAction
,
2444 * Convenience function to add a scrollable tree view to this
2447 * @param x column relative to parent
2448 * @param y row relative to parent
2449 * @param width width of tree view
2450 * @param height height of tree view
2451 * @return the new tree view
2453 public final TTreeViewWidget
addTreeViewWidget(final int x
, final int y
,
2454 final int width
, final int height
) {
2456 return new TTreeViewWidget(this, x
, y
, width
, height
);
2460 * Convenience function to add a scrollable tree view to this
2463 * @param x column relative to parent
2464 * @param y row relative to parent
2465 * @param width width of tree view
2466 * @param height height of tree view
2467 * @param action action to perform when an item is selected
2468 * @return the new tree view
2470 public final TTreeViewWidget
addTreeViewWidget(final int x
, final int y
,
2471 final int width
, final int height
, final TAction action
) {
2473 return new TTreeViewWidget(this, x
, y
, width
, height
, action
);
2477 * Convenience function to spawn a file open box.
2479 * @param path path of selected file
2480 * @return the result of the new file open box
2481 * @throws IOException if a java.io operation throws
2483 public final String
fileOpenBox(final String path
) throws IOException
{
2484 return getApplication().fileOpenBox(path
);
2488 * Convenience function to spawn a file save box.
2490 * @param path path of selected file
2491 * @return the result of the new file open box
2492 * @throws IOException if a java.io operation throws
2494 public final String
fileSaveBox(final String path
) throws IOException
{
2495 return getApplication().fileOpenBox(path
, TFileOpenBox
.Type
.SAVE
);
2499 * Convenience function to spawn a file open box.
2501 * @param path path of selected file
2502 * @param type one of the Type constants
2503 * @return the result of the new file open box
2504 * @throws IOException if a java.io operation throws
2506 public final String
fileOpenBox(final String path
,
2507 final TFileOpenBox
.Type type
) throws IOException
{
2509 return getApplication().fileOpenBox(path
, type
);
2513 * Convenience function to spawn a file open box.
2515 * @param path path of selected file
2516 * @param type one of the Type constants
2517 * @param filter a string that files must match to be displayed
2518 * @return the result of the new file open box
2519 * @throws IOException of a java.io operation throws
2521 public final String
fileOpenBox(final String path
,
2522 final TFileOpenBox
.Type type
, final String filter
) throws IOException
{
2524 ArrayList
<String
> filters
= new ArrayList
<String
>();
2525 filters
.add(filter
);
2527 return getApplication().fileOpenBox(path
, type
, filters
);
2531 * Convenience function to spawn a file open box.
2533 * @param path path of selected file
2534 * @param type one of the Type constants
2535 * @param filters a list of strings that files must match to be displayed
2536 * @return the result of the new file open box
2537 * @throws IOException of a java.io operation throws
2539 public final String
fileOpenBox(final String path
,
2540 final TFileOpenBox
.Type type
,
2541 final List
<String
> filters
) throws IOException
{
2543 return getApplication().fileOpenBox(path
, type
, filters
);
2547 * Convenience function to add a directory list to this container/window.
2549 * @param path directory path, must be a directory
2550 * @param x column relative to parent
2551 * @param y row relative to parent
2552 * @param width width of text area
2553 * @param height height of text area
2554 * @return the new directory list
2556 public final TDirectoryList
addDirectoryList(final String path
, final int x
,
2557 final int y
, final int width
, final int height
) {
2559 return new TDirectoryList(this, path
, x
, y
, width
, height
, null);
2563 * Convenience function to add a directory list to this container/window.
2565 * @param path directory path, must be a directory
2566 * @param x column relative to parent
2567 * @param y row relative to parent
2568 * @param width width of text area
2569 * @param height height of text area
2570 * @param action action to perform when an item is selected (enter or
2572 * @return the new directory list
2574 public final TDirectoryList
addDirectoryList(final String path
, final int x
,
2575 final int y
, final int width
, final int height
, final TAction action
) {
2577 return new TDirectoryList(this, path
, x
, y
, width
, height
, action
);
2581 * Convenience function to add a directory list to this container/window.
2583 * @param path directory path, must be a directory
2584 * @param x column relative to parent
2585 * @param y row relative to parent
2586 * @param width width of text area
2587 * @param height height of text area
2588 * @param action action to perform when an item is selected (enter or
2590 * @param singleClickAction action to perform when an item is selected
2592 * @return the new directory list
2594 public final TDirectoryList
addDirectoryList(final String path
, final int x
,
2595 final int y
, final int width
, final int height
, final TAction action
,
2596 final TAction singleClickAction
) {
2598 return new TDirectoryList(this, path
, x
, y
, width
, height
, action
,
2603 * Convenience function to add a directory list to this container/window.
2605 * @param path directory path, must be a directory
2606 * @param x column relative to parent
2607 * @param y row relative to parent
2608 * @param width width of text area
2609 * @param height height of text area
2610 * @param action action to perform when an item is selected (enter or
2612 * @param singleClickAction action to perform when an item is selected
2614 * @param filters a list of strings that files must match to be displayed
2615 * @return the new directory list
2617 public final TDirectoryList
addDirectoryList(final String path
, final int x
,
2618 final int y
, final int width
, final int height
, final TAction action
,
2619 final TAction singleClickAction
, final List
<String
> filters
) {
2621 return new TDirectoryList(this, path
, x
, y
, width
, height
, action
,
2622 singleClickAction
, filters
);
2626 * Convenience function to add a list to this container/window.
2628 * @param strings list of strings to show
2629 * @param x column relative to parent
2630 * @param y row relative to parent
2631 * @param width width of text area
2632 * @param height height of text area
2633 * @return the new directory list
2635 public final TList
addList(final List
<String
> strings
, final int x
,
2636 final int y
, final int width
, final int height
) {
2638 return new TList(this, strings
, x
, y
, width
, height
, null);
2642 * Convenience function to add a list to this container/window.
2644 * @param strings list of strings to show
2645 * @param x column relative to parent
2646 * @param y row relative to parent
2647 * @param width width of text area
2648 * @param height height of text area
2649 * @param enterAction action to perform when an item is selected
2650 * @return the new directory list
2652 public final TList
addList(final List
<String
> strings
, final int x
,
2653 final int y
, final int width
, final int height
,
2654 final TAction enterAction
) {
2656 return new TList(this, strings
, x
, y
, width
, height
, enterAction
);
2660 * Convenience function to add a list to this container/window.
2662 * @param strings list of strings to show
2663 * @param x column relative to parent
2664 * @param y row relative to parent
2665 * @param width width of text area
2666 * @param height height of text area
2667 * @param enterAction action to perform when an item is selected
2668 * @param moveAction action to perform when the user navigates to a new
2669 * item with arrow/page keys
2670 * @return the new directory list
2672 public final TList
addList(final List
<String
> strings
, final int x
,
2673 final int y
, final int width
, final int height
,
2674 final TAction enterAction
, final TAction moveAction
) {
2676 return new TList(this, strings
, x
, y
, width
, height
, enterAction
,
2681 * Convenience function to add a list to this container/window.
2683 * @param strings list of strings to show. This is allowed to be null
2684 * and set later with setList() or by subclasses.
2685 * @param x column relative to parent
2686 * @param y row relative to parent
2687 * @param width width of text area
2688 * @param height height of text area
2689 * @param enterAction action to perform when an item is selected
2690 * @param moveAction action to perform when the user navigates to a new
2691 * item with arrow/page keys
2692 * @param singleClickAction action to perform when the user clicks on an
2695 public TList
addList(final List
<String
> strings
, final int x
,
2696 final int y
, final int width
, final int height
,
2697 final TAction enterAction
, final TAction moveAction
,
2698 final TAction singleClickAction
) {
2700 return new TList(this, strings
, x
, y
, width
, height
, enterAction
,
2701 moveAction
, singleClickAction
);
2706 * Convenience function to add an image to this container/window.
2708 * @param x column relative to parent
2709 * @param y row relative to parent
2710 * @param width number of text cells for width of the image
2711 * @param height number of text cells for height of the image
2712 * @param image the image to display
2713 * @param left left column of the image. 0 is the left-most column.
2714 * @param top top row of the image. 0 is the top-most row.
2716 public final TImage
addImage(final int x
, final int y
,
2717 final int width
, final int height
,
2718 final BufferedImage image
, final int left
, final int top
) {
2720 return new TImage(this, x
, y
, width
, height
, image
, left
, top
);
2724 * Convenience function to add an image to this container/window.
2726 * @param x column relative to parent
2727 * @param y row relative to parent
2728 * @param width number of text cells for width of the image
2729 * @param height number of text cells for height of the image
2730 * @param image the image to display
2731 * @param left left column of the image. 0 is the left-most column.
2732 * @param top top row of the image. 0 is the top-most row.
2733 * @param clickAction function to call when mouse is pressed
2735 public final TImage
addImage(final int x
, final int y
,
2736 final int width
, final int height
,
2737 final BufferedImage image
, final int left
, final int top
,
2738 final TAction clickAction
) {
2740 return new TImage(this, x
, y
, width
, height
, image
, left
, top
,
2745 * Convenience function to add an editable 2D data table to this
2748 * @param x column relative to parent
2749 * @param y row relative to parent
2750 * @param width width of widget
2751 * @param height height of widget
2753 public TTableWidget
addTable(final int x
, final int y
, final int width
,
2756 return new TTableWidget(this, x
, y
, width
, height
);
2760 * Convenience function to add an editable 2D data table to this
2763 * @param x column relative to parent
2764 * @param y row relative to parent
2765 * @param width width of widget
2766 * @param height height of widget
2767 * @param gridColumns number of columns in grid
2768 * @param gridRows number of rows in grid
2770 public TTableWidget
addTable(final int x
, final int y
, final int width
,
2771 final int height
, final int gridColumns
, final int gridRows
) {
2773 return new TTableWidget(this, x
, y
, width
, height
, gridColumns
,
2778 * Convenience function to add a panel to this container/window.
2780 * @param x column relative to parent
2781 * @param y row relative to parent
2782 * @param width width of text area
2783 * @param height height of text area
2784 * @return the new panel
2786 public final TPanel
addPanel(final int x
, final int y
, final int width
,
2789 return new TPanel(this, x
, y
, width
, height
);
2793 * Convenience function to add a split pane to this container/window.
2795 * @param x column relative to parent
2796 * @param y row relative to parent
2797 * @param width width of text area
2798 * @param height height of text area
2799 * @param vertical if true, split vertically
2800 * @return the new split pane
2802 public final TSplitPane
addSplitPane(final int x
, final int y
,
2803 final int width
, final int height
, final boolean vertical
) {
2805 return new TSplitPane(this, x
, y
, width
, height
, vertical
);