/*========================================================================= 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 "vtkCallbackCommand.h" #include "vtkCommand.h" #include "vtkEvent.h" #include "vtkHandleWidget.h" #include "vtkObjectFactory.h" #include "vtkPointHandleRepresentation3D.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRendererCollection.h" #include "vtkWidgetCallbackMapper.h" #include "vtkWidgetEvent.h" #include "vtkWidgetEventTranslator.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(vtkTypeBool 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); }