ATLAS Offline Software
SoCooperativeSelection.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Class: SoCooperativeSelection.
6 // Author: Thomas.Kittelmann@cern.ch
7 // Initial version: October 2007
8 
10 
11 #include <Inventor/actions/SoHandleEventAction.h>
12 #include <Inventor/lists/SoCallbackList.h>
13 #include <Inventor/SoPickedPoint.h>
14 #include <Inventor/events/SoMouseButtonEvent.h>
15 
16 
17 SO_NODE_SOURCE(SoCooperativeSelection)
18 
19 //____________________________________________________________________
20 void SoCooperativeSelection::initClass()
21 {
22  SO_NODE_INIT_CLASS(SoCooperativeSelection,SoSelection,"CooperativeSelection");
23 }
24 
25 //____________________________________________________________________
27 {
28  [[maybe_unused]] static const bool needsinit = [&]() {
29  initClass();
30  return false;
31  }();
32 }
33 
34 //____________________________________________________________________
36  : SoSelection()
37 {
38  init();
39 }
40 
41 //____________________________________________________________________
43  : SoSelection(nChildren)
44 {
45  init();
46 }
47 
48 //____________________________________________________________________
50 {
51  SO_NODE_CONSTRUCTOR(SoCooperativeSelection);
52 
53  SO_NODE_ADD_FIELD(activePolicy, (SoCooperativeSelection::ACTIVE));
54  SO_NODE_DEFINE_ENUM_VALUE(ActivePolicy, INERT);
55  SO_NODE_DEFINE_ENUM_VALUE(ActivePolicy, ACTIVE);
56  SO_NODE_SET_SF_ENUM_TYPE(activePolicy, ActivePolicy);
57 
58  setNodeType(EXTENSION);
59  m_clickoutsideCBList = new SoCallbackList;
60 
61 }
62 
63 //____________________________________________________________________
65 {
66  if (this->mouseDownPickPath)
67  this->mouseDownPickPath->unref();
68  delete m_clickoutsideCBList;
69 }
70 
71 //____________________________________________________________________
73 {
74  for (int i = 0; i < path->getLength(); ++i) {
75  if (path->getNodeFromTail(i)->getTypeId().isDerivedFrom(SoCooperativeSelection::getClassTypeId())) {
76  SoCooperativeSelection* sel = static_cast<SoCooperativeSelection*>(path->getNodeFromTail(i));
77  if (sel->activePolicy.getValue() == ACTIVE)
78  return sel;
79  }
80  }
81  return 0;
82 }
83 
84 //____________________________________________________________________
86 {
87  m_clickoutsideCBList->addCallback((SoCallbackListCB *)f, userData);
88 }
89 
90 //____________________________________________________________________
92 {
93  m_clickoutsideCBList->removeCallback((SoCallbackListCB *)f, userData);
94 }
95 
96 //____________________________________________________________________
97 void SoCooperativeSelection::handleEvent(SoHandleEventAction * action)
98 {
99  // Overridden to do selection picking.
100  SoSeparator::handleEvent(action);//Skip the SoSelection impl and go directly to the SoSeparator action!!
101 
102  if (activePolicy.getValue()==INERT)
103  return;
104 
105  const SoEvent * event = action->getEvent();
106 
107  SbBool haltaction = FALSE;
108  if (SO_MOUSE_PRESS_EVENT(event, BUTTON1)) {
109  if (this->mouseDownPickPath) {
110  this->mouseDownPickPath->unref();
111  this->mouseDownPickPath = NULL;
112  }
113  const SoPickedPoint * pp = action->getPickedPoint();
114  if (!pp)
115  m_clickoutsideCBList->invokeCallbacks(this);
116  if (pp) {
117  SoPath * selectionpath = pp->getPath();
118  if (!selectionpath)
119  return;
120  // call pick filter callback also for mouse down events
121  if (this->pickCBFunc && (!this->callPickCBOnlyIfSelectable ||
122  selectionpath->findNode(this) >= 0)) {
123  selectionpath = this->pickCBFunc(this->pickCBData, pp);
124  }
125 
126  SoCooperativeSelection * lastsoselectionfrompath = getLastActiveSoSelectionFromPath(selectionpath);
127 
128  if (lastsoselectionfrompath==this) {
129  //We are the selection node furthest down the path => handle the event.
130  this->mouseDownPickPath = selectionpath;
131  this->mouseDownPickPath->ref();
132  action->setHandled();
133  }
134  }
135  }
136  else if (SO_MOUSE_RELEASE_EVENT(event, BUTTON1)) {
137 
138  SbBool ignorepick = FALSE;
139  // call pick filter callback (called from getSelectionPath()) even
140  // if the event was handled by a child node.
141  SoPath * selpath = this->getSelectionPath(action, ignorepick, haltaction);
142 
143  if (action->isHandled()) {
144  // if the event was handled by a child node we should not invoke
145  // the selection policy
146  if (selpath) {
147  selpath->ref();
148  selpath->unref();
149  }
150  }
151  else {
152  if (haltaction) action->setHandled();
153 
154  if (!ignorepick) {
155  if (selpath) selpath->ref();
156  this->startCBList->invokeCallbacks(this);
157  this->invokeSelectionPolicy(selpath, event->wasShiftDown());
158  this->finishCBList->invokeCallbacks(this);
159  if (selpath) selpath->unref();
160  }
161  }
162  if (this->mouseDownPickPath) {
163  this->mouseDownPickPath->unref();
164  this->mouseDownPickPath = NULL;
165  }
166  }
167 }
168 
169 
170 //Implementation of getSelectionPath is copied verbatim from
171 //SoSelection.cpp. If only it was protected rather than private...
172 
173 SoPath *
174 SoCooperativeSelection::getSelectionPath(SoHandleEventAction * action, SbBool & ignorepick,
175  SbBool & haltaction)
176 {
177  //
178  // handled like described in the man-pages for SoSelection
179  //
180 
181  haltaction = FALSE;
182  ignorepick = FALSE;
183  if (this->pickMatching && this->mouseDownPickPath == NULL) {
184  return NULL;
185  }
186  const SoPickedPoint * pp = action->getPickedPoint();
187  SoPath * selectionpath = NULL;
188  if (pp) {
189  selectionpath = pp->getPath();
190  // if there's no pickCBFunc we can just test against
191  // mouseDownPickPath and (possibly) return here.
192  if (this->pickMatching && !this->pickCBFunc) {
193  if (*(this->mouseDownPickPath) != *selectionpath) {
194  ignorepick = TRUE;
195  return NULL;
196  }
197  }
198  // if we have a pickCBFunc we have to get the pick filter path
199  // before comparing the mouse press and mouse release paths
200  if (this->pickCBFunc && (!this->callPickCBOnlyIfSelectable ||
201  selectionpath->findNode(this) >= 0)) {
202  selectionpath = this->pickCBFunc(this->pickCBData, pp);
203 
204  // From the SoSelection man-pages:
205  // Possible return values from pickCBFunc:
206  // 1) NULL - behave as if nothing was picked, halt action
207  // 2) path through the selection node - select/deselect path
208  // 3) path containing only the selection node - as 1, but do not halt action
209  // 4) path not through the selection node - ignore event
210  if (selectionpath) {
211  if (selectionpath->getLength() == 1 &&
212  selectionpath->getNode(0) == this) {
213  selectionpath->ref();
214  selectionpath->unref();
215  selectionpath = NULL;
216  }
217  else if (selectionpath->findNode(this) >= 0) {
218  if (*(this->mouseDownPickPath) == *selectionpath) {
219  // pick matched
220  haltaction = TRUE;
221  }
222  else {
223  // mouse release didn't match mouse down
224  ignorepick = TRUE;
225  selectionpath->ref();
226  selectionpath->unref();
227  ignorepick = TRUE;
228  }
229  }
230  else { // path with this not in the path (most probably an empty path)
231  selectionpath->ref();
232  selectionpath->unref();
233  selectionpath = NULL;
234  ignorepick = TRUE;
235  }
236  }
237  else { // pickCBFunc returned NULL
238  haltaction = TRUE;
239  }
240  }
241  else { // no pickCBFunc or not a valid path
242  haltaction = FALSE;
243  }
244  }
245  else if (this->mouseDownPickPath) {
246  ignorepick = TRUE;
247  }
248  return selectionpath;
249 }
SoCooperativeSelectionClickOutsideCB
void SoCooperativeSelectionClickOutsideCB(void *data, SoCooperativeSelection *sel)
Definition: SoCooperativeSelection.h:27
SoCooperativeSelection::removeClickOutsideCallback
void removeClickOutsideCallback(SoCooperativeSelectionClickOutsideCB *f, void *userData=0)
Definition: SoCooperativeSelection.cxx:91
SoCooperativeSelection::INERT
@ INERT
Definition: SoCooperativeSelection.h:41
python.CaloRecoConfig.f
f
Definition: CaloRecoConfig.py:127
SoCooperativeSelection::m_clickoutsideCBList
SoCallbackList * m_clickoutsideCBList
Definition: SoCooperativeSelection.h:67
SoCooperativeSelection::addClickOutsideCallback
void addClickOutsideCallback(SoCooperativeSelectionClickOutsideCB *f, void *userData=0)
Definition: SoCooperativeSelection.cxx:85
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:126
SoCooperativeSelection::~SoCooperativeSelection
virtual ~SoCooperativeSelection()
Definition: SoCooperativeSelection.cxx:64
SoCooperativeSelection::SoCooperativeSelection
SoCooperativeSelection()
Definition: SoCooperativeSelection.cxx:35
SoCooperativeSelection::activePolicy
SoSFEnum activePolicy
Definition: SoCooperativeSelection.h:49
SoCooperativeSelection::handleEvent
virtual void handleEvent(SoHandleEventAction *action)
Definition: SoCooperativeSelection.cxx:97
SoCooperativeSelection::getSelectionPath
SoPath * getSelectionPath(SoHandleEventAction *action, SbBool &ignorepick, SbBool &haltaction)
Definition: SoCooperativeSelection.cxx:174
SoCooperativeSelection::initClass
static void initClass()
Definition: SoCooperativeSelection.cxx:20
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
lumiFormat.i
int i
Definition: lumiFormat.py:92
sel
sel
Definition: SUSYToolsTester.cxx:92
SoCooperativeSelection::init
void init()
Definition: SoCooperativeSelection.cxx:49
python.Constants.TRUE
bool TRUE
for job options legacy (TODO: get rid of these!) ----------------------—
Definition: Control/AthenaCommon/python/Constants.py:22
SoCooperativeSelection::ensureInitClass
static void ensureInitClass()
Definition: SoCooperativeSelection.cxx:26
SoCooperativeSelection::ACTIVE
@ ACTIVE
Definition: SoCooperativeSelection.h:41
SoCooperativeSelection.h
SoCooperativeSelection::getLastActiveSoSelectionFromPath
SoCooperativeSelection * getLastActiveSoSelectionFromPath(SoPath *) const
Definition: SoCooperativeSelection.cxx:72
python.Constants.FALSE
bool FALSE
Definition: Control/AthenaCommon/python/Constants.py:23
python.CaloScaleNoiseConfig.action
action
Definition: CaloScaleNoiseConfig.py:77
SoCooperativeSelection::ActivePolicy
ActivePolicy
Definition: SoCooperativeSelection.h:40
SoCooperativeSelection
Definition: SoCooperativeSelection.h:29