Add 'src/jexer/' from commit 'cf01c92f5809a0732409e280fb0f32f27393618d'
[fanfix.git] / src / jexer / 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 menu item.
217 *
218 * @param id menu item ID. Must be greater than 1024.
219 * @param label menu item label
220 * @return the new menu item
221 */
222 public TMenuItem addItem(final int id, final String label) {
223 return menu.addItem(id, label);
224 }
225
226 /**
227 * Convenience function to add one of the default menu items.
228 *
229 * @param id menu item ID. Must be between 0 (inclusive) and 1023
230 * (inclusive).
231 * @return the new menu item
232 */
233 public TMenuItem addDefaultItem(final int id) {
234 return menu.addDefaultItem(id);
235 }
236
237 /**
238 * Convenience function to add one of the default menu items.
239 *
240 * @param id menu item ID. Must be between 0 (inclusive) and 1023
241 * (inclusive).
242 * @param enabled default state for enabled
243 * @return the new menu item
244 */
245 public TMenuItem addDefaultItem(final int id, final boolean enabled) {
246 return menu.addDefaultItem(id, enabled);
247 }
248
249 /**
250 * Convenience function to add a menu separator.
251 */
252 public void addSeparator() {
253 menu.addSeparator();
254 }
255
256 /**
257 * Convenience function to add a sub-menu.
258 *
259 * @param title menu title. Title must contain a keyboard shortcut,
260 * denoted by prefixing a letter with "&", e.g. "&File"
261 * @return the new sub-menu
262 */
263 public TSubMenu addSubMenu(final String title) {
264 return menu.addSubMenu(title);
265 }
266
267 }