GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/windows/itemamountwindow.cpp Lines: 60 232 25.9 %
Date: 2018-09-20 Branches: 63 336 18.8 %

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/itemamountwindow.h"
24
25
#include "settings.h"
26
27
#include "being/playerinfo.h"
28
29
#include "input/keyboardconfig.h"
30
31
#include "gui/viewport.h"
32
33
#include "gui/models/itemsmodel.h"
34
35
#include "gui/popups/itempopup.h"
36
37
#include "gui/windows/maileditwindow.h"
38
#include "gui/windows/npcdialog.h"
39
#include "gui/windows/shopwindow.h"
40
#include "gui/windows/tradewindow.h"
41
42
#include "gui/widgets/button.h"
43
#include "gui/widgets/containerplacer.h"
44
#include "gui/widgets/createwidget.h"
45
#include "gui/widgets/dropdown.h"
46
#include "gui/widgets/icon.h"
47
#include "gui/widgets/inttextfield.h"
48
#include "gui/widgets/label.h"
49
#include "gui/widgets/slider.h"
50
51
#include "net/inventoryhandler.h"
52
#include "net/mail2handler.h"
53
#include "net/npchandler.h"
54
55
#include "resources/item/item.h"
56
57
#include "utils/delete2.h"
58
#include "utils/gettext.h"
59
60
#ifndef USE_SDL2
61
#include <cmath>
62
#endif  // USE_SDL2
63
64
#include "debug.h"
65
66
void ItemAmountWindow::finish(Item *const item,
67
                              const int amount,
68
                              const int price,
69
                              const ItemAmountWindowUsageT usage)
70
{
71
    if (item == nullptr)
72
        return;
73
    switch (usage)
74
    {
75
        case ItemAmountWindowUsage::TradeAdd:
76
            if (tradeWindow != nullptr)
77
                tradeWindow->tradeItem(item, amount, false);
78
            break;
79
        case ItemAmountWindowUsage::ItemDrop:
80
            PlayerInfo::dropItem(item, amount, Sfx_true);
81
            break;
82
        case ItemAmountWindowUsage::ItemSplit:
83
            inventoryHandler->splitItem(item, amount);
84
            break;
85
        case ItemAmountWindowUsage::StoreAdd:
86
            inventoryHandler->moveItem2(InventoryType::Inventory,
87
                item->getInvIndex(), amount, InventoryType::Storage);
88
            break;
89
        case ItemAmountWindowUsage::StoreRemove:
90
            inventoryHandler->moveItem2(InventoryType::Storage,
91
                item->getInvIndex(), amount, InventoryType::Inventory);
92
            break;
93
        case ItemAmountWindowUsage::ShopBuyAdd:
94
            if (shopWindow != nullptr)
95
                shopWindow->addBuyItem(item, amount, price);
96
            break;
97
        case ItemAmountWindowUsage::ShopSellAdd:
98
            if (shopWindow != nullptr)
99
                shopWindow->addSellItem(item, amount, price);
100
            break;
101
        case ItemAmountWindowUsage::CartAdd:
102
            inventoryHandler->moveItem2(InventoryType::Inventory,
103
                item->getInvIndex(), amount, InventoryType::Cart);
104
            break;
105
        case ItemAmountWindowUsage::CartRemove:
106
            inventoryHandler->moveItem2(InventoryType::Cart,
107
                item->getInvIndex(), amount, InventoryType::Inventory);
108
            break;
109
        case ItemAmountWindowUsage::MailAdd:
110
            if (settings.enableNewMailSystem)
111
            {
112
                mail2Handler->addItem(item, amount);
113
            }
114
            else if (mailEditWindow != nullptr)
115
            {
116
                mailEditWindow->addItem(item, amount);
117
            }
118
            break;
119
        case ItemAmountWindowUsage::CraftAdd:
120
        {
121
            NpcDialog *const dialog = npcHandler->getCurrentNpcDialog();
122
            if (dialog != nullptr)
123
                dialog->addCraftItem(item, amount, price);  // price as slot
124
            break;
125
        }
126
        default:
127
            break;
128
    }
129
}
130
131
1
ItemAmountWindow::ItemAmountWindow(const ItemAmountWindowUsageT usage,
132
                                   Window *const parent,
133
                                   Item *const item,
134
1
                                   const int maxRange) :
135
    Window("", Modal_false, parent, "amount.xml"),
136
    ActionListener(),
137
    KeyListener(),
138

1
    mItemAmountTextField(new IntTextField(this, 1, 0, 0, Enable_true, 0)),
139
    mItemPriceTextField(nullptr),
140
    mGPLabel(nullptr),
141
    mItem(item),
142
    mItemIcon(new Icon(this,
143

2
        item != nullptr ? item->getImage() : nullptr, AutoRelease_false)),
