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/window.h" |
||
68 |
|||
69 |
#include "client.h" |
||
70 |
#include "configuration.h" |
||
71 |
#ifndef DYECMD |
||
72 |
#include "dragdrop.h" |
||
73 |
#else // DYECMD |
||
74 |
#include "resources/image/image.h" |
||
75 |
#endif // DYECMD |
||
76 |
#include "soundmanager.h" |
||
77 |
|||
78 |
#include "const/sound.h" |
||
79 |
|||
80 |
#include "gui/focushandler.h" |
||
81 |
#include "gui/gui.h" |
||
82 |
#include "gui/popupmanager.h" |
||
83 |
#include "gui/skin.h" |
||
84 |
#include "gui/viewport.h" |
||
85 |
|||
86 |
#include "gui/fonts/font.h" |
||
87 |
|||
88 |
#include "gui/popups/popupmenu.h" |
||
89 |
|||
90 |
#include "gui/windows/setupwindow.h" |
||
91 |
|||
92 |
#include "gui/widgets/containerplacer.h" |
||
93 |
#include "gui/widgets/layout.h" |
||
94 |
|||
95 |
#include "render/renderers.h" |
||
96 |
|||
97 |
#include "render/vertexes/imagecollection.h" |
||
98 |
|||
99 |
#include "utils/checkutils.h" |
||
100 |
#include "utils/delete2.h" |
||
101 |
|||
102 |
#include "debug.h" |
||
103 |
|||
104 |
const int resizeMask = 8 + 4 + 2 + 1; |
||
105 |
|||
106 |
int Window::windowInstances = 0; |
||
107 |
int Window::mouseResize = 0; |
||
108 |
|||
109 |
63 |
Window::Window(const std::string &caption, |
|
110 |
const Modal modal, |
||
111 |
Window *const parent, |
||
112 |
63 |
std::string skin) : |
|
113 |
BasicContainer2(nullptr), |
||
114 |
MouseListener(), |
||
115 |
WidgetListener(), |
||
116 |
mCaption(caption), |
||
117 |
mAlignment(Graphics::CENTER), |
||
118 |
mPadding(2), |
||
119 |
mTitleBarHeight(16), |
||
120 |
mMovable(Move_true), |
||
121 |
mDragOffsetX(0), |
||
122 |
mDragOffsetY(0), |
||
123 |
mMoved(false), |
||
124 |
mSkin(nullptr), |
||
125 |
mDefaultX(0), |
||
126 |
mDefaultY(0), |
||
127 |
mDefaultWidth(0), |
||
128 |
mDefaultHeight(0), |
||
129 |
mCaptionOffsetX(7), |
||
130 |
mCaptionOffsetY(5), |
||
131 |
mShowTitle(true), |
||
132 |
mLastRedraw(true), |
||
133 |
mGrip(nullptr), |
||
134 |
mParentWindow(parent), |
||
135 |
mLayout(nullptr), |
||
136 |
mCloseRect(), |
||
137 |
mStickyRect(), |
||
138 |
mGripRect(), |
||
139 |
mTextChunk(), |
||
140 |
mWindowName("window"), |
||
141 |
mMinWinWidth(100), |
||
142 |
mMinWinHeight(40), |
||
143 |
63 |
mMaxWinWidth(mainGraphics->mWidth), |
|
144 |
63 |
mMaxWinHeight(mainGraphics->mHeight), |
|
145 |
✓✗✓✗ |
63 |
mVertexes(new ImageCollection), |
146 |
mCaptionAlign(Graphics::LEFT), |
||
147 |
mTitlePadding(4), |
||
148 |
mGripPadding(2), |
||
149 |
mResizeHandles(-1), |
||
150 |
mOldResizeHandles(-1), |
||
151 |
mClosePadding(0), |
||
152 |
mStickySpacing(0), |
||
153 |
mStickyPadding(0), |
||
154 |
✓✗ | 63 |
mCaptionFont(getFont()), |
155 |
mModal(modal), |
||
156 |
mCloseWindowButton(false), |
||
157 |
mDefaultVisible(false), |
||
158 |
mSaveVisible(false), |
||
159 |
mStickyButton(false), |
||
160 |
mSticky(false), |
||
161 |
mStickyButtonLock(false), |
||
162 |
mPlayVisibleSound(false), |
||
163 |
mInit(false), |
||
164 |
mTextChanged(true), |
||
165 |
✓✗✓✗ |
819 |
mAllowClose(false) |
166 |
{ |
||
167 |
✓✗ | 63 |
logger->log("Window::Window(\"%s\")", caption.c_str()); |
168 |
|||
169 |
63 |
mWindow = this; |
|
170 |
|||
171 |
63 |
windowInstances++; |
|
172 |
|||
173 |
// mFrameSize = 1; |
||
174 |
✓✗ | 63 |
addMouseListener(this); |
175 |
|||
176 |
126 |
setFrameSize(0); |
|
177 |
126 |
setPadding(3); |
|
178 |
126 |
setTitleBarHeight(20); |
|
179 |
|||
180 |
✗✓ | 63 |
if (skin.empty()) |
181 |
{ |
||
182 |
reportAlways("Default skin was used for window: %s", |
||
183 |
caption.c_str()) |
||
184 |
skin = "window.xml"; |
||
185 |
} |
||
186 |
|||
187 |
63 |
int childPalette = 1; |
|
188 |
// Loads the skin |
||
189 |
✓✗ | 63 |
if (theme != nullptr) |
190 |
{ |
||
191 |
✓✗✓✗ |
252 |
mSkin = theme->load(skin, |
192 |
"window.xml", |
||
193 |
true, |
||
194 |
63 |
Theme::getThemePath()); |
|
195 |
✓✗ | 63 |
if (mSkin != nullptr) |
196 |
{ |
||
197 |
189 |
setPadding(mSkin->getPadding()); |
|
198 |
✓✗✓✓ |
315 |
if (getOptionBool("titlebarBold", false)) |
199 |
56 |
mCaptionFont = boldFont; |
|
200 |
126 |
mTitlePadding = mSkin->getTitlePadding(); |
|
201 |
✓✗ | 315 |
mGripPadding = getOption("resizePadding", 0); |
202 |
✓✗ | 315 |
mCaptionOffsetX = getOption("captionoffsetx", 0); |
203 |
✓✓ | 63 |
if (mCaptionOffsetX == 0) |
204 |
6 |
mCaptionOffsetX = 7; |
|
205 |
✓✗ | 315 |
mCaptionOffsetY = getOption("captionoffsety", 0); |
206 |
✓✓ | 63 |
if (mCaptionOffsetY == 0) |
207 |
6 |
mCaptionOffsetY = 5; |
|
208 |
63 |
mCaptionAlign = static_cast<Graphics::Alignment>( |
|
209 |
✓✗ | 315 |
getOption("captionalign", 0)); |
210 |
✗✓ | 63 |
if (mCaptionAlign < Graphics::LEFT |
211 |
|| mCaptionAlign > Graphics::RIGHT) |
||
212 |
{ |
||
213 |
mCaptionAlign = Graphics::LEFT; |
||
214 |
} |
||
215 |
63 |
setTitleBarHeight(CAST_U32( |
|
216 |
✓✗ | 441 |
getOption("titlebarHeight", 0))); |
217 |
✓✓ | 63 |
if (mTitleBarHeight == 0U) |
218 |
✓✗ | 7 |
mTitleBarHeight = mCaptionFont->getHeight() + mPadding; |
219 |
|||
220 |
✓✗ | 315 |
mTitleBarHeight += getOption("titlebarHeightRelative", 0); |
221 |
✓✗ | 378 |
setPalette(getOption("palette", 0)); |
222 |
✓✗ | 315 |
childPalette = getOption("childPalette", 0); |
223 |
✓✗ | 315 |
mShowTitle = getOptionBool("showTitle", true); |
224 |
✓✗ | 315 |
mClosePadding = getOption("closePadding", 0); |
225 |
✓✗ | 315 |
mStickySpacing = getOption("stickySpacing", 0); |
226 |
✓✗ | 315 |
mStickyPadding = getOption("stickyPadding", 0); |
227 |
} |
||
228 |
} |
||
229 |
|||
230 |
// Add this window to the window container |
||
231 |
✓✗ | 63 |
if (windowContainer != nullptr) |
232 |
✓✗ | 63 |
windowContainer->add(this); |
233 |
|||
234 |
✓✓ | 63 |
if (mModal == Modal_true) |
235 |
{ |
||
236 |
10 |
gui->setCursorType(Cursor::CURSOR_POINTER); |
|
237 |
✓✗ | 5 |
requestModalFocus(); |
238 |
} |
||
239 |
|||
240 |
// Windows are invisible by default |
||
241 |
✓✗ | 63 |
setVisible(Visible_false, false); |
242 |
|||
243 |
✓✗ | 63 |
addWidgetListener(this); |
244 |
126 |
mForegroundColor = getThemeColor(ThemeColorId::WINDOW, 255U); |
|
245 |
126 |
mForegroundColor2 = getThemeColor(ThemeColorId::WINDOW_OUTLINE, 255U); |
|
246 |
126 |
setPalette(childPalette); |
|
247 |
63 |
} |
|
248 |
|||
249 |
63 |
void Window::postInit() |
|
250 |
{ |
||
251 |
✗✓ | 63 |
if (mInit) |
252 |
{ |
||
253 |
reportAlways("error: Window created with calling postInit() " |
||
254 |
"more than once: %s", |
||
255 |
mWindowName.c_str()) |
||
256 |
} |
||
257 |
63 |
mInit = true; |
|
258 |
63 |
} |
|
259 |
|||
260 |
567 |
Window::~Window() |
|
261 |
{ |
||
262 |
63 |
logger->log("Window::~Window(\"%s\")", getCaption().c_str()); |
|
263 |
|||
264 |
✓✗ | 63 |
if (gui != nullptr) |
265 |
63 |
gui->removeDragged(this); |
|
266 |
|||
267 |
#ifndef DYECMD |
||
268 |
✓✓ | 63 |
if (setupWindow != nullptr) |
269 |
2 |
setupWindow->unregisterWindowForReset(this); |
|
270 |
#endif // DYECMD |
||
271 |
|||
272 |
63 |
client->windowRemoved(this); |
|
273 |
|||
274 |
63 |
saveWindowState(); |
|
275 |
|||
276 |
✓✓ | 126 |
delete2(mLayout) |
277 |
|||
278 |
✓✓ | 884 |
while (!mWidgets.empty()) |
279 |
✗✓ | 758 |
delete mWidgets.front(); |
280 |
|||
281 |
126 |
mWidgets.clear(); |
|
282 |
|||
283 |
63 |
removeWidgetListener(this); |
|
284 |
✓✗ | 63 |
delete2(mVertexes) |
285 |
|||
286 |
63 |
windowInstances--; |
|
287 |
|||
288 |
✓✗ | 63 |
if (mSkin != nullptr) |
289 |
{ |
||
290 |
✓✗ | 63 |
if (theme != nullptr) |
291 |
63 |
theme->unload(mSkin); |
|
292 |
63 |
mSkin = nullptr; |
|
293 |
} |
||
294 |
✓✓ | 63 |
if (mGrip != nullptr) |
295 |
{ |
||
296 |
42 |
mGrip->decRef(); |
|
297 |
42 |
mGrip = nullptr; |
|
298 |
} |
||
299 |
✗✓ | 63 |
if (!mInit) |
300 |
{ |
||
301 |
reportAlways("error: Window created without calling postInit(): %s", |
||
302 |
mWindowName.c_str()) |
||
303 |
} |
||
304 |
63 |
} |
|
305 |
|||
306 |
254 |
void Window::setWindowContainer(WindowContainer *const wc) |
|
307 |
{ |
||
308 |
254 |
windowContainer = wc; |
|
309 |
254 |
} |
|
310 |
|||
311 |
32 |
void Window::draw(Graphics *const graphics) |
|
312 |
{ |
||
313 |
✓✗ | 32 |
if (mSkin == nullptr) |
314 |
return; |
||
315 |
|||
316 |
BLOCK_START("Window::draw") |
||
317 |
32 |
bool update = false; |
|
318 |
|||
319 |
✓✗ | 32 |
if (mResizeHandles != mOldResizeHandles) |
320 |
{ |
||
321 |
32 |
mRedraw = true; |
|
322 |
32 |
mOldResizeHandles = mResizeHandles; |
|
323 |
} |
||
324 |
✓✗ | 32 |
if (mRedraw) |
325 |
{ |
||
326 |
32 |
mLastRedraw = true; |
|
327 |
32 |
mRedraw = false; |
|
328 |
32 |
update = true; |
|
329 |
32 |
mVertexes->clear(); |
|
330 |
32 |
graphics->calcWindow(mVertexes, |
|
331 |
0, 0, |
||
332 |
mDimension.width, |
||
333 |
mDimension.height, |
||
334 |
64 |
mSkin->getBorder()); |
|
335 |
|||
336 |
// Draw Close Button |
||
337 |
✓✓ | 32 |
if (mCloseWindowButton) |
338 |
{ |
||
339 |
18 |
const Image *const button = mSkin->getCloseImage( |
|
340 |
36 |
mResizeHandles == CLOSE); |
|
341 |
✓✗ | 18 |
if (button != nullptr) |
342 |
{ |
||
343 |
18 |
graphics->calcTileCollection(mVertexes, |
|
344 |
button, |
||
345 |
mCloseRect.x, |
||
346 |
36 |
mCloseRect.y); |
|
347 |
} |
||
348 |
} |
||
349 |
// Draw Sticky Button |
||
350 |
✓✓ | 32 |
if (mStickyButton) |
351 |
{ |
||
352 |
30 |
const Image *const button = mSkin->getStickyImage(mSticky); |
|
353 |
✓✓ | 15 |
if (button != nullptr) |
354 |
{ |
||
355 |
5 |
graphics->calcTileCollection(mVertexes, |
|
356 |
button, |
||
357 |
mStickyRect.x, |
||
358 |
10 |
mStickyRect.y); |
|
359 |
} |
||
360 |
} |
||
361 |
|||
362 |
✓✓ | 32 |
if (mGrip != nullptr) |
363 |
{ |
||
364 |
18 |
graphics->calcTileCollection(mVertexes, |
|
365 |
mGrip, |
||
366 |
mGripRect.x, |
||
367 |
36 |
mGripRect.y); |
|
368 |
} |
||
369 |
32 |
graphics->finalize(mVertexes); |
|
370 |
} |
||
371 |
else |
||
372 |
{ |
||
373 |
mLastRedraw = false; |
||
374 |
} |
||
375 |
32 |
graphics->drawTileCollection(mVertexes); |
|
376 |
|||
377 |
// Draw title |
||
378 |
✓✓ | 32 |
if (mShowTitle) |
379 |
{ |
||
380 |
int x; |
||
381 |
✓✗✗ | 31 |
switch (mCaptionAlign) |
382 |
{ |
||
383 |
case Graphics::LEFT: |
||
384 |
default: |
||
385 |
31 |
x = mCaptionOffsetX; |
|
386 |
31 |
break; |
|
387 |
case Graphics::CENTER: |
||
388 |
x = mCaptionOffsetX - mCaptionFont->getWidth(mCaption) / 2; |
||
389 |
break; |
||
390 |
case Graphics::RIGHT: |
||
391 |
x = mCaptionOffsetX - mCaptionFont->getWidth(mCaption); |
||
392 |
break; |
||
393 |
} |
||
394 |
✓✗ | 31 |
if (mTextChanged) |
395 |
{ |
||
396 |
31 |
mTextChunk.textFont = mCaptionFont; |
|
397 |
31 |
mTextChunk.deleteImage(); |
|
398 |
62 |
mTextChunk.text = mCaption; |
|
399 |
31 |
mTextChunk.color = mForegroundColor; |
|
400 |
31 |
mTextChunk.color2 = mForegroundColor2; |
|
401 |
31 |
mCaptionFont->generate(mTextChunk); |
|
402 |
31 |
mTextChanged = false; |
|
403 |
} |
||
404 |
|||
405 |
31 |
const Image *const image = mTextChunk.img; |
|
406 |
✓✓ | 31 |
if (image != nullptr) |
407 |
26 |
graphics->drawImage(image, x, mCaptionOffsetY); |
|
408 |
} |
||
409 |
|||
410 |
✓✗ | 32 |
if (update) |
411 |
{ |
||
412 |
64 |
graphics->setRedraw(update); |
|
413 |
32 |
drawChildren(graphics); |
|
414 |
graphics->setRedraw(false); |
||
415 |
} |
||
416 |
else |
||
417 |
{ |
||
418 |
drawChildren(graphics); |
||
419 |
} |
||
420 |
BLOCK_END("Window::draw") |
||
421 |
} |
||
422 |
|||
423 |
void Window::safeDraw(Graphics *const graphics) |
||
424 |
{ |
||
425 |
if (mSkin == nullptr) |
||
426 |
return; |
||
427 |
|||
428 |
BLOCK_START("Window::safeDraw") |
||
429 |
|||
430 |
graphics->drawImageRect(0, 0, |
||
431 |
mDimension.width, |
||
432 |
mDimension.height, |
||
433 |
mSkin->getBorder()); |
||
434 |
|||
435 |
// Draw Close Button |
||
436 |
if (mCloseWindowButton) |
||
437 |
{ |
||
438 |
const Image *const button = mSkin->getCloseImage( |
||
439 |
mResizeHandles == CLOSE); |
||
440 |
if (button != nullptr) |
||
441 |
graphics->drawImage(button, mCloseRect.x, mCloseRect.y); |
||
442 |
} |
||
443 |
// Draw Sticky Button |
||
444 |
if (mStickyButton) |
||
445 |
{ |
||
446 |
const Image *const button = mSkin->getStickyImage(mSticky); |
||
447 |
if (button != nullptr) |
||
448 |
graphics->drawImage(button, mStickyRect.x, mStickyRect.y); |
||
449 |
} |
||
450 |
|||
451 |
if (mGrip != nullptr) |
||
452 |
graphics->drawImage(mGrip, mGripRect.x, mGripRect.y); |
||
453 |
|||
454 |
// Draw title |
||
455 |
if (mShowTitle) |
||
456 |
{ |
||
457 |
int x; |
||
458 |
switch (mCaptionAlign) |
||
459 |
{ |
||
460 |
case Graphics::LEFT: |
||
461 |
default: |
||
462 |
x = mCaptionOffsetX; |
||
463 |
break; |
||
464 |
case Graphics::CENTER: |
||
465 |
x = mCaptionOffsetX - mCaptionFont->getWidth(mCaption) / 2; |
||
466 |
break; |
||
467 |
case Graphics::RIGHT: |
||
468 |
x = mCaptionOffsetX - mCaptionFont->getWidth(mCaption); |
||
469 |
break; |
||
470 |
} |
||
471 |
if (mTextChanged) |
||
472 |
{ |
||
473 |
mTextChunk.textFont = mCaptionFont; |
||
474 |
mTextChunk.deleteImage(); |
||
475 |
mTextChunk.text = mCaption; |
||
476 |
mTextChunk.color = mForegroundColor; |
||
477 |
mTextChunk.color2 = mForegroundColor2; |
||
478 |
mCaptionFont->generate(mTextChunk); |
||
479 |
mTextChanged = false; |
||
480 |
} |
||
481 |
|||
482 |
const Image *const image = mTextChunk.img; |
||
483 |
if (image != nullptr) |
||
484 |
graphics->drawImage(image, x, mCaptionOffsetY); |
||
485 |
} |
||
486 |
|||
487 |
safeDrawChildren(graphics); |
||
488 |
|||
489 |
BLOCK_END("Window::safeDraw") |
||
490 |
} |
||
491 |
|||
492 |
31 |
void Window::setContentSize(int width, int height) |
|
493 |
{ |
||
494 |
31 |
width = width + 2 * mPadding; |
|
495 |
31 |
height = height + mPadding + mTitleBarHeight; |
|
496 |
|||
497 |
✓✓ | 31 |
if (mMinWinWidth > width) |
498 |
width = mMinWinWidth; |
||
499 |
✓✓ | 29 |
else if (mMaxWinWidth < width) |
500 |
2 |
width = mMaxWinWidth; |
|
501 |
✓✗ | 31 |
if (mMinWinHeight > height) |
502 |
height = mMinWinHeight; |
||
503 |
✓✓ | 31 |
else if (mMaxWinHeight < height) |
504 |
2 |
height = mMaxWinHeight; |
|
505 |
|||
506 |
31 |
setSize(width, height); |
|
507 |
31 |
} |
|
508 |
|||
509 |
37 |
void Window::setLocationRelativeTo(const Widget *const widget) |
|
510 |
{ |
||
511 |
✓✓ | 37 |
if (widget == nullptr) |
512 |
1 |
return; |
|
513 |
|||
514 |
int wx; |
||
515 |
int wy; |
||
516 |
int x; |
||
517 |
int y; |
||
518 |
|||
519 |
36 |
widget->getAbsolutePosition(wx, wy); |
|
520 |
36 |
getAbsolutePosition(x, y); |
|
521 |
|||
522 |
144 |
setPosition(mDimension.x + (wx + (widget->getWidth() |
|
523 |
72 |
- mDimension.width) / 2 - x), |
|
524 |
108 |
mDimension.y + (wy + (widget->getHeight() |
|
525 |
108 |
- mDimension.height) / 2 - y)); |
|
526 |
} |
||
527 |
|||
528 |
void Window::setLocationHorisontallyRelativeTo(const Widget *const widget) |
||
529 |
{ |
||
530 |
if (widget == nullptr) |
||
531 |
return; |
||
532 |
|||
533 |
int wx; |
||
534 |
int wy; |
||
535 |
int x; |
||
536 |
int y; |
||
537 |
|||
538 |
widget->getAbsolutePosition(wx, wy); |
||
539 |
getAbsolutePosition(x, y); |
||
540 |
|||
541 |
setPosition(mDimension.x + (wx + (widget->getWidth() |
||
542 |
- mDimension.width) / 2 - x), 0); |
||
543 |
} |
||
544 |
|||
545 |
void Window::setLocationRelativeTo(const ImagePosition::Type &position, |
||
546 |
int offsetX, int offsetY) |
||
547 |
{ |
||
548 |
if (position == ImagePosition::UPPER_LEFT) |
||
549 |
{ |
||
550 |
} |
||
551 |
else if (position == ImagePosition::UPPER_CENTER) |
||
552 |
{ |
||
553 |
offsetX += (mainGraphics->mWidth - mDimension.width) / 2; |
||
554 |
} |
||
555 |
else if (position == ImagePosition::UPPER_RIGHT) |
||
556 |
{ |
||
557 |
offsetX += mainGraphics->mWidth - mDimension.width; |
||
558 |
} |
||
559 |
else if (position == ImagePosition::LEFT) |
||
560 |
{ |
||
561 |
offsetY += (mainGraphics->mHeight - mDimension.height) / 2; |
||
562 |
} |
||
563 |
else if (position == ImagePosition::CENTER) |
||
564 |
{ |
||
565 |
offsetX += (mainGraphics->mWidth - mDimension.width) / 2; |
||
566 |
offsetY += (mainGraphics->mHeight - mDimension.height) / 2; |
||
567 |
} |
||
568 |
else if (position == ImagePosition::RIGHT) |
||
569 |
{ |
||
570 |
offsetX += mainGraphics->mWidth - mDimension.width; |
||
571 |
offsetY += (mainGraphics->mHeight - mDimension.height) / 2; |
||
572 |
} |
||
573 |
else if (position == ImagePosition::LOWER_LEFT) |
||
574 |
{ |
||
575 |
offsetY += mainGraphics->mHeight - mDimension.height; |
||
576 |
} |
||
577 |
else if (position == ImagePosition::LOWER_CENTER) |
||
578 |
{ |
||
579 |
offsetX += (mainGraphics->mWidth - mDimension.width) / 2; |
||
580 |
offsetY += mainGraphics->mHeight - mDimension.height; |
||
581 |
} |
||
582 |
else if (position == ImagePosition::LOWER_RIGHT) |
||
583 |
{ |
||
584 |
offsetX += mainGraphics->mWidth - mDimension.width; |
||
585 |
offsetY += mainGraphics->mHeight - mDimension.height; |
||
586 |
} |
||
587 |
|||
588 |
setPosition(offsetX, offsetY); |
||
589 |
} |
||
590 |
|||
591 |
35 |
void Window::setMinWidth(const int width) |
|
592 |
{ |
||
593 |
✓✗ | 35 |
if (mSkin != nullptr) |
594 |
{ |
||
595 |
70 |
mMinWinWidth = width > mSkin->getMinWidth() |
|
596 |
✓✓ | 35 |
? width : mSkin->getMinWidth(); |
597 |
} |
||
598 |
else |
||
599 |
{ |
||
600 |
mMinWinWidth = width; |
||
601 |
} |
||
602 |
35 |
} |
|
603 |
|||
604 |
34 |
void Window::setMinHeight(const int height) |
|
605 |
{ |
||
606 |
✓✗ | 34 |
if (mSkin != nullptr) |
607 |
{ |
||
608 |
68 |
mMinWinHeight = height > mSkin->getMinHeight() |
|
609 |
✓✓ | 34 |
? height : mSkin->getMinHeight(); |
610 |
} |
||
611 |
else |
||
612 |
{ |
||
613 |
mMinWinHeight = height; |
||
614 |
} |
||
615 |
34 |
} |
|
616 |
|||
617 |
1 |
void Window::setMaxWidth(const int width) |
|
618 |
{ |
||
619 |
1 |
mMaxWinWidth = width; |
|
620 |
1 |
} |
|
621 |
|||
622 |
1 |
void Window::setMaxHeight(const int height) |
|
623 |
{ |
||
624 |
1 |
mMaxWinHeight = height; |
|
625 |
1 |
} |
|
626 |
|||
627 |
44 |
void Window::setResizable(const bool r) |
|
628 |
{ |
||
629 |
✓✓ | 44 |
if ((mGrip != nullptr) == r) |
630 |
return; |
||
631 |
|||
632 |
✗✓ | 42 |
if (mGrip != nullptr) |
633 |
mGrip->decRef(); |
||
634 |
✓✗ | 42 |
if (r) |
635 |
{ |
||
636 |
✓✗✓✗ |
294 |
mGrip = Theme::getImageFromThemeXml("resize.xml", ""); |
637 |
✓✗ | 42 |
if (mGrip != nullptr) |
638 |
{ |
||
639 |
84 |
mGripRect.x = mDimension.width - mGrip->getWidth() - mGripPadding; |
|
640 |
126 |
mGripRect.y = mDimension.height - mGrip->getHeight() |
|
641 |
42 |
- mGripPadding; |
|
642 |
} |
||
643 |
else |
||
644 |
{ |
||
645 |
mGripRect.x = 0; |
||
646 |
mGripRect.y = 0; |
||
647 |
} |
||
648 |
} |
||
649 |
else |
||
650 |
{ |
||
651 |
mGrip = nullptr; |
||
652 |
} |
||
653 |
} |
||
654 |
|||
655 |
83 |
void Window::widgetResized(const Event &event A_UNUSED) |
|
656 |
{ |
||
657 |
✓✓ | 83 |
if (mGrip != nullptr) |
658 |
{ |
||
659 |
102 |
mGripRect.x = mDimension.width - mGrip->getWidth() - mGripPadding; |
|
660 |
102 |
mGripRect.y = mDimension.height - mGrip->getHeight() - mGripPadding; |
|
661 |
} |
||
662 |
|||
663 |
✓✓ | 83 |
if (mLayout != nullptr) |
664 |
{ |
||
665 |
88 |
const Rect area = getChildrenArea(); |
|
666 |
44 |
int w = area.width; |
|
667 |
44 |
int h = area.height; |
|
668 |
44 |
mLayout->reflow(w, h); |
|
669 |
} |
||
670 |
✓✗ | 83 |
if (mSkin != nullptr) |
671 |
{ |
||
672 |
83 |
const bool showClose = mCloseWindowButton |
|
673 |
✓✓✗✓ |
136 |
&& (mSkin->getCloseImage(false) != nullptr); |
674 |
✓✓ | 83 |
if (showClose) |
675 |
{ |
||
676 |
106 |
const Image *const button = mSkin->getCloseImage(false); |
|
677 |
✓✗ | 53 |
if (button != nullptr) |
678 |
{ |
||
679 |
53 |
const int buttonWidth = button->getWidth(); |
|
680 |
53 |
mCloseRect.x = mDimension.width - buttonWidth - mClosePadding; |
|
681 |
53 |
mCloseRect.y = mClosePadding; |
|
682 |
53 |
mCloseRect.width = buttonWidth; |
|
683 |
53 |
mCloseRect.height = button->getHeight(); |
|
684 |
} |
||
685 |
} |
||
686 |
✓✓ | 83 |
if (mStickyButton) |
687 |
{ |
||
688 |
96 |
const Image *const button = mSkin->getStickyImage(mSticky); |
|
689 |
✓✓ | 48 |
if (button != nullptr) |
690 |
{ |
||
691 |
36 |
const int buttonWidth = button->getWidth(); |
|
692 |
36 |
int x = mDimension.width - buttonWidth |
|
693 |
36 |
- mStickySpacing - mClosePadding; |
|
694 |
|||
695 |
✓✓ | 36 |
if (showClose) |
696 |
99 |
x -= mSkin->getCloseImage(false)->getWidth(); |
|
697 |
|||
698 |
36 |
mStickyRect.x = x; |
|
699 |
36 |
mStickyRect.y = mStickyPadding; |
|
700 |
36 |
mStickyRect.width = buttonWidth; |
|
701 |
36 |
mStickyRect.height = button->getHeight(); |
|
702 |
} |
||
703 |
} |
||
704 |
} |
||
705 |
else |
||
706 |
{ |
||
707 |
mCloseRect.x = 0; |
||
708 |
mCloseRect.y = 0; |
||
709 |
mCloseRect.width = 0; |
||
710 |
mCloseRect.height = 0; |
||
711 |
mStickyRect.x = 0; |
||
712 |
mStickyRect.y = 0; |
||
713 |
mStickyRect.width = 0; |
||
714 |
mStickyRect.height = 0; |
||
715 |
} |
||
716 |
|||
717 |
83 |
mRedraw = true; |
|
718 |
83 |
} |
|
719 |
|||
720 |
63 |
void Window::widgetMoved(const Event& event A_UNUSED) |
|
721 |
{ |
||
722 |
63 |
mRedraw = true; |
|
723 |
63 |
} |
|
724 |
|||
725 |
1 |
void Window::widgetHidden(const Event &event A_UNUSED) |
|
726 |
{ |
||
727 |
✓✗ | 1 |
if (isBatchDrawRenders(openGLMode)) |
728 |
1 |
mVertexes->clear(); |
|
729 |
|||
730 |
1 |
mTextChunk.deleteImage(); |
|
731 |
|||
732 |
1 |
mTextChanged = true; |
|
733 |
1 |
mRedraw = true; |
|
734 |
|||
735 |
✓✗ | 1 |
if (gui != nullptr) |
736 |
1 |
gui->setCursorType(Cursor::CURSOR_POINTER); |
|
737 |
|||
738 |
✓✗ | 1 |
if (mFocusHandler == nullptr) |
739 |
return; |
||
740 |
|||
741 |
✓✓ | 8 |
for (WidgetListConstIterator it = mWidgets.begin(); |
742 |
10 |
it != mWidgets.end(); ++ it) |
|
743 |
{ |
||
744 |
✗✓ | 4 |
if (mFocusHandler->isFocused(*it)) |
745 |
mFocusHandler->focusNone(); |
||
746 |
} |
||
747 |
} |
||
748 |
|||
749 |
43 |
void Window::setCloseButton(const bool flag) |
|
750 |
{ |
||
751 |
43 |
mCloseWindowButton = flag; |
|
752 |
✓✓ | 43 |
if (flag) |
753 |
42 |
mAllowClose = true; |
|
754 |
43 |
} |
|
755 |
|||
756 |
bool Window::isResizable() const |
||
757 |
{ |
||
758 |
return mGrip != nullptr; |
||
759 |
} |
||
760 |
|||
761 |
1 |
void Window::setStickyButton(const bool flag) |
|
762 |
{ |
||
763 |
1 |
mStickyButton = flag; |
|
764 |
1 |
} |
|
765 |
|||
766 |
1 |
void Window::setSticky(const bool sticky) |
|
767 |
{ |
||
768 |
36 |
mSticky = sticky; |
|
769 |
36 |
mRedraw = true; |
|
770 |
1 |
} |
|
771 |
|||
772 |
36 |
void Window::setStickyButtonLock(const bool lock) |
|
773 |
{ |
||
774 |
36 |
mStickyButtonLock = lock; |
|
775 |
36 |
mStickyButton = lock; |
|
776 |
36 |
} |
|
777 |
|||
778 |
53 |
void Window::setVisible(Visible visible) |
|
779 |
{ |
||
780 |
53 |
setVisible(visible, false); |
|
781 |
53 |
} |
|
782 |
|||
783 |
117 |
void Window::setVisible(const Visible visible, const bool forceSticky) |
|
784 |
{ |
||
785 |
✓✓ | 117 |
if (visible == mVisible) |
786 |
return; |
||
787 |
|||
788 |
// Check if the window is off screen... |
||
789 |
✓✓ | 99 |
if (visible == Visible_true) |
790 |
35 |
ensureOnScreen(); |
|
791 |
else |
||
792 |
64 |
mResizeHandles = 0; |
|
793 |
|||
794 |
✓✓ | 99 |
if (mStickyButtonLock) |
795 |
{ |
||
796 |
16 |
BasicContainer2::setVisible(visible); |
|
797 |
} |
||
798 |
else |
||
799 |
{ |
||
800 |
✓✗✓✗ ✓✓ |
83 |
BasicContainer2::setVisible(fromBool((!forceSticky && mSticky) || |
801 |
83 |
visible == Visible_true, Visible)); |
|
802 |
} |
||
803 |
✓✓ | 99 |
if (visible == Visible_true) |
804 |
{ |
||
805 |
✓✓ | 35 |
if (mPlayVisibleSound) |
806 |
8 |
soundManager.playGuiSound(SOUND_SHOW_WINDOW); |
|
807 |
✓✗ | 35 |
if (gui != nullptr) |
808 |
{ |
||
809 |
MouseEvent *const event = reinterpret_cast<MouseEvent*>( |
||
810 |
35 |
gui->createMouseEvent(this)); |
|
811 |
✗✓ | 35 |
if (event != nullptr) |
812 |
{ |
||
813 |
const int x = event->getX(); |
||
814 |
const int y = event->getY(); |
||
815 |
if (x >= 0 && x <= mDimension.width |
||
816 |
&& y >= 0 && y <= mDimension.height) |
||
817 |
{ |
||
818 |
mouseMoved(*event); |
||
819 |
} |
||
820 |
delete event; |
||
821 |
} |
||
822 |
} |
||
823 |
} |
||
824 |
else |
||
825 |
{ |
||
826 |
✓✓ | 64 |
if (mPlayVisibleSound) |
827 |
1 |
soundManager.playGuiSound(SOUND_HIDE_WINDOW); |
|
828 |
} |
||
829 |
} |
||
830 |
|||
831 |
void Window::scheduleDelete() |
||
832 |
{ |
||
833 |
windowContainer->scheduleDelete(this); |
||
834 |
} |
||
835 |
|||
836 |
void Window::mousePressed(MouseEvent &event) |
||
837 |
{ |
||
838 |
if (event.isConsumed()) |
||
839 |
return; |
||
840 |
|||
841 |
if (event.getSource() == this) |
||
842 |
{ |
||
843 |
if (getParent() != nullptr) |
||
844 |
getParent()->moveToTop(this); |
||
845 |
|||
846 |
mDragOffsetX = event.getX(); |
||
847 |
mDragOffsetY = event.getY(); |
||
848 |
mMoved = event.getY() <= CAST_S32(mTitleBarHeight); |
||
849 |
} |
||
850 |
|||
851 |
const MouseButtonT button = event.getButton(); |
||
852 |
if (button == MouseButton::LEFT) |
||
853 |
{ |
||
854 |
const int x = event.getX(); |
||
855 |
const int y = event.getY(); |
||
856 |
|||
857 |
// Handle close button |
||
858 |
if (mCloseWindowButton && |
||
859 |
mSkin != nullptr && |
||
860 |
mCloseRect.isPointInRect(x, y)) |
||
861 |
{ |
||
862 |
mouseResize = 0; |
||
863 |
mMoved = false; |
||
864 |
event.consume(); |
||
865 |
close(); |
||
866 |
return; |
||
867 |
} |
||
868 |
|||
869 |
// Handle sticky button |
||
870 |
if (mStickyButton && |
||
871 |
mSkin != nullptr && |
||
872 |
mStickyRect.isPointInRect(x, y)) |
||
873 |
{ |
||
874 |
setSticky(!isSticky()); |
||
875 |
mouseResize = 0; |
||
876 |
mMoved = false; |
||
877 |
event.consume(); |
||
878 |
return; |
||
879 |
} |
||
880 |
|||
881 |
// Handle window resizing |
||
882 |
mouseResize = getResizeHandles(event) & resizeMask; |
||
883 |
if (mouseResize != 0) |
||
884 |
event.consume(); |
||
885 |
if (canMove()) |
||
886 |
mMoved = (mouseResize == 0); |
||
887 |
else |
||
888 |
mMoved = false; |
||
889 |
} |
||
890 |
#ifndef DYECMD |
||
891 |
else if (button == MouseButton::RIGHT) |
||
892 |
{ |
||
893 |
if (popupMenu != nullptr) |
||
894 |
{ |
||
895 |
event.consume(); |
||
896 |
popupMenu->showWindowPopup(this); |
||
897 |
} |
||
898 |
} |
||
899 |
#endif // DYECMD |
||
900 |
} |
||
901 |
|||
902 |
void Window::close() |
||
903 |
{ |
||
904 |
setVisible(Visible_false); |
||
905 |
} |
||
906 |
|||
907 |
void Window::mouseReleased(MouseEvent &event A_UNUSED) |
||
908 |
{ |
||
909 |
if ((mGrip != nullptr) && (mouseResize != 0)) |
||
910 |
{ |
||
911 |
mouseResize = 0; |
||
912 |
if (gui != nullptr) |
||
913 |
gui->setCursorType(Cursor::CURSOR_POINTER); |
||
914 |
} |
||
915 |
|||
916 |
mMoved = false; |
||
917 |
} |
||
918 |
|||
919 |
void Window::mouseEntered(MouseEvent &event) |
||
920 |
{ |
||
921 |
updateResizeHandler(event); |
||
922 |
} |
||
923 |
|||
924 |
void Window::mouseExited(MouseEvent &event A_UNUSED) |
||
925 |
{ |
||
926 |
if ((mGrip != nullptr) && (mouseResize == 0) && (gui != nullptr)) |
||
927 |
gui->setCursorType(Cursor::CURSOR_POINTER); |
||
928 |
} |
||
929 |
|||
930 |
void Window::updateResizeHandler(MouseEvent &event) |
||
931 |
{ |
||
932 |
if (gui == nullptr) |
||
933 |
return; |
||
934 |
|||
935 |
#ifndef DYECMD |
||
936 |
if (!dragDrop.isEmpty()) |
||
937 |
return; |
||
938 |
#endif // DYECMD |
||
939 |
|||
940 |
mResizeHandles = getResizeHandles(event); |
||
941 |
|||
942 |
// Changes the custom mouse cursor based on it's current position. |
||
943 |
switch (mResizeHandles & resizeMask) |
||
944 |
{ |
||
945 |
case BOTTOM | RIGHT: |
||
946 |
case TOP | LEFT: |
||
947 |
gui->setCursorType(Cursor::CURSOR_RESIZE_DOWN_RIGHT); |
||
948 |
break; |
||
949 |
case TOP | RIGHT: |
||
950 |
case BOTTOM | LEFT: |
||
951 |
gui->setCursorType(Cursor::CURSOR_RESIZE_DOWN_LEFT); |
||
952 |
break; |
||
953 |
case BOTTOM: |
||
954 |
case TOP: |
||
955 |
gui->setCursorType(Cursor::CURSOR_RESIZE_DOWN); |
||
956 |
break; |
||
957 |
case RIGHT: |
||
958 |
case LEFT: |
||
959 |
gui->setCursorType(Cursor::CURSOR_RESIZE_ACROSS); |
||
960 |
break; |
||
961 |
default: |
||
962 |
gui->setCursorType(Cursor::CURSOR_POINTER); |
||
963 |
break; |
||
964 |
} |
||
965 |
} |
||
966 |
|||
967 |
void Window::mouseMoved(MouseEvent &event) |
||
968 |
{ |
||
969 |
updateResizeHandler(event); |
||
970 |
if ((popupManager != nullptr) && !event.isConsumed()) |
||
971 |
{ |
||
972 |
PopupManager::hideBeingPopup(); |
||
973 |
PopupManager::hideTextPopup(); |
||
974 |
} |
||
975 |
} |
||
976 |
|||
977 |
bool Window::canMove() const |
||
978 |
{ |
||
979 |
return !mStickyButtonLock || !mSticky; |
||
980 |
} |
||
981 |
|||
982 |
void Window::mouseDragged(MouseEvent &event) |
||
983 |
{ |
||
984 |
if (canMove()) |
||
985 |
{ |
||
986 |
if (!event.isConsumed() && event.getSource() == this) |
||
987 |
{ |
||
988 |
if (isMovable() && mMoved) |
||
989 |
{ |
||
990 |
setPosition(event.getX() - mDragOffsetX + getX(), |
||
991 |
event.getY() - mDragOffsetY + getY()); |
||
992 |
} |
||
993 |
|||
994 |
event.consume(); |
||
995 |
} |
||
996 |
} |
||
997 |
else |
||
998 |
{ |
||
999 |
if (!event.isConsumed() && event.getSource() == this) |
||
1000 |
event.consume(); |
||
1001 |
return; |
||
1002 |
} |
||
1003 |
|||
1004 |
// Keep guichan window inside screen when it may be moved |
||
1005 |
if (isMovable() && mMoved) |
||
1006 |
{ |
||
1007 |
setPosition(std::min(mainGraphics->mWidth - mDimension.width, |
||
1008 |
std::max(0, mDimension.x)), |
||
1009 |
std::min(mainGraphics->mHeight - mDimension.height, |
||
1010 |
std::max(0, mDimension.y))); |
||
1011 |
} |
||
1012 |
|||
1013 |
if ((mouseResize != 0) && !mMoved) |
||
1014 |
{ |
||
1015 |
const int dy = event.getY() - mDragOffsetY; |
||
1016 |
Rect newDim = getDimension(); |
||
1017 |
|||
1018 |
if ((mouseResize & (TOP | BOTTOM)) != 0) |
||
1019 |
{ |
||
1020 |
const int newHeight = newDim.height |
||
1021 |
+ ((mouseResize & TOP) != 0 ? -dy : dy); |
||
1022 |
newDim.height = std::min(mMaxWinHeight, |
||
1023 |
std::max(mMinWinHeight, newHeight)); |
||
1024 |
|||
1025 |
if ((mouseResize & TOP) != 0) |
||
1026 |
newDim.y -= newDim.height - getHeight(); |
||
1027 |
} |
||
1028 |
|||
1029 |
if ((mouseResize & (LEFT | RIGHT)) != 0) |
||
1030 |
{ |
||
1031 |
const int dx = event.getX() - mDragOffsetX; |
||
1032 |
const int newWidth = newDim.width |
||
1033 |
+ ((mouseResize & LEFT) != 0 ? -dx : dx); |
||
1034 |
newDim.width = std::min(mMaxWinWidth, |
||
1035 |
std::max(mMinWinWidth, newWidth)); |
||
1036 |
|||
1037 |
if ((mouseResize & LEFT) != 0) |
||
1038 |
newDim.x -= newDim.width - mDimension.width; |
||
1039 |
} |
||
1040 |
|||
1041 |
// Keep guichan window inside screen (supports resizing any side) |
||
1042 |
if (newDim.x < 0) |
||
1043 |
{ |
||
1044 |
newDim.width += newDim.x; |
||
1045 |
newDim.x = 0; |
||
1046 |
} |
||
1047 |
if (newDim.y < 0) |
||
1048 |
{ |
||
1049 |
newDim.height += newDim.y; |
||
1050 |
newDim.y = 0; |
||
1051 |
} |
||
1052 |
if (newDim.x + newDim.width > mainGraphics->mWidth) |
||
1053 |
newDim.width = mainGraphics->mWidth - newDim.x; |
||
1054 |
if (newDim.y + newDim.height > mainGraphics->mHeight) |
||
1055 |
newDim.height = mainGraphics->mHeight - newDim.y; |
||
1056 |
|||
1057 |
// Update mouse offset when dragging bottom or right border |
||
1058 |
if ((mouseResize & BOTTOM) != 0) |
||
1059 |
mDragOffsetY += newDim.height - mDimension.height; |
||
1060 |
|||
1061 |
if ((mouseResize & RIGHT) != 0) |
||
1062 |
mDragOffsetX += newDim.width - mDimension.width; |
||
1063 |
|||
1064 |
// Set the new window and content dimensions |
||
1065 |
setDimension(newDim); |
||
1066 |
} |
||
1067 |
} |
||
1068 |
|||
1069 |
void Window::setModal(const Modal modal) |
||
1070 |
{ |
||
1071 |
if (mModal != modal) |
||
1072 |
{ |
||
1073 |
mModal = modal; |
||
1074 |
if (mModal == Modal_true) |
||
1075 |
{ |
||
1076 |
if (gui != nullptr) |
||
1077 |
gui->setCursorType(Cursor::CURSOR_POINTER); |
||
1078 |
requestModalFocus(); |
||
1079 |
} |
||
1080 |
else |
||
1081 |
{ |
||
1082 |
releaseModalFocus(); |
||
1083 |
} |
||
1084 |
} |
||
1085 |
} |
||
1086 |
|||
1087 |
45 |
void Window::loadWindowState() |
|
1088 |
{ |
||
1089 |
45 |
const std::string &name = mWindowName; |
|
1090 |
✓✓ | 45 |
if (name.empty()) |
1091 |
return; |
||
1092 |
|||
1093 |
✓✗✓✗ ✓✗ |
132 |
setPosition(config.getValueInt(name + "WinX", mDefaultX), |
1094 |
✓✗ | 132 |
config.getValueInt(name + "WinY", mDefaultY)); |
1095 |
|||
1096 |
✓✓ | 44 |
if (mSaveVisible) |
1097 |
{ |
||
1098 |
✓✗✓✓ |
32 |
setVisible(fromBool(config.getValueBool(name |
1099 |
✓✗ | 32 |
+ "Visible", mDefaultVisible), Visible)); |
1100 |
} |
||
1101 |
|||
1102 |
✓✓ | 44 |
if (mStickyButton) |
1103 |
{ |
||
1104 |
✓✗ | 70 |
setSticky(config.getValueBool(name |
1105 |
140 |
+ "Sticky", isSticky())); |
|
1106 |
} |
||
1107 |
|||
1108 |
✓✓ | 44 |
if (mGrip != nullptr) |
1109 |
{ |
||
1110 |
✓✗ | 76 |
int width = config.getValueInt(name + "WinWidth", mDefaultWidth); |
1111 |
✓✗ | 76 |
int height = config.getValueInt(name + "WinHeight", mDefaultHeight); |
1112 |
|||
1113 |
✓✓ | 38 |
if (getMinWidth() > width) |
1114 |
width = getMinWidth(); |
||
1115 |
✗✓ | 37 |
else if (getMaxWidth() < width) |
1116 |
width = getMaxWidth(); |
||
1117 |
✓✓ | 38 |
if (getMinHeight() > height) |
1118 |
height = getMinHeight(); |
||
1119 |
✓✓ | 37 |
else if (getMaxHeight() < height) |
1120 |
1 |
height = getMaxHeight(); |
|
1121 |
|||
1122 |
38 |
setSize(width, height); |
|
1123 |
} |
||
1124 |
else |
||
1125 |
{ |
||
1126 |
6 |
setSize(mDefaultWidth, mDefaultHeight); |
|
1127 |
} |
||
1128 |
|||
1129 |
// Check if the window is off screen... |
||
1130 |
44 |
ensureOnScreen(); |
|
1131 |
|||
1132 |
✗✓ | 44 |
if (viewport != nullptr) |
1133 |
{ |
||
1134 |
int width = mDimension.width; |
||
1135 |
int height = mDimension.height; |
||
1136 |
|||
1137 |
if (mDimension.x + width > viewport->getWidth()) |
||
1138 |
width = viewport->getWidth() - mDimension.x; |
||
1139 |
if (mDimension.y + height > viewport->getHeight()) |
||
1140 |
height = viewport->getHeight() - mDimension.y; |
||
1141 |
if (width < 0) |
||
1142 |
width = 0; |
||
1143 |
if (height < 0) |
||
1144 |
height = 0; |
||
1145 |
setSize(width, height); |
||
1146 |
} |
||
1147 |
} |
||
1148 |
|||
1149 |
63 |
void Window::saveWindowState() |
|
1150 |
{ |
||
1151 |
// Saving X, Y and Width and Height for resizables in the config |
||
1152 |
✓✓✓✓ ✓✓ |
188 |
if (!mWindowName.empty() && mWindowName != "window") |
1153 |
{ |
||
1154 |
✓✗ | 92 |
config.setValue(mWindowName + "WinX", mDimension.x); |
1155 |
✓✗ | 92 |
config.setValue(mWindowName + "WinY", mDimension.y); |
1156 |
|||
1157 |
✓✓ | 46 |
if (mSaveVisible) |
1158 |
48 |
config.setValue(mWindowName + "Visible", isWindowVisible()); |
|
1159 |
|||
1160 |
✓✓ | 46 |
if (mStickyButton) |
1161 |
105 |
config.setValue(mWindowName + "Sticky", isSticky()); |
|
1162 |
|||
1163 |
✓✓ | 46 |
if (mGrip != nullptr) |
1164 |
{ |
||
1165 |
✗✓ | 38 |
if (getMinWidth() > mDimension.width) |
1166 |
setWidth(getMinWidth()); |
||
1167 |
✗✓ | 38 |
else if (getMaxWidth() < mDimension.width) |
1168 |
setWidth(getMaxWidth()); |
||
1169 |
✗✓ | 38 |
if (getMinHeight() > mDimension.height) |
1170 |
setHeight(getMinHeight()); |
||
1171 |
✗✓ | 38 |
else if (getMaxHeight() < mDimension.height) |
1172 |
setHeight(getMaxHeight()); |
||
1173 |
|||
1174 |
✓✗ | 76 |
config.setValue(mWindowName + "WinWidth", mDimension.width); |
1175 |
✓✗ | 76 |
config.setValue(mWindowName + "WinHeight", mDimension.height); |
1176 |
} |
||
1177 |
} |
||
1178 |
63 |
} |
|
1179 |
|||
1180 |
6 |
void Window::setDefaultSize(const int defaultX, const int defaultY, |
|
1181 |
int defaultWidth, int defaultHeight) |
||
1182 |
{ |
||
1183 |
✓✗ | 6 |
if (mMinWinWidth > defaultWidth) |
1184 |
defaultWidth = mMinWinWidth; |
||
1185 |
✗✓ | 6 |
else if (mMaxWinWidth < defaultWidth) |
1186 |
defaultWidth = mMaxWinWidth; |
||
1187 |
✓✗ | 6 |
if (mMinWinHeight > defaultHeight) |
1188 |
defaultHeight = mMinWinHeight; |
||
1189 |
✓✓ | 6 |
else if (mMaxWinHeight < defaultHeight) |
1190 |
1 |
defaultHeight = mMaxWinHeight; |
|
1191 |
|||
1192 |
6 |
mDefaultX = defaultX; |
|
1193 |
6 |
mDefaultY = defaultY; |
|
1194 |
6 |
mDefaultWidth = defaultWidth; |
|
1195 |
6 |
mDefaultHeight = defaultHeight; |
|
1196 |
6 |
} |
|
1197 |
|||
1198 |
3 |
void Window::setDefaultSize() |
|
1199 |
{ |
||
1200 |
3 |
mDefaultX = mDimension.x; |
|
1201 |
3 |
mDefaultY = mDimension.y; |
|
1202 |
3 |
mDefaultWidth = mDimension.width; |
|
1203 |
3 |
mDefaultHeight = mDimension.height; |
|
1204 |
3 |
} |
|
1205 |
|||
1206 |
37 |
void Window::setDefaultSize(const int defaultWidth, const int defaultHeight, |
|
1207 |
const ImagePosition::Type &position, |
||
1208 |
const int offsetX, const int offsetY) |
||
1209 |
{ |
||
1210 |
37 |
int x = 0; |
|
1211 |
37 |
int y = 0; |
|
1212 |
|||
1213 |
✓✗ | 37 |
if (position == ImagePosition::UPPER_LEFT) |
1214 |
{ |
||
1215 |
} |
||
1216 |
✗✓ | 37 |
else if (position == ImagePosition::UPPER_CENTER) |
1217 |
{ |
||
1218 |
x = (mainGraphics->mWidth - defaultWidth) / 2; |
||
1219 |
} |
||
1220 |
✗✓ | 37 |
else if (position == ImagePosition::UPPER_RIGHT) |
1221 |
{ |
||
1222 |
x = mainGraphics->mWidth - defaultWidth; |
||
1223 |
} |
||
1224 |
✗✓ | 37 |
else if (position == ImagePosition::LEFT) |
1225 |
{ |
||
1226 |
y = (mainGraphics->mHeight - defaultHeight) / 2; |
||
1227 |
} |
||
1228 |
✓✓ | 37 |
else if (position == ImagePosition::CENTER) |
1229 |
{ |
||
1230 |
32 |
x = (mainGraphics->mWidth - defaultWidth) / 2; |
|
1231 |
32 |
y = (mainGraphics->mHeight - defaultHeight) / 2; |
|
1232 |
} |
||
1233 |
✓✓ | 5 |
else if (position == ImagePosition::RIGHT) |
1234 |
{ |
||
1235 |
1 |
x = mainGraphics->mWidth - defaultWidth; |
|
1236 |
1 |
y = (mainGraphics->mHeight - defaultHeight) / 2; |
|
1237 |
} |
||
1238 |
✓✓ | 4 |
else if (position == ImagePosition::LOWER_LEFT) |
1239 |
{ |
||
1240 |
3 |
y = mainGraphics->mHeight - defaultHeight; |
|
1241 |
} |
||
1242 |
✗✓ | 1 |
else if (position == ImagePosition::LOWER_CENTER) |
1243 |
{ |
||
1244 |
x = (mainGraphics->mWidth - defaultWidth) / 2; |
||
1245 |
y = mainGraphics->mHeight - defaultHeight; |
||
1246 |
} |
||
1247 |
✓✗ | 1 |
else if (position == ImagePosition::LOWER_RIGHT) |
1248 |
{ |
||
1249 |
1 |
x = mainGraphics->mWidth - defaultWidth; |
|
1250 |
1 |
y = mainGraphics->mHeight - defaultHeight; |
|
1251 |
} |
||
1252 |
|||
1253 |
37 |
mDefaultX = x - offsetX; |
|
1254 |
37 |
mDefaultY = y - offsetY; |
|
1255 |
37 |
mDefaultWidth = defaultWidth; |
|
1256 |
37 |
mDefaultHeight = defaultHeight; |
|
1257 |
37 |
} |
|
1258 |
|||
1259 |
void Window::resetToDefaultSize() |
||
1260 |
{ |
||
1261 |
setPosition(mDefaultX, mDefaultY); |
||
1262 |
setSize(mDefaultWidth, mDefaultHeight); |
||
1263 |
saveWindowState(); |
||
1264 |
} |
||
1265 |
|||
1266 |
void Window::adjustPositionAfterResize(const int oldScreenWidth, |
||
1267 |
const int oldScreenHeight) |
||
1268 |
{ |
||
1269 |
// If window was aligned to the right or bottom, keep it there |
||
1270 |
const int rightMargin = oldScreenWidth - (mDimension.x + mDimension.width); |
||
1271 |
const int bottomMargin = oldScreenHeight |
||
1272 |
- (mDimension.y + mDimension.height); |
||
1273 |
if (mDimension.x > 0 && mDimension.x > rightMargin) |
||
1274 |
mDimension.x = mainGraphics->mWidth - rightMargin - mDimension.width; |
||
1275 |
if (mDimension.y > 0 && mDimension.y > bottomMargin) |
||
1276 |
{ |
||
1277 |
mDimension.y = mainGraphics->mHeight |
||
1278 |
- bottomMargin - mDimension.height; |
||
1279 |
} |
||
1280 |
|||
1281 |
ensureOnScreen(); |
||
1282 |
adjustSizeToScreen(); |
||
1283 |
} |
||
1284 |
|||
1285 |
void Window::adjustSizeToScreen() |
||
1286 |
{ |
||
1287 |
if (mGrip == nullptr) |
||
1288 |
return; |
||
1289 |
|||
1290 |
const int screenWidth = mainGraphics->mWidth; |
||
1291 |
const int screenHeight = mainGraphics->mHeight; |
||
1292 |
const int oldWidth = mDimension.width; |
||
1293 |
const int oldHeight = mDimension.height; |
||
1294 |
if (oldWidth + mDimension.x > screenWidth) |
||
1295 |
mDimension.x = 0; |
||
1296 |
if (oldHeight + mDimension.y > screenHeight) |
||
1297 |
mDimension.x = 0; |
||
1298 |
if (mDimension.width > screenWidth) |
||
1299 |
mDimension.width = screenWidth; |
||
1300 |
if (mDimension.height > screenHeight) |
||
1301 |
mDimension.height = screenHeight; |
||
1302 |
if (oldWidth != mDimension.width || oldHeight != mDimension.height) |
||
1303 |
widgetResized(Event(this)); |
||
1304 |
} |
||
1305 |
|||
1306 |
int Window::getResizeHandles(const MouseEvent &event) |
||
1307 |
{ |
||
1308 |
if (event.getX() < 0 || event.getY() < 0) |
||
1309 |
return 0; |
||
1310 |
|||
1311 |
int resizeHandles = 0; |
||
1312 |
const unsigned y = event.getY(); |
||
1313 |
const unsigned x = event.getX(); |
||
1314 |
if (mCloseRect.isPointInRect(x, y)) |
||
1315 |
return CLOSE; |
||
1316 |
|||
1317 |
if (!mStickyButtonLock || !mSticky) |
||
1318 |
{ |
||
1319 |
if ((mGrip != nullptr) && |
||
1320 |
(y > mTitleBarHeight || |
||
1321 |
(CAST_S32(y) < mPadding && |
||
1322 |
CAST_S32(mTitleBarHeight) > mPadding))) |
||
1323 |
{ |
||
1324 |
if (!getWindowArea().isPointInRect(x, y) |
||
1325 |
&& event.getSource() == this) |
||
1326 |
{ |
||
1327 |
resizeHandles |= (x > mDimension.width - resizeBorderWidth) |
||
1328 |
? RIGHT : (x < resizeBorderWidth) ? LEFT : 0; |
||
1329 |
resizeHandles |= (y > mDimension.height - resizeBorderWidth) |
||
1330 |
? BOTTOM : (y < resizeBorderWidth) ? TOP : 0; |
||
1331 |
} |
||
1332 |
if (x >= CAST_U32(mGripRect.x) |
||
1333 |
&& y >= CAST_U32(mGripRect.y)) |
||
1334 |
{ |
||
1335 |
mDragOffsetX = x; |
||
1336 |
mDragOffsetY = y; |
||
1337 |
resizeHandles |= BOTTOM | RIGHT; |
||
1338 |
} |
||
1339 |
} |
||
1340 |
} |
||
1341 |
|||
1342 |
return resizeHandles; |
||
1343 |
} |
||
1344 |
|||
1345 |
bool Window::isResizeAllowed(const MouseEvent &event) const |
||
1346 |
{ |
||
1347 |
const int y = event.getY(); |
||
1348 |
|||
1349 |
if ((mGrip != nullptr) && |
||
1350 |
(y > CAST_S32(mTitleBarHeight) || |
||
1351 |
y < mPadding)) |
||
1352 |
{ |
||
1353 |
const int x = event.getX(); |
||
1354 |
|||
1355 |
if (!getWindowArea().isPointInRect(x, y) && event.getSource() == this) |
||
1356 |
return true; |
||
1357 |
|||
1358 |
if (x >= mGripRect.x && y >= mGripRect.y) |
||
1359 |
return true; |
||
1360 |
} |
||
1361 |
|||
1362 |
return false; |
||
1363 |
} |
||
1364 |
|||
1365 |
202 |
Layout &Window::getLayout() |
|
1366 |
{ |
||
1367 |
✓✓ | 202 |
if (mLayout == nullptr) |
1368 |
✓✗ | 44 |
mLayout = new Layout; |
1369 |
202 |
return *mLayout; |
|
1370 |
} |
||
1371 |
|||
1372 |
2 |
void Window::clearLayout() |
|
1373 |
{ |
||
1374 |
2 |
clear(); |
|
1375 |
|||
1376 |
// Recreate layout instance when one is present |
||
1377 |
✓✓ | 2 |
if (mLayout != nullptr) |
1378 |
{ |
||
1379 |
1 |
delete mLayout; |
|
1380 |
✓✗ | 1 |
mLayout = new Layout; |
1381 |
} |
||
1382 |
2 |
} |
|
1383 |
|||
1384 |
144 |
LayoutCell &Window::place(const int x, const int y, Widget *const wg, |
|
1385 |
const int w, const int h) |
||
1386 |
{ |
||
1387 |
144 |
add(wg); |
|
1388 |
144 |
return getLayout().place(wg, x, y, w, h); |
|
1389 |
} |
||
1390 |
|||
1391 |
27 |
ContainerPlacer Window::getPlacer(const int x, const int y) |
|
1392 |
{ |
||
1393 |
27 |
return ContainerPlacer(this, &getLayout().at(x, y)); |
|
1394 |
} |
||
1395 |
|||
1396 |
11 |
void Window::reflowLayout(int w, int h) |
|
1397 |
{ |
||
1398 |
✓✗ | 11 |
if (mLayout == nullptr) |
1399 |
return; |
||
1400 |
|||
1401 |
11 |
mLayout->reflow(w, h); |
|
1402 |
✓✗ | 22 |
delete2(mLayout) |
1403 |
11 |
setContentSize(w, h); |
|
1404 |
} |
||
1405 |
|||
1406 |
1 |
void Window::redraw() |
|
1407 |
{ |
||
1408 |
✓✗ | 1 |
if (mLayout != nullptr) |
1409 |
{ |
||
1410 |
2 |
const Rect area = getChildrenArea(); |
|
1411 |
1 |
int w = area.width; |
|
1412 |
1 |
int h = area.height; |
|
1413 |
1 |
mLayout->reflow(w, h); |
|
1414 |
} |
||
1415 |
1 |
} |
|
1416 |
|||
1417 |
31 |
void Window::center() |
|
1418 |
{ |
||
1419 |
62 |
setLocationRelativeTo(getParent()); |
|
1420 |
31 |
} |
|
1421 |
|||
1422 |
void Window::centerHorisontally() |
||
1423 |
{ |
||
1424 |
setLocationHorisontallyRelativeTo(getParent()); |
||
1425 |
} |
||
1426 |
|||
1427 |
79 |
void Window::ensureOnScreen() |
|
1428 |
{ |
||
1429 |
// Skip when a window hasn't got any size initialized yet |
||
1430 |
✓✓ | 79 |
if (mDimension.width == 0 && mDimension.height == 0) |
1431 |
return; |
||
1432 |
|||
1433 |
// Check the left and bottom screen boundaries |
||
1434 |
✓✓ | 73 |
if (mDimension.x + mDimension.width > mainGraphics->mWidth) |
1435 |
2 |
mDimension.x = mainGraphics->mWidth - mDimension.width; |
|
1436 |
✓✓ | 73 |
if (mDimension.y + mDimension.height > mainGraphics->mHeight) |
1437 |
3 |
mDimension.y = mainGraphics->mHeight - mDimension.height; |
|
1438 |
|||
1439 |
// But never allow the windows to disappear in to the right and top |
||
1440 |
✓✓ | 73 |
if (mDimension.x < 0) |
1441 |
14 |
mDimension.x = 0; |
|
1442 |
✓✓ | 73 |
if (mDimension.y < 0) |
1443 |
15 |
mDimension.y = 0; |
|
1444 |
} |
||
1445 |
|||
1446 |
Rect Window::getWindowArea() const |
||
1447 |
{ |
||
1448 |
return Rect(mPadding, |
||
1449 |
mPadding, |
||
1450 |
mDimension.width - mPadding * 2, |
||
1451 |
mDimension.height - mPadding * 2); |
||
1452 |
} |
||
1453 |
|||
1454 |
14 |
int Window::getOption(const std::string &name, const int def) const |
|
1455 |
{ |
||
1456 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
707 |
if (mSkin != nullptr) |
1457 |
{ |
||
1458 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
707 |
const int val = mSkin->getOption(name); |
1459 |
✓✓✗✓ ✓✓✓✓ ✓✗✓✓ ✓✗✓✗ ✓✓✗✓ ✗✓✗✓ |
707 |
if (val != 0) |
1460 |
return val; |
||
1461 |
7 |
return def; |
|
1462 |
} |
||
1463 |
return def; |
||
1464 |
} |
||
1465 |
|||
1466 |
28 |
bool Window::getOptionBool(const std::string &name, const bool def) const |
|
1467 |
{ |
||
1468 |
✓✗✓✗ ✓✗ |
154 |
if (mSkin != nullptr) |
1469 |
✓✗✓✗ |
154 |
return mSkin->getOption(name, static_cast<int>(def)) != 0; |
1470 |
return def; |
||
1471 |
} |
||
1472 |
|||
1473 |
87 |
Rect Window::getChildrenArea() |
|
1474 |
{ |
||
1475 |
return Rect(mPadding, |
||
1476 |
mTitleBarHeight, |
||
1477 |
87 |
mDimension.width - mPadding * 2, |
|
1478 |
261 |
mDimension.height - mPadding - mTitleBarHeight); |
|
1479 |
} |
||
1480 |
|||
1481 |
void Window::resizeToContent() |
||
1482 |
{ |
||
1483 |
int w = 0; |
||
1484 |
int h = 0; |
||
1485 |
for (WidgetListConstIterator it = mWidgets.begin(); |
||
1486 |
it != mWidgets.end(); ++ it) |
||
1487 |
{ |
||
1488 |
const Widget *const widget = *it; |
||
1489 |
const int x = widget->getX(); |
||
1490 |
const int y = widget->getY(); |
||
1491 |
const int width = widget->getWidth(); |
||
1492 |
const int height = widget->getHeight(); |
||
1493 |
if (x + width > w) |
||
1494 |
w = x + width; |
||
1495 |
|||
1496 |
if (y + height > h) |
||
1497 |
h = y + height; |
||
1498 |
} |
||
1499 |
|||
1500 |
setSize(w + 2 * mPadding, |
||
1501 |
h + mPadding + mTitleBarHeight); |
||
1502 |
✓✗✓✗ |
3 |
} |
1503 |
|||
1504 |
#ifdef USE_PROFILER |
||
1505 |
void Window::logic() |
||
1506 |
{ |
||
1507 |
BLOCK_START("Window::logic") |
||
1508 |
logicChildren(); |
||
1509 |
BLOCK_END("Window::logic") |
||
1510 |
} |
||
1511 |
#endif // USE_PROFILER |
Generated by: GCOVR (Version 3.3) |