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/scrollarea.h" |
||
68 |
|||
69 |
#include "settings.h" |
||
70 |
|||
71 |
#include "gui/gui.h" |
||
72 |
#include "gui/skin.h" |
||
73 |
|||
74 |
#include "utils/delete2.h" |
||
75 |
#include "utils/stringutils.h" |
||
76 |
|||
77 |
#include "render/graphics.h" |
||
78 |
|||
79 |
#include "render/vertexes/imagecollection.h" |
||
80 |
|||
81 |
#include "resources/imagerect.h" |
||
82 |
|||
83 |
#include "resources/image/image.h" |
||
84 |
|||
85 |
#include "debug.h" |
||
86 |
|||
87 |
int ScrollArea::instances = 0; |
||
88 |
float ScrollArea::mAlpha = 1.0; |
||
89 |
bool ScrollArea::mShowButtons = true; |
||
90 |
int ScrollArea::mMarkerSize = 0; |
||
91 |
int ScrollArea::mScrollbarSize = 12; |
||
92 |
1 |
ImageRect ScrollArea::background; |
|
93 |
1 |
ImageRect ScrollArea::vMarker; |
|
94 |
1 |
ImageRect ScrollArea::vMarkerHi; |
|
95 |
1 |
ImageRect ScrollArea::vBackground; |
|
96 |
1 |
ImageRect ScrollArea::hBackground; |
|
97 |
Image *ScrollArea::buttons[4][2]; |
||
98 |
|||
99 |
✓✓ | 3 |
static std::string const buttonFiles[2] = |
100 |
{ |
||
101 |
"scrollbuttons.xml", |
||
102 |
"scrollbuttons_pressed.xml" |
||
103 |
✓✗✓✗ ✗✗ |
5 |
}; |
104 |
|||
105 |
164 |
ScrollArea::ScrollArea(Widget2 *const widget2, |
|
106 |
Widget *const widget, |
||
107 |
const Opaque opaque, |
||
108 |
164 |
const std::string &skin) : |
|
109 |
BasicContainer(widget2), |
||
110 |
MouseListener(), |
||
111 |
WidgetListener(), |
||
112 |
✓✗✓✗ |
164 |
mVertexes(new ImageCollection), |
113 |
✓✗✓✗ |
164 |
mVertexes2(new ImageCollection), |
114 |
mHPolicy(SHOW_AUTO), |
||
115 |
mVPolicy(SHOW_AUTO), |
||
116 |
mVScroll(0), |
||
117 |
mHScroll(0), |
||
118 |
mScrollbarWidth(12), |
||
119 |
mUpButtonScrollAmount(10), |
||
120 |
mDownButtonScrollAmount(10), |
||
121 |
mLeftButtonScrollAmount(10), |
||
122 |
mRightButtonScrollAmount(10), |
||
123 |
mHorizontalMarkerDragOffset(0), |
||
124 |
mVerticalMarkerDragOffset(0), |
||
125 |
mX(0), |
||
126 |
mY(0), |
||
127 |
mClickX(0), |
||
128 |
mClickY(0), |
||
129 |
mXOffset(0), |
||
130 |
mYOffset(0), |
||
131 |
mDrawWidth(0), |
||
132 |
mDrawHeight(0), |
||
133 |
mVBarVisible(false), |
||
134 |
mHBarVisible(false), |
||
135 |
mUpButtonPressed(false), |
||
136 |
mDownButtonPressed(false), |
||
137 |
mLeftButtonPressed(false), |
||
138 |
mRightButtonPressed(false), |
||
139 |
mIsVerticalMarkerDragged(false), |
||
140 |
mIsHorizontalMarkerDragged(false), |
||
141 |
mOpaque(Opaque_true), |
||
142 |
984 |
mHasMouse(false) |
|
143 |
{ |
||
144 |
✓✗ | 164 |
setContent(widget); |
145 |
✓✗ | 164 |
addMouseListener(this); |
146 |
164 |
mOpaque = opaque; |
|
147 |
✓✗ | 328 |
init(skin); |
148 |
164 |
} |
|
149 |
|||
150 |
820 |
ScrollArea::~ScrollArea() |
|
151 |
{ |
||
152 |
✓✗ | 164 |
if (gui != nullptr) |
153 |
164 |
gui->removeDragged(this); |
|
154 |
|||
155 |
// Garbage collection |
||
156 |
✓✓ | 164 |
delete getContent(); |
157 |
|||
158 |
164 |
instances--; |
|
159 |
✓✓ | 164 |
if (instances == 0) |
160 |
{ |
||
161 |
35 |
Theme::unloadRect(background, 0, 8); |
|
162 |
35 |
Theme::unloadRect(vMarker, 0, 8); |
|
163 |
35 |
Theme::unloadRect(vMarkerHi, 0, 8); |
|
164 |
35 |
Theme::unloadRect(vBackground, 0, 8); |
|
165 |
35 |
Theme::unloadRect(hBackground, 0, 8); |
|
166 |
✓✓ | 105 |
for (int i = 0; i < 2; i ++) |
167 |
{ |
||
168 |
✓✓ | 630 |
for (int f = UP; f < BUTTONS_DIR; f ++) |
169 |
{ |
||
170 |
✓✗ | 280 |
if (buttons[f][i] != nullptr) |
171 |
280 |
buttons[f][i]->decRef(); |
|
172 |
} |
||
173 |
} |
||
174 |
} |
||
175 |
|||
176 |
✓✗ | 164 |
delete2(mVertexes) |
177 |
✓✗ | 164 |
delete2(mVertexes2) |
178 |
|||
179 |
164 |
setContent(nullptr); |
|
180 |
328 |
} |
|
181 |
|||
182 |
164 |
void ScrollArea::init(std::string skinName) |
|
183 |
{ |
||
184 |
328 |
setOpaque(mOpaque); |
|
185 |
|||
186 |
328 |
setUpButtonScrollAmount(2); |
|
187 |
328 |
setDownButtonScrollAmount(2); |
|
188 |
328 |
setLeftButtonScrollAmount(2); |
|
189 |
328 |
setRightButtonScrollAmount(2); |
|
190 |
|||
191 |
✓✓ | 164 |
if (instances == 0) |
192 |
{ |
||
193 |
✓✓ | 665 |
for (int f = 0; f < 9; f ++) |
194 |
{ |
||
195 |
315 |
background.grid[f] = nullptr; |
|
196 |
315 |
vMarker.grid[f] = nullptr; |
|
197 |
315 |
vMarkerHi.grid[f] = nullptr; |
|
198 |
315 |
vBackground.grid[f] = nullptr; |
|
199 |
315 |
hBackground.grid[f] = nullptr; |
|
200 |
} |
||
201 |
|||
202 |
// +++ here probably need move background from static |
||
203 |
✓✓ | 35 |
if (skinName.empty()) |
204 |
skinName = "scroll_background.xml"; |
||
205 |
✓✗ | 35 |
if (theme != nullptr) |
206 |
{ |
||
207 |
140 |
theme->loadRect(background, |
|
208 |
skinName, |
||
209 |
"scroll_background.xml", |
||
210 |
0, |
||
211 |
✓✗ | 35 |
8); |
212 |
✓✗ | 245 |
theme->loadRect(vMarker, |
213 |
"scroll.xml", |
||
214 |
"", |
||
215 |
0, |
||
216 |
✓✗ | 35 |
8); |
217 |
✓✗ | 245 |
theme->loadRect(vMarkerHi, |
218 |
"scroll_highlighted.xml", |
||
219 |
"scroll.xml", |
||
220 |
0, |
||
221 |
✓✗ | 35 |
8); |
222 |
✓✗ | 245 |
theme->loadRect(vBackground, |
223 |
"scroll_vbackground.xml", |
||
224 |
"", |
||
225 |
0, |
||
226 |
✓✗ | 35 |
8); |
227 |
✓✗ | 245 |
theme->loadRect(hBackground, |
228 |
"scroll_hbackground.xml", |
||
229 |
"", |
||
230 |
0, |
||
231 |
✓✗ | 35 |
8); |
232 |
} |
||
233 |
|||
234 |
✓✓ | 175 |
for (int i = 0; i < 2; i ++) |
235 |
{ |
||
236 |
70 |
Skin *skin = nullptr; |
|
237 |
✓✗ | 70 |
if (theme != nullptr) |
238 |
{ |
||
239 |
✓✗ | 280 |
skin = theme->load(buttonFiles[i], |
240 |
"scrollbuttons.xml", |
||
241 |
true, |
||
242 |
✓✗ | 140 |
Theme::getThemePath()); |
243 |
} |
||
244 |
✗✓ | 70 |
if (skin != nullptr) |
245 |
{ |
||
246 |
70 |
const ImageRect &rect = skin->getBorder(); |
|
247 |
✓✓ | 350 |
for (int f = UP; f < BUTTONS_DIR; f ++) |
248 |
{ |
||
249 |
✓✗ | 280 |
if (rect.grid[f] != nullptr) |
250 |
280 |
rect.grid[f]->incRef(); |
|
251 |
280 |
buttons[f][i] = rect.grid[f]; |
|
252 |
} |
||
253 |
✓✓ | 70 |
if (i == 0) |
254 |
{ |
||
255 |
✓✗ | 140 |
mShowButtons = (skin->getOption("showbuttons", 1) == 1); |
256 |
✓✗ | 140 |
mMarkerSize = skin->getOption("markersize", 0); |
257 |
✓✗ | 140 |
mScrollbarSize = skin->getOption("scrollbarsize", 12); |
258 |
} |
||
259 |
} |
||
260 |
else |
||
261 |
{ |
||
262 |
for (int f = UP; f < BUTTONS_DIR; f ++) |
||
263 |
buttons[f][i] = nullptr; |
||
264 |
} |
||
265 |
✓✗ | 70 |
if (theme != nullptr) |
266 |
70 |
theme->unload(skin); |
|
267 |
} |
||
268 |
} |
||
269 |
164 |
mScrollbarWidth = mScrollbarSize; |
|
270 |
164 |
instances++; |
|
271 |
164 |
} |
|
272 |
|||
273 |
1 |
void ScrollArea::logic() |
|
274 |
{ |
||
275 |
BLOCK_START("ScrollArea::logic") |
||
276 |
✓✗ | 2 |
if (!isVisible()) |
277 |
{ |
||
278 |
BLOCK_END("ScrollArea::logic") |
||
279 |
return; |
||
280 |
} |
||
281 |
|||
282 |
1 |
checkPolicies(); |
|
283 |
|||
284 |
2 |
setVerticalScrollAmount(mVScroll); |
|
285 |
2 |
setHorizontalScrollAmount(mHScroll); |
|
286 |
|||
287 |
1 |
Widget *const content = getContent(); |
|
288 |
✓✗ | 1 |
if (content != nullptr) |
289 |
{ |
||
290 |
1 |
unsigned int frameSize = content->getFrameSize(); |
|
291 |
1 |
content->setPosition(-mHScroll + frameSize, -mVScroll + frameSize); |
|
292 |
1 |
content->logic(); |
|
293 |
|||
294 |
// When no scrollbar in a certain direction, |
||
295 |
// adapt content size to match the content dimension exactly. |
||
296 |
1 |
frameSize = 2 * content->getFrameSize(); |
|
297 |
✓✗ | 1 |
if (mHPolicy == ScrollArea::SHOW_NEVER) |
298 |
{ |
||
299 |
✓✗ | 3 |
content->setWidth((mVBarVisible ? (mDimension.width |
300 |
3 |
- mScrollbarWidth) : mDimension.width) - frameSize); |
|
301 |
} |
||
302 |
✗✓ | 1 |
if (mVPolicy == ScrollArea::SHOW_NEVER) |
303 |
{ |
||
304 |
content->setHeight((mHBarVisible ? (mDimension.height |
||
305 |
- mScrollbarWidth) : mDimension.height) - frameSize); |
||
306 |
} |
||
307 |
} |
||
308 |
|||
309 |
✗✓ | 1 |
if (mUpButtonPressed) |
310 |
setVerticalScrollAmount(mVScroll - mUpButtonScrollAmount); |
||
311 |
✗✓ | 1 |
else if (mDownButtonPressed) |
312 |
setVerticalScrollAmount(mVScroll + mDownButtonScrollAmount); |
||
313 |
✗✓ | 1 |
else if (mLeftButtonPressed) |
314 |
setHorizontalScrollAmount(mHScroll - mLeftButtonScrollAmount); |
||
315 |
✗✓ | 1 |
else if (mRightButtonPressed) |
316 |
setHorizontalScrollAmount(mHScroll + mRightButtonScrollAmount); |
||
317 |
BLOCK_END("ScrollArea::logic") |
||
318 |
} |
||
319 |
|||
320 |
17 |
void ScrollArea::updateAlpha() |
|
321 |
{ |
||
322 |
const float alpha = std::max(settings.guiAlpha, |
||
323 |
51 |
theme->getMinimumOpacity()); |
|
324 |
|||
325 |
✗✓ | 17 |
if (alpha != mAlpha) |
326 |
{ |
||
327 |
mAlpha = alpha; |
||
328 |
for (int a = 0; a < 9; a++) |
||
329 |
{ |
||
330 |
if (background.grid[a] != nullptr) |
||
331 |
background.grid[a]->setAlpha(mAlpha); |
||
332 |
if (hBackground.grid[a] != nullptr) |
||
333 |
hBackground.grid[a]->setAlpha(mAlpha); |
||
334 |
if (vBackground.grid[a] != nullptr) |
||
335 |
vBackground.grid[a]->setAlpha(mAlpha); |
||
336 |
if (vMarker.grid[a] != nullptr) |
||
337 |
vMarker.grid[a]->setAlpha(mAlpha); |
||
338 |
if (vMarkerHi.grid[a] != nullptr) |
||
339 |
vMarkerHi.grid[a]->setAlpha(mAlpha); |
||
340 |
} |
||
341 |
} |
||
342 |
17 |
} |
|
343 |
|||
344 |
17 |
void ScrollArea::draw(Graphics *const graphics) |
|
345 |
{ |
||
346 |
BLOCK_START("ScrollArea::draw") |
||
347 |
✓✓✗✓ |
17 |
if (mVBarVisible || mHBarVisible) |
348 |
{ |
||
349 |
✗✓ | 11 |
if (mOpaque == Opaque_false) |
350 |
updateCalcFlag(graphics); |
||
351 |
// need add caching or remove calc calls. |
||
352 |
// if (mRedraw) |
||
353 |
{ |
||
354 |
11 |
mVertexes->clear(); |
|
355 |
✓✗ | 11 |
if (mVBarVisible) |
356 |
{ |
||
357 |
✗✓ | 11 |
if (mShowButtons) |
358 |
{ |
||
359 |
calcButton(graphics, UP); |
||
360 |
calcButton(graphics, DOWN); |
||
361 |
} |
||
362 |
11 |
calcVBar(graphics); |
|
363 |
11 |
calcVMarker(graphics); |
|
364 |
} |
||
365 |
|||
366 |
✗✓ | 11 |
if (mHBarVisible) |
367 |
{ |
||
368 |
if (mShowButtons) |
||
369 |
{ |
||
370 |
calcButton(graphics, LEFT); |
||
371 |
calcButton(graphics, RIGHT); |
||
372 |
} |
||
373 |
calcHBar(graphics); |
||
374 |
calcHMarker(graphics); |
||
375 |
} |
||
376 |
11 |
graphics->finalize(mVertexes); |
|
377 |
} |
||
378 |
11 |
graphics->drawTileCollection(mVertexes); |
|
379 |
} |
||
380 |
|||
381 |
17 |
updateAlpha(); |
|
382 |
|||
383 |
✓✗ | 17 |
if (mRedraw) |
384 |
{ |
||
385 |
17 |
const bool redraw = graphics->getRedraw(); |
|
386 |
17 |
graphics->setRedraw(true); |
|
387 |
17 |
drawChildren(graphics); |
|
388 |
17 |
graphics->setRedraw(redraw); |
|
389 |
} |
||
390 |
else |
||
391 |
{ |
||
392 |
drawChildren(graphics); |
||
393 |
} |
||
394 |
17 |
mRedraw = false; |
|
395 |
BLOCK_END("ScrollArea::draw") |
||
396 |
17 |
} |
|
397 |
|||
398 |
void ScrollArea::safeDraw(Graphics *const graphics) |
||
399 |
{ |
||
400 |
BLOCK_START("ScrollArea::draw") |
||
401 |
if (mVBarVisible) |
||
402 |
{ |
||
403 |
if (mShowButtons) |
||
404 |
{ |
||
405 |
drawButton(graphics, UP); |
||
406 |
drawButton(graphics, DOWN); |
||
407 |
} |
||
408 |
drawVBar(graphics); |
||
409 |
drawVMarker(graphics); |
||
410 |
} |
||
411 |
|||
412 |
if (mHBarVisible) |
||
413 |
{ |
||
414 |
if (mShowButtons) |
||
415 |
{ |
||
416 |
drawButton(graphics, LEFT); |
||
417 |
drawButton(graphics, RIGHT); |
||
418 |
} |
||
419 |
drawHBar(graphics); |
||
420 |
drawHMarker(graphics); |
||
421 |
} |
||
422 |
|||
423 |
updateAlpha(); |
||
424 |
|||
425 |
safeDrawChildren(graphics); |
||
426 |
mRedraw = false; |
||
427 |
BLOCK_END("ScrollArea::draw") |
||
428 |
} |
||
429 |
|||
430 |
16 |
void ScrollArea::updateCalcFlag(const Graphics *const graphics) |
|
431 |
{ |
||
432 |
✗✓ | 16 |
if (!mRedraw) |
433 |
{ |
||
434 |
// because we don't know where parent windows was moved, |
||
435 |
// need recalc vertexes |
||
436 |
const ClipRect &rect = graphics->getTopClip(); |
||
437 |
if (rect.xOffset != mXOffset || rect.yOffset != mYOffset) |
||
438 |
{ |
||
439 |
mRedraw = true; |
||
440 |
mXOffset = rect.xOffset; |
||
441 |
mYOffset = rect.yOffset; |
||
442 |
} |
||
443 |
else if (rect.width != mDrawWidth || rect.height != mDrawHeight) |
||
444 |
{ |
||
445 |
mRedraw = true; |
||
446 |
mDrawWidth = rect.width; |
||
447 |
mDrawHeight = rect.height; |
||
448 |
} |
||
449 |
else if (graphics->getRedraw()) |
||
450 |
{ |
||
451 |
mRedraw = true; |
||
452 |
} |
||
453 |
} |
||
454 |
16 |
} |
|
455 |
|||
456 |
16 |
void ScrollArea::drawFrame(Graphics *const graphics) |
|
457 |
{ |
||
458 |
BLOCK_START("ScrollArea::drawFrame") |
||
459 |
✓✗ | 16 |
if (mOpaque == Opaque_true) |
460 |
{ |
||
461 |
16 |
updateCalcFlag(graphics); |
|
462 |
|||
463 |
✓✗ | 16 |
if (mRedraw) |
464 |
{ |
||
465 |
16 |
const int bs = mFrameSize * 2; |
|
466 |
16 |
const int w = mDimension.width + bs; |
|
467 |
16 |
const int h = mDimension.height + bs; |
|
468 |
16 |
mVertexes2->clear(); |
|
469 |
16 |
graphics->calcWindow(mVertexes2, |
|
470 |
0, 0, |
||
471 |
w, h, |
||
472 |
32 |
background); |
|
473 |
16 |
graphics->finalize(mVertexes2); |
|
474 |
} |
||
475 |
16 |
graphics->drawTileCollection(mVertexes2); |
|
476 |
} |
||
477 |
BLOCK_END("ScrollArea::drawFrame") |
||
478 |
16 |
} |
|
479 |
|||
480 |
void ScrollArea::safeDrawFrame(Graphics *const graphics) |
||
481 |
{ |
||
482 |
BLOCK_START("ScrollArea::drawFrame") |
||
483 |
if (mOpaque == Opaque_true) |
||
484 |
{ |
||
485 |
const int bs = mFrameSize * 2; |
||
486 |
const int w = mDimension.width + bs; |
||
487 |
const int h = mDimension.height + bs; |
||
488 |
|||
489 |
updateCalcFlag(graphics); |
||
490 |
graphics->drawImageRect(0, 0, |
||
491 |
w, h, |
||
492 |
background); |
||
493 |
} |
||
494 |
BLOCK_END("ScrollArea::drawFrame") |
||
495 |
} |
||
496 |
|||
497 |
void ScrollArea::setOpaque(Opaque opaque) |
||
498 |
{ |
||
499 |
mOpaque = opaque; |
||
500 |
✗✗✓✓ |
328 |
setFrameSize(mOpaque == Opaque_true ? 2 : 0); |
501 |
} |
||
502 |
|||
503 |
Image *ScrollArea::getImageByState(Rect &dim, const BUTTON_DIR dir) |
||
504 |
{ |
||
505 |
int state = 0; |
||
506 |
|||
507 |
switch (dir) |
||
508 |
{ |
||
509 |
case UP: |
||
510 |
state = mUpButtonPressed ? 1 : 0; |
||
511 |
dim = getUpButtonDimension(); |
||
512 |
break; |
||
513 |
case DOWN: |
||
514 |
state = mDownButtonPressed ? 1 : 0; |
||
515 |
dim = getDownButtonDimension(); |
||
516 |
break; |
||
517 |
case LEFT: |
||
518 |
state = mLeftButtonPressed ? 1 : 0; |
||
519 |
dim = getLeftButtonDimension(); |
||
520 |
break; |
||
521 |
case RIGHT: |
||
522 |
state = mRightButtonPressed ? 1 : 0; |
||
523 |
dim = getRightButtonDimension(); |
||
524 |
break; |
||
525 |
case BUTTONS_DIR: |
||
526 |
default: |
||
527 |
logger->log("ScrollArea::drawButton unknown dir: " |
||
528 |
+ toString(CAST_U32(dir))); |
||
529 |
return nullptr; |
||
530 |
} |
||
531 |
return buttons[CAST_SIZE(dir)][state]; |
||
532 |
} |
||
533 |
|||
534 |
void ScrollArea::drawButton(Graphics *const graphics, |
||
535 |
const BUTTON_DIR dir) |
||
536 |
{ |
||
537 |
Rect dim; |
||
538 |
const Image *const image = getImageByState(dim, dir); |
||
539 |
|||
540 |
if (image != nullptr) |
||
541 |
graphics->drawImage(image, dim.x, dim.y); |
||
542 |
} |
||
543 |
|||
544 |
void ScrollArea::calcButton(Graphics *const graphics, |
||
545 |
const BUTTON_DIR dir) |
||
546 |
{ |
||
547 |
Rect dim; |
||
548 |
const Image *const image = getImageByState(dim, dir); |
||
549 |
|||
550 |
if (image != nullptr) |
||
551 |
{ |
||
552 |
static_cast<Graphics*>(graphics)->calcTileCollection( |
||
553 |
mVertexes, image, dim.x, dim.y); |
||
554 |
} |
||
555 |
} |
||
556 |
|||
557 |
void ScrollArea::drawVBar(Graphics *const graphics) const |
||
558 |
{ |
||
559 |
const Rect &dim = getVerticalBarDimension(); |
||
560 |
|||
561 |
if (vBackground.grid[4] != nullptr) |
||
562 |
{ |
||
563 |
graphics->drawPattern(vBackground.grid[4], |
||
564 |
dim.x, dim.y, dim.width, dim.height); |
||
565 |
} |
||
566 |
if (vBackground.grid[1] != nullptr) |
||
567 |
{ |
||
568 |
graphics->drawPattern(vBackground.grid[1], |
||
569 |
dim.x, dim.y, |
||
570 |
dim.width, vBackground.grid[1]->getHeight()); |
||
571 |
} |
||
572 |
if (vBackground.grid[7] != nullptr) |
||
573 |
{ |
||
574 |
graphics->drawPattern(vBackground.grid[7], |
||
575 |
dim.x, dim.height - vBackground.grid[7]->getHeight() + dim.y, |
||
576 |
dim.width, vBackground.grid[7]->getHeight()); |
||
577 |
} |
||
578 |
} |
||
579 |
|||
580 |
11 |
void ScrollArea::calcVBar(const Graphics *const graphics) |
|
581 |
{ |
||
582 |
22 |
const Rect &dim = getVerticalBarDimension(); |
|
583 |
|||
584 |
✓✗ | 11 |
if (vBackground.grid[4] != nullptr) |
585 |
{ |
||
586 |
11 |
graphics->calcPattern(mVertexes, |
|
587 |
vBackground.grid[4], |
||
588 |
11 |
dim.x, dim.y, |
|
589 |
22 |
dim.width, dim.height); |
|
590 |
} |
||
591 |
✓✗ | 11 |
if (vBackground.grid[1] != nullptr) |
592 |
{ |
||
593 |
22 |
graphics->calcPattern(mVertexes, |
|
594 |
vBackground.grid[1], |
||
595 |
11 |
dim.x, dim.y, |
|
596 |
33 |
dim.width, vBackground.grid[1]->getHeight()); |
|
597 |
} |
||
598 |
✓✗ | 11 |
if (vBackground.grid[7] != nullptr) |
599 |
{ |
||
600 |
33 |
graphics->calcPattern(mVertexes, |
|
601 |
vBackground.grid[7], |
||
602 |
22 |
dim.x, dim.height - vBackground.grid[7]->getHeight() + dim.y, |
|
603 |
33 |
dim.width, vBackground.grid[7]->getHeight()); |
|
604 |
} |
||
605 |
11 |
} |
|
606 |
|||
607 |
void ScrollArea::drawHBar(Graphics *const graphics) const |
||
608 |
{ |
||
609 |
const Rect &dim = getHorizontalBarDimension(); |
||
610 |
|||
611 |
if (hBackground.grid[4] != nullptr) |
||
612 |
{ |
||
613 |
graphics->drawPattern(hBackground.grid[4], |
||
614 |
dim.x, dim.y, |
||
615 |
dim.width, dim.height); |
||
616 |
} |
||
617 |
|||
618 |
if (hBackground.grid[3] != nullptr) |
||
619 |
{ |
||
620 |
graphics->drawPattern(hBackground.grid[3], |
||
621 |
dim.x, dim.y, |
||
622 |
hBackground.grid[3]->getWidth(), dim.height); |
||
623 |
} |
||
624 |
|||
625 |
if (hBackground.grid[5] != nullptr) |
||
626 |
{ |
||
627 |
graphics->drawPattern(hBackground.grid[5], |
||
628 |
dim.x + dim.width - hBackground.grid[5]->getWidth(), |
||
629 |
dim.y, |
||
630 |
hBackground.grid[5]->getWidth(), |
||
631 |
dim.height); |
||
632 |
} |
||
633 |
} |
||
634 |
|||
635 |
void ScrollArea::calcHBar(const Graphics *const graphics) |
||
636 |
{ |
||
637 |
const Rect &dim = getHorizontalBarDimension(); |
||
638 |
|||
639 |
if (hBackground.grid[4] != nullptr) |
||
640 |
{ |
||
641 |
graphics->calcPattern(mVertexes, |
||
642 |
hBackground.grid[4], |
||
643 |
dim.x, dim.y, |
||
644 |
dim.width, dim.height); |
||
645 |
} |
||
646 |
|||
647 |
if (hBackground.grid[3] != nullptr) |
||
648 |
{ |
||
649 |
graphics->calcPattern(mVertexes, |
||
650 |
hBackground.grid[3], |
||
651 |
dim.x, dim.y, |
||
652 |
hBackground.grid[3]->getWidth(), dim.height); |
||
653 |
} |
||
654 |
|||
655 |
if (hBackground.grid[5] != nullptr) |
||
656 |
{ |
||
657 |
graphics->calcPattern(mVertexes, |
||
658 |
hBackground.grid[5], |
||
659 |
dim.x + dim.width - hBackground.grid[5]->getWidth(), |
||
660 |
dim.y, |
||
661 |
hBackground.grid[5]->getWidth(), |
||
662 |
dim.height); |
||
663 |
} |
||
664 |
} |
||
665 |
|||
666 |
void ScrollArea::drawVMarker(Graphics *const graphics) |
||
667 |
{ |
||
668 |
const Rect &dim = getVerticalMarkerDimension(); |
||
669 |
|||
670 |
if ((mHasMouse) && (mX > (mDimension.width - mScrollbarWidth))) |
||
671 |
{ |
||
672 |
graphics->drawImageRect(dim.x, dim.y, |
||
673 |
dim.width, dim.height, |
||
674 |
vMarkerHi); |
||
675 |
} |
||
676 |
else |
||
677 |
{ |
||
678 |
graphics->drawImageRect(dim.x, dim.y, |
||
679 |
dim.width, dim.height, |
||
680 |
vMarker); |
||
681 |
} |
||
682 |
} |
||
683 |
|||
684 |
11 |
void ScrollArea::calcVMarker(Graphics *const graphics) |
|
685 |
{ |
||
686 |
22 |
const Rect &dim = getVerticalMarkerDimension(); |
|
687 |
|||
688 |
✗✓✗✗ |
11 |
if ((mHasMouse) && (mX > (mDimension.width - mScrollbarWidth))) |
689 |
{ |
||
690 |
graphics->calcWindow(mVertexes, |
||
691 |
dim.x, dim.y, |
||
692 |
dim.width, dim.height, |
||
693 |
vMarkerHi); |
||
694 |
} |
||
695 |
else |
||
696 |
{ |
||
697 |
11 |
graphics->calcWindow(mVertexes, |
|
698 |
11 |
dim.x, dim.y, |
|
699 |
11 |
dim.width, dim.height, |
|
700 |
22 |
vMarker); |
|
701 |
} |
||
702 |
11 |
} |
|
703 |
|||
704 |
void ScrollArea::drawHMarker(Graphics *const graphics) |
||
705 |
{ |
||
706 |
const Rect dim = getHorizontalMarkerDimension(); |
||
707 |
|||
708 |
if ((mHasMouse) && (mY > (mDimension.height - mScrollbarWidth))) |
||
709 |
{ |
||
710 |
graphics->drawImageRect(dim.x, dim.y, |
||
711 |
dim.width, dim.height, |
||
712 |
vMarkerHi); |
||
713 |
} |
||
714 |
else |
||
715 |
{ |
||
716 |
graphics->drawImageRect( |
||
717 |
dim.x, dim.y, |
||
718 |
dim.width, dim.height, |
||
719 |
vMarker); |
||
720 |
} |
||
721 |
} |
||
722 |
|||
723 |
void ScrollArea::calcHMarker(Graphics *const graphics) |
||
724 |
{ |
||
725 |
const Rect dim = getHorizontalMarkerDimension(); |
||
726 |
|||
727 |
if ((mHasMouse) && (mY > (mDimension.height - mScrollbarWidth))) |
||
728 |
{ |
||
729 |
graphics->calcWindow(mVertexes, |
||
730 |
dim.x, dim.y, |
||
731 |
dim.width, dim.height, |
||
732 |
vMarkerHi); |
||
733 |
} |
||
734 |
else |
||
735 |
{ |
||
736 |
graphics->calcWindow(mVertexes, |
||
737 |
dim.x, dim.y, |
||
738 |
dim.width, dim.height, |
||
739 |
vMarker); |
||
740 |
} |
||
741 |
} |
||
742 |
|||
743 |
void ScrollArea::mouseMoved(MouseEvent& event) |
||
744 |
{ |
||
745 |
mX = event.getX(); |
||
746 |
mY = event.getY(); |
||
747 |
} |
||
748 |
|||
749 |
void ScrollArea::mouseEntered(MouseEvent& event A_UNUSED) |
||
750 |
{ |
||
751 |
mHasMouse = true; |
||
752 |
} |
||
753 |
|||
754 |
void ScrollArea::mouseExited(MouseEvent& event A_UNUSED) |
||
755 |
{ |
||
756 |
mHasMouse = false; |
||
757 |
} |
||
758 |
|||
759 |
void ScrollArea::widgetResized(const Event &event A_UNUSED) |
||
760 |
{ |
||
761 |
mRedraw = true; |
||
762 |
Widget *const content = getContent(); |
||
763 |
if (content != nullptr) |
||
764 |
{ |
||
765 |
const unsigned int frameSize = 2 * mFrameSize; |
||
766 |
content->setSize(mDimension.width - frameSize, |
||
767 |
mDimension.height - frameSize); |
||
768 |
} |
||
769 |
} |
||
770 |
|||
771 |
void ScrollArea::widgetMoved(const Event& event A_UNUSED) |
||
772 |
{ |
||
773 |
mRedraw = true; |
||
774 |
} |
||
775 |
|||
776 |
void ScrollArea::mousePressed(MouseEvent& event) |
||
777 |
{ |
||
778 |
const int x = event.getX(); |
||
779 |
const int y = event.getY(); |
||
780 |
|||
781 |
if (getUpButtonDimension().isPointInRect(x, y)) |
||
782 |
{ |
||
783 |
setVerticalScrollAmount(mVScroll |
||
784 |
- mUpButtonScrollAmount); |
||
785 |
mUpButtonPressed = true; |
||
786 |
event.consume(); |
||
787 |
} |
||
788 |
else if (getDownButtonDimension().isPointInRect(x, y)) |
||
789 |
{ |
||
790 |
setVerticalScrollAmount(mVScroll |
||
791 |
+ mDownButtonScrollAmount); |
||
792 |
mDownButtonPressed = true; |
||
793 |
event.consume(); |
||
794 |
} |
||
795 |
else if (getLeftButtonDimension().isPointInRect(x, y)) |
||
796 |
{ |
||
797 |
setHorizontalScrollAmount(mHScroll |
||
798 |
- mLeftButtonScrollAmount); |
||
799 |
mLeftButtonPressed = true; |
||
800 |
event.consume(); |
||
801 |
} |
||
802 |
else if (getRightButtonDimension().isPointInRect(x, y)) |
||
803 |
{ |
||
804 |
setHorizontalScrollAmount(mHScroll |
||
805 |
+ mRightButtonScrollAmount); |
||
806 |
mRightButtonPressed = true; |
||
807 |
event.consume(); |
||
808 |
} |
||
809 |
else if (getVerticalMarkerDimension().isPointInRect(x, y)) |
||
810 |
{ |
||
811 |
mIsHorizontalMarkerDragged = false; |
||
812 |
mIsVerticalMarkerDragged = true; |
||
813 |
|||
814 |
mVerticalMarkerDragOffset = y - getVerticalMarkerDimension().y; |
||
815 |
event.consume(); |
||
816 |
} |
||
817 |
else if (getVerticalBarDimension().isPointInRect(x, y)) |
||
818 |
{ |
||
819 |
if (y < getVerticalMarkerDimension().y) |
||
820 |
{ |
||
821 |
setVerticalScrollAmount(mVScroll |
||
822 |
- CAST_S32(getChildrenArea().height * 0.1)); |
||
823 |
} |
||
824 |
else |
||
825 |
{ |
||
826 |
setVerticalScrollAmount(mVScroll |
||
827 |
+ CAST_S32(getChildrenArea().height * 0.1)); |
||
828 |
} |
||
829 |
event.consume(); |
||
830 |
} |
||
831 |
else if (getHorizontalMarkerDimension().isPointInRect(x, y)) |
||
832 |
{ |
||
833 |
mIsHorizontalMarkerDragged = true; |
||
834 |
mIsVerticalMarkerDragged = false; |
||
835 |
mHorizontalMarkerDragOffset = x - getHorizontalMarkerDimension().x; |
||
836 |
event.consume(); |
||
837 |
} |
||
838 |
else if (getHorizontalBarDimension().isPointInRect(x, y)) |
||
839 |
{ |
||
840 |
if (x < getHorizontalMarkerDimension().x) |
||
841 |
{ |
||
842 |
setHorizontalScrollAmount(mHScroll |
||
843 |
- CAST_S32(getChildrenArea().width * 0.1)); |
||
844 |
} |
||
845 |
else |
||
846 |
{ |
||
847 |
setHorizontalScrollAmount(mHScroll |
||
848 |
+ CAST_S32(getChildrenArea().width * 0.1)); |
||
849 |
} |
||
850 |
event.consume(); |
||
851 |
} |
||
852 |
|||
853 |
if (event.getButton() == MouseButton::LEFT && |
||
854 |
!event.isConsumed()) |
||
855 |
{ |
||
856 |
mClickX = event.getX(); |
||
857 |
mClickY = event.getY(); |
||
858 |
} |
||
859 |
} |
||
860 |
|||
861 |
void ScrollArea::mouseReleased(MouseEvent& event) |
||
862 |
{ |
||
863 |
if (event.getButton() == MouseButton::LEFT && |
||
864 |
mClickX != 0 && |
||
865 |
mClickY != 0) |
||
866 |
{ |
||
867 |
if (!event.isConsumed()) |
||
868 |
{ |
||
869 |
#ifdef ANDROID |
||
870 |
int dx = mClickX - event.getX(); |
||
871 |
int dy = mClickY - event.getY(); |
||
872 |
#else // ANDROID |
||
873 |
|||
874 |
int dx = event.getX() - mClickX; |
||
875 |
int dy = event.getY() - mClickY; |
||
876 |
#endif // ANDROID |
||
877 |
|||
878 |
if ((dx < 20 && dx > 0) || (dx > -20 && dx < 0)) |
||
879 |
dx = 0; |
||
880 |
|||
881 |
if ((dy < 20 && dy > 0) || (dy > -20 && dy < 0)) |
||
882 |
dy = 0; |
||
883 |
|||
884 |
if (abs(dx) > abs(dy)) |
||
885 |
{ |
||
886 |
int s = mHScroll + dx; |
||
887 |
if (s < 0) |
||
888 |
{ |
||
889 |
s = 0; |
||
890 |
} |
||
891 |
else |
||
892 |
{ |
||
893 |
const int maxH = getHorizontalMaxScroll(); |
||
894 |
if (s > maxH) |
||
895 |
s = maxH; |
||
896 |
} |
||
897 |
|||
898 |
setHorizontalScrollAmount(s); |
||
899 |
} |
||
900 |
else if (dy != 0) |
||
901 |
{ |
||
902 |
int s = mVScroll + dy; |
||
903 |
if (s < 0) |
||
904 |
{ |
||
905 |
s = 0; |
||
906 |
} |
||
907 |
else |
||
908 |
{ |
||
909 |
const int maxV = getVerticalMaxScroll(); |
||
910 |
if (s > maxV) |
||
911 |
s = maxV; |
||
912 |
} |
||
913 |
|||
914 |
setVerticalScrollAmount(s); |
||
915 |
} |
||
916 |
mClickX = 0; |
||
917 |
mClickY = 0; |
||
918 |
if (mMouseConsume && ((dx != 0) || (dy != 0))) |
||
919 |
event.consume(); |
||
920 |
} |
||
921 |
} |
||
922 |
mUpButtonPressed = false; |
||
923 |
mDownButtonPressed = false; |
||
924 |
mLeftButtonPressed = false; |
||
925 |
mRightButtonPressed = false; |
||
926 |
mIsHorizontalMarkerDragged = false; |
||
927 |
mIsVerticalMarkerDragged = false; |
||
928 |
if (mMouseConsume) |
||
929 |
event.consume(); |
||
930 |
mRedraw = true; |
||
931 |
} |
||
932 |
|||
933 |
void ScrollArea::mouseDragged(MouseEvent &event) |
||
934 |
{ |
||
935 |
if (mIsVerticalMarkerDragged) |
||
936 |
{ |
||
937 |
const Rect barDim = getVerticalBarDimension(); |
||
938 |
const int length = getVerticalMarkerDimension().height; |
||
939 |
|||
940 |
if ((barDim.height - length) > 0) |
||
941 |
{ |
||
942 |
const int pos = event.getY() - barDim.y |
||
943 |
- mVerticalMarkerDragOffset; |
||
944 |
setVerticalScrollAmount((getVerticalMaxScroll() * pos) |
||
945 |
/ (barDim.height - length)); |
||
946 |
} |
||
947 |
else |
||
948 |
{ |
||
949 |
setVerticalScrollAmount(0); |
||
950 |
} |
||
951 |
} |
||
952 |
|||
953 |
if (mIsHorizontalMarkerDragged) |
||
954 |
{ |
||
955 |
const Rect barDim = getHorizontalBarDimension(); |
||
956 |
const int length = getHorizontalMarkerDimension().width; |
||
957 |
|||
958 |
if ((barDim.width - length) > 0) |
||
959 |
{ |
||
960 |
const int pos = event.getX() - barDim.x |
||
961 |
- mHorizontalMarkerDragOffset; |
||
962 |
setHorizontalScrollAmount((getHorizontalMaxScroll() * pos) |
||
963 |
/ (barDim.width - length)); |
||
964 |
} |
||
965 |
else |
||
966 |
{ |
||
967 |
setHorizontalScrollAmount(0); |
||
968 |
} |
||
969 |
} |
||
970 |
|||
971 |
event.consume(); |
||
972 |
mRedraw = true; |
||
973 |
} |
||
974 |
|||
975 |
11 |
Rect ScrollArea::getVerticalBarDimension() const |
|
976 |
{ |
||
977 |
✗✓ | 11 |
if (!mVBarVisible) |
978 |
return Rect(0, 0, 0, 0); |
||
979 |
|||
980 |
✗✓ | 11 |
const int height = mShowButtons ? mScrollbarWidth : 0; |
981 |
✗✓ | 11 |
if (mHBarVisible) |
982 |
{ |
||
983 |
return Rect(mDimension.width - mScrollbarWidth, |
||
984 |
height, |
||
985 |
mScrollbarWidth, |
||
986 |
mDimension.height - 2 * height - mScrollbarWidth); |
||
987 |
} |
||
988 |
|||
989 |
11 |
return Rect(mDimension.width - mScrollbarWidth, |
|
990 |
height, |
||
991 |
11 |
mScrollbarWidth, |
|
992 |
22 |
mDimension.height - 2 * height); |
|
993 |
} |
||
994 |
|||
995 |
Rect ScrollArea::getHorizontalBarDimension() const |
||
996 |
{ |
||
997 |
if (!mHBarVisible) |
||
998 |
return Rect(0, 0, 0, 0); |
||
999 |
|||
1000 |
const int width = mShowButtons ? mScrollbarWidth : 0; |
||
1001 |
if (mVBarVisible) |
||
1002 |
{ |
||
1003 |
return Rect(width, |
||
1004 |
mDimension.height - mScrollbarWidth, |
||
1005 |
mDimension.width - 2 * width - mScrollbarWidth, |
||
1006 |
mScrollbarWidth); |
||
1007 |
} |
||
1008 |
|||
1009 |
return Rect(width, |
||
1010 |
mDimension.height - mScrollbarWidth, |
||
1011 |
mDimension.width - 2 * width, |
||
1012 |
mScrollbarWidth); |
||
1013 |
} |
||
1014 |
|||
1015 |
11 |
Rect ScrollArea::getVerticalMarkerDimension() |
|
1016 |
{ |
||
1017 |
✗✓ | 11 |
if (!mVBarVisible) |
1018 |
return Rect(0, 0, 0, 0); |
||
1019 |
|||
1020 |
int length; |
||
1021 |
int pos; |
||
1022 |
int height; |
||
1023 |
const int h2 = mShowButtons |
||
1024 |
✗✓ | 11 |
? mScrollbarWidth : mMarkerSize / 2; |
1025 |
const Widget *content; |
||
1026 |
✓✗ | 22 |
if (!mWidgets.empty()) |
1027 |
22 |
content = *mWidgets.begin(); |
|
1028 |
else |
||
1029 |
content = nullptr; |
||
1030 |
|||
1031 |
✗✓ | 11 |
if (mHBarVisible) |
1032 |
height = mDimension.height - 2 * h2 - mScrollbarWidth; |
||
1033 |
else |
||
1034 |
11 |
height = mDimension.height - 2 * h2; |
|
1035 |
|||
1036 |
11 |
const int maxV = getVerticalMaxScroll(); |
|
1037 |
✓✗✗✓ |
11 |
if ((mMarkerSize != 0) && (maxV != 0)) |
1038 |
{ |
||
1039 |
pos = (mVScroll * height / maxV - mMarkerSize / 2); |
||
1040 |
length = mMarkerSize; |
||
1041 |
} |
||
1042 |
else |
||
1043 |
{ |
||
1044 |
✓✗ | 11 |
if (content != nullptr) |
1045 |
{ |
||
1046 |
11 |
const int h3 = content->getHeight(); |
|
1047 |
✓✓ | 11 |
if (h3 != 0) |
1048 |
10 |
length = (height * getChildrenArea().height) / h3; |
|
1049 |
else |
||
1050 |
length = height; |
||
1051 |
} |
||
1052 |
else |
||
1053 |
{ |
||
1054 |
length = height; |
||
1055 |
} |
||
1056 |
|||
1057 |
✗✓ | 11 |
if (length < mScrollbarWidth) |
1058 |
length = mScrollbarWidth; |
||
1059 |
|||
1060 |
✓✓ | 11 |
if (length > height) |
1061 |
10 |
length = height; |
|
1062 |
|||
1063 |
✗✓ | 11 |
if (maxV != 0) |
1064 |
pos = ((height - length) * mVScroll) / maxV; |
||
1065 |
else |
||
1066 |
pos = 0; |
||
1067 |
} |
||
1068 |
|||
1069 |
11 |
return Rect(mDimension.width - mScrollbarWidth, h2 + pos, |
|
1070 |
22 |
mScrollbarWidth, length); |
|
1071 |
} |
||
1072 |
|||
1073 |
Rect ScrollArea::getHorizontalMarkerDimension() |
||
1074 |
{ |
||
1075 |
if (!mHBarVisible) |
||
1076 |
return Rect(0, 0, 0, 0); |
||
1077 |
|||
1078 |
int length; |
||
1079 |
int pos; |
||
1080 |
int width; |
||
1081 |
const int w2 = mShowButtons |
||
1082 |
? mScrollbarWidth : mMarkerSize / 2; |
||
1083 |
const Widget *content; |
||
1084 |
if (!mWidgets.empty()) |
||
1085 |
content = *mWidgets.begin(); |
||
1086 |
else |
||
1087 |
content = nullptr; |
||
1088 |
|||
1089 |
if (mVBarVisible) |
||
1090 |
width = mDimension.width - 2 * w2 - mScrollbarWidth; |
||
1091 |
else |
||
1092 |
width = mDimension.width - w2 - mScrollbarWidth; |
||
1093 |
|||
1094 |
const int maxH = getHorizontalMaxScroll(); |
||
1095 |
if (mMarkerSize != 0 && maxH != 0) |
||
1096 |
{ |
||
1097 |
pos = (mHScroll * width / maxH - mMarkerSize / 2); |
||
1098 |
length = mMarkerSize; |
||
1099 |
} |
||
1100 |
else |
||
1101 |
{ |
||
1102 |
if (content != nullptr) |
||
1103 |
{ |
||
1104 |
const int w3 = content->getWidth(); |
||
1105 |
if (w3 != 0) |
||
1106 |
length = (width * getChildrenArea().width) / w3; |
||
1107 |
else |
||
1108 |
length = width; |
||
1109 |
} |
||
1110 |
else |
||
1111 |
{ |
||
1112 |
length = width; |
||
1113 |
} |
||
1114 |
|||
1115 |
if (length < mScrollbarWidth) |
||
1116 |
length = mScrollbarWidth; |
||
1117 |
|||
1118 |
if (length > width) |
||
1119 |
length = width; |
||
1120 |
|||
1121 |
if (maxH != 0) |
||
1122 |
{ |
||
1123 |
pos = ((width - length) * mHScroll) / maxH; |
||
1124 |
} |
||
1125 |
else |
||
1126 |
{ |
||
1127 |
pos = 0; |
||
1128 |
} |
||
1129 |
} |
||
1130 |
|||
1131 |
return Rect(w2 + pos, mDimension.height - mScrollbarWidth, |
||
1132 |
length, mScrollbarWidth); |
||
1133 |
} |
||
1134 |
|||
1135 |
Rect ScrollArea::getUpButtonDimension() const |
||
1136 |
{ |
||
1137 |
if (!mVBarVisible || !mShowButtons) |
||
1138 |
return Rect(0, 0, 0, 0); |
||
1139 |
|||
1140 |
return Rect(mDimension.width - mScrollbarWidth, 0, |
||
1141 |
mScrollbarWidth, mScrollbarWidth); |
||
1142 |
} |
||
1143 |
|||
1144 |
Rect ScrollArea::getDownButtonDimension() const |
||
1145 |
{ |
||
1146 |
if (!mVBarVisible || !mShowButtons) |
||
1147 |
return Rect(0, 0, 0, 0); |
||
1148 |
|||
1149 |
if (mHBarVisible) |
||
1150 |
{ |
||
1151 |
return Rect(mDimension.width - mScrollbarWidth, |
||
1152 |
mDimension.height - mScrollbarWidth * 2, |
||
1153 |
mScrollbarWidth, |
||
1154 |
mScrollbarWidth); |
||
1155 |
} |
||
1156 |
|||
1157 |
return Rect(mDimension.width - mScrollbarWidth, |
||
1158 |
mDimension.height - mScrollbarWidth, |
||
1159 |
mScrollbarWidth, |
||
1160 |
mScrollbarWidth); |
||
1161 |
} |
||
1162 |
|||
1163 |
Rect ScrollArea::getLeftButtonDimension() const |
||
1164 |
{ |
||
1165 |
if (!mHBarVisible || !mShowButtons) |
||
1166 |
return Rect(0, 0, 0, 0); |
||
1167 |
|||
1168 |
return Rect(0, mDimension.height - mScrollbarWidth, |
||
1169 |
mScrollbarWidth, mScrollbarWidth); |
||
1170 |
} |
||
1171 |
|||
1172 |
Rect ScrollArea::getRightButtonDimension() const |
||
1173 |
{ |
||
1174 |
if (!mHBarVisible || !mShowButtons) |
||
1175 |
return Rect(0, 0, 0, 0); |
||
1176 |
|||
1177 |
if (mVBarVisible) |
||
1178 |
{ |
||
1179 |
return Rect(mDimension.width - mScrollbarWidth*2, |
||
1180 |
mDimension.height - mScrollbarWidth, |
||
1181 |
mScrollbarWidth, |
||
1182 |
mScrollbarWidth); |
||
1183 |
} |
||
1184 |
|||
1185 |
return Rect(mDimension.width - mScrollbarWidth, |
||
1186 |
mDimension.height - mScrollbarWidth, |
||
1187 |
mScrollbarWidth, |
||
1188 |
mScrollbarWidth); |
||
1189 |
} |
||
1190 |
|||
1191 |
165 |
void ScrollArea::setContent(Widget* widget) |
|
1192 |
{ |
||
1193 |
✓✗ | 165 |
if (widget != nullptr) |
1194 |
{ |
||
1195 |
165 |
clear(); |
|
1196 |
165 |
add(widget); |
|
1197 |
165 |
widget->setPosition(0, 0); |
|
1198 |
} |
||
1199 |
else |
||
1200 |
{ |
||
1201 |
164 |
clear(); |
|
1202 |
} |
||
1203 |
|||
1204 |
329 |
checkPolicies(); |
|
1205 |
165 |
} |
|
1206 |
|||
1207 |
2 |
Widget* ScrollArea::getContent() |
|
1208 |
{ |
||
1209 |
✓✓✗✗ ✓✗✓✗ ✓✗✓✗ ✗✗✓✗ ✓✓ |
4528 |
if (!mWidgets.empty()) |
1210 |
4136 |
return *mWidgets.begin(); |
|
1211 |
|||
1212 |
return nullptr; |
||
1213 |
} |
||
1214 |
|||
1215 |
56 |
void ScrollArea::setHorizontalScrollPolicy(const ScrollPolicy hPolicy) |
|
1216 |
{ |
||
1217 |
56 |
mHPolicy = hPolicy; |
|
1218 |
56 |
checkPolicies(); |
|
1219 |
56 |
} |
|
1220 |
|||
1221 |
26 |
void ScrollArea::setVerticalScrollPolicy(const ScrollPolicy vPolicy) |
|
1222 |
{ |
||
1223 |
26 |
mVPolicy = vPolicy; |
|
1224 |
26 |
checkPolicies(); |
|
1225 |
26 |
} |
|
1226 |
|||
1227 |
4 |
void ScrollArea::setScrollPolicy(const ScrollPolicy hPolicy, |
|
1228 |
const ScrollPolicy vPolicy) |
||
1229 |
{ |
||
1230 |
4 |
mHPolicy = hPolicy; |
|
1231 |
4 |
mVPolicy = vPolicy; |
|
1232 |
4 |
checkPolicies(); |
|
1233 |
4 |
} |
|
1234 |
|||
1235 |
3 |
void ScrollArea::setVerticalScrollAmount(const int vScroll) |
|
1236 |
{ |
||
1237 |
207 |
const int max = getVerticalMaxScroll(); |
|
1238 |
|||
1239 |
207 |
mVScroll = vScroll; |
|
1240 |
|||
1241 |
✗✗✗✗ ✓✓✓✗ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗ |
207 |
if (vScroll > max) |
1242 |
5 |
mVScroll = max; |
|
1243 |
|||
1244 |
✗✗✗✗ ✗✓✗✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✗✗✗✗ |
207 |
if (vScroll < 0) |
1245 |
mVScroll = 0; |
||
1246 |
3 |
} |
|
1247 |
|||
1248 |
void ScrollArea::setHorizontalScrollAmount(int hScroll) |
||
1249 |
{ |
||
1250 |
204 |
const int max = getHorizontalMaxScroll(); |
|
1251 |
|||
1252 |
204 |
mHScroll = hScroll; |
|
1253 |
|||
1254 |
✗✓✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗ |
204 |
if (hScroll > max) |
1255 |
mHScroll = max; |
||
1256 |
✗✓✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✗✗✗✗ |
204 |
else if (hScroll < 0) |
1257 |
mHScroll = 0; |
||
1258 |
} |
||
1259 |
|||
1260 |
1 |
void ScrollArea::setScrollAmount(const int hScroll, const int vScroll) |
|
1261 |
{ |
||
1262 |
1 |
setHorizontalScrollAmount(hScroll); |
|
1263 |
1 |
setVerticalScrollAmount(vScroll); |
|
1264 |
1 |
} |
|
1265 |
|||
1266 |
204 |
int ScrollArea::getHorizontalMaxScroll() |
|
1267 |
{ |
||
1268 |
204 |
checkPolicies(); |
|
1269 |
|||
1270 |
204 |
const Widget *const content = getContent(); |
|
1271 |
✓✗ | 204 |
if (content == nullptr) |
1272 |
return 0; |
||
1273 |
|||
1274 |
816 |
const int value = content->getWidth() - getChildrenArea().width + |
|
1275 |
408 |
2 * content->getFrameSize(); |
|
1276 |
|||
1277 |
✓✓ | 204 |
if (value < 0) |
1278 |
return 0; |
||
1279 |
|||
1280 |
1 |
return value; |
|
1281 |
} |
||
1282 |
|||
1283 |
219 |
int ScrollArea::getVerticalMaxScroll() |
|
1284 |
{ |
||
1285 |
219 |
checkPolicies(); |
|
1286 |
|||
1287 |
219 |
const Widget *const content = getContent(); |
|
1288 |
✓✗ | 219 |
if (content == nullptr) |
1289 |
return 0; |
||
1290 |
|||
1291 |
int value; |
||
1292 |
|||
1293 |
657 |
value = content->getHeight() - getChildrenArea().height + |
|
1294 |
219 |
2 * content->getFrameSize(); |
|
1295 |
|||
1296 |
✓✓ | 219 |
if (value < 0) |
1297 |
return 0; |
||
1298 |
|||
1299 |
201 |
return value; |
|
1300 |
} |
||
1301 |
|||
1302 |
void ScrollArea::setScrollbarWidth(const int width) |
||
1303 |
{ |
||
1304 |
if (width > 0) |
||
1305 |
mScrollbarWidth = width; |
||
1306 |
} |
||
1307 |
|||
1308 |
202 |
void ScrollArea::showWidgetPart(Widget *const widget, const Rect &area) |
|
1309 |
{ |
||
1310 |
202 |
const Widget *const content = getContent(); |
|
1311 |
✓✗ | 202 |
if (widget != content || (content == nullptr)) |
1312 |
return; |
||
1313 |
|||
1314 |
202 |
BasicContainer::showWidgetPart(widget, area); |
|
1315 |
|||
1316 |
404 |
setHorizontalScrollAmount(content->getFrameSize() |
|
1317 |
404 |
- content->getX()); |
|
1318 |
404 |
setVerticalScrollAmount(content->getFrameSize() |
|
1319 |
202 |
- content->getY()); |
|
1320 |
} |
||
1321 |
|||
1322 |
219 |
Rect ScrollArea::getChildrenArea() |
|
1323 |
{ |
||
1324 |
const Rect area = Rect(0, 0, |
||
1325 |
1793 |
mVBarVisible ? (getWidth() - mScrollbarWidth) : getWidth(), |
|
1326 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✗✗✗✗ ✗✓✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
3912 |
mHBarVisible ? (getHeight() - mScrollbarWidth) : getHeight()); |
1327 |
|||
1328 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✓✗✓ ✓✓✓✗ ✓✓✓✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
652 |
if (area.width < 0 || area.height < 0) |
1329 |
return Rect(); |
||
1330 |
|||
1331 |
return area; |
||
1332 |
} |
||
1333 |
|||
1334 |
Widget *ScrollArea::getWidgetAt(int x, int y) |
||
1335 |
{ |
||
1336 |
if (getChildrenArea().isPointInRect(x, y)) |
||
1337 |
return getContent(); |
||
1338 |
|||
1339 |
return nullptr; |
||
1340 |
} |
||
1341 |
|||
1342 |
315 |
void ScrollArea::setWidth(int width) |
|
1343 |
{ |
||
1344 |
315 |
Widget::setWidth(width); |
|
1345 |
315 |
checkPolicies(); |
|
1346 |
315 |
} |
|
1347 |
|||
1348 |
317 |
void ScrollArea::setHeight(int height) |
|
1349 |
{ |
||
1350 |
317 |
Widget::setHeight(height); |
|
1351 |
317 |
checkPolicies(); |
|
1352 |
317 |
} |
|
1353 |
|||
1354 |
1 |
void ScrollArea::setDimension(const Rect& dimension) |
|
1355 |
{ |
||
1356 |
1 |
Widget::setDimension(dimension); |
|
1357 |
1 |
checkPolicies(); |
|
1358 |
1 |
} |
|
1359 |
|||
1360 |
void ScrollArea::mouseWheelMovedUp(MouseEvent& event) |
||
1361 |
{ |
||
1362 |
if (event.isConsumed()) |
||
1363 |
return; |
||
1364 |
|||
1365 |
setVerticalScrollAmount(mVScroll |
||
1366 |
- getChildrenArea().height / 8); |
||
1367 |
|||
1368 |
event.consume(); |
||
1369 |
} |
||
1370 |
|||
1371 |
void ScrollArea::mouseWheelMovedDown(MouseEvent& event) |
||
1372 |
{ |
||
1373 |
if (event.isConsumed()) |
||
1374 |
return; |
||
1375 |
|||
1376 |
setVerticalScrollAmount(mVScroll |
||
1377 |
+ getChildrenArea().height / 8); |
||
1378 |
|||
1379 |
event.consume(); |
||
1380 |
} |
||
1381 |
|||
1382 |
1472 |
void ScrollArea::checkPolicies() |
|
1383 |
{ |
||
1384 |
2944 |
const int w = getWidth(); |
|
1385 |
2944 |
const int h = getHeight(); |
|
1386 |
|||
1387 |
1472 |
mHBarVisible = false; |
|
1388 |
1472 |
mVBarVisible = false; |
|
1389 |
|||
1390 |
1472 |
const Widget *const content = getContent(); |
|
1391 |
✓✓ | 1472 |
if (content == nullptr) |
1392 |
{ |
||
1393 |
164 |
mHBarVisible = (mHPolicy == SHOW_ALWAYS); |
|
1394 |
164 |
mVBarVisible = (mVPolicy == SHOW_ALWAYS); |
|
1395 |
164 |
return; |
|
1396 |
} |
||
1397 |
|||
1398 |
✓✓ | 1308 |
if (mHPolicy == SHOW_AUTO && |
1399 |
mVPolicy == SHOW_AUTO) |
||
1400 |
{ |
||
1401 |
1140 |
if (content->getWidth() <= w |
|
1402 |
&& content->getHeight() <= h) |
||
1403 |
{ |
||
1404 |
mHBarVisible = false; |
||
1405 |
mVBarVisible = false; |
||
1406 |
} |
||
1407 |
|||
1408 |
✓✓ | 1140 |
if (content->getWidth() > w) |
1409 |
{ |
||
1410 |
322 |
mHBarVisible = true; |
|
1411 |
} |
||
1412 |
|||
1413 |
✓✓ | 2280 |
if ((content->getHeight() > h) |
1414 |
✓✓✓✓ ✓✗ |
1142 |
|| (mHBarVisible && content->getHeight() |
1415 |
2 |
> h - mScrollbarWidth)) |
|
1416 |
{ |
||
1417 |
964 |
mVBarVisible = true; |
|
1418 |
} |
||
1419 |
|||
1420 |
✓✓✓✓ ✓✓ |
1140 |
if (mVBarVisible && content->getWidth() > w - mScrollbarWidth) |
1421 |
962 |
mHBarVisible = true; |
|
1422 |
|||
1423 |
return; |
||
1424 |
} |
||
1425 |
|||
1426 |
✗✓✓ | 168 |
switch (mHPolicy) |
1427 |
{ |
||
1428 |
case SHOW_NEVER: |
||
1429 |
mHBarVisible = false; |
||
1430 |
break; |
||
1431 |
|||
1432 |
case SHOW_ALWAYS: |
||
1433 |
mHBarVisible = true; |
||
1434 |
break; |
||
1435 |
|||
1436 |
case SHOW_AUTO: |
||
1437 |
✓✓ | 8 |
if (mVPolicy == SHOW_NEVER) |
1438 |
{ |
||
1439 |
2 |
mHBarVisible = (content->getWidth() > w); |
|
1440 |
} |
||
1441 |
else // (mVPolicy == SHOW_ALWAYS) |
||
1442 |
{ |
||
1443 |
12 |
mHBarVisible = (content->getWidth() |
|
1444 |
6 |
> w - mScrollbarWidth); |
|
1445 |
} |
||
1446 |
break; |
||
1447 |
|||
1448 |
default: |
||
1449 |
break; |
||
1450 |
} |
||
1451 |
|||
1452 |
✓✓✓ | 168 |
switch (mVPolicy) |
1453 |
{ |
||
1454 |
case SHOW_NEVER: |
||
1455 |
mVBarVisible = false; |
||
1456 |
break; |
||
1457 |
|||
1458 |
case SHOW_ALWAYS: |
||
1459 |
17 |
mVBarVisible = true; |
|
1460 |
17 |
break; |
|
1461 |
|||
1462 |
case SHOW_AUTO: |
||
1463 |
✓✗ | 144 |
if (mHPolicy == SHOW_NEVER) |
1464 |
{ |
||
1465 |
144 |
mVBarVisible = (content->getHeight() > h); |
|
1466 |
} |
||
1467 |
else // (mHPolicy == SHOW_ALWAYS) |
||
1468 |
{ |
||
1469 |
mVBarVisible = (content->getHeight() |
||
1470 |
> h - mScrollbarWidth); |
||
1471 |
} |
||
1472 |
break; |
||
1473 |
default: |
||
1474 |
break; |
||
1475 |
} |
||
1476 |
} |
||
1477 |
|||
1478 |
bool ScrollArea::isSelectable() const noexcept2 |
||
1479 |
{ |
||
1480 |
if (mVBarVisible || mHBarVisible) |
||
1481 |
return true; |
||
1482 |
return Widget::isSelectable(); |
||
1483 |
✓✗✓✗ |
3 |
} |
Generated by: GCOVR (Version 3.3) |