[SRUK] Initial copy from Tizen 2.2 version
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / public-api / controls / control-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 #include <dali-toolkit/public-api/controls/control-impl.h>
18
19 #include <boost/thread/tss.hpp>
20 #include <stack>
21
22 #include <dali/integration-api/debug.h>
23
24 #include "dali-toolkit/internal/controls/style-change-processor.h"
25 #include "dali-toolkit/internal/controls/relayout-controller.h"
26 #include "dali-toolkit/internal/controls/relayout-helper.h"
27 #include "dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h"
28 #include "dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h"
29 #include <dali-toolkit/public-api/controls/control.h>
30
31 namespace Dali
32 {
33
34 namespace Toolkit
35 {
36
37 namespace
38 {
39
40 #if defined(DEBUG_ENABLED)
41 Integration::Log::Filter* gLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_CONTROL");
42 #endif
43
44 const float MAX_FLOAT_VALUE( std::numeric_limits<float>::max() );
45
46 BaseHandle Create()
47 {
48   return ControlImpl::New();
49 }
50
51 TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
52
53 TypeAction ACTION_TYPE_1(CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &ControlImpl::DoAction);
54
55 /**
56  * Helper class used to set the Control's size through the Actor's API or through children added.
57  */
58 class SetSizeLock
59 {
60 public:
61   SetSizeLock( bool& lock )
62   : mLock( lock )
63   {
64     mLock = true;
65   }
66
67   ~SetSizeLock()
68   {
69     mLock = false;
70   }
71
72 private:
73   bool& mLock;
74 };
75
76 /**
77  * Helper function to calculate a dimension given the policy of that dimension; the minimum &
78  * maximum values that dimension can be; and the allocated value for that dimension.
79  *
80  * @param[in]  policy     The size policy for that dimension.
81  * @param[in]  minimum    The minimum value that dimension can be.
82  * @param[in]  maximum    The maximum value that dimension can be.
83  * @param[in]  allocated  The value allocated for that dimension.
84  *
85  * @return The value that the dimension should be.
86  *
87  * @note This does not handle Control::Fixed policy.
88  */
89 float Calculate( Control::SizePolicy policy, float minimum, float maximum, float allocated )
90 {
91   float size( allocated );
92
93   switch( policy )
94   {
95     case Control::Fixed:
96     {
97       // Use allocated value
98       break;
99     }
100
101     case Control::Minimum:
102     {
103       // Size is always at least the minimum.
104       size = std::max( allocated, minimum );
105       break;
106     }
107
108     case Control::Maximum:
109     {
110       // Size can grow but up to a maximum value.
111       size = std::min( allocated, maximum );
112       break;
113     }
114
115     case Control::Range:
116     {
117       // Size is at least the minimum and can grow up to the maximum
118       size = std::max( size, minimum );
119       size = std::min( size, maximum );
120      break;
121     }
122
123     case Control::Flexible:
124     {
125       // Size grows or shrinks with no limits.
126       size = allocated;
127       break;
128     }
129
130     default:
131     {
132       DALI_ASSERT_DEBUG( false && "This function was not intended to be used by any other policy." );
133       break;
134     }
135   }
136
137   return size;
138 }
139
140 } // unnamed namespace
141
142 class ControlImpl::Impl : public ConnectionTrackerInterface
143 {
144 public:
145   // Construction & Destruction
146   Impl(ControlImpl& controlImpl)
147   : mControlImpl(controlImpl),
148     mInitialized( false ),
149     mPinchGestureDetector(),
150     mPanGestureDetector(),
151     mTapGestureDetector(),
152     mLongPressGestureDetector(),
153     mStartingPinchScale(),
154     mLockSetSize( false ),
155     mWidthPolicy( Control::Fixed ),
156     mHeightPolicy( Control::Fixed ),
157     mSize(),
158     mSetSize(),
159     mMinimumSize(),
160     mMaximumSize( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE ),
161     mIsKeyboardNavigationSupported(false),
162     mIsKeyboardFocusGroup(false),
163     mKeyEventSignalV2()
164   {
165   }
166
167   ~Impl()
168   {
169     // All gesture detectors will be destroyed so no need to disconnect.
170   }
171
172   // Gesture Detection Methods
173
174   void PinchDetected(Actor actor, PinchGesture pinch)
175   {
176     mControlImpl.OnPinch(pinch);
177   }
178
179   void PanDetected(Actor actor, PanGesture pan)
180   {
181     mControlImpl.OnPan(pan);
182   }
183
184   void TapDetected(Actor actor, TapGesture tap)
185   {
186     mControlImpl.OnTap(tap);
187   }
188
189   void LongPressDetected(Actor actor, LongPressGesture longPress)
190   {
191     mControlImpl.OnLongPress(longPress);
192   }
193
194   /**
195    * @copydoc ConnectionTrackerInterface::SignalConnected
196    */
197   virtual void SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
198   {
199     mConnectionTracker.SignalConnected( slotObserver, callback );
200   }
201
202   /**
203    * @copydoc ConnectionTrackerInterface::SignalDisconnected
204    */
205   virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
206   {
207     mConnectionTracker.SignalDisconnected( slotObserver, callback );
208   }
209
210   /**
211    * @copydoc ConnectionTrackerInterface::GetConnectionCount
212    */
213   virtual std::size_t GetConnectionCount() const
214   {
215     return mConnectionTracker.GetConnectionCount();
216   }
217
218   // Data
219
220   ControlImpl& mControlImpl;
221
222   bool mInitialized:1;
223
224   ConnectionTracker mConnectionTracker; // signal connection tracker
225
226   // Gesture Detection
227
228   PinchGestureDetector     mPinchGestureDetector;
229   PanGestureDetector       mPanGestureDetector;
230   TapGestureDetector       mTapGestureDetector;
231   LongPressGestureDetector mLongPressGestureDetector;
232
233   Vector3 mStartingPinchScale;       ///< The scale when a pinch gesture starts
234
235   // Relayout and size negotiation
236
237   bool mLockSetSize;                 ///< Used to avoid. Can't be a bitfield as a reference to this member is used in SetSizeLock helper class.
238
239   Control::SizePolicy mWidthPolicy;  ///< Stores the width policy.
240   Control::SizePolicy mHeightPolicy; ///< Stores the height policy.
241
242   Vector3 mSize;                     ///< Stores the current control's size.
243   Vector3 mSetSize;                  ///< Always stores the size set through the Actor's API. Useful when reset to the initial size is needed.
244   Vector3 mMinimumSize;              ///< Stores the control's minimum size.
245   Vector3 mMaximumSize;              ///< Stores the control's maximum size.
246
247   bool mIsKeyboardNavigationSupported;  ///< Stores whether keyboard navigation is supported by the control.
248   bool mIsKeyboardFocusGroup;        ///< Stores whether the control is a focus group.
249
250   Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
251 };
252
253 Control ControlImpl::New()
254 {
255   // Create the implementation, temporarily owned on stack
256   IntrusivePtr<ControlImpl> controlImpl = new ControlImpl( false );
257
258   // Pass ownership to handle
259   Control handle( *controlImpl );
260
261   // Second-phase init of the implementation
262   // This can only be done after the CustomActor connection has been made...
263   controlImpl->Initialize();
264
265   return handle;
266 }
267
268 ControlImpl::~ControlImpl()
269 {
270   if( mImpl->mInitialized )
271   {
272     // Unregister only if control has been initialized.
273     Internal::StyleChangeProcessor::Unregister( this );
274   }
275   delete mImpl;
276 }
277
278 void ControlImpl::Initialize()
279 {
280   // Register with the style change processor so we are informed when the default style changes
281   Internal::StyleChangeProcessor::Register( this );
282
283   // Calling deriving classes
284   OnInitialize();
285
286   mImpl->mInitialized = true;
287 }
288
289 void ControlImpl::EnableGestureDetection(Gesture::Type type)
290 {
291   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
292   {
293     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
294     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
295     mImpl->mPinchGestureDetector.Attach(Self());
296   }
297
298   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
299   {
300     mImpl->mPanGestureDetector = PanGestureDetector::New();
301     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
302     mImpl->mPanGestureDetector.Attach(Self());
303   }
304
305   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
306   {
307     mImpl->mTapGestureDetector = TapGestureDetector::New();
308     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
309     mImpl->mTapGestureDetector.Attach(Self());
310   }
311
312   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
313   {
314     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
315     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
316     mImpl->mLongPressGestureDetector.Attach(Self());
317   }
318 }
319
320 void ControlImpl::DisableGestureDetection(Gesture::Type type)
321 {
322   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
323   {
324     mImpl->mPinchGestureDetector.Detach(Self());
325     mImpl->mPinchGestureDetector.Reset();
326   }
327
328   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
329   {
330     mImpl->mPanGestureDetector.Detach(Self());
331     mImpl->mPanGestureDetector.Reset();
332   }
333
334   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
335   {
336     mImpl->mTapGestureDetector.Detach(Self());
337     mImpl->mTapGestureDetector.Reset();
338   }
339
340   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
341   {
342     mImpl->mLongPressGestureDetector.Detach(Self());
343     mImpl->mLongPressGestureDetector.Reset();
344   }
345 }
346
347 PinchGestureDetector ControlImpl::GetPinchGestureDetector() const
348 {
349   return mImpl->mPinchGestureDetector;
350 }
351
352 PanGestureDetector ControlImpl::GetPanGestureDetector() const
353 {
354   return mImpl->mPanGestureDetector;
355 }
356
357 TapGestureDetector ControlImpl::GetTapGestureDetector() const
358 {
359   return mImpl->mTapGestureDetector;
360 }
361
362 LongPressGestureDetector ControlImpl::GetLongPressGestureDetector() const
363 {
364   return mImpl->mLongPressGestureDetector;
365 }
366
367 void ControlImpl::OnPinch(PinchGesture pinch)
368 {
369   if (pinch.state == Gesture::Started)
370   {
371     mImpl->mStartingPinchScale = Self().GetCurrentScale();
372   }
373
374   Self().SetScale(mImpl->mStartingPinchScale * pinch.scale);
375 }
376
377 void ControlImpl::OnStageConnection()
378 {
379   RelayoutRequest();
380
381   // Notify derived classes.
382   OnControlStageConnection();
383 }
384
385 void ControlImpl::OnStageDisconnection()
386 {
387   // Notify derived classes
388   OnControlStageDisconnection();
389 }
390
391 void ControlImpl::OnChildAdd(Actor& child)
392 {
393   // Request for relayout.
394   RelayoutRequest();
395
396   // Notify derived classes.
397   OnControlChildAdd( child );
398 }
399
400 void ControlImpl::OnChildRemove(Actor& child)
401 {
402   // Request for relayout.
403   RelayoutRequest();
404
405   // Notify derived classes.
406   OnControlChildRemove( child );
407 }
408
409 void ControlImpl::OnSizeSet(const Vector3& targetSize)
410 {
411   if( ( !mImpl->mLockSetSize ) && ( targetSize != mImpl->mSetSize ) )
412   {
413     // Only updates size if set through Actor's API
414     mImpl->mSetSize = targetSize;
415   }
416
417   if( targetSize != mImpl->mSize )
418   {
419     // Update control size.
420     mImpl->mSize = targetSize;
421
422     // Notify derived classes.
423     OnControlSizeSet( targetSize );
424   }
425 }
426
427 void ControlImpl::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
428 {
429   // Do Nothing
430 }
431
432 bool ControlImpl::OnTouchEvent(const TouchEvent& event)
433 {
434   return false; // Do not consume
435 }
436
437 bool ControlImpl::OnKeyEvent(const KeyEvent& event)
438 {
439   return false; // Do not consume
440 }
441
442 bool ControlImpl::OnMouseWheelEvent(const MouseWheelEvent& event)
443 {
444   return false; // Do not consume
445 }
446
447 void ControlImpl::OnKeyInputFocusGained()
448 {
449   // Do Nothing
450 }
451
452 void ControlImpl::OnKeyInputFocusLost()
453 {
454   // Do Nothing
455 }
456
457 Actor ControlImpl::GetChildByAlias(const std::string& actorAlias)
458 {
459   return Actor();
460 }
461
462 bool ControlImpl::OnAccessibilityPan(PanGesture gesture)
463 {
464   return false; // Accessibility pan gesture is not handled by default
465 }
466
467 bool ControlImpl::OnAccessibilityValueChange(bool isIncrease)
468 {
469   return false; // Accessibility value change action is not handled by default
470 }
471
472
473 void ControlImpl::SetKeyboardNavigationSupport(bool isSupported)
474 {
475   mImpl->mIsKeyboardNavigationSupported = isSupported;
476 }
477
478 bool ControlImpl::IsKeyboardNavigationSupported()
479 {
480   return mImpl->mIsKeyboardNavigationSupported;
481 }
482
483 void ControlImpl::SetAsKeyboardFocusGroup(bool isFocusGroup)
484 {
485   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
486
487   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
488   KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
489 }
490
491 bool ControlImpl::IsKeyboardFocusGroup()
492 {
493   return KeyboardFocusManager::Get().IsFocusGroup(Self());
494 }
495
496 Actor ControlImpl::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
497 {
498   return Actor();
499 }
500
501 bool ControlImpl::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
502 {
503   bool ret = false;
504
505   return ret;
506 }
507
508 void ControlImpl::DoActivatedAction(const PropertyValueContainer& attributes)
509 {
510   OnActivated();
511 }
512
513 Toolkit::Control::KeyEventSignalV2& ControlImpl::KeyEventSignal()
514 {
515   return mImpl->mKeyEventSignalV2;
516 }
517
518 void ControlImpl::SetSizePolicy( Control::SizePolicy widthPolicy, Control::SizePolicy heightPolicy )
519 {
520   bool relayoutRequest( false );
521
522   if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
523   {
524     relayoutRequest = true;
525   }
526
527   mImpl->mWidthPolicy = widthPolicy;
528   mImpl->mHeightPolicy = heightPolicy;
529
530   // Ensure RelayoutRequest is called AFTER new policies have been set.
531   if ( relayoutRequest )
532   {
533     RelayoutRequest();
534   }
535 }
536
537 void ControlImpl::GetSizePolicy( Control::SizePolicy& widthPolicy, Control::SizePolicy& heightPolicy ) const
538 {
539   widthPolicy = mImpl->mWidthPolicy;
540   heightPolicy = mImpl->mHeightPolicy;
541 }
542
543 void ControlImpl::SetMinimumSize( const Vector3& size )
544 {
545   if ( mImpl->mMinimumSize != size )
546   {
547     mImpl->mMinimumSize = size;
548
549     // Only relayout if our control is using the minimum or range policy.
550     if ( ( mImpl->mHeightPolicy == Control::Minimum ) || ( mImpl->mWidthPolicy  == Control::Minimum ) ||
551          ( mImpl->mHeightPolicy == Control::Range   ) || ( mImpl->mWidthPolicy  == Control::Range   ) )
552     {
553       RelayoutRequest();
554     }
555   }
556 }
557
558 const Vector3& ControlImpl::GetMinimumSize() const
559 {
560   return mImpl->mMinimumSize;
561 }
562
563 void ControlImpl::SetMaximumSize( const Vector3& size )
564 {
565   if ( mImpl->mMaximumSize != size )
566   {
567     mImpl->mMaximumSize = size;
568
569     // Only relayout if our control is using the maximum or range policy.
570     if ( ( mImpl->mHeightPolicy == Control::Maximum ) || ( mImpl->mWidthPolicy  == Control::Maximum ) ||
571          ( mImpl->mHeightPolicy == Control::Range   ) || ( mImpl->mWidthPolicy  == Control::Range   ) )
572     {
573       RelayoutRequest();
574     }
575   }
576 }
577
578 const Vector3& ControlImpl::GetMaximumSize() const
579 {
580   return mImpl->mMaximumSize;
581 }
582
583 Vector3 ControlImpl::GetNaturalSize()
584 {
585   // could be overridden in derived classes.
586   return mImpl->mSetSize;
587 }
588
589 float ControlImpl::GetHeightForWidth( float width )
590 {
591   // could be overridden in derived classes.
592   float height( 0.0f );
593   if ( mImpl->mSetSize.width > 0.0f )
594   {
595     height = mImpl->mSetSize.height * width / mImpl->mSetSize.width;
596   }
597   return height;
598 }
599
600 float ControlImpl::GetWidthForHeight( float height )
601 {
602   // could be overridden in derived classes.
603   float width( 0.0f );
604   if ( mImpl->mSetSize.height > 0.0f )
605   {
606     width = mImpl->mSetSize.width * height / mImpl->mSetSize.height;
607   }
608   return width;
609 }
610
611 const Vector3& ControlImpl::GetControlSize() const
612 {
613   return mImpl->mSize;
614 }
615
616 const Vector3& ControlImpl::GetSizeSet() const
617 {
618   return mImpl->mSetSize;
619 }
620
621 void ControlImpl::SetKeyInputFocus()
622 {
623   if( Self().OnStage() )
624   {
625     KeyInputFocusManager::Get().SetFocus(Control::DownCast(Self()));
626   }
627 }
628
629 bool ControlImpl::HasKeyInputFocus()
630 {
631   bool result = false;
632   if( Self().OnStage() )
633   {
634     result = KeyInputFocusManager::Get().IsKeyboardListener(Control::DownCast(Self()));
635   }
636   return result;
637 }
638
639 void ControlImpl::ClearKeyInputFocus()
640 {
641   if( Self().OnStage() )
642   {
643     KeyInputFocusManager::Get().RemoveFocus(Control::DownCast(Self()));
644   }
645 }
646
647 void ControlImpl::RelayoutRequest()
648 {
649   Internal::RelayoutController::Get().Request();
650 }
651
652 void ControlImpl::Relayout( Vector2 size, ActorSizeContainer& container )
653 {
654   // Avoids relayout again when OnSizeSet callback arrives.
655   {
656     SetSizeLock lock( mImpl->mLockSetSize );
657     Self().SetSize( size );
658   }
659
660   // Only relayout controls which requested to be relaid out.
661   OnRelaidOut( size, container );
662 }
663
664 void ControlImpl::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
665 {
666   if ( actor )
667   {
668     Control control( Control::DownCast( actor ) );
669     if( control )
670     {
671       control.GetImplementation().NegotiateSize( size, container );
672     }
673     else
674     {
675       container.push_back( ActorSizePair( actor, size ) );
676     }
677   }
678 }
679
680 void ControlImpl::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
681 {
682   unsigned int numChildren = Self().GetChildCount();
683
684   for( unsigned int i=0; i<numChildren; ++i )
685   {
686     container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
687   }
688 }
689
690 void ControlImpl::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
691 {
692   Vector2 size;
693
694   if ( mImpl->mWidthPolicy == Control::Fixed )
695   {
696     if ( mImpl->mHeightPolicy == Control::Fixed )
697     {
698       // If a control says it has a fixed size, then use the size set by the application / control.
699       Vector2 setSize( mImpl->mSetSize );
700       if ( setSize != Vector2::ZERO )
701       {
702         size = setSize;
703
704         // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
705         // then we should use the natural size of the control rather than the full allocation.
706         if ( EqualsZero( size.width ) )
707         {
708           size.width = GetWidthForHeight( size.height );
709         }
710         else if ( EqualsZero( size.height ) )
711         {
712           size.height = GetHeightForWidth( size.width );
713         }
714       }
715       else
716       {
717         // If that is not set then set the size to the control's natural size
718         size = Vector2( GetNaturalSize() );
719       }
720     }
721     else
722     {
723       // Width is fixed so if the application / control has set it, then use that.
724       if ( !EqualsZero( mImpl->mSetSize.width ) )
725       {
726         size.width = mImpl->mSetSize.width;
727       }
728       else
729       {
730         // Otherwise, set the width to what has been allocated.
731         size.width = allocatedSize.width;
732       }
733
734       // Height is flexible so ask control what the height should be for our width.
735       size.height = GetHeightForWidth( size.width );
736
737       // Ensure height is within our policy rules
738       size.height = Calculate( mImpl->mHeightPolicy, mImpl->mMinimumSize.height, mImpl->mMaximumSize.height, size.height );
739     }
740   }
741   else
742   {
743     if ( mImpl->mHeightPolicy == Control::Fixed )
744     {
745       // Height is fixed so if the application / control has set it, then use that.
746       if ( !EqualsZero( mImpl->mSetSize.height ) )
747       {
748         size.height = mImpl->mSetSize.height;
749       }
750       else
751       {
752         // Otherwise, set the height to what has been allocated.
753         size.height = allocatedSize.height;
754       }
755
756       // Width is flexible so ask control what the width should be for our height.
757       size.width = GetWidthForHeight( size.height );
758
759       // Ensure width is within our policy rules
760       size.width = Calculate( mImpl->mWidthPolicy, mImpl->mMinimumSize.width, mImpl->mMaximumSize.width, size.width );
761     }
762     else
763     {
764       // Width and height are BOTH flexible.
765       // Calculate the width and height using the policy rules.
766       size.width = Calculate( mImpl->mWidthPolicy, mImpl->mMinimumSize.width, mImpl->mMaximumSize.width, allocatedSize.width );
767       size.height = Calculate( mImpl->mHeightPolicy, mImpl->mMinimumSize.height, mImpl->mMaximumSize.height, allocatedSize.height );
768     }
769   }
770
771   // If the width has not been set, then set to the allocated width.
772   // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
773   if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
774   {
775     size.width = allocatedSize.width;
776   }
777
778   // If the height has not been set, then set to the allocated height.
779   // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
780   if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
781   {
782     size.height = allocatedSize.height;
783   }
784
785   DALI_LOG_INFO( gLogFilter, Debug::Verbose,
786                  "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
787                  Self().GetObjectPtr(),
788                  GetNaturalSize().x, GetNaturalSize().y,
789                  allocatedSize.x, allocatedSize.y,
790                  size.x, size.y );
791
792   Relayout( size, container );
793 }
794
795 bool ControlImpl::EmitKeyEventSignal( const KeyEvent& event )
796 {
797   // Guard against destruction during signal emission
798   Dali::Toolkit::Control handle( GetOwner() );
799
800   bool consumed = false;
801
802   // signals are allocated dynamically when someone connects
803   if ( !mImpl->mKeyEventSignalV2.Empty() )
804   {
805     consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
806   }
807
808   if (!consumed)
809   {
810     // Notification for derived classes
811     consumed = OnKeyEvent(event);
812   }
813
814   return consumed;
815 }
816
817 void ControlImpl::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
818 {
819   mImpl->SignalConnected( slotObserver, callback );
820 }
821
822 void ControlImpl::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
823 {
824   mImpl->SignalDisconnected( slotObserver, callback );
825 }
826
827 std::size_t ControlImpl::GetConnectionCount() const
828 {
829   return mImpl->GetConnectionCount();
830 }
831
832 ControlImpl::ControlImpl( bool requiresTouchEvents )
833 : CustomActorImpl( requiresTouchEvents ),
834   mImpl(new Impl(*this))
835 {
836 }
837
838 } // namespace Toolkit
839
840 } // namespace Dali