Implement pdf rendering (#5250)

* First PDF creation support

* Reimplement info box

* Set title and make overlay frame margins more unified

* Remove a style sheet that was never meant to be applied to Project Tree

* Update RiuDraggableOverlayFrame when changing content

* Default page layout in Preferences

* undo removal of elision

* Remove friend class assignment in cafCategoryMapper

* the required methods have been made public

* Fix up after review

* Remove spurious const on by-value return

* Fix compile errors on Linux

* Fix size adjustment of legends with plot resizing
This commit is contained in:
Gaute Lindkvist 2019-12-18 12:25:19 +01:00 committed by GitHub
parent f339b52907
commit 47b93dc0d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1675 additions and 559 deletions

View File

@ -59,9 +59,32 @@ void RiaPreferences::SummaryHistoryCurveStyleModeType::setUp()
addItem( RiaPreferences::SYMBOLS_AND_LINES, "SYMBOLS_AND_LINES", "Symbols and Lines" );
setDefault( RiaPreferences::SYMBOLS );
}
template <>
void RiaPreferences::PageSizeEnum::setUp()
{
addItem( QPageSize::A3, "A3", "A3" );
addItem( QPageSize::A4, "A4", "A4" );
addItem( QPageSize::A5, "A5", "A5" );
addItem( QPageSize::A6, "A6", "A6" );
addItem( QPageSize::Letter, "LETTER", "US Letter" );
addItem( QPageSize::Legal, "LEGAL", "US Legal" );
addItem( QPageSize::Ledger, "LEDGER", "US Ledger" );
addItem( QPageSize::Tabloid, "TABLOID", "US Tabloid" );
setDefault( QPageSize::A4 );
}
template <>
void RiaPreferences::PageOrientationEnum::setUp()
{
addItem( QPageLayout::Portrait, "PORTRAIT", "Portrait" );
addItem( QPageLayout::Landscape, "LANDSCAPE", "Landscape" );
setDefault( QPageLayout::Portrait );
}
} // namespace caf
CAF_PDM_SOURCE_INIT( RiaPreferences, "RiaPreferences" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -337,6 +360,19 @@ RiaPreferences::RiaPreferences( void )
"",
"" );
m_useMultipleThreadsWhenLoadingSummaryData.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
CAF_PDM_InitFieldNoDefault( &m_pageSize, "pageSize", "Page Size", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_pageOrientation, "pageOrientation", "Page Orientation", "", "", "" );
CAF_PDM_InitField( &m_pageLeftMargin, "pageLeftMargin", defaultMarginSize( m_pageSize() ), "Left Margin", "", "", "" );
CAF_PDM_InitField( &m_pageTopMargin, "pageTopMargin", defaultMarginSize( m_pageSize() ), "Top Margin", "", "", "" );
CAF_PDM_InitField( &m_pageRightMargin, "pageRightMargin", defaultMarginSize( m_pageSize() ), "Right Margin", "", "", "" );
CAF_PDM_InitField( &m_pageBottomMargin,
"pageBottomMargin",
defaultMarginSize( m_pageSize() ),
"Bottom Margin",
"",
"",
"" );
}
//--------------------------------------------------------------------------------------------------
@ -467,7 +503,26 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Plot Templates" );
group->add( &m_plotTemplateFolders );
group->add( &m_searchPlotTemplateFoldersRecursively );
caf::PdmUiGroup* pageSetup = uiOrdering.addNewGroup( "Page Setup" );
pageSetup->add( &m_pageSize );
pageSetup->add( &m_pageOrientation, false );
pageSetup->add( &m_pageLeftMargin );
pageSetup->add( &m_pageRightMargin, false );
pageSetup->add( &m_pageTopMargin );
pageSetup->add( &m_pageBottomMargin, false );
QString unitLabel = " [mm]";
if ( QPageSize( m_pageSize() ).definitionUnits() == QPageSize::Inch )
{
unitLabel = " [in]";
}
m_pageLeftMargin.uiCapability()->setUiName( "Left Margin" + unitLabel );
m_pageRightMargin.uiCapability()->setUiName( "Right Margin" + unitLabel );
m_pageTopMargin.uiCapability()->setUiName( "Top Margin" + unitLabel );
m_pageBottomMargin.uiCapability()->setUiName( "Bottom Margin" + unitLabel );
}
else if ( uiConfigName == RiaPreferences::tabNameScripting() )
{
caf::PdmUiGroup* octaveGroup = uiOrdering.addNewGroup( "Octave" );
@ -581,6 +636,21 @@ void RiaPreferences::initAfterRead()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaPreferences::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
if ( changedField == &m_pageSize )
{
m_pageLeftMargin = defaultMarginSize( m_pageSize() );
m_pageRightMargin = defaultMarginSize( m_pageSize() );
m_pageTopMargin = defaultMarginSize( m_pageSize() );
m_pageBottomMargin = defaultMarginSize( m_pageSize() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -629,6 +699,22 @@ QString RiaPreferences::tabNameSystem()
return "System";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RiaPreferences::defaultMarginSize( QPageSize::PageSizeId pageSizeId )
{
QPageSize::Unit unit = QPageSize( pageSizeId ).definitionUnits();
if ( unit == QPageSize::Inch )
{
return 1.0;
}
else
{
return 20.0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -851,3 +937,17 @@ void RiaPreferences::writePreferencesToApplicationStore()
{
caf::PdmSettings::writeFieldsToApplicationStore( this );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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() );
layout.setMode( QPageLayout::StandardMode );
return layout;
}

View File

@ -35,6 +35,8 @@
// Include to make Pdm work for cvf::Color
#include "cafPdmFieldCvfColor.h"
#include <QPageLayout>
#include <QPageSize>
#include <QStringList>
#include <map>
@ -66,6 +68,10 @@ public:
};
typedef caf::AppEnum<SummaryHistoryCurveStyleMode> SummaryHistoryCurveStyleModeType;
typedef caf::AppEnum<QPageSize::PageSizeId> PageSizeEnum;
typedef caf::AppEnum<QPageLayout::Orientation> PageOrientationEnum;
public:
RiaPreferences( void );
~RiaPreferences( void ) override;
@ -97,7 +103,8 @@ public:
std::map<RiaDefines::FontSettingType, RiaFontCache::FontSize> defaultFontSizes() const;
void writePreferencesToApplicationStore();
void writePreferencesToApplicationStore();
QPageLayout defaultPageLayout() const;
public: // Pdm Fields
caf::PdmField<caf::AppEnum<RiaGuiApplication::RINavigationPolicy>> navigationPolicy;
@ -156,6 +163,9 @@ protected:
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void initAfterRead() override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue ) override;
private:
static QString tabNameGeneral();
@ -165,6 +175,8 @@ private:
static QString tabNameExport();
static QString tabNameSystem();
static double defaultMarginSize( QPageSize::PageSizeId pageSizeId );
private:
caf::PdmChildField<RifReaderSettings*> m_readerSettings;
@ -184,6 +196,13 @@ private:
caf::PdmField<bool> m_showSummaryTimeAsLongString;
caf::PdmField<bool> m_useMultipleThreadsWhenLoadingSummaryData;
caf::PdmField<PageSizeEnum> m_pageSize;
caf::PdmField<PageOrientationEnum> m_pageOrientation;
caf::PdmField<double> m_pageLeftMargin;
caf::PdmField<double> m_pageRightMargin;
caf::PdmField<double> m_pageTopMargin;
caf::PdmField<double> m_pageBottomMargin;
caf::PdmField<QString> m_plotTemplateFolders;
caf::PdmField<bool> m_searchPlotTemplateFoldersRecursively;
caf::PdmField<caf::FilePath> m_defaultPlotTemplate;

View File

@ -20,8 +20,10 @@
#include "RiaGuiApplication.h"
#include "RiaLogging.h"
#include "RiaPlotWindowRedrawScheduler.h"
#include "RimMainPlotCollection.h"
#include "RimPlotWindow.h"
#include "RimProject.h"
#include "RimViewWindow.h"
#include "RiuPlotMainWindow.h"
@ -33,9 +35,13 @@
#include <QAction>
#include <QClipboard>
#include <QDebug>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QFileInfo>
#include <QMdiSubWindow>
#include <QPageLayout>
#include <QPainter>
#include <QPdfWriter>
CAF_CMD_SOURCE_INIT( RicSnapshotViewToFileFeature, "RicSnapshotViewToFileFeature" );
@ -72,7 +78,71 @@ void RicSnapshotViewToFileFeature::saveSnapshotAs( const QString& fileName, cons
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSnapshotViewToFileFeature::saveToFile( const QImage& image, const QString& defaultFileBaseName )
void RicSnapshotViewToFileFeature::savePlotPDFReportAs( const QString& fileName, RimPlotWindow* plot )
{
RiaPlotWindowRedrawScheduler::instance()->performScheduledUpdatesAndReplots();
QCoreApplication::processEvents();
QFile pdfFile( fileName );
if ( pdfFile.open( QIODevice::WriteOnly ) )
{
const int resolution = RiaGuiApplication::instance()->desktop()->logicalDpiX();
QPdfWriter pdfPrinter( fileName );
pdfPrinter.setPageLayout( plot->pageLayout() );
pdfPrinter.setCreator( QCoreApplication::applicationName() );
pdfPrinter.setResolution( resolution );
QPainter painter( &pdfPrinter );
QRect widgetRect = plot->viewWidget()->contentsRect();
QRect fullPageRect = pdfPrinter.pageLayout().fullRectPixels( resolution );
QRect paintRect = pdfPrinter.pageLayout().paintRectPixels( resolution );
plot->viewWidget()->resize( paintRect.size() );
plot->renderWindowContent( &painter );
plot->viewWidget()->resize( widgetRect.size() );
}
else
{
RiaLogging::error( QString( "Could not write PDF to %1" ).arg( fileName ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSnapshotViewToFileFeature::saveViewWindowToFile( RimViewWindow* viewWindow,
const QString& defaultFileBaseName /*= "image" */ )
{
RimPlotWindow* plotWindow = dynamic_cast<RimPlotWindow*>( viewWindow );
QString fileName = generateSaveFileName( defaultFileBaseName, plotWindow != nullptr );
if ( !fileName.isEmpty() )
{
if ( plotWindow && fileName.endsWith( "PDF", Qt::CaseInsensitive ) )
{
savePlotPDFReportAs( fileName, plotWindow );
}
else
{
RicSnapshotViewToFileFeature::saveSnapshotAs( fileName, viewWindow->snapshotWindowContent() );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSnapshotViewToFileFeature::saveImageToFile( const QImage& image, const QString& defaultFileBaseName )
{
QString fileName = generateSaveFileName( defaultFileBaseName, false );
if ( !fileName.isEmpty() )
{
RicSnapshotViewToFileFeature::saveSnapshotAs( fileName, image );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicSnapshotViewToFileFeature::generateSaveFileName( const QString& defaultFileBaseName /*= "image"*/,
bool supportPDF /*= false */ )
{
RiaApplication* app = RiaApplication::instance();
RimProject* proj = app->project();
@ -88,17 +158,30 @@ void RicSnapshotViewToFileFeature::saveToFile( const QImage& image, const QStrin
startPath = app->lastUsedDialogDirectory( "IMAGE_SNAPSHOT" );
}
QString defaultAbsFileName = caf::Utils::constructFullFileName( startPath, defaultFileBaseName, ".png" );
QString fileName = QFileDialog::getSaveFileName( nullptr, tr( "Export to File" ), defaultAbsFileName );
if ( fileName.isEmpty() )
QStringList imageFileExtensions;
imageFileExtensions << "*.png"
<< "*.jpg"
<< "*.bmp"
<< "*.pbm"
<< "*.pgm";
QString fileExtensionFilter = QString( "Images (%1)" ).arg( imageFileExtensions.join( " " ) );
if ( supportPDF )
{
return;
fileExtensionFilter += ";;PDF report( *.pdf )";
}
// Remember the directory to next time
app->setLastUsedDialogDirectory( "IMAGE_SNAPSHOT", QFileInfo( fileName ).absolutePath() );
RicSnapshotViewToFileFeature::saveSnapshotAs( fileName, image );
QString defaultAbsFileName = caf::Utils::constructFullFileName( startPath, defaultFileBaseName, ".png" );
QString fileName = QFileDialog::getSaveFileName( nullptr,
tr( "Export to File" ),
defaultAbsFileName,
fileExtensionFilter );
if ( !fileName.isEmpty() )
{
// Remember the directory to next time
app->setLastUsedDialogDirectory( "IMAGE_SNAPSHOT", QFileInfo( fileName ).absolutePath() );
}
return fileName;
}
//--------------------------------------------------------------------------------------------------
@ -142,8 +225,7 @@ void RicSnapshotViewToFileFeature::onActionTriggered( bool isChecked )
return;
}
QImage image = viewWindow->snapshotWindowContent();
saveToFile( image, RicSnapshotFilenameGenerator::generateSnapshotFileName( viewWindow ) );
saveViewWindowToFile( viewWindow, RicSnapshotFilenameGenerator::generateSnapshotFileName( viewWindow ) );
}
//--------------------------------------------------------------------------------------------------

View File

@ -20,6 +20,7 @@
#include "cafCmdFeature.h"
class RimPlotWindow;
class RimViewWindow;
class QImage;
@ -31,9 +32,13 @@ class RicSnapshotViewToFileFeature : public caf::CmdFeature
CAF_CMD_HEADER_INIT;
public:
static void saveSnapshotAs( const QString& fileName, RimViewWindow* viewWindow );
static void saveSnapshotAs( const QString& fileName, const QImage& image );
static void saveToFile( const QImage& image, const QString& defaultFileBaseName = "image" );
static void saveSnapshotAs( const QString& fileName, RimViewWindow* viewWindow );
static void saveSnapshotAs( const QString& fileName, const QImage& image );
static void savePlotPDFReportAs( const QString& fileName, RimPlotWindow* plotWindow );
static void saveViewWindowToFile( RimViewWindow* viewWindow, const QString& defaultFileBaseName = "image" );
static void saveImageToFile( const QImage& image, const QString& defaultFileBaseName = "image" );
static QString generateSaveFileName( const QString& defaultFileBaseName = "image", bool supportPDF = false );
static QIcon icon();
static QString text();

View File

@ -333,5 +333,5 @@ void RicGridStatisticsDialog::slotScreenShotToFile()
{
defaultFileBaseName = "Snapshot_Statistics";
}
RicSnapshotViewToFileFeature::saveToFile( snapshotImage, defaultFileBaseName );
RicSnapshotViewToFileFeature::saveImageToFile( snapshotImage, defaultFileBaseName );
}

View File

@ -19,4 +19,5 @@ setup(
license=license,
packages=['rips'],
package_data={'rips': ['*.py', 'generated/*.py', 'PythonExamples/*.py', 'tests/*.py']}
install_requires=['grpcio>=1.20.0']
)

View File

@ -56,6 +56,7 @@
#include "RimWellPltPlot.h"
#include "RiuCvfOverlayItemWidget.h"
#include "RiuDraggableOverlayFrame.h"
#include "RiuQwtPlotWidget.h"
#include "cafPdmUiListEditor.h"
@ -1268,10 +1269,12 @@ void RimWellRftPlot::defineCurveColorsAndSymbols( const std::set<RiaRftPltCurveD
{
if ( !m_ensembleLegendFrames[curveSet] )
{
m_ensembleLegendFrames[curveSet] = new RiuCvfOverlayItemWidget( track->viewer(),
track->viewer()->canvas() );
m_ensembleLegendFrames[curveSet] =
new RiuCvfOverlayItemWidget( curveSet->legendConfig()->titledOverlayFrame(),
track->viewer()->canvas(),
track->viewer()->overlayMargins() );
}
m_ensembleLegendFrames[curveSet]->updateFromOverlayItem( curveSet->legendConfig()->titledOverlayFrame() );
track->viewer()->addOverlayFrame( m_ensembleLegendFrames[curveSet] );
}
}

View File

@ -51,7 +51,7 @@ class RigEclipseCaseData;
class RiaRftPltCurveDefinition;
class RifDataSourceForRftPlt;
class RifEclipseRftAddress;
class RiuCvfOverlayItemWidget;
class RiuDraggableOverlayFrame;
namespace cvf
{
@ -156,8 +156,8 @@ private:
caf::PdmPtrField<RimWellPathCollection*> m_wellPathCollection;
caf::PdmChildArrayField<RimWellRftEnsembleCurveSet*> m_ensembleCurveSets;
std::map<RimWellRftEnsembleCurveSet*, QPointer<RiuCvfOverlayItemWidget>> m_ensembleLegendFrames;
caf::PdmChildArrayField<RimWellRftEnsembleCurveSet*> m_ensembleCurveSets;
std::map<RimWellRftEnsembleCurveSet*, QPointer<RiuDraggableOverlayFrame>> m_ensembleLegendFrames;
std::map<RifDataSourceForRftPlt, cvf::Color3f> m_dataSourceColors;
std::map<QDateTime, RiuQwtSymbol::PointSymbolEnum> m_timeStepSymbols;

View File

@ -22,6 +22,7 @@
#include "RiaPreferences.h"
#include "RifTextDataTableFormatter.h"
#include "RiuDraggableOverlayFrame.h"
#include "RiuGridCrossQwtPlot.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtPlotTools.h"
@ -276,6 +277,37 @@ bool RimGridCrossPlot::showInfoBox() const
return m_showInfoBox();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::updateInfoBox()
{
if ( m_plotWidget )
{
if ( m_showInfoBox )
{
if ( !m_infoBox )
{
m_infoBox = new RiuDraggableOverlayFrame( m_plotWidget->canvas(), m_plotWidget->overlayMargins() );
m_infoBox->setAnchorCorner( RiuDraggableOverlayFrame::AnchorCorner::TopRight );
RiuTextOverlayContentFrame* textFrame = new RiuTextOverlayContentFrame( m_infoBox );
textFrame->setText( generateInfoBoxText() );
m_infoBox->setContentFrame( textFrame );
}
m_plotWidget->addOverlayFrame( m_infoBox );
}
else
{
if ( m_plotWidget && m_infoBox )
{
m_plotWidget->removeOverlayFrame( m_infoBox );
delete m_infoBox;
m_infoBox = nullptr;
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -355,28 +387,6 @@ void RimGridCrossPlot::onAxisSelected( int axis, bool toggle )
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::addOrUpdateDataSetLegend( RimGridCrossPlotDataSet* dataSet )
{
if ( m_plotWidget )
{
m_plotWidget->addOrUpdateDataSetLegend( dataSet );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::removeDataSetLegend( RimGridCrossPlotDataSet* dataSet )
{
if ( m_plotWidget )
{
m_plotWidget->removeDataSetLegend( dataSet );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -391,6 +401,38 @@ void RimGridCrossPlot::doRemoveFromCollection()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlot::generateInfoBoxText() const
{
QStringList curveInfoTexts;
for ( auto dataSet : dataSets() )
{
QString curveInfoText = dataSet->infoText();
if ( dataSet->isChecked() && !curveInfoText.isEmpty() )
{
curveInfoTexts += curveInfoText;
}
}
QStringList infoText;
infoText << QString( "<b>View ID:</b> %1<br/>" ).arg( id() );
if ( curveInfoTexts.size() > 1 )
{
infoText += QString( "<ol style=\"margin-top: 0px; margin-left: 15px; -qt-list-indent:0;\">" );
for ( QString curveInfoText : curveInfoTexts )
{
infoText += QString( "<li>%1</li>" ).arg( curveInfoText );
}
infoText += QString( "</ol>" );
}
else if ( curveInfoTexts.size() > 0 )
{
infoText += curveInfoTexts.front();
}
return infoText.join( "\n" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -404,9 +446,9 @@ QWidget* RimGridCrossPlot::createViewWidget( QWidget* mainWindowParent )
{
dataSet->setParentQwtPlotNoReplot( m_plotWidget );
}
m_plotWidget->scheduleReplot();
}
m_plotWidget->scheduleReplot();
return m_plotWidget;
}
@ -433,6 +475,7 @@ void RimGridCrossPlot::onLoadDataAndUpdate()
updateCurveNamesAndPlotTitle();
updatePlot();
updateInfoBox();
}
//--------------------------------------------------------------------------------------------------
@ -724,6 +767,7 @@ bool RimGridCrossPlot::applyFontSize( RiaDefines::FontSettingType fontSettingTyp
if ( forceChange || legendFontSize() == oldFontSize )
{
setLegendFontSize( fontSize );
anyChange = true;
}

View File

@ -32,6 +32,7 @@
class RimPlotAxisPropertiesInterface;
class RimPlotAxisProperties;
class RimGridCrossPlotDataSet;
class RiuDraggableOverlayFrame;
class RiuGridCrossQwtPlot;
class RimGridCrossPlotNameConfig : public RimNameConfig
@ -76,6 +77,7 @@ public:
QString createAutoName() const override;
bool showInfoBox() const;
void updateInfoBox();
caf::PdmFieldHandle* userDescriptionField() override;
void detachAllCurves() override;
@ -109,9 +111,6 @@ public:
caf::PdmObject* findPdmObjectFromQwtCurve( const QwtPlotCurve* curve ) const override;
void onAxisSelected( int axis, bool toggle ) override;
void addOrUpdateDataSetLegend( RimGridCrossPlotDataSet* dataSet );
void removeDataSetLegend( RimGridCrossPlotDataSet* dataSet );
protected:
QWidget* createViewWidget( QWidget* mainWindowParent = nullptr ) override;
void deleteViewWidget() override;
@ -146,7 +145,8 @@ private:
void doUpdateLayout() override;
void cleanupBeforeClose();
void doRemoveFromCollection() override;
void doRemoveFromCollection() override;
QString generateInfoBoxText() const;
private:
caf::PdmField<bool> m_showInfoBox;
@ -158,5 +158,6 @@ private:
caf::PdmChildArrayField<RimGridCrossPlotDataSet*> m_crossPlotDataSets;
QPointer<RiuGridCrossQwtPlot> m_plotWidget;
QPointer<RiuGridCrossQwtPlot> m_plotWidget;
QPointer<RiuDraggableOverlayFrame> m_infoBox;
};

View File

@ -33,7 +33,9 @@
#include "RigFormationNames.h"
#include "RigMainGrid.h"
#include "RiuCvfOverlayItemWidget.h"
#include "RiuGridCrossQwtPlot.h"
#include "RiuScalarMapperLegendFrame.h"
#include "RimCase.h"
#include "RimEclipseCase.h"
@ -57,6 +59,7 @@
#include "cafPdmUiSliderEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cafProgressInfo.h"
#include "cafTitledOverlayFrame.h"
#include "cvfScalarMapper.h"
#include "cvfqtUtils.h"
@ -133,6 +136,18 @@ RimGridCrossPlotDataSet::RimGridCrossPlotDataSet()
setDefaults();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotDataSet::~RimGridCrossPlotDataSet()
{
if ( m_legendOverlayFrame )
{
m_legendOverlayFrame->setParent( nullptr );
delete m_legendOverlayFrame;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1020,11 +1035,20 @@ void RimGridCrossPlotDataSet::updateLegendRange()
m_groupingProperty->updateRangesForEmbeddedLegends( m_timeStep() );
}
}
parent->addOrUpdateDataSetLegend( this );
if ( !m_legendOverlayFrame )
{
m_legendOverlayFrame = new RiuDraggableOverlayFrame( parent->viewer()->canvas(),
parent->viewer()->overlayMargins() );
}
m_legendOverlayFrame->setContentFrame( legendConfig()->makeLegendFrame() );
parent->viewer()->addOverlayFrame( m_legendOverlayFrame );
}
else
{
parent->removeDataSetLegend( this );
if ( m_legendOverlayFrame )
{
parent->viewer()->removeOverlayFrame( m_legendOverlayFrame );
}
}
}
}

View File

@ -36,6 +36,7 @@
#include <cvfArray.h>
#include <QList>
#include <QPointer>
#include <map>
class RifTextDataTableFormatter;
@ -47,11 +48,12 @@ class RimEclipseResultCase;
class RimEclipseCellColors;
class RimEclipseResultDefinition;
class RimRegularLegendConfig;
class RimPlotCellFilterCollection;
class RimPlotCellFilter;
class RiuDraggableOverlayFrame;
class QwtPlot;
class QwtPlotCurve;
class QString;
class RimPlotCellFilterCollection;
class RimPlotCellFilter;
class RimGridCrossPlotDataSetNameConfig : public RimNameConfig
{
@ -93,7 +95,7 @@ public:
public:
RimGridCrossPlotDataSet();
~RimGridCrossPlotDataSet() = default;
~RimGridCrossPlotDataSet();
void setCellFilterView( RimGridView* cellFilterView );
void loadDataAndUpdate( bool updateParentPlot );
@ -188,5 +190,6 @@ private:
caf::PdmField<bool> m_useCustomColor;
caf::PdmField<cvf::Color3f> m_customColor;
caf::PdmChildField<RimPlotCellFilterCollection*> m_plotCellFilterCollection;
;
QPointer<RiuDraggableOverlayFrame> m_legendOverlayFrame;
};

View File

@ -22,6 +22,7 @@
#include "RiuPlotMainWindow.h"
#include "RiuPlotMainWindowTools.h"
#include <QPainter>
#include <QRegularExpression>
#include <cvfAssert.h>
@ -299,6 +300,17 @@ void RimMultiPlotWindow::doSetAutoScaleYEnabled( bool enabled )
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimMultiPlotWindow::doRenderWindowContent( QPainter* painter )
{
if ( m_viewer )
{
m_viewer->renderTo( painter );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -426,10 +438,10 @@ QImage RimMultiPlotWindow::snapshotWindowContent()
if ( m_viewer )
{
m_viewer->setSelectionsVisible( false );
QPixmap pix = m_viewer->grab();
image = pix.toImage();
m_viewer->setSelectionsVisible( true );
QPixmap pix( m_viewer->size() );
QPainter painter( &pix );
m_viewer->renderTo( &painter );
image = pix.toImage();
}
return image;

View File

@ -129,6 +129,7 @@ private:
virtual void updateSubPlotNames();
virtual void updatePlotWindowTitle();
virtual void doSetAutoScaleYEnabled( bool enabled );
void doRenderWindowContent( QPainter* painter ) override;
protected:
caf::PdmField<bool> m_showPlotWindowTitle;

View File

@ -123,3 +123,14 @@ void RimPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const Q
updateParentLayout();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlot::doRenderWindowContent( QPainter* painter )
{
if ( viewer() )
{
viewer()->renderTo( painter, viewer()->frameGeometry() );
}
}

View File

@ -93,6 +93,7 @@ protected:
private:
virtual void doRemoveFromCollection() = 0;
virtual void doRenderWindowContent( QPainter* painter );
protected:
caf::PdmField<RowOrColSpanEnum> m_rowSpan;

View File

@ -18,6 +18,7 @@
#include "RimPlotWindow.h"
#include "RiaApplication.h"
#include "RiaPlotWindowRedrawScheduler.h"
#include "RiaPreferences.h"
#include "RicfCommandObject.h"
@ -26,6 +27,8 @@
#include "cafPdmUiComboBoxEditor.h"
#include <QPainter>
CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimPlotWindow, "RimPlotWindow" ); // Do not use. Abstract class
//--------------------------------------------------------------------------------------------------
@ -153,6 +156,28 @@ void RimPlotWindow::updateParentLayout()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlotWindow::renderWindowContent( QPainter* painter )
{
doRenderWindowContent( painter );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QPageLayout RimPlotWindow::pageLayout() const
{
QPageLayout defaultPageLayout = RiaApplication::instance()->preferences()->defaultPageLayout();
QPageLayout customPageLayout;
if ( hasCustomPageLayout( &customPageLayout ) )
{
return customPageLayout;
}
return defaultPageLayout;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -218,6 +243,14 @@ void RimPlotWindow::uiOrderingForLegendSettings( QString uiConfigName, caf::PdmU
uiOrdering.add( &m_legendFontSize );
}
//--------------------------------------------------------------------------------------------------
/// Re-implement this in sub classes to provide a custom page layout for printing/PDF
//--------------------------------------------------------------------------------------------------
bool RimPlotWindow::hasCustomPageLayout( QPageLayout* customPageLayout ) const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -24,6 +24,8 @@
#include "cafPdmFieldHandle.h"
#include "cafPdmObject.h"
#include <QPageLayout>
class RimProject;
class QwtPlotCurve;
@ -57,6 +59,9 @@ public:
void updateLayout();
void updateParentLayout();
void renderWindowContent( QPainter* painter );
QPageLayout pageLayout() const;
protected:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
@ -69,6 +74,8 @@ protected:
private:
virtual void doUpdateLayout() {}
virtual bool hasCustomPageLayout( QPageLayout* customPageLayout ) const;
virtual void doRenderWindowContent( QPainter* painter ) = 0;
private:
friend class RimProject;

View File

@ -38,6 +38,8 @@
#include "RimWellMeasurementInView.h"
#include "RimWellRftEnsembleCurveSet.h"
#include "RimWellRftPlot.h"
#include "RiuCategoryLegendFrame.h"
#include "RiuScalarMapperLegendFrame.h"
#include "cafCategoryLegend.h"
#include "cafCategoryMapper.h"
@ -148,6 +150,7 @@ RimRegularLegendConfig::RimRegularLegendConfig()
"",
"The number of significant digits displayed in the legend numbers",
"" );
m_significantDigitsInData = m_precision;
CAF_PDM_InitField( &m_tickNumberFormat,
"TickNumberFormat",
caf::AppEnum<RimRegularLegendConfig::NumberFormatType>( FIXED ),
@ -312,6 +315,8 @@ void RimRegularLegendConfig::fieldChangedByUi( const caf::PdmFieldHandle* change
//--------------------------------------------------------------------------------------------------
void RimRegularLegendConfig::updateLegend()
{
m_significantDigitsInData = m_precision;
double adjustedMin = cvf::UNDEFINED_DOUBLE;
double adjustedMax = cvf::UNDEFINED_DOUBLE;
@ -461,7 +466,9 @@ void RimRegularLegendConfig::updateLegend()
{
numDecimalDigits -= static_cast<int>( decadesInRange );
}
m_scalarMapperLegend->setTickPrecision( cvf::Math::clamp( numDecimalDigits, 0, 20 ) );
numDecimalDigits = cvf::Math::clamp( numDecimalDigits, 0, 20 );
m_significantDigitsInData = numDecimalDigits;
m_scalarMapperLegend->setTickPrecision( numDecimalDigits );
RiaApplication* app = RiaApplication::instance();
RiaPreferences* preferences = app->preferences();
@ -762,7 +769,9 @@ double RimRegularLegendConfig::categoryValueFromCategoryName( const QString& cat
//--------------------------------------------------------------------------------------------------
void RimRegularLegendConfig::setTitle( const QString& title )
{
auto cvfTitle = cvfqt::Utils::toString( title );
m_title = title;
auto cvfTitle = cvfqt::Utils::toString( m_title );
m_scalarMapperLegend->setTitle( cvfTitle );
m_categoryLegend->setTitle( cvfTitle );
}
@ -805,6 +814,24 @@ const caf::TitledOverlayFrame* RimRegularLegendConfig::titledOverlayFrame() cons
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuAbstractLegendFrame* RimRegularLegendConfig::makeLegendFrame()
{
if ( m_currentScalarMapper == m_categoryMapper )
{
return new RiuCategoryLegendFrame( nullptr, m_title, m_categoryMapper.p() );
}
else
{
auto legend = new RiuScalarMapperLegendFrame( nullptr, m_title, m_currentScalarMapper.p() );
legend->setTickFormat( m_tickNumberFormat() );
legend->setTickPrecision( m_significantDigitsInData );
return legend;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -48,6 +48,7 @@ class OverlayScalarMapperLegend;
class Rim3dView;
class RimEnsembleCurveSet;
class RiuAbstractLegendFrame;
//==================================================================================================
///
@ -148,6 +149,7 @@ public:
const caf::TitledOverlayFrame* titledOverlayFrame() const override;
caf::TitledOverlayFrame* titledOverlayFrame() override;
RiuAbstractLegendFrame* makeLegendFrame();
RangeModeType rangeMode() const;
static cvf::Color3ubArray colorArrayFromColorType( ColorRangesType colorType );
@ -170,9 +172,6 @@ private:
friend class RimViewLinker;
caf::OverlayScalarMapperLegend* getOrCreateScalarMapperLegend();
caf::CategoryLegend* getOrCreateCategoryLegend();
private:
cvf::ref<cvf::ScalarMapperDiscreteLinear> m_linDiscreteScalarMapper;
cvf::ref<cvf::ScalarMapperDiscreteLog> m_logDiscreteScalarMapper;
@ -211,4 +210,7 @@ private:
caf::PdmField<double> m_userDefinedMinValue;
caf::PdmField<caf::AppEnum<ColorRangesType>> m_colorRangeMode;
caf::PdmField<caf::AppEnum<MappingType>> m_mappingMode;
QString m_title;
int m_significantDigitsInData;
};

View File

@ -693,26 +693,6 @@ void RimWellLogPlot::defineEditorAttribute( const caf::PdmFieldHandle* field,
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimWellLogPlot::snapshotWindowContent()
{
QImage image;
if ( m_viewer )
{
RiuWellLogPlot* wellLogViewer = dynamic_cast<RiuWellLogPlot*>( m_viewer.data() );
CAF_ASSERT( wellLogViewer );
bool isScrollbarVisible = wellLogViewer->isScrollbarVisible();
wellLogViewer->setScrollbarVisible( false );
image = RimMultiPlotWindow::snapshotWindowContent();
wellLogViewer->setScrollbarVisible( isScrollbarVisible );
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -122,8 +122,6 @@ protected:
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute ) override;
QImage snapshotWindowContent() override;
private:
void updateSubPlotNames() override;
void updatePlotWindowTitle() override;

View File

@ -21,6 +21,7 @@
#include "RiaColorTables.h"
#include "RiaGuiApplication.h"
#include "RiaStatisticsTools.h"
#include "RiuAbstractLegendFrame.h"
#include "SummaryPlotCommands/RicSummaryCurveCreator.h"
@ -47,6 +48,7 @@
#include "RimSummaryPlot.h"
#include "RiuCvfOverlayItemWidget.h"
#include "RiuDraggableOverlayFrame.h"
#include "RiuPlotMainWindow.h"
#include "RiuQwtPlotCurve.h"
#include "RiuSummaryCurveDefSelectionDialog.h"
@ -383,7 +385,7 @@ RimRegularLegendConfig* RimEnsembleCurveSet::legendConfig()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QFrame* RimEnsembleCurveSet::legendFrame() const
RiuDraggableOverlayFrame* RimEnsembleCurveSet::legendFrame() const
{
return m_legendOverlayFrame;
}
@ -888,10 +890,10 @@ void RimEnsembleCurveSet::updateCurveColors()
{
if ( !m_legendOverlayFrame )
{
m_legendOverlayFrame = new RiuCvfOverlayItemWidget( plot->viewer(), plot->viewer()->canvas() );
m_legendOverlayFrame = new RiuDraggableOverlayFrame( plot->viewer()->canvas(),
plot->viewer()->overlayMargins() );
}
m_legendOverlayFrame->updateFromOverlayItem( m_legendConfig()->titledOverlayFrame() );
plot->viewer()->addOverlayFrame( m_legendOverlayFrame );
m_legendOverlayFrame->setContentFrame( m_legendConfig->makeLegendFrame() );
}
else
{

View File

@ -52,7 +52,7 @@ class RimSummaryCurveAutoName;
class RimEnsembleCurveFilterCollection;
class RimEnsembleStatistics;
class RimEnsembleStatisticsCase;
class RiuCvfOverlayItemWidget;
class RiuDraggableOverlayFrame;
class QwtPlot;
class QwtPlotCurve;
@ -108,8 +108,8 @@ public:
RimRegularLegendConfig* legendConfig();
void updateEnsembleLegendItem();
QFrame* legendFrame() const;
void updateEnsembleLegendItem();
RiuDraggableOverlayFrame* legendFrame() const;
void updateAllCurves();
void updateStatisticsCurves();
@ -190,8 +190,8 @@ private:
caf::PdmProxyValueField<QString> m_autoGeneratedName;
caf::PdmChildField<RimSummaryCurveAutoName*> m_summaryAddressNameTools;
QwtPlotCurve* m_qwtPlotCurveForLegendText;
QPointer<RiuCvfOverlayItemWidget> m_legendOverlayFrame;
QwtPlotCurve* m_qwtPlotCurveForLegendText;
QPointer<RiuDraggableOverlayFrame> m_legendOverlayFrame;
std::unique_ptr<RimEnsembleStatisticsCase> m_ensembleStatCase;

View File

@ -87,6 +87,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuMdiMaximizeWindowGuard.h
${CMAKE_CURRENT_LIST_DIR}/RiuMainWindowTools.h
${CMAKE_CURRENT_LIST_DIR}/RiuComparisonViewMover.h
${CMAKE_CURRENT_LIST_DIR}/RiuAbstractOverlayContentFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuAbstractLegendFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuCategoryLegendFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuScalarMapperLegendFrame.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -173,6 +177,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuMdiMaximizeWindowGuard.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuMainWindowTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuComparisonViewMover.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuAbstractOverlayContentFrame.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuAbstractLegendFrame.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuCategoryLegendFrame.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuScalarMapperLegendFrame.cpp
)
list(APPEND CODE_HEADER_FILES
@ -223,6 +231,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuExpressionContextMenuManager.h
${CMAKE_CURRENT_LIST_DIR}/RiuCalculationsContextMenuManager.h
${CMAKE_CURRENT_LIST_DIR}/RiuMohrsCirclePlot.h
${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuAbstractOverlayContentFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuAbstractLegendFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuCategoryLegendFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuScalarMapperLegendFrame.h
)
list(APPEND QT_UI_FILES

View File

@ -0,0 +1,177 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuAbstractLegendFrame.h"
#include <QPaintEvent>
#include <QPainter>
#include <cmath>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuAbstractLegendFrame::RiuAbstractLegendFrame( QWidget* parent, const QString& title )
: RiuAbstractOverlayContentFrame( parent )
, m_title( title )
{
setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuAbstractLegendFrame::sizeHint() const
{
LayoutInfo layout( QSize( 200, 200 ) ); // Use default size
layoutInfo( &layout );
QFontMetrics fontMetrics( this->font() );
QStringList titleLines = m_title.split( "\n", QString::SkipEmptyParts );
int preferredContentHeight = titleLines.size() * layout.lineSpacing + labelCount() * layout.lineSpacing;
int preferredHeight = preferredContentHeight + layout.margins.top() + layout.margins.bottom();
int maxTickTextWidth = 0;
for ( int i = 0; i < labelCount(); ++i )
{
QString valueString = label( i );
int textWidth = fontMetrics.boundingRect( valueString ).width();
maxTickTextWidth = std::max( maxTickTextWidth, textWidth );
}
int preferredWidth = layout.tickEndX + layout.margins.left() + layout.margins.right() + layout.tickTextLeadSpace +
maxTickTextWidth;
preferredWidth = std::max( preferredWidth, fontMetrics.boundingRect( m_title ).width() );
preferredWidth = std::min( preferredWidth, 400 );
return QSize( preferredWidth, preferredHeight );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuAbstractLegendFrame::minimumSizeHint() const
{
LayoutInfo layout( QSize( 200, 200 ) ); // Use default size
layoutInfo( &layout );
QFontMetrics fontMetrics( this->font() );
QStringList titleLines = m_title.split( "\n", QString::SkipEmptyParts );
int preferredContentHeight = titleLines.size() * layout.lineSpacing + 2 * layout.lineSpacing;
int preferredHeight = preferredContentHeight + layout.margins.top() + layout.margins.bottom();
int firstTextWidth = fontMetrics.boundingRect( label( 0 ) ).width();
int lastTextWidth = fontMetrics.boundingRect( label( labelCount() - 1 ) ).width();
int maxTickTextWidth = std::max( firstTextWidth, lastTextWidth );
int preferredWidth = layout.tickEndX + layout.margins.left() + layout.margins.right() + layout.tickTextLeadSpace +
maxTickTextWidth;
preferredWidth = std::max( preferredWidth, fontMetrics.boundingRect( m_title ).width() );
preferredWidth = std::min( preferredWidth, 400 );
return QSize( preferredWidth, preferredHeight );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuAbstractLegendFrame::renderTo( QPainter* painter, const QRect& targetRect )
{
LayoutInfo layout( QSize( targetRect.width(), targetRect.height() ) );
layoutInfo( &layout );
painter->save();
painter->translate( targetRect.topLeft() );
QPoint titlePos( layout.margins.left(), layout.margins.top() + layout.lineSpacing / 2 );
painter->drawText( titlePos, m_title );
QStringList titleLines = m_title.split( "\n", QString::SkipEmptyParts );
std::vector<std::pair<QPoint, QString>> visibleTickLabels = visibleLabels( layout );
for ( auto tickLabel : visibleTickLabels )
{
painter->drawText( tickLabel.first, tickLabel.second );
}
// Render color bar as one colored rectangle per color interval
for ( int i = 0; i < rectCount(); ++i )
{
renderRect( painter, layout, i );
}
painter->drawRect( layout.colorBarRect );
// painter->drawLine( QPointF( layout.tickMidX, layout.tickYPixelPos->get( i ) ),
// QPointF( layout.tickMidX, layout.tickYPixelPos->get( i + 1 ) ) );
painter->restore();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuAbstractLegendFrame::paintEvent( QPaintEvent* e )
{
QPainter painter( this );
renderTo( &painter, e->rect() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<QPoint, QString>> RiuAbstractLegendFrame::visibleLabels( const LayoutInfo& layout ) const
{
const int textX = layout.tickEndX + layout.tickTextLeadSpace;
const double overlapTolerance = 1.1 * layout.charHeight;
int lastVisibleTextY = 0;
std::vector<std::pair<QPoint, QString>> visibleTickLabels;
int numLabels = labelCount();
for ( int i = 0; i < numLabels; i++ )
{
int textY = labelPixelPosY( layout, i );
// Always draw first and last tick label. For all others, skip drawing if text ends up
// on top of the previous label.
if ( i != 0 && i != ( numLabels - 1 ) )
{
if ( std::fabs( static_cast<double>( textY - lastVisibleTextY ) ) < overlapTolerance )
{
continue;
}
// Make sure it does not overlap the last tick as well
int lastTickY = layout.colorBarRect.bottom();
if ( std::fabs( static_cast<double>( lastTickY - textY ) ) < overlapTolerance )
{
continue;
}
}
QString valueString = label( numLabels - i - 1 );
QPoint pos( textX, textY );
lastVisibleTextY = textY;
visibleTickLabels.push_back( {pos, valueString} );
}
return visibleTickLabels;
}

View File

@ -0,0 +1,81 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiuAbstractOverlayContentFrame.h"
#include <QFrame>
#include <QString>
class RiuAbstractLegendFrame : public RiuAbstractOverlayContentFrame
{
Q_OBJECT
public:
RiuAbstractLegendFrame( QWidget* parent, const QString& title );
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
void renderTo( QPainter* painter, const QRect& targetRect ) override;
protected:
struct LayoutInfo
{
LayoutInfo( const QSize& size )
{
charHeight = 0;
charAscent = 0;
lineSpacing = 0;
margins = QMargins( 0, 0, 0, 0 );
tickEndX = 0;
tickStartX = 0;
tickMidX = 0;
overallLegendSize = size;
}
int charHeight;
int charAscent;
int lineSpacing;
QMargins margins;
int tickStartX, tickMidX, tickEndX;
int tickTextLeadSpace;
QRect colorBarRect;
std::vector<int> tickYPixelPos;
QSize overallLegendSize;
};
void paintEvent( QPaintEvent* e ) override;
std::vector<std::pair<QPoint, QString>> visibleLabels( const LayoutInfo& layout ) const;
private:
virtual void layoutInfo( LayoutInfo* layout ) const = 0;
virtual QString label( int index ) const = 0;
virtual int labelPixelPosY( const LayoutInfo& layout, int index ) const = 0;
virtual int labelCount() const = 0;
virtual int rectCount() const = 0;
virtual void renderRect( QPainter* painter, const LayoutInfo& layout, int rectIndex ) const = 0;
protected:
QString m_title;
};

View File

@ -0,0 +1,72 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuAbstractOverlayContentFrame.h"
#include <QLabel>
#include <QPainter>
#include <QTextDocument>
#include <QVBoxLayout>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuAbstractOverlayContentFrame::RiuAbstractOverlayContentFrame( QWidget* parent /*= nullptr */ )
: QFrame( parent )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuAbstractOverlayContentFrame::~RiuAbstractOverlayContentFrame() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuTextOverlayContentFrame::RiuTextOverlayContentFrame( QWidget* parent /*= nullptr */ )
: RiuAbstractOverlayContentFrame( parent )
{
QVBoxLayout* layout = new QVBoxLayout( this );
layout->setContentsMargins( 8, 8, 8, 8 );
m_textLabel = new QLabel;
layout->addWidget( m_textLabel );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuTextOverlayContentFrame::setText( const QString& text )
{
m_textLabel->setText( text );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuTextOverlayContentFrame::renderTo( QPainter* painter, const QRect& targetRect )
{
painter->save();
painter->translate( targetRect.topLeft() + QPoint( this->contentsMargins().left(), this->contentsMargins().top() ) );
painter->setFont( m_textLabel->font() );
QTextDocument td;
td.setHtml( m_textLabel->text() );
td.drawContents( painter );
painter->restore();
}

View File

@ -0,0 +1,47 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QFrame>
#include <QPointer>
#include <QString>
class QLabel;
class RiuAbstractOverlayContentFrame : public QFrame
{
Q_OBJECT
public:
RiuAbstractOverlayContentFrame( QWidget* parent = nullptr );
~RiuAbstractOverlayContentFrame();
virtual void renderTo( QPainter* painter, const QRect& targetRect ) = 0;
};
class RiuTextOverlayContentFrame : public RiuAbstractOverlayContentFrame
{
Q_OBJECT
public:
RiuTextOverlayContentFrame( QWidget* parent = nullptr );
void setText( const QString& text );
void renderTo( QPainter* painter, const QRect& targetRect ) override;
private:
QPointer<QLabel> m_textLabel;
};

View File

@ -0,0 +1,105 @@
#include "RiuCategoryLegendFrame.h"
#include "cafCategoryLegend.h"
#include "cvfqtUtils.h"
#include <QDebug>
#include <QPainter>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuCategoryLegendFrame::RiuCategoryLegendFrame( QWidget* parent, const QString& title, caf::CategoryMapper* categoryMapper )
: RiuAbstractLegendFrame( parent, title )
, m_categoryMapper( categoryMapper )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuCategoryLegendFrame::~RiuCategoryLegendFrame() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuCategoryLegendFrame::layoutInfo( LayoutInfo* layout ) const
{
QFontMetrics fontMetrics( this->font() );
QStringList titleLines = m_title.split( "\n", QString::SkipEmptyParts );
layout->charHeight = fontMetrics.height();
layout->charAscent = fontMetrics.ascent();
layout->lineSpacing = ( fontMetrics.lineSpacing() * 3 ) / 2;
layout->margins = QMargins( 8, 8, 8, 8 );
layout->tickTextLeadSpace = 5;
int colorBarWidth = 25;
int colorBarHeight = layout->overallLegendSize.height() - layout->margins.top() - layout->margins.bottom() -
titleLines.size() * layout->lineSpacing;
int colorBarStartY = layout->margins.top() + titleLines.size() * layout->lineSpacing;
layout->colorBarRect = QRect( layout->margins.left(), colorBarStartY, colorBarWidth, colorBarHeight );
layout->tickStartX = layout->margins.left();
layout->tickMidX = layout->margins.left() + layout->colorBarRect.width();
layout->tickEndX = layout->tickMidX + 5;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiuCategoryLegendFrame::label( int index ) const
{
return cvfqt::Utils::toQString( m_categoryMapper->textForCategoryIndex( index ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuCategoryLegendFrame::labelCount() const
{
return (int)m_categoryMapper->categoryCount();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuCategoryLegendFrame::rectCount() const
{
return (int)m_categoryMapper->categoryCount();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuCategoryLegendFrame::renderRect( QPainter* painter, const LayoutInfo& layout, int index ) const
{
int categoryIndex = static_cast<int>( rectCount() - index - 1u );
float categoryHeight = static_cast<float>( layout.colorBarRect.height() ) / labelCount();
float pos = ( categoryIndex + 0.5 ) * categoryHeight / layout.colorBarRect.height();
float domainValue = m_categoryMapper->domainValue( pos );
cvf::Color3ub clr = m_categoryMapper->mapToColor( domainValue );
// qDebug() << "Plot Legend: " << pos << " and " << domainValue << " = " << clr.r() << ", " << clr.g() << ", "
// << clr.b();
QColor color( clr.r(), clr.g(), clr.b() );
int yStart = layout.colorBarRect.top() + static_cast<int>( index * categoryHeight );
int yEnd = layout.colorBarRect.top() + static_cast<int>( ( index + 1 ) * categoryHeight );
QRect rect( QPoint( layout.tickStartX, yStart ), QPoint( layout.tickMidX, yEnd ) );
painter->fillRect( rect, QBrush( color ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuCategoryLegendFrame::labelPixelPosY( const LayoutInfo& layout, int index ) const
{
float categoryHeight = static_cast<float>( layout.colorBarRect.height() ) / labelCount();
int textY = static_cast<int>( layout.colorBarRect.top() + index * categoryHeight + categoryHeight / 2 );
textY += layout.charAscent / 2;
return textY;
}

View File

@ -0,0 +1,52 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiuAbstractLegendFrame.h"
#include "cvfObject.h"
#include "cafCategoryMapper.h"
#include <QLabel>
#include <QSize>
class QFont;
class QPaintEvent;
class QPainter;
class QRect;
class RiuCategoryLegendFrame : public RiuAbstractLegendFrame
{
Q_OBJECT
public:
RiuCategoryLegendFrame( QWidget* parent, const QString& title, caf::CategoryMapper* categoryMapper );
~RiuCategoryLegendFrame();
private:
void layoutInfo( LayoutInfo* layout ) const override;
QString label( int index ) const override;
int labelCount() const override;
int rectCount() const override;
void renderRect( QPainter* painter, const LayoutInfo& layout, int rectIndex ) const override;
int labelPixelPosY( const LayoutInfo& layout, int index ) const override;
private:
cvf::cref<caf::CategoryMapper> m_categoryMapper;
};

View File

@ -20,6 +20,7 @@
#include "RiaGuiApplication.h"
#include "cafAssert.h"
#include "cafTitledOverlayFrame.h"
#include "cafViewer.h"
@ -30,23 +31,24 @@
#include "cvfRendering.h"
#include "cvfqtUtils.h"
#include <QApplication>
#include <QBoxLayout>
#include <QFrame>
#include <QLabel>
#include <QPainter>
#include <QPixmap>
#include <QPushButton>
#include <QResizeEvent>
#include "glew/GL/glew.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuCvfOverlayItemWidget::RiuCvfOverlayItemWidget( QWidget* parent /*=0*/, QWidget* widgetToSnapTo )
: RiuDraggableOverlayFrame( parent, widgetToSnapTo )
RiuCvfOverlayItemWidget::RiuCvfOverlayItemWidget( caf::TitledOverlayFrame* overlayItem,
QWidget* parent,
const int snapMargins,
const QColor& backgroundColor /*= QColor( 255, 255, 255, 100 ) */ )
: RiuDraggableOverlayFrame( parent, snapMargins, backgroundColor )
, m_overlayItem( overlayItem )
{
this->layout()->setMargin( 0 );
this->layout()->setSpacing( 0 );
}
//--------------------------------------------------------------------------------------------------
@ -57,19 +59,25 @@ RiuCvfOverlayItemWidget::~RiuCvfOverlayItemWidget() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuCvfOverlayItemWidget::updateFromOverlayItem( caf::TitledOverlayFrame* item )
QSize RiuCvfOverlayItemWidget::sizeHint() const
{
item->setRenderSize( item->preferredSize() );
auto preferredSize = const_cast<caf::TitledOverlayFrame*>( m_overlayItem.p() )->preferredSize();
return QSize( preferredSize.x(), preferredSize.y() );
}
unsigned int width = item->renderSize().x();
unsigned int height = item->renderSize().y();
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuCvfOverlayItemWidget::renderTo( QPainter* painter, const QRect& paintRect, double scaleX, double scaleY )
{
unsigned int width = static_cast<unsigned int>( paintRect.width() );
unsigned int height = static_cast<unsigned int>( paintRect.height() );
m_overlayItem->setRenderSize( cvf::Vec2ui( width, height ) );
QGLFormat glFormat;
glFormat.setDirectRendering( RiaGuiApplication::instance()->useShaders() );
// Enforce no border to avoid
item->setBackgroundFrameColor( cvf::Color4f( 0, 0, 0, 0 ) );
caf::Viewer* viewer = new caf::Viewer( glFormat, nullptr );
cvf::OpenGLContext* cvfOglContext = viewer->cvfOpenGLContext();
viewer->resize( width, height );
@ -77,8 +85,8 @@ void RiuCvfOverlayItemWidget::updateFromOverlayItem( caf::TitledOverlayFrame* it
// Create a rendering
cvf::ref<cvf::Rendering> rendering = new cvf::Rendering;
item->setLayoutFixedPosition( {0, 0} );
rendering->addOverlayItem( item );
m_overlayItem->setLayoutFixedPosition( {0, 0} );
rendering->addOverlayItem( m_overlayItem.p() );
rendering->camera()->setViewport( 0, 0, width, height );
rendering->camera()->viewport()->setClearColor( {1, 1, 1, 0} );
@ -108,7 +116,7 @@ void RiuCvfOverlayItemWidget::updateFromOverlayItem( caf::TitledOverlayFrame* it
renderingSequence->render( cvfOglContext );
// Read data from framebuffer
// Read data from frame buffer
cvf::UByteArray arr( 4 * width * height );
glReadPixels( 0, 0, static_cast<GLsizei>( width ), static_cast<GLsizei>( height ), GL_RGBA, GL_UNSIGNED_BYTE, arr.ptr() );
@ -125,7 +133,17 @@ void RiuCvfOverlayItemWidget::updateFromOverlayItem( caf::TitledOverlayFrame* it
delete viewer;
m_overlayItemLabel->setPixmap( pixmap );
this->setMinimumSize( QSize( width, height ) );
this->resize( QSize( width, height ) );
painter->save();
painter->drawPixmap( paintRect.topLeft(), pixmap );
painter->restore();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuCvfOverlayItemWidget::paintEvent( QPaintEvent* e )
{
QRect paintRect = e->rect();
QPainter painter( this );
renderTo( &painter, paintRect, 1.0, 1.0 );
}

View File

@ -20,9 +20,12 @@
#include "RiuDraggableOverlayFrame.h"
#include "cvfObject.h"
#include <QLabel>
#include <QSize>
#include <QWidget>
class QLabel;
namespace caf
{
class TitledOverlayFrame;
@ -37,11 +40,18 @@ class RiuCvfOverlayItemWidget : public RiuDraggableOverlayFrame
{
Q_OBJECT
public:
explicit RiuCvfOverlayItemWidget( QWidget* parent = nullptr, QWidget* widgetToSnapTo = nullptr );
explicit RiuCvfOverlayItemWidget( caf::TitledOverlayFrame* overlayItem,
QWidget* parent,
const int snapMargins,
const QColor& backgroundColor = QColor( 255, 255, 255, 100 ) );
~RiuCvfOverlayItemWidget() override;
void updateFromOverlayItem( caf::TitledOverlayFrame* item );
QSize sizeHint() const override;
void renderTo( QPainter* painter, const QRect& paintRect, double scaleX, double scaleY );
// virtual QSize sizeHint() const override;
// virtual QSize minimumSizeHint() const override;
protected:
void paintEvent( QPaintEvent* e ) override;
private:
cvf::ref<caf::TitledOverlayFrame> m_overlayItem;
};

View File

@ -20,15 +20,18 @@
#include <QGraphicsDropShadowEffect>
#include <QLabel>
#include <QPainter>
#include <QResizeEvent>
#include <QVBoxLayout>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuDraggableOverlayFrame::RiuDraggableOverlayFrame( QWidget* parent, QWidget* widgetToSnapTo, const QColor& backgroundColor )
RiuDraggableOverlayFrame::RiuDraggableOverlayFrame( QWidget* parent, const int snapMargins, const QColor& backgroundColor )
: QFrame( parent )
, m_anchorCorner( AnchorCorner::TopLeft )
{
RiuWidgetDragger* dragger = new RiuWidgetDragger( this, widgetToSnapTo );
m_widgetDragger = new RiuWidgetDragger( this, snapMargins );
QPalette pal = this->palette();
pal.setColor( QPalette::Window, backgroundColor );
@ -40,22 +43,84 @@ RiuDraggableOverlayFrame::RiuDraggableOverlayFrame( QWidget* parent, QWidget* wi
dropShadowEffect->setBlurRadius( 3.0 );
dropShadowEffect->setColor( QColor( 100, 100, 100, 100 ) );
setGraphicsEffect( dropShadowEffect );
auto hblayout = new QVBoxLayout( this );
this->setLayout( hblayout );
m_overlayItemLabel = new QLabel( this );
hblayout->addWidget( m_overlayItemLabel );
m_overlayItemLabel->setObjectName( "OverlayFrameLabel" );
m_overlayItemLabel->setGraphicsEffect( nullptr );
m_overlayItemLabel->setAlignment( Qt::AlignTop | Qt::AlignLeft );
dragger->addWidget( m_overlayItemLabel );
this->setContentsMargins( 1, 1, 1, 1 );
m_layout = new QVBoxLayout( this );
m_layout->setContentsMargins( 0, 0, 0, 0 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QLabel* RiuDraggableOverlayFrame::label()
RiuAbstractOverlayContentFrame* RiuDraggableOverlayFrame::contentFrame()
{
return m_overlayItemLabel;
return m_contentFrame;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuDraggableOverlayFrame::setContentFrame( RiuAbstractOverlayContentFrame* contentFrame )
{
if ( m_contentFrame )
{
m_layout->removeWidget( m_contentFrame );
m_contentFrame->setParent( nullptr ); // TODO: check if both removeWidget and setParent is necessary
delete m_contentFrame;
m_contentFrame = nullptr;
}
m_contentFrame = contentFrame;
m_layout->addWidget( m_contentFrame );
this->adjustSize();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuDraggableOverlayFrame::renderTo( QPainter* painter, const QRect& targetRect )
{
if ( m_contentFrame )
{
painter->save();
painter->fillRect( targetRect, this->palette().color( QWidget::backgroundRole() ) );
QRect contentRect = targetRect;
contentRect.adjust( -1, -1, -1, -1 );
m_contentFrame->renderTo( painter, contentRect );
painter->drawRect( targetRect );
painter->restore();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuDraggableOverlayFrame::setAnchorCorner( AnchorCorner corner )
{
m_anchorCorner = corner;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuDraggableOverlayFrame::AnchorCorner RiuDraggableOverlayFrame::anchorCorner() const
{
return m_anchorCorner;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuDraggableOverlayFrame::sizeHint() const
{
QSize contentSize = m_contentFrame->sizeHint();
return QSize( contentSize.width() + 2, contentSize.height() + 2 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuDraggableOverlayFrame::minimumSizeHint() const
{
QSize contentSize = m_contentFrame->minimumSizeHint();
return QSize( contentSize.width() + 2, contentSize.height() + 2 );
}

View File

@ -17,21 +17,44 @@
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiuAbstractOverlayContentFrame.h"
#include <QFrame>
#include <QLabel>
#include <QPointer>
class QColor;
class QLabel;
class QVBoxLayout;
class RiuWidgetDragger;
class RiuDraggableOverlayFrame : public QFrame
{
Q_OBJECT
public:
RiuDraggableOverlayFrame( QWidget* parent,
QWidget* widgetToSnapTo = nullptr,
const QColor& backgroundColor = QColor( 255, 255, 255, 100 ) );
QLabel* label();
enum class AnchorCorner
{
TopLeft,
TopRight,
};
protected:
QPointer<QLabel> m_overlayItemLabel;
public:
RiuDraggableOverlayFrame( QWidget* parent,
const int snapMargins,
const QColor& backgroundColor = QColor( 255, 255, 255, 100 ) );
RiuAbstractOverlayContentFrame* contentFrame();
void setContentFrame( RiuAbstractOverlayContentFrame* contentFrame );
void renderTo( QPainter* painter, const QRect& targetRect );
void setAnchorCorner( AnchorCorner corner );
AnchorCorner anchorCorner() const;
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
private:
QPointer<RiuWidgetDragger> m_widgetDragger;
QPointer<QVBoxLayout> m_layout;
QPointer<RiuAbstractOverlayContentFrame> m_contentFrame;
AnchorCorner m_anchorCorner;
};

View File

@ -85,9 +85,7 @@ RiuGridCrossQwtPlot::RiuGridCrossQwtPlot( RimPlot* plotDefinition, QWidget* pare
connect( m_zoomerRight, SIGNAL( zoomed( const QRectF& ) ), SLOT( onZoomedSlot() ) );
connect( panner, SIGNAL( panned( int, int ) ), SLOT( onZoomedSlot() ) );
m_annotationTool = std::unique_ptr<RiuPlotAnnotationTool>( new RiuPlotAnnotationTool() );
m_infoBox = new RiuDraggableOverlayFrame( this, canvas() );
m_annotationTool = std::unique_ptr<RiuPlotAnnotationTool>( new RiuPlotAnnotationTool() );
m_selectedPointMarker = new QwtPlotMarker;
// QwtPlotMarker takes ownership of the symbol, it is deleted in destructor of QwtPlotMarker
@ -121,112 +119,6 @@ RiuGridCrossQwtPlot::~RiuGridCrossQwtPlot()
delete m_selectedPointMarker;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::addOrUpdateDataSetLegend( RimGridCrossPlotDataSet* dataSet )
{
RiuCvfOverlayItemWidget* overlayWidget = nullptr;
auto it = m_legendWidgets.find( dataSet );
if ( it == m_legendWidgets.end() || it->second == nullptr )
{
overlayWidget = new RiuCvfOverlayItemWidget( this, canvas() );
m_legendWidgets[dataSet] = overlayWidget;
}
else
{
overlayWidget = it->second;
}
if ( overlayWidget )
{
caf::TitledOverlayFrame* overlayItem = dataSet->legendConfig()->titledOverlayFrame();
applyFontSizeToOverlayItem( overlayItem );
resizeOverlayItemToFitPlot( overlayItem );
overlayWidget->updateFromOverlayItem( overlayItem );
}
this->updateLegendLayout();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::removeDataSetLegend( RimGridCrossPlotDataSet* dataSetToShowLegendFor )
{
auto it = m_legendWidgets.find( dataSetToShowLegendFor );
if ( it != m_legendWidgets.end() )
{
if ( it->second != nullptr )
{
it->second->hide();
it->second->setParent( nullptr );
delete it->second;
}
m_legendWidgets.erase( it );
}
this->updateLegendLayout();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::removeDanglingDataSetLegends()
{
for ( auto it = m_legendWidgets.begin(); it != m_legendWidgets.end(); )
{
if ( it->first.isNull() )
{
if ( it->second != nullptr )
{
it->second->hide();
it->second->setParent( nullptr );
delete it->second;
}
m_legendWidgets.erase( it++ );
}
else
{
++it;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::updateLegendSizesToMatchPlot()
{
RimGridCrossPlot* crossPlot = dynamic_cast<RimGridCrossPlot*>( plotDefinition() );
if ( !crossPlot ) return;
bool anyLegendResized = false;
for ( RimGridCrossPlotDataSet* dataSet : crossPlot->dataSets() )
{
if ( !dataSet->isChecked() || !dataSet->legendConfig()->showLegend() ) continue;
auto pairIt = m_legendWidgets.find( dataSet );
if ( pairIt != m_legendWidgets.end() )
{
RiuCvfOverlayItemWidget* overlayWidget = pairIt->second;
caf::TitledOverlayFrame* overlayItem = dataSet->legendConfig()->titledOverlayFrame();
applyFontSizeToOverlayItem( overlayItem );
if ( resizeOverlayItemToFitPlot( overlayItem ) )
{
anyLegendResized = true;
overlayWidget->updateFromOverlayItem( overlayItem );
}
}
}
if ( anyLegendResized )
{
updateLegendLayout();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -265,11 +157,10 @@ void RiuGridCrossQwtPlot::setLegendFontSize( int fontSize )
label->setFont( font );
}
}
updateInfoBoxLayout();
}
//--------------------------------------------------------------------------------------------------
/// The internal qwt legend is not used in grid plot windows
/// The internal qwt legend is not used in multi plot windows
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::setInternalQwtLegendVisible( bool visible )
{
@ -283,169 +174,6 @@ void RiuGridCrossQwtPlot::setInternalQwtLegendVisible( bool visible )
this->insertLegend( nullptr );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::updateLayout()
{
QwtPlot::updateLayout();
updateInfoBoxLayout();
updateLegendLayout();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::updateInfoBoxLayout()
{
RimGridCrossPlot* crossPlot = dynamic_cast<RimGridCrossPlot*>( plotDefinition() );
if ( !crossPlot ) return;
bool showInfo = false;
if ( crossPlot->showInfoBox() )
{
QStringList curveInfoTexts;
for ( auto dataSet : crossPlot->dataSets() )
{
QString curveInfoText = dataSet->infoText();
if ( dataSet->isChecked() && !curveInfoText.isEmpty() )
{
curveInfoTexts += curveInfoText;
}
}
QStringList infoText;
infoText << QString( "<b>View ID:</b> %1<br/>" ).arg( crossPlot->id() );
if ( curveInfoTexts.size() > 1 )
{
infoText += QString( "<ol style=\"margin-top: 0px; margin-left: 15px; -qt-list-indent:0;\">" );
for ( QString curveInfoText : curveInfoTexts )
{
infoText += QString( "<li>%1</li>" ).arg( curveInfoText );
}
infoText += QString( "</ol>" );
}
else if ( curveInfoTexts.size() > 0 )
{
infoText += curveInfoTexts.front();
}
if ( !infoText.empty() )
{
m_infoBox->label()->setText( infoText.join( "\n" ) );
QFont font = m_infoBox->label()->font();
font.setPointSize( crossPlot->legendFontSize() );
m_infoBox->label()->setFont( font );
m_infoBox->adjustSize();
QRect infoRect = m_infoBox->frameGeometry();
QRect canvasRect = canvas()->frameGeometry();
infoRect.moveTop( canvasRect.top() + 4 );
infoRect.moveRight( canvasRect.right() - 4 );
m_infoBox->move( infoRect.topLeft() );
showInfo = true;
}
}
if ( showInfo )
{
m_infoBox->show();
}
else
{
m_infoBox->hide();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::updateLegendLayout()
{
const int spacing = 5;
int startMarginX = this->canvas()->pos().x() + spacing;
int startMarginY = this->canvas()->pos().y() + spacing;
int xpos = startMarginX;
int ypos = startMarginY;
int maxColumnWidth = 0;
removeDanglingDataSetLegends();
RimGridCrossPlot* crossPlot = dynamic_cast<RimGridCrossPlot*>( plotDefinition() );
if ( !crossPlot ) return;
std::set<QString> legendTypes;
for ( RimGridCrossPlotDataSet* dataSet : crossPlot->dataSets() )
{
if ( dataSet->isChecked() && dataSet->groupingEnabled() && dataSet->legendConfig()->showLegend() )
{
auto pairIt = m_legendWidgets.find( dataSet );
if ( pairIt != m_legendWidgets.end() )
{
RiuCvfOverlayItemWidget* overlayWidget = pairIt->second;
// Show only one copy of each legend type
if ( !legendTypes.count( dataSet->groupParameter() ) )
{
if ( ypos + overlayWidget->height() + spacing > this->canvas()->height() )
{
xpos += spacing + maxColumnWidth;
ypos = startMarginY;
maxColumnWidth = 0;
}
overlayWidget->show();
overlayWidget->move( xpos, ypos );
ypos += pairIt->second->height() + spacing;
maxColumnWidth = std::max( maxColumnWidth, pairIt->second->width() );
legendTypes.insert( dataSet->groupParameter() );
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::resizeEvent( QResizeEvent* e )
{
QwtPlot::resizeEvent( e );
updateLegendSizesToMatchPlot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuGridCrossQwtPlot::resizeOverlayItemToFitPlot( caf::TitledOverlayFrame* overlayItem )
{
QSize plotSize = this->canvas()->contentsRect().size();
cvf::Vec2ui existingRenderSize = overlayItem->renderSize();
cvf::Vec2ui legendSize = overlayItem->preferredSize();
bool sizeAltered = false;
if ( plotSize.width() > 0 && (double)legendSize.x() > 0.9 * plotSize.width() )
{
legendSize.x() = ( plotSize.width() * 9 ) / 10;
sizeAltered = true;
}
if ( plotSize.height() > 0 && (double)legendSize.y() > 0.9 * plotSize.height() )
{
legendSize.y() = ( plotSize.height() * 9 ) / 10;
sizeAltered = true;
}
overlayItem->setRenderSize( legendSize );
if ( legendSize.x() != existingRenderSize.x() || legendSize.y() != existingRenderSize.y() )
{
sizeAltered = true;
}
return sizeAltered;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -531,17 +259,6 @@ bool RiuGridCrossQwtPlot::curveText( const QwtPlotCurve* curve,
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGridCrossQwtPlot::applyFontSizeToOverlayItem( caf::TitledOverlayFrame* overlayItem )
{
RimGridCrossPlot* crossPlot = static_cast<RimGridCrossPlot*>( ownerViewWindow() );
int fontSize = crossPlot->legendFontSize();
cvf::ref<cvf::Font> cafFont = RiaFontCache::getFont( RiaFontCache::fontSizeEnumFromPointSize( fontSize ) );
overlayItem->setFont( cafFont.p() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -55,10 +55,6 @@ public:
RiuGridCrossQwtPlot( const RiuGridCrossQwtPlot& ) = delete;
void addOrUpdateDataSetLegend( RimGridCrossPlotDataSet* dataSetToShowLegendFor );
void removeDataSetLegend( RimGridCrossPlotDataSet* dataSetToShowLegendFor );
void removeDanglingDataSetLegends();
void updateLegendSizesToMatchPlot();
void updateAnnotationObjects( RimPlotAxisProperties* axisProperties );
RimViewWindow* ownerViewWindow() const override;
@ -67,17 +63,11 @@ public:
void setInternalQwtLegendVisible( bool visible );
protected:
void updateLayout() override;
void updateInfoBoxLayout();
void updateLegendLayout();
void resizeEvent( QResizeEvent* e ) override;
bool resizeOverlayItemToFitPlot( caf::TitledOverlayFrame* overlayItem );
void contextMenuEvent( QContextMenuEvent* ) override;
void selectPoint( QwtPlotCurve* curve, int pointNumber ) override;
void clearPointSelection() override;
bool curveText( const QwtPlotCurve* curve, QString* curveTitle, QString* xParamName, QString* yParamName ) const;
void applyFontSizeToOverlayItem( caf::TitledOverlayFrame* overlayItem );
bool isZoomerActive() const override;
void endZoomOperations() override;
@ -85,12 +75,6 @@ private slots:
void onZoomedSlot();
private:
typedef caf::PdmPointer<RimGridCrossPlotDataSet> DataSetPtr;
typedef QPointer<RiuCvfOverlayItemWidget> LegendPtr;
typedef QPointer<RiuDraggableOverlayFrame> InfoBoxPtr;
InfoBoxPtr m_infoBox;
std::map<DataSetPtr, LegendPtr> m_legendWidgets;
std::unique_ptr<RiuPlotAnnotationTool> m_annotationTool;
QwtPlotMarker* m_selectedPointMarker;

View File

@ -680,7 +680,6 @@ void RiuMainWindow::createDockPanels()
m_projectTreeView = new caf::PdmUiTreeView( this );
m_projectTreeView->enableSelectionManagerUpdating( true );
m_styleSheet.applyToWidgetAndChildren( m_projectTreeView );
RiaApplication* app = RiaApplication::instance();
m_projectTreeView->enableAppendOfClassNameToUiItemText( app->preferences()->appendClassNameToUiText() );

View File

@ -46,7 +46,6 @@ RiuMainWindowBase::RiuMainWindowBase()
, m_blockSubWindowProjectTreeSelection( false )
{
setDockNestingEnabled( true );
m_styleSheet = createStyleSheet();
}
//--------------------------------------------------------------------------------------------------

View File

@ -94,7 +94,6 @@ protected slots:
protected:
caf::PdmUiTreeView* m_projectTreeView;
caf::UiStyleSheet m_styleSheet;
bool m_allowActiveViewChangeFromSelection; // To be used in selectedObjectsChanged() to control
// whether to select the corresponding active view or not
private:

View File

@ -42,10 +42,12 @@
#include "qwt_legend.h"
#include "qwt_plot_layout.h"
#include "qwt_plot_renderer.h"
#include "qwt_scale_draw.h"
#include <QDebug>
#include <QFocusEvent>
#include <QFontMetrics>
#include <QHBoxLayout>
#include <QMdiSubWindow>
#include <QMenu>
@ -279,6 +281,14 @@ void RiuMultiPlotWindow::scheduleReplotOfAllPlots()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::renderTo( QPainter* painter )
{
doRenderTo( painter );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -437,7 +447,7 @@ void RiuMultiPlotWindow::dropEvent( QDropEvent* event )
if ( insertAfter != plotToMove )
{
m_plotDefinition->movePlotsToThis( { plotToMove }, insertAfter );
m_plotDefinition->movePlotsToThis( {plotToMove}, insertAfter );
}
}
}
@ -534,13 +544,22 @@ void RiuMultiPlotWindow::reinsertPlotWidgets()
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
m_plotWidgets[tIdx]->hide();
m_legends[tIdx]->hide();
m_subTitles[tIdx]->hide();
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<QPointer<QLabel>> subTitles = this->visibleTitles();
QList<QPointer<RiuQwtPlotLegend>> legends = this->visibleLegends();
QList<QPointer<QLabel>> subTitles = this->subTitlesForVisiblePlots();
QList<QPointer<RiuQwtPlotLegend>> legends = this->legendsForVisiblePlots();
QList<QPointer<RiuQwtPlotWidget>> plotWidgets = this->visiblePlotWidgets();
if ( plotWidgets.empty() && acceptDrops() )
@ -566,7 +585,8 @@ void RiuMultiPlotWindow::reinsertPlotWidgets()
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 );
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() );
@ -617,7 +637,7 @@ int RiuMultiPlotWindow::alignCanvasTops()
CVF_ASSERT( m_legends.size() == m_plotWidgets.size() );
QList<QPointer<RiuQwtPlotWidget>> plotWidgets = visiblePlotWidgets();
QList<QPointer<RiuQwtPlotLegend>> legends = visibleLegends();
QList<QPointer<RiuQwtPlotLegend>> legends = legendsForVisiblePlots();
if ( plotWidgets.empty() ) return 0;
auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() );
@ -701,7 +721,7 @@ QList<QPointer<RiuQwtPlotWidget>> RiuMultiPlotWindow::visiblePlotWidgets() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<QPointer<RiuQwtPlotLegend>> RiuMultiPlotWindow::visibleLegends() const
QList<QPointer<RiuQwtPlotLegend>> RiuMultiPlotWindow::legendsForVisiblePlots() const
{
QList<QPointer<RiuQwtPlotLegend>> legends;
for ( int i = 0; i < m_plotWidgets.size(); ++i )
@ -717,7 +737,7 @@ QList<QPointer<RiuQwtPlotLegend>> RiuMultiPlotWindow::visibleLegends() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<QPointer<QLabel>> RiuMultiPlotWindow::visibleTitles() const
QList<QPointer<QLabel>> RiuMultiPlotWindow::subTitlesForVisiblePlots() const
{
QList<QPointer<QLabel>> subTitles;
for ( int i = 0; i < m_plotWidgets.size(); ++i )
@ -765,3 +785,37 @@ std::pair<int, int>
}
return std::make_pair( availableRow, availableColumn );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::doRenderTo( QPainter* painter )
{
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 );
}

View File

@ -41,8 +41,11 @@ class RiuQwtPlotWidget;
class QFocusEvent;
class QLabel;
class QPainter;
class QScrollBar;
class QwtLegend;
class QwtLegendData;
class QwtPlot;
//==================================================================================================
//
@ -78,6 +81,8 @@ public:
void scheduleReplotOfAllPlots();
virtual void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) {}
void renderTo( QPainter* painter );
protected:
void contextMenuEvent( QContextMenuEvent* ) override;
QLabel* createTitleLabel() const;
@ -104,11 +109,13 @@ protected:
caf::UiStyleSheet createDropTargetStyleSheet();
QList<QPointer<RiuQwtPlotWidget>> visiblePlotWidgets() const;
QList<QPointer<RiuQwtPlotLegend>> visibleLegends() const;
QList<QPointer<QLabel>> visibleTitles() const;
QList<QPointer<RiuQwtPlotLegend>> legendsForVisiblePlots() const;
QList<QPointer<QLabel>> subTitlesForVisiblePlots() const;
std::pair<int, int> findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const;
virtual void doRenderTo( QPainter* painter );
private slots:
virtual void performUpdate();
void onLegendUpdated();

View File

@ -31,6 +31,11 @@ RiuQwtPlotLegend::RiuQwtPlotLegend( QWidget* parent /*= nullptr */ )
: QwtLegend( parent )
, m_columnCount( 1 )
{
QwtDynGridLayout* legendLayout = qobject_cast<QwtDynGridLayout*>( contentsWidget()->layout() );
if ( legendLayout )
{
legendLayout->setExpandingDirections( Qt::Horizontal | Qt::Vertical );
}
}
//--------------------------------------------------------------------------------------------------
@ -75,7 +80,7 @@ QSize RiuQwtPlotLegend::sizeHint() const
maxHeight = std::max( maxHeight, itemSize.height() );
}
QMargins margins = legendLayout->contentsMargins();
int totalSpacing = ( numRows + 1 ) * legendLayout->spacing() + margins.top() + margins.bottom();
int totalSpacing = ( numRows + 2 ) * legendLayout->spacing() + margins.top() + margins.bottom();
int height = maxHeight * numRows + totalSpacing;

View File

@ -119,8 +119,6 @@ void RiuQwtPlotTools::setDefaultAxes( QwtPlot* plot )
plot->enableAxis( QwtPlot::xTop, false );
plot->enableAxis( QwtPlot::yRight, false );
plot->axisScaleDraw( QwtPlot::xBottom )->enableComponent( QwtAbstractScaleDraw::Backbone, false );
plot->axisScaleDraw( QwtPlot::yLeft )->enableComponent( QwtAbstractScaleDraw::Backbone, false );
plot->axisWidget( QwtPlot::xBottom )->setMargin( 0 );
plot->axisWidget( QwtPlot::yLeft )->setMargin( 0 );

View File

@ -21,11 +21,13 @@
#include "RiaApplication.h"
#include "RiaColorTools.h"
#include "RiaFontCache.h"
#include "RiaPlotWindowRedrawScheduler.h"
#include "RimPlot.h"
#include "RimPlotCurve.h"
#include "RiuDraggableOverlayFrame.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtCurvePointTracker.h"
#include "RiuQwtLinearScaleEngine.h"
@ -35,16 +37,19 @@
#include "cafAssert.h"
#include "qwt_legend.h"
#include "qwt_plot_canvas.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_grid.h"
#include "qwt_plot_layout.h"
#include "qwt_plot_marker.h"
#include "qwt_plot_picker.h"
#include "qwt_plot_renderer.h"
#include "qwt_scale_draw.h"
#include "qwt_scale_widget.h"
#include "qwt_symbol.h"
#include "qwt_text.h"
#include <QDebug>
#include <QDrag>
#include <QFont>
#include <QFontMetrics>
@ -55,6 +60,7 @@
#include <QScrollArea>
#include <QWheelEvent>
#include <algorithm>
#include <cfloat>
//--------------------------------------------------------------------------------------------------
@ -64,6 +70,7 @@ RiuQwtPlotWidget::RiuQwtPlotWidget( RimPlot* plot, QWidget* parent )
: QwtPlot( parent )
, m_plotDefinition( plot )
, m_draggable( true )
, m_overlayMargins( 5 )
{
RiuQwtPlotTools::setCommonPlotBehaviour( this );
@ -404,11 +411,11 @@ void RiuQwtPlotWidget::setWidgetState( const QString& widgetState )
//--------------------------------------------------------------------------------------------------
/// Adds an overlay frame. The overlay frame becomes the responsibility of the plot widget
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::addOverlayFrame( QFrame* overlayFrame )
void RiuQwtPlotWidget::addOverlayFrame( RiuDraggableOverlayFrame* overlayFrame )
{
if ( std::find( m_overlayFrames.begin(), m_overlayFrames.end(), overlayFrame ) == m_overlayFrames.end() )
{
overlayFrame->setParent( this );
overlayFrame->setParent( this->canvas() );
m_overlayFrames.push_back( overlayFrame );
updateLayout();
}
@ -417,7 +424,7 @@ void RiuQwtPlotWidget::addOverlayFrame( QFrame* overlayFrame )
//--------------------------------------------------------------------------------------------------
/// Remove the overlay widget. The frame becomes the responsibility of the caller
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::removeOverlayFrame( QFrame* overlayFrame )
void RiuQwtPlotWidget::removeOverlayFrame( RiuDraggableOverlayFrame* overlayFrame )
{
overlayFrame->hide();
overlayFrame->setParent( nullptr );
@ -544,6 +551,16 @@ void RiuQwtPlotWidget::showEvent( QShowEvent* event )
QwtPlot::showEvent( event );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::resizeEvent( QResizeEvent* event )
{
QwtPlot::resizeEvent( event );
updateOverlayFrameLayout();
event->accept();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -587,6 +604,47 @@ bool RiuQwtPlotWidget::isZoomerActive() const
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::endZoomOperations() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::renderTo( QPainter* painter, const QRect& targetRect )
{
static_cast<QwtPlotCanvas*>( this->canvas() )->setPaintAttribute( QwtPlotCanvas::BackingStore, false );
QwtPlotRenderer renderer( this );
renderer.render( this, painter, targetRect );
static_cast<QwtPlotCanvas*>( this->canvas() )->setPaintAttribute( QwtPlotCanvas::BackingStore, true );
for ( RiuDraggableOverlayFrame* overlayFrame : m_overlayFrames )
{
if ( overlayFrame->isVisible() )
{
QPoint overlayTopLeftInCanvasCoords = overlayFrame->frameGeometry().topLeft();
QPoint canvasTopLeftInPlotCoords = this->canvas()->frameGeometry().topLeft();
QPoint plotTopLeftInWindowCoords = targetRect.topLeft();
QPoint overlayTopLeftInWindowCoords = plotTopLeftInWindowCoords + canvasTopLeftInPlotCoords +
overlayTopLeftInCanvasCoords;
{
QRect overlayRect = overlayFrame->frameGeometry();
QSize desiredSize = overlayRect.size();
QSize minimumSize = overlayFrame->minimumSizeHint();
QSize actualSize = desiredSize.expandedTo( minimumSize );
overlayRect.moveTo( overlayTopLeftInWindowCoords );
overlayRect.setSize( actualSize );
overlayFrame->renderTo( painter, overlayRect );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuQwtPlotWidget::overlayMargins() const
{
return m_overlayMargins;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -651,26 +709,47 @@ caf::UiStyleSheet RiuQwtPlotWidget::createCanvasStyleSheet() const
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::updateOverlayFrameLayout()
{
const int spacing = 5;
int startMarginX = this->canvas()->pos().x() + spacing;
int startMarginY = this->canvas()->pos().y() + spacing;
const int spacing = 5;
int xpos = startMarginX;
int ypos = startMarginY;
int maxColumnWidth = 0;
for ( QPointer<QFrame> frame : m_overlayFrames )
int xpos = spacing;
int ypos = spacing;
int widthOfCurrentColumn = 0;
QSize canvasSize = this->canvas()->size();
QSize maxFrameSize( canvasSize.width() - 2 * m_overlayMargins, canvasSize.height() - 2 * m_overlayMargins );
for ( RiuDraggableOverlayFrame* frame : m_overlayFrames )
{
if ( !frame.isNull() )
if ( frame )
{
if ( ypos + frame->height() + spacing > this->canvas()->height() )
QSize minFrameSize = frame->minimumSizeHint();
QSize desiredFrameSize = frame->sizeHint();
int width = std::min( std::max( minFrameSize.width(), desiredFrameSize.width() ), maxFrameSize.width() );
int height = std::min( std::max( minFrameSize.height(), desiredFrameSize.height() ), maxFrameSize.height() );
frame->resize( width, height );
if ( frame->anchorCorner() == RiuDraggableOverlayFrame::AnchorCorner::TopLeft )
{
xpos += spacing + maxColumnWidth;
ypos = startMarginY;
maxColumnWidth = 0;
if ( ypos + frame->height() + spacing > this->canvas()->height() && widthOfCurrentColumn > 0 )
{
xpos += spacing + widthOfCurrentColumn;
ypos = spacing;
widthOfCurrentColumn = 0;
}
frame->move( xpos, ypos );
ypos += frame->height() + spacing;
widthOfCurrentColumn = std::max( widthOfCurrentColumn, frame->width() );
}
else if ( frame->anchorCorner() == RiuDraggableOverlayFrame::AnchorCorner::TopRight )
{
QRect frameRect = frame->frameGeometry();
QRect canvasRect = canvas()->rect();
QPoint canvasTopRight = canvasRect.topRight();
frameRect.moveTopRight( QPoint( canvasTopRight.x() - spacing, canvasTopRight.y() + spacing ) );
frame->move( frameRect.topLeft() );
}
frame->move( xpos, ypos );
ypos += frame->height() + spacing;
maxColumnWidth = std::max( maxColumnWidth, frame->width() );
frame->show();
}
}

View File

@ -32,6 +32,7 @@
class RiaPlotWindowRedrawScheduler;
class RimPlot;
class RiuDraggableOverlayFrame;
class QwtLegend;
class QwtPicker;
@ -98,16 +99,20 @@ public:
void scheduleReplot();
void setWidgetState( const QString& widgetState );
void addOverlayFrame( QFrame* overlayWidget );
void removeOverlayFrame( QFrame* overlayWidget );
void addOverlayFrame( RiuDraggableOverlayFrame* overlayWidget );
void removeOverlayFrame( RiuDraggableOverlayFrame* overlayWidget );
void updateLayout() override;
void renderTo( QPainter* painter, const QRect& targetRect );
int overlayMargins() const;
protected:
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
bool eventFilter( QObject* watched, QEvent* event ) override;
void hideEvent( QHideEvent* event ) override;
void showEvent( QShowEvent* event ) override;
void resizeEvent( QResizeEvent* event ) override;
void applyAxisTitleToQwt( QwtPlot::Axis axis );
@ -138,8 +143,9 @@ private:
std::map<QwtPlot::Axis, bool> m_axisTitlesEnabled;
QPointer<QwtPlotPicker> m_plotPicker;
bool m_draggable;
const int m_overlayMargins;
QList<QPointer<QFrame>> m_overlayFrames;
QList<QPointer<RiuDraggableOverlayFrame>> m_overlayFrames;
struct CurveColors
{

View File

@ -0,0 +1,203 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuScalarMapperLegendFrame.h"
#include "cvfString.h"
#include "cvfqtUtils.h"
#include <QFontMetrics>
#include <QPaintEvent>
#include <QPainter>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuScalarMapperLegendFrame::RiuScalarMapperLegendFrame( QWidget* parent,
const QString& title,
cvf::ScalarMapper* scalarMapper )
: RiuAbstractLegendFrame( parent, title )
, m_scalarMapper( scalarMapper )
, m_tickNumberPrecision( 4 )
, m_numberFormat( RimRegularLegendConfig::AUTO )
{
if ( m_scalarMapper.notNull() )
{
m_scalarMapper->majorTickValues( &m_tickValues );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuScalarMapperLegendFrame::~RiuScalarMapperLegendFrame() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuScalarMapperLegendFrame::setTickPrecision( int precision )
{
m_tickNumberPrecision = precision;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuScalarMapperLegendFrame::setTickFormat( NumberFormat format )
{
m_numberFormat = format;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuScalarMapperLegendFrame::layoutInfo( LayoutInfo* layout ) const
{
QFontMetrics fontMetrics( this->font() );
QStringList titleLines = m_title.split( "\n", QString::SkipEmptyParts );
layout->charHeight = fontMetrics.height();
layout->charAscent = fontMetrics.ascent();
layout->lineSpacing = ( fontMetrics.lineSpacing() * 3 ) / 2;
layout->margins = QMargins( 8, 8, 8, 8 );
layout->tickTextLeadSpace = 5;
int colorBarWidth = 25;
int colorBarHeight = layout->overallLegendSize.height() - layout->margins.top() - layout->margins.bottom() -
titleLines.size() * layout->lineSpacing;
int colorBarStartY = layout->margins.top() + titleLines.size() * layout->lineSpacing;
layout->colorBarRect = QRect( layout->margins.left(), colorBarStartY, colorBarWidth, colorBarHeight );
layout->tickStartX = layout->margins.left();
layout->tickMidX = layout->margins.left() + layout->colorBarRect.width();
layout->tickEndX = layout->tickMidX + 5;
// Build array containing the pixel positions of all the ticks
int numTicks = (int)m_tickValues.size();
layout->tickYPixelPos.reserve( numTicks );
int i;
for ( i = 0; i < numTicks; i++ )
{
double t = 0.0;
if ( m_scalarMapper.notNull() )
{
t = cvf::Math::clamp( m_scalarMapper->normalizedValue( m_tickValues[i] ), 0.0, 1.1 );
}
if ( i == 0 )
{
layout->tickYPixelPos.push_back( 0.0 );
}
else if ( i == numTicks - 1 )
{
layout->tickYPixelPos.push_back( layout->colorBarRect.height() );
}
else
{
layout->tickYPixelPos.push_back( t * layout->colorBarRect.height() );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiuScalarMapperLegendFrame::label( int index ) const
{
double tickValue = m_tickValues[index];
QString valueString;
switch ( m_numberFormat )
{
case RimRegularLegendConfig::FIXED:
valueString = QString::number( tickValue, 'f', m_tickNumberPrecision );
break;
case RimRegularLegendConfig::SCIENTIFIC:
valueString = QString::number( tickValue, 'e', m_tickNumberPrecision );
break;
default:
valueString = QString::number( tickValue );
break;
}
return valueString;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuScalarMapperLegendFrame::labelCount() const
{
return (int)m_tickValues.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuScalarMapperLegendFrame::rectCount() const
{
return (int)m_tickValues.size() - 1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuScalarMapperLegendFrame::renderRect( QPainter* painter, const LayoutInfo& layout, int rectIndex ) const
{
int rectIndexFromBottom = rectCount() - rectIndex - 1;
cvf::Color3ub startColor = m_scalarMapper->mapToColor(
m_scalarMapper->domainValue( m_tickValues[rectIndexFromBottom] ) );
cvf::Color3ub endColor = m_scalarMapper->mapToColor(
m_scalarMapper->domainValue( m_tickValues[rectIndexFromBottom + 1] ) );
QColor startQColor( startColor.r(), startColor.g(), startColor.b() );
QColor endQColor( endColor.r(), endColor.g(), endColor.b() );
QRectF gradientRect( QPointF( layout.tickStartX,
layout.colorBarRect.bottom() - layout.tickYPixelPos[rectIndexFromBottom] + 1 ),
QPointF( layout.tickStartX,
layout.colorBarRect.bottom() - layout.tickYPixelPos[rectIndexFromBottom + 1] + 1 ) );
QLinearGradient gradient( gradientRect.topLeft(), gradientRect.bottomRight() );
gradient.setCoordinateMode( QGradient::LogicalMode );
gradient.setColorAt( 0.0, startQColor );
gradient.setColorAt( 1.0, endQColor );
QRectF rect( QPointF( layout.tickStartX,
layout.colorBarRect.bottom() - layout.tickYPixelPos[rectIndexFromBottom] + 1 ),
QPointF( layout.tickMidX,
layout.colorBarRect.bottom() - layout.tickYPixelPos[rectIndexFromBottom + 1] + 1 ) );
painter->fillRect( rect, QBrush( gradient ) );
painter->drawLine( QPointF( layout.tickStartX,
layout.colorBarRect.bottom() - layout.tickYPixelPos[rectIndexFromBottom] + 1 ),
QPointF( layout.tickEndX,
layout.colorBarRect.bottom() - layout.tickYPixelPos[rectIndexFromBottom] + 1 ) );
painter->drawLine( QPointF( layout.tickStartX,
layout.colorBarRect.bottom() - layout.tickYPixelPos[rectIndexFromBottom + 1] + 1 ),
QPointF( layout.tickEndX,
layout.colorBarRect.bottom() - layout.tickYPixelPos[rectIndexFromBottom + 1] + 1 ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuScalarMapperLegendFrame::labelPixelPosY( const LayoutInfo& layout, int index ) const
{
int indexFromBottom = labelCount() - index - 1;
return layout.colorBarRect.bottom() - layout.tickYPixelPos[indexFromBottom] + layout.charAscent / 2;
}

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimRegularLegendConfig.h"
#include "RiuAbstractLegendFrame.h"
#include "cvfObject.h"
#include "cvfRect.h"
#include "cvfScalarMapper.h"
#include <QLabel>
#include <QSize>
class QFont;
class QPaintEvent;
class QPainter;
class QRect;
class RiuScalarMapperLegendFrame : public RiuAbstractLegendFrame
{
Q_OBJECT
public:
using NumberFormat = RimRegularLegendConfig::NumberFormatType;
public:
RiuScalarMapperLegendFrame( QWidget* parent, const QString& title, cvf::ScalarMapper* scalarMapper );
~RiuScalarMapperLegendFrame();
void setTickPrecision( int precision );
void setTickFormat( NumberFormat format );
private:
void layoutInfo( LayoutInfo* layout ) const override;
QString label( int index ) const override;
int labelCount() const override;
int rectCount() const override;
void renderRect( QPainter* painter, const LayoutInfo& layout, int rectIndex ) const override;
int labelPixelPosY( const LayoutInfo& layout, int index ) const override;
private:
cvf::cref<cvf::ScalarMapper> m_scalarMapper;
std::vector<double> m_tickValues;
int m_tickNumberPrecision;
NumberFormat m_numberFormat;
};

View File

@ -27,14 +27,6 @@ RiuWellLogPlot::RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent
connect( m_trackScrollBar, SIGNAL( valueChanged( int ) ), this, SLOT( slotSetMinDepth( int ) ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuWellLogPlot::isScrollbarVisible() const
{
return m_trackScrollBar->isVisible();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -48,9 +40,11 @@ RimWellLogPlot* RiuWellLogPlot::wellLogPlotDefinition()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuWellLogPlot::setScrollbarVisible( bool visible )
void RiuWellLogPlot::doRenderTo( QPainter* painter )
{
m_trackScrollBar->setVisible( visible );
m_trackScrollBar->setVisible( false );
RiuMultiPlotWindow::doRenderTo( painter );
m_trackScrollBar->setVisible( true );
}
//--------------------------------------------------------------------------------------------------
@ -102,7 +96,7 @@ bool RiuWellLogPlot::showYAxis( int row, int column ) const
void RiuWellLogPlot::reinsertScrollbar()
{
QList<QPointer<RiuQwtPlotWidget>> plotWidgets = this->visiblePlotWidgets();
QList<QPointer<RiuQwtPlotLegend>> legends = this->visibleLegends();
QList<QPointer<RiuQwtPlotLegend>> legends = this->legendsForVisiblePlots();
int rowCount = this->m_gridLayout->rowCount();
int colCount = this->m_gridLayout->columnCount();

View File

@ -28,8 +28,6 @@ class RiuWellLogPlot : public RiuMultiPlotWindow
public:
RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent );
bool isScrollbarVisible() const;
void setScrollbarVisible( bool visible );
void updateVerticalScrollBar( double minVisible, double maxVisible, double minAvailable, double maxAvailable ) override;
protected:
@ -39,6 +37,7 @@ protected:
void reinsertScrollbar();
void alignScrollbar( int offset );
void doRenderTo( QPainter* painter ) override;
private:
RimWellLogPlot* wellLogPlotDefinition();

View File

@ -24,12 +24,9 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuWidgetDragger::RiuWidgetDragger( QWidget* widgetToMove,
QWidget* widgetToSnapTo /*= nullptr*/,
int snapMargins /*= 5*/ )
RiuWidgetDragger::RiuWidgetDragger( QWidget* widgetToMove, int snapMargins /*= 5*/ )
: QObject( widgetToMove )
, m_widgetToMove( widgetToMove )
, m_widgetToSnapTo( widgetToSnapTo )
, m_snapMargins( snapMargins )
, m_startPos( 0, 0 )
{
@ -56,61 +53,58 @@ bool RiuWidgetDragger::eventFilter( QObject* watched, QEvent* event )
{
QPoint relativeMove = mMoveEv->pos() - m_startPos;
QRect newFrameRect = m_widgetToMove->frameGeometry().translated( relativeMove );
QRect snapToRect = m_widgetToMove->parentWidget()->rect();
if ( m_widgetToSnapTo )
{
QRect snapToRect = m_widgetToSnapTo->frameGeometry();
QPoint snapToTopLeft = snapToRect.topLeft();
QPoint widgetTopLeft = newFrameRect.topLeft();
QPoint diff = snapToTopLeft - widgetTopLeft;
if ( std::abs( diff.x() ) < 4 * m_snapMargins )
{
QPoint snapToTopLeft = snapToRect.topLeft();
QPoint widgetTopLeft = newFrameRect.topLeft();
QPoint diff = snapToTopLeft - widgetTopLeft;
if ( std::abs( diff.x() ) < 4 * m_snapMargins )
{
newFrameRect.moveLeft( snapToTopLeft.x() + m_snapMargins );
}
if ( std::abs( diff.y() ) < 4 * m_snapMargins )
{
newFrameRect.moveTop( snapToTopLeft.y() + m_snapMargins );
}
newFrameRect.moveLeft( snapToTopLeft.x() + m_snapMargins );
}
if ( std::abs( diff.y() ) < 4 * m_snapMargins )
{
QPoint snapToBottomLeft = snapToRect.bottomLeft();
QPoint widgetBottomLeft = newFrameRect.bottomLeft();
QPoint diff = snapToBottomLeft - widgetBottomLeft;
if ( std::abs( diff.x() ) < 4 * m_snapMargins )
{
newFrameRect.moveLeft( snapToBottomLeft.x() + m_snapMargins );
}
if ( std::abs( diff.y() ) < 4 * m_snapMargins )
{
newFrameRect.moveBottom( snapToBottomLeft.y() - m_snapMargins );
}
newFrameRect.moveTop( snapToTopLeft.y() + m_snapMargins );
}
}
{
QPoint snapToBottomLeft = snapToRect.bottomLeft();
QPoint widgetBottomLeft = newFrameRect.bottomLeft();
QPoint diff = snapToBottomLeft - widgetBottomLeft;
if ( std::abs( diff.x() ) < 4 * m_snapMargins )
{
QPoint snapToTopRight = snapToRect.topRight();
QPoint widgetTopRight = newFrameRect.topRight();
QPoint diff = snapToTopRight - widgetTopRight;
if ( std::abs( diff.x() ) < 4 * m_snapMargins )
{
newFrameRect.moveRight( snapToTopRight.x() - m_snapMargins );
}
if ( std::abs( diff.y() ) < 4 * m_snapMargins )
{
newFrameRect.moveTop( snapToTopRight.y() + m_snapMargins );
}
newFrameRect.moveLeft( snapToBottomLeft.x() + m_snapMargins );
}
if ( std::abs( diff.y() ) < 4 * m_snapMargins )
{
QPoint snapToBottomRight = snapToRect.bottomRight();
QPoint widgetBottomRight = newFrameRect.bottomRight();
QPoint diff = snapToBottomRight - widgetBottomRight;
if ( std::abs( diff.x() ) < 4 * m_snapMargins )
{
newFrameRect.moveRight( snapToBottomRight.x() - m_snapMargins );
}
if ( std::abs( diff.y() ) < 4 * m_snapMargins )
{
newFrameRect.moveBottom( snapToBottomRight.y() - m_snapMargins );
}
newFrameRect.moveBottom( snapToBottomLeft.y() - m_snapMargins );
}
}
{
QPoint snapToTopRight = snapToRect.topRight();
QPoint widgetTopRight = newFrameRect.topRight();
QPoint diff = snapToTopRight - widgetTopRight;
if ( std::abs( diff.x() ) < 4 * m_snapMargins )
{
newFrameRect.moveRight( snapToTopRight.x() - m_snapMargins );
}
if ( std::abs( diff.y() ) < 4 * m_snapMargins )
{
newFrameRect.moveTop( snapToTopRight.y() + m_snapMargins );
}
}
{
QPoint snapToBottomRight = snapToRect.bottomRight();
QPoint widgetBottomRight = newFrameRect.bottomRight();
QPoint diff = snapToBottomRight - widgetBottomRight;
if ( std::abs( diff.x() ) < 4 * m_snapMargins )
{
newFrameRect.moveRight( snapToBottomRight.x() - m_snapMargins );
}
if ( std::abs( diff.y() ) < 4 * m_snapMargins )
{
newFrameRect.moveBottom( snapToBottomRight.y() - m_snapMargins );
}
}
m_widgetToMove->move( newFrameRect.topLeft() );

View File

@ -28,14 +28,13 @@ class RiuWidgetDragger : public QObject
{
Q_OBJECT
public:
RiuWidgetDragger( QWidget* widgetToMove, QWidget* widgetToSnapTo = nullptr, int snapMargins = 5 );
RiuWidgetDragger( QWidget* widgetToMove, int snapMargins = 5 );
void addWidget( QWidget* widget );
bool eventFilter( QObject* watched, QEvent* event ) override;
private:
QPointer<QWidget> m_widgetToMove;
QPointer<QWidget> m_widgetToSnapTo;
int m_snapMargins;
QPoint m_startPos;
};

View File

@ -30,6 +30,7 @@
#include "cafInternalLegendRenderTools.h"
#include <cmath>
#include <QDebug>
using namespace cvf;

View File

@ -38,13 +38,13 @@ public:
void majorTickValues(std::vector<double>* domainValues) const override;
double normalizedValue(double domainValue) const override;
double domainValue(double normalizedValue) const override;
size_t categoryCount() const;
const cvf::String textForCategoryIndex(size_t index) const;
int categoryIndexForCategory(double domainValue) const;
private:
friend class CategoryLegend;
size_t categoryCount() const;
const cvf::String textForCategoryIndex(size_t index) const;
int categoryIndexForCategory(double domainValue) const;
void recomputeMaxTexCoord();
private:

View File

@ -682,7 +682,7 @@ cvf::Vec2ui OverlayScalarMapperLegend::preferredSize()
OverlayColorLegendLayoutInfo layout({200,200}); // Use default size
layoutInfo(&layout);
float prefferredYSize = 2 * layout.margins.y()
float preferredYSize = 2 * layout.margins.y()
+ layout.lineSpacing * this->titleStrings().size()
+ 1.5f * layout.lineSpacing * m_tickValues.size();
@ -706,18 +706,17 @@ cvf::Vec2ui OverlayScalarMapperLegend::preferredSize()
maxTickTextWidth = maxTickTextWidth < textWidth ? textWidth : maxTickTextWidth;
}
float prefferredXSize = layout.tickEndX + layout.margins.x() + layout.tickTextLeadSpace + maxTickTextWidth;
float preferredXSize = layout.tickEndX + layout.margins.x() + layout.tickTextLeadSpace + maxTickTextWidth;
for (const cvf::String& titleLine : titleStrings())
{
float titleWidth = this->font()->textExtent(titleLine).x() + 2*layout.margins.x();
prefferredXSize = prefferredXSize < titleWidth ? titleWidth : prefferredXSize;
preferredXSize = preferredXSize < titleWidth ? titleWidth : preferredXSize;
}
prefferredXSize = std::min(prefferredXSize, 400.0f);
return { (unsigned int)(std::ceil(prefferredXSize)), (unsigned int)(std::ceil(prefferredYSize)) };
preferredXSize = std::min(preferredXSize, 400.0f);
return { (unsigned int)(std::ceil(preferredXSize)), (unsigned int)(std::ceil(preferredYSize)) };
}
} // namespace cvf

View File

@ -218,4 +218,4 @@ namespace caf {
{
return m_font.p();
}
}
}

View File

@ -730,7 +730,7 @@ void QwtPlotCanvas::paintEvent( QPaintEvent *event )
QPainter painter( this );
painter.setClipRegion( event->region() );
if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) &&
if (testPaintAttribute( QwtPlotCanvas::BackingStore ) &&
d_data->backingStore != NULL )
{
QPixmap &bs = *d_data->backingStore;