71e8be8c5518942b98750b28b9df425b288dfdd2
[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 // INTERNAL INCLUDES
19 #include <dali-toolkit/internal/controls/scrollable/scrollable-impl.h>
20 #include <dali-toolkit/internal/controls/scroll-component/scroll-bar-internal-impl.h>
21
22 using namespace Dali;
23
24 namespace
25 {
26
27 } // unnamed namespace
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 TypeRegistration mType( typeid(Toolkit::Scrollable), typeid(Toolkit::Control), Create );
48
49 SignalConnectorType s1(mType, Toolkit::Scrollable::SIGNAL_SCROLL_STARTED,   &Scrollable::DoConnectSignal);
50 SignalConnectorType s2(mType, Toolkit::Scrollable::SIGNAL_SCROLL_COMPLETED, &Scrollable::DoConnectSignal);
51 SignalConnectorType s3(mType, Toolkit::Scrollable::SIGNAL_SCROLL_UPDATED,   &Scrollable::DoConnectSignal);
52 SignalConnectorType s4(mType, Toolkit::Scrollable::SIGNAL_SCROLL_CLAMPED,   &Scrollable::DoConnectSignal);
53
54 }
55
56 const std::string Scrollable::SCROLLABLE_CAN_SCROLL_VERTICAL( "scrollable-can-scroll-vertical" );
57 const std::string Scrollable::SCROLLABLE_CAN_SCROLL_HORIZONTAL( "scrollable-can-scroll-horizontal" );
58 const Vector4     Scrollable::DEFAULT_OVERSHOOT_COLOUR(0.0f, 0.64f, 0.85f, 0.6f);
59
60 ///////////////////////////////////////////////////////////////////////////////////////////////////
61 // Scrollable
62 ///////////////////////////////////////////////////////////////////////////////////////////////////
63
64 Scrollable::Scrollable()
65 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
66   mPropertyRelativePosition(Property::INVALID_INDEX),
67   mPropertyPositionMin(Property::INVALID_INDEX),
68   mPropertyPositionMax(Property::INVALID_INDEX),
69   mPropertyScrollDirection(Property::INVALID_INDEX),
70   mPropertyCanScrollVertical(Property::INVALID_INDEX),
71   mPropertyCanScrollHorizontal(Property::INVALID_INDEX),
72   mOvershootEnabled(false)
73 {
74 }
75
76 Scrollable::~Scrollable()
77 {
78   // Clear scroll components, forces their destruction before Scrollable is destroyed.
79   mComponents.clear();
80 }
81
82 void Scrollable::RegisterCommonProperties()
83 {
84   Actor self = Self();
85
86   // Register properties.
87   mPropertyRelativePosition = self.RegisterProperty(Toolkit::Scrollable::SCROLL_RELATIVE_POSITION_PROPERTY_NAME, Vector3::ZERO);
88   mPropertyPositionMin = self.RegisterProperty(Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME, Vector3::ZERO);
89   mPropertyPositionMax = self.RegisterProperty(Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME, Vector3::ZERO);
90   mPropertyScrollDirection = self.RegisterProperty(Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME, Vector3::ZERO);
91   mPropertyCanScrollVertical = self.RegisterProperty(SCROLLABLE_CAN_SCROLL_VERTICAL, true);
92   mPropertyCanScrollHorizontal = self.RegisterProperty(SCROLLABLE_CAN_SCROLL_HORIZONTAL, true);
93 }
94
95 bool Scrollable::IsScrollComponentEnabled(Toolkit::Scrollable::ScrollComponentType type) const
96 {
97   if(type == Toolkit::Scrollable::OvershootIndicator)
98   {
99     return mOvershootEnabled;
100   }
101   return (mComponents.find(type) != mComponents.end());
102 }
103
104 void Scrollable::EnableScrollComponent(Toolkit::Scrollable::ScrollComponentType type)
105 {
106   if(type == Toolkit::Scrollable::OvershootIndicator)
107   {
108     if( !mOvershootEnabled )
109     {
110       SetOvershootEnabled(true);
111       mOvershootEnabled = true;
112     }
113     return;
114   }
115   if( mComponents.find(type) == mComponents.end() )
116   {
117     // Create ScrollComponent
118     Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast(Self());
119     Toolkit::ScrollComponent scrollComponent = NewScrollComponent(scrollable, type);
120     Toolkit::ScrollComponentImpl& component = static_cast<Toolkit::ScrollComponentImpl&>(scrollComponent.GetImplementation());
121     ScrollComponentPtr componentPtr(&component);
122
123     mComponents[type] = componentPtr;
124   }
125 }
126
127 void Scrollable::DisableScrollComponent(Toolkit::Scrollable::ScrollComponentType type)
128 {
129   if(type == Toolkit::Scrollable::OvershootIndicator)
130   {
131     if( mOvershootEnabled )
132     {
133       SetOvershootEnabled(false);
134       mOvershootEnabled = false;
135     }
136     return;
137   }
138   ComponentIter pair = mComponents.find( type );
139
140   if( mComponents.end() != pair )
141   {
142     ScrollComponentPtr component = pair->second;
143
144     // Disconnect the scroll component first.
145     component->OnDisconnect();
146
147     // Destroy ScrollComponent.
148     mComponents.erase( type );
149   }
150 }
151
152 Toolkit::Scrollable::ScrollStartedSignalV2& Scrollable::ScrollStartedSignal()
153 {
154   return mScrollStartedSignalV2;
155 }
156
157 Toolkit::Scrollable::ScrollUpdatedSignalV2& Scrollable::ScrollUpdatedSignal()
158 {
159   return mScrollUpdatedSignalV2;
160 }
161
162 Toolkit::Scrollable::ScrollCompletedSignalV2& Scrollable::ScrollCompletedSignal()
163 {
164   return mScrollCompletedSignalV2;
165 }
166
167 Toolkit::Scrollable::ScrollClampedSignalV2& Scrollable::ScrollClampedSignal()
168 {
169   return mScrollClampedSignalV2;
170 }
171
172 bool Scrollable::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
173 {
174   Dali::BaseHandle handle( object );
175
176   bool connected( true );
177   Toolkit::Scrollable scrollable = Toolkit::Scrollable::DownCast( handle );
178
179   if( Toolkit::Scrollable::SIGNAL_SCROLL_STARTED == signalName )
180   {
181     scrollable.ScrollStartedSignal().Connect( tracker, functor );
182   }
183   else if( Toolkit::Scrollable::SIGNAL_SCROLL_UPDATED == signalName )
184   {
185     scrollable.ScrollUpdatedSignal().Connect( tracker, functor );
186   }
187   else if( Toolkit::Scrollable::SIGNAL_SCROLL_COMPLETED == signalName )
188   {
189     scrollable.ScrollCompletedSignal().Connect( tracker, functor );
190   }
191   else if( Toolkit::Scrollable::SIGNAL_SCROLL_CLAMPED == signalName )
192   {
193     scrollable.ScrollClampedSignal().Connect( tracker, functor );
194   }
195   else
196   {
197     // signalName does not match any signal
198     connected = false;
199   }
200
201   return connected;
202 }
203
204 Toolkit::ScrollComponent Scrollable::NewScrollComponent(Toolkit::Scrollable& scrollable, Toolkit::Scrollable::ScrollComponentType type)
205 {
206   Toolkit::ScrollComponent instance;
207
208   switch(type)
209   {
210     case Toolkit::Scrollable::VerticalScrollBar:
211     {
212       instance = static_cast<Toolkit::ScrollComponent>(Toolkit::ScrollBarInternal::New(scrollable, true));
213       break;
214     }
215     case Toolkit::Scrollable::HorizontalScrollBar:
216     {
217       instance = static_cast<Toolkit::ScrollComponent>(Toolkit::ScrollBarInternal::New(scrollable, false));
218       break;
219     }
220     default:
221     {
222       DALI_ASSERT_ALWAYS(true && "Unrecognized component type");
223     }
224   }
225
226   return instance;
227 }
228
229 } // namespace Internal
230
231 } // namespace Toolkit
232
233 } // namespace Dali