MyGUI 3.4.3
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"
10#include "MyGUI_Button.h"
11#include "MyGUI_ResourceSkin.h"
14
15namespace MyGUI
16{
17
19 {
21
22 // при нуле, будет игнорировать кнопки
23 mScrollPage = 1;
26 mMinTrackSize = 0;
28 mSkinRangeEnd = 0;
29
30 mRepeatTriggerTime = 0.5f;
31 mRepeatStepTime = 0.1f;
32
34 assignWidget(mWidgetStart, "Start");
35 if (mWidgetStart != nullptr)
36 {
37 mWidgetStart->eventMouseButtonPressed += newDelegate(this, &ScrollBar::notifyMousePressed);
38 mWidgetStart->eventMouseButtonReleased += newDelegate(this, &ScrollBar::notifyMouseReleased);
39 mWidgetStart->eventMouseWheel += newDelegate(this, &ScrollBar::notifyMouseWheel);
40 }
41
44 if (mWidgetEnd != nullptr)
45 {
46 mWidgetEnd->eventMouseButtonPressed += newDelegate(this, &ScrollBar::notifyMousePressed);
47 mWidgetEnd->eventMouseButtonReleased += newDelegate(this, &ScrollBar::notifyMouseReleased);
48 mWidgetEnd->eventMouseWheel += newDelegate(this, &ScrollBar::notifyMouseWheel);
49 }
50
52 assignWidget(mWidgetTrack, "Track");
53 if (mWidgetTrack)
54 {
55 mWidgetTrack->eventMouseDrag += newDelegate(this, &ScrollBar::notifyMouseDrag);
56 mWidgetTrack->eventMouseButtonPressed += newDelegate(this, &ScrollBar::notifyMousePressed);
57 mWidgetTrack->eventMouseButtonReleased += newDelegate(this, &ScrollBar::notifyMouseReleased);
58 mWidgetTrack->eventMouseWheel += newDelegate(this, &ScrollBar::notifyMouseWheel);
59 mWidgetTrack->setVisible(false);
60 }
61
63 assignWidget(mWidgetFirstPart, "FirstPart");
64 if (mWidgetFirstPart != nullptr)
65 {
66 mWidgetFirstPart->eventMouseButtonPressed += newDelegate(this, &ScrollBar::notifyMousePressed);
67 mWidgetFirstPart->eventMouseButtonReleased += newDelegate(this, &ScrollBar::notifyMouseReleased);
69 }
70
72 assignWidget(mWidgetSecondPart, "SecondPart");
73 if (mWidgetSecondPart != nullptr)
74 {
75 mWidgetSecondPart->eventMouseButtonPressed += newDelegate(this, &ScrollBar::notifyMousePressed);
76 mWidgetSecondPart->eventMouseButtonReleased += newDelegate(this, &ScrollBar::notifyMouseReleased);
78 }
79
80 if (isUserString("MinTrackSize"))
82
83 if (isUserString("TrackRangeMargins"))
85
86 if (mWidgetTrack != nullptr)
87 {
88 if (mWidgetTrack->isUserString("MinTrackSize"))
89 mMinTrackSize = utility::parseValue<int>(mWidgetTrack->getUserString("MinTrackSize"));
90 }
91 }
92
94 {
95 mWidgetStart = nullptr;
96 mWidgetEnd = nullptr;
97 mWidgetTrack = nullptr;
98 mWidgetFirstPart = nullptr;
99 mWidgetSecondPart = nullptr;
100
102 }
103
105 {
106 if (mWidgetTrack == nullptr)
107 return;
108
110 // размер диапазана в пикселях
111 int pos = getLineSize();
112
114 {
115 // скрываем если диапазан маленький или места мало
116 if ((mScrollRange < 2) || (pos <= mWidgetTrack->getHeight()))
117 {
118 mWidgetTrack->setVisible(false);
119 if (nullptr != mWidgetFirstPart)
120 mWidgetFirstPart->setSize(mWidgetFirstPart->getWidth(), pos / 2);
121 if (nullptr != mWidgetSecondPart)
122 mWidgetSecondPart->setCoord(
123 mWidgetSecondPart->getLeft(),
124 pos / 2 + (int)mSkinRangeStart,
125 mWidgetSecondPart->getWidth(),
126 pos - pos / 2);
127 return;
128 }
129 // если скрыт то покажем
130 if (!mWidgetTrack->getVisible())
131 mWidgetTrack->setVisible(true);
132
133 // и обновляем позицию
134 pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);
135
136 mWidgetTrack->setPosition(mWidgetTrack->getLeft(), pos);
137 if (nullptr != mWidgetFirstPart)
138 {
139 int height = pos - mWidgetFirstPart->getTop();
140 mWidgetFirstPart->setSize(mWidgetFirstPart->getWidth(), height);
141 }
142 if (nullptr != mWidgetSecondPart)
143 {
144 int top = pos + mWidgetTrack->getHeight();
145 int height = getTrackPlaceLength() - top;
146 mWidgetSecondPart->setCoord(mWidgetSecondPart->getLeft(), top, mWidgetSecondPart->getWidth(), height);
147 }
148 }
149 else
150 {
151 // скрываем если диапазан маленький или места мало
152 if ((mScrollRange < 2) || (pos <= mWidgetTrack->getWidth()))
153 {
154 mWidgetTrack->setVisible(false);
155 if (nullptr != mWidgetFirstPart)
156 mWidgetFirstPart->setSize(pos / 2, mWidgetFirstPart->getHeight());
157 if (nullptr != mWidgetSecondPart)
158 mWidgetSecondPart->setCoord(
159 pos / 2 + (int)mSkinRangeStart,
160 mWidgetSecondPart->getTop(),
161 pos - pos / 2,
162 mWidgetSecondPart->getHeight());
163 return;
164 }
165 // если скрыт то покажем
166 if (!mWidgetTrack->getVisible())
167 mWidgetTrack->setVisible(true);
168
169 // и обновляем позицию
170 pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);
171
172 mWidgetTrack->setPosition(pos, mWidgetTrack->getTop());
173 if (nullptr != mWidgetFirstPart)
174 {
175 int height = pos - mWidgetFirstPart->getLeft();
176 mWidgetFirstPart->setSize(height, mWidgetFirstPart->getHeight());
177 }
178 if (nullptr != mWidgetSecondPart)
179 {
180 int left = pos + mWidgetTrack->getWidth();
181 int width = getTrackPlaceLength() - left;
182 mWidgetSecondPart->setCoord(left, mWidgetSecondPart->getTop(), width, mWidgetSecondPart->getHeight());
183 }
184 }
185 }
186
187 void ScrollBar::TrackMove(int _left, int _top)
188 {
189 if (mWidgetTrack == nullptr)
190 return;
191
193
195 {
196 // расчитываем позицию виджета
197 int start = mPreActionOffset.top + (_top - point.top);
198 if (start < (int)mSkinRangeStart)
199 start = (int)mSkinRangeStart;
200 else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getHeight()))
201 start = (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getHeight());
202 if (mWidgetTrack->getTop() != start)
203 mWidgetTrack->setPosition(mWidgetTrack->getLeft(), start);
204
205 // расчитываем положение соответствующее позиции
206 // плюс пол позиции
207 int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
208 // высчитываем ближайшее значение и обновляем
209 pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
210
211 // проверяем на выходы и изменения
212 if (pos < 0)
213 pos = 0;
214 else if (pos >= (int)mScrollRange)
215 pos = (int)mScrollRange - 1;
216 if (pos == (int)mScrollPosition)
217 return;
218
219 mScrollPosition = pos;
220 }
221 else
222 {
223 // расчитываем позицию виджета
224 int start = mPreActionOffset.left + (_left - point.left);
225 if (start < (int)mSkinRangeStart)
226 start = (int)mSkinRangeStart;
227 else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth()))
228 start = (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth());
229 if (mWidgetTrack->getLeft() != start)
230 mWidgetTrack->setPosition(IntPoint(start, mWidgetTrack->getTop()));
231
232 // расчитываем положение соответствующее позиции
233 // плюс пол позиции
234 int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
235 // высчитываем ближайшее значение и обновляем
236 pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
237
238 // проверяем на выходы и изменения
239 if (pos < 0)
240 pos = 0;
241 else if (pos >= (int)mScrollRange)
242 pos = (int)mScrollRange - 1;
243 if (pos == (int)mScrollPosition)
244 return;
245
246 mScrollPosition = pos;
247 }
248
249 updateTrack();
250
251 // отсылаем событие
253 }
254
255 void ScrollBar::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
256 {
257 // диспечерезируем нажатие своих детей как свое
258 eventMouseButtonPressed(this, _left, _top, _id);
259
260 if (MouseButton::Left != _id)
261 return;
262
263 if (mEnableRepeat && _sender != mWidgetTrack &&
264 ((_sender != mWidgetFirstPart && _sender != mWidgetSecondPart) || !mMoveToClick))
265 {
266 ControllerItem* item =
269 controller->eventRepeatClick += newDelegate(this, &ScrollBar::repeatClick);
271 ControllerManager::getInstance().addItem(_sender, controller);
272 }
273
274 if (mMoveToClick && _sender != mWidgetTrack && _sender != mWidgetStart && _sender != mWidgetEnd)
275 {
276 if (mWidgetTrack != nullptr)
277 {
280 mWidgetTrack->getParent()->getAbsolutePosition();
281
282 mPreActionOffset.left -= getTrackSize() / 2;
283 mPreActionOffset.top -= getTrackSize() / 2;
284
285 TrackMove(point.left, point.top);
286 }
287 }
288 else if (_sender == mWidgetStart)
289 {
290 widgetStartPressed();
291 }
292 else if (_sender == mWidgetEnd)
293 {
294 widgetEndPressed();
295 }
296 else if (_sender == mWidgetFirstPart)
297 {
298 widgetFirstPartPressed();
299 }
300 else if (_sender == mWidgetSecondPart)
301 {
302 widgetSecondPartPressed();
303 }
304 else if (_sender == mWidgetTrack)
305 {
306 mPreActionOffset.left = _sender->getLeft();
307 mPreActionOffset.top = _sender->getTop();
308 }
309 }
310
311 void ScrollBar::notifyMouseReleased(Widget* _sender, int _left, int _top, MouseButton _id)
312 {
313 updateTrack();
315 }
316
317 void ScrollBar::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
318 {
319 if (mScrollRange < 2)
320 return;
321 if (_id == MouseButton::Left)
322 TrackMove(_left, _top);
323 }
324
325 void ScrollBar::setScrollRange(size_t _range)
326 {
327 if (_range == mScrollRange)
328 return;
329
330 mScrollRange = _range;
332 updateTrack();
333 }
334
335 void ScrollBar::setScrollPosition(size_t _position)
336 {
337 if (_position == mScrollPosition)
338 return;
339
340 if (_position >= mScrollRange)
341 _position = 0;
342
343 mScrollPosition = _position;
344 updateTrack();
345 }
346
348 {
349 Base::setPosition(_point);
350 }
351
352 void ScrollBar::setSize(const IntSize& _size)
353 {
354 Base::setSize(_size);
355 // обновляем трек
356 updateTrack();
357 }
358
359 void ScrollBar::setCoord(const IntCoord& _coord)
360 {
361 Base::setCoord(_coord);
362 // обновляем трек
363 updateTrack();
364 }
365
367 {
368 if (mWidgetTrack != nullptr)
369 {
371 mWidgetTrack->setSize(
372 mWidgetTrack->getWidth(),
373 ((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size);
374 else
375 mWidgetTrack->setSize(
376 ((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size,
377 mWidgetTrack->getHeight());
378 }
379 updateTrack();
380 }
381
383 {
384 mRepeatTriggerTime = time;
385 }
386
388 {
389 mRepeatStepTime = time;
390 }
391
392 float ScrollBar::getRepeatTriggerTime(float time) const
393 {
394 return mRepeatTriggerTime;
395 }
396
397 float ScrollBar::getRepeatStepTime(float time) const
398 {
399 return mRepeatStepTime;
400 }
401
403 {
404 mEnableRepeat = enabled;
405 }
406
408 {
409 return mEnableRepeat;
410 }
411
413 {
414 if (mWidgetTrack != nullptr)
415 {
417 return mWidgetTrack->getHeight();
418 return mWidgetTrack->getWidth();
419 }
420 return 1;
421 }
422
424 {
426 }
427
429 {
430 notifyMouseWheel(nullptr, _rel);
431
432 Base::onMouseWheel(_rel);
433 }
434
435 void ScrollBar::notifyMouseWheel(Widget* _sender, int _rel)
436 {
437 if (mScrollRange < 2)
438 return;
439
440 int offset = mScrollPosition;
441 if (_rel < 0)
442 offset += mScrollWheelPage;
443 else
444 offset -= mScrollWheelPage;
445
446 if (offset < 0)
447 offset = 0;
448 else if (offset > (int)(mScrollRange - 1))
449 offset = mScrollRange - 1;
450
451 if ((size_t)offset != mScrollPosition)
452 {
453 mScrollPosition = offset;
454 // оповещаем
456 updateTrack();
457 }
458 }
459
460 void ScrollBar::repeatClick(Widget* _widget, ControllerItem* _controller)
461 {
462 if (_widget == mWidgetStart)
463 widgetStartPressed();
464 else if (_widget == mWidgetEnd)
465 widgetEndPressed();
466 else if (_widget == mWidgetFirstPart)
467 widgetFirstPartPressed();
468 else if (_widget == mWidgetSecondPart)
469 widgetSecondPartPressed();
470 }
471
472 void ScrollBar::widgetStartPressed()
473 {
474 // минимальное значение
475 if (mScrollPosition == 0)
476 return;
477
478 // расчитываем следующее положение
481 else
482 mScrollPosition = 0;
483
484 // оповещаем
486 updateTrack();
487 }
488
489 void ScrollBar::widgetEndPressed()
490 {
491 // максимальное значение
492 if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
493 return;
494
495 // расчитываем следующее положение
498 else
500
501 // оповещаем
503 updateTrack();
504 }
505
506 void ScrollBar::widgetFirstPartPressed()
507 {
508 // минимальное значение
509 if (mScrollPosition == 0)
510 return;
511
512 // расчитываем следующее положение
515 else
516 mScrollPosition = 0;
517
518 // оповещаем
520 updateTrack();
521 }
522
523 void ScrollBar::widgetSecondPartPressed()
524 {
525 // максимальное значение
526 if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
527 return;
528
529 // расчитываем следующее положение
532 else
534
535 // оповещаем
537 updateTrack();
538 }
539
540 void ScrollBar::setPropertyOverride(std::string_view _key, std::string_view _value)
541 {
543 if (_key == "Range")
545
547 else if (_key == "RangePosition")
549
551 else if (_key == "Page")
553
555 else if (_key == "ViewPage")
557
559 else if (_key == "WheelPage")
561
563 else if (_key == "MoveToClick")
565
567 else if (_key == "VerticalAlignment")
569
571 else if (_key == "Repeat")
573
575 else if (_key == "RepeatTriggerTime")
577
579 else if (_key == "RepeatStepTime")
581
582 else
583 {
584 Base::setPropertyOverride(_key, _value);
585 return;
586 }
587
588 eventChangeProperty(this, _key, _value);
589 }
590
592 {
593 return mScrollRange;
594 }
595
597 {
598 return mScrollPosition;
599 }
600
601 void ScrollBar::setScrollPage(size_t _value)
602 {
603 mScrollPage = _value;
604 }
605
607 {
608 return mScrollPage;
609 }
610
612 {
613 mScrollViewPage = _value;
614 }
615
617 {
618 return mScrollViewPage;
619 }
620
622 {
623 mScrollWheelPage = _value;
624 }
626 {
627 return mScrollWheelPage;
628 }
629
631 {
632 mMinTrackSize = _value;
633 }
634
636 {
637 return mMinTrackSize;
638 }
639
641 {
642 mMoveToClick = _value;
643 }
644
646 {
647 return mMoveToClick;
648 }
649
651 {
652 if (mWidgetTrack != nullptr)
653 {
655 return mWidgetTrack->getParent()->getHeight();
656 return mWidgetTrack->getParent()->getWidth();
657 }
658 return 0;
659 }
660
662 {
663 mVerticalAlignment = _value;
664
665 updateTrack();
666 }
667
669 {
670 return mVerticalAlignment;
671 }
672
673} // namespace MyGUI
ControllerItem * createItem(std::string_view _type)
static ControllerManager & getInstance()
void addItem(Widget *_widget, ControllerItem *_item)
static std::string_view getClassTypeName()
void setRepeat(float init, float step)
Type * castType(bool _throw=true)
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 setScrollWheelPage(size_t _value)
void initialiseOverride() override
void setMinTrackSize(int _value)
size_t getScrollPage() const
void setTrackSize(int _size)
void notifyMousePressed(Widget *_sender, int _left, int _top, MouseButton _id)
void setRepeatTriggerTime(float time)
void setRepeatStepTime(float time)
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)
size_t getScrollViewPage() const
void setScrollPosition(size_t _position)
size_t getScrollRange() const
int getTrackPlaceLength() const
void setScrollViewPage(size_t _value)
bool getMoveToClick() const
void setCoord(const IntCoord &_coord) override
void notifyMouseDrag(Widget *_sender, int _left, int _top, MouseButton _id)
void setSize(const IntSize &_size) override
void setPosition(const IntPoint &_point) override
void onMouseWheel(int _rel) override
void setScrollRange(size_t _range)
float getRepeatTriggerTime(float time) const
void setScrollPage(size_t _value)
size_t getScrollWheelPage() const
void notifyMouseWheel(Widget *_sender, int _rel)
float getRepeatStepTime(float time) const
void setPropertyOverride(std::string_view _key, std::string_view _value) override
bool isUserString(std::string_view _key) const
std::string_view getUserString(std::string_view _key) const
widget description should be here.
EventHandle_WidgetStringString eventChangeProperty
void assignWidget(T *&_widget, std::string_view _name)
void _forcePick(Widget *_widget)
EventHandle_WidgetIntIntButton eventMouseButtonPressed
T parseValue(std::string_view _value)
bool parseComplex(std::string_view _value, Args &... args)
types::TPoint< int > IntPoint
Definition MyGUI_Types.h:27
types::TCoord< int > IntCoord
Definition MyGUI_Types.h:36
types::TSize< int > IntSize
Definition MyGUI_Types.h:30
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))