GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/tabs/tab.cpp Lines: 78 213 36.6 %
Date: 2017-11-29 Branches: 36 128 28.1 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2008-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/tabs/tab.h"
67
68
#include "settings.h"
69
70
#include "gui/gui.h"
71
#include "gui/skin.h"
72
73
#include "gui/widgets/label.h"
74
#include "gui/widgets/tabbedarea.h"
75
76
#include "render/vertexes/imagecollection.h"
77
78
#include "resources/imagerect.h"
79
80
#include "resources/image/image.h"
81
82
#include "utils/delete2.h"
83
84
#include "debug.h"
85
86
int Tab::mInstances = 0;
87
float Tab::mAlpha = 1.0;
88
89
namespace
90
{
91
6
    std::string const data[Tab::TAB_COUNT] =
92
    {
93
        "tab.xml",
94
        "tab_highlighted.xml",
95
        "tab_selected.xml",
96
        "tab_unused.xml"
97


18
    };
98
}  // namespace
99
100
Skin *Tab::tabImg[Tab::TAB_COUNT];
101
102
86
Tab::Tab(const Widget2 *const widget) :
103
    BasicContainer(widget),
104
    MouseListener(),
105
    WidgetListener(),
106

86
    mLabel(new Label(this)),
107
    mTabbedArea(nullptr),
108
172
    mTabColor(&getThemeColor(ThemeColorId::TAB)),
109
172
    mTabOutlineColor(&getThemeColor(ThemeColorId::TAB_OUTLINE)),
110
172
    mTabHighlightedColor(&getThemeColor(ThemeColorId::TAB_HIGHLIGHTED)),
111
    mTabHighlightedOutlineColor(&getThemeColor(
112
172
        ThemeColorId::TAB_HIGHLIGHTED_OUTLINE)),
113
172
    mTabSelectedColor(&getThemeColor(ThemeColorId::TAB_SELECTED)),
114
    mTabSelectedOutlineColor(&getThemeColor(
115
172
        ThemeColorId::TAB_SELECTED_OUTLINE)),
116
172
    mFlashColor(&getThemeColor(ThemeColorId::TAB_FLASH)),
117
172
    mFlashOutlineColor(&getThemeColor(ThemeColorId::TAB_FLASH_OUTLINE)),
118
172
    mPlayerFlashColor(&getThemeColor(ThemeColorId::TAB_PLAYER_FLASH)),
119
    mPlayerFlashOutlineColor(&getThemeColor(
120
172
        ThemeColorId::TAB_PLAYER_FLASH_OUTLINE)),
121
    mFlash(0),
122

86
    mVertexes(new ImageCollection),
123
    mImage(nullptr),
124
    mMode(0),
125
    mLabelMode(-1),
126
1376
    mHasMouse(false)
