only keep the (re)sources here
[nikiroo-utils.git] / jexer / TButton.java
CommitLineData
daa4106c 1/*
30d336cc
KL
2 * Jexer - Java Text User Interface
3 *
e16dda65 4 * The MIT License (MIT)
30d336cc 5 *
a69ed767 6 * Copyright (C) 2019 Kevin Lamonte
30d336cc 7 *
e16dda65
KL
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:
30d336cc 14 *
e16dda65
KL
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
30d336cc 17 *
e16dda65
KL
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.
30d336cc
KL
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29package jexer;
30
31import jexer.bits.CellAttributes;
32import jexer.bits.Color;
33import jexer.bits.GraphicsChars;
34import jexer.bits.MnemonicString;
3af53a35 35import jexer.bits.StringUtils;
30d336cc
KL
36import jexer.event.TKeypressEvent;
37import jexer.event.TMouseEvent;
a39c5665
KL
38import static jexer.TKeypress.kbEnter;
39import static jexer.TKeypress.kbSpace;
30d336cc
KL
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 */
051e2913 47public class TButton extends TWidget {
30d336cc 48
d36057df
KL
49 // ------------------------------------------------------------------------
50 // Variables --------------------------------------------------------------
51 // ------------------------------------------------------------------------
52
30d336cc
KL
53 /**
54 * The shortcut and button text.
55 */
56 private MnemonicString mnemonic;
57
58 /**
59 * Remember mouse state.
60 */
61 private TMouseEvent mouse;
62
63 /**
64 * True when the button is being pressed and held down.
65 */
66 private boolean inButtonPress = false;
67
68 /**
69 * The action to perform when the button is clicked.
70 */
71 private TAction action;
72
e23ea538 73 /**
a39c5665
KL
74 * The background color used for the button "shadow", or null for "no
75 * shadow".
e23ea538
KL
76 */
77 private CellAttributes shadowColor;
a39c5665 78
d36057df
KL
79 // ------------------------------------------------------------------------
80 // Constructors -----------------------------------------------------------
81 // ------------------------------------------------------------------------
91c9a837 82
30d336cc
KL
83 /**
84 * Private constructor.
85 *
86 * @param parent parent widget
87 * @param text label on the button
88 * @param x column relative to parent
89 * @param y row relative to parent
90 */
91 private TButton(final TWidget parent, final String text,
92 final int x, final int y) {
93
94 // Set parent and window
95 super(parent);
96
97 mnemonic = new MnemonicString(text);
98
99 setX(x);
100 setY(y);
d8dc8aea
KL
101 super.setHeight(2);
102 super.setWidth(StringUtils.width(mnemonic.getRawLabel()) + 3);
e23ea538
KL
103
104 shadowColor = new CellAttributes();
105 shadowColor.setTo(getWindow().getBackground());
106 shadowColor.setForeColor(Color.BLACK);
107 shadowColor.setBold(false);
d8dc8aea
KL
108
109 // Since we set dimensions after TWidget's constructor, we need to
110 // update the layout manager.
111 if (getParent().getLayoutManager() != null) {
112 getParent().getLayoutManager().remove(this);
113 getParent().getLayoutManager().add(this);
114 }
30d336cc
KL
115 }
116
117 /**
118 * Public constructor.
119 *
120 * @param parent parent widget
121 * @param text label on the button
122 * @param x column relative to parent
123 * @param y row relative to parent
124 * @param action to call when button is pressed
125 */
126 public TButton(final TWidget parent, final String text,
127 final int x, final int y, final TAction action) {
128
129 this(parent, text, x, y);
130 this.action = action;
131 }
132
d36057df
KL
133 // ------------------------------------------------------------------------
134 // Event handlers ---------------------------------------------------------
135 // ------------------------------------------------------------------------
136
30d336cc
KL
137 /**
138 * Returns true if the mouse is currently on the button.
139 *
140 * @return if true the mouse is currently on the button
141 */
142 private boolean mouseOnButton() {
143 int rightEdge = getWidth() - 1;
144 if (inButtonPress) {
145 rightEdge++;
146 }
147 if ((mouse != null)
148 && (mouse.getY() == 0)
149 && (mouse.getX() >= 0)
150 && (mouse.getX() < rightEdge)
151 ) {
152 return true;
153 }
154 return false;
155 }
156
30d336cc
KL
157 /**
158 * Handle mouse button presses.
159 *
160 * @param mouse mouse button event
161 */
162 @Override
163 public void onMouseDown(final TMouseEvent mouse) {
164 this.mouse = mouse;
165
7c870d89 166 if ((mouseOnButton()) && (mouse.isMouse1())) {
30d336cc
KL
167 // Begin button press
168 inButtonPress = true;
169 }
170 }
171
172 /**
173 * Handle mouse button releases.
174 *
175 * @param mouse mouse button release event
176 */
177 @Override
178 public void onMouseUp(final TMouseEvent mouse) {
179 this.mouse = mouse;
180
7c870d89 181 if (inButtonPress && mouse.isMouse1()) {
30d336cc 182 // Dispatch the event
a325f111 183 dispatch();
30d336cc
KL
184 }
185
186 }
187
188 /**
189 * Handle mouse movements.
190 *
191 * @param mouse mouse motion event
192 */
193 @Override
194 public void onMouseMotion(final TMouseEvent mouse) {
195 this.mouse = mouse;
196
197 if (!mouseOnButton()) {
198 inButtonPress = false;
199 }
200 }
201
202 /**
203 * Handle keystrokes.
204 *
205 * @param keypress keystroke event
206 */
207 @Override
208 public void onKeypress(final TKeypressEvent keypress) {
209 if (keypress.equals(kbEnter)
210 || keypress.equals(kbSpace)
211 ) {
212 // Dispatch
a325f111 213 dispatch();
30d336cc
KL
214 return;
215 }
216
217 // Pass to parent for the things we don't care about.
218 super.onKeypress(keypress);
219 }
220
d36057df
KL
221 // ------------------------------------------------------------------------
222 // TWidget ----------------------------------------------------------------
223 // ------------------------------------------------------------------------
224
d8dc8aea
KL
225 /**
226 * Override TWidget's width: we can only set width at construction time.
227 *
228 * @param width new widget width (ignored)
229 */
230 @Override
231 public void setWidth(final int width) {
232 // Do nothing
233 }
234
235 /**
236 * Override TWidget's height: we can only set height at construction
237 * time.
238 *
239 * @param height new widget height (ignored)
240 */
241 @Override
242 public void setHeight(final int height) {
243 // Do nothing
244 }
245
d36057df
KL
246 /**
247 * Draw a button with a shadow.
248 */
249 @Override
250 public void draw() {
251 CellAttributes buttonColor;
252 CellAttributes menuMnemonicColor;
d36057df
KL
253
254 if (!isEnabled()) {
255 buttonColor = getTheme().getColor("tbutton.disabled");
256 menuMnemonicColor = getTheme().getColor("tbutton.disabled");
257 } else if (isAbsoluteActive()) {
258 buttonColor = getTheme().getColor("tbutton.active");
259 menuMnemonicColor = getTheme().getColor("tbutton.mnemonic.highlighted");
260 } else {
261 buttonColor = getTheme().getColor("tbutton.inactive");
262 menuMnemonicColor = getTheme().getColor("tbutton.mnemonic");
263 }
264
265 if (inButtonPress) {
a39c5665
KL
266 putCharXY(1, 0, ' ', buttonColor);
267 putStringXY(2, 0, mnemonic.getRawLabel(), buttonColor);
a69ed767 268 putCharXY(getWidth() - 1, 0, ' ', buttonColor);
d36057df 269 } else {
a69ed767
KL
270 putCharXY(0, 0, ' ', buttonColor);
271 putStringXY(1, 0, mnemonic.getRawLabel(), buttonColor);
272 putCharXY(getWidth() - 2, 0, ' ', buttonColor);
a39c5665 273
255967a8 274 if (shadowColor != null) {
a39c5665
KL
275 putCharXY(getWidth() - 1, 0,
276 GraphicsChars.CP437[0xDC], shadowColor);
277 hLineXY(1, 1, getWidth() - 1,
278 GraphicsChars.CP437[0xDF], shadowColor);
255967a8 279 }
d36057df 280 }
3fe82fa7 281 if (mnemonic.getScreenShortcutIdx() >= 0) {
d36057df 282 if (inButtonPress) {
3fe82fa7 283 putCharXY(2 + mnemonic.getScreenShortcutIdx(), 0,
d36057df
KL
284 mnemonic.getShortcut(), menuMnemonicColor);
285 } else {
3fe82fa7 286 putCharXY(1 + mnemonic.getScreenShortcutIdx(), 0,
d36057df
KL
287 mnemonic.getShortcut(), menuMnemonicColor);
288 }
d36057df
KL
289 }
290 }
291
292 // ------------------------------------------------------------------------
293 // TButton ----------------------------------------------------------------
294 // ------------------------------------------------------------------------
295
296 /**
297 * Get the mnemonic string for this button.
298 *
299 * @return mnemonic string
300 */
301 public MnemonicString getMnemonic() {
302 return mnemonic;
303 }
304
305 /**
306 * Act as though the button was pressed. This is useful for other UI
307 * elements to get the same action as if the user clicked the button.
308 */
309 public void dispatch() {
310 if (action != null) {
a524aa2e 311 action.DO(this);
d36057df
KL
312 inButtonPress = false;
313 }
314 }
315
e23ea538 316 /**
a39c5665
KL
317 * Set the background color used for the button "shadow". If null, no
318 * shadow will be drawn.
e23ea538 319 *
a39c5665 320 * @param color the new background color, or null for no shadow
e23ea538
KL
321 */
322 public void setShadowColor(final CellAttributes color) {
a39c5665
KL
323 if (color != null) {
324 shadowColor = new CellAttributes();
325 shadowColor.setTo(color);
326 shadowColor.setForeColor(Color.BLACK);
327 shadowColor.setBold(false);
328 } else {
329 shadowColor = null;
330 }
e23ea538
KL
331 }
332
30d336cc 333}