From 318f187635c6bd98458310db03c23150cb144323 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 17 Aug 2022 10:10:20 +0200 Subject: [PATCH] #9202 Well Log Plot: add option for having the legend inside the plot --- .../ProjectDataModel/RimDepthTrackPlot.cpp | 2 +- .../ProjectDataModel/RimPlotWindow.cpp | 44 ++++++++++-- .../ProjectDataModel/RimPlotWindow.h | 29 +++++--- .../UserInterface/CMakeLists_files.cmake | 3 + .../UserInterface/RiuMultiPlotPage.cpp | 68 ++++++++++++++++--- .../UserInterface/RiuMultiPlotPage.h | 29 ++++---- .../RiuQwtLegendOverlayContentFrame.cpp | 56 +++++++++++++++ .../RiuQwtLegendOverlayContentFrame.h | 40 +++++++++++ 8 files changed, 230 insertions(+), 41 deletions(-) create mode 100644 ApplicationLibCode/UserInterface/RiuQwtLegendOverlayContentFrame.cpp create mode 100644 ApplicationLibCode/UserInterface/RiuQwtLegendOverlayContentFrame.h diff --git a/ApplicationLibCode/ProjectDataModel/RimDepthTrackPlot.cpp b/ApplicationLibCode/ProjectDataModel/RimDepthTrackPlot.cpp index 63a07a858c..369957f636 100644 --- a/ApplicationLibCode/ProjectDataModel/RimDepthTrackPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimDepthTrackPlot.cpp @@ -945,7 +945,7 @@ void RimDepthTrackPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrderi uiOrderingForAutoName( uiConfigName, *titleGroup ); caf::PdmUiGroup* plotLayoutGroup = uiOrdering.addNewGroup( "Plot Layout" ); - RimPlotWindow::uiOrderingForPlotLayout( uiConfigName, *plotLayoutGroup ); + RimPlotWindow::uiOrderingForPlotLayout( uiConfigName, *plotLayoutGroup, true ); plotLayoutGroup->add( &m_subTitleFontSize ); plotLayoutGroup->add( &m_axisTitleFontSize ); plotLayoutGroup->add( &m_axisValueFontSize ); diff --git a/ApplicationLibCode/ProjectDataModel/RimPlotWindow.cpp b/ApplicationLibCode/ProjectDataModel/RimPlotWindow.cpp index 17b33e746b..15bb532566 100644 --- a/ApplicationLibCode/ProjectDataModel/RimPlotWindow.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimPlotWindow.cpp @@ -33,6 +33,19 @@ CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimPlotWindow, "RimPlotWindow" ); // Do not use. Abstract class +#include "cafAppEnum.h" + +namespace caf +{ +template <> +void caf::AppEnum::setUp() +{ + addItem( RimPlotWindow::LegendPosition::ABOVE, "ABOVE", "Above" ); + addItem( RimPlotWindow::LegendPosition::INSIDE, "INSIDE", "Inside" ); + setDefault( RimPlotWindow::LegendPosition::ABOVE ); +} +}; // namespace caf + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -59,6 +72,7 @@ RimPlotWindow::RimPlotWindow() CAF_PDM_InitFieldNoDefault( &m_titleFontSize, "TitleFontSize", "Title Font Size" ); CAF_PDM_InitFieldNoDefault( &m_legendFontSize, "LegendDeltaFontSize", "Legend Font Size" ); + CAF_PDM_InitFieldNoDefault( &m_legendPosition, "LegendPosition", "Legend Position" ); m_titleFontSize = caf::FontTools::RelativeSize::XXLarge; m_legendFontSize = caf::FontTools::RelativeSize::Large; @@ -89,6 +103,7 @@ RimPlotWindow& RimPlotWindow::operator=( RimPlotWindow&& rhs ) m_plotLegendsHorizontal = rhs.m_plotLegendsHorizontal(); m_titleFontSize = rhs.m_titleFontSize(); m_legendFontSize = rhs.m_legendFontSize(); + m_legendPosition = rhs.m_legendPosition(); return *this; } @@ -180,6 +195,22 @@ void RimPlotWindow::setLegendFontSize( caf::FontTools::RelativeSize fontSize ) m_legendFontSize = fontSize; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotWindow::LegendPosition RimPlotWindow::legendPosition() const +{ + return m_legendPosition(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotWindow::setLegendPosition( RimPlotWindow::LegendPosition legendPosition ) +{ + m_legendPosition = legendPosition; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -250,11 +281,8 @@ void RimPlotWindow::fieldChangedByUi( const caf::PdmFieldHandle* changedField, updateWindowVisibility(); } - if ( changedField == &m_showPlotLegends || changedField == &m_plotLegendsHorizontal ) - { - updateLayout(); - } - else if ( changedField == &m_legendFontSize || changedField == &m_titleFontSize ) + if ( changedField == &m_showPlotLegends || changedField == &m_plotLegendsHorizontal || + changedField == &m_legendFontSize || changedField == &m_titleFontSize || changedField == &m_legendPosition ) { updateLayout(); } @@ -284,10 +312,14 @@ QList RimPlotWindow::calculateValueOptions( const caf::P //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimPlotWindow::uiOrderingForPlotLayout( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +void RimPlotWindow::uiOrderingForPlotLayout( QString uiConfigName, caf::PdmUiOrdering& uiOrdering, bool showLegendPosition ) { uiOrdering.add( &m_showPlotLegends ); uiOrdering.add( &m_plotLegendsHorizontal ); + if ( showLegendPosition ) + { + uiOrdering.add( &m_legendPosition ); + } uiOrdering.add( &m_titleFontSize ); uiOrdering.add( &m_legendFontSize ); } diff --git a/ApplicationLibCode/ProjectDataModel/RimPlotWindow.h b/ApplicationLibCode/ProjectDataModel/RimPlotWindow.h index 304c0e8bfa..5cf02e815e 100644 --- a/ApplicationLibCode/ProjectDataModel/RimPlotWindow.h +++ b/ApplicationLibCode/ProjectDataModel/RimPlotWindow.h @@ -44,6 +44,12 @@ class RimPlotWindow : public RimViewWindow CAF_PDM_HEADER_INIT; public: + enum class LegendPosition + { + ABOVE, + INSIDE, + }; + RimPlotWindow(); ~RimPlotWindow() override; @@ -54,11 +60,13 @@ public: bool plotTitleVisible() const; void setPlotTitleVisible( bool showPlotTitle ); - virtual QString description() const = 0; - bool legendsVisible() const; - void setLegendsVisible( bool doShow ); - bool legendsHorizontal() const; - void setLegendsHorizontal( bool horizontal ); + virtual QString description() const = 0; + bool legendsVisible() const; + void setLegendsVisible( bool doShow ); + bool legendsHorizontal() const; + void setLegendsHorizontal( bool horizontal ); + void setLegendPosition( RimPlotWindow::LegendPosition legendPosition ); + RimPlotWindow::LegendPosition legendPosition() const; void updateFonts() override; @@ -84,7 +92,7 @@ protected: QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; - void uiOrderingForPlotLayout( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ); + void uiOrderingForPlotLayout( QString uiConfigName, caf::PdmUiOrdering& uiOrdering, bool showLegendPosition = false ); void updateWindowVisibility(); @@ -100,10 +108,11 @@ private: void assignIdIfNecessary() final; protected: - caf::PdmField m_id; - caf::PdmField m_showPlotTitle; - caf::PdmField m_showPlotLegends; - caf::PdmField m_plotLegendsHorizontal; + caf::PdmField m_id; + caf::PdmField m_showPlotTitle; + caf::PdmField m_showPlotLegends; + caf::PdmField m_plotLegendsHorizontal; + caf::PdmField> m_legendPosition; caf::PdmField m_titleFontSize; caf::PdmField m_legendFontSize; diff --git a/ApplicationLibCode/UserInterface/CMakeLists_files.cmake b/ApplicationLibCode/UserInterface/CMakeLists_files.cmake index a76b6651b8..3eb868fb51 100644 --- a/ApplicationLibCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationLibCode/UserInterface/CMakeLists_files.cmake @@ -96,6 +96,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiuMainWindowTools.h ${CMAKE_CURRENT_LIST_DIR}/RiuComparisonViewMover.h ${CMAKE_CURRENT_LIST_DIR}/RiuAbstractOverlayContentFrame.h + ${CMAKE_CURRENT_LIST_DIR}/RiuQwtLegendOverlayContentFrame.h ${CMAKE_CURRENT_LIST_DIR}/RiuAbstractLegendFrame.h ${CMAKE_CURRENT_LIST_DIR}/RiuCategoryLegendFrame.h ${CMAKE_CURRENT_LIST_DIR}/RiuScalarMapperLegendFrame.h @@ -206,6 +207,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiuQssSyntaxHighlighter.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuTextEditWithCompletion.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuTextContentFrame.cpp + ${CMAKE_CURRENT_LIST_DIR}/RiuQwtLegendOverlayContentFrame.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuQwtDateScaleWrapper.cpp ) @@ -295,6 +297,7 @@ list( ${CMAKE_CURRENT_LIST_DIR}/RiuScalarMapperLegendFrame.h ${CMAKE_CURRENT_LIST_DIR}/RiuTextEditWithCompletion.h ${CMAKE_CURRENT_LIST_DIR}/RiuTextContentFrame.h + ${CMAKE_CURRENT_LIST_DIR}/RiuQwtLegendOverlayContentFrame.h ) list(APPEND QT_UI_FILES) diff --git a/ApplicationLibCode/UserInterface/RiuMultiPlotPage.cpp b/ApplicationLibCode/UserInterface/RiuMultiPlotPage.cpp index 6a89c8450b..f2f98a85c6 100644 --- a/ApplicationLibCode/UserInterface/RiuMultiPlotPage.cpp +++ b/ApplicationLibCode/UserInterface/RiuMultiPlotPage.cpp @@ -20,27 +20,28 @@ #include "RiuMultiPlotPage.h" #include "RiaApplication.h" +#include "RiaGuiApplication.h" +#include "RiaPlotDefines.h" #include "RiaPlotWindowRedrawScheduler.h" #include "RiaPreferences.h" #include "WellLogCommands/RicWellLogPlotTrackFeatureImpl.h" -#include "RiaGuiApplication.h" -#include "RiaPlotDefines.h" - #include "RimContextCommandBuilder.h" #include "RimMultiPlot.h" #include "RimPlotCurve.h" +#include "RimPlotWindow.h" #include "RimWellLogTrack.h" +#include "RiuDraggableOverlayFrame.h" #include "RiuMainWindow.h" #include "RiuPlotMainWindow.h" #include "RiuPlotObjectPicker.h" #include "RiuPlotWidget.h" +#include "RiuQwtLegendOverlayContentFrame.h" #include "RiuQwtPlotLegend.h" #include "RiuQwtPlotTools.h" #include "RiuQwtPlotWidget.h" -#include "qwt_legend_label.h" #ifdef USE_QTCHARTS #include "RiuQtChartsPlotWidget.h" #endif @@ -52,6 +53,7 @@ #include "qwt_axis.h" #include "qwt_legend.h" +#include "qwt_legend_label.h" #include "qwt_plot_layout.h" #include "qwt_plot_renderer.h" #include "qwt_scale_draw.h" @@ -167,10 +169,17 @@ void RiuMultiPlotPage::insertPlot( RiuPlotWidget* plotWidget, size_t index ) subTitle->setVisible( false ); m_subTitles.insert( static_cast( index ), subTitle ); - RiuQwtPlotLegend* legend = nullptr; + RiuQwtPlotWidget* qwtPlotWidget = dynamic_cast( plotWidget ); + + RiuQwtPlotLegend* legend = new RiuQwtPlotLegend( this ); + RiuDraggableOverlayFrame* legendFrame = nullptr; + if ( qwtPlotWidget ) + { + legendFrame = new RiuDraggableOverlayFrame( qwtPlotWidget->qwtPlot()->canvas(), plotWidget->overlayMargins() ); + } + if ( m_plotDefinition->legendsVisible() && plotWidget->plotDefinition()->legendsVisible() ) { - legend = new RiuQwtPlotLegend( this ); int legendColumns = 1; if ( m_plotDefinition->legendsHorizontal() ) { @@ -179,7 +188,6 @@ void RiuMultiPlotPage::insertPlot( RiuPlotWidget* plotWidget, size_t index ) legend->setMaxColumns( legendColumns ); legend->horizontalScrollBar()->setVisible( false ); legend->verticalScrollBar()->setVisible( false ); - RiuQwtPlotWidget* qwtPlotWidget = dynamic_cast( plotWidget ); if ( qwtPlotWidget ) { legend->connect( qwtPlotWidget->qwtPlot(), @@ -200,9 +208,11 @@ void RiuMultiPlotPage::insertPlot( RiuPlotWidget* plotWidget, size_t index ) legend->contentsWidget()->layout()->setAlignment( Qt::AlignBottom | Qt::AlignHCenter ); legend->setVisible( false ); + plotWidget->updateLegend(); } m_legends.insert( static_cast( index ), legend ); + m_legendFrames.insert( static_cast( index ), legendFrame ); scheduleUpdate(); } @@ -628,9 +638,10 @@ void RiuMultiPlotPage::reinsertPlotWidgets() { clearGridLayout(); - QList> subTitles = this->subTitlesForVisiblePlots(); - QList> legends = this->legendsForVisiblePlots(); - QList> plotWidgets = this->visiblePlotWidgets(); + QList> subTitles = this->subTitlesForVisiblePlots(); + QList> legends = this->legendsForVisiblePlots(); + QList> legendFrames = this->legendFramesForVisiblePlots(); + QList> plotWidgets = this->visiblePlotWidgets(); m_visibleIndexToPositionMapping.clear(); @@ -654,7 +665,25 @@ void RiuMultiPlotPage::reinsertPlotWidgets() m_gridLayout->addWidget( subTitles[visibleIndex], 3 * row, column, 1, colSpan ); if ( legends[visibleIndex] ) { - m_gridLayout->addWidget( legends[visibleIndex], 3 * row + 1, column, 1, colSpan, Qt::AlignHCenter | Qt::AlignBottom ); + if ( m_plotDefinition->legendPosition() == RimPlotWindow::LegendPosition::ABOVE ) + { + m_gridLayout->addWidget( legends[visibleIndex], + 3 * row + 1, + column, + 1, + colSpan, + Qt::AlignHCenter | Qt::AlignBottom ); + } + else + { + CAF_ASSERT( m_plotDefinition->legendPosition() == RimPlotWindow::LegendPosition::INSIDE ); + + auto overlayFrame = new RiuQwtLegendOverlayContentFrame; + overlayFrame->setLegend( legends[visibleIndex] ); + legendFrames[visibleIndex]->setContentFrame( overlayFrame ); + legendFrames[visibleIndex]->setAnchorCorner( RiuDraggableOverlayFrame::AnchorCorner::TopRight ); + plotWidgets[visibleIndex]->addOverlayFrame( legendFrames[visibleIndex] ); + } } m_gridLayout->addWidget( plotWidgets[visibleIndex], 3 * row + 2, column, 1 + ( rowSpan - 1 ) * 3, colSpan ); @@ -830,6 +859,7 @@ void RiuMultiPlotPage::clearGridLayout() { if ( m_plotWidgets[tIdx] ) { + m_plotWidgets[tIdx]->removeOverlayFrame( m_legendFrames[tIdx] ); m_plotWidgets[tIdx]->hide(); } if ( m_legends[tIdx] ) @@ -875,6 +905,22 @@ QList> RiuMultiPlotPage::legendsForVisiblePlots() con return legends; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList> RiuMultiPlotPage::legendFramesForVisiblePlots() const +{ + QList> legendFrames; + for ( int i = 0; i < m_plotWidgets.size(); ++i ) + { + if ( m_plotWidgets[i]->isChecked() ) + { + legendFrames.push_back( m_legendFrames[i] ); + } + } + return legendFrames; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/UserInterface/RiuMultiPlotPage.h b/ApplicationLibCode/UserInterface/RiuMultiPlotPage.h index fe203c7b92..7564973eba 100644 --- a/ApplicationLibCode/UserInterface/RiuMultiPlotPage.h +++ b/ApplicationLibCode/UserInterface/RiuMultiPlotPage.h @@ -17,6 +17,7 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once +#include "RiuDraggableOverlayFrame.h" #include "RiuInterfaceToViewWindow.h" #include "RiaDefines.h" @@ -127,9 +128,10 @@ protected: void clearGridLayout(); - QList> visiblePlotWidgets() const; - QList> legendsForVisiblePlots() const; - QList> subTitlesForVisiblePlots() const; + QList> visiblePlotWidgets() const; + QList> legendsForVisiblePlots() const; + QList> subTitlesForVisiblePlots() const; + QList> legendFramesForVisiblePlots() const; void applyLook(); @@ -137,16 +139,17 @@ private slots: void onLegendUpdated(); protected: - QPointer m_layout; - QPointer m_plotLayout; - QPointer m_plotWidgetFrame; - QPointer m_gridLayout; - QPointer m_plotTitle; - QList> m_subTitles; - QList> m_legends; - QList> m_plotWidgets; - std::map> m_visibleIndexToPositionMapping; - caf::PdmPointer m_plotDefinition; + QPointer m_layout; + QPointer m_plotLayout; + QPointer m_plotWidgetFrame; + QPointer m_gridLayout; + QPointer m_plotTitle; + QList> m_subTitles; + QList> m_legends; + QList> m_legendFrames; + QList> m_plotWidgets; + std::map> m_visibleIndexToPositionMapping; + caf::PdmPointer m_plotDefinition; int m_titleFontPixelSize; int m_subTitleFontPixelSize; diff --git a/ApplicationLibCode/UserInterface/RiuQwtLegendOverlayContentFrame.cpp b/ApplicationLibCode/UserInterface/RiuQwtLegendOverlayContentFrame.cpp new file mode 100644 index 0000000000..bde5e7e766 --- /dev/null +++ b/ApplicationLibCode/UserInterface/RiuQwtLegendOverlayContentFrame.cpp @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022- 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 "RiuQwtLegendOverlayContentFrame.h" + +#include +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuQwtLegendOverlayContentFrame::RiuQwtLegendOverlayContentFrame( QWidget* parent ) + : RiuAbstractOverlayContentFrame( parent ) +{ + QVBoxLayout* layout = new QVBoxLayout( this ); + layout->setContentsMargins( 4, 4, 4, 4 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtLegendOverlayContentFrame::setLegend( QwtLegend* legend ) +{ + m_legend = legend; + layout()->addWidget( legend ); + legend->adjustSize(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtLegendOverlayContentFrame::renderTo( QPainter* painter, const QRect& targetRect ) +{ + painter->save(); + painter->translate( targetRect.topLeft() + QPoint( this->contentsMargins().left(), this->contentsMargins().top() ) ); + + QRegion sourceRegion = visibleRegion(); + render( painter, QPoint(), sourceRegion ); + + painter->restore(); +} diff --git a/ApplicationLibCode/UserInterface/RiuQwtLegendOverlayContentFrame.h b/ApplicationLibCode/UserInterface/RiuQwtLegendOverlayContentFrame.h new file mode 100644 index 0000000000..7560cb3d9c --- /dev/null +++ b/ApplicationLibCode/UserInterface/RiuQwtLegendOverlayContentFrame.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022- 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 "RiuAbstractOverlayContentFrame.h" + +#include +#include + +#include "qwt_legend.h" + +class QLabel; + +class RiuQwtLegendOverlayContentFrame : public RiuAbstractOverlayContentFrame +{ + Q_OBJECT +public: + RiuQwtLegendOverlayContentFrame( QWidget* parent = nullptr ); + + void setLegend( QwtLegend* legend ); + void renderTo( QPainter* painter, const QRect& targetRect ) override; + +private: + QPointer m_legend; +};