GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/widget.cpp Lines: 180 222 81.1 %
Date: 2018-09-20 Branches: 66 114 57.9 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2018  The ManaPlus Developers
4
 *
5
 *  This file is part of The ManaPlus Client.
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
/*      _______   __   __   __   ______   __   __   _______   __   __
22
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
23
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
24
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
25
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
26
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
27
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
28
 *
29
 * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
30
 *
31
 *
32
 * Per Larsson a.k.a finalman
33
 * Olof Naessén a.k.a jansem/yakslem
34
 *
35
 * Visit: http://guichan.sourceforge.net
36
 *
37
 * License: (BSD)
38
 * Redistribution and use in source and binary forms, with or without
39
 * modification, are permitted provided that the following conditions
40
 * are met:
41
 * 1. Redistributions of source code must retain the above copyright
42
 *    notice, this list of conditions and the following disclaimer.
43
 * 2. Redistributions in binary form must reproduce the above copyright
44
 *    notice, this list of conditions and the following disclaimer in
45
 *    the documentation and/or other materials provided with the
46
 *    distribution.
47
 * 3. Neither the name of Guichan nor the names of its contributors may
48
 *    be used to endorse or promote products derived from this software
49
 *    without specific prior written permission.
50
 *
51
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
54
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
55
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
56
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
57
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
58
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
59
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
60
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
61
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
 */
63
64
/*
65
 * For comments regarding functions please see the header file.
66
 */
67
68
#include "gui/widgets/widget.h"
69
70
#include "gui/focushandler.h"
71
72
#include "listeners/actionlistener.h"
73
#include "listeners/widgetdeathlistener.h"
74
#include "listeners/widgetlistener.h"
75
76
#include "utils/foreach.h"
77
78
#include "debug.h"
79
80
Font* Widget::mGlobalFont = nullptr;
81
1
std::list<Widget*> Widget::mAllWidgets;
82
1
std::set<Widget*> Widget::mAllWidgetsSet;
83
84
2484
Widget::Widget(const Widget2 *const widget) :
85
    Widget2(widget),
86
    mVisible(Visible_true),
87
    mMouseListeners(),
88
    mKeyListeners(),
89
    mActionListeners(),
90
    mDeathListeners(),
91
    mFocusListeners(),
92
    mWidgetListeners(),
93
    mForegroundColor(0x000000),
94
    mBackgroundColor(0xffffff),
95
    mBaseColor(0x808090),
96
    mDimension(),
97
    mActionEventId(),
98
    mId(),
99
    mFocusHandler(nullptr),
100
    mInternalFocusHandler(nullptr),
101
    mParent(nullptr),
102
    mCurrentFont(nullptr),
103
    mFrameSize(0),
104
    mFocusable(false),
105
    mTabIn(true),
106
    mTabOut(true),
107
    mEnabled(true),
108
    mAllowLogic(true),
109
    mMouseConsume(true),
110
    mRedraw(true),
111
34776
    mSelectable(true)
