(Control) Added ability to specify a background color/image.
[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 const Property::Index Control::PROPERTY_BACKGROUND_COLOR      = ControlImpl::CONTROL_PROPERTY_START_INDEX;
38 const Property::Index Control::PROPERTY_BACKGROUND            = ControlImpl::CONTROL_PROPERTY_START_INDEX + 1;
39
40 namespace
41 {
42
43 #if defined(DEBUG_ENABLED)
44 Integration::Log::Filter* gLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_CONTROL");
45 #endif
46
47 const float MAX_FLOAT_VALUE( std::numeric_limits<float>::max() );
48 const float BACKGROUND_ACTOR_Z_POSITION( -0.1f );
49
50 BaseHandle Create()
51 {
52   return ControlImpl::New();
53 }
54
55 TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
56
57 // Property Registration after ControlImpl::Impl definition below
58
59 TypeAction ACTION_TYPE_1(CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &ControlImpl::DoAction);
60
61 /**
62  * Helper class used to set the Control's size through the Actor's API or through children added.
63  */
64 class SetSizeLock
65 {
66 public:
67   SetSizeLock( bool& lock )
68   : mLock( lock )
69   {
70     mLock = true;
71   }
72
73   ~SetSizeLock()
74   {
75     mLock = false;
76   }
77
78 private:
79   bool& mLock;
80 };
81
82 /**
83  * Structure which holds information about the background of a control
84  */
85 struct Background
86 {
87   Actor actor;   ///< Either a MeshActor or an ImageActor
88   Vector4 color; ///< The color of the actor.
89
90   /**
91    * Constructor
92    */
93   Background()
94   : actor(),
95     color( Color::WHITE )
96   {
97   }
98 };
99
100 /**
101  * Helper function to calculate a dimension given the policy of that dimension; the minimum &
102  * maximum values that dimension can be; and the allocated value for that dimension.
103  *
104  * @param[in]  policy     The size policy for that dimension.
105  * @param[in]  minimum    The minimum value that dimension can be.
106  * @param[in]  maximum    The maximum value that dimension can be.
107  * @param[in]  allocated  The value allocated for that dimension.
108  *
109  * @return The value that the dimension should be.
110  *
111  * @note This does not handle Control::Fixed policy.
112  */
113 float Calculate( Control::SizePolicy policy, float minimum, float maximum, float allocated )
114 {
115   float size( allocated );
116
117   switch( policy )
118   {
119     case Control::Fixed:
120     {
121       // Use allocated value
122       break;
123     }
124
125     case Control::Minimum:
126     {
127       // Size is always at least the minimum.
128       size = std::max( allocated, minimum );
129       break;
130     }
131
132     case Control::Maximum:
133     {
134       // Size can grow but up to a maximum value.
135       size = std::min( allocated, maximum );
136       break;
137     }
138
139     case Control::Range:
140     {
141       // Size is at least the minimum and can grow up to the maximum
142       size = std::max( size, minimum );
143       size = std::min( size, maximum );
144      break;
145     }
146
147     case Control::Flexible:
148     {
149       // Size grows or shrinks with no limits.
150       size = allocated;
151       break;
152     }
153
154     default:
155     {
156       DALI_ASSERT_DEBUG( false && "This function was not intended to be used by any other policy." );
157       break;
158     }
159   }
160
161   return size;
162 }
163
164 /**
165  * Creates a white coloured Mesh.
166  */
167 Mesh CreateMesh()
168 {
169   Vector3 white( Color::WHITE );
170
171   MeshData meshData;
172
173   // Create vertices with a white color (actual color is set by actor color)
174   MeshData::VertexContainer vertices(4);
175   vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
176   vertices[ 1 ] = MeshData::Vertex( Vector3(  0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
177   vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f,  0.5f, 0.0f ), Vector2::ZERO, white );
178   vertices[ 3 ] = MeshData::Vertex( Vector3(  0.5f,  0.5f, 0.0f ), Vector2::ZERO, white );
179
180   // Specify all the faces
181   MeshData::FaceIndices faces;
182   faces.reserve( 6 ); // 2 triangles in Quad
183   faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
184   faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
185
186   // Create the mesh data from the vertices and faces
187   meshData.SetMaterial( Material::New( "ControlMaterial" ) );
188   meshData.SetVertices( vertices );
189   meshData.SetFaceIndices( faces );
190   meshData.SetHasColor( true );
191
192   return Mesh::New( meshData );
193 }
194
195 /**
196  * Sets all the required properties for the background actor.
197  *
198  * @param[in]  actor              The actor to set the properties on.
199  * @param[in]  constrainingIndex  The property index to constrain the parent's size on.
200  * @param[in]  color              The required color of the actor.
201  */
202 void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const Vector4& color )
203 {
204   actor.SetColor( color );
205   actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
206   actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
207
208   Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
209                                                     ParentSource( Actor::SIZE ),
210                                                     EqualToConstraint() );
211   actor.ApplyConstraint( constraint );
212 }
213
214 } // unnamed namespace
215
216 class ControlImpl::Impl : public ConnectionTrackerInterface
217 {
218 public:
219   // Construction & Destruction
220   Impl(ControlImpl& controlImpl)
221   : mControlImpl(controlImpl),
222     mInitialized( false ),
223     mPinchGestureDetector(),
224     mPanGestureDetector(),
225     mTapGestureDetector(),
226     mLongPressGestureDetector(),
227     mStartingPinchScale(),
228     mLockSetSize( false ),
229     mWidthPolicy( Control::Fixed ),
230     mHeightPolicy( Control::Fixed ),
231     mSize(),
232     mSetSize(),
233     mMinimumSize(),
234     mMaximumSize( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE ),
235     mIsKeyboardNavigationSupported(false),
236     mIsKeyboardFocusGroup(false),
237     mKeyEventSignalV2(),
238     mBackground( NULL )
239   {
240   }
241
242   ~Impl()
243   {
244     // All gesture detectors will be destroyed so no need to disconnect.
245     if ( mBackground )
246     {
247       delete mBackground;
248     }
249   }
250
251   // Gesture Detection Methods
252
253   void PinchDetected(Actor actor, PinchGesture pinch)
254   {
255     mControlImpl.OnPinch(pinch);
256   }
257
258   void PanDetected(Actor actor, PanGesture pan)
259   {
260     mControlImpl.OnPan(pan);
261   }
262
263   void TapDetected(Actor actor, TapGesture tap)
264   {
265     mControlImpl.OnTap(tap);
266   }
267
268   void LongPressDetected(Actor actor, LongPressGesture longPress)
269   {
270     mControlImpl.OnLongPress(longPress);
271   }
272
273   /**
274    * @copydoc ConnectionTrackerInterface::SignalConnected
275    */
276   virtual void SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
277   {
278     mConnectionTracker.SignalConnected( slotObserver, callback );
279   }
280
281   /**
282    * @copydoc ConnectionTrackerInterface::SignalDisconnected
283    */
284   virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
285   {
286     mConnectionTracker.SignalDisconnected( slotObserver, callback );
287   }
288
289   /**
290    * @copydoc ConnectionTrackerInterface::GetConnectionCount
291    */
292   virtual std::size_t GetConnectionCount() const
293   {
294     return mConnectionTracker.GetConnectionCount();
295   }
296
297   // Background Methods
298
299   /**
300    * Only creates an instance of the background if we actually use it.
301    * @return A reference to the Background structure.
302    */
303   Background& GetBackground()
304   {
305     if ( !mBackground )
306     {
307       mBackground = new Background;
308     }
309     return *mBackground;
310   }
311
312   // Properties
313
314   /**
315    * Called when a property of an object of this type is set.
316    * @param[in] object The object whose property is set.
317    * @param[in] index The property index.
318    * @param[in] value The new property value.
319    */
320   static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
321   {
322     Control control = Control::DownCast( BaseHandle( object ) );
323
324     if ( control )
325     {
326       ControlImpl& controlImpl( control.GetImplementation() );
327
328       switch ( index )
329       {
330         case Control::PROPERTY_BACKGROUND_COLOR:
331         {
332           controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
333           break;
334         }
335
336         case Control::PROPERTY_BACKGROUND:
337         {
338           if ( value.HasKey( "image" ) )
339           {
340             Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
341             Image image = Scripting::NewImage( imageMap );
342
343             if ( image )
344             {
345               controlImpl.SetBackground( image );
346             }
347           }
348           else if ( value.Get< Property::Map >().empty() )
349           {
350             // An empty map means the background is no longer required
351             controlImpl.ClearBackground();
352           }
353           break;
354         }
355       }
356     }
357   }
358
359   /**
360    * Called to retrieve a property of an object of this type.
361    * @param[in] object The object whose property is to be retrieved.
362    * @param[in] index The property index.
363    * @return The current value of the property.
364    */
365   static Property::Value GetProperty( BaseObject* object, Property::Index index )
366   {
367     Property::Value value;
368
369     Control control = Control::DownCast( BaseHandle( object ) );
370
371     if ( control )
372     {
373       ControlImpl& controlImpl( control.GetImplementation() );
374
375       switch ( index )
376       {
377         case Control::PROPERTY_BACKGROUND_COLOR:
378         {
379           value = controlImpl.GetBackgroundColor();
380           break;
381         }
382
383         case Control::PROPERTY_BACKGROUND:
384         {
385           Property::Map map;
386
387           Actor actor = controlImpl.GetBackgroundActor();
388           if ( actor )
389           {
390             ImageActor imageActor = ImageActor::DownCast( actor );
391             if ( imageActor )
392             {
393               Image image = imageActor.GetImage();
394               Property::Map imageMap;
395               Scripting::CreatePropertyMap( image, imageMap );
396               map.push_back( Property::StringValuePair( "image", imageMap ) );
397             }
398           }
399
400           value = map;
401           break;
402         }
403
404       }
405     }
406
407     return value;
408   }
409
410   // Data
411
412   ControlImpl& mControlImpl;
413
414   bool mInitialized:1;
415
416   ConnectionTracker mConnectionTracker; // signal connection tracker
417
418   // Gesture Detection
419
420   PinchGestureDetector     mPinchGestureDetector;
421   PanGestureDetector       mPanGestureDetector;
422   TapGestureDetector       mTapGestureDetector;
423   LongPressGestureDetector mLongPressGestureDetector;
424
425   Vector3 mStartingPinchScale;       ///< The scale when a pinch gesture starts
426
427   // Relayout and size negotiation
428
429   bool mLockSetSize;                 ///< Used to avoid. Can't be a bitfield as a reference to this member is used in SetSizeLock helper class.
430
431   Control::SizePolicy mWidthPolicy;  ///< Stores the width policy.
432   Control::SizePolicy mHeightPolicy; ///< Stores the height policy.
433
434   Vector3 mSize;                     ///< Stores the current control's size.
435   Vector3 mSetSize;                  ///< Always stores the size set through the Actor's API. Useful when reset to the initial size is needed.
436   Vector3 mMinimumSize;              ///< Stores the control's minimum size.
437   Vector3 mMaximumSize;              ///< Stores the control's maximum size.
438
439   bool mIsKeyboardNavigationSupported;  ///< Stores whether keyboard navigation is supported by the control.
440   bool mIsKeyboardFocusGroup;        ///< Stores whether the control is a focus group.
441
442   Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
443
444   // Background
445   Background* mBackground;           ///< Only create the background if we use it
446
447   // Properties - need to be part of this class as ControlImpl::Impl is private
448   static PropertyRegistration PROPERTY_1;
449   static PropertyRegistration PROPERTY_2;
450 };
451
452 PropertyRegistration ControlImpl::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &ControlImpl::Impl::SetProperty, &ControlImpl::Impl::GetProperty );
453 PropertyRegistration ControlImpl::Impl::PROPERTY_2( CONTROL_TYPE, "background",       Control::PROPERTY_BACKGROUND,       Property::MAP,     &ControlImpl::Impl::SetProperty, &ControlImpl::Impl::GetProperty );
454
455 Control ControlImpl::New()
456 {
457   // Create the implementation, temporarily owned on stack
458   IntrusivePtr<ControlImpl> controlImpl = new ControlImpl( false );
459
460   // Pass ownership to handle
461   Control handle( *controlImpl );
462
463   // Second-phase init of the implementation
464   // This can only be done after the CustomActor connection has been made...
465   controlImpl->Initialize();
466
467   return handle;
468 }
469
470 ControlImpl::~ControlImpl()
471 {
472   if( mImpl->mInitialized )
473   {
474     // Unregister only if control has been initialized.
475     Internal::StyleChangeProcessor::Unregister( this );
476   }
477   delete mImpl;
478 }
479
480 void ControlImpl::Initialize()
481 {
482   // Register with the style change processor so we are informed when the default style changes
483   Internal::StyleChangeProcessor::Register( this );
484
485   // Calling deriving classes
486   OnInitialize();
487
488   mImpl->mInitialized = true;
489 }
490
491 void ControlImpl::EnableGestureDetection(Gesture::Type type)
492 {
493   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
494   {
495     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
496     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
497     mImpl->mPinchGestureDetector.Attach(Self());
498   }
499
500   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
501   {
502     mImpl->mPanGestureDetector = PanGestureDetector::New();
503     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
504     mImpl->mPanGestureDetector.Attach(Self());
505   }
506
507   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
508   {
509     mImpl->mTapGestureDetector = TapGestureDetector::New();
510     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
511     mImpl->mTapGestureDetector.Attach(Self());
512   }
513
514   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
515   {
516     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
517     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
518     mImpl->mLongPressGestureDetector.Attach(Self());
519   }
520 }
521
522 void ControlImpl::DisableGestureDetection(Gesture::Type type)
523 {
524   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
525   {
526     mImpl->mPinchGestureDetector.Detach(Self());
527     mImpl->mPinchGestureDetector.Reset();
528   }
529
530   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
531   {
532     mImpl->mPanGestureDetector.Detach(Self());
533     mImpl->mPanGestureDetector.Reset();
534   }
535
536   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
537   {
538     mImpl->mTapGestureDetector.Detach(Self());
539     mImpl->mTapGestureDetector.Reset();
540   }
541
542   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
543   {
544     mImpl->mLongPressGestureDetector.Detach(Self());
545     mImpl->mLongPressGestureDetector.Reset();
546   }
547 }
548
549 PinchGestureDetector ControlImpl::GetPinchGestureDetector() const
550 {
551   return mImpl->mPinchGestureDetector;
552 }
553
554 PanGestureDetector ControlImpl::GetPanGestureDetector() const
555 {
556   return mImpl->mPanGestureDetector;
557 }
558
559 TapGestureDetector ControlImpl::GetTapGestureDetector() const
560 {
561   return mImpl->mTapGestureDetector;
562 }
563
564 LongPressGestureDetector ControlImpl::GetLongPressGestureDetector() const
565 {
566   return mImpl->mLongPressGestureDetector;
567 }
568
569 void ControlImpl::SetBackgroundColor( const Vector4& color )
570 {
571   Background& background( mImpl->GetBackground() );
572
573   if ( background.actor )
574   {
575     // Just set the actor color
576     background.actor.SetColor( color );
577   }
578   else
579   {
580     // Create Mesh Actor
581     MeshActor meshActor = MeshActor::New( CreateMesh() );
582
583     meshActor.SetAffectedByLighting( false );
584     SetupBackgroundActor( meshActor, Actor::SCALE, color );
585
586     // Set the background actor before adding so that we do not inform deriving classes
587     background.actor = meshActor;
588     Self().Add( meshActor );
589   }
590
591   background.color = color;
592 }
593
594 Vector4 ControlImpl::GetBackgroundColor() const
595 {
596   if ( mImpl->mBackground )
597   {
598     return mImpl->mBackground->color;
599   }
600   return Color::TRANSPARENT;
601 }
602
603 void ControlImpl::SetBackground( Image image )
604 {
605   Background& background( mImpl->GetBackground() );
606
607   if ( background.actor )
608   {
609     // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
610     Self().Remove( background.actor );
611     background.actor = NULL;
612   }
613
614   ImageActor imageActor = ImageActor::New( image );
615   SetupBackgroundActor( imageActor, Actor::SIZE, background.color );
616
617   // Set the background actor before adding so that we do not inform derived classes
618   background.actor = imageActor;
619   Self().Add( imageActor );
620 }
621
622 void ControlImpl::ClearBackground()
623 {
624   if ( mImpl->mBackground )
625   {
626     Background& background( mImpl->GetBackground() );
627     Self().Remove( background.actor );
628
629     delete mImpl->mBackground;
630     mImpl->mBackground = NULL;
631   }
632 }
633
634 Actor ControlImpl::GetBackgroundActor() const
635 {
636   if ( mImpl->mBackground )
637   {
638     return mImpl->mBackground->actor;
639   }
640
641   return Actor();
642 }
643
644 void ControlImpl::OnPinch(PinchGesture pinch)
645 {
646   if (pinch.state == Gesture::Started)
647   {
648     mImpl->mStartingPinchScale = Self().GetCurrentScale();
649   }
650
651   Self().SetScale(mImpl->mStartingPinchScale * pinch.scale);
652 }
653
654 void ControlImpl::OnStageConnection()
655 {
656   RelayoutRequest();
657
658   // Notify derived classes.
659   OnControlStageConnection();
660 }
661
662 void ControlImpl::OnStageDisconnection()
663 {
664   // Notify derived classes
665   OnControlStageDisconnection();
666 }
667
668 void ControlImpl::OnChildAdd(Actor& child)
669 {
670   // If this is the background actor, then we do not want to relayout or inform deriving classes
671   if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
672   {
673     return;
674   }
675
676   // Request for relayout.
677   RelayoutRequest();
678
679   // Notify derived classes.
680   OnControlChildAdd( child );
681 }
682
683 void ControlImpl::OnChildRemove(Actor& child)
684 {
685   // If this is the background actor, then we do not want to relayout or inform deriving classes
686   if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
687   {
688     return;
689   }
690
691   // Request for relayout.
692   RelayoutRequest();
693
694   // Notify derived classes.
695   OnControlChildRemove( child );
696 }
697
698 void ControlImpl::OnSizeSet(const Vector3& targetSize)
699 {
700   if( ( !mImpl->mLockSetSize ) && ( targetSize != mImpl->mSetSize ) )
701   {
702     // Only updates size if set through Actor's API
703     mImpl->mSetSize = targetSize;
704   }
705
706   if( targetSize != mImpl->mSize )
707   {
708     // Update control size.
709     mImpl->mSize = targetSize;
710
711     // Notify derived classes.
712     OnControlSizeSet( targetSize );
713   }
714 }
715
716 void ControlImpl::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
717 {
718   // Do Nothing
719 }
720
721 bool ControlImpl::OnTouchEvent(const TouchEvent& event)
722 {
723   return false; // Do not consume
724 }
725
726 bool ControlImpl::OnKeyEvent(const KeyEvent& event)
727 {
728   return false; // Do not consume
729 }
730
731 bool ControlImpl::OnMouseWheelEvent(const MouseWheelEvent& event)
732 {
733   return false; // Do not consume
734 }
735
736 void ControlImpl::OnKeyInputFocusGained()
737 {
738   // Do Nothing
739 }
740
741 void ControlImpl::OnKeyInputFocusLost()
742 {
743   // Do Nothing
744 }
745
746 Actor ControlImpl::GetChildByAlias(const std::string& actorAlias)
747 {
748   return Actor();
749 }
750
751 bool ControlImpl::OnAccessibilityPan(PanGesture gesture)
752 {
753   return false; // Accessibility pan gesture is not handled by default
754 }
755
756 bool ControlImpl::OnAccessibilityValueChange(bool isIncrease)
757 {
758   return false; // Accessibility value change action is not handled by default
759 }
760
761
762 void ControlImpl::SetKeyboardNavigationSupport(bool isSupported)
763 {
764   mImpl->mIsKeyboardNavigationSupported = isSupported;
765 }
766
767 bool ControlImpl::IsKeyboardNavigationSupported()
768 {
769   return mImpl->mIsKeyboardNavigationSupported;
770 }
771
772 void ControlImpl::SetAsKeyboardFocusGroup(bool isFocusGroup)
773 {
774   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
775
776   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
777   KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
778 }
779
780 bool ControlImpl::IsKeyboardFocusGroup()
781 {
782   return KeyboardFocusManager::Get().IsFocusGroup(Self());
783 }
784
785 Actor ControlImpl::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
786 {
787   return Actor();
788 }
789
790 bool ControlImpl::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
791 {
792   bool ret = false;
793
794   return ret;
795 }
796
797 void ControlImpl::DoActivatedAction(const PropertyValueContainer& attributes)
798 {
799   OnActivated();
800 }
801
802 Toolkit::Control::KeyEventSignalV2& ControlImpl::KeyEventSignal()
803 {
804   return mImpl->mKeyEventSignalV2;
805 }
806
807 void ControlImpl::SetSizePolicy( Control::SizePolicy widthPolicy, Control::SizePolicy heightPolicy )
808 {
809   bool relayoutRequest( false );
810
811   if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
812   {
813     relayoutRequest = true;
814   }
815
816   mImpl->mWidthPolicy = widthPolicy;
817   mImpl->mHeightPolicy = heightPolicy;
818
819   // Ensure RelayoutRequest is called AFTER new policies have been set.
820   if ( relayoutRequest )
821   {
822     RelayoutRequest();
823   }
824 }
825
826 void ControlImpl::GetSizePolicy( Control::SizePolicy& widthPolicy, Control::SizePolicy& heightPolicy ) const
827 {
828   widthPolicy = mImpl->mWidthPolicy;
829   heightPolicy = mImpl->mHeightPolicy;
830 }
831
832 void ControlImpl::SetMinimumSize( const Vector3& size )
833 {
834   if ( mImpl->mMinimumSize != size )
835   {
836     mImpl->mMinimumSize = size;
837
838     // Only relayout if our control is using the minimum or range policy.
839     if ( ( mImpl->mHeightPolicy == Control::Minimum ) || ( mImpl->mWidthPolicy  == Control::Minimum ) ||
840          ( mImpl->mHeightPolicy == Control::Range   ) || ( mImpl->mWidthPolicy  == Control::Range   ) )
841     {
842       RelayoutRequest();
843     }
844   }
845 }
846
847 const Vector3& ControlImpl::GetMinimumSize() const
848 {
849   return mImpl->mMinimumSize;
850 }
851
852 void ControlImpl::SetMaximumSize( const Vector3& size )
853 {
854   if ( mImpl->mMaximumSize != size )
855   {
856     mImpl->mMaximumSize = size;
857
858     // Only relayout if our control is using the maximum or range policy.
859     if ( ( mImpl->mHeightPolicy == Control::Maximum ) || ( mImpl->mWidthPolicy  == Control::Maximum ) ||
860          ( mImpl->mHeightPolicy == Control::Range   ) || ( mImpl->mWidthPolicy  == Control::Range   ) )
861     {
862       RelayoutRequest();
863     }
864   }
865 }
866
867 const Vector3& ControlImpl::GetMaximumSize() const
868 {
869   return mImpl->mMaximumSize;
870 }
871
872 Vector3 ControlImpl::GetNaturalSize()
873 {
874   // could be overridden in derived classes.
875   return mImpl->mSetSize;
876 }
877
878 float ControlImpl::GetHeightForWidth( float width )
879 {
880   // could be overridden in derived classes.
881   float height( 0.0f );
882   if ( mImpl->mSetSize.width > 0.0f )
883   {
884     height = mImpl->mSetSize.height * width / mImpl->mSetSize.width;
885   }
886   return height;
887 }
888
889 float ControlImpl::GetWidthForHeight( float height )
890 {
891   // could be overridden in derived classes.
892   float width( 0.0f );
893   if ( mImpl->mSetSize.height > 0.0f )
894   {
895     width = mImpl->mSetSize.width * height / mImpl->mSetSize.height;
896   }
897   return width;
898 }
899
900 const Vector3& ControlImpl::GetControlSize() const
901 {
902   return mImpl->mSize;
903 }
904
905 const Vector3& ControlImpl::GetSizeSet() const
906 {
907   return mImpl->mSetSize;
908 }
909
910 void ControlImpl::SetKeyInputFocus()
911 {
912   if( Self().OnStage() )
913   {
914     KeyInputFocusManager::Get().SetFocus(Control::DownCast(Self()));
915   }
916 }
917
918 bool ControlImpl::HasKeyInputFocus()
919 {
920   bool result = false;
921   if( Self().OnStage() )
922   {
923     result = KeyInputFocusManager::Get().IsKeyboardListener(Control::DownCast(Self()));
924   }
925   return result;
926 }
927
928 void ControlImpl::ClearKeyInputFocus()
929 {
930   if( Self().OnStage() )
931   {
932     KeyInputFocusManager::Get().RemoveFocus(Control::DownCast(Self()));
933   }
934 }
935
936 void ControlImpl::RelayoutRequest()
937 {
938   Internal::RelayoutController::Get().Request();
939 }
940
941 void ControlImpl::Relayout( Vector2 size, ActorSizeContainer& container )
942 {
943   // Avoids relayout again when OnSizeSet callback arrives.
944   {
945     SetSizeLock lock( mImpl->mLockSetSize );
946     Self().SetSize( size );
947   }
948
949   // Only relayout controls which requested to be relaid out.
950   OnRelaidOut( size, container );
951 }
952
953 void ControlImpl::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
954 {
955   if ( actor )
956   {
957     Control control( Control::DownCast( actor ) );
958     if( control )
959     {
960       control.GetImplementation().NegotiateSize( size, container );
961     }
962     else
963     {
964       container.push_back( ActorSizePair( actor, size ) );
965     }
966   }
967 }
968
969 void ControlImpl::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
970 {
971   unsigned int numChildren = Self().GetChildCount();
972
973   for( unsigned int i=0; i<numChildren; ++i )
974   {
975     container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
976   }
977 }
978
979 void ControlImpl::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
980 {
981   Vector2 size;
982
983   if ( mImpl->mWidthPolicy == Control::Fixed )
984   {
985     if ( mImpl->mHeightPolicy == Control::Fixed )
986     {
987       // If a control says it has a fixed size, then use the size set by the application / control.
988       Vector2 setSize( mImpl->mSetSize );
989       if ( setSize != Vector2::ZERO )
990       {
991         size = setSize;
992
993         // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
994         // then we should use the natural size of the control rather than the full allocation.
995         if ( EqualsZero( size.width ) )
996         {
997           size.width = GetWidthForHeight( size.height );
998         }
999         else if ( EqualsZero( size.height ) )
1000         {
1001           size.height = GetHeightForWidth( size.width );
1002         }
1003       }
1004       else
1005       {
1006         // If that is not set then set the size to the control's natural size
1007         size = Vector2( GetNaturalSize() );
1008       }
1009     }
1010     else
1011     {
1012       // Width is fixed so if the application / control has set it, then use that.
1013       if ( !EqualsZero( mImpl->mSetSize.width ) )
1014       {
1015         size.width = mImpl->mSetSize.width;
1016       }
1017       else
1018       {
1019         // Otherwise, set the width to what has been allocated.
1020         size.width = allocatedSize.width;
1021       }
1022
1023       // Height is flexible so ask control what the height should be for our width.
1024       size.height = GetHeightForWidth( size.width );
1025
1026       // Ensure height is within our policy rules
1027       size.height = Calculate( mImpl->mHeightPolicy, mImpl->mMinimumSize.height, mImpl->mMaximumSize.height, size.height );
1028     }
1029   }
1030   else
1031   {
1032     if ( mImpl->mHeightPolicy == Control::Fixed )
1033     {
1034       // Height is fixed so if the application / control has set it, then use that.
1035       if ( !EqualsZero( mImpl->mSetSize.height ) )
1036       {
1037         size.height = mImpl->mSetSize.height;
1038       }
1039       else
1040       {
1041         // Otherwise, set the height to what has been allocated.
1042         size.height = allocatedSize.height;
1043       }
1044
1045       // Width is flexible so ask control what the width should be for our height.
1046       size.width = GetWidthForHeight( size.height );
1047
1048       // Ensure width is within our policy rules
1049       size.width = Calculate( mImpl->mWidthPolicy, mImpl->mMinimumSize.width, mImpl->mMaximumSize.width, size.width );
1050     }
1051     else
1052     {
1053       // Width and height are BOTH flexible.
1054       // Calculate the width and height using the policy rules.
1055       size.width = Calculate( mImpl->mWidthPolicy, mImpl->mMinimumSize.width, mImpl->mMaximumSize.width, allocatedSize.width );
1056       size.height = Calculate( mImpl->mHeightPolicy, mImpl->mMinimumSize.height, mImpl->mMaximumSize.height, allocatedSize.height );
1057     }
1058   }
1059
1060   // If the width has not been set, then set to the allocated width.
1061   // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
1062   if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
1063   {
1064     size.width = allocatedSize.width;
1065   }
1066
1067   // If the height has not been set, then set to the allocated height.
1068   // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
1069   if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
1070   {
1071     size.height = allocatedSize.height;
1072   }
1073
1074   DALI_LOG_INFO( gLogFilter, Debug::Verbose,
1075                  "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
1076                  Self().GetObjectPtr(),
1077                  GetNaturalSize().x, GetNaturalSize().y,
1078                  allocatedSize.x, allocatedSize.y,
1079                  size.x, size.y );
1080
1081   Relayout( size, container );
1082 }
1083
1084 bool ControlImpl::EmitKeyEventSignal( const KeyEvent& event )
1085 {
1086   // Guard against destruction during signal emission
1087   Dali::Toolkit::Control handle( GetOwner() );
1088
1089   bool consumed = false;
1090
1091   // signals are allocated dynamically when someone connects
1092   if ( !mImpl->mKeyEventSignalV2.Empty() )
1093   {
1094     consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1095   }
1096
1097   if (!consumed)
1098   {
1099     // Notification for derived classes
1100     consumed = OnKeyEvent(event);
1101   }
1102
1103   return consumed;
1104 }
1105
1106 void ControlImpl::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1107 {
1108   mImpl->SignalConnected( slotObserver, callback );
1109 }
1110
1111 void ControlImpl::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1112 {
1113   mImpl->SignalDisconnected( slotObserver, callback );
1114 }
1115
1116 std::size_t ControlImpl::GetConnectionCount() const
1117 {
1118   return mImpl->GetConnectionCount();
1119 }
1120
1121 ControlImpl::ControlImpl( bool requiresTouchEvents )
1122 : CustomActorImpl( requiresTouchEvents ),
1123   mImpl(new Impl(*this))
1124 {
1125 }
1126
1127 } // namespace Toolkit
1128
1129 } // namespace Dali