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