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