ManaPlus
windowmenu.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-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 
24 #include "gui/windowmenu.h"
25 
26 #include "configuration.h"
27 #include "settings.h"
28 
29 #include "input/inputmanager.h"
30 
31 #include "gui/buttoninfo.h"
32 #include "gui/buttontext.h"
33 #include "gui/popupmanager.h"
34 #include "gui/skin.h"
35 
36 #include "gui/popups/popupmenu.h"
37 #include "gui/popups/textpopup.h"
38 
40 
41 #include "gui/widgets/button.h"
42 
43 #include "utils/dtor.h"
44 #include "utils/foreach.h"
45 #include "utils/gettext.h"
46 
47 #include "resources/imageset.h"
48 
49 #include "debug.h"
50 
52 
53 WindowMenu::WindowMenu(const Widget2 *const widget) :
54  Container(widget),
58  MouseListener(),
59  mSkin(theme != nullptr ? theme->load("windowmenu.xml", "",
60  true, Theme::getThemePath()) : nullptr),
61  mImageSet(nullptr),
62  mPadding(mSkin != nullptr ? mSkin->getPadding() : 1),
63  mSpacing(mSkin != nullptr ? mSkin->getOption("spacing", 3) : 3),
64  mButtons(),
65  mButtonTexts(),
66  mButtonNames(),
67  mHaveMouse(false),
68  mAutoHide(1),
69  mSmallWindow(mainGraphics->getWidth() < 600)
70 {
71  int x = mPadding;
72  int h = 0;
73 
74  setFocusable(false);
75 
77  {
78  mImageSet = Theme::getImageSetFromTheme("buttonsicons.png",
79  mSkin->getOption("imageWidth", 20),
80  mSkin->getOption("imageHeight", 20));
81  }
82 
83  // TRANSLATORS: short button name for who is online window.
84  addButton(N_("ONL"),
85  13,
86  // TRANSLATORS: long button name for who is online window.
87  _("Who is online"), x, h, InputAction::WINDOW_ONLINE,
88  Visible_true);
89  // TRANSLATORS: short button name for help window.
90  addButton(N_("HLP"),
91  0,
92  // TRANSLATORS: long button name for help window.
93  _("Help"), x, h, InputAction::WINDOW_HELP,
94  Visible_true);
95  // TRANSLATORS: short button name for quests window.
96  addButton(N_("QE"),
97  12,
98  // TRANSLATORS: long button name for quests window.
99  _("Quests"), x, h, InputAction::WINDOW_QUESTS,
100  Visible_true);
101  // TRANSLATORS: short button name for kill stats window.
102  addButton(N_("KS"),
103  16,
104  // TRANSLATORS: long button name for kill stats window.
105  _("Kill stats"), x, h, InputAction::WINDOW_KILLS,
106  Visible_true);
107  addButton(":-)",
108  6,
109  // TRANSLATORS: long button name for emotes window.
110  _("Smilies"), x, h, InputAction::WINDOW_EMOTE_SHORTCUT,
111  Visible_true);
112  // TRANSLATORS: short button name for chat window.
113  addButton(N_("CH"),
114  20,
115  // TRANSLATORS: longt button name for chat window.
116  _("Chat"), x, h, InputAction::WINDOW_CHAT,
117 #ifdef ANDROID
118  Visible_true);
119 #else // ANDROID
120  Visible_false);
121 #endif // ANDROID
122 
123  // TRANSLATORS: short button name for status window.
124  addButton(N_("STA"),
125  17,
126  // TRANSLATORS: long button name for status window.
127  _("Status"), x, h, InputAction::WINDOW_STATUS,
128  Visible_true);
129  // TRANSLATORS: short button name for equipment window.
130  addButton(N_("EQU"),
131  7,
132  // TRANSLATORS: long button name for equipment window.
133  _("Equipment"), x, h, InputAction::WINDOW_EQUIPMENT,
134  Visible_true);
135  // TRANSLATORS: short button name for inventory window.
136  addButton(N_("INV"),
137  9,
138  // TRANSLATORS: long button name for inventory window.
139  _("Inventory"), x, h, InputAction::WINDOW_INVENTORY,
140  Visible_true);
141  // TRANSLATORS: short button name for cart window.
142  addButton(N_("CA"),
143  11,
144  // TRANSLATORS: long button name for cart window.
145  _("Cart"), x, h, InputAction::WINDOW_CART,
146  Visible_true);
147  // TRANSLATORS: short button name for map window.
148  addButton(N_("MAP"),
149  19,
150  // TRANSLATORS: long button name for map window.
151  _("Map"), x, h, InputAction::WINDOW_MINIMAP,
152  Visible_false);
153 
154  if (skillDialog->hasSkills())
155  {
156  // TRANSLATORS: short button name for skills window.
157  addButton(N_("SKI"),
158  5,
159  // TRANSLATORS: long button name for skills window.
160  _("Skills"), x, h, InputAction::WINDOW_SKILL,
161  Visible_true);
162  }
163 
164  // TRANSLATORS: short button name for social window.
165  addButton(N_("SOC"),
166  1,
167  // TRANSLATORS: long button name for social window.
168  _("Social"), x, h, InputAction::WINDOW_SOCIAL,
169  Visible_true);
170  // TRANSLATORS: short button name for shortcuts window.
171  addButton(N_("SH"),
172  14,
173  // TRANSLATORS: long button name for shortcuts window.
174  _("Shortcuts"), x, h, InputAction::WINDOW_SHORTCUT,
175  Visible_true);
176  // TRANSLATORS: short button name for spells window.
177  addButton(N_("SP"),
178  15,
179  // TRANSLATORS: long button name for spells window.
180  _("Spells"), x, h, InputAction::WINDOW_SPELLS,
181  Visible_true);
182  // TRANSLATORS: short button name for drops window.
183  addButton(N_("DR"),
184  26,
185  // TRANSLATORS: long button name for drops window.
186  _("Drop"), x, h, InputAction::WINDOW_DROP,
187  Visible_false);
188  // TRANSLATORS: short button name for did you know window.
189  addButton(N_("YK"),
190  24,
191  // TRANSLATORS: long button name for did you know window.
192  _("Did you know"), x, h, InputAction::WINDOW_DIDYOUKNOW,
193  Visible_false);
194  // TRANSLATORS: short button name for shop window.
195  addButton(N_("SHP"),
196  18,
197  // TRANSLATORS: long button name for shop window.
198  _("Shop"), x, h, InputAction::WINDOW_SHOP,
199  Visible_false);
200  // TRANSLATORS: short button name for outfits window.
201  addButton(N_("OU"),
202  21,
203  // TRANSLATORS: long button name for outfits window.
204  _("Outfits"), x, h, InputAction::WINDOW_OUTFIT,
205  Visible_false);
206  // TRANSLATORS: short button name for updates window.
207  addButton(N_("UP"),
208  25,
209  // TRANSLATORS: long button name for updates window.
210  _("Updates"), x, h, InputAction::WINDOW_UPDATER,
211  Visible_false);
212  // TRANSLATORS: short button name for bank window.
213  addButton(N_("BA"),
214  2,
215  // TRANSLATORS: long button name for bank window.
216  _("Bank"), x, h, InputAction::WINDOW_BANK,
217  Visible_true);
218  // TRANSLATORS: short button name for mail window.
219  addButton(N_("MA"),
220  10,
221  // TRANSLATORS: long button name for mail window.
222  _("Mail"), x, h, InputAction::WINDOW_MAIL,
223  Visible_true);
224  // TRANSLATORS: short button name for clan window.
225  addButton(N_("CL"),
226  4,
227  // TRANSLATORS: long button name for clan window.
228  _("Clan"), x, h, InputAction::WINDOW_CLAN,
229  Visible_true);
230  // TRANSLATORS: short button name for server info window.
231  addButton(N_("SI"),
232  8,
233  // TRANSLATORS: long button name for server info window.
234  _("Server info"), x, h, InputAction::WINDOW_SERVER_INFO,
235  Visible_true);
236  // TRANSLATORS: short button name for debug window.
237  addButton(N_("DBG"),
238  22,
239  // TRANSLATORS: long button name for debug window.
240  _("Debug"), x, h, InputAction::WINDOW_DEBUG,
241 #ifdef ANDROID
242  Visible_true);
243 #else // ANDROID
244  Visible_false);
245 #endif // ANDROID
246 
247  // TRANSLATORS: short button name for windows list menu.
248  addButton(N_("WIN"),
249  23,
250  // TRANSLATORS: long button name for windows list menu.
251  _("Windows"), x, h, InputAction::SHOW_WINDOWS,
252  Visible_false);
253  // TRANSLATORS: short button name for setup window.
254  addButton(N_("SET"),
255  3,
256  // TRANSLATORS: long button name for setup window.
257  _("Setup"), x, h, InputAction::WINDOW_SETUP,
258  Visible_true);
259 
260  x += mPadding - mSpacing;
261  if (mainGraphics != nullptr)
262  setDimension(Rect(mainGraphics->mWidth - x, 0, x, h));
263 
264  loadButtons();
265 
266  addMouseListener(this);
268 
269  config.addListener("autohideButtons", this);
270  mAutoHide = config.getIntValue("autohideButtons");
271 }
272 
274 {
275  config.removeListener("autohideButtons", this);
277 
278  for (std::map <std::string, ButtonInfo*>::iterator
279  it = mButtonNames.begin(),
280  it_fend = mButtonNames.end(); it != it_fend; ++it)
281  {
282  delete (*it).second;
283  }
284  mButtonNames.clear();
285  FOR_EACH (STD_VECTOR <Button*>::iterator, it, mButtons)
286  {
287  Button *const btn = *it;
288  if (btn == nullptr)
289  continue;
290  if (btn->mVisible == Visible_false)
291  delete btn;
292  }
294  mButtonTexts.clear();
295  if (mImageSet != nullptr)
296  {
297  mImageSet->decRef();
298  mImageSet = nullptr;
299  }
300  if (mSkin != nullptr)
301  {
302  if (theme != nullptr)
303  theme->unload(mSkin);
304  mSkin = nullptr;
305  }
306 }
307 
308 void WindowMenu::action(const ActionEvent &event)
309 {
310  const std::string &eventId = event.getId();
311  const std::map <std::string, ButtonInfo*>::iterator
312  it = mButtonNames.find(eventId);
313  if (it == mButtonNames.end())
314  return;
315 
316  const ButtonInfo *const info = (*it).second;
317  if (info == nullptr)
318  return;
319 
321 }
322 
323 void WindowMenu::addButton(const char *const text,
324  const int iconNumber,
325  const std::string &description,
326  int &restrict x,
327  int &restrict h,
328  const InputActionT key,
329  const Visible visible)
330 {
331  Button *btn = nullptr;
333  mImageSet)
334  {
335  Image *const image = mImageSet->get(iconNumber);
336  if (image != nullptr)
337  {
338 /*
339  btn = new Button(this,
340  "buttonsicons.png",
341  20,
342  20,
343  text,
344  BUTTON_SKIN,
345  this);
346 */
347  btn = new Button(this,
348  std::string(),
349  text,
350  BUTTON_SKIN,
351  this);
352  btn->setImage(image);
353  btn->adjustSize();
354  }
355  }
356  if (btn == nullptr)
357  {
358  btn = new Button(this,
359  gettext(text),
360  text,
361  BUTTON_SKIN,
362  this);
363  }
364  btn->setPosition(x, mPadding);
365  btn->setDescription(description);
366  btn->setTag(CAST_S32(key));
367  add(btn);
368  btn->setFocusable(false);
369  x += btn->getWidth() + mSpacing;
370  h = btn->getHeight() + 2 * mPadding;
371  mButtons.push_back(btn);
372  mButtonNames[text] = new ButtonInfo(btn, key, visible);
373  if (key != InputAction::SHOW_WINDOWS)
374  mButtonTexts.push_back(new ButtonText(description, key));
375 }
376 
378 {
379  if (popupManager == nullptr)
380  return;
381 
382  if (event.getButton() == MouseButton::RIGHT)
383  {
384  if (mSmallWindow)
385  return;
386 
387  event.consume();
388  Button *const btn = dynamic_cast<Button*>(event.getSource());
389  if (btn == nullptr)
390  return;
391  if (popupMenu != nullptr)
392  {
393  popupMenu->showPopup(getX() + event.getX(),
394  getY() + event.getY(), btn);
395  }
396  }
397 }
398 
400 {
401  mHaveMouse = true;
402 
403  if (textPopup == nullptr)
404  return;
405 
406  if (event.getSource() == this)
407  {
408  textPopup->hide();
409  return;
410  }
411 
412  const Button *const btn = dynamic_cast<const Button *>(
413  event.getSource());
414 
415  if (btn == nullptr)
416  {
417  textPopup->hide();
418  return;
419  }
420 
421  const int x = event.getX();
422  const int y = event.getY();
423  const InputActionT key = static_cast<InputActionT>(btn->getTag());
424  const Rect &rect = mDimension;
425  if (key != InputAction::NO_VALUE)
426  {
427  textPopup->show(x + rect.x, y + rect.y, btn->getDescription(),
428  // TRANSLATORS: short key name
430  key).c_str()));
431  }
432  else
433  {
434  textPopup->show(x + rect.x, y + rect.y, btn->getDescription());
435  }
436 }
437 
439 {
440  mHaveMouse = false;
441  if (textPopup == nullptr)
442  return;
443 
444  textPopup->hide();
445 }
446 
447 void WindowMenu::showButton(const std::string &name,
448  const Visible visible)
449 {
450  const ButtonInfo *const info = mButtonNames[name];
451  if ((info == nullptr) || (info->button == nullptr))
452  return;
453 
454  info->button->setVisible(visible);
455  updateButtons();
456  saveButtons();
457 }
458 
460 {
461  int x = mPadding;
462  int h = 0;
463  FOR_EACH (STD_VECTOR <Button*>::const_iterator, it, mButtons)
464  safeRemove(*it);
465  const int pad2 = 2 * mPadding;
466  FOR_EACH (STD_VECTOR <Button*>::iterator, it, mButtons)
467  {
468  Button *const btn = *it;
469  if (btn == nullptr)
470  continue;
471  if (btn->mVisible == Visible_true)
472  {
473  btn->setPosition(x, mPadding);
474  add(btn);
475  x += btn->getWidth() + mSpacing;
476  h = btn->getHeight() + pad2;
477  }
478  }
479  x += mPadding - mSpacing;
480  if (mainGraphics != nullptr)
481  setDimension(Rect(mainGraphics->mWidth - x, 0, x, h));
482 }
483 
485 {
486  if (!mSmallWindow)
487  {
488  if (config.getValue("windowmenu0", "").empty())
489  {
490  for (std::map <std::string, ButtonInfo*>::iterator
491  it = mButtonNames.begin(),
492  it_fend = mButtonNames.end(); it != it_fend; ++it)
493  {
494  const ButtonInfo *const info = (*it).second;
495  if (info == nullptr ||
496  info->button == nullptr ||
497  info->visible == Visible_true)
498  {
499  continue;
500  }
501  info->button->setVisible(Visible_false);
502  }
503  updateButtons();
504  return;
505  }
506 
507  for (int f = 0; f < 30; f ++)
508  {
509  const std::string str = config.getValue(
510  "windowmenu" + toString(f), "");
511  if (str.empty() || str == "SET")
512  continue;
513  const ButtonInfo *const info = mButtonNames[str];
514  if ((info == nullptr) || (info->button == nullptr))
515  continue;
516  info->button->setVisible(Visible_false);
517  }
518  }
519  else
520  {
521  for (std::map <std::string, ButtonInfo*>::iterator
522  it = mButtonNames.begin(),
523  it_fend = mButtonNames.end(); it != it_fend; ++it)
524  {
525  const ButtonInfo *const info = (*it).second;
526  if ((info == nullptr) || (info->button == nullptr))
527  continue;
528  Button *const button = info->button;
529  const std::string &str = button->getActionEventId();
530  button->setVisible(fromBool(
531  str == "SET" || str == "WIN", Visible));
532  }
533  }
534  updateButtons();
535 }
536 
538 {
539  int i = 0;
540  FOR_EACH (STD_VECTOR <Button*>::const_iterator, it, mButtons)
541  {
542  const Button *const btn = *it;
543  if ((btn != nullptr) && btn->mVisible == Visible_false)
544  {
545  config.setValue("windowmenu" + toString(i),
546  btn->getActionEventId());
547  i ++;
548  }
549  }
550  for (int f = i; f < 30; f ++)
551  config.deleteKey("windowmenu" + toString(f));
552 }
553 
554 void WindowMenu::drawChildren(Graphics *const graphics)
555 {
556  if (mHaveMouse ||
557  mAutoHide == 0 ||
558  (mAutoHide == 1 &&
559  mainGraphics != nullptr &&
560  (mSmallWindow || mainGraphics->mWidth > 800)))
561  {
562  Container::drawChildren(graphics);
563  }
564 }
565 
567 {
568  if (mHaveMouse ||
569  mAutoHide == 0 ||
570  (mAutoHide == 1 &&
571  mainGraphics != nullptr &&
572  (mSmallWindow || mainGraphics->mWidth > 800)))
573  {
574  Container::safeDrawChildren(graphics);
575  }
576 }
577 
578 void WindowMenu::optionChanged(const std::string &name)
579 {
580  if (name == "autohideButtons")
581  mAutoHide = config.getIntValue("autohideButtons");
582 }
583 
584 #ifdef USE_PROFILER
586 {
587  BLOCK_START("WindowMenu::logicChildren")
590 }
591 #endif // USE_PROFILER
#define fromBool(val, name)
Definition: booldefines.h:49
const std::string BUTTON_SKIN
Definition: button.h:89
#define CAST_S32
Definition: cast.h:30
virtual void add(Widget *const widget)
virtual void safeDrawChildren(Graphics *const graphics)
virtual void logicChildren()
virtual void drawChildren(Graphics *const graphics)
Definition: button.h:102
void setImage(Image *const image)
Definition: button.cpp:379
std::string getDescription() const
Definition: button.h:168
void setDescription(const std::string &text)
Definition: button.h:165
void setTag(int tag)
Definition: button.h:174
void adjustSize()
Definition: button.cpp:799
int getTag() const
Definition: button.h:177
std::string getValue(const std::string &key, const std::string &deflt) const
void deleteKey(const std::string &key)
void addListener(const std::string &key, ConfigListener *const listener)
void setValue(const std::string &key, const std::string &value)
void removeListener(const std::string &key, ConfigListener *const listener)
int getIntValue(const std::string &key) const
bool safeRemove(Widget *const widget)
Definition: container.cpp:49
Widget * getSource() const
Definition: event.h:104
int mWidth
Definition: graphics.h:484
Image * get(const size_type i) const
Definition: imageset.cpp:67
void executeAction(const InputActionT keyNum)
std::string getKeyValueString(const InputActionT index) const
MouseButtonT getButton() const
Definition: mouseevent.h:116
void showPopup(const int x, const int y, const Being *const being)
Definition: popupmenu.cpp:203
void hide()
Definition: popup.cpp:265
Definition: rect.h:74
int y
Definition: rect.h:214
int x
Definition: rect.h:209
virtual void decRef()
Definition: resource.cpp:50
bool showButtonIcons
Definition: settings.h:166
bool hasSkills() const
Definition: skilldialog.h:119
int getOption(const std::string &name) const
Definition: skin.h:106
void show(const int x, const int y, const std::string &str1)
Definition: textpopup.h:57
Definition: theme.h:55
void unload(Skin *const skin)
Definition: theme.cpp:250
static ImageSet * getImageSetFromTheme(const std::string &path, const int w, const int h)
Definition: theme.cpp:660
void setVisible(Visible visible)
Definition: widget.cpp:225
void setFocusable(const bool focusable)
Definition: widget.cpp:192
Rect mDimension
Definition: widget.h:1101
void addMouseListener(MouseListener *const mouseListener)
Definition: widget.cpp:292
int getY() const
Definition: widget.h:288
void setDimension(const Rect &dimension)
Definition: widget.cpp:169
Visible mVisible
Definition: widget.h:963
void setPosition(const int x, const int y)
Definition: widget.cpp:161
int getX() const
Definition: widget.h:269
int getHeight() const
Definition: widget.h:240
const std::string & getActionEventId() const
Definition: widget.h:605
int getWidth() const
Definition: widget.h:221
void loadButtons()
Definition: windowmenu.cpp:484
void saveButtons() const
Definition: windowmenu.cpp:537
WindowMenu(const Widget2 *const widget)
Definition: windowmenu.cpp:53
void safeDrawChildren(Graphics *const graphics)
Definition: windowmenu.cpp:566
void showButton(const std::string &name, const Visible visible)
Definition: windowmenu.cpp:447
void addButton(const char *const text, const int iconNumber, const std::string &description, int &x, int &h, const InputActionT key, const Visible visible)
Definition: windowmenu.cpp:323
void updateButtons()
Definition: windowmenu.cpp:459
ImageSet * mImageSet
Definition: windowmenu.h:109
std::vector< ButtonText * > mButtonTexts
Definition: windowmenu.h:113
void drawChildren(Graphics *const graphics)
Definition: windowmenu.cpp:554
void mousePressed(MouseEvent &event)
Definition: windowmenu.cpp:377
std::map< std::string, ButtonInfo * > mButtonNames
Definition: windowmenu.h:114
void mouseMoved(MouseEvent &event)
Definition: windowmenu.cpp:399
std::vector< Button * > mButtons
Definition: windowmenu.h:112
Skin * mSkin
Definition: windowmenu.h:108
int mAutoHide
Definition: windowmenu.h:116
void optionChanged(const std::string &name)
Definition: windowmenu.cpp:578
void action(const ActionEvent &event)
Definition: windowmenu.cpp:308
bool mHaveMouse
Definition: windowmenu.h:115
bool mSmallWindow
Definition: windowmenu.h:117
int mPadding
Definition: windowmenu.h:110
int mSpacing
Definition: windowmenu.h:111
void mouseExited(MouseEvent &event)
Definition: windowmenu.cpp:438
Configuration config
void delete_all(Container &c)
Definition: dtor.h:56
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define N_(s)
Definition: gettext.h:36
#define _(s)
Definition: gettext.h:35
Graphics * mainGraphics
Definition: graphics.cpp:109
InputAction ::T InputActionT
Definition: inputaction.h:717
InputManager inputManager
#define restrict
Definition: localconsts.h:165
#define nullptr
Definition: localconsts.h:45
#define A_UNUSED
Definition: localconsts.h:160
#define CHECKLISTENERS
Definition: localconsts.h:277
bool info(InputEvent &event)
Definition: commands.cpp:57
void load()
Definition: avatardb.cpp:46
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
@ WINDOW_SERVER_INFO
Definition: inputaction.h:704
@ WINDOW_EMOTE_SHORTCUT
Definition: inputaction.h:103
@ WINDOW_EQUIPMENT
Definition: inputaction.h:95
@ WINDOW_INVENTORY
Definition: inputaction.h:94
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
PopupManager * popupManager
PopupMenu * popupMenu
Definition: popupmenu.cpp:103
Settings settings
Definition: settings.cpp:32
SkillDialog * skillDialog
Definition: skilldialog.cpp:66
std::string strprintf(const char *const format,...)
TextPopup * textPopup
Definition: textpopup.cpp:33
Theme * theme
Definition: theme.cpp:62
bool Visible
Definition: visible.h:30
const bool Visible_false
Definition: visible.h:30
const bool Visible_true
Definition: visible.h:30
WindowMenu * windowMenu
Definition: windowmenu.cpp:51