ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
CustomVtkCaptionWidget.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <vtkCommand.h>
11 #include <vtkDoubleArray.h>
12 #include <vtkHandleWidget.h>
13 #include <vtkRenderer.h>
14 
15 // Qt
16 #include <QApplication>
17 #include <QMetaObject>
18 #include <QTimer>
19 
20 // Include headers for cc2DLabel and ecvDisplayTools
21 #include <CVLog.h>
25 
27 
28 CustomVtkCaptionWidget::CustomVtkCaptionWidget() : m_associatedLabel(nullptr) {
29  // Create callback for widget interaction events
32  m_interactionCallback->SetClientData(this);
33 
34  // Listen for multiple interaction events to catch clicks on the widget
35  // StartInteractionEvent: when user starts interacting (mouse down)
36  // InteractionEvent: during interaction (mouse move while pressed)
37  // LeftButtonPressEvent: explicit left button press
38  this->AddObserver(vtkCommand::StartInteractionEvent, m_interactionCallback);
39  this->AddObserver(vtkCommand::InteractionEvent, m_interactionCallback);
40  this->AddObserver(vtkCommand::LeftButtonPressEvent, m_interactionCallback);
41 }
42 
44  // Remove observer
46  this->RemoveObserver(m_interactionCallback);
47  }
48  m_associatedLabel = nullptr;
49 }
50 
52  this->HandleWidget->SetEnabled(state);
53  state ? this->HandleWidget->ProcessEventsOn()
54  : this->HandleWidget->ProcessEventsOff();
55 }
56 
58  m_associatedLabel = label;
59 }
60 
62  unsigned long eventId,
63  void* clientData,
64  void* /*callData*/) {
65  // Handle multiple event types to catch widget clicks
66  // StartInteractionEvent: when user starts interacting (mouse down on
67  // widget) LeftButtonPressEvent: explicit left button press on widget
68  // InteractionEvent: during interaction (but we only want the initial click)
69  if (eventId != vtkCommand::StartInteractionEvent &&
70  eventId != vtkCommand::LeftButtonPressEvent) {
71  return;
72  }
73 
75  static_cast<CustomVtkCaptionWidget*>(clientData);
76  if (!self || !self->m_associatedLabel) {
77  return;
78  }
79 
80  // Notify DB tree that the label is selected
81  cc2DLabel* label = self->m_associatedLabel;
82 
84  return;
85  }
86 
87  // CRITICAL: Mark that a widget was clicked and stop deferred picking timer
88  // to prevent it from overriding our widget selection. The deferred picking
89  // timer is started in QVTKWidgetCustom::mouseReleaseEvent when
90  // ProcessClickableItems returns false, and it would trigger doPicking()
91  // which might clear our selection.
93  if (tools) {
94  // Mark that a widget was clicked - this will prevent doPicking() from
95  // executing and overriding our selection
96  tools->m_widgetClicked = true;
97 
98  // Stop deferred picking timer immediately if already active
99  if (tools->m_deferredPickingTimer.isActive()) {
100  tools->m_deferredPickingTimer.stop();
101  }
102  }
103 
104  // Use QTimer::singleShot to safely emit signal from VTK callback
105  // This ensures the signal is emitted in the Qt event loop
106  QTimer::singleShot(0, [label, tools]() {
108  return;
109  }
110 
111  // Stop deferred picking timer again in case mouseReleaseEvent started
112  // it after our OnWidgetInteraction callback
113  if (tools && tools->m_deferredPickingTimer.isActive()) {
114  tools->m_deferredPickingTimer.stop();
115  }
116 
117  // Directly emit the signal - we're now in Qt event loop
118  emit ecvDisplayTools::TheInstance() -> entitySelectionChanged(label);
119  });
120 }
vtkStandardNewMacro(CustomVtkCaptionWidget)
static void OnWidgetInteraction(vtkObject *caller, unsigned long eventId, void *clientData, void *callData)
Callback for widget interaction events.
void SetAssociatedLabel(cc2DLabel *label)
Set the associated cc2DLabel for selection notification.
vtkSmartPointer< vtkCallbackCommand > m_interactionCallback
2D label (typically attached to points)
Definition: ecv2DLabel.h:22
static ecvDisplayTools * TheInstance()
QTimer m_deferredPickingTimer
Deferred picking.