Updated all cpp files to new format
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / tool-bar / tool-bar-impl.cpp
1 /*
2  * Copyright (c) 2021 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 "tool-bar-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/animation/constraints.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/public-api/object/type-registry.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/devel-api/controls/alignment/alignment.h>
28 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
29
30 namespace Dali
31 {
32 namespace Toolkit
33 {
34 namespace Internal
35 {
36 namespace
37 {
38 BaseHandle Create()
39 {
40   return Toolkit::ToolBar::New();
41 }
42
43 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::ToolBar, Toolkit::Control, Create)
44 DALI_TYPE_REGISTRATION_END()
45
46 const float                    DEFAULT_RELATIVE_SIZE(0.1f);
47 const Toolkit::Alignment::Type DEFAULT_ALIGNMENT(Toolkit::Alignment::HORIZONTAL_LEFT);
48 } // namespace
49
50 Toolkit::ToolBar ToolBar::New()
51 {
52   // Create the implementation, temporarily owned on stack
53   IntrusivePtr<ToolBar> internalToolBar = new ToolBar();
54
55   // Pass ownership to Toolkit::Toolbar
56   Toolkit::ToolBar toolBar(*internalToolBar);
57
58   // Second-phase init of the implementation
59   // This can only be done after the CustomActor connection has been made...
60   internalToolBar->Initialize();
61
62   return toolBar;
63 }
64
65 void ToolBar::AddControl(Actor control, float relativeSize, Toolkit::Alignment::Type alignment, const Toolkit::Alignment::Padding& padding)
66 {
67   // Work out index and update bases and offsets for further insertions.
68   unsigned int index = 0;
69   switch(alignment)
70   {
71     case Toolkit::Alignment::HORIZONTAL_LEFT:
72     {
73       index = mLeftOffset;
74       ++mLeftOffset;
75       ++mCenterBase;
76       ++mRightBase;
77       break;
78     }
79     case Toolkit::Alignment::HORIZONTAL_CENTER:
80     {
81       index = mCenterBase + mCenterOffset;
82       ++mCenterOffset;
83       ++mRightBase;
84       break;
85     }
86     case Toolkit::Alignment::HORIZONTAL_RIGHT:
87     {
88       index = mRightBase - mRightOffset;
89       ++mRightBase;
90       ++mRightOffset;
91       break;
92     }
93     default:
94     {
95       DALI_ASSERT_ALWAYS(false);
96     }
97   }
98
99   // Create a new column for the new control.
100   mLayout.InsertColumn(index);
101
102   // Create an alignment container where to place the control.
103   Toolkit::Alignment alignmentContainer = Toolkit::Alignment::New(alignment);
104   alignmentContainer.SetProperty(Actor::Property::SIZE_SCALE_POLICY, SizeScalePolicy::FIT_WITH_ASPECT_RATIO);
105   alignmentContainer.SetPadding(padding);
106   alignmentContainer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
107   alignmentContainer.Add(control);
108
109   // Insert the control in the table view.
110   mLayout.AddChild(alignmentContainer, Toolkit::TableView::CellPosition(0, index));
111   mLayout.SetRelativeWidth(index, relativeSize);
112
113   // Relate control and alignmentContainer in order to allow removing controls.
114   mControls[control] = alignmentContainer;
115
116   // Update accumulated relative space.
117   mAccumulatedRelativeSpace += relativeSize;
118
119   // Update spaces between left, center and right groups of controls.
120   switch(alignment)
121   {
122     case Toolkit::Alignment::HORIZONTAL_LEFT:
123     {
124       mLeftRelativeSpace -= relativeSize;
125       if(mLeftRelativeSpace < 0.f)
126       {
127         mLeftRelativeSpace = 0.f;
128       }
129       break;
130     }
131     case Toolkit::Alignment::HORIZONTAL_CENTER:
132     {
133       mLeftRelativeSpace -= 0.5f * relativeSize;
134       if(mLeftRelativeSpace < 0.f)
135       {
136         mLeftRelativeSpace = 0.f;
137       }
138       mRightRelativeSpace -= 0.5f * relativeSize;
139       if(mRightRelativeSpace < 0.f)
140       {
141         mRightRelativeSpace = 0.f;
142       }
143       break;
144     }
145     case Toolkit::Alignment::HORIZONTAL_RIGHT:
146     {
147       mRightRelativeSpace -= relativeSize;
148       if(mRightRelativeSpace < 0.f)
149       {
150         mRightRelativeSpace = 0.f;
151       }
152       break;
153     }
154     default:
155     {
156       DALI_ASSERT_ALWAYS(false);
157     }
158   }
159
160   mLayout.SetRelativeWidth(mLeftOffset, mLeftRelativeSpace);
161   mLayout.SetRelativeWidth(mCenterBase + mCenterOffset, mRightRelativeSpace);
162 }
163
164 void ToolBar::RemoveControl(Actor control)
165 {
166   Toolkit::TableView::CellPosition position;
167
168   // Find the alignment where the control is placed.
169   std::map<Actor, Toolkit::Alignment>::iterator it = mControls.find(control);
170
171   if((it != mControls.end()) && (mLayout.FindChildPosition(it->second, position)))
172   {
173     // Update accumulated relative space.
174     mAccumulatedRelativeSpace -= mLayout.GetRelativeWidth(position.columnIndex);
175
176     // Update spaces between left, center and right groups of controls.
177     if(1.0 > mAccumulatedRelativeSpace)
178     {
179       Toolkit::Alignment::Type alignment = Toolkit::Alignment::HORIZONTAL_LEFT;
180       if(position.columnIndex < mLeftOffset)
181       {
182         alignment = Toolkit::Alignment::HORIZONTAL_LEFT;
183       }
184       else if((position.columnIndex > mLeftOffset) && (position.columnIndex < mCenterBase + mCenterOffset))
185       {
186         alignment = Toolkit::Alignment::HORIZONTAL_CENTER;
187       }
188       else if(position.columnIndex > mCenterBase + mCenterOffset)
189       {
190         alignment = Toolkit::Alignment::HORIZONTAL_RIGHT;
191       }
192       else
193       {
194         DALI_ASSERT_ALWAYS(false);
195       }
196
197       float relativeSize = mLayout.GetRelativeWidth(position.columnIndex);
198
199       switch(alignment)
200       {
201         case Toolkit::Alignment::HORIZONTAL_LEFT:
202         {
203           mLeftRelativeSpace += relativeSize;
204           if(mLeftRelativeSpace < 0.f)
205           {
206             mLeftRelativeSpace = 0.f;
207           }
208           break;
209         }
210         case Toolkit::Alignment::HORIZONTAL_CENTER:
211         {
212           mLeftRelativeSpace += 0.5f * relativeSize;
213           if(mLeftRelativeSpace < 0.f)
214           {
215             mLeftRelativeSpace = 0.f;
216           }
217           mRightRelativeSpace += 0.5f * relativeSize;
218           if(mRightRelativeSpace < 0.f)
219           {
220             mRightRelativeSpace = 0.f;
221           }
222           break;
223         }
224         case Toolkit::Alignment::HORIZONTAL_RIGHT:
225         {
226           mRightRelativeSpace += relativeSize;
227           if(mRightRelativeSpace < 0.f)
228           {
229             mRightRelativeSpace = 0.f;
230           }
231           break;
232         }
233         default:
234         {
235           DALI_ASSERT_ALWAYS(false);
236         }
237       }
238       mLayout.SetRelativeWidth(mLeftOffset, mLeftRelativeSpace);
239       mLayout.SetRelativeWidth(mCenterBase + mCenterOffset, mRightRelativeSpace);
240     }
241
242     // Remove alignment as parent of control.
243     it->second.Remove(control);
244
245     // Remove the relationship between control and alignment.
246     mControls.erase(it);
247
248     // Remove column from tableview.
249     mLayout.DeleteColumn(position.columnIndex);
250
251     // Update bases and offsets.
252     if(position.columnIndex < mCenterBase)
253     {
254       // Control is on the left side. Decrease left offset and center and right bases.
255       --mLeftOffset;
256       --mCenterBase;
257       --mRightBase;
258     }
259     else if(position.columnIndex < mCenterBase + mCenterOffset)
260     {
261       // Control is on the center side. Decrease center offset and right base.
262       --mCenterOffset;
263       --mRightBase;
264     }
265     else
266     {
267       // Control is on the right side. Decrease right base and right offset.
268       --mRightBase;
269       --mRightOffset;
270     }
271   }
272 }
273
274 ToolBar::ToolBar()
275 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
276   mLayout(),
277   mLeftOffset(0),
278   mCenterBase(1),
279   mCenterOffset(0),
280   mRightBase(2),
281   mRightOffset(0),
282   mLeftRelativeSpace(0.5f),
283   mRightRelativeSpace(0.5f),
284   mAccumulatedRelativeSpace(0.f),
285   mInitializing(false),
286   mControls()
287 {
288 }
289
290 ToolBar::~ToolBar()
291 {
292 }
293
294 void ToolBar::OnInitialize()
295 {
296   Lock lock(mInitializing);
297
298   // Layout
299   mLayout = Toolkit::TableView::New(1, 1);
300   mLayout.SetProperty(Dali::Actor::Property::NAME, "TOOLBAR_LAYOUT");
301   mLayout.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
302   mLayout.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
303
304   Self().Add(mLayout);
305
306   // Add two default actors to create spaces between controls grouped on the left, center and right.
307   Actor leftSpace  = Actor::New();
308   Actor rightSpace = Actor::New();
309   mLayout.AddChild(leftSpace, Toolkit::TableView::CellPosition(0, 0));
310   mLayout.AddChild(rightSpace, Toolkit::TableView::CellPosition(0, 1));
311   mLayout.SetRelativeWidth(0, mLeftRelativeSpace);
312   mLayout.SetRelativeWidth(1, mRightRelativeSpace);
313
314   DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
315     return std::unique_ptr<Dali::Accessibility::Accessible>(
316       new Control::Impl::AccessibleImpl(actor, Dali::Accessibility::Role::TOOL_BAR));
317   });
318 }
319
320 void ToolBar::OnChildAdd(Actor& child)
321 {
322   if(!mInitializing)
323   {
324     // An actor is being added through the Actor's API.
325
326     // Remove child from tool bar actor and insert it in table view with some 'default' values
327     if(child && child.GetParent())
328     {
329       child.GetParent().Remove(child);
330     }
331
332     AddControl(child, DEFAULT_RELATIVE_SIZE, DEFAULT_ALIGNMENT, Toolkit::ToolBar::DEFAULT_PADDING);
333   }
334
335   // No OnChildRemove method required because Actors are added to the mLayout table view, so if an
336   // actor is removed using the Actor::RemoveChild method it will not remove anything because the
337   // actor is in mLayout not in Self().
338
339   Control::OnChildAdd(child);
340 }
341
342 } // namespace Internal
343
344 } // namespace Toolkit
345
346 } // namespace Dali