GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/windows/itemamountwindow.cpp Lines: 56 243 23.0 %
Date: 2017-11-29 Branches: 64 336 19.0 %

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/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);
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
2
ItemAmountWindow::ItemAmountWindow(const ItemAmountWindowUsageT usage,
132
                                   Window *const parent,
133
                                   Item *const item,
134
2
                                   const int maxRange) :
135
    Window("", Modal_false, parent, "amount.xml"),
136
    ActionListener(),
137
    KeyListener(),
138

2
    mItemAmountTextField(new IntTextField(this, 1)),
139
    mItemPriceTextField(nullptr),
140
    mGPLabel(nullptr),
141
    mItem(item),
142

4
    mItemIcon(new Icon(this, item != nullptr ? item->getImage() : nullptr)),
143

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

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


14
    Button *const minusAmountButton = new Button(this, _("-"), "dec", this);
197
    // TRANSLATORS: item amount window button
198


14
    Button *const plusAmountButton = new Button(this, _("+"), "inc", this);
199
    // TRANSLATORS: item amount window button
200


14
    Button *const okButton = new Button(this, _("OK"), "ok", this);
201
    // TRANSLATORS: item amount window button
202


14
    Button *const cancelButton = new Button(this, _("Cancel"), "cancel", this);
203
    // TRANSLATORS: item amount window button
204


14
    Button *const addAllButton = new Button(this, _("All"), "all", this);
205
206
2
    minusAmountButton->adjustSize();
207
4
    minusAmountButton->setWidth(plusAmountButton->getWidth());
208
209
    // Set positions
210
2
    ContainerPlacer placer;
211
2
    placer = getPlacer(0, 0);
212
2
    int n = 0;
213
2
    if (mUsage == ItemAmountWindowUsage::ShopBuyAdd)
214
    {
215
        placer(0, n, mItemDropDown, 8);
216
        n++;
217
    }
218
2
    placer(1, n, minusAmountButton);
219
2
    placer(2, n, mItemAmountTextField, 3);
220
2
    placer(5, n, plusAmountButton);
221
2
    placer(6, n, addAllButton);
222
223
2
    placer(0, n, mItemIcon, 1, 3);
224
2
    placer(1, n + 1, mItemAmountSlide, 7);
225
226
2
    if (mUsage == ItemAmountWindowUsage::ShopBuyAdd ||
227
        mUsage == ItemAmountWindowUsage::ShopSellAdd)
228
    {
229
        Button *const minusPriceButton = new Button(
230
            // TRANSLATORS: item amount window button
231
            this, _("-"), "decPrice", this);
232
        Button *const plusPriceButton = new Button(
233
            // TRANSLATORS: item amount window button
234
            this, _("+"), "incPrice", this);
235
        minusPriceButton->adjustSize();
236
        minusPriceButton->setWidth(plusPriceButton->getWidth());
237
238
        placer(1, n + 2, minusPriceButton);
239
        placer(2, n + 2, mItemPriceTextField, 3);
240
        placer(5, n + 2, plusPriceButton);
241
        placer(6, n + 2, mGPLabel);
242
243
        placer(1, n + 3, mItemPriceSlide, 7);
244
        placer(4, n + 5, cancelButton);
245
        placer(5, n + 5, okButton);
246
    }
247
    else
248
    {
249
2
        placer(4, n + 2, cancelButton);
250
2
        placer(5, n + 2, okButton);
251
    }
252
253
2
    reflowLayout(225, 0);
254
255
2
    resetAmount();
256
257



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

6
}