112
{
113
4968
    mAllWidgets.push_back(this);
114
4968
    mAllWidgetsSet.insert(this);
115
2484
}
116
117
27324
Widget::~Widget()
118
{
119
7452
    FOR_EACH (WidgetDeathListenerIterator, iter, mDeathListeners)
120
    {
121
4398
        Event event(this);
122
2199
        (*iter)->death(event);
123
    }
124
125
    // +++ call to virtual member
126
2484
    setFocusHandler(nullptr);
127
128
2484
    mAllWidgets.remove(this);
129
4968
    mAllWidgetsSet.erase(this);
130
2484
}
131
132
4841
void Widget::setWidth(const int width)
133
{
134
14523
    Rect newDimension = mDimension;
135
4841
    newDimension.width = width;
136
4841
    setDimension(newDimension);
137
4841
}
138
139
3633
void Widget::setHeight(const int height)
140
{
141
10899
    Rect newDimension = mDimension;
142
3633
    newDimension.height = height;
143
3633
    setDimension(newDimension);
144
3633
}
145
146
void Widget::setX(const int x)
147
{
148
    Rect newDimension = mDimension;
149
    newDimension.x = x;
150
    setDimension(newDimension);
151
}
152
153
198
void Widget::setY(const int y)
154
{
155
594
    Rect newDimension = mDimension;
156
198
    newDimension.y = y;
157
198
    setDimension(newDimension);
158
198
}
159
160
2408
void Widget::setPosition(const int x, const int y)
161
{
162
7224
    Rect newDimension = mDimension;
163
2408
    newDimension.x = x;
164
2408
    newDimension.y = y;
165
2408
    setDimension(newDimension);
166
2408
}
167
168
12900
void Widget::setDimension(const Rect& dimension)
169
{
170
38700
    const Rect oldDimension = mDimension;
171
25800
    mDimension = dimension;
172
173
12900
    if (mDimension.width != oldDimension.width
174
12900
        || mDimension.height != oldDimension.height)
175
    {
176
        distributeResizedEvent();
177
    }
178
179
12900
    if (mDimension.x != oldDimension.x || mDimension.y != oldDimension.y)
180
        distributeMovedEvent();
181
12900
}
182
183
562
bool Widget::isFocused() const
184
{
185
562
    if (mFocusHandler == nullptr)
186
        return false;
187
188
231
    return mFocusHandler->isFocused(this);
189
}
190
191
1343
void Widget::setFocusable(const bool focusable)
192
{
193


1343
    if (!focusable && isFocused() && (mFocusHandler != nullptr))
194
        mFocusHandler->focusNone();
195
1343
    mFocusable = focusable;
196
1343
}
197
198
29
bool Widget::isFocusable() const
199
{
200

58
    return mFocusable && isVisible() && isEnabled();
201
}
202
203
29
void Widget::requestFocus()
204
{
205
29
    if (mFocusHandler == nullptr)
206
        return;
207
208
29
    if (isFocusable())
209
24
        mFocusHandler->requestFocus(this);
210
}
211
212
void Widget::requestMoveToTop()
213
{
214
    if (mParent != nullptr)
215
        mParent->moveToTop(this);
216
}
217
218
void Widget::requestMoveToBottom()
219
{
220
    if (mParent != nullptr)
221
        mParent->moveToBottom(this);
222
}
223
224
555
void Widget::setVisible(Visible visible)
225
{
226


555
    if (visible == Visible_false && isFocused() && (mFocusHandler != nullptr))
227
        mFocusHandler->focusNone();
228
229
555
    if (visible == Visible_true)
230
        distributeShownEvent();
231
    else
232
        distributeHiddenEvent();
233
234
555
    mVisible = visible;
235
555
}
236
237
6460
void Widget::setFocusHandler(FocusHandler *const focusHandler)
238
{
239
6460
    if (mFocusHandler != nullptr)
240
    {
241
1232
        releaseModalFocus();
242
1232
        mFocusHandler->remove(this);
243
    }
244
245
6460
    if (focusHandler != nullptr)
246
1232
        focusHandler->add(this);
247
248
6460
    mFocusHandler = focusHandler;
249
6460
}
250
251
1962
void Widget::addActionListener(ActionListener *const actionListener)
252
{
253
3924
    mActionListeners.push_back(actionListener);
254
1962
}
255
256
6
void Widget::removeActionListener(ActionListener *const actionListener)
257
{
258
6
    mActionListeners.remove(actionListener);
259
6
}
260
261
2274
void Widget::addDeathListener(WidgetDeathListener *const deathListener)
262
{
263
4548
    mDeathListeners.push_back(deathListener);
264
2274
}
265
266
75
void Widget::removeDeathListener(WidgetDeathListener *const deathListener)
267
{
268
75
    mDeathListeners.remove(deathListener);
269
75
}
270
271
1165
void Widget::addKeyListener(KeyListener *const keyListener)
272
{
273
2330
    mKeyListeners.push_back(keyListener);
274
1165
}
275
276
96
void Widget::removeKeyListener(KeyListener *const keyListener)
277
{
278
96
    mKeyListeners.remove(keyListener);
279
96
}
280
281
539
void Widget::addFocusListener(FocusListener *const focusListener)
282
{
283
1078
    mFocusListeners.push_back(focusListener);
284
539
}
285
286
95
void Widget::removeFocusListener(FocusListener *const focusListener)
287
{
288
95
    mFocusListeners.remove(focusListener);
289
95
}
290
291
2249
void Widget::addMouseListener(MouseListener *const mouseListener)
292
{
293
4498
    mMouseListeners.push_back(mouseListener);
294
2249
}
295
296
611
void Widget::removeMouseListener(MouseListener *const mouseListener)
297
{
298
611
    mMouseListeners.remove(mouseListener);
299
611
}
300
301
2188
void Widget::addWidgetListener(WidgetListener *const widgetListener)
302
{
303
4376
    mWidgetListeners.push_back(widgetListener);
304
2188
}
305
306
1474
void Widget::removeWidgetListener(WidgetListener *const widgetListener)
307
{
308
1474
    mWidgetListeners.remove(widgetListener);
309
1474
}
310
311
113
void Widget::getAbsolutePosition(int& x, int& y) const
312
{
313
113
    if (mParent == nullptr)
314
    {
315
74
        x = mDimension.x;
316
74
        y = mDimension.y;
317
74
        return;
318
    }
319
320
    int parentX;
321
    int parentY;
322
323
39
    mParent->getAbsolutePosition(parentX, parentY);
324
325
78
    const Rect &rect = mParent->getChildrenArea();
326
39
    x = parentX + mDimension.x + rect.x;
327
39
    y = parentY + mDimension.y + rect.y;
328
}
329
330
2886
Font* Widget::getFont() const
331
{
332
2886
    if (mCurrentFont == nullptr)
333
2881
        return mGlobalFont;
334
    return mCurrentFont;
335
}
336
337
131
void Widget::setGlobalFont(Font *const font)
338
{
339
131
    mGlobalFont = font;
340
341
655
    FOR_EACH (std::list<Widget*>::const_iterator, iter, mAllWidgets)
342
    {
343
133
        if ((*iter)->mCurrentFont == nullptr)
344
133
            (*iter)->fontChanged();
345
    }
346
131
}
347
348
18
void Widget::setFont(Font *const font)
349
{
350
18
    mCurrentFont = font;
351
18
    fontChanged();
352
18
}
353
354
void Widget::distributeWindowResizeEvent()
355
{
356
    FOR_EACH (std::list<Widget*>::const_iterator, iter, mAllWidgets)
357
        (*iter)->windowResized();
358
}
359
360
127
bool Widget::widgetExists(const Widget *const widget)
361
{
362
254
    return mAllWidgetsSet.find(const_cast<Widget*>(widget))
363
254
        != mAllWidgetsSet.end();
364
}
365
366
951
void Widget::setSize(const int width, const int height)
367
{
368
2853
    Rect newDimension = mDimension;
369
951
    newDimension.width = width;
370
951
    newDimension.height = height;
371
951
    setDimension(newDimension);
372
951
}
373
374
128
bool Widget::isEnabled() const
375
{
376

225
    return mEnabled && isVisible();
377
}
378
379
7
void Widget::requestModalFocus()
380
{
381
7
    if (mFocusHandler == nullptr)
382
        return;
383
7
    mFocusHandler->requestModalFocus(this);
384
}
385
386
void Widget::requestModalMouseInputFocus()
387
{
388
    if (mFocusHandler == nullptr)
389
        return;
390
    mFocusHandler->requestModalMouseInputFocus(this);
391
}
392
393
1232
void Widget::releaseModalFocus()
394
{
395
1232
    if (mFocusHandler == nullptr)
396
        return;
397
1232
    mFocusHandler->releaseModalFocus(this);
398
}
399
400
void Widget::releaseModalMouseInputFocus()
401
{
402
    if (mFocusHandler == nullptr)
403
        return;
404
    mFocusHandler->releaseModalMouseInputFocus(this);
405
}
406
407
3
bool Widget::isModalFocused() const
408
{
409
3
    if (mFocusHandler == nullptr)
410
        return false;
411
412
3
    if (mParent != nullptr)
413
    {
414
2
        return (mFocusHandler->getModalFocused() == this)
415

2
            || mParent->isModalFocused();
416
    }
417
418
1
    return mFocusHandler->getModalFocused() == this;
419
}
420
421
bool Widget::isModalMouseInputFocused() const
422
{
423
    if (mFocusHandler == nullptr)
424
        return false;
425
426
    if (mParent != nullptr)
427
    {
428
        return (mFocusHandler->getModalMouseInputFocused() == this)
429
            || mParent->isModalMouseInputFocused();
430
    }
431
432
    return mFocusHandler->getModalMouseInputFocused() == this;
433
}
434
435
const std::list<MouseListener*> &Widget::getMouseListeners() const
436
{
437
    return mMouseListeners;
438
}
439
440
const std::list<KeyListener*> &Widget::getKeyListeners() const
441
{
442
    return mKeyListeners;
443
}
444
445
25
const std::list<FocusListener*> &Widget::getFocusListeners() const
446
{
447
25
    return mFocusListeners;
448
}
449
450
Rect Widget::getChildrenArea()
451
{
452
    return Rect(0, 0, 0, 0);
453
}
454
455
FocusHandler* Widget::getInternalFocusHandler()
456
{
457
    return mInternalFocusHandler;
458
}
459
460
void Widget::setInternalFocusHandler(FocusHandler *const focusHandler)
461
{
462
    mInternalFocusHandler = focusHandler;
463
}
464
465
9
void Widget::distributeResizedEvent()
466
{
467

18210
    FOR_EACH (WidgetListenerIterator, iter, mWidgetListeners)
468
    {
469
5026
        Event event(this);
470
2513
        (*iter)->widgetResized(event);
471
    }
472
9
}
473
474
void Widget::distributeMovedEvent()
475
{
476

6522
    FOR_EACH (WidgetListenerIterator, iter, mWidgetListeners)
477
    {
478
3738
        Event event(this);
479
1869
        (*iter)->widgetMoved(event);
480
    }
481
}
482
483
void Widget::distributeHiddenEvent()
484
{
485

1128
    FOR_EACH (WidgetListenerIterator, iter, mWidgetListeners)
486
    {
487
612
        Event event(this);
488
306
        (*iter)->widgetHidden(event);
489
    }
490
}
491
492
1
void Widget::distributeActionEvent()
493
{
494
3
    FOR_EACH (ActionListenerIterator, iter, mActionListeners)
495
    {
496
3
        ActionEvent actionEvent(this, mActionEventId);
497
1
        (*iter)->action(actionEvent);
498
    }
499
1
}
500
501
void Widget::distributeShownEvent()
502
{
503

537
    FOR_EACH (WidgetListenerIterator, iter, mWidgetListeners)
504
    {
505
734
        Event event(this);
506
367
        (*iter)->widgetShown(event);
507
    }
508
}
509
510
202
void Widget::showPart(const Rect &rectangle)
511
{
512
202
    if (mParent != nullptr)
513
202
        mParent->showWidgetPart(this, rectangle);
514
202
}
515
516
void Widget::windowResized()
517
{
518
    mRedraw = true;
519
}
520
521
246
Widget *Widget::callPostInit(Widget *const widget)
522
{
523
246
    if (widget != nullptr)
524
246
        widget->postInit();
525
246
    return widget;
526

3
}