From 643ccd67b893a5ed161b165fe7aa9f49a151ff20 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 19 Apr 2023 15:36:06 +0200 Subject: [PATCH] Improve ensemble curve colors * Use unique_ptr * Improve default assignment of curve appearance * Improve display of color tags in tree view items * Select curve or ensemble instead of plot * Only change curves connected to a Rim-object * Improve color management for ensemble curves Use a base color for statistics curves and set realization curves transparent Make sure new curves are assigned a unique color Harmonize how dropped addresses are handled * Update all tags always The update of tags for a subset of tree nodes is currently broken. Always update all tags. * Add const --- .../RicSummaryPlotBuilder.cpp | 9 +- .../RicSummaryPlotEditorUi.cpp | 15 +- .../Summary/RimEnsembleCurveSet.cpp | 204 ++++++++++++++---- .../Summary/RimEnsembleCurveSet.h | 22 +- .../Summary/RimEnsembleCurveSetCollection.cpp | 2 +- .../Summary/RimEnsembleCurveSetCollection.h | 2 +- .../RimEnsembleCurveSetColorManager.cpp | 12 +- .../Summary/RimEnsembleCurveSetColorManager.h | 6 +- .../Summary/RimEnsembleStatistics.cpp | 16 +- .../Summary/RimEnsembleStatistics.h | 27 ++- .../Summary/RimSummaryPlot.cpp | 163 ++++++++------ .../ProjectDataModel/Summary/RimSummaryPlot.h | 10 +- .../Summary/RimSummaryPlotManager.cpp | 5 +- .../UserInterface/RiuQwtPlotWidget.cpp | 20 +- .../cafUserInterface/cafPdmUiColorEditor.cpp | 13 ++ .../cafUserInterface/cafPdmUiColorEditor.h | 2 + .../cafUserInterface/cafPdmUiTreeAttributes.h | 9 +- .../cafPdmUiTreeViewEditor.cpp | 3 +- .../cafPdmUiTreeViewItemDelegate.cpp | 29 ++- 19 files changed, 399 insertions(+), 170 deletions(-) diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp index 6878880e00..77fd0c6dba 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp @@ -535,14 +535,17 @@ RimSummaryMultiPlot* RicSummaryPlotBuilder::createAndAppendSummaryMultiPlot( con if ( !plots.empty() ) { auto* plot = plots.front(); - RiuPlotMainWindowTools::selectAsCurrentItem( plot ); if ( !plot->curveSets().empty() ) { - RiuPlotMainWindowTools::setExpanded( plot->curveSets().front() ); + RiuPlotMainWindowTools::selectAsCurrentItem( plot->curveSets().front() ); } else if ( !plot->summaryCurves().empty() ) { - RiuPlotMainWindowTools::setExpanded( plot->summaryCurves().front() ); + RiuPlotMainWindowTools::selectAsCurrentItem( plot->summaryCurves().front() ); + } + else + { + RiuPlotMainWindowTools::selectAsCurrentItem( plot ); } } else diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp index 5fc03d14fc..3fe794e0d3 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp @@ -509,10 +509,11 @@ void RicSummaryPlotEditorUi::updatePreviewCurvesFromCurveDefinitions( const std: // Set single curve set color auto allCurveSets = m_previewPlot->ensembleCurveSetCollection()->curveSets(); - size_t colorIndex = std::count_if( allCurveSets.begin(), - allCurveSets.end(), - []( RimEnsembleCurveSet* curveSet ) - { return curveSet->colorMode() == RimEnsembleCurveSet::ColorMode::SINGLE_COLOR; } ); + size_t colorIndex = + std::count_if( allCurveSets.begin(), + allCurveSets.end(), + []( RimEnsembleCurveSet* curveSet ) + { return RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( curveSet->colorMode() ); } ); curveSet->setColor( RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex ) ); // Add curve to plot @@ -831,8 +832,10 @@ void RicSummaryPlotEditorUi::applyAppearanceToAllPreviewCurves() int colorIndex = 0; for ( auto& curveSet : m_previewPlot->ensembleCurveSetCollection()->curveSets() ) { - if ( curveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR ) continue; - curveSet->setColor( RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex++ ) ); + if ( RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( curveSet->colorMode() ) ) + { + curveSet->setColor( RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex++ ) ); + } } } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index 5e3f8440b3..50d9b57253 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -57,6 +57,7 @@ #include "RiuAbstractLegendFrame.h" #include "RiuDraggableOverlayFrame.h" +#include "RiuGuiTheme.h" #include "RiuPlotCurve.h" #include "RiuPlotCurveSymbol.h" #include "RiuPlotMainWindow.h" @@ -64,17 +65,21 @@ #include "RiuTextContentFrame.h" #include "cafPdmObject.h" +#include "cafPdmUiColorEditor.h" #include "cafPdmUiDateEditor.h" +#include "cafPdmUiDoubleSliderEditor.h" #include "cafPdmUiItem.h" #include "cafPdmUiLineEditor.h" #include "cafPdmUiListEditor.h" #include "cafPdmUiPushButtonEditor.h" #include "cafPdmUiSliderEditor.h" +#include "cafPdmUiTreeAttributes.h" #include "cafPdmUiTreeOrdering.h" #include "cafPdmUiTreeSelectionEditor.h" #include "cafTitledOverlayFrame.h" #include +#include //-------------------------------------------------------------------------------------------------- /// @@ -135,9 +140,12 @@ RimEnsembleCurveSet::RimEnsembleCurveSet() CAF_PDM_InitFieldNoDefault( &m_resampling, "Resampling", "Resampling" ); - CAF_PDM_InitField( &m_colorMode, "ColorMode", caf::AppEnum( ColorMode::SINGLE_COLOR ), "Coloring Mode" ); + CAF_PDM_InitField( &m_colorMode, "ColorMode", caf::AppEnum( ColorMode::SINGLE_COLOR_WITH_ALPHA ), "Coloring Mode" ); - CAF_PDM_InitField( &m_color, "Color", RiaColorTools::textColor3f(), "Color" ); + CAF_PDM_InitField( &m_colorForRealizations, "Color", RiaColorTools::textColor3f(), "Color" ); + CAF_PDM_InitField( &m_mainEnsembleColor, "MainEnsembleColor", RiaColorTools::textColor3f(), "Color" ); + CAF_PDM_InitField( &m_colorTransparency, "ColorTransparency", 0.3, "Transparency" ); + m_colorTransparency.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); CAF_PDM_InitField( &m_ensembleParameter, "EnsembleParameter", QString( "" ), "Parameter" ); m_ensembleParameter.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); @@ -221,8 +229,6 @@ RimEnsembleCurveSet::RimEnsembleCurveSet() m_summaryAddressNameTools = new RimSummaryCurveAutoName; - m_plotCurveForLegendText = nullptr; - m_ensembleStatCase.reset( new RimEnsembleStatisticsCase( this ) ); m_ensembleStatCase->createSummaryReaderInterface(); m_ensembleStatCase->createRftReaderInterface(); @@ -265,14 +271,12 @@ RimEnsembleCurveSet::~RimEnsembleCurveSet() m_objectiveFunctionOverlayFrame->setParent( nullptr ); delete m_objectiveFunctionOverlayFrame; } - - delete m_plotCurveForLegendText; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimEnsembleCurveSet::isCurvesVisible() +bool RimEnsembleCurveSet::isCurvesVisible() const { RimEnsembleCurveSetCollection* coll = nullptr; firstAncestorOrThisOfType( coll ); @@ -284,7 +288,25 @@ bool RimEnsembleCurveSet::isCurvesVisible() //-------------------------------------------------------------------------------------------------- void RimEnsembleCurveSet::setColor( cvf::Color3f color ) { - m_color = color; + m_mainEnsembleColor = color; + + setTransparentCurveColor(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::setStatisticsColor( const cvf::Color3f& color ) +{ + m_statistics->setColor( color ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::enableStatisticsLables( bool enable ) +{ + m_statistics->enableCurveLabels( enable ); } //-------------------------------------------------------------------------------------------------- @@ -335,7 +357,6 @@ void RimEnsembleCurveSet::deletePlotCurves() if ( m_plotCurveForLegendText ) { m_plotCurveForLegendText->detach(); - delete m_plotCurveForLegendText; m_plotCurveForLegendText = nullptr; } } @@ -362,7 +383,7 @@ void RimEnsembleCurveSet::addCurve( RimSummaryCurve* curve ) firstAncestorOrThisOfType( plot ); if ( plot && plot->plotWidget() ) curve->setParentPlotNoReplot( plot->plotWidget() ); - curve->setColor( m_color ); + curve->setColor( m_colorForRealizations ); m_curves.push_back( curve ); } } @@ -660,10 +681,14 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi { updateAllCurves(); } - else if ( changedField == &m_color ) + else if ( changedField == &m_colorForRealizations || changedField == &m_mainEnsembleColor || changedField == &m_colorTransparency ) { + setTransparentCurveColor(); + updateCurveColors(); + updateConnectedEditors(); + updateTextInPlot = true; } else if ( changedField == &m_ensembleParameter ) @@ -716,6 +741,7 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi } } + setTransparentCurveColor(); updateCurveColors(); updateTimeAnnotations(); updateObjectiveFunctionLegend(); @@ -863,6 +889,25 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) +{ + if ( auto* treeItemAttribute = dynamic_cast( attribute ) ) + { + treeItemAttribute->tags.clear(); + auto tag = caf::PdmUiTreeViewItemAttribute::Tag::create(); + tag->bgColor = RiaColorTools::toQColor( m_colorForRealizations ); + tag->fgColor = RiaColorTools::toQColor( m_statistics->color() ); + tag->text = "---"; + + tag->clicked.connect( this, &RimEnsembleCurveSet::onColorTagClicked ); + + treeItemAttribute->tags.push_back( std::move( tag ) ); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -894,7 +939,10 @@ void RimEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde } } - caf::PdmUiGroup* statGroup = uiOrdering.addNewGroup( "Statistics" ); + caf::PdmUiGroup* statGroup = uiOrdering.addNewGroup( "Statistics" ); + bool showStatisticsColor = m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR; + m_statistics->showColorField( showStatisticsColor ); + m_statistics->defineUiOrdering( uiConfigName, *statGroup ); uiOrdering.skipRemainingFields( true ); @@ -937,6 +985,68 @@ void RimEnsembleCurveSet::onCustomObjectiveFunctionChanged( const caf::SignalEmi updateObjectiveFunctionLegend(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::setTransparentCurveColor() +{ + if ( m_colorMode() == RimEnsembleCurveSet::ColorMode::SINGLE_COLOR_WITH_ALPHA ) + { + auto backgroundColor = RiuGuiTheme::getColorByVariableName( "backgroundColor1" ); + + auto sourceColor = RiaColorTools::toQColor( m_mainEnsembleColor ); + auto sourceWeight = 100; + int backgroundWeight = std::max( 1, static_cast( sourceWeight * 10 * m_colorTransparency ) ); + auto blendedColor = RiaColorTools::blendQColors( backgroundColor, sourceColor, backgroundWeight, sourceWeight ); + + m_colorForRealizations = RiaColorTools::fromQColorTo3f( blendedColor ); + setStatisticsColor( m_mainEnsembleColor ); + updateStatisticsCurves(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QColor RimEnsembleCurveSet::mainEnsembleColor() const +{ + if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR_WITH_ALPHA ) + { + return RiaColorTools::toQColor( m_mainEnsembleColor ); + } + + return RiaColorTools::toQColor( m_colorForRealizations ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::onColorTagClicked( const SignalEmitter* emitter, size_t index ) +{ + caf::PdmField* colorToModify = nullptr; + if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR ) + { + colorToModify = &m_colorForRealizations; + } + else + { + colorToModify = &m_mainEnsembleColor; + } + + if ( colorToModify ) + { + QColor sourceColor = RiaColorTools::toQColor( *colorToModify ); + QColor newColor = caf::PdmUiColorEditor::getColor( sourceColor ); + + if ( newColor.isValid() && newColor != sourceColor ) + { + auto myColor = RiaColorTools::fromQColorTo3f( newColor ); + + colorToModify->setValueWithFieldChanged( myColor ); + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -957,9 +1067,14 @@ void RimEnsembleCurveSet::appendColorGroup( caf::PdmUiOrdering& uiOrdering ) m_colorMode.uiCapability()->setUiReadOnly( !m_yValuesSummaryCaseCollection() ); colorsGroup->add( &m_colorMode ); - if ( m_colorMode == ColorMode::SINGLE_COLOR ) + if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR ) { - colorsGroup->add( &m_color ); + colorsGroup->add( &m_colorForRealizations ); + } + else if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR_WITH_ALPHA ) + { + colorsGroup->add( &m_mainEnsembleColor ); + colorsGroup->add( &m_colorTransparency ); } else if ( m_colorMode == ColorMode::BY_ENSEMBLE_PARAM ) { @@ -1008,6 +1123,8 @@ void RimEnsembleCurveSet::appendColorGroup( caf::PdmUiOrdering& uiOrdering ) } } } + + uiOrdering.skipRemainingFields(); } //-------------------------------------------------------------------------------------------------- @@ -1073,22 +1190,28 @@ caf::PdmFieldHandle* RimEnsembleCurveSet::objectToggleField() //-------------------------------------------------------------------------------------------------- void RimEnsembleCurveSet::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) { - caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast( attribute ); - if ( attrib ) + if ( auto* attrib = dynamic_cast( attribute ) ) { attrib->m_buttonText = "..."; } + if ( field == &m_minTimeStep || field == &m_maxTimeStep ) { - caf::PdmUiSliderEditorAttribute* myAttr = dynamic_cast( attribute ); - if ( !myAttr ) + if ( auto* myAttr = dynamic_cast( attribute ) ) { - return; + myAttr->m_minimum = *allAvailableTimeSteps().begin(); + myAttr->m_maximum = *allAvailableTimeSteps().rbegin(); + myAttr->m_showSpinBox = false; + } + } + if ( field == &m_colorTransparency ) + { + if ( auto* myAttr = dynamic_cast( attribute ) ) + { + myAttr->m_minimum = 0.001; + myAttr->m_maximum = 1.0; + myAttr->m_decimals = 2; } - - myAttr->m_minimum = *allAvailableTimeSteps().begin(); - myAttr->m_maximum = *allAvailableTimeSteps().rbegin(); - myAttr->m_showSpinBox = false; } } @@ -1113,12 +1236,14 @@ QList RimEnsembleCurveSet::calculateValueOptions( const } else if ( fieldNeedingOptions == &m_colorMode ) { - auto singleColorOption = ColorModeEnum( ColorMode::SINGLE_COLOR ); - auto byEnsParamOption = ColorModeEnum( ColorMode::BY_ENSEMBLE_PARAM ); - auto byObjFuncOption = ColorModeEnum( ColorMode::BY_OBJECTIVE_FUNCTION ); - auto byCustomObjFuncOption = ColorModeEnum( ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION ); + auto singleColorOption = ColorModeEnum( ColorMode::SINGLE_COLOR ); + auto singleColorWithAlphaOption = ColorModeEnum( ColorMode::SINGLE_COLOR_WITH_ALPHA ); + auto byEnsParamOption = ColorModeEnum( ColorMode::BY_ENSEMBLE_PARAM ); + auto byObjFuncOption = ColorModeEnum( ColorMode::BY_OBJECTIVE_FUNCTION ); + auto byCustomObjFuncOption = ColorModeEnum( ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION ); options.push_back( caf::PdmOptionItemInfo( singleColorOption.uiText(), ColorMode::SINGLE_COLOR ) ); + options.push_back( caf::PdmOptionItemInfo( singleColorWithAlphaOption.uiText(), ColorMode::SINGLE_COLOR_WITH_ALPHA ) ); RimSummaryCaseCollection* group = m_yValuesSummaryCaseCollection(); if ( group && group->hasEnsembleParameters() ) @@ -1493,9 +1618,9 @@ std::vector RimEnsembleCurveSet::generateColorsForCases( const std } } } - else if ( m_colorMode == ColorMode::SINGLE_COLOR ) + else if ( RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( m_colorMode() ) ) { - caseColors.resize( summaryCases.size(), m_color ); + caseColors.resize( summaryCases.size(), m_colorForRealizations ); } else if ( m_colorMode == ColorMode::BY_OBJECTIVE_FUNCTION ) { @@ -1551,7 +1676,7 @@ void RimEnsembleCurveSet::updateCurveColors() { updateLegendTitle(); - // Fint the curves to color (skip the statistics) + // Find the curves to color (skip the statistics) std::vector curvesToColor; std::vector summaryCases; for ( auto& curve : m_curves ) @@ -1575,14 +1700,15 @@ void RimEnsembleCurveSet::updateCurveColors() if ( m_plotCurveForLegendText ) { - m_plotCurveForLegendText->setColor( RiaColorTools::toQColor( m_color ) ); + m_plotCurveForLegendText->setColor( mainEnsembleColor() ); } RimSummaryPlot* plot; firstAncestorOrThisOfType( plot ); if ( plot && plot->plotWidget() ) { - if ( m_yValuesSummaryCaseCollection() && isCurvesVisible() && m_colorMode != ColorMode::SINGLE_COLOR && m_legendConfig->showLegend() ) + if ( m_yValuesSummaryCaseCollection() && isCurvesVisible() && + !RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( m_colorMode() ) && m_legendConfig->showLegend() ) { if ( !m_legendOverlayFrame ) { @@ -1728,7 +1854,7 @@ void RimEnsembleCurveSet::updateEnsembleCurves( const std::vectorplotWidget()->createPlotCurve( nullptr, "" ); + m_plotCurveForLegendText.reset( plot->plotWidget()->createPlotCurve( nullptr, "" ) ); } m_plotCurveForLegendText->attachToPlot( plot->plotWidget() ); updateEnsembleLegendItem(); @@ -1763,10 +1889,6 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vectorcalculate( statCases, m_statistics->includeIncompleteCurves() ); } - RimSummaryPlot* plot = nullptr; - firstAncestorOrThisOfType( plot ); - CVF_ASSERT( plot ); - std::vector addresses; if ( m_statistics->isActive() ) { @@ -1784,7 +1906,9 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vectorplotWidget() ) + RimSummaryPlot* plot = nullptr; + firstAncestorOrThisOfType( plot ); + if ( plot && plot->plotWidget() ) { for ( auto address : addresses ) { @@ -1984,9 +2108,9 @@ void RimEnsembleCurveSet::updateEnsembleLegendItem() { RiuPlotCurveSymbol* symbol = m_plotCurveForLegendText->createSymbol( RiuPlotCurveSymbol::SYMBOL_CROSS ); - if ( m_colorMode == ColorMode::SINGLE_COLOR ) + if ( RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( m_colorMode() ) ) { - QColor curveColor = RiaColorTools::toQColor( m_color ); + QColor curveColor = mainEnsembleColor(); QPen curvePen( curveColor ); curvePen.setWidth( 2 ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h index 66a2d724c8..c5a9072d35 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h @@ -95,8 +95,11 @@ public: QString name() const; - bool isCurvesVisible(); - void setColor( cvf::Color3f color ); + bool isCurvesVisible() const; + void setColor( cvf::Color3f color ); + void setStatisticsColor( const cvf::Color3f& color ); + void enableStatisticsLables( bool enable ); + QColor mainEnsembleColor() const; void loadDataAndUpdate( bool updateParentPlot ); void setParentPlotNoReplot( RiuPlotWidget* plot ); @@ -134,9 +137,8 @@ public: void updateEnsembleLegendItem(); RiuDraggableOverlayFrame* legendFrame() const; - - void setTimeSteps( const std::vector& timeStepIndices ); - std::vector selectedTimeSteps() const; + void setTimeSteps( const std::vector& timeStepIndices ); + std::vector selectedTimeSteps() const; RimEnsembleCurveSet* clone() const; void showCurves( bool show ); @@ -195,6 +197,7 @@ private: void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; void updatePlotAxis(); @@ -211,6 +214,9 @@ private: void onObjectiveFunctionChanged( const caf::SignalEmitter* emitter ); void onCustomObjectiveFunctionChanged( const caf::SignalEmitter* emitter ); + void setTransparentCurveColor(); + void onColorTagClicked( const SignalEmitter* emitter, size_t index ); + private: caf::PdmField m_showCurves; caf::PdmChildArrayField m_curves; @@ -224,7 +230,9 @@ private: caf::PdmField m_resampling; caf::PdmField m_colorMode; - caf::PdmField m_color; + caf::PdmField m_mainEnsembleColor; + caf::PdmField m_colorForRealizations; + caf::PdmField m_colorTransparency; caf::PdmField m_ensembleParameter; caf::PdmField> m_ensembleParameterSorting; @@ -255,7 +263,7 @@ private: caf::PdmProxyValueField m_autoGeneratedName; caf::PdmChildField m_summaryAddressNameTools; - RiuPlotCurve* m_plotCurveForLegendText; + std::unique_ptr m_plotCurveForLegendText; QPointer m_legendOverlayFrame; QPointer m_filterOverlayFrame; QPointer m_objectiveFunctionOverlayFrame; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp index 9651038550..a1ed857868 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.cpp @@ -66,7 +66,7 @@ RimEnsembleCurveSetCollection::~RimEnsembleCurveSetCollection() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimEnsembleCurveSetCollection::isCurveSetsVisible() +bool RimEnsembleCurveSetCollection::isCurveSetsVisible() const { return m_showCurves(); } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.h index 1ab3d79de8..587eaabca0 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetCollection.h @@ -40,7 +40,7 @@ public: RimEnsembleCurveSetCollection(); ~RimEnsembleCurveSetCollection() override; - bool isCurveSetsVisible(); + bool isCurveSetsVisible() const; void loadDataAndUpdate( bool updateParentPlot ); void setParentPlotAndReplot( RiuPlotWidget* plot ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.cpp index dbe710f64c..2770afcb29 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.cpp @@ -39,6 +39,7 @@ template <> void AppEnum::setUp() { addItem( RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR, "SINGLE_COLOR", "Single Color" ); + addItem( RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR_WITH_ALPHA, "SINGLE_COLOR_WITH_ALPHA", "Single Color with alpha" ); addItem( RimEnsembleCurveSetColorManager::ColorMode::BY_ENSEMBLE_PARAM, "BY_ENSEMBLE_PARAM", "By Ensemble Parameter" ); addItem( RimEnsembleCurveSetColorManager::ColorMode::BY_OBJECTIVE_FUNCTION, "BY_OBJECTIVE_FUNCTION", "By Objective Function" ); addItem( RimEnsembleCurveSetColorManager::ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION, @@ -227,7 +228,10 @@ cvf::Color3f RimEnsembleCurveSetColorManager::caseColor( const RimRegularLegendC return RiaColorTables::undefinedCellColor(); } -std::map RimEnsembleCurveSetColorManager::m_nextColorIndexes; - -std::map> - RimEnsembleCurveSetColorManager::m_colorCache; +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( ColorMode colorMode ) +{ + return ( colorMode == ColorMode::SINGLE_COLOR || colorMode == ColorMode::SINGLE_COLOR_WITH_ALPHA ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.h index b820a1dd36..4bb015c5db 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.h @@ -45,6 +45,7 @@ public: enum class ColorMode { SINGLE_COLOR, + SINGLE_COLOR_WITH_ALPHA, BY_ENSEMBLE_PARAM, BY_OBJECTIVE_FUNCTION, BY_CUSTOM_OBJECTIVE_FUNCTION @@ -85,9 +86,8 @@ public: RimSummaryCase* summaryCase, caf::PdmPointer customObjectiveFunction ); + static bool hasSameColorForAllRealizationCurves( ColorMode colorMode ); + private: static const std::map m_ensembleColorRanges; - - static std::map m_nextColorIndexes; - static std::map> m_colorCache; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.cpp index be1be2eb18..f6fbbff5b8 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.cpp @@ -59,6 +59,8 @@ RimEnsembleStatistics::RimEnsembleStatistics( RimEnsembleCurveSetInterface* pare // Set to always show curves before the version this feature was introduced in m_showStatisticsCurveLegends = true; } + + m_showColorField = true; } //-------------------------------------------------------------------------------------------------- @@ -109,6 +111,14 @@ void RimEnsembleStatistics::disableMeanCurve( bool disable ) m_showMeanCurve.uiCapability()->setUiReadOnly( disable ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleStatistics::showColorField( bool show ) +{ + m_showColorField = show; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -124,7 +134,8 @@ void RimEnsembleStatistics::fieldChangedByUi( const caf::PdmFieldHandle* changed curveSet->updateStatisticsCurves(); - if ( changedField == &m_active || changedField == &m_basedOnFilteredCases ) curveSet->updateEditors(); + // Trigger update of tree view editor for ensemble curve set as they depend on these fields + if ( changedField == &m_active || changedField == &m_basedOnFilteredCases || changedField == &m_color ) curveSet->updateEditors(); } if ( changedField == &m_hideEnsembleCurves ) @@ -150,7 +161,8 @@ void RimEnsembleStatistics::defineUiOrdering( QString uiConfigName, caf::PdmUiOr uiOrdering.add( &m_basedOnFilteredCases ); uiOrdering.add( &m_includeIncompleteCurves ); uiOrdering.add( &m_showCurveLabels ); - uiOrdering.add( &m_color ); + + if ( m_showColorField ) uiOrdering.add( &m_color ); auto group = uiOrdering.addNewGroup( "Curves" ); if ( !curveSet->hasMeanData() ) group->add( &m_warningLabel ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.h index 7cb19f7108..a95381a6fd 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.h @@ -34,17 +34,21 @@ class RimEnsembleStatistics : public caf::PdmObject public: RimEnsembleStatistics( RimEnsembleCurveSetInterface* parentCurveSet = nullptr ); - bool isActive() const; - void setShowStatisticsCurves( bool show ); - bool showStatisticsCurveLegends() const { return m_showStatisticsCurveLegends; } - bool hideEnsembleCurves() const { return m_hideEnsembleCurves; } - bool basedOnFilteredCases() const { return m_basedOnFilteredCases; } - bool showP10Curve() const { return m_showP10Curve; } - bool showP50Curve() const { return m_showP50Curve; } - bool showP90Curve() const { return m_showP90Curve; } - bool showMeanCurve() const { return m_showMeanCurve; } - bool showCurveLabels() const { return m_showCurveLabels; } + bool isActive() const; + void setShowStatisticsCurves( bool show ); + bool showStatisticsCurveLegends() const { return m_showStatisticsCurveLegends; } + bool hideEnsembleCurves() const { return m_hideEnsembleCurves; } + bool basedOnFilteredCases() const { return m_basedOnFilteredCases; } + bool showP10Curve() const { return m_showP10Curve; } + bool showP50Curve() const { return m_showP50Curve; } + bool showP90Curve() const { return m_showP90Curve; } + bool showMeanCurve() const { return m_showMeanCurve; } + + bool showCurveLabels() const { return m_showCurveLabels; } + void enableCurveLabels( bool enable ) { m_showCurveLabels = enable; } + cvf::Color3f color() const { return m_color; } + void setColor( const cvf::Color3f& color ) { m_color = color; } bool includeIncompleteCurves() const { return m_includeIncompleteCurves; } @@ -53,6 +57,8 @@ public: void disableP90Curve( bool disable ); void disableMeanCurve( bool disable ); + void showColorField( bool show ); + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; @@ -72,5 +78,6 @@ private: caf::PdmField m_warningLabel; + bool m_showColorField; caf::PdmField m_color; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index fa4a15c9bc..4c6f3071bd 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -101,6 +101,20 @@ CAF_PDM_SOURCE_INIT( RimSummaryPlot, "SummaryPlot" ); +struct RimSummaryPlot::CurveInfo +{ + int curveCount = 0; + std::vector curves; + std::vector curveSets; + + void appendCurveInfo( const CurveInfo& other ) + { + curveCount += other.curveCount; + curves.insert( curves.end(), other.curves.begin(), other.curves.end() ); + curveSets.insert( curveSets.end(), other.curveSets.begin(), other.curveSets.end() ); + }; +}; + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -775,11 +789,13 @@ bool RimSummaryPlot::containsResamplableCurves() const //-------------------------------------------------------------------------------------------------- size_t RimSummaryPlot::singleColorCurveCount() const { - auto allCurveSets = ensembleCurveSetCollection()->curveSets(); - size_t colorIndex = std::count_if( allCurveSets.begin(), - allCurveSets.end(), - []( RimEnsembleCurveSet* curveSet ) - { return curveSet->colorMode() == RimEnsembleCurveSet::ColorMode::SINGLE_COLOR; } ); + auto allCurveSets = ensembleCurveSetCollection()->curveSets(); + + size_t colorIndex = + std::count_if( allCurveSets.begin(), + allCurveSets.end(), + []( RimEnsembleCurveSet* curveSet ) + { return RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( curveSet->colorMode() ); } ); colorIndex += curveCount(); @@ -815,25 +831,54 @@ void RimSummaryPlot::applyDefaultCurveAppearances( std::vector //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::applyDefaultCurveAppearances( std::vector ensembleCurvesToUpdate ) { - auto allCurveSets = ensembleCurveSetCollection()->curveSets(); + std::vector usedColors; + for ( auto c : ensembleCurveSetCollection()->curveSets() ) + { + // ensembleCurvesToUpdate can be present in the ensembleCurveSetCollection()->curveSets() vector, exclude this from used + // colors + if ( std::find( ensembleCurvesToUpdate.begin(), ensembleCurvesToUpdate.end(), c ) == ensembleCurvesToUpdate.end() ) + { + usedColors.push_back( c->mainEnsembleColor() ); + } + } for ( auto curveSet : ensembleCurvesToUpdate ) { - size_t colorIndex = 0; + cvf::Color3f curveColor = cvf::Color3f::ORANGE; - auto it = std::find( allCurveSets.begin(), allCurveSets.end(), curveSet ); - if ( it != allCurveSets.end() ) + const auto adr = curveSet->summaryAddress(); + if ( adr.isHistoryVector() ) { - colorIndex = std::distance( allCurveSets.begin(), it ); + curveColor = RiaPreferencesSummary::current()->historyCurveContrastColor(); } + else + { + if ( RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( curveSet->colorMode() ) ) + { + 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 + candidateColors.push_back( RiaColorTools::toQColor( RimSummaryCurveAppearanceCalculator::assignColorByPhase( adr ) ) ); + } - if ( curveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR ) continue; + auto summaryColors = RiaColorTables::summaryCurveDefaultPaletteColors(); + for ( int i = 0; i < static_cast( summaryColors.size() ); i++ ) + { + candidateColors.push_back( summaryColors.cycledQColor( i ) ); + } - cvf::Color3f curveColor = RimSummaryCurveAppearanceCalculator::computeTintedCurveColorForAddress( curveSet->summaryAddress(), - static_cast( colorIndex ) ); - - auto adr = curveSet->summaryAddress(); - if ( adr.isHistoryVector() ) curveColor = RiaPreferencesSummary::current()->historyCurveContrastColor(); + for ( const auto& candidateCol : candidateColors ) + { + if ( std::find( usedColors.begin(), usedColors.end(), candidateCol ) == usedColors.end() ) + { + curveColor = RiaColorTools::fromQColorTo3f( candidateCol ); + usedColors.push_back( candidateCol ); + break; + } + } + } + } curveSet->setColor( curveColor ); } @@ -2053,7 +2098,7 @@ std::vector RimSummaryPlot::visibleCurvesForLegend() for ( auto curveSet : curveSets() ) { if ( !curveSet->isCurvesVisible() ) continue; - if ( curveSet->colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR ) + if ( RimEnsembleCurveSetColorManager::hasSameColorForAllRealizationCurves( curveSet->colorMode() ) ) { auto curveSetCurves = curveSet->curves(); @@ -2153,7 +2198,7 @@ bool RimSummaryPlot::autoPlotTitle() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::pair> RimSummaryPlot::handleSummaryCaseDrop( RimSummaryCase* summaryCase ) +RimSummaryPlot::CurveInfo RimSummaryPlot::handleSummaryCaseDrop( RimSummaryCase* summaryCase ) { int newCurves = 0; std::vector curves; @@ -2174,13 +2219,13 @@ std::pair> RimSummaryPlot::handleSummaryCaseD newCurves++; } - return { newCurves, curves }; + return { newCurves, curves, {} }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::pair> RimSummaryPlot::handleEnsembleDrop( RimSummaryCaseCollection* ensemble ) +RimSummaryPlot::CurveInfo RimSummaryPlot::handleEnsembleDrop( RimSummaryCaseCollection* ensemble ) { int newCurves = 0; std::vector curveSetsToUpdate; @@ -2202,16 +2247,17 @@ std::pair> RimSummaryPlot::handleEnsemble newCurves++; } - return { newCurves, curveSetsToUpdate }; + return { newCurves, {}, curveSetsToUpdate }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::pair> RimSummaryPlot::handleAddressCollectionDrop( RimSummaryAddressCollection* addressCollection ) +RimSummaryPlot::CurveInfo RimSummaryPlot::handleAddressCollectionDrop( RimSummaryAddressCollection* addressCollection ) { - int newCurves = 0; - std::vector curves; + int newCurves = 0; + std::vector curves; + std::vector curveSetsToUpdate; auto droppedName = addressCollection->name().toStdString(); @@ -2294,7 +2340,7 @@ std::pair> RimSummaryPlot::handleAddressColle auto addresses = curveDef.ensemble()->ensembleSummaryAddresses(); if ( addresses.find( curveDef.summaryAddress() ) != addresses.end() ) { - addNewEnsembleCurveY( curveDef.summaryAddress(), curveDef.ensemble() ); + curveSetsToUpdate.push_back( addNewEnsembleCurveY( curveDef.summaryAddress(), curveDef.ensemble() ) ); newCurves++; } } @@ -2308,16 +2354,17 @@ std::pair> RimSummaryPlot::handleAddressColle } } - return { newCurves, curves }; + return { newCurves, curves, curveSetsToUpdate }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::pair> RimSummaryPlot::handleSummaryAddressDrop( RimSummaryAddress* summaryAddr ) +RimSummaryPlot::CurveInfo RimSummaryPlot::handleSummaryAddressDrop( RimSummaryAddress* summaryAddr ) { - int newCurves = 0; - std::vector curves; + int newCurves = 0; + std::vector curves; + std::vector curveSetsToUpdate; std::vector newCurveAddresses; newCurveAddresses.push_back( summaryAddr->address() ); @@ -2354,7 +2401,7 @@ std::pair> RimSummaryPlot::handleSummaryAddre if ( !skipAddress ) { - addNewEnsembleCurveY( droppedAddress, ensemble ); + curveSetsToUpdate.push_back( addNewEnsembleCurveY( droppedAddress, ensemble ) ); newCurves++; } } @@ -2392,7 +2439,7 @@ std::pair> RimSummaryPlot::handleSummaryAddre } } } - return { newCurves, curves }; + return { newCurves, curves, curveSetsToUpdate }; } //-------------------------------------------------------------------------------------------------- @@ -2400,65 +2447,43 @@ std::pair> RimSummaryPlot::handleSummaryAddre //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::handleDroppedObjects( const std::vector& objects ) { - int accumulatedCurveCount = 0; - std::vector curvesToUpdate; - std::vector curveSetsToUpdate; - + CurveInfo curveInfo; for ( auto obj : objects ) { - auto summaryCase = dynamic_cast( obj ); - if ( summaryCase ) + if ( auto summaryCase = dynamic_cast( obj ) ) { - auto [curveCount, curvesCreated] = handleSummaryCaseDrop( summaryCase ); - accumulatedCurveCount += curveCount; - curvesToUpdate.insert( curvesToUpdate.end(), curvesCreated.begin(), curvesCreated.end() ); - continue; + curveInfo.appendCurveInfo( handleSummaryCaseDrop( summaryCase ) ); } - auto ensemble = dynamic_cast( obj ); - if ( ensemble ) + else if ( auto ensemble = dynamic_cast( obj ) ) { - auto [curveCount, curvesCreated] = handleEnsembleDrop( ensemble ); - accumulatedCurveCount += curveCount; - curveSetsToUpdate.insert( curveSetsToUpdate.end(), curvesCreated.begin(), curvesCreated.end() ); - continue; + curveInfo.appendCurveInfo( handleEnsembleDrop( ensemble ) ); + } + else if ( auto summaryAddr = dynamic_cast( obj ) ) + { + curveInfo.appendCurveInfo( handleSummaryAddressDrop( summaryAddr ) ); } - auto summaryAddr = dynamic_cast( obj ); - if ( summaryAddr ) - { - auto [curveCount, curvesCreated] = handleSummaryAddressDrop( summaryAddr ); - accumulatedCurveCount += curveCount; - curvesToUpdate.insert( curvesToUpdate.end(), curvesCreated.begin(), curvesCreated.end() ); - continue; - } - - auto addressCollection = dynamic_cast( obj ); - if ( addressCollection ) + else if ( auto addressCollection = dynamic_cast( obj ) ) { if ( addressCollection->isFolder() ) { for ( auto coll : addressCollection->subFolders() ) { - auto [curveCount, curvesCreated] = handleAddressCollectionDrop( coll ); - accumulatedCurveCount += curveCount; - curvesToUpdate.insert( curvesToUpdate.end(), curvesCreated.begin(), curvesCreated.end() ); + auto localInfo = handleAddressCollectionDrop( coll ); + curveInfo.appendCurveInfo( localInfo ); } - continue; } else { - auto [curveCount, curvesCreated] = handleAddressCollectionDrop( addressCollection ); - accumulatedCurveCount += curveCount; - curvesToUpdate.insert( curvesToUpdate.end(), curvesCreated.begin(), curvesCreated.end() ); - continue; + curveInfo.appendCurveInfo( handleAddressCollectionDrop( addressCollection ) ); } } } - if ( accumulatedCurveCount > 0 ) + if ( curveInfo.curveCount > 0 ) { - applyDefaultCurveAppearances( curvesToUpdate ); - applyDefaultCurveAppearances( curveSetsToUpdate ); + applyDefaultCurveAppearances( curveInfo.curves ); + applyDefaultCurveAppearances( curveInfo.curveSets ); loadDataAndUpdate(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h index a4a1b628db..2dde10aec9 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -303,10 +303,12 @@ private: bool updateStackedCurveDataForAxis( RiuPlotAxis plotAxis ); bool updateStackedCurveDataForRelevantAxes(); - std::pair> handleSummaryCaseDrop( RimSummaryCase* summaryCase ); - std::pair> handleEnsembleDrop( RimSummaryCaseCollection* ensemble ); - std::pair> handleAddressCollectionDrop( RimSummaryAddressCollection* addrColl ); - std::pair> handleSummaryAddressDrop( RimSummaryAddress* summaryAddr ); + struct CurveInfo; + + CurveInfo handleSummaryCaseDrop( RimSummaryCase* summaryCase ); + CurveInfo handleEnsembleDrop( RimSummaryCaseCollection* ensemble ); + CurveInfo handleAddressCollectionDrop( RimSummaryAddressCollection* addrColl ); + CurveInfo handleSummaryAddressDrop( RimSummaryAddress* summaryAddr ); bool isOnlyWaterCutCurvesVisible( RiuPlotAxis plotAxis ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotManager.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotManager.cpp index 9e2186f579..2ea3ce2b9e 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotManager.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotManager.cpp @@ -397,15 +397,14 @@ void RimSummaryPlotManager::createNewPlot() plotBuilder.setIndividualPlotPerDataSource( m_individualPlotPerDataSource ); - auto plots = plotBuilder.createPlots(); + auto summaryPlots = plotBuilder.createPlots(); if ( m_createMultiPlot ) { - auto summaryPlots = plotBuilder.createPlots(); RicSummaryPlotBuilder::createAndAppendSummaryMultiPlot( summaryPlots ); } else { - for ( auto plot : plots ) + for ( auto plot : summaryPlots ) { RicSummaryPlotBuilder::createAndAppendSingleSummaryMultiPlot( plot ); plot->loadDataAndUpdate(); diff --git a/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.cpp b/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.cpp index 87837fbc21..7a9d04f270 100644 --- a/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.cpp +++ b/ApplicationLibCode/UserInterface/RiuQwtPlotWidget.cpp @@ -996,6 +996,12 @@ void RiuQwtPlotWidget::highlightPlotCurves( const std::set& auto plotItemList = m_plot->itemList(); for ( QwtPlotItem* plotItem : plotItemList ) { + auto* riuPlotCurve = dynamic_cast( plotItem ); + auto pdmObject = m_plotDefinition->findPdmObjectFromPlotCurve( riuPlotCurve ); + + // Do not modify curve objects with no associated Rim object, as the Rim object is used to restore color after highlight manipulation + if ( !pdmObject ) continue; + auto* plotCurve = dynamic_cast( plotItem ); if ( plotCurve ) { @@ -1017,6 +1023,13 @@ void RiuQwtPlotWidget::highlightPlotCurves( const std::set& double zValue = plotCurve->z(); if ( closestItems.count( plotCurve ) > 0 ) { + auto saturation = 1.0; + auto value = 1.0; + auto hue = curveColor.hueF(); + + auto highlightColor = QColor::fromHsvF( hue, saturation, value ); + + existingPen.setColor( highlightColor ); existingPen.setWidth( penWidth + highlightItemWidthAdjustment() ); plotCurve->setPen( existingPen ); plotCurve->setZ( zValue + 100.0 ); @@ -1024,9 +1037,10 @@ void RiuQwtPlotWidget::highlightPlotCurves( const std::set& } else { - QColor blendedColor = RiaColorTools::blendQColors( bgColor, curveColor, 3, 1 ); - QColor blendedSymbolColor = RiaColorTools::blendQColors( bgColor, symbolColor, 3, 1 ); - QColor blendedSymbolLineColor = RiaColorTools::blendQColors( bgColor, symbolLineColor, 3, 1 ); + int backgroundWeight = 2; + QColor blendedColor = RiaColorTools::blendQColors( bgColor, curveColor, backgroundWeight, 1 ); + QColor blendedSymbolColor = RiaColorTools::blendQColors( bgColor, symbolColor, backgroundWeight, 1 ); + QColor blendedSymbolLineColor = RiaColorTools::blendQColors( bgColor, symbolLineColor, backgroundWeight, 1 ); plotCurve->setPen( blendedColor, existingPen.width(), existingPen.style() ); if ( symbol ) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiColorEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiColorEditor.cpp index 5e461604cc..da19e6d17a 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiColorEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiColorEditor.cpp @@ -66,6 +66,19 @@ PdmUiColorEditor::PdmUiColorEditor() m_color = QColor::Invalid; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QColor PdmUiColorEditor::getColor( const QColor& sourceColor ) +{ + QColorDialog::ColorDialogOptions flags; +#ifndef WIN32 + flags = QColorDialog::DontUseNativeDialog; +#endif + + return QColorDialog::getColor( sourceColor, nullptr, "Select color", flags ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiColorEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiColorEditor.h index 6cee09c00f..24ae589621 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiColorEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiColorEditor.h @@ -76,6 +76,8 @@ public: PdmUiColorEditor(); ~PdmUiColorEditor() override {} + static QColor getColor( const QColor& sourceColor ); + protected: QWidget* createEditorWidget( QWidget* parent ) override; QWidget* createLabelWidget( QWidget* parent ) override; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeAttributes.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeAttributes.h index 5c692a2084..ada1313fb6 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeAttributes.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeAttributes.h @@ -41,6 +41,8 @@ #include "cafPdmUiFieldEditorHandle.h" #include "cafSignal.h" +#include + namespace caf { class PdmUiTreeViewItemAttribute : public PdmUiEditorAttribute @@ -48,14 +50,13 @@ class PdmUiTreeViewItemAttribute : public PdmUiEditorAttribute public: struct Tag : public SignalEmitter { - enum Position + enum class Position { IN_FRONT, AT_END }; Tag() - : text() - , position( AT_END ) + : position( Position::AT_END ) , bgColor( Qt::red ) , fgColor( Qt::white ) , selectedOnly( false ) @@ -71,7 +72,7 @@ public: caf::Signal clicked; - static std::unique_ptr create() { return std::unique_ptr( new Tag ); } + static std::unique_ptr create() { return std::make_unique(); } private: Tag& operator=( const Tag& rhs ) { return *this; } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp index c02d365c64..7283554bd8 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp @@ -325,8 +325,7 @@ void PdmUiTreeViewEditor::updateMySubTree( PdmUiItem* uiItem, bool notifyEditors } m_treeViewModel->updateSubTree( itemToUpdate, notifyEditors ); - QModelIndex itemIndex = m_treeViewModel->findModelIndex( itemToUpdate ); - updateItemDelegateForSubTree( itemIndex ); + updateItemDelegateForSubTree(); } } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewItemDelegate.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewItemDelegate.cpp index 132bb939b5..f1e77cb785 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewItemDelegate.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewItemDelegate.cpp @@ -101,6 +101,19 @@ QRect PdmUiTreeViewItemDelegate::tagRect( const QRect& itemRect, QModelIndex ind auto it = m_tags.find( index ); if ( it == m_tags.end() ) return QRect(); + if ( it->second.size() == 1 ) + { + const PdmUiTreeViewItemAttribute::Tag* tag = it->second[0].get(); + if ( !tag->icon.valid() && tag->position == PdmUiTreeViewItemAttribute::Tag::Position::AT_END ) + { + // Special case for single tag at end, which is not an icon + + QPoint bottomRight = itemRect.bottomRight(); + QPoint topLeft = itemRect.topRight() - QPoint( itemRect.height() * 1.5, 0 ); + return QRect( topLeft, bottomRight ); + } + } + QSize fullSize = itemRect.size(); QPoint offset( 0, 0 ); @@ -113,7 +126,7 @@ QRect PdmUiTreeViewItemDelegate::tagRect( const QRect& itemRect, QModelIndex ind auto icon = tag->icon.icon(); QSize iconSize = icon->actualSize( fullSize ); QRect iconRect; - if ( tag->position == PdmUiTreeViewItemAttribute::Tag::AT_END ) + if ( tag->position == PdmUiTreeViewItemAttribute::Tag::Position::AT_END ) { QPoint bottomRight = itemRect.bottomRight() - offset; QPoint topLeft = bottomRight - QPoint( iconSize.width(), iconSize.height() ); @@ -162,7 +175,7 @@ void PdmUiTreeViewItemDelegate::paint( QPainter* painter, const QStyleOptionView auto icon = tag->icon.icon(); QSize iconSize = icon->actualSize( fullSize ); QRect iconRect; - if ( tag->position == PdmUiTreeViewItemAttribute::Tag::AT_END ) + if ( tag->position == PdmUiTreeViewItemAttribute::Tag::Position::AT_END ) { QPoint bottomRight( rect.bottomRight().x() - offset.x(), center.y() + iconSize.height() / 2 ); QPoint topLeft( bottomRight.x() - iconSize.width(), bottomRight.y() - iconSize.height() ); @@ -202,7 +215,7 @@ void PdmUiTreeViewItemDelegate::paint( QPainter* painter, const QStyleOptionView int textDiff = ( fullSize.height() - textSize.height() ); QRect textRect; - if ( tag->position == PdmUiTreeViewItemAttribute::Tag::AT_END ) + if ( tag->position == PdmUiTreeViewItemAttribute::Tag::Position::AT_END ) { QPoint bottomRight = rect.bottomRight() - QPoint( outsideLeftRightMargins, 0 ) - offset; QPoint textBottomRight = bottomRight - QPoint( insideleftRightMargins, textDiff / 2 ); @@ -283,14 +296,14 @@ bool PdmUiTreeViewItemDelegate::editorEvent( QEvent* event, PdmObjectHandle* pdmObject = uiObjectHandle->objectHandle(); if ( pdmObject ) { - PdmFieldReorderCapability* reorderability = - PdmFieldReorderCapability::reorderCapabilityOfParentContainer( pdmObject ); + size_t indexInParent = 0; - if ( reorderability ) + if ( PdmFieldReorderCapability* reorderability = + PdmFieldReorderCapability::reorderCapabilityOfParentContainer( pdmObject ) ) { - size_t indexInParent = reorderability->indexOf( pdmObject ); - tag->clicked.send( indexInParent ); + indexInParent = reorderability->indexOf( pdmObject ); } + tag->clicked.send( indexInParent ); } }