GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/window.cpp Lines: 393 729 53.9 %
Date: 2017-11-29 Branches: 268 641 41.8 %

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-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
/*      _______   __   __   __   ______   __   __   _______   __   __
24
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
25
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
26
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
27
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
28
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
29
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
30
 *
31
 * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
32
 *
33
 *
34
 * Per Larsson a.k.a finalman
35
 * Olof Naessén a.k.a jansem/yakslem
36
 *
37
 * Visit: http://guichan.sourceforge.net
38
 *
39
 * License: (BSD)
40
 * Redistribution and use in source and binary forms, with or without
41
 * modification, are permitted provided that the following conditions
42
 * are met:
43
 * 1. Redistributions of source code must retain the above copyright
44
 *    notice, this list of conditions and the following disclaimer.
45
 * 2. Redistributions in binary form must reproduce the above copyright
46
 *    notice, this list of conditions and the following disclaimer in
47
 *    the documentation and/or other materials provided with the
48
 *    distribution.
49
 * 3. Neither the name of Guichan nor the names of its contributors may
50
 *    be used to endorse or promote products derived from this software
51
 *    without specific prior written permission.
52
 *
53
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
54
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
55
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
56
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
57
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
59
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64
 */
65
66
#include "gui/widgets/window.h"
67
68
#include "client.h"
69
#include "configuration.h"
70
#ifndef DYECMD
71
#include "dragdrop.h"
72
#else  // DYECMD
73
#include "resources/image/image.h"
74
#endif  // DYECMD
75
#include "soundmanager.h"
76
77
#include "const/sound.h"
78
79
#include "gui/focushandler.h"
80
#include "gui/gui.h"
81
#include "gui/popupmanager.h"
82
#include "gui/skin.h"
83
#include "gui/viewport.h"
84
85
#include "gui/fonts/font.h"
86
87
#include "gui/popups/popupmenu.h"
88
89
#include "gui/windows/setupwindow.h"
90
91
#include "gui/widgets/containerplacer.h"
92
#include "gui/widgets/layout.h"
93
94
#include "render/renderers.h"
95
96
#include "render/vertexes/imagecollection.h"
97
98
#include "utils/checkutils.h"
99
#include "utils/delete2.h"
100
101
#include "debug.h"
102
103
const int resizeMask = 8 + 4 + 2 + 1;
104
105
int Window::windowInstances = 0;
106
int Window::mouseResize = 0;
107
108
124
Window::Window(const std::string &caption,
109
               const Modal modal,
110
               Window *const parent,
111
124
               std::string skin) :
112
    BasicContainer2(nullptr),
113
    MouseListener(),
114
    WidgetListener(),
115
    mCaption(caption),
116
    mAlignment(Graphics::CENTER),
117
    mPadding(2),
118
    mTitleBarHeight(16),
119
    mMovable(Move_true),
120
    mDragOffsetX(0),
121
    mDragOffsetY(0),
122
    mMoved(false),
123
    mSkin(nullptr),
124
    mDefaultX(0),
125
    mDefaultY(0),
126
    mDefaultWidth(0),
127
    mDefaultHeight(0),
128
    mCaptionOffsetX(7),
129
    mCaptionOffsetY(5),
130
    mShowTitle(true),
131
    mLastRedraw(true),
132
    mGrip(nullptr),
133
    mParentWindow(parent),
134
    mLayout(nullptr),
135
    mCloseRect(),
136
    mStickyRect(),
137
    mGripRect(),
138
    mTextChunk(),
139
    mWindowName("window"),
140
    mMinWinWidth(100),
141
    mMinWinHeight(40),
142
124
    mMaxWinWidth(mainGraphics->mWidth),
143
124
    mMaxWinHeight(mainGraphics->mHeight),
144

124
    mVertexes(new ImageCollection),
145
    mCaptionAlign(Graphics::LEFT),
146
    mTitlePadding(4),
147
    mGripPadding(2),
148
    mResizeHandles(-1),
149
    mOldResizeHandles(-1),
150
    mClosePadding(0),
151
    mStickySpacing(0),
152
    mStickyPadding(0),
153
124
    mCaptionFont(getFont()),
154
    mModal(modal),
155
    mCloseWindowButton(false),
156
    mDefaultVisible(false),
157
    mSaveVisible(false),
158
    mStickyButton(false),
159
    mSticky(false),
160
    mStickyButtonLock(false),
161
    mPlayVisibleSound(false),
162
    mInit(false),
163
    mTextChanged(true),
164

1612
    mAllowClose(false)
