[Tizen](ATSPI) squashed implementation
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / popup / confirmation-popup-impl.cpp
1 #include <dali-toolkit/internal/controls/control/control-data-impl.h>/*
2  * Copyright (c) 2015 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 "confirmation-popup-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/images/resource-image.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <cstring>
26
27 // INTERNAL INCLUDES
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 /*
43  * This struct is used to define all details required about a dynamically created signal.
44  */
45 struct ControlDetailType
46 {
47   const char* signalName;
48   const char* controlName;
49   const char* connectSignalPropertyName;
50 };
51
52 /* A table of all control details. These details are kept in one place for maintainability.
53  *  Name of the signal     | Name of the control  | Name of the property which lets the
54  *  the app-developer      | which will provide   | app developer choose which signal
55  *  can connect to.        | the signal.          | within the control to connect to.    */
56 const ControlDetailType ControlDetails[] = {
57   { "controlSignalOk",       "controlOk",           "connectSignalOkSelected"     },
58   { "controlSignalCancel",   "controlCancel",       "connectSignalCancelSelected" },
59 };
60 const unsigned int ControlDetailsCount = sizeof( ControlDetails ) / sizeof( ControlDetails[0] );
61
62 // To give sensible default behaviour to save the connect signal properties being set.
63 const char* const DEFAULT_CONNECT_SIGNAL_NAME = "clicked";
64
65 BaseHandle Create()
66 {
67   return Toolkit::ConfirmationPopup::New();
68 }
69
70 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ConfirmationPopup, Toolkit::Popup, Create )
71
72 DALI_PROPERTY_REGISTRATION( Toolkit, ConfirmationPopup, ControlDetails[0].connectSignalPropertyName, STRING, CONNECT_SIGNAL_OK_SELECTED     )
73 DALI_PROPERTY_REGISTRATION( Toolkit, ConfirmationPopup, ControlDetails[1].connectSignalPropertyName, STRING, CONNECT_SIGNAL_CANCEL_SELECTED )
74
75 // Note: We do not use the macros for signal registration as we do not want to redefine the signal name strings.
76 // We have predefined them for optimal signal name to control name lookup.
77 SignalConnectorType signalConnector1( typeRegistration, ControlDetails[0].signalName, &Toolkit::Internal::ConfirmationPopup::DoConnectSignal );
78 SignalConnectorType signalConnector2( typeRegistration, ControlDetails[1].signalName, &Toolkit::Internal::ConfirmationPopup::DoConnectSignal );
79
80 DALI_TYPE_REGISTRATION_END()
81
82 } // Unnamed namespace
83
84 Dali::Toolkit::ConfirmationPopup ConfirmationPopup::New()
85 {
86   // Create the implementation, temporarily owned on stack.
87   IntrusivePtr< ConfirmationPopup > internalConfirmationPopup = new ConfirmationPopup();
88
89   // Pass ownership to CustomActor
90   Dali::Toolkit::ConfirmationPopup confirmationPopup( *internalConfirmationPopup );
91
92   // Second-phase initialisation of the implementation.
93   // This can only be done after the CustomActor connection has been made...
94   internalConfirmationPopup->Initialize();
95
96   return confirmationPopup;
97 }
98
99 ConfirmationPopup::ConfirmationPopup()
100 : Toolkit::Internal::Popup()
101 {
102   mControlSignals.reserve( MAXIMUM_NUMBER_OF_CONTROLS );
103   mControlSignalNames[ Toolkit::ConfirmationPopup::CONTROL_OK ] = DEFAULT_CONNECT_SIGNAL_NAME;
104   mControlSignalNames[ Toolkit::ConfirmationPopup::CONTROL_CANCEL ] = DEFAULT_CONNECT_SIGNAL_NAME;
105   DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
106     return std::unique_ptr< Dali::Accessibility::Accessible >(
107         new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::DIALOG, true ) );
108   } );
109 }
110
111 ConfirmationPopup::~ConfirmationPopup()
112 {
113   for( SignalContainerType::iterator i = mControlSignals.begin(); i != mControlSignals.end(); ++i )
114   {
115     delete ( i->second );
116   }
117   mControlSignals.clear();
118 }
119
120 void ConfirmationPopup::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
121 {
122   Toolkit::ConfirmationPopup popup = Toolkit::ConfirmationPopup::DownCast( Dali::BaseHandle( object ) );
123
124   if ( popup )
125   {
126     ConfirmationPopup& popupImpl( GetDerivedImplementation( popup ) );
127
128     switch ( propertyIndex )
129     {
130       case Toolkit::ConfirmationPopup::Property::CONNECT_SIGNAL_OK_SELECTED:
131       {
132         popupImpl.SetControlSignalName( Toolkit::ConfirmationPopup::CONTROL_OK, value.Get< std::string >() );
133         break;
134       }
135       case Toolkit::ConfirmationPopup::Property::CONNECT_SIGNAL_CANCEL_SELECTED:
136       {
137         popupImpl.SetControlSignalName( Toolkit::ConfirmationPopup::CONTROL_CANCEL, value.Get< std::string >() );
138         break;
139       }
140     }
141   }
142 }
143
144 Property::Value ConfirmationPopup::GetProperty( BaseObject* object, Property::Index propertyIndex )
145 {
146   Property::Value value;
147
148   Toolkit::ConfirmationPopup popup = Toolkit::ConfirmationPopup::DownCast( Dali::BaseHandle( object ) );
149
150   if ( popup )
151   {
152     ConfirmationPopup& popupImpl( GetDerivedImplementation( popup ) );
153
154     switch ( propertyIndex )
155     {
156       case Toolkit::ConfirmationPopup::Property::CONNECT_SIGNAL_OK_SELECTED:
157       {
158         value = popupImpl.GetControlSignalName( Toolkit::ConfirmationPopup::CONTROL_OK );
159         break;
160       }
161       case Toolkit::ConfirmationPopup::Property::CONNECT_SIGNAL_CANCEL_SELECTED:
162       {
163         value = popupImpl.GetControlSignalName( Toolkit::ConfirmationPopup::CONTROL_CANCEL );
164         break;
165       }
166     }
167   }
168
169   return value;
170 }
171
172 void ConfirmationPopup::SetControlSignalName( const unsigned int controlNumber, const std::string& signalName )
173 {
174   if( controlNumber < ControlDetailsCount )
175   {
176     mControlSignalNames[ controlNumber ] = signalName;
177   }
178 }
179
180 std::string ConfirmationPopup::GetControlSignalName( unsigned int controlNumber ) const
181 {
182   if( controlNumber < ControlDetailsCount )
183   {
184     return mControlSignalNames[ controlNumber ];
185   }
186
187   return "";
188 }
189
190 bool ConfirmationPopup::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
191 {
192   Dali::BaseHandle handle( object );
193   Toolkit::ConfirmationPopup popup = Toolkit::ConfirmationPopup::DownCast( handle );
194
195   // Look up the requested signal, attempting to create it dynamically if it doesn't exist.
196   SignalDelegate* signalDelegate = Dali::Toolkit::GetDerivedImplementation( popup ).GetControlSignal( signalName );
197   if( signalDelegate )
198   {
199     // The signal delegate was created successfully, attempt to connect it to a callback if specified.
200     // If none is specified, the creation is still successful as the signal delegate can connect at a later time.
201     if( functor )
202     {
203       signalDelegate->Connect( tracker, functor );
204     }
205     return true;
206   }
207
208   // The signal could not be created.
209   return false;
210 }
211
212 SignalDelegate* ConfirmationPopup::GetControlSignal( const std::string& signalName )
213 {
214   // Check if the specified signal name already exists.
215   SignalContainerType::iterator end = mControlSignals.end();
216   for( SignalContainerType::iterator iter = mControlSignals.begin(); iter != end; ++iter )
217   {
218     // Find the first non-connected signal by matching signal name.
219     if( ( signalName == iter->first ) && ( !iter->second->IsConnected() ) )
220     {
221       // The requested signal (delegate) already exists, just return it.
222       return iter->second;
223     }
224   }
225
226   // The signal doesn't exist, or it does but it's already connected to something else.
227   // To make a new connection to an existing signal, we need a new delegate,
228   // as delegates house a signal connection functor each.
229   // Check the signal name is valid and if so create the signal dynamically.
230   for( unsigned int i = 0; i < ControlDetailsCount; ++i )
231   {
232     if( 0 == strcmp( signalName.c_str(), ControlDetails[ i ].signalName ) )
233     {
234       // The signal name is valid, check the respective actor to connect to exists.
235       Actor connectActor = Self().FindChildByName( ControlDetails[ i ].controlName );
236       if( connectActor )
237       {
238         // The actor exists, set up a signal delegate that will allow the application developer
239         // to connect the actor signal directly to their callback.
240         // Note: We don't use the GetControlSignalName() here for speedup, as we know the array bound is capped.
241         SignalDelegate* signalDelegate = new SignalDelegate( connectActor, mControlSignalNames[ i ] );
242
243         // Store the delegate with the signal name so we know what signals have been dynamically created so far.
244         mControlSignals.push_back( std::make_pair( signalName, signalDelegate ) );
245
246         // Return the delegate to allow connection to the newly created signal.
247         return signalDelegate;
248       }
249
250       // Signal name valid but could not connect to the control,
251       return NULL;
252     }
253   }
254
255   // Signal name was not found (invalid).
256   return NULL;
257 }
258
259
260 } // namespace Internal
261
262 } // namespace Toolkit
263
264 } // namespace Dali