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, &Control::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 OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
960 Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
962 return mImpl->mKeyEventSignalV2;
965 void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
967 bool relayoutRequest( false );
969 if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
971 relayoutRequest = true;
974 mImpl->mWidthPolicy = widthPolicy;
975 mImpl->mHeightPolicy = heightPolicy;
977 // Ensure RelayoutRequest is called AFTER new policies have been set.
978 if ( relayoutRequest )
984 void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
986 widthPolicy = mImpl->mWidthPolicy;
987 heightPolicy = mImpl->mHeightPolicy;
990 void Control::SetMinimumSize( const Vector3& size )
992 const Vector3& minSize = mImpl->GetMinimumSize();
993 if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
994 fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
996 mImpl->SetMinimumSize( size );
998 // Only relayout if our control is using the minimum or range policy.
999 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Minimum ) ||
1000 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1007 const Vector3& Control::GetMinimumSize() const
1009 return mImpl->GetMinimumSize();
1012 void Control::SetMaximumSize( const Vector3& size )
1014 const Vector3& maxSize = mImpl->GetMaximumSize();
1015 if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1016 fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1018 mImpl->SetMaximumSize( size );
1020 // Only relayout if our control is using the maximum or range policy.
1021 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Maximum ) ||
1022 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1029 const Vector3& Control::GetMaximumSize() const
1031 return mImpl->GetMaximumSize();
1034 Vector3 Control::GetNaturalSize()
1036 // could be overridden in derived classes.
1037 return mImpl->mNaturalSize;
1040 float Control::GetHeightForWidth( float width )
1042 // could be overridden in derived classes.
1043 float height( 0.0f );
1044 if ( mImpl->mNaturalSize.width > 0.0f )
1046 height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
1051 float Control::GetWidthForHeight( float height )
1053 // could be overridden in derived classes.
1054 float width( 0.0f );
1055 if ( mImpl->mNaturalSize.height > 0.0f )
1057 width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
1062 const Vector3& Control::GetControlSize() const
1064 return mImpl->mCurrentSize;
1067 const Vector3& Control::GetSizeSet() const
1069 return mImpl->mNaturalSize;
1072 void Control::SetKeyInputFocus()
1074 if( Self().OnStage() )
1076 Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1080 bool Control::HasKeyInputFocus()
1082 bool result = false;
1083 if( Self().OnStage() )
1085 result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1090 void Control::ClearKeyInputFocus()
1092 if( Self().OnStage() )
1094 Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1098 void Control::RelayoutRequest()
1100 // unfortunate double negative but thats to guarantee new controls get size negotiation
1101 // by default and have to "opt-out" if they dont want it
1102 if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
1104 Internal::RelayoutController::Request();
1108 void Control::Relayout(Vector2 size, ActorSizeContainer& container)
1110 // Avoids relayout again when OnSizeSet callback arrives.
1111 mImpl->mInsideRelayout = true;
1112 Self().SetSize( size );
1113 // @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
1114 mImpl->mInsideRelayout = false;
1116 // Only relayout controls which requested to be relaid out.
1117 OnRelaidOut( size, container );
1120 void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
1124 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
1127 control.GetImplementation().NegotiateSize( size, container );
1131 container.push_back( ActorSizePair( actor, size ) );
1136 void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1138 unsigned int numChildren = Self().GetChildCount();
1140 for( unsigned int i=0; i<numChildren; ++i )
1142 container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
1146 void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
1150 if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
1152 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1154 // If a control says it has a fixed size, then use the size set by the application / control.
1155 Vector2 setSize( mImpl->mNaturalSize );
1156 if ( setSize != Vector2::ZERO )
1160 // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
1161 // then we should use the natural size of the control rather than the full allocation.
1162 if ( EqualsZero( size.width ) )
1164 size.width = GetWidthForHeight( size.height );
1166 else if ( EqualsZero( size.height ) )
1168 size.height = GetHeightForWidth( size.width );
1173 // If that is not set then set the size to the control's natural size
1174 size = Vector2( GetNaturalSize() );
1179 // Width is fixed so if the application / control has set it, then use that.
1180 if ( !EqualsZero( mImpl->mNaturalSize.width ) )
1182 size.width = mImpl->mNaturalSize.width;
1186 // Otherwise, set the width to what has been allocated.
1187 size.width = allocatedSize.width;
1190 // Height is flexible so ask control what the height should be for our width.
1191 size.height = GetHeightForWidth( size.width );
1193 // Ensure height is within our policy rules
1194 size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
1199 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1201 // Height is fixed so if the application / control has set it, then use that.
1202 if ( !EqualsZero( mImpl->mNaturalSize.height ) )
1204 size.height = mImpl->mNaturalSize.height;
1208 // Otherwise, set the height to what has been allocated.
1209 size.height = allocatedSize.height;
1212 // Width is flexible so ask control what the width should be for our height.
1213 size.width = GetWidthForHeight( size.height );
1215 // Ensure width is within our policy rules
1216 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
1220 // Width and height are BOTH flexible.
1221 // Calculate the width and height using the policy rules.
1222 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
1223 size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
1227 // If the width has not been set, then set to the allocated width.
1228 // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
1229 if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
1231 size.width = allocatedSize.width;
1234 // If the height has not been set, then set to the allocated height.
1235 // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
1236 if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
1238 size.height = allocatedSize.height;
1241 DALI_LOG_INFO( gLogFilter, Debug::Verbose,
1242 "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
1243 Self().GetObjectPtr(),
1244 GetNaturalSize().x, GetNaturalSize().y,
1245 allocatedSize.x, allocatedSize.y,
1248 Relayout( size, container );
1251 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1253 // Guard against destruction during signal emission
1254 Dali::Toolkit::Control handle( GetOwner() );
1256 bool consumed = false;
1258 // signals are allocated dynamically when someone connects
1259 if ( !mImpl->mKeyEventSignalV2.Empty() )
1261 consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1266 // Notification for derived classes
1267 consumed = OnKeyEvent(event);
1273 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1275 mImpl->SignalConnected( slotObserver, callback );
1278 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1280 mImpl->SignalDisconnected( slotObserver, callback );
1283 std::size_t Control::GetConnectionCount() const
1285 return mImpl->GetConnectionCount();
1288 Control::Control( ControlBehaviour behaviourFlags )
1289 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
1290 mImpl(new Impl(*this))
1292 mImpl->mFlags = behaviourFlags;
1295 } // namespace Internal
1297 } // namespace Toolkit