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/devel-api/object/type-registry-helper.h>
25 #include <dali/public-api/size-negotiation/relayout-container.h>
42 return Toolkit::Alignment::New();
45 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Alignment, Toolkit::Control, Create )
46 DALI_TYPE_REGISTRATION_END()
49 * @param padding The padding value
50 * @param horizontalAlignment The horizontal alignment.
51 * @param verticalAlignment The vertical alignment.
52 * @param currentSize of the object
55 inline Vector3 GetPosition( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment,
56 const Vector2& currentSize, const Vector2& parentSize )
58 Vector3 position( 0.f, 0.f, 0.f );
60 switch( horizontalAlignment )
62 case Dali::Toolkit::Alignment::HorizontalLeft:
64 position.x += padding.left;
67 case Dali::Toolkit::Alignment::HorizontalRight:
69 position.x -= padding.right;
72 case Dali::Toolkit::Alignment::HorizontalCenter: // FALLTHROUGH
73 default: // use center as default
75 if( currentSize.width + padding.left + padding.right >= parentSize.width )
77 position.x += 0.5f * ( padding.left - padding.right );
83 switch( verticalAlignment )
85 case Dali::Toolkit::Alignment::VerticalTop:
87 position.y += padding.top;
90 case Dali::Toolkit::Alignment::VerticalBottom:
92 position.y -= padding.bottom;
95 case Dali::Toolkit::Alignment::VerticalCenter: // FALLTHROUGH
96 default: // use center as default
98 if( currentSize.height + padding.top + padding.bottom >= parentSize.height )
100 position.y += 0.5f * ( padding.top - padding.bottom );
111 Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
113 // Create the implementation, temporarily owned on stack
114 IntrusivePtr< Alignment > internalAlignment = new Alignment( horizontal, vertical );
116 // Pass ownership to Toolkit::Alignment
117 Toolkit::Alignment alignment( *internalAlignment );
119 // Second-phase init of the implementation
120 // This can only be done after the CustomActor connection has been made...
121 internalAlignment->Initialize();
126 void Alignment::SetAlignmentType( Toolkit::Alignment::Type type )
128 // Horizontal Alignment
129 if( type & Toolkit::Alignment::HorizontalRight )
131 mHorizontal = Toolkit::Alignment::HorizontalRight;
133 if( type & Toolkit::Alignment::HorizontalLeft )
135 mHorizontal = Toolkit::Alignment::HorizontalLeft;
137 if( type & Toolkit::Alignment::HorizontalCenter )
139 mHorizontal = Toolkit::Alignment::HorizontalCenter;
142 // Vertical Alignment
143 if( type & Toolkit::Alignment::VerticalBottom )
145 mVertical = Toolkit::Alignment::VerticalBottom;
147 if( type & Toolkit::Alignment::VerticalTop )
149 mVertical = Toolkit::Alignment::VerticalTop;
151 if( type & Toolkit::Alignment::VerticalCenter )
153 mVertical = Toolkit::Alignment::VerticalCenter;
159 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
161 return Toolkit::Alignment::Type( mHorizontal | mVertical );
164 void Alignment::SetScaling( Toolkit::Alignment::Scaling scaling )
171 Toolkit::Alignment::Scaling Alignment::GetScaling() const
176 void Alignment::SetPadding( const Toolkit::Alignment::Padding& padding )
178 DALI_ASSERT_ALWAYS( ( padding.left >= 0.f ) && ( padding.top >= 0.f ) && ( padding.right >= 0.f ) && ( padding.bottom >= 0.f ) );
185 const Toolkit::Alignment::Padding& Alignment::GetPadding() const
190 void Alignment::OnRelayout( const Vector2& size, RelayoutContainer& container )
192 // lay out the actors
193 Vector3 anchorPointAndParentOrigin = Vector3::ZERO;
194 anchorPointAndParentOrigin.z = 0.5f;
195 // anchorPoint.x is initialized to 0.0, which is HorizontalLeft
196 if( Toolkit::Alignment::HorizontalCenter == mHorizontal )
198 anchorPointAndParentOrigin.x = 0.5f;
200 else if( Toolkit::Alignment::HorizontalRight == mHorizontal )
202 anchorPointAndParentOrigin.x = 1.0f;
204 // anchorPoint.y is initialized to 0.0, which is VerticalTop
205 if( Toolkit::Alignment::VerticalCenter == mVertical )
207 anchorPointAndParentOrigin.y = 0.5f;
209 else if( Toolkit::Alignment::VerticalBottom == mVertical )
211 anchorPointAndParentOrigin.y = 1.0f;
214 for( unsigned int i = 0, childCount = Self().GetChildCount(); i < childCount; ++i )
216 Actor child = Self().GetChildAt(i);
218 child.SetAnchorPoint( anchorPointAndParentOrigin );
219 child.SetParentOrigin( anchorPointAndParentOrigin );
221 Vector2 currentChildSize( child.GetTargetSize().GetVectorXY() );
222 if( currentChildSize == Vector2::ZERO )
224 currentChildSize = child.GetNaturalSize();
227 bool renegotiate = true;
228 Vector2 newChildSize;
229 newChildSize.width = size.width - ( mPadding.left + mPadding.right );
230 newChildSize.height = size.height- ( mPadding.top + mPadding.bottom );
232 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
233 if( ( newChildSize.width > Math::MACHINE_EPSILON_1000 ) && ( newChildSize.height > Math::MACHINE_EPSILON_1000 ) &&
234 ( currentChildSize.width > Math::MACHINE_EPSILON_1000 ) && ( currentChildSize.height > Math::MACHINE_EPSILON_1000 ) )
236 // no point trying to squeeze actors into too small size
239 case Toolkit::Alignment::ScaleNone:
245 case Toolkit::Alignment::ScaleToFill:
247 // Nothing to do, newChildSize is already full size minus padding
250 case Toolkit::Alignment::ScaleToFitKeepAspect:
252 newChildSize = currentChildSize * std::min( ( newChildSize.width / currentChildSize.width ), ( newChildSize.height / currentChildSize.height ) );
255 case Toolkit::Alignment::ScaleToFillKeepAspect:
257 newChildSize = currentChildSize * std::max( ( newChildSize.width / currentChildSize.width ), ( newChildSize.height / currentChildSize.height ) );
260 case Toolkit::Alignment::ShrinkToFit:
262 newChildSize = Vector2( std::min( newChildSize.width, currentChildSize.width ), std::min( newChildSize.height, currentChildSize.height ) );
265 case Toolkit::Alignment::ShrinkToFitKeepAspect:
267 // check source size vs target size to see if we need to shrink
268 float widthScale = ( newChildSize.width < currentChildSize.width ) ? (newChildSize.width / currentChildSize.width) : 1.f;
269 float heightScale = ( newChildSize.height < currentChildSize.height ) ? (newChildSize.height / currentChildSize.height) : 1.0f;
270 // use smaller of the scales
271 float scale = std::min( widthScale, heightScale );
272 // check if we need to scale
275 // scale natural size to fit inside
276 newChildSize *= scale;
283 child.SetPosition( GetPosition( mPadding, mHorizontal, mVertical , newChildSize, currentChildSize ) );
287 container.Add( child, newChildSize );
292 Alignment::Alignment( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
293 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
294 mHorizontal( horizontal ),
295 mVertical( vertical ),
296 mScaling( Toolkit::Alignment::ScaleNone ),
297 mPadding( 0.f, 0.f, 0.f, 0.f )
301 Alignment::~Alignment()
305 } // namespace Internal
307 } // namespace Toolkit