/*========================================================================= Program: Visualization Toolkit Module: vtkSliderWidget.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 "vtkSliderWidget.h" #include "vtkCallbackCommand.h" #include "vtkCommand.h" #include "vtkEvent.h" #include "vtkObjectFactory.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkSliderRepresentation3D.h" #include "vtkWidgetCallbackMapper.h" #include "vtkWidgetEvent.h" #include "vtkWidgetEventTranslator.h" vtkStandardNewMacro(vtkSliderWidget); //------------------------------------------------------------------------------ vtkSliderWidget::vtkSliderWidget() { // Set the initial state this->WidgetState = vtkSliderWidget::Start; // Assign initial values this->AnimationMode = vtkSliderWidget::Jump; this->NumberOfAnimationSteps = 24; // Okay, define the events this->CallbackMapper->SetCallbackMethod( vtkCommand::LeftButtonPressEvent, vtkWidgetEvent::Select, this, vtkSliderWidget::SelectAction); this->CallbackMapper->SetCallbackMethod( vtkCommand::MouseMoveEvent, vtkWidgetEvent::Move, this, vtkSliderWidget::MoveAction); this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent, vtkWidgetEvent::EndSelect, this, vtkSliderWidget::EndSelectAction); } //------------------------------------------------------------------------------ void vtkSliderWidget::CreateDefaultRepresentation() { if (!this->WidgetRep) { this->WidgetRep = vtkSliderRepresentation3D::New(); } } //------------------------------------------------------------------------------ void vtkSliderWidget::SelectAction(vtkAbstractWidget* w) { vtkSliderWidget* self = reinterpret_cast(w); double eventPos[2]; eventPos[0] = self->Interactor->GetEventPosition()[0]; eventPos[1] = self->Interactor->GetEventPosition()[1]; // Okay, make sure that the pick is in the current renderer if (!self->CurrentRenderer || !self->CurrentRenderer->IsInViewport( static_cast(eventPos[0]), static_cast(eventPos[1]))) { self->WidgetState = vtkSliderWidget::Start; return; } // See if the widget has been selected. StartWidgetInteraction records the // starting point of the motion. self->WidgetRep->StartWidgetInteraction(eventPos); int interactionState = self->WidgetRep->GetInteractionState(); if (interactionState == vtkSliderRepresentation::Outside) { return; } // We are definitely selected self->GrabFocus(self->EventCallbackCommand); if (interactionState == vtkSliderRepresentation::Slider) { self->WidgetState = vtkSliderWidget::Sliding; } else { self->WidgetState = vtkSliderWidget::Animating; } // Highlight as necessary self->WidgetRep->Highlight(1); // start the interaction self->EventCallbackCommand->SetAbortFlag(1); self->StartInteraction(); self->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr); self->Render(); } //------------------------------------------------------------------------------ void vtkSliderWidget::MoveAction(vtkAbstractWidget* w) { vtkSliderWidget* self = reinterpret_cast(w); // See whether we're active if (self->WidgetState == vtkSliderWidget::Start || self->WidgetState == vtkSliderWidget::Animating) { return; } // Definitely moving the slider, get the updated position double eventPos[2]; eventPos[0] = self->Interactor->GetEventPosition()[0]; eventPos[1] = self->Interactor->GetEventPosition()[1]; self->WidgetRep->WidgetInteraction(eventPos); // Interact, if desired self->EventCallbackCommand->SetAbortFlag(1); self->InvokeEvent(vtkCommand::InteractionEvent, nullptr); self->Render(); } //------------------------------------------------------------------------------ void vtkSliderWidget::EndSelectAction(vtkAbstractWidget* w) { vtkSliderWidget* self = reinterpret_cast(w); if (self->WidgetState == vtkSliderWidget::Start) { return; } // If animating we do it and return if (self->WidgetState == vtkSliderWidget::Animating) { self->AnimateSlider(self->WidgetRep->GetInteractionState()); } // Highlight if necessary self->WidgetRep->Highlight(0); // The state returns to unselected self->WidgetState = vtkSliderWidget::Start; self->ReleaseFocus(); // Complete interaction self->EventCallbackCommand->SetAbortFlag(1); self->EndInteraction(); self->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr); self->Render(); } //------------------------------------------------------------------------------ void vtkSliderWidget::AnimateSlider(int selectionState) { // Get the representation and grab some information vtkSliderRepresentation* sliderRep = reinterpret_cast(this->WidgetRep); // If the slider bead has been selected, then nothing happens if (selectionState == vtkSliderRepresentation::Outside || selectionState == vtkSliderRepresentation::Slider) { return; } // Depending on animation mode, we'll jump to the pick point or // animate towards it. double minValue = sliderRep->GetMinimumValue(); double maxValue = sliderRep->GetMaximumValue(); double pickedT = sliderRep->GetPickedT(); if (this->AnimationMode == vtkSliderWidget::Jump) { if (selectionState == vtkSliderRepresentation::Tube) { sliderRep->SetValue(minValue + pickedT * (maxValue - minValue)); } else if (selectionState == vtkSliderRepresentation::LeftCap) { sliderRep->SetValue(minValue); } else if (selectionState == vtkSliderRepresentation::RightCap) { sliderRep->SetValue(maxValue); } sliderRep->BuildRepresentation(); this->InvokeEvent(vtkCommand::InteractionEvent, nullptr); } else if (this->AnimationMode == vtkSliderWidget::Animate) { double targetValue = minValue, originalValue = sliderRep->GetValue(); if (selectionState == vtkSliderRepresentation::Tube) { targetValue = minValue + pickedT * (maxValue - minValue); } else if (selectionState == vtkSliderRepresentation::LeftCap) { targetValue = minValue; } else if (selectionState == vtkSliderRepresentation::RightCap) { targetValue = maxValue; } // Okay, animate the slider double value; for (int i = 0; i < this->NumberOfAnimationSteps; i++) { value = originalValue + (static_cast(i + 1) / this->NumberOfAnimationSteps) * (targetValue - originalValue); sliderRep->SetValue(value); sliderRep->BuildRepresentation(); this->InvokeEvent(vtkCommand::InteractionEvent, nullptr); this->Render(); } } this->WidgetState = vtkSliderWidget::Start; } //------------------------------------------------------------------------------ void vtkSliderWidget::PrintSelf(ostream& os, vtkIndent indent) { // Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h this->Superclass::PrintSelf(os, indent); os << indent << "Animation Mode: "; switch (this->AnimationMode) { case vtkSliderWidget::Jump: os << "Jump\n"; break; case vtkSliderWidget::Animate: os << "Animate\n"; break; default: os << "AnimateOff\n"; } os << indent << "Number of Animation Steps: " << this->NumberOfAnimationSteps << "\n"; }