Jamba C++ API  4.1.0
ScrollbarView.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019 pongasoft
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  *
16  * @author Yan Pujante
17  */
18 #pragma once
19 
20 #include "CustomView.h"
22 #include <pongasoft/Utils/Lerp.h>
23 
25 
26 using namespace VSTGUI;
27 
52 class ScrollbarView : public CustomView
53 {
54 public:
55  // Constructor
56  explicit ScrollbarView(const CRect &iSize) : CustomView(iSize) {}
57 
58  // draw
59  void draw(CDrawContext *iContext) override;
60 
62  ParamID getOffsetPercentTag() const { return fOffsetPercentTag; }
63  void setOffsetPercentTag(ParamID offsetPercentTag);
64 
66  ParamID getZoomPercentTag() const { return fZoomPercentTag; }
67  void setZoomPercentTag(ParamID zoomPercentTag);
68 
70  Margin const &getMargin() const { return fMargin; }
71  void setMargin(Margin const &iMargin) { fMargin = iMargin; needsRecomputing();}
72 
74  const CColor &getScrollbarColor() const { return fScrollbarColor; }
75  void setScrollbarColor(const CColor &iColor) { fScrollbarColor = iColor; needsRecomputing(); }
76 
78  CCoord getScrollbarMinSize() const { return fScrollbarMinSize; }
79  void setScrollbarMinSize(CCoord iScrollbarMinSize) { fScrollbarMinSize = iScrollbarMinSize; needsRecomputing();}
80 
82  CCoord getScrollbarGutterSpacing() const { return fScrollbarGutterSpacing; }
83  void setScrollbarGutterSpacing(CCoord iScrollbarGutterSpacing) { fScrollbarGutterSpacing = iScrollbarGutterSpacing; needsRecomputing();}
84 
85  // showHandles
86  bool showHandles() const { return fZoomHandlesSize != 0; }
87 
89  const CColor &getZoomHandlesColor() const { return fZoomHandlesColor; }
90  void setZoomHandlesColor(const CColor &iColor) { fZoomHandlesColor = iColor; needsRecomputing(); }
91 
93  CCoord getZoomHandlesSize() const { return fZoomHandlesSize; }
94  void setZoomHandlesSize(CCoord iSize) { fZoomHandlesSize = iSize; needsRecomputing(); }
95 
103  Range const &getShiftDragFactor() const { return fShiftDragFactor; }
104 
106  void setShiftDragFactor(Range const &iShiftDragFactor) { fShiftDragFactor = iShiftDragFactor; }
107 
109  bool getEnableZoomDoubleClick() const { return fEnableZoomDoubleClick; }
110  void setEnableZoomDoubleClick(bool iEnableZoomDoubleClick) { fEnableZoomDoubleClick = iEnableZoomDoubleClick; }
111 
112  // offsetPercent accessor
113  double getOffsetPercent() const;
114  void setOffsetPercent(double iOffsetPercent);
115 
116  // zoomPercent accessor
117  double getZoomPercent() const;
118  void setZoomPercent(double iZoomPercent);
119 
120  CLASS_METHODS_NOCOPY(ScrollbarView, CustomView)
121 
122 protected:
123  // setViewSize
124  void setViewSize(const CRect &rect, bool invalid) override;
125 
126  // registerParameters
127  void registerParameters() override;
128 
129  // onParameterChange
130  void onParameterChange(ParamID iParamID) override;
131 
132  // onMouseDown
133  CMouseEventResult onMouseDown(CPoint &where, const CButtonState &buttons) override;
134 
135  // onMouseMoved
136  CMouseEventResult onMouseMoved(CPoint &where, const CButtonState &buttons) override;
137 
138  // onMouseUp
139  CMouseEventResult onMouseUp(CPoint &where, const CButtonState &buttons) override;
140 
141  // onMouseCancel
142  CMouseEventResult onMouseCancel() override;
143 
144 protected:
145  enum class DragType { kNone, kScroll, kZoomLeft, kZoomRight, kStretchLeft, kStretchRight };
146 
150  struct ZoomBox
151  {
152  CRect fViewSize;
156  CCoord fMinWidth;
157  CCoord fMaxWidth;
158  CCoord fHalfWidth;
160 
161  // when the box is full it cannot be moved anymore
162  bool isFull() const { return fMinCenter == fMaxCenter; }
163 
164  // left position
165  RelativeCoord getLeft() const { return fCenter - fHalfWidth; }
166  RelativeCoord getMinLeft() const { return fMinCenter - fHalfWidth; }
167  bool isMinLeft() const { return fCenter == fMinCenter; }
168 
169  // right position
170  RelativeCoord getRight() const { return fCenter + fHalfWidth; }
171  RelativeCoord getMaxRight() const { return fMaxCenter + fHalfWidth; }
172  bool isMaxRight() const { return fCenter == fMaxCenter; }
173 
174  // height of the box
175  CCoord getHeight() const { return fViewSize.getHeight(); }
176 
177  // width of the box
178  CCoord getWidth() const { return fHalfWidth * 2.0; }
179 
180  // the relative view containing the box (which is the original view minus the margin)
181  RelativeView getRelativeView() const { return RelativeView{fViewSize}; }
182 
183  // compute position from offsetPercent
184  RelativeCoord computeCenter(double iOffsetPercent) const
185  {
186  return Utils::mapValueDP(iOffsetPercent, 0.0, 1.0, fMinCenter, fMaxCenter);
187  }
188 
189  // compute the offsetPercent from the position
190  double computeOffsetPercent() const
191  {
192  return Utils::mapValueDP(fCenter, fMinCenter, fMaxCenter, 0.0, 1.0);
193  }
194 
195  // compute size from zoomPercent
196  CCoord computeWidth(double iZoomPercent) const
197  {
198  return Utils::mapValueDP(iZoomPercent, 1.0, 0.0, fMinWidth, fMaxWidth);
199  }
200 
201  // compute zoomPercent from size
202  double computeZoomPercent() const
203  {
204  return Utils::mapValueDP(getWidth(), fMinWidth, fMaxWidth, 1.0, 0.0);
205  }
206 
207  // move the box by iDeltaX (can be positive or negative)
208  void move(CCoord iDeltaX)
209  {
210  fCenter = Utils::clamp(fCenter + iDeltaX, fMinCenter, fMaxCenter);
211  }
212 
213  // move the box to a specific location
214  void moveTo(RelativeCoord const &iNewCenter)
215  {
216  fCenter = Utils::clamp(iNewCenter, fMinCenter, fMaxCenter);
217  }
218 
224  bool stretch(CCoord iDeltaX, DragType iDragType);
225 
226  // zoom to max and move to specific location
227  void maxZoom(RelativeCoord const &iNewCenter);
228 
229  // zoom to minimum (since the box is full, there is no specific location)
230  void minZoom();
231  };
232 
233 protected:
234  // drawLeftHandle - can be overridden to draw something different but should fit in fLeftHandleRect
235  virtual void drawLeftHandle(CDrawContext *iContext);
236 
237  // drawRightHandle - can be overridden to draw something different but should fit in fRightHandleRect
238  virtual void drawRightHandle(CDrawContext *iContext);
239 
240  // drawScrollbar - can be overridden to draw something different but should fit in fScrollbarRect
241  virtual void drawScrollbar(CDrawContext *iContext);
242 
243  // needsRecomputing when something changes that requires recomputing the 3 AbsoluteRect
244  void needsRecomputing() { fNeedsRecomputing = true; markDirty(); }
245 
246  // recompute the 3 AbsoluteRect
247  void recompute();
248 
249  // computeZoomBox
250  ZoomBox computeZoomBox() const;
251 
252  // returns the width of just the scrollbar (excluding handles and gutter)
253  CCoord getScrollbarWidth() const;
254 
255 protected:
256  // set to true when the 3 AbsoluteRect need to be recomputed
257  bool fNeedsRecomputing{true};
258  ZoomBox fZoomBox{};
259 
260  // the 3 Rect representing the position and size of the 3 pieces of the rendering
264 
265  // look and feel
266  Margin fMargin{};
267  CColor fScrollbarColor{kWhiteCColor};
268  CCoord fScrollbarMinSize{-1}; // -1 means it will be computed
269  CCoord fScrollbarGutterSpacing{1};
270 
271  CColor fZoomHandlesColor{kWhiteCColor};
272  CCoord fZoomHandlesSize{-1}; // -1 means it will be computed, 0 means no show
273 
274  // how much to slow down (if less than 1) or accelerate (if more than 1) when shift is held when dragging
275  Range fShiftDragFactor{1.0};
276  bool fEnableZoomDoubleClick{true};
277 
278  // offsetPercent tag/param/value + editor and editor value ("value" is used when no param)
279  ParamID fOffsetPercentTag{UNDEFINED_PARAM_ID};
280  GUIOptionalParam<ParamValue> fOffsetPercentParam{};
281  GUIOptionalParamEditor<ParamValue> fOffsetPercentEditor{};
282 
283  // zoomPercent tag/param/value + editor and editor value ("value" is used when no param)
284  ParamID fZoomPercentTag{UNDEFINED_PARAM_ID};
285  GUIOptionalParam<ParamValue> fZoomPercentParam{};
287 
288  // used when dragging
289  RelativeCoord fDragGestureX{-1.0};
290  DragType fDragType{DragType::kNone};
291 
292 public:
293  class Creator : public CustomViewCreator<ScrollbarView, CustomView>
294  {
295  public:
296  explicit Creator(char const *iViewName = nullptr, char const *iDisplayName = nullptr) :
297  CustomViewCreator(iViewName, iDisplayName)
298  {
299  registerTagAttribute("offset-percent-tag", &ScrollbarView::getOffsetPercentTag, &ScrollbarView::setOffsetPercentTag);
300  registerTagAttribute("zoom-percent-tag", &ScrollbarView::getZoomPercentTag, &ScrollbarView::setZoomPercentTag);
301  registerMarginAttribute("margin", &ScrollbarView::getMargin, &ScrollbarView::setMargin);
302  registerColorAttribute("scrollbar-color", &ScrollbarView::getScrollbarColor, &ScrollbarView::setScrollbarColor);
303  registerDoubleAttribute("scrollbar-min-size", &ScrollbarView::getScrollbarMinSize, &ScrollbarView::setScrollbarMinSize);
304  registerDoubleAttribute("scrollbar-gutter-spacing", &ScrollbarView::getScrollbarGutterSpacing, &ScrollbarView::setScrollbarGutterSpacing);
305  registerColorAttribute("zoom-handles-color", &ScrollbarView::getZoomHandlesColor, &ScrollbarView::setZoomHandlesColor);
306  registerDoubleAttribute("zoom-handles-size", &ScrollbarView::getZoomHandlesSize, &ScrollbarView::setZoomHandlesSize);
307  registerRangeAttribute("shift-drag-factor", &ScrollbarView::getShiftDragFactor, &ScrollbarView::setShiftDragFactor);
308  registerBooleanAttribute("enable-zoom-double-click", &ScrollbarView::getEnableZoomDoubleClick, &ScrollbarView::setEnableZoomDoubleClick);
309  }
310  };
311 };
312 
313 }
CCoord getZoomHandlesSize() const
Zoom handles size. If -1 it will be auto-computed. Set to 0 to disable handles entirely.
Definition: ScrollbarView.h:93
RelativeCoord fMaxCenter
Definition: ScrollbarView.h:154
RelativeCoord computeCenter(double iOffsetPercent) const
Definition: ScrollbarView.h:184
RelativeView getRelativeView() const
Definition: ScrollbarView.h:181
DragType
Definition: ScrollbarView.h:145
Inherit from this class to provide the factory for a custom view.
Definition: CustomViewCreator.h:1311
void setOffsetPercentTag(ParamID offsetPercentTag)
Definition: ScrollbarView.cpp:329
void setScrollbarGutterSpacing(CCoord iScrollbarGutterSpacing)
Definition: ScrollbarView.h:83
RelativeCoord getMinLeft() const
Definition: ScrollbarView.h:166
static T clamp(const U &iValue, const T &iLower, const T &iUpper)
Make sure that the value remains within its bounds.
Definition: Misc.h:33
void setShiftDragFactor(Range const &iShiftDragFactor)
Attribute shift-drag-factor.
Definition: ScrollbarView.h:106
AbsoluteRect fRightHandleRect
Definition: ScrollbarView.h:262
Creator(char const *iViewName=nullptr, char const *iDisplayName=nullptr)
Definition: ScrollbarView.h:296
CCoord RelativeCoord
Definition: DrawContext.h:45
void setZoomHandlesSize(CCoord iSize)
Definition: ScrollbarView.h:94
CCoord getScrollbarMinSize() const
Minimum size for the scrollbar (in pixels). If -1 it will be auto-computed.
Definition: ScrollbarView.h:78
std::unique_ptr< typename GUIOptionalParam< T >::EditorType > GUIOptionalParamEditor
Definition: GUIOptionalParam.h:178
RelativeCoord getLeft() const
Definition: ScrollbarView.h:165
Class you should inherit from if you want to write a custom view.
Definition: CustomView.h:60
CCoord computeWidth(double iZoomPercent) const
Definition: ScrollbarView.h:196
double computeZoomPercent() const
Definition: ScrollbarView.h:202
static double mapValueDP(double iValue, double iFromLow, double iFromHigh, double iToLow, double iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition: Lerp.h:220
void needsRecomputing()
Definition: ScrollbarView.h:244
ParamID getZoomPercentTag() const
id for the parameter tied to zoom percent
Definition: ScrollbarView.h:66
CCoord getHeight() const
Definition: ScrollbarView.h:175
void setEnableZoomDoubleClick(bool iEnableZoomDoubleClick)
Definition: ScrollbarView.h:110
Generic scrollbar which handles scrolling and (optional) zooming via handles.
Definition: ScrollbarView.h:52
CCoord getScrollbarGutterSpacing() const
Spacing (in pixels) between the scrollbar and zoom handles (only drawn when zoom handles)
Definition: ScrollbarView.h:82
bool isMaxRight() const
Definition: ScrollbarView.h:172
Range const & getShiftDragFactor() const
Defines how much to slow down (if less than 1) or accelerate (if more than 1) when shift is held when...
Definition: ScrollbarView.h:103
ParamID getOffsetPercentTag() const
id for the parameter tied to offset percent
Definition: ScrollbarView.h:62
void moveTo(RelativeCoord const &iNewCenter)
Definition: ScrollbarView.h:214
const CColor & getZoomHandlesColor() const
Zoom handles color.
Definition: ScrollbarView.h:89
CCoord fMinWidth
Definition: ScrollbarView.h:156
RelativeCoord getRight() const
Definition: ScrollbarView.h:170
AbsoluteRect fLeftHandleRect
Definition: ScrollbarView.h:261
void setScrollbarMinSize(CCoord iScrollbarMinSize)
Definition: ScrollbarView.h:79
void setZoomPercentTag(ParamID zoomPercentTag)
Definition: ScrollbarView.cpp:338
CRect AbsoluteRect
Definition: DrawContext.h:50
Margin is a similar concept to css: used to create space around elements, outside of any defined bord...
Definition: LookAndFeel.h:32
Definition: Types.h:29
ScrollbarView(const CRect &iSize)
Definition: ScrollbarView.h:56
bool showHandles() const
Definition: ScrollbarView.h:86
void move(CCoord iDeltaX)
Definition: ScrollbarView.h:208
CCoord fZoomHandlesSize
Definition: ScrollbarView.h:159
void setMargin(Margin const &iMargin)
Definition: ScrollbarView.h:71
RelativeCoord fCenter
Definition: ScrollbarView.h:155
Definition: CustomController.h:24
bool isMinLeft() const
Definition: ScrollbarView.h:167
CRect fViewSize
Definition: ScrollbarView.h:152
Margin const & getMargin() const
Amount of space (in pixels) to draw around the full scrollbar (includes handles)
Definition: ScrollbarView.h:70
CCoord fMaxWidth
Definition: ScrollbarView.h:157
Definition: DrawContext.h:52
bool getEnableZoomDoubleClick() const
true to allow zooming on double click on the scrollbar
Definition: ScrollbarView.h:109
RelativeCoord fMinCenter
Definition: ScrollbarView.h:153
RelativeCoord getMaxRight() const
Definition: ScrollbarView.h:171
Represents the box (dimension and position point of view) containing the zoom handles and scrollbar.
Definition: ScrollbarView.h:150
CCoord fHalfWidth
Definition: ScrollbarView.h:158
double computeOffsetPercent() const
Definition: ScrollbarView.h:190
void setZoomHandlesColor(const CColor &iColor)
Definition: ScrollbarView.h:90
void setScrollbarColor(const CColor &iColor)
Definition: ScrollbarView.h:75
bool isFull() const
Definition: ScrollbarView.h:162
constexpr ParamID UNDEFINED_PARAM_ID
Constant used throughout the code to test whether the ParamID represents a valid id or an undefined o...
Definition: Types.h:47
AbsoluteRect fScrollbarRect
Definition: ScrollbarView.h:263
const CColor & getScrollbarColor() const
the color of the scrollbar itself (the rectangle)
Definition: ScrollbarView.h:74
CCoord getWidth() const
Definition: ScrollbarView.h:178