064e927566effd281321502a7ad02031012fff84
[nikiroo-utils.git] / src / jexer / TButton.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;
32
33 import jexer.bits.CellAttributes;
34 import jexer.bits.Color;
35 import jexer.bits.GraphicsChars;
36 import jexer.bits.MnemonicString;
37 import jexer.event.TKeypressEvent;
38 import jexer.event.TMouseEvent;
39 import static jexer.TKeypress.*;
40
41 /**
42 * TButton implements a simple button. To make the button do something, pass
43 * a TAction class to its constructor.
44 *
45 * @see TAction#DO()
46 */
47 public final class TButton extends TWidget {
48
49 /**
50 * The shortcut and button text.
51 */
52 private MnemonicString mnemonic;
53
54 /**
55 * Get the mnemonic string for this button.
56 *
57 * @return mnemonic string
58 */
59 public MnemonicString getMnemonic() {
60 return mnemonic;
61 }
62
63 /**
64 * Remember mouse state.
65 */
66 private TMouseEvent mouse;
67
68 /**
69 * True when the button is being pressed and held down.
70 */
71 private boolean inButtonPress = false;
72
73 /**
74 * The action to perform when the button is clicked.
75 */
76 private TAction action;
77
78 /**
79 * Act as though the button was pressed. This is useful for other UI
80 * elements to get the same action as if the user clicked the button.
81 */
82 public void dispatch() {
83 if (action != null) {
84 action.DO();
85 }
86 }
87
88 /**
89 * Private constructor.
90 *
91 * @param parent parent widget
92 * @param text label on the button
93 * @param x column relative to parent
94 * @param y row relative to parent
95 */
96 private TButton(final TWidget parent, final String text,
97 final int x, final int y) {
98
99 // Set parent and window
100 super(parent);
101
102 mnemonic = new MnemonicString(text);
103
104 setX(x);
105 setY(y);
106 setHeight(2);
107 setWidth(mnemonic.getRawLabel().length() + 3);
108 }
109
110 /**
111 * Public constructor.
112 *
113 * @param parent parent widget
114 * @param text label on the button
115 * @param x column relative to parent
116 * @param y row relative to parent
117 * @param action to call when button is pressed
118 */
119 public TButton(final TWidget parent, final String text,
120 final int x, final int y, final TAction action) {
121
122 this(parent, text, x, y);
123 this.action = action;
124 }
125
126 /**
127 * Returns true if the mouse is currently on the button.
128 *
129 * @return if true the mouse is currently on the button
130 */
131 private boolean mouseOnButton() {
132 int rightEdge = getWidth() - 1;
133 if (inButtonPress) {
134 rightEdge++;
135 }
136 if ((mouse != null)
137 && (mouse.getY() == 0)
138 && (mouse.getX() >= 0)
139 && (mouse.getX() < rightEdge)
140 ) {
141 return true;
142 }
143 return false;
144 }
145
146 /**
147 * Draw a button with a shadow.
148 */
149 @Override
150 public void draw() {
151 CellAttributes buttonColor;
152 CellAttributes menuMnemonicColor;
153 CellAttributes shadowColor = new CellAttributes();
154 shadowColor.setTo(getWindow().getBackground());
155 shadowColor.setForeColor(Color.BLACK);
156 shadowColor.setBold(false);
157
158 if (!isEnabled()) {
159 buttonColor = getTheme().getColor("tbutton.disabled");
160 menuMnemonicColor = getTheme().getColor("tbutton.disabled");
161 } else if (isAbsoluteActive()) {
162 buttonColor = getTheme().getColor("tbutton.active");
163 menuMnemonicColor = getTheme().getColor("tbutton.mnemonic.highlighted");
164 } else {
165 buttonColor = getTheme().getColor("tbutton.inactive");
166 menuMnemonicColor = getTheme().getColor("tbutton.mnemonic");
167 }
168
169 if (inButtonPress) {
170 getScreen().putCharXY(1, 0, ' ', buttonColor);
171 getScreen().putStringXY(2, 0, mnemonic.getRawLabel(), buttonColor);
172 getScreen().putCharXY(getWidth() - 1, 0, ' ', buttonColor);
173 } else {
174 getScreen().putCharXY(0, 0, ' ', buttonColor);
175 getScreen().putStringXY(1, 0, mnemonic.getRawLabel(), buttonColor);
176 getScreen().putCharXY(getWidth() - 2, 0, ' ', buttonColor);
177
178 getScreen().putCharXY(getWidth() - 1, 0,
179 GraphicsChars.CP437[0xDC], shadowColor);
180 getScreen().hLineXY(1, 1, getWidth() - 1,
181 GraphicsChars.CP437[0xDF], shadowColor);
182 }
183 if (mnemonic.getShortcutIdx() >= 0) {
184 if (inButtonPress) {
185 getScreen().putCharXY(2 + mnemonic.getShortcutIdx(), 0,
186 mnemonic.getShortcut(), menuMnemonicColor);
187 } else {
188 getScreen().putCharXY(1 + mnemonic.getShortcutIdx(), 0,
189 mnemonic.getShortcut(), menuMnemonicColor);
190 }
191
192 }
193 }
194
195 /**
196 * Handle mouse button presses.
197 *
198 * @param mouse mouse button event
199 */
200 @Override
201 public void onMouseDown(final TMouseEvent mouse) {
202 this.mouse = mouse;
203
204 if ((mouseOnButton()) && (mouse.isMouse1())) {
205 // Begin button press
206 inButtonPress = true;
207 }
208 }
209
210 /**
211 * Handle mouse button releases.
212 *
213 * @param mouse mouse button release event
214 */
215 @Override
216 public void onMouseUp(final TMouseEvent mouse) {
217 this.mouse = mouse;
218
219 if (inButtonPress && mouse.isMouse1()) {
220 inButtonPress = false;
221 // Dispatch the event
222 if (action != null) {
223 action.DO();
224 }
225 }
226
227 }
228
229 /**
230 * Handle mouse movements.
231 *
232 * @param mouse mouse motion event
233 */
234 @Override
235 public void onMouseMotion(final TMouseEvent mouse) {
236 this.mouse = mouse;
237
238 if (!mouseOnButton()) {
239 inButtonPress = false;
240 }
241 }
242
243 /**
244 * Handle keystrokes.
245 *
246 * @param keypress keystroke event
247 */
248 @Override
249 public void onKeypress(final TKeypressEvent keypress) {
250 if (keypress.equals(kbEnter)
251 || keypress.equals(kbSpace)
252 ) {
253 // Dispatch
254 if (action != null) {
255 action.DO();
256 }
257 return;
258 }
259
260 // Pass to parent for the things we don't care about.
261 super.onKeypress(keypress);
262 }
263
264 }