2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/public-api/actors/image-actor.h>
24 #include <dali/public-api/actors/mesh-actor.h>
25 #include <dali/public-api/animation/constraints.h>
26 #include <dali/public-api/geometry/mesh.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/scripting/scripting.h>
29 #include <dali/integration-api/debug.h>
31 #include <dali-toolkit/internal/controls/relayout-controller.h>
32 #include <dali-toolkit/internal/controls/relayout-helper.h>
33 #include <dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h>
34 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
35 #include <dali-toolkit/public-api/controls/control.h>
36 #include <dali-toolkit/public-api/styling/style-manager.h>
37 #include <dali-toolkit/internal/styling/style-manager-impl.h>
45 const Property::Index Control::PROPERTY_BACKGROUND_COLOR = Internal::Control::CONTROL_PROPERTY_START_INDEX;
46 const Property::Index Control::PROPERTY_BACKGROUND = Internal::Control::CONTROL_PROPERTY_START_INDEX + 1;
47 const Property::Index Control::PROPERTY_WIDTH_POLICY = Internal::Control::CONTROL_PROPERTY_START_INDEX + 2;
48 const Property::Index Control::PROPERTY_HEIGHT_POLICY = Internal::Control::CONTROL_PROPERTY_START_INDEX + 3;
49 const Property::Index Control::PROPERTY_MINIMUM_SIZE = Internal::Control::CONTROL_PROPERTY_START_INDEX + 4;
50 const Property::Index Control::PROPERTY_MAXIMUM_SIZE = Internal::Control::CONTROL_PROPERTY_START_INDEX + 5;
51 const Property::Index Control::PROPERTY_KEY_INPUT_FOCUS = Internal::Control::CONTROL_PROPERTY_START_INDEX + 6;
56 const Scripting::StringEnum< Control::SizePolicy > SIZE_POLICY_STRING_TABLE[] =
58 { "FIXED", Control::Fixed },
59 { "MINIMUM", Control::Minimum },
60 { "MAXIMUM", Control::Maximum },
61 { "RANGE", Control::Range },
62 { "FLEXIBLE", Control::Flexible },
64 const unsigned int SIZE_POLICY_STRING_TABLE_COUNT = sizeof( SIZE_POLICY_STRING_TABLE ) / sizeof( SIZE_POLICY_STRING_TABLE[0] );
66 #if defined(DEBUG_ENABLED)
67 Integration::Log::Filter* gLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_CONTROL");
70 const float MAX_FLOAT_VALUE( std::numeric_limits<float>::max() );
71 const Vector3 MAX_SIZE( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE );
72 const float BACKGROUND_ACTOR_Z_POSITION( -0.1f );
76 return Internal::Control::New();
79 TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
81 // Property Registration after Internal::Control::Impl definition below
83 TypeAction ACTION_TYPE_1( CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &Internal::Control::DoAction );
85 SignalConnectorType SIGNAL_CONNECTOR_1( CONTROL_TYPE, Toolkit::Control::SIGNAL_KEY_EVENT, &Internal::Control::DoConnectSignal );
86 SignalConnectorType SIGNAL_CONNECTOR_2( CONTROL_TYPE, Toolkit::Control::SIGNAL_TAPPED, &Internal::Control::DoConnectSignal );
87 SignalConnectorType SIGNAL_CONNECTOR_3( CONTROL_TYPE, Toolkit::Control::SIGNAL_PANNED, &Internal::Control::DoConnectSignal );
88 SignalConnectorType SIGNAL_CONNECTOR_4( CONTROL_TYPE, Toolkit::Control::SIGNAL_PINCHED, &Internal::Control::DoConnectSignal );
89 SignalConnectorType SIGNAL_CONNECTOR_5( CONTROL_TYPE, Toolkit::Control::SIGNAL_LONG_PRESSED, &Internal::Control::DoConnectSignal );
92 * Structure which holds information about the background of a control
96 Actor actor; ///< Either a MeshActor or an ImageActor
97 Vector4 color; ///< The color of the actor.
104 color( Color::WHITE )
110 * Helper function to calculate a dimension given the policy of that dimension; the minimum &
111 * maximum values that dimension can be; and the allocated value for that dimension.
113 * @param[in] policy The size policy for that dimension.
114 * @param[in] minimum The minimum value that dimension can be.
115 * @param[in] maximum The maximum value that dimension can be.
116 * @param[in] allocated The value allocated for that dimension.
118 * @return The value that the dimension should be.
120 * @note This does not handle Control::Fixed policy.
122 float Calculate( Control::SizePolicy policy, float minimum, float maximum, float allocated )
124 float size( allocated );
130 // Use allocated value
134 case Control::Minimum:
136 // Size is always at least the minimum.
137 size = std::max( allocated, minimum );
141 case Control::Maximum:
143 // Size can grow but up to a maximum value.
144 size = std::min( allocated, maximum );
150 // Size is at least the minimum and can grow up to the maximum
151 size = std::max( size, minimum );
152 size = std::min( size, maximum );
156 case Control::Flexible:
158 // Size grows or shrinks with no limits.
165 DALI_ASSERT_DEBUG( false && "This function was not intended to be used by any other policy." );
174 * Creates a white coloured Mesh.
178 Vector3 white( Color::WHITE );
182 // Create vertices with a white color (actual color is set by actor color)
183 MeshData::VertexContainer vertices(4);
184 vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
185 vertices[ 1 ] = MeshData::Vertex( Vector3( 0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
186 vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
187 vertices[ 3 ] = MeshData::Vertex( Vector3( 0.5f, 0.5f, 0.0f ), Vector2::ZERO, white );
189 // Specify all the faces
190 MeshData::FaceIndices faces;
191 faces.reserve( 6 ); // 2 triangles in Quad
192 faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
193 faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
195 // Create the mesh data from the vertices and faces
196 meshData.SetMaterial( Material::New( "ControlMaterial" ) );
197 meshData.SetVertices( vertices );
198 meshData.SetFaceIndices( faces );
199 meshData.SetHasColor( true );
201 return Mesh::New( meshData );
205 * Sets all the required properties for the background actor.
207 * @param[in] actor The actor to set the properties on.
208 * @param[in] constrainingIndex The property index to constrain the parent's size on.
209 * @param[in] color The required color of the actor.
211 void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const Vector4& color )
213 actor.SetColor( color );
214 actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
215 actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
216 actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
218 Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
219 ParentSource( Actor::SIZE ),
220 EqualToConstraint() );
221 actor.ApplyConstraint( constraint );
224 } // unnamed namespace
229 class Control::Impl : public ConnectionTracker
234 * Size indices for mMinMaxSize array
243 // Construction & Destruction
244 Impl(Control& controlImpl)
245 : mControlImpl( controlImpl ),
247 mStartingPinchScale( NULL ),
249 mPinchGestureDetector(),
250 mPanGestureDetector(),
251 mTapGestureDetector(),
252 mLongPressGestureDetector(),
255 mWidthPolicy( Toolkit::Control::Fixed ),
256 mHeightPolicy( Toolkit::Control::Fixed ),
257 mFlags( Control::CONTROL_BEHAVIOUR_NONE ),
258 mInsideRelayout( false ),
259 mIsKeyboardNavigationSupported( false ),
260 mIsKeyboardFocusGroup( false ),
261 mInitialized( false )
267 // All gesture detectors will be destroyed so no need to disconnect.
269 delete mStartingPinchScale;
272 // Gesture Detection Methods
274 void PinchDetected(Actor actor, const PinchGesture& pinch)
276 mControlImpl.OnPinch(pinch);
279 void PanDetected(Actor actor, const PanGesture& pan)
281 mControlImpl.OnPan(pan);
284 void TapDetected(Actor actor, const TapGesture& tap)
286 mControlImpl.OnTap(tap);
289 void LongPressDetected(Actor actor, const LongPressGesture& longPress)
291 mControlImpl.OnLongPress(longPress);
294 // Background Methods
297 * Only creates an instance of the background if we actually use it.
298 * @return A reference to the Background structure.
300 Background& GetBackground()
304 mBackground = new Background;
312 * Called when a property of an object of this type is set.
313 * @param[in] object The object whose property is set.
314 * @param[in] index The property index.
315 * @param[in] value The new property value.
317 static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
319 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
323 Control& controlImpl( control.GetImplementation() );
327 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
329 controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
333 case Toolkit::Control::PROPERTY_BACKGROUND:
335 if ( value.HasKey( "image" ) )
337 Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
338 Image image = Scripting::NewImage( imageMap );
342 controlImpl.SetBackground( image );
345 else if ( value.Get< Property::Map >().Empty() )
347 // An empty map means the background is no longer required
348 controlImpl.ClearBackground();
353 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
355 controlImpl.mImpl->mWidthPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
359 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
361 controlImpl.mImpl->mHeightPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
365 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
367 controlImpl.SetMinimumSize( value.Get< Vector3 >() );
371 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
373 controlImpl.SetMaximumSize( value.Get< Vector3 >() );
377 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
379 if ( value.Get< bool >() )
381 controlImpl.SetKeyInputFocus();
385 controlImpl.ClearKeyInputFocus();
394 * Called to retrieve a property of an object of this type.
395 * @param[in] object The object whose property is to be retrieved.
396 * @param[in] index The property index.
397 * @return The current value of the property.
399 static Property::Value GetProperty( BaseObject* object, Property::Index index )
401 Property::Value value;
403 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
407 Control& controlImpl( control.GetImplementation() );
411 case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
413 value = controlImpl.GetBackgroundColor();
417 case Toolkit::Control::PROPERTY_BACKGROUND:
421 Actor actor = controlImpl.GetBackgroundActor();
424 ImageActor imageActor = ImageActor::DownCast( actor );
427 Image image = imageActor.GetImage();
428 Property::Map imageMap;
429 Scripting::CreatePropertyMap( image, imageMap );
430 map[ "image" ] = imageMap;
438 case Toolkit::Control::PROPERTY_WIDTH_POLICY:
440 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mWidthPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
444 case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
446 value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mHeightPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
450 case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
452 value = controlImpl.mImpl->GetMinimumSize();
456 case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
458 value = controlImpl.mImpl->GetMaximumSize();
462 case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
464 value = controlImpl.HasKeyInputFocus();
474 * Helper to get minimum size
475 * @return minimum size
477 inline const Vector3& GetMinimumSize()
479 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
481 return mMinMaxSize[ MIN_SIZE_INDEX ];
485 // its not been allocated so its ZERO
486 return Vector3::ZERO;
490 * Helper to Set minimum size
493 inline void SetMinimumSize( const Vector3& size )
495 if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
497 mMinMaxSize[ MIN_SIZE_INDEX ] = size;
501 // its not been allocated so push the new value there
502 mMinMaxSize.PushBack( size );
507 * Helper to get maximum size
508 * @return maximum size
510 inline const Vector3& GetMaximumSize()
512 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
514 return mMinMaxSize[ MAX_SIZE_INDEX ];
518 // its not been allocated so its MAX_SIZE
524 * Helper to Set minimum size
527 inline void SetMaximumSize( const Vector3& size )
529 if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
531 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
533 else if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
535 // max has not been allocated, but min has
536 mMinMaxSize.PushBack( size );
540 // min and max both unallocated so allocate both
541 mMinMaxSize.Resize( 2u ); // this will reserve and default construct two Vector3s
542 mMinMaxSize[ MAX_SIZE_INDEX ] = size;
548 Control& mControlImpl;
549 Background* mBackground; ///< Only create the background if we use it
550 Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this
551 Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
554 PinchGestureDetector mPinchGestureDetector;
555 PanGestureDetector mPanGestureDetector;
556 TapGestureDetector mTapGestureDetector;
557 LongPressGestureDetector mLongPressGestureDetector;
558 // @todo change all these to Vector2 when we have a chance to sanitize the public API as well
559 Vector3 mCurrentSize; ///< Stores the current control's size, this is the negotiated size
560 Vector3 mNaturalSize; ///< Stores the size set through the Actor's API. This is size the actor wants to be. Useful when reset to the initial size is needed.
561 Dali::Vector< Vector3 > mMinMaxSize; ///< Stores the minimum and maximum size if they are set
563 Toolkit::Control::SizePolicy mWidthPolicy :3; ///< Stores the width policy. 3 bits covers 8 values
564 Toolkit::Control::SizePolicy mHeightPolicy :3; ///< Stores the height policy. 3 bits covers 8 values
565 ControlBehaviour mFlags :6; ///< Flags passed in from constructor. Need to increase this size when new enums are added
566 bool mInsideRelayout:1; ///< Detect when were in Relayout
567 bool mIsKeyboardNavigationSupported:1; ///< Stores whether keyboard navigation is supported by the control.
568 bool mIsKeyboardFocusGroup:1; ///< Stores whether the control is a focus group.
571 // Properties - these need to be members of Internal::Control::Impl as they need to functions within this class.
572 static PropertyRegistration PROPERTY_1;
573 static PropertyRegistration PROPERTY_2;
574 static PropertyRegistration PROPERTY_3;
575 static PropertyRegistration PROPERTY_4;
576 static PropertyRegistration PROPERTY_5;
577 static PropertyRegistration PROPERTY_6;
578 static PropertyRegistration PROPERTY_7;
581 PropertyRegistration Control::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Toolkit::Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
582 PropertyRegistration Control::Impl::PROPERTY_2( CONTROL_TYPE, "background", Toolkit::Control::PROPERTY_BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
583 PropertyRegistration Control::Impl::PROPERTY_3( CONTROL_TYPE, "width-policy", Toolkit::Control::PROPERTY_WIDTH_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
584 PropertyRegistration Control::Impl::PROPERTY_4( CONTROL_TYPE, "height-policy", Toolkit::Control::PROPERTY_HEIGHT_POLICY, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
585 PropertyRegistration Control::Impl::PROPERTY_5( CONTROL_TYPE, "minimum-size", Toolkit::Control::PROPERTY_MINIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
586 PropertyRegistration Control::Impl::PROPERTY_6( CONTROL_TYPE, "maximum-size", Toolkit::Control::PROPERTY_MAXIMUM_SIZE, Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
587 PropertyRegistration Control::Impl::PROPERTY_7( CONTROL_TYPE, "key-input-focus", Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
589 Toolkit::Control Control::New()
591 // Create the implementation, temporarily owned on stack
592 IntrusivePtr<Control> controlImpl = new Control( CONTROL_BEHAVIOUR_NONE );
594 // Pass ownership to handle
595 Toolkit::Control handle( *controlImpl );
597 // Second-phase init of the implementation
598 // This can only be done after the CustomActor connection has been made...
599 controlImpl->Initialize();
609 void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
611 bool relayoutRequest( false );
613 if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
615 relayoutRequest = true;
618 mImpl->mWidthPolicy = widthPolicy;
619 mImpl->mHeightPolicy = heightPolicy;
621 // Ensure RelayoutRequest is called AFTER new policies have been set.
622 if ( relayoutRequest )
628 void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
630 widthPolicy = mImpl->mWidthPolicy;
631 heightPolicy = mImpl->mHeightPolicy;
634 void Control::SetMinimumSize( const Vector3& size )
636 const Vector3& minSize = mImpl->GetMinimumSize();
637 if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
638 fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
640 mImpl->SetMinimumSize( size );
642 // Only relayout if our control is using the minimum or range policy.
643 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Minimum ) ||
644 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
651 const Vector3& Control::GetMinimumSize() const
653 return mImpl->GetMinimumSize();
656 void Control::SetMaximumSize( const Vector3& size )
658 const Vector3& maxSize = mImpl->GetMaximumSize();
659 if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
660 fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
662 mImpl->SetMaximumSize( size );
664 // Only relayout if our control is using the maximum or range policy.
665 if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy == Toolkit::Control::Maximum ) ||
666 ( mImpl->mHeightPolicy == Toolkit::Control::Range ) || ( mImpl->mWidthPolicy == Toolkit::Control::Range ) )
673 const Vector3& Control::GetMaximumSize() const
675 return mImpl->GetMaximumSize();
678 Vector3 Control::GetNaturalSize()
680 // could be overridden in derived classes.
681 return mImpl->mNaturalSize;
684 float Control::GetHeightForWidth( float width )
686 // could be overridden in derived classes.
687 float height( 0.0f );
688 if ( mImpl->mNaturalSize.width > 0.0f )
690 height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
695 float Control::GetWidthForHeight( float height )
697 // could be overridden in derived classes.
699 if ( mImpl->mNaturalSize.height > 0.0f )
701 width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
706 const Vector3& Control::GetControlSize() const
708 return mImpl->mCurrentSize;
711 const Vector3& Control::GetSizeSet() const
713 return mImpl->mNaturalSize;
716 void Control::SetKeyInputFocus()
718 if( Self().OnStage() )
720 Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
724 bool Control::HasKeyInputFocus()
727 if( Self().OnStage() )
729 result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
734 void Control::ClearKeyInputFocus()
736 if( Self().OnStage() )
738 Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
742 PinchGestureDetector Control::GetPinchGestureDetector() const
744 return mImpl->mPinchGestureDetector;
747 PanGestureDetector Control::GetPanGestureDetector() const
749 return mImpl->mPanGestureDetector;
752 TapGestureDetector Control::GetTapGestureDetector() const
754 return mImpl->mTapGestureDetector;
757 LongPressGestureDetector Control::GetLongPressGestureDetector() const
759 return mImpl->mLongPressGestureDetector;
762 void Control::SetBackgroundColor( const Vector4& color )
764 Background& background( mImpl->GetBackground() );
766 if ( background.actor )
768 // Just set the actor color
769 background.actor.SetColor( color );
774 MeshActor meshActor = MeshActor::New( CreateMesh() );
776 meshActor.SetAffectedByLighting( false );
777 SetupBackgroundActor( meshActor, Actor::SCALE, color );
779 // Set the background actor before adding so that we do not inform deriving classes
780 background.actor = meshActor;
781 Self().Add( meshActor );
784 background.color = color;
787 Vector4 Control::GetBackgroundColor() const
789 if ( mImpl->mBackground )
791 return mImpl->mBackground->color;
793 return Color::TRANSPARENT;
796 void Control::SetBackground( Image image )
798 Background& background( mImpl->GetBackground() );
800 if ( background.actor )
802 // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
803 Self().Remove( background.actor );
804 background.actor.Reset();
807 ImageActor imageActor = ImageActor::New( image );
808 SetupBackgroundActor( imageActor, Actor::SIZE, background.color );
810 // Set the background actor before adding so that we do not inform derived classes
811 background.actor = imageActor;
812 Self().Add( imageActor );
815 void Control::ClearBackground()
817 if ( mImpl->mBackground )
819 Background& background( mImpl->GetBackground() );
820 Self().Remove( background.actor );
822 delete mImpl->mBackground;
823 mImpl->mBackground = NULL;
827 Actor Control::GetBackgroundActor() const
829 if ( mImpl->mBackground )
831 return mImpl->mBackground->actor;
837 void Control::SetKeyboardNavigationSupport(bool isSupported)
839 mImpl->mIsKeyboardNavigationSupported = isSupported;
842 bool Control::IsKeyboardNavigationSupported()
844 return mImpl->mIsKeyboardNavigationSupported;
847 void Control::Activate()
849 // Inform deriving classes
853 bool Control::OnAccessibilityPan(PanGesture gesture)
855 return false; // Accessibility pan gesture is not handled by default
858 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
860 return false; // Accessibility touch event is not handled by default
863 bool Control::OnAccessibilityValueChange(bool isIncrease)
865 return false; // Accessibility value change action is not handled by default
868 void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
872 if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
874 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
876 // If a control says it has a fixed size, then use the size set by the application / control.
877 Vector2 setSize( mImpl->mNaturalSize );
878 if ( setSize != Vector2::ZERO )
882 // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
883 // then we should use the natural size of the control rather than the full allocation.
884 if ( EqualsZero( size.width ) )
886 size.width = GetWidthForHeight( size.height );
888 else if ( EqualsZero( size.height ) )
890 size.height = GetHeightForWidth( size.width );
895 // If that is not set then set the size to the control's natural size
896 size = Vector2( GetNaturalSize() );
901 // Width is fixed so if the application / control has set it, then use that.
902 if ( !EqualsZero( mImpl->mNaturalSize.width ) )
904 size.width = mImpl->mNaturalSize.width;
908 // Otherwise, set the width to what has been allocated.
909 size.width = allocatedSize.width;
912 // Height is flexible so ask control what the height should be for our width.
913 size.height = GetHeightForWidth( size.width );
915 // Ensure height is within our policy rules
916 size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
921 if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
923 // Height is fixed so if the application / control has set it, then use that.
924 if ( !EqualsZero( mImpl->mNaturalSize.height ) )
926 size.height = mImpl->mNaturalSize.height;
930 // Otherwise, set the height to what has been allocated.
931 size.height = allocatedSize.height;
934 // Width is flexible so ask control what the width should be for our height.
935 size.width = GetWidthForHeight( size.height );
937 // Ensure width is within our policy rules
938 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
942 // Width and height are BOTH flexible.
943 // Calculate the width and height using the policy rules.
944 size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
945 size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
949 // If the width has not been set, then set to the allocated width.
950 // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
951 if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
953 size.width = allocatedSize.width;
956 // If the height has not been set, then set to the allocated height.
957 // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
958 if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
960 size.height = allocatedSize.height;
963 DALI_LOG_INFO( gLogFilter, Debug::Verbose,
964 "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
965 Self().GetObjectPtr(),
966 GetNaturalSize().x, GetNaturalSize().y,
967 allocatedSize.x, allocatedSize.y,
970 Relayout( size, container );
973 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
975 mImpl->mIsKeyboardFocusGroup = isFocusGroup;
977 // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
978 Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
981 bool Control::IsKeyboardFocusGroup()
983 return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
986 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
991 void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
995 bool Control::DoAction(BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes)
999 if( object && (actionName == Toolkit::Control::ACTION_CONTROL_ACTIVATED) )
1001 Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1004 // if cast succeeds there is an implementation so no need to check
1005 control.GetImplementation().OnActivated();
1012 bool Control::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1014 Dali::BaseHandle handle( object );
1016 bool connected( false );
1017 Toolkit::Control control = Toolkit::Control::DownCast(handle);
1020 Control& controlImpl( control.GetImplementation() );
1023 if ( Toolkit::Control::SIGNAL_KEY_EVENT == signalName )
1025 controlImpl.KeyEventSignal().Connect( tracker, functor );
1027 else if( Toolkit::Control::SIGNAL_TAPPED == signalName )
1029 controlImpl.EnableGestureDetection( Gesture::Tap );
1030 controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
1032 else if( Toolkit::Control::SIGNAL_PANNED == signalName )
1034 controlImpl.EnableGestureDetection( Gesture::Pan );
1035 controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
1037 else if( Toolkit::Control::SIGNAL_PINCHED == signalName )
1039 controlImpl.EnableGestureDetection( Gesture::Pinch );
1040 controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
1042 else if( Toolkit::Control::SIGNAL_LONG_PRESSED == signalName )
1044 controlImpl.EnableGestureDetection( Gesture::LongPress );
1045 controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
1049 // signalName does not match any signal
1056 Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
1058 return mImpl->mKeyEventSignalV2;
1061 bool Control::EmitKeyEventSignal( const KeyEvent& event )
1063 // Guard against destruction during signal emission
1064 Dali::Toolkit::Control handle( GetOwner() );
1066 bool consumed = false;
1068 // signals are allocated dynamically when someone connects
1069 if ( !mImpl->mKeyEventSignalV2.Empty() )
1071 consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
1076 // Notification for derived classes
1077 consumed = OnKeyEvent(event);
1083 Control::Control( ControlBehaviour behaviourFlags )
1084 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
1085 mImpl(new Impl(*this))
1087 mImpl->mFlags = behaviourFlags;
1090 void Control::Initialize()
1093 // Calling deriving classes
1096 if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
1098 Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1100 // Register for style changes
1101 styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange );
1104 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
1107 SetRequiresHoverEvents(mImpl->mFlags & REQUIRES_HOVER_EVENTS);
1108 SetRequiresMouseWheelEvents(mImpl->mFlags & REQUIRES_MOUSE_WHEEL_EVENTS);
1110 mImpl->mInitialized = true;
1113 void Control::EnableGestureDetection(Gesture::Type type)
1115 if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
1117 mImpl->mPinchGestureDetector = PinchGestureDetector::New();
1118 mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
1119 mImpl->mPinchGestureDetector.Attach(Self());
1122 if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
1124 mImpl->mPanGestureDetector = PanGestureDetector::New();
1125 mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
1126 mImpl->mPanGestureDetector.Attach(Self());
1129 if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
1131 mImpl->mTapGestureDetector = TapGestureDetector::New();
1132 mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
1133 mImpl->mTapGestureDetector.Attach(Self());
1136 if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
1138 mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
1139 mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
1140 mImpl->mLongPressGestureDetector.Attach(Self());
1144 void Control::DisableGestureDetection(Gesture::Type type)
1146 if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
1148 mImpl->mPinchGestureDetector.Detach(Self());
1149 mImpl->mPinchGestureDetector.Reset();
1152 if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
1154 mImpl->mPanGestureDetector.Detach(Self());
1155 mImpl->mPanGestureDetector.Reset();
1158 if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
1160 mImpl->mTapGestureDetector.Detach(Self());
1161 mImpl->mTapGestureDetector.Reset();
1164 if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
1166 mImpl->mLongPressGestureDetector.Detach(Self());
1167 mImpl->mLongPressGestureDetector.Reset();
1171 void Control::RelayoutRequest()
1173 // unfortunate double negative but thats to guarantee new controls get size negotiation
1174 // by default and have to "opt-out" if they dont want it
1175 if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
1177 Internal::RelayoutController::Request();
1181 void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
1185 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
1188 control.GetImplementation().NegotiateSize( size, container );
1192 container.push_back( ActorSizePair( actor, size ) );
1197 void Control::OnInitialize()
1201 void Control::OnActivated()
1205 void Control::OnThemeChange( Toolkit::StyleManager styleManager )
1207 GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
1210 void Control::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
1214 void Control::OnPinch(const PinchGesture& pinch)
1216 if( !( mImpl->mStartingPinchScale ) )
1219 mImpl->mStartingPinchScale = new Vector3;
1222 if( pinch.state == Gesture::Started )
1224 *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
1227 Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
1230 void Control::OnPan( const PanGesture& pan )
1234 void Control::OnTap(const TapGesture& tap)
1238 void Control::OnLongPress( const LongPressGesture& longPress )
1242 void Control::OnControlStageConnection()
1246 void Control::OnControlStageDisconnection()
1250 void Control::OnControlChildAdd( Actor& child )
1254 void Control::OnControlChildRemove( Actor& child )
1258 void Control::OnControlSizeSet( const Vector3& size )
1262 void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1264 unsigned int numChildren = Self().GetChildCount();
1266 for( unsigned int i=0; i<numChildren; ++i )
1268 container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
1272 void Control::OnKeyInputFocusGained()
1277 void Control::OnKeyInputFocusLost()
1282 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
1284 // @todo consider animating negotiated child sizes to target size
1287 bool Control::OnTouchEvent(const TouchEvent& event)
1289 return false; // Do not consume
1292 bool Control::OnHoverEvent(const HoverEvent& event)
1294 return false; // Do not consume
1297 bool Control::OnKeyEvent(const KeyEvent& event)
1299 return false; // Do not consume
1302 bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
1304 return false; // Do not consume
1307 Actor Control::GetChildByAlias(const std::string& actorAlias)
1312 void Control::OnStageConnection()
1316 // Notify derived classes.
1317 OnControlStageConnection();
1320 void Control::OnStageDisconnection()
1322 // Notify derived classes
1323 OnControlStageDisconnection();
1326 void Control::OnChildAdd(Actor& child)
1328 // If this is the background actor, then we do not want to relayout or inform deriving classes
1329 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
1334 // Request for relayout as we may need to position the new child and old ones
1337 // Notify derived classes.
1338 OnControlChildAdd( child );
1341 void Control::OnChildRemove(Actor& child)
1343 // If this is the background actor, then we do not want to relayout or inform deriving classes
1344 if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
1349 // Request for relayout as we may need to re-position the old child
1352 // Notify derived classes.
1353 OnControlChildRemove( child );
1356 void Control::OnSizeSet(const Vector3& targetSize)
1358 if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
1360 // Only updates size if set through Actor's API
1361 mImpl->mNaturalSize = targetSize;
1364 if( targetSize != mImpl->mCurrentSize )
1366 // Update control size.
1367 mImpl->mCurrentSize = targetSize;
1369 // Notify derived classes.
1370 OnControlSizeSet( targetSize );
1374 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1376 mImpl->SignalConnected( slotObserver, callback );
1379 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1381 mImpl->SignalDisconnected( slotObserver, callback );
1384 void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
1386 if( change.themeChange )
1388 OnThemeChange( styleManager );
1390 else if( change.defaultFontChange || change.defaultFontSizeChange )
1392 OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
1396 void Control::Relayout(Vector2 size, ActorSizeContainer& container)
1398 // Avoids relayout again when OnSizeSet callback arrives.
1399 mImpl->mInsideRelayout = true;
1400 Self().SetSize( size );
1401 // @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
1402 mImpl->mInsideRelayout = false;
1404 // Only relayout controls which requested to be relaid out.
1405 OnRelaidOut( size, container );
1408 } // namespace Internal
1410 } // namespace Toolkit