165
{
166
248
    logger->log("Window::Window(\"%s\")", caption.c_str());
167
168
124
    mWindow = this;
169
170
124
    windowInstances++;
171
172
//    mFrameSize = 1;
173
124
    addMouseListener(this);
174
175
248
    setFrameSize(0);
176
248
    setPadding(3);
177
248
    setTitleBarHeight(20);
178
179
124
    if (skin.empty())
180
        skin = "window.xml";
181
182
124
    int childPalette = 1;
183
    // Loads the skin
184
124
    if (theme != nullptr)
185
    {
186

620
        mSkin = theme->load(skin, "window.xml");
187
124
        if (mSkin != nullptr)
188
        {
189
372
            setPadding(mSkin->getPadding());
190

620
            if (getOptionBool("titlebarBold"))
191
112
                mCaptionFont = boldFont;
192
248
            mTitlePadding = mSkin->getTitlePadding();
193
620
            mGripPadding = getOption("resizePadding");
194
620
            mCaptionOffsetX = getOption("captionoffsetx");
195
124
            if (mCaptionOffsetX == 0)
196
10
                mCaptionOffsetX = 7;
197
620
            mCaptionOffsetY = getOption("captionoffsety");
198
124
            if (mCaptionOffsetY == 0)
199
10
                mCaptionOffsetY = 5;
200
124
            mCaptionAlign = static_cast<Graphics::Alignment>(
201
620
                getOption("captionalign"));
202
124
            if (mCaptionAlign < Graphics::LEFT
203
                || mCaptionAlign > Graphics::RIGHT)
204
            {
205
                mCaptionAlign = Graphics::LEFT;
206
            }
207
248
            setTitleBarHeight(CAST_U32(
208
620
                getOption("titlebarHeight")));
209
124
            if (mTitleBarHeight == 0u)
210
10
                mTitleBarHeight = mCaptionFont->getHeight() + mPadding;
211
212
620
            mTitleBarHeight += getOption("titlebarHeightRelative");
213
744
            setPalette(getOption("palette"));
214
620
            childPalette = getOption("childPalette");
215
620
            mShowTitle = getOptionBool("showTitle", true);
216
620
            mClosePadding = getOption("closePadding");
217
620
            mStickySpacing = getOption("stickySpacing");
218
620
            mStickyPadding = getOption("stickyPadding");
219
        }
220
    }
221
222
    // Add this window to the window container
223
124
    if (windowContainer != nullptr)
224
124
        windowContainer->add(this);
225
226
124
    if (mModal == Modal_true)
227
    {
228
20
        gui->setCursorType(Cursor::CURSOR_POINTER);
229
10
        requestModalFocus();
230
    }
231
232
    // Windows are invisible by default
233
124
    setVisible(Visible_false, false);
234
235
124
    addWidgetListener(this);
236
248
    mForegroundColor = getThemeColor(ThemeColorId::WINDOW);
237
248
    mForegroundColor2 = getThemeColor(ThemeColorId::WINDOW_OUTLINE);
238
248
    setPalette(childPalette);
239
124
}
240
241
124
void Window::postInit()
242
{
243
124
    if (mInit)
244
    {
245
        reportAlways("error: Window created with calling postInit() "
246
            "more than once: %s",
247
            mWindowName.c_str());
248
    }
249
124
    mInit = true;
250
124
}
251
252
1116
Window::~Window()
253
{
254
124
    logger->log("Window::~Window(\"%s\")", getCaption().c_str());
255
256
124
    if (gui != nullptr)
257
124
        gui->removeDragged(this);
258
259
#ifndef DYECMD
260
124
    if (setupWindow != nullptr)
261
4
        setupWindow->unregisterWindowForReset(this);
262
#endif  // DYECMD
263
264
124
    client->windowRemoved(this);
265
266
124
    saveWindowState();
267
268
248
    delete2(mLayout);
269
270
1756
    while (!mWidgets.empty())
271
1508
        delete mWidgets.front();
272
273
248
    mWidgets.clear();
274
275
124
    removeWidgetListener(this);
276
124
    delete2(mVertexes);
277
278
124
    windowInstances--;
279
280
124
    if (mSkin != nullptr)
281
    {
282
124
        if (theme != nullptr)
283
124
            theme->unload(mSkin);
284
124
        mSkin = nullptr;
285
    }
286
124
    if (mGrip != nullptr)
287
    {
288
82
        mGrip->decRef();
289
82
        mGrip = nullptr;
290
    }
291
124
    if (!mInit)
292
    {
293
        reportAlways("error: Window created without calling postInit(): %s",
294
            mWindowName.c_str());
295
    }
296
124
}
297
298
496
void Window::setWindowContainer(WindowContainer *const wc)
299
{
300
496
    windowContainer = wc;
301
496
}
302
303
64
void Window::draw(Graphics *const graphics)
304
{
305
64
    if (mSkin == nullptr)
306
        return;
307
308
    BLOCK_START("Window::draw")
309
64
    bool update = false;
310
311
64
    if (mResizeHandles != mOldResizeHandles)
312
    {
313
64
        mRedraw = true;
314
64
        mOldResizeHandles = mResizeHandles;
315
    }
316
64
    if (mRedraw)
317
    {
318
64
        mLastRedraw = true;
319
64
        mRedraw = false;
320
64
        update = true;
321
64
        mVertexes->clear();
322
64
        graphics->calcWindow(mVertexes,
323
            0, 0,
324
            mDimension.width,
325
            mDimension.height,
326
64
            mSkin->getBorder());
327
328
        // Draw Close Button
329
64
        if (mCloseWindowButton)
330
        {
331
72
            const Image *const button = mSkin->getCloseImage(
332
72
                mResizeHandles == CLOSE);
333
36
            if (button != nullptr)
334
            {
335
36
                graphics->calcTileCollection(mVertexes,
336
                    button,
337
                    mCloseRect.x,
338
36
                    mCloseRect.y);
339
            }
340
        }
341
        // Draw Sticky Button
342
64
        if (mStickyButton)
343
        {
344
60
            const Image *const button = mSkin->getStickyImage(mSticky);
345
30
            if (button != nullptr)
346
            {
347
10
                graphics->calcTileCollection(mVertexes,
348
                    button,
349
                    mStickyRect.x,
350
10
                    mStickyRect.y);
351
            }
352
        }
353
354
64
        if (mGrip != nullptr)
355
        {
356
36
            graphics->calcTileCollection(mVertexes,
357
                mGrip,
358
                mGripRect.x,
359
36
                mGripRect.y);
360
        }
361
64
        graphics->finalize(mVertexes);
362
    }
363
    else
364
    {
365
        mLastRedraw = false;
366
    }
367
64
    graphics->drawTileCollection(mVertexes);
368
369
    // Draw title
370
64
    if (mShowTitle)
371
    {
372
        int x;
373
62
        switch (mCaptionAlign)
374
        {
375
62
            case Graphics::LEFT:
376
            default:
377
62
                x = mCaptionOffsetX;
378
62
                break;
379
            case Graphics::CENTER:
380
                x = mCaptionOffsetX - mCaptionFont->getWidth(mCaption) / 2;
381
                break;
382
            case Graphics::RIGHT:
383
                x = mCaptionOffsetX - mCaptionFont->getWidth(mCaption);
384
                break;
385
        }
386
62
        if (mTextChanged)
387
        {
388
62
            mTextChunk.textFont = mCaptionFont;
389
62
            mTextChunk.deleteImage();
390
124
            mTextChunk.text = mCaption;
391
62
            mTextChunk.color = mForegroundColor;
392
62
            mTextChunk.color2 = mForegroundColor2;
393
62
            mCaptionFont->generate(mTextChunk);
394
62
            mTextChanged = false;
395
        }
396
397
62
        const Image *const image = mTextChunk.img;
398
62
        if (image != nullptr)
399
52
            graphics->drawImage(image, x, mCaptionOffsetY);
400
    }
401
402
64
    if (update)
403
    {
404
128
        graphics->setRedraw(update);
405
64
        drawChildren(graphics);
406
        graphics->setRedraw(false);
407
    }
408
    else
409
    {
410
        drawChildren(graphics);
411
    }
412
    BLOCK_END("Window::draw")
413
}
414
415
void Window::safeDraw(Graphics *const graphics)
416
{
417
    if (mSkin == nullptr)
418
        return;
419
420
    BLOCK_START("Window::safeDraw")
421
422
    graphics->drawImageRect(0, 0,
423
        mDimension.width,
424
        mDimension.height,
425
        mSkin->getBorder());
426
427
    // Draw Close Button
428
    if (mCloseWindowButton)
429
    {
430
        const Image *const button = mSkin->getCloseImage(
431
            mResizeHandles == CLOSE);
432
        if (button != nullptr)
433
            graphics->drawImage(button, mCloseRect.x, mCloseRect.y);
434
    }
435
    // Draw Sticky Button
436
    if (mStickyButton)
437
    {
438
        const Image *const button = mSkin->getStickyImage(mSticky);
439
        if (button != nullptr)
440
            graphics->drawImage(button, mStickyRect.x, mStickyRect.y);
441
    }
442
443
    if (mGrip != nullptr)
444
        graphics->drawImage(mGrip, mGripRect.x, mGripRect.y);
445
446
    // Draw title
447
    if (mShowTitle)
448
    {
449
        int x;
450
        switch (mCaptionAlign)
451
        {
452
            case Graphics::LEFT:
453
            default:
454
                x = mCaptionOffsetX;
455
                break;
456
            case Graphics::CENTER:
457
                x = mCaptionOffsetX - mCaptionFont->getWidth(mCaption) / 2;
458
                break;
459
            case Graphics::RIGHT:
460
                x = mCaptionOffsetX - mCaptionFont->getWidth(mCaption);
461
                break;
462
        }
463
        if (mTextChanged)
464
        {
465
            mTextChunk.textFont = mCaptionFont;
466
            mTextChunk.deleteImage();
467
            mTextChunk.text = mCaption;
468
            mTextChunk.color = mForegroundColor;
469
            mTextChunk.color2 = mForegroundColor2;
470
            mCaptionFont->generate(mTextChunk);
471
            mTextChanged = false;
472
        }
473
474
        const Image *const image = mTextChunk.img;
475
        if (image != nullptr)
476
            graphics->drawImage(image, x, mCaptionOffsetY);
477
    }
478
479
    safeDrawChildren(graphics);
480
481
    BLOCK_END("Window::safeDraw")
482
}
483
484
62
void Window::setContentSize(int width, int height)
485
{
486
62
    width = width + 2 * mPadding;
487
62
    height = height + mPadding + mTitleBarHeight;
488
489
62
    if (mMinWinWidth > width)
490
        width = mMinWinWidth;
491
58
    else if (mMaxWinWidth < width)
492
4
        width = mMaxWinWidth;
493
62
    if (mMinWinHeight > height)
494
        height = mMinWinHeight;
495
62
    else if (mMaxWinHeight < height)
496
4
        height = mMaxWinHeight;
497
498
62
    setSize(width, height);
499
62
}
500
501
74
void Window::setLocationRelativeTo(const Widget *const widget)
502
{
503
74
    if (widget == nullptr)
504
2
        return;
505
506
    int wx, wy;
507
    int x, y;
508
509
72
    widget->getAbsolutePosition(wx, wy);
510
72
    getAbsolutePosition(x, y);
511
512
288
    setPosition(mDimension.x + (wx + (widget->getWidth()
513
144
        - mDimension.width) / 2 - x),
514
216
        mDimension.y + (wy + (widget->getHeight()
515
144
        - mDimension.height) / 2 - y));
516
}
517
518
void Window::setLocationHorisontallyRelativeTo(const Widget *const widget)
519
{
520
    if (widget == nullptr)
521
        return;
522
523
    int wx, wy;
524
    int x, y;
525
526
    widget->getAbsolutePosition(wx, wy);
527
    getAbsolutePosition(x, y);
528
529
    setPosition(mDimension.x + (wx + (widget->getWidth()
530
        - mDimension.width) / 2 - x), 0);
531
}
532
533
void Window::setLocationRelativeTo(const ImagePosition::Type &position,
534
                                   int offsetX, int offsetY)
