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/actors/image-actor.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/devel-api/object/type-registry-helper.h>
25 #include <dali/public-api/images/resource-image.h>
26 #include <dali/devel-api/scripting/scripting.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, "unselected-icon", STRING, UNSELECTED_ICON )
57 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "selected-icon", STRING, SELECTED_ICON )
58 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "icon-alignment", STRING, ICON_ALIGNMENT )
59 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "label-padding", STRING, LABEL_PADDING )
60 DALI_PROPERTY_REGISTRATION( Toolkit, PushButton, "icon-padding", 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::OnButtonInitialize()
132 // Push button requires the Leave event.
134 self.SetLeaveRequired( true );
136 // Set resize policy to natural size so that buttons will resize to background images
137 self.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
139 SetUnselectedImage( UNSELECTED_BUTTON_IMAGE_DIR );
140 SetSelectedImage( SELECTED_BUTTON_IMAGE_DIR );
141 SetDisabledImage( DISABLED_UNSELECTED_BUTTON_IMAGE_DIR );
142 SetDisabledSelectedImage( DISABLED_SELECTED_BUTTON_IMAGE_DIR );
145 void PushButton::SetIcon( DecorationState state, const std::string iconFilename )
147 mIconName[ state ] = iconFilename;
148 SetDecoration( state, ImageActor::New( Dali::ResourceImage::New( iconFilename ) ) );
149 ConfigureSizeNegotiation();
152 std::string& PushButton::GetIcon( DecorationState state )
154 return mIconName[ state ];
157 void PushButton::SetIconAlignment( const PushButton::IconAlignment iconAlignment )
159 mIconAlignment = iconAlignment;
160 ConfigureSizeNegotiation();
163 const PushButton::IconAlignment PushButton::GetIconAlignment() const
165 return mIconAlignment;
168 void PushButton::SetLabelPadding( const Vector4& padding )
170 mLabelPadding = Padding( padding.x, padding.y, padding.z, padding.w );
171 ConfigureSizeNegotiation();
174 Vector4 PushButton::GetLabelPadding()
176 return Vector4( mLabelPadding.left, mLabelPadding.right, mLabelPadding.top, mLabelPadding.bottom );
179 void PushButton::SetIconPadding( const Vector4& padding )
181 mIconPadding = Padding( padding.x, padding.y, padding.z, padding.w );
182 ConfigureSizeNegotiation();
185 Vector4 PushButton::GetIconPadding()
187 return Vector4( mIconPadding.left, mIconPadding.right, mIconPadding.top, mIconPadding.bottom );
190 void PushButton::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
192 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
196 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
198 switch ( propertyIndex )
200 case Toolkit::PushButton::Property::UNSELECTED_ICON:
202 pushButtonImpl.SetIcon( UNSELECTED_DECORATION, value.Get< std::string >() );
205 case Toolkit::PushButton::Property::SELECTED_ICON:
207 pushButtonImpl.SetIcon( SELECTED_DECORATION, value.Get< std::string >() );
210 case Toolkit::PushButton::Property::ICON_ALIGNMENT:
212 IconAlignment iconAlignment;
213 if( Scripting::GetEnumeration< IconAlignment >( value.Get< std::string >().c_str(), IconAlignmentTable, IconAlignmentTableCount, iconAlignment ) )
215 pushButtonImpl.SetIconAlignment( iconAlignment );
219 case Toolkit::PushButton::Property::LABEL_PADDING:
221 pushButtonImpl.SetLabelPadding( value.Get< Vector4 >() );
224 case Toolkit::PushButton::Property::ICON_PADDING:
226 pushButtonImpl.SetIconPadding( value.Get< Vector4 >() );
233 Property::Value PushButton::GetProperty( BaseObject* object, Property::Index propertyIndex )
235 Property::Value value;
237 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
241 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
243 switch ( propertyIndex )
245 case Toolkit::PushButton::Property::UNSELECTED_ICON:
247 value = pushButtonImpl.GetIcon( UNSELECTED_DECORATION );
250 case Toolkit::PushButton::Property::SELECTED_ICON:
252 value = pushButtonImpl.GetIcon( UNSELECTED_DECORATION );
255 case Toolkit::PushButton::Property::ICON_ALIGNMENT:
257 value = Scripting::GetLinearEnumerationName< IconAlignment >( pushButtonImpl.GetIconAlignment(), IconAlignmentTable, IconAlignmentTableCount );
260 case Toolkit::PushButton::Property::LABEL_PADDING:
262 value = pushButtonImpl.GetLabelPadding();
265 case Toolkit::PushButton::Property::ICON_PADDING:
267 value = pushButtonImpl.GetIconPadding();
276 void PushButton::OnLabelSet( bool noPadding )
278 Actor& label = GetLabelActor();
284 mLabelPadding = Padding( 0.0f, 0.0f, 0.0f, 0.0f );
287 Toolkit::TextLabel textLabel = Toolkit::TextLabel::DownCast( label );
290 textLabel.SetProperty( Toolkit::TextLabel::Property::MULTI_LINE, false );
293 ConfigureSizeNegotiation();
296 void PushButton::OnButtonImageSet()
298 ConfigureSizeNegotiation();
301 void PushButton::OnSelectedImageSet()
303 ConfigureSizeNegotiation();
306 void PushButton::OnBackgroundImageSet()
308 ConfigureSizeNegotiation();
311 void PushButton::OnSelectedBackgroundImageSet()
313 ConfigureSizeNegotiation();
316 void PushButton::OnDisabledImageSet()
318 ConfigureSizeNegotiation();
321 void PushButton::OnDisabledSelectedImageSet()
323 ConfigureSizeNegotiation();
326 void PushButton::OnDisabledBackgroundImageSet()
328 ConfigureSizeNegotiation();
331 void PushButton::OnSizeSet( const Vector3& targetSize )
333 if( targetSize != mSize )
337 Actor& label = GetLabelActor();
341 label.SetSize( mSize );
346 void PushButton::PrepareForTranstionIn( Actor actor )
348 actor.SetOpacity( 0.0f );
351 void PushButton::PrepareForTranstionOut( Actor actor )
353 actor.SetOpacity( 1.0f );
356 void PushButton::OnTransitionIn( Actor actor )
358 FadeImageTo( actor, 1.f );
361 void PushButton::OnTransitionOut( Actor actor )
363 FadeImageTo( actor, 0.0f );
366 void PushButton::FadeImageTo( Actor actor, float opacity )
370 Dali::Animation transitionAnimation = GetTransitionAnimation();
371 DALI_ASSERT_DEBUG( transitionAnimation );
373 if( transitionAnimation )
375 transitionAnimation.AnimateTo( Property( actor, Actor::Property::COLOR_ALPHA ), opacity );
380 Vector3 PushButton::GetNaturalSize()
384 // If label, test against it's size
385 Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( GetLabelActor() );
387 Actor icon = GetDecoration( UNSELECTED_DECORATION );
390 Vector3 labelSize( Vector3::ZERO );
391 Vector3 iconSize( Vector3::ZERO );
395 Vector3 labelNaturalSize = label.GetNaturalSize();
396 labelSize.width = labelNaturalSize.width + mLabelPadding.left + mLabelPadding.right;
397 labelSize.height = labelNaturalSize.height + mLabelPadding.top + mLabelPadding.bottom;
402 Vector3 iconNaturalSize = icon.GetNaturalSize();
403 iconSize.width = iconNaturalSize.width + mIconPadding.left + mIconPadding.right;
404 iconSize.height = iconNaturalSize.height + mIconPadding.top + mIconPadding.bottom;
406 switch( mIconAlignment )
411 size.width = labelSize.width + iconSize.width;
412 size.height = std::max( labelSize.height, iconSize.height );
418 size.width = std::max( labelSize.width, iconSize.width );
419 size.height = labelSize.height + iconSize.height;
426 // No icon, so size is the same as label size.
427 // (If there is no label this is zero).
433 // Check Image and Background image and use the largest size as the control's Natural size.
434 SizeOfActorIfLarger( GetUnselectedImage(), size );
435 SizeOfActorIfLarger( GetBackgroundImage(), size );
441 void PushButton::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
443 ConfigureSizeNegotiation();
446 void PushButton::ConfigureSizeNegotiation()
448 std::vector< Actor > images;
451 images.push_back( GetUnselectedImage() );
452 images.push_back( GetSelectedImage() );
453 images.push_back( GetSelectedBackgroundImage() );
454 images.push_back( GetBackgroundImage() );
455 images.push_back( GetDisabledImage() );
456 images.push_back( GetDisabledSelectedImage() );
457 images.push_back( GetDisabledBackgroundImage() );
459 Actor label = GetLabelActor();
461 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
463 ConfigureSizeNegotiationDimension( static_cast< Dimension::Type >( 1 << i ), images, label );
466 // Add any vertical padding directly to the actors.
467 Actor icon = GetDecoration( UNSELECTED_DECORATION );
468 Actor selectedIcon = GetDecoration( SELECTED_DECORATION );
469 bool iconExists = icon || selectedIcon;
473 label.SetPadding( mLabelPadding );
477 icon.SetPadding( mIconPadding );
481 selectedIcon.SetPadding( mIconPadding );
484 // Calculate and apply horizontal alignments and offsets
485 // to text and icon (depending on existence).
486 Vector3 iconPosition( Vector3::ZERO );
487 Vector3 labelPosition( Vector3::ZERO );
488 Vector3 iconAnchoring( AnchorPoint::CENTER );
489 Vector3 labelAnchoring( AnchorPoint::CENTER );
490 std::string horizontalLabelAlignment = "CENTER";
491 std::string verticalLabelAlignment = "CENTER";
493 if( iconExists && label )
495 // There is an icon and a label to lay out.
496 switch( mIconAlignment )
500 iconPosition.x = mIconPadding.left;
501 labelPosition.x = -mLabelPadding.right;
502 iconAnchoring = AnchorPoint::CENTER_LEFT;
503 labelAnchoring = AnchorPoint::CENTER_RIGHT;
504 horizontalLabelAlignment = "END";
509 iconPosition.x = -mIconPadding.right;
510 labelPosition.x = mLabelPadding.left;
511 iconAnchoring = AnchorPoint::CENTER_RIGHT;
512 labelAnchoring = AnchorPoint::CENTER_LEFT;
513 horizontalLabelAlignment = "BEGIN";
518 iconPosition.y = mIconPadding.top;
519 labelPosition.y = -mLabelPadding.bottom;
520 iconAnchoring = AnchorPoint::TOP_CENTER;
521 labelAnchoring = AnchorPoint::BOTTOM_CENTER;
522 verticalLabelAlignment = "BOTTOM";
527 iconPosition.y = -mIconPadding.bottom;
528 labelPosition.y = mLabelPadding.top;
529 iconAnchoring = AnchorPoint::BOTTOM_CENTER;
530 labelAnchoring = AnchorPoint::TOP_CENTER;
531 verticalLabelAlignment = "TOP";
537 // Note: If there is only an icon, or only a label, the default values are now correct.
538 // Setup the icon(s) with the precalculated values.
541 icon.SetPosition( iconPosition );
542 icon.SetParentOrigin( iconAnchoring );
543 icon.SetAnchorPoint( iconAnchoring );
547 selectedIcon.SetPosition( iconPosition );
548 selectedIcon.SetParentOrigin( iconAnchoring );
549 selectedIcon.SetAnchorPoint( iconAnchoring );
555 label.SetPosition( labelPosition );
556 label.SetParentOrigin( labelAnchoring );
557 label.SetAnchorPoint( labelAnchoring );
558 label.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, horizontalLabelAlignment );
559 label.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, verticalLabelAlignment );
566 void PushButton::ConfigureSizeNegotiationDimension( Dimension::Type dimension, const std::vector< Actor >& images, Actor& label )
568 ResizePolicy::Type imageResizePolicy = ResizePolicy::FILL_TO_PARENT;
569 ResizePolicy::Type labelResizePolicy = ResizePolicy::FILL_TO_PARENT;
571 ResizePolicy::Type resizePolicy = Self().GetResizePolicy( dimension );
573 if( resizePolicy == ResizePolicy::FIT_TO_CHILDREN || resizePolicy == ResizePolicy::USE_NATURAL_SIZE )
577 labelResizePolicy = ResizePolicy::USE_NATURAL_SIZE;
581 imageResizePolicy = ResizePolicy::USE_NATURAL_SIZE;
587 label.SetResizePolicy( labelResizePolicy, dimension );
590 for( std::vector< Actor >::const_iterator it = images.begin(), itEnd = images.end(); it != itEnd; ++it )
595 actor.SetResizePolicy( imageResizePolicy, dimension );
601 } // namespace Internal
603 } // namespace Toolkit