[AT-SPI] Remove SetAccessibilityConstructor()
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / alignment / alignment-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "alignment-impl.h"
20
21 // EXTERNAL INCLUDES
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>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/devel-api/controls/control-devel.h>
29
30 namespace Dali
31 {
32 namespace Toolkit
33 {
34 namespace Internal
35 {
36 namespace
37 {
38 //Type Registration
39 BaseHandle Create()
40 {
41   return Toolkit::Alignment::New();
42 }
43
44 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::Alignment, Toolkit::Control, Create)
45 DALI_TYPE_REGISTRATION_END()
46
47 /**
48  * @param padding The padding value
49  * @param horizontalAlignment The horizontal alignment.
50  * @param verticalAlignment The vertical alignment.
51  * @param currentSize of the object
52  * @param parentSize
53  */
54 inline Vector3 GetPosition(const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment, const Vector2& currentSize, const Vector2& parentSize)
55 {
56   Vector3 position(0.f, 0.f, 0.f);
57
58   switch(horizontalAlignment)
59   {
60     case Dali::Toolkit::Alignment::HORIZONTAL_LEFT:
61     {
62       position.x += padding.left;
63       break;
64     }
65     case Dali::Toolkit::Alignment::HORIZONTAL_RIGHT:
66     {
67       position.x -= padding.right;
68       break;
69     }
70     case Dali::Toolkit::Alignment::HORIZONTAL_CENTER: // FALLTHROUGH
71     default:                                          // use center as default
72     {
73       if(currentSize.width + padding.left + padding.right >= parentSize.width)
74       {
75         position.x += 0.5f * (padding.left - padding.right);
76       }
77       break;
78     }
79   }
80
81   switch(verticalAlignment)
82   {
83     case Dali::Toolkit::Alignment::VERTICAL_TOP:
84     {
85       position.y += padding.top;
86       break;
87     }
88     case Dali::Toolkit::Alignment::VERTICAL_BOTTOM:
89     {
90       position.y -= padding.bottom;
91       break;
92     }
93     case Dali::Toolkit::Alignment::VERTICAL_CENTER: // FALLTHROUGH
94     default:                                        // use center as default
95     {
96       if(currentSize.height + padding.top + padding.bottom >= parentSize.height)
97       {
98         position.y += 0.5f * (padding.top - padding.bottom);
99       }
100       break;
101     }
102   }
103
104   return position;
105 }
106
107 } // namespace
108
109 Toolkit::Alignment Alignment::New(Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical)
110 {
111   // Create the implementation, temporarily owned on stack
112   IntrusivePtr<Alignment> internalAlignment = new Alignment(horizontal, vertical);
113
114   // Pass ownership to Toolkit::Alignment
115   Toolkit::Alignment alignment(*internalAlignment);
116
117   // Second-phase init of the implementation
118   // This can only be done after the CustomActor connection has been made...
119   internalAlignment->Initialize();
120
121   return alignment;
122 }
123
124 void Alignment::SetAlignmentType(Toolkit::Alignment::Type type)
125 {
126   // Horizontal Alignment
127   if(type & Toolkit::Alignment::HORIZONTAL_RIGHT)
128   {
129     mHorizontal = Toolkit::Alignment::HORIZONTAL_RIGHT;
130   }
131   if(type & Toolkit::Alignment::HORIZONTAL_LEFT)
132   {
133     mHorizontal = Toolkit::Alignment::HORIZONTAL_LEFT;
134   }
135   if(type & Toolkit::Alignment::HORIZONTAL_CENTER)
136   {
137     mHorizontal = Toolkit::Alignment::HORIZONTAL_CENTER;
138   }
139
140   // Vertical Alignment
141   if(type & Toolkit::Alignment::VERTICAL_BOTTOM)
142   {
143     mVertical = Toolkit::Alignment::VERTICAL_BOTTOM;
144   }
145   if(type & Toolkit::Alignment::VERTICAL_TOP)
146   {
147     mVertical = Toolkit::Alignment::VERTICAL_TOP;
148   }
149   if(type & Toolkit::Alignment::VERTICAL_CENTER)
150   {
151     mVertical = Toolkit::Alignment::VERTICAL_CENTER;
152   }
153
154   RelayoutRequest();
155 }
156
157 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
158 {
159   return Toolkit::Alignment::Type(mHorizontal | mVertical);
160 }
161
162 void Alignment::SetScaling(Toolkit::Alignment::Scaling scaling)
163 {
164   mScaling = scaling;
165
166   RelayoutRequest();
167 }
168
169 Toolkit::Alignment::Scaling Alignment::GetScaling() const
170 {
171   return mScaling;
172 }
173
174 void Alignment::SetPadding(const Toolkit::Alignment::Padding& padding)
175 {
176   DALI_ASSERT_ALWAYS((padding.left >= 0.f) && (padding.top >= 0.f) && (padding.right >= 0.f) && (padding.bottom >= 0.f));
177
178   mPadding = padding;
179
180   RelayoutRequest();
181 }
182
183 const Toolkit::Alignment::Padding& Alignment::GetPadding() const
184 {
185   return mPadding;
186 }
187
188 void Alignment::OnInitialize()
189 {
190   Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
191 }
192
193 void Alignment::OnRelayout(const Vector2& size, RelayoutContainer& container)
194 {
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)
200   {
201     anchorPointAndParentOrigin.x = 0.5f;
202   }
203   else if(Toolkit::Alignment::HORIZONTAL_RIGHT == mHorizontal)
204   {
205     anchorPointAndParentOrigin.x = 1.0f;
206   }
207   // anchorPoint.y is initialized to 0.0, which is VERTICAL_TOP
208   if(Toolkit::Alignment::VERTICAL_CENTER == mVertical)
209   {
210     anchorPointAndParentOrigin.y = 0.5f;
211   }
212   else if(Toolkit::Alignment::VERTICAL_BOTTOM == mVertical)
213   {
214     anchorPointAndParentOrigin.y = 1.0f;
215   }
216
217   for(unsigned int i = 0, childCount = Self().GetChildCount(); i < childCount; ++i)
218   {
219     Actor child = Self().GetChildAt(i);
220
221     child.SetProperty(Actor::Property::ANCHOR_POINT, anchorPointAndParentOrigin);
222     child.SetProperty(Actor::Property::PARENT_ORIGIN, anchorPointAndParentOrigin);
223
224     Vector2 currentChildSize(child.GetTargetSize().GetVectorXY());
225     if(currentChildSize == Vector2::ZERO)
226     {
227       currentChildSize = child.GetNaturalSize();
228     }
229
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);
234
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))
238     {
239       // no point trying to squeeze actors into too small size
240       switch(mScaling)
241       {
242         case Toolkit::Alignment::SCALE_NONE:
243         {
244           // Nothing to do
245           renegotiate = false;
246           break;
247         }
248         case Toolkit::Alignment::SCALE_TO_FILL:
249         {
250           // Nothing to do, newChildSize is already full size minus padding
251           break;
252         }
253         case Toolkit::Alignment::SCALE_TO_FIT_KEEP_ASPECT:
254         {
255           newChildSize = currentChildSize * std::min((newChildSize.width / currentChildSize.width), (newChildSize.height / currentChildSize.height));
256           break;
257         }
258         case Toolkit::Alignment::SCALE_TO_FILL_KEEP_ASPECT:
259         {
260           newChildSize = currentChildSize * std::max((newChildSize.width / currentChildSize.width), (newChildSize.height / currentChildSize.height));
261           break;
262         }
263         case Toolkit::Alignment::SHRINK_TO_FIT:
264         {
265           newChildSize = Vector2(std::min(newChildSize.width, currentChildSize.width), std::min(newChildSize.height, currentChildSize.height));
266           break;
267         }
268         case Toolkit::Alignment::SHRINK_TO_FIT_KEEP_ASPECT:
269         {
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
276           if(scale < 1.0f)
277           {
278             // scale natural size to fit inside
279             newChildSize *= scale;
280           }
281           break;
282         }
283       }
284     }
285
286     child.SetProperty(Actor::Property::POSITION, GetPosition(mPadding, mHorizontal, mVertical, newChildSize, currentChildSize));
287
288     if(renegotiate)
289     {
290       container.Add(child, newChildSize);
291     }
292   }
293 }
294
295 Alignment::Alignment(Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical)
296 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
297   mHorizontal(horizontal),
298   mVertical(vertical),
299   mScaling(Toolkit::Alignment::SCALE_NONE),
300   mPadding(0.f, 0.f, 0.f, 0.f)
301 {
302 }
303
304 Alignment::~Alignment()
305 {
306 }
307
308 } // namespace Internal
309
310 } // namespace Toolkit
311
312 } // namespace Dali