GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/windows/buydialog.cpp Lines: 132 365 36.2 %
Date: 2017-11-29 Branches: 114 448 25.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-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
#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
2
BuyDialog::DialogList BuyDialog::instances;
188
189
2
BuyDialog::BuyDialog() :
190
    // TRANSLATORS: buy dialog name
191
2
    Window(_("Create items"), Modal_false, nullptr, "buy.xml"),
192
    ActionListener(),
193
    SelectionListener(),
194
    mSortModel(nullptr),
195
    mSortDropDown(nullptr),
196
    mFilterTextField(new TextField(this, "", LoseFocusOnTab_true,
197

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


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

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



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

4
        Modal_false, this, "sort")),
242
    mFilterTextField(new TextField(this, "", LoseFocusOnTab_true,
243

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



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

4
        Modal_false, this, "sort")),
266
    mFilterTextField(new TextField(this, "", LoseFocusOnTab_true,
267

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



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

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

32
        fromBool(getOptionBool("showbackground"), Opaque),
309

16
        "buy_background.xml");
310
8
    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
311
312
8
    mSlider = new Slider(this, 1.0, 1.0);
313
24
    mQuantityLabel = new Label(this, strprintf(
314

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

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

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


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


56
    mDecreaseButton = new Button(this, _("-"), "dec", this);
336


70
    mBuyButton = new Button(this, mNpcId == fromInt(Items, BeingId)
337
        // TRANSLATORS: buy dialog button
338

14
        ? _("Create") : (mAdvanced ? _("Add") : _("Buy")), "buy", this);
339
8
    if (mAdvanced)
340
    {
341
        // TRANSLATORS: buy dialog button
342


28
        mConfirmButton = new Button(this, _("Buy"), "confirm", this);
343
4
        mConfirmButton->setEnabled(false);
344
    }
345
    else
346
    {
347
4
        mConfirmButton = nullptr;
348
    }
349
    // TRANSLATORS: buy dialog button
350


56
    mQuitButton = new Button(this, _("Quit"), "quit", this);
351
    // TRANSLATORS: buy dialog button
352


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

16
        mFilterLabel = new Label(this, _("Filter:"));
390
4
        mFilterLabel->adjustSize();
391
4
        placer(0, 8, mFilterLabel, 2);
392
    }
393
8
    placer(2, 8, mFilterTextField, 2);
394
8
    if (mAdvanced)
395
    {
396
4
        placer(6, 8, mBuyButton);
397
4
        placer(7, 8, mConfirmButton);
398
    }
399
    else
400
    {
401
4
        placer(7, 8, mBuyButton);
402
    }
403
8
    placer(8, 8, mQuitButton);
404
405
8
    Layout &layout = getLayout();
406
8
    layout.setRowHeight(0, LayoutType::SET);
407
408
8
    center();
409
8
    loadWindowState();
410
16
    enableVisibleSound(true);
411
412
16
    instances.push_back(this);
413
8
    setVisible(Visible_true);
414
415
8
    if (mSortDropDown != nullptr)
416

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

8
    if (visible == Visible_true && (mShopItemList != nullptr))
762
8
        mShopItemList->requestFocus();
763
    else
764
        scheduleDelete();
765
8
}
766
767
void BuyDialog::closeAll()
768
{
769
    FOR_EACH (DialogList::const_iterator, it, instances)
770
    {
771
        if (*it != nullptr)
772
            (*it)->close();
773
    }
774
}
775
776
void BuyDialog::applyNameFilter(const std::string &filter)
777
{
778
    STD_VECTOR<ShopItem*> &items = mShopItems->allItems();
779
    std::string filterStr = filter;
780
    toLower(filterStr);
781
    FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
782
    {
783
        ShopItem *const item = *it;
784
        if (item == nullptr)
785
            continue;
786
        std::string name = item->getName();
787
        toLower(name);
788
        if (name.find(filterStr) != std::string::npos)
789
            item->setVisible(true);
790
        else
791
            item->setVisible(false);
792
    }
793
    mShopItems->updateList();
794

6
}