Files
ThirdParty-6/ParaView-5.0.1/ParaViewCore/ServerManager/Core/vtkSMProxySelectionModel.cxx

473 lines
15 KiB
C++

/*=========================================================================
Program: ParaView
Module: vtkSMProxySelectionModel.cxx
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.
=========================================================================*/
#include "vtkSMProxySelectionModel.h"
#include "vtkBoundingBox.h"
#include "vtkCollection.h"
#include "vtkCommand.h"
#include "vtkObjectFactory.h"
#include "vtkPVDataInformation.h"
#include "vtkPVSession.h"
#include "vtkSmartPointer.h"
#include "vtkSMCollaborationManager.h"
#include "vtkSMMessage.h"
#include "vtkSMOutputPort.h"
#include "vtkSMProxy.h"
#include "vtkSMProxyLocator.h"
#include "vtkSMSession.h"
#include "vtkSMSourceProxy.h"
#include "vtkSMTrace.h"
#include <vector>
#include <set>
#include <vtkNew.h>
//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkSMProxySelectionModel);
//-----------------------------------------------------------------------------
class vtkSMProxySelectionModel::vtkInternal
{
public:
unsigned int CollaborationManagerObserverID;
vtkSMProxySelectionModel* Owner;
bool FollowinMaster;
bool Initilized;
bool DisableSessionStatePush;
std::map<int, vtkSMMessage> ClientsCachedState;
vtkInternal(vtkSMProxySelectionModel* owner)
{
this->DisableSessionStatePush = false;
this->Owner = owner;
this->CollaborationManagerObserverID = 0;
this->FollowinMaster = true;
this->Initilized = false;
}
~vtkInternal()
{
if(this->Owner->Session && this->CollaborationManagerObserverID)
{
this->Owner->Session->GetCollaborationManager()->RemoveObserver(
this->CollaborationManagerObserverID);
}
this->CollaborationManagerObserverID = 0;
}
void MasterChangedCallBack( vtkObject* vtkNotUsed(src),
unsigned long vtkNotUsed(event),
void* vtkNotUsed(data))
{
if(this->FollowinMaster && this->GetMasterId() != -1 &&
this->ClientsCachedState.find(
this->GetMasterId()) != this->ClientsCachedState.end())
{
this->Owner->LoadState( &this->ClientsCachedState[this->GetMasterId()],
this->Owner->Session->GetProxyLocator());
this->Owner->PushStateToSession();
}
}
void ExportSelection(vtkCollection* src, vtkCollection* dst)
{
dst->RemoveAllItems();
src->InitTraversal();
while (vtkObject* obj = src->GetNextItemAsObject())
{
dst->AddItem(obj);
}
}
int GetMasterId()
{
if(!this->Owner->Session || !this->Owner->Session->GetCollaborationManager())
{
return -1;
}
return this->Owner->Session->GetCollaborationManager()->GetMasterId();
}
};
//-----------------------------------------------------------------------------
vtkSMProxySelectionModel::vtkSMProxySelectionModel()
{
this->Internal = new vtkSMProxySelectionModel::vtkInternal(this);
this->State = new vtkSMMessage();
this->SetLocation(vtkPVSession::CLIENT);
this->State->SetExtension(DefinitionHeader::server_class, "vtkSIObject"); // Dummy SIObject
}
//-----------------------------------------------------------------------------
vtkSMProxySelectionModel::~vtkSMProxySelectionModel()
{
delete this->Internal;
delete this->State;
}
//-----------------------------------------------------------------------------
vtkSMProxy* vtkSMProxySelectionModel::GetCurrentProxy()
{
return this->Current;
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::SetCurrentProxy(vtkSMProxy* proxy, int command)
{
if (this->Current != proxy)
{
SM_SCOPED_TRACE(SetCurrentProxy)
.arg("selmodel", this)
.arg("proxy", proxy)
.arg("command", command);
this->Internal->DisableSessionStatePush = true;
this->Current = proxy;
this->Select(proxy, command);
this->Internal->DisableSessionStatePush = false;
this->InvokeCurrentChanged(proxy);
}
}
//-----------------------------------------------------------------------------
bool vtkSMProxySelectionModel::IsSelected(vtkSMProxy* proxy)
{
return this->Selection.find(proxy) != this->Selection.end();
}
//-----------------------------------------------------------------------------
unsigned int vtkSMProxySelectionModel::GetNumberOfSelectedProxies()
{
return static_cast<unsigned int>(this->Selection.size());
}
//-----------------------------------------------------------------------------
vtkSMProxy* vtkSMProxySelectionModel::GetSelectedProxy(unsigned int idx)
{
if (idx < this->GetNumberOfSelectedProxies())
{
SelectionType::iterator iter = this->Selection.begin();
for (unsigned int cc=0; cc < idx; ++cc, ++iter)
{
}
return vtkSMProxy::SafeDownCast(iter->GetPointer());
}
return NULL;
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::Select(vtkSMProxy* proxy, int command)
{
SelectionType selection;
if (proxy)
{
selection.insert(proxy);
}
this->Select(selection, command);
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::Select(
const vtkSMProxySelectionModel::SelectionType& proxies, int command)
{
if (command == vtkSMProxySelectionModel::NO_UPDATE)
{
return;
}
SelectionType new_selection;
if (command & vtkSMProxySelectionModel::CLEAR)
{
// everything from old-selection needs to be removed.
}
else
{
// start with existing selection.
new_selection = this->Selection;
}
for (SelectionType::const_iterator iter = proxies.begin();
iter != proxies.end(); ++iter)
{
vtkSMProxy* proxy = iter->GetPointer();
if (proxy && (command & vtkSMProxySelectionModel::SELECT) !=0)
{
new_selection.insert(proxy);
}
if (proxy && (command & vtkSMProxySelectionModel::DESELECT) !=0)
{
new_selection.erase(proxy);
}
}
bool changed = (this->Selection != new_selection);
if (changed)
{
this->Selection = new_selection;
this->InvokeSelectionChanged();
}
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::InvokeCurrentChanged(vtkSMProxy* proxy)
{
this->InvokeEvent(vtkCommand::CurrentChangedEvent, proxy);
this->PushStateToSession();
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::InvokeSelectionChanged()
{
this->InvokeEvent(vtkCommand::SelectionChangedEvent);
this->PushStateToSession();
}
//-----------------------------------------------------------------------------
bool vtkSMProxySelectionModel::GetSelectionDataBounds(double bounds[6])
{
vtkBoundingBox bbox;
for (SelectionType::iterator iter = this->Selection.begin();
iter != this->Selection.end(); ++iter)
{
vtkSMProxy* proxy = iter->GetPointer();
vtkSMSourceProxy* source = vtkSMSourceProxy::SafeDownCast(proxy);
vtkSMOutputPort* opPort = vtkSMOutputPort::SafeDownCast(proxy);
if (source)
{
for (unsigned int kk=0; kk < source->GetNumberOfOutputPorts(); kk++)
{
bbox.AddBounds(source->GetDataInformation(kk)->GetBounds());
}
}
else if (opPort)
{
bbox.AddBounds(opPort->GetDataInformation()->GetBounds());
}
}
if (bbox.IsValid())
{
bbox.GetBounds(bounds);
return true;
}
return false;
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Current Proxy: "
<< (this->Current ? this->Current->GetGlobalIDAsString() : "NULL") << endl;
os << indent << "Selected Proxies: ";
for( SelectionType::iterator iter = this->Selection.begin();
iter != this->Selection.end(); iter++)
{
os << iter->GetPointer()->GetGlobalIDAsString() << " ";
}
os << endl;
}
//-----------------------------------------------------------------------------
const vtkSMMessage* vtkSMProxySelectionModel::GetFullState()
{
return this->State;
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::LoadState( const vtkSMMessage* msg, vtkSMProxyLocator* locator)
{
// Store in cache the state
this->Internal->ClientsCachedState[msg->client_id()] = *msg;
if(!this->HasGlobalID())
{
this->SetGlobalID(msg->global_id());
}
// Make sure we are loading the master state and we want to follow it.
// Otherwise don't try to load that state
// If we did not get initialized yet, we don't filter
if( this->Internal->GetMasterId() != -1 &&
!( !this->Internal->Initilized ||
(this->IsFollowingMaster() &&
this->Internal->GetMasterId() == static_cast<int>(msg->client_id()))))
{
return;
}
// Has we are going to load a state, we can consider to be initialized
this->Internal->Initilized = true;
// Load current proxy
vtkSMProxy* currentProxy = NULL;
if( msg->GetExtension(ProxySelectionModelState::current_proxy) != 0)
{
vtkTypeUInt32 currentProxyId =
msg->GetExtension(ProxySelectionModelState::current_proxy);
currentProxy = locator->LocateProxy(currentProxyId);
if(currentProxy)
{
if(msg->GetExtension(ProxySelectionModelState::current_port) != -1)
{
// We have to select an output port
vtkSMSourceProxy* source = vtkSMSourceProxy::SafeDownCast(currentProxy);
assert("Try to select an output port of a non source proxy" && source);
currentProxy =
source->GetOutputPort(
msg->GetExtension(ProxySelectionModelState::current_port));
}
}
else
{
// Switch to warning as the selected proxy could be simply removed by
// master when we finally decided to select it.
vtkWarningMacro(
"Did not find the CURRENT proxy for selection Model with ID: "
<< currentProxyId);
}
}
SelectionType new_selection;
// Load the proxy in the state
for(int i=0; i < msg->ExtensionSize(ProxySelectionModelState::proxy); i++)
{
vtkSMProxy* proxy =
locator->LocateProxy(msg->GetExtension(ProxySelectionModelState::proxy, i));
if(proxy)
{
if(msg->GetExtension(ProxySelectionModelState::port, i) != -1)
{
// We have to select an output port
vtkSMSourceProxy* source = vtkSMSourceProxy::SafeDownCast(proxy);
assert("Try to select an output port of a non source proxy" && source);
proxy = source->GetOutputPort(msg->GetExtension(ProxySelectionModelState::port, i));
}
// Just add the proxy in the set
new_selection.insert(proxy);
}
}
// Apply the state
bool tmp = this->IsLocalPushOnly();
this->EnableLocalPushOnly();
this->Select(new_selection, CLEAR_AND_SELECT);
this->SetCurrentProxy(currentProxy, new_selection.size() == 0 ? SELECT : NO_UPDATE);
if(!tmp) this->DisableLocalPushOnly();
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::PushStateToSession()
{
if(this->Internal->DisableSessionStatePush)
{
return;
}
// Update the local state and push to the session
this->State->ClearExtension(ProxySelectionModelState::current_proxy);
this->State->ClearExtension(ProxySelectionModelState::current_port);
this->State->ClearExtension(ProxySelectionModelState::proxy);
this->State->ClearExtension(ProxySelectionModelState::port);
// - Selection
for ( SelectionType::iterator iter = this->Selection.begin();
iter != this->Selection.end(); ++iter)
{
vtkSMProxy* obj = iter->GetPointer();
if (vtkSMOutputPort* port = vtkSMOutputPort::SafeDownCast(obj))
{
this->State->AddExtension( ProxySelectionModelState::proxy,
port->GetSourceProxy()->GetGlobalID());
this->State->AddExtension( ProxySelectionModelState::port,
port->GetPortIndex());
}
else
{
this->State->AddExtension(ProxySelectionModelState::proxy, obj->GetGlobalID());
this->State->AddExtension(ProxySelectionModelState::port, -1); // Not an outputport
}
}
// - Current
if ( this->Current )
{
if (vtkSMOutputPort* port = vtkSMOutputPort::SafeDownCast(this->Current.GetPointer()))
{
this->State->SetExtension( ProxySelectionModelState::current_proxy,
port->GetSourceProxy()->GetGlobalID());
this->State->SetExtension( ProxySelectionModelState::current_port,
port->GetPortIndex());
}
else
{
this->State->SetExtension( ProxySelectionModelState::current_proxy,
this->Current->GetGlobalID());
this->State->SetExtension( ProxySelectionModelState::current_port,
-1); // Not an outputport
}
}
// If we push our state we are correctly initialized
this->Internal->Initilized = true;
if(!this->IsLocalPushOnly() && this->GetSession())
{
this->PushState(this->State);
}
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::SetSession(vtkSMSession* session)
{
// Unregister observer if meaningful
if(this->Session && this->Internal->CollaborationManagerObserverID)
{
this->Session->GetCollaborationManager()->RemoveObserver(
this->Internal->CollaborationManagerObserverID);
this->Internal->CollaborationManagerObserverID = 0;
}
this->Superclass::SetSession(session);
if(this->Session && this->Session->GetCollaborationManager())
{
this->Internal->CollaborationManagerObserverID =
this->Session->GetCollaborationManager()->AddObserver(
vtkSMCollaborationManager::UpdateMasterUser, this->Internal,
&vtkSMProxySelectionModel::vtkInternal::MasterChangedCallBack);
}
}
//-----------------------------------------------------------------------------
void vtkSMProxySelectionModel::SetFollowingMaster(bool following)
{
this->Internal->FollowinMaster = following;
if(following)
{
this->Internal->MasterChangedCallBack(0,0,0);
}
}
//-----------------------------------------------------------------------------
bool vtkSMProxySelectionModel::IsFollowingMaster()
{
return this->Internal->FollowinMaster;
}