1 //
2 // Copyright (c) 2008-2017 the Urho3D project.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 //
22 
23 #pragma once
24 
25 #include "../UI/UIElement.h"
26 
27 namespace Urho3D
28 {
29 
30 class BorderImage;
31 class ScrollBar;
32 
33 /// Scrollable %UI element for showing a (possibly large) child element.
34 class URHO3D_API ScrollView : public UIElement
35 {
36     URHO3D_OBJECT(ScrollView, UIElement);
37 
38 public:
39     /// Construct.
40     ScrollView(Context* context);
41     /// Destruct.
42     virtual ~ScrollView();
43     /// Register object factory.
44     static void RegisterObject(Context* context);
45 
46     /// Perform UI element update.
47     virtual void Update(float timeStep);
48     /// Apply attribute changes that can not be applied immediately.
49     virtual void ApplyAttributes();
50     /// React to mouse wheel.
51     virtual void OnWheel(int delta, int buttons, int qualifiers);
52     /// React to a key press.
53     virtual void OnKey(int key, int buttons, int qualifiers);
54     /// React to resize.
55     virtual void OnResize(const IntVector2& newSize, const IntVector2& delta);
56 
57     /// Set content element.
58     void SetContentElement(UIElement* element);
59     /// Set view offset from the top-left corner.
60     void SetViewPosition(const IntVector2& position);
61     /// Set view offset from the top-left corner.
62     void SetViewPosition(int x, int y);
63     /// Set scrollbars' visibility manually. Disables scrollbar autoshow/hide.
64     void SetScrollBarsVisible(bool horizontal, bool vertical);
65     /// Set whether to automatically show/hide scrollbars. Default true.
66     void SetScrollBarsAutoVisible(bool enable);
67     /// Set arrow key scroll step. Also sets it on the scrollbars.
68     void SetScrollStep(float step);
69     /// Set arrow key page step.
70     void SetPageStep(float step);
71 
72     /// Set scroll deceleration.
SetScrollDeceleration(float deceleration)73     void SetScrollDeceleration(float deceleration) { scrollDeceleration_ = deceleration; }
74 
75     /// Set scroll snap epsilon
SetScrollSnapEpsilon(float snap)76     void SetScrollSnapEpsilon(float snap) { scrollSnapEpsilon_ = snap; }
77 
78     /// Set whether child elements should be disabled while touch scrolling.
SetAutoDisableChildren(bool disable)79     void SetAutoDisableChildren(bool disable) { autoDisableChildren_ = disable; };
80 
81     /// Set how much touch movement is needed to trigger child element disabling.
SetAutoDisableThreshold(float amount)82     void SetAutoDisableThreshold(float amount) { autoDisableThreshold_ = amount; };
83 
84     /// Return view offset from the top-left corner.
GetViewPosition()85     const IntVector2& GetViewPosition() const { return viewPosition_; }
86 
87     /// Return content element.
GetContentElement()88     UIElement* GetContentElement() const { return contentElement_; }
89 
90     /// Return horizontal scroll bar.
GetHorizontalScrollBar()91     ScrollBar* GetHorizontalScrollBar() const { return horizontalScrollBar_; }
92 
93     /// Return vertical scroll bar.
GetVerticalScrollBar()94     ScrollBar* GetVerticalScrollBar() const { return verticalScrollBar_; }
95 
96     /// Return scroll panel.
GetScrollPanel()97     BorderImage* GetScrollPanel() const { return scrollPanel_; }
98 
99     /// Return whether scrollbars are automatically shown/hidden.
GetScrollBarsAutoVisible()100     bool GetScrollBarsAutoVisible() const { return scrollBarsAutoVisible_; }
101 
102     /// Return arrow key scroll step.
103     float GetScrollStep() const;
104 
105     /// Return arrow key page step.
GetPageStep()106     float GetPageStep() const { return pageStep_; }
107 
108     /// Return scroll deceleration.
GetScrollDeceleration()109     float GetScrollDeceleration() const { return scrollDeceleration_; }
110 
111     /// Return scroll snap epsilon
GetScrollSnapEpsilon()112     float GetScrollSnapEpsilon() const { return scrollSnapEpsilon_; }
113 
114     /// Return whether child element will be disabled while touch scrolling.
GetAutoDisableChildren()115     bool GetAutoDisableChildren() const { return autoDisableChildren_; }
116 
117     /// Return how much touch movement is needed to trigger child element disabling.
GetAutoDisableThreshold()118     float GetAutoDisableThreshold() const { return autoDisableThreshold_; }
119 
120     /// Set view position attribute.
121     void SetViewPositionAttr(const IntVector2& value);
122 
123 protected:
124     /// Filter implicit attributes in serialization process.
125     virtual bool FilterImplicitAttributes(XMLElement& dest) const;
126     /// Filter implicit attributes in serialization process for internal scroll bar.
127     bool FilterScrollBarImplicitAttributes(XMLElement& dest, const String& name) const;
128     /// Resize panel based on scrollbar visibility.
129     void UpdatePanelSize();
130     /// Recalculate view size, validate view position and update scrollbars.
131     void UpdateViewSize();
132     /// Update the scrollbars' ranges and positions.
133     void UpdateScrollBars();
134     /// Limit and update the view with a new position.
135     void UpdateView(const IntVector2& position);
136 
137     /// Content element.
138     SharedPtr<UIElement> contentElement_;
139     /// Horizontal scroll bar.
140     SharedPtr<ScrollBar> horizontalScrollBar_;
141     /// Vertical scroll bar.
142     SharedPtr<ScrollBar> verticalScrollBar_;
143     /// Scroll panel element.
144     SharedPtr<BorderImage> scrollPanel_;
145     /// Current view offset from the top-left corner.
146     IntVector2 viewPosition_;
147     /// Total view size.
148     IntVector2 viewSize_;
149     /// View offset attribute.
150     IntVector2 viewPositionAttr_;
151     /// Accumulated touch scroll speed.
152     Vector2 touchScrollSpeed_;
153     /// Max touch scroll speed.
154     Vector2 touchScrollSpeedMax_;
155     /// Arrow key page step.
156     float pageStep_;
157     /// Automatically show/hide scrollbars flag.
158     bool scrollBarsAutoVisible_;
159     /// Ignore scrollbar events flag. Used to prevent possible endless loop when resizing.
160     bool ignoreEvents_;
161     /// Resize content widget width to match panel. Internal flag, used by the ListView class.
162     bool resizeContentWidth_;
163     /// Scroll deceleration
164     float scrollDeceleration_;
165     /// Scroll snap epsilon
166     float scrollSnapEpsilon_;
167     /// Used to trigger scroll smoothing when false;
168     bool scrollTouchDown_;
169     /// Used to prevent touch scroll - scroll bar conflict
170     bool barScrolling_;
171     /// Used to determine if child elements should be disabled while touch scrolling, to prevent their trigger.
172     bool autoDisableChildren_;
173     /// Used to determine if children have been disabled.
174     bool scrollChildrenDisable_;
175     /// Distance moved with touch scrolling
176     float touchDistanceSum_;
177     /// Threshold to trigger auto disable children
178     float autoDisableThreshold_;
179 
180 private:
181     /// Handle scrollbar value changed.
182     void HandleScrollBarChanged(StringHash eventType, VariantMap& eventData);
183     /// Handle scrollbar visibility changed.
184     void HandleScrollBarVisibleChanged(StringHash eventType, VariantMap& eventData);
185     /// Handle content element resized.
186     void HandleElementResized(StringHash eventType, VariantMap& eventData);
187     /// Handle touch move event for scrolling.
188     void HandleTouchMove(StringHash eventType, VariantMap& eventData);
189     /// Handle the scroll smoothing.
190     void ScrollSmooth(float timeStep);
191 };
192 
193 }
194