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