GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/shoplistbox.cpp Lines: 28 120 23.3 %
Date: 2021-03-17 Branches: 8 104 7.7 %

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-2019  The ManaPlus Developers
6
 *  Copyright (C) 2019-2021  Andrei Karas
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "gui/widgets/shoplistbox.h"
25
26
#include "dragdrop.h"
27
#include "settings.h"
28
29
#include "being/playerinfo.h"
30
31
#include "gui/viewport.h"
32
33
#include "gui/fonts/font.h"
34
35
#include "gui/popups/itempopup.h"
36
#include "gui/popups/popupmenu.h"
37
38
#include "gui/models/shopitems.h"
39
40
#include "gui/windows/itemamountwindow.h"
41
42
#include "net/net.h"
43
44
#include "resources/inventory/inventory.h"
45
46
#include "resources/item/shopitem.h"
47
48
#include "debug.h"
49
50
const int ITEM_ICON_SIZE = 32;
51
52
ShopListBox::ShopListBox(const Widget2 *const widget,
53
                         ListModel *const listModel,
54
                         const ShopListBoxTypeT type) :
55
    ListBox(widget, listModel, "shoplistbox.xml"),
56
    mPlayerMoney(0),
57
    mShopItems(nullptr),
58
    mWarningColor(getThemeColor(ThemeColorId::SHOP_WARNING, 255U)),
59
    mType(type),
60
    mPriceCheck(true),
61
    mProtectItems(false)
62
{
63
    mRowHeight = getFont()->getHeight();
64
    mHighlightColor = getThemeColor(ThemeColorId::HIGHLIGHT, 255U);
65
    mForegroundColor = getThemeColor(ThemeColorId::LISTBOX, 255U);
66
    mBackgroundColor = getThemeColor(ThemeColorId::BACKGROUND, 255U);
67
}
68
69
10
ShopListBox::ShopListBox(const Widget2 *const widget,
70
                         ListModel *const listModel,
71
                         ShopItems *const shopListModel,
72
10
                         const ShopListBoxTypeT type) :
73
    ListBox(widget, listModel, "shoplistbox.xml"),
74
    mPlayerMoney(0),
75
    mShopItems(shopListModel),
76
20
    mWarningColor(getThemeColor(ThemeColorId::SHOP_WARNING, 255U)),
77
    mType(type),
78
    mPriceCheck(true),
79
50
    mProtectItems(false)
