[dali_1.0.38] Merge branch '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 <cstring> // for strcmp
20 #include <dali/public-api/object/type-registry.h>
21 #include <dali/public-api/object/type-registry-helper.h>
22
23 // INTERNAL INCLUDES
24 #include <dali-toolkit/internal/controls/scrollable/scrollable-impl.h>
25 #include <dali-toolkit/internal/controls/scroll-component/scroll-bar-internal-impl.h>
26
27 using namespace Dali;
28
29 namespace Dali
30 {
31
32 namespace Toolkit
33 {
34
35 namespace Internal
36 {
37
38 namespace
39 {
40
41 BaseHandle Create()
42 {
43   // empty handle as we cannot create Scrollable (but type registered for scroll signal)
44   return BaseHandle();
45 }
46
47 // Setup properties, signals and actions using the type-registry.
48 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Scrollable, Toolkit::Control, Create );
49
50 DALI_PROPERTY_REGISTRATION( Scrollable, "overshoot-effect-color",    VECTOR4, OVERSHOOT_EFFECT_COLOR    )
51 DALI_PROPERTY_REGISTRATION( Scrollable, "overshoot-animation-speed", FLOAT,   OVERSHOOT_ANIMATION_SPEED )
52
53 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "scroll-relative-position", VECTOR3, SCROLL_RELATIVE_POSITION)
54 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "scroll-position-min",      VECTOR3, SCROLL_POSITION_MIN)
55 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "scroll-position-max",      VECTOR3, SCROLL_POSITION_MAX)
56 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "scroll-direction",         VECTOR3, SCROLL_DIRECTION)
57 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "can-scroll-vertical",      BOOLEAN, CAN_SCROLL_VERTICAL)
58 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "can-scroll-horizontal",    BOOLEAN, CAN_SCROLL_HORIZONTAL)
59
60 DALI_SIGNAL_REGISTRATION(   Scrollable, "scroll-started",                     SIGNAL_SCROLL_STARTED     )
61 DALI_SIGNAL_REGISTRATION(   Scrollable, "scroll-completed",                   SIGNAL_SCROLL_COMPLETED   )
62 DALI_SIGNAL_REGISTRATION(   Scrollable, "scroll-updated",                     SIGNAL_SCROLL_UPDATED     )
63
64 DALI_TYPE_REGISTRATION_END()
65
66 const Vector4 DEFAULT_OVERSHOOT_COLOUR(0.0f, 0.64f, 0.85f, 0.25f);
67 const float DEFAULT_OVERSHOOT_ANIMATION_SPEED(120.0f); // 120 pixels per second
68
69 }
70
71 ///////////////////////////////////////////////////////////////////////////////////////////////////
72 // Scrollable
73 ///////////////////////////////////////////////////////////////////////////////////////////////////
74
75 // Scrollable controls are not layout containers so they dont need size negotiation..
76 // we dont want size negotiation while scrolling if we can avoid it
77 Scrollable::Scrollable()
78 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS | NO_SIZE_NEGOTIATION ) ),
79   mOvershootEffectColor(  DEFAULT_OVERSHOOT_COLOUR ),
80   mOvershootAnimationSpeed ( DEFAULT_OVERSHOOT_ANIMATION_SPEED ),
81   mOvershootEnabled(false)
82 {
83 }
84
85 Scrollable::~Scrollable()
86 {
87   // Clear scroll components, forces their destruction before Scrollable is destroyed.
88   mComponents.clear();
89 }
90
91 bool Scrollable::IsScrollComponentEnabled(Toolkit::Scrollable::ScrollComponentType type) const
92 {
93   if(type == Toolkit::Scrollable::OvershootIndicator)
94   {
95     return mOvershootEnabled;
96   }
97   return (mComponents.find(type) != mComponents.end());
98 }
99
100 void Scrollable::EnableScrollComponent(Toolkit::Scrollable::ScrollComponentType type)
101 {
102   if(type == Toolkit::Scrollable::OvershootIndicator)
103   {
104     if( !mOvershootEnabled )
105     {
106       SetOvershootEnabled(true);
107       mOvershootEnabled = true;
108     }
109     return;
110   }
111   if( mComponents.find(type) == mComponents.end() )
112   {
113     // Create ScrollComponent
114     Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast(Self());
115     Toolkit::ScrollComponent scrollComponent = NewScrollComponent(scrollable, type);
116     Toolkit::ScrollComponentImpl& component = static_cast<Toolkit::ScrollComponentImpl&>(scrollComponent.GetImplementation());
117     ScrollComponentPtr componentPtr(&component);
118
119     mComponents[type] = componentPtr;
120   }
121 }
122
123 void Scrollable::DisableScrollComponent(Toolkit::Scrollable::ScrollComponentType type)
124 {
125   if(type == Toolkit::Scrollable::OvershootIndicator)
126   {
127     if( mOvershootEnabled )
128     {
129       SetOvershootEnabled(false);
130       mOvershootEnabled = false;
131     }
132     return;
133   }
134   ComponentIter pair = mComponents.find( type );
135
136   if( mComponents.end() != pair )
137   {
138     ScrollComponentPtr component = pair->second;
139
140     // Disconnect the scroll component first.
141     component->OnDisconnect();
142
143     // Destroy ScrollComponent.
144     mComponents.erase( type );
145   }
146 }
147
148 Vector4 Scrollable::GetOvershootEffectColor() const
149 {
150   return mOvershootEffectColor;
151 };
152
153 void Scrollable::SetOvershootAnimationSpeed( float pixelsPerSecond )
154 {
155   mOvershootAnimationSpeed = pixelsPerSecond;
156 }
157
158 float Scrollable::GetOvershootAnimationSpeed() const
159 {
160   return mOvershootAnimationSpeed;
161 };
162
163 Toolkit::Scrollable::ScrollStartedSignalType& Scrollable::ScrollStartedSignal()
164 {
165   return mScrollStartedSignal;
166 }
167
168 Toolkit::Scrollable::ScrollUpdatedSignalType& Scrollable::ScrollUpdatedSignal()
169 {
170   return mScrollUpdatedSignal;
171 }
172
173 Toolkit::Scrollable::ScrollCompletedSignalType& Scrollable::ScrollCompletedSignal()
174 {
175   return mScrollCompletedSignal;
176 }
177
178 bool Scrollable::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
179 {
180   Dali::BaseHandle handle( object );
181
182   bool connected( true );
183   Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast( handle );
184
185   if( 0 == strcmp( signalName.c_str(), SIGNAL_SCROLL_STARTED ) )
186   {
187     scrollable.ScrollStartedSignal().Connect( tracker, functor );
188   }
189   else if( 0 == strcmp( signalName.c_str(), SIGNAL_SCROLL_UPDATED ) )
190   {
191     scrollable.ScrollUpdatedSignal().Connect( tracker, functor );
192   }
193   else if( 0 == strcmp( signalName.c_str(), SIGNAL_SCROLL_COMPLETED ) )
194   {
195     scrollable.ScrollCompletedSignal().Connect( tracker, functor );
196   }
197   else
198   {
199     // signalName does not match any signal
200     connected = false;
201   }
202
203   return connected;
204 }
205
206 void Scrollable::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
207 {
208   Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast( Dali::BaseHandle( object ) );
209
210   if( scrollable )
211   {
212     Scrollable& scrollableImpl( GetImpl( scrollable ) );
213     switch( index )
214     {
215       case Toolkit::Scrollable::Property::OVERSHOOT_EFFECT_COLOR:
216       {
217         scrollableImpl.SetOvershootEffectColor( value.Get<Vector4>() );
218         break;
219       }
220       case Toolkit::Scrollable::Property::OVERSHOOT_ANIMATION_SPEED:
221       {
222         scrollableImpl.SetOvershootAnimationSpeed( value.Get<float>() );
223         break;
224       }
225     }
226   }
227 }
228
229 Property::Value Scrollable::GetProperty( BaseObject* object, Property::Index index )
230 {
231   Property::Value value;
232
233   Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast( Dali::BaseHandle( object ) );
234
235   if( scrollable )
236   {
237     Scrollable& scrollableImpl( GetImpl( scrollable ) );
238     switch( index )
239     {
240       case Toolkit::Scrollable::Property::OVERSHOOT_EFFECT_COLOR:
241       {
242         value = scrollableImpl.GetOvershootEffectColor();
243         break;
244       }
245       case Toolkit::Scrollable::Property::OVERSHOOT_ANIMATION_SPEED:
246       {
247         value = scrollableImpl.GetOvershootAnimationSpeed();
248         break;
249       }
250     }
251   }
252
253   return value;
254 }
255
256 Toolkit::ScrollComponent Scrollable::NewScrollComponent(Toolkit::Scrollable& scrollable, Toolkit::Scrollable::ScrollComponentType type)
257 {
258   Toolkit::ScrollComponent instance;
259
260   switch(type)
261   {
262     case Toolkit::Scrollable::VerticalScrollBar:
263     {
264       instance = static_cast<Toolkit::ScrollComponent>(Toolkit::ScrollBarInternal::New(scrollable, true));
265       break;
266     }
267     case Toolkit::Scrollable::HorizontalScrollBar:
268     {
269       instance = static_cast<Toolkit::ScrollComponent>(Toolkit::ScrollBarInternal::New(scrollable, false));
270       break;
271     }
272     case Toolkit::Scrollable::OvershootIndicator:
273     {
274       DALI_ASSERT_ALWAYS(!"Unrecognized component type");
275       break;
276     }
277   }
278
279   return instance;
280 }
281
282 } // namespace Internal
283
284 } // namespace Toolkit
285
286 } // namespace Dali