ManaPlus
itemshortcutcontainer.cpp
Go to the documentation of this file.
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-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
25 
26 #include "dragdrop.h"
27 #include "settings.h"
28 #include "spellmanager.h"
29 
30 #include "being/playerinfo.h"
31 
32 #include "input/inputmanager.h"
33 
34 #include "gui/skin.h"
35 #include "gui/viewport.h"
36 
37 #include "gui/fonts/font.h"
38 
41 
42 #include "gui/popups/itempopup.h"
43 #include "gui/popups/popupmenu.h"
44 #include "gui/popups/skillpopup.h"
45 #include "gui/popups/spellpopup.h"
46 
49 
51 
52 #include "const/resources/skill.h"
53 
54 #include "utils/stringutils.h"
55 
56 #include "debug.h"
57 
59  const unsigned number) :
60  ShortcutContainer(widget),
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  mNumber(number),
67  mKeyOffsetX(2),
68  mKeyOffsetY(2),
69  mItemClicked(false)
70 {
72 }
73 
75 {
76 }
77 
78 void ItemShortcutContainer::setSkin(const Widget2 *const widget,
79  Skin *const skin)
80 {
81  ShortcutContainer::setSkin(widget, skin);
82  mEquipedColor = getThemeColor(ThemeColorId::ITEM_EQUIPPED, 255U);
83  mEquipedColor2 = getThemeColor(ThemeColorId::ITEM_EQUIPPED_OUTLINE, 255U);
84  mUnEquipedColor = getThemeColor(ThemeColorId::ITEM_NOT_EQUIPPED, 255U);
85  mUnEquipedColor2 = getThemeColor(ThemeColorId::ITEM_NOT_EQUIPPED_OUTLINE,
86  255U);
88  mForegroundColor2 = getThemeColor(ThemeColorId::TEXT_OUTLINE, 255U);
89  if (mSkin != nullptr)
90  {
91  mKeyOffsetX = mSkin->getOption("keyOffsetX", 2);
92  mKeyOffsetY = mSkin->getOption("keyOffsetY", 2);
93  }
94 }
95 
97 {
98  BLOCK_START("ItemShortcutContainer::draw")
99  const ItemShortcut *const selShortcut = itemShortcut[mNumber];
100  if (selShortcut == nullptr)
101  {
102  BLOCK_END("ItemShortcutContainer::draw")
103  return;
104  }
105 
106  if (settings.guiAlpha != mAlpha)
107  {
108  if (mBackgroundImg != nullptr)
109  mBackgroundImg->setAlpha(mAlpha);
111  }
112 
113  Font *const font = getFont();
114  drawBackground(graphics);
115 
116  const Inventory *const inv = PlayerInfo::getInventory();
117  if (inv == nullptr)
118  {
119  BLOCK_END("ItemShortcutContainer::draw")
120  return;
121  }
122 
123  // +++ for future usage need reorder drawing images before text or back
124  for (unsigned i = 0; i < mMaxItems; i++)
125  {
126  const int itemX = (i % mGridWidth) * mBoxWidth;
127  const int itemY = (i / mGridWidth) * mBoxHeight;
128 
129  // Draw item keyboard shortcut.
130  const std::string key = inputManager.getKeyValueString(
132  font->drawString(graphics,
135  key,
136  itemX + mKeyOffsetX,
137  itemY + mKeyOffsetY);
138 
139  const int itemId = selShortcut->getItem(i);
140  const ItemColor itemColor = selShortcut->getItemColor(i);
141 
142  if (itemId < 0)
143  continue;
144 
145  // this is item
146  if (itemId < SPELL_MIN_ID)
147  {
148  const Item *const item = inv->findItem(itemId, itemColor);
149  if (item != nullptr)
150  {
151  // Draw item icon.
152  Image *const image = item->getImage();
153  if (image != nullptr)
154  {
155  std::string caption;
156  if (item->getQuantity() > 1)
157  caption = toString(item->getQuantity());
158  else if (item->isEquipped() == Equipped_true)
159  caption = "Eq.";
160 
161  image->setAlpha(1.0F);
162  graphics->drawImage(image,
163  itemX + mImageOffsetX,
164  itemY + mImageOffsetY);
165  if (item->isEquipped() == Equipped_true)
166  {
167  font->drawString(graphics,
170  caption,
171  itemX + (mBoxWidth - font->getWidth(caption)) / 2,
172  itemY + mBoxHeight - 14);
173  }
174  else
175  {
176  font->drawString(graphics,
179  caption,
180  itemX + (mBoxWidth - font->getWidth(caption)) / 2,
181  itemY + mBoxHeight - 14);
182  }
183  }
184  }
185  }
186  else if (itemId < SKILL_MIN_ID && (spellManager != nullptr))
187  { // this is magic shortcut
188  const TextCommand *const spell = spellManager
189  ->getSpellByItem(itemId);
190  if (spell != nullptr)
191  {
192  if (!spell->isEmpty())
193  {
194  Image *const image = spell->getImage();
195 
196  if (image != nullptr)
197  {
198  image->setAlpha(1.0F);
199  graphics->drawImage(image,
200  itemX + mImageOffsetX,
201  itemY + mImageOffsetY);
202  }
203  }
204 
205  font->drawString(graphics,
208  spell->getSymbol(),
209  itemX + mTextOffsetX,
210  itemY + mTextOffsetY);
211  }
212  }
213  else if (skillDialog != nullptr)
214  {
215  const SkillInfo *const skill = skillDialog->getSkill(
216  itemId - SKILL_MIN_ID);
217  if (skill != nullptr)
218  {
219  Image *const image = skill->data->icon;
220 
221  if (image != nullptr)
222  {
223  image->setAlpha(1.0F);
224  graphics->drawImage(image,
225  itemX + mImageOffsetX,
226  itemY + mImageOffsetY);
227  }
228  if (!skill->data->haveIcon)
229  {
230  font->drawString(graphics,
233  skill->data->shortName,
234  itemX + mTextOffsetX,
235  itemY + mTextOffsetY);
236  }
237  }
238  }
239  }
240  BLOCK_END("ItemShortcutContainer::draw")
241 }
242 
244 {
245  BLOCK_START("ItemShortcutContainer::draw")
246  const ItemShortcut *const selShortcut = itemShortcut[mNumber];
247  if (selShortcut == nullptr)
248  {
249  BLOCK_END("ItemShortcutContainer::draw")
250  return;
251  }
252 
253  if (settings.guiAlpha != mAlpha)
254  {
255  if (mBackgroundImg != nullptr)
256  mBackgroundImg->setAlpha(mAlpha);
258  }
259 
260  Font *const font = getFont();
261  safeDrawBackground(graphics);
262 
263  const Inventory *const inv = PlayerInfo::getInventory();
264  if (inv == nullptr)
265  {
266  BLOCK_END("ItemShortcutContainer::draw")
267  return;
268  }
269 
270  // +++ for future usage need reorder drawing images before text or back
271  for (unsigned i = 0; i < mMaxItems; i++)
272  {
273  const int itemX = (i % mGridWidth) * mBoxWidth;
274  const int itemY = (i / mGridWidth) * mBoxHeight;
275 
276  // Draw item keyboard shortcut.
277  const std::string key = inputManager.getKeyValueString(
279  font->drawString(graphics,
282  key,
283  itemX + mKeyOffsetX,
284  itemY + mKeyOffsetY);
285 
286  const int itemId = selShortcut->getItem(i);
287  const ItemColor itemColor = selShortcut->getItemColor(i);
288 
289  if (itemId < 0)
290  continue;
291 
292  // this is item
293  if (itemId < SPELL_MIN_ID)
294  {
295  const Item *const item = inv->findItem(itemId, itemColor);
296  if (item != nullptr)
297  {
298  // Draw item icon.
299  Image *const image = item->getImage();
300  if (image != nullptr)
301  {
302  std::string caption;
303  if (item->getQuantity() > 1)
304  caption = toString(item->getQuantity());
305  else if (item->isEquipped() == Equipped_true)
306  caption = "Eq.";
307 
308  image->setAlpha(1.0F);
309  graphics->drawImage(image,
310  itemX + mImageOffsetX,
311  itemY + mImageOffsetY);
312  if (item->isEquipped() == Equipped_true)
313  {
314  font->drawString(graphics,
317  caption,
318  itemX + (mBoxWidth - font->getWidth(caption)) / 2,
319  itemY + mBoxHeight - 14);
320  }
321  else
322  {
323  font->drawString(graphics,
326  caption,
327  itemX + (mBoxWidth - font->getWidth(caption)) / 2,
328  itemY + mBoxHeight - 14);
329  }
330  }
331  }
332  }
333  else if (itemId < SKILL_MIN_ID && (spellManager != nullptr))
334  { // this is magic shortcut
335  const TextCommand *const spell = spellManager
336  ->getSpellByItem(itemId);
337  if (spell != nullptr)
338  {
339  if (!spell->isEmpty())
340  {
341  Image *const image = spell->getImage();
342 
343  if (image != nullptr)
344  {
345  image->setAlpha(1.0F);
346  graphics->drawImage(image,
347  itemX + mImageOffsetX,
348  itemY + mImageOffsetY);
349  }
350  }
351 
352  font->drawString(graphics,
355  spell->getSymbol(),
356  itemX + mTextOffsetX,
357  itemY + mTextOffsetY);
358  }
359  }
360  else if (skillDialog != nullptr)
361  {
362  const SkillInfo *const skill = skillDialog->getSkill(
363  itemId - SKILL_MIN_ID);
364  if (skill != nullptr)
365  {
366  Image *const image = skill->data->icon;
367 
368  if (image != nullptr)
369  {
370  image->setAlpha(1.0F);
371  graphics->drawImage(image,
372  itemX + mImageOffsetX,
373  itemY + mImageOffsetY);
374  }
375  if (!skill->data->haveIcon)
376  {
377  font->drawString(graphics,
380  skill->data->shortName,
381  itemX + mTextOffsetX,
382  itemY + mTextOffsetY);
383  }
384  }
385  }
386  }
387  BLOCK_END("ItemShortcutContainer::draw")
388 }
389 
391 {
392  if (mNumber == SHORTCUT_AUTO_TAB)
393  return;
394  ItemShortcut *const selShortcut = itemShortcut[mNumber];
395  if (selShortcut == nullptr)
396  return;
397 
398  if (event.getButton() == MouseButton::LEFT)
399  {
400  if (dragDrop.isEmpty() && mItemClicked)
401  {
402  mItemClicked = false;
403 
404  const int index = getIndexFromGrid(event.getX(), event.getY());
405  if (index == -1)
406  return;
407 
408  const int itemId = selShortcut->getItem(index);
409  const ItemColor itemColor = selShortcut->getItemColor(index);
410 
411  if (itemId < 0)
412  return;
413 
414  event.consume();
415  if (itemId < SPELL_MIN_ID)
416  { // items
417  if (PlayerInfo::getInventory() == nullptr)
418  return;
419 
420  const Item *const item = PlayerInfo::getInventory()->findItem(
421  itemId, itemColor);
422 
423  if (item != nullptr)
424  {
425  selShortcut->removeItem(index);
427  }
428  else
429  {
430  dragDrop.clear();
431  }
432  }
433  else if (itemId < SKILL_MIN_ID)
434  { // spells/commands
435  if (spellManager == nullptr)
436  {
437  dragDrop.clear();
438  return;
439  }
440 
441  const TextCommand *const spell = spellManager->getSpellByItem(
442  itemId);
443  if (spell != nullptr)
444  {
445  selShortcut->removeItem(index);
446  dragDrop.dragCommand(spell,
448  dragDrop.setItem(itemId);
449  }
450  else
451  {
452  dragDrop.clear();
453  }
454  }
455  else
456  { // skills
457  if (skillDialog == nullptr)
458  {
459  dragDrop.clear();
460  return;
461  }
462  const SkillInfo *const skill
463  = skillDialog->getSkillByItem(itemId);
464  if (skill != nullptr)
465  {
466  const std::string itemData = selShortcut->getItemData(
467  index);
468  selShortcut->removeItem(index);
471  index);
472  dragDrop.setItem(itemId);
473  dragDrop.setItemColor(itemColor);
474  dragDrop.setItemData(itemData);
475  }
476  else
477  {
478  dragDrop.clear();
479  }
480  }
481  }
482  }
483 }
484 
486 {
487  ItemShortcut *const selShortcut = itemShortcut[mNumber];
488  if (selShortcut == nullptr)
489  return;
490 
491  const int index = getIndexFromGrid(event.getX(), event.getY());
492 
493  if (index == -1)
494  return;
495 
496  if (event.getButton() == MouseButton::LEFT)
497  {
498  event.consume();
499  // Stores the selected item if theirs one.
500  if (selShortcut->isItemSelected() && (inventoryWindow != nullptr) &&
502  || selShortcut->getSelectedItem() >= SPELL_MIN_ID))
503  {
504  selShortcut->setItem(index);
505  selShortcut->setItemSelected(-1);
506  if (spellShortcut != nullptr)
509  }
510  else if (selShortcut->getItem(index) != 0)
511  {
512  mItemClicked = true;
513  }
514  }
515  else if (event.getButton() == MouseButton::RIGHT)
516  {
517  event.consume();
518  if (popupMenu != nullptr &&
519  viewport != nullptr)
520  {
522  viewport->mMouseY,
523  selShortcut->getItem(index),
524  selShortcut->getItemColor(index));
525  }
526  }
527 }
528 
530 {
531  ItemShortcut *const selShortcut = itemShortcut[mNumber];
532  if (selShortcut == nullptr)
533  return;
534 
535  if (event.getButton() == MouseButton::LEFT)
536  {
537  if (selShortcut->isItemSelected())
538  selShortcut->setItemSelected(-1);
539 
540  const int index = getIndexFromGrid(event.getX(), event.getY());
541  if (index == -1)
542  return;
543 
544  if (dragDrop.isEmpty())
545  {
546  if ((selShortcut->getItem(index) != 0) && mItemClicked)
547  selShortcut->useItem(index);
548  }
549  else
550  {
552  {
553  const int oldIndex = dragDrop.getTag();
554  selShortcut->setItem(oldIndex, dragDrop.getItem(),
556  selShortcut->swap(oldIndex, index);
557  }
558  else
559  {
560  selShortcut->setItemData(index,
562  selShortcut->setItem(index, dragDrop.getItem(),
564  }
565  dragDrop.clear();
566  dragDrop.deselect();
567  }
568 
569  mItemClicked = false;
570  }
571 }
572 
574 {
575  const ItemShortcut *const selShortcut = itemShortcut[mNumber];
576  if (selShortcut == nullptr)
577  return;
578 
579  const int index = getIndexFromGrid(event.getX(), event.getY());
580 
581  if (index == -1)
582  return;
583 
584  const int itemId = selShortcut->getItem(index);
585  const ItemColor itemColor = selShortcut->getItemColor(index);
586 
587  if (itemId < 0)
588  return;
589 
590  if (itemId < SPELL_MIN_ID)
591  {
594 
595  Inventory *const inv = PlayerInfo::getInventory();
596  if (inv == nullptr)
597  return;
598 
599  const Item *const item = inv->findItem(itemId, itemColor);
600  if ((item != nullptr) && (viewport != nullptr))
601  {
602  itemPopup->setItem(item, false);
604  }
605  else
606  {
608  }
609  }
610  else if (itemId < SKILL_MIN_ID && (spellManager != nullptr))
611  {
614  const TextCommand *const spell = spellManager->getSpellByItem(itemId);
615  if ((spell != nullptr) && (viewport != nullptr))
616  {
617  spellPopup->setItem(spell);
619  viewport->mMouseY);
620  }
621  else
622  {
624  }
625  }
626  else if (skillDialog != nullptr)
627  {
630  const SkillInfo *const skill = skillDialog->getSkillByItem(itemId);
631  if (skill == nullptr)
632  return;
633 
634  const std::string data = selShortcut->getItemData(index);
635  CastTypeT castType = CastType::Default;
636  int offsetX = 0;
637  int offsetY = 0;
638  if (!data.empty())
639  {
640  STD_VECTOR<int> vect;
641  splitToIntVector(vect, data, ' ');
642  const size_t sz = vect.size();
643  if (sz > 0)
644  castType = static_cast<CastTypeT>(vect[0]);
645  if (sz > 2)
646  {
647  offsetX = vect[1];
648  offsetY = vect[2];
649  }
650  }
652  toInt(itemColor, int),
653  castType,
654  offsetX,
655  offsetY);
657  viewport->mMouseY);
658  }
659 }
660 
661 // Hide ItemTooltip
663 {
664  if (itemPopup != nullptr)
666  if (spellPopup != nullptr)
668  if (skillPopup != nullptr)
670 }
671 
673 {
674  if (itemPopup != nullptr)
676  if (spellPopup != nullptr)
678 }
CastType ::T CastTypeT
Definition: casttype.h:34
void dragItem(const Item *const item, const DragDropSourceT source, const int tag)
Definition: dragdrop.h:87
DragDropSourceT getSource() const
Definition: dragdrop.h:84
void deselect()
Definition: dragdrop.h:213
void setItem(const int item)
Definition: dragdrop.h:238
void dragCommand(const TextCommand *const command, const DragDropSourceT source, const int tag)
Definition: dragdrop.h:117
std::string getItemData()
Definition: dragdrop.h:81
void dragSkill(const SkillInfo *const info, const DragDropSourceT source, const int tag)
Definition: dragdrop.h:152
void setItemColor(const ItemColor color)
Definition: dragdrop.h:72
bool isEmpty() const
Definition: dragdrop.h:196
int getTag() const
Definition: dragdrop.h:235
void clear()
Definition: dragdrop.h:183
int getItem() const
Definition: dragdrop.h:66
ItemColor getItemColor() const
Definition: dragdrop.h:69
void setItemData(const std::string &data)
Definition: dragdrop.h:78
Definition: event.h:79
Definition: font.h:90
int getWidth(const std::string &text) const
Definition: font.cpp:334
void drawString(Graphics *const graphics, Color col, const Color &col2, const std::string &text, const int x, const int y)
Definition: font.cpp:254
virtual void drawImage(const Image *const image, int dstX, int dstY)=0
std::string getKeyValueString(const InputActionT index) const
Item * findItem(const int itemId, const ItemColor color) const
Definition: inventory.cpp:94
void setItem(const ItemInfo &item, const ItemColor color, const bool showImage, int id, const int *const cards, const ItemOptionsList *const options)
Definition: itempopup.cpp:189
void mouseDragged(MouseEvent &event)
void draw(Graphics *const graphics)
void setSkin(const Widget2 *const widget, Skin *const skin)
void mouseExited(MouseEvent &event)
void safeDraw(Graphics *const graphics)
ItemShortcutContainer(Widget2 *const widget, const unsigned number)
void mousePressed(MouseEvent &event)
void mouseReleased(MouseEvent &event)
void mouseMoved(MouseEvent &event)
void widgetHidden(const Event &event)
int getSelectedItem() const
Definition: itemshortcut.h:134
ItemColor getItemColor(const size_t index) const
Definition: itemshortcut.h:73
void setItemSelected(const int itemId)
Definition: itemshortcut.h:126
void setItemData(const size_t index, const std::string &data)
Definition: itemshortcut.h:76
int getItem(const size_t index) const
Definition: itemshortcut.h:70
static int getItemCount()
Definition: itemshortcut.h:86
bool isItemSelected() const
Definition: itemshortcut.h:140
void removeItem(const size_t index)
Definition: itemshortcut.h:146
void swap(const size_t index1, const size_t index2)
void setItem(const size_t index)
void useItem(const size_t index) const
std::string getItemData(const size_t index) const
Definition: itemshortcut.h:80
Definition: item.h:50
int getQuantity() const
Definition: item.h:105
Equipped isEquipped() const
Definition: item.h:129
Image * getImage() const
Definition: item.h:87
MouseButtonT getButton() const
Definition: mouseevent.h:116
int getX() const
Definition: mouseevent.h:127
int getY() const
Definition: mouseevent.h:138
void showItemPopup(const int x, const int y, const Item *const item)
Definition: popupmenu.cpp:1790
void position(const int x, const int y)
Definition: popup.cpp:235
float guiAlpha
Definition: settings.h:131
virtual void setSkin(const Widget2 *const widget, Skin *const skin)
void drawBackground(Graphics *const g)
void safeDrawBackground(Graphics *const g)
int getIndexFromGrid(const int pointX, const int pointY) const
SkillInfo * getSkill(const int id) const
SkillInfo * getSkillByItem(const int itemId) const
void show(const SkillInfo *const skill, const int level, const CastTypeT type, const int offsetX, const int offsetY)
Definition: skillpopup.cpp:106
Definition: skin.h:37
int getOption(const std::string &name) const
Definition: skin.h:106
const TextCommand * getSpellByItem(const int itemId) const
void view(const int x, const int y)
Definition: spellpopup.cpp:91
void setItem(const TextCommand *const spell)
Definition: spellpopup.cpp:63
void setItemSelected(const int itemId)
Definition: spellshortcut.h:58
bool isEmpty() const
Definition: textcommand.h:153
std::string getSymbol() const
Definition: textcommand.h:91
Image * getImage() const
Definition: textcommand.h:156
int mMouseX
Definition: viewport.h:154
int mMouseY
Definition: viewport.h:155
Color mForegroundColor2
Definition: widget2.h:113
const Color & getThemeColor(const ThemeColorIdT type, const unsigned int alpha) const A_INLINE
Definition: widget2.h:45
void setVisible(Visible visible)
Definition: widget.cpp:225
Color mForegroundColor
Definition: widget.h:1086
Font * getFont() const
Definition: widget.cpp:331
bool isWindowVisible() const
Definition: window.h:484
const size_t SHORTCUT_AUTO_TAB
Definition: itemshortcut.h:29
DragDrop dragDrop
Viewport * viewport
Definition: viewport.cpp:36
const bool Equipped_true
Definition: equipped.h:30
InputManager inputManager
#define toInt(val, name)
Definition: intdefines.h:47
InventoryWindow * inventoryWindow
uint16_t ItemColor
Definition: itemcolor.h:30
ItemPopup * itemPopup
Definition: itempopup.cpp:64
ItemShortcut * itemShortcut[SHORTCUT_TABS]
#define A_UNUSED
Definition: localconsts.h:160
uint32_t data
bool skill(InputEvent &event)
Definition: commands.cpp:97
@ Default
Definition: casttype.h:29
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
Inventory * getInventory()
Definition: playerinfo.cpp:195
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
PopupMenu * popupMenu
Definition: popupmenu.cpp:103
const int SKILL_MIN_ID
Definition: skill.h:25
Settings settings
Definition: settings.cpp:32
SkillDialog * skillDialog
Definition: skilldialog.cpp:66
SkillPopup * skillPopup
Definition: skillpopup.cpp:42
SpellManager * spellManager
SpellPopup * spellPopup
Definition: spellpopup.cpp:34
const int SPELL_MIN_ID
Definition: spells.h:27
SpellShortcut * spellShortcut
void splitToIntVector(std::vector< int > &tokens, const std::string &text, const char separator)
const bool Visible_false
Definition: visible.h:30