ManaPlus
skilllistbox.h
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 #ifndef GUI_WIDGETS_SKILLLISTBOX_H
25 #define GUI_WIDGETS_SKILLLISTBOX_H
26 
27 #include "const/resources/skill.h"
28 
29 #include "dragdrop.h"
30 
31 #include "gui/skin.h"
32 #include "gui/viewport.h"
33 
34 #include "gui/widgets/listbox.h"
35 
36 #include "gui/fonts/font.h"
37 
38 #include "gui/models/skillmodel.h"
39 
40 #include "gui/popups/popupmenu.h"
41 #include "gui/popups/skillpopup.h"
42 
43 #include "utils/delete2.h"
44 
45 #include "render/graphics.h"
46 
47 #include "localconsts.h"
48 
49 class SkillModel;
50 
51 class SkillListBox final : public ListBox
52 {
53  public:
54  SkillListBox(const Widget2 *const widget,
55  SkillModel *const model) :
56  ListBox(widget, model, "skilllistbox.xml"),
57  mModel(model),
59  mTextColor2(getThemeColor(ThemeColorId::TEXT_OUTLINE, 255U)),
62  mSkin->getOption("textPadding", 34) : 34),
63  mSpacing(mSkin != nullptr ? mSkin->getOption("spacing", 0) : 0),
64  mSkillClicked(false)
65  {
66  mRowHeight = getFont()->getHeight() * 2 + mSpacing + 2 * mPadding;
67  mHighlightColor = getThemeColor(ThemeColorId::HIGHLIGHT, 255U);
68 
69  if (mRowHeight < 34)
70  mRowHeight = 34;
71  }
72 
74 
76  {
78  }
79 
81  {
82  const int selected = getSelected();
83  if ((mListModel == nullptr) || selected < 0
84  || selected > mListModel->getNumberOfElements())
85  {
86  return nullptr;
87  }
88 
89  return static_cast<SkillModel*>(mListModel)->getSkillAt(selected);
90  }
91 
92  void draw(Graphics *const graphics) override final A_NONNULL(2)
93  {
94  if (mListModel == nullptr)
95  return;
96 
97  SkillModel *const model = static_cast<SkillModel*>(mListModel);
98  updateAlpha();
99 
100  mHighlightColor.a = CAST_S32(mAlpha * 255.0F);
101  graphics->setColor(mHighlightColor);
102 
103  const int width1 = getWidth();
104  const int usableWidth = width1 - 2 * mPadding;
105 
106  // Draw filled rectangle around the selected list element
107  if (mSelected >= 0)
108  {
109  graphics->fillRectangle(Rect(mPadding, getRowHeight()
110  * mSelected + mPadding, usableWidth,
111  getRowHeight()));
112  }
113 
114  // Draw the list elements
115  Font *const font = getFont();
116  const int space = font->getHeight() + mSpacing;
117  const int width2 = width1 - mPadding;
118 
119  graphics->setColor(mCooldownColor);
120  for (int i = 0, y = 1 + mPadding;
121  i < model->getNumberOfElements();
122  ++i, y += getRowHeight())
123  {
124  SkillInfo *const e = model->getSkillAt(i);
125  if (e != nullptr)
126  {
127  if (e->cooldown != 0)
128  {
129  graphics->fillRectangle(Rect(mPadding, y,
130  usableWidth * 100 / e->cooldown, 10));
131  }
132  }
133  }
134 
135  for (int i = 0, y = 1 + mPadding;
136  i < model->getNumberOfElements();
137  ++i, y += getRowHeight())
138  {
139  SkillInfo *const e = model->getSkillAt(i);
140  if (e != nullptr)
141  {
142  const SkillData *const data = e->data;
143  const std::string &description = data->description;
144  graphics->drawImage(data->icon, mPadding, y);
145  font->drawString(graphics,
146  mTextColor,
147  mTextColor2,
148  data->name,
149  mTextPadding, y);
150  if (!description.empty())
151  {
152  font->drawString(graphics,
153  mTextColor,
154  mTextColor2,
155  description,
156  mTextPadding,
157  y + space);
158  }
159 
160  if (e->skillLevelWidth < 0)
161  {
162  // Add one for padding
163  e->skillLevelWidth = font->getWidth(e->skillLevel) + 1;
164  }
165 
166  font->drawString(graphics,
167  mTextColor,
168  mTextColor2,
169  e->skillLevel,
170  width2 - e->skillLevelWidth,
171  y);
172  }
173  }
174  }
175 
176  void safeDraw(Graphics *const graphics) override final A_NONNULL(2)
177  {
178  SkillListBox::draw(graphics);
179  }
180 
181  unsigned int getRowHeight() const override final
182  { return mRowHeight; }
183 
184  const SkillInfo *getSkillByEvent(const MouseEvent &event) const
185  {
186  const int y = (event.getY() + mPadding) / getRowHeight();
187  if (mModel == nullptr || y >= mModel->getNumberOfElements())
188  return nullptr;
189  const SkillInfo *const skill = mModel->getSkillAt(y);
190  if (skill == nullptr)
191  return nullptr;
192  return skill;
193  }
194 
195  void mouseMoved(MouseEvent &event) override final
196  {
197  ListBox::mouseMoved(event);
198  if ((viewport == nullptr) || !dragDrop.isEmpty())
199  return;
200 
201  const SkillInfo *const skill = getSkillByEvent(event);
202  if (skill == nullptr)
203  return;
205  skill->customSelectedLevel,
206  skill->customCastType,
207  skill->customOffsetX,
208  skill->customOffsetY);
210  viewport->mMouseY);
211  }
212 
213  void mouseDragged(MouseEvent &event) override final
214  {
215  if (event.getButton() == MouseButton::LEFT)
216  {
217  if (dragDrop.isEmpty())
218  {
219  if (mSkillClicked)
220  {
221  mSkillClicked = false;
222  const SkillInfo *const skill = getSkillByEvent(event);
223  if (skill == nullptr)
224  return;
227  dragDrop.setItemData(skill->toDataStr());
228  }
229  ListBox::mouseDragged(event);
230  }
231  }
232  else
233  {
234  ListBox::mouseDragged(event);
235  }
236  }
237 
238  void mousePressed(MouseEvent &event) override final
239  {
240  ListBox::mousePressed(event);
241  const MouseButtonT button = event.getButton();
242  if (button == MouseButton::LEFT ||
243  button == MouseButton::RIGHT)
244  {
245  const SkillInfo *const skill = getSkillByEvent(event);
246  if (skill == nullptr)
247  return;
248  event.consume();
249  mSkillClicked = true;
250  SkillModel *const model = static_cast<SkillModel*>(
251  mListModel);
252  if ((model != nullptr) &&
253  mSelected >= 0 &&
254  model->getSkillAt(mSelected) == skill)
255  {
256  skillPopup->hide();
257  if (button == MouseButton::LEFT &&
258  event.getX() >
259  getWidth() - mPadding - skill->skillLevelWidth)
260  {
262  }
263  else if (button == MouseButton::RIGHT)
264  {
266  }
267  }
268  }
269  }
270 
271  void mouseReleased(MouseEvent &event) override final
272  {
273  ListBox::mouseReleased(event);
274  }
275 
276  void mouseExited(MouseEvent &event A_UNUSED) override final
277  {
278  skillPopup->hide();
279  }
280 
281  private:
287  int mSpacing;
289 };
290 
291 #endif // GUI_WIDGETS_SKILLLISTBOX_H
#define CAST_S32
Definition: cast.h:30
Definition: color.h:76
unsigned int a
Definition: color.h:251
void setItem(const int item)
Definition: dragdrop.h:238
void dragSkill(const SkillInfo *const info, const DragDropSourceT source, const int tag)
Definition: dragdrop.h:152
bool isEmpty() const
Definition: dragdrop.h:196
void setItemData(const std::string &data)
Definition: dragdrop.h:78
Definition: font.h:90
int getHeight() const
Definition: font.cpp:362
int getWidth(const std::string &text) const
Definition: font.cpp:334
void drawString(Graphics *const graphics, Color col, const Color &col2, const std::string &text, const int x, const int y)
Definition: font.cpp:254
int mSelected
Definition: listbox.h:256
Color mHighlightColor
Definition: listbox.h:283
void mouseDragged(MouseEvent &event)
Definition: listbox.cpp:355
void updateAlpha()
Definition: listbox.cpp:154
void mousePressed(MouseEvent &event)
Definition: listbox.cpp:304
unsigned int mRowHeight
Definition: listbox.h:289
void mouseReleased(MouseEvent &event)
Definition: listbox.cpp:311
ListModel * mListModel
Definition: listbox.h:261
int mPadding
Definition: listbox.h:287
int getSelected() const
Definition: listbox.h:168
static float mAlpha
Definition: listbox.h:292
Skin * mSkin
Definition: listbox.h:291
virtual int getNumberOfElements()=0
virtual void mouseMoved(MouseEvent &event)
void showSkillLevelPopup(const SkillInfo *const info)
Definition: popupmenu.cpp:2356
void showSkillPopup(const SkillInfo *const info)
Definition: popupmenu.cpp:2263
void hide()
Definition: popup.cpp:265
void position(const int x, const int y)
Definition: popup.cpp:235
Definition: rect.h:74
void mousePressed(MouseEvent &event)
Definition: skilllistbox.h:238
SkillListBox(const Widget2 *const widget, SkillModel *const model)
Definition: skilllistbox.h:54
unsigned int getRowHeight() const
Definition: skilllistbox.h:181
Color mCooldownColor
Definition: skilllistbox.h:285
SkillModel * mModel
Definition: skilllistbox.h:282
void mouseReleased(MouseEvent &event)
Definition: skilllistbox.h:271
void draw(Graphics *const graphics)
Definition: skilllistbox.h:92
SkillInfo * getSelectedInfo() const
Definition: skilllistbox.h:80
void mouseDragged(MouseEvent &event)
Definition: skilllistbox.h:213
void mouseExited(MouseEvent &event)
Definition: skilllistbox.h:276
void safeDraw(Graphics *const graphics)
Definition: skilllistbox.h:176
Color mTextColor2
Definition: skilllistbox.h:284
void mouseMoved(MouseEvent &event)
Definition: skilllistbox.h:195
const SkillInfo * getSkillByEvent(const MouseEvent &event) const
Definition: skilllistbox.h:184
bool mSkillClicked
Definition: skilllistbox.h:288
Color mTextColor
Definition: skilllistbox.h:283
SkillInfo * getSkillAt(const int i) const
Definition: skillmodel.cpp:39
int getNumberOfElements()
Definition: skillmodel.h:46
void show(const SkillInfo *const skill, const int level, const CastTypeT type, const int offsetX, const int offsetY)
Definition: skillpopup.cpp:106
int mMouseX
Definition: viewport.h:154
int mMouseY
Definition: viewport.h:155
const Color & getThemeColor(const ThemeColorIdT type, const unsigned int alpha) const A_INLINE
Definition: widget2.h:45
Font * getFont() const
Definition: widget.cpp:331
int getWidth() const
Definition: widget.h:221
#define delete2(var)
Definition: delete2.h:25
DragDrop dragDrop
Viewport * viewport
Definition: viewport.cpp:36
#define override
Definition: localconsts.h:47
#define A_NONNULL(...)
Definition: localconsts.h:168
#define final
Definition: localconsts.h:46
#define A_DELETE_COPY(func)
Definition: localconsts.h:53
#define nullptr
Definition: localconsts.h:45
#define A_UNUSED
Definition: localconsts.h:160
uint32_t data
MouseButton ::T MouseButtonT
Definition: mousebutton.h:78
bool skill(InputEvent &event)
Definition: commands.cpp:97
@ SKILL_COOLDOWN
Definition: sp.h:256
PopupMenu * popupMenu
Definition: popupmenu.cpp:103
const int SKILL_MIN_ID
Definition: skill.h:25
SkillPopup * skillPopup
Definition: skillpopup.cpp:42
int skillLevelWidth
Definition: skillinfo.h:68
int cooldown
Definition: skillinfo.h:74
std::string skillLevel
Definition: skillinfo.h:52
SkillData * data
Definition: skillinfo.h:63