GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* The ManaPlus Client |
||
3 |
* Copyright (C) 2004-2009 The Mana World Development Team |
||
4 |
* Copyright (C) 2009-2010 The Mana Developers |
||
5 |
* Copyright (C) 2011-2019 The ManaPlus Developers |
||
6 |
* Copyright (C) 2019-2021 Andrei Karas |
||
7 |
* |
||
8 |
* This file is part of The ManaPlus Client. |
||
9 |
* |
||
10 |
* This program is free software; you can redistribute it and/or modify |
||
11 |
* it under the terms of the GNU General Public License as published by |
||
12 |
* the Free Software Foundation; either version 2 of the License, or |
||
13 |
* any later version. |
||
14 |
* |
||
15 |
* This program is distributed in the hope that it will be useful, |
||
16 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 |
* GNU General Public License for more details. |
||
19 |
* |
||
20 |
* You should have received a copy of the GNU General Public License |
||
21 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
22 |
*/ |
||
23 |
|||
24 |
/* _______ __ __ __ ______ __ __ _______ __ __ |
||
25 |
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ |
||
26 |
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / |
||
27 |
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / |
||
28 |
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / |
||
29 |
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / |
||
30 |
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ |
||
31 |
* |
||
32 |
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson |
||
33 |
* |
||
34 |
* |
||
35 |
* Per Larsson a.k.a finalman |
||
36 |
* Olof Naessén a.k.a jansem/yakslem |
||
37 |
* |
||
38 |
* Visit: http://guichan.sourceforge.net |
||
39 |
* |
||
40 |
* License: (BSD) |
||
41 |
* Redistribution and use in source and binary forms, with or without |
||
42 |
* modification, are permitted provided that the following conditions |
||
43 |
* are met: |
||
44 |
* 1. Redistributions of source code must retain the above copyright |
||
45 |
* notice, this list of conditions and the following disclaimer. |
||
46 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
47 |
* notice, this list of conditions and the following disclaimer in |
||
48 |
* the documentation and/or other materials provided with the |
||
49 |
* distribution. |
||
50 |
* 3. Neither the name of Guichan nor the names of its contributors may |
||
51 |
* be used to endorse or promote products derived from this software |
||
52 |
* without specific prior written permission. |
||
53 |
* |
||
54 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
55 |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
56 |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
57 |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||
58 |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
59 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
||
60 |
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||
61 |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||
62 |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||
63 |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
64 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
65 |
*/ |
||
66 |
|||
67 |
#include "gui/widgets/button.h" |
||
68 |
|||
69 |
#include "settings.h" |
||
70 |
|||
71 |
#include "resources/imageset.h" |
||
72 |
#include "resources/imagerect.h" |
||
73 |
|||
74 |
#include "resources/image/image.h" |
||
75 |
|||
76 |
#include "gui/gui.h" |
||
77 |
#include "gui/skin.h" |
||
78 |
|||
79 |
#include "gui/fonts/font.h" |
||
80 |
|||
81 |
#include "render/renderers.h" |
||
82 |
|||
83 |
#include "render/vertexes/imagecollection.h" |
||
84 |
|||
85 |
#include "utils/delete2.h" |
||
86 |
|||
87 |
#include "debug.h" |
||
88 |
|||
89 |
float Button::mAlpha = 1.0; |
||
90 |
|||
91 |
✓✓ | 3 |
static std::string const data[Button::BUTTON_COUNT] = |
92 |
{ |
||
93 |
".xml", |
||
94 |
"_highlighted.xml", |
||
95 |
"_pressed.xml", |
||
96 |
"_disabled.xml" |
||
97 |
✓✗✓✗ ✓✗✓✗ ✗✗ |
9 |
}; |
98 |
|||
99 |
24 |
Button::Button(const Widget2 *const widget, |
|
100 |
24 |
const std::string &restrict skinName) : |
|
101 |
Widget(widget), |
||
102 |
MouseListener(), |
||
103 |
KeyListener(), |
||
104 |
FocusListener(), |
||
105 |
WidgetListener(), |
||
106 |
mSkin(), |
||
107 |
mCaption(), |
||
108 |
mDescription(), |
||
109 |
mSkinName(skinName), |
||
110 |
mTextChunk(), |
||
111 |
✓✗✓✗ |
24 |
mVertexes2(new ImageCollection), |
112 |
48 |
mEnabledColor(getThemeColor(ThemeColorId::BUTTON, 255U)), |
|
113 |
48 |
mEnabledColor2(getThemeColor(ThemeColorId::BUTTON_OUTLINE, 255U)), |
|
114 |
48 |
mDisabledColor(getThemeColor(ThemeColorId::BUTTON_DISABLED, 255U)), |
|
115 |
mDisabledColor2(getThemeColor(ThemeColorId::BUTTON_DISABLED_OUTLINE, |
||
116 |
48 |
255U)), |
|
117 |
48 |
mHighlightedColor(getThemeColor(ThemeColorId::BUTTON_HIGHLIGHTED, 255U)), |
|
118 |
mHighlightedColor2(getThemeColor( |
||
119 |
48 |
ThemeColorId::BUTTON_HIGHLIGHTED_OUTLINE, 255U)), |
|
120 |
48 |
mPressedColor(getThemeColor(ThemeColorId::BUTTON_PRESSED, 255U)), |
|
121 |
48 |
mPressedColor2(getThemeColor(ThemeColorId::BUTTON_PRESSED_OUTLINE, 255U)), |
|
122 |
mImages(nullptr), |
||
123 |
mImageSet(nullptr), |
||
124 |
mAlignment(Graphics::CENTER), |
||
125 |
mClickCount(0), |
||
126 |
mSpacing(), |
||
127 |
mTag(0), |
||
128 |
mMode(0), |
||
129 |
mXOffset(0), |
||
130 |
mYOffset(0), |
||
131 |
mImageWidth(0), |
||
132 |
mImageHeight(0), |
||
133 |
mHasMouse(false), |
||
134 |
mKeyPressed(false), |
||
135 |
mMousePressed(false), |
||
136 |
mStick(false), |
||
137 |
mPressed(false), |
||
138 |
✓✓✓✗ ✓✓ |
408 |
mTextChanged(true) |
139 |
{ |
||
140 |
✓✗ | 24 |
init(); |
141 |
✓✗ | 24 |
adjustSize(); |
142 |
24 |
} |
|
143 |
|||
144 |
304 |
Button::Button(const Widget2 *const widget, |
|
145 |
const std::string &restrict caption, |
||
146 |
const std::string &restrict actionEventId, |
||
147 |
const std::string &restrict skinName, |
||
148 |
304 |
ActionListener *const listener) : |
|
149 |
Widget(widget), |
||
150 |
MouseListener(), |
||
151 |
KeyListener(), |
||
152 |
FocusListener(), |
||
153 |
WidgetListener(), |
||
154 |
mSkin(), |
||
155 |
mCaption(caption), |
||
156 |
mDescription(), |
||
157 |
mSkinName(skinName), |
||
158 |
mTextChunk(), |
||
159 |
✓✗✓✗ |
304 |
mVertexes2(new ImageCollection), |
160 |
608 |
mEnabledColor(getThemeColor(ThemeColorId::BUTTON, 255U)), |
|
161 |
608 |
mEnabledColor2(getThemeColor(ThemeColorId::BUTTON_OUTLINE, 255U)), |
|
162 |
608 |
mDisabledColor(getThemeColor(ThemeColorId::BUTTON_DISABLED, 255U)), |
|
163 |
mDisabledColor2(getThemeColor(ThemeColorId::BUTTON_DISABLED_OUTLINE, |
||
164 |
608 |
255U)), |
|
165 |
608 |
mHighlightedColor(getThemeColor(ThemeColorId::BUTTON_HIGHLIGHTED, 255U)), |
|
166 |
mHighlightedColor2(getThemeColor( |
||
167 |
608 |
ThemeColorId::BUTTON_HIGHLIGHTED_OUTLINE, 255U)), |
|
168 |
608 |
mPressedColor(getThemeColor(ThemeColorId::BUTTON_PRESSED, 255U)), |
|
169 |
608 |
mPressedColor2(getThemeColor(ThemeColorId::BUTTON_PRESSED_OUTLINE, 255U)), |
|
170 |
mImages(nullptr), |
||
171 |
mImageSet(nullptr), |
||
172 |
mAlignment(Graphics::CENTER), |
||
173 |
mClickCount(0), |
||
174 |
mSpacing(), |
||
175 |
mTag(0), |
||
176 |
mMode(0), |
||
177 |
mXOffset(0), |
||
178 |
mYOffset(0), |
||
179 |
mImageWidth(0), |
||
180 |
mImageHeight(0), |
||
181 |
mHasMouse(false), |
||
182 |
mKeyPressed(false), |
||
183 |
mMousePressed(false), |
||
184 |
mStick(false), |
||
185 |
mPressed(false), |
||
186 |
✓✓✓✗ ✓✓ |
5168 |
mTextChanged(true) |
187 |
{ |
||
188 |
✓✗ | 304 |
init(); |
189 |
✓✗ | 304 |
adjustSize(); |
190 |
608 |
setActionEventId(actionEventId); |
|
191 |
|||
192 |
✓✗ | 304 |
if (listener != nullptr) |
193 |
✓✗ | 304 |
addActionListener(listener); |
194 |
304 |
} |
|
195 |
|||
196 |
Button::Button(const Widget2 *const widget, |
||
197 |
const std::string &restrict caption, |
||
198 |
const std::string &restrict imageName, |
||
199 |
const int imageWidth, |
||
200 |
const int imageHeight, |
||
201 |
const std::string &restrict actionEventId, |
||
202 |
const std::string &restrict skinName, |
||
203 |
ActionListener *const listener) : |
||
204 |
Widget(widget), |
||
205 |
MouseListener(), |
||
206 |
KeyListener(), |
||
207 |
FocusListener(), |
||
208 |
WidgetListener(), |
||
209 |
mSkin(), |
||
210 |
mCaption(caption), |
||
211 |
mDescription(), |
||
212 |
mSkinName(skinName), |
||
213 |
mTextChunk(), |
||
214 |
mVertexes2(new ImageCollection), |
||
215 |
mEnabledColor(getThemeColor(ThemeColorId::BUTTON, 255U)), |
||
216 |
mEnabledColor2(getThemeColor(ThemeColorId::BUTTON_OUTLINE, 255U)), |
||
217 |
mDisabledColor(getThemeColor(ThemeColorId::BUTTON_DISABLED, 255U)), |
||
218 |
mDisabledColor2(getThemeColor(ThemeColorId::BUTTON_DISABLED_OUTLINE, |
||
219 |
255U)), |
||
220 |
mHighlightedColor(getThemeColor(ThemeColorId::BUTTON_HIGHLIGHTED, 255U)), |
||
221 |
mHighlightedColor2(getThemeColor( |
||
222 |
ThemeColorId::BUTTON_HIGHLIGHTED_OUTLINE, 255U)), |
||
223 |
mPressedColor(getThemeColor(ThemeColorId::BUTTON_PRESSED, 255U)), |
||
224 |
mPressedColor2(getThemeColor(ThemeColorId::BUTTON_PRESSED_OUTLINE, 255U)), |
||
225 |
mImages(nullptr), |
||
226 |
mImageSet(nullptr), |
||
227 |
mAlignment(Graphics::CENTER), |
||
228 |
mClickCount(0), |
||
229 |
mSpacing(), |
||
230 |
mTag(0), |
||
231 |
mMode(0), |
||
232 |
mXOffset(0), |
||
233 |
mYOffset(0), |
||
234 |
mImageWidth(imageWidth), |
||
235 |
mImageHeight(imageHeight), |
||
236 |
mHasMouse(false), |
||
237 |
mKeyPressed(false), |
||
238 |
mMousePressed(false), |
||
239 |
mStick(false), |
||
240 |
mPressed(false), |
||
241 |
mTextChanged(true) |
||
242 |
{ |
||
243 |
init(); |
||
244 |
loadImageSet(imageName); |
||
245 |
adjustSize(); |
||
246 |
setActionEventId(actionEventId); |
||
247 |
|||
248 |
if (listener != nullptr) |
||
249 |
addActionListener(listener); |
||
250 |
} |
||
251 |
|||
252 |
24 |
Button::Button(const Widget2 *const widget, |
|
253 |
const std::string &restrict imageName, |
||
254 |
const int imageWidth, |
||
255 |
const int imageHeight, |
||
256 |
const std::string &restrict actionEventId, |
||
257 |
const std::string &restrict skinName, |
||
258 |
24 |
ActionListener *const listener) : |
|
259 |
Widget(widget), |
||
260 |
MouseListener(), |
||
261 |
KeyListener(), |
||
262 |
FocusListener(), |
||
263 |
WidgetListener(), |
||
264 |
mSkin(), |
||
265 |
mCaption(), |
||
266 |
mDescription(), |
||
267 |
mSkinName(skinName), |
||
268 |
mTextChunk(), |
||
269 |
✓✗✓✗ |
24 |
mVertexes2(new ImageCollection), |
270 |
48 |
mEnabledColor(getThemeColor(ThemeColorId::BUTTON, 255U)), |
|
271 |
48 |
mEnabledColor2(getThemeColor(ThemeColorId::BUTTON_OUTLINE, 255U)), |
|
272 |
48 |
mDisabledColor(getThemeColor(ThemeColorId::BUTTON_DISABLED, 255U)), |
|
273 |
mDisabledColor2(getThemeColor(ThemeColorId::BUTTON_DISABLED_OUTLINE, |
||
274 |
48 |
255U)), |
|
275 |
48 |
mHighlightedColor(getThemeColor(ThemeColorId::BUTTON_HIGHLIGHTED, 255U)), |
|
276 |
mHighlightedColor2(getThemeColor( |
||
277 |
48 |
ThemeColorId::BUTTON_HIGHLIGHTED_OUTLINE, 255U)), |
|
278 |
48 |
mPressedColor(getThemeColor(ThemeColorId::BUTTON_PRESSED, 255U)), |
|
279 |
48 |
mPressedColor2(getThemeColor(ThemeColorId::BUTTON_PRESSED_OUTLINE, 255U)), |
|
280 |
mImages(nullptr), |
||
281 |
mImageSet(nullptr), |
||
282 |
mAlignment(Graphics::CENTER), |
||
283 |
mClickCount(0), |
||
284 |
mSpacing(), |
||
285 |
mTag(0), |
||
286 |
mMode(0), |
||
287 |
mXOffset(0), |
||
288 |
mYOffset(0), |
||
289 |
mImageWidth(imageWidth), |
||
290 |
mImageHeight(imageHeight), |
||
291 |
mHasMouse(false), |
||
292 |
mKeyPressed(false), |
||
293 |
mMousePressed(false), |
||
294 |
mStick(false), |
||
295 |
mPressed(false), |
||
296 |
✓✓✓✗ ✓✓ |
408 |
mTextChanged(true) |
297 |
{ |
||
298 |
✓✗ | 24 |
init(); |
299 |
✓✗ | 24 |
loadImageSet(imageName); |
300 |
✓✗ | 24 |
adjustSize(); |
301 |
48 |
setActionEventId(actionEventId); |
|
302 |
|||
303 |
✓✗ | 24 |
if (listener != nullptr) |
304 |
✓✗ | 24 |
addActionListener(listener); |
305 |
24 |
} |
|
306 |
|||
307 |
352 |
void Button::init() |
|
308 |
{ |
||
309 |
352 |
mAllowLogic = false; |
|
310 |
352 |
addMouseListener(this); |
|
311 |
352 |
addKeyListener(this); |
|
312 |
352 |
addFocusListener(this); |
|
313 |
352 |
addWidgetListener(this); |
|
314 |
|||
315 |
352 |
setFocusable(true); |
|
316 |
704 |
setFrameSize(0); |
|
317 |
|||
318 |
✓✗ | 352 |
if (theme != nullptr) |
319 |
{ |
||
320 |
✓✓ | 3168 |
for (int mode = 0; mode < BUTTON_COUNT; mode ++) |
321 |
{ |
||
322 |
✓✗✓✗ |
7040 |
Skin *const skin = theme->load(mSkinName + data[mode], |
323 |
"button.xml", |
||
324 |
true, |
||
325 |
✓✗ | 2816 |
Theme::getThemePath()); |
326 |
✓✗ | 1408 |
if (skin != nullptr) |
327 |
{ |
||
328 |
1408 |
mSkin[mode] = skin; |
|
329 |
✓✗ | 5632 |
mSpacing[mode] = skin->getOption("spacing"); |
330 |
} |
||
331 |
} |
||
332 |
} |
||
333 |
|||
334 |
352 |
updateAlpha(); |
|
335 |
352 |
} |
|
336 |
|||
337 |
3520 |
Button::~Button() |
|
338 |
{ |
||
339 |
✓✓ | 352 |
if (mWindow != nullptr) |
340 |
350 |
mWindow->removeWidgetListener(this); |
|
341 |
|||
342 |
✓✗ | 352 |
if (gui != nullptr) |
343 |
352 |
gui->removeDragged(this); |
|
344 |
|||
345 |
✓✗ | 352 |
if (theme != nullptr) |
346 |
{ |
||
347 |
✓✓ | 3168 |
for (int mode = 0; mode < BUTTON_COUNT; mode ++) |
348 |
1408 |
theme->unload(mSkin[mode]); |
|
349 |
} |
||
350 |
✓✗ | 352 |
delete2(mVertexes2) |
351 |
✓✓ | 352 |
if (mImageSet != nullptr) |
352 |
{ |
||
353 |
24 |
mImageSet->decRef(); |
|
354 |
24 |
mImageSet = nullptr; |
|
355 |
} |
||
356 |
✓✓ | 352 |
if (mImages != nullptr) |
357 |
{ |
||
358 |
✓✓ | 216 |
for (int f = 0; f < BUTTON_COUNT; f ++) |
359 |
96 |
mImages[f] = nullptr; |
|
360 |
24 |
delete [] mImages; |
|
361 |
24 |
mImages = nullptr; |
|
362 |
} |
||
363 |
352 |
mTextChunk.deleteImage(); |
|
364 |
704 |
} |
|
365 |
|||
366 |
void Button::loadImage(const std::string &imageName) |
||
367 |
{ |
||
368 |
if (mImageSet != nullptr) |
||
369 |
{ |
||
370 |
mImageSet->decRef(); |
||
371 |
mImageSet = nullptr; |
||
372 |
} |
||
373 |
Image *const image = Theme::getImageFromThemeXml(imageName, ""); |
||
374 |
mImages = new Image*[BUTTON_COUNT]; |
||
375 |
for (int f = 0; f < BUTTON_COUNT; f ++) |
||
376 |
mImages[f] = image; |
||
377 |
} |
||
378 |
|||
379 |
void Button::setImage(Image *const image) |
||
380 |
{ |
||
381 |
if (image == nullptr) |
||
382 |
return; |
||
383 |
if (mImageSet != nullptr) |
||
384 |
{ |
||
385 |
mImageSet->decRef(); |
||
386 |
mImageSet = nullptr; |
||
387 |
} |
||
388 |
mImageWidth = image->getWidth(); |
||
389 |
mImageHeight = image->getHeight(); |
||
390 |
mImages = new Image*[BUTTON_COUNT]; |
||
391 |
for (int f = 0; f < BUTTON_COUNT; f ++) |
||
392 |
mImages[f] = image; |
||
393 |
} |
||
394 |
|||
395 |
24 |
void Button::loadImageSet(const std::string &imageName) |
|
396 |
{ |
||
397 |
✗✓ | 24 |
if (mImageSet != nullptr) |
398 |
{ |
||
399 |
mImageSet->decRef(); |
||
400 |
mImageSet = nullptr; |
||
401 |
} |
||
402 |
24 |
mImageSet = Theme::getImageSetFromTheme(imageName, |
|
403 |
mImageWidth, mImageHeight); |
||
404 |
✓✗ | 24 |
if (mImageSet == nullptr) |
405 |
return; |
||
406 |
24 |
mImages = new Image*[BUTTON_COUNT]; |
|
407 |
24 |
mImages[0] = nullptr; |
|
408 |
✓✓ | 120 |
for (size_t f = 0; f < BUTTON_COUNT; f ++) |
409 |
{ |
||
410 |
96 |
Image *const img = mImageSet->get(f); |
|
411 |
✓✗ | 96 |
if (img != nullptr) |
412 |
96 |
mImages[f] = img; |
|
413 |
else |
||
414 |
mImages[f] = mImages[0]; |
||
415 |
} |
||
416 |
} |
||
417 |
|||
418 |
455 |
void Button::updateAlpha() |
|
419 |
{ |
||
420 |
const float alpha = std::max(settings.guiAlpha, |
||
421 |
1365 |
theme->getMinimumOpacity()); |
|
422 |
|||
423 |
✗✓ | 455 |
if (mAlpha != alpha) |
424 |
{ |
||
425 |
mAlpha = alpha; |
||
426 |
for (int mode = 0; mode < BUTTON_COUNT; mode ++) |
||
427 |
{ |
||
428 |
for (int a = 0; a < 9; a ++) |
||
429 |
{ |
||
430 |
Skin *const skin = mSkin[mode]; |
||
431 |
if (skin != nullptr) |
||
432 |
{ |
||
433 |
const ImageRect &rect = skin->getBorder(); |
||
434 |
Image *const image = rect.grid[a]; |
||
435 |
if (image != nullptr) |
||
436 |
image->setAlpha(mAlpha); |
||
437 |
} |
||
438 |
} |
||
439 |
} |
||
440 |
} |
||
441 |
455 |
} |
|
442 |
|||
443 |
103 |
void Button::draw(Graphics *const graphics) |
|
444 |
{ |
||
445 |
BLOCK_START("Button::draw") |
||
446 |
int mode; |
||
447 |
|||
448 |
✓✓ | 103 |
if (!isEnabled()) |
449 |
mode = BUTTON_DISABLED; |
||
450 |
✓✗ | 73 |
else if (isPressed2()) |
451 |
mode = BUTTON_PRESSED; |
||
452 |
✓✗ | 73 |
else if (mHasMouse) |
453 |
mode = BUTTON_HIGHLIGHTED; |
||
454 |
else |
||
455 |
73 |
mode = BUTTON_STANDARD; |
|
456 |
|||
457 |
103 |
const Skin *const skin = mSkin[mode]; |
|
458 |
✓✗ | 103 |
if (skin == nullptr) |
459 |
{ |
||
460 |
BLOCK_END("Button::draw") |
||
461 |
return; |
||
462 |
} |
||
463 |
|||
464 |
103 |
updateAlpha(); |
|
465 |
|||
466 |
103 |
bool recalc = false; |
|
467 |
✗✓ | 103 |
if (mRedraw) |
468 |
{ |
||
469 |
recalc = true; |
||
470 |
} |
||
471 |
else |
||
472 |
{ |
||
473 |
// because we don't know where parent windows was moved, |
||
474 |
// need recalc vertexes |
||
475 |
ClipRect &rect = graphics->getTopClip(); |
||
476 |
if (rect.xOffset != mXOffset || rect.yOffset != mYOffset) |
||
477 |
{ |
||
478 |
recalc = true; |
||
479 |
mXOffset = rect.xOffset; |
||
480 |
mYOffset = rect.yOffset; |
||
481 |
} |
||
482 |
else if (mMode != mode) |
||
483 |
{ |
||
484 |
recalc = true; |
||
485 |
mMode = mode; |
||
486 |
} |
||
487 |
else if (graphics->getRedraw()) |
||
488 |
{ |
||
489 |
recalc = true; |
||
490 |
} |
||
491 |
} |
||
492 |
|||
493 |
103 |
const int padding = skin->getPadding(); |
|
494 |
103 |
const int spacing = mSpacing[mode]; |
|
495 |
|||
496 |
✓✗ | 103 |
if (recalc) |
497 |
103 |
mTextChanged = true; |
|
498 |
|||
499 |
103 |
int imageX = 0; |
|
500 |
103 |
int imageY = 0; |
|
501 |
103 |
int textX = 0; |
|
502 |
103 |
const Rect &rect = mDimension; |
|
503 |
103 |
const int width = rect.width; |
|
504 |
103 |
const int height = rect.height; |
|
505 |
103 |
Font *const font = getFont(); |
|
506 |
103 |
int textY = height / 2 - font->getHeight() / 2; |
|
507 |
✗✓ | 103 |
if (mImages != nullptr) |
508 |
imageY = height / 2 - mImageHeight / 2; |
||
509 |
|||
510 |
// need move calculation from draw!!! |
||
511 |
|||
512 |
✗✓✗ | 103 |
switch (mAlignment) |
513 |
{ |
||
514 |
default: |
||
515 |
case Graphics::LEFT: |
||
516 |
{ |
||
517 |
if (mImages != nullptr) |
||
518 |
{ |
||
519 |
imageX = padding; |
||
520 |
textX = padding + mImageWidth + spacing; |
||
521 |
} |
||
522 |
else |
||
523 |
{ |
||
524 |
textX = padding; |
||
525 |
} |
||
526 |
break; |
||
527 |
} |
||
528 |
case Graphics::CENTER: |
||
529 |
{ |
||
530 |
103 |
const int width1 = font->getWidth(mCaption); |
|
531 |
✗✓ | 103 |
if (mImages != nullptr) |
532 |
{ |
||
533 |
const int w = width1 + mImageWidth + spacing; |
||
534 |
imageX = (width - w) / 2; |
||
535 |
textX = imageX + mImageWidth + spacing - width1 / 2; |
||
536 |
} |
||
537 |
else |
||
538 |
{ |
||
539 |
103 |
textX = (width - width1) / 2; |
|
540 |
} |
||
541 |
break; |
||
542 |
} |
||
543 |
case Graphics::RIGHT: |
||
544 |
{ |
||
545 |
const int width1 = font->getWidth(mCaption); |
||
546 |
textX = width - width1 - padding; |
||
547 |
imageX = textX - width1 - spacing; |
||
548 |
break; |
||
549 |
} |
||
550 |
} |
||
551 |
|||
552 |
✓✗ | 103 |
if (recalc) |
553 |
{ |
||
554 |
103 |
mRedraw = false; |
|
555 |
103 |
mMode = mode; |
|
556 |
103 |
mVertexes2->clear(); |
|
557 |
103 |
graphics->calcWindow(mVertexes2, |
|
558 |
0, 0, |
||
559 |
width, height, |
||
560 |
206 |
skin->getBorder()); |
|
561 |
|||
562 |
✗✓ | 103 |
if (mImages != nullptr) |
563 |
{ |
||
564 |
if (isPressed()) |
||
565 |
{ |
||
566 |
graphics->calcTileCollection(mVertexes2, |
||
567 |
mImages[mode], |
||
568 |
imageX + 1, imageY + 1); |
||
569 |
} |
||
570 |
else |
||
571 |
{ |
||
572 |
graphics->calcTileCollection(mVertexes2, |
||
573 |
mImages[mode], |
||
574 |
imageX, imageY); |
||
575 |
} |
||
576 |
} |
||
577 |
103 |
graphics->finalize(mVertexes2); |
|
578 |
} |
||
579 |
103 |
graphics->drawTileCollection(mVertexes2); |
|
580 |
|||
581 |
✗✓ | 103 |
if (isPressed()) |
582 |
{ |
||
583 |
textX ++; |
||
584 |
textY ++; |
||
585 |
} |
||
586 |
|||
587 |
✓✗ | 103 |
if (mTextChanged) |
588 |
{ |
||
589 |
103 |
mTextChunk.textFont = font; |
|
590 |
103 |
mTextChunk.deleteImage(); |
|
591 |
206 |
mTextChunk.text = mCaption; |
|
592 |
✓✗✗✓ |
103 |
switch (mode) |
593 |
{ |
||
594 |
case BUTTON_DISABLED: |
||
595 |
30 |
mTextChunk.color = mDisabledColor; |
|
596 |
30 |
mTextChunk.color2 = mDisabledColor2; |
|
597 |
30 |
break; |
|
598 |
case BUTTON_PRESSED: |
||
599 |
mTextChunk.color = mPressedColor; |
||
600 |
mTextChunk.color2 = mPressedColor2; |
||
601 |
break; |
||
602 |
case BUTTON_HIGHLIGHTED: |
||
603 |
mTextChunk.color = mHighlightedColor; |
||
604 |
mTextChunk.color2 = mHighlightedColor2; |
||
605 |
break; |
||
606 |
default: |
||
607 |
73 |
mTextChunk.color = mEnabledColor; |
|
608 |
73 |
mTextChunk.color2 = mEnabledColor2; |
|
609 |
73 |
break; |
|
610 |
} |
||
611 |
103 |
font->generate(mTextChunk); |
|
612 |
103 |
mTextChanged = false; |
|
613 |
} |
||
614 |
|||
615 |
103 |
const Image *const image = mTextChunk.img; |
|
616 |
✓✓ | 103 |
if (image != nullptr) |
617 |
101 |
graphics->drawImage(image, textX, textY); |
|
618 |
|||
619 |
BLOCK_END("Button::draw") |
||
620 |
} |
||
621 |
|||
622 |
void Button::safeDraw(Graphics *const graphics) |
||
623 |
{ |
||
624 |
BLOCK_START("Button::safeDraw") |
||
625 |
int mode; |
||
626 |
|||
627 |
if (!isEnabled()) |
||
628 |
mode = BUTTON_DISABLED; |
||
629 |
else if (isPressed2()) |
||
630 |
mode = BUTTON_PRESSED; |
||
631 |
else if (mHasMouse || isFocused()) |
||
632 |
mode = BUTTON_HIGHLIGHTED; |
||
633 |
else |
||
634 |
mode = BUTTON_STANDARD; |
||
635 |
|||
636 |
const Skin *const skin = mSkin[mode]; |
||
637 |
if (skin == nullptr) |
||
638 |
{ |
||
639 |
BLOCK_END("Button::safeDraw") |
||
640 |
return; |
||
641 |
} |
||
642 |
|||
643 |
updateAlpha(); |
||
644 |
|||
645 |
if (mMode != mode) |
||
646 |
{ |
||
647 |
mTextChanged = true; |
||
648 |
mMode = mode; |
||
649 |
} |
||
650 |
|||
651 |
const int padding = skin->getPadding(); |
||
652 |
const int spacing = mSpacing[mode]; |
||
653 |
|||
654 |
int imageX = 0; |
||
655 |
int imageY = 0; |
||
656 |
int textX = 0; |
||
657 |
const Rect &rect = mDimension; |
||
658 |
const int width = rect.width; |
||
659 |
const int height = rect.height; |
||
660 |
Font *const font = getFont(); |
||
661 |
int textY = height / 2 - font->getHeight() / 2; |
||
662 |
if (mImages != nullptr) |
||
663 |
imageY = height / 2 - mImageHeight / 2; |
||
664 |
|||
665 |
// need move calculation from draw!!! |
||
666 |
|||
667 |
switch (mAlignment) |
||
668 |
{ |
||
669 |
default: |
||
670 |
case Graphics::LEFT: |
||
671 |
{ |
||
672 |
if (mImages != nullptr) |
||
673 |
{ |
||
674 |
imageX = padding; |
||
675 |
textX = padding + mImageWidth + spacing; |
||
676 |
} |
||
677 |
else |
||
678 |
{ |
||
679 |
textX = padding; |
||
680 |
} |
||
681 |
break; |
||
682 |
} |
||
683 |
case Graphics::CENTER: |
||
684 |
{ |
||
685 |
const int width1 = font->getWidth(mCaption); |
||
686 |
if (mImages != nullptr) |
||
687 |
{ |
||
688 |
const int w = width1 + mImageWidth + spacing; |
||
689 |
imageX = (width - w) / 2; |
||
690 |
textX = imageX + mImageWidth + spacing - width1 / 2; |
||
691 |
} |
||
692 |
else |
||
693 |
{ |
||
694 |
textX = (width - width1) / 2; |
||
695 |
} |
||
696 |
break; |
||
697 |
} |
||
698 |
case Graphics::RIGHT: |
||
699 |
{ |
||
700 |
const int width1 = font->getWidth(mCaption); |
||
701 |
textX = width - width1 - padding; |
||
702 |
imageX = textX - width1 - spacing; |
||
703 |
break; |
||
704 |
} |
||
705 |
} |
||
706 |
|||
707 |
graphics->drawImageRect(0, 0, width, height, skin->getBorder()); |
||
708 |
|||
709 |
if (mImages != nullptr) |
||
710 |
{ |
||
711 |
if (isPressed()) |
||
712 |
graphics->drawImage(mImages[mode], imageX + 1, imageY + 1); |
||
713 |
else |
||
714 |
graphics->drawImage(mImages[mode], imageX, imageY); |
||
715 |
} |
||
716 |
|||
717 |
if (isPressed()) |
||
718 |
{ |
||
719 |
textX ++; |
||
720 |
textY ++; |
||
721 |
} |
||
722 |
|||
723 |
if (mTextChanged) |
||
724 |
{ |
||
725 |
mTextChunk.textFont = font; |
||
726 |
mTextChunk.deleteImage(); |
||
727 |
mTextChunk.text = mCaption; |
||
728 |
switch (mode) |
||
729 |
{ |
||
730 |
case BUTTON_DISABLED: |
||
731 |
mTextChunk.color = mDisabledColor; |
||
732 |
mTextChunk.color2 = mDisabledColor2; |
||
733 |
break; |
||
734 |
case BUTTON_PRESSED: |
||
735 |
mTextChunk.color = mPressedColor; |
||
736 |
mTextChunk.color2 = mPressedColor2; |
||
737 |
break; |
||
738 |
case BUTTON_HIGHLIGHTED: |
||
739 |
mTextChunk.color = mHighlightedColor; |
||
740 |
mTextChunk.color2 = mHighlightedColor2; |
||
741 |
break; |
||
742 |
default: |
||
743 |
mTextChunk.color = mEnabledColor; |
||
744 |
mTextChunk.color2 = mEnabledColor2; |
||
745 |
break; |
||
746 |
} |
||
747 |
font->generate(mTextChunk); |
||
748 |
mTextChanged = false; |
||
749 |
} |
||
750 |
|||
751 |
const Image *const image = mTextChunk.img; |
||
752 |
if (image != nullptr) |
||
753 |
graphics->drawImage(image, textX, textY); |
||
754 |
|||
755 |
BLOCK_END("Button::safeDraw") |
||
756 |
} |
||
757 |
|||
758 |
void Button::mouseReleased(MouseEvent& event) |
||
759 |
{ |
||
760 |
if (event.getButton() == MouseButton::LEFT) |
||
761 |
{ |
||
762 |
if (mStick) |
||
763 |
mPressed = !mPressed; |
||
764 |
|||
765 |
if (mMousePressed && mHasMouse) |
||
766 |
{ |
||
767 |
mMousePressed = false; |
||
768 |
mClickCount = event.getClickCount(); |
||
769 |
distributeActionEvent(); |
||
770 |
} |
||
771 |
else |
||
772 |
{ |
||
773 |
mMousePressed = false; |
||
774 |
mClickCount = 0; |
||
775 |
} |
||
776 |
event.consume(); |
||
777 |
} |
||
778 |
} |
||
779 |
|||
780 |
935 |
void Button::widgetResized(const Event &event A_UNUSED) |
|
781 |
{ |
||
782 |
935 |
mRedraw = true; |
|
783 |
935 |
} |
|
784 |
|||
785 |
638 |
void Button::widgetMoved(const Event &event A_UNUSED) |
|
786 |
{ |
||
787 |
638 |
mRedraw = true; |
|
788 |
638 |
} |
|
789 |
|||
790 |
174 |
void Button::widgetHidden(const Event &event A_UNUSED) |
|
791 |
{ |
||
792 |
✓✗ | 174 |
if (isBatchDrawRenders(openGLMode)) |
793 |
174 |
mVertexes2->clear(); |
|
794 |
174 |
mTextChunk.deleteImage(); |
|
795 |
174 |
mRedraw = true; |
|
796 |
174 |
mTextChanged = true; |
|
797 |
174 |
} |
|
798 |
|||
799 |
395 |
void Button::adjustSize() |
|
800 |
{ |
||
801 |
395 |
const Font *const font = getFont(); |
|
802 |
395 |
const Skin *const skin = mSkin[BUTTON_STANDARD]; |
|
803 |
✓✗ | 395 |
if (skin == nullptr) |
804 |
return; |
||
805 |
395 |
const int padding = skin->getPadding(); |
|
806 |
|||
807 |
✓✓ | 395 |
if (mImages != nullptr) |
808 |
{ |
||
809 |
24 |
const int width = font->getWidth(mCaption); |
|
810 |
✗✓ | 24 |
if (width != 0) |
811 |
{ |
||
812 |
const int spacing = mSpacing[BUTTON_STANDARD]; |
||
813 |
setWidth(width + mImageWidth + spacing + 2 * padding); |
||
814 |
} |
||
815 |
else |
||
816 |
{ |
||
817 |
24 |
setWidth(mImageWidth + 2 * padding); |
|
818 |
} |
||
819 |
24 |
int height = font->getHeight(); |
|
820 |
✗✓ | 24 |
if (height < mImageHeight) |
821 |
height = mImageHeight; |
||
822 |
24 |
setHeight(height + 2 * padding); |
|
823 |
} |
||
824 |
else |
||
825 |
{ |
||
826 |
371 |
setWidth(font->getWidth(mCaption) + 2 * padding); |
|
827 |
371 |
setHeight(font->getHeight() + 2 * padding); |
|
828 |
} |
||
829 |
} |
||
830 |
|||
831 |
void Button::keyPressed(KeyEvent& event) |
||
832 |
{ |
||
833 |
const InputActionT action = event.getActionId(); |
||
834 |
|||
835 |
if (action == InputAction::GUI_SELECT) |
||
836 |
{ |
||
837 |
mKeyPressed = true; |
||
838 |
event.consume(); |
||
839 |
} |
||
840 |
} |
||
841 |
|||
842 |
void Button::keyReleased(KeyEvent& event) |
||
843 |
{ |
||
844 |
const InputActionT action = event.getActionId(); |
||
845 |
|||
846 |
if (action == InputAction::GUI_SELECT && mKeyPressed) |
||
847 |
{ |
||
848 |
mKeyPressed = false; |
||
849 |
if (mStick) |
||
850 |
mPressed = !mPressed; |
||
851 |
distributeActionEvent(); |
||
852 |
event.consume(); |
||
853 |
} |
||
854 |
} |
||
855 |
|||
856 |
bool Button::isPressed2() const |
||
857 |
{ |
||
858 |
✗✗✗✗ ✗✗✗✗ ✓✗✗✓ |
146 |
return mPressed || isPressed(); |
859 |
} |
||
860 |
|||
861 |
bool Button::isPressed() const |
||
862 |
{ |
||
863 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✗✗✗✓ |
176 |
if (mMousePressed) |
864 |
return mHasMouse; |
||
865 |
176 |
return mKeyPressed; |
|
866 |
} |
||
867 |
|||
868 |
1 |
void Button::focusLost(const Event& event A_UNUSED) |
|
869 |
{ |
||
870 |
1 |
mMousePressed = false; |
|
871 |
1 |
mKeyPressed = false; |
|
872 |
1 |
} |
|
873 |
|||
874 |
void Button::mousePressed(MouseEvent& event) |
||
875 |
{ |
||
876 |
if (event.getButton() == MouseButton::LEFT) |
||
877 |
{ |
||
878 |
mMousePressed = true; |
||
879 |
event.consume(); |
||
880 |
} |
||
881 |
} |
||
882 |
|||
883 |
void Button::mouseEntered(MouseEvent& event A_UNUSED) |
||
884 |
{ |
||
885 |
mHasMouse = true; |
||
886 |
} |
||
887 |
|||
888 |
void Button::mouseExited(MouseEvent& event A_UNUSED) |
||
889 |
{ |
||
890 |
mHasMouse = false; |
||
891 |
} |
||
892 |
|||
893 |
void Button::mouseDragged(MouseEvent& event) |
||
894 |
{ |
||
895 |
event.consume(); |
||
896 |
} |
||
897 |
|||
898 |
333 |
void Button::setParent(Widget *widget) |
|
899 |
{ |
||
900 |
✓✓ | 333 |
if (mWindow != nullptr) |
901 |
331 |
mWindow->addWidgetListener(this); |
|
902 |
666 |
Widget::setParent(widget); |
|
903 |
333 |
} |
|
904 |
|||
905 |
2 |
void Button::setWindow(Widget *const widget) |
|
906 |
{ |
||
907 |
✓✗✓✗ |
2 |
if ((widget == nullptr) && (mWindow != nullptr)) |
908 |
{ |
||
909 |
2 |
mWindow->removeWidgetListener(this); |
|
910 |
2 |
mWindow = nullptr; |
|
911 |
} |
||
912 |
else |
||
913 |
{ |
||
914 |
Widget2::setWindow(widget); |
||
915 |
} |
||
916 |
✓✗✓✗ |
5 |
} |
Generated by: GCOVR (Version 3.3) |