GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/selldialog.cpp Lines: 103 198 52.0 %
Date: 2021-03-17 Branches: 48 168 28.6 %

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/selldialog.h"
25
26
#include "const/resources/currency.h"
27
28
#include "enums/gui/layouttype.h"
29
30
#include "gui/windows/setupwindow.h"
31
32
#include "gui/models/shopitems.h"
33
34
#include "gui/widgets/button.h"
35
#include "gui/widgets/containerplacer.h"
36
#include "gui/widgets/createwidget.h"
37
#include "gui/widgets/label.h"
38
#include "gui/widgets/layout.h"
39
#include "gui/widgets/scrollarea.h"
40
#include "gui/widgets/shoplistbox.h"
41
#include "gui/widgets/slider.h"
42
43
#include "utils/delete2.h"
44
#include "utils/foreach.h"
45
#include "utils/gettext.h"
46
#include "utils/stringutils.h"
47
48
#include "resources/db/unitsdb.h"
49
50
#include "resources/item/shopitem.h"
51
52
#include "debug.h"
53
54
1
SellDialog::DialogList SellDialog::instances;
55
56
4
SellDialog::SellDialog(const IsSell isSell,
57
4
                       const Advanced advanced) :
58
    // TRANSLATORS: sell dialog name
59
4
    Window(_("Sell"), Modal_false, nullptr, "sell.xml"),
60
    ActionListener(),
61
    SelectionListener(),
62
    mSellButton(nullptr),
63
    mQuitButton(nullptr),
64
    mConfirmButton(nullptr),
65
    mAddMaxButton(nullptr),
66
    mIncreaseButton(nullptr),
67
    mDecreaseButton(nullptr),
68
    mShopItemList(nullptr),
69
    mScrollArea(nullptr),
70
    mMoneyLabel(nullptr),
71
    mQuantityLabel(nullptr),
72
    mSlider(nullptr),
73
    mShopItems(nullptr),
74
    mPlayerMoney(0),
75
    mMaxItems(0),
76
    mAmountItems(0),
77
    mIsSell(isSell),
78

36
    mAdvanced(advanced)
