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
57 changed files with 1675 additions and 559 deletions

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;
};