535
{
536
    if (position == ImagePosition::UPPER_LEFT)
537
    {
538
    }
539
    else if (position == ImagePosition::UPPER_CENTER)
540
    {
541
        offsetX += (mainGraphics->mWidth - mDimension.width) / 2;
542
    }
543
    else if (position == ImagePosition::UPPER_RIGHT)
544
    {
545
        offsetX += mainGraphics->mWidth - mDimension.width;
546
    }
547
    else if (position == ImagePosition::LEFT)
548
    {
549
        offsetY += (mainGraphics->mHeight - mDimension.height) / 2;
550
    }
551
    else if (position == ImagePosition::CENTER)
552
    {
553
        offsetX += (mainGraphics->mWidth - mDimension.width) / 2;
554
        offsetY += (mainGraphics->mHeight - mDimension.height) / 2;
555
    }
556
    else if (position == ImagePosition::RIGHT)
557
    {
558
        offsetX += mainGraphics->mWidth - mDimension.width;
559
        offsetY += (mainGraphics->mHeight - mDimension.height) / 2;
560
    }
561
    else if (position == ImagePosition::LOWER_LEFT)
562
    {
563
        offsetY += mainGraphics->mHeight - mDimension.height;
564
    }
565
    else if (position == ImagePosition::LOWER_CENTER)
566
    {
567
        offsetX += (mainGraphics->mWidth - mDimension.width) / 2;
568
        offsetY += mainGraphics->mHeight - mDimension.height;
569
    }
570
    else if (position == ImagePosition::LOWER_RIGHT)
571
    {
572
        offsetX += mainGraphics->mWidth - mDimension.width;
573
        offsetY += mainGraphics->mHeight - mDimension.height;
574
    }
575
576
    setPosition(offsetX, offsetY);
577
}
578
579
70
void Window::setMinWidth(const int width)
580
{
581
70
    if (mSkin != nullptr)
582
    {
583
140
        mMinWinWidth = width > mSkin->getMinWidth()
584
70
            ? width : mSkin->getMinWidth();
585
    }
586
    else
587
    {
588
        mMinWinWidth = width;
589
    }
590
70
}
591
592
68
void Window::setMinHeight(const int height)
593
{
594
68
    if (mSkin != nullptr)
595
    {
596
136
        mMinWinHeight = height > mSkin->getMinHeight()
597
68
            ? height : mSkin->getMinHeight();
598
    }
599
    else
600
    {
601
        mMinWinHeight = height;
602
    }
603
68
}
604
605
2
void Window::setMaxWidth(const int width)
606
{
607
2
    mMaxWinWidth = width;
608
2
}
609
610
2
void Window::setMaxHeight(const int height)
611
{
612
2
    mMaxWinHeight = height;
613
2
}
614
615
86
void Window::setResizable(const bool r)
616
{
617
86
    if ((mGrip != nullptr) == r)
618
        return;
619
620
82
    if (mGrip != nullptr)
621
        mGrip->decRef();
622
82
    if (r)
623
    {
624

574
        mGrip = Theme::getImageFromThemeXml("resize.xml", "");
625
82
        if (mGrip != nullptr)
626
        {
627
164
            mGripRect.x = mDimension.width - mGrip->getWidth() - mGripPadding;
628
246
            mGripRect.y = mDimension.height - mGrip->getHeight()
629
82
                - mGripPadding;
630
        }
631
        else
632
        {
633
            mGripRect.x = 0;
634
            mGripRect.y = 0;
635
        }
636
    }
637
    else
638
    {
639
        mGrip = nullptr;
640
    }
641
}
642
643
164
void Window::widgetResized(const Event &event A_UNUSED)
644
{
645
164
    if (mGrip != nullptr)
646
    {
647
200
        mGripRect.x = mDimension.width - mGrip->getWidth() - mGripPadding;
648
200
        mGripRect.y = mDimension.height - mGrip->getHeight() - mGripPadding;
649
    }
650
651
164
    if (mLayout != nullptr)
652
    {
653
176
        const Rect area = getChildrenArea();
654
88
        int w = area.width;
655
88
        int h = area.height;
656
88
        mLayout->reflow(w, h);
657
    }
658
164
    if (mSkin != nullptr)
659
    {
660
164
        const bool showClose = mCloseWindowButton
661

268
            && (mSkin->getCloseImage(false) != nullptr);
662
        if (showClose)
663
        {
664
104
            const Image *const button = mSkin->getCloseImage(false);
665
            if (button != nullptr)
666
            {
667
104
                const int buttonWidth = button->getWidth();
668
104
                mCloseRect.x = mDimension.width - buttonWidth - mClosePadding;
669
104
                mCloseRect.y = mClosePadding;
670
104
                mCloseRect.width = buttonWidth;
671
104
                mCloseRect.height = button->getHeight();
672
            }
673
        }
674
164
        if (mStickyButton)
675
        {
676
188
            const Image *const button = mSkin->getStickyImage(mSticky);
677
94
            if (button != nullptr)
678
            {
679
70
                const int buttonWidth = button->getWidth();
680
140
                int x = mDimension.width - buttonWidth
681
70
                    - mStickySpacing - mClosePadding;
682
683
70
                if (showClose)
684
192
                    x -= mSkin->getCloseImage(false)->getWidth();
685
686
70
                mStickyRect.x = x;
687
70
                mStickyRect.y = mStickyPadding;
688
70
                mStickyRect.width = buttonWidth;
689
70
                mStickyRect.height = button->getHeight();
690
            }
691
        }
692
    }
693
    else
694
    {
695
        mCloseRect.x = 0;
696
        mCloseRect.y = 0;
697
        mCloseRect.width = 0;
698
        mCloseRect.height = 0;
699
        mStickyRect.x = 0;
700
        mStickyRect.y = 0;
701
        mStickyRect.width = 0;
702
        mStickyRect.height = 0;
703
    }
704
705
164
    mRedraw = true;
706
164
}
707
708
124
void Window::widgetMoved(const Event& event A_UNUSED)
709
{
710
124
    mRedraw = true;
711
124
}
712
713
1
void Window::widgetHidden(const Event &event A_UNUSED)
714
{
715
1
    if (isBatchDrawRenders(openGLMode))
716
1
        mVertexes->clear();
717
718
1
    mTextChunk.deleteImage();
719
720
1
    mTextChanged = true;
721
1
    mRedraw = true;
722
723
1
    if (gui != nullptr)
724
1
        gui->setCursorType(Cursor::CURSOR_POINTER);
725
726
1
    if (mFocusHandler == nullptr)
727
        return;
728
729
3
    for (WidgetListConstIterator it = mWidgets.begin();
730
15
         it != mWidgets.end(); ++ it)
731
    {
732
4
        if (mFocusHandler->isFocused(*it))
733
            mFocusHandler->focusNone();
734
    }
735
}
736
737
84
void Window::setCloseButton(const bool flag)
738
{
739
84
    mCloseWindowButton = flag;
740
84
    if (flag)
741
82
        mAllowClose = true;
742
84
}
743
744
bool Window::isResizable() const
745
{
746
    return mGrip != nullptr;
747
}
748
749
2
void Window::setStickyButton(const bool flag)
750
{
751
2
    mStickyButton = flag;
752
2
}
753
754
2
void Window::setSticky(const bool sticky)
755
{
756
70
    mSticky = sticky;
757
70
    mRedraw = true;
758
2
}
759
760
70
void Window::setStickyButtonLock(const bool lock)
761
{
762
70
    mStickyButtonLock = lock;
763
70
    mStickyButton = lock;
764
70
}
765
766
104
void Window::setVisible(Visible visible)
767
{
768
104
    setVisible(visible, false);
769
104
}
770
771
230
void Window::setVisible(const Visible visible, const bool forceSticky)
772
{
773
230
    if (visible == mVisible)
774
        return;
775
776
    // Check if the window is off screen...
777
194
    if (visible == Visible_true)
778
69
        ensureOnScreen();
779
    else
780
125
        mResizeHandles = 0;
781
782
194
    if (mStickyButtonLock)
783
    {
784
30
        BasicContainer2::setVisible(visible);
785
    }
786
    else
787
    {
788

164
        BasicContainer2::setVisible(fromBool((!forceSticky && mSticky) ||
789
            visible == Visible_true, Visible));
790
    }
791
194
    if (visible == Visible_true)
792
    {
793
69
        if (mPlayVisibleSound)
794
16
            soundManager.playGuiSound(SOUND_SHOW_WINDOW);
795
69
        if (gui != nullptr)
796
        {
797
            MouseEvent *const event = reinterpret_cast<MouseEvent*>(
798
69
                gui->createMouseEvent(this));
799
69
            if (event != nullptr)
800
            {
801
                const int x = event->getX();
802
                const int y = event->getY();
803
                if (x >= 0 && x <= mDimension.width
804
                    && y >= 0 && y <= mDimension.height)
805
                {
806
                    mouseMoved(*event);
807
                }
808
                delete event;
809
            }
810
        }
811
    }
812
    else
813
    {
814
125
        if (mPlayVisibleSound)
815
1
            soundManager.playGuiSound(SOUND_HIDE_WINDOW);
816
    }
817
}
818
819
void Window::scheduleDelete()
820
{
821
    windowContainer->scheduleDelete(this);
822
}
823
824
void Window::mousePressed(MouseEvent &event)
825
{
826
    if (event.isConsumed())
827
        return;
828
829
    if (event.getSource() == this)
830
    {
831
        if (getParent() != nullptr)
832
            getParent()->moveToTop(this);
833
834
        mDragOffsetX = event.getX();
835
        mDragOffsetY = event.getY();
836
        mMoved = event.getY() <= CAST_S32(mTitleBarHeight);
837
    }
838
839
    const MouseButtonT button = event.getButton();
840
    if (button == MouseButton::LEFT)
841
    {
842
        const int x = event.getX();
843
        const int y = event.getY();
844
845
        // Handle close button
846
        if (mCloseWindowButton &&
847
            mSkin != nullptr &&
848
            mCloseRect.isPointInRect(x, y))
849
        {
850
            mouseResize = 0;
851
            mMoved = false;
852
            event.consume();
853
            close();
854
            return;
855
        }
856
857
        // Handle sticky button
858
        if (mStickyButton &&
859
            mSkin != nullptr &&
860
            mStickyRect.isPointInRect(x, y))
861
        {
862
            setSticky(!isSticky());
863
            mouseResize = 0;
864
            mMoved = false;
865
            event.consume();
866
            return;
867
        }
868
869
        // Handle window resizing
870
        mouseResize = getResizeHandles(event) & resizeMask;
871
        if (mouseResize != 0)
872
            event.consume();
873
        if (canMove())
874
            mMoved = (mouseResize == 0);
875
        else
876
            mMoved = false;
877
    }
878
#ifndef DYECMD
879
    else if (button == MouseButton::RIGHT)
880
    {
881
        if (popupMenu != nullptr)
882
        {
883
            event.consume();
884
            popupMenu->showWindowPopup(this);
885
        }
886
    }
887
#endif  // DYECMD
888
}
889
890
void Window::close()
891
{
892
    setVisible(Visible_false);
893
}
894
895
void Window::mouseReleased(MouseEvent &event A_UNUSED)
896
{
897
    if ((mGrip != nullptr) && (mouseResize != 0))
898
    {
899
        mouseResize = 0;
900
        if (gui != nullptr)
901
            gui->setCursorType(Cursor::CURSOR_POINTER);
902
    }
903
904
    mMoved = false;
905
}
906
907
void Window::mouseEntered(MouseEvent &event)
908
{
909
    updateResizeHandler(event);
910
}
911
912
void Window::mouseExited(MouseEvent &event A_UNUSED)
913
{
914
    if ((mGrip != nullptr) && (mouseResize == 0) && (gui != nullptr))
915
        gui->setCursorType(Cursor::CURSOR_POINTER);
916
}
917
918
void Window::updateResizeHandler(MouseEvent &event)
919
{
920
    if (gui == nullptr)
921
        return;
922
923
#ifndef DYECMD
924
    if (!dragDrop.isEmpty())
925
        return;
926
#endif  // DYECMD
927
928
    mResizeHandles = getResizeHandles(event);
929
930
    // Changes the custom mouse cursor based on it's current position.
931
    switch (mResizeHandles & resizeMask)
932
    {
933
        case BOTTOM | RIGHT:
934
        case TOP | LEFT:
935
            gui->setCursorType(Cursor::CURSOR_RESIZE_DOWN_RIGHT);
936
            break;
937
        case TOP | RIGHT:
938
        case BOTTOM | LEFT:
939
            gui->setCursorType(Cursor::CURSOR_RESIZE_DOWN_LEFT);
940
            break;
941
        case BOTTOM:
942
        case TOP:
943
            gui->setCursorType(Cursor::CURSOR_RESIZE_DOWN);
944
            break;
945
        case RIGHT:
946
        case LEFT:
947
            gui->setCursorType(Cursor::CURSOR_RESIZE_ACROSS);
948
            break;
949
        default:
950
            gui->setCursorType(Cursor::CURSOR_POINTER);
951
            break;
952
    }
953
}
954
955
void Window::mouseMoved(MouseEvent &event)
956
{
957
    updateResizeHandler(event);
958
    if ((popupManager != nullptr) && !event.isConsumed())
959
    {
960
        PopupManager::hideBeingPopup();
961
        PopupManager::hideTextPopup();
962
    }
963
}
964
965
bool Window::canMove() const
966
{
967
    return !mStickyButtonLock || !mSticky;
968
}
969
970
void Window::mouseDragged(MouseEvent &event)
971
{
972
    if (canMove())
973
    {
974
        if (!event.isConsumed() && event.getSource() == this)
975
        {
976
            if (isMovable() && mMoved)
977
            {
978
                setPosition(event.getX() - mDragOffsetX + getX(),
979
                    event.getY() - mDragOffsetY + getY());
980
            }
981
982
            event.consume();
983
        }
984
    }
985
    else
986
    {
987
        if (!event.isConsumed() && event.getSource() == this)
988
            event.consume();
989
        return;
990
    }
991
992
    // Keep guichan window inside screen when it may be moved
993
    if (isMovable() && mMoved)
994
    {
995
        setPosition(std::min(mainGraphics->mWidth - mDimension.width,
996
            std::max(0, mDimension.x)),
997
            std::min(mainGraphics->mHeight - mDimension.height,
998
            std::max(0, mDimension.y)));
999
    }
1000
1001
    if ((mouseResize != 0) && !mMoved)
1002
    {
1003
        const int dx = event.getX() - mDragOffsetX;
1004
        const int dy = event.getY() - mDragOffsetY;
1005
        Rect newDim = getDimension();
1006
1007
        if ((mouseResize & (TOP | BOTTOM)) != 0)
1008
        {
1009
            const int newHeight = newDim.height
1010
                + ((mouseResize & TOP) != 0 ? -dy : dy);
1011
            newDim.height = std::min(mMaxWinHeight,
1012
                std::max(mMinWinHeight, newHeight));
1013
1014
            if ((mouseResize & TOP) != 0)
1015
                newDim.y -= newDim.height - getHeight();
1016
        }
1017
1018
        if ((mouseResize & (LEFT | RIGHT)) != 0)
1019
        {
1020
            const int newWidth = newDim.width
1021
                + ((mouseResize & LEFT) != 0 ? -dx : dx);
1022
            newDim.width = std::min(mMaxWinWidth,
1023
                std::max(mMinWinWidth, newWidth));
1024
1025
            if ((mouseResize & LEFT) != 0)
1026
                newDim.x -= newDim.width - mDimension.width;
1027
        }
1028
1029
        // Keep guichan window inside screen (supports resizing any side)
1030
        if (newDim.x < 0)
1031
        {
1032
            newDim.width += newDim.x;
1033
            newDim.x = 0;
1034
        }
1035
        if (newDim.y < 0)
1036
        {
1037
            newDim.height += newDim.y;
1038
            newDim.y = 0;
1039
        }
1040
        if (newDim.x + newDim.width > mainGraphics->mWidth)
1041
            newDim.width = mainGraphics->mWidth - newDim.x;
1042
        if (newDim.y + newDim.height > mainGraphics->mHeight)
1043
            newDim.height = mainGraphics->mHeight - newDim.y;
1044
1045
        // Update mouse offset when dragging bottom or right border
1046
        if ((mouseResize & BOTTOM) != 0)
1047
            mDragOffsetY += newDim.height - mDimension.height;
1048
1049
        if ((mouseResize & RIGHT) != 0)
1050
            mDragOffsetX += newDim.width - mDimension.width;
1051
1052
        // Set the new window and content dimensions
1053
        setDimension(newDim);
1054
    }
1055
}
1056
1057
void Window::setModal(const Modal modal)
1058
{
1059
    if (mModal != modal)
1060
    {
1061
        mModal = modal;
1062
        if (mModal == Modal_true)
1063
        {
1064
            if (gui != nullptr)
1065
                gui->setCursorType(Cursor::CURSOR_POINTER);
1066
            requestModalFocus();
1067
        }
1068
        else
1069
        {
1070
            releaseModalFocus();
1071
        }
1072
    }
1073
}
1074
1075
88
void Window::loadWindowState()
1076
{
1077
88
    const std::string &name = mWindowName;
1078
88
    if (name.empty())
1079
        return;
1080
1081


258
    setPosition(config.getValueInt(name + "WinX", mDefaultX),
1082
172
        config.getValueInt(name + "WinY", mDefaultY));
1083
1084
86
    if (mSaveVisible)
1085
    {
1086

60
        setVisible(fromBool(config.getValueBool(name
1087
30
            + "Visible", mDefaultVisible), Visible));
1088
    }
1089
1090
86
    if (mStickyButton)
1091
    {
1092
204
        setSticky(config.getValueBool(name
1093
204
            + "Sticky", isSticky()));
1094
    }
1095
1096
86
    if (mGrip != nullptr)
1097
    {
1098
148
        int width = config.getValueInt(name + "WinWidth", mDefaultWidth);
1099
148
        int height = config.getValueInt(name + "WinHeight", mDefaultHeight);
1100
1101
74
        if (getMinWidth() > width)
1102
            width = getMinWidth();
1103
73
        else if (getMaxWidth() < width)
1104
            width = getMaxWidth();
1105
74
        if (getMinHeight() > height)
1106
            height = getMinHeight();
1107
73
        else if (getMaxHeight() < height)
1108
1
            height = getMaxHeight();
1109
1110
74
        setSize(width, height);
1111
    }
1112
    else
1113
    {
1114
12
        setSize(mDefaultWidth, mDefaultHeight);
1115
    }
1116
1117
    // Check if the window is off screen...
1118
86
    ensureOnScreen();
1119
1120
86
    if (viewport != nullptr)
1121
    {
1122
        int width = mDimension.width;
1123
        int height = mDimension.height;
1124
1125
        if (mDimension.x + width > viewport->getWidth())
1126
            width = viewport->getWidth() - mDimension.x;
1127
        if (mDimension.y + height > viewport->getHeight())
1128
            height = viewport->getHeight() - mDimension.y;
1129
        if (width < 0)
1130
            width = 0;
1131
        if (height < 0)
1132
            height = 0;
1133
        setSize(width, height);
1134
    }
1135
}
1136
1137
124
void Window::saveWindowState()
1138
{
1139
    // Saving X, Y and Width and Height for resizables in the config
1140

370
    if (!mWindowName.empty() && mWindowName != "window")
1141
    {
1142
180
        config.setValue(mWindowName + "WinX", mDimension.x);
1143
180
        config.setValue(mWindowName + "WinY", mDimension.y);
1144
1145
90
        if (mSaveVisible)
1146
90
            config.setValue(mWindowName + "Visible", isWindowVisible());
1147
1148
90
        if (mStickyButton)
1149
204
            config.setValue(mWindowName + "Sticky", isSticky());
1150
1151
90
        if (mGrip != nullptr)
1152
        {
1153
74
            if (getMinWidth() > mDimension.width)
1154
                setWidth(getMinWidth());
1155
74
            else if (getMaxWidth() < mDimension.width)
1156
                setWidth(getMaxWidth());
1157
74
            if (getMinHeight() > mDimension.height)
1158
                setHeight(getMinHeight());
1159
74
            else if (getMaxHeight() < mDimension.height)
1160
                setHeight(getMaxHeight());
1161
1162
148
            config.setValue(mWindowName + "WinWidth", mDimension.width);
1163
148
            config.setValue(mWindowName + "WinHeight", mDimension.height);
1164
        }
1165
    }
1166
124
}
1167
1168
12
void Window::setDefaultSize(const int defaultX, const int defaultY,
1169
                            int defaultWidth, int defaultHeight)
