diff --git a/ApplicationCode/Commands/CMakeLists_files.cmake b/ApplicationCode/Commands/CMakeLists_files.cmake index 12c6a76858..5ede27a556 100644 --- a/ApplicationCode/Commands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/CMakeLists_files.cmake @@ -93,6 +93,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicExportContourMapToTextFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicExportContourMapToTextUi.h ${CMAKE_CURRENT_LIST_DIR}/RicNewMultiPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicExportFractureModelPlotToFileFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicStackSelectedCurvesFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicUnstackSelectedCurvesFeature.h ) @@ -184,6 +186,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicExportContourMapToTextFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicExportContourMapToTextUi.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewMultiPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicExportFractureModelPlotToFileFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicStackSelectedCurvesFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicUnstackSelectedCurvesFeature.cpp ) diff --git a/ApplicationCode/Commands/RicStackSelectedCurvesFeature.cpp b/ApplicationCode/Commands/RicStackSelectedCurvesFeature.cpp new file mode 100644 index 0000000000..89adaefe19 --- /dev/null +++ b/ApplicationCode/Commands/RicStackSelectedCurvesFeature.cpp @@ -0,0 +1,149 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicStackSelectedCurvesFeature.h" + +#include "RiaGuiApplication.h" +#include "RiaLogging.h" + +#include "cafPdmFieldIOScriptability.h" +#include "cafPdmObject.h" +#include "cafPdmScriptResponse.h" +#include "cafPdmUiItem.h" +#include "cafSelectionManager.h" + +#include +#include + +RICF_SOURCE_INIT( RicStackSelectedCurvesFeature, "RicStackSelectedCurvesFeature", "stackCurves" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicStackSelectedCurvesFeature::RicStackSelectedCurvesFeature() +{ + CAF_PDM_InitScriptableFieldWithIONoDefault( &m_curves, "curves", "", "", "", "" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector + RicStackSelectedCurvesFeature::plotCurvesFromSelection( const std::vector& selectedItems ) +{ + std::vector selectedPlotCurves; + + for ( caf::PdmUiItem* uiItem : selectedItems ) + { + auto plotCurve = dynamic_cast( uiItem ); + if ( plotCurve ) + { + selectedPlotCurves.push_back( plotCurve ); + } + } + + return selectedPlotCurves; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector + RicStackSelectedCurvesFeature::subsetOfPlotCurvesFromStacking( const std::vector& plotCurves, + bool isStacked ) +{ + std::vector matchingPlotCurves; + + for ( RimPlotCurve* plotCurve : plotCurves ) + { + if ( plotCurve->isStacked() == isStacked ) + { + matchingPlotCurves.push_back( plotCurve ); + } + } + + return matchingPlotCurves; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmScriptResponse RicStackSelectedCurvesFeature::execute() +{ + if ( m_curves().empty() ) + { + return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, "No Curves Provided" ); + } + + for ( auto plotCurve : m_curves() ) + { + plotCurve->setIsStacked( true ); + } + return caf::PdmScriptResponse(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicStackSelectedCurvesFeature::isCommandEnabled() +{ + std::vector selectedItems; + caf::SelectionManager::instance()->selectedItems( selectedItems ); + + auto plotCurves = plotCurvesFromSelection( selectedItems ); + + if ( plotCurves.size() != selectedItems.size() ) return false; + + auto unstackedPlotCurves = subsetOfPlotCurvesFromStacking( plotCurves, false ); + + return !unstackedPlotCurves.empty(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicStackSelectedCurvesFeature::onActionTriggered( bool isChecked ) +{ + std::vector selectedItems; + caf::SelectionManager::instance()->selectedItems( selectedItems ); + + auto plotCurves = plotCurvesFromSelection( selectedItems ); + auto unstackedPlotCurves = subsetOfPlotCurvesFromStacking( plotCurves, false ); + + m_curves.setValue( unstackedPlotCurves ); + + caf::PdmScriptResponse response = execute(); + + if ( response.status() != caf::PdmScriptResponse::COMMAND_OK ) + { + QString displayMessage = response.messages().join( "\n" ); + if ( RiaGuiApplication::isRunning() ) + { + QMessageBox::warning( nullptr, "Error when saving project file", displayMessage ); + } + RiaLogging::error( displayMessage ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicStackSelectedCurvesFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Stack Selected Curves" ); +} diff --git a/ApplicationCode/Commands/RicStackSelectedCurvesFeature.h b/ApplicationCode/Commands/RicStackSelectedCurvesFeature.h new file mode 100644 index 0000000000..5a7387f0af --- /dev/null +++ b/ApplicationCode/Commands/RicStackSelectedCurvesFeature.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RicfCommandObject.h" +#include "RimPlotCurve.h" + +#include "cafCmdFeature.h" +#include "cafPdmPtrArrayField.h" + +#include +//================================================================================================== +/// +//================================================================================================== +class RicStackSelectedCurvesFeature : public caf::CmdFeature, public RicfCommandObject +{ + RICF_HEADER_INIT; + +public: + RicStackSelectedCurvesFeature(); + caf::PdmScriptResponse execute() override; + + static std::vector plotCurvesFromSelection( const std::vector& selectedItems ); + static std::vector subsetOfPlotCurvesFromStacking( const std::vector& plotCurves, + bool isStacked ); + +protected: + // Overrides + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + +private: + caf::PdmPtrArrayField m_curves; +}; diff --git a/ApplicationCode/Commands/RicUnstackSelectedCurvesFeature.cpp b/ApplicationCode/Commands/RicUnstackSelectedCurvesFeature.cpp new file mode 100644 index 0000000000..baf025b4c8 --- /dev/null +++ b/ApplicationCode/Commands/RicUnstackSelectedCurvesFeature.cpp @@ -0,0 +1,109 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicUnstackSelectedCurvesFeature.h" + +#include "RiaGuiApplication.h" +#include "RiaLogging.h" + +#include "cafPdmFieldIOScriptability.h" +#include "cafPdmObject.h" +#include "cafPdmScriptResponse.h" +#include "cafPdmUiItem.h" +#include "cafSelectionManager.h" + +#include +#include + +RICF_SOURCE_INIT( RicUnstackSelectedCurvesFeature, "RicUnstackSelectedCurvesFeature", "unstackCurves" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicUnstackSelectedCurvesFeature::RicUnstackSelectedCurvesFeature() +{ + CAF_PDM_InitScriptableFieldWithIONoDefault( &m_curves, "curves", "", "", "", "" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmScriptResponse RicUnstackSelectedCurvesFeature::execute() +{ + if ( m_curves().empty() ) + { + return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, "No Curves Provided" ); + } + + for ( auto plotCurve : m_curves() ) + { + plotCurve->setIsStacked( false ); + } + return caf::PdmScriptResponse(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicUnstackSelectedCurvesFeature::isCommandEnabled() +{ + std::vector selectedItems; + caf::SelectionManager::instance()->selectedItems( selectedItems ); + + auto plotCurves = RicStackSelectedCurvesFeature::plotCurvesFromSelection( selectedItems ); + + if ( plotCurves.size() != selectedItems.size() ) return false; + + auto stackedPlotCurves = RicStackSelectedCurvesFeature::subsetOfPlotCurvesFromStacking( plotCurves, true ); + + return !stackedPlotCurves.empty(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicUnstackSelectedCurvesFeature::onActionTriggered( bool isChecked ) +{ + std::vector selectedItems; + caf::SelectionManager::instance()->selectedItems( selectedItems ); + + auto plotCurves = RicStackSelectedCurvesFeature::plotCurvesFromSelection( selectedItems ); + auto unstackedPlotCurves = RicStackSelectedCurvesFeature::subsetOfPlotCurvesFromStacking( plotCurves, true ); + + m_curves.setValue( unstackedPlotCurves ); + + caf::PdmScriptResponse response = execute(); + + if ( response.status() != caf::PdmScriptResponse::COMMAND_OK ) + { + QString displayMessage = response.messages().join( "\n" ); + if ( RiaGuiApplication::isRunning() ) + { + QMessageBox::warning( nullptr, "Error when saving project file", displayMessage ); + } + RiaLogging::error( displayMessage ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicUnstackSelectedCurvesFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Unstack Selected Curves" ); +} diff --git a/ApplicationCode/Commands/RicUnstackSelectedCurvesFeature.h b/ApplicationCode/Commands/RicUnstackSelectedCurvesFeature.h new file mode 100644 index 0000000000..e3ee60e850 --- /dev/null +++ b/ApplicationCode/Commands/RicUnstackSelectedCurvesFeature.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RicStackSelectedCurvesFeature.h" + +#include "RicfCommandObject.h" +#include "RimPlotCurve.h" + +#include "cafCmdFeature.h" +#include "cafPdmPtrArrayField.h" + +//================================================================================================== +/// +//================================================================================================== +class RicUnstackSelectedCurvesFeature : public caf::CmdFeature, public RicfCommandObject +{ + RICF_HEADER_INIT; + +public: + RicUnstackSelectedCurvesFeature(); + caf::PdmScriptResponse execute() override; + +protected: + // Overrides + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + +private: + caf::PdmPtrArrayField m_curves; +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 18d6d5c4cb..b8b59790c5 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -665,6 +665,9 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicSetSourceSteppingSummaryCurveFeature"; menuBuilder << "RicClearSourceSteppingSummaryCurveFeature"; menuBuilder << "Separator"; + menuBuilder << "RicStackSelectedCurvesFeature"; + menuBuilder << "RicUnstackSelectedCurvesFeature"; + menuBuilder << "Separator"; menuBuilder << "RicCopyReferencesToClipboardFeature"; menuBuilder << "Separator"; menuBuilder << "RicEditSummaryCurveCalculationFeature"; @@ -969,6 +972,10 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.addSeparator(); menuBuilder << "RicConvertGroupToEnsembleFeature"; menuBuilder.addSeparator(); + menuBuilder.addSeparator(); + menuBuilder << "RicStackSelectedCurvesFeature"; + menuBuilder << "RicUnstackSelectedCurvesFeature"; + menuBuilder.addSeparator(); menuBuilder << "RicFlyToObjectFeature"; diff --git a/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp b/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp index 0f12e7033f..83442bb18d 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp @@ -740,6 +740,22 @@ bool RimPlotCurve::isStackedWithPhaseColors() const return m_isStackedWithPhaseColors; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCurve::setIsStacked( bool stacked ) +{ + m_isStacked = stacked; + + if ( !m_isStacked() && m_fillStyle() != Qt::NoBrush ) + { + // Switch off area fill when turning off stacking. + m_fillStyle = Qt::NoBrush; + } + + stackingChanged.send( m_isStacked() ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimPlotCurve.h b/ApplicationCode/ProjectDataModel/RimPlotCurve.h index b903ce3fa8..1e220cb6d4 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotCurve.h +++ b/ApplicationCode/ProjectDataModel/RimPlotCurve.h @@ -125,6 +125,7 @@ public: void assignStackColor( size_t index, size_t count ); bool isStacked() const; bool isStackedWithPhaseColors() const; + void setIsStacked( bool stacked ); protected: virtual QString createCurveAutoName() = 0; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index 303cee2e34..da7ac3bb95 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -1370,10 +1370,10 @@ void RimSummaryPlot::childFieldChangedByUi( const caf::PdmFieldHandle* changedCh //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateStackedCurveData() { + loadDataAndUpdate(); + updateStackedCurveDataForAxis( RiaDefines::PlotAxis::PLOT_AXIS_LEFT ); updateStackedCurveDataForAxis( RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ); - - loadDataAndUpdate(); } //--------------------------------------------------------------------------------------------------