// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkAnnotationLink.h" #include "vtkAnnotationLayers.h" #include "vtkCommand.h" #include "vtkDataObjectCollection.h" #include "vtkIdTypeArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkMultiBlockDataSet.h" #include "vtkObjectFactory.h" #include "vtkSelection.h" #include "vtkSmartPointer.h" #include "vtkTable.h" VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkAnnotationLink); // vtkCxxSetObjectMacro(vtkAnnotationLink, AnnotationLayers, vtkAnnotationLayers); //------------------------------------------------------------------------------ // vtkAnnotationLink::Command //------------------------------------------------------------------------------ class vtkAnnotationLink::Command : public vtkCommand { public: static Command* New() { return new Command(); } void Execute(vtkObject* caller, unsigned long eventId, void* callData) override { if (this->Target) { this->Target->ProcessEvents(caller, eventId, callData); } } void SetTarget(vtkAnnotationLink* t) { this->Target = t; } private: Command() { this->Target = nullptr; } vtkAnnotationLink* Target; }; //------------------------------------------------------------------------------ vtkAnnotationLink::vtkAnnotationLink() { this->SetNumberOfInputPorts(2); this->SetNumberOfOutputPorts(3); this->AnnotationLayers = vtkAnnotationLayers::New(); this->DomainMaps = vtkDataObjectCollection::New(); this->Observer = Command::New(); this->Observer->SetTarget(this); this->AnnotationLayers->AddObserver(vtkCommand::ModifiedEvent, this->Observer); } //------------------------------------------------------------------------------ vtkAnnotationLink::~vtkAnnotationLink() { this->Observer->Delete(); if (this->AnnotationLayers) { this->AnnotationLayers->Delete(); } if (this->DomainMaps) { this->DomainMaps->Delete(); } } //------------------------------------------------------------------------------ void vtkAnnotationLink::ProcessEvents( vtkObject* caller, unsigned long eventId, void* vtkNotUsed(callData)) { if (this->AnnotationLayers) { vtkAnnotationLayers* caller_annotations = vtkAnnotationLayers::SafeDownCast(caller); if (caller_annotations == this->AnnotationLayers && eventId == vtkCommand::ModifiedEvent) { this->InvokeEvent(vtkCommand::AnnotationChangedEvent, this->AnnotationLayers); } } } //------------------------------------------------------------------------------ void vtkAnnotationLink::SetAnnotationLayers(vtkAnnotationLayers* layers) { // This method is a cut and paste of vtkCxxSetObjectMacro // except that we listen for modified events from the annotations layers if (layers != this->AnnotationLayers) { vtkAnnotationLayers* tmp = this->AnnotationLayers; if (tmp) { tmp->RemoveObserver(this->Observer); } this->AnnotationLayers = layers; if (this->AnnotationLayers != nullptr) { this->AnnotationLayers->Register(this); this->AnnotationLayers->AddObserver(vtkCommand::ModifiedEvent, this->Observer); } if (tmp != nullptr) { tmp->UnRegister(this); } this->Modified(); this->InvokeEvent(vtkCommand::AnnotationChangedEvent, this->AnnotationLayers); } } //------------------------------------------------------------------------------ void vtkAnnotationLink::AddDomainMap(vtkTable* map) { if (this->DomainMaps->IndexOfFirstOccurrence(map) < 0) { this->DomainMaps->AddItem(map); } } //------------------------------------------------------------------------------ void vtkAnnotationLink::RemoveDomainMap(vtkTable* map) { this->DomainMaps->RemoveItem(map); } //------------------------------------------------------------------------------ void vtkAnnotationLink::RemoveAllDomainMaps() { if (this->DomainMaps->GetNumberOfItems() > 0) { this->DomainMaps->RemoveAllItems(); } } //------------------------------------------------------------------------------ int vtkAnnotationLink::GetNumberOfDomainMaps() { return this->DomainMaps->GetNumberOfItems(); } //------------------------------------------------------------------------------ vtkTable* vtkAnnotationLink::GetDomainMap(int i) { return vtkTable::SafeDownCast(this->DomainMaps->GetItem(i)); } //------------------------------------------------------------------------------ void vtkAnnotationLink::SetCurrentSelection(vtkSelection* sel) { if (this->AnnotationLayers) { this->AnnotationLayers->SetCurrentSelection(sel); } } //------------------------------------------------------------------------------ vtkSelection* vtkAnnotationLink::GetCurrentSelection() { if (this->AnnotationLayers) { return this->AnnotationLayers->GetCurrentSelection(); } return nullptr; } //------------------------------------------------------------------------------ int vtkAnnotationLink::RequestData(vtkInformation* vtkNotUsed(info), vtkInformationVector** inVector, vtkInformationVector* outVector) { vtkInformation* inInfo = inVector[0]->GetInformationObject(0); vtkTable* inputMap = vtkTable::GetData(inVector[1]); vtkAnnotationLayers* input = nullptr; vtkSelection* inputSelection = nullptr; if (inInfo) { input = vtkAnnotationLayers::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); inputSelection = vtkSelection::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); } vtkInformation* outInfo = outVector->GetInformationObject(0); vtkAnnotationLayers* output = vtkAnnotationLayers::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); vtkInformation* mapInfo = outVector->GetInformationObject(1); vtkMultiBlockDataSet* maps = vtkMultiBlockDataSet::SafeDownCast(mapInfo->Get(vtkDataObject::DATA_OBJECT())); vtkInformation* selInfo = outVector->GetInformationObject(2); vtkSelection* sel = vtkSelection::SafeDownCast(selInfo->Get(vtkDataObject::DATA_OBJECT())); // Give preference to input annotations if (input) { this->ShallowCopyToOutput(input, output, sel); } else if (this->AnnotationLayers) { this->ShallowCopyToOutput(this->AnnotationLayers, output, sel); } // If there is an input selection, set it on the annotation layers if (inputSelection) { sel->ShallowCopy(inputSelection); output->SetCurrentSelection(sel); } // If there are input domain maps, give preference to them if (inputMap) { vtkSmartPointer outMap = vtkSmartPointer::New(); outMap->ShallowCopy(inputMap); maps->SetBlock(0, outMap); } else { unsigned int numMaps = static_cast(this->DomainMaps->GetNumberOfItems()); maps->SetNumberOfBlocks(numMaps); for (unsigned int i = 0; i < numMaps; ++i) { vtkSmartPointer map = vtkSmartPointer::New(); map->ShallowCopy(this->DomainMaps->GetItem(i)); maps->SetBlock(i, map); } } this->CheckAbort(); return 1; } //------------------------------------------------------------------------------ void vtkAnnotationLink::ShallowCopyToOutput( vtkAnnotationLayers* input, vtkAnnotationLayers* output, vtkSelection* sel) { output->ShallowCopy(input); if (input->GetCurrentSelection()) { sel->ShallowCopy(input->GetCurrentSelection()); } } //------------------------------------------------------------------------------ int vtkAnnotationLink::FillInputPortInformation(int port, vtkInformation* info) { if (port == 0) { info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkAnnotationLayers"); info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkSelection"); return 1; } else if (port == 1) { info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); // info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable"); return 1; } return 0; } //------------------------------------------------------------------------------ int vtkAnnotationLink::FillOutputPortInformation(int port, vtkInformation* info) { if (port == 0) { info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkAnnotationLayers"); return 1; } else if (port == 1) { info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet"); return 1; } else if (port == 2) { info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkSelection"); return 1; } return 0; } //------------------------------------------------------------------------------ vtkMTimeType vtkAnnotationLink::GetMTime() { vtkMTimeType mtime = this->Superclass::GetMTime(); if (this->AnnotationLayers) { vtkMTimeType atime = this->AnnotationLayers->GetMTime(); mtime = std::max(atime, mtime); } if (this->DomainMaps) { vtkMTimeType dtime = this->DomainMaps->GetMTime(); mtime = std::max(dtime, mtime); } return mtime; } //------------------------------------------------------------------------------ void vtkAnnotationLink::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "AnnotationLayers: "; if (this->AnnotationLayers) { os << "\n"; this->AnnotationLayers->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)\n"; } os << indent << "DomainMaps: "; if (this->DomainMaps) { os << "\n"; this->DomainMaps->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)\n"; } } VTK_ABI_NAMESPACE_END