Merge "[AT-SPI] Support for hidden text added" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / scroll-view / scroll-view-impl-property-handler.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h>
23 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-mode.h>
24
25 namespace Dali::Toolkit::Internal
26 {
27
28 void ScrollViewPropertyHandler::Set(BaseObject* object, Property::Index index, const Property::Value& value)
29 {
30   Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
31
32   if(scrollView)
33   {
34     ScrollView& scrollViewImpl(GetImpl(scrollView));
35     switch(index)
36     {
37       case Toolkit::ScrollView::Property::WRAP_ENABLED:
38       {
39         scrollViewImpl.SetWrapMode(value.Get<bool>());
40         break;
41       }
42       case Toolkit::ScrollView::Property::PANNING_ENABLED:
43       {
44         scrollViewImpl.SetScrollSensitive(value.Get<bool>());
45         break;
46       }
47       case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED:
48       {
49         scrollViewImpl.SetAxisAutoLock(value.Get<bool>());
50         break;
51       }
52       case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP:
53       {
54         scrollViewImpl.SetWheelScrollDistanceStep(value.Get<Vector2>());
55         break;
56       }
57       case Toolkit::ScrollView::Property::SCROLL_MODE:
58       {
59         const Property::Map* map = value.GetMap();
60         if(map)
61         {
62           SetScrollMode(scrollViewImpl, *map);
63         }
64       }
65     }
66   }
67 }
68
69 Property::Value ScrollViewPropertyHandler::Get(BaseObject* object, Property::Index index)
70 {
71   Property::Value value;
72
73   Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
74
75   if(scrollView)
76   {
77     ScrollView& scrollViewImpl(GetImpl(scrollView));
78     switch(index)
79     {
80       case Toolkit::ScrollView::Property::WRAP_ENABLED:
81       {
82         value = scrollViewImpl.GetWrapMode();
83         break;
84       }
85       case Toolkit::ScrollView::Property::PANNING_ENABLED:
86       {
87         value = scrollViewImpl.GetScrollSensitive();
88         break;
89       }
90       case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED:
91       {
92         value = scrollViewImpl.GetAxisAutoLock();
93         break;
94       }
95       case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP:
96       {
97         value = scrollViewImpl.GetWheelScrollDistanceStep();
98         break;
99       }
100     }
101   }
102
103   return value;
104 }
105
106 void ScrollViewPropertyHandler::SetScrollMode(ScrollView& scrollView, const Property::Map& scrollModeMap)
107 {
108   Toolkit::RulerPtr rulerX, rulerY;
109
110   // Check the scroll mode in the X axis
111   bool             xAxisScrollEnabled = true;
112   Property::Value* valuePtr           = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SCROLL_ENABLED, "xAxisScrollEnabled");
113   if(valuePtr && valuePtr->GetType() == Property::BOOLEAN)
114   {
115     valuePtr->Get(xAxisScrollEnabled);
116   }
117
118   if(!xAxisScrollEnabled)
119   {
120     // Default ruler and disabled
121     rulerX = new Toolkit::DefaultRuler();
122     rulerX->Disable();
123   }
124   else
125   {
126     valuePtr                  = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SNAP_TO_INTERVAL, "xAxisSnapToInterval");
127     float xAxisSnapToInterval = 0.0f;
128     if(valuePtr && valuePtr->Get(xAxisSnapToInterval))
129     {
130       // Fixed ruler and enabled
131       rulerX = new Toolkit::FixedRuler(xAxisSnapToInterval);
132     }
133     else
134     {
135       // Default ruler and enabled
136       rulerX = new Toolkit::DefaultRuler();
137     }
138
139     valuePtr                  = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SCROLL_BOUNDARY, "xAxisScrollBoundary");
140     float xAxisScrollBoundary = 0.0f;
141     if(valuePtr && valuePtr->Get(xAxisScrollBoundary))
142     {
143       // By default ruler domain is disabled unless set
144       rulerX->SetDomain(Toolkit::RulerDomain(0, xAxisScrollBoundary, true));
145     }
146   }
147
148   // Check the scroll mode in the Y axis
149   bool yAxisScrollEnabled = true;
150   valuePtr                = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SCROLL_ENABLED, "yAxisScrollEnabled");
151   if(valuePtr && valuePtr->GetType() == Property::BOOLEAN)
152   {
153     valuePtr->Get(yAxisScrollEnabled);
154   }
155
156   if(!yAxisScrollEnabled)
157   {
158     // Default ruler and disabled
159     rulerY = new Toolkit::DefaultRuler();
160     rulerY->Disable();
161   }
162   else
163   {
164     valuePtr                  = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SNAP_TO_INTERVAL, "yAxisSnapToInterval");
165     float yAxisSnapToInterval = 0.0f;
166     if(valuePtr && valuePtr->Get(yAxisSnapToInterval))
167     {
168       // Fixed ruler and enabled
169       rulerY = new Toolkit::FixedRuler(yAxisSnapToInterval);
170     }
171     else
172     {
173       // Default ruler and enabled
174       rulerY = new Toolkit::DefaultRuler();
175     }
176
177     valuePtr                  = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SCROLL_BOUNDARY, "yAxisScrollBoundary");
178     float yAxisScrollBoundary = 0.0f;
179     if(valuePtr && valuePtr->Get(yAxisScrollBoundary))
180     {
181       // By default ruler domain is disabled unless set
182       rulerY->SetDomain(Toolkit::RulerDomain(0, yAxisScrollBoundary, true));
183     }
184   }
185
186   scrollView.SetRulerX(rulerX);
187   scrollView.SetRulerY(rulerY);
188 }
189
190 void ScrollViewPropertyHandler::UpdatePropertyDomain(ScrollView& scrollView)
191 {
192   Actor   self                  = scrollView.Self();
193   Vector3 size                  = self.GetTargetSize();
194   Vector2 min                   = scrollView.mMinScroll;
195   Vector2 max                   = scrollView.mMaxScroll;
196   bool    scrollPositionChanged = false;
197   bool    domainChanged         = false;
198
199   bool canScrollVertical   = false;
200   bool canScrollHorizontal = false;
201   scrollView.UpdateLocalScrollProperties();
202   if(scrollView.mRulerX->IsEnabled())
203   {
204     const Toolkit::RulerDomain& rulerDomain = scrollView.mRulerX->GetDomain();
205     if(fabsf(min.x - rulerDomain.min) > Math::MACHINE_EPSILON_100 || fabsf(max.x - rulerDomain.max) > Math::MACHINE_EPSILON_100)
206     {
207       domainChanged = true;
208       min.x         = rulerDomain.min;
209       max.x         = rulerDomain.max;
210
211       // make sure new scroll value is within new domain
212       if(scrollView.mScrollPrePosition.x < min.x || scrollView.mScrollPrePosition.x > max.x)
213       {
214         scrollPositionChanged = true;
215         scrollView.mScrollPrePosition.x  = Clamp(scrollView.mScrollPrePosition.x, -(max.x - size.x), -min.x);
216       }
217     }
218     if((fabsf(rulerDomain.max - rulerDomain.min) - size.x) > Math::MACHINE_EPSILON_100)
219     {
220       canScrollHorizontal = true;
221     }
222   }
223   else if(fabs(min.x) > Math::MACHINE_EPSILON_100 || fabs(max.x) > Math::MACHINE_EPSILON_100)
224   {
225     // need to reset to 0
226     domainChanged       = true;
227     min.x               = 0.0f;
228     max.x               = 0.0f;
229     canScrollHorizontal = false;
230   }
231
232   if(scrollView.mRulerY->IsEnabled())
233   {
234     const Toolkit::RulerDomain& rulerDomain = scrollView.mRulerY->GetDomain();
235     if(fabsf(min.y - rulerDomain.min) > Math::MACHINE_EPSILON_100 || fabsf(max.y - rulerDomain.max) > Math::MACHINE_EPSILON_100)
236     {
237       domainChanged = true;
238       min.y         = rulerDomain.min;
239       max.y         = rulerDomain.max;
240
241       // make sure new scroll value is within new domain
242       if(scrollView.mScrollPrePosition.y < min.y || scrollView.mScrollPrePosition.y > max.y)
243       {
244         scrollPositionChanged = true;
245         scrollView.mScrollPrePosition.y  = Clamp(scrollView.mScrollPrePosition.y, -(max.y - size.y), -min.y);
246       }
247     }
248     if((fabsf(rulerDomain.max - rulerDomain.min) - size.y) > Math::MACHINE_EPSILON_100)
249     {
250       canScrollVertical = true;
251     }
252   }
253   else if(fabs(min.y) > Math::MACHINE_EPSILON_100 || fabs(max.y) > Math::MACHINE_EPSILON_100)
254   {
255     // need to reset to 0
256     domainChanged     = true;
257     min.y             = 0.0f;
258     max.y             = 0.0f;
259     canScrollVertical = false;
260   }
261
262   // avoid setting properties if possible, otherwise this will cause an entire update as well as triggering constraints using each property we update
263   if(scrollView.mCanScrollVertical != canScrollVertical)
264   {
265     scrollView.mCanScrollVertical = canScrollVertical;
266     self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, canScrollVertical);
267   }
268   if(scrollView.mCanScrollHorizontal != canScrollHorizontal)
269   {
270     scrollView.mCanScrollHorizontal = canScrollHorizontal;
271     self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, canScrollHorizontal);
272   }
273   if(scrollPositionChanged)
274   {
275     self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, scrollView.mScrollPrePosition);
276   }
277   if(domainChanged)
278   {
279     scrollView.mMinScroll = min;
280     scrollView.mMaxScroll = max;
281     self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN, scrollView.mMinScroll);
282     self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX, scrollView.mMaxScroll);
283   }
284 }
285
286 } // namespace Dali::Toolkit::Internal