2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/public-api/actors/image-actor.h>
24 #include <dali/public-api/actors/mesh-actor.h>
25 #include <dali/public-api/animation/constraints.h>
26 #include <dali/public-api/geometry/mesh.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/scripting/scripting.h>
29 #include <dali/integration-api/debug.h>
31 #include <dali-toolkit/internal/controls/relayout-controller.h>
32 #include <dali-toolkit/internal/controls/relayout-helper.h>
33 #include <dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h>
34 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
35 #include <dali-toolkit/public-api/controls/control.h>
36 #include <dali-toolkit/public-api/styling/style-manager.h>
37 #include <dali-toolkit/internal/styling/style-manager-impl.h>
45 const Property::Index Control::PROPERTY_BACKGROUND_COLOR = Internal::Control::CONTROL_PROPERTY_START_INDEX;
46 const Property::Index Control::PROPERTY_BACKGROUND = Internal::Control::CONTROL_PROPERTY_START_INDEX + 1;
47 const Property::Index Control::PROPERTY_WIDTH_POLICY = Internal::Control::CONTROL_PROPERTY_START_INDEX + 2;
48 const Property::Index Control::PROPERTY_HEIGHT_POLICY = Internal::Control::CONTROL_PROPERTY_START_INDEX + 3;
49 const Property::Index Control::PROPERTY_MINIMUM_SIZE = Internal::Control::CONTROL_PROPERTY_START_INDEX + 4;
50 const Property::Index Control::PROPERTY_MAXIMUM_SIZE = Internal::Control::CONTROL_PROPERTY_START_INDEX + 5;
51 const Property::Index Control::PROPERTY_KEY_INPUT_FOCUS = Internal::Control::CONTROL_PROPERTY_START_INDEX + 6;
56 const Scripting::StringEnum< Control::SizePolicy > SIZE_POLICY_STRING_TABLE[] =
58 { "FIXED", Control::Fixed },
59 { "MINIMUM", Control::Minimum },
60 { "MAXIMUM", Control::Maximum },
61 { "RANGE", Control::Range },
62 { "FLEXIBLE", Control::Flexible },
64 const unsigned int SIZE_POLICY_STRING_TABLE_COUNT = sizeof( SIZE_POLICY_STRING_TABLE ) / sizeof( SIZE_POLICY_STRING_TABLE[0] );
66 #if defined(DEBUG_ENABLED)
67 Integration::Log::Filter* gLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_CONTROL");
70 const float MAX_FLOAT_VALUE( std::numeric_limits<float>::max() );
71 const Vector3 MAX_SIZE( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE );
72 const float BACKGROUND_ACTOR_Z_POSITION( -0.1f );
76 return Internal::Control::New();
79 TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
81 // Property Registration after Internal::Control::Impl definition below
83 TypeAction ACTION_TYPE_1( CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &Internal::Control::DoAction );
85 SignalConnectorType SIGNAL_CONNECTOR_1( CONTROL_TYPE, Toolkit::Control::SIGNAL_KEY_EVENT, &Internal::Control::DoConnectSignal );
86 SignalConnectorType SIGNAL_CONNECTOR_2( CONTROL_TYPE, Toolkit::Control::SIGNAL_TAPPED, &Internal::Control::DoConnectSignal );
87 SignalConnectorType SIGNAL_CONNECTOR_3( CONTROL_TYPE, Toolkit::Control::SIGNAL_PANNED, &Internal::Control::DoConnectSignal );
88 SignalConnectorType SIGNAL_CONNECTOR_4( CONTROL_TYPE, Toolkit::Control::SIGNAL_PINCHED, &Internal::Control::DoConnectSignal );
89 SignalConnectorType SIGNAL_CONNECTOR_5( CONTROL_TYPE, Toolkit::Control::SIGNAL_LONG_PRESSED, &Internal::Control::DoConnectSignal );
92 * Structure which holds information about the background of a control
96 Actor actor; ///< Either a MeshActor or an ImageActor
97 Vector4 color; ///< The color of the actor.
104 color( Color::WHITE )
110 * Helper function to calculate a dimension given the policy of that dimension; the minimum &
111 * maximum values that dimension can be; and the allocated value for that dimension.
113 * @param[in] policy The size policy for that dimension.
114 * @param[in] minimum The minimum value that dimension can be.
115 * @param[in] maximum The maximum value that dimension can be.
116 * @param[in] allocated The value allocated for that dimension.
118 * @return The value that the dimension should be.
120 * @note This does not handle Control::Fixed policy.
122 float Calculate( Control::SizePolicy policy, float minimum, float maximum, float allocated )
124 float size( allocated );
130 // Use allocated value
134 case Control::Minimum:
136 // Size is always at least the minimum.
137 size = std::max( allocated, minimum );
141 case Control::Maximum:
143 // Size can grow but up to a maximum value.
144 size = std::min( allocated, maximum );
150 // Size is at least the minimum and can grow up to the maximum
151 size = std::max( size, minimum );
152 size = std::min( size, maximum );
156 case Control::Flexible:
158 // Size grows or shrinks with no limits.
165 DALI_ASSERT_DEBUG( false && "This function was not intended to be used by any other policy." );
174 * Creates a white coloured Mesh.
178 Vector3 white( Color::WHITE );
182 // Create vertices with a white color (actual color is set by actor color)
183 MeshData::VertexContainer vertices(4);
184 vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
185 vertices[ 1 ] = MeshData::Vertex( Vector3( 0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
186 vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
187 vertices[ 3 ] = MeshData::Vertex( Vector3( 0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
189 // Specify all the faces
190 MeshData::FaceIndices faces;
191 faces.reserve( 6 ); // 2 triangles in Quad
192 faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
193 faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
195 // Create the mesh data from the vertices and faces
196 meshData.SetMaterial( Material::New( "ControlMaterial" ) );
197 meshData.SetVertices( vertices );
198 meshData.SetFaceIndices( faces );
199 meshData.SetHasColor( true );
201 return Mesh::New( meshData );
205 * Sets all the required properties for the background actor.
207 * @param[in] actor The actor to set the properties on.
208 * @param[in] constrainingIndex The property index to constrain the parent's size on.
209 * @param[in] color The required color of the actor.
211 void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const Vector4& color )
213 actor.SetColor( color );
214 actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
215 actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
216 actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
218 Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
219 ParentSource( Actor::SIZE ),
220 EqualToConstraint() );
221 actor.ApplyConstraint( constraint );
224 } // unnamed namespace
229 class Control::Impl : public ConnectionTracker
234 * Size indices for mMinMaxSize array
243 // Construction & Destruction
244 Impl(Control& controlImpl)
245 : mControlImpl( controlImpl ),
247 mStartingPinchScale( NULL ),
249 mPinchGestureDetector(),
250 mPanGestureDetector(),
251 mTapGestureDetector(),
252 mLongPressGestureDetector(),
255 mWidthPolicy( Toolkit::Control::Fixed ),
256 mHeightPolicy( Toolkit::Control::Fixed ),
257 mFlags( Control::CONTROL_BEHAVIOUR_NONE ),
258 mInsideRelayout( false ),
259 mIsKeyboardNavigationSupported( false ),
260 mIsKeyboardFocusGroup( false ),
261 mInitialized( false )
267 // All gesture detectors will be destroyed so no need to disconnect.
269 delete mStartingPinchScale;
272 // Gesture Detection Methods
274 void PinchDetected(Actor actor, const PinchGesture& pinch)
276 mControlImpl.OnPinch(pinch);
279 void PanDetected(Actor actor, const PanGesture& pan)
281 mControlImpl.OnPan(pan);
284 void TapDetected(Actor actor, const TapGesture& tap)
286 mControlImpl.OnTap(tap);
289 void LongPressDetected(Actor actor, const LongPressGesture& longPress)
291 mControlImpl.OnLongPress(longPress);
294 // Background Methods
297 * Only creates an instance of the background if we actually use it.
298 * @return A reference to the Background structure.
300 Background& GetBackground()
304 mBackground = new Background;
312 * Called when a property of an object of this type is set.
313 * @param[in] object The object whose property is set.
314 * @param[in] index The property index.
315 * @param[in] value The new property value.
317 static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
319 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
323 Control& controlImpl( control.GetImplementation() );
327 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
329 controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
333 case Toolkit::Control::PROPERTY_BACKGROUND:
335 if ( value.HasKey( "image" ) )
337 Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
338 Image image = Scripting::NewImage( imageMap );
342 controlImpl.SetBackground( image );
345 else if ( value.Get< Property::Map >().Empty() )
347 // An empty map means the background is no longer required
348 controlImpl.ClearBackground();
353 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
355 controlImpl.mImpl->mWidthPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
359 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
361 controlImpl.mImpl->mHeightPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
365 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
367 controlImpl.SetMinimumSize( value.Get< Vector3 >() );
371 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
373 controlImpl.SetMaximumSize( value.Get< Vector3 >() );
377 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
379 if ( value.Get< bool >() )
381 controlImpl.SetKeyInputFocus();
385 controlImpl.ClearKeyInputFocus();
394 * Called to retrieve a property of an object of this type.
395 * @param[in] object The object whose property is to be retrieved.
396 * @param[in] index The property index.
397 * @return The current value of the property.
399 static Property::Value GetProperty( BaseObject* object, Property::Index index )
401 Property::Value value;
403 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
407 Control& controlImpl( control.GetImplementation() );
411 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
413 value = controlImpl.GetBackgroundColor();
417 case Toolkit::Control::PROPERTY_BACKGROUND:
421 Actor actor = controlImpl.GetBackgroundActor();
424 ImageActor imageActor = ImageActor::DownCast( actor );
427 Image image = imageActor.GetImage();
428 Property::Map imageMap;
429 Scripting::CreatePropertyMap( image, imageMap );
430 map[ "image" ] = imageMap;
438 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
440 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mWidthPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
444 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
446 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mHeightPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
450 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
452 value = controlImpl.mImpl->GetMinimumSize();
456 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
458 value = controlImpl.mImpl->GetMaximumSize();
462 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
464 value = controlImpl.HasKeyInputFocus();
474 * Helper to get minimum size
475 * @return minimum size
477 inline const Vector3& GetMinimumSize()
479 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
481 return mMinMaxSize[ MIN_SIZE_INDEX ];
485 // its not been allocated so its ZERO
486 return Vector3::ZERO;
490 * Helper to Set minimum size
493 inline void SetMinimumSize( const Vector3& size )
495 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
497 mMinMaxSize[ MIN_SIZE_INDEX ] = size;
501 // its not been allocated so push the new value there
502 mMinMaxSize.PushBack( size );
507 * Helper to get maximum size
508 * @return maximum size
510 inline const Vector3& GetMaximumSize()
512 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
514 return mMinMaxSize[ MAX_SIZE_INDEX ];
518 // its not been allocated so its MAX_SIZE
524 * Helper to Set minimum size
527 inline void SetMaximumSize( const Vector3& size )
529 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
531 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
533 else if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
535 // max has not been allocated, but min has
536 mMinMaxSize.PushBack( size );
540 // min and max both unallocated so allocate both
541 mMinMaxSize.Resize( 2u ); // this will reserve and default construct two Vector3s
542 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
548 Control& mControlImpl;
549 Background* mBackground; ///< Only create the background if we use it
550 Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this
551 Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
554 PinchGestureDetector mPinchGestureDetector;
555 PanGestureDetector mPanGestureDetector;
556 TapGestureDetector mTapGestureDetector;
557 LongPressGestureDetector mLongPressGestureDetector;
558 // @todo change all these to Vector2 when we have a chance to sanitize the public API as well
559 Vector3 mCurrentSize; ///< Stores the current control's size, this is the negotiated size
560 Vector3 mNaturalSize; ///< Stores the size set through the Actor's API. This is size the actor wants to be. Useful when reset to the initial size is needed.
561 Dali::Vector< Vector3 > mMinMaxSize; ///< Stores the minimum and maximum size if they are set
563 Toolkit::Control::SizePolicy mWidthPolicy :3; ///< Stores the width policy. 3 bits covers 8 values
564 Toolkit::Control::SizePolicy mHeightPolicy :3; ///< Stores the height policy. 3 bits covers 8 values
565 ControlBehaviour mFlags :6; ///< Flags passed in from constructor. Need to increase this size when new enums are added
566 bool mInsideRelayout:1; ///< Detect when were in Relayout
567 bool mIsKeyboardNavigationSupported:1; ///< Stores whether keyboard navigation is supported by the control.
568 bool mIsKeyboardFocusGroup:1; ///< Stores whether the control is a focus group.
571 // Properties - these need to be members of Internal::Control::Impl as they need to functions within this class.
572 static PropertyRegistration PROPERTY_1;
573 static PropertyRegistration PROPERTY_2;
574 static PropertyRegistration PROPERTY_3;
575 static PropertyRegistration PROPERTY_4;
576 static PropertyRegistration PROPERTY_5;
577 static PropertyRegistration PROPERTY_6;
578 static PropertyRegistration PROPERTY_7;
581 PropertyRegistration Control::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Toolkit::Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
582 PropertyRegistration Control::Impl::PROPERTY_2( CONTROL_TYPE, "background", Toolkit::Control::PROPERTY_BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
583 PropertyRegistration Control::Impl::PROPERTY_3( CONTROL_TYPE, "width-policy", Toolkit::Control::PROPERTY_WIDTH_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
584 PropertyRegistration Control::Impl::PROPERTY_4( CONTROL_TYPE, "height-policy", Toolkit::Control::PROPERTY_HEIGHT_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
585 PropertyRegistration Control::Impl::PROPERTY_5( CONTROL_TYPE, "minimum-size", Toolkit::Control::PROPERTY_MINIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
586 PropertyRegistration Control::Impl::PROPERTY_6( CONTROL_TYPE, "maximum-size", Toolkit::Control::PROPERTY_MAXIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
587 PropertyRegistration Control::Impl::PROPERTY_7( CONTROL_TYPE, "key-input-focus", Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
589 Toolkit::Control Control::New()
591 // Create the implementation, temporarily owned on stack
592 IntrusivePtr<Control> controlImpl = new Control( CONTROL_BEHAVIOUR_NONE );
594 // Pass ownership to handle
595 Toolkit::Control handle( *controlImpl );
597 // Second-phase init of the implementation
598 // This can only be done after the CustomActor connection has been made...
599 controlImpl->Initialize();
609 void Control::Initialize()
612 // Calling deriving classes
615 if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
617 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
619 // Register for style changes
620 styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange );
623 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
626 SetRequiresHoverEvents(mImpl->mFlags & REQUIRES_HOVER_EVENTS);
627 SetRequiresMouseWheelEvents(mImpl->mFlags & REQUIRES_MOUSE_WHEEL_EVENTS);
629 mImpl->mInitialized = true;
632 void Control::EnableGestureDetection(Gesture::Type type)
634 if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
636 mImpl->mPinchGestureDetector = PinchGestureDetector::New();
637 mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
638 mImpl->mPinchGestureDetector.Attach(Self());
641 if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
643 mImpl->mPanGestureDetector = PanGestureDetector::New();
644 mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
645 mImpl->mPanGestureDetector.Attach(Self());
648 if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
650 mImpl->mTapGestureDetector = TapGestureDetector::New();
651 mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
652 mImpl->mTapGestureDetector.Attach(Self());
655 if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
657 mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
658 mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
659 mImpl->mLongPressGestureDetector.Attach(Self());
663 void Control::DisableGestureDetection(Gesture::Type type)
665 if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
667 mImpl->mPinchGestureDetector.Detach(Self());
668 mImpl->mPinchGestureDetector.Reset();
671 if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
673 mImpl->mPanGestureDetector.Detach(Self());
674 mImpl->mPanGestureDetector.Reset();
677 if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
679 mImpl->mTapGestureDetector.Detach(Self());
680 mImpl->mTapGestureDetector.Reset();
683 if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
685 mImpl->mLongPressGestureDetector.Detach(Self());
686 mImpl->mLongPressGestureDetector.Reset();
690 PinchGestureDetector Control::GetPinchGestureDetector() const
692 return mImpl->mPinchGestureDetector;
695 PanGestureDetector Control::GetPanGestureDetector() const
697 return mImpl->mPanGestureDetector;
700 TapGestureDetector Control::GetTapGestureDetector() const
702 return mImpl->mTapGestureDetector;
705 LongPressGestureDetector Control::GetLongPressGestureDetector() const
707 return mImpl->mLongPressGestureDetector;
710 void Control::SetBackgroundColor( const Vector4& color )
712 Background& background( mImpl->GetBackground() );
714 if ( background.actor )
716 // Just set the actor color
717 background.actor.SetColor( color );
722 MeshActor meshActor = MeshActor::New( CreateMesh() );
724 meshActor.SetAffectedByLighting( false );
725 SetupBackgroundActor( meshActor, Actor::SCALE, color );
727 // Set the background actor before adding so that we do not inform deriving classes
728 background.actor = meshActor;
729 Self().Add( meshActor );
732 background.color = color;
735 Vector4 Control::GetBackgroundColor() const
737 if ( mImpl->mBackground )
739 return mImpl->mBackground->color;
741 return Color::TRANSPARENT;
744 void Control::SetBackground( Image image )
746 Background& background( mImpl->GetBackground() );
748 if ( background.actor )
750 // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
751 Self().Remove( background.actor );
752 background.actor.Reset();
755 ImageActor imageActor = ImageActor::New( image );
756 SetupBackgroundActor( imageActor, Actor::SIZE, background.color );
758 // Set the background actor before adding so that we do not inform derived classes
759 background.actor = imageActor;
760 Self().Add( imageActor );
763 void Control::ClearBackground()
765 if ( mImpl->mBackground )
767 Background& background( mImpl->GetBackground() );
768 Self().Remove( background.actor );
770 delete mImpl->mBackground;
771 mImpl->mBackground = NULL;
775 Actor Control::GetBackgroundActor() const
777 if ( mImpl->mBackground )
779 return mImpl->mBackground->actor;
785 void Control::OnThemeChange( Toolkit::StyleManager styleManager )
787 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
790 void Control::OnPinch(const PinchGesture& pinch)
792 if( !( mImpl->mStartingPinchScale ) )
795 mImpl->mStartingPinchScale = new Vector3;
798 if( pinch.state == Gesture::Started )
800 *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
803 Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
806 void Control::OnPan( const PanGesture& pan )
810 void Control::OnTap(const TapGesture& tap)
814 void Control::OnLongPress( const LongPressGesture& longPress )
818 void Control::OnStageConnection()
822 // Notify derived classes.
823 OnControlStageConnection();
826 void Control::OnStageDisconnection()
828 // Notify derived classes
829 OnControlStageDisconnection();
832 void Control::OnChildAdd(Actor& child)
834 // If this is the background actor, then we do not want to relayout or inform deriving classes
835 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
840 // Request for relayout as we may need to position the new child and old ones
843 // Notify derived classes.
844 OnControlChildAdd( child );
847 void Control::OnChildRemove(Actor& child)
849 // If this is the background actor, then we do not want to relayout or inform deriving classes
850 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
855 // Request for relayout as we may need to re-position the old child
858 // Notify derived classes.
859 OnControlChildRemove( child );
862 void Control::OnSizeSet(const Vector3& targetSize)
864 if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
866 // Only updates size if set through Actor's API
867 mImpl->mNaturalSize = targetSize;
870 if( targetSize != mImpl->mCurrentSize )
872 // Update control size.
873 mImpl->mCurrentSize = targetSize;
875 // Notify derived classes.
876 OnControlSizeSet( targetSize );
880 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
882 // @todo consider animating negotiated child sizes to target size
885 bool Control::OnTouchEvent(const TouchEvent& event)
887 return false; // Do not consume
890 bool Control::OnHoverEvent(const HoverEvent& event)
892 return false; // Do not consume
895 bool Control::OnKeyEvent(const KeyEvent& event)
897 return false; // Do not consume
900 bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
902 return false; // Do not consume
905 void Control::OnKeyInputFocusGained()
910 void Control::OnKeyInputFocusLost()
915 Actor Control::GetChildByAlias(const std::string& actorAlias)
920 bool Control::OnAccessibilityPan(PanGesture gesture)
922 return false; // Accessibility pan gesture is not handled by default
925 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
927 return false; // Accessibility touch event is not handled by default
930 bool Control::OnAccessibilityValueChange(bool isIncrease)
932 return false; // Accessibility value change action is not handled by default
936 void Control::SetKeyboardNavigationSupport(bool isSupported)
938 mImpl->mIsKeyboardNavigationSupported = isSupported;
941 bool Control::IsKeyboardNavigationSupported()
943 return mImpl->mIsKeyboardNavigationSupported;
946 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
948 mImpl->mIsKeyboardFocusGroup = isFocusGroup;
950 // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
951 Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
954 bool Control::IsKeyboardFocusGroup()
956 return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
959 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
964 bool Control::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
968 if( object && (actionName == Toolkit::Control::ACTION_CONTROL_ACTIVATED) )
970 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
973 // if cast succeeds there is an implementation so no need to check
974 control.GetImplementation().OnActivated();
981 bool Control::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
983 Dali::BaseHandle handle( object );
985 bool connected( false );
986 Toolkit::Control control = Toolkit::Control::DownCast(handle);
989 Control& controlImpl( control.GetImplementation() );
992 if ( Toolkit::Control::SIGNAL_KEY_EVENT == signalName )
994 controlImpl.KeyEventSignal().Connect( tracker, functor );
996 else if( Toolkit::Control::SIGNAL_TAPPED == signalName )
998 controlImpl.EnableGestureDetection( Gesture::Tap );
999 controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
1001 else if( Toolkit::Control::SIGNAL_PANNED == signalName )
1003 controlImpl.EnableGestureDetection( Gesture::Pan );
1004 controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
1006 else if( Toolkit::Control::SIGNAL_PINCHED == signalName )
1008 controlImpl.EnableGestureDetection( Gesture::Pinch );
1009 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
1011 else if( Toolkit::Control::SIGNAL_LONG_PRESSED == signalName )
1013 controlImpl.EnableGestureDetection( Gesture::LongPress );
1014 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
1018 // signalName does not match any signal
1025 void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
1027 if( change.themeChange )
1029 OnThemeChange( styleManager );
1031 else if( change.defaultFontChange || change.defaultFontSizeChange )
1033 OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
1037 Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
1039 return mImpl->mKeyEventSignalV2;
1042 void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
1044 bool relayoutRequest( false );
1046 if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
1048 relayoutRequest = true;
1051 mImpl->mWidthPolicy = widthPolicy;
1052 mImpl->mHeightPolicy = heightPolicy;
1054 // Ensure RelayoutRequest is called AFTER new policies have been set.
1055 if ( relayoutRequest )
1061 void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
1063 widthPolicy = mImpl->mWidthPolicy;
1064 heightPolicy = mImpl->mHeightPolicy;
1067 void Control::SetMinimumSize( const Vector3& size )
1069 const Vector3& minSize = mImpl->GetMinimumSize();
1070 if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1071 fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1073 mImpl->SetMinimumSize( size );
1075 // Only relayout if our control is using the minimum or range policy.
1076 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Minimum ) ||
1077 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1084 const Vector3& Control::GetMinimumSize() const
1086 return mImpl->GetMinimumSize();
1089 void Control::SetMaximumSize( const Vector3& size )
1091 const Vector3& maxSize = mImpl->GetMaximumSize();
1092 if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1093 fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1095 mImpl->SetMaximumSize( size );
1097 // Only relayout if our control is using the maximum or range policy.
1098 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Maximum ) ||
1099 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1106 const Vector3& Control::GetMaximumSize() const
1108 return mImpl->GetMaximumSize();
1111 Vector3 Control::GetNaturalSize()
1113 // could be overridden in derived classes.
1114 return mImpl->mNaturalSize;
1117 float Control::GetHeightForWidth( float width )
1119 // could be overridden in derived classes.
1120 float height( 0.0f );
1121 if ( mImpl->mNaturalSize.width > 0.0f )
1123 height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
1128 float Control::GetWidthForHeight( float height )
1130 // could be overridden in derived classes.
1131 float width( 0.0f );
1132 if ( mImpl->mNaturalSize.height > 0.0f )
1134 width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
1139 const Vector3& Control::GetControlSize() const
1141 return mImpl->mCurrentSize;
1144 const Vector3& Control::GetSizeSet() const
1146 return mImpl->mNaturalSize;
1149 void Control::SetKeyInputFocus()
1151 if( Self().OnStage() )
1153 Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1157 bool Control::HasKeyInputFocus()
1159 bool result = false;
1160 if( Self().OnStage() )
1162 result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1167 void Control::ClearKeyInputFocus()
1169 if( Self().OnStage() )
1171 Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1175 void Control::RelayoutRequest()
1177 // unfortunate double negative but thats to guarantee new controls get size negotiation
1178 // by default and have to "opt-out" if they dont want it
1179 if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
1181 Internal::RelayoutController::Request();
1185 void Control::Relayout(Vector2 size, ActorSizeContainer& container)
1187 // Avoids relayout again when OnSizeSet callback arrives.
1188 mImpl->mInsideRelayout = true;
1189 Self().SetSize( size );
1190 // @todo this really needs to be at the end of method but not sure why the scope used to be only the SetSize, needs to be cleaned up in size negotiation rework
1191 mImpl->mInsideRelayout = false;
1193 // Only relayout controls which requested to be relaid out.
1194 OnRelaidOut( size, container );
1197 void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
1201 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
1204 control.GetImplementation().NegotiateSize( size, container );
1208 container.push_back( ActorSizePair( actor, size ) );
1213 void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1215 unsigned int numChildren = Self().GetChildCount();
1217 for( unsigned int i=0; i<numChildren; ++i )
1219 container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
1223 void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
1227 if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
1229 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1231 // If a control says it has a fixed size, then use the size set by the application / control.
1232 Vector2 setSize( mImpl->mNaturalSize );
1233 if ( setSize != Vector2::ZERO )
1237 // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
1238 // then we should use the natural size of the control rather than the full allocation.
1239 if ( EqualsZero( size.width ) )
1241 size.width = GetWidthForHeight( size.height );
1243 else if ( EqualsZero( size.height ) )
1245 size.height = GetHeightForWidth( size.width );
1250 // If that is not set then set the size to the control's natural size
1251 size = Vector2( GetNaturalSize() );
1256 // Width is fixed so if the application / control has set it, then use that.
1257 if ( !EqualsZero( mImpl->mNaturalSize.width ) )
1259 size.width = mImpl->mNaturalSize.width;
1263 // Otherwise, set the width to what has been allocated.
1264 size.width = allocatedSize.width;
1267 // Height is flexible so ask control what the height should be for our width.
1268 size.height = GetHeightForWidth( size.width );
1270 // Ensure height is within our policy rules
1271 size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
1276 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1278 // Height is fixed so if the application / control has set it, then use that.
1279 if ( !EqualsZero( mImpl->mNaturalSize.height ) )
1281 size.height = mImpl->mNaturalSize.height;
1285 // Otherwise, set the height to what has been allocated.
1286 size.height = allocatedSize.height;
1289 // Width is flexible so ask control what the width should be for our height.
1290 size.width = GetWidthForHeight( size.height );
1292 // Ensure width is within our policy rules
1293 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
1297 // Width and height are BOTH flexible.
1298 // Calculate the width and height using the policy rules.
1299 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
1300 size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
1304 // If the width has not been set, then set to the allocated width.
1305 // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
1306 if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
1308 size.width = allocatedSize.width;
1311 // If the height has not been set, then set to the allocated height.
1312 // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
1313 if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
1315 size.height = allocatedSize.height;
1318 DALI_LOG_INFO( gLogFilter, Debug::Verbose,
1319 "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
1320 Self().GetObjectPtr(),
1321 GetNaturalSize().x, GetNaturalSize().y,
1322 allocatedSize.x, allocatedSize.y,
1325 Relayout( size, container );
1328 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1330 // Guard against destruction during signal emission
1331 Dali::Toolkit::Control handle( GetOwner() );
1333 bool consumed = false;
1335 // signals are allocated dynamically when someone connects
1336 if ( !mImpl->mKeyEventSignalV2.Empty() )
1338 consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1343 // Notification for derived classes
1344 consumed = OnKeyEvent(event);
1350 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1352 mImpl->SignalConnected( slotObserver, callback );
1355 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1357 mImpl->SignalDisconnected( slotObserver, callback );
1360 Control::Control( ControlBehaviour behaviourFlags )
1361 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
1362 mImpl(new Impl(*this))
1364 mImpl->mFlags = behaviourFlags;
1367 } // namespace Internal
1369 } // namespace Toolkit