1170
{
1171
12
    if (mMinWinWidth > defaultWidth)
1172
        defaultWidth = mMinWinWidth;
1173
12
    else if (mMaxWinWidth < defaultWidth)
1174
        defaultWidth = mMaxWinWidth;
1175
12
    if (mMinWinHeight > defaultHeight)
1176
        defaultHeight = mMinWinHeight;
1177
12
    else if (mMaxWinHeight < defaultHeight)
1178
2
        defaultHeight = mMaxWinHeight;
1179
1180
12
    mDefaultX = defaultX;
1181
12
    mDefaultY = defaultY;
1182
12
    mDefaultWidth = defaultWidth;
1183
12
    mDefaultHeight = defaultHeight;
1184
12
}
1185
1186
6
void Window::setDefaultSize()
1187
{
1188
6
    mDefaultX = mDimension.x;
1189
6
    mDefaultY = mDimension.y;
1190
6
    mDefaultWidth = mDimension.width;
1191
6
    mDefaultHeight = mDimension.height;
1192
6
}
1193
1194
72
void Window::setDefaultSize(const int defaultWidth, const int defaultHeight,
1195
                            const ImagePosition::Type &position,
1196
                            const int offsetX, const int offsetY)
1197
{
1198
72
    int x = 0;
1199
72
    int y = 0;
1200
1201
72
    if (position == ImagePosition::UPPER_LEFT)
1202
    {
1203
    }
1204
72
    else if (position == ImagePosition::UPPER_CENTER)
1205
    {
1206
        x = (mainGraphics->mWidth - defaultWidth) / 2;
1207
    }
1208
72
    else if (position == ImagePosition::UPPER_RIGHT)
1209
    {
1210
        x = mainGraphics->mWidth - defaultWidth;
1211
    }
1212
72
    else if (position == ImagePosition::LEFT)
1213
    {
1214
        y = (mainGraphics->mHeight - defaultHeight) / 2;
1215
    }
1216
72
    else if (position == ImagePosition::CENTER)
1217
    {
1218
62
        x = (mainGraphics->mWidth - defaultWidth) / 2;
1219
62
        y = (mainGraphics->mHeight - defaultHeight) / 2;
1220
    }
1221
10
    else if (position == ImagePosition::RIGHT)
1222
    {
1223
2
        x = mainGraphics->mWidth - defaultWidth;
1224
2
        y = (mainGraphics->mHeight - defaultHeight) / 2;
1225
    }
1226
8
    else if (position == ImagePosition::LOWER_LEFT)
1227
    {
1228
6
        y = mainGraphics->mHeight - defaultHeight;
1229
    }
1230
2
    else if (position == ImagePosition::LOWER_CENTER)
1231
    {
1232
        x = (mainGraphics->mWidth - defaultWidth) / 2;
1233
        y = mainGraphics->mHeight - defaultHeight;
1234
    }
1235
2
    else if (position == ImagePosition::LOWER_RIGHT)
1236
    {
1237
2
        x = mainGraphics->mWidth - defaultWidth;
1238
2
        y = mainGraphics->mHeight - defaultHeight;
1239
    }
1240
1241
72
    mDefaultX = x - offsetX;
1242
72
    mDefaultY = y - offsetY;
1243
72
    mDefaultWidth = defaultWidth;
1244
72
    mDefaultHeight = defaultHeight;
1245
72
}
1246
1247
void Window::resetToDefaultSize()
1248
{
1249
    setPosition(mDefaultX, mDefaultY);
1250
    setSize(mDefaultWidth, mDefaultHeight);
1251
    saveWindowState();
1252
}
1253
1254
void Window::adjustPositionAfterResize(const int oldScreenWidth,
1255
                                       const int oldScreenHeight)
