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 "push-button-impl.h"
22 #include <dali/public-api/object/type-registry.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/public-api/images/resource-image.h>
25 #include <dali/devel-api/scripting/scripting.h>
28 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
29 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
43 const float ANIMATION_TIME( 0.2f );
44 const Padding DEFAULT_LABEL_PADDING( 12.0f, 12.0f, 12.0f, 12.0f );
45 const Padding DEFAULT_ICON_PADDING( 12.0f, 12.0f, 12.0f, 12.0f );
49 return Toolkit::PushButton::New();
54 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::PushButton, Toolkit::Button, Create )
56 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "unselectedIcon", STRING, UNSELECTED_ICON )
57 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "selectedIcon", STRING, SELECTED_ICON )
58 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "iconAlignment", STRING, ICON_ALIGNMENT )
59 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "labelPadding", STRING, LABEL_PADDING )
60 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "iconPadding", STRING, ICON_PADDING )
62 DALI_TYPE_REGISTRATION_END()
65 * Table to define Text-to-enum conversions for IconAlignment.
67 const Dali::Scripting::StringEnum IconAlignmentTable[] = {
68 { "LEFT", Toolkit::Internal::PushButton::LEFT },
69 { "RIGHT", Toolkit::Internal::PushButton::RIGHT },
70 { "TOP", Toolkit::Internal::PushButton::TOP },
71 { "BOTTOM", Toolkit::Internal::PushButton::BOTTOM },
72 }; const unsigned int IconAlignmentTableCount = sizeof( IconAlignmentTable ) / sizeof( IconAlignmentTable[0] );
74 const char* const UNSELECTED_BUTTON_IMAGE_DIR = DALI_IMAGE_DIR "button-up.9.png";
75 const char* const SELECTED_BUTTON_IMAGE_DIR = DALI_IMAGE_DIR "button-down.9.png";
76 const char* const DISABLED_UNSELECTED_BUTTON_IMAGE_DIR = DALI_IMAGE_DIR "button-disabled.9.png";
77 const char* const DISABLED_SELECTED_BUTTON_IMAGE_DIR = DALI_IMAGE_DIR "button-down-disabled.9.png";
79 } // unnamed namespace
85 * Get size of Actor if larger than given size
86 * @param[in] root the actor to get the size of
87 * @param[out] size the greater of the given size or the size of the Actor
89 void SizeOfActorIfLarger( Actor root, Vector3& size )
93 // RelayoutSize retreived for Actor to use any padding set to it.
94 size.width = std::max( root.GetRelayoutSize( Dimension::WIDTH ), size.width );
95 size.height = std::max( root.GetRelayoutSize( Dimension::HEIGHT ), size.height );
99 } // unnamed namespace
101 Dali::Toolkit::PushButton PushButton::New()
103 // Create the implementation, temporarily owned on stack
104 IntrusivePtr< PushButton > internalPushButton = new PushButton();
106 // Pass ownership to CustomActor
107 Dali::Toolkit::PushButton pushButton( *internalPushButton );
109 // Second-phase init of the implementation
110 // This can only be done after the CustomActor connection has been made...
111 internalPushButton->Initialize();
116 PushButton::PushButton()
118 mLabelPadding( DEFAULT_LABEL_PADDING ),
119 mIconPadding( DEFAULT_ICON_PADDING ),
120 mIconAlignment( RIGHT ),
123 SetAnimationTime( ANIMATION_TIME );
126 PushButton::~PushButton()
130 void PushButton::OnInitialize()
132 Button::OnInitialize();
134 // Push button requires the Leave event.
136 self.SetLeaveRequired( true );
138 // Set resize policy to natural size so that buttons will resize to background images
139 self.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
141 SetUnselectedImage( UNSELECTED_BUTTON_IMAGE_DIR );
142 SetSelectedImage( SELECTED_BUTTON_IMAGE_DIR );
143 SetDisabledImage( DISABLED_UNSELECTED_BUTTON_IMAGE_DIR );
144 SetDisabledSelectedImage( DISABLED_SELECTED_BUTTON_IMAGE_DIR );
147 void PushButton::SetIcon( DecorationState state, const std::string iconFilename )
149 mIconName[ state ] = iconFilename;
150 SetDecoration( state, Toolkit::ImageView::New( iconFilename ) );
151 ConfigureSizeNegotiation();
154 std::string& PushButton::GetIcon( DecorationState state )
156 return mIconName[ state ];
159 void PushButton::SetIconAlignment( const PushButton::IconAlignment iconAlignment )
161 mIconAlignment = iconAlignment;
162 ConfigureSizeNegotiation();
165 const PushButton::IconAlignment PushButton::GetIconAlignment() const
167 return mIconAlignment;
170 void PushButton::SetLabelPadding( const Vector4& padding )
172 mLabelPadding = Padding( padding.x, padding.y, padding.z, padding.w );
173 ConfigureSizeNegotiation();
176 Vector4 PushButton::GetLabelPadding()
178 return Vector4( mLabelPadding.left, mLabelPadding.right, mLabelPadding.top, mLabelPadding.bottom );
181 void PushButton::SetIconPadding( const Vector4& padding )
183 mIconPadding = Padding( padding.x, padding.y, padding.z, padding.w );
184 ConfigureSizeNegotiation();
187 Vector4 PushButton::GetIconPadding()
189 return Vector4( mIconPadding.left, mIconPadding.right, mIconPadding.top, mIconPadding.bottom );
192 void PushButton::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
194 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
198 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
200 switch ( propertyIndex )
202 case Toolkit::PushButton::Property::UNSELECTED_ICON:
204 pushButtonImpl.SetIcon( UNSELECTED_DECORATION, value.Get< std::string >() );
207 case Toolkit::PushButton::Property::SELECTED_ICON:
209 pushButtonImpl.SetIcon( SELECTED_DECORATION, value.Get< std::string >() );
212 case Toolkit::PushButton::Property::ICON_ALIGNMENT:
214 IconAlignment iconAlignment;
215 if( Scripting::GetEnumeration< IconAlignment >( value.Get< std::string >().c_str(), IconAlignmentTable, IconAlignmentTableCount, iconAlignment ) )
217 pushButtonImpl.SetIconAlignment( iconAlignment );
221 case Toolkit::PushButton::Property::LABEL_PADDING:
223 pushButtonImpl.SetLabelPadding( value.Get< Vector4 >() );
226 case Toolkit::PushButton::Property::ICON_PADDING:
228 pushButtonImpl.SetIconPadding( value.Get< Vector4 >() );
235 Property::Value PushButton::GetProperty( BaseObject* object, Property::Index propertyIndex )
237 Property::Value value;
239 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
243 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
245 switch ( propertyIndex )
247 case Toolkit::PushButton::Property::UNSELECTED_ICON:
249 value = pushButtonImpl.GetIcon( UNSELECTED_DECORATION );
252 case Toolkit::PushButton::Property::SELECTED_ICON:
254 value = pushButtonImpl.GetIcon( UNSELECTED_DECORATION );
257 case Toolkit::PushButton::Property::ICON_ALIGNMENT:
259 value = Scripting::GetLinearEnumerationName< IconAlignment >( pushButtonImpl.GetIconAlignment(), IconAlignmentTable, IconAlignmentTableCount );
262 case Toolkit::PushButton::Property::LABEL_PADDING:
264 value = pushButtonImpl.GetLabelPadding();
267 case Toolkit::PushButton::Property::ICON_PADDING:
269 value = pushButtonImpl.GetIconPadding();
278 void PushButton::OnLabelSet( bool noPadding )
280 Actor& label = GetLabelActor();
286 mLabelPadding = Padding( 0.0f, 0.0f, 0.0f, 0.0f );
289 Toolkit::TextLabel textLabel = Toolkit::TextLabel::DownCast( label );
292 textLabel.SetProperty( Toolkit::TextLabel::Property::MULTI_LINE, false );
295 ConfigureSizeNegotiation();
298 void PushButton::OnButtonImageSet()
300 ConfigureSizeNegotiation();
303 void PushButton::OnSelectedImageSet()
305 ConfigureSizeNegotiation();
308 void PushButton::OnBackgroundImageSet()
310 ConfigureSizeNegotiation();
313 void PushButton::OnSelectedBackgroundImageSet()
315 ConfigureSizeNegotiation();
318 void PushButton::OnDisabledImageSet()
320 ConfigureSizeNegotiation();
323 void PushButton::OnDisabledSelectedImageSet()
325 ConfigureSizeNegotiation();
328 void PushButton::OnDisabledBackgroundImageSet()
330 ConfigureSizeNegotiation();
333 void PushButton::OnSizeSet( const Vector3& targetSize )
335 if( targetSize != mSize )
339 Actor& label = GetLabelActor();
343 label.SetSize( mSize );
348 void PushButton::PrepareForTranstionIn( Actor actor )
350 actor.SetOpacity( 0.0f );
353 void PushButton::PrepareForTranstionOut( Actor actor )
355 actor.SetOpacity( 1.0f );
358 void PushButton::OnTransitionIn( Actor actor )
360 FadeImageTo( actor, 1.f );
363 void PushButton::OnTransitionOut( Actor actor )
365 FadeImageTo( actor, 0.0f );
368 void PushButton::FadeImageTo( Actor actor, float opacity )
372 Dali::Animation transitionAnimation = GetTransitionAnimation();
373 DALI_ASSERT_DEBUG( transitionAnimation );
375 if( transitionAnimation )
377 transitionAnimation.AnimateTo( Property( actor, Actor::Property::COLOR_ALPHA ), opacity );
382 Vector3 PushButton::GetNaturalSize()
386 // If label, test against it's size
387 Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( GetLabelActor() );
389 Actor icon = GetDecoration( UNSELECTED_DECORATION );
392 Vector3 labelSize( Vector3::ZERO );
393 Vector3 iconSize( Vector3::ZERO );
397 Vector3 labelNaturalSize = label.GetNaturalSize();
398 labelSize.width = labelNaturalSize.width + mLabelPadding.left + mLabelPadding.right;
399 labelSize.height = labelNaturalSize.height + mLabelPadding.top + mLabelPadding.bottom;
404 Vector3 iconNaturalSize = icon.GetNaturalSize();
405 iconSize.width = iconNaturalSize.width + mIconPadding.left + mIconPadding.right;
406 iconSize.height = iconNaturalSize.height + mIconPadding.top + mIconPadding.bottom;
408 switch( mIconAlignment )
413 size.width = labelSize.width + iconSize.width;
414 size.height = std::max( labelSize.height, iconSize.height );
420 size.width = std::max( labelSize.width, iconSize.width );
421 size.height = labelSize.height + iconSize.height;
428 // No icon, so size is the same as label size.
429 // (If there is no label this is zero).
435 // Check Image and Background image and use the largest size as the control's Natural size.
436 SizeOfActorIfLarger( GetUnselectedImage(), size );
437 SizeOfActorIfLarger( GetBackgroundImage(), size );
443 void PushButton::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
445 ConfigureSizeNegotiation();
448 void PushButton::ConfigureSizeNegotiation()
450 std::vector< Actor > images;
453 images.push_back( GetUnselectedImage() );
454 images.push_back( GetSelectedImage() );
455 images.push_back( GetSelectedBackgroundImage() );
456 images.push_back( GetBackgroundImage() );
457 images.push_back( GetDisabledImage() );
458 images.push_back( GetDisabledSelectedImage() );
459 images.push_back( GetDisabledBackgroundImage() );
461 Actor label = GetLabelActor();
463 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
465 ConfigureSizeNegotiationDimension( static_cast< Dimension::Type >( 1 << i ), images, label );
468 // Add any vertical padding directly to the actors.
469 Actor icon = GetDecoration( UNSELECTED_DECORATION );
470 Actor selectedIcon = GetDecoration( SELECTED_DECORATION );
471 bool iconExists = icon || selectedIcon;
475 label.SetPadding( mLabelPadding );
479 icon.SetPadding( mIconPadding );
483 selectedIcon.SetPadding( mIconPadding );
486 // Calculate and apply horizontal alignments and offsets
487 // to text and icon (depending on existence).
488 Vector3 iconPosition( Vector3::ZERO );
489 Vector3 labelPosition( Vector3::ZERO );
490 Vector3 iconAnchoring( AnchorPoint::CENTER );
491 Vector3 labelAnchoring( AnchorPoint::CENTER );
492 std::string horizontalLabelAlignment = "CENTER";
493 std::string verticalLabelAlignment = "CENTER";
495 if( iconExists && label )
497 // There is an icon and a label to lay out.
498 switch( mIconAlignment )
502 iconPosition.x = mIconPadding.left;
503 labelPosition.x = -mLabelPadding.right;
504 iconAnchoring = AnchorPoint::CENTER_LEFT;
505 labelAnchoring = AnchorPoint::CENTER_RIGHT;
506 horizontalLabelAlignment = "END";
511 iconPosition.x = -mIconPadding.right;
512 labelPosition.x = mLabelPadding.left;
513 iconAnchoring = AnchorPoint::CENTER_RIGHT;
514 labelAnchoring = AnchorPoint::CENTER_LEFT;
515 horizontalLabelAlignment = "BEGIN";
520 iconPosition.y = mIconPadding.top;
521 labelPosition.y = -mLabelPadding.bottom;
522 iconAnchoring = AnchorPoint::TOP_CENTER;
523 labelAnchoring = AnchorPoint::BOTTOM_CENTER;
524 verticalLabelAlignment = "BOTTOM";
529 iconPosition.y = -mIconPadding.bottom;
530 labelPosition.y = mLabelPadding.top;
531 iconAnchoring = AnchorPoint::BOTTOM_CENTER;
532 labelAnchoring = AnchorPoint::TOP_CENTER;
533 verticalLabelAlignment = "TOP";
539 // Note: If there is only an icon, or only a label, the default values are now correct.
540 // Setup the icon(s) with the precalculated values.
543 icon.SetPosition( iconPosition );
544 icon.SetParentOrigin( iconAnchoring );
545 icon.SetAnchorPoint( iconAnchoring );
549 selectedIcon.SetPosition( iconPosition );
550 selectedIcon.SetParentOrigin( iconAnchoring );
551 selectedIcon.SetAnchorPoint( iconAnchoring );
557 label.SetPosition( labelPosition );
558 label.SetParentOrigin( labelAnchoring );
559 label.SetAnchorPoint( labelAnchoring );
560 label.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, horizontalLabelAlignment );
561 label.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, verticalLabelAlignment );
568 void PushButton::ConfigureSizeNegotiationDimension( Dimension::Type dimension, const std::vector< Actor >& images, Actor& label )
570 ResizePolicy::Type imageResizePolicy = ResizePolicy::FILL_TO_PARENT;
571 ResizePolicy::Type labelResizePolicy = ResizePolicy::FILL_TO_PARENT;
573 ResizePolicy::Type resizePolicy = Self().GetResizePolicy( dimension );
575 if( resizePolicy == ResizePolicy::FIT_TO_CHILDREN || resizePolicy == ResizePolicy::USE_NATURAL_SIZE )
579 labelResizePolicy = ResizePolicy::USE_NATURAL_SIZE;
583 imageResizePolicy = ResizePolicy::USE_NATURAL_SIZE;
589 label.SetResizePolicy( labelResizePolicy, dimension );
592 for( std::vector< Actor >::const_iterator it = images.begin(), itEnd = images.end(); it != itEnd; ++it )
597 actor.SetResizePolicy( imageResizePolicy, dimension );
603 } // namespace Internal
605 } // namespace Toolkit