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 );
79 SignalConnectorType SIGNAL_CONNECTOR_1( CONTROL_TYPE, Toolkit::Control::SIGNAL_KEY_EVENT, &Internal::Control::DoConnectSignal );
80 SignalConnectorType SIGNAL_CONNECTOR_2( CONTROL_TYPE, Toolkit::Control::SIGNAL_TAPPED, &Internal::Control::DoConnectSignal );
81 SignalConnectorType SIGNAL_CONNECTOR_3( CONTROL_TYPE, Toolkit::Control::SIGNAL_PANNED, &Internal::Control::DoConnectSignal );
82 SignalConnectorType SIGNAL_CONNECTOR_4( CONTROL_TYPE, Toolkit::Control::SIGNAL_PINCHED, &Internal::Control::DoConnectSignal );
83 SignalConnectorType SIGNAL_CONNECTOR_5( CONTROL_TYPE, Toolkit::Control::SIGNAL_LONG_PRESSED, &Internal::Control::DoConnectSignal );
86 * Structure which holds information about the background of a control
90 Actor actor; ///< Either a MeshActor or an ImageActor
91 Vector4 color; ///< The color of the actor.
104 * Helper function to calculate a dimension given the policy of that dimension; the minimum &
105 * maximum values that dimension can be; and the allocated value for that dimension.
107 * @param[in] policy The size policy for that dimension.
108 * @param[in] minimum The minimum value that dimension can be.
109 * @param[in] maximum The maximum value that dimension can be.
110 * @param[in] allocated The value allocated for that dimension.
112 * @return The value that the dimension should be.
114 * @note This does not handle Control::Fixed policy.
116 float Calculate( Control::SizePolicy policy, float minimum, float maximum, float allocated )
118 float size( allocated );
124 // Use allocated value
128 case Control::Minimum:
130 // Size is always at least the minimum.
131 size = std::max( allocated, minimum );
135 case Control::Maximum:
137 // Size can grow but up to a maximum value.
138 size = std::min( allocated, maximum );
144 // Size is at least the minimum and can grow up to the maximum
145 size = std::max( size, minimum );
146 size = std::min( size, maximum );
150 case Control::Flexible:
152 // Size grows or shrinks with no limits.
159 DALI_ASSERT_DEBUG( false && "This function was not intended to be used by any other policy." );
168 * Creates a white coloured Mesh.
172 Vector3 white( Color::WHITE );
176 // Create vertices with a white color (actual color is set by actor color)
177 MeshData::VertexContainer vertices(4);
178 vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
179 vertices[ 1 ] = MeshData::Vertex( Vector3( 0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
180 vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
181 vertices[ 3 ] = MeshData::Vertex( Vector3( 0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
183 // Specify all the faces
184 MeshData::FaceIndices faces;
185 faces.reserve( 6 ); // 2 triangles in Quad
186 faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
187 faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
189 // Create the mesh data from the vertices and faces
190 meshData.SetMaterial( Material::New( "ControlMaterial" ) );
191 meshData.SetVertices( vertices );
192 meshData.SetFaceIndices( faces );
193 meshData.SetHasColor( true );
195 return Mesh::New( meshData );
199 * Sets all the required properties for the background actor.
201 * @param[in] actor The actor to set the properties on.
202 * @param[in] constrainingIndex The property index to constrain the parent's size on.
203 * @param[in] color The required color of the actor.
205 void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const Vector4& color )
207 actor.SetColor( color );
208 actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
209 actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
210 actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
212 Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
213 ParentSource( Actor::SIZE ),
214 EqualToConstraint() );
215 actor.ApplyConstraint( constraint );
218 } // unnamed namespace
223 class Control::Impl : public ConnectionTracker
228 * Size indices for mMinMaxSize array
237 // Construction & Destruction
238 Impl(Control& controlImpl)
239 : mControlImpl( controlImpl ),
241 mStartingPinchScale( NULL ),
243 mPinchGestureDetector(),
244 mPanGestureDetector(),
245 mTapGestureDetector(),
246 mLongPressGestureDetector(),
249 mWidthPolicy( Toolkit::Control::Fixed ),
250 mHeightPolicy( Toolkit::Control::Fixed ),
251 mFlags( Control::CONTROL_BEHAVIOUR_NONE ),
252 mInsideRelayout( false ),
253 mIsKeyboardNavigationSupported( false ),
254 mIsKeyboardFocusGroup( false ),
255 mInitialized( false )
261 // All gesture detectors will be destroyed so no need to disconnect.
263 delete mStartingPinchScale;
266 // Gesture Detection Methods
268 void PinchDetected(Actor actor, PinchGesture pinch)
270 mControlImpl.OnPinch(pinch);
273 void PanDetected(Actor actor, PanGesture pan)
275 mControlImpl.OnPan(pan);
278 void TapDetected(Actor actor, TapGesture tap)
280 mControlImpl.OnTap(tap);
283 void LongPressDetected(Actor actor, LongPressGesture longPress)
285 mControlImpl.OnLongPress(longPress);
288 // Background Methods
291 * Only creates an instance of the background if we actually use it.
292 * @return A reference to the Background structure.
294 Background& GetBackground()
298 mBackground = new Background;
306 * Called when a property of an object of this type is set.
307 * @param[in] object The object whose property is set.
308 * @param[in] index The property index.
309 * @param[in] value The new property value.
311 static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
313 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
317 Control& controlImpl( control.GetImplementation() );
321 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
323 controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
327 case Toolkit::Control::PROPERTY_BACKGROUND:
329 if ( value.HasKey( "image" ) )
331 Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
332 Image image = Scripting::NewImage( imageMap );
336 controlImpl.SetBackground( image );
339 else if ( value.Get< Property::Map >().empty() )
341 // An empty map means the background is no longer required
342 controlImpl.ClearBackground();
347 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
349 controlImpl.mImpl->mWidthPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
353 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
355 controlImpl.mImpl->mHeightPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
359 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
361 controlImpl.SetMinimumSize( value.Get< Vector3 >() );
365 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
367 controlImpl.SetMaximumSize( value.Get< Vector3 >() );
371 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
373 if ( value.Get< bool >() )
375 controlImpl.SetKeyInputFocus();
379 controlImpl.ClearKeyInputFocus();
388 * Called to retrieve a property of an object of this type.
389 * @param[in] object The object whose property is to be retrieved.
390 * @param[in] index The property index.
391 * @return The current value of the property.
393 static Property::Value GetProperty( BaseObject* object, Property::Index index )
395 Property::Value value;
397 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
401 Control& controlImpl( control.GetImplementation() );
405 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
407 value = controlImpl.GetBackgroundColor();
411 case Toolkit::Control::PROPERTY_BACKGROUND:
415 Actor actor = controlImpl.GetBackgroundActor();
418 ImageActor imageActor = ImageActor::DownCast( actor );
421 Image image = imageActor.GetImage();
422 Property::Map imageMap;
423 Scripting::CreatePropertyMap( image, imageMap );
424 map.push_back( Property::StringValuePair( "image", imageMap ) );
432 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
434 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mWidthPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
438 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
440 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mHeightPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
444 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
446 value = controlImpl.mImpl->GetMinimumSize();
450 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
452 value = controlImpl.mImpl->GetMaximumSize();
456 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
458 value = controlImpl.HasKeyInputFocus();
468 * Helper to get minimum size
469 * @return minimum size
471 inline const Vector3& GetMinimumSize()
473 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
475 return mMinMaxSize[ MIN_SIZE_INDEX ];
479 // its not been allocated so its ZERO
480 return Vector3::ZERO;
484 * Helper to Set minimum size
487 inline void SetMinimumSize( const Vector3& size )
489 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
491 mMinMaxSize[ MIN_SIZE_INDEX ] = size;
495 // its not been allocated so push the new value there
496 mMinMaxSize.PushBack( size );
501 * Helper to get maximum size
502 * @return maximum size
504 inline const Vector3& GetMaximumSize()
506 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
508 return mMinMaxSize[ MAX_SIZE_INDEX ];
512 // its not been allocated so its MAX_SIZE
518 * Helper to Set minimum size
521 inline void SetMaximumSize( const Vector3& size )
523 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
525 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
527 else if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
529 // max has not been allocated, but min has
530 mMinMaxSize.PushBack( size );
534 // min and max both unallocated so allocate both
535 mMinMaxSize.Resize( 2u ); // this will reserve and default construct two Vector3s
536 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
542 Control& mControlImpl;
543 Background* mBackground; ///< Only create the background if we use it
544 Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this
545 Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
548 PinchGestureDetector mPinchGestureDetector;
549 PanGestureDetector mPanGestureDetector;
550 TapGestureDetector mTapGestureDetector;
551 LongPressGestureDetector mLongPressGestureDetector;
552 // @todo change all these to Vector2 when we have a chance to sanitize the public API as well
553 Vector3 mCurrentSize; ///< Stores the current control's size, this is the negotiated size
554 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.
555 Dali::Vector< Vector3 > mMinMaxSize; ///< Stores the minimum and maximum size if they are set
557 Toolkit::Control::SizePolicy mWidthPolicy :3; ///< Stores the width policy. 3 bits covers 8 values
558 Toolkit::Control::SizePolicy mHeightPolicy :3; ///< Stores the height policy. 3 bits covers 8 values
559 ControlBehaviour mFlags :4; ///< Flags passed in from constructor. Need to increase this size when new enums are added
560 bool mInsideRelayout:1; ///< Detect when were in Relayout
561 bool mIsKeyboardNavigationSupported:1; ///< Stores whether keyboard navigation is supported by the control.
562 bool mIsKeyboardFocusGroup:1; ///< Stores whether the control is a focus group.
565 // Properties - these need to be members of Internal::Control::Impl as they need to functions within this class.
566 static PropertyRegistration PROPERTY_1;
567 static PropertyRegistration PROPERTY_2;
568 static PropertyRegistration PROPERTY_3;
569 static PropertyRegistration PROPERTY_4;
570 static PropertyRegistration PROPERTY_5;
571 static PropertyRegistration PROPERTY_6;
572 static PropertyRegistration PROPERTY_7;
575 PropertyRegistration Control::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Toolkit::Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
576 PropertyRegistration Control::Impl::PROPERTY_2( CONTROL_TYPE, "background", Toolkit::Control::PROPERTY_BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
577 PropertyRegistration Control::Impl::PROPERTY_3( CONTROL_TYPE, "width-policy", Toolkit::Control::PROPERTY_WIDTH_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
578 PropertyRegistration Control::Impl::PROPERTY_4( CONTROL_TYPE, "height-policy", Toolkit::Control::PROPERTY_HEIGHT_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
579 PropertyRegistration Control::Impl::PROPERTY_5( CONTROL_TYPE, "minimum-size", Toolkit::Control::PROPERTY_MINIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
580 PropertyRegistration Control::Impl::PROPERTY_6( CONTROL_TYPE, "maximum-size", Toolkit::Control::PROPERTY_MAXIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
581 PropertyRegistration Control::Impl::PROPERTY_7( CONTROL_TYPE, "key-input-focus", Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
583 Toolkit::Control Control::New()
585 // Create the implementation, temporarily owned on stack
586 IntrusivePtr<Control> controlImpl = new Control( CONTROL_BEHAVIOUR_NONE );
588 // Pass ownership to handle
589 Toolkit::Control handle( *controlImpl );
591 // Second-phase init of the implementation
592 // This can only be done after the CustomActor connection has been made...
593 controlImpl->Initialize();
603 void Control::Initialize()
606 // Calling deriving classes
609 if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
611 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
613 // Register for style changes
614 styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange );
617 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
620 mImpl->mInitialized = true;
623 void Control::EnableGestureDetection(Gesture::Type type)
625 if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
627 mImpl->mPinchGestureDetector = PinchGestureDetector::New();
628 mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
629 mImpl->mPinchGestureDetector.Attach(Self());
632 if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
634 mImpl->mPanGestureDetector = PanGestureDetector::New();
635 mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
636 mImpl->mPanGestureDetector.Attach(Self());
639 if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
641 mImpl->mTapGestureDetector = TapGestureDetector::New();
642 mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
643 mImpl->mTapGestureDetector.Attach(Self());
646 if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
648 mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
649 mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
650 mImpl->mLongPressGestureDetector.Attach(Self());
654 void Control::DisableGestureDetection(Gesture::Type type)
656 if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
658 mImpl->mPinchGestureDetector.Detach(Self());
659 mImpl->mPinchGestureDetector.Reset();
662 if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
664 mImpl->mPanGestureDetector.Detach(Self());
665 mImpl->mPanGestureDetector.Reset();
668 if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
670 mImpl->mTapGestureDetector.Detach(Self());
671 mImpl->mTapGestureDetector.Reset();
674 if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
676 mImpl->mLongPressGestureDetector.Detach(Self());
677 mImpl->mLongPressGestureDetector.Reset();
681 PinchGestureDetector Control::GetPinchGestureDetector() const
683 return mImpl->mPinchGestureDetector;
686 PanGestureDetector Control::GetPanGestureDetector() const
688 return mImpl->mPanGestureDetector;
691 TapGestureDetector Control::GetTapGestureDetector() const
693 return mImpl->mTapGestureDetector;
696 LongPressGestureDetector Control::GetLongPressGestureDetector() const
698 return mImpl->mLongPressGestureDetector;
701 void Control::SetBackgroundColor( const Vector4& color )
703 Background& background( mImpl->GetBackground() );
705 if ( background.actor )
707 // Just set the actor color
708 background.actor.SetColor( color );
713 MeshActor meshActor = MeshActor::New( CreateMesh() );
715 meshActor.SetAffectedByLighting( false );
716 SetupBackgroundActor( meshActor, Actor::SCALE, color );
718 // Set the background actor before adding so that we do not inform deriving classes
719 background.actor = meshActor;
720 Self().Add( meshActor );
723 background.color = color;
726 Vector4 Control::GetBackgroundColor() const
728 if ( mImpl->mBackground )
730 return mImpl->mBackground->color;
732 return Color::TRANSPARENT;
735 void Control::SetBackground( Image image )
737 Background& background( mImpl->GetBackground() );
739 if ( background.actor )
741 // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
742 Self().Remove( background.actor );
743 background.actor = NULL;
746 ImageActor imageActor = ImageActor::New( image );
747 SetupBackgroundActor( imageActor, Actor::SIZE, background.color );
749 // Set the background actor before adding so that we do not inform derived classes
750 background.actor = imageActor;
751 Self().Add( imageActor );
754 void Control::ClearBackground()
756 if ( mImpl->mBackground )
758 Background& background( mImpl->GetBackground() );
759 Self().Remove( background.actor );
761 delete mImpl->mBackground;
762 mImpl->mBackground = NULL;
766 Actor Control::GetBackgroundActor() const
768 if ( mImpl->mBackground )
770 return mImpl->mBackground->actor;
776 void Control::OnThemeChange( Toolkit::StyleManager styleManager )
778 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
781 void Control::OnPinch(PinchGesture pinch)
783 if( !( mImpl->mStartingPinchScale ) )
786 mImpl->mStartingPinchScale = new Vector3;
789 if( pinch.state == Gesture::Started )
791 *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
794 Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
797 void Control::OnStageConnection()
801 // Notify derived classes.
802 OnControlStageConnection();
805 void Control::OnStageDisconnection()
807 // Notify derived classes
808 OnControlStageDisconnection();
811 void Control::OnChildAdd(Actor& child)
813 // If this is the background actor, then we do not want to relayout or inform deriving classes
814 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
819 // Request for relayout as we may need to position the new child and old ones
822 // Notify derived classes.
823 OnControlChildAdd( child );
826 void Control::OnChildRemove(Actor& child)
828 // If this is the background actor, then we do not want to relayout or inform deriving classes
829 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
834 // Request for relayout as we may need to re-position the old child
837 // Notify derived classes.
838 OnControlChildRemove( child );
841 void Control::OnSizeSet(const Vector3& targetSize)
843 if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
845 // Only updates size if set through Actor's API
846 mImpl->mNaturalSize = targetSize;
849 if( targetSize != mImpl->mCurrentSize )
851 // Update control size.
852 mImpl->mCurrentSize = targetSize;
854 // Notify derived classes.
855 OnControlSizeSet( targetSize );
859 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
861 // @todo consider animating negotiated child sizes to target size
864 bool Control::OnTouchEvent(const TouchEvent& event)
866 return false; // Do not consume
869 bool Control::OnKeyEvent(const KeyEvent& event)
871 return false; // Do not consume
874 bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
876 return false; // Do not consume
879 void Control::OnKeyInputFocusGained()
884 void Control::OnKeyInputFocusLost()
889 Actor Control::GetChildByAlias(const std::string& actorAlias)
894 bool Control::OnAccessibilityPan(PanGesture gesture)
896 return false; // Accessibility pan gesture is not handled by default
899 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
901 return false; // Accessibility touch event is not handled by default
904 bool Control::OnAccessibilityValueChange(bool isIncrease)
906 return false; // Accessibility value change action is not handled by default
910 void Control::SetKeyboardNavigationSupport(bool isSupported)
912 mImpl->mIsKeyboardNavigationSupported = isSupported;
915 bool Control::IsKeyboardNavigationSupported()
917 return mImpl->mIsKeyboardNavigationSupported;
920 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
922 mImpl->mIsKeyboardFocusGroup = isFocusGroup;
924 // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
925 Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
928 bool Control::IsKeyboardFocusGroup()
930 return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
933 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
938 bool Control::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
942 if( object && (actionName == Toolkit::Control::ACTION_CONTROL_ACTIVATED) )
944 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
947 // if cast succeeds there is an implementation so no need to check
948 control.GetImplementation().OnActivated();
955 bool Control::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
957 Dali::BaseHandle handle( object );
959 bool connected( false );
960 Toolkit::Control control = Toolkit::Control::DownCast(handle);
963 Control& controlImpl( control.GetImplementation() );
966 if ( Toolkit::Control::SIGNAL_KEY_EVENT == signalName )
968 controlImpl.KeyEventSignal().Connect( tracker, functor );
970 else if( Toolkit::Control::SIGNAL_TAPPED == signalName )
972 controlImpl.EnableGestureDetection( Gesture::Tap );
973 controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
975 else if( Toolkit::Control::SIGNAL_PANNED == signalName )
977 controlImpl.EnableGestureDetection( Gesture::Pan );
978 controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
980 else if( Toolkit::Control::SIGNAL_PINCHED == signalName )
982 controlImpl.EnableGestureDetection( Gesture::Pinch );
983 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
985 else if( Toolkit::Control::SIGNAL_LONG_PRESSED == signalName )
987 controlImpl.EnableGestureDetection( Gesture::LongPress );
988 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
992 // signalName does not match any signal
999 void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
1001 if( change.themeChange )
1003 OnThemeChange( styleManager );
1005 else if( change.defaultFontChange || change.defaultFontSizeChange )
1007 OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
1011 Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
1013 return mImpl->mKeyEventSignalV2;
1016 void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
1018 bool relayoutRequest( false );
1020 if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
1022 relayoutRequest = true;
1025 mImpl->mWidthPolicy = widthPolicy;
1026 mImpl->mHeightPolicy = heightPolicy;
1028 // Ensure RelayoutRequest is called AFTER new policies have been set.
1029 if ( relayoutRequest )
1035 void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
1037 widthPolicy = mImpl->mWidthPolicy;
1038 heightPolicy = mImpl->mHeightPolicy;
1041 void Control::SetMinimumSize( const Vector3& size )
1043 const Vector3& minSize = mImpl->GetMinimumSize();
1044 if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1045 fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1047 mImpl->SetMinimumSize( size );
1049 // Only relayout if our control is using the minimum or range policy.
1050 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Minimum ) ||
1051 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1058 const Vector3& Control::GetMinimumSize() const
1060 return mImpl->GetMinimumSize();
1063 void Control::SetMaximumSize( const Vector3& size )
1065 const Vector3& maxSize = mImpl->GetMaximumSize();
1066 if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1067 fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1069 mImpl->SetMaximumSize( size );
1071 // Only relayout if our control is using the maximum or range policy.
1072 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Maximum ) ||
1073 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1080 const Vector3& Control::GetMaximumSize() const
1082 return mImpl->GetMaximumSize();
1085 Vector3 Control::GetNaturalSize()
1087 // could be overridden in derived classes.
1088 return mImpl->mNaturalSize;
1091 float Control::GetHeightForWidth( float width )
1093 // could be overridden in derived classes.
1094 float height( 0.0f );
1095 if ( mImpl->mNaturalSize.width > 0.0f )
1097 height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
1102 float Control::GetWidthForHeight( float height )
1104 // could be overridden in derived classes.
1105 float width( 0.0f );
1106 if ( mImpl->mNaturalSize.height > 0.0f )
1108 width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
1113 const Vector3& Control::GetControlSize() const
1115 return mImpl->mCurrentSize;
1118 const Vector3& Control::GetSizeSet() const
1120 return mImpl->mNaturalSize;
1123 void Control::SetKeyInputFocus()
1125 if( Self().OnStage() )
1127 Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1131 bool Control::HasKeyInputFocus()
1133 bool result = false;
1134 if( Self().OnStage() )
1136 result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1141 void Control::ClearKeyInputFocus()
1143 if( Self().OnStage() )
1145 Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1149 void Control::RelayoutRequest()
1151 // unfortunate double negative but thats to guarantee new controls get size negotiation
1152 // by default and have to "opt-out" if they dont want it
1153 if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
1155 Internal::RelayoutController::Request();
1159 void Control::Relayout(Vector2 size, ActorSizeContainer& container)
1161 // Avoids relayout again when OnSizeSet callback arrives.
1162 mImpl->mInsideRelayout = true;
1163 Self().SetSize( size );
1164 // @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
1165 mImpl->mInsideRelayout = false;
1167 // Only relayout controls which requested to be relaid out.
1168 OnRelaidOut( size, container );
1171 void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
1175 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
1178 control.GetImplementation().NegotiateSize( size, container );
1182 container.push_back( ActorSizePair( actor, size ) );
1187 void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1189 unsigned int numChildren = Self().GetChildCount();
1191 for( unsigned int i=0; i<numChildren; ++i )
1193 container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
1197 void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
1201 if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
1203 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1205 // If a control says it has a fixed size, then use the size set by the application / control.
1206 Vector2 setSize( mImpl->mNaturalSize );
1207 if ( setSize != Vector2::ZERO )
1211 // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
1212 // then we should use the natural size of the control rather than the full allocation.
1213 if ( EqualsZero( size.width ) )
1215 size.width = GetWidthForHeight( size.height );
1217 else if ( EqualsZero( size.height ) )
1219 size.height = GetHeightForWidth( size.width );
1224 // If that is not set then set the size to the control's natural size
1225 size = Vector2( GetNaturalSize() );
1230 // Width is fixed so if the application / control has set it, then use that.
1231 if ( !EqualsZero( mImpl->mNaturalSize.width ) )
1233 size.width = mImpl->mNaturalSize.width;
1237 // Otherwise, set the width to what has been allocated.
1238 size.width = allocatedSize.width;
1241 // Height is flexible so ask control what the height should be for our width.
1242 size.height = GetHeightForWidth( size.width );
1244 // Ensure height is within our policy rules
1245 size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
1250 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1252 // Height is fixed so if the application / control has set it, then use that.
1253 if ( !EqualsZero( mImpl->mNaturalSize.height ) )
1255 size.height = mImpl->mNaturalSize.height;
1259 // Otherwise, set the height to what has been allocated.
1260 size.height = allocatedSize.height;
1263 // Width is flexible so ask control what the width should be for our height.
1264 size.width = GetWidthForHeight( size.height );
1266 // Ensure width is within our policy rules
1267 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
1271 // Width and height are BOTH flexible.
1272 // Calculate the width and height using the policy rules.
1273 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
1274 size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
1278 // If the width has not been set, then set to the allocated width.
1279 // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
1280 if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
1282 size.width = allocatedSize.width;
1285 // If the height has not been set, then set to the allocated height.
1286 // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
1287 if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
1289 size.height = allocatedSize.height;
1292 DALI_LOG_INFO( gLogFilter, Debug::Verbose,
1293 "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
1294 Self().GetObjectPtr(),
1295 GetNaturalSize().x, GetNaturalSize().y,
1296 allocatedSize.x, allocatedSize.y,
1299 Relayout( size, container );
1302 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1304 // Guard against destruction during signal emission
1305 Dali::Toolkit::Control handle( GetOwner() );
1307 bool consumed = false;
1309 // signals are allocated dynamically when someone connects
1310 if ( !mImpl->mKeyEventSignalV2.Empty() )
1312 consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1317 // Notification for derived classes
1318 consumed = OnKeyEvent(event);
1324 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1326 mImpl->SignalConnected( slotObserver, callback );
1329 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1331 mImpl->SignalDisconnected( slotObserver, callback );
1334 Control::Control( ControlBehaviour behaviourFlags )
1335 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
1336 mImpl(new Impl(*this))
1338 mImpl->mFlags = behaviourFlags;
1341 } // namespace Internal
1343 } // namespace Toolkit