127
{
128
86
    init();
129
86
}
130
131
418
Tab::~Tab()
132
{
133
86
    if (gui != nullptr)
134
86
        gui->removeDragged(this);
135
136
86
    mInstances--;
137

86
    if (mInstances == 0 && (theme != nullptr))
138
    {
139
108
        for (int mode = 0; mode < TAB_COUNT; mode ++)
140
48
            theme->unload(tabImg[mode]);
141
    }
142
143
86
    delete2(mLabel);
144
145
86
    if (mImage != nullptr)
146
    {
147
        mImage->decRef();
148
        mImage = nullptr;
149
    }
150
86
    delete2(mVertexes);
151
160
}
152
153
86
void Tab::init()
154
{
155
86
    addMouseListener(this);
156
86
    setFocusable(false);
157
172
    setFrameSize(0);
158
86
    mFlash = 0;
159
160
86
    addWidgetListener(this);
161
162
86
    if (mInstances == 0)
163
    {
164
        // Load the skin
165
12
        if (theme != nullptr)
166
        {
167
108
            for (int mode = 0; mode < TAB_COUNT; mode ++)
168

288
                tabImg[mode] = theme->load(data[mode], "tab.xml");
169
        }
170
12
        updateAlpha();
171
    }
172
86
    mInstances++;
173
174
86
    add(mLabel);
175
176
86
    const Skin *const skin = tabImg[TAB_STANDARD];
177
86
    if (skin == nullptr)
178
        return;
179
86
    const int padding = skin->getPadding();
180
181
86
    mLabel->setPosition(padding, padding);
182
}
183
184
12
void Tab::updateAlpha()
185
{
186
    const float alpha = std::max(settings.guiAlpha,
187
36
        theme->getMinimumOpacity());
188
189
12
    if (alpha != mAlpha)
190
    {
191
        mAlpha = alpha;
192
        for (int a = 0; a < 9; a++)
193
        {
194
            for (int t = 0; t < TAB_COUNT; t++)
195
            {
196
                Skin *const skin = tabImg[t];
197
                if (skin != nullptr)
198
                {
199
                    const ImageRect &rect = skin->getBorder();
200
                    Image *const image = rect.grid[a];
201
                    if (image != nullptr)
202
                        image->setAlpha(mAlpha);
203
                }
204
            }
205
        }
206
    }
207
12
}
208
209
void Tab::draw(Graphics *const graphics)
210
{
211
    BLOCK_START("Tab::draw")
212
    int mode = TAB_STANDARD;
213
214
    // check which type of tab to draw
215
    if (mTabbedArea != nullptr)
216
    {
217
        int labelMode = mFlash;
218
219
        if (mTabbedArea->isTabSelected(this))
220
        {
221
            labelMode = 3;
222
            mode = TAB_SELECTED;
223
            // if tab is selected, it doesnt need to highlight activity
224
            mFlash = 0;
225
        }
226
        else if (labelMode == 0)
227
        {
228
            if (mHasMouse)
229
            {
230
                labelMode = 4;
231
                mode = TAB_HIGHLIGHTED;
232
            }
233
        }
234
        else if (mHasMouse)
235
        {
236
            mode = TAB_HIGHLIGHTED;
237
        }
238
239
        // mRedraw need here because no other way to say label to change color
240
        // +++ text from label must be moved to tab itself
241
        if (labelMode != mLabelMode || mRedraw)
242
        {
243
            mLabelMode = labelMode;
244
            switch (labelMode)
245
            {
246
                case 0:  // default state
247
                default:
248
                    mLabel->setForegroundColorAll(*mTabColor,
249
                        *mTabOutlineColor);
250
                    break;
251
                case 1:  // mFlash == 1
252
                    mLabel->setForegroundColorAll(*mFlashColor,
253
                        *mFlashOutlineColor);
254
                    break;
255
                case 2:  // mFlash == 2
256
                    mLabel->setForegroundColorAll(*mPlayerFlashColor,
257
                        *mPlayerFlashOutlineColor);
258
                    break;
259
                case 3:  // mTabbedArea->isTabSelected(this)
260
                    mLabel->setForegroundColorAll(*mTabSelectedColor,
261
                        *mTabSelectedOutlineColor);
262
                    break;
263
                case 4:  // mHasMouse
264
                    mLabel->setForegroundColorAll(*mTabHighlightedColor,
265
                        *mTabHighlightedOutlineColor);
266
                    break;
267
            }
268
        }
269
    }
270
271
    const Skin *const skin = tabImg[mode];
272
    if (skin == nullptr)
273
    {
274
        BLOCK_END("Tab::draw")
275
        return;
276
    }
277
278
    updateAlpha();
279
280
    const ImageRect &rect = skin->getBorder();
281
    if (mRedraw || mode != mMode || graphics->getRedraw())
282
    {
283
        mMode = mode;
284
        mRedraw = false;
285
        mVertexes->clear();
286
        graphics->calcWindow(mVertexes,
287
            0, 0,
288
            mDimension.width, mDimension.height,
289
            rect);
290
291
        if (mImage != nullptr)
292
        {
293
            const Skin *const skin1 = tabImg[TAB_STANDARD];
294
            if (skin1 != nullptr)
295
            {
296
                const int padding = skin1->getPadding();
297
                graphics->calcTileCollection(mVertexes,
298
                    mImage,
299
                    padding,
300
                    padding);
301
            }
302
        }
303
        graphics->finalize(mVertexes);
304
    }
305
306
    graphics->drawTileCollection(mVertexes);
307
308
    drawChildren(graphics);
309
    BLOCK_END("Tab::draw")
310
}
311
312
void Tab::safeDraw(Graphics *const graphics)
313
{
314
    BLOCK_START("Tab::draw")
315
    int mode = TAB_STANDARD;
316
317
    // check which type of tab to draw
318
    if (mTabbedArea != nullptr)
319
    {
320
        int labelMode = mFlash;
321
322
        if (mTabbedArea->isTabSelected(this))
323
        {
324
            labelMode = 3;
325
            mode = TAB_SELECTED;
326
            // if tab is selected, it doesnt need to highlight activity
327
            mFlash = 0;
328
        }
329
        else if (labelMode == 0)
330
        {
331
            if (mHasMouse)
332
            {
333
                labelMode = 4;
334
                mode = TAB_HIGHLIGHTED;
335
            }
336
        }
337
        else if (mHasMouse)
338
        {
339
            mode = TAB_HIGHLIGHTED;
340
        }
341
342
        if (labelMode != mLabelMode)
343
        {
344
            mLabelMode = labelMode;
345
            switch (labelMode)
346
            {
347
                case 0:  // default state
348
                default:
349
                    mLabel->setForegroundColorAll(*mTabColor,
350
                        *mTabOutlineColor);
351
                    break;
352
                case 1:  // mFlash == 1
353
                    mLabel->setForegroundColorAll(*mFlashColor,
354
                        *mFlashOutlineColor);
355
                    break;
356
                case 2:  // mFlash == 2
357
                    mLabel->setForegroundColorAll(*mPlayerFlashColor,
358
                        *mPlayerFlashOutlineColor);
359
                    break;
360
                case 3:  // mTabbedArea->isTabSelected(this)
361
                    mLabel->setForegroundColorAll(*mTabSelectedColor,
362
                        *mTabSelectedOutlineColor);
363
                    break;
364
                case 4:  // mHasMouse
365
                    mLabel->setForegroundColorAll(*mTabHighlightedColor,
366
                        *mTabHighlightedOutlineColor);
367
                    break;
368
            }
369
        }
370
    }
371
372
    const Skin *const skin = tabImg[mode];
373
    if (skin == nullptr)
374
    {
375
        BLOCK_END("Tab::draw")
376
        return;
377
    }
378
379
    updateAlpha();
380
381
    graphics->drawImageRect(0, 0,
382
        mDimension.width, mDimension.height,
383
        skin->getBorder());
384
    if (mImage != nullptr)
385
    {
386
        const Skin *const skin1 = tabImg[TAB_STANDARD];
387
        if (skin1 != nullptr)
388
        {
389
            const int padding = skin1->getPadding();
390
            graphics->drawImage(mImage, padding, padding);
391
        }
392
    }
393
394
    safeDrawChildren(graphics);
395
    BLOCK_END("Tab::draw")
396
}
397
398
86
void Tab::widgetResized(const Event &event A_UNUSED)
399
{
400
86
    mRedraw = true;
401
86
}
402
403
110
void Tab::widgetMoved(const Event &event A_UNUSED)
404
{
405
110
    mRedraw = true;
406
110
}
407
408
void Tab::setLabelFont(Font *const font)
409
{
410
    if (mLabel == nullptr)
411
        return;
412
413
    mLabel->setFont(font);
414
    mLabel->adjustSize();
415
    adjustSize();
416
    mRedraw = true;
417
}
418
419
420
86
void Tab::adjustSize()
421
{
422
86
    const Skin *const skin = tabImg[TAB_STANDARD];
423
86
    if (skin == nullptr)
424
        return;
425
86
    const int pad2 = skin->getPadding() * 2;
426
427
86
    if (mImage != nullptr)
428
    {
429
        const SDL_Rect &rect = mImage->mBounds;
430
        setSize(rect.w + pad2, rect.h + pad2);
431
    }
432
    else
433
    {
434
258
        setSize(mLabel->getWidth() + pad2,
435
172
                mLabel->getHeight() + pad2);
436
    }
437
438
86
    if (mTabbedArea != nullptr)
439
        mTabbedArea->adjustTabPositions();
440
}
441
442
86
void Tab::setTabbedArea(TabbedArea* tabbedArea)
443
{
444
86
    mTabbedArea = tabbedArea;
445
86
}
446
447
TabbedArea* Tab::getTabbedArea() const
448
{
449
    return mTabbedArea;
450
}
451
452
86
void Tab::setCaption(const std::string &caption)
453
{
454
86
    mLabel->setCaption(caption);
455
86
    mLabel->adjustSize();
456
86
    adjustSize();
457
86
}
458
459
void Tab::setImage(Image *const image)
460
{
461
    if (mImage != nullptr)
462
        mImage->decRef();
463
    mImage = image;
464
    adjustSize();
465
}
466
467
664
const std::string &Tab::getCaption() const
468
{
469
1328
    return mLabel->getCaption();
470
}
471
472
void Tab::mouseEntered(MouseEvent& event A_UNUSED)
473
{
474
    mHasMouse = true;
475
}
476
477
void Tab::mouseExited(MouseEvent& event A_UNUSED)
478
{
479
    mHasMouse = false;
480
}
481
482
248
void Tab::finalCleanup()
483
{
484
1240
    for (int f = 0; f < TAB_COUNT; f ++)
485
    {
486
992
        tabImg[f] = nullptr;
487
    }
488

254
}