GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/itemshortcutcontainer.cpp Lines: 1 274 0.4 %
Date: 2018-05-19 03:07:18 Branches: 0 276 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2007-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/widgets/itemshortcutcontainer.h"
24
25
#include "dragdrop.h"
26
#include "settings.h"
27
#include "spellmanager.h"
28
29
#include "being/playerinfo.h"
30
31
#include "input/inputmanager.h"
32
33
#include "gui/viewport.h"
34
35
#include "gui/fonts/font.h"
36
37
#include "gui/shortcut/itemshortcut.h"
38
#include "gui/shortcut/spellshortcut.h"
39
40
#include "gui/popups/itempopup.h"
41
#include "gui/popups/popupmenu.h"
42
#include "gui/popups/skillpopup.h"
43
#include "gui/popups/spellpopup.h"
44
45
#include "gui/windows/inventorywindow.h"
46
#include "gui/windows/skilldialog.h"
47
48
#include "input/inputactionoperators.h"
49
50
#include "const/resources/skill.h"
51
52
#include "utils/stringutils.h"
53
54
#include "debug.h"
55
56
ItemShortcutContainer::ItemShortcutContainer(Widget2 *const widget,
57
                                             const unsigned number) :
58
    ShortcutContainer(widget),
59
    mItemClicked(false),
60
    mNumber(number),
61
    mEquipedColor(getThemeColor(ThemeColorId::ITEM_EQUIPPED, 255U)),
62
    mEquipedColor2(getThemeColor(ThemeColorId::ITEM_EQUIPPED_OUTLINE, 255U)),
63
    mUnEquipedColor(getThemeColor(ThemeColorId::ITEM_NOT_EQUIPPED, 255U)),
64
    mUnEquipedColor2(getThemeColor(ThemeColorId::ITEM_NOT_EQUIPPED_OUTLINE,
65
        255U))
