(TableView) Move from devel-api to public-api
[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 #include <dali/devel-api/object/type-registry-helper.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/public-api/controls/alignment/alignment.h>
29
30 namespace Dali
31 {
32
33 namespace Toolkit
34 {
35
36 namespace Internal
37 {
38
39 namespace
40 {
41
42 BaseHandle Create()
43 {
44   return Toolkit::ToolBar::New();
45 }
46
47 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ToolBar, Toolkit::Control, Create )
48 DALI_TYPE_REGISTRATION_END()
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::Toolbar
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( Vector2( mToolBarSize.width, mToolBarSize.height ) );
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.SetSizeScalePolicy( SizeScalePolicy::FIT_WITH_ASPECT_RATIO );
128   alignmentContainer.SetPadding( padding );
129   alignmentContainer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
130   alignmentContainer.Add( control );
131
132   // Insert the control in the table view.
133   mLayout.AddChild( alignmentContainer, Toolkit::TableView::CellPosition( 0, index ) );
134   mLayout.SetRelativeWidth( index, relativeSize );
135
136   // Relate control and alignmentContainer in order to allow removing controls.
137   mControls[control] = alignmentContainer;
138
139   // Update accumulated relative space.
140   mAccumulatedRelativeSpace += relativeSize;
141
142   // Update spaces between left, center and right groups of controls.
143   switch( alignment )
144   {
145     case Toolkit::Alignment::HorizontalLeft:
146     {
147       mLeftRelativeSpace -= relativeSize;
148       if ( mLeftRelativeSpace < 0.f )
149       {
150         mLeftRelativeSpace = 0.f;
151       }
152       break;
153     }
154     case Toolkit::Alignment::HorizontalCenter:
155     {
156       mLeftRelativeSpace -= 0.5f * relativeSize;
157       if ( mLeftRelativeSpace < 0.f )
158       {
159         mLeftRelativeSpace = 0.f;
160       }
161       mRightRelativeSpace -= 0.5f * relativeSize;
162       if ( mRightRelativeSpace < 0.f )
163       {
164         mRightRelativeSpace = 0.f;
165       }
166       break;
167     }
168     case Toolkit::Alignment::HorizontalRight:
169     {
170       mRightRelativeSpace -= relativeSize;
171       if ( mRightRelativeSpace < 0.f )
172       {
173         mRightRelativeSpace = 0.f;
174       }
175       break;
176     }
177     default:
178     {
179       DALI_ASSERT_ALWAYS( false );
180     }
181   }
182
183   mLayout.SetRelativeWidth( mLeftOffset, mLeftRelativeSpace );
184   mLayout.SetRelativeWidth( mCenterBase + mCenterOffset, mRightRelativeSpace );
185 }
186
187 void ToolBar::RemoveControl( Actor control )
188 {
189   Toolkit::TableView::CellPosition position;
190
191   // Find the alignment where the control is placed.
192   std::map<Actor,Toolkit::Alignment>::iterator it = mControls.find( control );
193
194   if( ( it != mControls.end() ) && ( mLayout.FindChildPosition( it->second, position ) ) )
195   {
196     // Update accumulated relative space.
197     mAccumulatedRelativeSpace -= mLayout.GetRelativeWidth( position.columnIndex );
198
199     // Update spaces between left, center and right groups of controls.
200     if( 1.0 > mAccumulatedRelativeSpace )
201     {
202       Toolkit::Alignment::Type alignment = Toolkit::Alignment::HorizontalLeft;
203       if( position.columnIndex < mLeftOffset )
204       {
205         alignment = Toolkit::Alignment::HorizontalLeft;
206       }
207       else if( ( position.columnIndex > mLeftOffset ) && ( position.columnIndex < mCenterBase + mCenterOffset ) )
208       {
209         alignment = Toolkit::Alignment::HorizontalCenter;
210       }
211       else if( position.columnIndex > mCenterBase + mCenterOffset )
212       {
213         alignment = Toolkit::Alignment::HorizontalRight;
214       }
215       else
216       {
217         DALI_ASSERT_ALWAYS( false );
218       }
219
220       float relativeSize = mLayout.GetRelativeWidth( position.columnIndex );
221
222       switch( alignment )
223       {
224         case Toolkit::Alignment::HorizontalLeft:
225         {
226           mLeftRelativeSpace += relativeSize;
227           if ( mLeftRelativeSpace < 0.f )
228           {
229             mLeftRelativeSpace = 0.f;
230           }
231           break;
232         }
233         case Toolkit::Alignment::HorizontalCenter:
234         {
235           mLeftRelativeSpace += 0.5f * relativeSize;
236           if ( mLeftRelativeSpace < 0.f )
237           {
238             mLeftRelativeSpace = 0.f;
239           }
240           mRightRelativeSpace += 0.5f * relativeSize;
241           if ( mRightRelativeSpace < 0.f )
242           {
243             mRightRelativeSpace = 0.f;
244           }
245           break;
246         }
247         case Toolkit::Alignment::HorizontalRight:
248         {
249           mRightRelativeSpace += relativeSize;
250           if ( mRightRelativeSpace < 0.f )
251           {
252             mRightRelativeSpace = 0.f;
253           }
254           break;
255         }
256         default:
257         {
258           DALI_ASSERT_ALWAYS( false );
259         }
260       }
261       mLayout.SetRelativeWidth( mLeftOffset, mLeftRelativeSpace );
262       mLayout.SetRelativeWidth( mCenterBase + mCenterOffset, mRightRelativeSpace );
263     }
264
265     // Remove alignment as parent of control.
266     it->second.Remove( control );
267
268     // Remove the relationship between control and alignment.
269     mControls.erase( it );
270
271     // Remove column from tableview.
272     mLayout.DeleteColumn( position.columnIndex );
273
274     // Update bases and offsets.
275     if( position.columnIndex < mCenterBase )
276     {
277       // Control is on the left side. Decrease left offset and center and right bases.
278       --mLeftOffset;
279       --mCenterBase;
280       --mRightBase;
281     }
282     else if( position.columnIndex < mCenterBase + mCenterOffset )
283     {
284       // Control is on the center side. Decrease center offset and right base.
285       --mCenterOffset;
286       --mRightBase;
287     }
288     else
289     {
290       // Control is on the right side. Decrease right base and right offset.
291       --mRightBase;
292       --mRightOffset;
293     }
294   }
295 }
296
297 ToolBar::ToolBar()
298 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
299   mLayout(),
300   mLeftOffset( 0 ),
301   mCenterBase( 1 ),
302   mCenterOffset( 0 ),
303   mRightBase( 2 ),
304   mRightOffset( 0 ),
305   mLeftRelativeSpace( 0.5f ),
306   mRightRelativeSpace( 0.5f ),
307   mAccumulatedRelativeSpace( 0.f ),
308   mInitializing( false ),
309   mControls()
310 {
311 }
312
313 ToolBar::~ToolBar()
314 {
315 }
316
317 void ToolBar::OnInitialize()
318 {
319   Lock lock( mInitializing );
320
321   // Layout
322   mLayout = Toolkit::TableView::New( 1, 1 );
323   mLayout.SetName( "TOOLBAR_LAYOUT" );
324   mLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
325   mLayout.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
326
327   Self().Add( mLayout );
328
329   // Add two default actors to create spaces between controls grouped on the left, center and right.
330   Actor leftSpace = Actor::New();
331   Actor rightSpace = Actor::New();
332   mLayout.AddChild( leftSpace, Toolkit::TableView::CellPosition( 0, 0 ) );
333   mLayout.AddChild( rightSpace, Toolkit::TableView::CellPosition( 0, 1 ) );
334   mLayout.SetRelativeWidth( 0, mLeftRelativeSpace );
335   mLayout.SetRelativeWidth( 1, mRightRelativeSpace );
336 }
337
338 void ToolBar::OnControlChildAdd(Actor& child)
339 {
340   if( !mInitializing )
341   {
342     // An actor is being added through the Actor's API.
343
344     // Remove child from tool bar actor and insert it in table view with some 'default' values
345     if ( child && child.GetParent() )
346     {
347       child.GetParent().Remove( child );
348     }
349
350     AddControl( child, DEFAULT_RELATIVE_SIZE, DEFAULT_ALIGNMENT, Toolkit::ToolBar::DEFAULT_PADDING );
351   }
352
353   // No OnControlChildRemove method required because Actors are added to the mLayout table view, so if an
354   // actor is removed using the Actor::RemoveChild method it will not remove anything because the
355   // actor is in mLayout not in Self().
356 }
357
358 void ToolBar::OnControlSizeSet( const Vector3& targetSize )
359 {
360   mToolBarSize = targetSize;
361   mBackground.SetSize( Vector2( mToolBarSize.width, mToolBarSize.height ) );
362 }
363
364 } // namespace Internal
365
366 } // namespace Toolkit
367
368 } // namespace Dali