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.
18 #include <dali-toolkit/public-api/controls/control-impl.h>
22 #include <dali/integration-api/debug.h>
24 #include "dali-toolkit/internal/controls/relayout-controller.h"
25 #include "dali-toolkit/internal/controls/relayout-helper.h"
26 #include "dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h"
27 #include "dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h"
28 #include <dali-toolkit/public-api/controls/control.h>
30 #include <dali-toolkit/public-api/styling/style-manager.h>
31 #include <dali-toolkit/internal/styling/style-manager-impl.h>
39 const Property::Index Control::PROPERTY_BACKGROUND_COLOR = Internal::Control::CONTROL_PROPERTY_START_INDEX;
40 const Property::Index Control::PROPERTY_BACKGROUND = Internal::Control::CONTROL_PROPERTY_START_INDEX + 1;
41 const Property::Index Control::PROPERTY_WIDTH_POLICY = Internal::Control::CONTROL_PROPERTY_START_INDEX + 2;
42 const Property::Index Control::PROPERTY_HEIGHT_POLICY = Internal::Control::CONTROL_PROPERTY_START_INDEX + 3;
43 const Property::Index Control::PROPERTY_MINIMUM_SIZE = Internal::Control::CONTROL_PROPERTY_START_INDEX + 4;
44 const Property::Index Control::PROPERTY_MAXIMUM_SIZE = Internal::Control::CONTROL_PROPERTY_START_INDEX + 5;
45 const Property::Index Control::PROPERTY_KEY_INPUT_FOCUS = Internal::Control::CONTROL_PROPERTY_START_INDEX + 6;
50 const Scripting::StringEnum< Control::SizePolicy > SIZE_POLICY_STRING_TABLE[] =
52 { "FIXED", Control::Fixed },
53 { "MINIMUM", Control::Minimum },
54 { "MAXIMUM", Control::Maximum },
55 { "RANGE", Control::Range },
56 { "FLEXIBLE", Control::Flexible },
58 const unsigned int SIZE_POLICY_STRING_TABLE_COUNT = sizeof( SIZE_POLICY_STRING_TABLE ) / sizeof( SIZE_POLICY_STRING_TABLE[0] );
60 #if defined(DEBUG_ENABLED)
61 Integration::Log::Filter* gLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_CONTROL");
64 const float MAX_FLOAT_VALUE( std::numeric_limits<float>::max() );
65 const Vector3 MAX_SIZE( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE );
66 const float BACKGROUND_ACTOR_Z_POSITION( -0.1f );
70 return Internal::Control::New();
73 TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
75 // Property Registration after Internal::Control::Impl definition below
77 TypeAction ACTION_TYPE_1( CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &Internal::Control::DoAction );
80 * Structure which holds information about the background of a control
84 Actor actor; ///< Either a MeshActor or an ImageActor
85 Vector4 color; ///< The color of the actor.
98 * Helper function to calculate a dimension given the policy of that dimension; the minimum &
99 * maximum values that dimension can be; and the allocated value for that dimension.
101 * @param[in] policy The size policy for that dimension.
102 * @param[in] minimum The minimum value that dimension can be.
103 * @param[in] maximum The maximum value that dimension can be.
104 * @param[in] allocated The value allocated for that dimension.
106 * @return The value that the dimension should be.
108 * @note This does not handle Control::Fixed policy.
110 float Calculate( Control::SizePolicy policy, float minimum, float maximum, float allocated )
112 float size( allocated );
118 // Use allocated value
122 case Control::Minimum:
124 // Size is always at least the minimum.
125 size = std::max( allocated, minimum );
129 case Control::Maximum:
131 // Size can grow but up to a maximum value.
132 size = std::min( allocated, maximum );
138 // Size is at least the minimum and can grow up to the maximum
139 size = std::max( size, minimum );
140 size = std::min( size, maximum );
144 case Control::Flexible:
146 // Size grows or shrinks with no limits.
153 DALI_ASSERT_DEBUG( false && "This function was not intended to be used by any other policy." );
162 * Creates a white coloured Mesh.
166 Vector3 white( Color::WHITE );
170 // Create vertices with a white color (actual color is set by actor color)
171 MeshData::VertexContainer vertices(4);
172 vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
173 vertices[ 1 ] = MeshData::Vertex( Vector3( 0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
174 vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
175 vertices[ 3 ] = MeshData::Vertex( Vector3( 0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
177 // Specify all the faces
178 MeshData::FaceIndices faces;
179 faces.reserve( 6 ); // 2 triangles in Quad
180 faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
181 faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
183 // Create the mesh data from the vertices and faces
184 meshData.SetMaterial( Material::New( "ControlMaterial" ) );
185 meshData.SetVertices( vertices );
186 meshData.SetFaceIndices( faces );
187 meshData.SetHasColor( true );
189 return Mesh::New( meshData );
193 * Sets all the required properties for the background actor.
195 * @param[in] actor The actor to set the properties on.
196 * @param[in] constrainingIndex The property index to constrain the parent's size on.
197 * @param[in] color The required color of the actor.
199 void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const Vector4& color )
201 actor.SetColor( color );
202 actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
203 actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
205 Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
206 ParentSource( Actor::SIZE ),
207 EqualToConstraint() );
208 actor.ApplyConstraint( constraint );
211 } // unnamed namespace
216 class Control::Impl : public ConnectionTracker
221 * Size indices for mMinMaxSize array
230 // Construction & Destruction
231 Impl(Control& controlImpl)
232 : mControlImpl( controlImpl ),
234 mStartingPinchScale( NULL ),
236 mPinchGestureDetector(),
237 mPanGestureDetector(),
238 mTapGestureDetector(),
239 mLongPressGestureDetector(),
242 mWidthPolicy( Toolkit::Control::Fixed ),
243 mHeightPolicy( Toolkit::Control::Fixed ),
244 mFlags( Control::CONTROL_BEHAVIOUR_NONE ),
245 mInsideRelayout( false ),
246 mIsKeyboardNavigationSupported( false ),
247 mIsKeyboardFocusGroup( false ),
248 mInitialized( false )
254 // All gesture detectors will be destroyed so no need to disconnect.
256 delete mStartingPinchScale;
259 // Gesture Detection Methods
261 void PinchDetected(Actor actor, PinchGesture pinch)
263 mControlImpl.OnPinch(pinch);
266 void PanDetected(Actor actor, PanGesture pan)
268 mControlImpl.OnPan(pan);
271 void TapDetected(Actor actor, TapGesture tap)
273 mControlImpl.OnTap(tap);
276 void LongPressDetected(Actor actor, LongPressGesture longPress)
278 mControlImpl.OnLongPress(longPress);
281 // Background Methods
284 * Only creates an instance of the background if we actually use it.
285 * @return A reference to the Background structure.
287 Background& GetBackground()
291 mBackground = new Background;
299 * Called when a property of an object of this type is set.
300 * @param[in] object The object whose property is set.
301 * @param[in] index The property index.
302 * @param[in] value The new property value.
304 static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
306 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
310 Control& controlImpl( control.GetImplementation() );
314 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
316 controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
320 case Toolkit::Control::PROPERTY_BACKGROUND:
322 if ( value.HasKey( "image" ) )
324 Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
325 Image image = Scripting::NewImage( imageMap );
329 controlImpl.SetBackground( image );
332 else if ( value.Get< Property::Map >().empty() )
334 // An empty map means the background is no longer required
335 controlImpl.ClearBackground();
340 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
342 controlImpl.mImpl->mWidthPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
346 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
348 controlImpl.mImpl->mHeightPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
352 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
354 controlImpl.SetMinimumSize( value.Get< Vector3 >() );
358 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
360 controlImpl.SetMaximumSize( value.Get< Vector3 >() );
364 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
366 if ( value.Get< bool >() )
368 controlImpl.SetKeyInputFocus();
372 controlImpl.ClearKeyInputFocus();
381 * Called to retrieve a property of an object of this type.
382 * @param[in] object The object whose property is to be retrieved.
383 * @param[in] index The property index.
384 * @return The current value of the property.
386 static Property::Value GetProperty( BaseObject* object, Property::Index index )
388 Property::Value value;
390 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
394 Control& controlImpl( control.GetImplementation() );
398 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
400 value = controlImpl.GetBackgroundColor();
404 case Toolkit::Control::PROPERTY_BACKGROUND:
408 Actor actor = controlImpl.GetBackgroundActor();
411 ImageActor imageActor = ImageActor::DownCast( actor );
414 Image image = imageActor.GetImage();
415 Property::Map imageMap;
416 Scripting::CreatePropertyMap( image, imageMap );
417 map.push_back( Property::StringValuePair( "image", imageMap ) );
425 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
427 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mWidthPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
431 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
433 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mHeightPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
437 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
439 value = controlImpl.mImpl->GetMinimumSize();
443 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
445 value = controlImpl.mImpl->GetMaximumSize();
449 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
451 value = controlImpl.HasKeyInputFocus();
461 * Helper to get minimum size
462 * @return minimum size
464 inline const Vector3& GetMinimumSize()
466 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
468 return mMinMaxSize[ MIN_SIZE_INDEX ];
472 // its not been allocated so its ZERO
473 return Vector3::ZERO;
477 * Helper to Set minimum size
480 inline void SetMinimumSize( const Vector3& size )
482 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
484 mMinMaxSize[ MIN_SIZE_INDEX ] = size;
488 // its not been allocated so push the new value there
489 mMinMaxSize.PushBack( size );
494 * Helper to get maximum size
495 * @return maximum size
497 inline const Vector3& GetMaximumSize()
499 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
501 return mMinMaxSize[ MAX_SIZE_INDEX ];
505 // its not been allocated so its MAX_SIZE
511 * Helper to Set minimum size
514 inline void SetMaximumSize( const Vector3& size )
516 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
518 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
520 else if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
522 // max has not been allocated, but min has
523 mMinMaxSize.PushBack( size );
527 // min and max both unallocated so allocate both
528 mMinMaxSize.Resize( 2u ); // this will reserve and default construct two Vector3s
529 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
535 Control& mControlImpl;
536 Background* mBackground; ///< Only create the background if we use it
537 Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this
538 Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
541 PinchGestureDetector mPinchGestureDetector;
542 PanGestureDetector mPanGestureDetector;
543 TapGestureDetector mTapGestureDetector;
544 LongPressGestureDetector mLongPressGestureDetector;
545 // @todo change all these to Vector2 when we have a chance to sanitize the public API as well
546 Vector3 mCurrentSize; ///< Stores the current control's size, this is the negotiated size
547 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.
548 Dali::Vector< Vector3 > mMinMaxSize; ///< Stores the minimum and maximum size if they are set
550 Toolkit::Control::SizePolicy mWidthPolicy :3; ///< Stores the width policy. 3 bits covers 8 values
551 Toolkit::Control::SizePolicy mHeightPolicy :3; ///< Stores the height policy. 3 bits covers 8 values
552 ControlBehaviour mFlags :4; ///< Flags passed in from constructor. Need to increase this size when new enums are added
553 bool mInsideRelayout:1; ///< Detect when were in Relayout
554 bool mIsKeyboardNavigationSupported:1; ///< Stores whether keyboard navigation is supported by the control.
555 bool mIsKeyboardFocusGroup:1; ///< Stores whether the control is a focus group.
558 // Properties - these need to be members of Internal::Control::Impl as they need to functions within this class.
559 static PropertyRegistration PROPERTY_1;
560 static PropertyRegistration PROPERTY_2;
561 static PropertyRegistration PROPERTY_3;
562 static PropertyRegistration PROPERTY_4;
563 static PropertyRegistration PROPERTY_5;
564 static PropertyRegistration PROPERTY_6;
565 static PropertyRegistration PROPERTY_7;
568 PropertyRegistration Control::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Toolkit::Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
569 PropertyRegistration Control::Impl::PROPERTY_2( CONTROL_TYPE, "background", Toolkit::Control::PROPERTY_BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
570 PropertyRegistration Control::Impl::PROPERTY_3( CONTROL_TYPE, "width-policy", Toolkit::Control::PROPERTY_WIDTH_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
571 PropertyRegistration Control::Impl::PROPERTY_4( CONTROL_TYPE, "height-policy", Toolkit::Control::PROPERTY_HEIGHT_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
572 PropertyRegistration Control::Impl::PROPERTY_5( CONTROL_TYPE, "minimum-size", Toolkit::Control::PROPERTY_MINIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
573 PropertyRegistration Control::Impl::PROPERTY_6( CONTROL_TYPE, "maximum-size", Toolkit::Control::PROPERTY_MAXIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
574 PropertyRegistration Control::Impl::PROPERTY_7( CONTROL_TYPE, "key-input-focus", Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
576 Toolkit::Control Control::New()
578 // Create the implementation, temporarily owned on stack
579 IntrusivePtr<Control> controlImpl = new Control( CONTROL_BEHAVIOUR_NONE );
581 // Pass ownership to handle
582 Toolkit::Control handle( *controlImpl );
584 // Second-phase init of the implementation
585 // This can only be done after the CustomActor connection has been made...
586 controlImpl->Initialize();
596 void Control::Initialize()
599 // Calling deriving classes
602 if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
604 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
606 // Register for style changes
607 styleManager.StyleChangeSignal().Connect( this, &ControlImpl::DoStyleChange );
610 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
613 mImpl->mInitialized = true;
616 void Control::EnableGestureDetection(Gesture::Type type)
618 if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
620 mImpl->mPinchGestureDetector = PinchGestureDetector::New();
621 mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
622 mImpl->mPinchGestureDetector.Attach(Self());
625 if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
627 mImpl->mPanGestureDetector = PanGestureDetector::New();
628 mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
629 mImpl->mPanGestureDetector.Attach(Self());
632 if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
634 mImpl->mTapGestureDetector = TapGestureDetector::New();
635 mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
636 mImpl->mTapGestureDetector.Attach(Self());
639 if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
641 mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
642 mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
643 mImpl->mLongPressGestureDetector.Attach(Self());
647 void Control::DisableGestureDetection(Gesture::Type type)
649 if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
651 mImpl->mPinchGestureDetector.Detach(Self());
652 mImpl->mPinchGestureDetector.Reset();
655 if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
657 mImpl->mPanGestureDetector.Detach(Self());
658 mImpl->mPanGestureDetector.Reset();
661 if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
663 mImpl->mTapGestureDetector.Detach(Self());
664 mImpl->mTapGestureDetector.Reset();
667 if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
669 mImpl->mLongPressGestureDetector.Detach(Self());
670 mImpl->mLongPressGestureDetector.Reset();
674 PinchGestureDetector Control::GetPinchGestureDetector() const
676 return mImpl->mPinchGestureDetector;
679 PanGestureDetector Control::GetPanGestureDetector() const
681 return mImpl->mPanGestureDetector;
684 TapGestureDetector Control::GetTapGestureDetector() const
686 return mImpl->mTapGestureDetector;
689 LongPressGestureDetector Control::GetLongPressGestureDetector() const
691 return mImpl->mLongPressGestureDetector;
694 void Control::SetBackgroundColor( const Vector4& color )
696 Background& background( mImpl->GetBackground() );
698 if ( background.actor )
700 // Just set the actor color
701 background.actor.SetColor( color );
706 MeshActor meshActor = MeshActor::New( CreateMesh() );
708 meshActor.SetAffectedByLighting( false );
709 SetupBackgroundActor( meshActor, Actor::SCALE, color );
711 // Set the background actor before adding so that we do not inform deriving classes
712 background.actor = meshActor;
713 Self().Add( meshActor );
716 background.color = color;
719 Vector4 Control::GetBackgroundColor() const
721 if ( mImpl->mBackground )
723 return mImpl->mBackground->color;
725 return Color::TRANSPARENT;
728 void Control::SetBackground( Image image )
730 Background& background( mImpl->GetBackground() );
732 if ( background.actor )
734 // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
735 Self().Remove( background.actor );
736 background.actor = NULL;
739 ImageActor imageActor = ImageActor::New( image );
740 SetupBackgroundActor( imageActor, Actor::SIZE, background.color );
742 // Set the background actor before adding so that we do not inform derived classes
743 background.actor = imageActor;
744 Self().Add( imageActor );
747 void Control::ClearBackground()
749 if ( mImpl->mBackground )
751 Background& background( mImpl->GetBackground() );
752 Self().Remove( background.actor );
754 delete mImpl->mBackground;
755 mImpl->mBackground = NULL;
759 Actor Control::GetBackgroundActor() const
761 if ( mImpl->mBackground )
763 return mImpl->mBackground->actor;
769 void Control::OnThemeChange( Toolkit::StyleManager styleManager )
771 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
774 void Control::OnPinch(PinchGesture pinch)
776 if( !( mImpl->mStartingPinchScale ) )
779 mImpl->mStartingPinchScale = new Vector3;
782 if( pinch.state == Gesture::Started )
784 *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
787 Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
790 void Control::OnStageConnection()
794 // Notify derived classes.
795 OnControlStageConnection();
798 void Control::OnStageDisconnection()
800 // Notify derived classes
801 OnControlStageDisconnection();
804 void Control::OnChildAdd(Actor& child)
806 // If this is the background actor, then we do not want to relayout or inform deriving classes
807 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
812 // Request for relayout as we may need to position the new child and old ones
815 // Notify derived classes.
816 OnControlChildAdd( child );
819 void Control::OnChildRemove(Actor& child)
821 // If this is the background actor, then we do not want to relayout or inform deriving classes
822 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
827 // Request for relayout as we may need to re-position the old child
830 // Notify derived classes.
831 OnControlChildRemove( child );
834 void Control::OnSizeSet(const Vector3& targetSize)
836 if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
838 // Only updates size if set through Actor's API
839 mImpl->mNaturalSize = targetSize;
842 if( targetSize != mImpl->mCurrentSize )
844 // Update control size.
845 mImpl->mCurrentSize = targetSize;
847 // Notify derived classes.
848 OnControlSizeSet( targetSize );
852 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
854 // @todo consider animating negotiated child sizes to target size
857 bool Control::OnTouchEvent(const TouchEvent& event)
859 return false; // Do not consume
862 bool Control::OnKeyEvent(const KeyEvent& event)
864 return false; // Do not consume
867 bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
869 return false; // Do not consume
872 void Control::OnKeyInputFocusGained()
877 void Control::OnKeyInputFocusLost()
882 Actor Control::GetChildByAlias(const std::string& actorAlias)
887 bool Control::OnAccessibilityPan(PanGesture gesture)
889 return false; // Accessibility pan gesture is not handled by default
892 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
894 return false; // Accessibility touch event is not handled by default
897 bool Control::OnAccessibilityValueChange(bool isIncrease)
899 return false; // Accessibility value change action is not handled by default
903 void Control::SetKeyboardNavigationSupport(bool isSupported)
905 mImpl->mIsKeyboardNavigationSupported = isSupported;
908 bool Control::IsKeyboardNavigationSupported()
910 return mImpl->mIsKeyboardNavigationSupported;
913 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
915 mImpl->mIsKeyboardFocusGroup = isFocusGroup;
917 // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
918 Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
921 bool Control::IsKeyboardFocusGroup()
923 return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
926 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
931 bool Control::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
935 if( object && (actionName == Toolkit::Control::ACTION_CONTROL_ACTIVATED) )
937 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
940 // if cast succeeds there is an implementation so no need to check
941 control.GetImplementation().OnActivated();
948 void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
950 if( change.themeChange )
952 OnThemeChange( styleManager );
954 else if( change.defaultFontChange || change.defaultFontSizeChange )
956 // This OnStyleChange(StyleChange change ) is deprecated, use OnFontChange instead
957 OnStyleChange( change );
959 OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
963 Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
965 return mImpl->mKeyEventSignalV2;
968 void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
970 bool relayoutRequest( false );
972 if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
974 relayoutRequest = true;
977 mImpl->mWidthPolicy = widthPolicy;
978 mImpl->mHeightPolicy = heightPolicy;
980 // Ensure RelayoutRequest is called AFTER new policies have been set.
981 if ( relayoutRequest )
987 void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
989 widthPolicy = mImpl->mWidthPolicy;
990 heightPolicy = mImpl->mHeightPolicy;
993 void Control::SetMinimumSize( const Vector3& size )
995 const Vector3& minSize = mImpl->GetMinimumSize();
996 if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
997 fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
999 mImpl->SetMinimumSize( size );
1001 // Only relayout if our control is using the minimum or range policy.
1002 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Minimum ) ||
1003 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1010 const Vector3& Control::GetMinimumSize() const
1012 return mImpl->GetMinimumSize();
1015 void Control::SetMaximumSize( const Vector3& size )
1017 const Vector3& maxSize = mImpl->GetMaximumSize();
1018 if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1019 fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1021 mImpl->SetMaximumSize( size );
1023 // Only relayout if our control is using the maximum or range policy.
1024 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Maximum ) ||
1025 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1032 const Vector3& Control::GetMaximumSize() const
1034 return mImpl->GetMaximumSize();
1037 Vector3 Control::GetNaturalSize()
1039 // could be overridden in derived classes.
1040 return mImpl->mNaturalSize;
1043 float Control::GetHeightForWidth( float width )
1045 // could be overridden in derived classes.
1046 float height( 0.0f );
1047 if ( mImpl->mNaturalSize.width > 0.0f )
1049 height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
1054 float Control::GetWidthForHeight( float height )
1056 // could be overridden in derived classes.
1057 float width( 0.0f );
1058 if ( mImpl->mNaturalSize.height > 0.0f )
1060 width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
1065 const Vector3& Control::GetControlSize() const
1067 return mImpl->mCurrentSize;
1070 const Vector3& Control::GetSizeSet() const
1072 return mImpl->mNaturalSize;
1075 void Control::SetKeyInputFocus()
1077 if( Self().OnStage() )
1079 Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1083 bool Control::HasKeyInputFocus()
1085 bool result = false;
1086 if( Self().OnStage() )
1088 result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1093 void Control::ClearKeyInputFocus()
1095 if( Self().OnStage() )
1097 Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1101 void Control::RelayoutRequest()
1103 // unfortunate double negative but thats to guarantee new controls get size negotiation
1104 // by default and have to "opt-out" if they dont want it
1105 if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
1107 Internal::RelayoutController::Request();
1111 void Control::Relayout(Vector2 size, ActorSizeContainer& container)
1113 // Avoids relayout again when OnSizeSet callback arrives.
1114 mImpl->mInsideRelayout = true;
1115 Self().SetSize( size );
1116 // @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
1117 mImpl->mInsideRelayout = false;
1119 // Only relayout controls which requested to be relaid out.
1120 OnRelaidOut( size, container );
1123 void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
1127 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
1130 control.GetImplementation().NegotiateSize( size, container );
1134 container.push_back( ActorSizePair( actor, size ) );
1139 void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1141 unsigned int numChildren = Self().GetChildCount();
1143 for( unsigned int i=0; i<numChildren; ++i )
1145 container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
1149 void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
1153 if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
1155 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1157 // If a control says it has a fixed size, then use the size set by the application / control.
1158 Vector2 setSize( mImpl->mNaturalSize );
1159 if ( setSize != Vector2::ZERO )
1163 // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
1164 // then we should use the natural size of the control rather than the full allocation.
1165 if ( EqualsZero( size.width ) )
1167 size.width = GetWidthForHeight( size.height );
1169 else if ( EqualsZero( size.height ) )
1171 size.height = GetHeightForWidth( size.width );
1176 // If that is not set then set the size to the control's natural size
1177 size = Vector2( GetNaturalSize() );
1182 // Width is fixed so if the application / control has set it, then use that.
1183 if ( !EqualsZero( mImpl->mNaturalSize.width ) )
1185 size.width = mImpl->mNaturalSize.width;
1189 // Otherwise, set the width to what has been allocated.
1190 size.width = allocatedSize.width;
1193 // Height is flexible so ask control what the height should be for our width.
1194 size.height = GetHeightForWidth( size.width );
1196 // Ensure height is within our policy rules
1197 size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
1202 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1204 // Height is fixed so if the application / control has set it, then use that.
1205 if ( !EqualsZero( mImpl->mNaturalSize.height ) )
1207 size.height = mImpl->mNaturalSize.height;
1211 // Otherwise, set the height to what has been allocated.
1212 size.height = allocatedSize.height;
1215 // Width is flexible so ask control what the width should be for our height.
1216 size.width = GetWidthForHeight( size.height );
1218 // Ensure width is within our policy rules
1219 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
1223 // Width and height are BOTH flexible.
1224 // Calculate the width and height using the policy rules.
1225 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
1226 size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
1230 // If the width has not been set, then set to the allocated width.
1231 // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
1232 if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
1234 size.width = allocatedSize.width;
1237 // If the height has not been set, then set to the allocated height.
1238 // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
1239 if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
1241 size.height = allocatedSize.height;
1244 DALI_LOG_INFO( gLogFilter, Debug::Verbose,
1245 "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
1246 Self().GetObjectPtr(),
1247 GetNaturalSize().x, GetNaturalSize().y,
1248 allocatedSize.x, allocatedSize.y,
1251 Relayout( size, container );
1254 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1256 // Guard against destruction during signal emission
1257 Dali::Toolkit::Control handle( GetOwner() );
1259 bool consumed = false;
1261 // signals are allocated dynamically when someone connects
1262 if ( !mImpl->mKeyEventSignalV2.Empty() )
1264 consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1269 // Notification for derived classes
1270 consumed = OnKeyEvent(event);
1276 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1278 mImpl->SignalConnected( slotObserver, callback );
1281 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1283 mImpl->SignalDisconnected( slotObserver, callback );
1286 std::size_t Control::GetConnectionCount() const
1288 return mImpl->GetConnectionCount();
1291 Control::Control( bool requiresTouchEvents )
1292 : CustomActorImpl( requiresTouchEvents ),
1293 mImpl(new Impl(*this))
1297 Control::Control( ControlBehaviour behaviourFlags )
1298 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
1299 mImpl(new Impl(*this))
1301 mImpl->mFlags = behaviourFlags;
1304 } // namespace Internal
1306 } // namespace Toolkit