Files
ThirdParty-6/ParaView-5.0.1/ParaViewCore/ServerManager/Core/vtkSMProxyPropertyInternals.h

404 lines
13 KiB
C++

/*=========================================================================
Program: ParaView
Module: vtkSMProxyPropertyInternals.h
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#ifndef vtkSMProxyPropertyInternals_h
#define vtkSMProxyPropertyInternals_h
#include "vtkCommand.h"
#include "vtkSmartPointer.h"
#include "vtkSMMessage.h"
#include "vtkSMObject.h"
#include "vtkSMProxy.h"
#include "vtkSMProxyLocator.h"
#include "vtkSMSession.h"
#include "vtkWeakPointer.h"
#include <algorithm>
#include <map>
#include <set>
#include <vector>
/// This class is used by vtkSMProxyProperty to keep track of the proxies. It
/// keeps proxies as well as output port information which is needed for
/// vtkSMInputProperty. That makes it easier and less error prone to keep the
/// number of ports and proxies in sync and correctly check when values are
/// modified.
class vtkSMProxyProperty::vtkPPInternals
{
public:
typedef std::vector<vtkSmartPointer<vtkSMProxy> > SmartVectorOfProxies;
typedef std::vector<vtkWeakPointer<vtkSMProxy> > WeakVectorOfProxies;
typedef std::vector<unsigned int> VectorOfUInts;
private:
vtkWeakPointer<vtkSMProxyProperty> Self;
SmartVectorOfProxies Proxies;
SmartVectorOfProxies PreviousProxies; // < These are used to remove observers
// and break producer/consumer links
// whenever the value is changed.
WeakVectorOfProxies UncheckedProxies;
VectorOfUInts Ports;
VectorOfUInts PreviousPorts;
VectorOfUInts UncheckedPorts;
std::map<void*, unsigned long> ObserverIds;
private:
void UpdateProducerConsumerLinks()
{
if (this->Self == NULL ||
this->Self->GetSkipDependency() == true ||
this->Self->GetParent() == NULL ||
this->PreviousProxies == this->Proxies)
{
return;
}
vtkSMProxyProperty* self = this->Self;
// create sets for each.
typedef std::set<vtkSMProxy*> proxy_set;
proxy_set previous_proxies(
this->PreviousProxies.begin(), this->PreviousProxies.end());
proxy_set proxies(
this->Proxies.begin(), this->Proxies.end());
proxy_set removed;
std::set_difference(previous_proxies.begin(), previous_proxies.end(),
proxies.begin(), proxies.end(),
std::insert_iterator<proxy_set>(removed, removed.begin()));
for (proxy_set::iterator iter = removed.begin(); iter != removed.end(); ++iter)
{
vtkSMProxy* producer = (*iter);
if (producer)
{
// remove observer.
producer->RemoveObserver(this->ObserverIds[producer]);
this->ObserverIds.erase(producer);
// break producer/consumer link.
producer->RemoveConsumer(self, self->GetParent());
self->GetParent()->RemoveProducer(self, producer);
}
}
removed.clear();
proxy_set added;
std::set_difference(proxies.begin(), proxies.end(),
previous_proxies.begin(), previous_proxies.end(),
std::insert_iterator<proxy_set>(added, added.begin()));
for (proxy_set::iterator iter = added.begin(); iter != added.end(); ++iter)
{
vtkSMProxy* producer = (*iter);
if (producer)
{
// observe UpdateDataEvent, so we can update dependent domains when the
// data changes.
this->ObserverIds[producer] = producer->AddObserver(
vtkCommand::UpdateDataEvent, self, &vtkSMProxyProperty::OnUpdateDataEvent);
// add producer/consumer link.
producer->AddConsumer(self, self->GetParent());
self->GetParent()->AddProducer(self, producer);
}
}
this->PreviousProxies = this->Proxies;
}
bool CheckedValueChanged()
{
this->ClearUnchecked();
this->UpdateProducerConsumerLinks();
return true;
}
public:
vtkPPInternals(vtkSMProxyProperty* self) : Self(self)
{
}
//====================================================================================
// ** All methods return true if the "datastructure" was modified, false otherwise
// ** The key thing to keep in mind is whenever the "checked" value is
// ** changed, "unchecked" value must be cleared and the producer/consumer
// ** links must be corrected.
//====================================================================================
// Add a proxy/port to the unchecked list. Returns true if value modified.
bool AddUnchecked(vtkSMProxy* proxy, unsigned int port=0)
{
this->UncheckedProxies.push_back(proxy);
this->UncheckedPorts.push_back(port);
return true;
}
//------------------------------------------------------------------------------------
// Add a proxy/port to the list and clear any unchecked values. Returns true if value modified.
bool Add(vtkSMProxy* proxy, unsigned int port=0)
{
this->Proxies.push_back(proxy);
this->Ports.push_back(port);
return this->CheckedValueChanged();
}
//------------------------------------------------------------------------------------
bool Remove(vtkSMProxy* proxy)
{
SmartVectorOfProxies::iterator iter = this->Proxies.begin();
VectorOfUInts::iterator iter2 = this->Ports.begin();
for (;iter != this->Proxies.end() && iter2 != this->Ports.end(); ++iter, ++iter2)
{
if (iter->GetPointer() == proxy)
{
this->Proxies.erase(iter);
this->Ports.erase(iter2);
return this->CheckedValueChanged();
}
}
return false;
}
//------------------------------------------------------------------------------------
bool Resize(unsigned int count)
{
if (this->Proxies.size() != count)
{
this->Proxies.resize(count);
this->Ports.resize(count);
return this->CheckedValueChanged();
}
return false;
}
//------------------------------------------------------------------------------------
bool ResizeUnchecked(unsigned int count)
{
if (this->UncheckedProxies.size() != count)
{
this->UncheckedProxies.resize(count);
this->UncheckedPorts.resize(count);
return true;
}
return false;
}
//------------------------------------------------------------------------------------
bool Clear()
{
if (this->Proxies.size() > 0)
{
this->Proxies.clear();
this->Ports.clear();
return this->CheckedValueChanged();
}
return false;
}
//------------------------------------------------------------------------------------
bool ClearUnchecked()
{
if (this->UncheckedProxies.size() > 0)
{
this->UncheckedProxies.clear();
this->UncheckedPorts.clear();
return true;
}
return false;
}
//------------------------------------------------------------------------------------
bool Set(unsigned int index, vtkSMProxy* proxy, unsigned int port=0)
{
if (static_cast<unsigned int>(this->Proxies.size()) > index &&
this->Proxies[index] == proxy &&
this->Ports[index] == port)
{
return false;
}
if (static_cast<unsigned int>(this->Proxies.size()) <= index)
{
this->Proxies.resize(index+1);
this->Ports.resize(index+1);
}
this->Proxies[index] = proxy;
this->Ports[index] = port;
return this->CheckedValueChanged();
}
//------------------------------------------------------------------------------------
bool SetUnchecked(unsigned int index, vtkSMProxy* proxy, unsigned int port=0)
{
if (static_cast<unsigned int>(this->UncheckedProxies.size()) > index &&
this->UncheckedProxies[index] == proxy &&
this->UncheckedPorts[index] == port)
{
return false;
}
if (static_cast<unsigned int>(this->UncheckedProxies.size()) <= index)
{
this->UncheckedProxies.resize(index+1);
this->UncheckedPorts.resize(index+1);
}
this->UncheckedProxies[index] = proxy;
this->UncheckedPorts[index] = port;
return true;
}
//------------------------------------------------------------------------------------
bool Set(unsigned int count, vtkSMProxy** proxies, const unsigned int* ports=NULL)
{
SmartVectorOfProxies newValues(proxies, proxies+count);
VectorOfUInts newPorts;
if (ports)
{
newPorts.insert(newPorts.end(), ports, ports+count);
}
else
{
newPorts.resize(count);
}
if (this->Proxies != newValues ||
this->Ports != newPorts)
{
this->Proxies = newValues;
this->Ports = newPorts;
return this->CheckedValueChanged();
}
return false;
}
//------------------------------------------------------------------------------------
bool SetProxies(const SmartVectorOfProxies& otherProxies, const VectorOfUInts& otherPorts)
{
if (this->Proxies != otherProxies || this->Ports != otherPorts)
{
this->Proxies = otherProxies;
this->Ports = otherPorts;
return this->CheckedValueChanged();
}
return false;
}
//------------------------------------------------------------------------------------
bool SetUncheckedProxies(const WeakVectorOfProxies& otherProxies,
const VectorOfUInts& otherPorts)
{
if (this->UncheckedProxies != otherProxies || this->UncheckedPorts != otherPorts)
{
this->UncheckedProxies = otherProxies;
this->UncheckedPorts = otherPorts;
return true;
}
return false;
}
//------------------------------------------------------------------------------------
// Get methods.
//------------------------------------------------------------------------------------
bool IsAdded(vtkSMProxy* proxy)
{
SmartVectorOfProxies::iterator iter = std::find(
this->Proxies.begin(), this->Proxies.end(), proxy);
return (iter != this->Proxies.end());
}
//------------------------------------------------------------------------------------
const SmartVectorOfProxies& GetProxies() const { return this->Proxies; }
const WeakVectorOfProxies& GetUncheckedProxies() const { return this->UncheckedProxies; }
const VectorOfUInts& GetPorts() const { return this->Ports; }
const VectorOfUInts& GetUncheckedPorts() const { return this->UncheckedPorts; }
//------------------------------------------------------------------------------------
vtkSMProxy* Get(unsigned int index) const
{
return (index < static_cast<unsigned int>(this->Proxies.size())?
this->Proxies[index].GetPointer() : NULL);
}
//------------------------------------------------------------------------------------
vtkSMProxy* GetUnchecked(unsigned int index) const
{
if (this->UncheckedProxies.size() > 0)
{
return (index < static_cast<unsigned int>(this->UncheckedProxies.size())?
this->UncheckedProxies[index].GetPointer() : NULL);
}
return this->Get(index);
}
unsigned int GetPort(unsigned int index) const
{
return (index < static_cast<unsigned int>(this->Ports.size())?
this->Ports[index] : 0);
}
unsigned int GetUncheckedPort(unsigned int index) const
{
if (this->UncheckedPorts.size() > 0)
{
return (index < static_cast<unsigned int>(this->UncheckedPorts.size())?
this->UncheckedPorts[index] : 0);
}
return this->GetPort(index);
}
//------------------------------------------------------------------------------------
// Serialization methods.
//------------------------------------------------------------------------------------
bool WriteTo(paraview_protobuf::Variant* variant) const
{
variant->set_type(Variant::INPUT); // or PROXY?
for (SmartVectorOfProxies::const_iterator iter = this->Proxies.begin();
iter != this->Proxies.end(); ++iter)
{
if (vtkSMProxy* proxy = iter->GetPointer())
{
proxy->CreateVTKObjects();
variant->add_proxy_global_id(proxy->GetGlobalID());
}
else
{
variant->add_proxy_global_id(0);
}
}
for (VectorOfUInts::const_iterator iter = this->Ports.begin();
iter != this->Ports.end(); ++iter)
{
variant->add_port_number(*iter);
}
return true;
}
bool ReadFrom(const paraview_protobuf::Variant& variant, vtkSMProxyLocator* locator)
{
SmartVectorOfProxies proxies;
VectorOfUInts ports;
assert(variant.proxy_global_id_size() == variant.port_number_size());
for (int cc=0, max = variant.proxy_global_id_size(); cc<max; cc++)
{
vtkTypeUInt32 gid = variant.proxy_global_id(cc);
unsigned int port = variant.port_number(cc);
// either ask the locator for the proxy, or find an existing one.
vtkSMProxy* proxy = NULL;
if (locator && vtkSMProxyProperty::CanCreateProxy())
{
proxy = locator->LocateProxy(gid);
}
else
{
proxy = vtkSMProxy::SafeDownCast(
this->Self->GetParent()->GetSession()->GetRemoteObject(gid));
}
if (proxy != NULL || gid == 0)
{
proxies.push_back(proxy);
ports.push_back(port);
}
}
return this->SetProxies(proxies, ports);
}
};
#endif
// VTK-HeaderTest-Exclude: vtkSMProxyPropertyInternals.h