22#include <Inventor/nodes/SoSeparator.h>
23#include <Inventor/SoPath.h>
24#include <QApplication>
82 static bool shiftIsDown() {
return Qt::ShiftModifier & QApplication::keyboardModifiers(); }
112 if (m==
SINGLE)
return "SINGLE";
113 else if (m==
TOGGLE)
return "TOGGLE";
114 else if (m==
SHIFT)
return "SHIFT";
115 else return "UNKNOWN(ERROR)";
137 return m_d->sel_assocobjs_click;
143 if (!simple||!detailed||!handle) {
144 message(
"registerAscObj ERROR: Received null pointer!");
147 std::map<SoSeparator*,AssociatedObjectHandleBase*>::iterator it, itE;
148 itE =
m_d->ascobjs_simpleToHandle.end();
149 for (it=
m_d->ascobjs_simpleToHandle.begin();it!=itE;++it) {
150 if (it->first==simple||it->second==handle)
151 message(
"registerAscObj ERROR: Simple separator/handle already registered!");
153 itE =
m_d->ascobjs_detailedToHandle.end();
154 for (it=
m_d->ascobjs_detailedToHandle.begin();it!=itE;++it) {
155 if (it->first==detailed||it->second==handle)
156 message(
"registerAscObj ERROR: Detailed separator/handle already registered!");
159 m_d->ascobjs_simpleToHandle[simple]=handle;
160 m_d->ascobjs_detailedToHandle[detailed]=handle;
167 if (!simple||!detailed) {
168 message(
"unregisterAscObj ERROR: Received null pointer!");
172 std::map<SoSeparator*,AssociatedObjectHandleBase*>::iterator itSimple =
m_d->ascobjs_simpleToHandle.find(simple);
173 if (itSimple==
m_d->ascobjs_simpleToHandle.end()) {
174 message(
"unregisterAscObj ERROR: Not previously registered simple sep!");
176 m_d->ascobjs_simpleToHandle.erase(itSimple);
178 std::map<SoSeparator*,AssociatedObjectHandleBase*>::iterator itDetailed =
m_d->ascobjs_detailedToHandle.find(detailed);
179 if (itDetailed==
m_d->ascobjs_detailedToHandle.end()) {
180 message(
"unregisterAscObj ERROR: Not previously registered detailed sep!");
182 m_d->ascobjs_detailedToHandle.erase(itDetailed);
189 const int n(path?path->getLength():0);
191 for (
int i = 0; i < n; ++i) {
192 if (path->getNodeFromTail(i)->getTypeId()==SoSeparator::getClassTypeId()) {
193 handle =
ascObjHandle(
static_cast<SoSeparator*
>(path->getNodeFromTail(i)));
204 std::map<SoSeparator*,AssociatedObjectHandleBase*>::const_iterator
221 (isSimpleMode?handle->shapeSimple():handle->shapeDetailed()))) {
222 theclass->message(
"updateSelectionVisuals ERROR: Failed to relocate picked node.");
236 pickedHandle =
nullptr;
237 if (
sel==
m_d->sel_assocobjs) {
241 if (
sel!=
m_d->sel_assocobjs_click) {
247 m_d->sel_assocobjs_click->deselectAll();
249 message(
"ERROR: Unknown associated object.");
253 pickedHandle = handle;
264 const bool alreadyselected =
m_d->selAscObjHandles.contains(handle);
266 QList<AssociatedObjectHandleBase*> selHandlesBefore =
m_d->selAscObjHandles;
269 if (
m_d->selAscObjHandles.isEmpty()) {
271 m_d->selAscObjHandles << handle;
272 if (
m_d->controller->printInfoOnSingleSelection())
276 m_d->selAscObjHandles.clear();
278 if (!alreadyselected) {
279 m_d->selAscObjHandles << handle;
280 if (
m_d->controller->printInfoOnSingleSelection())
287 m_d->selAscObjHandles.removeAll(handle);
289 m_d->selAscObjHandles << handle;
291 m_d->selAscObjHandles.clear();
292 if (!alreadyselected)
293 m_d->selAscObjHandles << handle;
296 if (alreadyselected) {
297 m_d->selAscObjHandles.removeAll(handle);
299 m_d->selAscObjHandles << handle;
302 message(
"ERROR: Should not happen!");
308 if (selHandlesBefore!=
m_d->selAscObjHandles) {
309 m_d->updateSelectionVisuals();
328 if (
m_d->selAscObjHandles.isEmpty())
330 m_d->selAscObjHandles.clear();
332 m_d->updateSelectionVisuals();
338 if (handles.isEmpty())
340 QList<AssociatedObjectHandleBase*> selHandlesBefore =
m_d->selAscObjHandles;
342 m_d->selAscObjHandles.removeAll(handle);
343 if (selHandlesBefore!=
m_d->selAscObjHandles) {
344 m_d->updateSelectionVisuals();
352 if (handles.isEmpty())
356 if (handles.count()>1)
357 message(
"WARNING: ensureSelected called with more than one handle in SINGLE mode. Ignoring all but the first.");
358 if (
m_d->selAscObjHandles.contains(handles.at(0)))
360 m_d->selAscObjHandles.clear();
361 m_d->selAscObjHandles << handles.at(0);
363 m_d->updateSelectionVisuals();
366 QList<AssociatedObjectHandleBase*> selHandlesBefore =
m_d->selAscObjHandles;
368 if (!
m_d->selAscObjHandles.contains(handle))
369 m_d->selAscObjHandles << handle;
372 if (selHandlesBefore!=
m_d->selAscObjHandles) {
373 m_d->updateSelectionVisuals();
383 messageVerbose(
"Signal received in ascObjDetailLevelChanged slot");
384 if (
m_d->selAscObjHandles.isEmpty()) {
385 m_d->sel_assocobjs->deselectAll();
388 const SoPathList * pathlist =
m_d->sel_assocobjs->getList();
389 if (!pathlist||pathlist->getLength()!=
m_d->selAscObjHandles.count())
395 SoPath * path = (*pathlist)[i++];
400 message(
"Warning: Failed to relocate picked node.");
410 return m_d->selAscObjHandles;
415 return m_d->eventRoot;
void updateSelectionVisuals()
QList< AssociatedObjectHandleBase * > selAscObjHandles
Imp(AscObjSelectionManager *tc, SoSeparator *root, IVP13DSystem *sys, TrackSystemController *c)
TrackSystemController * controller
AssociatedObjectHandleBase * ascObjHandle(const SoPath *)
std::map< SoSeparator *, AssociatedObjectHandleBase * > ascobjs_detailedToHandle
SoCooperativeSelection * sel_assocobjs
static bool shiftIsDown()
SoCooperativeSelection * sel_assocobjs_click
Imp & operator=(const Imp &)=delete
AscObjSelectionManager * theclass
std::map< SoSeparator *, AssociatedObjectHandleBase * > ascobjs_simpleToHandle
void unregisterAscObj(SoSeparator *simple, SoSeparator *detailed)
SoSeparator * eventRoot()
void pretendUserClicked(AssociatedObjectHandleBase *)
void ensureSelected(const QList< AssociatedObjectHandleBase * > &)
bool handleUserSelectedSingleNode(SoCooperativeSelection *, SoNode *, SoPath *, AssociatedObjectHandleBase *&)
void currentSelectionChanged(const QList< AssociatedObjectHandleBase * > &)
friend class AssociatedObjectHandleBase
void registerAscObj(SoSeparator *simple, SoSeparator *detailed, AssociatedObjectHandleBase *)
static QString toString(MODE)
void ascObjDetailLevelChanged()
SoSeparator * getAscObjAttachSep() const
AscObjSelectionManager(SoSeparator *eventRoot, IVP13DSystem *, TrackSystemController *)
const QList< AssociatedObjectHandleBase * > & currentSelection() const
void ensureDeselected(const QList< AssociatedObjectHandleBase * > &)
virtual ~AscObjSelectionManager()
SoSeparator * shapeSimple() const
virtual QStringList clicked()=0
SoSeparator * shapeDetailed() const
VP1HelperClassBase(IVP1System *sys=0, QString helpername="")
void messageVerbose(const QString &) const
void message(const QString &) const
static bool changePathTail(SoPath *path, SoNode *commonBranchPoint, SoNode *newtail)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.