80
{
81

20
    mRowHeight = std::max(getFont()->getHeight(), ITEM_ICON_SIZE);
82
20
    mHighlightColor = getThemeColor(ThemeColorId::HIGHLIGHT, 255U);
83
20
    mForegroundColor = getThemeColor(ThemeColorId::LISTBOX, 255U);
84
20
    mBackgroundColor = getThemeColor(ThemeColorId::BACKGROUND, 255U);
85
10
}
86
87
void ShopListBox::setPlayersMoney(const int money)
88
{
89
    mPlayerMoney = money;
90
}
91
92
8
void ShopListBox::draw(Graphics *const graphics)
93
{
94
    BLOCK_START("ShopListBox::draw")
95

8
    if ((mListModel == nullptr) || (mShopItems == nullptr))
96
    {
97
        BLOCK_END("ShopListBox::draw")
98
        return;
99
    }
100
101
8
    if (settings.guiAlpha != mAlpha)
102
        mAlpha = settings.guiAlpha;
103
104
8
    const unsigned int alpha = CAST_U32(mAlpha * 255.0F);
105
8
    Font *const font = getFont();
106
107
8
    const int sz = mListModel->getNumberOfElements();
108
8
    const int fontHeigh = getFont()->getHeight();
109
8
    const int width = mDimension.width - 2 * mPadding;
110
    // Draw the list elements
111
8
    for (int i = 0, y = 0;
112
8
         i < sz;
113
         ++i, y += mRowHeight)
114
    {
115
        bool needDraw(false);
116
        Color temp;
117
        Color* backgroundColor = &mBackgroundColor;
118
119
        ShopItem *const item = mShopItems->at(i);
120
        if ((item != nullptr) &&
121
            (item->getDisabled() ||
122
            (mPlayerMoney < item->getPrice() && mPriceCheck) ||
123
            (mProtectItems && PlayerInfo::isItemProtected(item->getId()))))
124
        {
125
            if (i != mSelected)
126
            {
127
                backgroundColor = &mWarningColor;
128
                backgroundColor->a = alpha;
129
            }
130
            else
131
            {
132
                temp = mWarningColor;
133
                temp.r = (temp.r + mHighlightColor.r) / 2;
134
                temp.g = (temp.g + mHighlightColor.g) / 2;
135
                temp.b = (temp.b + mHighlightColor.b) / 2;
136
                temp.a = alpha;
137
                backgroundColor = &temp;
138
            }
139
            needDraw = true;
140
        }
141
        else if (i == mSelected)
142
        {
143
            mHighlightColor.a = alpha;
144
            backgroundColor = &mHighlightColor;
145
            needDraw = true;
146
        }
147
        else
148
        {
149
            mBackgroundColor.a = alpha;
150
        }
151
152
        if (needDraw)
153
        {
154
            graphics->setColor(*backgroundColor);
155
            graphics->fillRectangle(Rect(mPadding, y + mPadding,
156
                width, mRowHeight));
157
        }
158
159
        if ((mShopItems != nullptr) && (item != nullptr))
160
        {
161
            Image *const icon = item->getImage();
162
            if (icon != nullptr)
163
            {
164
                icon->setAlpha(1.0F);
165
                graphics->drawImage(icon, mPadding, y + mPadding);
166
            }
167
        }
168
        if (mSelected == i)
169
        {
170
            font->drawString(graphics,
171
                mForegroundSelectedColor,
172
                mForegroundSelectedColor2,
173
                mListModel->getElementAt(i),
174
                ITEM_ICON_SIZE + mPadding,
175
                y + (ITEM_ICON_SIZE - fontHeigh) / 2 + mPadding);
176
        }
177
        else
178
        {
179
            font->drawString(graphics,
180
                mForegroundColor,
181
                mForegroundColor2,
182
                mListModel->getElementAt(i),
183
                ITEM_ICON_SIZE + mPadding,
184
                y + (ITEM_ICON_SIZE - fontHeigh) / 2 + mPadding);
185
        }
186
    }
187
    BLOCK_END("ShopListBox::draw")
188
}
189
190
void ShopListBox::safeDraw(Graphics *const graphics)
191
{
192
    ShopListBox::draw(graphics);
193
}
194
195
10
void ShopListBox::adjustSize()
196
{
197
    BLOCK_START("ShopListBox::adjustSize")
198
10
    if (mListModel != nullptr)
199
    {
200
20
        setHeight(mRowHeight * mListModel->getNumberOfElements()
201
20
            + 2 * mPadding);
202
    }
203
    BLOCK_END("ShopListBox::adjustSize")
204
10
}
205
206
6
void ShopListBox::setPriceCheck(const bool check)
207
{
208
6
    mPriceCheck = check;
209
6
}
210
211
void ShopListBox::mouseMoved(MouseEvent &event)
212
{
213
    if ((itemPopup == nullptr) || (mRowHeight == 0U))
214
        return;
215
216
    if (mShopItems == nullptr)
217
    {
218
        itemPopup->hide();
219
        return;
220
    }
221
222
    const int index = (event.getY() - mPadding) / mRowHeight;
223
224
    if (index < 0 || index >= mShopItems->getNumberOfElements())
225
    {
226
        itemPopup->hide();
227
    }
228
    else
229
    {
230
        const Item *const item = mShopItems->at(index);
231
        if (item != nullptr)
232
        {
233
            itemPopup->setItem(item, false);
234
            itemPopup->position(viewport->mMouseX, viewport->mMouseY);
235
        }
236
        else
237
        {
238
            itemPopup->setVisible(Visible_false);
239
        }
240
    }
241
}
242
243
void ShopListBox::mouseReleased(MouseEvent& event)
244
{
245
    ListBox::mouseReleased(event);
246
    if (event.getType() == MouseEventType::RELEASED2)
247
    {
248
        if (dragDrop.isEmpty())
249
            return;
250
        const DragDropSourceT src = dragDrop.getSource();
251
        if (mType != ShopListBoxType::SellShop &&
252
            mType != ShopListBoxType::BuyShop)
253
        {
254
            return;
255
        }
256
        if (mType == ShopListBoxType::SellShop &&
257
            Net::getNetworkType() != ServerType::TMWATHENA &&
258
            src != DragDropSource::Cart)
259
        {
260
            return;
261
        }
262
        Inventory *inventory;
263
        if (src == DragDropSource::Inventory)
264
            inventory = PlayerInfo::getInventory();
265
        else if (src == DragDropSource::Cart)
266
            inventory = PlayerInfo::getCartInventory();
267
        else
268
            return;
269
        if (inventory == nullptr)
270
            return;
271
        Item *const item = inventory->getItem(dragDrop.getTag());
272
        if (mType == ShopListBoxType::BuyShop)
273
        {
274
            ItemAmountWindow::showWindow(
275
                ItemAmountWindowUsage::ShopBuyAdd,
276
                nullptr,
277
                item,
278
                0,
279
                0);
280
        }
281
        else
282
        {
283
            ItemAmountWindow::showWindow(
284
                ItemAmountWindowUsage::ShopSellAdd,
285
                nullptr,
286
                item,
287
                0,
288
                0);
289
        }
290
    }
291
292
    if (event.getButton() == MouseButton::RIGHT)
293
    {
294
        setSelected(std::max(0, getSelectionByMouse(event.getY())));
295
296
        if (mSelected < 0 || mSelected >= mShopItems->getNumberOfElements())
297
            return;
298
299
        Item *const item = mShopItems->at(mSelected);
300
        if ((popupMenu != nullptr) && (viewport != nullptr))
301
        {
302
            popupMenu->showItemPopup(viewport->mMouseX,
303
            viewport->mMouseY,
304
            item);
305
        }
306
    }
307
}
308
309
void ShopListBox::mouseExited(MouseEvent& event A_UNUSED)
310
{
311
    if (itemPopup == nullptr)
312
        return;
313
314
    itemPopup->hide();
315
2
}