GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/windows/buydialog.cpp Lines: 139 365 38.1 %
Date: 2018-09-20 Branches: 103 440 23.4 %

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-2018  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
#include "gui/windows/buydialog.h"
24
25
#include "actormanager.h"
26
#include "configuration.h"
27
28
#include "being/being.h"
29
30
#include "enums/gui/layouttype.h"
31
32
#include "gui/windows/setupwindow.h"
33
#ifdef TMWA_SUPPORT
34
#include "gui/windows/tradewindow.h"
35
#endif  // TMWA_SUPPORT
36
37
#include "gui/models/shopitems.h"
38
#include "gui/models/sortlistmodelbuy.h"
39
40
#include "gui/widgets/button.h"
41
#include "gui/widgets/containerplacer.h"
42
#include "gui/widgets/createwidget.h"
43
#include "gui/widgets/dropdown.h"
44
#include "gui/widgets/inttextfield.h"
45
#include "gui/widgets/label.h"
46
#include "gui/widgets/layout.h"
47
#include "gui/widgets/scrollarea.h"
48
#include "gui/widgets/shoplistbox.h"
49
#include "gui/widgets/slider.h"
50
51
#include "net/adminhandler.h"
52
#include "net/buysellhandler.h"
53
#include "net/cashshophandler.h"
54
#include "net/markethandler.h"
55
#include "net/net.h"
56
#include "net/vendinghandler.h"
57
#include "net/npchandler.h"
58
59
#include "resources/iteminfo.h"
60
61
#include "resources/db/unitsdb.h"
62
63
#include "utils/delete2.h"
64
#include "utils/foreach.h"
65
66
#include <algorithm>
67
68
#include "debug.h"
69
70
namespace
71
{
72
    class SortItemPriceFunctor final
73
    {
74
        public:
75
            A_DEFAULT_COPY(SortItemPriceFunctor)
76
77
            bool operator() (const ShopItem *const item1,
78
                             const ShopItem *const item2) const
79
            {
80
                if ((item1 == nullptr) || (item2 == nullptr))
81
                    return false;
82
83
                const int price1 = item1->getPrice();
84
                const int price2 = item2->getPrice();
85
                if (price1 == price2)
86
                    return item1->getDisplayName() < item2->getDisplayName();
87
                return price1 < price2;
88
            }
89
    } itemPriceBuySorter;
90
91
    class SortItemNameFunctor final
92
    {
93
        public:
94
            A_DEFAULT_COPY(SortItemNameFunctor)
95
96
            bool operator() (const ShopItem *const item1,
97
                             const ShopItem *const item2) const
98
            {
99
                if ((item1 == nullptr) || (item2 == nullptr))
100
                    return false;
101
102
                const std::string &name1 = item1->getDisplayName();
103
                const std::string &name2 = item2->getDisplayName();
104
                if (name1 == name2)
105
                    return item1->getPrice() < item2->getPrice();
106
                return name1 < name2;
107
            }
108
    } itemNameBuySorter;
109
110
    class SortItemIdFunctor final
111
    {
112
        public:
113
            A_DEFAULT_COPY(SortItemIdFunctor)
114
115
            bool operator() (const ShopItem *const item1,
116
                             const ShopItem *const item2) const
117
            {
118
                if ((item1 == nullptr) || (item2 == nullptr))
119
                    return false;
120
121
                const int id1 = item1->getId();
122
                const int id2 = item2->getId();
123
                if (id1 == id2)
124
                    return item1->getPrice() < item2->getPrice();
125
                return id1 < id2;
126
            }
127
    } itemIdBuySorter;
128
129
    class SortItemWeightFunctor final
130
    {
131
        public:
132
            A_DEFAULT_COPY(SortItemWeightFunctor)
133
134
            bool operator() (const ShopItem *const item1,
135
                             const ShopItem *const item2) const
136
            {
137
                if ((item1 == nullptr) || (item2 == nullptr))
138
                    return false;
139
140
                const int weight1 = item1->getInfo().getWeight();
141
                const int weight2 = item2->getInfo().getWeight();
142
                if (weight1 == weight2)
143
                    return item1->getPrice() < item2->getPrice();
144
                return weight1 < weight2;
145
            }
146
    } itemWeightBuySorter;
147
148
    class SortItemAmountFunctor final
149
    {
150
        public:
151
            A_DEFAULT_COPY(SortItemAmountFunctor)
152
153
            bool operator() (const ShopItem *const item1,
154
                             const ShopItem *const item2) const
155
            {
156
                if ((item1 == nullptr) || (item2 == nullptr))
157
                    return false;
158
159
                const int amount1 = item1->getQuantity();
160
                const int amount2 = item2->getQuantity();
161
                if (amount1 == amount2)
162
                    return item1->getPrice() < item2->getPrice();
163
                return amount1 < amount2;
164
            }
165
    } itemAmountBuySorter;
166
167
    class SortItemTypeFunctor final
168
    {
169
        public:
170
            A_DEFAULT_COPY(SortItemTypeFunctor)
171
172
            bool operator() (const ShopItem *const item1,
173
                             const ShopItem *const item2) const
174
            {
175
                if ((item1 == nullptr) || (item2 == nullptr))
176
                    return false;
177
178
                const ItemDbTypeT type1 = item1->getInfo().getType();
179
                const ItemDbTypeT type2 = item2->getInfo().getType();
180
                if (type1 == type2)
181
                    return item1->getPrice() < item2->getPrice();
182
                return type1 < type2;
183
            }
184
    } itemTypeBuySorter;
185
}  // namespace
186
187
1
BuyDialog::DialogList BuyDialog::instances;
188
189
1
BuyDialog::BuyDialog() :
190
    // TRANSLATORS: buy dialog name
