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