1256
{
1257
    // If window was aligned to the right or bottom, keep it there
1258
    const int rightMargin = oldScreenWidth - (mDimension.x + mDimension.width);
1259
    const int bottomMargin = oldScreenHeight
1260
        - (mDimension.y + mDimension.height);
1261
    if (mDimension.x > 0 && mDimension.x > rightMargin)
1262
        mDimension.x = mainGraphics->mWidth - rightMargin - mDimension.width;
1263
    if (mDimension.y > 0 && mDimension.y > bottomMargin)
1264
    {
1265
        mDimension.y = mainGraphics->mHeight
1266
            - bottomMargin - mDimension.height;
1267
    }
1268
1269
    ensureOnScreen();
1270
    adjustSizeToScreen();
1271
}
1272
1273
void Window::adjustSizeToScreen()
1274
{
1275
    if (mGrip == nullptr)
1276
        return;
1277
1278
    const int screenWidth = mainGraphics->mWidth;
1279
    const int screenHeight = mainGraphics->mHeight;
1280
    const int oldWidth = mDimension.width;
1281
    const int oldHeight = mDimension.height;
1282
    if (oldWidth + mDimension.x > screenWidth)
1283
        mDimension.x = 0;
1284
    if (oldHeight + mDimension.y > screenHeight)
1285
        mDimension.x = 0;
1286
    if (mDimension.width > screenWidth)
1287
        mDimension.width = screenWidth;
1288
    if (mDimension.height > screenHeight)
1289
        mDimension.height = screenHeight;
1290
    if (oldWidth != mDimension.width || oldHeight != mDimension.height)
1291
        widgetResized(Event(this));
1292
}
1293
1294
int Window::getResizeHandles(const MouseEvent &event)
1295
{
1296
    if (event.getX() < 0 || event.getY() < 0)
1297
        return 0;
1298
1299
    int resizeHandles = 0;
1300
    const unsigned y = event.getY();
1301
    const unsigned x = event.getX();
1302
    if (mCloseRect.isPointInRect(x, y))
1303
        return CLOSE;
1304
1305
    if (!mStickyButtonLock || !mSticky)
1306
    {
1307
        if ((mGrip != nullptr) &&
1308
            (y > mTitleBarHeight ||
1309
            (CAST_S32(y) < mPadding &&
1310
            CAST_S32(mTitleBarHeight) > mPadding)))
1311
        {
1312
            if (!getWindowArea().isPointInRect(x, y)
1313
                && event.getSource() == this)
1314
            {
1315
                resizeHandles |= (x > mDimension.width - resizeBorderWidth)
1316
                    ? RIGHT : (x < resizeBorderWidth) ? LEFT : 0;
1317
                resizeHandles |= (y > mDimension.height - resizeBorderWidth)
1318
                    ? BOTTOM : (y < resizeBorderWidth) ? TOP : 0;
1319
            }
1320
            if (x >= CAST_U32(mGripRect.x)
1321
                && y >= CAST_U32(mGripRect.y))
1322
            {
1323
                mDragOffsetX = x;
1324
                mDragOffsetY = y;
1325
                resizeHandles |= BOTTOM | RIGHT;
1326
            }
1327
        }
1328
    }
1329
1330
    return resizeHandles;
1331
}
1332
1333
bool Window::isResizeAllowed(const MouseEvent &event) const
1334
{
1335
    const int y = event.getY();
1336
1337
    if ((mGrip != nullptr) &&
1338
        (y > CAST_S32(mTitleBarHeight) ||
1339
        y < mPadding))
1340
    {
1341
        const int x = event.getX();
1342
1343
        if (!getWindowArea().isPointInRect(x, y) && event.getSource() == this)
1344
            return true;
1345
1346
        if (x >= mGripRect.x && y >= mGripRect.y)
1347
            return true;
1348
    }
1349
1350
    return false;
1351
}
1352
1353
404
Layout &Window::getLayout()
1354
{
1355
404
    if (mLayout == nullptr)
1356
88
        mLayout = new Layout;
1357
404
    return *mLayout;
1358
}
1359
1360
4
void Window::clearLayout()
1361
{
1362
4
    clear();
1363
1364
    // Recreate layout instance when one is present
1365
4
    if (mLayout != nullptr)
1366
    {
1367
2
        delete mLayout;
1368
2
        mLayout = new Layout;
1369
    }
1370
4
}
1371
1372
288
LayoutCell &Window::place(const int x, const int y, Widget *const wg,
1373
                          const int w, const int h)
