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-helper.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/size-negotiation/relayout-container.h>
28 #include <dali-toolkit/devel-api/controls/control-devel.h>
41 return Toolkit::Alignment::New();
44 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::Alignment, Toolkit::Control, Create)
45 DALI_TYPE_REGISTRATION_END()
48 * @param padding The padding value
49 * @param horizontalAlignment The horizontal alignment.
50 * @param verticalAlignment The vertical alignment.
51 * @param currentSize of the object
54 inline Vector3 GetPosition(const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment, const Vector2& currentSize, const Vector2& parentSize)
56 Vector3 position(0.f, 0.f, 0.f);
58 switch(horizontalAlignment)
60 case Dali::Toolkit::Alignment::HORIZONTAL_LEFT:
62 position.x += padding.left;
65 case Dali::Toolkit::Alignment::HORIZONTAL_RIGHT:
67 position.x -= padding.right;
70 case Dali::Toolkit::Alignment::HORIZONTAL_CENTER: // FALLTHROUGH
71 default: // use center as default
73 if(currentSize.width + padding.left + padding.right >= parentSize.width)
75 position.x += 0.5f * (padding.left - padding.right);
81 switch(verticalAlignment)
83 case Dali::Toolkit::Alignment::VERTICAL_TOP:
85 position.y += padding.top;
88 case Dali::Toolkit::Alignment::VERTICAL_BOTTOM:
90 position.y -= padding.bottom;
93 case Dali::Toolkit::Alignment::VERTICAL_CENTER: // FALLTHROUGH
94 default: // use center as default
96 if(currentSize.height + padding.top + padding.bottom >= parentSize.height)
98 position.y += 0.5f * (padding.top - padding.bottom);
109 Toolkit::Alignment Alignment::New(Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical)
111 // Create the implementation, temporarily owned on stack
112 IntrusivePtr<Alignment> internalAlignment = new Alignment(horizontal, vertical);
114 // Pass ownership to Toolkit::Alignment
115 Toolkit::Alignment alignment(*internalAlignment);
117 // Second-phase init of the implementation
118 // This can only be done after the CustomActor connection has been made...
119 internalAlignment->Initialize();
124 void Alignment::SetAlignmentType(Toolkit::Alignment::Type type)
126 // Horizontal Alignment
127 if(type & Toolkit::Alignment::HORIZONTAL_RIGHT)
129 mHorizontal = Toolkit::Alignment::HORIZONTAL_RIGHT;
131 if(type & Toolkit::Alignment::HORIZONTAL_LEFT)
133 mHorizontal = Toolkit::Alignment::HORIZONTAL_LEFT;
135 if(type & Toolkit::Alignment::HORIZONTAL_CENTER)
137 mHorizontal = Toolkit::Alignment::HORIZONTAL_CENTER;
140 // Vertical Alignment
141 if(type & Toolkit::Alignment::VERTICAL_BOTTOM)
143 mVertical = Toolkit::Alignment::VERTICAL_BOTTOM;
145 if(type & Toolkit::Alignment::VERTICAL_TOP)
147 mVertical = Toolkit::Alignment::VERTICAL_TOP;
149 if(type & Toolkit::Alignment::VERTICAL_CENTER)
151 mVertical = Toolkit::Alignment::VERTICAL_CENTER;
157 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
159 return Toolkit::Alignment::Type(mHorizontal | mVertical);
162 void Alignment::SetScaling(Toolkit::Alignment::Scaling scaling)
169 Toolkit::Alignment::Scaling Alignment::GetScaling() const
174 void Alignment::SetPadding(const Toolkit::Alignment::Padding& padding)
176 DALI_ASSERT_ALWAYS((padding.left >= 0.f) && (padding.top >= 0.f) && (padding.right >= 0.f) && (padding.bottom >= 0.f));
183 const Toolkit::Alignment::Padding& Alignment::GetPadding() const
188 void Alignment::OnInitialize()
190 Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
193 void Alignment::OnRelayout(const Vector2& size, RelayoutContainer& container)
195 // lay out the actors
196 Vector3 anchorPointAndParentOrigin = Vector3::ZERO;
197 anchorPointAndParentOrigin.z = 0.5f;
198 // anchorPoint.x is initialized to 0.0, which is HORIZONTAL_LEFT
199 if(Toolkit::Alignment::HORIZONTAL_CENTER == mHorizontal)
201 anchorPointAndParentOrigin.x = 0.5f;
203 else if(Toolkit::Alignment::HORIZONTAL_RIGHT == mHorizontal)
205 anchorPointAndParentOrigin.x = 1.0f;
207 // anchorPoint.y is initialized to 0.0, which is VERTICAL_TOP
208 if(Toolkit::Alignment::VERTICAL_CENTER == mVertical)
210 anchorPointAndParentOrigin.y = 0.5f;
212 else if(Toolkit::Alignment::VERTICAL_BOTTOM == mVertical)
214 anchorPointAndParentOrigin.y = 1.0f;
217 for(unsigned int i = 0, childCount = Self().GetChildCount(); i < childCount; ++i)
219 Actor child = Self().GetChildAt(i);
221 child.SetProperty(Actor::Property::ANCHOR_POINT, anchorPointAndParentOrigin);
222 child.SetProperty(Actor::Property::PARENT_ORIGIN, anchorPointAndParentOrigin);
224 Vector2 currentChildSize(child.GetTargetSize().GetVectorXY());
225 if(currentChildSize == Vector2::ZERO)
227 currentChildSize = child.GetNaturalSize();
230 bool renegotiate = true;
231 Vector2 newChildSize;
232 newChildSize.width = size.width - (mPadding.left + mPadding.right);
233 newChildSize.height = size.height - (mPadding.top + mPadding.bottom);
235 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
236 if((newChildSize.width > Math::MACHINE_EPSILON_1000) && (newChildSize.height > Math::MACHINE_EPSILON_1000) &&
237 (currentChildSize.width > Math::MACHINE_EPSILON_1000) && (currentChildSize.height > Math::MACHINE_EPSILON_1000))
239 // no point trying to squeeze actors into too small size
242 case Toolkit::Alignment::SCALE_NONE:
248 case Toolkit::Alignment::SCALE_TO_FILL:
250 // Nothing to do, newChildSize is already full size minus padding
253 case Toolkit::Alignment::SCALE_TO_FIT_KEEP_ASPECT:
255 newChildSize = currentChildSize * std::min((newChildSize.width / currentChildSize.width), (newChildSize.height / currentChildSize.height));
258 case Toolkit::Alignment::SCALE_TO_FILL_KEEP_ASPECT:
260 newChildSize = currentChildSize * std::max((newChildSize.width / currentChildSize.width), (newChildSize.height / currentChildSize.height));
263 case Toolkit::Alignment::SHRINK_TO_FIT:
265 newChildSize = Vector2(std::min(newChildSize.width, currentChildSize.width), std::min(newChildSize.height, currentChildSize.height));
268 case Toolkit::Alignment::SHRINK_TO_FIT_KEEP_ASPECT:
270 // check source size vs target size to see if we need to shrink
271 float widthScale = (newChildSize.width < currentChildSize.width) ? (newChildSize.width / currentChildSize.width) : 1.f;
272 float heightScale = (newChildSize.height < currentChildSize.height) ? (newChildSize.height / currentChildSize.height) : 1.0f;
273 // use smaller of the scales
274 float scale = std::min(widthScale, heightScale);
275 // check if we need to scale
278 // scale natural size to fit inside
279 newChildSize *= scale;
286 child.SetProperty(Actor::Property::POSITION, GetPosition(mPadding, mHorizontal, mVertical, newChildSize, currentChildSize));
290 container.Add(child, newChildSize);
295 Alignment::Alignment(Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical)
296 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
297 mHorizontal(horizontal),
299 mScaling(Toolkit::Alignment::SCALE_NONE),
300 mPadding(0.f, 0.f, 0.f, 0.f)
304 Alignment::~Alignment()
308 } // namespace Internal
310 } // namespace Toolkit