2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "confirmation-popup-impl.h"
22 #include <dali/public-api/object/type-registry.h>
23 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
42 * This struct is used to define all details required about a dynamically created signal.
44 struct ControlDetailType
46 const char* signalName;
47 const char* controlName;
48 const char* connectSignalPropertyName;
51 /* A table of all control details. These details are kept in one place for maintainability.
52 * Name of the signal | Name of the control | Name of the property which lets the
53 * the app-developer | which will provide | app developer choose which signal
54 * can connect to. | the signal. | within the control to connect to. */
55 const ControlDetailType ControlDetails[] = {
56 { "controlSignalOk", "controlOk", "connectSignalOkSelected" },
57 { "controlSignalCancel", "controlCancel", "connectSignalCancelSelected" },
59 const unsigned int ControlDetailsCount = sizeof( ControlDetails ) / sizeof( ControlDetails[0] );
61 // To give sensible default behaviour to save the connect signal properties being set.
62 const char* const DEFAULT_CONNECT_SIGNAL_NAME = "clicked";
66 return Toolkit::ConfirmationPopup::New();
69 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ConfirmationPopup, Toolkit::Popup, Create )
71 DALI_PROPERTY_REGISTRATION( Toolkit, ConfirmationPopup, ControlDetails[0].connectSignalPropertyName, STRING, CONNECT_SIGNAL_OK_SELECTED )
72 DALI_PROPERTY_REGISTRATION( Toolkit, ConfirmationPopup, ControlDetails[1].connectSignalPropertyName, STRING, CONNECT_SIGNAL_CANCEL_SELECTED )
74 // Note: We do not use the macros for signal registration as we do not want to redefine the signal name strings.
75 // We have predefined them for optimal signal name to control name lookup.
76 SignalConnectorType signalConnector1( typeRegistration, ControlDetails[0].signalName, &Toolkit::Internal::ConfirmationPopup::DoConnectSignal );
77 SignalConnectorType signalConnector2( typeRegistration, ControlDetails[1].signalName, &Toolkit::Internal::ConfirmationPopup::DoConnectSignal );
79 DALI_TYPE_REGISTRATION_END()
81 } // Unnamed namespace
83 Dali::Toolkit::ConfirmationPopup ConfirmationPopup::New()
85 // Create the implementation, temporarily owned on stack.
86 IntrusivePtr< ConfirmationPopup > internalConfirmationPopup = new ConfirmationPopup();
88 // Pass ownership to CustomActor
89 Dali::Toolkit::ConfirmationPopup confirmationPopup( *internalConfirmationPopup );
91 // Second-phase initialisation of the implementation.
92 // This can only be done after the CustomActor connection has been made...
93 internalConfirmationPopup->Initialize();
95 return confirmationPopup;
98 ConfirmationPopup::ConfirmationPopup()
99 : Toolkit::Internal::Popup()
101 mControlSignals.reserve( MAXIMUM_NUMBER_OF_CONTROLS );
102 mControlSignalNames[ Toolkit::ConfirmationPopup::CONTROL_OK ] = DEFAULT_CONNECT_SIGNAL_NAME;
103 mControlSignalNames[ Toolkit::ConfirmationPopup::CONTROL_CANCEL ] = DEFAULT_CONNECT_SIGNAL_NAME;
104 DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
105 return std::unique_ptr< Dali::Accessibility::Accessible >(
106 new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::DIALOG, true ) );
110 ConfirmationPopup::~ConfirmationPopup()
112 for( SignalContainerType::iterator i = mControlSignals.begin(); i != mControlSignals.end(); ++i )
114 delete ( i->second );
116 mControlSignals.clear();
119 void ConfirmationPopup::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
121 Toolkit::ConfirmationPopup popup = Toolkit::ConfirmationPopup::DownCast( Dali::BaseHandle( object ) );
125 ConfirmationPopup& popupImpl( GetDerivedImplementation( popup ) );
127 switch ( propertyIndex )
129 case Toolkit::ConfirmationPopup::Property::CONNECT_SIGNAL_OK_SELECTED:
131 popupImpl.SetControlSignalName( Toolkit::ConfirmationPopup::CONTROL_OK, value.Get< std::string >() );
134 case Toolkit::ConfirmationPopup::Property::CONNECT_SIGNAL_CANCEL_SELECTED:
136 popupImpl.SetControlSignalName( Toolkit::ConfirmationPopup::CONTROL_CANCEL, value.Get< std::string >() );
143 Property::Value ConfirmationPopup::GetProperty( BaseObject* object, Property::Index propertyIndex )
145 Property::Value value;
147 Toolkit::ConfirmationPopup popup = Toolkit::ConfirmationPopup::DownCast( Dali::BaseHandle( object ) );
151 ConfirmationPopup& popupImpl( GetDerivedImplementation( popup ) );
153 switch ( propertyIndex )
155 case Toolkit::ConfirmationPopup::Property::CONNECT_SIGNAL_OK_SELECTED:
157 value = popupImpl.GetControlSignalName( Toolkit::ConfirmationPopup::CONTROL_OK );
160 case Toolkit::ConfirmationPopup::Property::CONNECT_SIGNAL_CANCEL_SELECTED:
162 value = popupImpl.GetControlSignalName( Toolkit::ConfirmationPopup::CONTROL_CANCEL );
171 void ConfirmationPopup::SetControlSignalName( const unsigned int controlNumber, const std::string& signalName )
173 if( controlNumber < ControlDetailsCount )
175 mControlSignalNames[ controlNumber ] = signalName;
179 std::string ConfirmationPopup::GetControlSignalName( unsigned int controlNumber ) const
181 if( controlNumber < ControlDetailsCount )
183 return mControlSignalNames[ controlNumber ];
189 bool ConfirmationPopup::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
191 Dali::BaseHandle handle( object );
192 Toolkit::ConfirmationPopup popup = Toolkit::ConfirmationPopup::DownCast( handle );
194 // Look up the requested signal, attempting to create it dynamically if it doesn't exist.
195 SignalDelegate* signalDelegate = Dali::Toolkit::GetDerivedImplementation( popup ).GetControlSignal( signalName );
198 // The signal delegate was created successfully, attempt to connect it to a callback if specified.
199 // If none is specified, the creation is still successful as the signal delegate can connect at a later time.
202 signalDelegate->Connect( tracker, functor );
207 // The signal could not be created.
211 SignalDelegate* ConfirmationPopup::GetControlSignal( const std::string& signalName )
213 // Check if the specified signal name already exists.
214 SignalContainerType::iterator end = mControlSignals.end();
215 for( SignalContainerType::iterator iter = mControlSignals.begin(); iter != end; ++iter )
217 // Find the first non-connected signal by matching signal name.
218 if( ( signalName == iter->first ) && ( !iter->second->IsConnected() ) )
220 // The requested signal (delegate) already exists, just return it.
225 // The signal doesn't exist, or it does but it's already connected to something else.
226 // To make a new connection to an existing signal, we need a new delegate,
227 // as delegates house a signal connection functor each.
228 // Check the signal name is valid and if so create the signal dynamically.
229 for( unsigned int i = 0; i < ControlDetailsCount; ++i )
231 if( 0 == strcmp( signalName.c_str(), ControlDetails[ i ].signalName ) )
233 // The signal name is valid, check the respective actor to connect to exists.
234 Actor connectActor = Self().FindChildByName( ControlDetails[ i ].controlName );
237 // The actor exists, set up a signal delegate that will allow the application developer
238 // to connect the actor signal directly to their callback.
239 // Note: We don't use the GetControlSignalName() here for speedup, as we know the array bound is capped.
240 SignalDelegate* signalDelegate = new SignalDelegate( connectActor, mControlSignalNames[ i ] );
242 // Store the delegate with the signal name so we know what signals have been dynamically created so far.
243 mControlSignals.push_back( std::make_pair( signalName, signalDelegate ) );
245 // Return the delegate to allow connection to the newly created signal.
246 return signalDelegate;
249 // Signal name valid but could not connect to the control,
254 // Signal name was not found (invalid).
259 } // namespace Internal
261 } // namespace Toolkit