[AT-SPI] Squashed implementation
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / tool-bar / tool-bar-impl.cpp
1 /*
2  * Copyright (c) 2017 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/animation/constraints.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/devel-api/controls/alignment/alignment.h>
28 #include <dali-toolkit/internal/controls/control/control-data-impl.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::HORIZONTAL_LEFT );
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::AddControl( Actor control, float relativeSize, Toolkit::Alignment::Type alignment, const Toolkit::Alignment::Padding& padding )
70 {
71   // Work out index and update bases and offsets for further insertions.
72   unsigned int index = 0;
73   switch( alignment )
74   {
75     case Toolkit::Alignment::HORIZONTAL_LEFT:
76     {
77       index = mLeftOffset;
78       ++mLeftOffset;
79       ++mCenterBase;
80       ++mRightBase;
81       break;
82     }
83     case Toolkit::Alignment::HORIZONTAL_CENTER:
84     {
85       index = mCenterBase + mCenterOffset;
86       ++mCenterOffset;
87       ++mRightBase;
88       break;
89     }
90     case Toolkit::Alignment::HORIZONTAL_RIGHT:
91     {
92       index = mRightBase - mRightOffset;
93       ++mRightBase;
94       ++mRightOffset;
95       break;
96     }
97     default:
98     {
99       DALI_ASSERT_ALWAYS( false );
100     }
101   }
102
103   // Create a new column for the new control.
104   mLayout.InsertColumn( index );
105
106   // Create an alignment container where to place the control.
107   Toolkit::Alignment alignmentContainer = Toolkit::Alignment::New( alignment );
108   alignmentContainer.SetProperty( Actor::Property::SIZE_SCALE_POLICY, SizeScalePolicy::FIT_WITH_ASPECT_RATIO );
109   alignmentContainer.SetPadding( padding );
110   alignmentContainer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
111   alignmentContainer.Add( control );
112
113   // Insert the control in the table view.
114   mLayout.AddChild( alignmentContainer, Toolkit::TableView::CellPosition( 0, index ) );
115   mLayout.SetRelativeWidth( index, relativeSize );
116
117   // Relate control and alignmentContainer in order to allow removing controls.
118   mControls[control] = alignmentContainer;
119
120   // Update accumulated relative space.
121   mAccumulatedRelativeSpace += relativeSize;
122
123   // Update spaces between left, center and right groups of controls.
124   switch( alignment )
125   {
126     case Toolkit::Alignment::HORIZONTAL_LEFT:
127     {
128       mLeftRelativeSpace -= relativeSize;
129       if ( mLeftRelativeSpace < 0.f )
130       {
131         mLeftRelativeSpace = 0.f;
132       }
133       break;
134     }
135     case Toolkit::Alignment::HORIZONTAL_CENTER:
136     {
137       mLeftRelativeSpace -= 0.5f * relativeSize;
138       if ( mLeftRelativeSpace < 0.f )
139       {
140         mLeftRelativeSpace = 0.f;
141       }
142       mRightRelativeSpace -= 0.5f * relativeSize;
143       if ( mRightRelativeSpace < 0.f )
144       {
145         mRightRelativeSpace = 0.f;
146       }
147       break;
148     }
149     case Toolkit::Alignment::HORIZONTAL_RIGHT:
150     {
151       mRightRelativeSpace -= relativeSize;
152       if ( mRightRelativeSpace < 0.f )
153       {
154         mRightRelativeSpace = 0.f;
155       }
156       break;
157     }
158     default:
159     {
160       DALI_ASSERT_ALWAYS( false );
161     }
162   }
163
164   mLayout.SetRelativeWidth( mLeftOffset, mLeftRelativeSpace );
165   mLayout.SetRelativeWidth( mCenterBase + mCenterOffset, mRightRelativeSpace );
166 }
167
168 void ToolBar::RemoveControl( Actor control )
169 {
170   Toolkit::TableView::CellPosition position;
171
172   // Find the alignment where the control is placed.
173   std::map<Actor,Toolkit::Alignment>::iterator it = mControls.find( control );
174
175   if( ( it != mControls.end() ) && ( mLayout.FindChildPosition( it->second, position ) ) )
176   {
177     // Update accumulated relative space.
178     mAccumulatedRelativeSpace -= mLayout.GetRelativeWidth( position.columnIndex );
179
180     // Update spaces between left, center and right groups of controls.
181     if( 1.0 > mAccumulatedRelativeSpace )
182     {
183       Toolkit::Alignment::Type alignment = Toolkit::Alignment::HORIZONTAL_LEFT;
184       if( position.columnIndex < mLeftOffset )
185       {
186         alignment = Toolkit::Alignment::HORIZONTAL_LEFT;
187       }
188       else if( ( position.columnIndex > mLeftOffset ) && ( position.columnIndex < mCenterBase + mCenterOffset ) )
189       {
190         alignment = Toolkit::Alignment::HORIZONTAL_CENTER;
191       }
192       else if( position.columnIndex > mCenterBase + mCenterOffset )
193       {
194         alignment = Toolkit::Alignment::HORIZONTAL_RIGHT;
195       }
196       else
197       {
198         DALI_ASSERT_ALWAYS( false );
199       }
200
201       float relativeSize = mLayout.GetRelativeWidth( position.columnIndex );
202
203       switch( alignment )
204       {
205         case Toolkit::Alignment::HORIZONTAL_LEFT:
206         {
207           mLeftRelativeSpace += relativeSize;
208           if ( mLeftRelativeSpace < 0.f )
209           {
210             mLeftRelativeSpace = 0.f;
211           }
212           break;
213         }
214         case Toolkit::Alignment::HORIZONTAL_CENTER:
215         {
216           mLeftRelativeSpace += 0.5f * relativeSize;
217           if ( mLeftRelativeSpace < 0.f )
218           {
219             mLeftRelativeSpace = 0.f;
220           }
221           mRightRelativeSpace += 0.5f * relativeSize;
222           if ( mRightRelativeSpace < 0.f )
223           {
224             mRightRelativeSpace = 0.f;
225           }
226           break;
227         }
228         case Toolkit::Alignment::HORIZONTAL_RIGHT:
229         {
230           mRightRelativeSpace += relativeSize;
231           if ( mRightRelativeSpace < 0.f )
232           {
233             mRightRelativeSpace = 0.f;
234           }
235           break;
236         }
237         default:
238         {
239           DALI_ASSERT_ALWAYS( false );
240         }
241       }
242       mLayout.SetRelativeWidth( mLeftOffset, mLeftRelativeSpace );
243       mLayout.SetRelativeWidth( mCenterBase + mCenterOffset, mRightRelativeSpace );
244     }
245
246     // Remove alignment as parent of control.
247     it->second.Remove( control );
248
249     // Remove the relationship between control and alignment.
250     mControls.erase( it );
251
252     // Remove column from tableview.
253     mLayout.DeleteColumn( position.columnIndex );
254
255     // Update bases and offsets.
256     if( position.columnIndex < mCenterBase )
257     {
258       // Control is on the left side. Decrease left offset and center and right bases.
259       --mLeftOffset;
260       --mCenterBase;
261       --mRightBase;
262     }
263     else if( position.columnIndex < mCenterBase + mCenterOffset )
264     {
265       // Control is on the center side. Decrease center offset and right base.
266       --mCenterOffset;
267       --mRightBase;
268     }
269     else
270     {
271       // Control is on the right side. Decrease right base and right offset.
272       --mRightBase;
273       --mRightOffset;
274     }
275   }
276 }
277
278 ToolBar::ToolBar()
279 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
280   mLayout(),
281   mLeftOffset( 0 ),
282   mCenterBase( 1 ),
283   mCenterOffset( 0 ),
284   mRightBase( 2 ),
285   mRightOffset( 0 ),
286   mLeftRelativeSpace( 0.5f ),
287   mRightRelativeSpace( 0.5f ),
288   mAccumulatedRelativeSpace( 0.f ),
289   mInitializing( false ),
290   mControls()
291 {
292   DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
293     return std::unique_ptr< Dali::Accessibility::Accessible >(
294       new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::TOOL_BAR, true ) );
295   } );
296 }
297
298 ToolBar::~ToolBar()
299 {
300 }
301
302 void ToolBar::OnInitialize()
303 {
304   Lock lock( mInitializing );
305
306   // Layout
307   mLayout = Toolkit::TableView::New( 1, 1 );
308   mLayout.SetProperty( Dali::Actor::Property::NAME, "TOOLBAR_LAYOUT" );
309   mLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
310   mLayout.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
311
312   Self().Add( mLayout );
313
314   // Add two default actors to create spaces between controls grouped on the left, center and right.
315   Actor leftSpace = Actor::New();
316   Actor rightSpace = Actor::New();
317   mLayout.AddChild( leftSpace, Toolkit::TableView::CellPosition( 0, 0 ) );
318   mLayout.AddChild( rightSpace, Toolkit::TableView::CellPosition( 0, 1 ) );
319   mLayout.SetRelativeWidth( 0, mLeftRelativeSpace );
320   mLayout.SetRelativeWidth( 1, mRightRelativeSpace );
321 }
322
323 void ToolBar::OnChildAdd(Actor& child)
324 {
325   if( !mInitializing )
326   {
327     // An actor is being added through the Actor's API.
328
329     // Remove child from tool bar actor and insert it in table view with some 'default' values
330     if ( child && child.GetParent() )
331     {
332       child.GetParent().Remove( child );
333     }
334
335     AddControl( child, DEFAULT_RELATIVE_SIZE, DEFAULT_ALIGNMENT, Toolkit::ToolBar::DEFAULT_PADDING );
336   }
337
338   // No OnChildRemove method required because Actors are added to the mLayout table view, so if an
339   // actor is removed using the Actor::RemoveChild method it will not remove anything because the
340   // actor is in mLayout not in Self().
341
342   Control::OnChildAdd( child );
343 }
344
345 } // namespace Internal
346
347 } // namespace Toolkit
348
349 } // namespace Dali