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-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 
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 
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 
47 
49 
50 #include "const/resources/skill.h"
51 
52 #include "utils/stringutils.h"
53 
54 #include "debug.h"
55 
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 {
68 }
69 
71 {
72 }
73 
74 void ItemShortcutContainer::setWidget2(const Widget2 *const widget)
75 {
76  Widget2::setWidget2(widget);
81  255U);
84 }
85 
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)
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(
122  font->drawString(graphics,
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,
157  caption,
158  itemX + (mBoxWidth - font->getWidth(caption)) / 2,
159  itemY + mBoxHeight - 14);
160  }
161  else
162  {
163  font->drawString(graphics,
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,
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,
215  skill->data->shortName,
216  itemX + 2,
217  itemY + mBoxHeight / 2);
218  }
219  }
220  }
221  }
222  BLOCK_END("ItemShortcutContainer::draw")
223 }
224 
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)
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(
261  font->drawString(graphics,
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,
296  caption,
297  itemX + (mBoxWidth - font->getWidth(caption)) / 2,
298  itemY + mBoxHeight - 14);
299  }
300  else
301  {
302  font->drawString(graphics,
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,
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,
354  skill->data->shortName,
355  itemX + 2,
356  itemY + mBoxHeight / 2);
357  }
358  }
359  }
360  }
361  BLOCK_END("ItemShortcutContainer::draw")
362 }
363 
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);
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,
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,
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 
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) &&
476  || selShortcut->getSelectedItem() >= SPELL_MIN_ID))
477  {
478  selShortcut->setItem(index);
479  selShortcut->setItemSelected(-1);
480  if (spellShortcut != nullptr)
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  {
496  viewport->mMouseY,
497  selShortcut->getItem(index),
498  selShortcut->getItemColor(index));
499  }
500  }
501 }
502 
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  {
526  {
527  const int oldIndex = dragDrop.getTag();
528  selShortcut->setItem(oldIndex, dragDrop.getItem(),
530  selShortcut->swap(oldIndex, index);
531  }
532  else
533  {
534  selShortcut->setItemData(index,
536  selShortcut->setItem(index, dragDrop.getItem(),
538  }
539  dragDrop.clear();
540  dragDrop.deselect();
541  }
542 
543  mItemClicked = false;
544  }
545 }
546 
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  {
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);
578  }
579  else
580  {
582  }
583  }
584  else if (itemId < SKILL_MIN_ID && (spellManager != nullptr))
585  {
588  const TextCommand *const spell = spellManager->getSpellByItem(itemId);
589  if ((spell != nullptr) && (viewport != nullptr))
590  {
591  spellPopup->setItem(spell);
593  viewport->mMouseY);
594  }
595  else
596  {
598  }
599  }
600  else if (skillDialog != nullptr)
601  {
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);
631  viewport->mMouseY);
632  }
633 }
634 
635 // Hide ItemTooltip
637 {
638  if (itemPopup != nullptr)
640  if (spellPopup != nullptr)
642  if (skillPopup != nullptr)
644 }
645 
647 {
648  if (itemPopup != nullptr)
650  if (spellPopup != nullptr)
652 }
Font * getFont() const
Definition: widget.cpp:330
void useItem(const size_t index) const
void removeItem(const size_t index)
Definition: itemshortcut.h:145
void setWidget2(const Widget2 *const widget)
void setItemSelected(const int itemId)
Definition: itemshortcut.h:125
int getTag() const
Definition: dragdrop.h:234
bool skill(InputEvent &event)
Definition: commands.cpp:96
void draw(Graphics *const graphics)
int getSelectedItem() const
Definition: itemshortcut.h:133
SkillInfo * getSkillByItem(const int itemId) const
Definition: font.h:88
SpellManager * spellManager
void clear()
Definition: dragdrop.h:182
Item * findItem(const int itemId, const ItemColor color) const
Definition: inventory.cpp:93
SkillPopup * skillPopup
Definition: skillpopup.cpp:41
void setVisible(Visible visible)
Definition: widget.cpp:224
Equipped isEquipped() const
Definition: item.h:128
MouseButtonT getButton() const
Definition: mouseevent.h:115
virtual void setWidget2(const Widget2 *const widget)
Definition: widget2.h:63
Inventory * getInventory()
Definition: playerinfo.cpp:192
#define BLOCK_START(name)
Definition: perfomance.h:78
DragDrop dragDrop
bool isItemSelected() const
Definition: itemshortcut.h:139
#define BLOCK_END(name)
Definition: perfomance.h:79
const size_t SHORTCUT_AUTO_TAB
Definition: itemshortcut.h:28
uint16_t ItemColor
Definition: itemcolor.h:29
int mMouseX
Definition: viewport.h:153
void swap(const size_t index1, const size_t index2)
SpellPopup * spellPopup
Definition: spellpopup.cpp:34
const bool Equipped_true
Definition: equipped.h:29
bool isEmpty() const
Definition: dragdrop.h:195
std::string getItemData()
Definition: dragdrop.h:80
const int SKILL_MIN_ID
Definition: skill.h:24
InventoryWindow * inventoryWindow
void show(const SkillInfo *const skill, const int level, const CastTypeT type, const int offsetX, const int offsetY)
Definition: skillpopup.cpp:105
Color mForegroundColor
Definition: widget.h:1085
Image * icon
Definition: skilldata.h:46
void dragItem(const Item *const item, const DragDropSourceT source, const int tag)
Definition: dragdrop.h:86
void setItemData(const size_t index, const std::string &data)
Definition: itemshortcut.h:75
SkillData * data
Definition: skillinfo.h:62
int getIndexFromGrid(const int pointX, const int pointY) const
void mouseReleased(MouseEvent &event)
#define toInt(val, name)
Definition: intdefines.h:46
Settings settings
Definition: settings.cpp:31
virtual void setAlpha(const float alpha)
Definition: image.cpp:285
const int SPELL_MIN_ID
Definition: spells.h:27
void mouseDragged(MouseEvent &event)
SkillInfo * getSkill(const int id) const
void safeDraw(Graphics *const graphics)
const bool Visible_false
Definition: visible.h:29
int getQuantity() const
Definition: item.h:104
void mouseExited(MouseEvent &event)
void setItemData(const std::string &data)
Definition: dragdrop.h:77
std::string getKeyValueString(const InputActionT index) const
void dragSkill(const SkillInfo *const info, const DragDropSourceT source, const int tag)
Definition: dragdrop.h:151
uint32_t data
PopupMenu * popupMenu
Definition: popupmenu.cpp:102
void position(const int x, const int y)
Definition: popup.cpp:232
void drawString(Graphics *const graphics, Color col, const Color &col2, const std::string &text, const int x, const int y)
Definition: font.cpp:253
Definition: item.h:48
void setItem(const TextCommand *const spell)
Definition: spellpopup.cpp:63
bool isWindowVisible() const
Definition: window.h:483
void setItem(const int item)
Definition: dragdrop.h:237
void setItemColor(const ItemColor color)
Definition: dragdrop.h:71
int getItem(const size_t index) const
Definition: itemshortcut.h:69
void deselect()
Definition: dragdrop.h:212
void setItemSelected(const int itemId)
Definition: spellshortcut.h:58
void setItem(const ItemInfo &item, const ItemColor color, const bool showImage, int id, const int *const cards, const ItemOptionsList *const options)
Definition: itempopup.cpp:188
void view(const int x, const int y)
Definition: spellpopup.cpp:91
ItemShortcut * itemShortcut[SHORTCUT_TABS]
void setItem(const size_t index)
int mMouseY
Definition: viewport.h:154
void drawBackground(Graphics *const g)
bool haveIcon
Definition: skilldata.h:57
SkillDialog * skillDialog
Definition: skilldialog.cpp:65
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
const TextCommand * getSpellByItem(const int itemId) const
#define A_UNUSED
Definition: localconsts.h:171
Color mForegroundColor2
Definition: widget2.h:112
Image * getImage() const
Definition: item.h:86
virtual void drawImage(const Image *const image, int dstX, int dstY)=0
std::string getSymbol() const
Definition: textcommand.h:91
int getWidth(const std::string &text) const
Definition: font.cpp:333
Definition: event.h:77
ItemColor getItemColor() const
Definition: dragdrop.h:68
Definition: image.h:61
void showItemPopup(const int x, const int y, const Item *const item)
Definition: popupmenu.cpp:1789
void safeDrawBackground(Graphics *const g)
bool isEmpty() const
Definition: textcommand.h:153
static int getItemCount()
Definition: itemshortcut.h:85
const Color & getThemeColor(const ThemeColorIdT type, const unsigned int alpha) const A_INLINE
Definition: widget2.h:44
int getX() const
Definition: mouseevent.h:126
InputManager inputManager
void splitToIntVector(std::vector< int > &tokens, const std::string &text, const char separator)
DragDropSourceT getSource() const
Definition: dragdrop.h:83
ItemPopup * itemPopup
Definition: itempopup.cpp:63
ItemShortcutContainer(Widget2 *const widget, const unsigned number)
float guiAlpha
Definition: settings.h:129
void widgetHidden(const Event &event)
std::string shortName
Definition: skilldata.h:34
std::string getItemData(const size_t index) const
Definition: itemshortcut.h:79
ItemColor getItemColor(const size_t index) const
Definition: itemshortcut.h:72
void dragCommand(const TextCommand *const command, const DragDropSourceT source, const int tag)
Definition: dragdrop.h:116
SpellShortcut * spellShortcut
void mouseMoved(MouseEvent &event)
Image * getImage() const
Definition: textcommand.h:156
void mousePressed(MouseEvent &event)
Viewport * viewport
Definition: viewport.cpp:35
int getItem() const
Definition: dragdrop.h:65
CastType ::T CastTypeT
Definition: casttype.h:33