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