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 "alignment-impl.h"
22 #include <dali/public-api/object/property-input.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/public-api/size-negotiation/relayout-container.h>
28 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
45 return Toolkit::Alignment::New();
48 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Alignment, Toolkit::Control, Create )
49 DALI_TYPE_REGISTRATION_END()
52 * @param padding The padding value
53 * @param horizontalAlignment The horizontal alignment.
54 * @param verticalAlignment The vertical alignment.
55 * @param currentSize of the object
58 inline Vector3 GetPosition( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment,
59 const Vector2& currentSize, const Vector2& parentSize )
61 Vector3 position( 0.f, 0.f, 0.f );
63 switch( horizontalAlignment )
65 case Dali::Toolkit::Alignment::HORIZONTAL_LEFT:
67 position.x += padding.left;
70 case Dali::Toolkit::Alignment::HORIZONTAL_RIGHT:
72 position.x -= padding.right;
75 case Dali::Toolkit::Alignment::HORIZONTAL_CENTER: // FALLTHROUGH
76 default: // use center as default
78 if( currentSize.width + padding.left + padding.right >= parentSize.width )
80 position.x += 0.5f * ( padding.left - padding.right );
86 switch( verticalAlignment )
88 case Dali::Toolkit::Alignment::VERTICAL_TOP:
90 position.y += padding.top;
93 case Dali::Toolkit::Alignment::VERTICAL_BOTTOM:
95 position.y -= padding.bottom;
98 case Dali::Toolkit::Alignment::VERTICAL_CENTER: // FALLTHROUGH
99 default: // use center as default
101 if( currentSize.height + padding.top + padding.bottom >= parentSize.height )
103 position.y += 0.5f * ( padding.top - padding.bottom );
114 Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
116 // Create the implementation, temporarily owned on stack
117 IntrusivePtr< Alignment > internalAlignment = new Alignment( horizontal, vertical );
119 // Pass ownership to Toolkit::Alignment
120 Toolkit::Alignment alignment( *internalAlignment );
122 // Second-phase init of the implementation
123 // This can only be done after the CustomActor connection has been made...
124 internalAlignment->Initialize();
129 void Alignment::SetAlignmentType( Toolkit::Alignment::Type type )
131 // Horizontal Alignment
132 if( type & Toolkit::Alignment::HORIZONTAL_RIGHT )
134 mHorizontal = Toolkit::Alignment::HORIZONTAL_RIGHT;
136 if( type & Toolkit::Alignment::HORIZONTAL_LEFT )
138 mHorizontal = Toolkit::Alignment::HORIZONTAL_LEFT;
140 if( type & Toolkit::Alignment::HORIZONTAL_CENTER )
142 mHorizontal = Toolkit::Alignment::HORIZONTAL_CENTER;
145 // Vertical Alignment
146 if( type & Toolkit::Alignment::VERTICAL_BOTTOM )
148 mVertical = Toolkit::Alignment::VERTICAL_BOTTOM;
150 if( type & Toolkit::Alignment::VERTICAL_TOP )
152 mVertical = Toolkit::Alignment::VERTICAL_TOP;
154 if( type & Toolkit::Alignment::VERTICAL_CENTER )
156 mVertical = Toolkit::Alignment::VERTICAL_CENTER;
162 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
164 return Toolkit::Alignment::Type( mHorizontal | mVertical );
167 void Alignment::SetScaling( Toolkit::Alignment::Scaling scaling )
174 Toolkit::Alignment::Scaling Alignment::GetScaling() const
179 void Alignment::SetPadding( const Toolkit::Alignment::Padding& padding )
181 DALI_ASSERT_ALWAYS( ( padding.left >= 0.f ) && ( padding.top >= 0.f ) && ( padding.right >= 0.f ) && ( padding.bottom >= 0.f ) );
188 const Toolkit::Alignment::Padding& Alignment::GetPadding() const
193 void Alignment::OnInitialize()
195 DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
196 return std::unique_ptr< Dali::Accessibility::Accessible >(
197 new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::FILLER ) );
201 void Alignment::OnRelayout( const Vector2& size, RelayoutContainer& container )
203 // lay out the actors
204 Vector3 anchorPointAndParentOrigin = Vector3::ZERO;
205 anchorPointAndParentOrigin.z = 0.5f;
206 // anchorPoint.x is initialized to 0.0, which is HORIZONTAL_LEFT
207 if( Toolkit::Alignment::HORIZONTAL_CENTER == mHorizontal )
209 anchorPointAndParentOrigin.x = 0.5f;
211 else if( Toolkit::Alignment::HORIZONTAL_RIGHT == mHorizontal )
213 anchorPointAndParentOrigin.x = 1.0f;
215 // anchorPoint.y is initialized to 0.0, which is VERTICAL_TOP
216 if( Toolkit::Alignment::VERTICAL_CENTER == mVertical )
218 anchorPointAndParentOrigin.y = 0.5f;
220 else if( Toolkit::Alignment::VERTICAL_BOTTOM == mVertical )
222 anchorPointAndParentOrigin.y = 1.0f;
225 for( unsigned int i = 0, childCount = Self().GetChildCount(); i < childCount; ++i )
227 Actor child = Self().GetChildAt(i);
229 child.SetProperty( Actor::Property::ANCHOR_POINT, anchorPointAndParentOrigin );
230 child.SetProperty( Actor::Property::PARENT_ORIGIN, anchorPointAndParentOrigin );
232 Vector2 currentChildSize( child.GetTargetSize().GetVectorXY() );
233 if( currentChildSize == Vector2::ZERO )
235 currentChildSize = child.GetNaturalSize();
238 bool renegotiate = true;
239 Vector2 newChildSize;
240 newChildSize.width = size.width - ( mPadding.left + mPadding.right );
241 newChildSize.height = size.height- ( mPadding.top + mPadding.bottom );
243 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
244 if( ( newChildSize.width > Math::MACHINE_EPSILON_1000 ) && ( newChildSize.height > Math::MACHINE_EPSILON_1000 ) &&
245 ( currentChildSize.width > Math::MACHINE_EPSILON_1000 ) && ( currentChildSize.height > Math::MACHINE_EPSILON_1000 ) )
247 // no point trying to squeeze actors into too small size
250 case Toolkit::Alignment::SCALE_NONE:
256 case Toolkit::Alignment::SCALE_TO_FILL:
258 // Nothing to do, newChildSize is already full size minus padding
261 case Toolkit::Alignment::SCALE_TO_FIT_KEEP_ASPECT:
263 newChildSize = currentChildSize * std::min( ( newChildSize.width / currentChildSize.width ), ( newChildSize.height / currentChildSize.height ) );
266 case Toolkit::Alignment::SCALE_TO_FILL_KEEP_ASPECT:
268 newChildSize = currentChildSize * std::max( ( newChildSize.width / currentChildSize.width ), ( newChildSize.height / currentChildSize.height ) );
271 case Toolkit::Alignment::SHRINK_TO_FIT:
273 newChildSize = Vector2( std::min( newChildSize.width, currentChildSize.width ), std::min( newChildSize.height, currentChildSize.height ) );
276 case Toolkit::Alignment::SHRINK_TO_FIT_KEEP_ASPECT:
278 // check source size vs target size to see if we need to shrink
279 float widthScale = ( newChildSize.width < currentChildSize.width ) ? (newChildSize.width / currentChildSize.width) : 1.f;
280 float heightScale = ( newChildSize.height < currentChildSize.height ) ? (newChildSize.height / currentChildSize.height) : 1.0f;
281 // use smaller of the scales
282 float scale = std::min( widthScale, heightScale );
283 // check if we need to scale
286 // scale natural size to fit inside
287 newChildSize *= scale;
294 child.SetProperty( Actor::Property::POSITION, GetPosition( mPadding, mHorizontal, mVertical , newChildSize, currentChildSize ) );
298 container.Add( child, newChildSize );
303 Alignment::Alignment( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
304 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
305 mHorizontal( horizontal ),
306 mVertical( vertical ),
307 mScaling( Toolkit::Alignment::SCALE_NONE ),
308 mPadding( 0.f, 0.f, 0.f, 0.f )
312 Alignment::~Alignment()
316 } // namespace Internal
318 } // namespace Toolkit