191
1
    Window(_("Create items"), Modal_false, nullptr, "buy.xml"),
192
    ActionListener(),
193
    SelectionListener(),
194
2
    mSortModel(new SortListModelBuy),
195
1
    mSortDropDown(new DropDown(this, mSortModel, false,
196

2
        Modal_false, this, "sort")),
197
    mFilterTextField(new TextField(this, "", LoseFocusOnTab_true,
198

1
        this, "namefilter", true)),
199
    mFilterLabel(nullptr),
200
    mNick(),
201
    mCurrency(),
202
    mNpcId(fromInt(Items, BeingId)),
203
    mMoney(0),
204
    mAmountItems(0),
205
    mMaxItems(0),
206


23
    mAdvanced(false)
207
{
208
1
    init();
209
1
}
210
211
1
BuyDialog::BuyDialog(const BeingId npcId,
212
1
                     const std::string &currency) :
213
    // TRANSLATORS: buy dialog name
214
1
    Window(_("Buy"), Modal_false, nullptr, "buy.xml"),
215
    ActionListener(),
216
    SelectionListener(),
217
    mSortModel(nullptr),
218
    mSortDropDown(nullptr),
219
    mFilterTextField(new TextField(this, "", LoseFocusOnTab_true,
220

1
        this, "namefilter", true)),
221
    mFilterLabel(nullptr),
222
    mNick(),
223
    mCurrency(currency),
224
    mNpcId(npcId),
225
    mMoney(0),
226
    mAmountItems(0),
227
    mMaxItems(0),
228


18
    mAdvanced(Net::getNetworkType() != ServerType::TMWATHENA)
229
{
230
1
    init();
231
1
}
232
233
#ifdef TMWA_SUPPORT
234
1
BuyDialog::BuyDialog(const std::string &nick,
235
1
                     const std::string &currency) :
236
    // TRANSLATORS: buy dialog name
237
1
    Window(_("Buy"), Modal_false, nullptr, "buy.xml"),
238
    ActionListener(),
239
    SelectionListener(),
240
2
    mSortModel(new SortListModelBuy),
241
1
    mSortDropDown(new DropDown(this, mSortModel, false,
242

2
        Modal_false, this, "sort")),
243
    mFilterTextField(new TextField(this, "", LoseFocusOnTab_true,
244

1
        this, "namefilter", true)),
245
    mFilterLabel(nullptr),
