ScrollBarImpl.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2020 to 2022 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_GUI_HELPER_SCROLL_BAR_IMPL
  24. #define DFPSR_GUI_HELPER_SCROLL_BAR_IMPL
  25. #include "../../VisualComponent.h"
  26. namespace dsr {
  27. struct ScrollRange {
  28. // The minimum value the scrollbar can be assigned in the current range.
  29. // Set minValue to 0 for scrolling through items in a list.
  30. int64_t minValue = 0;
  31. // The maximum value the scrollbar can be assigned in the current range.
  32. // Set maxValue to length - 1 and visibleItems to 1 for selecting an item in a list directly.
  33. // Set maxValue to length - visibleItems for scrolling through items with visibleItems sepresented by the knob's length.
  34. int64_t maxValue = 0;
  35. // Scrolling represents a range starting at the selected value of length visibleItems.
  36. // Use 1 if you are just selecting one integer value.
  37. // Use the value that you subtracted from the total length in maxValue if you want to represent a range of multiple values.
  38. // This argument only affects the knob size and how the selected range is constrained to include a certain value.
  39. int64_t visibleItems = 1;
  40. ScrollRange() {}
  41. ScrollRange(int64_t minValue, int64_t maxValue, int64_t visibleItems)
  42. : minValue(minValue), maxValue(maxValue), visibleItems(visibleItems) {}
  43. };
  44. // To be value allocated inside of components that need a scroll-bar.
  45. // Initialized with true if the scroll-bar is vertical, and with false if the scroll-bar is horizontal.
  46. // Call loadTheme when the parent component loads a new theme, or you will have a crash when trying to draw the scroll-bar.
  47. // When the range of values or view's size changed, recalculate the range of valid values and send it to updateScrollRange.
  48. class ScrollBarImpl {
  49. private:
  50. // Locked settings.
  51. const bool vertical;
  52. // Calculated automatically.
  53. bool visible = false;
  54. // Temporary.
  55. bool pressScrollUp = false;
  56. bool pressScrollDown = false;
  57. bool holdingScrollBar = false;
  58. const int scrollBarThickness = 16;
  59. const int scrollButtonLength = 16;
  60. int64_t knobHoldOffset = 0; // The number of pixels right or down from the center that the knob was grabbed at.
  61. // Updated manually.
  62. ScrollRange scrollRange; // Range of valid values.
  63. int64_t value = 0; // The selected value.
  64. int64_t reservedStart = 0; // How many pixels to leave empty at the left/top side to avoid collisions.
  65. int64_t reservedEnd = 0; // How many pixels to leave empty at the right/bottom side to avoid collisions.
  66. // Scalable parametric images.
  67. MediaMethod scalableImage_scrollTop, scalableImage_scrollBottom, scalableImage_scrollBackground, scalableImage_scrollKnob;
  68. // Generated raster images.
  69. OrderedImageRgbaU8 scrollButtonTopImage_normal, scrollButtonTopImage_pressed;
  70. OrderedImageRgbaU8 scrollButtonBottomImage_normal, scrollButtonBottomImage_pressed;
  71. OrderedImageRgbaU8 scrollKnobImage_normal, scrollKnobImage_pressed;
  72. OrderedImageRgbaU8 scrollBarImage;
  73. private:
  74. IRect getScrollBarLocation(int32_t parentWidth, int32_t parentHeight);
  75. IRect getScrollRegion(const IRect &scrollBarLocation);
  76. IRect getDecreaseButton(const IRect &scrollBarLocation);
  77. IRect getIncreaseButton(const IRect &scrollBarLocation);
  78. IRect getKnobLocation(const IRect &scrollBarLocation);
  79. // Returns true iff value updated.
  80. bool pressScrollBar(const IRect &parentLocation, int64_t localY);
  81. public:
  82. ScrollBarImpl(bool vertical, bool reserveEnd = false)
  83. : vertical(vertical), reservedStart(0), reservedEnd(reserveEnd ? 16 : 0) {}
  84. void loadTheme(VisualTheme theme, const ColorRgbI32 &color);
  85. // Pre-condition: range.minValue <= range.maxValue
  86. void updateScrollRange(const ScrollRange &range);
  87. void setValue(int64_t newValue);
  88. int64_t getValue();
  89. // Pre-condition: scrollRange must have been updated since the last changes that may affect it
  90. // Side-effects: Constrains value within minValue and maxValue.
  91. // If keepPinValueInRange is true, it will also try to constrain the selected range to include pinValue,
  92. // which is used for making sure that something selected stays visible, when scrolling is used for navigating a view.
  93. void limitScrolling(const IRect &parentLocation, bool keepPinValueInRange = false, int64_t pinValue = 0);
  94. // For mouse-down events, it returns true iff the event landed inside of the scroll-bar.
  95. // For other event types, it returns true iff the scroll-bar needs to be redrawn.
  96. bool receiveMouseEvent(const IRect &parentLocation, const MouseEvent& event);
  97. // Draw the scroll-bar on top of target.
  98. void draw(OrderedImageRgbaU8 &target, VisualTheme &theme, const ColorRgbI32 &color);
  99. };
  100. }
  101. #endif