2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2017 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
.io
.IOException
;
32 import java
.util
.List
;
33 import java
.util
.ArrayList
;
35 import jexer
.backend
.Screen
;
36 import jexer
.bits
.ColorTheme
;
37 import jexer
.event
.TCommandEvent
;
38 import jexer
.event
.TInputEvent
;
39 import jexer
.event
.TKeypressEvent
;
40 import jexer
.event
.TMenuEvent
;
41 import jexer
.event
.TMouseEvent
;
42 import jexer
.event
.TResizeEvent
;
43 import jexer
.menu
.TMenu
;
44 import jexer
.ttree
.TTreeItem
;
45 import jexer
.ttree
.TTreeView
;
46 import jexer
.ttree
.TTreeViewWidget
;
47 import static jexer
.TKeypress
.*;
50 * TWidget is the base class of all objects that can be drawn on screen or
51 * handle user input events.
53 public abstract class TWidget
implements Comparable
<TWidget
> {
55 // ------------------------------------------------------------------------
56 // Variables --------------------------------------------------------------
57 // ------------------------------------------------------------------------
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.
64 private TWidget parent
= null;
67 * Child widgets that this widget contains.
69 private List
<TWidget
> children
;
72 * The currently active child widget that will receive keypress events.
74 private TWidget activeChild
= null;
77 * If true, this widget will receive events.
79 private boolean active
= false;
82 * The window that this widget draws to.
84 private TWindow window
= null;
87 * Absolute X position of the top-left corner.
92 * Absolute Y position of the top-left corner.
99 private int width
= 0;
104 private int height
= 0;
107 * My tab order inside a window or containing widget.
109 private int tabOrder
= 0;
112 * If true, this widget can be tabbed to or receive events.
114 private boolean enabled
= true;
117 * If true, this widget has a cursor.
119 private boolean cursorVisible
= false;
122 * Cursor column position in relative coordinates.
124 private int cursorX
= 0;
127 * Cursor row position in relative coordinates.
129 private int cursorY
= 0;
131 // ------------------------------------------------------------------------
132 // Constructors -----------------------------------------------------------
133 // ------------------------------------------------------------------------
136 * Default constructor for subclasses.
138 protected TWidget() {
139 children
= new ArrayList
<TWidget
>();
143 * Protected constructor.
145 * @param parent parent widget
147 protected TWidget(final TWidget parent
) {
152 * Protected constructor.
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
160 protected TWidget(final TWidget parent
, final int x
, final int y
,
161 final int width
, final int height
) {
163 this(parent
, true, x
, y
, width
, height
);
167 * Protected constructor used by subclasses that are disabled by default.
169 * @param parent parent widget
170 * @param enabled if true assume enabled
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
>();
178 // Do not add TStatusBars, they are drawn by TApplication
179 if (this instanceof TStatusBar
) {
181 parent
.addChild(this);
186 * Protected constructor used by subclasses that are disabled by default.
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
195 protected TWidget(final TWidget parent
, final boolean enabled
,
196 final int x
, final int y
, final int width
, final int height
) {
198 this.enabled
= enabled
;
199 this.parent
= parent
;
200 this.window
= parent
.window
;
201 children
= new ArrayList
<TWidget
>();
203 // Do not add TStatusBars, they are drawn by TApplication
204 if (this instanceof TStatusBar
) {
206 parent
.addChild(this);
212 this.height
= height
;
216 * Backdoor access for TWindow's constructor. ONLY TWindow USES THIS.
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
224 protected final void setupForTWindow(final TWindow window
,
225 final int x
, final int y
, final int width
, final int height
) {
227 this.parent
= window
;
228 this.window
= window
;
232 this.height
= height
;
235 // ------------------------------------------------------------------------
236 // Event handlers ---------------------------------------------------------
237 // ------------------------------------------------------------------------
240 * Check if a mouse press/release event coordinate is contained in this
243 * @param mouse a mouse-based event
244 * @return whether or not a mouse click would be sent to this widget
246 public final boolean mouseWouldHit(final TMouseEvent mouse
) {
252 if ((this instanceof TTreeItem
)
253 && ((y
< 0) || (y
> parent
.getHeight() - 1))
258 if ((mouse
.getAbsoluteX() >= getAbsoluteX())
259 && (mouse
.getAbsoluteX() < getAbsoluteX() + width
)
260 && (mouse
.getAbsoluteY() >= getAbsoluteY())
261 && (mouse
.getAbsoluteY() < getAbsoluteY() + height
)
269 * Method that subclasses can override to handle keystrokes.
271 * @param keypress keystroke event
273 public void onKeypress(final TKeypressEvent keypress
) {
275 if ((children
.size() == 0)
276 || (this instanceof TTreeView
)
277 || (this instanceof TText
)
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
))
286 parent
.switchWidget(true);
288 } else if ((keypress
.equals(kbShiftTab
))
289 || (keypress
.equals(kbBackTab
))
290 || (keypress
.equals(kbUp
))
292 parent
.switchWidget(false);
297 if ((children
.size() == 0)
298 && !(this instanceof TTreeView
)
302 // right-arrow or down-arrow: same as tab
303 if (keypress
.equals(kbRight
)) {
304 parent
.switchWidget(true);
306 } else if (keypress
.equals(kbLeft
)) {
307 parent
.switchWidget(false);
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()))
325 widget
.onKeypress(new TKeypressEvent(kbEnter
));
331 // Dispatch the keypress to an active widget
332 for (TWidget widget
: children
) {
334 widget
.onKeypress(keypress
);
341 * Method that subclasses can override to handle mouse button presses.
343 * @param mouse mouse button event
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
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
);
363 * Method that subclasses can override to handle mouse button releases.
365 * @param mouse mouse button event
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
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
);
385 * Method that subclasses can override to handle mouse movements.
387 * @param mouse mouse motion event
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
);
401 * Method that subclasses can override to handle mouse button
404 * @param mouse mouse button event
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
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
);
424 * Method that subclasses can override to handle window/screen resize
427 * @param resize resize event
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();
435 // Let children see the screen resize
436 for (TWidget widget
: children
) {
437 widget
.onResize(resize
);
443 * Method that subclasses can override to handle posted command events.
445 * @param command command event
447 public void onCommand(final TCommandEvent command
) {
448 // Default: do nothing, pass to children instead
449 for (TWidget widget
: children
) {
450 widget
.onCommand(command
);
455 * Method that subclasses can override to handle menu or posted menu
458 * @param menu menu event
460 public void onMenu(final TMenuEvent menu
) {
461 // Default: do nothing, pass to children instead
462 for (TWidget widget
: children
) {
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().
472 public void onIdle() {
473 // Default: do nothing, pass to children instead
474 for (TWidget widget
: children
) {
480 * Consume event. Subclasses that want to intercept all events in one go
481 * can override this method.
483 * @param event keyboard, mouse, resize, command, or menu event
485 public void handleEvent(final TInputEvent event
) {
487 System.err.printf("TWidget (%s) event: %s\n", this.getClass().getName(),
493 // System.err.println(" -- discard --");
497 if (event
instanceof TKeypressEvent
) {
498 onKeypress((TKeypressEvent
) event
);
499 } else if (event
instanceof TMouseEvent
) {
501 TMouseEvent mouse
= (TMouseEvent
) event
;
503 switch (mouse
.getType()) {
514 onMouseMotion(mouse
);
517 case MOUSE_DOUBLE_CLICK
:
518 onMouseDoubleClick(mouse
);
522 throw new IllegalArgumentException("Invalid mouse event type: "
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
);
537 // ------------------------------------------------------------------------
538 // TWidget ----------------------------------------------------------------
539 // ------------------------------------------------------------------------
544 * @return parent widget
546 public final TWidget
getParent() {
551 * Get the list of child widgets that this widget contains.
553 * @return the list of child widgets
555 public List
<TWidget
> getChildren() {
562 * @return if true, this widget will receive events
564 public final boolean isActive() {
571 * @param active if true, this widget will receive events
573 public final void setActive(final boolean active
) {
574 this.active
= active
;
578 * Get the window this widget is on.
582 public final TWindow
getWindow() {
589 * @return absolute X position of the top-left corner
591 public final int getX() {
598 * @param x absolute X position of the top-left corner
600 public final void setX(final int x
) {
607 * @return absolute Y position of the top-left corner
609 public final int getY() {
616 * @param y absolute Y position of the top-left corner
618 public final void setY(final int y
) {
625 * @return widget width
627 public final int getWidth() {
634 * @param width new widget width
636 public final void setWidth(final int width
) {
643 * @return widget height
645 public final int getHeight() {
652 * @param height new widget height
654 public final void setHeight(final int height
) {
655 this.height
= height
;
659 * Change the dimensions.
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
666 public final void setDimensions(final int x
, final int y
, final int width
,
678 * @return if true, this widget can be tabbed to or receive events
680 public final boolean isEnabled() {
687 * @param enabled if true, this widget can be tabbed to or receive events
689 public final void setEnabled(final boolean enabled
) {
690 this.enabled
= enabled
;
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
) {
698 && !(this instanceof THScroller
)
699 && !(this instanceof TVScroller
)
707 parent
.activeChild
= null;
714 * Set visible cursor flag.
716 * @param cursorVisible if true, this widget has a cursor
718 public final void setCursorVisible(final boolean cursorVisible
) {
719 this.cursorVisible
= cursorVisible
;
723 * See if this widget has a visible cursor.
725 * @return if true, this widget has a visible cursor
727 public final boolean isCursorVisible() {
728 // If cursor is out of my bounds, it is not visible.
729 if ((cursorX
>= width
)
731 || (cursorY
>= height
)
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)
747 return cursorVisible
;
751 * Get cursor X value.
753 * @return cursor column position in relative coordinates
755 public final int getCursorX() {
760 * Set cursor X value.
762 * @param cursorX column position in relative coordinates
764 public final void setCursorX(final int cursorX
) {
765 this.cursorX
= cursorX
;
769 * Get cursor Y value.
771 * @return cursor row position in relative coordinates
773 public final int getCursorY() {
778 * Set cursor Y value.
780 * @param cursorY row position in relative coordinates
782 public final void setCursorY(final int cursorY
) {
783 this.cursorY
= cursorY
;
787 * Get this TWidget's parent TApplication.
789 * @return the parent TApplication
791 public TApplication
getApplication() {
792 return window
.getApplication();
800 public Screen
getScreen() {
801 return window
.getScreen();
805 * Comparison operator. For various subclasses it sorts on:
807 * <li>tabOrder for TWidgets</li>
808 * <li>z for TWindows</li>
809 * <li>text for TTreeItems</li>
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)
816 public final int compareTo(final TWidget that
) {
817 if ((this instanceof TWindow
)
818 && (that
instanceof TWindow
)
820 return (((TWindow
) this).getZ() - ((TWindow
) that
).getZ());
822 if ((this instanceof TTreeItem
)
823 && (that
instanceof TTreeItem
)
825 return (((TTreeItem
) this).getText().compareTo(
826 ((TTreeItem
) that
).getText()));
828 return (this.tabOrder
- that
.tabOrder
);
832 * See if this widget should render with the active color.
834 * @return true if this widget is active and all of its parents are
837 public final boolean isAbsoluteActive() {
838 if (parent
== this) {
841 return (active
&& parent
.isAbsoluteActive());
845 * Returns the cursor X position.
847 * @return absolute screen column number for the cursor's X position
849 public final int getCursorAbsoluteX() {
850 return getAbsoluteX() + cursorX
;
854 * Returns the cursor Y position.
856 * @return absolute screen row number for the cursor's Y position
858 public final int getCursorAbsoluteY() {
859 return getAbsoluteY() + cursorY
;
863 * Compute my absolute X position as the sum of my X plus all my parent's
866 * @return absolute screen column number for my X position
868 public final int getAbsoluteX() {
869 assert (parent
!= null);
870 if (parent
== this) {
873 if ((parent
instanceof TWindow
)
874 && !(parent
instanceof TMenu
)
875 && !(parent
instanceof TDesktop
)
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;
881 return parent
.getAbsoluteX() + x
;
885 * Compute my absolute Y position as the sum of my Y plus all my parent's
888 * @return absolute screen row number for my Y position
890 public final int getAbsoluteY() {
891 assert (parent
!= null);
892 if (parent
== this) {
895 if ((parent
instanceof TWindow
)
896 && !(parent
instanceof TMenu
)
897 && !(parent
instanceof TDesktop
)
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;
903 return parent
.getAbsoluteY() + y
;
907 * Get the global color theme.
909 * @return the ColorTheme
911 public final ColorTheme
getTheme() {
912 return window
.getApplication().getTheme();
916 * Draw my specific widget. When called, the screen rectangle I draw
917 * into is already setup (offset and clipping).
920 // Default widget draws nothing.
924 * Called by parent to render to TWindow.
926 public final void drawChildren() {
927 // Set my clipping rectangle
928 assert (window
!= null);
929 assert (getScreen() != null);
930 Screen screen
= getScreen();
932 // Special case: TStatusBar is drawn by TApplication, not anything
934 if (this instanceof TStatusBar
) {
938 screen
.setClipRight(width
);
939 screen
.setClipBottom(height
);
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;
946 if (!(this instanceof TWindow
) && !(this instanceof THScroller
)) {
947 absoluteBottomEdge
-= 1;
949 int myRightEdge
= getAbsoluteX() + width
;
950 int myBottomEdge
= getAbsoluteY() + height
;
951 if (getAbsoluteX() > absoluteRightEdge
) {
953 screen
.setClipRight(0);
954 } else if (myRightEdge
> absoluteRightEdge
) {
955 screen
.setClipRight(screen
.getClipRight()
956 - (myRightEdge
- absoluteRightEdge
));
958 if (getAbsoluteY() > absoluteBottomEdge
) {
960 screen
.setClipBottom(0);
961 } else if (myBottomEdge
> absoluteBottomEdge
) {
962 screen
.setClipBottom(screen
.getClipBottom()
963 - (myBottomEdge
- absoluteBottomEdge
));
967 screen
.setOffsetX(getAbsoluteX());
968 screen
.setOffsetY(getAbsoluteY());
973 // Continue down the chain
974 for (TWidget widget
: children
) {
975 widget
.drawChildren();
980 * Repaint the screen on the next update.
982 public void doRepaint() {
983 window
.getApplication().doRepaint();
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.
990 * @param child TWidget to add
992 private void addChild(final TWidget child
) {
996 && !(child
instanceof THScroller
)
997 && !(child
instanceof TVScroller
)
999 for (TWidget widget
: children
) {
1000 widget
.active
= false;
1002 child
.active
= true;
1003 activeChild
= child
;
1005 for (int i
= 0; i
< children
.size(); i
++) {
1006 children
.get(i
).tabOrder
= i
;
1011 * Switch the active child.
1013 * @param child TWidget to activate
1015 public final void activate(final TWidget child
) {
1016 assert (child
.enabled
);
1017 if ((child
instanceof THScroller
)
1018 || (child
instanceof TVScroller
)
1023 if (child
!= activeChild
) {
1024 if (activeChild
!= null) {
1025 activeChild
.active
= false;
1027 child
.active
= true;
1028 activeChild
= child
;
1033 * Switch the active child.
1035 * @param tabOrder tabOrder of the child to activate. If that child
1036 * isn't enabled, then the next enabled child will be activated.
1038 public final void activate(final int tabOrder
) {
1039 if (activeChild
== null) {
1042 TWidget child
= null;
1043 for (TWidget widget
: children
) {
1044 if ((widget
.enabled
)
1045 && !(widget
instanceof THScroller
)
1046 && !(widget
instanceof TVScroller
)
1047 && (widget
.tabOrder
>= tabOrder
)
1053 if ((child
!= null) && (child
!= activeChild
)) {
1054 activeChild
.active
= false;
1055 assert (child
.enabled
);
1056 child
.active
= true;
1057 activeChild
= child
;
1062 * Switch the active widget with the next in the tab order.
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
1067 public final void switchWidget(final boolean forward
) {
1069 // Only switch if there are multiple enabled widgets
1070 if ((children
.size() < 2) || (activeChild
== null)) {
1074 int tabOrder
= activeChild
.tabOrder
;
1083 // If at the end, pass the switch to my parent.
1084 if ((!forward
) && (parent
!= this)) {
1085 parent
.switchWidget(forward
);
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
);
1099 if (activeChild
.tabOrder
== tabOrder
) {
1100 // We wrapped around
1103 } while ((!children
.get(tabOrder
).enabled
)
1104 && !(children
.get(tabOrder
) instanceof THScroller
)
1105 && !(children
.get(tabOrder
) instanceof TVScroller
));
1107 assert (children
.get(tabOrder
).enabled
);
1109 activeChild
.active
= false;
1110 children
.get(tabOrder
).active
= true;
1111 activeChild
= children
.get(tabOrder
);
1115 * Returns my active widget.
1117 * @return widget that is active, or this if no children
1119 public TWidget
getActiveChild() {
1120 if ((this instanceof THScroller
)
1121 || (this instanceof TVScroller
)
1126 for (TWidget widget
: children
) {
1127 if (widget
.active
) {
1128 return widget
.getActiveChild();
1131 // No active children, return me
1135 // ------------------------------------------------------------------------
1136 // Other TWidget constructors ---------------------------------------------
1137 // ------------------------------------------------------------------------
1140 * Convenience function to add a label to this container/window.
1143 * @param x column relative to parent
1144 * @param y row relative to parent
1145 * @return the new label
1147 public final TLabel
addLabel(final String text
, final int x
, final int y
) {
1148 return addLabel(text
, x
, y
, "tlabel");
1152 * Convenience function to add a label to this container/window.
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
1161 public final TLabel
addLabel(final String text
, final int x
, final int y
,
1162 final String colorKey
) {
1164 return new TLabel(this, text
, x
, y
, colorKey
);
1168 * Convenience function to add a button to this container/window.
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
1176 public final TButton
addButton(final String text
, final int x
, final int y
,
1177 final TAction action
) {
1179 return new TButton(this, text
, x
, y
, action
);
1183 * Convenience function to add a checkbox to this container/window.
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
1191 public final TCheckbox
addCheckbox(final int x
, final int y
,
1192 final String label
, final boolean checked
) {
1194 return new TCheckbox(this, x
, y
, label
, checked
);
1198 * Convenience function to add a progress bar to this container/window.
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
1204 * @return the new progress bar
1206 public final TProgressBar
addProgressBar(final int x
, final int y
,
1207 final int width
, final int value
) {
1209 return new TProgressBar(this, x
, y
, width
, value
);
1213 * Convenience function to add a radio button group to this
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
1221 public final TRadioGroup
addRadioGroup(final int x
, final int y
,
1222 final String label
) {
1224 return new TRadioGroup(this, x
, y
, label
);
1228 * Convenience function to add a text field to this container/window.
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
1236 public final TField
addField(final int x
, final int y
,
1237 final int width
, final boolean fixed
) {
1239 return new TField(this, x
, y
, width
, fixed
);
1243 * Convenience function to add a text field to this container/window.
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
1252 public final TField
addField(final int x
, final int y
,
1253 final int width
, final boolean fixed
, final String text
) {
1255 return new TField(this, x
, y
, width
, fixed
, text
);
1259 * Convenience function to add a text field to this container/window.
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
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
) {
1274 return new TField(this, x
, y
, width
, fixed
, text
, enterAction
,
1279 * Convenience function to add a scrollable text box to this
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
1290 public final TText
addText(final String text
, final int x
,
1291 final int y
, final int width
, final int height
, final String colorKey
) {
1293 return new TText(this, text
, x
, y
, width
, height
, colorKey
);
1297 * Convenience function to add a scrollable text box to this
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
1307 public final TText
addText(final String text
, final int x
, final int y
,
1308 final int width
, final int height
) {
1310 return new TText(this, text
, x
, y
, width
, height
, "ttext");
1314 * Convenience function to add an editable text area box to this
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
1324 public final TEditorWidget
addEditor(final String text
, final int x
,
1325 final int y
, final int width
, final int height
) {
1327 return new TEditorWidget(this, text
, x
, y
, width
, height
);
1331 * Convenience function to spawn a message box.
1333 * @param title window title, will be centered along the top border
1334 * @param caption message to display. Use embedded newlines to get a
1336 * @return the new message box
1338 public final TMessageBox
messageBox(final String title
,
1339 final String caption
) {
1341 return getApplication().messageBox(title
, caption
, TMessageBox
.Type
.OK
);
1345 * Convenience function to spawn a message box.
1347 * @param title window title, will be centered along the top border
1348 * @param caption message to display. Use embedded newlines to get a
1350 * @param type one of the TMessageBox.Type constants. Default is
1352 * @return the new message box
1354 public final TMessageBox
messageBox(final String title
,
1355 final String caption
, final TMessageBox
.Type type
) {
1357 return getApplication().messageBox(title
, caption
, type
);
1361 * Convenience function to spawn an input box.
1363 * @param title window title, will be centered along the top border
1364 * @param caption message to display. Use embedded newlines to get a
1366 * @return the new input box
1368 public final TInputBox
inputBox(final String title
, final String caption
) {
1370 return getApplication().inputBox(title
, caption
);
1374 * Convenience function to spawn an input box.
1376 * @param title window title, will be centered along the top border
1377 * @param caption message to display. Use embedded newlines to get a
1379 * @param text initial text to seed the field with
1380 * @return the new input box
1382 public final TInputBox
inputBox(final String title
, final String caption
,
1383 final String text
) {
1385 return getApplication().inputBox(title
, caption
, text
);
1389 * Convenience function to add a password text field to this
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
1398 public final TPasswordField
addPasswordField(final int x
, final int y
,
1399 final int width
, final boolean fixed
) {
1401 return new TPasswordField(this, x
, y
, width
, fixed
);
1405 * Convenience function to add a password text field to this
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
1415 public final TPasswordField
addPasswordField(final int x
, final int y
,
1416 final int width
, final boolean fixed
, final String text
) {
1418 return new TPasswordField(this, x
, y
, width
, fixed
, text
);
1422 * Convenience function to add a password text field to this
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
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
) {
1438 return new TPasswordField(this, x
, y
, width
, fixed
, text
, enterAction
,
1443 * Convenience function to add a scrollable tree view to this
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
1450 * @return the new tree view
1452 public final TTreeViewWidget
addTreeViewWidget(final int x
, final int y
,
1453 final int width
, final int height
) {
1455 return new TTreeViewWidget(this, x
, y
, width
, height
);
1459 * Convenience function to add a scrollable tree view to this
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
1467 * @return the new tree view
1469 public final TTreeViewWidget
addTreeViewWidget(final int x
, final int y
,
1470 final int width
, final int height
, final TAction action
) {
1472 return new TTreeViewWidget(this, x
, y
, width
, height
, action
);
1476 * Convenience function to spawn a file open box.
1478 * @param path path of selected file
1479 * @return the result of the new file open box
1480 * @throws IOException if a java.io operation throws
1482 public final String
fileOpenBox(final String path
) throws IOException
{
1483 return getApplication().fileOpenBox(path
);
1487 * Convenience function to spawn a file open box.
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
1492 * @throws IOException if a java.io operation throws
1494 public final String
fileOpenBox(final String path
,
1495 final TFileOpenBox
.Type type
) throws IOException
{
1497 return getApplication().fileOpenBox(path
, type
);
1500 * Convenience function to add a directory list to this container/window.
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
1507 * @return the new directory list
1509 public final TDirectoryList
addDirectoryList(final String path
, final int x
,
1510 final int y
, final int width
, final int height
) {
1512 return new TDirectoryList(this, path
, x
, y
, width
, height
, null);
1516 * Convenience function to add a directory list to this container/window.
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
1524 * @return the new directory list
1526 public final TDirectoryList
addDirectoryList(final String path
, final int x
,
1527 final int y
, final int width
, final int height
, final TAction action
) {
1529 return new TDirectoryList(this, path
, x
, y
, width
, height
, action
);
1533 * Convenience function to add a directory list to this container/window.
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
1542 public final TList
addList(final List
<String
> strings
, final int x
,
1543 final int y
, final int width
, final int height
) {
1545 return new TList(this, strings
, x
, y
, width
, height
, null);
1549 * Convenience function to add a directory list to this container/window.
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
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
) {
1563 return new TList(this, strings
, x
, y
, width
, height
, enterAction
);
1567 * Convenience function to add a directory list to this container/window.
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
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
) {
1583 return new TList(this, strings
, x
, y
, width
, height
, enterAction
,