From fea662ea718313b429668a558306bded951b060c Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 25 Dec 2017 01:19:02 +0100 Subject: [PATCH] notify selection node about cleared pre-selection --- src/Gui/Selection.cpp | 23 +++++++++ src/Gui/Selection.h | 2 + src/Gui/SoFCDB.cpp | 2 + src/Gui/SoFCSelectionAction.cpp | 86 ++++++++++++++++++++++++++++++++ src/Gui/SoFCSelectionAction.h | 25 ++++++++++ src/Gui/SoFCUnifiedSelection.cpp | 17 +++++++ src/Gui/SoFCUnifiedSelection.h | 1 + src/Gui/View3DInventorViewer.cpp | 4 ++ 8 files changed, 160 insertions(+) diff --git a/src/Gui/Selection.cpp b/src/Gui/Selection.cpp index adc3c03114..317ad2c6ce 100644 --- a/src/Gui/Selection.cpp +++ b/src/Gui/Selection.cpp @@ -1016,6 +1016,10 @@ PyMethodDef SelectionSingleton::Methods[] = { "given the complete selection is cleared."}, {"isSelected", (PyCFunction) SelectionSingleton::sIsSelected, METH_VARARGS, "isSelected(object) -- Check if a given object is selected"}, + {"getPreselection", (PyCFunction) SelectionSingleton::sGetPreselection, METH_VARARGS, + "getPreselection() -- Get preselected object"}, + {"clearPreselection", (PyCFunction) SelectionSingleton::sRemPreselection, METH_VARARGS, + "clearPreselection() -- Clear the preselection"}, {"countObjectsOfType", (PyCFunction) SelectionSingleton::sCountObjectsOfType, METH_VARARGS, "countObjectsOfType(string, [string]) -- Get the number of selected objects\n" "The first argument defines the object type e.g. \"Part::Feature\" and the\n" @@ -1191,6 +1195,25 @@ PyObject *SelectionSingleton::sGetSelection(PyObject * /*self*/, PyObject *args, } } +PyObject *SelectionSingleton::sGetPreselection(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + const SelectionChanges& sel = Selection().getPreselection(); + SelectionObject obj(sel); + return obj.getPyObject(); +} + +PyObject *SelectionSingleton::sRemPreselection(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + Selection().rmvPreselect(); + Py_Return; +} + PyObject *SelectionSingleton::sGetCompleteSelection(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/) { if (!PyArg_ParseTuple(args, "")) diff --git a/src/Gui/Selection.h b/src/Gui/Selection.h index 3ac285da25..bb79394559 100644 --- a/src/Gui/Selection.h +++ b/src/Gui/Selection.h @@ -336,6 +336,8 @@ protected: static PyObject *sIsSelected (PyObject *self,PyObject *args,PyObject *kwd); static PyObject *sCountObjectsOfType (PyObject *self,PyObject *args,PyObject *kwd); static PyObject *sGetSelection (PyObject *self,PyObject *args,PyObject *kwd); + static PyObject *sGetPreselection (PyObject *self,PyObject *args,PyObject *kwd); + static PyObject *sRemPreselection (PyObject *self,PyObject *args,PyObject *kwd); static PyObject *sGetCompleteSelection(PyObject *self,PyObject *args,PyObject *kwd); static PyObject *sGetSelectionEx (PyObject *self,PyObject *args,PyObject *kwd); static PyObject *sGetSelectionObject (PyObject *self,PyObject *args,PyObject *kwd); diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index 8be3c3a0ec..d27d6e051b 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -89,6 +89,7 @@ void Gui::SoFCDB::init() SoFCBoundingBox ::initClass(); SoFCSelection ::initClass(); SoFCUnifiedSelection ::initClass(); + SoFCHighlightAction ::initClass(); SoFCSelectionAction ::initClass(); SoFCDocumentAction ::initClass(); SoGLWidgetNode ::initClass(); @@ -192,6 +193,7 @@ void Gui::SoFCDB::finish() SoFCBackgroundGradient ::finish(); SoFCBoundingBox ::finish(); SoFCSelection ::finish(); + SoFCHighlightAction ::finish(); SoFCSelectionAction ::finish(); SoFCDocumentAction ::finish(); SoFCDocumentObjectAction ::finish(); diff --git a/src/Gui/SoFCSelectionAction.cpp b/src/Gui/SoFCSelectionAction.cpp index da0a879f27..c00a22e29e 100644 --- a/src/Gui/SoFCSelectionAction.cpp +++ b/src/Gui/SoFCSelectionAction.cpp @@ -94,6 +94,92 @@ using namespace Gui; +SO_ACTION_SOURCE(SoFCHighlightAction); + +/** + * The order of the defined SO_ACTION_ADD_METHOD statements is very important. First the base + * classes and afterwards subclasses of them must be listed, otherwise the registered methods + * of subclasses will be overridden. For more details see the thread in the Coin3d forum + * https://www.coin3d.org/pipermail/coin-discuss/2004-May/004346.html. + * This means that \c SoSwitch must be listed after \c SoGroup and \c SoFCSelection after + * \c SoSeparator because both classes inherits the others. + */ +void SoFCHighlightAction::initClass() +{ + SO_ACTION_INIT_CLASS(SoFCHighlightAction,SoAction); + + SO_ENABLE(SoFCHighlightAction, SoSwitchElement); + + SO_ACTION_ADD_METHOD(SoNode,nullAction); + + SO_ENABLE(SoFCHighlightAction, SoModelMatrixElement); + SO_ENABLE(SoFCHighlightAction, SoShapeStyleElement); + SO_ENABLE(SoFCHighlightAction, SoComplexityElement); + SO_ENABLE(SoFCHighlightAction, SoComplexityTypeElement); + SO_ENABLE(SoFCHighlightAction, SoCoordinateElement); + SO_ENABLE(SoFCHighlightAction, SoFontNameElement); + SO_ENABLE(SoFCHighlightAction, SoFontSizeElement); + SO_ENABLE(SoFCHighlightAction, SoProfileCoordinateElement); + SO_ENABLE(SoFCHighlightAction, SoProfileElement); + SO_ENABLE(SoFCHighlightAction, SoSwitchElement); + SO_ENABLE(SoFCHighlightAction, SoUnitsElement); + SO_ENABLE(SoFCHighlightAction, SoViewVolumeElement); + SO_ENABLE(SoFCHighlightAction, SoViewingMatrixElement); + SO_ENABLE(SoFCHighlightAction, SoViewportRegionElement); + + + + + SO_ACTION_ADD_METHOD(SoCallback,callDoAction); + SO_ACTION_ADD_METHOD(SoComplexity,callDoAction); + SO_ACTION_ADD_METHOD(SoCoordinate3,callDoAction); + SO_ACTION_ADD_METHOD(SoCoordinate4,callDoAction); + SO_ACTION_ADD_METHOD(SoFont,callDoAction); + SO_ACTION_ADD_METHOD(SoGroup,callDoAction); + SO_ACTION_ADD_METHOD(SoProfile,callDoAction); + SO_ACTION_ADD_METHOD(SoProfileCoordinate2,callDoAction); + SO_ACTION_ADD_METHOD(SoProfileCoordinate3,callDoAction); + SO_ACTION_ADD_METHOD(SoTransformation,callDoAction); + SO_ACTION_ADD_METHOD(SoSwitch,callDoAction); + + SO_ACTION_ADD_METHOD(SoSeparator,callDoAction); + SO_ACTION_ADD_METHOD(SoFCSelection,callDoAction); + + SO_ACTION_ADD_METHOD(SoIndexedLineSet,callDoAction); + SO_ACTION_ADD_METHOD(SoIndexedFaceSet,callDoAction); + SO_ACTION_ADD_METHOD(SoPointSet,callDoAction); +} + +void SoFCHighlightAction::finish() +{ + atexit_cleanup(); +} + + +SoFCHighlightAction::SoFCHighlightAction (const SelectionChanges &SelCh) +:SelChange(SelCh) +{ + SO_ACTION_CONSTRUCTOR(SoFCHighlightAction); +} + + +SoFCHighlightAction::~SoFCHighlightAction() +{ +} + + +void SoFCHighlightAction::beginTraversal(SoNode *node) +{ + traverse(node); +} + +void SoFCHighlightAction::callDoAction(SoAction *action,SoNode *node) +{ + node->doAction(action); +} + +// --------------------------------------------------------------- + SO_ACTION_SOURCE(SoFCSelectionAction); /** diff --git a/src/Gui/SoFCSelectionAction.h b/src/Gui/SoFCSelectionAction.h index 78b965bdae..92d650672b 100644 --- a/src/Gui/SoFCSelectionAction.h +++ b/src/Gui/SoFCSelectionAction.h @@ -38,6 +38,31 @@ namespace Gui { class SelectionChanges; +/** + * The SoFCHighlightAction class is used to inform an SoFCSelection node + * whether an object gets highlighted. + * @author Jürgen Riegel + */ +class GuiExport SoFCHighlightAction : public SoAction +{ + SO_ACTION_HEADER(SoFCHighlightAction); + +public: + SoFCHighlightAction (const SelectionChanges &SelCh); + ~SoFCHighlightAction(); + + static void initClass(); + static void finish(void); + + const SelectionChanges &SelChange; + +protected: + virtual void beginTraversal(SoNode *node); + +private: + static void callDoAction(SoAction *action,SoNode *node); +}; + /** * The SoFCSelectionAction class is used to inform an SoFCSelection node * whether an object gets selected. diff --git a/src/Gui/SoFCUnifiedSelection.cpp b/src/Gui/SoFCUnifiedSelection.cpp index 7b94d90912..d6a18efba1 100644 --- a/src/Gui/SoFCUnifiedSelection.cpp +++ b/src/Gui/SoFCUnifiedSelection.cpp @@ -119,6 +119,7 @@ SoFCUnifiedSelection::SoFCUnifiedSelection() : pcDocument(0) SO_NODE_SET_SF_ENUM_TYPE (highlightMode, HighlightModes); highlighted = false; + setPreSelection = false; preSelection = -1; } @@ -268,6 +269,19 @@ void SoFCUnifiedSelection::doAction(SoAction *action) this->colorHighlight = colaction->highlightColor; } + if (highlightMode.getValue() != OFF && action->getTypeId() == SoFCHighlightAction::getClassTypeId()) { + SoFCHighlightAction *hilaction = static_cast(action); + // Do not clear currently highlighted object when setting new pre-selection + if (!setPreSelection && hilaction->SelChange.Type == SelectionChanges::RmvPreselect) { + if (currenthighlight) { + SoHighlightElementAction action; + action.apply(currenthighlight); + currenthighlight->unref(); + currenthighlight = 0; + } + } + } + if (selectionMode.getValue() == ON && action->getTypeId() == SoFCSelectionAction::getClassTypeId()) { SoFCSelectionAction *selaction = static_cast(action); if (selaction->SelChange.Type == SelectionChanges::AddSelection || @@ -391,6 +405,7 @@ SoFCUnifiedSelection::handleEvent(SoHandleEventAction * action) getMainWindow()->showMessage(QString::fromUtf8(buf)); + setPreSelection = true; if (Gui::Selection().setPreselect(documentName.c_str() ,objectName.c_str() ,subElementName.c_str() @@ -421,6 +436,8 @@ SoFCUnifiedSelection::handleEvent(SoHandleEventAction * action) currenthighlight->ref(); } } + + setPreSelection = false; } // nothing picked else if (!pp) { diff --git a/src/Gui/SoFCUnifiedSelection.h b/src/Gui/SoFCUnifiedSelection.h index 0dbaae2071..438c0f6320 100644 --- a/src/Gui/SoFCUnifiedSelection.h +++ b/src/Gui/SoFCUnifiedSelection.h @@ -101,6 +101,7 @@ private: static SoFullPath * currenthighlight; SbBool highlighted; + SbBool setPreSelection; // -1 = not handled, 0 = not selected, 1 = selected int32_t preSelection; SoColorPacker colorpacker; diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 6f987e3bb2..b5a41529dc 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -602,6 +602,10 @@ void View3DInventorViewer::OnChange(Gui::SelectionSingleton::SubjectType& rCalle SoFCSelectionAction cAct(Reason); cAct.apply(pcViewProviderRoot); } + else if (Reason.Type == SelectionChanges::RmvPreselect) { + SoFCHighlightAction cAct(Reason); + cAct.apply(pcViewProviderRoot); + } } /// @endcond