ManaPlus
slider.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-2017 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 /* _______ __ __ __ ______ __ __ _______ __ __
24  * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
25  * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
26  * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
27  * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
28  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
29  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
30  *
31  * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
32  *
33  *
34  * Per Larsson a.k.a finalman
35  * Olof Naessén a.k.a jansem/yakslem
36  *
37  * Visit: http://guichan.sourceforge.net
38  *
39  * License: (BSD)
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  * 1. Redistributions of source code must retain the above copyright
44  * notice, this list of conditions and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  * notice, this list of conditions and the following disclaimer in
47  * the documentation and/or other materials provided with the
48  * distribution.
49  * 3. Neither the name of Guichan nor the names of its contributors may
50  * be used to endorse or promote products derived from this software
51  * without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
54  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
55  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
56  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
57  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
59  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */
65 
66 #include "gui/widgets/slider.h"
67 
68 #include "settings.h"
69 
70 #include "enums/gui/slidergrid.h"
71 
72 #include "gui/gui.h"
73 
74 #include "utils/delete2.h"
75 
76 #include "resources/imagerect.h"
77 
78 #include "resources/image/image.h"
79 
80 #include "render/graphics.h"
81 
83 
84 #include "debug.h"
85 
87 float Slider::mAlpha = 1.0;
88 int Slider::mInstances = 0;
89 
90 static std::string const data[2] =
91 {
92  "slider.xml",
93  "slider_highlighted.xml"
94 };
95 
96 Slider::Slider(Widget2 *const widget,
97  const double scaleEnd,
98  const double stepLength) :
99  Widget(widget),
100  MouseListener(),
101  KeyListener(),
102  mValue(0),
103  mStepLength(stepLength),
104  mScaleStart(0),
105  mScaleEnd(scaleEnd),
106  mOrientation(Orientation::HORIZONTAL),
107  mVertexes(new ImageCollection),
108  mMarkerLength(10),
109  mHasMouse(false)
110 {
111  init();
112 }
113 
114 Slider::Slider(Widget2 *const widget,
115  const double scaleStart,
116  const double scaleEnd,
117  const double stepLength) :
118  Widget(widget),
119  MouseListener(),
120  KeyListener(),
121  mValue(scaleStart),
122  mStepLength(stepLength),
123  mScaleStart(scaleStart),
124  mScaleEnd(scaleEnd),
127  mMarkerLength(10),
128  mHasMouse(false)
129 {
130  init();
131 }
132 
134 {
135  if (gui != nullptr)
136  gui->removeDragged(this);
137 
139  mInstances--;
140  if (mInstances == 0)
141  {
142  for (int mode = 0; mode < 2; mode ++)
143  Theme::unloadRect(buttons[mode]);
144  }
145 }
146 
148 {
149  mAllowLogic = false;
150  setFocusable(true);
151  setFrameSize(1);
152 
153  addMouseListener(this);
154  addKeyListener(this);
155 
156  setFrameSize(0);
157 
158  // Load resources
159  if (mInstances == 0)
160  {
161  if (theme != nullptr)
162  {
163  for (int mode = 0; mode < 2; mode ++)
164  theme->loadRect(buttons[mode], data[mode], "slider.xml", 0, 8);
165  }
166  updateAlpha();
167  }
168 
169  mInstances++;
170 
171  if (buttons[0].grid[SliderGrid::HGRIP] != nullptr)
173 }
174 
176 {
177  const float alpha = std::max(settings.guiAlpha,
179 
180  if (alpha != mAlpha)
181  {
182  mAlpha = alpha;
183  for (int f = 0; f < 2; f ++)
184  {
185  for (int d = 0; d < SliderGrid::SLIDER_MAX; d ++)
186  {
187  if (buttons[f].grid[d] != nullptr)
188  buttons[f].grid[d]->setAlpha(mAlpha);
189  }
190  }
191  }
192 }
193 
194 void Slider::draw(Graphics *const graphics)
195 {
196  BLOCK_START("Slider::draw")
197  if ((buttons[0].grid[SliderGrid::HSTART] == nullptr) ||
198  (buttons[1].grid[SliderGrid::HSTART] == nullptr) ||
199  (buttons[0].grid[SliderGrid::HEND] == nullptr))
200  {
201  BLOCK_END("Slider::draw")
202  return;
203  }
204 
205  int w = getWidth();
206  const int h = getHeight();
207  const int y = mHasMouse ?
208  (h - buttons[1].grid[SliderGrid::HSTART]->getHeight()) / 2 :
209  (h - buttons[0].grid[SliderGrid::HSTART]->getHeight()) / 2;
210 
211  updateAlpha();
212 
213  if (mRedraw || graphics->getRedraw())
214  {
215  int x = 0;
216  mRedraw = false;
217  mVertexes->clear();
218  if (!mHasMouse)
219  {
220  graphics->calcTileCollection(mVertexes,
221  buttons[0].grid[SliderGrid::HSTART],
222  x, y);
223 
224  const int width = buttons[0].grid[SliderGrid::HSTART]->getWidth();
225  w -= width + buttons[0].grid[SliderGrid::HEND]->getWidth();
226  x += width;
227 
228  if (buttons[0].grid[SliderGrid::HMID] != nullptr)
229  {
230  const Image *const hMid = buttons[0].grid[SliderGrid::HMID];
231  graphics->calcPattern(mVertexes,
232  hMid,
233  x, y,
234  w, hMid->getHeight());
235  }
236 
237  x += w;
238  graphics->calcTileCollection(mVertexes,
239  buttons[0].grid[SliderGrid::HEND],
240  x, y);
241 
242  const Image *const img = buttons[0].grid[SliderGrid::HGRIP];
243  if (img != nullptr)
244  {
245  graphics->calcTileCollection(mVertexes,
246  img,
248  (mDimension.height - img->getHeight()) / 2);
249  }
250  }
251  else
252  {
253  graphics->calcTileCollection(mVertexes,
254  buttons[1].grid[SliderGrid::HSTART],
255  x, y);
256 
257  const int width = buttons[1].grid[SliderGrid::HSTART]->getWidth();
258  w -= width;
259  if (buttons[1].grid[SliderGrid::HEND] != nullptr)
261  x += width;
262 
263  if (buttons[1].grid[SliderGrid::HMID] != nullptr)
264  {
265  const Image *const hMid = buttons[1].grid[SliderGrid::HMID];
266  graphics->calcPattern(mVertexes,
267  hMid,
268  x, y,
269  w, hMid->getHeight());
270  }
271 
272  x += w;
273  if (buttons[1].grid[SliderGrid::HEND] != nullptr)
274  {
275  graphics->calcTileCollection(mVertexes,
276  buttons[1].grid[SliderGrid::HEND], x, y);
277  }
278 
279  const Image *const img = buttons[1].grid[SliderGrid::HGRIP];
280  if (img != nullptr)
281  {
282  graphics->calcTileCollection(mVertexes,
283  img,
285  (mDimension.height - img->getHeight()) / 2);
286  }
287  }
288  graphics->finalize(mVertexes);
289  }
290  graphics->drawTileCollection(mVertexes);
291 
292  BLOCK_END("Slider::draw")
293 }
294 
295 void Slider::safeDraw(Graphics *const graphics)
296 {
297  BLOCK_START("Slider::draw")
298  if ((buttons[0].grid[SliderGrid::HSTART] == nullptr) ||
299  (buttons[1].grid[SliderGrid::HSTART] == nullptr) ||
300  (buttons[0].grid[SliderGrid::HEND] == nullptr))
301  {
302  BLOCK_END("Slider::draw")
303  return;
304  }
305 
306  int w = getWidth();
307  const int h = getHeight();
308  int x = 0;
309  const int y = mHasMouse ?
310  (h - buttons[1].grid[SliderGrid::HSTART]->getHeight()) / 2 :
311  (h - buttons[0].grid[SliderGrid::HSTART]->getHeight()) / 2;
312 
313  updateAlpha();
314 
315  if (!mHasMouse)
316  {
317  graphics->drawImage(buttons[0].grid[SliderGrid::HSTART], x, y);
318  const int width = buttons[0].grid[SliderGrid::HSTART]->getWidth();
319  w -= width + buttons[0].grid[SliderGrid::HEND]->getWidth();
320  x += width;
321 
322  if (buttons[0].grid[SliderGrid::HMID] != nullptr)
323  {
324  const Image *const hMid = buttons[0].grid[SliderGrid::HMID];
325  graphics->drawPattern(hMid, x, y, w, hMid->getHeight());
326  }
327 
328  x += w;
329  graphics->drawImage(buttons[0].grid[SliderGrid::HEND], x, y);
330 
331  const Image *const img = buttons[0].grid[SliderGrid::HGRIP];
332  if (img != nullptr)
333  {
334  graphics->drawImage(img, getMarkerPosition(),
335  (mDimension.height - img->getHeight()) / 2);
336  }
337  }
338  else
339  {
340  graphics->drawImage(buttons[1].grid[SliderGrid::HSTART], x, y);
341 
342  const int width = buttons[1].grid[SliderGrid::HSTART]->getWidth();
343  w -= width;
344  if (buttons[1].grid[SliderGrid::HEND] != nullptr)
346  x += width;
347 
348  if (buttons[1].grid[SliderGrid::HMID] != nullptr)
349  {
350  const Image *const hMid = buttons[1].grid[SliderGrid::HMID];
351  graphics->drawPattern(hMid, x, y, w, hMid->getHeight());
352  }
353 
354  x += w;
355  if (buttons[1].grid[SliderGrid::HEND] != nullptr)
356  graphics->drawImage(buttons[1].grid[SliderGrid::HEND], x, y);
357 
358  const Image *const img = buttons[1].grid[SliderGrid::HGRIP];
359  if (img != nullptr)
360  {
361  graphics->drawImage(img, getMarkerPosition(),
362  (mDimension.height - img->getHeight()) / 2);
363  }
364  }
365 
366  BLOCK_END("Slider::draw")
367 }
368 
370 {
371  mHasMouse = true;
372  mRedraw = true;
373 }
374 
376 {
377  mHasMouse = false;
378  mRedraw = true;
379 }
380 
382 {
383  const int x = event.getX();
384  const int y = event.getY();
385  const int width = mDimension.width;
386  const int height = mDimension.height;
387 
388  if (event.getButton() == MouseButton::LEFT
389  && x >= 0 && x <= width && y >= 0 && y <= height)
390  {
391  event.consume();
394  else
395  setValue(markerPositionToValue(height - y - mMarkerLength / 2));
397  }
398 }
399 
401 {
403  {
405  }
406  else
407  {
409  mDimension.height - event.getY() - mMarkerLength / 2));
410  }
411 
413 
414  event.consume();
415 }
416 
418 {
421  event.consume();
422 }
423 
425 {
428  event.consume();
429 }
430 
432 {
433  const InputActionT action = event.getActionId();
434 
436  {
437  if (action == InputAction::GUI_RIGHT)
438  {
441  event.consume();
442  }
443  else if (action == InputAction::GUI_LEFT)
444  {
447  event.consume();
448  }
449  }
450  else
451  {
452  if (action == InputAction::GUI_UP)
453  {
456  event.consume();
457  }
458  else if (action == InputAction::GUI_DOWN)
459  {
462  event.consume();
463  }
464  }
465 }
466 
467 void Slider::setScale(const double scaleStart, const double scaleEnd)
468 {
469  mScaleStart = scaleStart;
470  mScaleEnd = scaleEnd;
471 }
472 
473 void Slider::setValue(const double value)
474 {
475  mRedraw = true;
476  if (value > mScaleEnd)
477  mValue = mScaleEnd;
478  else if (value < mScaleStart)
480  else
481  mValue = value;
484 }
485 
486 double Slider::markerPositionToValue(const int v) const
487 {
488  int w;
490  w = mDimension.width;
491  else
492  w = mDimension.height;
493 
494  const double pos = v / (static_cast<double>(w) - mMarkerLength);
495  return (1.0 - pos) * mScaleStart + pos * mScaleEnd;
496 }
497 
498 int Slider::valueToMarkerPosition(const double value) const
499 {
500  int v;
502  v = mDimension.width;
503  else
504  v = mDimension.height;
505 
506  const int w = CAST_S32((v - mMarkerLength)
507  * (value - mScaleStart)
508  / (mScaleEnd - mScaleStart));
509 
510  if (w < 0)
511  return 0;
512 
513  if (w > v - mMarkerLength)
514  return v - mMarkerLength;
515 
516  return w;
517 }
int width
Definition: rect.h:218
void setMarkerLength(const int length)
Definition: slider.h:221
int getWidth() const
Definition: widget.h:220
OrientationT mOrientation
Definition: slider.h:325
static int mInstances
Definition: slider.h:298
virtual void drawTileCollection(const ImageCollection *const vertCol)=0
void updateAlpha()
Definition: slider.cpp:175
static ImageRect buttons[2]
Definition: slider.h:296
static void unloadRect(const ImageRect &rect, const int start=0, const int end=8)
Definition: theme.cpp:1118
void mousePressed(MouseEvent &event)
Definition: slider.cpp:381
Gui * gui
Definition: gui.cpp:110
Slider(Widget2 *const widget, const double scaleEnd, const double stepLength)
Definition: slider.cpp:96
MouseButtonT getButton() const
Definition: mouseevent.h:113
float getMinimumOpacity() const
Definition: theme.h:124
double mStepLength
Definition: slider.h:309
ImageCollection * mVertexes
Definition: slider.h:327
#define BLOCK_START(name)
Definition: perfomance.h:78
void init()
Definition: slider.cpp:147
static std::string const data[2]
Definition: slider.cpp:90
int mMarkerLength
Definition: slider.h:332
#define BLOCK_END(name)
Definition: perfomance.h:79
void keyPressed(KeyEvent &event)
Definition: slider.cpp:431
#define delete2(var)
Definition: delete2.h:24
double mScaleEnd
Definition: slider.h:319
void setScale(const double scaleStart, const double scaleEnd)
Definition: slider.cpp:467
bool mHasMouse
Definition: slider.h:334
virtual void finalize(ImageCollection *const col)
Definition: graphics.h:464
void distributeActionEvent()
Definition: widget.cpp:492
#define new
Definition: debug_new.h:147
Settings settings
Definition: settings.cpp:31
virtual void setAlpha(const float alpha)
Definition: image.cpp:285
double markerPositionToValue(const int position) const
Definition: slider.cpp:486
#define CAST_S32
Definition: cast.h:29
int getMarkerPosition() const
Definition: slider.h:293
Image * grid[9]
Definition: imagerect.h:41
void setFrameSize(const unsigned int frameSize)
Definition: widget.h:167
InputAction ::T InputActionT
Definition: inputaction.h:714
void mouseExited(MouseEvent &event)
Definition: slider.cpp:375
void mouseDragged(MouseEvent &event)
Definition: slider.cpp:400
void mouseWheelMovedDown(MouseEvent &event)
Definition: slider.cpp:424
bool mAllowLogic
Definition: widget.h:1159
void addMouseListener(MouseListener *const mouseListener)
Definition: widget.cpp:291
void loadRect(ImageRect &image, const std::string &name, const std::string &name2, const int start=0, const int end=8)
Definition: theme.cpp:1092
int height
Definition: rect.h:223
void addKeyListener(KeyListener *const keyListener)
Definition: widget.cpp:271
bool getRedraw() const
Definition: graphics.h:286
double mValue
Definition: slider.h:303
int getY() const
Definition: mouseevent.h:135
virtual void calcPattern(ImageVertexes *const vert, const Image *const image, const int x, const int y, const int w, const int h) const =0
Theme * theme
Definition: theme.cpp:61
#define A_UNUSED
Definition: localconsts.h:171
void setFocusable(const bool focusable)
Definition: widget.cpp:191
virtual void drawImage(const Image *const image, int dstX, int dstY)=0
void removeDragged(const Widget *const widget)
Definition: gui.cpp:1144
Definition: widget.h:97
void setValue(const double value)
Definition: slider.cpp:473
double mScaleStart
Definition: slider.h:314
void draw(Graphics *const graphics)
Definition: slider.cpp:194
bool mRedraw
Definition: widget.h:1163
static float mAlpha
Definition: slider.h:297
Definition: image.h:61
virtual void calcTileCollection(ImageCollection *const vertCol, const Image *const image, int x, int y)=0
int getHeight() const
Definition: widget.h:239
int getWidth() const A_INLINE
Definition: image.h:116
virtual void drawPattern(const Image *const image, const int x, const int y, const int w, const int h)=0
int getX() const
Definition: mouseevent.h:124
void safeDraw(Graphics *const graphics)
Definition: slider.cpp:295
float guiAlpha
Definition: settings.h:129
~Slider()
Definition: slider.cpp:133
Rect mDimension
Definition: widget.h:1100
void mouseWheelMovedUp(MouseEvent &event)
Definition: slider.cpp:417
int valueToMarkerPosition(const double value) const
Definition: slider.cpp:498
int getHeight() const A_INLINE
Definition: image.h:122
void mouseEntered(MouseEvent &event)
Definition: slider.cpp:369