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