1374
{
1375
288
    add(wg);
1376
288
    return getLayout().place(wg, x, y, w, h);
1377
}
1378
1379
54
ContainerPlacer Window::getPlacer(const int x, const int y)
1380
{
1381
54
    return ContainerPlacer(this, &getLayout().at(x, y));
1382
}
1383
1384
22
void Window::reflowLayout(int w, int h)
1385
{
1386
22
    if (mLayout == nullptr)
1387
        return;
1388
1389
22
    mLayout->reflow(w, h);
1390
44
    delete2(mLayout);
1391
22
    setContentSize(w, h);
1392
}
1393
1394
2
void Window::redraw()
1395
{
1396
2
    if (mLayout != nullptr)
1397
    {
1398
4
        const Rect area = getChildrenArea();
1399
2
        int w = area.width;
1400
2
        int h = area.height;
1401
2
        mLayout->reflow(w, h);
1402
    }
1403
2
}
1404
1405
62
void Window::center()
1406
{
1407
124
    setLocationRelativeTo(getParent());
1408
62
}
1409
1410
void Window::centerHorisontally()
1411
{
1412
    setLocationHorisontallyRelativeTo(getParent());
1413
}
1414
1415
155
void Window::ensureOnScreen()
1416
{
1417
    // Skip when a window hasn't got any size initialized yet
1418
155
    if (mDimension.width == 0 && mDimension.height == 0)
1419
        return;
1420
1421
    // Check the left and bottom screen boundaries
1422
144
    if (mDimension.x + mDimension.width > mainGraphics->mWidth)
1423
2
        mDimension.x = mainGraphics->mWidth - mDimension.width;
1424
144
    if (mDimension.y + mDimension.height > mainGraphics->mHeight)
1425
4
        mDimension.y = mainGraphics->mHeight - mDimension.height;
1426
1427
    // But never allow the windows to disappear in to the right and top
1428
144
    if (mDimension.x < 0)
1429
24
        mDimension.x = 0;
1430
144
    if (mDimension.y < 0)
1431
26
        mDimension.y = 0;
1432
}
1433
1434
Rect Window::getWindowArea() const
1435
{
1436
    return Rect(mPadding,
1437
        mPadding,
1438
        mDimension.width - mPadding * 2,
1439
        mDimension.height - mPadding * 2);
1440
}
1441
1442
28
int Window::getOption(const std::string &name, const int def) const
1443
{
1444






1392
    if (mSkin != nullptr)
1445
    {
1446





1392
        const int val = mSkin->getOption(name);
1447






1392
        if (val != 0)
1448
            return val;
1449
14
        return def;
1450
    }
1451
    return def;
1452
}
1453
1454
56
bool Window::getOptionBool(const std::string &name, const bool def) const
1455
{
1456

304
    if (mSkin != nullptr)
1457

304
        return mSkin->getOption(name, static_cast<int>(def)) != 0;
1458
    return def;
1459
}
1460
1461
174
Rect Window::getChildrenArea()
1462
{
1463
    return Rect(mPadding,
1464
        mTitleBarHeight,
1465
174
        mDimension.width - mPadding * 2,
1466
522
        mDimension.height - mPadding - mTitleBarHeight);
1467
}
1468
1469
void Window::resizeToContent()
1470
{
1471
    int w = 0;
1472
    int h = 0;
1473
    for (WidgetListConstIterator it = mWidgets.begin();
1474
          it != mWidgets.end(); ++ it)
1475
    {
1476
        const Widget *const widget = *it;
1477
        const int x = widget->getX();
1478
        const int y = widget->getY();
1479
        const int width = widget->getWidth();
1480
        const int height = widget->getHeight();
1481
        if (x + width > w)
1482
            w = x + width;
1483
1484
        if (y + height > h)
1485
            h = y + height;
1486
    }
1487
1488
    setSize(w + 2 * mPadding,
1489
        h + mPadding + mTitleBarHeight);
1490

6
}
1491
1492
#ifdef USE_PROFILER
1493
void Window::logic()
1494
{
1495
    BLOCK_START("Window::logic")
1496
    logicChildren();
1497
    BLOCK_END("Window::logic")
1498
}
1499
#endif  // USE_PROFILER