[dali_1.2.32] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / buttons / toggle-button-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 "toggle-button-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/object/type-registry.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/public-api/images/resource-image.h>
25 #include <dali/devel-api/scripting/scripting.h>
26 #include <dali/public-api/object/property-array.h>
27 #include <dali/integration-api/debug.h>
28
29 // INTERNAL INCLUDES
30 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
31 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
32 #include <dali-toolkit/devel-api/controls/buttons/button-devel.h>
33 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
34 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
35 #include <dali-toolkit/devel-api/align-enums.h>
36 #include <dali-toolkit/devel-api/controls/tooltip/tooltip-properties.h>
37 #include <dali-toolkit/devel-api/visuals/text-visual-properties.h>
38 #include <dali-toolkit/devel-api/controls/control-devel.h>
39
40 #if defined(DEBUG_ENABLED)
41   extern Debug::Filter* gLogButtonFilter;
42 #endif
43
44 namespace Dali
45 {
46
47 namespace Toolkit
48 {
49
50 namespace Internal
51 {
52
53 namespace
54 {
55
56 BaseHandle Create()
57 {
58   return Toolkit::ToggleButton::New();
59 }
60
61 // Properties
62 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ToggleButton, Toolkit::Button, Create )
63
64 DALI_PROPERTY_REGISTRATION( Toolkit, ToggleButton, "stateVisuals",       ARRAY,     STATE_VISUALS        )
65 DALI_PROPERTY_REGISTRATION( Toolkit, ToggleButton, "tooltips",           ARRAY,     TOOLTIPS             )
66 DALI_PROPERTY_REGISTRATION( Toolkit, ToggleButton, "currentStateIndex",  INTEGER,   CURRENT_STATE_INDEX  )
67
68 DALI_TYPE_REGISTRATION_END()
69
70 } // unnamed namespace
71
72 Dali::Toolkit::ToggleButton ToggleButton::New()
73 {
74   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::New\n" );
75   // Create the implementation, temporarily owned on stack
76   IntrusivePtr< ToggleButton > internalToggleButton = new ToggleButton();
77
78   // Pass ownership to CustomActor
79   Dali::Toolkit::ToggleButton toggleButton( *internalToggleButton );
80
81   // Second-phase init of the implementation
82   // This can only be done after the CustomActor connection has been made...
83   internalToggleButton->Initialize();
84
85   return toggleButton;
86 }
87
88 ToggleButton::ToggleButton()
89 : Button(),
90   mToggleStates(),
91   mToggleVisuals(),
92   mToggleSelectedVisuals(),
93   mToggleDisabledVisuals(),
94   mToggleDisabledSelectedVisuals(),
95   mToggleTooltips(),
96   mCurrentToggleIndex(0)
97 {
98   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::Constructor\n" );
99   SetTogglableButton( false );
100 }
101
102 ToggleButton::~ToggleButton()
103 {
104 }
105
106 void ToggleButton::OnInitialize()
107 {
108   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::OnInitialize\n" );
109   Button::OnInitialize();
110
111   // Toggle button requires the Leave event.
112   Actor self = Self();
113   self.SetLeaveRequired( true );
114 }
115
116 void ToggleButton::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
117 {
118   Toolkit::ToggleButton toggleButton = Toolkit::ToggleButton::DownCast( Dali::BaseHandle( object ) );
119
120   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "ToggleButton::SetProperty index[%d]\n", propertyIndex );
121
122   if ( toggleButton )
123   {
124     ToggleButton& toggleButtonImpl( GetImplementation( toggleButton ) );
125
126     switch ( propertyIndex )
127     {
128       case Toolkit::ToggleButton::Property::STATE_VISUALS:
129       {
130         Property::Array stateArray;
131         if( value.Get( stateArray ) )
132         {
133           toggleButtonImpl.SetToggleStates( stateArray );
134         }
135
136         break;
137       }
138       case Toolkit::ToggleButton::Property::TOOLTIPS:
139       {
140         Property::Array* tipArray = value.GetArray();
141         if( tipArray )
142         {
143           std::vector<std::string> tips;
144           size_t tipsCount = tipArray->Count();
145           tips.resize( tipsCount );
146           for( size_t i = 0; i != tipsCount; ++i )
147           {
148             tipArray->GetElementAt( i ).Get( tips[i] );
149           }
150           toggleButtonImpl.SetToggleTooltips(tips);
151         }
152         break;
153       }
154       default :
155       {
156         break;
157       }
158     } // end of switch
159   }
160 }
161
162 Property::Value ToggleButton::GetProperty( BaseObject* object, Property::Index propertyIndex )
163 {
164   Property::Value value;
165
166   Toolkit::ToggleButton toggleButton = Toolkit::ToggleButton::DownCast( Dali::BaseHandle( object ) );
167
168   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "ToggleButton::GetProperty index[%d]\n", propertyIndex );
169
170   if ( toggleButton )
171   {
172     ToggleButton& toggleButtonImpl( GetImplementation( toggleButton ) );
173
174     switch ( propertyIndex )
175     {
176       case Toolkit::ToggleButton::Property::STATE_VISUALS:
177       {
178         Property::Array array = toggleButtonImpl.GetToggleStates();
179         value = Property::Value( array );
180         break;
181       }
182       case Toolkit::ToggleButton::Property::TOOLTIPS:
183       {
184         Property::Value value1( Property::ARRAY );
185         Property::Array* tipArray = value1.GetArray();
186
187         if( tipArray )
188         {
189           std::vector<std::string> tips = toggleButtonImpl.GetToggleTooltips();
190           size_t tipsCount( tips.size() );
191           for( size_t i( 0 ); i != tipsCount; ++i )
192           {
193             tipArray->PushBack( tips[i] );
194           }
195         }
196         value = value1;
197         break;
198       }
199       case Toolkit::ToggleButton::Property::CURRENT_STATE_INDEX:
200       {
201         value = static_cast<int>(toggleButtonImpl.mCurrentToggleIndex);
202         break;
203       }
204     } // end of switch
205   }
206
207   return value;
208 }
209
210 void ToggleButton::CreateVisualsForAllStates( const Property::Array& states, std::vector<Toolkit::Visual::Base>& visuals )
211 {
212   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::CreateVisualsForAllStates\n" );
213
214   visuals.clear();
215
216   for ( unsigned int i = 0; i < states.Count(); i++ )
217   {
218     Property::Value value(  states[i] );
219
220     Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
221     Toolkit::Visual::Base stateVisual;
222
223     if ( value.GetType() == Property::MAP )
224     {
225       Property::Map *map = value.GetMap();
226       if( map && !map->Empty() ) // Empty map results in current visual removal.
227       {
228         DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "ToggleButton::CreateVisuals Using Map\n" );
229         stateVisual = visualFactory.CreateVisual( *map );
230       }
231     }
232     else if ( value.GetType() ==  Property::STRING )
233     {
234       std::string imageUrl = value.Get<std::string>();
235       DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "ToggleButton::CreateVisuals Using image URL\n" );
236       if ( !imageUrl.empty() )
237       {
238         stateVisual = visualFactory.CreateVisual( imageUrl, ImageDimensions() );
239       }
240     }
241
242     if ( stateVisual )
243     {
244       stateVisual.SetDepthIndex( DepthIndex::CONTENT );
245       visuals.push_back( stateVisual );
246     }
247   } // end of for
248   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "ToggleButton::CreateVisuals mToggleVisuals:%d\n", mToggleVisuals.size() );
249 }
250
251 void ToggleButton::SetToggleStates( const Property::Array& states )
252 { //this should really be generalized to be either string or maps so that any visual can be created.
253   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::SetToggleStates\n" );
254   if ( !states.Empty() )
255   {
256     mToggleStates.Clear();
257     mToggleStates = states;
258     /* New toggle button index from 0. */
259     mCurrentToggleIndex = 0;
260
261     // Create all visuals, save to mToggleVisuals.
262     CreateVisualsForAllStates( states, mToggleVisuals );
263     CreateVisualsForAllStates( states, mToggleSelectedVisuals );
264     CreateVisualsForAllStates( states, mToggleDisabledVisuals );
265     CreateVisualsForAllStates( states, mToggleDisabledSelectedVisuals );
266
267     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::Began to register visual.\n" );
268
269     PrepareVisual( Toolkit::DevelButton::Property::UNSELECTED_VISUAL, mToggleVisuals[mCurrentToggleIndex] );
270     PrepareVisual( Toolkit::DevelButton::Property::SELECTED_VISUAL, mToggleSelectedVisuals[mCurrentToggleIndex] );
271     PrepareVisual( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL, mToggleDisabledVisuals[mCurrentToggleIndex] );
272     PrepareVisual( Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL, mToggleDisabledSelectedVisuals[mCurrentToggleIndex] );
273
274     RelayoutRequest();
275   }
276 }
277
278 Property::Array ToggleButton::GetToggleStates() const
279 {
280   return mToggleStates;
281 }
282
283 void ToggleButton::SetToggleTooltips( std::vector<std::string>& tips )
284 {
285   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::SetToggleTooltips\n" );
286   if ( !tips.empty() )
287   {
288     mToggleTooltips.clear();
289     mToggleTooltips.swap( tips );
290   }
291
292   if ( !mToggleTooltips.empty() && ( mCurrentToggleIndex < mToggleTooltips.size() ) )
293   {
294     Self().SetProperty( Toolkit::DevelControl::Property::TOOLTIP, mToggleTooltips[mCurrentToggleIndex] );
295   }
296
297   RelayoutRequest();
298 }
299
300 const std::vector<std::string>& ToggleButton::GetToggleTooltips() const
301 {
302   return mToggleTooltips;
303 }
304
305 void ToggleButton::PrepareVisual(Property::Index index, Toolkit::Visual::Base& visual)
306 {
307   RegisterVisual( index, visual, true );
308   EnableVisual( index, false );
309 }
310
311 void ToggleButton::RelayoutVisual( Property::Index index, const Vector2& size )
312 {
313   Toolkit::Visual::Base visual = GetVisual( index );
314   if ( visual )
315   {
316     Size visualSize = Size::ZERO;
317     Vector2 visualPosition = Vector2::ZERO;
318
319     visual.GetNaturalSize( visualSize );
320
321     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::OnRelayout Setting visual size to(%f,%f)\n", visualSize.width, visualSize.height );
322     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::OnRelayout Setting visual position to(%f,%f)\n", visualPosition.x, visualPosition.y );
323
324     Property::Map visualTransform;
325     visualTransform.Add( Toolkit::DevelVisual::Transform::Property::SIZE, visualSize )
326                    .Add( Toolkit::DevelVisual::Transform::Property::OFFSET, visualPosition )
327                    .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_POLICY, Vector2( DevelVisual::Transform::Policy::ABSOLUTE, DevelVisual::Transform::Policy::ABSOLUTE ) )
328                    .Add( Toolkit::DevelVisual::Transform::Property::SIZE_POLICY, Vector2( DevelVisual::Transform::Policy::ABSOLUTE, DevelVisual::Transform::Policy::ABSOLUTE ) )
329                    .Add( Toolkit::DevelVisual::Transform::Property::ORIGIN, Toolkit::Align::CENTER )
330                    .Add( Toolkit::DevelVisual::Transform::Property::ANCHOR_POINT, Toolkit::Align::CENTER );
331
332     visual.SetTransformAndSize( visualTransform, size );
333   }
334 }
335
336 void ToggleButton::OnRelayout( const Vector2& size, RelayoutContainer& container )
337 {
338   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::OnRelayout targetSize(%f,%f) ptr(%p)\n", size.width, size.height, this );
339
340   RelayoutVisual( Toolkit::DevelButton::Property::UNSELECTED_VISUAL, size );
341   RelayoutVisual( Toolkit::DevelButton::Property::SELECTED_VISUAL, size );
342   RelayoutVisual( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL, size );
343   RelayoutVisual( Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL, size );
344 }
345
346 void ToggleButton::OnPressed()
347 {
348   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "ToggleButton::OnPressed\n" );
349   // State index will add 1 only when button is pressed.
350   mCurrentToggleIndex = ( mCurrentToggleIndex + 1 ) % mToggleVisuals.size();
351
352   // Both create SelectedVisual and UnselectedVisual
353   PrepareVisual( Toolkit::DevelButton::Property::UNSELECTED_VISUAL, mToggleVisuals[mCurrentToggleIndex] );
354   PrepareVisual( Toolkit::DevelButton::Property::SELECTED_VISUAL, mToggleSelectedVisuals[mCurrentToggleIndex] );
355   PrepareVisual( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL, mToggleDisabledVisuals[mCurrentToggleIndex] );
356   PrepareVisual( Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL, mToggleDisabledSelectedVisuals[mCurrentToggleIndex] );
357
358   //Need to check mCurrentToggleIndex, it must less than the size of mToggleTooltips.
359   if ( !mToggleTooltips.empty() && ( mCurrentToggleIndex < mToggleTooltips.size() ) )
360   {
361     Self().SetProperty( Toolkit::DevelControl::Property::TOOLTIP, mToggleTooltips[mCurrentToggleIndex] );
362   }
363
364   RelayoutRequest();
365 }
366
367 } // namespace Internal
368
369 } // namespace Toolkit
370
371 } // namespace Dali