79
{
80
4
}
81
82
4
void SellDialog::postInit()
83
{
84
4
    Window::postInit();
85
16
    setWindowName("Sell");
86
4
    setResizable(true);
87
4
    setCloseButton(true);
88
4
    setStickyButtonLock(true);
89
4
    setMinWidth(260);
90
4
    setMinHeight(220);
91
4
    setDefaultSize(260, 230, ImagePosition::CENTER, 0, 0);
92
93
4
    if (setupWindow != nullptr)
94
        setupWindow->registerWindowForReset(this);
95
96
    // Create a ShopItems instance, that is aware of duplicate entries.
97
4
    mShopItems = new ShopItems(true,
98
4
        DEFAULT_CURRENCY);
99
100
4
    if (mAdvanced == Advanced_true)
101
1
        mShopItems->setMergeDuplicates(false);
102
103
4
    mShopItemList = CREATEWIDGETR(ShopListBox,
104
        this,
105
        mShopItems,
106
        mShopItems,
107
        ShopListBoxType::Unknown);
108
8
    mShopItemList->setProtectItems(true);
109
8
    mScrollArea = new ScrollArea(this, mShopItemList,
110

12
        fromBool(getOptionBool("showbackground", false), Opaque),
111

20
        "sell_background.xml");
112
4
    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
113
114
4
    mSellButton = new Button(this,
115
        // TRANSLATORS: sell dialog button
116
4
        mAdvanced == Advanced_true ? _("Add") : _("Sell"),
117
        "presell",
118
        BUTTON_SKIN,
119


24
        this);
120
4
    mQuitButton = new Button(this,
121
        // TRANSLATORS: sell dialog button
122
4
        _("Quit"),
123
        "quit",
124
        BUTTON_SKIN,
125

24
        this);
126
127
4
    initButtons();
128
129
8
    mSellButton->setEnabled(false);
130
131
8
    mShopItemList->setDistributeMousePressed(false);
132
4
    mShopItemList->setPriceCheck(false);
133
4
    mShopItemList->addSelectionListener(this);
134
16
    mShopItemList->setActionEventId("sell");
135
4
    mShopItemList->addActionListener(this);
136
137
4
    ContainerPlacer placer(nullptr, nullptr);
138
4
    placer = getPlacer(0, 0);
139
140
4
    if (mIsSell == IsSell_true)
141
    {
142
2
        mIncreaseButton = new Button(this,
143
            // TRANSLATORS: sell dialog button
144
2
            _("+"),
145
            "inc",
146
            BUTTON_SKIN,
147

12
            this);
148
2
        mDecreaseButton = new Button(this,
149
            // TRANSLATORS: sell dialog button
150
2
            _("-"),
151
            "dec",
152
            BUTTON_SKIN,
153

12
            this);
154
2
        mAddMaxButton = new Button(this,
155
            // TRANSLATORS: sell dialog button
156
2
            _("Max"),
157
            "max",
158
            BUTTON_SKIN,
159

12
            this);
160
2
        mSlider = new Slider(this, 1.0, 1.0);
161
162
6
        mQuantityLabel = new Label(this, strprintf(
163

2
            "%d / %d", mAmountItems, mMaxItems));
164
4
        mQuantityLabel->setAlignment(Graphics::CENTER);
165
        // TRANSLATORS: sell dialog label
166
6
        mMoneyLabel = new Label(this, strprintf(_("Price: %s / Total: %s"),
167

2
            "", ""));
168
2
        if (mAdvanced == Advanced_true)
169
        {
170
1
            mConfirmButton = new Button(this,
171
                // TRANSLATORS: sell dialog button
172
1
                _("Sell"),
173
                "confirm",
174
                BUTTON_SKIN,
175

6
                this);
176
1
            mConfirmButton->setEnabled(false);
177
        }
178
179
2
        mDecreaseButton->adjustSize();
180
4
        mDecreaseButton->setWidth(mIncreaseButton->getWidth());
181
4
        mIncreaseButton->setEnabled(false);
182
4
        mDecreaseButton->setEnabled(false);
183
4
        mSlider->setEnabled(false);
184
8
        mSlider->setActionEventId("slider");
185
2
        mSlider->addActionListener(this);
186
187
4
        placer(0, 0, mScrollArea, 8, 5).setPadding(3);
188
2
        placer(0, 5, mDecreaseButton, 1, 1);
189
2
        placer(1, 5, mSlider, 3, 1);
190
2
        placer(4, 5, mIncreaseButton, 1, 1);
191
2
        placer(5, 5, mQuantityLabel, 2, 1);
192
2
        placer(7, 5, mAddMaxButton, 1, 1);
193
2
        placer(0, 6, mMoneyLabel, 8, 1);
194
2
        if (mAdvanced == Advanced_true)
195
        {
196
1
            placer(5, 7, mSellButton, 1, 1);
197
1
            placer(6, 7, mConfirmButton, 1, 1);
198
        }
199
        else
200
        {
201
1
            placer(6, 7, mSellButton, 1, 1);
202
        }
203
2
        placer(7, 7, mQuitButton, 1, 1);
204
    }
205
    else
206
    {
207
4
        placer(0, 0, mScrollArea, 8, 5).setPadding(3);
208
2
        placer(6, 5, mSellButton, 1, 1);
209
2
        placer(7, 5, mQuitButton, 1, 1);
210
    }
211
212
4
    Layout &layout = getLayout();
213
4
    layout.setRowHeight(0, LayoutType::SET);
214
215
4
    center();
216
4
    loadWindowState();
217
218
8
    instances.push_back(this);
219
4
    setVisible(Visible_true);
220
8
    enableVisibleSound(true);
221
4
}
222
223
16
SellDialog::~SellDialog()
224
{
225
4
    delete2(mShopItems)
226
4
    instances.remove(this);
227
4
}
228
229
void SellDialog::reset()
230
{
231
    mShopItems->clear();
232
    if (mSlider != nullptr)
233
        mSlider->setValue(0);
234
    mShopItemList->setSelected(-1);
235
    updateButtonsAndLabels();
236
}
237
238
void SellDialog::addItem(const Item *const item, const int price)
239
{
240
    if (item == nullptr)
241
        return;
242
243
    mShopItems->addItem2(item->getInvIndex(),
244
        item->getId(),
245
        item->getType(),
246
        item->getColor(),
247
        item->getQuantity(),
248
        price);
249
250
    mShopItemList->adjustSize();
251
}
252
253
ShopItem *SellDialog::addItem(const int id,
254
                              const ItemTypeT type,
255
                              const ItemColor color,
256
                              const int amount,
257
                              const int price)
