1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkFinitePlaneWidget.cxx
5 
6   Copyright (c)
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkFinitePlaneWidget.h"
16 #include "vtkCallbackCommand.h"
17 #include "vtkCommand.h"
18 #include "vtkEvent.h"
19 #include "vtkFinitePlaneRepresentation.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkRenderWindow.h"
22 #include "vtkRenderWindowInteractor.h"
23 #include "vtkRenderer.h"
24 #include "vtkWidgetCallbackMapper.h"
25 #include "vtkWidgetEvent.h"
26 #include "vtkWidgetEventTranslator.h"
27 
28 vtkStandardNewMacro(vtkFinitePlaneWidget);
29 
30 //------------------------------------------------------------------------------
vtkFinitePlaneWidget()31 vtkFinitePlaneWidget::vtkFinitePlaneWidget()
32 {
33   this->WidgetState = vtkFinitePlaneWidget::Start;
34   this->ManagesCursor = 1;
35 
36   // Define widget events
37   this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent, vtkWidgetEvent::Select,
38     this, vtkFinitePlaneWidget::SelectAction);
39   this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent,
40     vtkWidgetEvent::EndSelect, this, vtkFinitePlaneWidget::EndSelectAction);
41 
42   this->CallbackMapper->SetCallbackMethod(
43     vtkCommand::MouseMoveEvent, vtkWidgetEvent::Move, this, vtkFinitePlaneWidget::MoveAction);
44 }
45 
46 //------------------------------------------------------------------------------
47 vtkFinitePlaneWidget::~vtkFinitePlaneWidget() = default;
48 
49 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)50 void vtkFinitePlaneWidget::PrintSelf(ostream& os, vtkIndent indent)
51 {
52   this->Superclass::PrintSelf(os, indent);
53 }
54 
55 //------------------------------------------------------------------------------
SetRepresentation(vtkFinitePlaneRepresentation * r)56 void vtkFinitePlaneWidget::SetRepresentation(vtkFinitePlaneRepresentation* r)
57 {
58   this->Superclass::SetWidgetRepresentation(r);
59 }
60 
61 //------------------------------------------------------------------------------
SelectAction(vtkAbstractWidget * w)62 void vtkFinitePlaneWidget::SelectAction(vtkAbstractWidget* w)
63 {
64   // We are in a static method, cast to ourself
65   vtkFinitePlaneWidget* self = reinterpret_cast<vtkFinitePlaneWidget*>(w);
66 
67   // Get the event position
68   int X = self->Interactor->GetEventPosition()[0];
69   int Y = self->Interactor->GetEventPosition()[1];
70 
71   // We want to compute an orthogonal vector to the plane that has been selected
72   reinterpret_cast<vtkFinitePlaneRepresentation*>(self->WidgetRep)
73     ->SetInteractionState(vtkFinitePlaneRepresentation::Moving);
74   int interactionState = self->WidgetRep->ComputeInteractionState(X, Y);
75   self->UpdateCursorShape(interactionState);
76 
77   if (self->WidgetRep->GetInteractionState() == vtkFinitePlaneRepresentation::Outside)
78   {
79     return;
80   }
81 
82   // We are definitely selected
83   self->GrabFocus(self->EventCallbackCommand);
84   double eventPos[2];
85   eventPos[0] = static_cast<double>(X);
86   eventPos[1] = static_cast<double>(Y);
87   self->WidgetState = vtkFinitePlaneWidget::Active;
88   self->WidgetRep->StartWidgetInteraction(eventPos);
89 
90   self->EventCallbackCommand->SetAbortFlag(1);
91   self->StartInteraction();
92   self->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
93   self->Render();
94 }
95 
96 //------------------------------------------------------------------------------
MoveAction(vtkAbstractWidget * w)97 void vtkFinitePlaneWidget::MoveAction(vtkAbstractWidget* w)
98 {
99   vtkFinitePlaneWidget* self = reinterpret_cast<vtkFinitePlaneWidget*>(w);
100 
101   // So as to change the cursor shape when the mouse is poised over
102   // the widget. Unfortunately, this results in a few extra picks
103   // due to the cell picker. However given that its picking planes
104   // and the handles/arrows, this should be very quick
105   int X = self->Interactor->GetEventPosition()[0];
106   int Y = self->Interactor->GetEventPosition()[1];
107   int changed = 0;
108 
109   vtkFinitePlaneRepresentation* repr =
110     reinterpret_cast<vtkFinitePlaneRepresentation*>(self->WidgetRep);
111 
112   if (self->ManagesCursor && self->WidgetState != vtkFinitePlaneWidget::Active)
113   {
114     int oldInteractionState = repr->GetInteractionState();
115 
116     repr->SetInteractionState(vtkFinitePlaneRepresentation::Moving);
117     int state = self->WidgetRep->ComputeInteractionState(X, Y);
118     changed = self->UpdateCursorShape(state);
119     repr->SetInteractionState(oldInteractionState);
120     changed = (changed || state != oldInteractionState) ? 1 : 0;
121   }
122 
123   // See whether we're active
124   if (self->WidgetState == vtkFinitePlaneWidget::Start)
125   {
126     if (changed && self->ManagesCursor)
127     {
128       self->Render();
129     }
130     return;
131   }
132 
133   // Adjust the representation
134   double e[2];
135   e[0] = static_cast<double>(X);
136   e[1] = static_cast<double>(Y);
137   self->WidgetRep->WidgetInteraction(e);
138 
139   // Moving something
140   self->EventCallbackCommand->SetAbortFlag(1);
141   self->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
142   self->Render();
143 }
144 
145 //------------------------------------------------------------------------------
EndSelectAction(vtkAbstractWidget * w)146 void vtkFinitePlaneWidget::EndSelectAction(vtkAbstractWidget* w)
147 {
148   vtkFinitePlaneWidget* self = reinterpret_cast<vtkFinitePlaneWidget*>(w);
149 
150   if (self->WidgetState != vtkFinitePlaneWidget::Active ||
151     self->WidgetRep->GetInteractionState() == vtkFinitePlaneRepresentation::Outside)
152   {
153     return;
154   }
155 
156   // Return state to not selected
157   double e[2];
158   self->WidgetRep->EndWidgetInteraction(e);
159   self->WidgetState = vtkFinitePlaneWidget::Start;
160   self->ReleaseFocus();
161 
162   // Update cursor if managed
163   self->UpdateCursorShape(
164     reinterpret_cast<vtkFinitePlaneRepresentation*>(self->WidgetRep)->GetRepresentationState());
165 
166   self->EventCallbackCommand->SetAbortFlag(1);
167   self->EndInteraction();
168   self->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
169   self->Render();
170 }
171 
172 //------------------------------------------------------------------------------
CreateDefaultRepresentation()173 void vtkFinitePlaneWidget::CreateDefaultRepresentation()
174 {
175   if (!this->WidgetRep)
176   {
177     this->WidgetRep = vtkFinitePlaneRepresentation::New();
178   }
179 }
180 
181 //------------------------------------------------------------------------------
UpdateCursorShape(int state)182 int vtkFinitePlaneWidget::UpdateCursorShape(int state)
183 {
184   // So as to change the cursor shape when the mouse is poised over
185   // the widget.
186   if (this->ManagesCursor)
187   {
188     if (state == vtkFinitePlaneRepresentation::Outside)
189     {
190       return this->RequestCursorShape(VTK_CURSOR_DEFAULT);
191     }
192     else
193     {
194       return this->RequestCursorShape(VTK_CURSOR_HAND);
195     }
196   }
197 
198   return 0;
199 }
200