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