246
    mNick(nick),
247
    mCurrency(currency),
248
    mNpcId(fromInt(Nick, BeingId)),
249
    mMoney(0),
250
    mAmountItems(0),
251
    mMaxItems(0),
252


23
    mAdvanced(false)
253
{
254
1
    init();
255
1
}
256
#endif  // TMWA_SUPPORT
257
258
1
BuyDialog::BuyDialog(const Being *const being,
259
1
                     const std::string &currency) :
260
    // TRANSLATORS: buy dialog name
261
1
    Window(_("Buy"), Modal_false, nullptr, "buy.xml"),
262
    ActionListener(),
263
    SelectionListener(),
264
2
    mSortModel(new SortListModelBuy),
265
1
    mSortDropDown(new DropDown(this, mSortModel, false,
266

2
        Modal_false, this, "sort")),
267
    mFilterTextField(new TextField(this, "", LoseFocusOnTab_true,
268

1
        this, "namefilter", true)),
269
    mFilterLabel(nullptr),
270
1
    mNick(being != nullptr ? being->getName() : std::string()),
271
    mCurrency(currency),
272
    mNpcId(fromInt(Vending, BeingId)),
273
    mMoney(0),
274
    mAmountItems(0),
275
    mMaxItems(0),
276



24
    mAdvanced(true)
