e378a3d8ba2c7401d35c31ce5727ccae80b7b0bd
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / scrollable / scrollable-impl.cpp
1 /*
2  * Copyright (c) 2014 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 // EXTERNAL INCLUDES
19 #include <dali/public-api/object/type-registry.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/internal/controls/scrollable/scrollable-impl.h>
23 #include <dali-toolkit/internal/controls/scroll-component/scroll-bar-internal-impl.h>
24
25 using namespace Dali;
26
27 namespace
28 {
29
30 } // unnamed namespace
31
32 namespace Dali
33 {
34
35 namespace Toolkit
36 {
37
38 const Property::Index Scrollable::PROPERTY_OVERSHOOT_EFFECT_COLOR( Toolkit::Internal::Control::CONTROL_PROPERTY_END_INDEX + 1 );
39 const Property::Index Scrollable::PROPERTY_OVERSHOOT_ANIMATION_SPEED( Toolkit::Internal::Control::CONTROL_PROPERTY_END_INDEX + 2 );
40
41 namespace Internal
42 {
43
44 namespace
45 {
46 const Vector4 DEFAULT_OVERSHOOT_COLOUR(0.0f, 0.64f, 0.85f, 0.25f);
47 const float DEFAULT_OVERSHOOT_ANIMATION_SPEED(120.0f); // 120 pixels per second
48
49 BaseHandle Create()
50 {
51   // empty handle as we cannot create Scrollable (but type registered for scroll signal)
52   return BaseHandle();
53 }
54
55 TypeRegistration mType( typeid(Toolkit::Scrollable), typeid(Toolkit::Control), Create );
56
57 SignalConnectorType s1(mType, Toolkit::Scrollable::SIGNAL_SCROLL_STARTED,   &Scrollable::DoConnectSignal);
58 SignalConnectorType s2(mType, Toolkit::Scrollable::SIGNAL_SCROLL_COMPLETED, &Scrollable::DoConnectSignal);
59 SignalConnectorType s3(mType, Toolkit::Scrollable::SIGNAL_SCROLL_UPDATED,   &Scrollable::DoConnectSignal);
60 SignalConnectorType s4(mType, Toolkit::Scrollable::SIGNAL_SCROLL_CLAMPED,   &Scrollable::DoConnectSignal);
61
62 PropertyRegistration property1( mType,
63                                 "overshoot-effect-color",
64                                 Toolkit::Scrollable::PROPERTY_OVERSHOOT_EFFECT_COLOR,
65                                 Property::VECTOR4,
66                                 &Scrollable::SetProperty,
67                                 &Scrollable::GetProperty );
68
69 PropertyRegistration property2( mType,
70                                 "overshoot-animation-speed",
71                                 Toolkit::Scrollable::PROPERTY_OVERSHOOT_ANIMATION_SPEED,
72                                 Property::FLOAT,
73                                 &Scrollable::SetProperty,
74                                 &Scrollable::GetProperty );
75
76 }
77
78 const std::string Scrollable::SCROLLABLE_CAN_SCROLL_VERTICAL( "scrollable-can-scroll-vertical" );
79 const std::string Scrollable::SCROLLABLE_CAN_SCROLL_HORIZONTAL( "scrollable-can-scroll-horizontal" );
80
81 ///////////////////////////////////////////////////////////////////////////////////////////////////
82 // Scrollable
83 ///////////////////////////////////////////////////////////////////////////////////////////////////
84
85 // Scrollable controls are not layout containers so they dont need size negotiation..
86 // we dont want size negotiation while scrolling if we can avoid it
87 Scrollable::Scrollable()
88 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS | NO_SIZE_NEGOTIATION ) ),
89   mOvershootEffectColor(  DEFAULT_OVERSHOOT_COLOUR ),
90   mOvershootAnimationSpeed ( DEFAULT_OVERSHOOT_ANIMATION_SPEED ),
91   mPropertyRelativePosition(Property::INVALID_INDEX),
92   mPropertyPositionMin(Property::INVALID_INDEX),
93   mPropertyPositionMax(Property::INVALID_INDEX),
94   mPropertyScrollDirection(Property::INVALID_INDEX),
95   mPropertyCanScrollVertical(Property::INVALID_INDEX),
96   mPropertyCanScrollHorizontal(Property::INVALID_INDEX),
97   mOvershootEnabled(false)
98 {
99 }
100
101 Scrollable::~Scrollable()
102 {
103   // Clear scroll components, forces their destruction before Scrollable is destroyed.
104   mComponents.clear();
105 }
106
107 void Scrollable::RegisterCommonProperties()
108 {
109   Actor self = Self();
110
111   // Register properties.
112   mPropertyRelativePosition = self.RegisterProperty(Toolkit::Scrollable::SCROLL_RELATIVE_POSITION_PROPERTY_NAME, Vector3::ZERO);
113   mPropertyPositionMin = self.RegisterProperty(Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME, Vector3::ZERO);
114   mPropertyPositionMax = self.RegisterProperty(Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME, Vector3::ZERO);
115   mPropertyScrollDirection = self.RegisterProperty(Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME, Vector3::ZERO);
116   mPropertyCanScrollVertical = self.RegisterProperty(SCROLLABLE_CAN_SCROLL_VERTICAL, true);
117   mPropertyCanScrollHorizontal = self.RegisterProperty(SCROLLABLE_CAN_SCROLL_HORIZONTAL, true);
118 }
119
120 bool Scrollable::IsScrollComponentEnabled(Toolkit::Scrollable::ScrollComponentType type) const
121 {
122   if(type == Toolkit::Scrollable::OvershootIndicator)
123   {
124     return mOvershootEnabled;
125   }
126   return (mComponents.find(type) != mComponents.end());
127 }
128
129 void Scrollable::EnableScrollComponent(Toolkit::Scrollable::ScrollComponentType type)
130 {
131   if(type == Toolkit::Scrollable::OvershootIndicator)
132   {
133     if( !mOvershootEnabled )
134     {
135       SetOvershootEnabled(true);
136       mOvershootEnabled = true;
137     }
138     return;
139   }
140   if( mComponents.find(type) == mComponents.end() )
141   {
142     // Create ScrollComponent
143     Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast(Self());
144     Toolkit::ScrollComponent scrollComponent = NewScrollComponent(scrollable, type);
145     Toolkit::ScrollComponentImpl& component = static_cast<Toolkit::ScrollComponentImpl&>(scrollComponent.GetImplementation());
146     ScrollComponentPtr componentPtr(&component);
147
148     mComponents[type] = componentPtr;
149   }
150 }
151
152 void Scrollable::DisableScrollComponent(Toolkit::Scrollable::ScrollComponentType type)
153 {
154   if(type == Toolkit::Scrollable::OvershootIndicator)
155   {
156     if( mOvershootEnabled )
157     {
158       SetOvershootEnabled(false);
159       mOvershootEnabled = false;
160     }
161     return;
162   }
163   ComponentIter pair = mComponents.find( type );
164
165   if( mComponents.end() != pair )
166   {
167     ScrollComponentPtr component = pair->second;
168
169     // Disconnect the scroll component first.
170     component->OnDisconnect();
171
172     // Destroy ScrollComponent.
173     mComponents.erase( type );
174   }
175 }
176
177 Vector4 Scrollable::GetOvershootEffectColor() const
178 {
179   return mOvershootEffectColor;
180 };
181
182 void Scrollable::SetOvershootAnimationSpeed( float pixelsPerSecond )
183 {
184   mOvershootAnimationSpeed = pixelsPerSecond;
185 }
186
187 float Scrollable::GetOvershootAnimationSpeed() const
188 {
189   return mOvershootAnimationSpeed;
190 };
191
192 Toolkit::Scrollable::ScrollStartedSignalV2& Scrollable::ScrollStartedSignal()
193 {
194   return mScrollStartedSignalV2;
195 }
196
197 Toolkit::Scrollable::ScrollUpdatedSignalV2& Scrollable::ScrollUpdatedSignal()
198 {
199   return mScrollUpdatedSignalV2;
200 }
201
202 Toolkit::Scrollable::ScrollCompletedSignalV2& Scrollable::ScrollCompletedSignal()
203 {
204   return mScrollCompletedSignalV2;
205 }
206
207 Toolkit::Scrollable::ScrollClampedSignalV2& Scrollable::ScrollClampedSignal()
208 {
209   return mScrollClampedSignalV2;
210 }
211
212 bool Scrollable::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
213 {
214   Dali::BaseHandle handle( object );
215
216   bool connected( true );
217   Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast( handle );
218
219   if( Toolkit::Scrollable::SIGNAL_SCROLL_STARTED == signalName )
220   {
221     scrollable.ScrollStartedSignal().Connect( tracker, functor );
222   }
223   else if( Toolkit::Scrollable::SIGNAL_SCROLL_UPDATED == signalName )
224   {
225     scrollable.ScrollUpdatedSignal().Connect( tracker, functor );
226   }
227   else if( Toolkit::Scrollable::SIGNAL_SCROLL_COMPLETED == signalName )
228   {
229     scrollable.ScrollCompletedSignal().Connect( tracker, functor );
230   }
231   else if( Toolkit::Scrollable::SIGNAL_SCROLL_CLAMPED == signalName )
232   {
233     scrollable.ScrollClampedSignal().Connect( tracker, functor );
234   }
235   else
236   {
237     // signalName does not match any signal
238     connected = false;
239   }
240
241   return connected;
242 }
243
244 void Scrollable::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
245 {
246   Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast( Dali::BaseHandle( object ) );
247
248   if( scrollable )
249   {
250     Scrollable& scrollableImpl( GetImpl( scrollable ) );
251     switch( index )
252     {
253       case Toolkit::Scrollable::PROPERTY_OVERSHOOT_EFFECT_COLOR:
254       {
255         scrollableImpl.SetOvershootEffectColor( value.Get<Vector4>() );
256         break;
257       }
258       case Toolkit::Scrollable::PROPERTY_OVERSHOOT_ANIMATION_SPEED:
259       {
260         scrollableImpl.SetOvershootAnimationSpeed( value.Get<float>() );
261         break;
262       }
263     }
264   }
265 }
266
267 Property::Value Scrollable::GetProperty( BaseObject* object, Property::Index index )
268 {
269   Property::Value value;
270
271   Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast( Dali::BaseHandle( object ) );
272
273   if( scrollable )
274   {
275     Scrollable& scrollableImpl( GetImpl( scrollable ) );
276     switch( index )
277     {
278       case Toolkit::Scrollable::PROPERTY_OVERSHOOT_EFFECT_COLOR:
279       {
280         value = scrollableImpl.GetOvershootEffectColor();
281         break;
282       }
283       case Toolkit::Scrollable::PROPERTY_OVERSHOOT_ANIMATION_SPEED:
284       {
285         value = scrollableImpl.GetOvershootAnimationSpeed();
286         break;
287       }
288     }
289   }
290
291   return value;
292 }
293
294 Toolkit::ScrollComponent Scrollable::NewScrollComponent(Toolkit::Scrollable& scrollable, Toolkit::Scrollable::ScrollComponentType type)
295 {
296   Toolkit::ScrollComponent instance;
297
298   switch(type)
299   {
300     case Toolkit::Scrollable::VerticalScrollBar:
301     {
302       instance = static_cast<Toolkit::ScrollComponent>(Toolkit::ScrollBarInternal::New(scrollable, true));
303       break;
304     }
305     case Toolkit::Scrollable::HorizontalScrollBar:
306     {
307       instance = static_cast<Toolkit::ScrollComponent>(Toolkit::ScrollBarInternal::New(scrollable, false));
308       break;
309     }
310     case Toolkit::Scrollable::OvershootIndicator:
311     {
312       DALI_ASSERT_ALWAYS(!"Unrecognized component type");
313       break;
314     }
315   }
316
317   return instance;
318 }
319
320 } // namespace Internal
321
322 } // namespace Toolkit
323
324 } // namespace Dali