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