Program Listing for File vtkMRMLLayerDMObjectEventObserver.cxx
↰ Return to documentation for file (MRML/vtkMRMLLayerDMObjectEventObserver.cxx)
#include "vtkMRMLLayerDMObjectEventObserver.h"
// VTK includes
#include <vtkCallbackCommand.h>
#include <vtkObjectFactory.h>
vtkStandardNewMacro(vtkMRMLLayerDMObjectEventObserver);
template <class... Ts>
struct Overloaded : Ts...
{
using Ts::operator()...;
};
template <class... Ts>
Overloaded(Ts...) -> Overloaded<Ts...>;
vtkMRMLLayerDMObjectEventObserver::vtkMRMLLayerDMObjectEventObserver()
: m_updateCommand(vtkSmartPointer<vtkCallbackCommand>::New())
, m_isBlocked(false)
{
this->m_updateCommand->SetClientData(this);
this->m_updateCommand->SetCallback(
[](vtkObject* caller, unsigned long eid, void* clientData, void* callData)
{
auto client = static_cast<vtkMRMLLayerDMObjectEventObserver*>(clientData);
if (client->m_isBlocked)
{
return;
}
try
{
// Dispatch to callback depending on current std variant content
std::visit(Overloaded{ [&](const std::function<void(vtkObject * node)>& f) { f(caller); },
[&](const std::function<void(vtkObject * node, unsigned long eventId)>& f) { f(caller, eid); },
[&](const std::function<void(vtkObject * node, unsigned long eventId, void* callData)>& f) { f(caller, eid, callData); } },
client->m_callback);
}
catch (const std::bad_function_call&)
{
// Ignore unset function callbacks
}
});
}
vtkMRMLLayerDMObjectEventObserver::~vtkMRMLLayerDMObjectEventObserver()
{
for (const auto& obs : m_obsMap)
{
if (obs.first)
{
for (auto& event : obs.second)
{
obs.first->RemoveObserver(event);
}
}
}
}
bool vtkMRMLLayerDMObjectEventObserver::UpdateObserver(vtkObject* prevObj, vtkObject* obj, unsigned long event)
{
return this->UpdateObserver(prevObj, obj, std::vector<unsigned long>{ event });
}
bool vtkMRMLLayerDMObjectEventObserver::UpdateObserver(vtkObject* prevObj, vtkObject* obj, const std::vector<unsigned long>& events)
{
if (prevObj == obj)
{
return false;
}
this->RemoveObserver(prevObj);
for (const auto& event : events)
{
this->AddObserver(obj, event);
}
return true;
}
void vtkMRMLLayerDMObjectEventObserver::SetUpdateCallback(const std::function<void(vtkObject* node)>& callback)
{
this->m_callback = callback;
}
bool vtkMRMLLayerDMObjectEventObserver::SetBlocked(bool isBlocked)
{
bool wasBlocked = this->m_isBlocked;
this->m_isBlocked = isBlocked;
return wasBlocked;
}
void vtkMRMLLayerDMObjectEventObserver::SetUpdateCallback(const std::function<void(vtkObject* node, unsigned long eventId)>& callback)
{
this->m_callback = callback;
}
void vtkMRMLLayerDMObjectEventObserver::SetUpdateCallback(const std::function<void(vtkObject* node, unsigned long eventId, void* callData)>& callback)
{
this->m_callback = callback;
}
void vtkMRMLLayerDMObjectEventObserver::AddObserver(vtkObject* node, unsigned long event)
{
if (!node)
{
return;
}
if (this->m_obsMap.find(node) == std::end(this->m_obsMap))
{
this->m_obsMap[node] = std::set<unsigned long>{};
}
if (this->m_obsMap[node].find(event) != std::end(this->m_obsMap[node]))
{
return;
}
this->m_obsMap[node].insert(node->AddObserver(event, this->m_updateCommand));
}
void vtkMRMLLayerDMObjectEventObserver::RemoveObserver(vtkObject* node)
{
if (!node || this->m_obsMap.find(node) == std::end(this->m_obsMap))
{
return;
}
for (auto& event : m_obsMap[node])
{
node->RemoveObserver(event);
}
this->m_obsMap.erase(node);
}
vtkMRMLLayerDMObjectEventObserver::UpdateGuard::UpdateGuard(vtkMRMLLayerDMObjectEventObserver* obs)
: m_obs(obs)
{
if (m_obs)
{
m_wasBlocked = m_obs->SetBlocked(true);
}
}
vtkMRMLLayerDMObjectEventObserver::UpdateGuard::~UpdateGuard()
{
if (m_obs)
{
m_obs->SetBlocked(m_wasBlocked);
}
}