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