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