2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.h>
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>
25 namespace Dali::Toolkit::Internal
28 void ScrollViewPropertyHandler::Set(BaseObject* object, Property::Index index, const Property::Value& value)
30 Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
34 ScrollView& scrollViewImpl(GetImpl(scrollView));
37 case Toolkit::ScrollView::Property::WRAP_ENABLED:
39 scrollViewImpl.SetWrapMode(value.Get<bool>());
42 case Toolkit::ScrollView::Property::PANNING_ENABLED:
44 scrollViewImpl.SetScrollSensitive(value.Get<bool>());
47 case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED:
49 scrollViewImpl.SetAxisAutoLock(value.Get<bool>());
52 case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP:
54 scrollViewImpl.SetWheelScrollDistanceStep(value.Get<Vector2>());
57 case Toolkit::ScrollView::Property::SCROLL_MODE:
59 const Property::Map* map = value.GetMap();
62 SetScrollMode(scrollViewImpl, *map);
69 Property::Value ScrollViewPropertyHandler::Get(BaseObject* object, Property::Index index)
71 Property::Value value;
73 Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
77 ScrollView& scrollViewImpl(GetImpl(scrollView));
80 case Toolkit::ScrollView::Property::WRAP_ENABLED:
82 value = scrollViewImpl.GetWrapMode();
85 case Toolkit::ScrollView::Property::PANNING_ENABLED:
87 value = scrollViewImpl.GetScrollSensitive();
90 case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED:
92 value = scrollViewImpl.GetAxisAutoLock();
95 case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP:
97 value = scrollViewImpl.GetWheelScrollDistanceStep();
106 void ScrollViewPropertyHandler::SetScrollMode(ScrollView& scrollView, const Property::Map& scrollModeMap)
108 Toolkit::RulerPtr rulerX, rulerY;
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)
115 valuePtr->Get(xAxisScrollEnabled);
118 if(!xAxisScrollEnabled)
120 // Default ruler and disabled
121 rulerX = new Toolkit::DefaultRuler();
126 valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SNAP_TO_INTERVAL, "xAxisSnapToInterval");
127 float xAxisSnapToInterval = 0.0f;
128 if(valuePtr && valuePtr->Get(xAxisSnapToInterval))
130 // Fixed ruler and enabled
131 rulerX = new Toolkit::FixedRuler(xAxisSnapToInterval);
135 // Default ruler and enabled
136 rulerX = new Toolkit::DefaultRuler();
139 valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SCROLL_BOUNDARY, "xAxisScrollBoundary");
140 float xAxisScrollBoundary = 0.0f;
141 if(valuePtr && valuePtr->Get(xAxisScrollBoundary))
143 // By default ruler domain is disabled unless set
144 rulerX->SetDomain(Toolkit::RulerDomain(0, xAxisScrollBoundary, true));
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)
153 valuePtr->Get(yAxisScrollEnabled);
156 if(!yAxisScrollEnabled)
158 // Default ruler and disabled
159 rulerY = new Toolkit::DefaultRuler();
164 valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SNAP_TO_INTERVAL, "yAxisSnapToInterval");
165 float yAxisSnapToInterval = 0.0f;
166 if(valuePtr && valuePtr->Get(yAxisSnapToInterval))
168 // Fixed ruler and enabled
169 rulerY = new Toolkit::FixedRuler(yAxisSnapToInterval);
173 // Default ruler and enabled
174 rulerY = new Toolkit::DefaultRuler();
177 valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SCROLL_BOUNDARY, "yAxisScrollBoundary");
178 float yAxisScrollBoundary = 0.0f;
179 if(valuePtr && valuePtr->Get(yAxisScrollBoundary))
181 // By default ruler domain is disabled unless set
182 rulerY->SetDomain(Toolkit::RulerDomain(0, yAxisScrollBoundary, true));
186 scrollView.SetRulerX(rulerX);
187 scrollView.SetRulerY(rulerY);
190 void ScrollViewPropertyHandler::UpdatePropertyDomain(ScrollView& scrollView)
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;
199 bool canScrollVertical = false;
200 bool canScrollHorizontal = false;
201 scrollView.UpdateLocalScrollProperties();
202 if(scrollView.mRulerX->IsEnabled())
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)
207 domainChanged = true;
208 min.x = rulerDomain.min;
209 max.x = rulerDomain.max;
211 // make sure new scroll value is within new domain
212 if(scrollView.mScrollPrePosition.x < min.x || scrollView.mScrollPrePosition.x > max.x)
214 scrollPositionChanged = true;
215 scrollView.mScrollPrePosition.x = Clamp(scrollView.mScrollPrePosition.x, -(max.x - size.x), -min.x);
218 if((fabsf(rulerDomain.max - rulerDomain.min) - size.x) > Math::MACHINE_EPSILON_100)
220 canScrollHorizontal = true;
223 else if(fabs(min.x) > Math::MACHINE_EPSILON_100 || fabs(max.x) > Math::MACHINE_EPSILON_100)
225 // need to reset to 0
226 domainChanged = true;
229 canScrollHorizontal = false;
232 if(scrollView.mRulerY->IsEnabled())
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)
237 domainChanged = true;
238 min.y = rulerDomain.min;
239 max.y = rulerDomain.max;
241 // make sure new scroll value is within new domain
242 if(scrollView.mScrollPrePosition.y < min.y || scrollView.mScrollPrePosition.y > max.y)
244 scrollPositionChanged = true;
245 scrollView.mScrollPrePosition.y = Clamp(scrollView.mScrollPrePosition.y, -(max.y - size.y), -min.y);
248 if((fabsf(rulerDomain.max - rulerDomain.min) - size.y) > Math::MACHINE_EPSILON_100)
250 canScrollVertical = true;
253 else if(fabs(min.y) > Math::MACHINE_EPSILON_100 || fabs(max.y) > Math::MACHINE_EPSILON_100)
255 // need to reset to 0
256 domainChanged = true;
259 canScrollVertical = false;
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)
265 scrollView.mCanScrollVertical = canScrollVertical;
266 self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, canScrollVertical);
268 if(scrollView.mCanScrollHorizontal != canScrollHorizontal)
270 scrollView.mCanScrollHorizontal = canScrollHorizontal;
271 self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, canScrollHorizontal);
273 if(scrollPositionChanged)
275 self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, scrollView.mScrollPrePosition);
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);
286 } // namespace Dali::Toolkit::Internal