MyGUI  3.2.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"
12 
13 namespace MyGUI
14 {
15 
17  mWidgetStart(nullptr),
18  mWidgetEnd(nullptr),
19  mWidgetTrack(nullptr),
20  mWidgetFirstPart(nullptr),
21  mWidgetSecondPart(nullptr),
22  mSkinRangeStart(0),
23  mSkinRangeEnd(0),
24  mScrollRange(0),
25  mScrollPosition(0),
26  mScrollPage(0),
27  mScrollViewPage(0),
28  mScrollWheelPage(0),
29  mMinTrackSize(0),
30  mMoveToClick(false),
31  mVerticalAlignment(true)
32  {
33  }
34 
36  {
37  Base::initialiseOverride();
38 
39  // при нуле, будет игнорировать кнопки
40  mScrollPage = 1;
41  mScrollViewPage = 1;
42  mScrollWheelPage = 1;
43  mMinTrackSize = 0;
44  mSkinRangeStart = 0;
45  mSkinRangeEnd = 0;
46 
48  assignWidget(mWidgetStart, "Start");
49  if (mWidgetStart != nullptr)
50  {
53  }
54 
56  assignWidget(mWidgetEnd, "End");
57  if (mWidgetEnd != nullptr)
58  {
61  }
62 
64  assignWidget(mWidgetTrack, "Track");
65  if (mWidgetTrack)
66  {
71  mWidgetTrack->setVisible(false);
72  }
73 
75  assignWidget(mWidgetFirstPart, "FirstPart");
76  if (mWidgetFirstPart != nullptr)
77  {
80  }
81 
83  assignWidget(mWidgetSecondPart, "SecondPart");
84  if (mWidgetSecondPart != nullptr)
85  {
88  }
89 
90  if (isUserString("MinTrackSize"))
91  mMinTrackSize = utility::parseValue<int>(getUserString("MinTrackSize"));
92 
93  if (isUserString("TrackRangeMargins"))
94  utility::parseComplex<size_t>(getUserString("TrackRangeMargins"), mSkinRangeStart, mSkinRangeEnd);
95 
96  if (mWidgetTrack != nullptr)
97  {
98  if (mWidgetTrack->isUserString("MinTrackSize"))
99  mMinTrackSize = utility::parseValue<int>(mWidgetTrack->getUserString("MinTrackSize"));
100  }
101  }
102 
104  {
105  mWidgetStart = nullptr;
106  mWidgetEnd = nullptr;
107  mWidgetTrack = nullptr;
108  mWidgetFirstPart = nullptr;
109  mWidgetSecondPart = nullptr;
110 
111  Base::shutdownOverride();
112  }
113 
115  {
116  if (mWidgetTrack == nullptr)
117  return;
118 
120  // размер диапазана в пикселях
121  int pos = getLineSize();
122 
123  if (mVerticalAlignment)
124  {
125  // скрываем если диапазан маленький или места мало
126  if ((mScrollRange < 2) || (pos <= mWidgetTrack->getHeight()))
127  {
128  mWidgetTrack->setVisible(false);
129  if (nullptr != mWidgetFirstPart)
131  if (nullptr != mWidgetSecondPart)
133  return;
134  }
135  // если скрыт то покажем
136  if (!mWidgetTrack->getVisible())
137  mWidgetTrack->setVisible(true);
138 
139  // и обновляем позицию
140  pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);
141 
143  if (nullptr != mWidgetFirstPart)
144  {
145  int height = pos - mWidgetFirstPart->getTop();
147  }
148  if (nullptr != mWidgetSecondPart)
149  {
150  int top = pos + mWidgetTrack->getHeight();
151  int height = mWidgetSecondPart->getHeight() + mWidgetSecondPart->getTop() - top;
153  }
154  }
155  else
156  {
157  // скрываем если диапазан маленький или места мало
158  if ((mScrollRange < 2) || (pos <= mWidgetTrack->getWidth()))
159  {
160  mWidgetTrack->setVisible(false);
161  if (nullptr != mWidgetFirstPart)
163  if (nullptr != mWidgetSecondPart)
165  return;
166  }
167  // если скрыт то покажем
168  if (!mWidgetTrack->getVisible())
169  mWidgetTrack->setVisible(true);
170 
171  // и обновляем позицию
172  pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);
173 
175  if (nullptr != mWidgetFirstPart)
176  {
177  int height = pos - mWidgetFirstPart->getLeft();
179  }
180  if (nullptr != mWidgetSecondPart)
181  {
182  int top = pos + mWidgetTrack->getWidth();
183  int height = mWidgetSecondPart->getWidth() + mWidgetSecondPart->getLeft() - top;
185  }
186  }
187  }
188 
189  void ScrollBar::TrackMove(int _left, int _top)
190  {
191  if (mWidgetTrack == nullptr)
192  return;
193 
195 
196  if (mVerticalAlignment)
197  {
198  // расчитываем позицию виджета
199  int start = mPreActionOffset.top + (_top - point.top);
200  if (start < (int)mSkinRangeStart)
201  start = (int)mSkinRangeStart;
202  else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getHeight()))
204  if (mWidgetTrack->getTop() != start)
206 
207  // расчитываем положение соответствующее позиции
208  // плюс пол позиции
209  int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
210  // высчитываем ближайшее значение и обновляем
211  pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
212 
213  // проверяем на выходы и изменения
214  if (pos < 0)
215  pos = 0;
216  else if (pos >= (int)mScrollRange)
217  pos = (int)mScrollRange - 1;
218  if (pos == (int)mScrollPosition)
219  return;
220 
221  mScrollPosition = pos;
222  }
223  else
224  {
225  // расчитываем позицию виджета
226  int start = mPreActionOffset.left + (_left - point.left);
227  if (start < (int)mSkinRangeStart)
228  start = (int)mSkinRangeStart;
229  else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth()))
230  start = (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth());
231  if (mWidgetTrack->getLeft() != start)
233 
234  // расчитываем положение соответствующее позиции
235  // плюс пол позиции
236  int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
237  // высчитываем ближайшее значение и обновляем
238  pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
239 
240  // проверяем на выходы и изменения
241  if (pos < 0)
242  pos = 0;
243  else if (pos >= (int)mScrollRange)
244  pos = (int)mScrollRange - 1;
245  if (pos == (int)mScrollPosition)
246  return;
247 
248  mScrollPosition = pos;
249  }
250 
251  updateTrack();
252 
253  // отсылаем событие
255  }
256 
257  void ScrollBar::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
258  {
259  // диспечерезируем нажатие своих детей как свое
260  eventMouseButtonPressed(this, _left, _top, _id);
261 
262  if (MouseButton::Left != _id)
263  return;
264 
265  if (mMoveToClick &&
266  _sender != mWidgetTrack &&
267  _sender != mWidgetStart &&
268  _sender != mWidgetEnd)
269  {
270  if (mWidgetTrack != nullptr)
271  {
274 
277 
278  TrackMove(point.left, point.top);
279  }
280  }
281  else if (_sender == mWidgetStart)
282  {
283  // минимальное значение
284  if (mScrollPosition == 0)
285  return;
286 
287  // расчитываем следующее положение
290  else
291  mScrollPosition = 0;
292 
293  // оповещаем
295  updateTrack();
296  }
297  else if (_sender == mWidgetEnd)
298  {
299  // максимальное значение
300  if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
301  return;
302 
303  // расчитываем следующее положение
304  if ((mScrollPosition + mScrollPage) < (mScrollRange - 1))
306  else
308 
309  // оповещаем
311  updateTrack();
312  }
313  else if (_sender == mWidgetFirstPart)
314  {
315  // минимальное значение
316  if (mScrollPosition == 0)
317  return;
318 
319  // расчитываем следующее положение
322  else
323  mScrollPosition = 0;
324 
325  // оповещаем
327  updateTrack();
328  }
329  else if (_sender == mWidgetSecondPart)
330  {
331  // максимальное значение
332  if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
333  return;
334 
335  // расчитываем следующее положение
338  else
340 
341  // оповещаем
343  updateTrack();
344  }
345  else if (_sender == mWidgetTrack)
346  {
347  mPreActionOffset.left = _sender->getLeft();
348  mPreActionOffset.top = _sender->getTop();
349  }
350  }
351 
352  void ScrollBar::notifyMouseReleased(Widget* _sender, int _left, int _top, MouseButton _id)
353  {
354  updateTrack();
355  }
356 
357  void ScrollBar::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
358  {
359  if (_id == MouseButton::Left)
360  TrackMove(_left, _top);
361  }
362 
363  void ScrollBar::setScrollRange(size_t _range)
364  {
365  if (_range == mScrollRange)
366  return;
367 
368  mScrollRange = _range;
370  updateTrack();
371  }
372 
373  void ScrollBar::setScrollPosition(size_t _position)
374  {
375  if (_position == mScrollPosition)
376  return;
377 
378  if (_position >= mScrollRange)
379  _position = 0;
380 
381  mScrollPosition = _position;
382  updateTrack();
383  }
384 
385  void ScrollBar::setPosition(const IntPoint& _point)
386  {
387  Base::setPosition(_point);
388  }
389 
390  void ScrollBar::setSize(const IntSize& _size)
391  {
392  Base::setSize(_size);
393  // обновляем трек
394  updateTrack();
395  }
396 
397  void ScrollBar::setCoord(const IntCoord& _coord)
398  {
399  Base::setCoord(_coord);
400  // обновляем трек
401  updateTrack();
402  }
403 
404  void ScrollBar::setTrackSize(int _size)
405  {
406  if (mWidgetTrack != nullptr)
407  {
408  if (mVerticalAlignment)
409  mWidgetTrack->setSize(mWidgetTrack->getWidth(), ((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size);
410  else
411  mWidgetTrack->setSize(((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size, mWidgetTrack->getHeight());
412  }
413 
414  updateTrack();
415  }
416 
418  {
419  if (mWidgetTrack != nullptr)
420  {
421  if (mVerticalAlignment)
422  return mWidgetTrack->getHeight();
423  else
424  return mWidgetTrack->getWidth();
425  }
426  return 1;
427  }
428 
430  {
432  }
433 
434  void ScrollBar::onMouseWheel(int _rel)
435  {
436  notifyMouseWheel(nullptr, _rel);
437 
438  Base::onMouseWheel(_rel);
439  }
440 
441  void ScrollBar::notifyMouseWheel(Widget* _sender, int _rel)
442  {
443  if (mScrollRange < 2)
444  return;
445 
446  int offset = mScrollPosition;
447  if (_rel < 0)
448  offset += mScrollWheelPage;
449  else
450  offset -= mScrollWheelPage;
451 
452  if (offset < 0)
453  offset = 0;
454  else if (offset > (int)(mScrollRange - 1))
455  offset = mScrollRange - 1;
456 
457  if ((size_t)offset != mScrollPosition)
458  {
459  mScrollPosition = offset;
460  // оповещаем
462  updateTrack();
463  }
464  }
465 
466  void ScrollBar::setPropertyOverride(const std::string& _key, const std::string& _value)
467  {
469  if (_key == "Range")
470  setScrollRange(utility::parseValue<size_t>(_value));
471 
473  else if (_key == "RangePosition")
474  setScrollPosition(utility::parseValue<size_t>(_value));
475 
477  else if (_key == "Page")
478  setScrollPage(utility::parseValue<size_t>(_value));
479 
481  else if (_key == "ViewPage")
482  setScrollViewPage(utility::parseValue<size_t>(_value));
483 
485  else if (_key == "WheelPage")
486  setScrollWheelPage(utility::parseValue<size_t>(_value));
487 
489  else if (_key == "MoveToClick")
490  setMoveToClick(utility::parseValue<bool>(_value));
491 
493  else if (_key == "VerticalAlignment")
494  setVerticalAlignment(utility::parseValue<bool>(_value));
495 
496  else
497  {
498  Base::setPropertyOverride(_key, _value);
499  return;
500  }
501 
502  eventChangeProperty(this, _key, _value);
503  }
504 
506  {
507  return mScrollRange;
508  }
509 
511  {
512  return mScrollPosition;
513  }
514 
515  void ScrollBar::setScrollPage(size_t _value)
516  {
517  mScrollPage = _value;
518  }
519 
521  {
522  return mScrollPage;
523  }
524 
525  void ScrollBar::setScrollViewPage(size_t _value)
526  {
527  mScrollViewPage = _value;
528  }
529 
531  {
532  return mScrollViewPage;
533  }
534 
535  void ScrollBar::setScrollWheelPage(size_t _value)
536  {
537  mScrollWheelPage = _value;
538  }
540  {
541  return mScrollWheelPage;
542  }
543 
544  void ScrollBar::setMinTrackSize(int _value)
545  {
546  mMinTrackSize = _value;
547  }
548 
550  {
551  return mMinTrackSize;
552  }
553 
554  void ScrollBar::setMoveToClick(bool _value)
555  {
556  mMoveToClick = _value;
557  }
558 
560  {
561  return mMoveToClick;
562  }
563 
564  void ScrollBar::setPosition(int _left, int _top)
565  {
566  setPosition(IntPoint(_left, _top));
567  }
568 
569  void ScrollBar::setSize(int _width, int _height)
570  {
571  setSize(IntSize(_width, _height));
572  }
573 
574  void ScrollBar::setCoord(int _left, int _top, int _width, int _height)
575  {
576  setCoord(IntCoord(_left, _top, _width, _height));
577  }
578 
580  {
581  if (mWidgetTrack != nullptr)
582  {
583  if (mVerticalAlignment)
584  return mWidgetTrack->getParent()->getHeight();
585  else
586  return mWidgetTrack->getParent()->getWidth();
587  }
588  return 0;
589  }
590 
592  {
593  mVerticalAlignment = _value;
594 
595  updateTrack();
596  }
597 
599  {
600  return mVerticalAlignment;
601  }
602 
603 } // namespace MyGUI