089887006d1f15bc8400c4b0b73319ecd75f5123
[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 * Get the menu item ID.
61 *
62 * @return the id
63 */
64 public final int getId() {
65 return id;
66 }
67
68 /**
69 * When true, this item can be checked or unchecked.
70 */
71 private boolean checkable = false;
72
73 /**
74 * Set checkable flag.
75 *
76 * @param checkable if true, this menu item can be checked/unchecked
77 */
78 public final void setCheckable(final boolean checkable) {
79 this.checkable = checkable;
80 }
81
82 /**
83 * When true, this item is checked.
84 */
85 private boolean checked = false;
86
87 /**
88 * Global shortcut key.
89 */
90 private TKeypress key;
91
92 /**
93 * The title string. Use '&' to specify a mnemonic, i.e. "&File" will
94 * highlight the 'F' and allow 'f' or 'F' to select it.
95 */
96 private MnemonicString mnemonic;
97
98 /**
99 * Get the mnemonic string for this menu item.
100 *
101 * @return mnemonic string
102 */
103 public final MnemonicString getMnemonic() {
104 return mnemonic;
105 }
106
107 /**
108 * Get a global accelerator key for this menu item.
109 *
110 * @return global keyboard accelerator, or null if no key is associated
111 * with this item
112 */
113 public final TKeypress getKey() {
114 return key;
115 }
116
117 /**
118 * Set a global accelerator key for this menu item.
119 *
120 * @param key global keyboard accelerator
121 */
122 public final void setKey(final TKeypress key) {
123 this.key = key;
124
125 if (key != null) {
126 int newWidth = (label.length() + 4 + key.toString().length() + 2);
127 if (newWidth > getWidth()) {
128 setWidth(newWidth);
129 }
130 }
131 }
132
133 /**
134 * Package private constructor.
135 *
136 * @param parent parent widget
137 * @param id menu id
138 * @param x column relative to parent
139 * @param y row relative to parent
140 * @param label menu item title
141 */
142 TMenuItem(final TMenu parent, final int id, final int x, final int y,
143 final String label) {
144
145 // Set parent and window
146 super(parent);
147
148 mnemonic = new MnemonicString(label);
149
150 setX(x);
151 setY(y);
152 setHeight(1);
153 this.label = mnemonic.getRawLabel();
154 setWidth(label.length() + 4);
155 this.id = id;
156
157 // Default state for some known menu items
158 switch (id) {
159
160 case TMenu.MID_CUT:
161 setEnabled(false);
162 break;
163 case TMenu.MID_COPY:
164 setEnabled(false);
165 break;
166 case TMenu.MID_PASTE:
167 setEnabled(false);
168 break;
169 case TMenu.MID_CLEAR:
170 setEnabled(false);
171 break;
172
173 case TMenu.MID_TILE:
174 break;
175 case TMenu.MID_CASCADE:
176 break;
177 case TMenu.MID_CLOSE_ALL:
178 break;
179 case TMenu.MID_WINDOW_MOVE:
180 break;
181 case TMenu.MID_WINDOW_ZOOM:
182 break;
183 case TMenu.MID_WINDOW_NEXT:
184 break;
185 case TMenu.MID_WINDOW_PREVIOUS:
186 break;
187 case TMenu.MID_WINDOW_CLOSE:
188 break;
189 default:
190 break;
191 }
192
193 }
194
195 /**
196 * Returns true if the mouse is currently on the menu item.
197 *
198 * @param mouse mouse event
199 * @return if true then the mouse is currently on this item
200 */
201 private boolean mouseOnMenuItem(final TMouseEvent mouse) {
202 if ((mouse.getY() == 0)
203 && (mouse.getX() >= 0)
204 && (mouse.getX() < getWidth())
205 ) {
206 return true;
207 }
208 return false;
209 }
210
211 /**
212 * Draw a menu item with label.
213 */
214 @Override
215 public void draw() {
216 CellAttributes background = getTheme().getColor("tmenu");
217 CellAttributes menuColor;
218 CellAttributes menuMnemonicColor;
219 if (isAbsoluteActive()) {
220 menuColor = getTheme().getColor("tmenu.highlighted");
221 menuMnemonicColor = getTheme().getColor("tmenu.mnemonic.highlighted");
222 } else {
223 if (isEnabled()) {
224 menuColor = getTheme().getColor("tmenu");
225 menuMnemonicColor = getTheme().getColor("tmenu.mnemonic");
226 } else {
227 menuColor = getTheme().getColor("tmenu.disabled");
228 menuMnemonicColor = getTheme().getColor("tmenu.disabled");
229 }
230 }
231
232 char cVSide = GraphicsChars.WINDOW_SIDE;
233 getScreen().vLineXY(0, 0, 1, cVSide, background);
234 getScreen().vLineXY(getWidth() - 1, 0, 1, cVSide, background);
235
236 getScreen().hLineXY(1, 0, getWidth() - 2, ' ', menuColor);
237 getScreen().putStringXY(2, 0, mnemonic.getRawLabel(), menuColor);
238 if (key != null) {
239 String keyLabel = key.toString();
240 getScreen().putStringXY((getWidth() - keyLabel.length() - 2), 0,
241 keyLabel, menuColor);
242 }
243 if (mnemonic.getShortcutIdx() >= 0) {
244 getScreen().putCharXY(2 + mnemonic.getShortcutIdx(), 0,
245 mnemonic.getShortcut(), menuMnemonicColor);
246 }
247 if (checked) {
248 assert (checkable);
249 getScreen().putCharXY(1, 0, GraphicsChars.CHECK, menuColor);
250 }
251
252 }
253
254 /**
255 * Dispatch event(s) due to selection or click.
256 */
257 public void dispatch() {
258 assert (isEnabled());
259
260 getApplication().addMenuEvent(new TMenuEvent(id));
261 if (checkable) {
262 checked = !checked;
263 }
264 }
265
266 /**
267 * Handle mouse button releases.
268 *
269 * @param mouse mouse button release event
270 */
271 @Override
272 public void onMouseUp(final TMouseEvent mouse) {
273 if ((mouseOnMenuItem(mouse)) && (mouse.isMouse1())) {
274 dispatch();
275 return;
276 }
277 }
278
279 /**
280 * Handle keystrokes.
281 *
282 * @param keypress keystroke event
283 */
284 @Override
285 public void onKeypress(final TKeypressEvent keypress) {
286 if (keypress.equals(kbEnter)) {
287 dispatch();
288 return;
289 }
290
291 // Pass to parent for the things we don't care about.
292 super.onKeypress(keypress);
293 }
294 }