ManaPlus
itempopup.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2008 The Legend of Mazzeroth Development Team
4  * Copyright (C) 2008-2009 The Mana World Development Team
5  * Copyright (C) 2009-2010 The Mana Developers
6  * Copyright (C) 2011-2019 The ManaPlus Developers
7  * Copyright (C) 2019-2021 Andrei Karas
8  *
9  * This file is part of The ManaPlus Client.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <http://www.gnu.org/licenses/>.
23  */
24 
25 #include "gui/popups/itempopup.h"
26 
27 #include "actormanager.h"
28 #include "configuration.h"
29 
30 #include "gui/gui.h"
31 
32 #include "gui/fonts/font.h"
33 
34 #include "gui/widgets/icon.h"
35 #include "gui/widgets/label.h"
36 #include "gui/widgets/textbox.h"
37 
38 #include "net/beinghandler.h"
39 #ifdef TMWA_SUPPORT
40 #include "net/net.h"
41 #endif // TMWA_SUPPORT
42 
43 #include "utils/foreach.h"
44 #include "utils/gettext.h"
45 #include "utils/stdmove.h"
46 
48 
49 #include "resources/iteminfo.h"
50 
52 #include "resources/db/unitsdb.h"
53 
54 #include "resources/image/image.h"
55 
56 #include "resources/item/item.h"
59 
61 
62 #include "debug.h"
63 
64 ItemPopup *itemPopup = nullptr;
65 
67  Popup("ItemPopup", "itempopup.xml"),
68  mItemName(new Label(this)),
69  mItemDesc(new TextBox(this)),
70  mItemEffect(new TextBox(this)),
71  mItemWeight(new TextBox(this)),
72  mItemCards(new TextBox(this)),
73  mItemOptions(new TextBox(this)),
74  mItemType(ItemDbType::UNUSABLE),
76  mLastName(),
77  mCardsStr(),
78  mItemOptionsStr(),
79  mLastId(0),
80  mLastColor(ItemColor_one)
81 {
82  // Item name
84  mItemName->setPosition(0, 0);
85 
86  const int fontHeight = getFont()->getHeight();
87 
88  // Item description
89  mItemDesc->setEditable(false);
90  mItemDesc->setPosition(0, fontHeight);
92  getThemeColor(ThemeColorId::POPUP, 255U),
93  getThemeColor(ThemeColorId::POPUP_OUTLINE, 255U));
94 
95  // Item effect
96  mItemEffect->setEditable(false);
97  mItemEffect->setPosition(0, 2 * fontHeight);
99  getThemeColor(ThemeColorId::POPUP, 255U),
100  getThemeColor(ThemeColorId::POPUP_OUTLINE, 255U));
101 
102  // Item weight
103  mItemWeight->setEditable(false);
104  mItemWeight->setPosition(0, 3 * fontHeight);
106  getThemeColor(ThemeColorId::POPUP, 255U),
107  getThemeColor(ThemeColorId::POPUP_OUTLINE, 255U));
108 
109  // Item cards
110  mItemCards->setEditable(false);
111  mItemCards->setPosition(0, 4 * fontHeight);
113  getThemeColor(ThemeColorId::POPUP, 255U),
114  getThemeColor(ThemeColorId::POPUP_OUTLINE, 255U));
115 
116  // Item options
117  mItemOptions->setEditable(false);
118  mItemOptions->setPosition(0, 5 * fontHeight);
120  getThemeColor(ThemeColorId::POPUP, 255U),
121  getThemeColor(ThemeColorId::POPUP_OUTLINE, 255U));
122 }
123 
125 {
126  Popup::postInit();
127  add(mItemName);
128  add(mItemDesc);
129  add(mItemEffect);
130  add(mItemWeight);
131  add(mItemCards);
132  add(mItemOptions);
133  add(mIcon);
134 
135  addMouseListener(this);
136 }
137 
139 {
140  if (mIcon != nullptr)
141  {
142  Image *const image = mIcon->getImage();
143  if (image != nullptr)
144  image->decRef();
145  }
146 }
147 
148 void ItemPopup::setItem(const Item *const item,
149  const bool showImage)
150 {
151  if (item == nullptr)
152  return;
153 
154  const ItemInfo &ii = item->getInfo();
155  setItem(ii,
156  item->getColor(),
157  showImage,
158  item->getId(),
159  item->getCards(),
160  item->getOptions());
161  if (item->getRefine() > 0)
162  {
163  mLastName = ii.getName();
164  mLastColor = item->getColor();
165  mLastId = item->getId();
166 #ifdef TMWA_SUPPORT
168  {
169  mItemName->setCaption(strprintf("%s (+%u), %d",
170  ii.getName().c_str(),
171  CAST_U32(item->getRefine()),
172  ii.getId()));
173  }
174  else
175 #endif // TMWA_SUPPORT
176  {
177  mItemName->setCaption(strprintf("%s (+%u), %d",
178  ii.getName(item->getColor()).c_str(),
179  CAST_U32(item->getRefine()),
180  ii.getId()));
181  }
183  const unsigned minWidth = mItemName->getWidth() + 8;
184  if (CAST_U32(getWidth()) < minWidth)
185  setWidth(minWidth);
186  }
187 }
188 
189 void ItemPopup::setItem(const ItemInfo &item,
190  const ItemColor color,
191  const bool showImage,
192  int id,
193  const int *const cards,
194  const ItemOptionsList *const options)
195 {
196  if (mIcon == nullptr)
197  return;
198 
199  std::string cardsStr;
200  std::string optionsStr;
201 
202  if (item.getName() == mLastName &&
203  color == mLastColor &&
204  id == mLastId)
205  {
206  cardsStr = getCardsString(cards);
207  optionsStr = getOptionsString(options);
208  if (mItemOptionsStr == optionsStr &&
209  mCardsStr == cardsStr)
210  {
211  return;
212  }
213  }
214  else
215  {
216  cardsStr = getCardsString(cards);
217  optionsStr = getOptionsString(options);
218  }
219  mItemOptionsStr = STD_MOVE(optionsStr);
220  mCardsStr = STD_MOVE(cardsStr);
221 
222  if (id == -1)
223  id = item.getId();
224 
225  int space = 0;
226 
227  Image *const oldImage = mIcon->getImage();
228  if (oldImage != nullptr)
229  oldImage->decRef();
230 
231  if (showImage)
232  {
233  Image *const image = Loader::getImage(combineDye2(
234  pathJoin(paths.getStringValue("itemIcons"),
235  item.getDisplay().image),
236  item.getDyeIconColorsString(color)));
237 
238  mIcon->setImage(image);
239  if (image != nullptr)
240  {
241  mIcon->setPosition(0, 0);
242  space = mIcon->getWidth();
243  }
244  }
245  else
246  {
247  mIcon->setImage(nullptr);
248  }
249 
250  mItemType = item.getType();
251 
252  mLastName = item.getName();
253  mLastColor = color;
254  mLastId = id;
255 
256 #ifdef TMWA_SUPPORT
258  {
259  mItemName->setCaption(strprintf("%s, %d",
260  item.getName().c_str(), id));
262  }
263  else
264 #endif // TMWA_SUPPORT
265  {
266  mItemName->setCaption(strprintf("%s, %d",
267  item.getName(color).c_str(), id));
268  mItemDesc->setTextWrapped(item.getDescription(color), 196);
269  }
270 
273  mItemName->setPosition(space, 0);
274 
275  mItemEffect->setTextWrapped(item.getEffect(), 196);
276  // TRANSLATORS: popup label
277  mItemWeight->setTextWrapped(strprintf(_("Weight: %s"),
278  UnitsDb::formatWeight(item.getWeight()).c_str()), 196);
281 
282  int minWidth = mItemName->getWidth() + space;
283 
284  if (mItemName->getWidth() + space > minWidth)
285  minWidth = mItemName->getWidth() + space;
286  if (mItemDesc->getMinWidth() > minWidth)
287  minWidth = mItemDesc->getMinWidth();
288  if (mItemEffect->getMinWidth() > minWidth)
289  minWidth = mItemEffect->getMinWidth();
290  if (mItemWeight->getMinWidth() > minWidth)
291  minWidth = mItemWeight->getMinWidth();
292  if (mItemCards->getMinWidth() > minWidth)
293  minWidth = mItemCards->getMinWidth();
294  if (mItemOptions->getMinWidth() > minWidth)
295  minWidth = mItemOptions->getMinWidth();
296 
297  const int numRowsDesc = mItemDesc->getNumberOfRows();
298  const int numRowsWeight = mItemWeight->getNumberOfRows();
299  const int numRowsCards = mItemCards->getNumberOfRows();
300  const int numRowsOptions = mItemOptions->getNumberOfRows();
301  const int height = getFont()->getHeight();
302 
303  if (item.getEffect().empty())
304  {
305  setContentSize(minWidth,
306  (numRowsDesc + 2 + numRowsWeight + numRowsCards + numRowsOptions) *
307  height);
308  mItemWeight->setPosition(0, (numRowsDesc + 2) * height);
309  mItemCards->setPosition(0, (numRowsDesc + numRowsWeight + 2) * height);
311  (numRowsDesc + numRowsWeight + numRowsCards + 2) * height);
312  }
313  else
314  {
315  const int numRowsEffect = mItemEffect->getNumberOfRows();
316  setContentSize(minWidth, (numRowsDesc + numRowsEffect + 2
317  + numRowsWeight + numRowsCards + numRowsOptions) * height);
318  mItemEffect->setPosition(0, (numRowsDesc + 2) * height);
319  mItemWeight->setPosition(0, (numRowsDesc + numRowsEffect + 2)
320  * height);
321  mItemCards->setPosition(0, (numRowsDesc + numRowsEffect
322  + numRowsWeight + 2) * height);
323  mItemOptions->setPosition(0, (numRowsDesc + numRowsEffect
324  + numRowsWeight + numRowsCards + 2) * height);
325  }
326 
327  mItemDesc->setPosition(0, 2 * height);
328 }
329 
330 std::string ItemPopup::getCardsString(const int *const cards)
331 {
332  if (cards == nullptr)
333  return std::string();
334 
335  std::string label;
336 
337  switch (cards[0])
338  {
339  case CARD0_CREATE: // named item
340  {
341  const int32_t charId = cards[2] + 65536 * cards[3];
342  std::string name = actorManager->findCharById(charId);
343  if (name.empty())
344  {
345  name = toString(charId);
347  mLastId = 0; // allow recreate popup with same data
348  }
349  // TRANSLATORS: named item description
350  label.append(strprintf(_("Item named: %s"), name.c_str()));
351  return label;
352  }
353  case CARD0_FORGE: // forged item
354  case CARD0_PET:
355  {
356  return label;
357  }
358  default:
359  {
360  for (int f = 0; f < maxCards; f ++)
361  {
362  const int id = cards[f];
363  if (id != 0)
364  {
365  if (!label.empty())
366  label.append(" / ");
367  const ItemInfo &info = ItemDB::get(id);
368  label.append(info.getName());
369  }
370  }
371  if (label.empty())
372  return label;
373  // TRANSLATORS: popup label
374  return _("Cards: ") + label;
375  }
376  }
377 }
378 
379 std::string ItemPopup::getOptionsString(const ItemOptionsList *const options)
380 {
381  if (options == nullptr || translator == nullptr)
382  return std::string();
383  const size_t sz = options->size();
384  std::string effect;
385  for (size_t f = 0; f < sz; f ++)
386  {
387  const ItemOption &option = options->get(f);
388  if (option.index == 0)
389  continue;
390  const STD_VECTOR<ItemFieldType*> &fields = ItemOptionDb::getFields(
391  option.index);
392  if (fields.empty())
393  continue;
394  const std::string valueStr = toString(option.value);
395  FOR_EACH (STD_VECTOR<ItemFieldType*>::const_iterator, it, fields)
396  {
397  const ItemFieldType *const field = *it;
398  std::string value = valueStr;
399  if (!effect.empty())
400  effect.append(" / ");
401  if (field->sign && value[0] != '-')
402  value = std::string("+").append(value);
403  const std::string format = translator->getStr(field->description);
404  effect.append(strprintf(format.c_str(),
405  value.c_str()));
406  }
407  }
408  if (effect.empty())
409  return effect;
410  // TRANSLATORS: popup label
411  return _("Options: ") + effect;
412 }
413 
414 #define caseSetColor(name1, name2) \
415  case name1: \
416  { \
417  return label->setForegroundColorAll( \
418  getThemeColor(name2, 255U), \
419  getThemeColor(name2##_OUTLINE, 255U)); \
420  }
422  const ItemDbTypeT type) const
423 {
424  switch (type)
425  {
426  caseSetColor(ItemDbType::UNUSABLE, ThemeColorId::GENERIC)
429  ThemeColorId::ONEHAND)
431  ThemeColorId::TWOHAND)
432  caseSetColor(ItemDbType::EQUIPMENT_TORSO, ThemeColorId::TORSO)
433  caseSetColor(ItemDbType::EQUIPMENT_ARMS, ThemeColorId::ARMS)
434  caseSetColor(ItemDbType::EQUIPMENT_HEAD, ThemeColorId::HEAD)
435  caseSetColor(ItemDbType::EQUIPMENT_LEGS, ThemeColorId::LEGS)
436  caseSetColor(ItemDbType::EQUIPMENT_SHIELD, ThemeColorId::SHIELD)
437  caseSetColor(ItemDbType::EQUIPMENT_RING, ThemeColorId::RING)
438  caseSetColor(ItemDbType::EQUIPMENT_NECKLACE, ThemeColorId::NECKLACE)
439  caseSetColor(ItemDbType::EQUIPMENT_FEET, ThemeColorId::FEET)
440  caseSetColor(ItemDbType::EQUIPMENT_AMMO, ThemeColorId::AMMO)
441  caseSetColor(ItemDbType::EQUIPMENT_CHARM, ThemeColorId::CHARM)
442  caseSetColor(ItemDbType::SPRITE_RACE, ThemeColorId::UNKNOWN_ITEM)
443  caseSetColor(ItemDbType::SPRITE_HAIR, ThemeColorId::UNKNOWN_ITEM)
445  default:
446  {
447  return label->setForegroundColorAll(
448  getThemeColor(ThemeColorId::UNKNOWN_ITEM, 255U),
449  getThemeColor(ThemeColorId::UNKNOWN_ITEM_OUTLINE, 255U));
450  }
451  }
452 }
453 #undef caseSetColor
454 
456 {
457  Popup::mouseMoved(event);
458 
459  // When the mouse moved on top of the popup, hide it
461  resetPopup();
462 }
463 
465 {
466  mLastName.clear();
468  mLastId = 0;
469 }
ActorManager * actorManager
const bool AutoRelease_false
Definition: autorelease.h:30
Net::BeingHandler * beingHandler
Definition: net.cpp:99
#define CARD0_CREATE
Definition: cards.h:29
#define maxCards
Definition: cards.h:25
#define CARD0_PET
Definition: cards.h:30
#define CARD0_FORGE
Definition: cards.h:28
#define CAST_U32
Definition: cast.h:31
std::string findCharById(const int32_t id)
virtual void add(Widget *const widget)
std::string getStringValue(const std::string &key) const
int getHeight() const
Definition: font.cpp:362
Definition: icon.h:41
Image * getImage() const
Definition: icon.h:64
void setImage(Image *const image)
Definition: icon.cpp:74
const std::string & getDescription() const
Definition: iteminfo.h:100
int getId() const
Definition: iteminfo.h:68
const std::string & getName() const
Definition: iteminfo.h:74
int getWeight() const
Definition: iteminfo.h:133
ItemDbTypeT getType() const
Definition: iteminfo.h:127
const SpriteDisplay & getDisplay() const
Definition: iteminfo.h:94
const std::string & getEffect() const
Definition: iteminfo.h:109
std::string getDyeIconColorsString(const ItemColor color) const
Definition: iteminfo.cpp:240
Icon * mIcon
Definition: itempopup.h:92
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
std::string mLastName
Definition: itempopup.h:93
TextBox * mItemCards
Definition: itempopup.h:89
Label * mItemName
Definition: itempopup.h:85
static std::string getOptionsString(const ItemOptionsList *const options)
Definition: itempopup.cpp:379
void postInit()
Definition: itempopup.cpp:124
void setLabelColor(Label *label, const ItemDbTypeT type) const
Definition: itempopup.cpp:421
void resetPopup()
Definition: itempopup.cpp:464
ItemDbTypeT mItemType
Definition: itempopup.h:91
TextBox * mItemDesc
Definition: itempopup.h:86
ItemColor mLastColor
Definition: itempopup.h:97
int mLastId
Definition: itempopup.h:96
std::string getCardsString(const int *const cards)
Definition: itempopup.cpp:330
TextBox * mItemWeight
Definition: itempopup.h:88
void mouseMoved(MouseEvent &event)
Definition: itempopup.cpp:455
std::string mCardsStr
Definition: itempopup.h:94
std::string mItemOptionsStr
Definition: itempopup.h:95
TextBox * mItemEffect
Definition: itempopup.h:87
TextBox * mItemOptions
Definition: itempopup.h:90
Definition: item.h:50
uint8_t getRefine() const
Definition: item.h:141
const ItemOptionsList * getOptions() const
Definition: item.h:219
int getId() const
Definition: item.h:81
ItemColor getColor() const
Definition: item.h:181
const int * getCards() const
Definition: item.h:214
const ItemInfo & getInfo() const
Definition: item.h:171
Definition: label.h:91
void adjustSize()
Definition: label.cpp:200
void setForegroundColorAll(const Color &color1, const Color &color2)
Definition: label.cpp:217
void setCaption(const std::string &caption)
Definition: label.cpp:264
virtual void requestNameByCharId(const int id) const =0
const std::string getStr(const std::string &str)
Definition: podict.cpp:45
Definition: popup.h:52
void setContentSize(int width, int height)
Definition: popup.cpp:155
void mouseMoved(MouseEvent &event)
Definition: popup.cpp:255
void postInit()
Definition: popup.h:177
void setEditable(const bool editable)
Definition: textbox.cpp:650
unsigned int getNumberOfRows() const
Definition: textbox.h:162
void setForegroundColorAll(const Color &color1, const Color &color2)
Definition: textbox.cpp:488
int getMinWidth() const
Definition: textbox.h:108
void setTextWrapped(const std::string &text, const int minDimension)
Definition: textbox.cpp:109
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
void setWidth(const int width)
Definition: widget.cpp:133
void addMouseListener(MouseListener *const mouseListener)
Definition: widget.cpp:292
void setFont(Font *const font)
Definition: widget.cpp:349
Font * getFont() const
Definition: widget.cpp:331
void setPosition(const int x, const int y)
Definition: widget.cpp:161
int getWidth() const
Definition: widget.h:221
Configuration paths
#define new
Definition: debug_new.h:147
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define _(s)
Definition: gettext.h:35
Font * boldFont
Definition: gui.cpp:112
const ItemColor ItemColor_one
Definition: itemcolor.h:30
uint16_t ItemColor
Definition: itemcolor.h:30
ItemDbType ::T ItemDbTypeT
Definition: itemdbtype.h:49
#define caseSetColor(name1, name2)
Definition: itempopup.cpp:414
ItemPopup * itemPopup
Definition: itempopup.cpp:64
#define nullptr
Definition: localconsts.h:45
bool info(InputEvent &event)
Definition: commands.cpp:57
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
@ EQUIPMENT_HEAD
Definition: itemdbtype.h:38
@ EQUIPMENT_RING
Definition: itemdbtype.h:41
@ EQUIPMENT_LEGS
Definition: itemdbtype.h:39
@ EQUIPMENT_TWO_HANDS_WEAPON
Definition: itemdbtype.h:34
@ EQUIPMENT_FEET
Definition: itemdbtype.h:43
@ EQUIPMENT_AMMO
Definition: itemdbtype.h:44
@ EQUIPMENT_SHIELD
Definition: itemdbtype.h:40
@ EQUIPMENT_ONE_HAND_WEAPON
Definition: itemdbtype.h:33
@ EQUIPMENT_CHARM
Definition: itemdbtype.h:45
@ EQUIPMENT_TORSO
Definition: itemdbtype.h:35
@ EQUIPMENT_ARMS
Definition: itemdbtype.h:36
@ EQUIPMENT_NECKLACE
Definition: itemdbtype.h:42
const std::vector< ItemFieldType * > & getFields(const int id)
Image * getImage(const std::string &idPath)
Definition: imageloader.cpp:86
ServerTypeT getNetworkType()
Definition: net.cpp:189
std::string formatWeight(const int value)
Definition: unitsdb.cpp:352
PoDict * translator
Definition: podict.cpp:28
#define STD_MOVE(var)
Definition: stdmove.h:28
std::string strprintf(const char *const format,...)
std::string combineDye2(std::string file, const std::string &dye)
std::string pathJoin(std::string str1, const std::string &str2)
const bool sign
Definition: itemfieldtype.h:43
const std::string description
Definition: itemfieldtype.h:42
uint16_t index
Definition: itemoption.h:36
int16_t value
Definition: itemoption.h:37
const ItemOption & get(const size_t index) const
size_t size() const
std::string image
Definition: spritedisplay.h:45
const bool Visible_false
Definition: visible.h:30