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