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