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