277
{
278
1
    init();
279
1
}
280
281
4
void BuyDialog::init()
282
{
283
20
    setWindowName("Buy");
284
4
    setResizable(true);
285
4
    setCloseButton(true);
286
4
    setStickyButtonLock(true);
287
4
    setMinWidth(260);
288
4
    setMinHeight(220);
289
4
    setDefaultSize(260, 230, ImagePosition::CENTER, 0, 0);
290
291
#ifdef TMWA_SUPPORT
292
    // reset advance flag for personal shops
293

6
    if (mAdvanced &&
294
2
        mNpcId == fromInt(Nick, BeingId))
295
    {
296
        mAdvanced = false;
297
    }
298
#endif  // TMWA_SUPPORT
299
300
4
    if (setupWindow != nullptr)
301
        setupWindow->registerWindowForReset(this);
302
303
4
    mShopItems = new ShopItems(false,
304
4
        mCurrency);
305
306
4
    CREATEWIDGETV(mShopItemList, ShopListBox, this,
307
4
        mShopItems, mShopItems, ShopListBoxType::Unknown);
308
8
    mScrollArea = new ScrollArea(this, mShopItemList,
309

16
        fromBool(getOptionBool("showbackground", false), Opaque),
310

20
        "buy_background.xml");
311
4
    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
312
313
4
    mSlider = new Slider(this, 1.0, 1.0);
314
12
    mQuantityLabel = new Label(this, strprintf(
315

4
        "%d / %d", mAmountItems, mMaxItems));
316
8
    mQuantityLabel->setAlignment(Graphics::CENTER);
317
12
    mMoneyLabel = new Label(this, strprintf(
318
        // TRANSLATORS: buy dialog label
319

8
        _("Price: %s / Total: %s"), "", ""));
320
321
4
    mAmountField = new IntTextField(this, 1, 1, 123, Enable_true, 0);
322
20
    mAmountField->setActionEventId("amount");
323
4
    mAmountField->addActionListener(this);
324
8
    mAmountField->setSendAlwaysEvents(true);
325
8
    mAmountField->setEnabled(false);
326
327
    // TRANSLATORS: buy dialog label
328

16
    mAmountLabel = new Label(this, _("Amount:"));
329
4
    mAmountLabel->adjustSize();
330
331
    // TRANSLATORS: This is a narrow symbol used to denote 'increasing'.
332
    // You may change this symbol if your language uses another.
333

28
    mIncreaseButton = new Button(this, _("+"), "inc", BUTTON_SKIN, this);
334
    // TRANSLATORS: This is a narrow symbol used to denote 'decreasing'.
335
    // You may change this symbol if your language uses another.
336

28
    mDecreaseButton = new Button(this, _("-"), "dec", BUTTON_SKIN, this);
337
8
    mBuyButton = new Button(this, mNpcId == fromInt(Items, BeingId)
338
        // TRANSLATORS: buy dialog button
339
3
        ? _("Create") : (mAdvanced ? _("Add") : _("Buy")),
340
        "buy",
341
        BUTTON_SKIN,
342


31
        this);
343
4
    if (mAdvanced)
344
    {
345
2
        mConfirmButton = new Button(this,
346
            // TRANSLATORS: buy dialog button
347
2
            _("Buy"),
348
            "confirm",
349
            BUTTON_SKIN,
350

14
            this);
351
2
        mConfirmButton->setEnabled(false);
352
    }
353
    else
354
    {
355
2
        mConfirmButton = nullptr;
356
    }
357
    // TRANSLATORS: buy dialog button
358

28
    mQuitButton = new Button(this, _("Quit"), "quit", BUTTON_SKIN, this);
359
    // TRANSLATORS: buy dialog button
360

28
    mAddMaxButton = new Button(this, _("Max"), "max", BUTTON_SKIN, this);
361
362
4
    mDecreaseButton->adjustSize();
363
8
    mDecreaseButton->setWidth(mIncreaseButton->getWidth());
364
365
8
    mIncreaseButton->setEnabled(false);
366
8
    mDecreaseButton->setEnabled(false);
367
8
    mBuyButton->setEnabled(false);
368
8
    mSlider->setEnabled(false);
369
370
20
    mSlider->setActionEventId("slider");
371
4
    mSlider->addActionListener(this);
372
373
8
    mShopItemList->setDistributeMousePressed(false);
374
20
    mShopItemList->setActionEventId("buy");
375
4
    mShopItemList->addActionListener(this);
376
4
    mShopItemList->addSelectionListener(this);
377
378
4
    mFilterTextField->setWidth(100);
379
380
4
    ContainerPlacer placer = getPlacer(0, 0);
381
8
    placer(0, 0, mScrollArea, 9, 5).setPadding(3);
382
4
    placer(0, 5, mDecreaseButton, 1, 1);
383
4
    placer(1, 5, mSlider, 4, 1);
384
4
    placer(5, 5, mIncreaseButton, 1, 1);
385
4
    placer(6, 5, mQuantityLabel, 2, 1);
386
4
    placer(8, 5, mAddMaxButton, 1, 1);
387
4
    placer(0, 6, mAmountLabel, 2, 1);
388
4
    placer(2, 6, mAmountField, 2, 1);
389
4
    placer(0, 7, mMoneyLabel, 8, 1);
390
4
    if (mSortDropDown != nullptr)
391
    {
392
3
        placer(0, 8, mSortDropDown, 2, 1);
393
    }
394
    else
395
    {
396
        // TRANSLATORS: buy dialog label
397

4
        mFilterLabel = new Label(this, _("Filter:"));
398
1
        mFilterLabel->adjustSize();
399
1
        placer(0, 8, mFilterLabel, 2, 1);
400
    }
401
4
    placer(2, 8, mFilterTextField, 2, 1);
402
4
    if (mAdvanced)
403
    {
404
2
        placer(6, 8, mBuyButton, 1, 1);
405
2
        placer(7, 8, mConfirmButton, 1, 1);
406
    }
407
    else
408
    {
409
2
        placer(7, 8, mBuyButton, 1, 1);
410
    }
411
4
    placer(8, 8, mQuitButton, 1, 1);
412
413
4
    Layout &layout = getLayout();
414
4
    layout.setRowHeight(0, LayoutType::SET);
415
416
4
    center();
417
4
    loadWindowState();
418
8
    enableVisibleSound(true);
419
420
8
    instances.push_back(this);
421
4
    setVisible(Visible_true);
422
423
4
    if (mSortDropDown != nullptr)
424

12
        mSortDropDown->setSelected(config.getIntValue("buySortOrder"));
425
4
}
426
427
28
BuyDialog::~BuyDialog()
428
{
429
4
    delete2(mShopItems);
430
8
    delete2(mSortModel);
431
4
    instances.remove(this);
432
4
    if (buySellHandler != nullptr)
433
        buySellHandler->cleanDialogReference(this);
434
8
}
435
436
void BuyDialog::setMoney(const int amount)
437
{
438
    mMoney = amount;
439
    mShopItemList->setPlayersMoney(amount);
440
441
    updateButtonsAndLabels();
442
}
443
444
void BuyDialog::reset()
445
{
446
    mShopItems->clear();
447
    mShopItemList->adjustSize();
448
449
    // Reset previous selected items to prevent failing asserts
450
    mShopItemList->setSelected(-1);
451
    mSlider->setValue(0);
452
453
    setMoney(0);
454
}
455
456
ShopItem *BuyDialog::addItem(const int id,
457
                             const ItemTypeT type,
458
                             const ItemColor color,
459
                             const int amount,
460
                             const int price)
