GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/skilllistbox.h Lines: 0 114 0.0 %
Date: 2017-11-29 Branches: 0 88 0.0 %

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
#ifndef GUI_WIDGETS_SKILLLISTBOX_H
24
#define GUI_WIDGETS_SKILLLISTBOX_H
25
26
#include "const/resources/skill.h"
27
28
#include "dragdrop.h"
29
30
#include "gui/skin.h"
31
#include "gui/viewport.h"
32
33
#include "gui/widgets/listbox.h"
34
35
#include "gui/fonts/font.h"
36
37
#include "gui/models/skillmodel.h"
38
39
#include "gui/popups/popupmenu.h"
40
#include "gui/popups/skillpopup.h"
41
42
#include "utils/delete2.h"
43
44
#include "render/graphics.h"
45
46
#include "localconsts.h"
47
48
class SkillModel;
49
50
class SkillListBox final : public ListBox
51
{
52
    public:
53
        SkillListBox(const Widget2 *const widget,
54
                     SkillModel *const model) :
55
            ListBox(widget, model, "skilllistbox.xml"),
56
            mModel(model),
57
            mTextColor(getThemeColor(ThemeColorId::TEXT)),
58
            mTextColor2(getThemeColor(ThemeColorId::TEXT_OUTLINE)),
59
            mCooldownColor(getThemeColor(ThemeColorId::SKILL_COOLDOWN)),
60
            mTextPadding(mSkin != nullptr ?
61
                mSkin->getOption("textPadding", 34) : 34),
62
            mSpacing(mSkin != nullptr ? mSkin->getOption("spacing", 0) : 0),
63
            mSkillClicked(false)
64
        {
65
            mRowHeight = getFont()->getHeight() * 2 + mSpacing + 2 * mPadding;
66
            mHighlightColor = getThemeColor(ThemeColorId::HIGHLIGHT);
67
68
            if (mRowHeight < 34)
69
                mRowHeight = 34;
70
        }
71
72
        A_DELETE_COPY(SkillListBox)
73
74
        ~SkillListBox()
75
        {
76
            delete2(mModel)
77
        }
78
79
        SkillInfo *getSelectedInfo() const
80
        {
81
            const int selected = getSelected();
82
            if ((mListModel == nullptr) || selected < 0
83
                || selected > mListModel->getNumberOfElements())
84
            {
85
                return nullptr;
86
            }
87
88
            return static_cast<SkillModel*>(mListModel)->getSkillAt(selected);
89
        }
90
91
        void draw(Graphics *const graphics) override final A_NONNULL(2)
92
        {
93
            if (mListModel == nullptr)
94
                return;
95
96
            SkillModel *const model = static_cast<SkillModel*>(mListModel);
97
            updateAlpha();
98
99
            mHighlightColor.a = CAST_S32(mAlpha * 255.0F);
100
            graphics->setColor(mHighlightColor);
101
102
            const int width1 = getWidth();
103
            const int usableWidth = width1 - 2 * mPadding;
104
105
            // Draw filled rectangle around the selected list element
106
            if (mSelected >= 0)
107
            {
108
                graphics->fillRectangle(Rect(mPadding, getRowHeight()
109
                    * mSelected + mPadding, usableWidth,
110
                    getRowHeight()));
111
            }
112
113
            // Draw the list elements
114
            Font *const font = getFont();
115
            const int space = font->getHeight() + mSpacing;
116
            const int width2 = width1 - mPadding;
117
118
            graphics->setColor(mCooldownColor);
119
            for (int i = 0, y = 1 + mPadding;
120
                 i < model->getNumberOfElements();
121
                 ++i, y += getRowHeight())
122
            {
123
                SkillInfo *const e = model->getSkillAt(i);
124
                if (e != nullptr)
125
                {
126
                    if (e->cooldown != 0)
127
                    {
128
                        graphics->fillRectangle(Rect(mPadding, y,
129
                            usableWidth * 100 / e->cooldown, 10));
130
                    }
131
                }
132
            }
133
134
            for (int i = 0, y = 1 + mPadding;
135
                 i < model->getNumberOfElements();
136
                 ++i, y += getRowHeight())
137
            {
138
                SkillInfo *const e = model->getSkillAt(i);
139
                if (e != nullptr)
140
                {
141
                    const SkillData *const data = e->data;
142
                    const std::string &description = data->description;
143
                    graphics->drawImage(data->icon, mPadding, y);
144
                    font->drawString(graphics,
145
                        mTextColor,
146
                        mTextColor2,
147
                        data->name,
148
                        mTextPadding, y);
149
                    if (!description.empty())
150
                    {
151
                        font->drawString(graphics,
152
                            mTextColor,
153
                            mTextColor2,
154
                            description,
155
                            mTextPadding,
156
                            y + space);
157
                    }
158
159
                    if (e->skillLevelWidth < 0)
160
                    {
161
                        // Add one for padding
162
                        e->skillLevelWidth = font->getWidth(e->skillLevel) + 1;
163
                    }
164
165
                    font->drawString(graphics,
166
                        mTextColor,
167
                        mTextColor2,
168
                        e->skillLevel,
169
                        width2 - e->skillLevelWidth,
170
                        y);
171
                }
172
            }
173
        }
174
175
        void safeDraw(Graphics *const graphics) override final A_NONNULL(2)
176
        {
177
            SkillListBox::draw(graphics);
178
        }
179
180
        unsigned int getRowHeight() const override final
181
        { return mRowHeight; }
182
183
        const SkillInfo *getSkillByEvent(const MouseEvent &event) const
184
        {
185
            const int y = (event.getY() + mPadding) / getRowHeight();
186
            if (mModel == nullptr || y >= mModel->getNumberOfElements())
187
                return nullptr;
188
            const SkillInfo *const skill = mModel->getSkillAt(y);
189
            if (skill == nullptr)
190
                return nullptr;
191
            return skill;
192
        }
193
194
        void mouseMoved(MouseEvent &event) override final
195
        {
196
            ListBox::mouseMoved(event);
197
            if ((viewport == nullptr) || !dragDrop.isEmpty())
198
                return;
199
200
            const SkillInfo *const skill = getSkillByEvent(event);
201
            if (skill == nullptr)
202
                return;
203
            skillPopup->show(skill,
204
                skill->customSelectedLevel,
205
                skill->customCastType,
206
                skill->customOffsetX,
207
                skill->customOffsetY);
208
            skillPopup->position(viewport->mMouseX,
209
                viewport->mMouseY);
210
        }
211
212
        void mouseDragged(MouseEvent &event) override final
213
        {
214
            if (event.getButton() == MouseButton::LEFT)
215
            {
216
                if (dragDrop.isEmpty())
217
                {
218
                    if (mSkillClicked)
219
                    {
220
                        mSkillClicked = false;
221
                        const SkillInfo *const skill = getSkillByEvent(event);
222
                        if (skill == nullptr)
223
                            return;
224
                        dragDrop.dragSkill(skill, DragDropSource::Skills);
225
                        dragDrop.setItem(skill->id + SKILL_MIN_ID);
226
                        dragDrop.setItemData(skill->toDataStr());
227
                    }
228
                    ListBox::mouseDragged(event);
229
                }
230
            }
231
            else
232
            {
233
                ListBox::mouseDragged(event);
234
            }
235
        }
236
237
        void mousePressed(MouseEvent &event) override final
238
        {
239
            ListBox::mousePressed(event);
240
            const MouseButtonT button = event.getButton();
241
            if (button == MouseButton::LEFT ||
242
                button == MouseButton::RIGHT)
243
            {
244
                const SkillInfo *const skill = getSkillByEvent(event);
245
                if (skill == nullptr)
246
                    return;
247
                event.consume();
248
                mSkillClicked = true;
249
                SkillModel *const model = static_cast<SkillModel*>(
250
                    mListModel);
251
                if ((model != nullptr) &&
252
                    mSelected >= 0 &&
253
                    model->getSkillAt(mSelected) == skill)
254
                {
255
                    skillPopup->hide();
256
                    if (button == MouseButton::LEFT &&
257
                        event.getX() >
258
                        getWidth() - mPadding - skill->skillLevelWidth)
259
                    {
260
                        popupMenu->showSkillLevelPopup(skill);
261
                    }
262
                    else if (button == MouseButton::RIGHT)
263
                    {
264
                        popupMenu->showSkillPopup(skill);
265
                    }
266
                }
267
            }
268
        }
269
270
        void mouseReleased(MouseEvent &event) override final
271
        {
272
            ListBox::mouseReleased(event);
273
        }
274
275
        void mouseExited(MouseEvent &event A_UNUSED) override final
276
        {
277
            skillPopup->hide();
278
        }
279
280
    private:
281
        SkillModel *mModel;
282
        Color mTextColor;
283
        Color mTextColor2;
284
        Color mCooldownColor;
285
        int mTextPadding;
286
        int mSpacing;
287
        bool mSkillClicked;
288
};
289
290
#endif  // GUI_WIDGETS_SKILLLISTBOX_H