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

730 lines
21 KiB
C++

/*=========================================================================
Program: ParaView
Module: vtkSMProperty.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 "vtkSMProperty.h"
#include "vtkClientServerStream.h"
#include "vtkCommand.h"
#include "vtkObjectFactory.h"
#include "vtkProcessModule.h"
#include "vtkPVInstantiator.h"
#include "vtkPVXMLElement.h"
#include "vtkSmartPointer.h"
#include "vtkSMDocumentation.h"
#include "vtkSMDomain.h"
#include "vtkSMDomainIterator.h"
#include "vtkSMMessage.h"
#include "vtkSMProperty.h"
#include "vtkSMPropertyLink.h"
#include "vtkSMProxy.h"
#include <vector>
#include <sstream>
#include "vtkSMPropertyInternals.h"
vtkStandardNewMacro(vtkSMProperty);
vtkCxxSetObjectMacro(vtkSMProperty, InformationProperty, vtkSMProperty);
vtkCxxSetObjectMacro(vtkSMProperty, Documentation, vtkSMDocumentation);
vtkCxxSetObjectMacro(vtkSMProperty, Hints, vtkPVXMLElement);
//---------------------------------------------------------------------------
vtkSMProperty::vtkSMProperty()
{
this->StateIgnored = false;
this->Command = 0;
this->ImmediateUpdate = 0;
this->Animateable = 2; // By default Animateable in advanced mode only.
this->PInternals = new vtkSMPropertyInternals;
this->XMLName = 0;
this->XMLLabel = 0;
this->PanelVisibility = 0;
this->PanelVisibilityDefaultForRepresentation = 0;
this->PanelWidget = 0;
this->DomainIterator = vtkSMDomainIterator::New();
this->DomainIterator->SetProperty(this);
this->Proxy = 0;
this->InformationOnly = 0;
this->InformationProperty = 0;
this->IsInternal = 0;
this->NoCustomDefault = 0;
this->Documentation = 0;
this->Repeatable = 0;
this->IgnoreSynchronization = 0;
this->Links = NULL;
this->Hints = 0;
this->BlockModifiedEvents = false;
this->PendingModifiedEvents = false;
// by default, properties are set to show only in advanced mode
this->SetPanelVisibility("default");
this->Proxy = 0;
// Whenever the property fires UncheckedPropertyModifiedEvent, we update any
// dependent domains.
this->AddObserver(vtkCommand::UncheckedPropertyModifiedEvent,
this, &vtkSMProperty::UpdateDomains);
}
//---------------------------------------------------------------------------
vtkSMProperty::~vtkSMProperty()
{
this->RemoveFromSourceLink();
this->SetCommand(0);
delete this->PInternals;
this->SetXMLName(0);
this->SetXMLLabel(0);
this->DomainIterator->Delete();
this->SetInformationProperty(0);
this->SetDocumentation(0);
this->SetHints(0);
this->SetParent(0);
this->SetPanelVisibility(0);
this->SetPanelVisibilityDefaultForRepresentation(0);
this->SetPanelWidget(0);
if (this->Links)
{
this->Links->Delete();
this->Links = NULL;
}
}
//-----------------------------------------------------------------------------
// UnRegister is overloaded because the object has a reference to itself
// through the domain iterator.
void vtkSMProperty::UnRegister(vtkObjectBase* obj)
{
if (this->ReferenceCount == 2)
{
this->Superclass::UnRegister(obj);
vtkSMDomainIterator *tmp = this->DomainIterator;
tmp->Register(0);
tmp->SetProperty(0);
tmp->UnRegister(0);
return;
}
this->Superclass::UnRegister(obj);
}
//---------------------------------------------------------------------------
int vtkSMProperty::IsInDomains()
{
return this->IsInDomains(NULL);
}
//---------------------------------------------------------------------------
int vtkSMProperty::IsInDomains(vtkSMDomain** ptr)
{
this->DomainIterator->Begin();
while(!this->DomainIterator->IsAtEnd())
{
if (!this->DomainIterator->GetDomain()->IsInDomain(this))
{
if (ptr)
{
*ptr = this->DomainIterator->GetDomain();
}
return 0;
}
this->DomainIterator->Next();
}
return 1;
}
//---------------------------------------------------------------------------
void vtkSMProperty::AddDomain(const char* name, vtkSMDomain* domain)
{
// Check if the proxy already exists. If it does, we will
// replace it
vtkSMPropertyInternals::DomainMap::iterator it =
this->PInternals->Domains.find(name);
if (it != this->PInternals->Domains.end())
{
vtkWarningMacro("Domain " << name << " already exists. Replacing");
it->second->SetProperty(NULL);
}
this->PInternals->Domains[name] = domain;
if (domain)
{
domain->SetProperty(this); // doesn't change reference count.
domain->AddObserver(vtkCommand::DomainModifiedEvent,
this, &vtkSMProperty::InvokeDomainModifiedEvent);
}
}
//---------------------------------------------------------------------------
void vtkSMProperty::AddLinkedProperty(vtkSMProperty* targetProperty)
{
if (!targetProperty)
{
return;
}
// This sets up the target property to take on the value of this property
// whenever it is updated.
if (!this->Links)
{
this->Links = vtkSMPropertyLink::New();
this->Links->AddLinkedProperty(this->GetParent(), this->GetXMLName(), vtkSMLink::INPUT);
}
this->Links->AddLinkedProperty(targetProperty->GetParent(), targetProperty->GetXMLName(),
vtkSMLink::OUTPUT);
targetProperty->PInternals->LinkSourceProperty = this;
}
//---------------------------------------------------------------------------
void vtkSMProperty::RemoveLinkedProperty(vtkSMProperty* targetProperty)
{
if (!targetProperty || !this->Links)
{
return;
}
this->Links->RemoveLinkedProperty(targetProperty->GetParent(), targetProperty->GetXMLName());
}
//---------------------------------------------------------------------------
void vtkSMProperty::RemoveFromSourceLink()
{
if (this->PInternals->LinkSourceProperty)
{
// Remove this instance as a subscriber to the source proxy
this->PInternals->LinkSourceProperty->RemoveLinkedProperty(this);
this->PInternals->LinkSourceProperty = NULL;
}
}
//---------------------------------------------------------------------------
void vtkSMProperty::InvokeDomainModifiedEvent()
{
this->InvokeEvent(vtkCommand::DomainModifiedEvent);
}
//---------------------------------------------------------------------------
vtkSMDomain* vtkSMProperty::GetDomain(const char* name)
{
vtkSMPropertyInternals::DomainMap::iterator it =
this->PInternals->Domains.find(name);
if (it == this->PInternals->Domains.end())
{
return 0;
}
return it->second.GetPointer();
}
//---------------------------------------------------------------------------
vtkSMDomain* vtkSMProperty::FindDomain(const char* classname)
{
vtkSmartPointer<vtkSMDomainIterator> iter;
iter.TakeReference(this->NewDomainIterator());
for (iter->Begin(); !iter->IsAtEnd(); iter->Next())
{
if (iter->GetDomain()->IsA(classname))
{
return iter->GetDomain();
}
}
return 0;
}
//---------------------------------------------------------------------------
unsigned int vtkSMProperty::GetNumberOfDomains()
{
return static_cast<unsigned int>(this->PInternals->Domains.size());
}
//---------------------------------------------------------------------------
vtkSMDomainIterator* vtkSMProperty::NewDomainIterator()
{
vtkSMDomainIterator* iter = vtkSMDomainIterator::New();
iter->SetProperty(this);
return iter;
}
//---------------------------------------------------------------------------
void vtkSMProperty::AddDependent(vtkSMDomain* dom)
{
this->PInternals->Dependents.push_back(dom);
}
//---------------------------------------------------------------------------
void vtkSMProperty::RemoveAllDependents()
{
vtkSMPropertyInternals::DependentsVector::iterator iter =
this->PInternals->Dependents.begin();
for (; iter != this->PInternals->Dependents.end(); iter++)
{
iter->GetPointer()->RemoveRequiredProperty(this);
}
this->PInternals->Dependents.erase(
this->PInternals->Dependents.begin(), this->PInternals->Dependents.end());
}
//---------------------------------------------------------------------------
#if !defined(VTK_LEGACY_REMOVE)
void vtkSMProperty::UpdateDependentDomains()
{
}
#endif
//---------------------------------------------------------------------------
void vtkSMProperty::UpdateDomains()
{
// I genuinely doubt when a property changes, its domain should change!!
//// Update own domains
//this->DomainIterator->Begin();
//while(!this->DomainIterator->IsAtEnd())
// {
// this->DomainIterator->GetDomain()->Update(0);
// this->DomainIterator->Next();
// }
// Update other dependent domains
vtkSMPropertyInternals::DependentsVector::iterator iter =
this->PInternals->Dependents.begin();
for (; iter != this->PInternals->Dependents.end(); iter++)
{
iter->GetPointer()->Update(this);
}
}
//---------------------------------------------------------------------------
vtkSMProperty* vtkSMProperty::NewProperty(const char* name)
{
if (!this->Proxy)
{
return 0;
}
return this->Proxy->NewProperty(name);
}
//---------------------------------------------------------------------------
void vtkSMProperty::CreatePrettyLabel(const char* xmlname)
{
// Add space before every capital letter not preceeded by a capital letter
// or space hence:
// "MySpace" ==> "My Space"
// "MySPACE" ==> "My SPACE"
// "My Space" ==> "My Space"
int max = static_cast<int>(strlen(xmlname));
char* label = new char[2*max+10];
char* ptr = label;
bool previous_capital = false;
*ptr = xmlname[0];
ptr++;
for (int cc=1; cc < max; ++cc)
{
if (xmlname[cc] >= 'A' && xmlname[cc] <= 'Z')
{
if (!previous_capital && *(ptr-1) != ' ')
{
*ptr = ' ';
ptr++;
}
previous_capital = true;
}
else
{
previous_capital = false;
}
*ptr = xmlname[cc];
ptr++;
}
*ptr = 0;
this->SetXMLLabel(label);
delete [] label;
}
//---------------------------------------------------------------------------
int vtkSMProperty::ReadXMLAttributes(vtkSMProxy* proxy,
vtkPVXMLElement* element)
{
// TODO: some of the attributes are no longer necessary on the proxy-side,
// eg. "Command". We will remove those once we've verified that they are
// present on the PMProperty side.
const char* xmlname = element->GetAttribute("name");
if(xmlname)
{
this->SetXMLName(xmlname);
}
const char* xmllabel = element->GetAttribute("label");
if (xmllabel)
{
this->SetXMLLabel(xmllabel);
}
else
{
this->CreatePrettyLabel(xmlname);
}
const char* command = element->GetAttribute("command");
if(command)
{
this->SetCommand(command);
}
int repeatable;
int retVal = 1;
if( element->GetScalarAttribute("repeatable", &repeatable) ||
element->GetScalarAttribute("repeat_command", &repeatable))
{
this->Repeatable = repeatable;
}
const char* information_property =
element->GetAttribute("information_property");
if(information_property)
{
this->SetInformationProperty(this->NewProperty(information_property));
}
int immediate_update;
retVal = element->GetScalarAttribute("immediate_update", &immediate_update);
if(retVal)
{
this->SetImmediateUpdate(immediate_update);
}
int state_ignored;
retVal = element->GetScalarAttribute("state_ignored", &state_ignored);
if(retVal)
{
this->SetStateIgnored( state_ignored != 0 );
}
else
{
this->StateIgnoredOff(); // Default value
}
int information_only;
retVal = element->GetScalarAttribute("information_only", &information_only);
if(retVal)
{
this->SetInformationOnly(information_only);
}
int ignore_synch;
retVal = element->GetScalarAttribute("ignore_synchronization", &ignore_synch);
if(retVal)
{
this->SetIgnoreSynchronization(ignore_synch);
}
int animateable;
retVal = element->GetScalarAttribute("animateable", &animateable);
if (retVal)
{
this->SetAnimateable(animateable);
}
int is_internal;
if (element->GetScalarAttribute("is_internal", &is_internal))
{
this->SetIsInternal(is_internal);
}
int no_custom_default;
if (element->GetScalarAttribute("no_custom_default", &no_custom_default))
{
this->SetNoCustomDefault(no_custom_default);
}
const char *panel_visibility = element->GetAttribute("panel_visibility");
if(panel_visibility)
{
this->SetPanelVisibility(panel_visibility);
}
const char *panel_visibility_default_for_representation =
element->GetAttribute("panel_visibility_default_for_representation");
if(panel_visibility_default_for_representation)
{
this->SetPanelVisibilityDefaultForRepresentation(
panel_visibility_default_for_representation);
}
const char *panel_widget = element->GetAttribute("panel_widget");
if(panel_widget)
{
this->SetPanelWidget(panel_widget);
}
// Manage deprecated XML definition
int deprecated_attr_value;
if(element->GetScalarAttribute("update_self", &deprecated_attr_value))
{
std::ostringstream proxyXML;
element->GetParent()->PrintXML(proxyXML, vtkIndent(1));
vtkWarningMacro(<< "Attribute update_self is not managed anymore."
<< "It is deprecated. " << endl
<< "Please FIX the decalaration of the following Proxy."
<< endl << proxyXML.str().c_str());
}
// Read and create domains.
for(unsigned int i=0; i < element->GetNumberOfNestedElements(); ++i)
{
vtkPVXMLElement* domainEl = element->GetNestedElement(i);
// These are not domain elements.
if (strcmp(domainEl->GetName(),"Documentation") == 0)
{
vtkSMDocumentation* doc = vtkSMDocumentation::New();
doc->SetDocumentationElement(domainEl);
this->SetDocumentation(doc);
doc->Delete();
continue;
}
else if (strcmp(domainEl->GetName(), "Hints") == 0)
{
this->SetHints(domainEl);
continue;
}
else if ( std::string(domainEl->GetName()).find("InformationHelper") !=
std::string::npos)
{
// InformationHelper are used to extract information from VTK object
// therefore they are not used on the proxy side (SM).
continue;
}
else if ( std::string(domainEl->GetName()).find("StringArrayHelper") !=
std::string::npos)
{
// InformationHelper are used to extract information from VTK object
// therefore they are not used on the proxy side (SM).
continue;
}
// Everything else is assumed to be a domain element.
vtkObject* object = 0;
std::ostringstream name;
name << "vtkSM" << domainEl->GetName() << ends;
object = vtkPVInstantiator::CreateInstance(name.str().c_str());
if (object)
{
vtkSMDomain* domain = vtkSMDomain::SafeDownCast(object);
if (domain)
{
domain->SetSession(proxy->GetSession());
if (domain->ReadXMLAttributes(this, domainEl))
{
const char* dname = domainEl->GetAttribute("name");
if (dname)
{
domain->SetXMLName(dname);
this->AddDomain(dname, domain);
}
}
}
else
{
vtkErrorMacro("Object created (type: " << name.str().c_str()
<< ") is not of a recognized type.");
}
object->Delete();
}
else
{
vtkErrorMacro("Could not create object of type: " << name.str().c_str()
<< ". Did you specify wrong xml element?");
}
}
return 1;
}
//---------------------------------------------------------------------------
void vtkSMProperty::Copy(vtkSMProperty* )
{
}
//---------------------------------------------------------------------------
void vtkSMProperty::WriteTo(vtkSMMessage* msg)
{
ProxyState_Property *prop = msg->AddExtension(ProxyState::property);
prop->set_name(this->GetXMLName());
}
//---------------------------------------------------------------------------
bool vtkSMProperty::ResetToDomainDefaults(bool use_unchecked_values)
{
if (vtkProcessModule::GetProcessModule() &&
vtkProcessModule::GetProcessModule()->GetSymmetricMPIMode())
{
// when using symmetric mpi, we disable domains since they don't always have
// the most updated information.
return false;
}
this->DomainIterator->Begin();
while (!this->DomainIterator->IsAtEnd())
{
if (this->DomainIterator->GetDomain()->SetDefaultValues(this, use_unchecked_values))
{
return true;
}
this->DomainIterator->Next();
}
return false;
}
//---------------------------------------------------------------------------
void vtkSMProperty::ResetToDefault()
{
if (!this->ResetToDomainDefaults(false))
{
this->ResetToXMLDefaults();
}
}
//---------------------------------------------------------------------------
void vtkSMProperty::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Proxy: " << this->Proxy << endl;
os << indent << "Command: "
<< (this->Command ? this->Command : "(null)") << endl;
os << indent << "ImmediateUpdate:" << this->ImmediateUpdate << endl;
os << indent << "InformationOnly:" << this->InformationOnly << endl;
os << indent << "XMLName:"
<< (this->XMLName ? this->XMLName : "(null)") << endl;
os << indent << "XMLLabel: "
<< (this->XMLLabel? this->XMLLabel : "(null)") << endl;
os << indent << "InformationProperty: " << this->InformationProperty << endl;
os << indent << "Animateable: " << this->Animateable << endl;
os << indent << "Internal: " << this->IsInternal << endl;
os << indent << "Repeatable: " << this->Repeatable << endl;
os << indent << "Documentation: " << this->Documentation << endl;
os << indent << "Hints: " ;
if (this->Hints)
{
this->Hints->PrintSelf(os, indent);
}
else
{
os << "(none)" << endl;
}
if (this->Links)
{
os << indent << "Links: " << endl;
this->Links->PrintSelf(os, indent.GetNextIndent());
}
else
{
os << indent << "Links: none" << endl;
}
}
//---------------------------------------------------------------------------
void vtkSMProperty::SaveState(vtkPVXMLElement* parent,
const char* property_name, const char* uid,
int saveDomains/*=1*/)
{
vtkPVXMLElement* propertyElement = vtkPVXMLElement::New();
propertyElement->SetName("Property");
propertyElement->AddAttribute("name", property_name);
propertyElement->AddAttribute("id", uid);
this->SaveStateValues(propertyElement);
if (saveDomains)
{
this->SaveDomainState(propertyElement, uid);
}
parent->AddNestedElement(propertyElement);
propertyElement->Delete();
}
//---------------------------------------------------------------------------
void vtkSMProperty::SaveStateValues(vtkPVXMLElement* /*propertyElement*/)
{
// Concreate class should overide it !!!
}
//---------------------------------------------------------------------------
void vtkSMProperty::SaveDomainState(vtkPVXMLElement* propertyElement,
const char* uid)
{
this->DomainIterator->Begin();
while(!this->DomainIterator->IsAtEnd())
{
std::ostringstream dname;
dname << uid << "." << this->DomainIterator->GetKey() << ends;
this->DomainIterator->GetDomain()->SaveState(propertyElement,
dname.str().c_str());
this->DomainIterator->Next();
}
}
//---------------------------------------------------------------------------
int vtkSMProperty::LoadState(vtkPVXMLElement* propertyElement,
vtkSMProxyLocator* loader)
{
// Process the domains.
unsigned int numElems = propertyElement->GetNumberOfNestedElements();
for (unsigned int cc=0; cc < numElems; cc++)
{
vtkPVXMLElement* child = propertyElement->GetNestedElement(cc);
if (!child->GetName())
{
continue;
}
if (strcmp(child->GetName(),"Domain") == 0)
{
const char* name = child->GetAttribute("name");
vtkSMDomain* domain = name? this->GetDomain(name) : 0;
if (domain)
{
domain->LoadState(child, loader);
}
}
}
return 1;
}
//---------------------------------------------------------------------------
void vtkSMProperty::SetParent(vtkSMProxy *proxy)
{
this->Proxy = proxy;
}
//---------------------------------------------------------------------------
vtkSMProxy* vtkSMProperty::GetParent()
{
return this->Proxy.GetPointer();
}
//---------------------------------------------------------------------------
bool vtkSMProperty::HasDomainsWithRequiredProperties()
{
for (vtkSMPropertyInternals::DomainMap::iterator iter =
this->PInternals->Domains.begin();
iter != this->PInternals->Domains.end(); ++iter)
{
if (iter->second->GetNumberOfRequiredProperties() > 0)
{
return true;
}
}
return false;
}