258
{
259
    ShopItem *const item = mShopItems->addItem(id,
260
        type,
261
        color,
262
        amount,
263
        price);
264
    mShopItemList->adjustSize();
265
    return item;
266
}
267
268
269
void SellDialog::action(const ActionEvent &event)
270
{
271
    const std::string &eventId = event.getId();
272
273
    if (eventId == "quit")
274
    {
275
        close();
276
        return;
277
    }
278
279
    const int selectedItem = mShopItemList->getSelected();
280
281
    // The following actions require a valid item selection
282
    if (selectedItem == -1
283
        || selectedItem >= mShopItems->getNumberOfElements())
284
    {
285
        return;
286
    }
287
288
    if (eventId == "slider")
289
    {
290
        if (mSlider != nullptr)
291
        {
292
            mAmountItems = CAST_S32(mSlider->getValue());
293
            updateButtonsAndLabels();
294
        }
295
    }
296
    else if (eventId == "inc" &&
297
             mSlider != nullptr &&
298
             mAmountItems < mMaxItems)
299
    {
300
        mAmountItems++;
301
        mSlider->setValue(mAmountItems);
302
        updateButtonsAndLabels();
303
    }
304
    else if (eventId == "dec" &&
305
             mSlider != nullptr &&
306
             mAmountItems > 1)
307
    {
308
        mAmountItems--;
309
        mSlider->setValue(mAmountItems);
310
        updateButtonsAndLabels();
311
    }
312
    else if (eventId == "max" &&
313
             mSlider != nullptr)
314
    {
315
        mAmountItems = mMaxItems;
316
        mSlider->setValue(mAmountItems);
317
        updateButtonsAndLabels();
318
    }
319
    else if (eventId == "presell" ||
320
             eventId == "sell" ||
321
             eventId == "yes" ||
322
             eventId == "confirm")
323
    {
324
        sellAction(event);
325
    }
326
}
327
328
void SellDialog::valueChanged(const SelectionEvent &event A_UNUSED)
329
{
330
    // Reset amount of items and update labels
331
    mAmountItems = 1;
332
    if (mSlider != nullptr)
333
    {
334
        mSlider->setValue(0);
335
        mSlider->setScale(1, mMaxItems);
336
    }
337
    updateButtonsAndLabels();
338
}
339
340
void SellDialog::setMoney(const int amount)
341
{
342
    mPlayerMoney = amount;
343
    mShopItemList->setPlayersMoney(amount);
344
}
345
346
void SellDialog::updateButtonsAndLabels()
347
{
348
    const int selectedItem = mShopItemList->getSelected();
349
    int income = 0;
350
    ShopItem *item = nullptr;
351
352
    if (selectedItem > -1 && (mShopItems->at(selectedItem) != nullptr))
353
    {
354
        item = mShopItems->at(selectedItem);
355
        if (item != nullptr)
356
        {
357
            mMaxItems = item->getQuantity();
358
            if (mAmountItems > mMaxItems)
359
                mAmountItems = mMaxItems;
360
            income = mAmountItems * mShopItems->at(selectedItem)->getPrice();
361
        }
362
        else
363
        {
364
            mMaxItems = 0;
365
            mAmountItems = 0;
366
        }
367
    }
368
    else
369
    {
370
        mMaxItems = 0;
371
        mAmountItems = 0;
372
    }
373
374
    // Update Buttons and slider
375
    mSellButton->setEnabled(mAmountItems > 0);
376
    if (mDecreaseButton != nullptr)
377
        mDecreaseButton->setEnabled(mAmountItems > 1);
378
    if (mIncreaseButton != nullptr)
379
        mIncreaseButton->setEnabled(mAmountItems < mMaxItems);
380
    if (mSlider != nullptr)
381
        mSlider->setEnabled(mMaxItems > 1);
382
383
    if (mQuantityLabel != nullptr)
384
    {
385
        // Update the quantity and money labels
386
        mQuantityLabel->setCaption(strprintf("%d / %d",
387
            mAmountItems, mMaxItems));
388
    }
389
    if (mMoneyLabel != nullptr)
390
    {
391
        // TRANSLATORS: sell dialog label
392
        mMoneyLabel->setCaption(strprintf(_("Price: %s / Total: %s"),
393
            UnitsDb::formatCurrency(income).c_str(),
394
            UnitsDb::formatCurrency(mPlayerMoney + income).c_str()));
395
    }
396
    if (item != nullptr)
397
        item->update();
398
}
399
400
4
void SellDialog::setVisible(Visible visible)
401
{
402
4
    Window::setVisible(visible);
403
404
4
    if (visible == Visible_true)
405
    {
406
4
        if (mShopItemList != nullptr)
407
4
            mShopItemList->requestFocus();
408
    }
409
    else
410
    {
411
        scheduleDelete();
412
    }
413
4
}
414
415
void SellDialog::closeAll()
416
{
417
    FOR_EACH (DialogList::const_iterator, it, instances)
418
        (*it)->close();
419

3
}