MyGUI 3.4.4
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 int pos = 0;
206 if (mScrollRange >= 2)
207 {
208 // расчитываем положение соответствующее позиции
209 // плюс пол позиции
210 pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
211 // высчитываем ближайшее значение и обновляем
212 pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
213 }
214
215 // проверяем на выходы и изменения
216 if (pos < 0)
217 pos = 0;
218 else if (pos >= (int)mScrollRange)
219 pos = (int)mScrollRange - 1;
220 if (pos == (int)mScrollPosition)
221 return;
222
223 mScrollPosition = pos;
224 }
225 else
226 {
227 // расчитываем позицию виджета
228 int start = mPreActionOffset.left + (_left - point.left);
229 if (start < (int)mSkinRangeStart)
230 start = (int)mSkinRangeStart;
231 else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth()))
232 start = (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth());
233 if (mWidgetTrack->getLeft() != start)
234 mWidgetTrack->setPosition(IntPoint(start, mWidgetTrack->getTop()));
235
236 int pos = 0;
237 if (mScrollRange >= 2)
238 {
239 // расчитываем положение соответствующее позиции
240 // плюс пол позиции
241 pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
242 // высчитываем ближайшее значение и обновляем
243 pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());
244 }
245
246 // проверяем на выходы и изменения
247 if (pos < 0)
248 pos = 0;
249 else if (pos >= (int)mScrollRange)
250 pos = (int)mScrollRange - 1;
251 if (pos == (int)mScrollPosition)
252 return;
253
254 mScrollPosition = pos;
255 }
256
257 updateTrack();
258
259 // отсылаем событие
261 }
262
263 void ScrollBar::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
264 {
265 // диспечерезируем нажатие своих детей как свое
266 eventMouseButtonPressed(this, _left, _top, _id);
267
268 if (MouseButton::Left != _id)
269 return;
270
271 if (mEnableRepeat && _sender != mWidgetTrack &&
272 ((_sender != mWidgetFirstPart && _sender != mWidgetSecondPart) || !mMoveToClick))
273 {
274 ControllerItem* item =
277 controller->eventRepeatClick += newDelegate(this, &ScrollBar::repeatClick);
279 ControllerManager::getInstance().addItem(_sender, controller);
280 }
281
282 if (mMoveToClick && _sender != mWidgetTrack && _sender != mWidgetStart && _sender != mWidgetEnd)
283 {
284 if (mWidgetTrack != nullptr)
285 {
288 mWidgetTrack->getParent()->getAbsolutePosition();
289
290 mPreActionOffset.left -= getTrackSize() / 2;
291 mPreActionOffset.top -= getTrackSize() / 2;
292
293 TrackMove(point.left, point.top);
294 }
295 }
296 else if (_sender == mWidgetStart)
297 {
298 widgetStartPressed();
299 }
300 else if (_sender == mWidgetEnd)
301 {
302 widgetEndPressed();
303 }
304 else if (_sender == mWidgetFirstPart)
305 {
306 widgetFirstPartPressed();
307 }
308 else if (_sender == mWidgetSecondPart)
309 {
310 widgetSecondPartPressed();
311 }
312 else if (_sender == mWidgetTrack)
313 {
314 mPreActionOffset.left = _sender->getLeft();
315 mPreActionOffset.top = _sender->getTop();
316 }
317 }
318
319 void ScrollBar::notifyMouseReleased(Widget* _sender, int _left, int _top, MouseButton _id)
320 {
321 updateTrack();
323 }
324
325 void ScrollBar::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
326 {
327 if (mScrollRange < 2)
328 return;
329 if (_id == MouseButton::Left)
330 TrackMove(_left, _top);
331 }
332
333 void ScrollBar::setScrollRange(size_t _range)
334 {
335 if (_range == mScrollRange)
336 return;
337
338 mScrollRange = _range;
340 updateTrack();
341 }
342
343 void ScrollBar::setScrollPosition(size_t _position)
344 {
345 if (_position == mScrollPosition)
346 return;
347
348 if (_position >= mScrollRange)
349 _position = 0;
350
351 mScrollPosition = _position;
352 updateTrack();
353 }
354
356 {
357 Base::setPosition(_point);
358 }
359
360 void ScrollBar::setSize(const IntSize& _size)
361 {
362 Base::setSize(_size);
363 // обновляем трек
364 updateTrack();
365 }
366
367 void ScrollBar::setCoord(const IntCoord& _coord)
368 {
369 Base::setCoord(_coord);
370 // обновляем трек
371 updateTrack();
372 }
373
375 {
376 if (mWidgetTrack != nullptr)
377 {
379 mWidgetTrack->setSize(
380 mWidgetTrack->getWidth(),
381 ((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size);
382 else
383 mWidgetTrack->setSize(
384 ((int)_size < (int)mMinTrackSize) ? (int)mMinTrackSize : (int)_size,
385 mWidgetTrack->getHeight());
386 }
387 updateTrack();
388 }
389
391 {
392 mRepeatTriggerTime = time;
393 }
394
396 {
397 mRepeatStepTime = time;
398 }
399
400 float ScrollBar::getRepeatTriggerTime(float time) const
401 {
402 return mRepeatTriggerTime;
403 }
404
405 float ScrollBar::getRepeatStepTime(float time) const
406 {
407 return mRepeatStepTime;
408 }
409
411 {
412 mEnableRepeat = enabled;
413 }
414
416 {
417 return mEnableRepeat;
418 }
419
421 {
422 if (mWidgetTrack != nullptr)
423 {
425 return mWidgetTrack->getHeight();
426 return mWidgetTrack->getWidth();
427 }
428 return 1;
429 }
430
432 {
434 }
435
437 {
438 notifyMouseWheel(nullptr, _rel);
439
440 Base::onMouseWheel(_rel);
441 }
442
443 void ScrollBar::notifyMouseWheel(Widget* _sender, int _rel)
444 {
445 if (mScrollRange < 2)
446 return;
447
448 int offset = mScrollPosition;
449 if (_rel < 0)
450 offset += mScrollWheelPage;
451 else
452 offset -= mScrollWheelPage;
453
454 if (offset < 0)
455 offset = 0;
456 else if (offset > (int)(mScrollRange - 1))
457 offset = mScrollRange - 1;
458
459 if ((size_t)offset != mScrollPosition)
460 {
461 mScrollPosition = offset;
462 // оповещаем
464 updateTrack();
465 }
466 }
467
468 void ScrollBar::repeatClick(Widget* _widget, ControllerItem* _controller)
469 {
470 if (_widget == mWidgetStart)
471 widgetStartPressed();
472 else if (_widget == mWidgetEnd)
473 widgetEndPressed();
474 else if (_widget == mWidgetFirstPart)
475 widgetFirstPartPressed();
476 else if (_widget == mWidgetSecondPart)
477 widgetSecondPartPressed();
478 }
479
480 void ScrollBar::widgetStartPressed()
481 {
482 // минимальное значение
483 if (mScrollPosition == 0)
484 return;
485
486 // расчитываем следующее положение
489 else
490 mScrollPosition = 0;
491
492 // оповещаем
494 updateTrack();
495 }
496
497 void ScrollBar::widgetEndPressed()
498 {
499 // максимальное значение
500 if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
501 return;
502
503 // расчитываем следующее положение
506 else
508
509 // оповещаем
511 updateTrack();
512 }
513
514 void ScrollBar::widgetFirstPartPressed()
515 {
516 // минимальное значение
517 if (mScrollPosition == 0)
518 return;
519
520 // расчитываем следующее положение
523 else
524 mScrollPosition = 0;
525
526 // оповещаем
528 updateTrack();
529 }
530
531 void ScrollBar::widgetSecondPartPressed()
532 {
533 // максимальное значение
534 if ((mScrollRange < 2) || (mScrollPosition >= (mScrollRange - 1)))
535 return;
536
537 // расчитываем следующее положение
540 else
542
543 // оповещаем
545 updateTrack();
546 }
547
548 void ScrollBar::setPropertyOverride(std::string_view _key, std::string_view _value)
549 {
551 if (_key == "Range")
553
555 else if (_key == "RangePosition")
557
559 else if (_key == "Page")
561
563 else if (_key == "ViewPage")
565
567 else if (_key == "WheelPage")
569
571 else if (_key == "MoveToClick")
573
575 else if (_key == "VerticalAlignment")
577
579 else if (_key == "Repeat")
581
583 else if (_key == "RepeatTriggerTime")
585
587 else if (_key == "RepeatStepTime")
589
590 else
591 {
592 Base::setPropertyOverride(_key, _value);
593 return;
594 }
595
596 eventChangeProperty(this, _key, _value);
597 }
598
600 {
601 return mScrollRange;
602 }
603
605 {
606 return mScrollPosition;
607 }
608
609 void ScrollBar::setScrollPage(size_t _value)
610 {
611 mScrollPage = _value;
612 }
613
615 {
616 return mScrollPage;
617 }
618
620 {
621 mScrollViewPage = _value;
622 }
623
625 {
626 return mScrollViewPage;
627 }
628
630 {
631 mScrollWheelPage = _value;
632 }
634 {
635 return mScrollWheelPage;
636 }
637
639 {
640 mMinTrackSize = _value;
641 }
642
644 {
645 return mMinTrackSize;
646 }
647
649 {
650 mMoveToClick = _value;
651 }
652
654 {
655 return mMoveToClick;
656 }
657
659 {
660 if (mWidgetTrack != nullptr)
661 {
663 return mWidgetTrack->getParent()->getHeight();
664 return mWidgetTrack->getParent()->getWidth();
665 }
666 return 0;
667 }
668
670 {
671 mVerticalAlignment = _value;
672
673 updateTrack();
674 }
675
677 {
678 return mVerticalAlignment;
679 }
680
681} // 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))