MyGUI  3.4.1
MyGUI_ScrollBar.cpp
Go to the documentation of this file.
1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 #include "MyGUI_Precompiled.h"
8 #include "MyGUI_ScrollBar.h"
9 #include "MyGUI_InputManager.h"
10 #include "MyGUI_Button.h"
11 #include "MyGUI_ResourceSkin.h"
14 
15 namespace MyGUI
16 {
17 
19  mWidgetStart(nullptr),
20  mWidgetEnd(nullptr),
21  mWidgetTrack(nullptr),
22  mWidgetFirstPart(nullptr),
23  mWidgetSecondPart(nullptr),
24  mSkinRangeStart(0),
25  mSkinRangeEnd(0),
26  mScrollRange(0),
27  mScrollPosition(0),
28  mScrollPage(0),
29  mScrollViewPage(0),
30  mScrollWheelPage(0),
31  mEnableRepeat(true),
32  mRepeatTriggerTime(0.f),
33  mRepeatStepTime(0.f),
34  mMinTrackSize(0),
35  mMoveToClick(false),
36  mVerticalAlignment(true)
37  {
38  }
39 
41  {
42  Base::initialiseOverride();
43 
44  // при нуле, будет игнорировать кнопки
45  mScrollPage = 1;
46  mScrollViewPage = 1;
47  mScrollWheelPage = 1;
48  mMinTrackSize = 0;
49  mSkinRangeStart = 0;
50  mSkinRangeEnd = 0;
51 
52  mRepeatTriggerTime = 0.5f;
53  mRepeatStepTime = 0.1f;
54 
56  assignWidget(mWidgetStart, "Start");
57  if (mWidgetStart != nullptr)
58  {
62  }
63 
65  assignWidget(mWidgetEnd, "End");
66  if (mWidgetEnd != nullptr)
67  {
71  }
72 
74  assignWidget(mWidgetTrack, "Track");
75  if (mWidgetTrack)
76  {
81  mWidgetTrack->setVisible(false);
82  }
83 
85  assignWidget(mWidgetFirstPart, "FirstPart");
86  if (mWidgetFirstPart != nullptr)
87  {
91  }
92 
94  assignWidget(mWidgetSecondPart, "SecondPart");
95  if (mWidgetSecondPart != nullptr)
96  {
100  }
101 
102  if (isUserString("MinTrackSize"))
103  mMinTrackSize = utility::parseValue<int>(getUserString("MinTrackSize"));
104 
105  if (isUserString("TrackRangeMargins"))
106  utility::parseComplex<size_t>(getUserString("TrackRangeMargins"), mSkinRangeStart, mSkinRangeEnd);
107 
108  if (mWidgetTrack != nullptr)
109  {
110  if (mWidgetTrack->isUserString("MinTrackSize"))
111  mMinTrackSize = utility::parseValue<int>(mWidgetTrack->getUserString("MinTrackSize"));
112  }
113  }
114 
116  {
117  mWidgetStart = nullptr;
118  mWidgetEnd = nullptr;
119  mWidgetTrack = nullptr;
120  mWidgetFirstPart = nullptr;
121  mWidgetSecondPart = nullptr;
122 
123  Base::shutdownOverride();
124  }
125 
127  {
128  if (mWidgetTrack == nullptr)
129  return;
130 
132  // размер диапазана в пикселях
133  int pos = getLineSize();
134 
135  if (mVerticalAlignment)
136  {
137  // скрываем если диапазан маленький или места мало
138  if ((mScrollRange < 2) || (pos <= mWidgetTrack->getHeight()))
139  {
140  mWidgetTrack->setVisible(false);
141  if (nullptr != mWidgetFirstPart)
143  if (nullptr != mWidgetSecondPart)
145  return;
146  }
147  // если скрыт то покажем
148  if (!mWidgetTrack->getVisible())
149  mWidgetTrack->setVisible(true);
150 
151  // и обновляем позицию
152  pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);
153 
155  if (nullptr != mWidgetFirstPart)
156  {
157  int height = pos - mWidgetFirstPart->getTop();
159  }
160  if (nullptr != mWidgetSecondPart)
161  {
162  int top = pos + mWidgetTrack->getHeight();
163  int height = getTrackPlaceLength() - top;
165  }
166  }
167  else
168  {
169  // скрываем если диапазан маленький или места мало
170  if ((mScrollRange < 2) || (pos <= mWidgetTrack->getWidth()))
171  {
172  mWidgetTrack->setVisible(false);
173  if (nullptr != mWidgetFirstPart)
175  if (nullptr != mWidgetSecondPart)
177  return;
178  }
179  // если скрыт то покажем
180  if (!mWidgetTrack->getVisible())
181  mWidgetTrack->setVisible(true);
182 
183  // и обновляем позицию
184  pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);
185 
187  if (nullptr != mWidgetFirstPart)
188  {
189  int height = pos - mWidgetFirstPart->getLeft();
191  }
192  if (nullptr != mWidgetSecondPart)
193  {
194  int left = pos + mWidgetTrack->getWidth();
195  int width = getTrackPlaceLength() - left;
197  }
198  }
199  }
200 
201  void ScrollBar::TrackMove(int _left, int _top)
202  {
203  if (mWidgetTrack == nullptr)
204  return;
205 
207 
208  if (mVerticalAlignment)
209  {
210  // расчитываем позицию виджета
211  int start = mPreActionOffset.top + (_top - point.top);
212  if (start < (int)mSkinRangeStart)
213  start = (int)mSkinRangeStart;
214  else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getHeight()))
216  if (mWidgetTrack->getTop() != start)
218 
219  // расчитываем положение соответствующее позиции
220  // плюс пол позиции
221  int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
222  // высчитываем ближайшее значение и обновляем
223  pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
224 
225  // проверяем на выходы и изменения
226  if (pos < 0)
227  pos = 0;
228  else if (pos >= (int)mScrollRange)
229  pos = (int)mScrollRange - 1;
230  if (pos == (int)mScrollPosition)
231  return;
232 
233  mScrollPosition = pos;
234  }
235  else
236  {
237  // расчитываем позицию виджета
238  int start = mPreActionOffset.left + (_left - point.left);
239  if (start < (int)mSkinRangeStart)
240  start = (int)mSkinRangeStart;
241  else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth()))
242  start = (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth());
243  if (mWidgetTrack->getLeft() != start)
245 
246  // расчитываем положение соответствующее позиции
247  // плюс пол позиции
248  int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
249  // высчитываем ближайшее значение и обновляем
250  pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
251 
252  // проверяем на выходы и изменения
253  if (pos < 0)
254  pos = 0;
255  else if (pos >= (int)mScrollRange)
256  pos = (int)mScrollRange - 1;
257  if (pos == (int)mScrollPosition)
258  return;
259 
260  mScrollPosition = pos;
261  }
262 
263  updateTrack();
264 
265  // отсылаем событие
267  }
268 
269  void ScrollBar::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
270  {
271  // диспечерезируем нажатие своих детей как свое
272  eventMouseButtonPressed(this, _left, _top, _id);
273 
274  if (MouseButton::Left != _id)
275  return;
276 
277  if (mEnableRepeat && _sender != mWidgetTrack
278  && ((_sender != mWidgetFirstPart && _sender != mWidgetSecondPart) || !mMoveToClick))
279  {
282  controller->eventRepeatClick += newDelegate(this, &ScrollBar::repeatClick);
284  ControllerManager::getInstance().addItem(_sender, controller);
285  }
286 
287  if (mMoveToClick &&
288  _sender != mWidgetTrack &&
289  _sender != mWidgetStart &&
290  _sender != mWidgetEnd)
291  {
292  if (mWidgetTrack != nullptr)
293  {
296 
299 
300  TrackMove(point.left, point.top);
301  }
302  }
303  else if (_sender == mWidgetStart)
304  {
305  widgetStartPressed();
306  }
307  else if (_sender == mWidgetEnd)
308  {
309  widgetEndPressed();
310  }
311  else if (_sender == mWidgetFirstPart)
312  {
313  widgetFirstPartPressed();
314  }
315  else if (_sender == mWidgetSecondPart)
316  {
317  widgetSecondPartPressed();
318  }
319  else if (_sender == mWidgetTrack)
320  {
321  mPreActionOffset.left = _sender->getLeft();
322  mPreActionOffset.top = _sender->getTop();
323  }
324  }
325 
326  void ScrollBar::notifyMouseReleased(Widget* _sender, int _left, int _top, MouseButton _id)
327  {
328  updateTrack();
330  }
331 
332  void ScrollBar::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
333  {
334  if (mScrollRange < 2)
335  return;
336  if (_id == MouseButton::Left)
337  TrackMove(_left, _top);
338  }
339 
340  void ScrollBar::setScrollRange(size_t _range)
341  {
342  if (_range == mScrollRange)
343  return;
344 
345  mScrollRange = _range;
347  updateTrack();
348  }
349 
350  void ScrollBar::setScrollPosition(size_t _position)
351  {
352  if (_position == mScrollPosition)
353  return;
354 
355  if (_position >= mScrollRange)
356  _position = 0;
357 
358  mScrollPosition = _position;
359  updateTrack();
360  }
361 
362  void ScrollBar::setPosition(const IntPoint& _point)
363  {
364  Base::setPosition(_point);
365  }
366 
367  void ScrollBar::setSize(const IntSize& _size)
368  {
369  Base::setSize(_size);
370  // обновляем трек
371  updateTrack();
372  }
373 
374  void ScrollBar::setCoord(const IntCoord& _coord)
375  {
376  Base::setCoord(_coord);
377  // обновляем трек
378  updateTrack();
379  }
380 
381  void ScrollBar::setTrackSize(int _size)
382  {
383  if (mWidgetTrack != nullptr)
384  {
385  if (mVerticalAlignment)
386  mWidgetTrack->setSize(mWidgetTrack->getWidth(), ((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size);
387  else
388  mWidgetTrack->setSize(((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size, mWidgetTrack->getHeight());
389  }
390  updateTrack();
391  }
392 
394  {
395  mRepeatTriggerTime = time;
396  }
397 
399  {
400  mRepeatStepTime = time;
401  }
402 
403  float ScrollBar::getRepeatTriggerTime(float time) const
404  {
405  return mRepeatTriggerTime;
406  }
407 
408  float ScrollBar::getRepeatStepTime(float time) const
409  {
410  return mRepeatStepTime;
411  }
412 
413  void ScrollBar::setRepeatEnabled(bool enabled)
414  {
415  mEnableRepeat = enabled;
416  }
417 
419  {
420  return mEnableRepeat;
421  }
422 
424  {
425  if (mWidgetTrack != nullptr)
426  {
427  if (mVerticalAlignment)
428  return mWidgetTrack->getHeight();
429  else
430  return mWidgetTrack->getWidth();
431  }
432  return 1;
433  }
434 
436  {
438  }
439 
440  void ScrollBar::onMouseWheel(int _rel)
441  {
442  notifyMouseWheel(nullptr, _rel);
443 
444  Base::onMouseWheel(_rel);
445  }
446 
447  void ScrollBar::notifyMouseWheel(Widget* _sender, int _rel)
448  {
449  if (mScrollRange < 2)
450  return;
451 
452  int offset = mScrollPosition;
453  if (_rel < 0)
454  offset += mScrollWheelPage;
455  else
456  offset -= mScrollWheelPage;
457 
458  if (offset < 0)
459  offset = 0;
460  else if (offset > (int)(mScrollRange - 1))
461  offset = mScrollRange - 1;
462 
463  if ((size_t)offset != mScrollPosition)
464  {
465  mScrollPosition = offset;
466  // оповещаем
468  updateTrack();
469  }
470  }
471 
472  void ScrollBar::repeatClick(Widget *_widget, ControllerItem *_controller)
473  {
474  if (_widget == mWidgetStart)
475  widgetStartPressed();
476  else if (_widget == mWidgetEnd)
477  widgetEndPressed();
478  else if (_widget == mWidgetFirstPart)
479  widgetFirstPartPressed();
480  else if (_widget == mWidgetSecondPart)
481  widgetSecondPartPressed();
482  }
483 
484  void ScrollBar::widgetStartPressed()
485  {
486  // минимальное значение
487  if (mScrollPosition == 0)
488  return;
489 
490  // расчитываем следующее положение
493  else
494  mScrollPosition = 0;
495 
496  // оповещаем
498  updateTrack();
499  }
500 
501  void ScrollBar::widgetEndPressed()
502  {
503  // максимальное значение
504  if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
505  return;
506 
507  // расчитываем следующее положение
508  if ((mScrollPosition + mScrollPage) < (mScrollRange - 1))
510  else
512 
513  // оповещаем
515  updateTrack();
516  }
517 
518  void ScrollBar::widgetFirstPartPressed()
519  {
520  // минимальное значение
521  if (mScrollPosition == 0)
522  return;
523 
524  // расчитываем следующее положение
527  else
528  mScrollPosition = 0;
529 
530  // оповещаем
532  updateTrack();
533  }
534 
535  void ScrollBar::widgetSecondPartPressed()
536  {
537  // максимальное значение
538  if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
539  return;
540 
541  // расчитываем следующее положение
544  else
546 
547  // оповещаем
549  updateTrack();
550  }
551 
552  void ScrollBar::setPropertyOverride(const std::string& _key, const std::string& _value)
553  {
555  if (_key == "Range")
556  setScrollRange(utility::parseValue<size_t>(_value));
557 
559  else if (_key == "RangePosition")
560  setScrollPosition(utility::parseValue<size_t>(_value));
561 
563  else if (_key == "Page")
564  setScrollPage(utility::parseValue<size_t>(_value));
565 
567  else if (_key == "ViewPage")
568  setScrollViewPage(utility::parseValue<size_t>(_value));
569 
571  else if (_key == "WheelPage")
572  setScrollWheelPage(utility::parseValue<size_t>(_value));
573 
575  else if (_key == "MoveToClick")
576  setMoveToClick(utility::parseValue<bool>(_value));
577 
579  else if (_key == "VerticalAlignment")
580  setVerticalAlignment(utility::parseValue<bool>(_value));
581 
583  else if (_key == "Repeat")
584  setRepeatEnabled(utility::parseValue<bool>(_value));
585 
587  else if (_key == "RepeatTriggerTime")
588  setRepeatTriggerTime(utility::parseValue<float>(_value));
589 
591  else if (_key == "RepeatStepTime")
592  setRepeatStepTime(utility::parseValue<float>(_value));
593 
594  else
595  {
596  Base::setPropertyOverride(_key, _value);
597  return;
598  }
599 
600  eventChangeProperty(this, _key, _value);
601  }
602 
604  {
605  return mScrollRange;
606  }
607 
609  {
610  return mScrollPosition;
611  }
612 
613  void ScrollBar::setScrollPage(size_t _value)
614  {
615  mScrollPage = _value;
616  }
617 
619  {
620  return mScrollPage;
621  }
622 
623  void ScrollBar::setScrollViewPage(size_t _value)
624  {
625  mScrollViewPage = _value;
626  }
627 
629  {
630  return mScrollViewPage;
631  }
632 
633  void ScrollBar::setScrollWheelPage(size_t _value)
634  {
635  mScrollWheelPage = _value;
636  }
638  {
639  return mScrollWheelPage;
640  }
641 
642  void ScrollBar::setMinTrackSize(int _value)
643  {
644  mMinTrackSize = _value;
645  }
646 
648  {
649  return mMinTrackSize;
650  }
651 
652  void ScrollBar::setMoveToClick(bool _value)
653  {
654  mMoveToClick = _value;
655  }
656 
658  {
659  return mMoveToClick;
660  }
661 
663  {
664  if (mWidgetTrack != nullptr)
665  {
666  if (mVerticalAlignment)
667  return mWidgetTrack->getParent()->getHeight();
668  else
669  return mWidgetTrack->getParent()->getWidth();
670  }
671  return 0;
672  }
673 
675  {
676  mVerticalAlignment = _value;
677 
678  updateTrack();
679  }
680 
682  {
683  return mVerticalAlignment;
684  }
685 
686 } // namespace MyGUI
ControllerItem * createItem(const std::string &_type)
static ControllerManager & getInstance()
void addItem(Widget *_widget, ControllerItem *_item)
EventHandle_RepeatClick eventRepeatClick
void setRepeat(float init, float step)
static const std::string & getClassTypeName()
const IntPoint & getAbsolutePosition() const
Type * castType(bool _throw=true)
Definition: MyGUI_IObject.h:18
const IntPoint & getLastPressedPosition(MouseButton _id) const
static InputManager & getInstance()
IntPoint getMousePositionByLayer() const
int getMinTrackSize() const
void setVerticalAlignment(bool _value)
void setRepeatEnabled(bool enabled)
EventHandle_ScrollBarPtrSizeT eventScrollChangePosition
void setMoveToClick(bool _value)
void shutdownOverride() override
void setCoord(const IntCoord &_value) override
void setScrollRange(size_t _value)
int getLineSize() const
void setScrollWheelPage(size_t _value)
void initialiseOverride() override
void setTrackSize(int _value)
void setMinTrackSize(int _value)
size_t getScrollPage() const
void setPropertyOverride(const std::string &_key, const std::string &_value) override
void notifyMousePressed(Widget *_sender, int _left, int _top, MouseButton _id)
void setRepeatTriggerTime(float time)
void setRepeatStepTime(float time)
Widget * mWidgetFirstPart
bool getVerticalAlignment() const
bool getRepeatEnabled() const
size_t getScrollPosition() const
void TrackMove(int _left, int _top)
void notifyMouseReleased(Widget *_sender, int _left, int _top, MouseButton _id)
Widget * mWidgetSecondPart
size_t getScrollViewPage() const
void setPosition(const IntPoint &_value) override
void setScrollPosition(size_t _value)
void setSize(const IntSize &_value) override
size_t getScrollRange() const
int getTrackPlaceLength() const
void setScrollViewPage(size_t _value)
bool getMoveToClick() const
void notifyMouseDrag(Widget *_sender, int _left, int _top, MouseButton _id)
int getTrackSize() const
void onMouseWheel(int _rel) override
float getRepeatTriggerTime(float time) const
void setScrollPage(size_t _value)
IntPoint mPreActionOffset
size_t getScrollWheelPage() const
void notifyMouseWheel(Widget *_sender, int _rel)
float getRepeatStepTime(float time) const
bool isUserString(const std::string &_key) const
const std::string & getUserString(const std::string &_key) const
widget description should be here.
Definition: MyGUI_Widget.h:37
Widget * getParent() const
void setCoord(const IntCoord &_value) override
EventHandle_WidgetStringString eventChangeProperty
Definition: MyGUI_Widget.h:267
void assignWidget(T *&_widget, const std::string &_name)
Definition: MyGUI_Widget.h:335
virtual void setVisible(bool _value)
void setPosition(const IntPoint &_value) override
bool getVisible() const
void setSize(const IntSize &_value) override
void _forcePick(Widget *_widget)
EventHandle_WidgetIntIntButton eventMouseButtonReleased
EventHandle_WidgetIntIntButton eventMouseButtonPressed
EventPairAddParameter< EventHandle_WidgetIntInt, EventHandle_WidgetIntIntButton > eventMouseDrag
EventHandle_WidgetInt eventMouseWheel
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))