461
{
462
    ShopItem *const item = mShopItems->addItem(id,
463
        type,
464
        color,
465
        amount,
466
        price);
467
    mShopItemList->adjustSize();
468
    return item;
469
}
470
471
void BuyDialog::sort()
472
{
473
    if ((mSortDropDown != nullptr) && (mShopItems != nullptr))
474
    {
475
        STD_VECTOR<ShopItem*> &items = mShopItems->items();
476
        switch (mSortDropDown->getSelected())
477
        {
478
            case 1:
479
                std::sort(items.begin(), items.end(), itemPriceBuySorter);
480
            break;
481
            case 2:
482
                std::sort(items.begin(), items.end(), itemNameBuySorter);
483
                break;
484
            case 3:
485
                std::sort(items.begin(), items.end(), itemIdBuySorter);
486
                break;
487
            case 4:
488
                std::sort(items.begin(), items.end(), itemWeightBuySorter);
489
                break;
490
            case 5:
491
                std::sort(items.begin(), items.end(), itemAmountBuySorter);
492
                break;
493
            case 6:
494
                std::sort(items.begin(), items.end(), itemTypeBuySorter);
495
                break;
496
            case 0:
497
            default:
498
                break;
499
        }
500
    }
501
}
502
503
void BuyDialog::close()
504
{
505
    switch (toInt(mNpcId, int))
506
    {
507
#ifdef TMWA_SUPPORT
508
        case Nick:
509
#endif  // TMWA_SUPPORT
510
        case Items:
511
            break;
512
        case Market:
513
            marketHandler->close();
514
            break;
515
        case Cash:
516
            cashShopHandler->close();
517
            break;
518
        case Vending:
519
            vendingHandler->close();
520
            break;
521
        default:
522
            buySellHandler->close();
523
            break;
524
    }
525
    Window::close();
526
}
527
528
void BuyDialog::action(const ActionEvent &event)
529
{
530
    const std::string &eventId = event.getId();
531
    if (eventId == "quit")
532
    {
533
        close();
534
        return;
535
    }
536
    else if (eventId == "sort")
537
    {
538
        sort();
539
        if (mSortDropDown != nullptr)
540
            config.setValue("buySortOrder", mSortDropDown->getSelected());
541
        return;
542
    }
543
    else if (eventId == "namefilter")
544
    {
545
        applyNameFilter(mFilterTextField->getText());
546
    }
547
548
    const int selectedItem = mShopItemList->getSelected();
549
550
    // The following actions require a valid selection
551
    if (selectedItem < 0 || selectedItem >= mShopItems->getNumberOfElements())
552
        return;
553
554
    if (eventId == "slider")
555
    {
556
        mAmountItems = CAST_S32(mSlider->getValue());
557
        mAmountField->setValue(mAmountItems);
558
        updateButtonsAndLabels();
559
    }
560
    else if (eventId == "inc" && mAmountItems < mMaxItems)
561
    {
562
        mAmountItems++;
563
        mSlider->setValue(mAmountItems);
564
        mAmountField->setValue(mAmountItems);
565
        updateButtonsAndLabels();
566
    }
567
    else if (eventId == "dec" && mAmountItems > 1)
568
    {
569
        mAmountItems--;
570
        mSlider->setValue(mAmountItems);
571
        mAmountField->setValue(mAmountItems);
572
        updateButtonsAndLabels();
573
    }
574
    else if (eventId == "max")
575
    {
576
        mAmountItems = mMaxItems;
577
        mSlider->setValue(mAmountItems);
578
        mAmountField->setValue(mAmountItems);
579
        updateButtonsAndLabels();
580
    }
581
    else if (eventId == "amount")
582
    {
583
        mAmountItems = mAmountField->getValue();
584
        mSlider->setValue(mAmountItems);
585
        updateButtonsAndLabels();
586
    }
587
    else if (eventId == "buy" && mAmountItems > 0 && mAmountItems <= mMaxItems)
588
    {
589
        ShopItem *const item = mShopItems->at(selectedItem);
590
        if (item == nullptr)
591
            return;
592
        if (mNpcId == fromInt(Items, BeingId))
593
        {
594
            adminHandler->createItems(item->getId(),
595
                item->getColor(),
596
                mAmountItems);
597
        }
598
#ifdef TMWA_SUPPORT
599
        else if (mNpcId == fromInt(Nick, BeingId))
600
        {
601
            if (tradeWindow != nullptr)
602
            {
603
                buySellHandler->sendBuyRequest(mNick,
604
                    item, mAmountItems);
605
                tradeWindow->addAutoMoney(mNick,
606
                    item->getPrice() * mAmountItems);
607
            }
608
        }
609
#endif  // TMWA_SUPPORT
610
        else if (mNpcId == fromInt(Vending, BeingId))
611
        {
612
            item->increaseUsedQuantity(mAmountItems);
613
            item->update();
614
            if (mConfirmButton != nullptr)
615
                mConfirmButton->setEnabled(true);
616
        }
617
#ifdef TMWA_SUPPORT
618
        else if (mNpcId != fromInt(Nick, BeingId))
619
#else
620
        else
621
#endif  // TMWA_SUPPORT
622
        {
623
            if (mAdvanced)
624
            {
625
                item->increaseUsedQuantity(mAmountItems);
626
                item->update();
627
                if (mConfirmButton != nullptr)
628
                    mConfirmButton->setEnabled(true);
629
            }
630
            else if (mNpcId == fromInt(Market, BeingId))
631
            {
632
                marketHandler->buyItem(item->getId(),
633
                    item->getType(),
634
                    item->getColor(),
635
                    mAmountItems);
636
                item->increaseQuantity(-mAmountItems);
637
                item->update();
638
            }
639
            else if (mNpcId == fromInt(Cash, BeingId))
640
            {
641
                cashShopHandler->buyItem(item->getPrice(),
642
                    item->getId(),
643
                    item->getColor(),
644
                    mAmountItems);
645
            }
646
            else
647
            {
648
                npcHandler->buyItem(mNpcId,
649
                    item->getId(),
650
                    item->getColor(),
651
                    mAmountItems);
652
            }
653
654
            updateSlider(selectedItem);
655
        }
656
    }
657
    else if (eventId == "confirm")
658
    {
659
        STD_VECTOR<ShopItem*> &items = mShopItems->allItems();
660
661
        if (mNpcId == fromInt(Market, BeingId))
662
        {
663
            marketHandler->buyItems(items);
664
        }
665
        else if (mNpcId == fromInt(Vending, BeingId))
666
        {
667
            const Being *const being = actorManager->findBeingByName(
668
                mNick,
669
                ActorType::Player);
670
            if (being != nullptr)
671
            {
672
                vendingHandler->buyItems(being,
673
                    items);
674
            }
675
        }
676
        else if (mNpcId == fromInt(Cash, BeingId))
677
        {
678
            cashShopHandler->buyItems(0, items);
679
        }
680
        else
681
        {
682
            npcHandler->buyItems(items);
683
        }
684
        close();
685
    }
686
}
687
688
void BuyDialog::updateSlider(const int selectedItem)
689
{
690
    // Update money and adjust the max number of items
691
    // that can be bought
692
    mMaxItems -= mAmountItems;
693
    const ShopItem *const item = mShopItems->at(selectedItem);
694
    if (item != nullptr)
695
        setMoney(mMoney - mAmountItems * item->getPrice());
696
    else
697
        setMoney(mMoney);
698
699
    // Reset selection
700
    mAmountItems = 1;
701
    mSlider->setScale(1, mMaxItems);
702
    mSlider->setValue(1);
703
}
704
705
void BuyDialog::valueChanged(const SelectionEvent &event A_UNUSED)
706
{
707
    // Reset amount of items and update labels
708
    mAmountItems = 1;
709
    mSlider->setValue(1);
710
711
    updateButtonsAndLabels();
712
    mSlider->setScale(1, mMaxItems);
713
    mAmountField->setRange(1, mMaxItems);
714
    mAmountField->setValue(1);
715
}
716
717
void BuyDialog::updateButtonsAndLabels()
718
{
719
    const int selectedItem = mShopItemList->getSelected();
720
    int price = 0;
721
722
    if (selectedItem > -1)
723
    {
724
        const ShopItem *const item = mShopItems->at(selectedItem);
725
        if (item != nullptr)
726
        {
727
            const int itemPrice = item->getPrice();
728
729
            // Calculate how many the player can afford
730
            if (mNpcId == fromInt(Items, BeingId))
731
                mMaxItems = 100;
732
            else if (itemPrice != 0)
733
                mMaxItems = mMoney / itemPrice;
734
            else
735
                mMaxItems = 1;
736
737
            if (mNpcId == fromInt(Market, BeingId))
738
            {
739
                if (mMaxItems > item->getQuantity())
740
                    mMaxItems = item->getQuantity();
741
            }
742
            else if (item->getQuantity() > 0 &&
743
                     mMaxItems > item->getQuantity())
744
            {
745
                mMaxItems = item->getQuantity();
746
            }
747
748
            if (mAmountItems > mMaxItems)
749
                mAmountItems = mMaxItems;
750
751
            price = mAmountItems * itemPrice;
752
        }
753
    }
754
    else
755
    {
756
        mMaxItems = 0;
757
        mAmountItems = 0;
758
    }
759
760
    mIncreaseButton->setEnabled(mAmountItems < mMaxItems);
761
    mDecreaseButton->setEnabled(mAmountItems > 1);
762
    mBuyButton->setEnabled(mAmountItems > 0);
763
    mSlider->setEnabled(mMaxItems > 1);
764
    mAmountField->setEnabled(mAmountItems > 0);
765
766
    mQuantityLabel->setCaption(strprintf("%d / %d", mAmountItems, mMaxItems));
767
    // TRANSLATORS: buy dialog label
768
    mMoneyLabel->setCaption(strprintf(_("Price: %s / Total: %s"),
769
        UnitsDb::formatCurrency(mCurrency, price).c_str(),
770
        UnitsDb::formatCurrency(mCurrency, mMoney - price).c_str()));
771
}
772
773
4
void BuyDialog::setVisible(Visible visible)
774
{
775
4
    Window::setVisible(visible);
776
777

4
    if (visible == Visible_true && (mShopItemList != nullptr))
778
4
        mShopItemList->requestFocus();
779
    else
780
        scheduleDelete();
781
4
}
782
783
void BuyDialog::closeAll()
784
{
785
    FOR_EACH (DialogList::const_iterator, it, instances)
786
    {
787
        if (*it != nullptr)
788
            (*it)->close();
789
    }
790
}
791
792
void BuyDialog::applyNameFilter(const std::string &filter)
793
{
794
    STD_VECTOR<ShopItem*> &items = mShopItems->allItems();
795
    std::string filterStr = filter;
796
    toLower(filterStr);
797
    FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
798
    {
799
        ShopItem *const item = *it;
800
        if (item == nullptr)
801
            continue;
802
        std::string name = item->getName();
803
        toLower(name);
804
        if (name.find(filterStr) != std::string::npos)
805
            item->setVisible(true);
806
        else
807
            item->setVisible(false);
808
    }
809
    mShopItems->updateList();
810

3
}