diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 31143abb9f..990ef9d86a 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -116,6 +116,7 @@ #include "cvfqtUtils.h" #include +#include #include #include #include @@ -1718,6 +1719,18 @@ void RiaGuiApplication::applyGuiPreferences( const RiaPreferences* oldPreference { m_mainWindow->applyFontSizesToDockedPlots(); } + + if ( oldPreferences->defaultPageLayout() != m_preferences->defaultPageLayout() ) + { + for ( RimViewWindow* viewWindow : allViewWindows ) + { + RimPlotWindow* plotWindow = dynamic_cast( viewWindow ); + if ( plotWindow ) + { + plotWindow->updateLayout(); + } + } + } } std::vector uiEditorsToUpdate; @@ -1752,6 +1765,14 @@ void RiaGuiApplication::updateGrpcServer() #endif } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiaGuiApplication::applicationResolution() +{ + return RiaGuiApplication::instance()->desktop()->logicalDpiX(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaGuiApplication.h b/ApplicationCode/Application/RiaGuiApplication.h index 92046ae353..a528614ff7 100644 --- a/ApplicationCode/Application/RiaGuiApplication.h +++ b/ApplicationCode/Application/RiaGuiApplication.h @@ -125,6 +125,7 @@ public: static void clearAllSelections(); void applyGuiPreferences( const RiaPreferences* oldPreferences = nullptr ); void updateGrpcServer(); + static int applicationResolution(); // Public RiaApplication overrides void initialize() override; diff --git a/ApplicationCode/Application/RiaPlotWindowRedrawScheduler.cpp b/ApplicationCode/Application/RiaPlotWindowRedrawScheduler.cpp index 15773e511d..0f47668016 100644 --- a/ApplicationCode/Application/RiaPlotWindowRedrawScheduler.cpp +++ b/ApplicationCode/Application/RiaPlotWindowRedrawScheduler.cpp @@ -17,6 +17,7 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaPlotWindowRedrawScheduler.h" +#include "RiuMultiPlotPage.h" #include "RiuMultiPlotWindow.h" #include "RiuQwtPlotWidget.h" @@ -40,13 +41,23 @@ RiaPlotWindowRedrawScheduler* RiaPlotWindowRedrawScheduler::instance() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiaPlotWindowRedrawScheduler::schedulePlotWindowUpdate( RiuMultiPlotWindow* plotWindow ) +void RiaPlotWindowRedrawScheduler::scheduleMultiPlotWindowUpdate( RiuMultiPlotWindow* plotWindow ) { m_plotWindowsToUpdate.push_back( plotWindow ); startTimer( 0 ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaPlotWindowRedrawScheduler::scheduleMultiPlotPageUpdate( RiuMultiPlotPage* plotPage ) +{ + m_plotPagesToUpdate.push_back( plotPage ); + + startTimer( 0 ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -70,6 +81,7 @@ void RiaPlotWindowRedrawScheduler::clearAllScheduledUpdates() } } m_plotWidgetsToReplot.clear(); + m_plotPagesToUpdate.clear(); m_plotWindowsToUpdate.clear(); } @@ -80,6 +92,7 @@ void RiaPlotWindowRedrawScheduler::performScheduledUpdatesAndReplots() { std::set updatedPlots; std::set updatedPlotWindows; + std::set updatedPlotPages; for ( RiuMultiPlotWindow* plotWindow : m_plotWindowsToUpdate ) { @@ -87,6 +100,19 @@ void RiaPlotWindowRedrawScheduler::performScheduledUpdatesAndReplots() { plotWindow->performUpdate(); updatedPlotWindows.insert( plotWindow ); + for ( RiuMultiPlotPage* page : plotWindow->pages() ) + { + updatedPlotPages.insert( page ); + } + } + } + + for ( RiuMultiPlotPage* plotPage : m_plotPagesToUpdate ) + { + if ( plotPage && !updatedPlotPages.count( plotPage ) ) + { + plotPage->performUpdate(); + updatedPlotPages.insert( plotPage ); } } @@ -101,6 +127,7 @@ void RiaPlotWindowRedrawScheduler::performScheduledUpdatesAndReplots() } m_plotWidgetsToReplot.clear(); + m_plotPagesToUpdate.clear(); m_plotWindowsToUpdate.clear(); } diff --git a/ApplicationCode/Application/RiaPlotWindowRedrawScheduler.h b/ApplicationCode/Application/RiaPlotWindowRedrawScheduler.h index c91ff68e7c..7288188d3d 100644 --- a/ApplicationCode/Application/RiaPlotWindowRedrawScheduler.h +++ b/ApplicationCode/Application/RiaPlotWindowRedrawScheduler.h @@ -26,6 +26,7 @@ #include +class RiuMultiPlotPage; class RiuMultiPlotWindow; class RiuQwtPlotWidget; @@ -35,7 +36,8 @@ class RiaPlotWindowRedrawScheduler : public QObject public: static RiaPlotWindowRedrawScheduler* instance(); - void schedulePlotWindowUpdate( RiuMultiPlotWindow* plotWindow ); + void scheduleMultiPlotWindowUpdate( RiuMultiPlotWindow* plotWindow ); + void scheduleMultiPlotPageUpdate( RiuMultiPlotPage* plotWindow ); void schedulePlotWidgetReplot( RiuQwtPlotWidget* plotWidget ); void clearAllScheduledUpdates(); void performScheduledUpdatesAndReplots(); @@ -52,5 +54,6 @@ private: private: std::vector> m_plotWidgetsToReplot; std::vector> m_plotWindowsToUpdate; + std::vector> m_plotPagesToUpdate; QScopedPointer m_plotWindowUpdateTimer; }; diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 5dc851c6a7..e56a5f6409 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -944,10 +944,15 @@ void RiaPreferences::writePreferencesToApplicationStore() QPageLayout RiaPreferences::defaultPageLayout() const { QPageSize pageSize( m_pageSize() ); - QPageLayout layout( pageSize, - m_pageOrientation(), - QMarginsF( m_pageLeftMargin, m_pageTopMargin, m_pageRightMargin, m_pageBottomMargin ), - (QPageLayout::Unit)pageSize.definitionUnits() ); + QPageLayout layout( pageSize, m_pageOrientation(), margins(), (QPageLayout::Unit)pageSize.definitionUnits() ); layout.setMode( QPageLayout::StandardMode ); return layout; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMarginsF RiaPreferences::margins() const +{ + return QMarginsF( m_pageLeftMargin, m_pageTopMargin, m_pageRightMargin, m_pageBottomMargin ); +} diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 72d5bb84e1..655c19e007 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -105,6 +105,7 @@ public: void writePreferencesToApplicationStore(); QPageLayout defaultPageLayout() const; + QMarginsF margins() const; public: // Pdm Fields caf::PdmField> navigationPolicy; diff --git a/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToFileFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToFileFeature.cpp index fc44161f4b..bf95a6ea85 100644 --- a/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToFileFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicSnapshotViewToFileFeature.cpp @@ -89,10 +89,9 @@ void RicSnapshotViewToFileFeature::savePlotPDFReportAs( const QString& fileName, pdfPrinter.setPageLayout( plot->pageLayout() ); pdfPrinter.setCreator( QCoreApplication::applicationName() ); pdfPrinter.setResolution( resolution ); - QRect widgetRect = plot->viewWidget()->contentsRect(); - QRect fullPageRect = pdfPrinter.pageLayout().fullRectPixels( resolution ); - QRect paintRect = pdfPrinter.pageLayout().paintRectPixels( resolution ); - plot->viewWidget()->resize( paintRect.size() ); + QRect widgetRect = plot->viewWidget()->contentsRect(); + QRect pageRect = pdfPrinter.pageLayout().fullRectPixels( resolution ); + plot->viewWidget()->resize( pageRect.size() ); plot->renderWindowContent( &pdfPrinter ); plot->viewWidget()->resize( widgetRect.size() ); } diff --git a/ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.cpp index 52b4bb4649..8ea5567446 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.cpp @@ -21,7 +21,7 @@ #include "RicWellLogPlotCurveFeatureImpl.h" #include "RiaGuiApplication.h" -#include "RiuMultiPlotWindow.h" +#include "RiuMultiPlotPage.h" #include "RiuPlotMainWindow.h" #include "RiuQwtPlotWidget.h" diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellDistributionPlotCollection.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellDistributionPlotCollection.cpp index 57fde46525..e252bad3fc 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellDistributionPlotCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellDistributionPlotCollection.cpp @@ -72,7 +72,7 @@ RimWellDistributionPlotCollection::RimWellDistributionPlotCollection() "" ); m_plotWindowTitle = "Well Distribution Plots"; - m_columnCountEnum = RimMultiPlotWindow::COLUMNS_UNLIMITED; + m_columnCount = RimMultiPlotWindow::COLUMNS_UNLIMITED; m_showPlotLegends = false; m_showWindow = false; diff --git a/ApplicationCode/ProjectDataModel/RimMultiPlotWindow.cpp b/ApplicationCode/ProjectDataModel/RimMultiPlotWindow.cpp index 6d53cb5ed0..fc3ba0d33d 100644 --- a/ApplicationCode/ProjectDataModel/RimMultiPlotWindow.cpp +++ b/ApplicationCode/ProjectDataModel/RimMultiPlotWindow.cpp @@ -19,10 +19,11 @@ #include "RimPlot.h" +#include "RiuMultiPlotWindow.h" #include "RiuPlotMainWindow.h" #include "RiuPlotMainWindowTools.h" -#include +#include #include #include @@ -39,6 +40,16 @@ void RimMultiPlotWindow::ColumnCountEnum::setUp() addItem( RimMultiPlotWindow::COLUMNS_UNLIMITED, "UNLIMITED", "Unlimited" ); setDefault( RimMultiPlotWindow::COLUMNS_2 ); } +template <> +void RimMultiPlotWindow::RowCountEnum::setUp() +{ + addItem( RimMultiPlotWindow::ROWS_1, "1", "1 Row" ); + addItem( RimMultiPlotWindow::ROWS_2, "2", "2 Rows" ); + addItem( RimMultiPlotWindow::ROWS_3, "3", "3 Rows" ); + addItem( RimMultiPlotWindow::ROWS_4, "4", "4 Rows" ); + setDefault( RimMultiPlotWindow::ROWS_2 ); +} + } // namespace caf CAF_PDM_SOURCE_INIT( RimMultiPlotWindow, "MultiPlot" ); @@ -58,7 +69,8 @@ RimMultiPlotWindow::RimMultiPlotWindow( bool hidePlotsInTreeView ) m_plots.uiCapability()->setUiHidden( true ); m_plots.uiCapability()->setUiTreeChildrenHidden( hidePlotsInTreeView ); - CAF_PDM_InitFieldNoDefault( &m_columnCountEnum, "NumberOfColumns", "Number of Columns", "", "", "" ); + CAF_PDM_InitFieldNoDefault( &m_columnCount, "NumberOfColumns", "Number of Columns", "", "", "" ); + CAF_PDM_InitFieldNoDefault( &m_rowsPerPage, "RowsPerPage", "Rows per Page", "", "", "" ); CAF_PDM_InitField( &m_showIndividualPlotTitles, "ShowPlotTitles", false, "Show Sub Plot Titles", "", "", "" ); @@ -91,7 +103,13 @@ RimMultiPlotWindow& RimMultiPlotWindow::operator=( RimMultiPlotWindow&& rhs ) m_plots.push_back( plot ); } - m_columnCountEnum = rhs.m_columnCountEnum; + m_showPlotWindowTitle = rhs.m_showPlotWindowTitle; + m_plotWindowTitle = rhs.m_plotWindowTitle; + m_columnCount = rhs.m_columnCount; + m_rowsPerPage = rhs.m_rowsPerPage; + m_showIndividualPlotTitles = rhs.m_showIndividualPlotTitles; + + m_acceptDrops = rhs.m_acceptDrops; return *this; } @@ -274,7 +292,7 @@ std::vector RimMultiPlotWindow::visiblePlots() const //-------------------------------------------------------------------------------------------------- void RimMultiPlotWindow::doUpdateLayout() { - if ( m_showWindow ) + if ( m_showWindow && m_viewer ) { m_viewer->scheduleUpdate(); } @@ -350,11 +368,19 @@ void RimMultiPlotWindow::setAutoScaleYEnabled( bool enabled ) //-------------------------------------------------------------------------------------------------- int RimMultiPlotWindow::columnCount() const { - if ( m_columnCountEnum() == COLUMNS_UNLIMITED ) + if ( m_columnCount() == COLUMNS_UNLIMITED ) { return std::numeric_limits::max(); } - return static_cast( m_columnCountEnum() ); + return static_cast( m_columnCount() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimMultiPlotWindow::rowsPerPage() const +{ + return static_cast( m_rowsPerPage() ); } //-------------------------------------------------------------------------------------------------- @@ -362,7 +388,15 @@ int RimMultiPlotWindow::columnCount() const //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimMultiPlotWindow::columnCountField() { - return &m_columnCountEnum; + return &m_columnCount; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimMultiPlotWindow::rowsPerPageField() +{ + return &m_rowsPerPage; } //-------------------------------------------------------------------------------------------------- @@ -494,7 +528,7 @@ void RimMultiPlotWindow::fieldChangedByUi( const caf::PdmFieldHandle* changedFie updatePlotWindowTitle(); applyPlotWindowTitleToWidgets(); } - else if ( changedField == &m_columnCountEnum ) + else if ( changedField == &m_columnCount || changedField == &m_rowsPerPage ) { updateLayout(); RiuPlotMainWindowTools::refreshToolbars(); @@ -520,7 +554,8 @@ void RimMultiPlotWindow::uiOrderingForPlotLayout( QString uiConfigName, caf::Pdm uiOrdering.add( &m_plotWindowTitle ); uiOrdering.add( &m_showIndividualPlotTitles ); RimPlotWindow::uiOrderingForLegendSettings( uiConfigName, uiOrdering ); - uiOrdering.add( &m_columnCountEnum ); + uiOrdering.add( &m_columnCount ); + uiOrdering.add( &m_rowsPerPage ); } //-------------------------------------------------------------------------------------------------- @@ -531,7 +566,7 @@ QList RimMultiPlotWindow::calculateValueOptions( const c { QList options = RimPlotWindow::calculateValueOptions( fieldNeedingOptions, useOptionsOnly ); - if ( fieldNeedingOptions == &m_columnCountEnum ) + if ( fieldNeedingOptions == &m_columnCount ) { for ( size_t i = 0; i < ColumnCountEnum::size(); ++i ) { diff --git a/ApplicationCode/ProjectDataModel/RimMultiPlotWindow.h b/ApplicationCode/ProjectDataModel/RimMultiPlotWindow.h index ecbbe97f47..b898e0e632 100644 --- a/ApplicationCode/ProjectDataModel/RimMultiPlotWindow.h +++ b/ApplicationCode/ProjectDataModel/RimMultiPlotWindow.h @@ -18,7 +18,7 @@ #pragma once #include "RimPlotWindow.h" -#include "RiuMultiPlotWindow.h" +#include "RiuMultiPlotInterface.h" #include "cafAppEnum.h" #include "cafPdmChildArrayField.h" @@ -49,6 +49,15 @@ public: }; using ColumnCountEnum = caf::AppEnum; + enum RowCount + { + ROWS_1 = 1, + ROWS_2 = 2, + ROWS_3 = 3, + ROWS_4 = 4, + }; + using RowCountEnum = caf::AppEnum; + public: RimMultiPlotWindow( bool hidePlotsInTreeView = false ); ~RimMultiPlotWindow() override; @@ -82,7 +91,9 @@ public: void setAutoScaleYEnabled( bool enabled ); int columnCount() const; + int rowsPerPage() const; caf::PdmFieldHandle* columnCountField(); + caf::PdmFieldHandle* rowsPerPageField(); bool showPlotTitles() const; void zoomAll() override; @@ -134,11 +145,12 @@ private: protected: caf::PdmField m_showPlotWindowTitle; caf::PdmField m_plotWindowTitle; - caf::PdmField m_columnCountEnum; + caf::PdmField m_columnCount; + caf::PdmField m_rowsPerPage; caf::PdmField m_showIndividualPlotTitles; - friend class RiuMultiPlotWindow; - QPointer m_viewer; + friend class RiuMultiPlotInterface; + QPointer m_viewer; private: caf::PdmChildArrayField m_plots; diff --git a/ApplicationCode/ProjectDataModel/RimWellLogPlot.cpp b/ApplicationCode/ProjectDataModel/RimWellLogPlot.cpp index 16b57b5194..ef781220ab 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogPlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogPlot.cpp @@ -32,7 +32,7 @@ #include "RimWellLogCurveCommonDataSource.h" #include "RimWellLogTrack.h" -#include "RiuMultiPlotWindow.h" +#include "RiuMultiPlotPage.h" #include "RiuPlotMainWindow.h" #include "RiuPlotMainWindowTools.h" #include "RiuQwtPlotWidget.h" @@ -105,7 +105,7 @@ RimWellLogPlot::RimWellLogPlot() m_maxAvailableDepth = -HUGE_VAL; m_commonDataSourceEnabled = true; - m_columnCountEnum = RimMultiPlotWindow::COLUMNS_UNLIMITED; + m_columnCount = RimMultiPlotWindow::COLUMNS_UNLIMITED; m_plotWindowTitle.xmlCapability()->setIOWritable( false ); m_plotLegendsHorizontal = false; @@ -616,7 +616,7 @@ void RimWellLogPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* titleAndLegendsGroup = uiOrdering.addNewGroup( "Plot Layout" ); uiOrderingForAutoName( uiConfigName, *titleAndLegendsGroup ); RimPlotWindow::uiOrderingForLegendSettings( uiConfigName, *titleAndLegendsGroup ); - titleAndLegendsGroup->add( &m_columnCountEnum ); + titleAndLegendsGroup->add( &m_columnCount ); uiOrdering.skipRemainingFields( true ); } @@ -683,7 +683,7 @@ void RimWellLogPlot::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) { - if ( field == &m_columnCountEnum ) + if ( field == &m_columnCount ) { auto comboAttr = dynamic_cast( attribute ); if ( comboAttr ) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogPlot.h b/ApplicationCode/ProjectDataModel/RimWellLogPlot.h index 1516eaf8c1..a2c96c3edb 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogPlot.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogPlot.h @@ -35,7 +35,7 @@ #include class RimWellLogCurveCommonDataSource; -class RiuMultiPlotWindow; +class RiuMultiPlotPage; class RimPlotWindow; class QKeyEvent; diff --git a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp index 154cb4ef43..fb81a16908 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp @@ -67,7 +67,6 @@ #include "RimWellRftPlot.h" #include "RiuMainWindow.h" -#include "RiuMultiPlotWindow.h" #include "RiuPlotAnnotationTool.h" #include "RiuPlotMainWindowTools.h" #include "RiuQwtPlotWidget.h" diff --git a/ApplicationCode/UserInterface/CMakeLists_files.cmake b/ApplicationCode/UserInterface/CMakeLists_files.cmake index b3e535cfbc..82a2be8422 100644 --- a/ApplicationCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationCode/UserInterface/CMakeLists_files.cmake @@ -52,7 +52,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuCellAndNncPickEventHandler.h ${CMAKE_CURRENT_LIST_DIR}/RiuPickItemInfo.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.h +${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotInterface.h +${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotPage.h ${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotWindow.h +${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotPage.h ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.h ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.h ${CMAKE_CURRENT_LIST_DIR}/RiuPlotAnnotationTool.h @@ -144,6 +147,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuCellAndNncPickEventHandler.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuPickItemInfo.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.cpp +${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotPage.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotWindow.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.cpp @@ -209,6 +213,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuViewerCommands.h ${CMAKE_CURRENT_LIST_DIR}/RiuTreeViewEventFilter.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.h +${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotInterface.h +${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotPage.h ${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotWindow.h ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.h ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.h diff --git a/ApplicationCode/UserInterface/RiuAbstractLegendFrame.cpp b/ApplicationCode/UserInterface/RiuAbstractLegendFrame.cpp index c852890a48..7b36c9c6e8 100644 --- a/ApplicationCode/UserInterface/RiuAbstractLegendFrame.cpp +++ b/ApplicationCode/UserInterface/RiuAbstractLegendFrame.cpp @@ -139,7 +139,7 @@ std::vector> RiuAbstractLegendFrame::visibleLabels( c { const int textX = layout.tickEndX + layout.tickTextLeadSpace; - const double overlapTolerance = 1.1 * layout.charHeight; + const double overlapTolerance = 1.2 * layout.charHeight; int lastVisibleTextY = 0; std::vector> visibleTickLabels; diff --git a/ApplicationCode/UserInterface/RiuCategoryLegendFrame.cpp b/ApplicationCode/UserInterface/RiuCategoryLegendFrame.cpp index 7c06932acf..bf69673b4d 100644 --- a/ApplicationCode/UserInterface/RiuCategoryLegendFrame.cpp +++ b/ApplicationCode/UserInterface/RiuCategoryLegendFrame.cpp @@ -100,6 +100,9 @@ int RiuCategoryLegendFrame::labelPixelPosY( const LayoutInfo& layout, int index { float categoryHeight = static_cast( layout.colorBarRect.height() ) / labelCount(); int textY = static_cast( layout.colorBarRect.top() + index * categoryHeight + categoryHeight / 2 ); - textY += layout.charAscent / 2; + + int offset = layout.charAscent - static_cast( std::ceil( layout.charHeight / 2.0 ) ); + + textY += offset; return textY; } diff --git a/ApplicationCode/UserInterface/RiuMultiPlotInterface.h b/ApplicationCode/UserInterface/RiuMultiPlotInterface.h new file mode 100644 index 0000000000..e9adcc5b8b --- /dev/null +++ b/ApplicationCode/UserInterface/RiuMultiPlotInterface.h @@ -0,0 +1,58 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 + +class RiuQwtPlotWidget; + +class QPaintDevice; +class QScrollBar; + +//================================================================================================== +// +// RiuMultiPlotInterface +// +//================================================================================================== +class RiuMultiPlotInterface : public QWidget +{ + Q_OBJECT + +public: + RiuMultiPlotInterface( QWidget* parent = nullptr ) + : QWidget( parent ) + { + } + virtual ~RiuMultiPlotInterface() {} + + virtual void addPlot( RiuQwtPlotWidget* plotWidget ) = 0; + virtual void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ) = 0; + virtual void removePlot( RiuQwtPlotWidget* plotWidget ) = 0; + virtual int indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ) = 0; + + virtual void setPlotTitle( const QString& plotTitle ) = 0; + virtual void setTitleVisible( bool visible ) = 0; + virtual void setFontSize( int fontSize ) = 0; + virtual int fontSize() const = 0; + + virtual void scheduleUpdate() = 0; + virtual void scheduleReplotOfAllPlots() = 0; + virtual void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) = 0; + + virtual void renderTo( QPaintDevice* paintDevice ) = 0; +}; diff --git a/ApplicationCode/UserInterface/RiuMultiPlotPage.cpp b/ApplicationCode/UserInterface/RiuMultiPlotPage.cpp new file mode 100644 index 0000000000..da7eaca425 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuMultiPlotPage.cpp @@ -0,0 +1,902 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "RiuMultiPlotPage.h" + +#include "RiaApplication.h" +#include "RiaPlotWindowRedrawScheduler.h" +#include "RiaPreferences.h" + +#include "WellLogCommands/RicWellLogPlotTrackFeatureImpl.h" + +#include "RiaGuiApplication.h" + +#include "RimContextCommandBuilder.h" +#include "RimMultiPlotWindow.h" +#include "RimWellLogTrack.h" + +#include "RiuMainWindow.h" +#include "RiuPlotMainWindow.h" +#include "RiuPlotObjectPicker.h" +#include "RiuQwtPlotLegend.h" +#include "RiuQwtPlotWidget.h" + +#include "cafCmdFeatureMenuBuilder.h" +#include "cafSelectionManager.h" + +#include "cvfAssert.h" + +#include "qwt_legend.h" +#include "qwt_plot_layout.h" +#include "qwt_plot_renderer.h" +#include "qwt_scale_draw.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuMultiPlotPage::RiuMultiPlotPage( RimMultiPlotWindow* plotDefinition, QWidget* parent ) + : RiuMultiPlotInterface( parent ) + , m_plotDefinition( plotDefinition ) +{ + Q_ASSERT( plotDefinition ); + m_plotDefinition = plotDefinition; + + m_layout = new QVBoxLayout( this ); + m_layout->setMargin( 0 ); + m_layout->setSpacing( 2 ); + + m_plotTitle = createTitleLabel(); + m_layout->addWidget( m_plotTitle ); + + m_plotLayout = new QHBoxLayout; + m_layout->addLayout( m_plotLayout ); + + m_plotWidgetFrame = new QFrame; + m_plotWidgetFrame->setVisible( true ); + m_plotLayout->addWidget( m_plotWidgetFrame, 1 ); + + m_gridLayout = new QGridLayout( m_plotWidgetFrame ); + m_gridLayout->setContentsMargins( 0, 0, 0, 0 ); + m_gridLayout->setSpacing( 1 ); + + QPalette newPalette( palette() ); + newPalette.setColor( QPalette::Window, Qt::white ); + setPalette( newPalette ); + + setAutoFillBackground( true ); + + new RiuPlotObjectPicker( m_plotTitle, m_plotDefinition ); + + m_dropTargetPlaceHolder = new QLabel( "Drag plots here" ); + m_dropTargetPlaceHolder->setAlignment( Qt::AlignCenter ); + m_dropTargetPlaceHolder->setObjectName( + QString( "%1" ).arg( reinterpret_cast( m_dropTargetPlaceHolder.data() ) ) ); + m_dropTargetStyleSheet = createDropTargetStyleSheet(); + m_dropTargetStyleSheet.applyToWidget( m_dropTargetPlaceHolder ); + + this->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding ); + + setFocusPolicy( Qt::StrongFocus ); + + setAcceptDrops( m_plotDefinition->acceptDrops() ); + + RiaApplication* app = RiaApplication::instance(); + int defaultFontSize = RiaFontCache::pointSizeFromFontSizeEnum( app->preferences()->defaultPlotFontSize() ); + setFontSize( defaultFontSize ); + + this->setObjectName( QString( "%1" ).arg( reinterpret_cast( this ) ) ); + + this->setBackgroundRole( QPalette::Window ); + + QGraphicsDropShadowEffect* dropShadowEffect = new QGraphicsDropShadowEffect( this ); + dropShadowEffect->setOffset( 4.0, 4.0 ); + dropShadowEffect->setBlurRadius( 4.0 ); + dropShadowEffect->setColor( QColor( 40, 40, 40, 40 ) ); + this->setGraphicsEffect( dropShadowEffect ); + + updateMarginsFromPageLayout(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuMultiPlotPage::~RiuMultiPlotPage() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimMultiPlotWindow* RiuMultiPlotPage::ownerPlotDefinition() +{ + return m_plotDefinition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::addPlot( RiuQwtPlotWidget* plotWidget ) +{ + // Insert the plot to the left of the scroll bar + insertPlot( plotWidget, m_plotWidgets.size() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ) +{ + plotWidget->setDraggable( true ); // Becomes draggable when added to a grid plot window + m_plotWidgets.insert( static_cast( index ), plotWidget ); + plotWidget->setVisible( false ); + + QLabel* subTitle = new QLabel( plotWidget->plotDefinition()->description() ); + subTitle->setAlignment( Qt::AlignRight ); + subTitle->setVisible( false ); + m_subTitles.insert( static_cast( index ), subTitle ); + + RiuQwtPlotLegend* legend = new RiuQwtPlotLegend( this ); + int legendColumns = 1; + if ( m_plotDefinition->legendsHorizontal() ) + { + legendColumns = 4; // unlimited + } + legend->setMaxColumns( legendColumns ); + legend->horizontalScrollBar()->setVisible( false ); + legend->verticalScrollBar()->setVisible( false ); + legend->connect( plotWidget, + SIGNAL( legendDataChanged( const QVariant&, const QList& ) ), + SLOT( updateLegend( const QVariant&, const QList& ) ) ); + QObject::connect( legend, SIGNAL( legendUpdated() ), this, SLOT( onLegendUpdated() ) ); + + legend->contentsWidget()->layout()->setAlignment( Qt::AlignBottom | Qt::AlignHCenter ); + legend->setVisible( false ); + plotWidget->updateLegend(); + m_legends.insert( static_cast( index ), legend ); + + scheduleUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::removePlot( RiuQwtPlotWidget* plotWidget ) +{ + if ( !plotWidget ) return; + + int plotWidgetIdx = m_plotWidgets.indexOf( plotWidget ); + if ( plotWidgetIdx < 0 ) return; + + m_plotWidgets.removeAt( plotWidgetIdx ); + plotWidget->setParent( nullptr ); + + RiuQwtPlotLegend* legend = m_legends[plotWidgetIdx]; + legend->setParent( nullptr ); + m_legends.removeAt( plotWidgetIdx ); + delete legend; + + QLabel* subTitle = m_subTitles[plotWidgetIdx]; + subTitle->setParent( nullptr ); + m_subTitles.removeAt( plotWidgetIdx ); + delete subTitle; + + scheduleUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::removeAllPlots() +{ + auto plotWidgets = m_plotWidgets; + for ( RiuQwtPlotWidget* plotWidget : plotWidgets ) + { + removePlot( plotWidget ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::setPlotTitle( const QString& plotTitle ) +{ + m_plotTitle->setText( plotTitle ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::setTitleVisible( bool visible ) +{ + m_plotTitle->setVisible( visible ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::setSelectionsVisible( bool visible ) +{ + for ( RiuQwtPlotWidget* plotWidget : m_plotWidgets ) + { + if ( visible && caf::SelectionManager::instance()->isSelected( plotWidget->plotDefinition(), 0 ) ) + { + plotWidget->setWidgetState( "selected" ); + } + else + { + caf::UiStyleSheet::clearWidgetStates( plotWidget ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::setFontSize( int fontSize ) +{ + QFont font = m_plotTitle->font(); + + font.setPointSize( fontSize + 1 ); + font.setBold( true ); + m_plotTitle->setFont( font ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuMultiPlotPage::fontSize() const +{ + return m_plotTitle->font().pointSize() - 1; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuMultiPlotPage::indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ) +{ + return m_plotWidgets.indexOf( plotWidget ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::scheduleUpdate() +{ + RiaPlotWindowRedrawScheduler::instance()->scheduleMultiPlotPageUpdate( this ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::scheduleReplotOfAllPlots() +{ + for ( RiuQwtPlotWidget* plotWidget : visiblePlotWidgets() ) + { + plotWidget->scheduleReplot(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::renderTo( QPaintDevice* paintDevice ) +{ + QPainter painter( paintDevice ); + renderTo( &painter ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::renderTo( QPainter* painter ) +{ + setSelectionsVisible( false ); + m_plotTitle->render( painter ); + + // Subtract margins because we are rendering into part inside the margins + QPoint marginOffset( m_layout->contentsMargins().left(), m_layout->contentsMargins().top() ); + + for ( auto subTitle : subTitlesForVisiblePlots() ) + { + if ( subTitle->isVisible() ) + { + QPoint renderOffset = m_plotWidgetFrame->mapToParent( subTitle->frameGeometry().topLeft() ) - marginOffset; + subTitle->render( painter, renderOffset ); + } + } + + for ( auto legend : legendsForVisiblePlots() ) + { + QPoint renderOffset = m_plotWidgetFrame->mapToParent( legend->frameGeometry().topLeft() ) - marginOffset; + legend->render( painter, renderOffset ); + } + + for ( auto plotWidget : visiblePlotWidgets() ) + { + QRect plotWidgetGeometry = plotWidget->frameGeometry(); + QPoint plotWidgetTopLeft = plotWidgetGeometry.topLeft(); + QPoint plotWidgetFrameTopLeft = m_plotWidgetFrame->frameGeometry().topLeft(); + plotWidgetGeometry.moveTo( plotWidgetTopLeft + plotWidgetFrameTopLeft - marginOffset ); + + plotWidget->renderTo( painter, plotWidgetGeometry ); + } + + setSelectionsVisible( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::contextMenuEvent( QContextMenuEvent* event ) +{ + QMenu menu; + caf::CmdFeatureMenuBuilder menuBuilder; + + caf::SelectionManager::instance()->setSelectedItem( ownerPlotDefinition() ); + + menuBuilder << "RicShowPlotDataFeature"; + menuBuilder << "RicShowContributingWellsFromPlotFeature"; + + menuBuilder.appendToMenu( &menu ); + + if ( menu.actions().size() > 0 ) + { + menu.exec( event->globalPos() ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QLabel* RiuMultiPlotPage::createTitleLabel() const +{ + QLabel* plotTitle = new QLabel( "PLOT TITLE HERE", nullptr ); + plotTitle->setVisible( m_plotDefinition->isMultiPlotTitleVisible() ); + plotTitle->setAlignment( Qt::AlignHCenter ); + plotTitle->setWordWrap( true ); + plotTitle->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); + return plotTitle; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::showEvent( QShowEvent* event ) +{ + QWidget::showEvent( event ); + scheduleUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::dragEnterEvent( QDragEnterEvent* event ) +{ + RiuQwtPlotWidget* source = dynamic_cast( event->source() ); + if ( source ) + { + setWidgetState( "dragTargetInto" ); + event->acceptProposedAction(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::dragMoveEvent( QDragMoveEvent* event ) +{ + if ( event->answerRect().intersects( this->geometry() ) ) + { + RiuQwtPlotWidget* source = dynamic_cast( event->source() ); + if ( source && willAcceptDroppedPlot( source ) ) + { + setWidgetState( "dragTargetInto" ); + + QRect originalGeometry = source->geometry(); + QPoint offset = source->dragStartPosition(); + QRect newRect( event->pos() - offset, originalGeometry.size() ); + + QList> visiblePlotWidgets = this->visiblePlotWidgets(); + + int insertBeforeIndex = visiblePlotWidgets.size(); + for ( int visibleIndex = 0; visibleIndex < visiblePlotWidgets.size(); ++visibleIndex ) + { + caf::UiStyleSheet::clearWidgetStates( visiblePlotWidgets[visibleIndex] ); + + if ( visiblePlotWidgets[visibleIndex]->frameIsInFrontOfThis( newRect ) ) + { + insertBeforeIndex = std::min( insertBeforeIndex, visibleIndex ); + } + } + if ( insertBeforeIndex >= 0 && insertBeforeIndex < visiblePlotWidgets.size() ) + { + visiblePlotWidgets[insertBeforeIndex]->setWidgetState( "dragTargetBefore" ); + } + + if ( insertBeforeIndex > 0 ) + { + int insertAfterIndex = insertBeforeIndex - 1; + visiblePlotWidgets[insertAfterIndex]->setWidgetState( "dragTargetAfter" ); + } + event->acceptProposedAction(); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::dragLeaveEvent( QDragLeaveEvent* event ) +{ + caf::UiStyleSheet::clearWidgetStates( this ); + + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::dropEvent( QDropEvent* event ) +{ + caf::UiStyleSheet::clearWidgetStates( this ); + + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] ); + } + + if ( this->geometry().contains( event->pos() ) ) + { + RiuQwtPlotWidget* source = dynamic_cast( event->source() ); + + if ( source && willAcceptDroppedPlot( source ) ) + { + event->acceptProposedAction(); + + QRect originalGeometry = source->geometry(); + QPoint offset = source->dragStartPosition(); + QRect newRect( event->pos() - offset, originalGeometry.size() ); + + int beforeIndex = m_plotWidgets.size(); + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + if ( m_plotWidgets[tIdx]->isVisible() ) + { + if ( m_plotWidgets[tIdx]->frameIsInFrontOfThis( newRect ) ) + { + beforeIndex = tIdx; + break; + } + } + } + RimPlot* insertAfter = nullptr; + if ( beforeIndex > 0 ) + { + insertAfter = m_plotWidgets[beforeIndex - 1]->plotDefinition(); + } + + RimPlot* plotToMove = source->plotDefinition(); + + if ( insertAfter != plotToMove ) + { + m_plotDefinition->movePlotsToThis( {plotToMove}, insertAfter ); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuMultiPlotPage::hasHeightForWidth() const +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuMultiPlotPage::heightForWidth( int width ) const +{ + QPageLayout pageLayout = m_plotDefinition->pageLayout(); + QRectF rect = pageLayout.fullRectPoints(); + double aspectRatio = rect.height() / rect.width(); + int height = static_cast( width * aspectRatio ); + return height; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::updateMarginsFromPageLayout() +{ + QPageLayout pageLayout = m_plotDefinition->pageLayout(); + const int resolution = RiaGuiApplication::applicationResolution(); + QMargins margins = pageLayout.marginsPixels( resolution ); + m_layout->setContentsMargins( margins ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuMultiPlotPage::sizeHint() const +{ + QPageLayout pageLayout = m_plotDefinition->pageLayout(); + const int resolution = RiaGuiApplication::applicationResolution(); + QRect rect = pageLayout.fullRectPixels( resolution ); + + return rect.size(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuMultiPlotPage::minimumSizeHint() const +{ + QSize fullSizeHint = sizeHint(); + return QSize( fullSizeHint.width() / 2, fullSizeHint.height() / 2 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuMultiPlotPage::willAcceptDroppedPlot( const RiuQwtPlotWidget* plotWidget ) const +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RiuMultiPlotPage::rowAndColumnCount( int plotWidgetCount ) const +{ + if ( plotWidgetCount == 0 ) + { + return std::make_pair( 0, 0 ); + } + + int columnCount = std::max( 1, m_plotDefinition->columnCount() ); + int rowCount = static_cast( std::ceil( plotWidgetCount / static_cast( columnCount ) ) ); + return std::make_pair( rowCount, columnCount ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) +{ + for ( RiuQwtPlotWidget* plotWidget : m_plotWidgets ) + { + CAF_ASSERT( plotWidget ); + + bool isSelected = false; + for ( int changedLevel : changedSelectionLevels ) + { + isSelected = isSelected || + caf::SelectionManager::instance()->isSelected( plotWidget->plotDefinition(), changedLevel ); + } + if ( isSelected ) + { + plotWidget->setWidgetState( "selected" ); + } + else + { + caf::UiStyleSheet::clearWidgetStates( plotWidget ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::setWidgetState( const QString& widgetState ) +{ + m_dropTargetStyleSheet.setWidgetState( m_dropTargetPlaceHolder, widgetState ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuMultiPlotPage::showYAxis( int row, int column ) const +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::performUpdate() +{ + updateMarginsFromPageLayout(); + reinsertPlotWidgets(); + alignCanvasTops(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::onLegendUpdated() +{ + scheduleUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::reinsertPlotWidgets() +{ + clearGridLayout(); + + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + if ( m_plotWidgets[tIdx] ) + { + m_plotWidgets[tIdx]->hide(); + } + if ( m_legends[tIdx] ) + { + m_legends[tIdx]->hide(); + } + if ( m_subTitles[tIdx] ) + { + m_subTitles[tIdx]->hide(); + } + } + + QList> subTitles = this->subTitlesForVisiblePlots(); + QList> legends = this->legendsForVisiblePlots(); + QList> plotWidgets = this->visiblePlotWidgets(); + + if ( plotWidgets.empty() && acceptDrops() ) + { + m_gridLayout->addWidget( m_dropTargetPlaceHolder, 0, 0 ); + m_gridLayout->setRowStretch( 0, 1 ); + m_dropTargetPlaceHolder->setVisible( true ); + } + else + { + m_dropTargetPlaceHolder->setVisible( false ); + + auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() ); + + int row = 0; + int column = 0; + for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) + { + int expextedColSpan = static_cast( plotWidgets[visibleIndex]->plotDefinition()->colSpan() ); + int colSpan = std::min( expextedColSpan, rowAndColumnCount.second ); + int rowSpan = plotWidgets[visibleIndex]->plotDefinition()->rowSpan(); + + std::tie( row, column ) = findAvailableRowAndColumn( row, column, colSpan, rowAndColumnCount.second ); + + m_gridLayout->addWidget( subTitles[visibleIndex], 3 * row, column, 1, colSpan ); + m_gridLayout + ->addWidget( legends[visibleIndex], 3 * row + 1, column, 1, colSpan, Qt::AlignHCenter | Qt::AlignBottom ); + m_gridLayout->addWidget( plotWidgets[visibleIndex], 3 * row + 2, column, 1 + ( rowSpan - 1 ) * 3, colSpan ); + + subTitles[visibleIndex]->setVisible( m_plotDefinition->showPlotTitles() ); + + plotWidgets[visibleIndex]->setAxisLabelsAndTicksEnabled( QwtPlot::yLeft, showYAxis( row, column ) ); + plotWidgets[visibleIndex]->setAxisTitleEnabled( QwtPlot::yLeft, showYAxis( row, column ) ); + + plotWidgets[visibleIndex]->show(); + + if ( m_plotDefinition->legendsVisible() ) + { + int legendColumns = 1; + if ( m_plotDefinition->legendsHorizontal() ) + { + legendColumns = 4; // unlimited + } + legends[visibleIndex]->setMaxColumns( legendColumns ); + QFont legendFont = legends[visibleIndex]->font(); + legendFont.setPointSize( m_plotDefinition->legendFontSize() ); + legends[visibleIndex]->setFont( legendFont ); + legends[visibleIndex]->show(); + } + else + { + legends[visibleIndex]->hide(); + } + + // Set basic row and column stretches + for ( int r = row; r < row + rowSpan; ++r ) + { + m_gridLayout->setRowStretch( 3 * r + 2, 1 ); + } + for ( int c = column; c < column + colSpan; ++c ) + { + int colStretch = 1; + if ( showYAxis( row, column ) ) colStretch += 1; + m_gridLayout->setColumnStretch( c, std::max( colStretch, m_gridLayout->columnStretch( c ) ) ); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuMultiPlotPage::alignCanvasTops() +{ + CVF_ASSERT( m_legends.size() == m_plotWidgets.size() ); + + QList> plotWidgets = visiblePlotWidgets(); + QList> legends = legendsForVisiblePlots(); + if ( plotWidgets.empty() ) return 0; + + auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() ); + + std::vector maxExtents( rowAndColumnCount.first, 0.0 ); + + for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) + { + int row = visibleIndex / rowAndColumnCount.second; + + QFont font = m_plotWidgets[visibleIndex]->axisFont( QwtPlot::xTop ); + maxExtents[row] = std::max( maxExtents[row], + plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->extent( font ) ); + } + + for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) + { + int row = visibleIndex / rowAndColumnCount.second; + plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->setMinimumExtent( maxExtents[row] ); + legends[visibleIndex]->adjustSize(); + } + return maxExtents[0]; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMultiPlotPage::clearGridLayout() +{ + if ( m_gridLayout ) + { + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + m_gridLayout->removeWidget( m_subTitles[tIdx] ); + m_gridLayout->removeWidget( m_legends[tIdx] ); + m_gridLayout->removeWidget( m_plotWidgets[tIdx] ); + } + + QLayoutItem* item; + while ( ( item = m_gridLayout->takeAt( 0 ) ) != nullptr ) + { + } + QWidget().setLayout( m_gridLayout ); + delete m_gridLayout; + m_gridLayout = new QGridLayout( m_plotWidgetFrame ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::UiStyleSheet RiuMultiPlotPage::createDropTargetStyleSheet() +{ + caf::UiStyleSheet styleSheet; + + styleSheet.set( "background-color", "white" ); + styleSheet.set( "border", "1px dashed black" ); + styleSheet.set( "font-size", "14pt" ); + styleSheet.property( "dragTargetInto" ).set( "border", "1px dashed lime" ); + styleSheet.property( "dragTargetInto" ).set( "background-color", "#DDFFDD" ); + + return styleSheet; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList> RiuMultiPlotPage::visiblePlotWidgets() const +{ + QList> plotWidgets; + for ( QPointer plotWidget : m_plotWidgets ) + { + if ( plotWidget->isChecked() ) + { + plotWidgets.push_back( plotWidget ); + } + } + return plotWidgets; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList> RiuMultiPlotPage::legendsForVisiblePlots() const +{ + QList> legends; + for ( int i = 0; i < m_plotWidgets.size(); ++i ) + { + if ( m_plotWidgets[i]->isChecked() ) + { + legends.push_back( m_legends[i] ); + } + } + return legends; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList> RiuMultiPlotPage::subTitlesForVisiblePlots() const +{ + QList> subTitles; + for ( int i = 0; i < m_plotWidgets.size(); ++i ) + { + if ( m_plotWidgets[i]->isChecked() ) + { + subTitles.push_back( m_subTitles[i] ); + } + } + return subTitles; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair + RiuMultiPlotPage::findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const +{ + int availableRow = startRow; + int availableColumn = startColumn; + while ( true ) + { + for ( ; availableColumn < columnCount; ++availableColumn ) + { + bool fits = true; + for ( int c = availableColumn; ( c < availableColumn + columnSpan ) && fits; ++c ) + { + if ( c >= columnCount ) + { + fits = false; + } + + if ( m_gridLayout->itemAtPosition( 3 * availableRow, c ) != nullptr ) + { + fits = false; + } + } + if ( fits ) + { + return std::make_pair( availableRow, availableColumn ); + } + } + availableColumn = 0; + availableRow++; + } + return std::make_pair( availableRow, availableColumn ); +} diff --git a/ApplicationCode/UserInterface/RiuMultiPlotPage.h b/ApplicationCode/UserInterface/RiuMultiPlotPage.h new file mode 100644 index 0000000000..127310eb82 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuMultiPlotPage.h @@ -0,0 +1,145 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiuMultiPlotInterface.h" + +#include "cafUiStyleSheet.h" + +#include "cafPdmPointer.h" +#include "cafSelectionChangedReceiver.h" + +#include +#include +#include +#include +#include +#include + +#include + +class RiaPlotWindowRedrawScheduler; +class RimMultiPlotWindow; +class RiuQwtPlotLegend; +class RiuQwtPlotWidget; + +class QFocusEvent; +class QLabel; +class QPaintDevice; +class QScrollBar; +class QwtLegend; +class QwtLegendData; +class QwtPlot; + +//================================================================================================== +// +// RiuMultiPlotPage +// +//================================================================================================== +class RiuMultiPlotPage : public RiuMultiPlotInterface, public caf::SelectionChangedReceiver +{ + Q_OBJECT + +public: + RiuMultiPlotPage( RimMultiPlotWindow* plotDefinition, QWidget* parent = nullptr ); + ~RiuMultiPlotPage() override; + + RimMultiPlotWindow* ownerPlotDefinition(); + + void addPlot( RiuQwtPlotWidget* plotWidget ) override; + void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ) override; + void removePlot( RiuQwtPlotWidget* plotWidget ) override; + void removeAllPlots(); + int indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ) override; + + void setSelectionsVisible( bool visible ); + + void setPlotTitle( const QString& plotTitle ) override; + void setTitleVisible( bool visible ) override; + void setFontSize( int fontSize ) override; + int fontSize() const override; + + void scheduleUpdate() override; + void scheduleReplotOfAllPlots() override; + void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) override {} + + void renderTo( QPaintDevice* paintDevice ) override; + void renderTo( QPainter* painter ); + + QSize sizeHint() const override; + QSize minimumSizeHint() const override; + int heightForWidth( int width ) const override; + +protected: + void contextMenuEvent( QContextMenuEvent* ) override; + QLabel* createTitleLabel() const; + + void showEvent( QShowEvent* event ) override; + void dragEnterEvent( QDragEnterEvent* event ) override; + void dragMoveEvent( QDragMoveEvent* event ) override; + void dragLeaveEvent( QDragLeaveEvent* event ) override; + void dropEvent( QDropEvent* event ) override; + bool hasHeightForWidth() const override; + void updateMarginsFromPageLayout(); + + virtual bool willAcceptDroppedPlot( const RiuQwtPlotWidget* plotWidget ) const; + + std::pair rowAndColumnCount( int plotWidgetCount ) const; + + virtual void onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) override; + + void setWidgetState( const QString& widgetState ); + + virtual bool showYAxis( int row, int column ) const; + + void reinsertPlotWidgets(); + int alignCanvasTops(); + + void clearGridLayout(); + caf::UiStyleSheet createDropTargetStyleSheet(); + + QList> visiblePlotWidgets() const; + QList> legendsForVisiblePlots() const; + QList> subTitlesForVisiblePlots() const; + + std::pair findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const; + +private slots: + virtual void performUpdate(); + void onLegendUpdated(); + +protected: + friend class RiuMultiPlotWindow; + + QPointer m_layout; + QPointer m_plotLayout; + QPointer m_plotWidgetFrame; + QPointer m_gridLayout; + QPointer m_plotTitle; + QList> m_subTitles; + QList> m_legends; + QList> m_plotWidgets; + caf::PdmPointer m_plotDefinition; + QPointer m_dropTargetPlaceHolder; + + caf::UiStyleSheet m_dropTargetStyleSheet; + +private: + friend class RiaPlotWindowRedrawScheduler; +}; diff --git a/ApplicationCode/UserInterface/RiuMultiPlotWindow.cpp b/ApplicationCode/UserInterface/RiuMultiPlotWindow.cpp index 715cc4a11e..1fa329c120 100644 --- a/ApplicationCode/UserInterface/RiuMultiPlotWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMultiPlotWindow.cpp @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS +// Copyright (C) 2019- 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 @@ -19,17 +18,16 @@ #include "RiuMultiPlotWindow.h" -#include "RiaApplication.h" +#include "RiaGuiApplication.h" #include "RiaPlotWindowRedrawScheduler.h" #include "RiaPreferences.h" -#include "WellLogCommands/RicWellLogPlotTrackFeatureImpl.h" - #include "RimContextCommandBuilder.h" #include "RimMultiPlotWindow.h" #include "RimWellLogTrack.h" #include "RiuMainWindow.h" +#include "RiuMultiPlotPage.h" #include "RiuPlotMainWindow.h" #include "RiuPlotObjectPicker.h" #include "RiuQwtPlotLegend.h" @@ -51,63 +49,98 @@ #include #include #include +#include +#include #include #include +#include #include +class BookFrame : public QFrame +{ +public: + BookFrame( int margins, QWidget* parent = nullptr ) + : QFrame( parent ) + , m_margins( margins ) + { + } + QSize calculateSize( int width ) const + { + int pageWidth = width - 2 * m_margins; + QList pages = this->findChildren(); + QSize fullSize( 0, 0 ); + for ( auto page : pages ) + { + fullSize.setWidth( pageWidth ); + fullSize.setHeight( fullSize.height() + m_margins + page->heightForWidth( pageWidth ) ); + } + QSize minSize = minimumSizeHint(); + return QSize( std::max( minSize.width(), fullSize.width() ), std::max( minSize.height(), fullSize.height() ) ); + } + +protected: + QSize minimumSizeHint() const override + { + QList pages = this->findChildren(); + QSize fullSize( 0, 0 ); + for ( auto page : pages ) + { + fullSize.setWidth( std::max( fullSize.width(), page->minimumSizeHint().width() ) ); + fullSize.setHeight( fullSize.height() + 8 + page->minimumSizeHint().height() ); + } + return fullSize; + } + +private: + int m_margins; +}; + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuMultiPlotWindow::RiuMultiPlotWindow( RimMultiPlotWindow* plotDefinition, QWidget* parent ) - : QWidget( parent ) + : RiuMultiPlotInterface( parent ) + , m_plotDefinition( plotDefinition ) + , m_plotTitle( "Multi Plot" ) + , m_titleVisible( true ) { Q_ASSERT( plotDefinition ); m_plotDefinition = plotDefinition; + const int spacing = 8; + + this->setBackgroundRole( QPalette::Dark ); + this->setContentsMargins( 0, 0, 0, 0 ); m_layout = new QVBoxLayout( this ); - m_layout->setMargin( 0 ); - m_layout->setSpacing( 2 ); - - m_plotTitle = createTitleLabel(); - m_layout->addWidget( m_plotTitle ); - - m_plotLayout = new QHBoxLayout; - m_layout->addLayout( m_plotLayout ); - - m_plotWidgetFrame = new QFrame; - m_plotWidgetFrame->setVisible( true ); - m_plotLayout->addWidget( m_plotWidgetFrame, 1 ); - - m_gridLayout = new QGridLayout( m_plotWidgetFrame ); - m_gridLayout->setContentsMargins( 1, 1, 1, 1 ); - m_gridLayout->setSpacing( 1 ); - - QPalette newPalette( palette() ); - newPalette.setColor( QPalette::Window, Qt::white ); - setPalette( newPalette ); + m_layout->setContentsMargins( 0, 0, 0, 0 ); + m_scrollArea = new QScrollArea( this ); + m_scrollArea->setFrameStyle( QFrame::NoFrame ); + m_scrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + m_scrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn ); + m_layout->addWidget( m_scrollArea ); + m_book = new BookFrame( spacing ); + m_book->setFrameStyle( QFrame::NoFrame ); + m_scrollArea->setWidget( m_book ); + m_scrollArea->setWidgetResizable( true ); + m_book->setBackgroundRole( QPalette::Dark ); + m_bookLayout = new QVBoxLayout( m_book ); + m_bookLayout->setSpacing( spacing ); + m_scrollArea->setVisible( true ); + m_book->setVisible( true ); setAutoFillBackground( true ); - new RiuPlotObjectPicker( m_plotTitle, m_plotDefinition ); - - m_dropTargetPlaceHolder = new QLabel( "Drag plots here" ); - m_dropTargetPlaceHolder->setAlignment( Qt::AlignCenter ); - m_dropTargetPlaceHolder->setObjectName( - QString( "%1" ).arg( reinterpret_cast( m_dropTargetPlaceHolder.data() ) ) ); - m_dropTargetStyleSheet = createDropTargetStyleSheet(); - m_dropTargetStyleSheet.applyToWidget( m_dropTargetPlaceHolder ); - this->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding ); setFocusPolicy( Qt::StrongFocus ); - setAcceptDrops( m_plotDefinition->acceptDrops() ); - RiaApplication* app = RiaApplication::instance(); int defaultFontSize = RiaFontCache::pointSizeFromFontSizeEnum( app->preferences()->defaultPlotFontSize() ); setFontSize( defaultFontSize ); + QSize pageSize = m_plotDefinition->pageLayout().fullRectPixels( RiaGuiApplication::applicationResolution() ).size(); + setBookSize( pageSize.width() ); this->setObjectName( QString( "%1" ).arg( reinterpret_cast( this ) ) ); } @@ -137,7 +170,7 @@ RimViewWindow* RiuMultiPlotWindow::ownerViewWindow() const //-------------------------------------------------------------------------------------------------- void RiuMultiPlotWindow::addPlot( RiuQwtPlotWidget* plotWidget ) { - // Insert the plot to the left of the scroll bar + // Push the plot to the back of the list insertPlot( plotWidget, m_plotWidgets.size() ); } @@ -148,29 +181,6 @@ void RiuMultiPlotWindow::insertPlot( RiuQwtPlotWidget* plotWidget, size_t index { plotWidget->setDraggable( true ); // Becomes draggable when added to a grid plot window m_plotWidgets.insert( static_cast( index ), plotWidget ); - - QLabel* subTitle = new QLabel( plotWidget->plotDefinition()->description() ); - subTitle->setAlignment( Qt::AlignRight ); - m_subTitles.insert( static_cast( index ), subTitle ); - - RiuQwtPlotLegend* legend = new RiuQwtPlotLegend( this ); - int legendColumns = 1; - if ( m_plotDefinition->legendsHorizontal() ) - { - legendColumns = 4; // unlimited - } - legend->setMaxColumns( legendColumns ); - legend->horizontalScrollBar()->setVisible( false ); - legend->verticalScrollBar()->setVisible( false ); - legend->connect( plotWidget, - SIGNAL( legendDataChanged( const QVariant&, const QList& ) ), - SLOT( updateLegend( const QVariant&, const QList& ) ) ); - QObject::connect( legend, SIGNAL( legendUpdated() ), this, SLOT( onLegendUpdated() ) ); - - legend->contentsWidget()->layout()->setAlignment( Qt::AlignBottom | Qt::AlignHCenter ); - plotWidget->updateLegend(); - m_legends.insert( static_cast( index ), legend ); - scheduleUpdate(); } @@ -185,17 +195,6 @@ void RiuMultiPlotWindow::removePlot( RiuQwtPlotWidget* plotWidget ) CVF_ASSERT( plotWidgetIdx >= 0 ); m_plotWidgets.removeAt( plotWidgetIdx ); - plotWidget->setParent( nullptr ); - - RiuQwtPlotLegend* legend = m_legends[plotWidgetIdx]; - legend->setParent( nullptr ); - m_legends.removeAt( plotWidgetIdx ); - delete legend; - - QLabel* subTitle = m_subTitles[plotWidgetIdx]; - subTitle->setParent( nullptr ); - m_subTitles.removeAt( plotWidgetIdx ); - delete subTitle; scheduleUpdate(); } @@ -205,7 +204,11 @@ void RiuMultiPlotWindow::removePlot( RiuQwtPlotWidget* plotWidget ) //-------------------------------------------------------------------------------------------------- void RiuMultiPlotWindow::setPlotTitle( const QString& plotTitle ) { - m_plotTitle->setText( plotTitle ); + m_plotTitle = plotTitle; + for ( int i = 0; i < m_pages.size(); ++i ) + { + m_pages[i]->setPlotTitle( QString( "%1 %2/%3" ).arg( m_plotTitle ).arg( i + 1 ).arg( m_pages.size() ) ); + } } //-------------------------------------------------------------------------------------------------- @@ -213,7 +216,11 @@ void RiuMultiPlotWindow::setPlotTitle( const QString& plotTitle ) //-------------------------------------------------------------------------------------------------- void RiuMultiPlotWindow::setTitleVisible( bool visible ) { - m_plotTitle->setVisible( visible ); + m_titleVisible = visible; + for ( auto page : m_pages ) + { + page->setTitleVisible( visible ); + } } //-------------------------------------------------------------------------------------------------- @@ -239,11 +246,8 @@ void RiuMultiPlotWindow::setSelectionsVisible( bool visible ) //-------------------------------------------------------------------------------------------------- void RiuMultiPlotWindow::setFontSize( int fontSize ) { - QFont font = m_plotTitle->font(); - - font.setPointSize( fontSize + 1 ); - font.setBold( true ); - m_plotTitle->setFont( font ); + QFont font = this->font(); + font.setPointSize( fontSize ); } //-------------------------------------------------------------------------------------------------- @@ -251,7 +255,7 @@ void RiuMultiPlotWindow::setFontSize( int fontSize ) //-------------------------------------------------------------------------------------------------- int RiuMultiPlotWindow::fontSize() const { - return m_plotTitle->font().pointSize() - 1; + return this->font().pointSize(); } //-------------------------------------------------------------------------------------------------- @@ -267,7 +271,7 @@ int RiuMultiPlotWindow::indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ) //-------------------------------------------------------------------------------------------------- void RiuMultiPlotWindow::scheduleUpdate() { - RiaPlotWindowRedrawScheduler::instance()->schedulePlotWindowUpdate( this ); + RiaPlotWindowRedrawScheduler::instance()->scheduleMultiPlotWindowUpdate( this ); } //-------------------------------------------------------------------------------------------------- @@ -286,7 +290,25 @@ void RiuMultiPlotWindow::scheduleReplotOfAllPlots() //-------------------------------------------------------------------------------------------------- void RiuMultiPlotWindow::renderTo( QPaintDevice* paintDevice ) { - doRenderTo( paintDevice ); + setSelectionsVisible( false ); + + bool firstPage = true; + QPainter painter( paintDevice ); + for ( RiuMultiPlotPage* page : m_pages ) + { + if ( !firstPage ) + { + QPagedPaintDevice* pagedDevice = dynamic_cast( paintDevice ); + if ( pagedDevice ) + { + pagedDevice->newPage(); + } + } + page->renderTo( &painter ); + firstPage = false; + } + + setSelectionsVisible( true ); } //-------------------------------------------------------------------------------------------------- @@ -310,155 +332,37 @@ void RiuMultiPlotWindow::contextMenuEvent( QContextMenuEvent* event ) } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QLabel* RiuMultiPlotWindow::createTitleLabel() const -{ - QLabel* plotTitle = new QLabel( "PLOT TITLE HERE", nullptr ); - plotTitle->setVisible( m_plotDefinition->isMultiPlotTitleVisible() ); - plotTitle->setAlignment( Qt::AlignHCenter ); - plotTitle->setWordWrap( true ); - plotTitle->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); - return plotTitle; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuMultiPlotWindow::showEvent( QShowEvent* event ) { QWidget::showEvent( event ); - scheduleUpdate(); + performUpdate(); + setBookSize( width() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::dragEnterEvent( QDragEnterEvent* event ) +void RiuMultiPlotWindow::resizeEvent( QResizeEvent* event ) { - RiuQwtPlotWidget* source = dynamic_cast( event->source() ); - if ( source ) - { - setWidgetState( "dragTargetInto" ); - event->acceptProposedAction(); - } + setBookSize( event->size().width() ); + QWidget::resizeEvent( event ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::dragMoveEvent( QDragMoveEvent* event ) +void RiuMultiPlotWindow::setBookSize( int frameWidth ) { - if ( event->answerRect().intersects( this->geometry() ) ) + for ( auto page : m_pages ) { - RiuQwtPlotWidget* source = dynamic_cast( event->source() ); - if ( source && willAcceptDroppedPlot( source ) ) - { - setWidgetState( "dragTargetInto" ); - - QRect originalGeometry = source->geometry(); - QPoint offset = source->dragStartPosition(); - QRect newRect( event->pos() - offset, originalGeometry.size() ); - - QList> visiblePlotWidgets = this->visiblePlotWidgets(); - - int insertBeforeIndex = visiblePlotWidgets.size(); - for ( int visibleIndex = 0; visibleIndex < visiblePlotWidgets.size(); ++visibleIndex ) - { - caf::UiStyleSheet::clearWidgetStates( visiblePlotWidgets[visibleIndex] ); - - if ( visiblePlotWidgets[visibleIndex]->frameIsInFrontOfThis( newRect ) ) - { - insertBeforeIndex = std::min( insertBeforeIndex, visibleIndex ); - } - } - if ( insertBeforeIndex >= 0 && insertBeforeIndex < visiblePlotWidgets.size() ) - { - visiblePlotWidgets[insertBeforeIndex]->setWidgetState( "dragTargetBefore" ); - } - - if ( insertBeforeIndex > 0 ) - { - int insertAfterIndex = insertBeforeIndex - 1; - visiblePlotWidgets[insertAfterIndex]->setWidgetState( "dragTargetAfter" ); - } - event->acceptProposedAction(); - } + int width = page->width(); + int heightForWidth = page->heightForWidth( width ); + page->resize( width, heightForWidth ); } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::dragLeaveEvent( QDragLeaveEvent* event ) -{ - caf::UiStyleSheet::clearWidgetStates( this ); - - for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) - { - caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::dropEvent( QDropEvent* event ) -{ - caf::UiStyleSheet::clearWidgetStates( this ); - - for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) - { - caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] ); - } - - if ( this->geometry().contains( event->pos() ) ) - { - RiuQwtPlotWidget* source = dynamic_cast( event->source() ); - - if ( source && willAcceptDroppedPlot( source ) ) - { - event->acceptProposedAction(); - - QRect originalGeometry = source->geometry(); - QPoint offset = source->dragStartPosition(); - QRect newRect( event->pos() - offset, originalGeometry.size() ); - - int beforeIndex = m_plotWidgets.size(); - for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) - { - if ( m_plotWidgets[tIdx]->isVisible() ) - { - if ( m_plotWidgets[tIdx]->frameIsInFrontOfThis( newRect ) ) - { - beforeIndex = tIdx; - break; - } - } - } - RimPlot* insertAfter = nullptr; - if ( beforeIndex > 0 ) - { - insertAfter = m_plotWidgets[beforeIndex - 1]->plotDefinition(); - } - - RimPlot* plotToMove = source->plotDefinition(); - - if ( insertAfter != plotToMove ) - { - m_plotDefinition->movePlotsToThis( {plotToMove}, insertAfter ); - } - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuMultiPlotWindow::willAcceptDroppedPlot( const RiuQwtPlotWidget* plotWidget ) const -{ - return true; + m_book->setFixedSize( m_book->calculateSize( frameWidth ) ); } //-------------------------------------------------------------------------------------------------- @@ -476,40 +380,6 @@ std::pair RiuMultiPlotWindow::rowAndColumnCount( int plotWidgetCount ) return std::make_pair( rowCount, columnCount ); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) -{ - for ( RiuQwtPlotWidget* plotWidget : m_plotWidgets ) - { - CAF_ASSERT( plotWidget ); - - bool isSelected = false; - for ( int changedLevel : changedSelectionLevels ) - { - isSelected = isSelected || - caf::SelectionManager::instance()->isSelected( plotWidget->plotDefinition(), changedLevel ); - } - if ( isSelected ) - { - plotWidget->setWidgetState( "selected" ); - } - else - { - caf::UiStyleSheet::clearWidgetStates( plotWidget ); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::setWidgetState( const QString& widgetState ) -{ - m_dropTargetStyleSheet.setWidgetState( m_dropTargetPlaceHolder, widgetState ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -523,183 +393,9 @@ bool RiuMultiPlotWindow::showYAxis( int row, int column ) const //-------------------------------------------------------------------------------------------------- void RiuMultiPlotWindow::performUpdate() { - reinsertPlotWidgets(); - alignCanvasTops(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::onLegendUpdated() -{ - scheduleUpdate(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::reinsertPlotWidgets() -{ - clearGridLayout(); - - for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) - { - if ( m_plotWidgets[tIdx] ) - { - m_plotWidgets[tIdx]->hide(); - } - if ( m_legends[tIdx] ) - { - m_legends[tIdx]->hide(); - } - if ( m_subTitles[tIdx] ) - { - m_subTitles[tIdx]->hide(); - } - } - - QList> subTitles = this->subTitlesForVisiblePlots(); - QList> legends = this->legendsForVisiblePlots(); - QList> plotWidgets = this->visiblePlotWidgets(); - - if ( plotWidgets.empty() && acceptDrops() ) - { - m_gridLayout->addWidget( m_dropTargetPlaceHolder, 0, 0 ); - m_gridLayout->setRowStretch( 0, 1 ); - m_dropTargetPlaceHolder->setVisible( true ); - } - else - { - m_dropTargetPlaceHolder->setVisible( false ); - - auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() ); - - int row = 0; - int column = 0; - for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) - { - int expextedColSpan = static_cast( plotWidgets[visibleIndex]->plotDefinition()->colSpan() ); - int colSpan = std::min( expextedColSpan, rowAndColumnCount.second ); - int rowSpan = plotWidgets[visibleIndex]->plotDefinition()->rowSpan(); - - std::tie( row, column ) = findAvailableRowAndColumn( row, column, colSpan, rowAndColumnCount.second ); - - m_gridLayout->addWidget( subTitles[visibleIndex], 3 * row, column, 1, colSpan ); - m_gridLayout - ->addWidget( legends[visibleIndex], 3 * row + 1, column, 1, colSpan, Qt::AlignHCenter | Qt::AlignBottom ); - m_gridLayout->addWidget( plotWidgets[visibleIndex], 3 * row + 2, column, 1 + ( rowSpan - 1 ) * 3, colSpan ); - - subTitles[visibleIndex]->setVisible( m_plotDefinition->showPlotTitles() ); - - plotWidgets[visibleIndex]->setAxisLabelsAndTicksEnabled( QwtPlot::yLeft, showYAxis( row, column ) ); - plotWidgets[visibleIndex]->setAxisTitleEnabled( QwtPlot::yLeft, showYAxis( row, column ) ); - - plotWidgets[visibleIndex]->show(); - - if ( m_plotDefinition->legendsVisible() ) - { - int legendColumns = 1; - if ( m_plotDefinition->legendsHorizontal() ) - { - legendColumns = 4; // unlimited - } - legends[visibleIndex]->setMaxColumns( legendColumns ); - QFont legendFont = legends[visibleIndex]->font(); - legendFont.setPointSize( m_plotDefinition->legendFontSize() ); - legends[visibleIndex]->setFont( legendFont ); - legends[visibleIndex]->show(); - } - else - { - legends[visibleIndex]->hide(); - } - - // Set basic row and column stretches - for ( int r = row; r < row + rowSpan; ++r ) - { - m_gridLayout->setRowStretch( 3 * r + 2, 1 ); - } - for ( int c = column; c < column + colSpan; ++c ) - { - int colStretch = 1; - if ( showYAxis( row, column ) ) colStretch += 1; - m_gridLayout->setColumnStretch( c, std::max( colStretch, m_gridLayout->columnStretch( c ) ) ); - } - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RiuMultiPlotWindow::alignCanvasTops() -{ - CVF_ASSERT( m_legends.size() == m_plotWidgets.size() ); - - QList> plotWidgets = visiblePlotWidgets(); - QList> legends = legendsForVisiblePlots(); - if ( plotWidgets.empty() ) return 0; - - auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() ); - - std::vector maxExtents( rowAndColumnCount.first, 0.0 ); - - for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) - { - int row = visibleIndex / rowAndColumnCount.second; - - QFont font = m_plotWidgets[visibleIndex]->axisFont( QwtPlot::xTop ); - maxExtents[row] = std::max( maxExtents[row], - plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->extent( font ) ); - } - - for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) - { - int row = visibleIndex / rowAndColumnCount.second; - plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->setMinimumExtent( maxExtents[row] ); - legends[visibleIndex]->adjustSize(); - } - return maxExtents[0]; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::clearGridLayout() -{ - if ( m_gridLayout ) - { - for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) - { - m_gridLayout->removeWidget( m_subTitles[tIdx] ); - m_gridLayout->removeWidget( m_legends[tIdx] ); - m_gridLayout->removeWidget( m_plotWidgets[tIdx] ); - } - - QLayoutItem* item; - while ( ( item = m_gridLayout->takeAt( 0 ) ) != nullptr ) - { - } - QWidget().setLayout( m_gridLayout ); - delete m_gridLayout; - m_gridLayout = new QGridLayout( m_plotWidgetFrame ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::UiStyleSheet RiuMultiPlotWindow::createDropTargetStyleSheet() -{ - caf::UiStyleSheet styleSheet; - - styleSheet.set( "background-color", "white" ); - styleSheet.set( "border", "1px dashed black" ); - styleSheet.set( "font-size", "14pt" ); - styleSheet.property( "dragTargetInto" ).set( "border", "1px dashed lime" ); - styleSheet.property( "dragTargetInto" ).set( "background-color", "#DDFFDD" ); - - return styleSheet; + deleteAllPages(); + createPages(); + updateGeometry(); } //-------------------------------------------------------------------------------------------------- @@ -721,102 +417,61 @@ QList> RiuMultiPlotWindow::visiblePlotWidgets() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QList> RiuMultiPlotWindow::legendsForVisiblePlots() const +void RiuMultiPlotWindow::deleteAllPages() { - QList> legends; - for ( int i = 0; i < m_plotWidgets.size(); ++i ) + for ( RiuMultiPlotPage* page : m_pages ) { - if ( m_plotWidgets[i]->isChecked() ) - { - legends.push_back( m_legends[i] ); - } + m_bookLayout->removeWidget( page ); + page->removeAllPlots(); + delete page; } - return legends; + m_pages.clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QList> RiuMultiPlotWindow::subTitlesForVisiblePlots() const +void RiuMultiPlotWindow::createPages() { - QList> subTitles; - for ( int i = 0; i < m_plotWidgets.size(); ++i ) + QList> plotWidgets = this->visiblePlotWidgets(); + auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() ); + + int rowsPerPage = m_plotDefinition->rowsPerPage(); + int row = 0; + int column = 0; + + RiuMultiPlotPage* page = new RiuMultiPlotPage( m_plotDefinition, this ); + m_pages.push_back( page ); + m_bookLayout->addWidget( page ); + for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) { - if ( m_plotWidgets[i]->isChecked() ) + int expextedColSpan = static_cast( plotWidgets[visibleIndex]->plotDefinition()->colSpan() ); + int colSpan = std::min( expextedColSpan, rowAndColumnCount.second ); + + std::tie( row, column ) = page->findAvailableRowAndColumn( row, column, colSpan, rowAndColumnCount.second ); + if ( row >= rowsPerPage ) { - subTitles.push_back( m_subTitles[i] ); + page = new RiuMultiPlotPage( m_plotDefinition, this ); + + m_pages.push_back( page ); + m_bookLayout->addWidget( page ); + row = 0; + column = 0; } + page->addPlot( plotWidgets[visibleIndex] ); + page->setVisible( true ); + page->performUpdate(); } - return subTitles; + // Reapply plot titles + setPlotTitle( m_plotTitle ); + setTitleVisible( m_titleVisible ); + m_book->adjustSize(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::pair - RiuMultiPlotWindow::findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const +const QList>& RiuMultiPlotWindow::pages() const { - int availableRow = startRow; - int availableColumn = startColumn; - while ( true ) - { - for ( ; availableColumn < columnCount; ++availableColumn ) - { - bool fits = true; - for ( int c = availableColumn; ( c < availableColumn + columnSpan ) && fits; ++c ) - { - if ( c >= columnCount ) - { - fits = false; - } - - if ( m_gridLayout->itemAtPosition( 3 * availableRow, c ) != nullptr ) - { - fits = false; - } - } - if ( fits ) - { - return std::make_pair( availableRow, availableColumn ); - } - } - availableColumn = 0; - availableRow++; - } - return std::make_pair( availableRow, availableColumn ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuMultiPlotWindow::doRenderTo( QPaintDevice* paintDevice ) -{ - QPainter painter( paintDevice ); - setSelectionsVisible( false ); - m_plotTitle->render( &painter ); - - for ( auto subTitle : subTitlesForVisiblePlots() ) - { - if ( subTitle->isVisible() ) - { - subTitle->render( &painter, m_plotWidgetFrame->mapToParent( subTitle->frameGeometry().topLeft() ) ); - } - } - - for ( auto legend : legendsForVisiblePlots() ) - { - legend->render( &painter, m_plotWidgetFrame->mapToParent( legend->frameGeometry().topLeft() ) ); - } - - for ( auto plotWidget : visiblePlotWidgets() ) - { - QRect plotWidgetGeometry = plotWidget->frameGeometry(); - QPoint plotWidgetTopLeft = plotWidgetGeometry.topLeft(); - QPoint plotWidgetFrameTopLeft = m_plotWidgetFrame->frameGeometry().topLeft(); - plotWidgetGeometry.moveTo( plotWidgetTopLeft + plotWidgetFrameTopLeft ); - - plotWidget->renderTo( &painter, plotWidgetGeometry ); - } - - setSelectionsVisible( true ); + return m_pages; } diff --git a/ApplicationCode/UserInterface/RiuMultiPlotWindow.h b/ApplicationCode/UserInterface/RiuMultiPlotWindow.h index e3539c1049..b534fa66ac 100644 --- a/ApplicationCode/UserInterface/RiuMultiPlotWindow.h +++ b/ApplicationCode/UserInterface/RiuMultiPlotWindow.h @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS +// Copyright (C) 2019- 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 @@ -20,6 +19,8 @@ #pragma once #include "RiuInterfaceToViewWindow.h" +#include "RiuMultiPlotInterface.h" + #include "cafUiStyleSheet.h" #include "cafPdmPointer.h" @@ -36,15 +37,15 @@ class RiaPlotWindowRedrawScheduler; class RimMultiPlotWindow; -class RiuQwtPlotLegend; +class RiuMultiPlotPage; class RiuQwtPlotWidget; +class BookFrame; class QFocusEvent; class QLabel; -class QPainter; +class QPaintDevice; +class QScrollArea; class QScrollBar; -class QwtLegend; -class QwtLegendData; class QwtPlot; //================================================================================================== @@ -52,7 +53,7 @@ class QwtPlot; // RiuMultiPlotWidget // //================================================================================================== -class RiuMultiPlotWindow : public QWidget, public RiuInterfaceToViewWindow, public caf::SelectionChangedReceiver +class RiuMultiPlotWindow : public RiuMultiPlotInterface, public RiuInterfaceToViewWindow { Q_OBJECT @@ -63,13 +64,13 @@ public: RimMultiPlotWindow* ownerPlotDefinition(); RimViewWindow* ownerViewWindow() const override; - void addPlot( RiuQwtPlotWidget* plotWidget ); - void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ); - void removePlot( RiuQwtPlotWidget* plotWidget ); + void addPlot( RiuQwtPlotWidget* plotWidget ) override; + void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ) override; + void removePlot( RiuQwtPlotWidget* plotWidget ) override; - void setPlotTitle( const QString& plotTitle ); + void setPlotTitle( const QString& plotTitle ) override; - void setTitleVisible( bool visible ); + void setTitleVisible( bool visible ) override; void setSelectionsVisible( bool visible ); void setFontSize( int fontSize ); @@ -77,63 +78,45 @@ public: int indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ); - void scheduleUpdate(); - void scheduleReplotOfAllPlots(); - virtual void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) {} + void scheduleUpdate(); + void scheduleReplotOfAllPlots(); + void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) override {} - void renderTo( QPaintDevice* paintDevice ); + void renderTo( QPaintDevice* painter ) override; protected: - void contextMenuEvent( QContextMenuEvent* ) override; - QLabel* createTitleLabel() const; + void contextMenuEvent( QContextMenuEvent* ) override; - void showEvent( QShowEvent* event ) override; - void dragEnterEvent( QDragEnterEvent* event ) override; - void dragMoveEvent( QDragMoveEvent* event ) override; - void dragLeaveEvent( QDragLeaveEvent* event ) override; - void dropEvent( QDropEvent* event ) override; - virtual bool willAcceptDroppedPlot( const RiuQwtPlotWidget* plotWidget ) const; + void showEvent( QShowEvent* event ) override; + void resizeEvent( QResizeEvent* event ) override; + + void setBookSize( int frameWidth ); std::pair rowAndColumnCount( int plotWidgetCount ) const; - virtual void onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) override; - - void setWidgetState( const QString& widgetState ); - virtual bool showYAxis( int row, int column ) const; - void reinsertPlotWidgets(); - int alignCanvasTops(); - - void clearGridLayout(); - caf::UiStyleSheet createDropTargetStyleSheet(); - QList> visiblePlotWidgets() const; - QList> legendsForVisiblePlots() const; - QList> subTitlesForVisiblePlots() const; - std::pair findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const; - - virtual void doRenderTo( QPaintDevice* paintDevice ); +private: + void deleteAllPages(); + void createPages(); + const QList>& pages() const; private slots: virtual void performUpdate(); - void onLegendUpdated(); protected: - QPointer m_layout; - QPointer m_plotLayout; - QPointer m_plotWidgetFrame; - QPointer m_gridLayout; - QPointer m_plotTitle; - QList> m_subTitles; - QList> m_legends; + friend class RiaPlotWindowRedrawScheduler; + + QPointer m_layout; + QPointer m_scrollArea; + QPointer m_book; + QPointer m_bookLayout; + + QList> m_pages; QList> m_plotWidgets; caf::PdmPointer m_plotDefinition; - QPointer m_dropTargetPlaceHolder; - - caf::UiStyleSheet m_dropTargetStyleSheet; - -private: - friend class RiaPlotWindowRedrawScheduler; + QString m_plotTitle; + bool m_titleVisible; }; diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index 2baa3074f6..2390e58022 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -43,7 +43,7 @@ #include "RiuDockWidgetTools.h" #include "RiuDragDrop.h" #include "RiuMdiSubWindow.h" -#include "RiuMultiPlotWindow.h" +#include "RiuMultiPlotPage.h" #include "RiuToolTipMenu.h" #include "RiuTreeViewEventFilter.h" #include "RiuWellAllocationPlot.h" diff --git a/ApplicationCode/UserInterface/RiuScalarMapperLegendFrame.cpp b/ApplicationCode/UserInterface/RiuScalarMapperLegendFrame.cpp index 01b2185bba..a94ba7ae4e 100644 --- a/ApplicationCode/UserInterface/RiuScalarMapperLegendFrame.cpp +++ b/ApplicationCode/UserInterface/RiuScalarMapperLegendFrame.cpp @@ -199,5 +199,6 @@ void RiuScalarMapperLegendFrame::renderRect( QPainter* painter, const LayoutInfo int RiuScalarMapperLegendFrame::labelPixelPosY( const LayoutInfo& layout, int index ) const { int indexFromBottom = labelCount() - index - 1; - return layout.colorBarRect.bottom() - layout.tickYPixelPos[indexFromBottom] + layout.charAscent / 2; + int offset = layout.charAscent - static_cast( std::ceil( layout.charHeight / 2.0 ) ); + return layout.colorBarRect.bottom() - layout.tickYPixelPos[indexFromBottom] + offset; } diff --git a/ApplicationCode/UserInterface/RiuWellLogPlot.cpp b/ApplicationCode/UserInterface/RiuWellLogPlot.cpp index cb679cd2e1..95c5ee557c 100644 --- a/ApplicationCode/UserInterface/RiuWellLogPlot.cpp +++ b/ApplicationCode/UserInterface/RiuWellLogPlot.cpp @@ -15,7 +15,7 @@ /// //-------------------------------------------------------------------------------------------------- RiuWellLogPlot::RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent ) - : RiuMultiPlotWindow( plotDefinition, parent ) + : RiuMultiPlotPage( plotDefinition, parent ) { m_trackScrollBar = new QScrollBar( nullptr ); m_trackScrollBar->setOrientation( Qt::Vertical ); @@ -40,11 +40,9 @@ RimWellLogPlot* RiuWellLogPlot::wellLogPlotDefinition() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::doRenderTo( QPaintDevice* paintDevice ) +RimViewWindow* RiuWellLogPlot::ownerViewWindow() const { - m_trackScrollBar->setVisible( false ); - RiuMultiPlotWindow::doRenderTo( paintDevice ); - m_trackScrollBar->setVisible( true ); + return m_plotDefinition; } //-------------------------------------------------------------------------------------------------- @@ -66,6 +64,16 @@ void RiuWellLogPlot::updateVerticalScrollBar( double minVisible, double maxVisib m_trackScrollBar->blockSignals( false ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogPlot::renderTo( QPaintDevice* paintDevice ) +{ + m_trackScrollBar->setVisible( false ); + RiuMultiPlotPage::renderTo( paintDevice ); + m_trackScrollBar->setVisible( true ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuWellLogPlot.h b/ApplicationCode/UserInterface/RiuWellLogPlot.h index 0ebc4c36ad..842b2ba11c 100644 --- a/ApplicationCode/UserInterface/RiuWellLogPlot.h +++ b/ApplicationCode/UserInterface/RiuWellLogPlot.h @@ -17,18 +17,22 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once -#include "RiuMultiPlotWindow.h" +#include "RiuInterfaceToViewWindow.h" +#include "RiuMultiPlotPage.h" class RiuQwtPlotWidget; class RimWellLogPlot; -class RiuWellLogPlot : public RiuMultiPlotWindow +class RiuWellLogPlot : public RiuMultiPlotPage, public RiuInterfaceToViewWindow { Q_OBJECT public: RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent ); + RimViewWindow* ownerViewWindow() const override; + void updateVerticalScrollBar( double minVisible, double maxVisible, double minAvailable, double maxAvailable ) override; + void renderTo( QPaintDevice* paintDevice ) override; protected: void keyPressEvent( QKeyEvent* event ) override; @@ -37,7 +41,6 @@ protected: void reinsertScrollbar(); void alignScrollbar( int offset ); - void doRenderTo( QPaintDevice* paintDevice ) override; private: RimWellLogPlot* wellLogPlotDefinition();