Include required header files directly rather than through dali.h
[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 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.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
77
78   RenderableActor renderableActor = RenderableActor::DownCast( background );
79   if ( renderableActor )
80   {
81     renderableActor.SetSortModifier( 1.f );
82   }
83
84   Self().Add( background );
85 }
86
87 void ToolBar::AddControl( Actor control, float relativeSize, Toolkit::Alignment::Type alignment, const Toolkit::Alignment::Padding& padding )
88 {
89   // Work out index and update bases and offsets for further insertions.
90   unsigned int index = 0;
91   switch( alignment )
92   {
93     case Toolkit::Alignment::HorizontalLeft:
94     {
95       index = mLeftOffset;
96       ++mLeftOffset;
97       ++mCenterBase;
98       ++mRightBase;
99       break;
100     }
101     case Toolkit::Alignment::HorizontalCenter:
102     {
103       index = mCenterBase + mCenterOffset;
104       ++mCenterOffset;
105       ++mRightBase;
106       break;
107     }
108     case Toolkit::Alignment::HorizontalRight:
109     {
110       index = mRightBase - mRightOffset;
111       ++mRightBase;
112       ++mRightOffset;
113       break;
114     }
115     default:
116     {
117       DALI_ASSERT_ALWAYS( false );
118     }
119   }
120
121   // Create a new column for the new control.
122   mLayout.InsertColumn( index );
123
124   // Create an alignment container where to place the control.
125   Toolkit::Alignment alignmentContainer = Toolkit::Alignment::New( alignment );
126   alignmentContainer.SetScaling( Toolkit::Alignment::ScaleToFill );
127   alignmentContainer.SetPadding( padding );
128   alignmentContainer.Add( control );
129
130   // Insert the control in the table view.
131   mLayout.AddChild( alignmentContainer, Toolkit::TableView::CellPosition( 0, index ) );
132   mLayout.SetRelativeWidth( index, relativeSize );
133
134   // Relate control and alignmentContainer in order to allow removing controls.
135   mControls[control] = alignmentContainer;
136
137   // Update accumulated relative space.
138   mAccumulatedRelativeSpace += relativeSize;
139
140   // Update spaces between left, center and right groups of controls.
141   switch( alignment )
142   {
143     case Toolkit::Alignment::HorizontalLeft:
144     {
145       mLeftRelativeSpace -= relativeSize;
146       if ( mLeftRelativeSpace < 0.f )
147       {
148         mLeftRelativeSpace = 0.f;
149       }
150       break;
151     }
152     case Toolkit::Alignment::HorizontalCenter:
153     {
154       mLeftRelativeSpace -= 0.5f * relativeSize;
155       if ( mLeftRelativeSpace < 0.f )
156       {
157         mLeftRelativeSpace = 0.f;
158       }
159       mRightRelativeSpace -= 0.5f * relativeSize;
160       if ( mRightRelativeSpace < 0.f )
161       {
162         mRightRelativeSpace = 0.f;
163       }
164       break;
165     }
166     case Toolkit::Alignment::HorizontalRight:
167     {
168       mRightRelativeSpace -= relativeSize;
169       if ( mRightRelativeSpace < 0.f )
170       {
171         mRightRelativeSpace = 0.f;
172       }
173       break;
174     }
175     default:
176     {
177       DALI_ASSERT_ALWAYS( false );
178     }
179   }
180
181   mLayout.SetRelativeWidth( mLeftOffset, mLeftRelativeSpace );
182   mLayout.SetRelativeWidth( mCenterBase + mCenterOffset, mRightRelativeSpace );
183 }
184
185 void ToolBar::RemoveControl( Actor control )
186 {
187   Toolkit::TableView::CellPosition position;
188
189   // Find the alignment where the control is placed.
190   std::map<Actor,Toolkit::Alignment>::iterator it = mControls.find( control );
191
192   if( ( it != mControls.end() ) && ( mLayout.FindChildPosition( it->second, position ) ) )
193   {
194     // Update accumulated relative space.
195     mAccumulatedRelativeSpace -= mLayout.GetRelativeWidth( position.columnIndex );
196
197     // Update spaces between left, center and right groups of controls.
198     if( 1.0 > mAccumulatedRelativeSpace )
199     {
200       Toolkit::Alignment::Type alignment = Toolkit::Alignment::HorizontalLeft;
201       if( position.columnIndex < mLeftOffset )
202       {
203         alignment = Toolkit::Alignment::HorizontalLeft;
204       }
205       else if( ( position.columnIndex > mLeftOffset ) && ( position.columnIndex < mCenterBase + mCenterOffset ) )
206       {
207         alignment = Toolkit::Alignment::HorizontalCenter;
208       }
209       else if( position.columnIndex > mCenterBase + mCenterOffset )
210       {
211         alignment = Toolkit::Alignment::HorizontalRight;
212       }
213       else
214       {
215         DALI_ASSERT_ALWAYS( false );
216       }
217
218       float relativeSize = mLayout.GetRelativeWidth( position.columnIndex );
219
220       switch( alignment )
221       {
222         case Toolkit::Alignment::HorizontalLeft:
223         {
224           mLeftRelativeSpace += relativeSize;
225           if ( mLeftRelativeSpace < 0.f )
226           {
227             mLeftRelativeSpace = 0.f;
228           }
229           break;
230         }
231         case Toolkit::Alignment::HorizontalCenter:
232         {
233           mLeftRelativeSpace += 0.5f * relativeSize;
234           if ( mLeftRelativeSpace < 0.f )
235           {
236             mLeftRelativeSpace = 0.f;
237           }
238           mRightRelativeSpace += 0.5f * relativeSize;
239           if ( mRightRelativeSpace < 0.f )
240           {
241             mRightRelativeSpace = 0.f;
242           }
243           break;
244         }
245         case Toolkit::Alignment::HorizontalRight:
246         {
247           mRightRelativeSpace += relativeSize;
248           if ( mRightRelativeSpace < 0.f )
249           {
250             mRightRelativeSpace = 0.f;
251           }
252           break;
253         }
254         default:
255         {
256           DALI_ASSERT_ALWAYS( false );
257         }
258       }
259       mLayout.SetRelativeWidth( mLeftOffset, mLeftRelativeSpace );
260       mLayout.SetRelativeWidth( mCenterBase + mCenterOffset, mRightRelativeSpace );
261     }
262
263     // Remove alignment as parent of control.
264     it->second.Remove( control );
265
266     // Remove the relationship between control and alignment.
267     mControls.erase( it );
268
269     // Remove column from tableview.
270     mLayout.DeleteColumn( position.columnIndex );
271
272     // Update bases and offsets.
273     if( position.columnIndex < mCenterBase )
274     {
275       // Control is on the left side. Decrease left offset and center and right bases.
276       --mLeftOffset;
277       --mCenterBase;
278       --mRightBase;
279     }
280     else if( position.columnIndex < mCenterBase + mCenterOffset )
281     {
282       // Control is on the center side. Decrease center offset and right base.
283       --mCenterOffset;
284       --mRightBase;
285     }
286     else
287     {
288       // Control is on the right side. Decrease right base and right offset.
289       --mRightBase;
290       --mRightOffset;
291     }
292   }
293 }
294
295 ToolBar::ToolBar()
296 : Control( CONTROL_BEHAVIOUR_NONE ),
297   mLayout(),
298   mLeftOffset( 0 ),
299   mCenterBase( 1 ),
300   mCenterOffset( 0 ),
301   mRightBase( 2 ),
302   mRightOffset( 0 ),
303   mLeftRelativeSpace( 0.5f ),
304   mRightRelativeSpace( 0.5f ),
305   mAccumulatedRelativeSpace( 0.f ),
306   mInitializing( false ),
307   mControls()
308 {
309 }
310
311 ToolBar::~ToolBar()
312 {
313 }
314
315 void ToolBar::OnInitialize()
316 {
317   Lock lock( mInitializing );
318
319   // Layout
320   mLayout = Toolkit::TableView::New( 1, 1 );
321   mLayout.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
322
323   Self().Add( mLayout );
324
325   // Add two default actors to create spaces between controls grouped on the left, center and right.
326   Actor leftSpace = Actor::New();
327   Actor rightSpace = Actor::New();
328   mLayout.AddChild( leftSpace, Toolkit::TableView::CellPosition( 0, 0 ) );
329   mLayout.AddChild( rightSpace, Toolkit::TableView::CellPosition( 0, 1 ) );
330   mLayout.SetRelativeWidth( 0, mLeftRelativeSpace );
331   mLayout.SetRelativeWidth( 1, mRightRelativeSpace );
332 }
333
334 void ToolBar::OnControlChildAdd(Actor& child)
335 {
336   if( !mInitializing )
337   {
338     // An actor is being added through the Actor's API.
339
340     // Remove child from tool bar actor and insert it in table view with some 'default' values
341     if ( child && child.GetParent() )
342     {
343       child.GetParent().Remove( child );
344     }
345
346     AddControl( child, DEFAULT_RELATIVE_SIZE, DEFAULT_ALIGNMENT, Toolkit::ToolBar::DEFAULT_PADDING );
347   }
348
349   // No OnControlChildRemove method required because Actors are added to the mLayout table view, so if an
350   // actor is removed using the Actor::RemoveChild method it will not remove anything because the
351   // actor is in mLayout not in Self().
352 }
353
354 void ToolBar::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
355 {
356   Relayout( mLayout, size, container );
357 }
358
359 } // namespace Internal
360
361 } // namespace Toolkit
362
363 } // namespace Dali