Merge branch 'upstream' into subtree
[nikiroo-utils.git] / menu / TSubMenu.java
1 /*
2 * Jexer - Java Text User Interface
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (C) 2019 Kevin Lamonte
7 *
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:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
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.
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29 package jexer.menu;
30
31 import jexer.TKeypress;
32 import jexer.TWidget;
33 import jexer.bits.CellAttributes;
34 import jexer.bits.GraphicsChars;
35 import jexer.event.TKeypressEvent;
36 import static jexer.TKeypress.*;
37
38 /**
39 * TSubMenu is a special case menu item that wraps another TMenu.
40 */
41 public class TSubMenu extends TMenuItem {
42
43 // ------------------------------------------------------------------------
44 // Variables --------------------------------------------------------------
45 // ------------------------------------------------------------------------
46
47 /**
48 * The menu window. Note package private access.
49 */
50 TMenu menu;
51
52 // ------------------------------------------------------------------------
53 // Constructors -----------------------------------------------------------
54 // ------------------------------------------------------------------------
55
56 /**
57 * Package private constructor.
58 *
59 * @param parent parent widget
60 * @param title menu title. Title must contain a keyboard shortcut,
61 * denoted by prefixing a letter with "&", e.g. "&File"
62 * @param x column relative to parent
63 * @param y row relative to parent
64 */
65 TSubMenu(final TMenu parent, final String title, final int x, final int y) {
66 super(parent, TMenu.MID_UNUSED, x, y, title);
67
68 setActive(false);
69 setEnabled(true);
70
71 this.menu = new TMenu(parent.getApplication(), x, getAbsoluteY() - 1,
72 title);
73 setWidth(menu.getWidth() + 2);
74
75 this.menu.isSubMenu = true;
76 }
77
78 // ------------------------------------------------------------------------
79 // Event handlers ---------------------------------------------------------
80 // ------------------------------------------------------------------------
81
82 /**
83 * Handle keystrokes.
84 *
85 * @param keypress keystroke event
86 */
87 @Override
88 public void onKeypress(final TKeypressEvent keypress) {
89
90 // Open me if they hit my mnemonic.
91 if (!keypress.getKey().isFnKey()
92 && !keypress.getKey().isAlt()
93 && !keypress.getKey().isCtrl()
94 && (getMnemonic() != null)
95 && (Character.toLowerCase(getMnemonic().getShortcut())
96 == Character.toLowerCase(keypress.getKey().getChar()))
97 ) {
98 dispatch();
99 return;
100 }
101
102 if (menu.isActive()) {
103 menu.onKeypress(keypress);
104 return;
105 }
106
107 if (keypress.equals(kbEnter)) {
108 dispatch();
109 return;
110 }
111
112 if (keypress.equals(kbRight)) {
113 dispatch();
114 return;
115 }
116
117 if (keypress.equals(kbDown)) {
118 getParent().switchWidget(true);
119 return;
120 }
121
122 if (keypress.equals(kbUp)) {
123 getParent().switchWidget(false);
124 return;
125 }
126
127 if (keypress.equals(kbLeft)) {
128 TMenu parentMenu = (TMenu) getParent();
129 if (parentMenu.isSubMenu) {
130 getApplication().closeSubMenu();
131 } else {
132 getApplication().switchMenu(false);
133 }
134 return;
135 }
136
137 if (keypress.equals(kbEsc)) {
138 getApplication().closeMenu();
139 return;
140 }
141 }
142
143 // ------------------------------------------------------------------------
144 // TMenuItem --------------------------------------------------------------
145 // ------------------------------------------------------------------------
146
147 /**
148 * Draw the menu title.
149 */
150 @Override
151 public void draw() {
152 super.draw();
153
154 CellAttributes menuColor;
155 if (isAbsoluteActive()) {
156 menuColor = getTheme().getColor("tmenu.highlighted");
157 } else {
158 if (isEnabled()) {
159 menuColor = getTheme().getColor("tmenu");
160 } else {
161 menuColor = getTheme().getColor("tmenu.disabled");
162 }
163 }
164
165 // Add the arrow
166 putCharXY(getWidth() - 2, 0, GraphicsChars.CP437[0x10], menuColor);
167 }
168
169 /**
170 * Override dispatch() to do nothing.
171 */
172 @Override
173 public void dispatch() {
174 assert (isEnabled());
175 if (isAbsoluteActive()) {
176 if (!menu.isActive()) {
177 getApplication().addSubMenu(menu);
178 menu.setActive(true);
179 }
180 }
181 }
182
183 /**
184 * Returns my active widget.
185 *
186 * @return widget that is active, or this if no children
187 */
188 @Override
189 public TWidget getActiveChild() {
190 if (menu.isActive()) {
191 return menu;
192 }
193 // Menu not active, return me
194 return this;
195 }
196
197 // ------------------------------------------------------------------------
198 // TSubMenu ---------------------------------------------------------------
199 // ------------------------------------------------------------------------
200
201 /**
202 * Convenience function to add a custom menu item.
203 *
204 * @param id menu item ID. Must be greater than 1024.
205 * @param label menu item label
206 * @param key global keyboard accelerator
207 * @return the new menu item
208 */
209 public TMenuItem addItem(final int id, final String label,
210 final TKeypress key) {
211
212 return menu.addItem(id, label, key);
213 }
214
215 /**
216 * Convenience function to add a custom menu item.
217 *
218 * @param id menu item ID. Must be greater than 1024.
219 * @param label menu item label
220 * @param key global keyboard accelerator
221 * @param enabled default state for enabled
222 * @return the new menu item
223 */
224 public TMenuItem addItem(final int id, final String label,
225 final TKeypress key, final boolean enabled) {
226
227 return menu.addItem(id, label, key, enabled);
228 }
229
230 /**
231 * Convenience function to add a menu item.
232 *
233 * @param id menu item ID. Must be greater than 1024.
234 * @param label menu item label
235 * @return the new menu item
236 */
237 public TMenuItem addItem(final int id, final String label) {
238 return menu.addItem(id, label);
239 }
240
241 /**
242 * Convenience function to add a menu item.
243 *
244 * @param id menu item ID. Must be greater than 1024.
245 * @param label menu item label
246 * @param enabled default state for enabled
247 * @return the new menu item
248 */
249 public TMenuItem addItem(final int id, final String label,
250 final boolean enabled) {
251
252 return menu.addItem(id, label, enabled);
253 }
254
255 /**
256 * Convenience function to add one of the default menu items.
257 *
258 * @param id menu item ID. Must be between 0 (inclusive) and 1023
259 * (inclusive).
260 * @return the new menu item
261 */
262 public TMenuItem addDefaultItem(final int id) {
263 return menu.addDefaultItem(id);
264 }
265
266 /**
267 * Convenience function to add one of the default menu items.
268 *
269 * @param id menu item ID. Must be between 0 (inclusive) and 1023
270 * (inclusive).
271 * @param enabled default state for enabled
272 * @return the new menu item
273 */
274 public TMenuItem addDefaultItem(final int id, final boolean enabled) {
275 return menu.addDefaultItem(id, enabled);
276 }
277
278 /**
279 * Convenience function to add a menu separator.
280 */
281 public void addSeparator() {
282 menu.addSeparator();
283 }
284
285 /**
286 * Convenience function to add a sub-menu.
287 *
288 * @param title menu title. Title must contain a keyboard shortcut,
289 * denoted by prefixing a letter with "&", e.g. "&File"
290 * @return the new sub-menu
291 */
292 public TSubMenu addSubMenu(final String title) {
293 return menu.addSubMenu(title);
294 }
295
296 }