1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkAngleWidget.cxx,v
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
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 "vtkAngleWidget.h"
16 #include "vtkAngleRepresentation2D.h"
17 #include "vtkCallbackCommand.h"
18 #include "vtkRenderWindowInteractor.h"
19 #include "vtkObjectFactory.h"
20 #include "vtkRenderer.h"
21 #include "vtkHandleWidget.h"
22 #include "vtkHandleRepresentation.h"
23 #include "vtkCoordinate.h"
24 #include "vtkWidgetCallbackMapper.h"
25 #include "vtkWidgetEvent.h"
26 #include "vtkWidgetEventTranslator.h"
27 
28 vtkStandardNewMacro(vtkAngleWidget);
29 
30 // The angle widget observes the handles.
31 // Here we create the command/observer classes to respond to the
32 // slider widgets.
33 class vtkAngleWidgetCallback : public vtkCommand
34 {
35 public:
New()36   static vtkAngleWidgetCallback *New()
37     { return new vtkAngleWidgetCallback; }
Execute(vtkObject *,unsigned long eventId,void *)38   void Execute(vtkObject*, unsigned long eventId, void*) override
39   {
40       switch (eventId)
41       {
42         case vtkCommand::StartInteractionEvent:
43           this->AngleWidget->StartAngleInteraction(this->HandleNumber);
44           break;
45         case vtkCommand::InteractionEvent:
46           this->AngleWidget->AngleInteraction(this->HandleNumber);
47           break;
48         case vtkCommand::EndInteractionEvent:
49           this->AngleWidget->EndAngleInteraction(this->HandleNumber);
50           break;
51       }
52   }
53   int HandleNumber;
54   vtkAngleWidget *AngleWidget;
55 };
56 
57 
58 //----------------------------------------------------------------------
vtkAngleWidget()59 vtkAngleWidget::vtkAngleWidget()
60 {
61   this->ManagesCursor = 0;
62 
63   this->WidgetState = vtkAngleWidget::Start;
64   this->CurrentHandle = 0;
65 
66   // The widgets for moving the end points. They observe this widget (i.e.,
67   // this widget is the parent to the handles).
68   this->Point1Widget = vtkHandleWidget::New();
69   this->Point1Widget->SetParent(this);
70   this->CenterWidget = vtkHandleWidget::New();
71   this->CenterWidget->SetParent(this);
72   this->Point2Widget = vtkHandleWidget::New();
73   this->Point2Widget->SetParent(this);
74 
75   // Set up the callbacks on the two handles
76   this->AngleWidgetCallback1 = vtkAngleWidgetCallback::New();
77   this->AngleWidgetCallback1->HandleNumber = 0;
78   this->AngleWidgetCallback1->AngleWidget = this;
79   this->Point1Widget->AddObserver(vtkCommand::StartInteractionEvent, this->AngleWidgetCallback1,
80                                   this->Priority);
81   this->Point1Widget->AddObserver(vtkCommand::InteractionEvent, this->AngleWidgetCallback1,
82                                   this->Priority);
83   this->Point1Widget->AddObserver(vtkCommand::EndInteractionEvent, this->AngleWidgetCallback1,
84                                   this->Priority);
85 
86   // Set up the callbacks on the two handles
87   this->AngleWidgetCenterCallback = vtkAngleWidgetCallback::New();
88   this->AngleWidgetCenterCallback->HandleNumber = 1;
89   this->AngleWidgetCenterCallback->AngleWidget = this;
90   this->CenterWidget->AddObserver(vtkCommand::StartInteractionEvent, this->AngleWidgetCenterCallback,
91                                   this->Priority);
92   this->CenterWidget->AddObserver(vtkCommand::InteractionEvent, this->AngleWidgetCenterCallback,
93                                   this->Priority);
94   this->CenterWidget->AddObserver(vtkCommand::EndInteractionEvent, this->AngleWidgetCenterCallback,
95                                   this->Priority);
96 
97   this->AngleWidgetCallback2 = vtkAngleWidgetCallback::New();
98   this->AngleWidgetCallback2->HandleNumber = 2;
99   this->AngleWidgetCallback2->AngleWidget = this;
100   this->Point2Widget->AddObserver(vtkCommand::StartInteractionEvent, this->AngleWidgetCallback2,
101                                   this->Priority);
102   this->Point2Widget->AddObserver(vtkCommand::InteractionEvent, this->AngleWidgetCallback2,
103                                   this->Priority);
104   this->Point2Widget->AddObserver(vtkCommand::EndInteractionEvent, this->AngleWidgetCallback2,
105                                   this->Priority);
106 
107 
108   // These are the event callbacks supported by this widget
109   this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent,
110                                           vtkWidgetEvent::AddPoint,
111                                           this, vtkAngleWidget::AddPointAction);
112   this->CallbackMapper->SetCallbackMethod(vtkCommand::MouseMoveEvent,
113                                           vtkWidgetEvent::Move,
114                                           this, vtkAngleWidget::MoveAction);
115   this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent,
116                                           vtkWidgetEvent::EndSelect,
117                                           this, vtkAngleWidget::EndSelectAction);
118 }
119 
120 //----------------------------------------------------------------------
~vtkAngleWidget()121 vtkAngleWidget::~vtkAngleWidget()
122 {
123   this->Point1Widget->RemoveObserver(this->AngleWidgetCallback1);
124   this->Point1Widget->Delete();
125   this->AngleWidgetCallback1->Delete();
126 
127   this->CenterWidget->RemoveObserver(this->AngleWidgetCenterCallback);
128   this->CenterWidget->Delete();
129   this->AngleWidgetCenterCallback->Delete();
130 
131   this->Point2Widget->RemoveObserver(this->AngleWidgetCallback2);
132   this->Point2Widget->Delete();
133   this->AngleWidgetCallback2->Delete();
134 }
135 
136 //----------------------------------------------------------------------
CreateDefaultRepresentation()137 void vtkAngleWidget::CreateDefaultRepresentation()
138 {
139   if ( ! this->WidgetRep )
140   {
141     this->WidgetRep = vtkAngleRepresentation2D::New();
142   }
143   reinterpret_cast<vtkAngleRepresentation*>(this->WidgetRep)->
144     InstantiateHandleRepresentation();
145 }
146 
147 //----------------------------------------------------------------------
SetEnabled(int enabling)148 void vtkAngleWidget::SetEnabled(int enabling)
149 {
150   // The handle widgets are not actually enabled until they are placed.
151   // The handle widgets take their representation from the vtkAngleRepresentation.
152   if ( enabling )
153   {
154     if ( this->WidgetState == vtkAngleWidget::Start )
155     {
156       if (this->WidgetRep)
157       {
158         reinterpret_cast<vtkAngleRepresentation*>(this->WidgetRep)->
159           Ray1VisibilityOff();
160         reinterpret_cast<vtkAngleRepresentation*>(this->WidgetRep)->
161           Ray2VisibilityOff();
162         reinterpret_cast<vtkAngleRepresentation*>(this->WidgetRep)->
163           ArcVisibilityOff();
164       }
165     }
166     else
167     {
168       if (this->WidgetRep)
169       {
170         reinterpret_cast<vtkAngleRepresentation*>(this->WidgetRep)->
171           Ray1VisibilityOn();
172         reinterpret_cast<vtkAngleRepresentation*>(this->WidgetRep)->
173           Ray2VisibilityOn();
174         reinterpret_cast<vtkAngleRepresentation*>(this->WidgetRep)->
175           ArcVisibilityOn();
176       }
177 
178       // The interactor must be set prior to enabling the widget.
179       if (this->Interactor)
180       {
181         this->Point1Widget->SetInteractor(this->Interactor);
182         this->CenterWidget->SetInteractor(this->Interactor);
183         this->Point2Widget->SetInteractor(this->Interactor);
184       }
185 
186       this->Point1Widget->SetEnabled(1);
187       this->CenterWidget->SetEnabled(1);
188       this->Point2Widget->SetEnabled(1);
189     }
190   }
191 
192 
193   if ( enabling ) //----------------
194   {
195     if ( this->Enabled ) //already enabled, just return
196     {
197       return;
198     }
199 
200     if ( ! this->Interactor )
201     {
202       vtkErrorMacro(<<"The interactor must be set prior to enabling the widget");
203       return;
204     }
205 
206     int X=this->Interactor->GetEventPosition()[0];
207     int Y=this->Interactor->GetEventPosition()[1];
208 
209     if ( ! this->CurrentRenderer )
210     {
211       this->SetCurrentRenderer(this->Interactor->FindPokedRenderer(X,Y));
212 
213       if (this->CurrentRenderer == nullptr)
214       {
215         return;
216       }
217     }
218 
219     // We're ready to enable
220     this->Enabled = 1;
221     this->CreateDefaultRepresentation();
222     this->WidgetRep->SetRenderer(this->CurrentRenderer);
223 
224     // listen for the events found in the EventTranslator
225     if ( ! this->Parent )
226     {
227       this->EventTranslator->AddEventsToInteractor(this->Interactor,
228         this->EventCallbackCommand,this->Priority);
229     }
230     else
231     {
232       this->EventTranslator->AddEventsToParent(this->Parent,
233         this->EventCallbackCommand,this->Priority);
234     }
235 
236     if ( this->ManagesCursor )
237     {
238       this->WidgetRep->ComputeInteractionState(X, Y);
239       this->SetCursor(this->WidgetRep->GetInteractionState());
240     }
241 
242     vtkAngleRepresentation *rep =
243         static_cast<vtkAngleRepresentation*>(this->WidgetRep);
244 
245     // Set the renderer, representation and interactor on the child widgets.
246     if (this->Point1Widget)
247     {
248       this->Point1Widget->SetRepresentation(rep->GetPoint1Representation());
249       this->Point1Widget->SetInteractor(this->Interactor);
250       this->Point1Widget->GetRepresentation()->SetRenderer(
251         this->CurrentRenderer);
252     }
253 
254     if (this->CenterWidget)
255     {
256       this->CenterWidget->SetRepresentation(rep->GetCenterRepresentation());
257       this->CenterWidget->SetInteractor(this->Interactor);
258       this->CenterWidget->GetRepresentation()->SetRenderer(
259         this->CurrentRenderer);
260     }
261 
262     if (this->Point2Widget)
263     {
264       this->Point2Widget->SetRepresentation(rep->GetPoint2Representation());
265       this->Point2Widget->SetInteractor(this->Interactor);
266       this->Point2Widget->GetRepresentation()->SetRenderer(
267         this->CurrentRenderer);
268     }
269 
270     if (rep)
271     {
272       rep->SetRay1Visibility(
273           this->WidgetState != vtkAngleWidget::Start ? 1 : 0);
274       rep->SetRay2Visibility(
275           this->WidgetState != vtkAngleWidget::Start ? 1 : 0);
276       rep->SetArcVisibility(
277           this->WidgetState != vtkAngleWidget::Start ? 1 : 0);
278     }
279 
280 
281     if ( this->WidgetState != vtkAngleWidget::Start )
282     {
283       if (this->Point1Widget)
284       {
285         this->Point1Widget->SetEnabled(1);
286       }
287       if (this->CenterWidget)
288       {
289         this->CenterWidget->SetEnabled(1);
290       }
291       if (this->Point2Widget)
292       {
293         this->Point2Widget->SetEnabled(1);
294       }
295     }
296 
297     this->WidgetRep->BuildRepresentation();
298     this->CurrentRenderer->AddViewProp(this->WidgetRep);
299 
300     this->InvokeEvent(vtkCommand::EnableEvent,nullptr);
301   }
302 
303   else //disabling------------------
304   {
305     if ( ! this->Enabled ) //already disabled, just return
306     {
307       return;
308     }
309 
310     this->Enabled = 0;
311 
312     // don't listen for events any more
313     if ( ! this->Parent )
314     {
315       this->Interactor->RemoveObserver(this->EventCallbackCommand);
316     }
317     else
318     {
319       this->Parent->RemoveObserver(this->EventCallbackCommand);
320     }
321 
322     this->CurrentRenderer->RemoveViewProp(this->WidgetRep);
323 
324 
325     if (vtkAngleRepresentation *rep =
326         static_cast<vtkAngleRepresentation*>(this->WidgetRep))
327     {
328       rep->Ray1VisibilityOff();
329       rep->Ray2VisibilityOff();
330       rep->ArcVisibilityOff();
331     }
332 
333     if (this->Point1Widget)
334     {
335       this->Point1Widget->SetEnabled(0);
336     }
337 
338     if (this->CenterWidget)
339     {
340       this->CenterWidget->SetEnabled(0);
341     }
342 
343     if (this->Point2Widget)
344     {
345       this->Point2Widget->SetEnabled(0);
346     }
347 
348     this->InvokeEvent(vtkCommand::DisableEvent,nullptr);
349     this->SetCurrentRenderer(nullptr);
350   }
351 
352 
353   // Should only render if there is no parent
354   if ( this->Interactor && !this->Parent )
355   {
356     this->Interactor->Render();
357   }
358 }
359 
360 //----------------------------------------------------------------------
IsAngleValid()361 vtkTypeBool vtkAngleWidget::IsAngleValid()
362 {
363   if ( this->WidgetState == vtkAngleWidget::Manipulate ||
364        (this->WidgetState == vtkAngleWidget::Define && this->CurrentHandle == 2) )
365   {
366     return 1;
367   }
368   else
369   {
370     return 0;
371   }
372 }
373 
374 // The following methods are the callbacks that the angle widget responds to.
375 //-------------------------------------------------------------------------
AddPointAction(vtkAbstractWidget * w)376 void vtkAngleWidget::AddPointAction(vtkAbstractWidget *w)
377 {
378   vtkAngleWidget *self = reinterpret_cast<vtkAngleWidget*>(w);
379   int X = self->Interactor->GetEventPosition()[0];
380   int Y = self->Interactor->GetEventPosition()[1];
381 
382   // If we are placing the first point it's easy
383   if ( self->WidgetState == vtkAngleWidget::Start )
384   {
385     self->GrabFocus(self->EventCallbackCommand);
386     self->WidgetState = vtkAngleWidget::Define;
387     self->InvokeEvent(vtkCommand::StartInteractionEvent,nullptr);
388     double e[2];
389     e[0] = static_cast<double>(X);
390     e[1] = static_cast<double>(Y);
391     reinterpret_cast<vtkAngleRepresentation*>(self->WidgetRep)->StartWidgetInteraction(e);
392     self->CurrentHandle = 0;
393     self->InvokeEvent(vtkCommand::PlacePointEvent,&(self->CurrentHandle));
394     reinterpret_cast<vtkAngleRepresentation*>(self->WidgetRep)->Ray1VisibilityOn();
395     self->Point1Widget->SetEnabled(1);
396     self->CurrentHandle++;
397   }
398 
399   // If defining we are placing the second or third point
400   else if ( self->WidgetState == vtkAngleWidget::Define )
401   {
402     self->InvokeEvent(vtkCommand::PlacePointEvent,&(self->CurrentHandle));
403     if ( self->CurrentHandle == 1 )
404     {
405       double e[2];
406       e[0] = static_cast<double>(X);
407       e[1] = static_cast<double>(Y);
408       reinterpret_cast<vtkAngleRepresentation*>(self->WidgetRep)->CenterWidgetInteraction(e);
409       self->CurrentHandle++;
410       self->CenterWidget->SetEnabled(1);
411       reinterpret_cast<vtkAngleRepresentation*>(self->WidgetRep)->Ray2VisibilityOn();
412       reinterpret_cast<vtkAngleRepresentation*>(self->WidgetRep)->ArcVisibilityOn();
413     }
414     else if ( self->CurrentHandle == 2 )
415     {
416       self->WidgetState = vtkAngleWidget::Manipulate;
417       self->Point2Widget->SetEnabled(1);
418       self->CurrentHandle = (-1);
419       self->ReleaseFocus();
420       self->InvokeEvent(vtkCommand::EndInteractionEvent,nullptr);
421     }
422   }
423 
424   // Maybe we are trying to manipulate the widget handles
425   else //if ( self->WidgetState == vtkAngleWidget::Manipulate )
426   {
427     int state = self->WidgetRep->ComputeInteractionState(X,Y);
428     if ( state == vtkAngleRepresentation::Outside )
429     {
430       self->CurrentHandle = (-1);
431       return;
432     }
433 
434     self->GrabFocus(self->EventCallbackCommand);
435     if ( state == vtkAngleRepresentation::NearP1 )
436     {
437       self->CurrentHandle = 0;
438     }
439     else if ( state == vtkAngleRepresentation::NearCenter )
440     {
441       self->CurrentHandle = 1;
442     }
443     else if ( state == vtkAngleRepresentation::NearP2 )
444     {
445       self->CurrentHandle = 2;
446     }
447     self->InvokeEvent(vtkCommand::LeftButtonPressEvent,nullptr);
448   }
449 
450   self->EventCallbackCommand->SetAbortFlag(1);
451   self->Render();
452 }
453 
454 //-------------------------------------------------------------------------
MoveAction(vtkAbstractWidget * w)455 void vtkAngleWidget::MoveAction(vtkAbstractWidget *w)
456 {
457   vtkAngleWidget *self = reinterpret_cast<vtkAngleWidget*>(w);
458 
459   // Do nothing if outside
460   if ( self->WidgetState == vtkAngleWidget::Start )
461   {
462     return;
463   }
464 
465   // Delegate the event consistent with the state
466   if ( self->WidgetState == vtkAngleWidget::Define )
467   {
468     int X = self->Interactor->GetEventPosition()[0];
469     int Y = self->Interactor->GetEventPosition()[1];
470     double e[2];
471     e[0] = static_cast<double>(X);
472     e[1] = static_cast<double>(Y);
473     if ( self->CurrentHandle == 1 )
474     {
475       reinterpret_cast<vtkAngleRepresentation*>(self->WidgetRep)->
476         CenterWidgetInteraction(e);
477     }
478     else
479     {
480       reinterpret_cast<vtkAngleRepresentation*>(self->WidgetRep)->
481         WidgetInteraction(e);
482     }
483     self->InvokeEvent(vtkCommand::InteractionEvent,nullptr);
484     self->EventCallbackCommand->SetAbortFlag(1);
485   }
486 
487   else //must be moving a handle, invoke a event for the handle widgets
488   {
489     self->InvokeEvent(vtkCommand::MouseMoveEvent, nullptr);
490   }
491 
492   self->WidgetRep->BuildRepresentation();
493   self->Render();
494 }
495 
496 //-------------------------------------------------------------------------
EndSelectAction(vtkAbstractWidget * w)497 void vtkAngleWidget::EndSelectAction(vtkAbstractWidget *w)
498 {
499   vtkAngleWidget *self = reinterpret_cast<vtkAngleWidget*>(w);
500 
501   // Do nothing if outside
502   if ( self->WidgetState == vtkAngleWidget::Start ||
503        self->WidgetState == vtkAngleWidget::Define ||
504        self->CurrentHandle < 0 )
505   {
506     return;
507   }
508 
509   self->ReleaseFocus();
510   self->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,nullptr);
511   self->CurrentHandle = (-1);
512   self->WidgetRep->BuildRepresentation();
513   self->EventCallbackCommand->SetAbortFlag(1);
514   self->Render();
515 }
516 
517 // These are callbacks that are active when the user is manipulating the
518 // handles of the angle widget.
519 //----------------------------------------------------------------------
StartAngleInteraction(int)520 void vtkAngleWidget::StartAngleInteraction(int)
521 {
522   this->Superclass::StartInteraction();
523   this->InvokeEvent(vtkCommand::StartInteractionEvent,nullptr);
524 }
525 
526 //----------------------------------------------------------------------
AngleInteraction(int)527 void vtkAngleWidget::AngleInteraction(int)
528 {
529   this->InvokeEvent(vtkCommand::InteractionEvent,nullptr);
530 }
531 
532 //----------------------------------------------------------------------
EndAngleInteraction(int)533 void vtkAngleWidget::EndAngleInteraction(int)
534 {
535   this->Superclass::EndInteraction();
536 
537   this->InvokeEvent(vtkCommand::EndInteractionEvent,nullptr);
538 }
539 
540 //----------------------------------------------------------------------
SetProcessEvents(vtkTypeBool pe)541 void vtkAngleWidget::SetProcessEvents(vtkTypeBool pe)
542 {
543   this->Superclass::SetProcessEvents(pe);
544 
545   //Pass pe flag to component widgets.
546   this->Point1Widget->SetProcessEvents(pe);
547   this->CenterWidget->SetProcessEvents(pe);
548   this->Point2Widget->SetProcessEvents(pe);
549 }
550 
551 //----------------------------------------------------------------------
SetWidgetStateToStart()552 void vtkAngleWidget::SetWidgetStateToStart()
553 {
554   this->WidgetState = vtkAngleWidget::Start;
555   this->CurrentHandle = -1;
556   this->ReleaseFocus();
557   this->GetRepresentation()->BuildRepresentation(); // update this->Angle
558   this->SetEnabled(this->GetEnabled()); // show/hide the handles properly
559 }
560 
561 //----------------------------------------------------------------------
SetWidgetStateToManipulate()562 void vtkAngleWidget::SetWidgetStateToManipulate()
563 {
564   this->WidgetState = vtkAngleWidget::Manipulate;
565   this->CurrentHandle = -1;
566   this->ReleaseFocus();
567   this->GetRepresentation()->BuildRepresentation(); // update this->Angle
568   this->SetEnabled(this->GetEnabled()); // show/hide the handles properly
569 }
570 
571 //----------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)572 void vtkAngleWidget::PrintSelf(ostream& os, vtkIndent indent)
573 {
574   //Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
575   this->Superclass::PrintSelf(os,indent);
576 }
577