From e26a57011d4af734a2a82c2fca151424a8efc60e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 31 Aug 2018 15:13:58 +0200 Subject: [PATCH] #3296 caf::SelectionManager: Refactoring to avoid sending multiple selection changes Must be considered if using the CmdSelectionGangeExec --- .../RicPointTangentManipulator.cpp | 21 ++- .../RicPointTangentManipulator.h | 4 +- .../cafCommand/cafCmdSelectionChangeExec.cpp | 4 +- .../cafCommand/cafCmdSelectionHelper.cpp | 1 + .../cafSelectionChangedReceiver.h | 4 +- .../cafPdmUiCore/cafSelectionManager.cpp | 148 +++++++++++++++--- .../cafPdmUiCore/cafSelectionManager.h | 40 +++-- .../cafPdmUiTableViewEditor.cpp | 31 ++-- .../cafPdmUiTableViewEditor.h | 2 +- .../cafPdmUiTreeViewEditor.cpp | 1 - 10 files changed, 196 insertions(+), 60 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulator.cpp b/ApplicationCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulator.cpp index 0fc70a68bf..9001dc8615 100644 --- a/ApplicationCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulator.cpp +++ b/ApplicationCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulator.cpp @@ -107,6 +107,7 @@ bool RicPointTangentManipulator::eventFilter(QObject *obj, QEvent* inputEvent) if(m_partManager->isManipulatorActive()) { + emit notifySelected(); emit notifyRedraw(); return true; @@ -307,7 +308,6 @@ void RicPointTangentManipulatorPartMgr::tryToActivateManipulator(const cvf::HitI m_tangentOnStartManipulation = m_tangent; m_originOnStartManipulation = m_origin; m_currentHandleIndex = i; - caf::SelectionManager::instance()->clear(caf::SelectionManager::FIRST_LEVEL); } } @@ -639,9 +639,9 @@ PdmUiSelectionVisualizer3d::~PdmUiSelectionVisualizer3d() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiSelectionVisualizer3d::onSelectionManagerSelectionChanged(int selectionLevel) +void PdmUiSelectionVisualizer3d::onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) { - if (selectionLevel != 0) return; + if (!changedSelectionLevels.count(0)) return; for (auto editor: m_active3DEditors) { @@ -805,6 +805,10 @@ void RicWellTarget3dEditor::configureAndUpdateUi(const QString& uiConfigName) SIGNAL( notifyUpdate(const cvf::Vec3d& , const cvf::Vec3d& ) ), this, SLOT( slotUpdated(const cvf::Vec3d& , const cvf::Vec3d& ) ) ); + QObject::connect(m_manipulator, + SIGNAL( notifySelected() ), + this, + SLOT( slotSelectedIn3D() ) ); m_cvfModel = new cvf::ModelBasicList; m_ownerViewer->addStaticModelOnce(m_cvfModel.p()); } @@ -873,3 +877,14 @@ void RicWellTarget3dEditor::slotUpdated(const cvf::Vec3d& origin, const cvf::Vec std::cout << "RicWellTarget3dEditor::slotUpdated() end" << std::endl; } + +void RicWellTarget3dEditor::slotSelectedIn3D() +{ + RimWellPathTarget* target = dynamic_cast(this->pdmObject()); + if ( !target) + { + return; + } + + caf::SelectionManager::instance()->setSelectedItemAtLevel(target, caf::SelectionManager::FIRST_LEVEL); +} \ No newline at end of file diff --git a/ApplicationCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulator.h b/ApplicationCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulator.h index 65f57ad6ac..4d53c2a9fb 100644 --- a/ApplicationCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulator.h +++ b/ApplicationCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulator.h @@ -59,6 +59,7 @@ public: void appendPartsToModel(cvf::ModelBasicList* model); signals: + void notifySelected(); void notifyRedraw(); void notifyUpdate(const cvf::Vec3d& origin, const cvf::Vec3d& tangent); @@ -229,7 +230,7 @@ public: PdmUiSelectionVisualizer3d(caf::Viewer* ownerViewer); ~PdmUiSelectionVisualizer3d(); protected: - virtual void onSelectionManagerSelectionChanged(int selectionLevel) override; + virtual void onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) override; std::vector< QPointer > m_active3DEditors; @@ -284,6 +285,7 @@ protected: private slots: void slotUpdated(const cvf::Vec3d& origin, const cvf::Vec3d& tangent); + void slotSelectedIn3D(); private: QPointer m_manipulator; cvf::ref m_cvfModel; diff --git a/Fwk/AppFwk/cafCommand/cafCmdSelectionChangeExec.cpp b/Fwk/AppFwk/cafCommand/cafCmdSelectionChangeExec.cpp index 31067d8342..fab5475222 100644 --- a/Fwk/AppFwk/cafCommand/cafCmdSelectionChangeExec.cpp +++ b/Fwk/AppFwk/cafCommand/cafCmdSelectionChangeExec.cpp @@ -58,7 +58,7 @@ QString CmdSelectionChangeExec::name() //-------------------------------------------------------------------------------------------------- void CmdSelectionChangeExec::redo() { - SelectionManager::instance()->setSelectionFromReferences(m_commandData->m_newSelection.v(), m_commandData->m_selectionLevel.v()); + SelectionManager::instance()->setSelectionAtLevelFromReferences(m_commandData->m_newSelection.v(), m_commandData->m_selectionLevel.v()); } //-------------------------------------------------------------------------------------------------- @@ -66,7 +66,7 @@ void CmdSelectionChangeExec::redo() //-------------------------------------------------------------------------------------------------- void CmdSelectionChangeExec::undo() { - SelectionManager::instance()->setSelectionFromReferences(m_commandData->m_previousSelection.v(), m_commandData->m_selectionLevel.v()); + SelectionManager::instance()->setSelectionAtLevelFromReferences(m_commandData->m_previousSelection.v(), m_commandData->m_selectionLevel.v()); } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafCommand/cafCmdSelectionHelper.cpp b/Fwk/AppFwk/cafCommand/cafCmdSelectionHelper.cpp index d2d461e975..f8ccf61a14 100644 --- a/Fwk/AppFwk/cafCommand/cafCmdSelectionHelper.cpp +++ b/Fwk/AppFwk/cafCommand/cafCmdSelectionHelper.cpp @@ -63,6 +63,7 @@ CmdSelectionChangeExec* CmdSelectionHelper::createSelectionCommand(const std::ve { CmdSelectionChangeExec* selectionChangeExec = new CmdSelectionChangeExec(SelectionManager::instance()->notificationCenter()); selectionChangeExec->commandData()->m_selectionLevel.v() = selectionLevel; + SelectionManager::instance()->selectionAsReferences(selectionChangeExec->commandData()->m_previousSelection.v(), selectionLevel); for (size_t i = 0; i < selection.size(); i++) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionChangedReceiver.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionChangedReceiver.h index 13def31dfa..296c14a67e 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionChangedReceiver.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionChangedReceiver.h @@ -35,6 +35,8 @@ //################################################################################################## #pragma once +#include + namespace caf { class SelectionChangedReceiver @@ -46,7 +48,7 @@ public: protected: friend class SelectionManager; /// Called whenever caf::SelectionManager's selection changes - virtual void onSelectionManagerSelectionChanged(int selectionLevel) = 0; + virtual void onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) = 0; }; } diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.cpp index 1550c6f0c7..8d513543bf 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.cpp @@ -87,37 +87,131 @@ void SelectionManager::selectedItems(std::vector& items, int selecti //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void SelectionManager::setSelectedItems(const std::vector& items, int selectionLevel /*= 0*/) +void SelectionManager::setSelectedItems(const std::vector& items) { - std::vector< std::pair, PdmUiItem*> >& selection = m_selectionPrLevel[selectionLevel]; - std::vector< std::pair, PdmUiItem*> > newSelection; + std::map , PdmUiItem*> > > newCompleteSelectionMap; - for (size_t i = 0; i < items.size(); i++) + std::vector< std::pair, PdmUiItem*> > & newSelection = newCompleteSelectionMap[0]; + + extractInternalSelectionItems(items, &newSelection); + + std::set changedLevels = findChangedLevels(newCompleteSelectionMap); + + if ( !changedLevels.empty() ) + { + m_selectionPrLevel = newCompleteSelectionMap; + notifySelectionChanged(changedLevels); + } +} + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void SelectionManager::extractInternalSelectionItems(const std::vector &items, + std::vector, PdmUiItem *>> *newSelection) +{ + for ( size_t i = 0; i < items.size(); i++ ) { PdmUiFieldHandle* fieldHandle = dynamic_cast(items[i]); - if (fieldHandle) + if ( fieldHandle ) { PdmObjectHandle* obj = fieldHandle->fieldHandle()->ownerObject(); - newSelection.push_back(std::make_pair(obj, fieldHandle)); + newSelection->push_back(std::make_pair(obj, fieldHandle)); } else { PdmUiObjectHandle* obj = dynamic_cast(items[i]); - if (obj) + if ( obj ) { - newSelection.push_back(std::make_pair(obj->objectHandle(), obj)); + newSelection->push_back(std::make_pair(obj->objectHandle(), obj)); } } } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void SelectionManager::setSelectedItemsAtLevel(const std::vector& items, int selectionLevel) +{ + std::vector< std::pair, PdmUiItem*> >& selection = m_selectionPrLevel[selectionLevel]; + std::vector< std::pair, PdmUiItem*> > newSelection; + + extractInternalSelectionItems(items, &newSelection); if (newSelection != selection) { selection = newSelection; - notifySelectionChanged(selectionLevel); + notifySelectionChanged({selectionLevel}); } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void SelectionManager::setSelection(const std::vector< SelectionItem > completeSelection) +{ + std::map , PdmUiItem*> > > newCompleteSelectionMap; + std::map > newSelectionPrLevel; + + for (const SelectionItem& item: completeSelection) + { + newSelectionPrLevel[item.selectionLevel].push_back(item.item); + } + + for (auto& levelItemsPair: newSelectionPrLevel) + { + std::vector< std::pair, PdmUiItem*> > & newSelectionLevel = newCompleteSelectionMap[levelItemsPair.first]; + extractInternalSelectionItems(levelItemsPair.second, &newSelectionLevel); + } + + std::set changedLevels = findChangedLevels(newCompleteSelectionMap); + + if ( !changedLevels.empty()) + { + m_selectionPrLevel = newCompleteSelectionMap; + notifySelectionChanged(changedLevels); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set SelectionManager::findChangedLevels(const std::map, PdmUiItem *>>> & newCompleteSelectionMap ) const +{ + std::set changedLevels; + + // Compare the existing levels with the corresponding levels in the new selection + + for ( auto& levelSelectionPair : m_selectionPrLevel ) + { + auto it = newCompleteSelectionMap.find(levelSelectionPair.first); + if ( it != newCompleteSelectionMap.end() ) + { + if ( levelSelectionPair.second != it->second ) changedLevels.insert(levelSelectionPair.first); + } + else + { + if ( !levelSelectionPair.second.empty() ) changedLevels.insert(levelSelectionPair.first); + } + } + + // Add each of the levels in the new selection that are not present in the existing selection + for ( auto& levelSelectionPair : newCompleteSelectionMap ) + { + auto it = m_selectionPrLevel.find(levelSelectionPair.first); + if ( it == m_selectionPrLevel.end() ) + { + changedLevels.insert(levelSelectionPair.first); + } + } + + return changedLevels; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -142,12 +236,23 @@ PdmUiItem* SelectionManager::selectedItem(int selectionLevel /*= 0*/) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void SelectionManager::setSelectedItem(PdmUiItem* item, int selectionLevel /*= 0*/) +void SelectionManager::setSelectedItem(PdmUiItem* item) { std::vector singleSelection; singleSelection.push_back(item); - setSelectedItems(singleSelection, selectionLevel); + setSelectedItems(singleSelection); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void SelectionManager::setSelectedItemAtLevel(PdmUiItem* item, int selectionLevel) +{ + std::vector singleSelection; + singleSelection.push_back(item); + + setSelectedItemsAtLevel(singleSelection, selectionLevel); } //-------------------------------------------------------------------------------------------------- @@ -187,7 +292,7 @@ void SelectionManager::selectionAsReferences(std::vector& referenceList //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void SelectionManager::setSelectionFromReferences(const std::vector& referenceList, int selectionLevel /*= 0*/) +void SelectionManager::setSelectionAtLevelFromReferences(const std::vector& referenceList, int selectionLevel /*= 0*/) { std::vector uiItems; @@ -206,7 +311,7 @@ void SelectionManager::setSelectionFromReferences(const std::vector& re } } - setSelectedItems(uiItems, selectionLevel); + setSelectedItemsAtLevel(uiItems, selectionLevel); } //-------------------------------------------------------------------------------------------------- @@ -253,10 +358,10 @@ void SelectionManager::clearAll() } m_selectionPrLevel.clear(); - - for (int level: changedSelectionLevels) + + if ( changedSelectionLevels.size() ) { - notifySelectionChanged(level); + notifySelectionChanged(changedSelectionLevels); } } @@ -274,18 +379,18 @@ void SelectionManager::clear(int selectionLevel) { m_selectionPrLevel[selectionLevel].clear(); - notifySelectionChanged(selectionLevel); + notifySelectionChanged({selectionLevel}); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void SelectionManager::notifySelectionChanged( int selectionLevel) +void SelectionManager::notifySelectionChanged( const std::set& changedSelectionLevels ) { for (auto receiver: m_selectionReceivers) { - receiver->onSelectionManagerSelectionChanged(selectionLevel); + receiver->onSelectionManagerSelectionChanged(changedSelectionLevels); } } @@ -324,10 +429,7 @@ void SelectionManager::removeObjectFromAllSelections(PdmObjectHandle* pdmObject) } } - for (int level: changedSelectionLevels) - { - notifySelectionChanged(level); - } + notifySelectionChanged(changedSelectionLevels); } void SelectionManager::setPdmRootObject(PdmObjectHandle* root) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.h index ae0a64a8f9..4668b3c627 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.h @@ -69,23 +69,21 @@ public: public: static SelectionManager* instance(); - // OBSOLETE ! Remove when time to refactor the command system - NotificationCenter* notificationCenter(); - - void setActiveChildArrayFieldHandle(PdmChildArrayFieldHandle* childArray); - PdmChildArrayFieldHandle* activeChildArrayFieldHandle(); - - void setPdmRootObject(PdmObjectHandle* root); - PdmObjectHandle* pdmRootObject() { return m_rootObject; } - PdmUiItem* selectedItem(int selectionLevel = 0); - void setSelectedItem(PdmUiItem* item, int selectionLevel = 0); - void selectedItems(std::vector& items, int selectionLevel = 0); - void setSelectedItems(const std::vector& items, int selectionLevel = 0); + + void setSelectedItem(PdmUiItem* item); + void setSelectedItemAtLevel(PdmUiItem* item, int selectionLevel); + + void setSelectedItems(const std::vector& items); + void setSelectedItemsAtLevel(const std::vector& items, int selectionLevel = 0); + + struct SelectionItem { PdmUiItem* item; int selectionLevel; }; + void setSelection(const std::vector< SelectionItem > completeSelection); + void selectionAsReferences(std::vector& referenceList, int selectionLevel = 0) const; - void setSelectionFromReferences(const std::vector& referenceList, int selectionLevel = 0); + void setSelectionAtLevelFromReferences(const std::vector& referenceList, int selectionLevel); bool isSelected(PdmUiItem* item, int selectionLevel) const; @@ -150,10 +148,24 @@ public: return nullptr; } + // OBSOLETE ! Remove when time to refactor the command system + NotificationCenter* notificationCenter(); + + void setActiveChildArrayFieldHandle(PdmChildArrayFieldHandle* childArray); + PdmChildArrayFieldHandle* activeChildArrayFieldHandle(); + + void setPdmRootObject(PdmObjectHandle* root); + PdmObjectHandle* pdmRootObject() { return m_rootObject; } + // End OBSOLETE + private: SelectionManager(); - void notifySelectionChanged( int selectionLevel); + static void extractInternalSelectionItems(const std::vector &items, + std::vector, PdmUiItem *>> *internalSelectionItems); + + void notifySelectionChanged( const std::set& changedSelectionLevels ); + std::set findChangedLevels(const std::map, PdmUiItem *>>> &newCompleteSelectionMap) const; friend class SelectionChangedReceiver; void registerSelectionChangedReceiver ( SelectionChangedReceiver* receiver) { m_selectionReceivers.insert(receiver);} diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewEditor.cpp index 42342fe7c1..52136b420e 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewEditor.cpp @@ -282,11 +282,11 @@ void PdmUiTableViewEditor::setRowSelectionLevel(int selectionLevel) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiTableViewEditor::onSelectionManagerSelectionChanged(int selectionLevel) +void PdmUiTableViewEditor::onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) { if (m_isBlockingSelectionManagerChanged) return; - if (isSelectionRoleDefined() && (m_rowSelectionLevel == selectionLevel)) + if (isSelectionRoleDefined() && (changedSelectionLevels.count(m_rowSelectionLevel) )) { std::vector items; SelectionManager::instance()->selectedItems(items, m_rowSelectionLevel); @@ -355,21 +355,24 @@ void PdmUiTableViewEditor::updateSelectionManagerFromTableSelection() } } - std::vector items { selectedRowObjects.begin(), selectedRowObjects.end() }; + std::vector newCompleteSelection; + + for (auto item : selectedRowObjects) + { + newCompleteSelection.push_back({ item, m_rowSelectionLevel }); + } + + + if ( childArrayFieldHandle() && childArrayFieldHandle()->ownerObject() ) + { + newCompleteSelection.push_back({ childArrayFieldHandle()->ownerObject()->uiCapability() , + m_tableSelectionLevel }); + } m_isBlockingSelectionManagerChanged = true; - { - SelectionManager::instance()->clearAll(); - - if (childArrayFieldHandle() && childArrayFieldHandle()->ownerObject()) - { - SelectionManager::instance()->setSelectedItem(childArrayFieldHandle()->ownerObject()->uiCapability(), - m_tableSelectionLevel); - } - - SelectionManager::instance()->setSelectedItems(items, m_rowSelectionLevel); - } + SelectionManager::instance()->setSelection(newCompleteSelection); m_isBlockingSelectionManagerChanged = false; + } } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewEditor.h index fb99b5dada..acd0e9dc4e 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTableViewEditor.h @@ -128,7 +128,7 @@ protected: QWidget* createLabelWidget(QWidget * parent) override; virtual void configureAndUpdateUi(const QString& uiConfigName) override; - virtual void onSelectionManagerSelectionChanged(int selectionLevel) override; + virtual void onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) override; private: void selectedUiItems(const QModelIndexList& modelIndexList, std::vector& objects); diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp index ea4266873f..0d6e90260c 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp @@ -384,7 +384,6 @@ void PdmUiTreeViewEditor::updateSelectionManager() std::vector items; this->selectedUiItems(items); - SelectionManager::instance()->clearAll(); SelectionManager::instance()->setSelectedItems(items); } }