144

1
    mItemAmountSlide(new Slider(this, 1.0, maxRange, 1.0)),
145
    mItemPriceSlide(nullptr),
146
    mItemDropDown(nullptr),
147
    mItemsModal(nullptr),
148
    mPrice(0),
149
    mMax(maxRange),
150
    mUsage(usage),
151

13
    mEnabledKeyboard(keyboard.isEnabled())
152
{
153
1
    if (mItem == nullptr)
154
        return;
155
156
1
    if (usage == ItemAmountWindowUsage::ShopBuyAdd)
157
        mMax = 10000;
158
1
    else if (mMax == 0)
159
2
        mMax = mItem->getQuantity();
160
161
1
    keyboard.setEnabled(false);
162
163
1
    mItemAmountTextField->setRange(1, mMax);
164
1
    mItemAmountTextField->setWidth(35);
165
1
    mItemAmountTextField->addKeyListener(this);
166
167
1
    mItemAmountSlide->setHeight(10);
168
5
    mItemAmountSlide->setActionEventId("slide");
169
1
    mItemAmountSlide->addActionListener(this);
170
171
1
    if (mUsage == ItemAmountWindowUsage::ShopBuyAdd ||
172
        mUsage == ItemAmountWindowUsage::ShopSellAdd)
173
    {
174
        mItemPriceTextField = new IntTextField(this, 1, 0, 0, Enable_true, 0);
175
        mItemPriceTextField->setRange(1, 10000000);
176
        mItemPriceTextField->setWidth(35);
177
        mItemPriceTextField->addKeyListener(this);
178
179
        mItemPriceSlide = new Slider(this, 1.0, 10000000, 1.0);
180
        mItemPriceSlide->setHeight(10);
181
        mItemPriceSlide->setActionEventId("slidePrice");
182
        mItemPriceSlide->addActionListener(this);
183
184
        mGPLabel = new Label(this, " GP");
185
    }
186
187
1
    if (mUsage == ItemAmountWindowUsage::ShopBuyAdd)
188
    {
189
        mItemsModal = new ItemsModal;
190
        mItemDropDown = new DropDown(this,
191
            mItemsModal,
192
            false,
193
            Modal_false,
194
            nullptr,
195
            std::string());
196
        mItemDropDown->setActionEventId("itemType");
197
        mItemDropDown->addActionListener(this);
198
    }
199
200
    // Buttons
201
    Button *const minusAmountButton = new Button(this,
202
        // TRANSLATORS: item amount window button
203
1
        _("-"),
204
        "dec",
205
        BUTTON_SKIN,
206


7
        this);
207
    Button *const plusAmountButton = new Button(this,
208
        // TRANSLATORS: item amount window button
209
1
        _("+"),
210
        "inc",
211
        BUTTON_SKIN,
212


7
        this);
213
    Button *const okButton = new Button(this,
214
        // TRANSLATORS: item amount window button
215
1
        _("OK"),
216
        "ok",
217
        BUTTON_SKIN,
218


7
        this);
219
    Button *const cancelButton = new Button(this,
220
        // TRANSLATORS: item amount window button
221
1
        _("Cancel"),
222
        "cancel",
223
        BUTTON_SKIN,
224


7
        this);
225
    Button *const addAllButton = new Button(this,
226
        // TRANSLATORS: item amount window button
227
1
        _("All"),
228
        "all",
229
        BUTTON_SKIN,
230


7
        this);
231
232
1
    minusAmountButton->adjustSize();
233
2
    minusAmountButton->setWidth(plusAmountButton->getWidth());
234
235
    // Set positions
236
1
    ContainerPlacer placer(nullptr, nullptr);
237
1
    placer = getPlacer(0, 0);
238
1
    int n = 0;
239
1
    if (mUsage == ItemAmountWindowUsage::ShopBuyAdd)
240
    {
241
        placer(0, n, mItemDropDown, 8, 1);
242
        n++;
243
    }
244
1
    placer(1, n, minusAmountButton, 1, 1);
245
1
    placer(2, n, mItemAmountTextField, 3, 1);
246
1
    placer(5, n, plusAmountButton, 1, 1);
247
1
    placer(6, n, addAllButton, 1, 1);
248
249
1
    placer(0, n, mItemIcon, 1, 3);
250
1
    placer(1, n + 1, mItemAmountSlide, 7, 1);
251
252
1
    if (mUsage == ItemAmountWindowUsage::ShopBuyAdd ||
253
        mUsage == ItemAmountWindowUsage::ShopSellAdd)
254
    {
255
        Button *const minusPriceButton = new Button(this,
256
            // TRANSLATORS: item amount window button
257
            _("-"),
258
            "decPrice",
259
            BUTTON_SKIN,
260
            this);
261
        Button *const plusPriceButton = new Button(this,
262
            // TRANSLATORS: item amount window button
263
            _("+"),
264
            "incPrice",
265
            BUTTON_SKIN,
266
            this);
267
        minusPriceButton->adjustSize();
268
        minusPriceButton->setWidth(plusPriceButton->getWidth());
269
270
        placer(1, n + 2, minusPriceButton, 1, 1);
271
        placer(2, n + 2, mItemPriceTextField, 3, 1);
272
        placer(5, n + 2, plusPriceButton, 1, 1);
273
        placer(6, n + 2, mGPLabel, 1, 1);
274
275
        placer(1, n + 3, mItemPriceSlide, 7, 1);
276
        placer(4, n + 5, cancelButton, 1, 1);
277
        placer(5, n + 5, okButton, 1, 1);
278
    }
279
    else
280
    {
281
1
        placer(4, n + 2, cancelButton, 1, 1);
282
1
        placer(5, n + 2, okButton, 1, 1);
283
    }
284
285
1
    reflowLayout(225, 0);
286
287
1
    resetAmount();
288
289



1
    switch (usage)
290
    {
291
        case ItemAmountWindowUsage::TradeAdd:
292
            // TRANSLATORS: amount window message
293
            setCaption(_("Select amount of items to trade."));
294
            break;
295
        case ItemAmountWindowUsage::ItemDrop:
296
            // TRANSLATORS: amount window message
297
5
            setCaption(_("Select amount of items to drop."));
298
1
            break;
299
        case ItemAmountWindowUsage::StoreAdd:
300
            // TRANSLATORS: amount window message
301
            setCaption(_("Select amount of items to store."));
302
            break;
303
        case ItemAmountWindowUsage::MailAdd:
304
            // TRANSLATORS: amount window message
305
            setCaption(_("Select amount of items to send."));
306
            break;
307
        case ItemAmountWindowUsage::CraftAdd:
308
            // TRANSLATORS: amount window message
309
            setCaption(_("Select amount of items to craft."));
310
            break;
311
        case ItemAmountWindowUsage::CartAdd:
312
            // TRANSLATORS: amount window message
313
            setCaption(_("Select amount of items to store to cart."));
314
            break;
315
        case ItemAmountWindowUsage::StoreRemove:
316
            // TRANSLATORS: amount window message
317
            setCaption(_("Select amount of items to retrieve."));
318
            break;
319
        case ItemAmountWindowUsage::CartRemove:
320
            // TRANSLATORS: amount window message
321
            setCaption(_("Select amount of items to retrieve from cart."));
322
            break;
323
        case ItemAmountWindowUsage::ItemSplit:
324
            // TRANSLATORS: amount window message
325
            setCaption(_("Select amount of items to split."));
326
            break;
327
        case ItemAmountWindowUsage::ShopBuyAdd:
328
            // TRANSLATORS: amount window message
329
            setCaption(_("Add to buy shop."));
330
            break;
331
        case ItemAmountWindowUsage::ShopSellAdd:
332
            // TRANSLATORS: amount window message
333
            setCaption(_("Add to sell shop."));
334
            break;
335
        default:
336
            // TRANSLATORS: amount window message
337
            setCaption(_("Unknown."));
338
            break;
339
    }
340
341
1
    setLocationRelativeTo(getParentWindow());
342
343
1
    mItemIcon->addMouseListener(this);
344
}
345
346
1
void ItemAmountWindow::postInit()
347
{
348
1
    Window::postInit();
349
1
    setVisible(fromBool(mItem, Visible));
350
1
}
351
352
5
ItemAmountWindow::~ItemAmountWindow()
353
{
354
2
    delete2(mItemsModal);
355
2
}
356
357
// Show ItemTooltip
358
void ItemAmountWindow::mouseMoved(MouseEvent &event)
359
{
360
    Window::mouseMoved(event);
361
362
    if ((viewport == nullptr) || (itemPopup == nullptr))
363
        return;
364
365
    if (event.getSource() == mItemIcon)
366
    {
367
        itemPopup->setItem(mItem, false);
368
        itemPopup->position(viewport->mMouseX, viewport->mMouseY);
369
    }
370
}
371
372
// Hide ItemTooltip
373
void ItemAmountWindow::mouseExited(MouseEvent &event A_UNUSED)
374
{
375
    if (itemPopup != nullptr)
376
        itemPopup->setVisible(Visible_false);
377
}
378
379
void ItemAmountWindow::resetAmount()
380
{
381
1
    mItemAmountTextField->setValue(1);
382
}
383
384
void ItemAmountWindow::action(const ActionEvent &event)
385
{
386
    const std::string &eventId = event.getId();
387
    if (eventId == "cancel")
388
    {
389
        close();
390
        return;
391
    }
392
    else if (eventId == "ok")
393
    {
394
        if (mItemPriceTextField != nullptr)
395
        {
396
            finish(mItem,
397
                mItemAmountTextField->getValue(),
398
                mItemPriceTextField->getValue(),
399
                mUsage);
400
        }
401
        else
402
        {
403
            if (mUsage == ItemAmountWindowUsage::CraftAdd)
404
            {
405
                finish(mItem,
406
                    mItemAmountTextField->getValue(),
407
                    mPrice,
408
                    mUsage);
409
            }
410
            else
411
            {
412
                finish(mItem,
413
                    mItemAmountTextField->getValue(),
414
                    0,
415
                    mUsage);
416
            }
417
        }
418
        close();
419
        return;
420
    }
421
    else if (eventId == "itemType")
422
    {
423
        if ((mItemDropDown == nullptr) || (mItemsModal == nullptr))
424
            return;
425
426
        const int id = ItemDB::get(mItemsModal->getElementAt(
427
            mItemDropDown->getSelected())).getId();
428
429
        mItem = new Item(id,
430
            ItemType::Unknown,
431
            10000,
432
            0,
433
            ItemColor_one,
434
            Identified_true,
435
            Damaged_true,
436
            Favorite_false,
437
            Equipm_false,
438
            Equipped_false);
439
440
        if (mUsage == ItemAmountWindowUsage::ShopBuyAdd)
441
            mMax = 10000;
442
        else if (mMax == 0)
443
            mMax = mItem->getQuantity();
444
445
        mItemIcon->setImage(mItem->getImage());
446
    }
447
448
    int amount = mItemAmountTextField->getValue();
449
450
    if (eventId == "inc" && amount < mMax)
451
        amount++;
452
    else if (eventId == "dec" && amount > 1)
453
        amount--;
454
    else if (eventId == "all")
455
        amount = mMax;
456
    else if (eventId == "slide")
457
        amount = CAST_S32(mItemAmountSlide->getValue());
458
    mItemAmountTextField->setValue(amount);
459
    mItemAmountSlide->setValue(amount);
460
461
    if ((mItemPriceTextField != nullptr) && (mItemPriceSlide != nullptr))
462
    {
463
        if (mPrice > 7)
464
            mPrice = 7;
465
        else if (mPrice < 0)
466
            mPrice = 0;
467
468
        int price = 0;
469
470
        if (eventId == "incPrice")
471
        {
472
            mPrice++;
473
            price = CAST_S32(pow(10.0, mPrice));
474
            mItemPriceTextField->setValue(price);
475
            mItemPriceSlide->setValue(price);
476
        }
477
        else if (eventId == "decPrice")
478
        {
479
            mPrice--;
480
            price = CAST_S32(pow(10.0, mPrice));
481
            mItemPriceTextField->setValue(price);
482
            mItemPriceSlide->setValue(price);
483
        }
484
        else if (eventId == "slidePrice")
485
        {
486
            price = CAST_S32(mItemPriceSlide->getValue());
487
            if (price != 0)
488
                mPrice = CAST_S32(log(static_cast<float>(price)));
489
            else
490
                mPrice = 0;
491
            mItemPriceTextField->setValue(price);
492
            mItemPriceSlide->setValue(price);
493
        }
494
    }
495
}
496
497
void ItemAmountWindow::close()
498
{
499
    keyboard.setEnabled(mEnabledKeyboard);
500
    scheduleDelete();
501
}
502
503
void ItemAmountWindow::keyReleased(KeyEvent &event A_UNUSED)
504
{
505
    mItemAmountSlide->setValue(mItemAmountTextField->getValue());
506
}
507
508
void ItemAmountWindow::showWindow(const ItemAmountWindowUsageT usage,
509
                                  Window *const parent,
510
                                  Item *const item,
511
                                  int maxRange,
512
                                  int tag)
513
{
514
    if (item == nullptr)
515
        return;
516
517
    if (maxRange == 0)
518
        maxRange = item->getQuantity();
519
520
    if (usage != ItemAmountWindowUsage::ShopBuyAdd &&
521
        usage != ItemAmountWindowUsage::ShopSellAdd &&
522
        maxRange <= 1)
523
    {
524
        if (usage == ItemAmountWindowUsage::CraftAdd)
525
            finish(item, maxRange, tag, usage);
526
        else
527
            finish(item, maxRange, 0, usage);
528
    }
529
    else
530
    {
531
        ItemAmountWindow *const window = CREATEWIDGETR(ItemAmountWindow,
532
            usage, parent, item, maxRange);
533
        if (usage == ItemAmountWindowUsage::CraftAdd)
534
            window->mPrice = tag;
535
    }
536

3
}