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()
278 Actor& label = GetLabelActor();
282 Toolkit::TextLabel textLabel = Toolkit::TextLabel::DownCast( label );
285 textLabel.SetProperty( Toolkit::TextLabel::Property::MULTI_LINE, false );
288 ConfigureSizeNegotiation();
291 void PushButton::OnButtonImageSet()
293 ConfigureSizeNegotiation();
296 void PushButton::OnSelectedImageSet()
298 ConfigureSizeNegotiation();
301 void PushButton::OnBackgroundImageSet()
303 ConfigureSizeNegotiation();
306 void PushButton::OnSelectedBackgroundImageSet()
308 ConfigureSizeNegotiation();
311 void PushButton::OnDisabledImageSet()
313 ConfigureSizeNegotiation();
316 void PushButton::OnDisabledSelectedImageSet()
318 ConfigureSizeNegotiation();
321 void PushButton::OnDisabledBackgroundImageSet()
323 ConfigureSizeNegotiation();
326 void PushButton::OnSizeSet( const Vector3& targetSize )
328 if( targetSize != mSize )
332 Actor& label = GetLabelActor();
336 label.SetSize( mSize );
341 void PushButton::PrepareForTranstionIn( Actor actor )
343 actor.SetOpacity( 0.0f );
346 void PushButton::PrepareForTranstionOut( Actor actor )
348 actor.SetOpacity( 1.0f );
351 void PushButton::OnTransitionIn( Actor actor )
353 FadeImageTo( actor, 1.f );
356 void PushButton::OnTransitionOut( Actor actor )
358 FadeImageTo( actor, 0.0f );
361 void PushButton::FadeImageTo( Actor actor, float opacity )
365 Dali::Animation transitionAnimation = GetTransitionAnimation();
366 DALI_ASSERT_DEBUG( transitionAnimation );
368 if( transitionAnimation )
370 transitionAnimation.AnimateTo( Property( actor, Actor::Property::COLOR_ALPHA ), opacity );
375 Vector3 PushButton::GetNaturalSize()
379 // If label, test against it's size
380 Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( GetLabelActor() );
382 Actor icon = GetDecoration( UNSELECTED_DECORATION );
385 Vector3 labelSize( Vector3::ZERO );
386 Vector3 iconSize( Vector3::ZERO );
390 Vector3 labelNaturalSize = label.GetNaturalSize();
391 labelSize.width = labelNaturalSize.width + mLabelPadding.left + mLabelPadding.right;
392 labelSize.height = labelNaturalSize.height + mLabelPadding.top + mLabelPadding.bottom;
397 Vector3 iconNaturalSize = icon.GetNaturalSize();
398 iconSize.width = iconNaturalSize.width + mIconPadding.left + mIconPadding.right;
399 iconSize.height = iconNaturalSize.height + mIconPadding.top + mIconPadding.bottom;
401 switch( mIconAlignment )
406 size.width = labelSize.width + iconSize.width;
407 size.height = std::max( labelSize.height, iconSize.height );
413 size.width = std::max( labelSize.width, iconSize.width );
414 size.height = labelSize.height + iconSize.height;
421 // No icon, so size is the same as label size.
422 // (If there is no label this is zero).
428 // Check Image and Background image and use the largest size as the control's Natural size.
429 SizeOfActorIfLarger( GetUnselectedImage(), size );
430 SizeOfActorIfLarger( GetBackgroundImage(), size );
436 void PushButton::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
438 ConfigureSizeNegotiation();
441 void PushButton::ConfigureSizeNegotiation()
443 std::vector< Actor > images;
446 images.push_back( GetUnselectedImage() );
447 images.push_back( GetSelectedImage() );
448 images.push_back( GetSelectedBackgroundImage() );
449 images.push_back( GetBackgroundImage() );
450 images.push_back( GetDisabledImage() );
451 images.push_back( GetDisabledSelectedImage() );
452 images.push_back( GetDisabledBackgroundImage() );
454 Actor label = GetLabelActor();
456 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
458 ConfigureSizeNegotiationDimension( static_cast< Dimension::Type >( 1 << i ), images, label );
461 // Add any vertical padding directly to the actors.
462 Actor icon = GetDecoration( UNSELECTED_DECORATION );
463 Actor selectedIcon = GetDecoration( SELECTED_DECORATION );
464 bool iconExists = icon || selectedIcon;
468 label.SetPadding( mLabelPadding );
472 icon.SetPadding( mIconPadding );
476 selectedIcon.SetPadding( mIconPadding );
479 // Calculate and apply horizontal alignments and offsets
480 // to text and icon (depending on existence).
481 Vector3 iconPosition( Vector3::ZERO );
482 Vector3 labelPosition( Vector3::ZERO );
483 Vector3 iconAnchoring( AnchorPoint::CENTER );
484 Vector3 labelAnchoring( AnchorPoint::CENTER );
485 std::string horizontalLabelAlignment = "CENTER";
486 std::string verticalLabelAlignment = "CENTER";
488 if( iconExists && label )
490 // There is an icon and a label to lay out.
491 switch( mIconAlignment )
495 iconPosition.x = mIconPadding.left;
496 labelPosition.x = -mLabelPadding.right;
497 iconAnchoring = AnchorPoint::CENTER_LEFT;
498 labelAnchoring = AnchorPoint::CENTER_RIGHT;
499 horizontalLabelAlignment = "END";
504 iconPosition.x = -mIconPadding.right;
505 labelPosition.x = mLabelPadding.left;
506 iconAnchoring = AnchorPoint::CENTER_RIGHT;
507 labelAnchoring = AnchorPoint::CENTER_LEFT;
508 horizontalLabelAlignment = "BEGIN";
513 iconPosition.y = mIconPadding.top;
514 labelPosition.y = -mLabelPadding.bottom;
515 iconAnchoring = AnchorPoint::TOP_CENTER;
516 labelAnchoring = AnchorPoint::BOTTOM_CENTER;
517 verticalLabelAlignment = "BOTTOM";
522 iconPosition.y = -mIconPadding.bottom;
523 labelPosition.y = mLabelPadding.top;
524 iconAnchoring = AnchorPoint::BOTTOM_CENTER;
525 labelAnchoring = AnchorPoint::TOP_CENTER;
526 verticalLabelAlignment = "TOP";
532 // Note: If there is only an icon, or only a label, the default values are now correct.
533 // Setup the icon(s) with the precalculated values.
536 icon.SetPosition( iconPosition );
537 icon.SetParentOrigin( iconAnchoring );
538 icon.SetAnchorPoint( iconAnchoring );
542 selectedIcon.SetPosition( iconPosition );
543 selectedIcon.SetParentOrigin( iconAnchoring );
544 selectedIcon.SetAnchorPoint( iconAnchoring );
550 label.SetPosition( labelPosition );
551 label.SetParentOrigin( labelAnchoring );
552 label.SetAnchorPoint( labelAnchoring );
553 label.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, horizontalLabelAlignment );
554 label.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, verticalLabelAlignment );
560 void PushButton::ConfigureSizeNegotiationDimension( Dimension::Type dimension, const std::vector< Actor >& images, Actor& label )
562 ResizePolicy::Type imageResizePolicy = ResizePolicy::FILL_TO_PARENT;
563 ResizePolicy::Type labelResizePolicy = ResizePolicy::FILL_TO_PARENT;
565 ResizePolicy::Type resizePolicy = Self().GetResizePolicy( dimension );
567 if( resizePolicy == ResizePolicy::FIT_TO_CHILDREN || resizePolicy == ResizePolicy::USE_NATURAL_SIZE )
571 labelResizePolicy = ResizePolicy::USE_NATURAL_SIZE;
575 imageResizePolicy = ResizePolicy::USE_NATURAL_SIZE;
581 label.SetResizePolicy( labelResizePolicy, dimension );
584 for( std::vector< Actor >::const_iterator it = images.begin(), itEnd = images.end(); it != itEnd; ++it )
589 actor.SetResizePolicy( imageResizePolicy, dimension );
595 } // namespace Internal
597 } // namespace Toolkit