MyGUI  3.2.0
MyGUI_ScrollBar.cpp
Go to the documentation of this file.
1 
6 /*
7  This file is part of MyGUI.
8 
9  MyGUI is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  MyGUI 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 Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
21 */
22 #include "MyGUI_Precompiled.h"
23 #include "MyGUI_ScrollBar.h"
24 #include "MyGUI_InputManager.h"
25 #include "MyGUI_Button.h"
26 #include "MyGUI_ResourceSkin.h"
27 
28 namespace MyGUI
29 {
30 
31  // FIXME - move to widget property
32  const int SCROLL_MOUSE_WHEEL = 50; // колличество пикселей для колеса мыши
33 
35  mWidgetStart(nullptr),
36  mWidgetEnd(nullptr),
37  mWidgetTrack(nullptr),
38  mWidgetFirstPart(nullptr),
39  mWidgetSecondPart(nullptr),
40  mSkinRangeStart(0),
41  mSkinRangeEnd(0),
42  mScrollRange(0),
43  mScrollPosition(0),
44  mScrollPage(0),
45  mScrollViewPage(0),
46  mMinTrackSize(0),
47  mMoveToClick(false),
48  mVerticalAlignment(true)
49  {
50  }
51 
53  {
54  Base::initialiseOverride();
55 
56  // при нуле, будет игнорировать кнопки
57  mScrollPage = 1;
58  mScrollViewPage = 1;
59  mMinTrackSize = 0;
60  mSkinRangeStart = 0;
61  mSkinRangeEnd = 0;
62 
63  assignWidget(mWidgetStart, "Start");
64  if (mWidgetStart != nullptr)
65  {
68  }
69 
70  assignWidget(mWidgetEnd, "End");
71  if (mWidgetEnd != nullptr)
72  {
75  }
76 
77  assignWidget(mWidgetTrack, "Track");
78  if (mWidgetTrack)
79  {
84  mWidgetTrack->setVisible(false);
85  }
86 
87  assignWidget(mWidgetFirstPart, "FirstPart");
88  if (mWidgetFirstPart != nullptr)
89  {
92  }
93 
94  assignWidget(mWidgetSecondPart, "SecondPart");
95  if (mWidgetSecondPart != nullptr)
96  {
99  }
100 
101  if (isUserString("MinTrackSize"))
102  mMinTrackSize = utility::parseValue<int>(getUserString("MinTrackSize"));
103  if (isUserString("TrackRangeMargins"))
104  utility::parseComplex<size_t>(getUserString("TrackRangeMargins"), mSkinRangeStart, mSkinRangeEnd);
105 
106  if (mWidgetTrack != nullptr)
107  {
108  if (mWidgetTrack->isUserString("MinTrackSize"))
109  mMinTrackSize = utility::parseValue<int>(mWidgetTrack->getUserString("MinTrackSize"));
110  }
111  }
112 
114  {
115  mWidgetStart = nullptr;
116  mWidgetEnd = nullptr;
117  mWidgetTrack = nullptr;
118  mWidgetFirstPart = nullptr;
119  mWidgetSecondPart = nullptr;
120 
121  Base::shutdownOverride();
122  }
123 
125  {
126  if (mWidgetTrack == nullptr)
127  return;
128 
130  // размер диапазана в пикселях
131  int pos = getLineSize();
132 
133  if (mVerticalAlignment)
134  {
135  // скрываем если диапазан маленький или места мало
136  if ((mScrollRange < 2) || (pos <= mWidgetTrack->getHeight()))
137  {
138  mWidgetTrack->setVisible(false);
139  if (nullptr != mWidgetFirstPart)
141  if (nullptr != mWidgetSecondPart)
143  return;
144  }
145  // если скрыт то покажем
146  if (!mWidgetTrack->getVisible())
147  mWidgetTrack->setVisible(true);
148 
149  // и обновляем позицию
150  pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);
151 
153  if (nullptr != mWidgetFirstPart)
154  {
155  int height = pos - mWidgetFirstPart->getTop();
157  }
158  if (nullptr != mWidgetSecondPart)
159  {
160  int top = pos + mWidgetTrack->getHeight();
161  int height = mWidgetSecondPart->getHeight() + mWidgetSecondPart->getTop() - top;
163  }
164  }
165  else
166  {
167  // скрываем если диапазан маленький или места мало
168  if ((mScrollRange < 2) || (pos <= mWidgetTrack->getWidth()))
169  {
170  mWidgetTrack->setVisible(false);
171  if (nullptr != mWidgetFirstPart)
173  if (nullptr != mWidgetSecondPart)
175  return;
176  }
177  // если скрыт то покажем
178  if (!mWidgetTrack->getVisible())
179  mWidgetTrack->setVisible(true);
180 
181  // и обновляем позицию
182  pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);
183 
185  if (nullptr != mWidgetFirstPart)
186  {
187  int height = pos - mWidgetFirstPart->getLeft();
189  }
190  if (nullptr != mWidgetSecondPart)
191  {
192  int top = pos + mWidgetTrack->getWidth();
193  int height = mWidgetSecondPart->getWidth() + mWidgetSecondPart->getLeft() - top;
195  }
196  }
197  }
198 
199  void ScrollBar::TrackMove(int _left, int _top)
200  {
201  if (mWidgetTrack == nullptr)
202  return;
203 
205 
206  if (mVerticalAlignment)
207  {
208  // расчитываем позицию виджета
209  int start = mPreActionOffset.top + (_top - point.top);
210  if (start < (int)mSkinRangeStart)
211  start = (int)mSkinRangeStart;
212  else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getHeight()))
214  if (mWidgetTrack->getTop() != start)
216 
217  // расчитываем положение соответствующее позиции
218  // плюс пол позиции
219  int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
220  // высчитываем ближайшее значение и обновляем
221  pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
222 
223  // проверяем на выходы и изменения
224  if (pos < 0)
225  pos = 0;
226  else if (pos >= (int)mScrollRange)
227  pos = (int)mScrollRange - 1;
228  if (pos == (int)mScrollPosition)
229  return;
230 
231  mScrollPosition = pos;
232  }
233  else
234  {
235  // расчитываем позицию виджета
236  int start = mPreActionOffset.left + (_left - point.left);
237  if (start < (int)mSkinRangeStart)
238  start = (int)mSkinRangeStart;
239  else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth()))
240  start = (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth());
241  if (mWidgetTrack->getLeft() != start)
243 
244  // расчитываем положение соответствующее позиции
245  // плюс пол позиции
246  int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
247  // высчитываем ближайшее значение и обновляем
248  pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
249 
250  // проверяем на выходы и изменения
251  if (pos < 0)
252  pos = 0;
253  else if (pos >= (int)mScrollRange)
254  pos = (int)mScrollRange - 1;
255  if (pos == (int)mScrollPosition)
256  return;
257 
258  mScrollPosition = pos;
259  }
260 
261  updateTrack();
262 
263  // отсылаем событие
265  }
266 
267  void ScrollBar::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
268  {
269  // диспечерезируем нажатие своих детей как свое
270  eventMouseButtonPressed(this, _left, _top, _id);
271 
272  if (MouseButton::Left != _id)
273  return;
274 
275  if (mMoveToClick &&
276  _sender != mWidgetTrack &&
277  _sender != mWidgetStart &&
278  _sender != mWidgetEnd)
279  {
280  if (mWidgetTrack != nullptr)
281  {
284 
287 
288  TrackMove(point.left, point.top);
289  }
290  }
291  else if (_sender == mWidgetStart)
292  {
293  // минимальное значение
294  if (mScrollPosition == 0)
295  return;
296 
297  // расчитываем следующее положение
300  else
301  mScrollPosition = 0;
302 
303  // оповещаем
305  updateTrack();
306  }
307  else if (_sender == mWidgetEnd)
308  {
309  // максимальное значение
310  if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
311  return;
312 
313  // расчитываем следующее положение
314  if ((mScrollPosition + mScrollPage) < (mScrollRange - 1))
316  else
318 
319  // оповещаем
321  updateTrack();
322  }
323  else if (_sender == mWidgetFirstPart)
324  {
325  // минимальное значение
326  if (mScrollPosition == 0)
327  return;
328 
329  // расчитываем следующее положение
332  else
333  mScrollPosition = 0;
334 
335  // оповещаем
337  updateTrack();
338  }
339  else if (_sender == mWidgetSecondPart)
340  {
341  // максимальное значение
342  if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
343  return;
344 
345  // расчитываем следующее положение
348  else
350 
351  // оповещаем
353  updateTrack();
354  }
355  else if (_sender == mWidgetTrack)
356  {
357  mPreActionOffset.left = _sender->getLeft();
358  mPreActionOffset.top = _sender->getTop();
359  }
360  }
361 
362  void ScrollBar::notifyMouseReleased(Widget* _sender, int _left, int _top, MouseButton _id)
363  {
364  updateTrack();
365  }
366 
367  void ScrollBar::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
368  {
369  if (_id == MouseButton::Left)
370  TrackMove(_left, _top);
371  }
372 
373  void ScrollBar::setScrollRange(size_t _range)
374  {
375  if (_range == mScrollRange)
376  return;
377 
378  mScrollRange = _range;
380  updateTrack();
381  }
382 
383  void ScrollBar::setScrollPosition(size_t _position)
384  {
385  if (_position == mScrollPosition)
386  return;
387 
388  if (_position >= mScrollRange)
389  _position = 0;
390 
391  mScrollPosition = _position;
392  updateTrack();
393  }
394 
395  void ScrollBar::setPosition(const IntPoint& _point)
396  {
397  Base::setPosition(_point);
398  }
399 
400  void ScrollBar::setSize(const IntSize& _size)
401  {
402  Base::setSize(_size);
403  // обновляем трек
404  updateTrack();
405  }
406 
407  void ScrollBar::setCoord(const IntCoord& _coord)
408  {
409  Base::setCoord(_coord);
410  // обновляем трек
411  updateTrack();
412  }
413 
414  void ScrollBar::setTrackSize(int _size)
415  {
416  if (mWidgetTrack != nullptr)
417  {
418  if (mVerticalAlignment)
419  mWidgetTrack->setSize(mWidgetTrack->getWidth(), ((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size);
420  else
421  mWidgetTrack->setSize(((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size, mWidgetTrack->getHeight());
422  }
423 
424  updateTrack();
425  }
426 
428  {
429  if (mWidgetTrack != nullptr)
430  {
431  if (mVerticalAlignment)
432  return mWidgetTrack->getHeight();
433  else
434  return mWidgetTrack->getWidth();
435  }
436  return 1;
437  }
438 
440  {
442  }
443 
444  void ScrollBar::onMouseWheel(int _rel)
445  {
446  notifyMouseWheel(nullptr, _rel);
447 
448  Base::onMouseWheel(_rel);
449  }
450 
451  void ScrollBar::notifyMouseWheel(Widget* _sender, int _rel)
452  {
453  if (mScrollRange < 2)
454  return;
455 
456  int offset = mScrollPosition;
457  if (_rel < 0)
458  offset += SCROLL_MOUSE_WHEEL;
459  else
460  offset -= SCROLL_MOUSE_WHEEL;
461 
462  if (offset < 0)
463  offset = 0;
464  else if (offset > (int)(mScrollRange - 1))
465  offset = mScrollRange - 1;
466 
467  if ((size_t)offset != mScrollPosition)
468  {
469  mScrollPosition = offset;
470  // оповещаем
472  updateTrack();
473  }
474  }
475 
476  void ScrollBar::setPropertyOverride(const std::string& _key, const std::string& _value)
477  {
478  if (_key == "Range")
479  setScrollRange(utility::parseValue<size_t>(_value));
480  else if (_key == "RangePosition")
481  setScrollPosition(utility::parseValue<size_t>(_value));
482  else if (_key == "Page")
483  setScrollPage(utility::parseValue<size_t>(_value));
484  else if (_key == "ViewPage")
485  setScrollViewPage(utility::parseValue<size_t>(_value));
486  else if (_key == "MoveToClick")
487  setMoveToClick(utility::parseValue<bool>(_value));
488  else if (_key == "VerticalAlignment")
489  setVerticalAlignment(utility::parseValue<bool>(_value));
490  else
491  {
492  Base::setPropertyOverride(_key, _value);
493  return;
494  }
495  eventChangeProperty(this, _key, _value);
496  }
497 
499  {
500  return mScrollRange;
501  }
502 
504  {
505  return mScrollPosition;
506  }
507 
508  void ScrollBar::setScrollPage(size_t _value)
509  {
510  mScrollPage = _value;
511  }
512 
514  {
515  return mScrollPage;
516  }
517 
518  void ScrollBar::setScrollViewPage(size_t _value)
519  {
520  mScrollViewPage = _value;
521  }
522 
524  {
525  return mScrollViewPage;
526  }
527 
528  void ScrollBar::setMinTrackSize(int _value)
529  {
530  mMinTrackSize = _value;
531  }
532 
534  {
535  return mMinTrackSize;
536  }
537 
538  void ScrollBar::setMoveToClick(bool _value)
539  {
540  mMoveToClick = _value;
541  }
542 
544  {
545  return mMoveToClick;
546  }
547 
548  void ScrollBar::setPosition(int _left, int _top)
549  {
550  setPosition(IntPoint(_left, _top));
551  }
552 
553  void ScrollBar::setSize(int _width, int _height)
554  {
555  setSize(IntSize(_width, _height));
556  }
557 
558  void ScrollBar::setCoord(int _left, int _top, int _width, int _height)
559  {
560  setCoord(IntCoord(_left, _top, _width, _height));
561  }
562 
564  {
565  if (mWidgetTrack != nullptr)
566  {
567  if (mVerticalAlignment)
568  return mWidgetTrack->getParent()->getHeight();
569  else
570  return mWidgetTrack->getParent()->getWidth();
571  }
572  return 0;
573  }
574 
576  {
577  mVerticalAlignment = _value;
578 
579  updateTrack();
580  }
581 
583  {
584  return mVerticalAlignment;
585  }
586 
587 } // namespace MyGUI