2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/public-api/actors/image-actor.h>
24 #include <dali/public-api/actors/mesh-actor.h>
25 #include <dali/public-api/animation/constraints.h>
26 #include <dali/public-api/geometry/mesh.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/scripting/scripting.h>
29 #include <dali/integration-api/debug.h>
31 #include <dali-toolkit/internal/controls/relayout-controller.h>
32 #include <dali-toolkit/internal/controls/relayout-helper.h>
33 #include <dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h>
34 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
35 #include <dali-toolkit/public-api/controls/control.h>
36 #include <dali-toolkit/public-api/styling/style-manager.h>
37 #include <dali-toolkit/internal/styling/style-manager-impl.h>
45 const Property::Index Control::PROPERTY_BACKGROUND_COLOR = Internal::Control::CONTROL_PROPERTY_START_INDEX;
46 const Property::Index Control::PROPERTY_BACKGROUND = Internal::Control::CONTROL_PROPERTY_START_INDEX + 1;
47 const Property::Index Control::PROPERTY_WIDTH_POLICY = Internal::Control::CONTROL_PROPERTY_START_INDEX + 2;
48 const Property::Index Control::PROPERTY_HEIGHT_POLICY = Internal::Control::CONTROL_PROPERTY_START_INDEX + 3;
49 const Property::Index Control::PROPERTY_MINIMUM_SIZE = Internal::Control::CONTROL_PROPERTY_START_INDEX + 4;
50 const Property::Index Control::PROPERTY_MAXIMUM_SIZE = Internal::Control::CONTROL_PROPERTY_START_INDEX + 5;
51 const Property::Index Control::PROPERTY_KEY_INPUT_FOCUS = Internal::Control::CONTROL_PROPERTY_START_INDEX + 6;
56 const Scripting::StringEnum< Control::SizePolicy > SIZE_POLICY_STRING_TABLE[] =
58 { "FIXED", Control::Fixed },
59 { "MINIMUM", Control::Minimum },
60 { "MAXIMUM", Control::Maximum },
61 { "RANGE", Control::Range },
62 { "FLEXIBLE", Control::Flexible },
64 const unsigned int SIZE_POLICY_STRING_TABLE_COUNT = sizeof( SIZE_POLICY_STRING_TABLE ) / sizeof( SIZE_POLICY_STRING_TABLE[0] );
66 #if defined(DEBUG_ENABLED)
67 Integration::Log::Filter* gLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_CONTROL");
70 const float MAX_FLOAT_VALUE( std::numeric_limits<float>::max() );
71 const Vector3 MAX_SIZE( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE );
72 const float BACKGROUND_ACTOR_Z_POSITION( -0.1f );
76 return Internal::Control::New();
79 TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
81 // Property Registration after Internal::Control::Impl definition below
83 TypeAction ACTION_TYPE_1( CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &Internal::Control::DoAction );
85 SignalConnectorType SIGNAL_CONNECTOR_1( CONTROL_TYPE, Toolkit::Control::SIGNAL_KEY_EVENT, &Internal::Control::DoConnectSignal );
86 SignalConnectorType SIGNAL_CONNECTOR_2( CONTROL_TYPE, Toolkit::Control::SIGNAL_TAPPED, &Internal::Control::DoConnectSignal );
87 SignalConnectorType SIGNAL_CONNECTOR_3( CONTROL_TYPE, Toolkit::Control::SIGNAL_PANNED, &Internal::Control::DoConnectSignal );
88 SignalConnectorType SIGNAL_CONNECTOR_4( CONTROL_TYPE, Toolkit::Control::SIGNAL_PINCHED, &Internal::Control::DoConnectSignal );
89 SignalConnectorType SIGNAL_CONNECTOR_5( CONTROL_TYPE, Toolkit::Control::SIGNAL_LONG_PRESSED, &Internal::Control::DoConnectSignal );
92 * Structure which holds information about the background of a control
96 Actor actor; ///< Either a MeshActor or an ImageActor
97 Vector4 color; ///< The color of the actor.
104 color( Color::WHITE )
110 * Helper function to calculate a dimension given the policy of that dimension; the minimum &
111 * maximum values that dimension can be; and the allocated value for that dimension.
113 * @param[in] policy The size policy for that dimension.
114 * @param[in] minimum The minimum value that dimension can be.
115 * @param[in] maximum The maximum value that dimension can be.
116 * @param[in] allocated The value allocated for that dimension.
118 * @return The value that the dimension should be.
120 * @note This does not handle Control::Fixed policy.
122 float Calculate( Control::SizePolicy policy, float minimum, float maximum, float allocated )
124 float size( allocated );
130 // Use allocated value
134 case Control::Minimum:
136 // Size is always at least the minimum.
137 size = std::max( allocated, minimum );
141 case Control::Maximum:
143 // Size can grow but up to a maximum value.
144 size = std::min( allocated, maximum );
150 // Size is at least the minimum and can grow up to the maximum
151 size = std::max( size, minimum );
152 size = std::min( size, maximum );
156 case Control::Flexible:
158 // Size grows or shrinks with no limits.
165 DALI_ASSERT_DEBUG( false && "This function was not intended to be used by any other policy." );
174 * Creates a white coloured Mesh.
178 Vector3 white( Color::WHITE );
182 // Create vertices with a white color (actual color is set by actor color)
183 MeshData::VertexContainer vertices(4);
184 vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
185 vertices[ 1 ] = MeshData::Vertex( Vector3( 0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
186 vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
187 vertices[ 3 ] = MeshData::Vertex( Vector3( 0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
189 // Specify all the faces
190 MeshData::FaceIndices faces;
191 faces.reserve( 6 ); // 2 triangles in Quad
192 faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
193 faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
195 // Create the mesh data from the vertices and faces
196 meshData.SetMaterial( Material::New( "ControlMaterial" ) );
197 meshData.SetVertices( vertices );
198 meshData.SetFaceIndices( faces );
199 meshData.SetHasColor( true );
201 return Mesh::New( meshData );
205 * Sets all the required properties for the background actor.
207 * @param[in] actor The actor to set the properties on.
208 * @param[in] constrainingIndex The property index to constrain the parent's size on.
209 * @param[in] color The required color of the actor.
211 void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const Vector4& color )
213 actor.SetColor( color );
214 actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
215 actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
216 actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
218 Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
219 ParentSource( Actor::SIZE ),
220 EqualToConstraint() );
221 actor.ApplyConstraint( constraint );
224 } // unnamed namespace
229 class Control::Impl : public ConnectionTracker
234 * Size indices for mMinMaxSize array
243 // Construction & Destruction
244 Impl(Control& controlImpl)
245 : mControlImpl( controlImpl ),
247 mStartingPinchScale( NULL ),
249 mPinchGestureDetector(),
250 mPanGestureDetector(),
251 mTapGestureDetector(),
252 mLongPressGestureDetector(),
255 mWidthPolicy( Toolkit::Control::Fixed ),
256 mHeightPolicy( Toolkit::Control::Fixed ),
257 mFlags( Control::CONTROL_BEHAVIOUR_NONE ),
258 mInsideRelayout( false ),
259 mIsKeyboardNavigationSupported( false ),
260 mIsKeyboardFocusGroup( false ),
261 mInitialized( false )
267 // All gesture detectors will be destroyed so no need to disconnect.
269 delete mStartingPinchScale;
272 // Gesture Detection Methods
274 void PinchDetected(Actor actor, PinchGesture pinch)
276 mControlImpl.OnPinch(pinch);
279 void PanDetected(Actor actor, PanGesture pan)
281 mControlImpl.OnPan(pan);
284 void TapDetected(Actor actor, TapGesture tap)
286 mControlImpl.OnTap(tap);
289 void LongPressDetected(Actor actor, LongPressGesture longPress)
291 mControlImpl.OnLongPress(longPress);
294 // Background Methods
297 * Only creates an instance of the background if we actually use it.
298 * @return A reference to the Background structure.
300 Background& GetBackground()
304 mBackground = new Background;
312 * Called when a property of an object of this type is set.
313 * @param[in] object The object whose property is set.
314 * @param[in] index The property index.
315 * @param[in] value The new property value.
317 static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
319 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
323 Control& controlImpl( control.GetImplementation() );
327 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
329 controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
333 case Toolkit::Control::PROPERTY_BACKGROUND:
335 if ( value.HasKey( "image" ) )
337 Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
338 Image image = Scripting::NewImage( imageMap );
342 controlImpl.SetBackground( image );
345 else if ( value.Get< Property::Map >().Empty() )
347 // An empty map means the background is no longer required
348 controlImpl.ClearBackground();
353 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
355 controlImpl.mImpl->mWidthPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
359 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
361 controlImpl.mImpl->mHeightPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
365 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
367 controlImpl.SetMinimumSize( value.Get< Vector3 >() );
371 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
373 controlImpl.SetMaximumSize( value.Get< Vector3 >() );
377 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
379 if ( value.Get< bool >() )
381 controlImpl.SetKeyInputFocus();
385 controlImpl.ClearKeyInputFocus();
394 * Called to retrieve a property of an object of this type.
395 * @param[in] object The object whose property is to be retrieved.
396 * @param[in] index The property index.
397 * @return The current value of the property.
399 static Property::Value GetProperty( BaseObject* object, Property::Index index )
401 Property::Value value;
403 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
407 Control& controlImpl( control.GetImplementation() );
411 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
413 value = controlImpl.GetBackgroundColor();
417 case Toolkit::Control::PROPERTY_BACKGROUND:
421 Actor actor = controlImpl.GetBackgroundActor();
424 ImageActor imageActor = ImageActor::DownCast( actor );
427 Image image = imageActor.GetImage();
428 Property::Map imageMap;
429 Scripting::CreatePropertyMap( image, imageMap );
430 map[ "image" ] = imageMap;
438 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
440 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mWidthPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
444 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
446 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mHeightPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
450 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
452 value = controlImpl.mImpl->GetMinimumSize();
456 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
458 value = controlImpl.mImpl->GetMaximumSize();
462 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
464 value = controlImpl.HasKeyInputFocus();
474 * Helper to get minimum size
475 * @return minimum size
477 inline const Vector3& GetMinimumSize()
479 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
481 return mMinMaxSize[ MIN_SIZE_INDEX ];
485 // its not been allocated so its ZERO
486 return Vector3::ZERO;
490 * Helper to Set minimum size
493 inline void SetMinimumSize( const Vector3& size )
495 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
497 mMinMaxSize[ MIN_SIZE_INDEX ] = size;
501 // its not been allocated so push the new value there
502 mMinMaxSize.PushBack( size );
507 * Helper to get maximum size
508 * @return maximum size
510 inline const Vector3& GetMaximumSize()
512 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
514 return mMinMaxSize[ MAX_SIZE_INDEX ];
518 // its not been allocated so its MAX_SIZE
524 * Helper to Set minimum size
527 inline void SetMaximumSize( const Vector3& size )
529 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
531 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
533 else if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
535 // max has not been allocated, but min has
536 mMinMaxSize.PushBack( size );
540 // min and max both unallocated so allocate both
541 mMinMaxSize.Resize( 2u ); // this will reserve and default construct two Vector3s
542 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
548 Control& mControlImpl;
549 Background* mBackground; ///< Only create the background if we use it
550 Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this
551 Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
554 PinchGestureDetector mPinchGestureDetector;
555 PanGestureDetector mPanGestureDetector;
556 TapGestureDetector mTapGestureDetector;
557 LongPressGestureDetector mLongPressGestureDetector;
558 // @todo change all these to Vector2 when we have a chance to sanitize the public API as well
559 Vector3 mCurrentSize; ///< Stores the current control's size, this is the negotiated size
560 Vector3 mNaturalSize; ///< Stores the size set through the Actor's API. This is size the actor wants to be. Useful when reset to the initial size is needed.
561 Dali::Vector< Vector3 > mMinMaxSize; ///< Stores the minimum and maximum size if they are set
563 Toolkit::Control::SizePolicy mWidthPolicy :3; ///< Stores the width policy. 3 bits covers 8 values
564 Toolkit::Control::SizePolicy mHeightPolicy :3; ///< Stores the height policy. 3 bits covers 8 values
565 ControlBehaviour mFlags :6; ///< Flags passed in from constructor. Need to increase this size when new enums are added
566 bool mInsideRelayout:1; ///< Detect when were in Relayout
567 bool mIsKeyboardNavigationSupported:1; ///< Stores whether keyboard navigation is supported by the control.
568 bool mIsKeyboardFocusGroup:1; ///< Stores whether the control is a focus group.
571 // Properties - these need to be members of Internal::Control::Impl as they need to functions within this class.
572 static PropertyRegistration PROPERTY_1;
573 static PropertyRegistration PROPERTY_2;
574 static PropertyRegistration PROPERTY_3;
575 static PropertyRegistration PROPERTY_4;
576 static PropertyRegistration PROPERTY_5;
577 static PropertyRegistration PROPERTY_6;
578 static PropertyRegistration PROPERTY_7;
581 PropertyRegistration Control::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Toolkit::Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
582 PropertyRegistration Control::Impl::PROPERTY_2( CONTROL_TYPE, "background", Toolkit::Control::PROPERTY_BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
583 PropertyRegistration Control::Impl::PROPERTY_3( CONTROL_TYPE, "width-policy", Toolkit::Control::PROPERTY_WIDTH_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
584 PropertyRegistration Control::Impl::PROPERTY_4( CONTROL_TYPE, "height-policy", Toolkit::Control::PROPERTY_HEIGHT_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
585 PropertyRegistration Control::Impl::PROPERTY_5( CONTROL_TYPE, "minimum-size", Toolkit::Control::PROPERTY_MINIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
586 PropertyRegistration Control::Impl::PROPERTY_6( CONTROL_TYPE, "maximum-size", Toolkit::Control::PROPERTY_MAXIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
587 PropertyRegistration Control::Impl::PROPERTY_7( CONTROL_TYPE, "key-input-focus", Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
589 Toolkit::Control Control::New()
591 // Create the implementation, temporarily owned on stack
592 IntrusivePtr<Control> controlImpl = new Control( CONTROL_BEHAVIOUR_NONE );
594 // Pass ownership to handle
595 Toolkit::Control handle( *controlImpl );
597 // Second-phase init of the implementation
598 // This can only be done after the CustomActor connection has been made...
599 controlImpl->Initialize();
609 void Control::Initialize()
612 // Calling deriving classes
615 if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
617 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
619 // Register for style changes
620 styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange );
623 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
626 SetRequiresHoverEvents(mImpl->mFlags & REQUIRES_HOVER_EVENTS);
627 SetRequiresMouseWheelEvents(mImpl->mFlags & REQUIRES_MOUSE_WHEEL_EVENTS);
629 mImpl->mInitialized = true;
632 void Control::EnableGestureDetection(Gesture::Type type)
634 if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
636 mImpl->mPinchGestureDetector = PinchGestureDetector::New();
637 mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
638 mImpl->mPinchGestureDetector.Attach(Self());
641 if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
643 mImpl->mPanGestureDetector = PanGestureDetector::New();
644 mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
645 mImpl->mPanGestureDetector.Attach(Self());
648 if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
650 mImpl->mTapGestureDetector = TapGestureDetector::New();
651 mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
652 mImpl->mTapGestureDetector.Attach(Self());
655 if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
657 mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
658 mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
659 mImpl->mLongPressGestureDetector.Attach(Self());
663 void Control::DisableGestureDetection(Gesture::Type type)
665 if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
667 mImpl->mPinchGestureDetector.Detach(Self());
668 mImpl->mPinchGestureDetector.Reset();
671 if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
673 mImpl->mPanGestureDetector.Detach(Self());
674 mImpl->mPanGestureDetector.Reset();
677 if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
679 mImpl->mTapGestureDetector.Detach(Self());
680 mImpl->mTapGestureDetector.Reset();
683 if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
685 mImpl->mLongPressGestureDetector.Detach(Self());
686 mImpl->mLongPressGestureDetector.Reset();
690 PinchGestureDetector Control::GetPinchGestureDetector() const
692 return mImpl->mPinchGestureDetector;
695 PanGestureDetector Control::GetPanGestureDetector() const
697 return mImpl->mPanGestureDetector;
700 TapGestureDetector Control::GetTapGestureDetector() const
702 return mImpl->mTapGestureDetector;
705 LongPressGestureDetector Control::GetLongPressGestureDetector() const
707 return mImpl->mLongPressGestureDetector;
710 void Control::SetBackgroundColor( const Vector4& color )
712 Background& background( mImpl->GetBackground() );
714 if ( background.actor )
716 // Just set the actor color
717 background.actor.SetColor( color );
722 MeshActor meshActor = MeshActor::New( CreateMesh() );
724 meshActor.SetAffectedByLighting( false );
725 SetupBackgroundActor( meshActor, Actor::SCALE, color );
727 // Set the background actor before adding so that we do not inform deriving classes
728 background.actor = meshActor;
729 Self().Add( meshActor );
732 background.color = color;
735 Vector4 Control::GetBackgroundColor() const
737 if ( mImpl->mBackground )
739 return mImpl->mBackground->color;
741 return Color::TRANSPARENT;
744 void Control::SetBackground( Image image )
746 Background& background( mImpl->GetBackground() );
748 if ( background.actor )
750 // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
751 Self().Remove( background.actor );
752 background.actor.Reset();
755 ImageActor imageActor = ImageActor::New( image );
756 SetupBackgroundActor( imageActor, Actor::SIZE, background.color );
758 // Set the background actor before adding so that we do not inform derived classes
759 background.actor = imageActor;
760 Self().Add( imageActor );
763 void Control::ClearBackground()
765 if ( mImpl->mBackground )
767 Background& background( mImpl->GetBackground() );
768 Self().Remove( background.actor );
770 delete mImpl->mBackground;
771 mImpl->mBackground = NULL;
775 Actor Control::GetBackgroundActor() const
777 if ( mImpl->mBackground )
779 return mImpl->mBackground->actor;
785 void Control::OnThemeChange( Toolkit::StyleManager styleManager )
787 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
790 void Control::OnPinch(PinchGesture pinch)
792 if( !( mImpl->mStartingPinchScale ) )
795 mImpl->mStartingPinchScale = new Vector3;
798 if( pinch.state == Gesture::Started )
800 *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
803 Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
806 void Control::OnStageConnection()
810 // Notify derived classes.
811 OnControlStageConnection();
814 void Control::OnStageDisconnection()
816 // Notify derived classes
817 OnControlStageDisconnection();
820 void Control::OnChildAdd(Actor& child)
822 // If this is the background actor, then we do not want to relayout or inform deriving classes
823 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
828 // Request for relayout as we may need to position the new child and old ones
831 // Notify derived classes.
832 OnControlChildAdd( child );
835 void Control::OnChildRemove(Actor& child)
837 // If this is the background actor, then we do not want to relayout or inform deriving classes
838 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
843 // Request for relayout as we may need to re-position the old child
846 // Notify derived classes.
847 OnControlChildRemove( child );
850 void Control::OnSizeSet(const Vector3& targetSize)
852 if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
854 // Only updates size if set through Actor's API
855 mImpl->mNaturalSize = targetSize;
858 if( targetSize != mImpl->mCurrentSize )
860 // Update control size.
861 mImpl->mCurrentSize = targetSize;
863 // Notify derived classes.
864 OnControlSizeSet( targetSize );
868 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
870 // @todo consider animating negotiated child sizes to target size
873 bool Control::OnTouchEvent(const TouchEvent& event)
875 return false; // Do not consume
878 bool Control::OnHoverEvent(const HoverEvent& event)
880 return false; // Do not consume
883 bool Control::OnKeyEvent(const KeyEvent& event)
885 return false; // Do not consume
888 bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
890 return false; // Do not consume
893 void Control::OnKeyInputFocusGained()
898 void Control::OnKeyInputFocusLost()
903 Actor Control::GetChildByAlias(const std::string& actorAlias)
908 bool Control::OnAccessibilityPan(PanGesture gesture)
910 return false; // Accessibility pan gesture is not handled by default
913 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
915 return false; // Accessibility touch event is not handled by default
918 bool Control::OnAccessibilityValueChange(bool isIncrease)
920 return false; // Accessibility value change action is not handled by default
924 void Control::SetKeyboardNavigationSupport(bool isSupported)
926 mImpl->mIsKeyboardNavigationSupported = isSupported;
929 bool Control::IsKeyboardNavigationSupported()
931 return mImpl->mIsKeyboardNavigationSupported;
934 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
936 mImpl->mIsKeyboardFocusGroup = isFocusGroup;
938 // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
939 Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
942 bool Control::IsKeyboardFocusGroup()
944 return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
947 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
952 bool Control::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
956 if( object && (actionName == Toolkit::Control::ACTION_CONTROL_ACTIVATED) )
958 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
961 // if cast succeeds there is an implementation so no need to check
962 control.GetImplementation().OnActivated();
969 bool Control::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
971 Dali::BaseHandle handle( object );
973 bool connected( false );
974 Toolkit::Control control = Toolkit::Control::DownCast(handle);
977 Control& controlImpl( control.GetImplementation() );
980 if ( Toolkit::Control::SIGNAL_KEY_EVENT == signalName )
982 controlImpl.KeyEventSignal().Connect( tracker, functor );
984 else if( Toolkit::Control::SIGNAL_TAPPED == signalName )
986 controlImpl.EnableGestureDetection( Gesture::Tap );
987 controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
989 else if( Toolkit::Control::SIGNAL_PANNED == signalName )
991 controlImpl.EnableGestureDetection( Gesture::Pan );
992 controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
994 else if( Toolkit::Control::SIGNAL_PINCHED == signalName )
996 controlImpl.EnableGestureDetection( Gesture::Pinch );
997 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
999 else if( Toolkit::Control::SIGNAL_LONG_PRESSED == signalName )
1001 controlImpl.EnableGestureDetection( Gesture::LongPress );
1002 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
1006 // signalName does not match any signal
1013 void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
1015 if( change.themeChange )
1017 OnThemeChange( styleManager );
1019 else if( change.defaultFontChange || change.defaultFontSizeChange )
1021 OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
1025 Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
1027 return mImpl->mKeyEventSignalV2;
1030 void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
1032 bool relayoutRequest( false );
1034 if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
1036 relayoutRequest = true;
1039 mImpl->mWidthPolicy = widthPolicy;
1040 mImpl->mHeightPolicy = heightPolicy;
1042 // Ensure RelayoutRequest is called AFTER new policies have been set.
1043 if ( relayoutRequest )
1049 void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
1051 widthPolicy = mImpl->mWidthPolicy;
1052 heightPolicy = mImpl->mHeightPolicy;
1055 void Control::SetMinimumSize( const Vector3& size )
1057 const Vector3& minSize = mImpl->GetMinimumSize();
1058 if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1059 fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1061 mImpl->SetMinimumSize( size );
1063 // Only relayout if our control is using the minimum or range policy.
1064 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Minimum ) ||
1065 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1072 const Vector3& Control::GetMinimumSize() const
1074 return mImpl->GetMinimumSize();
1077 void Control::SetMaximumSize( const Vector3& size )
1079 const Vector3& maxSize = mImpl->GetMaximumSize();
1080 if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
1081 fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
1083 mImpl->SetMaximumSize( size );
1085 // Only relayout if our control is using the maximum or range policy.
1086 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Maximum ) ||
1087 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
1094 const Vector3& Control::GetMaximumSize() const
1096 return mImpl->GetMaximumSize();
1099 Vector3 Control::GetNaturalSize()
1101 // could be overridden in derived classes.
1102 return mImpl->mNaturalSize;
1105 float Control::GetHeightForWidth( float width )
1107 // could be overridden in derived classes.
1108 float height( 0.0f );
1109 if ( mImpl->mNaturalSize.width > 0.0f )
1111 height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
1116 float Control::GetWidthForHeight( float height )
1118 // could be overridden in derived classes.
1119 float width( 0.0f );
1120 if ( mImpl->mNaturalSize.height > 0.0f )
1122 width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
1127 const Vector3& Control::GetControlSize() const
1129 return mImpl->mCurrentSize;
1132 const Vector3& Control::GetSizeSet() const
1134 return mImpl->mNaturalSize;
1137 void Control::SetKeyInputFocus()
1139 if( Self().OnStage() )
1141 Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
1145 bool Control::HasKeyInputFocus()
1147 bool result = false;
1148 if( Self().OnStage() )
1150 result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
1155 void Control::ClearKeyInputFocus()
1157 if( Self().OnStage() )
1159 Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
1163 void Control::RelayoutRequest()
1165 // unfortunate double negative but thats to guarantee new controls get size negotiation
1166 // by default and have to "opt-out" if they dont want it
1167 if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
1169 Internal::RelayoutController::Request();
1173 void Control::Relayout(Vector2 size, ActorSizeContainer& container)
1175 // Avoids relayout again when OnSizeSet callback arrives.
1176 mImpl->mInsideRelayout = true;
1177 Self().SetSize( size );
1178 // @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
1179 mImpl->mInsideRelayout = false;
1181 // Only relayout controls which requested to be relaid out.
1182 OnRelaidOut( size, container );
1185 void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
1189 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
1192 control.GetImplementation().NegotiateSize( size, container );
1196 container.push_back( ActorSizePair( actor, size ) );
1201 void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1203 unsigned int numChildren = Self().GetChildCount();
1205 for( unsigned int i=0; i<numChildren; ++i )
1207 container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
1211 void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
1215 if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
1217 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1219 // If a control says it has a fixed size, then use the size set by the application / control.
1220 Vector2 setSize( mImpl->mNaturalSize );
1221 if ( setSize != Vector2::ZERO )
1225 // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
1226 // then we should use the natural size of the control rather than the full allocation.
1227 if ( EqualsZero( size.width ) )
1229 size.width = GetWidthForHeight( size.height );
1231 else if ( EqualsZero( size.height ) )
1233 size.height = GetHeightForWidth( size.width );
1238 // If that is not set then set the size to the control's natural size
1239 size = Vector2( GetNaturalSize() );
1244 // Width is fixed so if the application / control has set it, then use that.
1245 if ( !EqualsZero( mImpl->mNaturalSize.width ) )
1247 size.width = mImpl->mNaturalSize.width;
1251 // Otherwise, set the width to what has been allocated.
1252 size.width = allocatedSize.width;
1255 // Height is flexible so ask control what the height should be for our width.
1256 size.height = GetHeightForWidth( size.width );
1258 // Ensure height is within our policy rules
1259 size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
1264 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
1266 // Height is fixed so if the application / control has set it, then use that.
1267 if ( !EqualsZero( mImpl->mNaturalSize.height ) )
1269 size.height = mImpl->mNaturalSize.height;
1273 // Otherwise, set the height to what has been allocated.
1274 size.height = allocatedSize.height;
1277 // Width is flexible so ask control what the width should be for our height.
1278 size.width = GetWidthForHeight( size.height );
1280 // Ensure width is within our policy rules
1281 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
1285 // Width and height are BOTH flexible.
1286 // Calculate the width and height using the policy rules.
1287 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
1288 size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
1292 // If the width has not been set, then set to the allocated width.
1293 // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
1294 if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
1296 size.width = allocatedSize.width;
1299 // If the height has not been set, then set to the allocated height.
1300 // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
1301 if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
1303 size.height = allocatedSize.height;
1306 DALI_LOG_INFO( gLogFilter, Debug::Verbose,
1307 "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
1308 Self().GetObjectPtr(),
1309 GetNaturalSize().x, GetNaturalSize().y,
1310 allocatedSize.x, allocatedSize.y,
1313 Relayout( size, container );
1316 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1318 // Guard against destruction during signal emission
1319 Dali::Toolkit::Control handle( GetOwner() );
1321 bool consumed = false;
1323 // signals are allocated dynamically when someone connects
1324 if ( !mImpl->mKeyEventSignalV2.Empty() )
1326 consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1331 // Notification for derived classes
1332 consumed = OnKeyEvent(event);
1338 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1340 mImpl->SignalConnected( slotObserver, callback );
1343 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1345 mImpl->SignalDisconnected( slotObserver, callback );
1348 Control::Control( ControlBehaviour behaviourFlags )
1349 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
1350 mImpl(new Impl(*this))
1352 mImpl->mFlags = behaviourFlags;
1355 } // namespace Internal
1357 } // namespace Toolkit