int UtcDaliSignalConnectN01(void)
{
- // difficult to perform a negative test on Connect as no checks are performed
- // when creating a callback for a null function ( during Connect).
- // so we test an assert on Emit
TestApplication application; // Create core for debug logging
TestSignals::VoidRetNoParamSignal signal;
- signal.Connect(NULL);
- try
- {
- signal.Emit();
- }
- catch(Dali::DaliException& e)
- {
- // Tests that a negative test of an assertion succeeds
- DALI_TEST_PRINT_ASSERT(e);
- tet_result(TET_PASS);
- }
+ signal.Connect(nullptr);
+ signal.Emit();
+
+ // No assert occurs any more - the callback is silently ignored.
+ // If we execute this code, then the test case didn't crash.
+ tet_result(TET_PASS);
+
END_TEST;
}
END_TEST;
}
+
+
+int UtcDaliTouchEventIntercept(void)
+{
+ TestApplication application;
+
+ Actor parent = Actor::New();
+ parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(parent);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false /* Do not consume */);
+ actor.TouchedSignal().Connect(&application, functor);
+
+
+ // Connect to parent's touched signal
+ SignalData parentData;
+ TouchEventFunctor parentFunctor(parentData, false /* Do not consume */);
+ parent.TouchedSignal().Connect(&application, parentFunctor);
+ // Connect to parent's intercept touched signal
+ SignalData interceptData;
+ TouchEventFunctor interceptFunctor(interceptData, true /* Do intercept */);
+ Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ // The actor touched signal is not called because the touch is intercepted in the parent.
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, interceptData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, interceptData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == interceptData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(parent == interceptData.touchedActor);
+ DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, parentData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == parentData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(parent == parentData.touchedActor);
+ data.Reset();
+ parentData.Reset();
+
+ END_TEST;
+}
+
END_TEST;
}
+int UtcDaliVectorEraseFreeFunction(void)
+{
+ tet_infoline("Testing Dali::Erase<Vector<int>>");
+
+ Vector<int> vector;
+
+ // erasing from empty vector
+ Dali::Erase(vector, 2);
+ DALI_TEST_EQUALS(ZERO, vector.Count(), TEST_LOCATION);
+ DALI_TEST_EQUALS(ZERO, vector.Capacity(), TEST_LOCATION);
+
+
+ vector.PushBack(1);
+ vector.PushBack(2);
+ vector.PushBack(3);
+ vector.PushBack(4);
+ vector.PushBack(5);
+ vector.PushBack(3);
+
+ // erase multiple value
+ Dali::Erase(vector, 3);
+ DALI_TEST_EQUALS(static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION);
+
+ DALI_TEST_EQUALS(vector[0], 1, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[1], 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[2], 4, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[3], 5, TEST_LOCATION);
+
+
+ // erase an element present at start
+ Dali::Erase(vector, 1);
+ DALI_TEST_EQUALS(static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[2], 5, TEST_LOCATION);
+
+ // erase an element present at end
+ Dali::Erase(vector, 5);
+ DALI_TEST_EQUALS(static_cast<Dali::VectorBase::SizeType>(2), vector.Count(), TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION);
+
+ // erase an element not present in the vector
+ Dali::Erase(vector, 42);
+ DALI_TEST_EQUALS(static_cast<Dali::VectorBase::SizeType>(2), vector.Count(), TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliVectorEraseIfFreeFunction(void)
+{
+ tet_infoline("Testing Dali::EraseIf<Vector<int>>");
+
+ Vector<int> vector;
+
+ // erasing from empty vector
+ Dali::EraseIf(vector, [](const auto & value) {return value == 2;});
+ DALI_TEST_EQUALS(ZERO, vector.Count(), TEST_LOCATION);
+ DALI_TEST_EQUALS(ZERO, vector.Capacity(), TEST_LOCATION);
+
+
+ vector.PushBack(1);
+ vector.PushBack(2);
+ vector.PushBack(3);
+ vector.PushBack(4);
+ vector.PushBack(5);
+ vector.PushBack(3);
+
+ // erase multiple value
+ Dali::EraseIf(vector, [](const auto & value) {return value == 3;});
+ DALI_TEST_EQUALS(static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION);
+
+ DALI_TEST_EQUALS(vector[0], 1, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[1], 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[2], 4, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[3], 5, TEST_LOCATION);
+
+
+ // erase an element present at start
+ Dali::EraseIf(vector, [](const auto & value) {return value == 1;});
+ DALI_TEST_EQUALS(static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[2], 5, TEST_LOCATION);
+
+ // erase an element present at end
+ Dali::EraseIf(vector, [](const auto & value) {return value == 5;});
+ DALI_TEST_EQUALS(static_cast<Dali::VectorBase::SizeType>(2), vector.Count(), TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION);
+
+ // erase an element not present in the vector
+ Dali::EraseIf(vector, [](const auto & value) {return value == 42;});
+ DALI_TEST_EQUALS(static_cast<Dali::VectorBase::SizeType>(2), vector.Count(), TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[0], 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(vector[1], 4, TEST_LOCATION);
+
+ END_TEST;
+}
+
/*
* this does not compile at the moment
* Vector< Actor > classvector; this does not compile yet either
return GetImplementation(actor).ChildOrderChangedSignal();
}
+Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor)
+{
+ return GetImplementation(actor).InterceptTouchedSignal();
+}
+
} // namespace DevelActor
} // namespace Dali
*/
DALI_CORE_API ChildOrderChangedSignalType& ChildOrderChangedSignal(Actor actor);
+/**
+ * @brief This signal is emitted when intercepting the actor's touch event.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void MyCallbackName( Actor actor );
+ * @endcode
+ * actor The actor to intercept
+ *
+ * @note TouchEvent callbacks are called from the last child in the order of the parent's actor.
+ * The InterceptTouchEvent callback is to intercept the touch event in the parent.
+ * So, if the parent interepts the touch event, the child cannot receive the touch event.
+ *
+ * @note example
+ * Actor parent = Actor::New();
+ * Actor child = Actor::New();
+ * parent.Add(child);
+ * child.TouchedSignal().Connect(&application, childFunctor);
+ * parent.TouchedSignal().Connect(&application, parentFunctor);
+ * The touch event callbacks are called in the order childFunctor -> parentFunctor.
+ *
+ * If you connect interceptTouchSignal to parentActor.
+ * Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor);
+ *
+ * When interceptFunctor returns false, the touch event callbacks are called in the same order childFunctor -> parentFunctor.
+ * If interceptFunctor returns true, it means that the TouchEvent was intercepted.
+ * So the child actor will not be able to receive touch events.
+ * Only the parentFunctor is called.
+ *
+ * @return The signal to connect to
+ * @pre The Actor has been initialized
+ */
+DALI_CORE_API Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor);
+
} // namespace DevelActor
} // namespace Dali
// node is being used in a separate thread; queue a message to set the value & base value
SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
+
+ RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
}
float Actor::GetCurrentOpacity() const
// node is being used in a separate thread; queue a message to set the value & base value
SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
+
+ RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
}
void Actor::SetColorRed( float red )
// node is being used in a separate thread; queue a message to set the value & base value
SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
+
+ RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
}
void Actor::SetColorGreen( float green )
// node is being used in a separate thread; queue a message to set the value & base value
SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
+
+ RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
}
void Actor::SetColorBlue( float blue )
// node is being used in a separate thread; queue a message to set the value & base value
SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
+
+ RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
}
const Vector4& Actor::GetCurrentColor() const
return mGestureData && mGestureData->IsGestureRequired( type );
}
+bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
+{
+ return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
+}
+
bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
{
return EmitConsumingSignal( *this, mTouchedSignal, touch );
mAnchorPoint( nullptr ),
mRelayoutData( nullptr ),
mGestureData( nullptr ),
+ mInterceptTouchedSignal(),
mTouchedSignal(),
mHoveredSignal(),
mWheelEventSignal(),
{
// node is being used in a separate thread; queue a message to set the value & base value
SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
+
+ RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
}
mVisible = visible;
return mKeyboardFocusable;
}
+
+ /**
+ * Query whether the application or derived actor type requires intercept touch events.
+ * @return True if intercept touch events are required.
+ */
+ bool GetInterceptTouchRequired() const
+ {
+ return !mInterceptTouchedSignal.Empty();
+ }
+
/**
* Query whether the application or derived actor type requires touch events.
* @return True if touch events are required.
// Signals
/**
+ * Used by the EventProcessor to emit intercept touch event signals.
+ * @param[in] touch The touch data.
+ * @return True if the event was intercepted.
+ */
+ bool EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch );
+
+ /**
* Used by the EventProcessor to emit touch event signals.
* @param[in] touch The touch data.
* @return True if the event was consumed.
void EmitChildRemovedSignal( Actor& child );
/**
+ * @copydoc DevelActor::InterceptTouchedSignal()
+ */
+ Dali::Actor::TouchEventSignalType& InterceptTouchedSignal()
+ {
+ return mInterceptTouchedSignal;
+ }
+
+ /**
* @copydoc Dali::Actor::TouchedSignal()
*/
Dali::Actor::TouchEventSignalType& TouchedSignal()
ActorGestureData* mGestureData; ///< Optional Gesture data. Only created when actor requires gestures
// Signals
+ Dali::Actor::TouchEventSignalType mInterceptTouchedSignal;
Dali::Actor::TouchEventSignalType mTouchedSignal;
Dali::Actor::HoverSignalType mHoveredSignal;
Dali::Actor::WheelEventSignalType mWheelEventSignal;
#endif // defined(DEBUG_ENABLED)
+Dali::Actor EmitInterceptTouchSignals( Dali::Actor actor, const Dali::TouchEvent& touchEvent )
+{
+ Dali::Actor interceptedActor;
+
+ if( actor )
+ {
+ Dali::Actor parent = actor.GetParent();
+ if( parent )
+ {
+ // Recursively deliver events to the actor and its parents for intercept touch event.
+ interceptedActor = EmitInterceptTouchSignals( parent, touchEvent );
+ }
+
+ if( !interceptedActor )
+ {
+ bool intercepted = false;
+ Actor& actorImpl( GetImplementation(actor) );
+ if( actorImpl.GetInterceptTouchRequired() )
+ {
+ intercepted = actorImpl.EmitInterceptTouchEventSignal( touchEvent );
+ if( intercepted )
+ {
+ interceptedActor = Dali::Actor( &actorImpl );
+ }
+ }
+ }
+ }
+
+ return interceptedActor;
+}
/**
* Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
Dali::Actor consumedActor;
if ( currentRenderTask )
{
- consumedActor = EmitTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+ // Emit the intercept touch signal
+ Dali::Actor interceptedActor = EmitInterceptTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+ if( interceptedActor )
+ {
+ consumedActor = EmitTouchSignals( interceptedActor, touchEventHandle );
+ }
+ else
+ {
+ consumedActor = EmitTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+ }
consumed = consumedActor ? true : false;
}
{
const RenderItem& item = renderList.GetItem( index );
+ // Discard renderers outside the root clipping rect
+ bool skip = true;
+ if( !rootClippingRect.IsEmpty() )
+ {
+ auto rect = item.CalculateViewportSpaceAABB( item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height );
+
+ if(rect.Intersect( rootClippingRect ))
+ {
+ skip = false;
+ }
+ }
+ else
+ {
+ skip = false;
+ }
+
DALI_PRINT_RENDER_ITEM( item );
// Set up clipping based on both the Renderer and Actor APIs.
// draw-mode state, such as Overlays.
// If the flags are set to "AUTO", the behavior then depends on the type of renderer. Overlay Renderers will always
// disable depth testing and writing. Color Renderers will enable them if the Layer does.
- if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
+ if (depthBufferAvailable == Integration::DepthBufferAvailable::TRUE)
{
- SetupDepthBuffer( item, context, autoDepthTestMode, firstDepthBufferUse );
+ SetupDepthBuffer(item, context, autoDepthTestMode, firstDepthBufferUse);
}
// Depending on whether the renderer has draw commands attached or not the rendering process will
// iteration must be done and the default behaviour of the renderer will be executed.
// The queues allow to iterate over the same renderer multiple times changing the state of the renderer.
// It is similar to the multi-pass rendering.
- auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX;
- for( auto queue = 0u; queue < MAX_QUEUE; ++queue )
+ if( !skip )
{
- // Render the item.
- item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix,
- viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue);
+ auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX;
+ for (auto queue = 0u; queue < MAX_QUEUE; ++queue)
+ {
+ // Render the item.
+ item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix,
+ viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue);
+ }
}
}
}
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
mDisconnectAction(disconnectAction),
mState(Stopped),
mProgressReachedSignalRequired( false ),
- mAutoReverseEnabled( false )
+ mAutoReverseEnabled( false ),
+ mIsActive{ false }
{
}
void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished )
{
+ mIsActive[bufferIndex] = false;
+
const Vector2 playRange( mPlayRange * mDurationSeconds );
float elapsedSecondsClamped = Clamp( mElapsedSeconds, playRange.x, playRange.y );
progress = Clamp((elapsedSecondsClamped - intervalDelay) / animatorDuration, 0.0f , 1.0f );
}
animator->Update(bufferIndex, progress, bake);
+
+ if (animatorDuration > 0.0f && (elapsedSecondsClamped - intervalDelay) <= animatorDuration)
+ {
+ mIsActive[bufferIndex] = true;
+ }
}
applied = true;
}
#define DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
/**
+ * Query whether the animation is currently active (i.e. at least one of the animators has been updated in either frame)
+ * @return True if the animation is currently active
+ */
+ bool IsActive() const
+ {
+ // As we have double buffering, if animator is updated in either frame, it needs to be rendered.
+ return mIsActive[0] || mIsActive[1];
+ }
+
+ /**
* @brief Sets the looping mode.
*
* Animation plays forwards and then restarts from the beginning or runs backwards again.
bool mProgressReachedSignalRequired; // Flag to indicate the progress marker was hit
bool mAutoReverseEnabled; // Flag to identify that the looping mode is auto reverse.
+ bool mIsActive[2]; // Flag to indicate whether the animation is active in the current frame (which is double buffered)
};
}; //namespace SceneGraph
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
}
-void TransformManager::Update()
+bool TransformManager::Update()
{
+ bool componentsChanged = false;
+
if( mReorder )
{
//If some transform component has change its parent or has been removed since last update
mBoundingSpheres[i] = mWorld[i].GetTranslation();
mBoundingSpheres[i].w = Length( centerToEdgeWorldSpace );
+ componentsChanged = componentsChanged || mComponentDirty[i];
mComponentDirty[i] = false;
}
+
+ return componentsChanged;
}
void TransformManager::SwapComponents( unsigned int i, unsigned int j )
case TRANSFORM_PROPERTY_POSITION:
{
TransformId index( mIds[id] );
- mComponentDirty[ index ] = true;
return mTxComponentAnimatable[ index ].mPosition;
}
case TRANSFORM_PROPERTY_SCALE:
{
TransformId index( mIds[id] );
- mComponentDirty[ index ] = true;
return mTxComponentAnimatable[ index ].mScale;
}
case TRANSFORM_PROPERTY_PARENT_ORIGIN:
{
TransformId index( mIds[id] );
- mComponentDirty[ index ] = true;
return mTxComponentStatic[ index ].mParentOrigin;
}
case TRANSFORM_PROPERTY_ANCHOR_POINT:
{
TransformId index( mIds[id] );
- mComponentDirty[ index ] = true;
return mTxComponentStatic[ index ].mAnchorPoint;
}
case TRANSFORM_PROPERTY_SIZE:
{
TransformId index( mIds[id] );
- mComponentDirty[ index ] = true;
return mSize[ index ];
}
default:
Quaternion& TransformManager::GetQuaternionPropertyValue( TransformId id )
{
TransformId index( mIds[id] );
- mComponentDirty[ index ] = true;
return mTxComponentAnimatable[ index ].mOrientation;
}
#define DALI_INTERNAL_TRANSFORM_MANAGER_H
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* Recomputes all world transform matrices
+ * @return true if any component has been changed in this frame, false otherwise
*/
- void Update();
+ bool Update();
/**
* Resets all the animatable properties to its base value
previousUpdateScene( false ),
renderTaskWaiting( false ),
renderersAdded( false ),
- surfaceRectChanged( false )
+ surfaceRectChanged( false ),
+ renderingRequired( false )
{
sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
bool surfaceRectChanged; ///< True if the default surface rect is changed
+ bool renderingRequired; ///< True if required to render the current frame
private:
return gestureUpdated;
}
-void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
+bool UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
{
+ bool animationActive = false;
+
auto&& iter = mImpl->animations.Begin();
bool animationLooped = false;
bool progressMarkerReached = false;
animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
+ animationActive = animationActive || animation->IsActive();
+
if ( progressMarkerReached )
{
mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
// The application should be notified by NotificationManager, in another thread
mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
}
+
+ return animationActive;
}
void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
//Apply constraints
ConstrainPropertyOwner( *renderer, bufferIndex );
- renderer->PrepareRender( bufferIndex );
+ mImpl->renderingRequired = renderer->PrepareRender( bufferIndex ) || mImpl->renderingRequired;
}
}
//Clear nodes/resources which were previously discarded
mImpl->discardQueue.Clear( bufferIndex );
+ bool isAnimationRunning = IsAnimationRunning();
+
//Process Touches & Gestures
const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
bool updateScene = // The scene-graph requires an update if..
(mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
- IsAnimationRunning() || // ..at least one animation is running OR
+ isAnimationRunning || // ..at least one animation is running OR
mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
mImpl->frameCallbackProcessor || // ..a frame callback processor is existed OR
gestureUpdated; // ..a gesture property was updated
bool keepRendererRendering = false;
+ mImpl->renderingRequired = false;
// Although the scene-graph may not require an update, we still need to synchronize double-buffered
// values if the scene was updated in the previous frame.
if( updateScene || mImpl->previousUpdateScene )
{
//Animate
- Animate( bufferIndex, elapsedSeconds );
+ bool animationActive = Animate( bufferIndex, elapsedSeconds );
//Constraint custom objects
ConstrainCustomObjects( bufferIndex );
UpdateRenderers( bufferIndex );
//Update the transformations of all the nodes
- mImpl->transformManager.Update();
+ if ( mImpl->transformManager.Update() )
+ {
+ mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM;
+ }
//Process Property Notifications
ProcessPropertyNotifications( bufferIndex );
}
}
-
std::size_t numberOfRenderInstructions = 0;
for ( auto&& scene : mImpl->scenes )
{
scene->scene->GetRenderInstructions().ResetAndReserve( bufferIndex,
static_cast<uint32_t>( scene->taskList->GetTasks().Count() ) );
- keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
- *scene->taskList,
- *scene->root,
- scene->sortedLayerList,
- scene->scene->GetRenderInstructions(),
- renderToFboEnabled,
- isRenderingToFbo );
+ // If there are animations running, only add render instruction if at least one animation is currently active (i.e. not delayed)
+ // or the nodes are dirty
+ if ( !isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags) )
+ {
+ keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
+ *scene->taskList,
+ *scene->root,
+ scene->sortedLayerList,
+ scene->scene->GetRenderInstructions(),
+ renderToFboEnabled,
+ isRenderingToFbo );
+
+ }
numberOfRenderInstructions += scene->scene->GetRenderInstructions().Count( bufferIndex );
}
mImpl->renderingBehavior = renderingBehavior;
}
+void UpdateManager::RequestRendering()
+{
+ mImpl->renderingRequired = true;
+}
+
void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
{
for ( auto&& scene : mImpl->scenes )
void SetRenderingBehavior( DevelStage::Rendering renderingBehavior );
/**
+ * Request to render the current frame
+ * @note This is a temporary workaround (to be removed in the future) to request the rendering of
+ * the current frame if the color or visibility of any actor is updated. It MUST NOT be used
+ * for any other purposes.
+ */
+ void RequestRendering();
+
+ /**
* Sets the depths of all layers.
* @param layers The layers in depth order.
* @param[in] rootLayer The root layer of the sorted layers.
* Perform animation updates
* @param[in] bufferIndex to use
* @param[in] elapsedSeconds time since last frame
+ * @return true if at least one animations is currently active or false otherwise
*/
- void Animate( BufferIndex bufferIndex, float elapsedSeconds );
+ bool Animate( BufferIndex bufferIndex, float elapsedSeconds );
/**
* Applies constraints to CustomObjects
new (slot) LocalType( &manager, &UpdateManager::SetRenderingBehavior, renderingBehavior );
}
+inline void RequestRenderingMessage( UpdateManager& manager )
+{
+ using LocalType = Message<UpdateManager>;
+
+ // Reserve some memory inside the message queue
+ uint32_t* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) LocalType( &manager, &UpdateManager::RequestRendering );
+}
+
/**
* Create a message for setting the depth of a layer
* @param[in] manager The update manager
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
-void Renderer::PrepareRender( BufferIndex updateBufferIndex )
+bool Renderer::PrepareRender( BufferIndex updateBufferIndex )
{
if( mRegenerateUniformMap == UNIFORM_MAP_READY )
{
mRegenerateUniformMap--;
}
+ bool rendererUpdated = mUniformMapChanged[updateBufferIndex] || mResendFlag;
+
if( mResendFlag != 0 )
{
if( mResendFlag & RESEND_GEOMETRY )
mResendFlag = 0;
}
+
+ return rendererUpdated;
}
void Renderer::SetTextures( TextureSet* textureSet )
#define DALI_INTERNAL_SCENE_GRAPH_RENDERER_H
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* Prepare the object for rendering.
* This is called by the UpdateManager when an object is due to be rendered in the current frame.
* @param[in] updateBufferIndex The current update buffer index.
+ * @return Whether this renderer has been updated in the current frame
*/
- void PrepareRender( BufferIndex updateBufferIndex );
+ bool PrepareRender( BufferIndex updateBufferIndex );
/**
* Retrieve the Render thread renderer
* D E F
*
* @endcode
- * @param[in] depth The depth in the hierarchy for the actor
*/
virtual void OnSceneConnection(int32_t depth) = 0;
*
* @SINCE_1_0.0
* @param[in] implementation The implementation for this custom actor
- * @return A handle to a newly allocated Dali resource
*/
CustomActor(CustomActorImpl& implementation);
* @brief Default constructor.
* Creates an alpha function object with the default built-in alpha function.
* @SINCE_1_0.0
- * @return The alpha function
*/
AlphaFunction();
* to the constructor.
* @SINCE_1_0.0
* @param[in] function One of the built-in alpha functions
- * @return The alpha function
*/
AlphaFunction(BuiltinFunction function);
* to the constructor.
* @SINCE_1_0.0
* @param[in] function A pointer to an alpha function
- * @return The alpha function
*/
AlphaFunction(AlphaFunctionPrototype function);
* @SINCE_1_0.0
* @param[in] controlPoint0 A Vector2 which will be used as the first control point of the curve
* @param[in] controlPoint1 A Vector2 which will be used as the second control point of the curve
- * @return The alpha function
* @note The x components of the control points will be clamped to the range [0,1] to prevent
* non monotonic curves.
*/
CallbackBase* Clone()
{
CallbackBase* callback = nullptr;
- if(mImpl && mImpl->mObjectPointer && mCopyConstructorDispatcher)
+ if(mImpl.mObjectPointer && mCopyConstructorDispatcher)
{
- callback = new Function(mCopyConstructorDispatcher(reinterpret_cast<UndefinedClass*>(mImpl->mObjectPointer)) /* Copy the object */,
+ callback = new Function(mCopyConstructorDispatcher(reinterpret_cast<UndefinedClass*>(mImpl.mObjectPointer)) /* Copy the object */,
mMemberFunction,
- mImpl->mMemberFunctionDispatcher,
- mImpl->mDestructorDispatcher,
+ mImpl.mMemberFunctionDispatcher,
+ mImpl.mDestructorDispatcher,
mCopyConstructorDispatcher);
}
else
};
/**
+ * @brief Erases all elements that compare equal to value from the vector.
+ *
+ * @SINCE_1_9.33
+ * @param[in] vector The vector
+ * @param[in] value The value to be removed.
+ */
+template <class T, class U>
+inline void Erase(Dali::Vector<T>& vector, const U& value)
+{
+ auto begin = vector.Begin();
+ auto end = vector.End();
+
+ vector.Erase(std::remove(begin, end, value), end);
+}
+
+/**
+ * @brief Erases all elements that satisfy the predicate from the vector.
+ *
+ * @SINCE_1_9.33
+ * @param[in] vector The vector
+ * @param[in] predicate The predicate
+ */
+template <class T, class Predicate>
+inline void EraseIf(Dali::Vector<T>& vector, Predicate predicate)
+{
+ auto begin = vector.Begin();
+ auto end = vector.End();
+
+ vector.Erase(std::remove_if(begin, end, predicate), end);
+}
+
+/**
* @}
*/
} // namespace Dali
{
const uint32_t CORE_MAJOR_VERSION = 1;
const uint32_t CORE_MINOR_VERSION = 9;
-const uint32_t CORE_MICRO_VERSION = 32;
+const uint32_t CORE_MICRO_VERSION = 34;
const char* const CORE_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
/**
* @brief PropertySetSignal function prototype for signal handler. Called when a property is set on this object.
*/
- using PropertySetSignalType = Signal<void(Handle& handle, Property::Index index, Property::Value value)>;
+ using PropertySetSignalType = Signal<void(Handle& handle, Property::Index index, const Property::Value& value)>;
public:
/**
// The signal is being destroyed. We have to inform any slots
// that are connected, that the signal is dead.
- const std::size_t count(mSignalConnections.Count());
+ const std::size_t count(mSignalConnections.size());
for(std::size_t i = 0; i < count; i++)
{
- SignalConnection* connection = mSignalConnections[i];
+ auto& connection = mSignalConnections[i];
// Note that values are set to NULL in DeleteConnection
if(connection)
{
- connection->Disconnect(this);
- delete connection;
+ connection.Disconnect(this);
}
}
-
- mSignalConnections.Clear();
-}
-
-bool BaseSignal::Empty() const
-{
- return (0 == GetConnectionCount());
-}
-
-std::size_t BaseSignal::GetConnectionCount() const
-{
- std::size_t count(0);
-
- const std::size_t size(mSignalConnections.Count());
- for(std::size_t i = 0; i < size; ++i)
- {
- // Note that values are set to NULL in DeleteConnection
- if(nullptr != mSignalConnections[i])
- {
- ++count;
- }
- }
-
- return count;
-}
-
-void BaseSignal::Emit()
-{
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that mSignalConnections.Count() count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.Count());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- CallbackBase::Execute(*callback);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
}
void BaseSignal::OnConnect(CallbackBase* callback)
if(INVALID_CALLBACK_INDEX == index)
{
// create a new signal connection object, to allow the signal to track the connection.
- SignalConnection* connection = new SignalConnection(callback);
+ //SignalConnection* connection = new SignalConnection(callback);
- mSignalConnections.PushBack(connection);
+ mSignalConnections.push_back(SignalConnection(callback));
}
else
{
if(INVALID_CALLBACK_INDEX == index)
{
// create a new signal connection object, to allow the signal to track the connection.
- SignalConnection* connection = new SignalConnection(tracker, callback);
+ //SignalConnection* connection = new SignalConnection(tracker, callback);
- mSignalConnections.PushBack(connection);
+ mSignalConnections.push_back({tracker, callback});
// Let the connection tracker know that a connection between a signal and a slot has been made.
tracker->SignalConnected(this, callback);
if(index > INVALID_CALLBACK_INDEX)
{
// temporary pointer to disconnected callback
- CallbackBase* disconnectedCallback = mSignalConnections[index]->GetCallback();
+ CallbackBase* disconnectedCallback = mSignalConnections[index].GetCallback();
// close the signal side connection first.
DeleteConnection(index);
// for SlotObserver::SlotDisconnected
void BaseSignal::SlotDisconnected(CallbackBase* callback)
{
- const std::size_t count(mSignalConnections.Count());
+ const std::size_t count(mSignalConnections.size());
for(std::size_t i = 0; i < count; ++i)
{
const CallbackBase* connectionCallback = GetCallback(i);
DALI_ABORT("Callback lost in SlotDisconnected()");
}
-CallbackBase* BaseSignal::GetCallback(std::size_t connectionIndex) const
-{
- DALI_ASSERT_ALWAYS(connectionIndex < mSignalConnections.Count() && "GetCallback called with invalid index");
-
- CallbackBase* callback(nullptr);
-
- SignalConnection* connection(mSignalConnections[connectionIndex]);
- // Note that values are set to NULL in DeleteConnection
- if(connection)
- {
- callback = connection->GetCallback();
- }
-
- return callback;
-}
-
-int32_t BaseSignal::FindCallback(CallbackBase* callback)
+int32_t BaseSignal::FindCallback(CallbackBase* callback) const noexcept
{
int32_t index(INVALID_CALLBACK_INDEX);
// A signal can have multiple slots connected to it.
// We need to search for the slot which has the same call back function (if it's static)
// Or the same object / member function (for non-static)
- const std::size_t count = mSignalConnections.Count();
- for(std::size_t i = 0; i < count; ++i)
+ for(auto i = 0u; i < mSignalConnections.size(); ++i)
{
const CallbackBase* connectionCallback = GetCallback(i);
void BaseSignal::DeleteConnection(std::size_t connectionIndex)
{
- DALI_ASSERT_ALWAYS(connectionIndex < mSignalConnections.Count() && "DeleteConnection called with invalid index");
-
- // delete the object
- SignalConnection* connection(mSignalConnections[connectionIndex]);
- delete connection;
if(mEmittingFlag)
{
- // IMPORTANT - do not remove from items from mSignalConnections, set to NULL instead.
+ // IMPORTANT - do not remove from items from mSignalConnections, reset instead.
// Signal Emit() methods require that connection count is not reduced while iterating
// i.e. DeleteConnection can be called from within callbacks, while iterating through mSignalConnections.
- mSignalConnections[connectionIndex] = nullptr;
+ mSignalConnections[connectionIndex] = {nullptr};
+ ++mNullConnections;
}
else
{
// If application connects and disconnects without the signal never emitting,
// the mSignalConnections vector keeps growing and growing as CleanupConnections() is done from Emit.
- mSignalConnections.Erase(mSignalConnections.Begin() + connectionIndex);
+ mSignalConnections.erase(mSignalConnections.begin() + connectionIndex);
}
}
void BaseSignal::CleanupConnections()
{
- const std::size_t total = mSignalConnections.Count();
- // only do something if there are items
- if(total > 0)
+ if(!mSignalConnections.empty())
{
- std::size_t index = 0;
- // process the whole vector
- for(std::size_t i = 0; i < total; ++i)
- {
- if(mSignalConnections[index] == nullptr)
- {
- // items will be moved so don't increase index (erase will decrease the count of vector)
- mSignalConnections.Erase(mSignalConnections.Begin() + index);
- }
- else
- {
- // increase to next element
- ++index;
- }
- }
+ //Remove Signals that are already markeed nullptr.
+ mSignalConnections.erase(std::remove_if(mSignalConnections.begin(),
+ mSignalConnections.end(),
+ [](auto& elm) { return (elm) ? false : true; }),
+ mSignalConnections.end());
}
+ mNullConnections = 0;
}
// BaseSignal::EmitGuard
*
*/
+// EXTERNAL INCLUDES
+#include <vector>
+
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/common/dali-vector.h>
* @SINCE_1_0.0
* @return True if there are any slots connected to the signal.
*/
- bool Empty() const;
+ bool Empty() const
+ {
+ return (0 == GetConnectionCount());
+ }
/**
* @brief Queries the number of slots.
* @SINCE_1_0.0
* @return The number of slots connected to this signal
*/
- std::size_t GetConnectionCount() const;
+ std::size_t GetConnectionCount() const
+ {
+ return mSignalConnections.size() - mNullConnections;
+ }
// Templated Emit functions for the Signal implementations
};
/**
- * @brief Emits a signal with no parameters.
- *
- * @SINCE_1_0.0
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- void Emit();
-
- /**
- * @brief Emits a signal with no parameters.
+ * @brief Emits a signal with parameter pack.
*
- * @SINCE_1_0.0
+ * @SINCE_1_9.33
+ * @param[in] args The parameter pack
* @return The value returned by the last callback
* @pre Cannot be called from inside the same Signal's Emit methods.
*/
- template<typename Ret>
- Ret EmitReturn()
+ template<typename Ret, typename... Args>
+ Ret EmitReturn(Args... args)
{
Ret returnVal = Ret();
// If more connections are added by callbacks, these are ignore until the next Emit()
// Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.Count());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- returnVal = CallbackBase::ExecuteReturn<Ret>(*callback);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
-
- return returnVal;
- }
-
- /**
- * @brief Emits a signal with 1 parameter.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Arg0>
- void Emit(Arg0 arg0)
- {
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.Count());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- CallbackBase::Execute<Arg0>(*callback, arg0);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
- }
-
- /**
- * @brief Emits a signal with 1 parameter.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @return The value returned by the last callback
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Ret, typename Arg0>
- Ret EmitReturn(Arg0 arg0)
- {
- Ret returnVal = Ret();
-
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return returnVal;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.Count());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- returnVal = CallbackBase::ExecuteReturn<Ret, Arg0>(*callback, arg0);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
-
- return returnVal;
- }
-
- /**
- * @brief Emits a signal with 2 parameters.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @param[in] arg1 The second parameter
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Arg0, typename Arg1>
- void Emit(Arg0 arg0, Arg1 arg1)
- {
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.Count());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- CallbackBase::Execute<Arg0, Arg1>(*callback, arg0, arg1);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
- }
-
- /**
- * @brief Emits a signal with 2 parameters.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @param[in] arg1 The second parameter
- * @return The value returned by the last callback
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Ret, typename Arg0, typename Arg1>
- Ret EmitReturn(Arg0 arg0, Arg1 arg1)
- {
- Ret returnVal = Ret();
-
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return returnVal;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.Count());
+ const std::size_t initialCount(mSignalConnections.size());
for(std::size_t i = 0; i < initialCount; ++i)
{
// This is preferable to reducing the connection count while iterating
if(callback)
{
- returnVal = CallbackBase::ExecuteReturn<Ret, Arg0, Arg1>(*callback, arg0, arg1);
+ returnVal = CallbackBase::ExecuteReturn<Ret, Args...>(*callback, args...);
}
}
}
/**
- * @brief Emits a signal with 3 parameters.
+ * @brief Emits a signal with parameter pack.
*
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @param[in] arg1 The second parameter
- * @param[in] arg2 The third parameter
+ * @SINCE_1_9.33
+ * @param[in] args The parameter pack
* @pre Cannot be called from inside the same Signal's Emit methods.
*/
- template<typename Arg0, typename Arg1, typename Arg2>
- void Emit(Arg0 arg0, Arg1 arg1, Arg2 arg2)
+ template<typename... Args>
+ void Emit(Args... args)
{
// Guards against nested Emit() calls
EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
// If more connections are added by callbacks, these are ignore until the next Emit()
// Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.Count());
-
- for(std::size_t i = 0; i < initialCount; ++i)
- {
- CallbackBase* callback(GetCallback(i));
-
- // Note that connections will be set to NULL when disconnected
- // This is preferable to reducing the connection count while iterating
- if(callback)
- {
- CallbackBase::Execute<Arg0, Arg1, Arg2>(*callback, arg0, arg1, arg2);
- }
- }
-
- // Cleanup NULL values from Connection container
- CleanupConnections();
- }
-
- /**
- * @brief Emits a signal with 3 parameters.
- *
- * @SINCE_1_0.0
- * @param[in] arg0 The first parameter
- * @param[in] arg1 The second parameter
- * @param[in] arg2 The third parameter
- * @return The value returned by the last callback
- * @pre Cannot be called from inside the same Signal's Emit methods.
- */
- template<typename Ret, typename Arg0, typename Arg1, typename Arg2>
- Ret EmitReturn(Arg0 arg0, Arg1 arg1, Arg2 arg2)
- {
- Ret returnVal = Ret();
-
- // Guards against nested Emit() calls
- EmitGuard guard(mEmittingFlag); // Guards against nested Emit() calls
- if(guard.ErrorOccurred())
- {
- return returnVal;
- }
-
- // If more connections are added by callbacks, these are ignore until the next Emit()
- // Note that count cannot be reduced while iterating
- const std::size_t initialCount(mSignalConnections.Count());
+ const std::size_t initialCount(mSignalConnections.size());
for(std::size_t i = 0; i < initialCount; ++i)
{
// This is preferable to reducing the connection count while iterating
if(callback)
{
- returnVal = CallbackBase::ExecuteReturn<Ret, Arg0, Arg1, Arg2>(*callback, arg0, arg1, arg2);
+ CallbackBase::Execute<Args...>(*callback, args...);
}
}
// Cleanup NULL values from Connection container
CleanupConnections();
-
- return returnVal;
}
// Connect / Disconnect function for use by Signal implementations
* @param[in] connectionIndex The index of the callback
* @return The callback, or NULL if the connection has been deleted
*/
- CallbackBase* GetCallback(std::size_t connectionIndex) const;
+ CallbackBase* GetCallback(std::size_t connectionIndex) const noexcept
+ {
+ return mSignalConnections[connectionIndex].GetCallback();
+ }
/**
* @brief Helper to find whether a callback is connected.
* @param[in] callback The call back object
* @return A valid index if the callback is connected
*/
- int32_t FindCallback(CallbackBase* callback);
+ int32_t FindCallback(CallbackBase* callback) const noexcept;
/**
* @brief Deletes a connection object from the list of connections.
BaseSignal& operator=(BaseSignal&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25
private:
- Dali::Vector<SignalConnection*> mSignalConnections; ///< Array of connections
-
- bool mEmittingFlag; ///< Used to guard against nested Emit() calls
+ std::vector<SignalConnection> mSignalConnections; ///< Array of connections
+ uint32_t mNullConnections{0}; ///< Empty Connections in the array.
+ bool mEmittingFlag{false}; ///< Used to guard against nested Emit() calls
};
/**
// CallbackBase
CallbackBase::CallbackBase()
-: mImpl(nullptr),
- mFunction(nullptr)
+: mFunction(nullptr)
{
}
}
CallbackBase::CallbackBase(Function function)
-: mImpl(nullptr),
- mFunction(function)
+: mFunction(function)
{
}
CallbackBase::CallbackBase(void* object, MemberFunction function, Dispatcher dispatcher)
: mMemberFunction(function)
{
- mImpl = new CallbackBase::Impl;
- if(mImpl)
- {
- mImpl->mObjectPointer = object;
- mImpl->mMemberFunctionDispatcher = dispatcher;
- mImpl->mDestructorDispatcher = nullptr; // object is not owned
- }
+ mImpl.mObjectPointer = object;
+ mImpl.mMemberFunctionDispatcher = dispatcher;
+ mImpl.mDestructorDispatcher = nullptr; // object is not owned
}
CallbackBase::CallbackBase(void* object, MemberFunction function, Dispatcher dispatcher, Destructor destructor)
: mMemberFunction(function)
{
- mImpl = new CallbackBase::Impl;
- if(mImpl)
- {
- mImpl->mObjectPointer = object;
- mImpl->mMemberFunctionDispatcher = dispatcher;
- mImpl->mDestructorDispatcher = destructor; // object is owned
- }
+ mImpl.mObjectPointer = object;
+ mImpl.mMemberFunctionDispatcher = dispatcher;
+ mImpl.mDestructorDispatcher = destructor; // object is owned
}
void CallbackBase::Reset()
{
- if(mImpl)
+ // if destructor function is set it means we own this object
+ if(mImpl.mObjectPointer &&
+ mImpl.mDestructorDispatcher)
{
- // if destructor function is set it means we own this object
- if(mImpl->mObjectPointer &&
- mImpl->mDestructorDispatcher)
- {
- // call the destructor dispatcher
- (*mImpl->mDestructorDispatcher)(mImpl->mObjectPointer);
- }
-
- delete mImpl;
- mImpl = nullptr;
+ // call the destructor dispatcher
+ (*mImpl.mDestructorDispatcher)(mImpl.mObjectPointer);
}
- mFunction = nullptr;
-}
-
-// CallbackBase::Impl
-
-CallbackBase::Impl::Impl()
-: mObjectPointer(nullptr),
- mMemberFunctionDispatcher(nullptr),
- mDestructorDispatcher(nullptr)
-{
-}
-
-// Non-member equality operator
+ mImpl = {};
-bool operator==(const CallbackBase& lhs, const CallbackBase& rhs)
-{
- if(lhs.mImpl)
- {
- // check it's the same member function / object
- return (lhs.mFunction == rhs.mFunction) && (lhs.mImpl->mObjectPointer == rhs.mImpl->mObjectPointer);
- }
- else
- {
- // check if it the same C function or a static member function
- return (lhs.mFunction == rhs.mFunction);
- }
+ mFunction = nullptr;
}
} // namespace Dali
/**
* @brief Function to call the function or member function dispatcher.
*
- * @SINCE_1_0.0
- * @param[in] callback The callback to call
- */
- static void Execute(CallbackBase& callback)
- {
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code so the library containing
- // the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl && callback.mImpl->mObjectPointer)
- {
- Dispatcher dispatcher = callback.mImpl->mMemberFunctionDispatcher;
- (*dispatcher)(callback);
- }
- // its also possible to have a member function pointer to a CallbackProvider
- // that has been deleted, so check if we have impl still
- else if(!callback.mImpl && callback.mFunction)
- {
- (*(callback.mFunction))();
- }
- else
- {
- DALI_ASSERT_ALWAYS(0 && "no function to execute");
- }
- }
-
- /**
- * @brief Function to call the function or member function dispatcher.
- *
- * @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @return The value from the function
- */
- template<typename R>
- static R ExecuteReturn(CallbackBase& callback)
- {
- R returnVal = R();
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code so the library containing
- // the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl && callback.mImpl->mObjectPointer)
- {
- using Dispatcher = R (*)(CallbackBase&);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl->mMemberFunctionDispatcher);
- returnVal = (*dispatcher)(callback);
- }
- else if(!callback.mImpl && callback.mFunction)
- {
- using Function1 = R (*)();
- returnVal = (*(reinterpret_cast<Function1>(callback.mFunction)))();
- }
-
- return returnVal;
- }
-
- /**
- * @brief Function to call the function or member function dispatcher.
- *
- * This function template gets instantiated at the call site.
- * @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- */
- template<typename P1>
- static void Execute(CallbackBase& callback, P1 param1)
- {
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code (where the callback was created)
- // so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl && callback.mImpl->mObjectPointer)
- {
- using Dispatcher = void (*)(CallbackBase&, P1);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl->mMemberFunctionDispatcher);
- (*dispatcher)(callback, param1);
- }
- else if(!callback.mImpl && callback.mFunction)
- {
- // convert function type
- using Function1 = void (*)(P1);
- (*(reinterpret_cast<Function1>(callback.mFunction)))(param1);
- }
- }
-
- /**
- * @brief Function to call the function or member function dispatcher.
- *
* This function template gets instantiated at the call site.
- * @SINCE_1_0.0
+ * @SINCE_1_9.33
* @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
+ * @param[in] args parameter pack to pass into the function
* @return The value from the function
*/
- template<typename R, typename P1>
- static R ExecuteReturn(CallbackBase& callback, P1 param1)
+ template<typename R, typename... Args>
+ static R ExecuteReturn(CallbackBase& callback, Args... args)
{
R returnVal = R();
// if we point to a function, we can call it directly
// otherwise call the dispatcher function that knows the real type of the object
// Note that this template dispatcher lives in client code (where the callback was created)
// so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl && callback.mImpl->mObjectPointer)
+ if(callback.mImpl.mObjectPointer)
{
- using Dispatcher = R (*)(CallbackBase&, P1);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl->mMemberFunctionDispatcher);
- returnVal = (*dispatcher)(callback, param1);
+ using Dispatcher = R (*)(CallbackBase&, Args...);
+ Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
+ returnVal = (*dispatcher)(callback, args...);
}
- else if(!callback.mImpl && callback.mFunction)
+ else if(callback.mFunction)
{
// convert function type
- using Function1 = R (*)(P1);
- returnVal = (*(reinterpret_cast<Function1>(callback.mFunction)))(param1);
+ using Function = R (*)(Args...);
+ returnVal = (*(reinterpret_cast<Function>(callback.mFunction)))(args...);
}
return returnVal;
* @brief Function to call the function or member function dispatcher.
*
* This function template gets instantiated at the call site.
- * @SINCE_1_0.0
+ * @SINCE_1_9.33
* @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- * @param[in] param2 The second parameter to pass into the function
+ * @param[in] args parameter pack to pass into the function
*/
- template<typename P1, typename P2>
- static void Execute(CallbackBase& callback, P1 param1, P2 param2)
+ template<typename... Args>
+ static void Execute(CallbackBase& callback, Args... args)
{
// if we point to a function, we can call it directly
// otherwise call the dispatcher function that knows the real type of the object
// Note that this template dispatcher lives in client code (where the callback was created)
// so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl && callback.mImpl->mObjectPointer)
+ if(callback.mImpl.mObjectPointer)
{
- using Dispatcher = void (*)(CallbackBase&, P1, P2);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl->mMemberFunctionDispatcher);
- (*dispatcher)(callback, param1, param2);
+ using Dispatcher = void (*)(CallbackBase&, Args...);
+ Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl.mMemberFunctionDispatcher);
+ (*dispatcher)(callback, args...);
}
- else if(!callback.mImpl && callback.mFunction)
+ else if(callback.mFunction)
{
// convert function type
- using Function2 = void (*)(P1, P2);
- (*(reinterpret_cast<Function2>(callback.mFunction)))(param1, param2);
+ using Function = void (*)(Args...);
+ (*(reinterpret_cast<Function>(callback.mFunction)))(args...);
}
}
+public:
/**
- * @brief Function to call the function or member function dispatcher.
- *
- * This function template gets instantiated at the call site.
- * @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- * @param[in] param2 The second parameter to pass into the function
- * @return The return value from the function
- */
- template<typename R, typename P1, typename P2>
- static R ExecuteReturn(CallbackBase& callback, P1 param1, P2 param2)
- {
- R returnVal = R();
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code (where the callback was created)
- // so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl && callback.mImpl->mObjectPointer)
- {
- using Dispatcher = R (*)(CallbackBase&, P1, P2);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl->mMemberFunctionDispatcher);
- returnVal = (*dispatcher)(callback, param1, param2);
- }
- else if(!callback.mImpl && callback.mFunction)
- {
- // convert function type
- using Function2 = R (*)(P1, P2);
- returnVal = (*(reinterpret_cast<Function2>(callback.mFunction)))(param1, param2);
- }
-
- return returnVal;
- }
-
- /**
- * @brief Function to call the function or member function dispatcher.
- *
- * This function template gets instantiated at the call site.
+ * @brief Function with static linkage.
* @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- * @param[in] param2 The second parameter to pass into the function
- * @param[in] param3 The third parameter to pass into the function
*/
- template<typename P1, typename P2, typename P3>
- static void Execute(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
- {
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code (where the callback was created)
- // so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl && callback.mImpl->mObjectPointer)
- {
- using Dispatcher = void (*)(CallbackBase&, P1, P2, P3);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl->mMemberFunctionDispatcher);
- (*dispatcher)(callback, param1, param2, param3);
- }
- else if(!callback.mImpl && callback.mFunction)
- {
- // convert function type
- using Function2 = void (*)(P1, P2, P3);
- (*(reinterpret_cast<Function2>(callback.mFunction)))(param1, param2, param3);
- }
- }
+ using Function = void (*)();
/**
- * @brief Function to call the function or member function dispatcher.
+ * @brief Constructor for function with static linkage.
*
- * This function template gets instantiated at the call site.
* @SINCE_1_0.0
- * @param[in] callback The callback to call
- * @param[in] param1 The first parameter to pass into the function
- * @param[in] param2 The second parameter to pass into the function
- * @param[in] param3 The third parameter to pass into the function
- * @return The return value from the function
+ * @param[in] function The function to call
*/
- template<typename R, typename P1, typename P2, typename P3>
- static R ExecuteReturn(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
- {
- R returnVal = R();
- // if we point to a function, we can call it directly
- // otherwise call the dispatcher function that knows the real type of the object
- // Note that this template dispatcher lives in client code (where the callback was created)
- // so the library containing the code has to be loaded, otherwise we crash boom bang
- if(callback.mImpl && callback.mImpl->mObjectPointer)
- {
- using Dispatcher = R (*)(CallbackBase&, P1, P2, P3);
- Dispatcher dispatcher = reinterpret_cast<Dispatcher>(callback.mImpl->mMemberFunctionDispatcher);
- returnVal = (*dispatcher)(callback, param1, param2, param3);
- }
- else if(!callback.mImpl && callback.mFunction)
- {
- // convert function type
- using Function2 = R (*)(P1, P2, P3);
- returnVal = (*(reinterpret_cast<Function2>(callback.mFunction)))(param1, param2, param3);
- }
-
- return returnVal;
- }
+ CallbackBase(Function function);
protected: // Constructors for deriving classes
- /**
- * @brief Function with static linkage.
- * @SINCE_1_0.0
- */
- using Function = void (*)();
+
/**
* @brief Member function.
CallbackBase& operator=(const CallbackBase& rhs);
/**
- * @brief Constructor for function with static linkage.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- */
- CallbackBase(Function function);
-
- /**
* @brief Constructor for member function.
*
* @SINCE_1_0.0
*/
struct Impl
{
- Impl(); ///< Default constructor @SINCE_1_0.0
-
- void* mObjectPointer; ///< Object whose member function will be called. Not owned if mDestructorDispatcher is NULL.
- Dispatcher mMemberFunctionDispatcher; ///< Dispatcher for member functions
- Destructor mDestructorDispatcher; ///< Destructor for owned objects. NULL if mDestructorDispatcher is not owned.
+ void* mObjectPointer{nullptr}; ///< Object whose member function will be called. Not owned if mDestructorDispatcher is NULL.
+ Dispatcher mMemberFunctionDispatcher{nullptr}; ///< Dispatcher for member functions
+ Destructor mDestructorDispatcher{nullptr}; ///< Destructor for owned objects. NULL if mDestructorDispatcher is not owned.
};
- Impl* mImpl; ///< Implementation pointer
+ Impl mImpl;
union
{
* @param[in] rhs A reference to compare to
* @return True if lhs is same as rhs
*/
-bool operator==(const CallbackBase& lhs, const CallbackBase& rhs);
+inline bool operator==(const CallbackBase& lhs, const CallbackBase& rhs)
+{
+ if (lhs.mFunction == rhs.mFunction &&
+ lhs.mImpl.mObjectPointer == rhs.mImpl.mObjectPointer)
+ {
+ return true;
+ }
+ return false;
+}
/**
* @brief Dispatcher to delete an object.
static void Dispatch(CallbackBase& callback)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)();
static void Dispatch(CallbackBase& callback, P1 param1)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)(P1);
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(param1);
static void Dispatch(CallbackBase& callback, P1 param1, P2 param2)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)(P1, P2);
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(param1, param2);
static void Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)(P1, P2, P3);
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(param1, param2, param3);
static R Dispatch(CallbackBase& callback)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = R (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
return (object->*function)();
static R Dispatch(CallbackBase& callback, P1 param1)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = R (T::*)(P1);
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
return (object->*function)(param1);
static R Dispatch(CallbackBase& callback, P1 param1, P2 param2)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = R (T::*)(P1, P2);
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
return (object->*function)(param1, param2);
static R Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = R (T::*)(P1, P2, P3);
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
return (object->*function)(param1, param2, param3);
static void Dispatch(CallbackBase& callback)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
(*object)();
}
};
static void Dispatch(CallbackBase& callback, P1 param1)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
(*object)(param1);
}
};
static void Dispatch(CallbackBase& callback, P1 param1, P2 param2)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
(*object)(param1, param2);
}
};
static void Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
(*object)(param1, param2, param3);
}
};
static R Dispatch(CallbackBase& callback)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
return (*object)();
}
};
static R Dispatch(CallbackBase& callback, P1 param1)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
return (*object)(param1);
}
};
static R Dispatch(CallbackBase& callback, P1 param1, P2 param2)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
return (*object)(param1, param2);
}
};
static R Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
return (*object)(param1, param2, param3);
}
};
static void Dispatch(CallbackBase& callback)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)();
static void Dispatch(CallbackBase& callback, P1 param1)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(/*ignore params*/);
static void Dispatch(CallbackBase& callback, P1 param1, P2 param2)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(/*ignore params*/);
static void Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(/*ignore params*/);
static R Dispatch(CallbackBase& callback)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(/*ignore params*/);
static R Dispatch(CallbackBase& callback, P1 param1)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(/*ignore params*/);
static R Dispatch(CallbackBase& callback, P1 param1, P2 param2)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(/*ignore params*/);
static R Dispatch(CallbackBase& callback, P1 param1, P2 param2, P3 param3)
{
// "downcast" the object and function type back to the correct ones
- T* object = reinterpret_cast<T*>(callback.mImpl->mObjectPointer);
+ T* object = reinterpret_cast<T*>(callback.mImpl.mObjectPointer);
using MemberFunction = void (T::*)();
MemberFunction function = reinterpret_cast<MemberFunction>(callback.mMemberFunction);
(object->*function)(/*ignore params*/);
};
/**
- * @brief Specializations for static function callbacks.
- * @SINCE_1_0.0
- */
-class CallbackFunction : public CallbackBase
-{
-public:
- /**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- CallbackFunction()
- : CallbackBase()
- {
- }
-
- /**
- * @brief Constructors for functions with static linkage.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- */
- CallbackFunction(void (*function)())
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename R>
- CallbackFunction(R (*function)())
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1>
- CallbackFunction(void (*function)(P1))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename R>
- CallbackFunction(R (*function)(P1))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename P2>
- CallbackFunction(void (*function)(P1, P2))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename P2, typename R>
- CallbackFunction(R (*function)(P1, P2))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename P2, typename P3>
- CallbackFunction(void (*function)(P1, P2, P3))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
- template<typename P1, typename P2, typename P3, typename R>
- CallbackFunction(R (*function)(P1, P2, P3))
- : CallbackBase(reinterpret_cast<CallbackBase::Function>(function))
- {
- }
-};
-
-/**
* @brief Specializations for function object callbacks.
* @SINCE_1_0.0
*/
// Callback creation thin templates
/**
- * @brief Creates a callback from a C function or static member function with no parameters.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-inline CallbackBase* MakeCallback(void (*function)(void))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with one parameter.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename P1>
-inline CallbackBase* MakeCallback(void (*function)(P1))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with no parameters and a return type.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename R>
-inline CallbackBase* MakeCallback(R (*function)(void))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with one parameter and a return type.
+ * @brief Creates a callback from a free function with parameter pack.
*
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename R, typename P1>
-inline CallbackBase* MakeCallback(R (*function)(P1))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with two parameters.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename P1, typename P2>
-inline CallbackBase* MakeCallback(void (*function)(P1, P2))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with two parameters and a return type.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename R, typename P1, typename P2>
-inline CallbackBase* MakeCallback(R (*function)(P1, P2))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with three parameters.
- *
- * @SINCE_1_0.0
- * @param[in] function The function to call
- * @return A newly allocated Callback object, ownership transferred to caller
- */
-template<typename P1, typename P2, typename P3>
-inline CallbackBase* MakeCallback(void (*function)(P1, P2, P3))
-{
- return new CallbackFunction(function);
-}
-
-/**
- * @brief Creates a callback from a C function or static member function with three parameters and a return type.
- *
- * @SINCE_1_0.0
+ * @SINCE_1_9.33
* @param[in] function The function to call
* @return A newly allocated Callback object, ownership transferred to caller
*/
-template<typename R, typename P1, typename P2, typename P3>
-inline CallbackBase* MakeCallback(R (*function)(P1, P2, P3))
+template<typename R, typename... Args>
+inline CallbackBase* MakeCallback(R (*function)(Args... args))
{
- return new CallbackFunction(function);
+ return new CallbackBase(reinterpret_cast<CallbackBase::Function>(function));
}
/**
for(std::size_t i = 0; i < size; ++i)
{
- SlotConnection* connection = mConnections[i];
+ auto& connection = mConnections[i];
// Tell the signal that the slot is disconnected
- connection->GetSlotObserver()->SlotDisconnected(connection->GetCallback());
+ connection.GetSlotObserver()->SlotDisconnected(connection.GetCallback());
- delete connection;
}
mConnections.Clear();
void ConnectionTracker::SignalConnected(SlotObserver* slotObserver, CallbackBase* callback)
{
- SlotConnection* connection = new SlotConnection(slotObserver, callback);
- mConnections.PushBack(connection);
+ mConnections.PushBack(SlotConnection(slotObserver, callback));
}
void ConnectionTracker::SignalDisconnected(SlotObserver* signal, CallbackBase* callback)
for(std::size_t i = 0; i < size; ++i)
{
- SlotConnection* connection = mConnections[i];
+ auto& connection = mConnections[i];
// Pointer comparison i.e. SignalConnection contains pointer to same callback instance
- if(connection->GetCallback() == callback)
+ if(connection.GetCallback() == callback)
{
// Remove from connection list
mConnections.Erase(mConnections.Begin() + i);
- // Delete connection
- delete connection;
-
// Disconnection complete
return;
}
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/common/dali-vector.h>
#include <dali/public-api/signals/connection-tracker-interface.h>
+#include <dali/public-api/signals/signal-slot-connections.h>
namespace Dali
{
ConnectionTracker& operator=(ConnectionTracker&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25
private:
- Dali::Vector<SlotConnection*> mConnections; ///< Vector of connection pointers
+ Dali::Vector<SlotConnection> mConnections; ///< Vector of connection
};
/**
* @SINCE_1_0.0
*/
+// EXTERNAL_INCLUDES
+#include <memory>
+
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/signals/base-signal.h>
{
};
-/**
- * @brief A template for Signals with no parameters or return value.
- * @SINCE_1_0.0
- */
-template<>
-class Signal<void()>
+class SignalMixin
{
public:
/**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- Signal()
- {
- }
-
- /**
- * @brief Non-virtual destructor.
- * @SINCE_1_0.0
- */
- ~Signal()
- {
- }
-
- /**
* @brief Queries whether there are any connected slots.
*
* @SINCE_1_0.0
*/
bool Empty() const
{
- return mImpl.Empty();
+ return mImpl ? mImpl->Empty() : true;
}
/**
*/
std::size_t GetConnectionCount() const
{
- return mImpl.GetConnectionCount();
+ return mImpl ? mImpl->GetConnectionCount() : 0;
}
+protected:
+ BaseSignal& Impl()
+ {
+ if(!mImpl)
+ {
+ mImpl = std::make_unique<BaseSignal>();
+ }
+ return *mImpl;
+ }
+
+private:
+ std::unique_ptr<BaseSignal> mImpl;
+};
+
+/**
+ * @brief A template for Signals with no parameters or return value.
+ * @SINCE_1_0.0
+ */
+template<>
+class Signal<void()> : public SignalMixin
+{
+public:
/**
* @brief Connects a function.
*
*/
void Connect(void (*func)())
{
- mImpl.OnConnect(MakeCallback(func));
+ Impl().OnConnect(MakeCallback(func));
}
/**
*/
void Disconnect(void (*func)())
{
- mImpl.OnDisconnect(MakeCallback(func));
+ Impl().OnDisconnect(MakeCallback(func));
}
/**
template<class X>
void Connect(X* obj, void (X::*func)())
{
- mImpl.OnConnect(obj, MakeCallback(obj, func));
+ Impl().OnConnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Disconnect(X* obj, void (X::*func)())
{
- mImpl.OnDisconnect(obj, MakeCallback(obj, func));
+ Impl().OnDisconnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Connect(SlotDelegate<X>& delegate, void (X::*func)())
{
- mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Disconnect(SlotDelegate<X>& delegate, void (X::*func)())
{
- mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Connect(ConnectionTrackerInterface* connectionTracker, const X& func)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctor0<X>(func));
+ Impl().OnConnect(connectionTracker, new CallbackFunctor0<X>(func));
}
/**
*/
void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegate0(delegate));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorDelegate0(delegate));
}
/**
*/
void Emit()
{
- mImpl.Emit();
+ Impl().Emit();
}
-
-private:
- Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0
- Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25
- Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0
- Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25
-
-private:
- // Use composition instead of inheritance (virtual methods don't mix well with templates)
- BaseSignal mImpl; ///< The base signal implementation
};
/**
* @SINCE_1_0.0
*/
template<typename Ret>
-class Signal<Ret()>
+class Signal<Ret()> : public SignalMixin
{
public:
/**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- Signal()
- {
- }
-
- /**
- * @brief Non-virtual destructor.
- * @SINCE_1_0.0
- */
- ~Signal()
- {
- }
-
- /**
- * @brief Queries whether there are any connected slots.
- *
- * @SINCE_1_0.0
- * @return True if there are any slots connected to the signal
- */
- bool Empty() const
- {
- return mImpl.Empty();
- }
-
- /**
- * @brief Queries the number of slots.
- *
- * @SINCE_1_0.0
- * @return The number of slots connected to this signal
- */
- std::size_t GetConnectionCount() const
- {
- return mImpl.GetConnectionCount();
- }
- /**
* @brief Connects a function.
*
* @SINCE_1_0.0
*/
void Connect(Ret (*func)())
{
- mImpl.OnConnect(MakeCallback(func));
+ Impl().OnConnect(MakeCallback(func));
}
/**
*/
void Disconnect(Ret (*func)())
{
- mImpl.OnDisconnect(MakeCallback(func));
+ Impl().OnDisconnect(MakeCallback(func));
}
/**
template<class X>
void Connect(X* obj, Ret (X::*func)())
{
- mImpl.OnConnect(obj, MakeCallback(obj, func));
+ Impl().OnConnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Disconnect(X* obj, Ret (X::*func)())
{
- mImpl.OnDisconnect(obj, MakeCallback(obj, func));
+ Impl().OnDisconnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Connect(SlotDelegate<X>& delegate, Ret (X::*func)())
{
- mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Disconnect(SlotDelegate<X>& delegate, Ret (X::*func)())
{
- mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Connect(ConnectionTrackerInterface* connectionTracker, const X& func)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorReturn0<X, Ret>(func));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorReturn0<X, Ret>(func));
}
/**
*/
void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegateReturn0<Ret>(delegate));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorDelegateReturn0<Ret>(delegate));
}
/**
*/
Ret Emit()
{
- return mImpl.EmitReturn<Ret>();
+ return Impl().template EmitReturn<Ret>();
}
-
-private:
- Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0
- Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25
- Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0
- Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25
-
-private:
- // Use composition instead of inheritance (virtual methods don't mix well with templates)
- BaseSignal mImpl; ///< Implementation
};
/**
* @SINCE_1_0.0
*/
template<typename Arg0>
-class Signal<void(Arg0)>
+class Signal<void(Arg0)> : public SignalMixin
{
public:
/**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- Signal()
- {
- }
-
- /**
- * @brief Non-virtual destructor.
- * @SINCE_1_0.0
- */
- ~Signal()
- {
- }
-
- /**
- * @brief Queries whether there are any connected slots.
- *
- * @SINCE_1_0.0
- * @return True if there are any slots connected to the signal
- */
- bool Empty() const
- {
- return mImpl.Empty();
- }
-
- /**
- * @brief Queries the number of slots.
- *
- * @SINCE_1_0.0
- * @return The number of slots connected to this signal
- */
- std::size_t GetConnectionCount() const
- {
- return mImpl.GetConnectionCount();
- }
- /**
* @brief Connects a function.
*
* @SINCE_1_0.0
*/
void Connect(void (*func)(Arg0 arg0))
{
- mImpl.OnConnect(MakeCallback(func));
+ Impl().OnConnect(MakeCallback(func));
}
/**
*/
void Disconnect(void (*func)(Arg0 arg0))
{
- mImpl.OnDisconnect(MakeCallback(func));
+ Impl().OnDisconnect(MakeCallback(func));
}
/**
template<class X>
void Connect(X* obj, void (X::*func)(Arg0 arg0))
{
- mImpl.OnConnect(obj, MakeCallback(obj, func));
+ Impl().OnConnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Disconnect(X* obj, void (X::*func)(Arg0 arg0))
{
- mImpl.OnDisconnect(obj, MakeCallback(obj, func));
+ Impl().OnDisconnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Connect(SlotDelegate<X>& delegate, void (X::*func)(Arg0 arg0))
{
- mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Disconnect(SlotDelegate<X>& delegate, void (X::*func)(Arg0 arg0))
{
- mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Connect(ConnectionTrackerInterface* connectionTracker, const X& func)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctor1<X, Arg0>(func));
+ Impl().OnConnect(connectionTracker, new CallbackFunctor1<X, Arg0>(func));
}
/**
*/
void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegate1<Arg0>(delegate));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorDelegate1<Arg0>(delegate));
}
/**
*/
void Emit(Arg0 arg0)
{
- mImpl.Emit<Arg0>(arg0);
+ Impl().template Emit<Arg0>(arg0);
}
-
-private:
- Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0
- Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25
- Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0
- Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25
-
-private:
- // Use composition instead of inheritance (virtual methods don't mix well with templates)
- BaseSignal mImpl; ///< Implementation
};
/**
* @SINCE_1_0.0
*/
template<typename Ret, typename Arg0>
-class Signal<Ret(Arg0)>
+class Signal<Ret(Arg0)> : public SignalMixin
{
public:
/**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- Signal()
- {
- }
-
- /**
- * @brief Non-virtual destructor.
- * @SINCE_1_0.0
- */
- ~Signal()
- {
- }
-
- /**
- * @brief Queries whether there are any connected slots.
- *
- * @SINCE_1_0.0
- * @return True if there are any slots connected to the signal
- */
- bool Empty() const
- {
- return mImpl.Empty();
- }
-
- /**
- * @brief Queries the number of slots.
- *
- * @SINCE_1_0.0
- * @return The number of slots connected to this signal
- */
- std::size_t GetConnectionCount() const
- {
- return mImpl.GetConnectionCount();
- }
- /**
* @brief Connects a function.
*
* @SINCE_1_0.0
*/
void Connect(Ret (*func)(Arg0 arg0))
{
- mImpl.OnConnect(MakeCallback(func));
+ Impl().OnConnect(MakeCallback(func));
}
/**
*/
void Disconnect(Ret (*func)(Arg0 arg0))
{
- mImpl.OnDisconnect(MakeCallback(func));
+ Impl().OnDisconnect(MakeCallback(func));
}
/**
template<class X>
void Connect(X* obj, Ret (X::*func)(Arg0 arg0))
{
- mImpl.OnConnect(obj, MakeCallback(obj, func));
+ Impl().OnConnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Disconnect(X* obj, Ret (X::*func)(Arg0 arg0))
{
- mImpl.OnDisconnect(obj, MakeCallback(obj, func));
+ Impl().OnDisconnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Connect(SlotDelegate<X>& delegate, Ret (X::*func)(Arg0 arg0))
{
- mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Disconnect(SlotDelegate<X>& delegate, Ret (X::*func)(Arg0 arg0))
{
- mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Connect(ConnectionTrackerInterface* connectionTracker, const X& func)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorReturn1<X, Arg0, Ret>(func));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorReturn1<X, Arg0, Ret>(func));
}
/**
*/
void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegateReturn1<Arg0, Ret>(delegate));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorDelegateReturn1<Arg0, Ret>(delegate));
}
/**
*/
Ret Emit(Arg0 arg0)
{
- return mImpl.EmitReturn<Ret, Arg0>(arg0);
+ return Impl().template EmitReturn<Ret, Arg0>(arg0);
}
-
-private:
- Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0
- Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25
- Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0
- Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25
-
-private:
- // Use composition instead of inheritance (virtual methods don't mix well with templates)
- BaseSignal mImpl; ///< Implementation
};
/**
* @SINCE_1_0.0
*/
template<typename Arg0, typename Arg1>
-class Signal<void(Arg0, Arg1)>
+class Signal<void(Arg0, Arg1)> : public SignalMixin
{
public:
/**
- * @brief Default constructor.
- *
- * @SINCE_1_0.0
- */
- Signal()
- {
- }
-
- /**
- * @brief Non-virtual destructor.
- *
- * @SINCE_1_0.0
- */
- ~Signal()
- {
- }
-
- /**
- * @brief Queries whether there are any connected slots.
- *
- * @SINCE_1_0.0
- * @return True if there are any slots connected to the signal
- */
- bool Empty() const
- {
- return mImpl.Empty();
- }
-
- /**
- * @brief Queries the number of slots.
- *
- * @SINCE_1_0.0
- * @return The number of slots connected to this signal
- */
- std::size_t GetConnectionCount() const
- {
- return mImpl.GetConnectionCount();
- }
- /**
* @brief Connects a function.
*
* @SINCE_1_0.0
*/
void Connect(void (*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnConnect(MakeCallback(func));
+ Impl().OnConnect(MakeCallback(func));
}
/**
*/
void Disconnect(void (*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnDisconnect(MakeCallback(func));
+ Impl().OnDisconnect(MakeCallback(func));
}
/**
template<class X>
void Connect(X* obj, void (X::*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnConnect(obj, MakeCallback(obj, func));
+ Impl().OnConnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Disconnect(X* obj, void (X::*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnDisconnect(obj, MakeCallback(obj, func));
+ Impl().OnDisconnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Connect(SlotDelegate<X>& delegate, void (X::*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Disconnect(SlotDelegate<X>& delegate, void (X::*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Connect(ConnectionTrackerInterface* connectionTracker, const X& func)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctor2<X, Arg0, Arg1>(func));
+ Impl().OnConnect(connectionTracker, new CallbackFunctor2<X, Arg0, Arg1>(func));
}
/**
*/
void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegate2<Arg0, Arg1>(delegate));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorDelegate2<Arg0, Arg1>(delegate));
}
/**
*/
void Emit(Arg0 arg0, Arg1 arg1)
{
- mImpl.Emit<Arg0, Arg1>(arg0, arg1);
+ Impl().template Emit<Arg0, Arg1>(arg0, arg1);
}
-
-private:
- Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0
- Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25
- Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0
- Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25
-
-private:
- // Use composition instead of inheritance (virtual methods don't mix well with templates)
- BaseSignal mImpl; ///< Implementation
};
/**
* @SINCE_1_0.0
*/
template<typename Ret, typename Arg0, typename Arg1>
-class Signal<Ret(Arg0, Arg1)>
+class Signal<Ret(Arg0, Arg1)> : public SignalMixin
{
public:
/**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- Signal()
- {
- }
-
- /**
- * @brief Non-virtual destructor.
- * @SINCE_1_0.0
- */
- ~Signal()
- {
- }
-
- /**
- * @brief Queries whether there are any connected slots.
- *
- * @SINCE_1_0.0
- * @return True if there are any slots connected to the signal
- */
- bool Empty() const
- {
- return mImpl.Empty();
- }
-
- /**
- * @brief Queries the number of slots.
- *
- * @SINCE_1_0.0
- * @return The number of slots connected to this signal
- */
- std::size_t GetConnectionCount() const
- {
- return mImpl.GetConnectionCount();
- }
- /**
* @brief Connects a function.
* @SINCE_1_0.0
* @param[in] func The function to connect
*/
void Connect(Ret (*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnConnect(MakeCallback(func));
+ Impl().OnConnect(MakeCallback(func));
}
/**
*/
void Disconnect(Ret (*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnDisconnect(MakeCallback(func));
+ Impl().OnDisconnect(MakeCallback(func));
}
/**
template<class X>
void Connect(X* obj, Ret (X::*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnConnect(obj, MakeCallback(obj, func));
+ Impl().OnConnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Disconnect(X* obj, Ret (X::*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnDisconnect(obj, MakeCallback(obj, func));
+ Impl().OnDisconnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Connect(SlotDelegate<X>& delegate, Ret (X::*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Disconnect(SlotDelegate<X>& delegate, Ret (X::*func)(Arg0 arg0, Arg1 arg1))
{
- mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Connect(ConnectionTrackerInterface* connectionTracker, const X& func)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorReturn2<X, Arg0, Arg1, Ret>(func));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorReturn2<X, Arg0, Arg1, Ret>(func));
}
/**
*/
void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegateReturn2<Arg0, Arg1, Ret>(delegate));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorDelegateReturn2<Arg0, Arg1, Ret>(delegate));
}
/**
*/
Ret Emit(Arg0 arg0, Arg1 arg1)
{
- return mImpl.EmitReturn<Ret, Arg0, Arg1>(arg0, arg1);
+ return Impl().template EmitReturn<Ret, Arg0, Arg1>(arg0, arg1);
}
-
-private:
- Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0
- Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25
- Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0
- Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25
-
-private:
- // Use composition instead of inheritance (virtual methods don't mix well with templates)
- BaseSignal mImpl; ///< Implementation
};
/**
* @SINCE_1_0.0
*/
template<typename Arg0, typename Arg1, typename Arg2>
-class Signal<void(Arg0, Arg1, Arg2)>
+class Signal<void(Arg0, Arg1, Arg2)> : public SignalMixin
{
public:
/**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- Signal()
- {
- }
-
- /**
- * @brief Non-virtual destructor.
- * @SINCE_1_0.0
- */
- ~Signal()
- {
- }
-
- /**
- * @brief Queries whether there are any connected slots.
- *
- * @SINCE_1_0.0
- * @return True if there are any slots connected to the signal
- */
- bool Empty() const
- {
- return mImpl.Empty();
- }
-
- /**
- * @brief Queries the number of slots.
- *
- * @SINCE_1_0.0
- * @return The number of slots connected to this signal
- */
- std::size_t GetConnectionCount() const
- {
- return mImpl.GetConnectionCount();
- }
- /**
* @brief Connects a function.
*
* @SINCE_1_0.0
*/
void Connect(void (*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnConnect(MakeCallback(func));
+ Impl().OnConnect(MakeCallback(func));
}
/**
*/
void Disconnect(void (*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnDisconnect(MakeCallback(func));
+ Impl().OnDisconnect(MakeCallback(func));
}
/**
template<class X>
void Connect(X* obj, void (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnConnect(obj, MakeCallback(obj, func));
+ Impl().OnConnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Disconnect(X* obj, void (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnDisconnect(obj, MakeCallback(obj, func));
+ Impl().OnDisconnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Connect(SlotDelegate<X>& delegate, void (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Disconnect(SlotDelegate<X>& delegate, void (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Connect(ConnectionTrackerInterface* connectionTracker, const X& func)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctor3<X, Arg0, Arg1, Arg2>(func));
+ Impl().OnConnect(connectionTracker, new CallbackFunctor3<X, Arg0, Arg1, Arg2>(func));
}
/**
*/
void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegate3<Arg0, Arg1, Arg2>(delegate));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorDelegate3<Arg0, Arg1, Arg2>(delegate));
}
/**
*/
void Emit(Arg0 arg0, Arg1 arg1, Arg2 arg2)
{
- mImpl.Emit<Arg0, Arg1, Arg2>(arg0, arg1, arg2);
+ Impl().template Emit<Arg0, Arg1, Arg2>(arg0, arg1, arg2);
}
-
-private:
- Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0
- Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25
- Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0
- Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25
-
-private:
- // Use composition instead of inheritance (virtual methods don't mix well with templates)
- BaseSignal mImpl; ///< Implementation
};
/**
* @SINCE_1_0.0
*/
template<typename Ret, typename Arg0, typename Arg1, typename Arg2>
-class Signal<Ret(Arg0, Arg1, Arg2)>
+class Signal<Ret(Arg0, Arg1, Arg2)> : public SignalMixin
{
public:
/**
- * @brief Default constructor.
- * @SINCE_1_0.0
- */
- Signal()
- {
- }
-
- /**
- * @brief Non-virtual destructor.
- * @SINCE_1_0.0
- */
- ~Signal()
- {
- }
-
- /**
- * @brief Queries whether there are any connected slots.
- *
- * @SINCE_1_0.0
- * @return True if there are any slots connected to the signal
- */
- bool Empty() const
- {
- return mImpl.Empty();
- }
-
- /**
- * @brief Queries the number of slots.
- *
- * @SINCE_1_0.0
- * @return The number of slots connected to this signal
- */
- std::size_t GetConnectionCount() const
- {
- return mImpl.GetConnectionCount();
- }
-
- /**
* @brief Connects a function.
*
* @SINCE_1_0.0
*/
void Connect(Ret (*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnConnect(MakeCallback(func));
+ Impl().OnConnect(MakeCallback(func));
}
/**
*/
void Disconnect(Ret (*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnDisconnect(MakeCallback(func));
+ Impl().OnDisconnect(MakeCallback(func));
}
/**
template<class X>
void Connect(X* obj, Ret (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnConnect(obj, MakeCallback(obj, func));
+ Impl().OnConnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Disconnect(X* obj, Ret (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnDisconnect(obj, MakeCallback(obj, func));
+ Impl().OnDisconnect(obj, MakeCallback(obj, func));
}
/**
template<class X>
void Connect(SlotDelegate<X>& delegate, Ret (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnConnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Disconnect(SlotDelegate<X>& delegate, Ret (X::*func)(Arg0 arg0, Arg1 arg1, Arg2 arg2))
{
- mImpl.OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
+ Impl().OnDisconnect(delegate.GetConnectionTracker(), MakeCallback(delegate.GetSlot(), func));
}
/**
template<class X>
void Connect(ConnectionTrackerInterface* connectionTracker, const X& func)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorReturn3<X, Arg0, Arg1, Arg2, Ret>(func));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorReturn3<X, Arg0, Arg1, Arg2, Ret>(func));
}
/**
*/
void Connect(ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate)
{
- mImpl.OnConnect(connectionTracker, new CallbackFunctorDelegateReturn3<Arg0, Arg1, Arg2, Ret>(delegate));
+ Impl().OnConnect(connectionTracker, new CallbackFunctorDelegateReturn3<Arg0, Arg1, Arg2, Ret>(delegate));
}
/**
*/
Ret Emit(Arg0 arg0, Arg1 arg1, Arg2 arg2)
{
- return mImpl.EmitReturn<Ret, Arg0, Arg1, Arg2>(arg0, arg1, arg2);
+ return Impl().template EmitReturn<Ret, Arg0, Arg1, Arg2>(arg0, arg1, arg2);
}
-
-private:
- Signal(const Signal&) = delete; ///< Deleted copy constructor, signals don't support copying. @SINCE_1_0.0
- Signal(Signal&&) = delete; ///< Deleted move constructor, signals don't support moving. @SINCE_1_9.25
- Signal& operator=(const Signal&) = delete; ///< Deleted copy assignment operator @SINCE_1_0.0
- Signal& operator=(Signal&&) = delete; ///< Deleted move assignment operator @SINCE_1_9.25
-
-private:
- // Use composition instead of inheritance (virtual methods don't mix well with templates)
- BaseSignal mImpl; ///< Implementation
};
/**
// EXTERNAL INCLUDES
#include <cstddef>
+#include <type_traits>
// INTERNAL INCLUDES
#include <dali/public-api/signals/callback.h>
namespace Dali
{
+
SlotConnection::SlotConnection(SlotObserver* slotObserver, CallbackBase* callback)
: mSlotObserver(slotObserver),
mCallback(callback)
{
}
-SlotConnection::~SlotConnection()
-{
-}
-
-CallbackBase* SlotConnection::GetCallback()
-{
- return mCallback;
-}
-
-SlotObserver* SlotConnection::GetSlotObserver()
-{
- return mSlotObserver;
-}
-
-SignalConnection::SignalConnection(CallbackBase* callback)
-: mSignalObserver(nullptr),
- mCallback(callback)
-{
-}
-
-SignalConnection::SignalConnection(SignalObserver* signalObserver, CallbackBase* callback)
-: mSignalObserver(signalObserver),
- mCallback(callback)
-{
-}
-
-SignalConnection::~SignalConnection()
-{
- // signal connections have ownership of the callback.
- delete mCallback;
-}
-
-void SignalConnection::Disconnect(SlotObserver* slotObserver)
+void SignalConnection::Disconnect(SlotObserver* slotObserver) noexcept
{
if(mSignalObserver)
{
mCallback = nullptr;
}
-CallbackBase* SignalConnection::GetCallback()
-{
- return mCallback;
-}
+static_assert(std::is_nothrow_move_constructible_v<SignalConnection>);
+static_assert(std::is_nothrow_move_assignable_v<SignalConnection>);
+
+static_assert(std::is_copy_constructible_v<SignalConnection> == false);
+static_assert(std::is_copy_assignable_v<SignalConnection> == false);
} // namespace Dali
*/
// INTERNAL INCLUDES
+#include <dali/public-api/signals/callback.h>
#include <dali/public-api/signals/signal-slot-observers.h>
namespace Dali
* @{
*/
-class CallbackBase;
/**
* @brief Slot connection is the connection information held by a connection tracker.
SlotConnection(SlotObserver* slotObserver, CallbackBase* callback);
/**
- * @brief Non-virtual destructor, not intended as a base class.
- * @SINCE_1_0.0
- */
- ~SlotConnection();
-
- /**
* @brief Retrieves the callback.
*
* @SINCE_1_0.0
* @return A pointer to the callback
*/
- CallbackBase* GetCallback();
+ CallbackBase* GetCallback() const
+ {
+ return mCallback;
+ }
/**
* @brief Retrieves the slot observer.
* @SINCE_1_0.0
* @return A pointer to the slot observer
*/
- SlotObserver* GetSlotObserver();
-
-private:
- SlotConnection(const SlotConnection&) = delete; ///< Deleted copy constructor. @SINCE_1_0.0
- SlotConnection(SlotConnection&&) = delete; ///< Deleted move constructor. @SINCE_1_9.25
- SlotConnection& operator=(const SlotConnection&) = delete; ///< Deleted copy assignment operator. @SINCE_1_0.0
- SlotConnection& operator=(SlotConnection&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25
+ SlotObserver* GetSlotObserver() const
+ {
+ return mSlotObserver;
+ }
private:
- SlotObserver* mSlotObserver; ///< a pointer to the slot observer (not owned)
- CallbackBase* mCallback; ///< The callback. This is not owned, the corresponding SignalConnection has ownership.
+ SlotObserver* mSlotObserver{nullptr}; ///< a pointer to the slot observer (not owned)
+ CallbackBase* mCallback{nullptr}; ///< The callback. This is not owned, the corresponding SignalConnection has ownership.
};
/**
* @SINCE_1_0.0
* @param[in] callback The callback which should be a C function
*/
- SignalConnection(CallbackBase* callback);
+ SignalConnection(CallbackBase* callback) noexcept
+ : mCallback(callback)
+ {
+ }
/**
* @brief Constructor.
* @param[in] signalObserver The signal observer
* @param[in] callback Ownership of this callback object is taken
*/
- SignalConnection(SignalObserver* signalObserver, CallbackBase* callback);
+ SignalConnection(SignalObserver* signalObserver, CallbackBase* callback) noexcept
+ : mSignalObserver(signalObserver),
+ mCallback(callback)
+ {
+ }
/**
* @brief Non-virtual destructor, not intended as a base class.
* @SINCE_1_0.0
*/
- ~SignalConnection();
+ ~SignalConnection() noexcept
+ {
+ // signal connections have ownership of the callback.
+ delete mCallback;
+ }
/**
* @brief Disconnects the signal from the slot.
* @SINCE_1_0.0
* @param[in] slotObserver The signal disconnecting from the slot
*/
- void Disconnect(SlotObserver* slotObserver);
+ void Disconnect(SlotObserver* slotObserver) noexcept;
/**
* @brief Retrieves the callback.
* @SINCE_1_0.0
* @return A pointer to the callback
*/
- CallbackBase* GetCallback();
+ CallbackBase* GetCallback() const noexcept
+ {
+ return mCallback;
+ }
-private:
SignalConnection(const SignalConnection&) = delete; ///< Deleted copy constructor. @SINCE_1_0.0
- SignalConnection(SignalConnection&&) = delete; ///< Deleted move constructor. @SINCE_1_9.25
SignalConnection& operator=(const SignalConnection&) = delete; ///< Deleted copy assignment operator. @SINCE_1_0.0
- SignalConnection& operator=(SignalConnection&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25
+
+ /**
+ * @brief Move constructor.
+ *
+ * A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying.
+ * @SINCE_1_9.38
+ * @param[in] connection The property value to move from
+ */
+ SignalConnection(SignalConnection&& connection) noexcept
+ : mSignalObserver(connection.mSignalObserver),
+ mCallback(connection.mCallback)
+ {
+ connection.mSignalObserver = nullptr;
+ connection.mCallback = nullptr;
+ }
+
+ /**
+ * @brief Move assignment operator.
+ *
+ * @SINCE_1_9.38
+ * @param[in] connection The connection to move from
+ * @return a reference to this
+ */
+ SignalConnection& operator=(SignalConnection&& connection) noexcept
+ {
+ if(this != &connection)
+ {
+ // release the callback
+ delete mCallback;
+
+ mSignalObserver = connection.mSignalObserver;
+ mCallback = connection.mCallback;
+
+ connection.mSignalObserver = nullptr;
+ connection.mCallback = nullptr;
+ }
+ return *this;
+ }
+
+ explicit operator bool() const noexcept
+ {
+ return mCallback ? true : false;
+ }
private:
- SignalObserver* mSignalObserver; ///< a pointer to the signal observer (not owned)
- CallbackBase* mCallback; ///< The callback, has ownership.
+ SignalObserver* mSignalObserver{nullptr}; ///< a pointer to the signal observer (not owned)
+ CallbackBase* mCallback{nullptr}; ///< The callback, has ownership.
};
/**
Name: dali2
Summary: DALi 3D Engine
-Version: 1.9.32
+Version: 1.9.34
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT