#35 try to emit raw CJK
[fanfix.git] / src / 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);
101 setHeight(2);
3af53a35 102 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);
30d336cc
KL
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
d36057df
KL
126 // ------------------------------------------------------------------------
127 // Event handlers ---------------------------------------------------------
128 // ------------------------------------------------------------------------
129
30d336cc
KL
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
30d336cc
KL
150 /**
151 * Handle mouse button presses.
152 *
153 * @param mouse mouse button event
154 */
155 @Override
156 public void onMouseDown(final TMouseEvent mouse) {
157 this.mouse = mouse;
158
7c870d89 159 if ((mouseOnButton()) && (mouse.isMouse1())) {
30d336cc
KL
160 // Begin button press
161 inButtonPress = true;
162 }
163 }
164
165 /**
166 * Handle mouse button releases.
167 *
168 * @param mouse mouse button release event
169 */
170 @Override
171 public void onMouseUp(final TMouseEvent mouse) {
172 this.mouse = mouse;
173
7c870d89 174 if (inButtonPress && mouse.isMouse1()) {
30d336cc 175 // Dispatch the event
a325f111 176 dispatch();
30d336cc
KL
177 }
178
179 }
180
181 /**
182 * Handle mouse movements.
183 *
184 * @param mouse mouse motion event
185 */
186 @Override
187 public void onMouseMotion(final TMouseEvent mouse) {
188 this.mouse = mouse;
189
190 if (!mouseOnButton()) {
191 inButtonPress = false;
192 }
193 }
194
195 /**
196 * Handle keystrokes.
197 *
198 * @param keypress keystroke event
199 */
200 @Override
201 public void onKeypress(final TKeypressEvent keypress) {
202 if (keypress.equals(kbEnter)
203 || keypress.equals(kbSpace)
204 ) {
205 // Dispatch
a325f111 206 dispatch();
30d336cc
KL
207 return;
208 }
209
210 // Pass to parent for the things we don't care about.
211 super.onKeypress(keypress);
212 }
213
d36057df
KL
214 // ------------------------------------------------------------------------
215 // TWidget ----------------------------------------------------------------
216 // ------------------------------------------------------------------------
217
218 /**
219 * Draw a button with a shadow.
220 */
221 @Override
222 public void draw() {
223 CellAttributes buttonColor;
224 CellAttributes menuMnemonicColor;
d36057df
KL
225
226 if (!isEnabled()) {
227 buttonColor = getTheme().getColor("tbutton.disabled");
228 menuMnemonicColor = getTheme().getColor("tbutton.disabled");
229 } else if (isAbsoluteActive()) {
230 buttonColor = getTheme().getColor("tbutton.active");
231 menuMnemonicColor = getTheme().getColor("tbutton.mnemonic.highlighted");
232 } else {
233 buttonColor = getTheme().getColor("tbutton.inactive");
234 menuMnemonicColor = getTheme().getColor("tbutton.mnemonic");
235 }
236
237 if (inButtonPress) {
a39c5665
KL
238 putCharXY(1, 0, ' ', buttonColor);
239 putStringXY(2, 0, mnemonic.getRawLabel(), buttonColor);
a69ed767 240 putCharXY(getWidth() - 1, 0, ' ', buttonColor);
d36057df 241 } else {
a69ed767
KL
242 putCharXY(0, 0, ' ', buttonColor);
243 putStringXY(1, 0, mnemonic.getRawLabel(), buttonColor);
244 putCharXY(getWidth() - 2, 0, ' ', buttonColor);
a39c5665 245
255967a8 246 if (shadowColor != null) {
a39c5665
KL
247 putCharXY(getWidth() - 1, 0,
248 GraphicsChars.CP437[0xDC], shadowColor);
249 hLineXY(1, 1, getWidth() - 1,
250 GraphicsChars.CP437[0xDF], shadowColor);
255967a8 251 }
d36057df
KL
252 }
253 if (mnemonic.getShortcutIdx() >= 0) {
254 if (inButtonPress) {
a69ed767 255 putCharXY(2 + mnemonic.getShortcutIdx(), 0,
d36057df
KL
256 mnemonic.getShortcut(), menuMnemonicColor);
257 } else {
a69ed767 258 putCharXY(1 + mnemonic.getShortcutIdx(), 0,
d36057df
KL
259 mnemonic.getShortcut(), menuMnemonicColor);
260 }
d36057df
KL
261 }
262 }
263
264 // ------------------------------------------------------------------------
265 // TButton ----------------------------------------------------------------
266 // ------------------------------------------------------------------------
267
268 /**
269 * Get the mnemonic string for this button.
270 *
271 * @return mnemonic string
272 */
273 public MnemonicString getMnemonic() {
274 return mnemonic;
275 }
276
277 /**
278 * Act as though the button was pressed. This is useful for other UI
279 * elements to get the same action as if the user clicked the button.
280 */
281 public void dispatch() {
282 if (action != null) {
283 action.DO();
284 inButtonPress = false;
285 }
286 }
287
e23ea538 288 /**
a39c5665
KL
289 * Set the background color used for the button "shadow". If null, no
290 * shadow will be drawn.
e23ea538 291 *
a39c5665 292 * @param color the new background color, or null for no shadow
e23ea538
KL
293 */
294 public void setShadowColor(final CellAttributes color) {
a39c5665
KL
295 if (color != null) {
296 shadowColor = new CellAttributes();
297 shadowColor.setTo(color);
298 shadowColor.setForeColor(Color.BLACK);
299 shadowColor.setBold(false);
300 } else {
301 shadowColor = null;
302 }
e23ea538
KL
303 }
304
30d336cc 305}