menu system compiles
[nikiroo-utils.git] / src / jexer / menu / TMenuItem.java
1 /**
2 * Jexer - Java Text User Interface
3 *
4 * License: LGPLv3 or later
5 *
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
9 *
10 * Copyright (C) 2015 Kevin Lamonte
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * 02110-1301 USA
27 *
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 * @version 1
30 */
31 package jexer.menu;
32
33 import jexer.TKeypress;
34 import jexer.TWidget;
35 import jexer.bits.CellAttributes;
36 import jexer.bits.GraphicsChars;
37 import jexer.bits.MnemonicString;
38 import jexer.event.TKeypressEvent;
39 import jexer.event.TMouseEvent;
40 import jexer.event.TMenuEvent;
41 import static jexer.TKeypress.*;
42
43 /**
44 * TMenuItem implements a menu item.
45 */
46 public class TMenuItem extends TWidget {
47
48 /**
49 * Label for this menu item.
50 */
51 private String label;
52
53 /**
54 * Menu ID. IDs less than 1024 are reserved for common system
55 * functions. Existing ones are defined in TMenu, i.e. TMenu.MID_EXIT.
56 */
57 private int id = TMenu.MID_UNUSED;
58
59 /**
60 * When true, this item can be checked or unchecked.
61 */
62 private boolean checkable = false;
63
64 /**
65 * When true, this item is checked.
66 */
67 private boolean checked = false;
68
69 /**
70 * Global shortcut key.
71 */
72 private TKeypress key;
73
74 /**
75 * When true, a global accelerator can be used to select this item.
76 */
77 private boolean hasKey = false;
78
79 /**
80 * The title string. Use '&' to specify a mnemonic, i.e. "&File" will
81 * highlight the 'F' and allow 'f' or 'F' to select it.
82 */
83 private MnemonicString mnemonic;
84
85 /**
86 * Get the mnemonic string for this menu item.
87 *
88 * @return mnemonic string
89 */
90 public final MnemonicString getMnemonic() {
91 return mnemonic;
92 }
93
94 /**
95 * Set a global accelerator key for this menu item.
96 *
97 * @param key global keyboard accelerator
98 */
99 public final void setKey(final TKeypress key) {
100 hasKey = true;
101 this.key = key;
102
103 int newWidth = (label.length() + 4 + key.toString().length() + 2);
104 if (newWidth > getWidth()) {
105 setWidth(newWidth);
106 }
107 }
108
109 /**
110 * Package private constructor.
111 *
112 * @param parent parent widget
113 * @param id menu id
114 * @param x column relative to parent
115 * @param y row relative to parent
116 * @param label menu item title
117 */
118 TMenuItem(final TMenu parent, final int id, final int x, final int y,
119 final String label) {
120
121 // Set parent and window
122 super(parent);
123
124 mnemonic = new MnemonicString(label);
125
126 setX(x);
127 setY(y);
128 setHeight(1);
129 this.label = mnemonic.getRawLabel();
130 setWidth(label.length() + 4);
131 this.id = id;
132
133 // Default state for some known menu items
134 switch (id) {
135
136 case TMenu.MID_CUT:
137 setEnabled(false);
138 break;
139 case TMenu.MID_COPY:
140 setEnabled(false);
141 break;
142 case TMenu.MID_PASTE:
143 setEnabled(false);
144 break;
145 case TMenu.MID_CLEAR:
146 setEnabled(false);
147 break;
148
149 case TMenu.MID_TILE:
150 break;
151 case TMenu.MID_CASCADE:
152 break;
153 case TMenu.MID_CLOSE_ALL:
154 break;
155 case TMenu.MID_WINDOW_MOVE:
156 break;
157 case TMenu.MID_WINDOW_ZOOM:
158 break;
159 case TMenu.MID_WINDOW_NEXT:
160 break;
161 case TMenu.MID_WINDOW_PREVIOUS:
162 break;
163 case TMenu.MID_WINDOW_CLOSE:
164 break;
165 default:
166 break;
167 }
168
169 }
170
171 /**
172 * Returns true if the mouse is currently on the menu item.
173 *
174 * @param mouse mouse event
175 */
176 private boolean mouseOnMenuItem(final TMouseEvent mouse) {
177 if ((mouse.getY() == 0)
178 && (mouse.getX() >= 0)
179 && (mouse.getX() < getWidth())
180 ) {
181 return true;
182 }
183 return false;
184 }
185
186 /**
187 * Draw a menu item with label.
188 */
189 @Override
190 public void draw() {
191 CellAttributes background = getTheme().getColor("tmenu");
192 CellAttributes menuColor;
193 CellAttributes menuMnemonicColor;
194 if (getAbsoluteActive()) {
195 menuColor = getTheme().getColor("tmenu.highlighted");
196 menuMnemonicColor = getTheme().getColor("tmenu.mnemonic.highlighted");
197 } else {
198 if (getEnabled()) {
199 menuColor = getTheme().getColor("tmenu");
200 menuMnemonicColor = getTheme().getColor("tmenu.mnemonic");
201 } else {
202 menuColor = getTheme().getColor("tmenu.disabled");
203 menuMnemonicColor = getTheme().getColor("tmenu.disabled");
204 }
205 }
206
207 char cVSide = GraphicsChars.WINDOW_SIDE;
208 getScreen().vLineXY(0, 0, 1, cVSide, background);
209 getScreen().vLineXY(getWidth() - 1, 0, 1, cVSide, background);
210
211 getScreen().hLineXY(1, 0, getWidth() - 2, ' ', menuColor);
212 getScreen().putStrXY(2, 0, mnemonic.getRawLabel(), menuColor);
213 if (hasKey) {
214 String keyLabel = key.toString();
215 getScreen().putStrXY((getWidth() - keyLabel.length() - 2), 0,
216 keyLabel, menuColor);
217 }
218 if (mnemonic.getShortcutIdx() >= 0) {
219 getScreen().putCharXY(2 + mnemonic.getShortcutIdx(), 0,
220 mnemonic.getShortcut(), menuMnemonicColor);
221 }
222 if (checked) {
223 assert (checkable);
224 getScreen().putCharXY(1, 0, GraphicsChars.CHECK, menuColor);
225 }
226
227 }
228
229 /**
230 * Dispatch event(s) due to selection or click.
231 */
232 public void dispatch() {
233 assert (getEnabled());
234
235 getApplication().addMenuEvent(new TMenuEvent(id));
236 if (checkable) {
237 checked = !checked;
238 }
239 }
240
241 /**
242 * Handle mouse button presses.
243 *
244 * @param event mouse button press event
245 */
246 /* TODO: this was commented out in d-tui, why?
247 @Override
248 public void onMouseDown(final TMouseEvent event) {
249 if ((mouseOnMenuItem(event)) && (event.mouse1)) {
250 dispatch();
251 return;
252 }
253 }
254 */
255
256 /**
257 * Handle mouse button releases.
258 *
259 * @param mouse mouse button release event
260 */
261 @Override
262 public void onMouseUp(final TMouseEvent mouse) {
263 if ((mouseOnMenuItem(mouse)) && (mouse.getMouse1())) {
264 dispatch();
265 return;
266 }
267 }
268
269 /**
270 * Handle keystrokes.
271 *
272 * @param keypress keystroke event
273 */
274 @Override
275 public void onKeypress(final TKeypressEvent keypress) {
276 if (keypress.equals(kbEnter)) {
277 dispatch();
278 return;
279 }
280
281 // Pass to parent for the things we don't care about.
282 super.onKeypress(keypress);
283 }
284 }