/*========================================================================= Program: Visualization Toolkit Module: vtkBalloonWidget.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkBalloonWidget.h" #include "vtkAssemblyPath.h" #include "vtkBalloonRepresentation.h" #include "vtkCommand.h" #include "vtkImageData.h" #include "vtkObjectFactory.h" #include "vtkPickingManager.h" #include "vtkProp.h" #include "vtkPropPicker.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkRendererCollection.h" #include "vtkStdString.h" #include "vtkWidgetCallbackMapper.h" #include "vtkWidgetEvent.h" #include #include vtkStandardNewMacro(vtkBalloonWidget); //-- Define the PIMPLd array of vtkProp and vtkString -- struct vtkBalloon { vtkStdString Text; vtkImageData* Image; vtkBalloon() : Image(nullptr) { } vtkBalloon(const vtkBalloon& balloon) : Text(balloon.Text) , Image(balloon.Image) { if (this->Image) { this->Image->Register(nullptr); } } vtkBalloon(vtkStdString* str, vtkImageData* img) { this->Text = *str; this->Image = img; if (this->Image) { this->Image->Register(nullptr); } } vtkBalloon(const char* str, vtkImageData* img) { this->Text = vtkStdString(str); this->Image = img; if (this->Image) { this->Image->Register(nullptr); } } ~vtkBalloon() { if (this->Image) { this->Image->UnRegister(nullptr); } } vtkBalloon& operator=(const vtkBalloon& balloon) { if (this == &balloon) { return *this; } this->Text = balloon.Text; // Don't leak if we already have an image. if (this->Image) { this->Image->UnRegister(nullptr); this->Image = nullptr; } this->Image = balloon.Image; if (this->Image) { this->Image->Register(nullptr); } return *this; } bool operator==(const vtkBalloon& balloon) const { if (this->Image == balloon.Image) { if (this->Text == balloon.Text) { return true; } } return false; } bool operator!=(const vtkBalloon& balloon) const { return !(*this == balloon); } }; class vtkPropMap : public std::map { }; typedef std::map::iterator vtkPropMapIterator; //------------------------------------------------------------------------------ vtkBalloonWidget::vtkBalloonWidget() { this->Picker = vtkPropPicker::New(); this->Picker->PickFromListOn(); this->CurrentProp = nullptr; this->PropMap = new vtkPropMap; } //------------------------------------------------------------------------------ vtkBalloonWidget::~vtkBalloonWidget() { this->Picker->Delete(); if (this->CurrentProp) { this->CurrentProp->Delete(); this->CurrentProp = nullptr; } this->PropMap->clear(); delete this->PropMap; } //------------------------------------------------------------------------------ void vtkBalloonWidget::SetEnabled(int enabling) { this->Superclass::SetEnabled(enabling); if (this->Interactor && this->Interactor->GetRenderWindow()) { this->SetCurrentRenderer( this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()); } if (!this->CurrentRenderer) { return; } if (enabling) { this->CreateDefaultRepresentation(); this->WidgetRep->SetRenderer(this->CurrentRenderer); this->WidgetRep->BuildRepresentation(); this->CurrentRenderer->AddViewProp(this->WidgetRep); } else { this->CurrentRenderer->RemoveViewProp(this->WidgetRep); this->SetCurrentRenderer(nullptr); } } //------------------------------------------------------------------------------ void vtkBalloonWidget::SetPicker(vtkAbstractPropPicker* picker) { if (picker == nullptr || picker == this->Picker) { return; } // Configure picker appropriately picker->PickFromListOn(); this->Picker->Delete(); this->Picker = picker; this->Picker->Register(this); this->UnRegisterPickers(); this->RegisterPickers(); this->Modified(); } //------------------------------------------------------------------------------ void vtkBalloonWidget::RegisterPickers() { vtkPickingManager* pm = this->GetPickingManager(); if (!pm) { return; } pm->AddPicker(this->Picker, this); } //------------------------------------------------------------------------------ void vtkBalloonWidget::CreateDefaultRepresentation() { if (!this->WidgetRep) { this->WidgetRep = vtkBalloonRepresentation::New(); } } //------------------------------------------------------------------------------ void vtkBalloonWidget::AddBalloon(vtkProp* prop, vtkStdString* str, vtkImageData* img) { assert(prop); vtkPropMapIterator iter = this->PropMap->find(prop); if (iter == this->PropMap->end() || (*this->PropMap)[prop] != vtkBalloon(str, img)) { (*this->PropMap)[prop] = vtkBalloon(str, img); this->Picker->DeletePickList(prop); // ensure only entered once this->Picker->AddPickList(prop); this->Modified(); } } //------------------------------------------------------------------------------ void vtkBalloonWidget::AddBalloon(vtkProp* prop, const char* str, vtkImageData* img) { vtkStdString s; if (str) { s = vtkStdString(str); } this->AddBalloon(prop, &s, img); } //------------------------------------------------------------------------------ void vtkBalloonWidget::RemoveBalloon(vtkProp* prop) { vtkPropMapIterator iter = this->PropMap->find(prop); if (iter != this->PropMap->end()) { this->PropMap->erase(iter); if (prop != nullptr) { this->Picker->DeletePickList(prop); } this->Modified(); } } //------------------------------------------------------------------------------ const char* vtkBalloonWidget::GetBalloonString(vtkProp* prop) { vtkPropMapIterator iter = this->PropMap->find(prop); if (iter != this->PropMap->end()) { return (*iter).second.Text.c_str(); } return nullptr; } //------------------------------------------------------------------------------ vtkImageData* vtkBalloonWidget::GetBalloonImage(vtkProp* prop) { vtkPropMapIterator iter = this->PropMap->find(prop); if (iter != this->PropMap->end()) { return (*iter).second.Image; } return nullptr; } //------------------------------------------------------------------------------ void vtkBalloonWidget::UpdateBalloonString(vtkProp* prop, const char* str) { vtkPropMapIterator iter = this->PropMap->find(prop); if (iter != this->PropMap->end()) { (*iter).second.Text = str; this->WidgetRep->Modified(); } } //------------------------------------------------------------------------------ void vtkBalloonWidget::UpdateBalloonImage(vtkProp* prop, vtkImageData* image) { vtkPropMapIterator iter = this->PropMap->find(prop); if (iter != this->PropMap->end()) { (*iter).second.Image = image; this->WidgetRep->Modified(); } } //------------------------------------------------------------------------------ int vtkBalloonWidget::SubclassHoverAction() { double e[2]; e[0] = static_cast(this->Interactor->GetEventPosition()[0]); e[1] = static_cast(this->Interactor->GetEventPosition()[1]); if (this->CurrentProp) { this->CurrentProp->UnRegister(this); this->CurrentProp = nullptr; } vtkAssemblyPath* path = this->GetAssemblyPath(e[0], e[1], 0., this->Picker); if (path != nullptr) { vtkPropMapIterator iter = this->PropMap->find(path->GetFirstNode()->GetViewProp()); if (iter != this->PropMap->end()) { this->CurrentProp = (*iter).first; this->CurrentProp->Register(this); reinterpret_cast(this->WidgetRep) ->SetBalloonText((*iter).second.Text); reinterpret_cast(this->WidgetRep) ->SetBalloonImage((*iter).second.Image); this->WidgetRep->StartWidgetInteraction(e); this->Render(); } } return 1; } //------------------------------------------------------------------------------ int vtkBalloonWidget::SubclassEndHoverAction() { double e[2]; e[0] = static_cast(this->Interactor->GetEventPosition()[0]); e[1] = static_cast(this->Interactor->GetEventPosition()[1]); this->WidgetRep->EndWidgetInteraction(e); this->Render(); return 1; } //------------------------------------------------------------------------------ void vtkBalloonWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Current Prop: "; if (this->CurrentProp) { os << this->CurrentProp << "\n"; } else { os << "(none)\n"; } os << indent << "Picker: " << this->Picker << "\n"; }