66
{
67
    mMaxItems = ItemShortcut::getItemCount();
68
}
69
70
ItemShortcutContainer::~ItemShortcutContainer()
71
{
72
}
73
74
void ItemShortcutContainer::setWidget2(const Widget2 *const widget)
75
{
76
    Widget2::setWidget2(widget);
77
    mEquipedColor = getThemeColor(ThemeColorId::ITEM_EQUIPPED, 255U);
78
    mEquipedColor2 = getThemeColor(ThemeColorId::ITEM_EQUIPPED_OUTLINE, 255U);
79
    mUnEquipedColor = getThemeColor(ThemeColorId::ITEM_NOT_EQUIPPED, 255U);
80
    mUnEquipedColor2 = getThemeColor(ThemeColorId::ITEM_NOT_EQUIPPED_OUTLINE,
81
        255U);
82
    mForegroundColor = getThemeColor(ThemeColorId::TEXT, 255U);
83
    mForegroundColor2 = getThemeColor(ThemeColorId::TEXT_OUTLINE, 255U);
84
}
85
86
void ItemShortcutContainer::draw(Graphics *const graphics)
87
{
88
    BLOCK_START("ItemShortcutContainer::draw")
89
    const ItemShortcut *const selShortcut = itemShortcut[mNumber];
90
    if (selShortcut == nullptr)
91
    {
92
        BLOCK_END("ItemShortcutContainer::draw")
93
        return;
94
    }
95
96
    if (settings.guiAlpha != mAlpha)
97
    {
98
        if (mBackgroundImg != nullptr)
99
            mBackgroundImg->setAlpha(mAlpha);
100
        mAlpha = settings.guiAlpha;
101
    }
102
103
    Font *const font = getFont();
104
    drawBackground(graphics);
105
106
    const Inventory *const inv = PlayerInfo::getInventory();
107
    if (inv == nullptr)
108
    {
109
        BLOCK_END("ItemShortcutContainer::draw")
110
        return;
111
    }
112
113
    // +++ for future usage need reorder drawing images before text or back
114
    for (unsigned i = 0; i < mMaxItems; i++)
115
    {
116
        const int itemX = (i % mGridWidth) * mBoxWidth;
117
        const int itemY = (i / mGridWidth) * mBoxHeight;
118
119
        // Draw item keyboard shortcut.
120
        const std::string key = inputManager.getKeyValueString(
121
            InputAction::SHORTCUT_1 + i);
122
        font->drawString(graphics,
123
            mForegroundColor,
124
            mForegroundColor,
125
            key,
126
            itemX + 2, itemY + 2);
127
128
        const int itemId = selShortcut->getItem(i);
129
        const ItemColor itemColor = selShortcut->getItemColor(i);
130
131
        if (itemId < 0)
132
            continue;
133
134
        // this is item
135
        if (itemId < SPELL_MIN_ID)
136
        {
137
            const Item *const item = inv->findItem(itemId, itemColor);
138
            if (item != nullptr)
139
            {
140
                // Draw item icon.
141
                Image *const image = item->getImage();
142
                if (image != nullptr)
143
                {
144
                    std::string caption;
145
                    if (item->getQuantity() > 1)
146
                        caption = toString(item->getQuantity());
147
                    else if (item->isEquipped() == Equipped_true)
148
                        caption = "Eq.";
149
150
                    image->setAlpha(1.0F);
151
                    graphics->drawImage(image, itemX, itemY);
152
                    if (item->isEquipped() == Equipped_true)
153
                    {
154
                        font->drawString(graphics,
155
                            mEquipedColor,
156
                            mEquipedColor2,
157
                            caption,
158
                            itemX + (mBoxWidth - font->getWidth(caption)) / 2,
159
                            itemY + mBoxHeight - 14);
160
                    }
161
                    else
162
                    {
163
                        font->drawString(graphics,
164
                            mUnEquipedColor,
165
                            mUnEquipedColor2,
166
                            caption,
167
                            itemX + (mBoxWidth - font->getWidth(caption)) / 2,
168
                            itemY + mBoxHeight - 14);
169
                    }
170
                }
171
            }
172
        }
173
        else if (itemId < SKILL_MIN_ID && (spellManager != nullptr))
174
        {   // this is magic shortcut
175
            const TextCommand *const spell = spellManager
176
                ->getSpellByItem(itemId);
177
            if (spell != nullptr)
178
            {
179
                if (!spell->isEmpty())
180
                {
181
                    Image *const image = spell->getImage();
182
183
                    if (image != nullptr)
184
                    {
185
                        image->setAlpha(1.0F);
186
                        graphics->drawImage(image, itemX, itemY);
187
                    }
188
                }
189
190
                font->drawString(graphics,
191
                    mForegroundColor,
192
                    mForegroundColor,
193
                    spell->getSymbol(),
194
                    itemX + 2, itemY + mBoxHeight / 2);
195
            }
196
        }
197
        else if (skillDialog != nullptr)
198
        {
199
            const SkillInfo *const skill = skillDialog->getSkill(
200
                itemId - SKILL_MIN_ID);
201
            if (skill != nullptr)
202
            {
203
                Image *const image = skill->data->icon;
204
205
                if (image != nullptr)
206
                {
207
                    image->setAlpha(1.0F);
208
                    graphics->drawImage(image, itemX, itemY);
209
                }
210
                if (!skill->data->haveIcon)
211
                {
212
                    font->drawString(graphics,
213
                        mForegroundColor,
214
                        mForegroundColor,
215
                        skill->data->shortName,
216
                        itemX + 2,
217
                        itemY + mBoxHeight / 2);
218
                }
219
            }
220
        }
221
    }
222
    BLOCK_END("ItemShortcutContainer::draw")
223
}
224
225
void ItemShortcutContainer::safeDraw(Graphics *const graphics)
226
{
227
    BLOCK_START("ItemShortcutContainer::draw")
228
    const ItemShortcut *const selShortcut = itemShortcut[mNumber];
229
    if (selShortcut == nullptr)
230
    {
231
        BLOCK_END("ItemShortcutContainer::draw")
232
        return;
233
    }
234
235
    if (settings.guiAlpha != mAlpha)
236
    {
237
        if (mBackgroundImg != nullptr)
238
            mBackgroundImg->setAlpha(mAlpha);
239
        mAlpha = settings.guiAlpha;
240
    }
241
242
    Font *const font = getFont();
243
    safeDrawBackground(graphics);
244
245
    const Inventory *const inv = PlayerInfo::getInventory();
246
    if (inv == nullptr)
247
    {
248
        BLOCK_END("ItemShortcutContainer::draw")
249
        return;
250
    }
251
252
    // +++ for future usage need reorder drawing images before text or back
253
    for (unsigned i = 0; i < mMaxItems; i++)
254
    {
255
        const int itemX = (i % mGridWidth) * mBoxWidth;
256
        const int itemY = (i / mGridWidth) * mBoxHeight;
257
258
        // Draw item keyboard shortcut.
259
        const std::string key = inputManager.getKeyValueString(
260
            InputAction::SHORTCUT_1 + i);
261
        font->drawString(graphics,
262
            mForegroundColor,
263
            mForegroundColor,
264
            key,
265
            itemX + 2, itemY + 2);
266
267
        const int itemId = selShortcut->getItem(i);
268
        const ItemColor itemColor = selShortcut->getItemColor(i);
269
270
        if (itemId < 0)
271
            continue;
272
273
        // this is item
274
        if (itemId < SPELL_MIN_ID)
275
        {
276
            const Item *const item = inv->findItem(itemId, itemColor);
277
            if (item != nullptr)
278
            {
279
                // Draw item icon.
280
                Image *const image = item->getImage();
281
                if (image != nullptr)
282
                {
283
                    std::string caption;
284
                    if (item->getQuantity() > 1)
285
                        caption = toString(item->getQuantity());
286
                    else if (item->isEquipped() == Equipped_true)
287
                        caption = "Eq.";
288
289
                    image->setAlpha(1.0F);
290
                    graphics->drawImage(image, itemX, itemY);
291
                    if (item->isEquipped() == Equipped_true)
292
                    {
293
                        font->drawString(graphics,
294
                            mEquipedColor,
295
                            mEquipedColor2,
296
                            caption,
297
                            itemX + (mBoxWidth - font->getWidth(caption)) / 2,
298
                            itemY + mBoxHeight - 14);
299
                    }
300
                    else
301
                    {
302
                        font->drawString(graphics,
303
                            mUnEquipedColor,
304
                            mUnEquipedColor2,
305
                            caption,
306
                            itemX + (mBoxWidth - font->getWidth(caption)) / 2,
307
                            itemY + mBoxHeight - 14);
308
                    }
309
                }
310
            }
311
        }
312
        else if (itemId < SKILL_MIN_ID && (spellManager != nullptr))
313
        {   // this is magic shortcut
314
            const TextCommand *const spell = spellManager
315
                ->getSpellByItem(itemId);
316
            if (spell != nullptr)
317
            {
318
                if (!spell->isEmpty())
319
                {
320
                    Image *const image = spell->getImage();
321
322
                    if (image != nullptr)
323
                    {
324
                        image->setAlpha(1.0F);
325
                        graphics->drawImage(image, itemX, itemY);
326
                    }
327
                }
328
329
                font->drawString(graphics,
330
                    mForegroundColor,
331
                    mForegroundColor,
332
                    spell->getSymbol(),
333
                    itemX + 2, itemY + mBoxHeight / 2);
334
            }
335
        }
336
        else if (skillDialog != nullptr)
337
        {
338
            const SkillInfo *const skill = skillDialog->getSkill(
339
                itemId - SKILL_MIN_ID);
340
            if (skill != nullptr)
341
            {
342
                Image *const image = skill->data->icon;
343
344
                if (image != nullptr)
345
                {
346
                    image->setAlpha(1.0F);
347
                    graphics->drawImage(image, itemX, itemY);
348
                }
349
                if (!skill->data->haveIcon)
350
                {
351
                    font->drawString(graphics,
352
                        mForegroundColor,
353
                        mForegroundColor,
354
                        skill->data->shortName,
355
                        itemX + 2,
356
                        itemY + mBoxHeight / 2);
357
                }
358
            }
359
        }
360
    }
361
    BLOCK_END("ItemShortcutContainer::draw")
362
}
363
364
void ItemShortcutContainer::mouseDragged(MouseEvent &event)
365
{
366
    if (mNumber == SHORTCUT_AUTO_TAB)
367
        return;
368
    ItemShortcut *const selShortcut = itemShortcut[mNumber];
369
    if (selShortcut == nullptr)
370
        return;
371
372
    if (event.getButton() == MouseButton::LEFT)
373
    {
374
        if (dragDrop.isEmpty() && mItemClicked)
375
        {
376
            mItemClicked = false;
377
378
            const int index = getIndexFromGrid(event.getX(), event.getY());
379
            if (index == -1)
380
                return;
381
382
            const int itemId = selShortcut->getItem(index);
383
            const ItemColor itemColor = selShortcut->getItemColor(index);
384
385
            if (itemId < 0)
386
                return;
387
388
            event.consume();
389
            if (itemId < SPELL_MIN_ID)
390
            {   // items
391
                if (PlayerInfo::getInventory() == nullptr)
392
                    return;
393
394
                const Item *const item = PlayerInfo::getInventory()->findItem(
395
                    itemId, itemColor);
396
397
                if (item != nullptr)
398
                {
399
                    selShortcut->removeItem(index);
400
                    dragDrop.dragItem(item, DragDropSource::Shortcuts, index);
401
                }
402
                else
403
                {
404
                    dragDrop.clear();
405
                }
406
            }
407
            else if (itemId < SKILL_MIN_ID)
408
            {   // spells/commands
409
                if (spellManager == nullptr)
410
                {
411
                    dragDrop.clear();
412
                    return;
413
                }
414
415
                const TextCommand *const spell = spellManager->getSpellByItem(
416
                    itemId);
417
                if (spell != nullptr)
418
                {
419
                    selShortcut->removeItem(index);
420
                    dragDrop.dragCommand(spell,
421
                        DragDropSource::Shortcuts, index);
422
                    dragDrop.setItem(itemId);
423
                }
424
                else
425
                {
426
                    dragDrop.clear();
427
                }
428
            }
429
            else
430
            {   // skills
431
                if (skillDialog == nullptr)
432
                {
433
                    dragDrop.clear();
434
                    return;
435
                }
436
                const SkillInfo *const skill
437
                    = skillDialog->getSkillByItem(itemId);
438
                if (skill != nullptr)
439
                {
440
                    const std::string itemData = selShortcut->getItemData(
441
                        index);
442
                    selShortcut->removeItem(index);
443
                    dragDrop.dragSkill(skill,
444
                        DragDropSource::Shortcuts,
445
                        index);
446
                    dragDrop.setItem(itemId);
447
                    dragDrop.setItemColor(itemColor);
448
                    dragDrop.setItemData(itemData);
449
                }
450
                else
451
                {
452
                    dragDrop.clear();
453
                }
454
            }
455
        }
456
    }
457
}
458
459
void ItemShortcutContainer::mousePressed(MouseEvent &event)
460
{
461
    ItemShortcut *const selShortcut = itemShortcut[mNumber];
462
    if (selShortcut == nullptr)
463
        return;
464
465
    const int index = getIndexFromGrid(event.getX(), event.getY());
466
467
    if (index == -1)
468
        return;
469
470
    if (event.getButton() == MouseButton::LEFT)
471
    {
472
        event.consume();
473
        // Stores the selected item if theirs one.
474
        if (selShortcut->isItemSelected() && (inventoryWindow != nullptr) &&
475
            (inventoryWindow->isWindowVisible()
476
            || selShortcut->getSelectedItem() >= SPELL_MIN_ID))
477
        {
478
            selShortcut->setItem(index);
479
            selShortcut->setItemSelected(-1);
480
            if (spellShortcut != nullptr)
481
                spellShortcut->setItemSelected(-1);
482
            inventoryWindow->unselectItem();
483
        }
484
        else if (selShortcut->getItem(index) != 0)
485
        {
486
            mItemClicked = true;
487
        }
488
    }
489
    else if (event.getButton() == MouseButton::RIGHT)
490
    {
491
        event.consume();
492
        if (popupMenu != nullptr &&
493
            viewport != nullptr)
494
        {
495
            popupMenu->showItemPopup(viewport->mMouseX,
496
                viewport->mMouseY,
497
                selShortcut->getItem(index),
498
                selShortcut->getItemColor(index));
499
        }
500
    }
501
}
502
503
void ItemShortcutContainer::mouseReleased(MouseEvent &event)
504
{
505
    ItemShortcut *const selShortcut = itemShortcut[mNumber];
506
    if (selShortcut == nullptr)
507
        return;
508
509
    if (event.getButton() == MouseButton::LEFT)
510
    {
511
        if (selShortcut->isItemSelected())
512
            selShortcut->setItemSelected(-1);
513
514
        const int index = getIndexFromGrid(event.getX(), event.getY());
515
        if (index == -1)
516
            return;
517
518
        if (dragDrop.isEmpty())
519
        {
520
            if ((selShortcut->getItem(index) != 0) && mItemClicked)
521
                selShortcut->useItem(index);
522
        }
523
        else
524
        {
525
            if (dragDrop.getSource() == DragDropSource::Shortcuts)
526
            {
527
                const int oldIndex = dragDrop.getTag();
528
                selShortcut->setItem(oldIndex, dragDrop.getItem(),
529
                    dragDrop.getItemColor());
530
                selShortcut->swap(oldIndex, index);
531
            }
532
            else
533
            {
534
                selShortcut->setItemData(index,
535
                    dragDrop.getItemData());
536
                selShortcut->setItem(index, dragDrop.getItem(),
537
                    dragDrop.getItemColor());
538
            }
539
            dragDrop.clear();
540
            dragDrop.deselect();
541
        }
542
543
        mItemClicked = false;
544
    }
545
}
546
547
void ItemShortcutContainer::mouseMoved(MouseEvent &event)
548
{
549
    const ItemShortcut *const selShortcut = itemShortcut[mNumber];
550
    if (selShortcut == nullptr)
551
        return;
552
553
    const int index = getIndexFromGrid(event.getX(), event.getY());
554
555
    if (index == -1)
556
        return;
557
558
    const int itemId = selShortcut->getItem(index);
559
    const ItemColor itemColor = selShortcut->getItemColor(index);
560
561
    if (itemId < 0)
562
        return;
563
564
    if (itemId < SPELL_MIN_ID)
565
    {
566
        skillPopup->setVisible(Visible_false);
567
        spellPopup->setVisible(Visible_false);
568
569
        Inventory *const inv = PlayerInfo::getInventory();
570
        if (inv == nullptr)
571
            return;
572
573
        const Item *const item = inv->findItem(itemId, itemColor);
574
        if ((item != nullptr) && (viewport != nullptr))
575
        {
576
            itemPopup->setItem(item, false);
577
            itemPopup->position(viewport->mMouseX, viewport->mMouseY);
578
        }
579
        else
580
        {
581
            itemPopup->setVisible(Visible_false);
582
        }
583
    }
584
    else if (itemId < SKILL_MIN_ID && (spellManager != nullptr))
585
    {
586
        skillPopup->setVisible(Visible_false);
587
        itemPopup->setVisible(Visible_false);
588
        const TextCommand *const spell = spellManager->getSpellByItem(itemId);
589
        if ((spell != nullptr) && (viewport != nullptr))
590
        {
591
            spellPopup->setItem(spell);
592
            spellPopup->view(viewport->mMouseX,
593
                viewport->mMouseY);
594
        }
595
        else
596
        {
597
            spellPopup->setVisible(Visible_false);
598
        }
599
    }
600
    else if (skillDialog != nullptr)
601
    {
602
        itemPopup->setVisible(Visible_false);
603
        spellPopup->setVisible(Visible_false);
604
        const SkillInfo *const skill = skillDialog->getSkillByItem(itemId);
605
        if (skill == nullptr)
606
            return;
607
608
        const std::string data = selShortcut->getItemData(index);
609
        CastTypeT castType = CastType::Default;
610
        int offsetX = 0;
611
        int offsetY = 0;
612
        if (!data.empty())
613
        {
614
            STD_VECTOR<int> vect;
615
            splitToIntVector(vect, data, ' ');
616
            const size_t sz = vect.size();
617
            if (sz > 0)
618
                castType = static_cast<CastTypeT>(vect[0]);
619
            if (sz > 2)
620
            {
621
                offsetX = vect[1];
622
                offsetY = vect[2];
623
            }
624
        }
625
        skillPopup->show(skill,
626
            toInt(itemColor, int),
627
            castType,
628
            offsetX,
629
            offsetY);
630
        skillPopup->position(viewport->mMouseX,
631
            viewport->mMouseY);
632
    }
633
}
634
635
// Hide ItemTooltip
636
void ItemShortcutContainer::mouseExited(MouseEvent &event A_UNUSED)
637
{
638
    if (itemPopup != nullptr)
639
        itemPopup->setVisible(Visible_false);
640
    if (spellPopup != nullptr)
641
        spellPopup->setVisible(Visible_false);
642
    if (skillPopup != nullptr)
643
        skillPopup->setVisible(Visible_false);
644
}
645
646
void ItemShortcutContainer::widgetHidden(const Event &event A_UNUSED)
647
{
648
    if (itemPopup != nullptr)
649
        itemPopup->setVisible(Visible_false);
650
    if (spellPopup != nullptr)
651
        spellPopup->setVisible(Visible_false);
652
4
}