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