GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/widget.cpp Lines: 180 222 81.1 %
Date: 2017-11-29 Branches: 61 106 57.5 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2017  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
2
std::list<Widget*> Widget::mAllWidgets;
82
2
std::set<Widget*> Widget::mAllWidgetsSet;
83
84
4730
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
66220
    mSelectable(true)
112
{
113
9460
    mAllWidgets.push_back(this);
114
9460
    mAllWidgetsSet.insert(this);
115
4730
}
116
117
52030
Widget::~Widget()
118
{
119
14190
    FOR_EACH (WidgetDeathListenerIterator, iter, mDeathListeners)
120
    {
121
8396
        Event event(this);
122
4198
        (*iter)->death(event);
123
    }
124
125
    // +++ call to virtual member
126
4730
    setFocusHandler(nullptr);
127
128
4730
    mAllWidgets.remove(this);
129
9460
    mAllWidgetsSet.erase(this);
130
4730
}
131
132
9179
void Widget::setWidth(const int width)
133
{
134
27537
    Rect newDimension = mDimension;
135
9179
    newDimension.width = width;
136
9179
    setDimension(newDimension);
137
9179
}
138
139
6967
void Widget::setHeight(const int height)
140
{
141
20901
    Rect newDimension = mDimension;
142
6967
    newDimension.height = height;
143
6967
    setDimension(newDimension);
144
6967
}
145
146
void Widget::setX(const int x)
147
{
148
    Rect newDimension = mDimension;
149
    newDimension.x = x;
150
    setDimension(newDimension);
151
}
152
153
390
void Widget::setY(const int y)
154
{
155
1170
    Rect newDimension = mDimension;
156
390
    newDimension.y = y;
157
390
    setDimension(newDimension);
158
390
}
159
160
4549
void Widget::setPosition(const int x, const int y)
161
{
162
13647
    Rect newDimension = mDimension;
163
4549
    newDimension.x = x;
164
4549
    newDimension.y = y;
165
4549
    setDimension(newDimension);
166
4549
}
167
168
24441
void Widget::setDimension(const Rect& dimension)
169
{
170
73323
    const Rect oldDimension = mDimension;
171
48882
    mDimension = dimension;
172
173
24441
    if (mDimension.width != oldDimension.width
174
24441
        || mDimension.height != oldDimension.height)
175
    {
176
        distributeResizedEvent();
177
    }
178
179
24441
    if (mDimension.x != oldDimension.x || mDimension.y != oldDimension.y)
180
        distributeMovedEvent();
181
24441
}
182
183
1081
bool Widget::isFocused() const
184
{
185
1081
    if (mFocusHandler == nullptr)
186
        return false;
187
188
455
    return mFocusHandler->isFocused(this);
189
}
190
191
2616
void Widget::setFocusable(const bool focusable)
192
{
193

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

108
    return mFocusable && isVisible() && isEnabled();
201
}
202
203
58
void Widget::requestFocus()
204
{
205
58
    if (mFocusHandler == nullptr)
206
        return;
207
208
58
    if (isFocusable())
209
48
        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
1040
void Widget::setVisible(Visible visible)
225
{
226

1040
    if (visible == Visible_false && isFocused() && (mFocusHandler != nullptr))
227
        mFocusHandler->focusNone();
228
229
1040
    if (visible == Visible_true)
230
        distributeShownEvent();
231
    else
232
        distributeHiddenEvent();
233
234
1040
    mVisible = visible;
235
1040
}
236
237
12268
void Widget::setFocusHandler(FocusHandler *const focusHandler)
238
{
239
12268
    if (mFocusHandler != nullptr)
240
    {
241
2410
        releaseModalFocus();
242
2410
        mFocusHandler->remove(this);
243
    }
244
245
12268
    if (focusHandler != nullptr)
246
2410
        focusHandler->add(this);
247
248
12268
    mFocusHandler = focusHandler;
249
12268
}
250
251
3836
void Widget::addActionListener(ActionListener *const actionListener)
252
{
253
7672
    mActionListeners.push_back(actionListener);
254
3836
}
255
256
12
void Widget::removeActionListener(ActionListener *const actionListener)
257
{
258
12
    mActionListeners.remove(actionListener);
259
12
}
260
261
4332
void Widget::addDeathListener(WidgetDeathListener *const deathListener)
262
{
263
8664
    mDeathListeners.push_back(deathListener);
264
4332
}
265
266
134
void Widget::removeDeathListener(WidgetDeathListener *const deathListener)
267
{
268
134
    mDeathListeners.remove(deathListener);
269
134
}
270
271
2280
void Widget::addKeyListener(KeyListener *const keyListener)
272
{
273
4560
    mKeyListeners.push_back(keyListener);
274
2280
}
275
276
190
void Widget::removeKeyListener(KeyListener *const keyListener)
277
{
278
190
    mKeyListeners.remove(keyListener);
279
190
}
280
281
1038
void Widget::addFocusListener(FocusListener *const focusListener)
282
{
283
2076
    mFocusListeners.push_back(focusListener);
284
1038
}
285
286
188
void Widget::removeFocusListener(FocusListener *const focusListener)
287
{
288
188
    mFocusListeners.remove(focusListener);
289
188
}
290
291
4282
void Widget::addMouseListener(MouseListener *const mouseListener)
292
{
293
8564
    mMouseListeners.push_back(mouseListener);
294
4282
}
295
296
1090
void Widget::removeMouseListener(MouseListener *const mouseListener)
297
{
298
1090
    mMouseListeners.remove(mouseListener);
299
1090
}
300
301
4136
void Widget::addWidgetListener(WidgetListener *const widgetListener)
302
{
303
8272
    mWidgetListeners.push_back(widgetListener);
304
4136
}
305
306
2766
void Widget::removeWidgetListener(WidgetListener *const widgetListener)
307
{
308
2766
    mWidgetListeners.remove(widgetListener);
309
2766
}
310
311
226
void Widget::getAbsolutePosition(int& x, int& y) const
312
{
313
226
    if (mParent == nullptr)
314
    {
315
148
        x = mDimension.x;
316
148
        y = mDimension.y;
317
148
        return;
318
    }
319
320
    int parentX;
321
    int parentY;
322
323
78
    mParent->getAbsolutePosition(parentX, parentY);
324
325
156
    const Rect &rect = mParent->getChildrenArea();
326
78
    x = parentX + mDimension.x + rect.x;
327
78
    y = parentY + mDimension.y + rect.y;
328
}
329
330
5411
Font* Widget::getFont() const
331
{
332
5411
    if (mCurrentFont == nullptr)
333
5401
        return mGlobalFont;
334
    return mCurrentFont;
335
}
336
337
252
void Widget::setGlobalFont(Font *const font)
338
{
339
252
    mGlobalFont = font;
340
341
1260
    FOR_EACH (std::list<Widget*>::const_iterator, iter, mAllWidgets)
342
    {
343
254
        if ((*iter)->mCurrentFont == nullptr)
344
254
            (*iter)->fontChanged();
345
    }
346
252
}
347
348
36
void Widget::setFont(Font *const font)
349
{
350
36
    mCurrentFont = font;
351
36
    fontChanged();
352
36
}
353
354
void Widget::distributeWindowResizeEvent()
355
{
356
    FOR_EACH (std::list<Widget*>::const_iterator, iter, mAllWidgets)
357
        (*iter)->windowResized();
358
}
359
360
248
bool Widget::widgetExists(const Widget *const widget)
361
{
362
496
    return mAllWidgetsSet.find(const_cast<Widget*>(widget))
363
496
        != mAllWidgetsSet.end();
364
}
365
366
1756
void Widget::setSize(const int width, const int height)
367
{
368
5268
    Rect newDimension = mDimension;
369
1756
    newDimension.width = width;
370
1756
    newDimension.height = height;
371
1756
    setDimension(newDimension);
372
1756
}
373
374
254
bool Widget::isEnabled() const
375
{
376
508
    return mEnabled && isVisible();
377
}
378
379
14
void Widget::requestModalFocus()
380
{
381
14
    if (mFocusHandler == nullptr)
382
        return;
383
14
    mFocusHandler->requestModalFocus(this);
384
}
385
386
void Widget::requestModalMouseInputFocus()
387
{
388
    if (mFocusHandler == nullptr)
389
        return;
390
    mFocusHandler->requestModalMouseInputFocus(this);
391
}
392
393
2410
void Widget::releaseModalFocus()
394
{
395
2410
    if (mFocusHandler == nullptr)
396
        return;
397
2410
    mFocusHandler->releaseModalFocus(this);
398
}
399
400
void Widget::releaseModalMouseInputFocus()
401
{
402
    if (mFocusHandler == nullptr)
403
        return;
404
    mFocusHandler->releaseModalMouseInputFocus(this);
405
}
406
407
6
bool Widget::isModalFocused() const
408
{
409
6
    if (mFocusHandler == nullptr)
410
        return false;
411
412
6
    if (mParent != nullptr)
413
    {
414
4
        return (mFocusHandler->getModalFocused() == this)
415

4
            || mParent->isModalFocused();
416
    }
417
418
2
    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
50
const std::list<FocusListener*> &Widget::getFocusListeners() const
446
{
447
50
    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
18
void Widget::distributeResizedEvent()
466
{
467

34629
    FOR_EACH (WidgetListenerIterator, iter, mWidgetListeners)
468
    {
469
9530
        Event event(this);
470
4765
        (*iter)->widgetResized(event);
471
    }
472
18
}
473
474
void Widget::distributeMovedEvent()
475
{
476

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

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

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

6
}