From 625d7e684ede7a41016b80061113b01d677598eb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 19 Oct 2026 09:40:46 +0200 Subject: [PATCH] #12925: Apply global curve appearance to summary plots and ensemble curve sets --- .../RicNewSummaryEnsembleCurveSetFeature.cpp | 3 + .../Summary/RimEnsembleCurveSet.cpp | 26 ++ .../Summary/RimEnsembleCurveSet.h | 12 +- .../Summary/RimSummaryCurve.cpp | 14 ++ .../RimSummaryCurveAppearanceCalculator.cpp | 127 ++-------- .../RimSummaryCurveAppearanceCalculator.h | 15 +- .../Summary/RimSummaryPlot.cpp | 234 ++++++++++++++++++ .../ProjectDataModel/Summary/RimSummaryPlot.h | 3 + .../Summary/RimSummaryPlotSourceStepping.cpp | 18 ++ 9 files changed, 321 insertions(+), 131 deletions(-) diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp index 133b77a62a..7daa56433a 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicNewSummaryEnsembleCurveSetFeature.cpp @@ -112,6 +112,9 @@ RimEnsembleCurveSet* RicNewSummaryEnsembleCurveSetFeature::addCurveSet( RimSumma filter->setActive( false ); plot->ensembleCurveSetCollection()->addCurveSet( curveSet ); + + if ( plot->useGlobalCurveAppearance() ) plot->applyDefaultCurveAppearances( { curveSet } ); + return curveSet; } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index 8b13986841..5ef0726bc9 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -32,6 +32,7 @@ #include "SummaryPlotCommands/RicSummaryPlotEditorUi.h" +#include "RimCurveStyleRules.h" #include "RimCustomObjectiveFunction.h" #include "RimCustomObjectiveFunctionCollection.h" #include "RimDeltaSummaryEnsemble.h" @@ -333,6 +334,23 @@ void RimEnsembleCurveSet::setColor( cvf::Color3f color ) computeRealizationColor(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::setColorAndUpdateCurves( cvf::Color3f color ) +{ + setColor( color ); + updateCurveColors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Color3f RimEnsembleCurveSet::color() const +{ + return m_mainEnsembleColor(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1415,7 +1433,15 @@ void RimEnsembleCurveSet::appendColorGroup( caf::PdmUiOrdering& uiOrdering ) if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR ) { + auto plot = firstAncestorOrThisOfType(); + auto rules = RimProject::current() ? RimProject::current()->curveStyleRules() : nullptr; + const auto caseName = summaryEnsemble() ? summaryEnsemble()->name().toStdString() : std::string(); + const bool isColorGlobal = plot && plot->useGlobalCurveAppearance() && rules && rules->controlsColor( summaryAddressY(), caseName ); + m_mainEnsembleColor.uiCapability()->setUiReadOnly( isColorGlobal ); colorsGroup->add( &m_mainEnsembleColor ); + if ( isColorGlobal ) + RimCurveStyleRules::addGlobalAppearanceLink( *colorsGroup, + "The color is controlled by the global curve appearance." ); } else if ( m_colorMode == ColorMode::BY_ENSEMBLE_PARAM ) { diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h index 1c1a53fafd..eec24c1c9e 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h @@ -99,11 +99,13 @@ public: QString name() const; - bool isCurvesVisible() const; - void setColor( cvf::Color3f color ); - void setStatisticsColor( const cvf::Color3f& color ); - void enableStatisticsLables( bool enable ); - QColor mainEnsembleColor() const; + bool isCurvesVisible() const; + void setColor( cvf::Color3f color ); + void setColorAndUpdateCurves( cvf::Color3f color ); + cvf::Color3f color() const; + void setStatisticsColor( const cvf::Color3f& color ); + void enableStatisticsLables( bool enable ); + QColor mainEnsembleColor() const; void loadDataAndUpdate( bool updateParentPlot ); void setParentPlotNoReplot( RiuPlotWidget* plot ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index cdd09962d8..5fb5b3244b 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -31,6 +31,7 @@ #include "Summary/RiaSummaryDefines.h" #include "Summary/RiaSummaryTools.h" +#include "RimCurveStyleRules.h" #include "RimEclipseResultCase.h" #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" @@ -893,7 +894,20 @@ void RimSummaryCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering caf::PdmUiGroup* stackingGroup = uiOrdering.addNewGroup( "Stacking" ); RimStackablePlotCurve::stackingUiOrdering( *stackingGroup ); + const auto plot = firstAncestorOrThisOfType(); + const auto rules = RimProject::current() ? RimProject::current()->curveStyleRules() : nullptr; + const auto caseName = RimCurveStyleSettings::caseName( summaryCaseY() ); + + // Curves without a value for the selected dimensions are not changed by the global appearance + const bool isAppearanceGlobal = + plot && plot->useGlobalCurveAppearance() && firstAncestorOrThisOfType() && rules && + ( rules->controlsColor( summaryAddressY(), caseName ) || rules->controlsSymbol( summaryAddressY(), caseName ) ); + m_curveAppearance->setUiLocked( isAppearanceGlobal ); + caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup( "Appearance" ); + if ( isAppearanceGlobal ) + RimCurveStyleRules::addGlobalAppearanceLink( *appearanceGroup, + "The appearance is controlled by the global curve appearance." ); RimPlotCurve::appearanceUiOrdering( *appearanceGroup ); caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup( "Curve Name" ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp index fc63704538..81b2e3aea3 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp @@ -22,37 +22,22 @@ #include "RiaColorTools.h" #include "RiaPreferencesSummary.h" #include "Summary/RiaSummaryCurveDefinition.h" +#include "Summary/RiaSummaryTools.h" #include "RiuQwtPlotCurve.h" +#include "RifSummaryReaderInterface.h" +#include "RimCurveStyleRules.h" #include "RimProject.h" #include "RimSummaryCase.h" #include "RimSummaryCurve.h" -#include "RifSummaryReaderInterface.h" - #include "cvfVector3.h" #include "cafAssert.h" #include -namespace caf -{ -template <> -void caf::AppEnum::setUp() -{ - addItem( RimSummaryCurveAppearanceCalculator::NONE, "NONE", "None" ); - addItem( RimSummaryCurveAppearanceCalculator::COLOR, "COLOR", "Color" ); - addItem( RimSummaryCurveAppearanceCalculator::SYMBOL, "SYMBOL", "Symbols" ); - addItem( RimSummaryCurveAppearanceCalculator::LINE_STYLE, "LINE_STYLE", "Line Style" ); - addItem( RimSummaryCurveAppearanceCalculator::GRADIENT, "GRADIENT", "Gradient" ); - addItem( RimSummaryCurveAppearanceCalculator::LINE_THICKNESS, "LINE_THICKNESS", "Line Thickness" ); - - setDefault( RimSummaryCurveAppearanceCalculator::NONE ); -} -} // namespace caf - namespace internal { //-------------------------------------------------------------------------------------------------- @@ -99,32 +84,6 @@ RimSummaryCurveAppearanceCalculator::RimSummaryCurveAppearanceCalculator( const init( curveDefVector ); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryCurveAppearanceCalculator::assignDimensions( CurveAppearanceType caseAppearance, - CurveAppearanceType variAppearance, - CurveAppearanceType wellAppearance, - CurveAppearanceType gropAppearance, - CurveAppearanceType regiAppearance ) -{ - m_caseAppearanceType = caseAppearance; - m_varAppearanceType = variAppearance; - m_wellAppearanceType = wellAppearance; - m_groupAppearanceType = gropAppearance; - m_regionAppearanceType = regiAppearance; - - // Update the dimensionCount - m_dimensionCount = 0; - if ( m_caseAppearanceType != NONE ) ++m_dimensionCount; - if ( m_varAppearanceType != NONE ) ++m_dimensionCount; - if ( m_wellAppearanceType != NONE ) ++m_dimensionCount; - if ( m_groupAppearanceType != NONE ) ++m_dimensionCount; - if ( m_regionAppearanceType != NONE ) ++m_dimensionCount; - - updateApperanceIndices(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -259,22 +218,6 @@ std::map RimSummaryCurveAppearanceCalculator::mapNameToAppe return nameToIndex; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryCurveAppearanceCalculator::getDimensions( CurveAppearanceType* caseAppearance, - CurveAppearanceType* variAppearance, - CurveAppearanceType* wellAppearance, - CurveAppearanceType* gropAppearance, - CurveAppearanceType* regiAppearance ) const -{ - *caseAppearance = m_caseAppearanceType; - *variAppearance = m_varAppearanceType; - *wellAppearance = m_wellAppearanceType; - *gropAppearance = m_groupAppearanceType; - *regiAppearance = m_regionAppearanceType; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -425,8 +368,8 @@ cvf::Color3f RimSummaryCurveAppearanceCalculator::computeTintedCurveColorForAddr //-------------------------------------------------------------------------------------------------- void RimSummaryCurveAppearanceCalculator::init( const std::vector& curveDefinitions ) { - m_allSummaryCaseNames = getAllSummaryCaseNames(); - m_allSummaryWellNames = getAllSummaryWellNames(); + m_allSummaryCaseNames = RiaSummaryTools::allSummaryCaseNames(); + m_allSummaryWellNames = RiaSummaryTools::allSummaryWellNames(); for ( const RiaSummaryCurveDefinition& curveDef : curveDefinitions ) { @@ -549,6 +492,16 @@ cvf::Color3f RimSummaryCurveAppearanceCalculator::cycledPaletteColor( int colorI { if ( colorIndex < 0 ) return cvf::Color3f::BLACK; + // The palette selected for the global appearance is only used by plots using it + if ( auto project = RimProject::current() ) + { + auto rules = project->curveStyleRules(); + if ( rules && rules->useGlobalAppearance() ) + { + if ( auto legendColor = rules->autoLegendColor( colorIndex ) ) return *legendColor; + } + } + return RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex ); } @@ -661,53 +614,3 @@ cvf::Color3f RimSummaryCurveAppearanceCalculator::gradeColor( const cvf::Color3f return cvf::Color3f( newColor[0], newColor[1], newColor[2] ); } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::set RimSummaryCurveAppearanceCalculator::getAllSummaryCaseNames() -{ - std::set summaryCaseHashes; - RimProject* proj = RimProject::current(); - - std::vector cases = proj->allSummaryCases(); - for ( RimSummaryCase* rimCase : cases ) - { - summaryCaseHashes.insert( rimCase->summaryHeaderFilename().toUtf8().constData() ); - } - - return summaryCaseHashes; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::set RimSummaryCurveAppearanceCalculator::getAllSummaryWellNames() -{ - std::set summaryWellNames; - RimProject* proj = RimProject::current(); - - std::vector cases = proj->allSummaryCases(); - for ( RimSummaryCase* rimCase : cases ) - { - RifSummaryReaderInterface* reader = nullptr; - if ( rimCase ) - { - reader = rimCase->summaryReader(); - } - - if ( reader ) - { - const std::set allAddresses = reader->allResultAddresses(); - - for ( auto& address : allAddresses ) - { - if ( address.category() == RifEclipseSummaryAddressDefines::SummaryCategory::SUMMARY_WELL ) - { - summaryWellNames.insert( address.wellName() ); - } - } - } - } - return summaryWellNames; -} diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.h index 4b98a2f795..5af2f0a214 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.h @@ -36,6 +36,7 @@ class RimSummaryCurveAppearanceCalculator public: explicit RimSummaryCurveAppearanceCalculator( const std::set& curveDefinitions ); explicit RimSummaryCurveAppearanceCalculator( const std::vector& curveDefinitions ); + enum CurveAppearanceType { NONE, @@ -46,17 +47,6 @@ public: LINE_THICKNESS }; - void assignDimensions( CurveAppearanceType caseAppearance, - CurveAppearanceType variAppearance, - CurveAppearanceType wellAppearance, - CurveAppearanceType gropAppearance, - CurveAppearanceType regiAppearance ); - void getDimensions( CurveAppearanceType* caseAppearance, - CurveAppearanceType* variAppearance, - CurveAppearanceType* wellAppearance, - CurveAppearanceType* gropAppearance, - CurveAppearanceType* regiAppearance ) const; - void setupCurveLook( RimSummaryCurve* curve ); static cvf::Color3f assignColorByPhase( const RifEclipseSummaryAddress& address ); @@ -82,9 +72,6 @@ private: cvf::Color3f gradeColor( const cvf::Color3f& color, float factor ); void assignColorByPhase( RimSummaryCurve* curve, int colorIndex ); - static std::set getAllSummaryCaseNames(); - static std::set getAllSummaryWellNames(); - cvf::Color3f m_currentCurveBaseColor; float m_currentCurveGradient; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index a57c121a5b..ca4e59454d 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -35,6 +35,9 @@ #include "Annotations/RimTimeAxisAnnotationUpdater.h" #include "RimAsciiDataCurve.h" +#include "RimCurveStyleRule.h" +#include "RimCurveStyleRules.h" +#include "RimCurveStyleSettings.h" #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" #include "RimGridTimeHistoryCurve.h" @@ -776,12 +779,179 @@ void RimSummaryPlot::applyDefaultCurveAppearances() applyDefaultCurveAppearances( ensembleCurveSetCollection()->curveSets() ); } +namespace +{ +//-------------------------------------------------------------------------------------------------- +/// Project-stored custom rules for specific items of the dimensions selected for color or symbol. Later rules win. +//-------------------------------------------------------------------------------------------------- +std::vector rulesForCurve( RimSummaryCurve* curve ) +{ + auto project = RimProject::current(); + if ( !project || !project->curveStyleRules() ) return {}; + + return project->curveStyleRules()->rulesFor( curve->summaryAddressY(), RimCurveStyleSettings::caseName( curve->summaryCaseY() ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// Custom color for an ensemble curve set, if any. Later matching rules win. +//-------------------------------------------------------------------------------------------------- +std::optional overriddenEnsembleColor( RimEnsembleCurveSet* curveSet ) +{ + auto project = RimProject::current(); + if ( !project || !project->curveStyleRules() ) return std::nullopt; + + const std::string caseName = curveSet->summaryEnsemble() ? curveSet->summaryEnsemble()->name().toStdString() : std::string(); + + const auto colorDimension = project->curveStyleRules()->settings()->colorDimension(); + + std::optional color; + for ( auto rule : project->curveStyleRules()->rulesFor( curveSet->summaryAddressY(), caseName ) ) + { + if ( rule->dimension() == colorDimension && rule->overriddenColor() ) color = rule->overriddenColor(); + } + + return color; +} + +//-------------------------------------------------------------------------------------------------- +/// Maps the values of a dimension to indices used to pick palette colors and symbols. Cases and wells are +/// indexed among all items in the project to give the same item the same look in every plot, all other +/// dimensions among the values present in the plot. +//-------------------------------------------------------------------------------------------------- +class DimensionIndexer +{ +public: + using Settings = RimCurveStyleSettings; + + DimensionIndexer( Settings::Dimension dimension, const std::set& curveDefs ) + : m_dimension( dimension ) + { + if ( dimension == Settings::Dimension::NONE ) return; + + if ( dimension == Settings::Dimension::CASE || dimension == Settings::Dimension::WELL ) + { + auto rules = RimProject::current()->curveStyleRules(); + rules->registerItemNames( dimension, RimCurveStyleRule::availableNames( dimension ) ); + for ( const auto& [name, index] : rules->itemIndices( dimension ) ) + { + m_indices[name.toStdString()] = index; + } + } + else + { + std::set values; + for ( const auto& curveDef : curveDefs ) + { + auto value = Settings::dimensionValue( dimension, curveDef.summaryAddressY(), caseName( curveDef ) ); + if ( !value.empty() ) values.insert( value ); + } + + int index = 0; + for ( const auto& value : values ) + { + m_indices[value] = index++; + } + } + } + + static std::string caseName( RimSummaryCase* summaryCase ) { return Settings::caseName( summaryCase ); } + + static std::string caseName( const RiaSummaryCurveDefinition& curveDef ) + { + if ( curveDef.summaryCaseY() ) return caseName( curveDef.summaryCaseY() ); + return curveDef.ensemble() ? curveDef.ensemble()->name().toStdString() : std::string(); + } + + // -1 if the dimension has no value for the address + int index( const RifEclipseSummaryAddress& address, const std::string& caseName ) const + { + if ( m_dimension == Settings::Dimension::NONE ) return -1; + + const auto it = m_indices.find( Settings::dimensionValue( m_dimension, address, caseName ) ); + return it == m_indices.end() ? -1 : it->second; + } + + Settings::Dimension dimension() const { return m_dimension; } + +private: + Settings::Dimension m_dimension; + std::map m_indices; +}; + +//-------------------------------------------------------------------------------------------------- +/// Color from the global appearance. Vectors can be colored by phase. +//-------------------------------------------------------------------------------------------------- +std::optional globalColor( const DimensionIndexer& indexer, const RifEclipseSummaryAddress& address, const std::string& caseName ) +{ + if ( indexer.dimension() == RimCurveStyleSettings::Dimension::NONE ) return std::nullopt; + + if ( indexer.dimension() == RimCurveStyleSettings::Dimension::VECTOR && RiaPreferencesSummary::current()->colorCurvesByPhase() ) + { + return RimSummaryCurveAppearanceCalculator::assignColorByPhase( address ); + } + + const int index = indexer.index( address, caseName ); + if ( index < 0 ) return std::nullopt; + + return RimSummaryCurveAppearanceCalculator::cycledPaletteColor( index ); +} +} // namespace + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::applyDefaultCurveAppearances( std::vector curvesToUpdate ) { std::set allCurveDefs = summaryAndEnsembleCurveDefinitions(); + + const RimCurveStyleSettings* settings = nullptr; + if ( useGlobalCurveAppearance() ) + { + settings = RimProject::current()->curveStyleRules()->settings(); + + // Indices depend on all curves in the plot, so all curves must be updated to stay consistent + curvesToUpdate = summaryCurves(); + } + + if ( settings ) + { + RimCurveStyleRule::AvailableNamesCache namesCache; + + const auto rules = RimProject::current()->curveStyleRules(); + const DimensionIndexer colorIndexer( settings->colorDimension(), allCurveDefs ); + const DimensionIndexer symbolIndexer( settings->symbolDimension(), allCurveDefs ); + + for ( auto& curve : curvesToUpdate ) + { + const auto address = curve->summaryAddressY(); + const auto caseName = DimensionIndexer::caseName( curve->summaryCaseY() ); + + // Curves without a value for the selected dimensions keep their own appearance and stay editable + if ( !rules->controlsColor( address, caseName ) && !rules->controlsSymbol( address, caseName ) ) continue; + + const auto originalColor = curve->color(); + curve->resetAppearance(); + + // Curves where only the symbol is assigned globally keep their color + if ( !rules->controlsColor( address, caseName ) ) + curve->setColor( originalColor ); + else if ( auto color = globalColor( colorIndexer, address, caseName ) ) + curve->setColor( *color ); + + const int symbolIndex = symbolIndexer.index( address, caseName ); + if ( symbolIndex >= 0 ) curve->setSymbol( RimSummaryCurveAppearanceCalculator::cycledSymbol( symbolIndex ) ); + + curve->setCurveAppearanceFromCaseType(); + + for ( auto rule : rulesForCurve( curve ) ) + { + rule->applyToCurve( curve, rule->dimension() == settings->colorDimension(), rule->dimension() == settings->symbolDimension() ); + } + } + + return; + } + RimSummaryCurveAppearanceCalculator curveLookCalc( allCurveDefs ); for ( auto& curve : curvesToUpdate ) @@ -791,11 +961,58 @@ void RimSummaryPlot::applyDefaultCurveAppearances( std::vector } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSummaryPlot::useGlobalCurveAppearance() const +{ + auto project = RimProject::current(); + if ( !project || !project->curveStyleRules() ) return false; + + return project->curveStyleRules()->useGlobalAppearance(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::updateCurveAppearanceFromGlobalSettings() +{ + if ( !useGlobalCurveAppearance() ) return; + + applyGlobalCurveAppearance(); + loadDataAndUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::applyGlobalCurveAppearance() +{ + if ( !useGlobalCurveAppearance() ) return; + + RimCurveStyleRule::AvailableNamesCache namesCache; + + applyDefaultCurveAppearances( summaryCurves() ); + applyDefaultCurveAppearances( ensembleCurveSetCollection()->curveSets() ); + + updateConnectedEditors(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::applyDefaultCurveAppearances( std::vector ensembleCurvesToUpdate ) { + // Indices depend on all curve sets in the plot, so all must be updated to stay consistent + RimCurveStyleRule::AvailableNamesCache namesCache; + std::optional globalColorIndexer; + if ( useGlobalCurveAppearance() ) + { + ensembleCurvesToUpdate = ensembleCurveSetCollection()->curveSets(); + globalColorIndexer.emplace( RimProject::current()->curveStyleRules()->settings()->colorDimension(), + summaryAndEnsembleCurveDefinitions() ); + } + std::vector usedColors; for ( auto c : ensembleCurveSetCollection()->curveSets() ) { @@ -820,7 +1037,24 @@ void RimSummaryPlot::applyDefaultCurveAppearances( std::vectorcolorMode() ) ) { + if ( globalColorIndexer ) + { + const auto caseName = curveSet->summaryEnsemble() ? curveSet->summaryEnsemble()->name().toStdString() : std::string(); + if ( auto overrideColor = overriddenEnsembleColor( curveSet ) ) + { + curveSet->setColorAndUpdateCurves( *overrideColor ); + } + else if ( auto color = globalColor( *globalColorIndexer, adr, caseName ) ) + { + curveSet->setColorAndUpdateCurves( *color ); + } + + // Curve sets without a value for the color dimension keep their own color + continue; + } + std::vector candidateColors; + if ( RiaPreferencesSummary::current()->colorCurvesByPhase() ) { // Put the the phase color as first candidate, will then be used if there is only one ensemble in the plot diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h index 803a0c8254..1bc042bc26 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -187,6 +187,9 @@ public: void applyDefaultCurveAppearances(); void applyDefaultCurveAppearances( std::vector curvesToUpdate ); void applyDefaultCurveAppearances( std::vector ensembleCurvesToUpdate ); + bool useGlobalCurveAppearance() const; + void updateCurveAppearanceFromGlobalSettings(); + void applyGlobalCurveAppearance(); void setNormalizationEnabled( bool enable ); bool isNormalizationEnabled(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index 680aeec838..c056612e49 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -549,6 +549,24 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle* if ( triggerLoadDataAndUpdate ) { + // Plots using global curve appearance must be restyled after the stepped addresses and cases are updated + std::set plotsToRestyle; + for ( auto curve : curves ) + { + if ( auto plot = curve->firstAncestorOfType() ) plotsToRestyle.insert( plot ); + } + if ( dataSourceSteppingObject() ) + { + for ( auto curveSet : dataSourceSteppingObject()->curveSets() ) + { + if ( auto plot = curveSet->firstAncestorOfType() ) plotsToRestyle.insert( plot ); + } + } + for ( auto plot : plotsToRestyle ) + { + plot->applyGlobalCurveAppearance(); + } + RimSummaryMultiPlot* summaryMultiPlot = dynamic_cast( m_objectForSourceStepping.p() ); if ( summaryMultiPlot ) {