/*========================================================================= Program: Visualization Toolkit Module: vtkAxesTransformWidget.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 "vtkAxesTransformWidget.h" #include "vtkAxesTransformRepresentation.h" #include "vtkPointHandleRepresentation3D.h" #include "vtkHandleWidget.h" #include "vtkCommand.h" #include "vtkCallbackCommand.h" #include "vtkRendererCollection.h" #include "vtkRenderWindowInteractor.h" #include "vtkObjectFactory.h" #include "vtkWidgetEventTranslator.h" #include "vtkWidgetCallbackMapper.h" #include "vtkEvent.h" #include "vtkWidgetEvent.h" #include "vtkRenderWindow.h" vtkStandardNewMacro(vtkAxesTransformWidget); //---------------------------------------------------------------------------- vtkAxesTransformWidget::vtkAxesTransformWidget() { this->WidgetState = vtkAxesTransformWidget::Start; this->ManagesCursor = 1; this->CurrentHandle = 0; // The widgets for moving the end points. They observe this widget (i.e., // this widget is the parent to the handles). this->OriginWidget = vtkHandleWidget::New(); this->OriginWidget->SetPriority(this->Priority-0.01); this->OriginWidget->SetParent(this); this->OriginWidget->ManagesCursorOff(); this->SelectionWidget = vtkHandleWidget::New(); this->SelectionWidget->SetPriority(this->Priority-0.01); this->SelectionWidget->SetParent(this); this->SelectionWidget->ManagesCursorOff(); // Define widget events this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent, vtkWidgetEvent::Select, this, vtkAxesTransformWidget::SelectAction); this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent, vtkWidgetEvent::EndSelect, this, vtkAxesTransformWidget::EndSelectAction); this->CallbackMapper->SetCallbackMethod(vtkCommand::MouseMoveEvent, vtkWidgetEvent::Move, this, vtkAxesTransformWidget::MoveAction); } //---------------------------------------------------------------------------- vtkAxesTransformWidget::~vtkAxesTransformWidget() { this->OriginWidget->Delete(); this->SelectionWidget->Delete(); } //---------------------------------------------------------------------- void vtkAxesTransformWidget::SetEnabled(int enabling) { // We defer enabling the handles until the selection process begins if ( enabling ) { if ( ! this->CurrentRenderer ) { int X=this->Interactor->GetEventPosition()[0]; int Y=this->Interactor->GetEventPosition()[1]; this->SetCurrentRenderer(this->Interactor->FindPokedRenderer(X,Y)); if (this->CurrentRenderer == nullptr) { return; } } // Don't actually turn these on until cursor is near the end points or the line. this->CreateDefaultRepresentation(); vtkHandleRepresentation * originRep = reinterpret_cast (this->WidgetRep)->GetOriginRepresentation(); originRep->SetRenderer(this->CurrentRenderer); this->OriginWidget->SetRepresentation(originRep); this->OriginWidget->SetInteractor(this->Interactor); vtkHandleRepresentation * selectionRep = reinterpret_cast (this->WidgetRep)->GetSelectionRepresentation(); selectionRep->SetRenderer(this->CurrentRenderer); this->SelectionWidget->SetRepresentation(selectionRep); this->SelectionWidget->SetInteractor(this->Interactor); // We do this step first because it sets the CurrentRenderer this->Superclass::SetEnabled(enabling); } else { this->OriginWidget->SetEnabled(0); this->SelectionWidget->SetEnabled(0); } } //---------------------------------------------------------------------- void vtkAxesTransformWidget::SelectAction(vtkAbstractWidget *w) { vtkAxesTransformWidget *self = reinterpret_cast(w); if ( self->WidgetRep->GetInteractionState() == vtkAxesTransformRepresentation::Outside ) { return; } // Get the event position int X = self->Interactor->GetEventPosition()[0]; int Y = self->Interactor->GetEventPosition()[1]; // We are definitely selected self->WidgetState = vtkAxesTransformWidget::Active; self->GrabFocus(self->EventCallbackCommand); double e[2]; e[0] = static_cast(X); e[1] = static_cast(Y); reinterpret_cast(self->WidgetRep)-> StartWidgetInteraction(e); self->InvokeEvent(vtkCommand::LeftButtonPressEvent,nullptr); //for the handles self->StartInteraction(); self->InvokeEvent(vtkCommand::StartInteractionEvent,nullptr); self->EventCallbackCommand->SetAbortFlag(1); } //---------------------------------------------------------------------- void vtkAxesTransformWidget::MoveAction(vtkAbstractWidget *w) { vtkAxesTransformWidget *self = reinterpret_cast(w); // compute some info we need for all cases int X = self->Interactor->GetEventPosition()[0]; int Y = self->Interactor->GetEventPosition()[1]; // See whether we're active if ( self->WidgetState == vtkAxesTransformWidget::Start ) { self->Interactor->Disable(); //avoid extra renders self->OriginWidget->SetEnabled(0); self->SelectionWidget->SetEnabled(0); int oldState = self->WidgetRep->GetInteractionState(); int state = self->WidgetRep->ComputeInteractionState(X,Y); int changed; // Determine if we are near the end points or the line if ( state == vtkAxesTransformRepresentation::Outside ) { changed = self->RequestCursorShape(VTK_CURSOR_DEFAULT); } else //must be near something { changed = self->RequestCursorShape(VTK_CURSOR_HAND); if ( state == vtkAxesTransformRepresentation::OnOrigin ) { self->OriginWidget->SetEnabled(1); } else //if ( state == vtkAxesTransformRepresentation::OnXXX ) { self->SelectionWidget->SetEnabled(1); changed = 1; //movement along the line always needs render } } self->Interactor->Enable(); //avoid extra renders if ( changed || oldState != state ) { self->Render(); } } else //if ( self->WidgetState == vtkAxesTransformWidget::Active ) { // moving something double e[2]; e[0] = static_cast(X); e[1] = static_cast(Y); self->InvokeEvent(vtkCommand::MouseMoveEvent,nullptr); //handles observe this reinterpret_cast(self->WidgetRep)-> WidgetInteraction(e); self->InvokeEvent(vtkCommand::InteractionEvent,nullptr); self->EventCallbackCommand->SetAbortFlag(1); self->Render(); } } //---------------------------------------------------------------------- void vtkAxesTransformWidget::EndSelectAction(vtkAbstractWidget *w) { vtkAxesTransformWidget *self = reinterpret_cast(w); if ( self->WidgetState == vtkAxesTransformWidget::Start ) { return; } // Return state to not active self->WidgetState = vtkAxesTransformWidget::Start; self->ReleaseFocus(); self->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,nullptr); //handles observe this self->EventCallbackCommand->SetAbortFlag(1); self->InvokeEvent(vtkCommand::EndInteractionEvent,nullptr); self->Superclass::EndInteraction(); self->Render(); } //---------------------------------------------------------------------- void vtkAxesTransformWidget::CreateDefaultRepresentation() { if ( ! this->WidgetRep ) { this->WidgetRep = vtkAxesTransformRepresentation::New(); } } //---------------------------------------------------------------------------- void vtkAxesTransformWidget::SetProcessEvents(int pe) { this->Superclass::SetProcessEvents(pe); this->OriginWidget->SetProcessEvents(pe); this->SelectionWidget->SetProcessEvents(pe); } //---------------------------------------------------------------------------- void vtkAxesTransformWidget::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); }