Much improved legend rendering

This commit is contained in:
Gaute Lindkvist
2020-01-07 09:26:39 +01:00
parent 185b26514b
commit 7bd62052ca
10 changed files with 100 additions and 108 deletions

View File

@@ -86,7 +86,7 @@ void RicSnapshotViewToFileFeature::savePlotPDFReportAs( const QString& fileName,
if ( pdfFile.open( QIODevice::WriteOnly ) ) if ( pdfFile.open( QIODevice::WriteOnly ) )
{ {
int resolution = RiaGuiApplication::applicationResolution(); int resolution = RiaGuiApplication::applicationResolution();
/* int pageWidth = plot->pageLayout().fullRectPixels( resolution ).width(); int pageWidth = plot->pageLayout().fullRectPixels( resolution ).width();
int widgetWidth = plot->viewWidget()->width(); int widgetWidth = plot->viewWidget()->width();
int deltaWidth = widgetWidth - pageWidth; int deltaWidth = widgetWidth - pageWidth;
@@ -100,7 +100,6 @@ void RicSnapshotViewToFileFeature::savePlotPDFReportAs( const QString& fileName,
resolution = newResolution; resolution = newResolution;
deltaWidth = newDeltaWidth; deltaWidth = newDeltaWidth;
} }
*/
QPdfWriter pdfPrinter( fileName ); QPdfWriter pdfPrinter( fileName );
pdfPrinter.setPageLayout( plot->pageLayout() ); pdfPrinter.setPageLayout( plot->pageLayout() );
pdfPrinter.setCreator( QCoreApplication::applicationName() ); pdfPrinter.setCreator( QCoreApplication::applicationName() );

View File

@@ -17,8 +17,13 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
#include "RiuAbstractLegendFrame.h" #include "RiuAbstractLegendFrame.h"
#include "RiaApplication.h"
#include "RiaFontCache.h"
#include "RiaPreferences.h"
#include <QPaintEvent> #include <QPaintEvent>
#include <QPainter> #include <QPainter>
#include <QTextDocument>
#include <cmath> #include <cmath>
@@ -76,7 +81,7 @@ QSize RiuAbstractLegendFrame::minimumSizeHint() const
QFontMetrics fontMetrics( this->font() ); QFontMetrics fontMetrics( this->font() );
QRect titleRect = fontMetrics.boundingRect( QRect( 0, 0, 200, 200 ), Qt::AlignLeft, m_title ); QRect titleRect = fontMetrics.boundingRect( QRect( 0, 0, 200, 200 ), Qt::AlignLeft, m_title );
int preferredContentHeight = titleRect.height() + 2 * layout.lineSpacing; int preferredContentHeight = titleRect.height() + 2.25 * layout.lineSpacing;
int preferredHeight = preferredContentHeight + layout.margins.top() + layout.margins.bottom(); int preferredHeight = preferredContentHeight + layout.margins.top() + layout.margins.bottom();
int titleWidth = titleRect.width() + layout.margins.left() + layout.margins.right(); int titleWidth = titleRect.width() + layout.margins.left() + layout.margins.right();
@@ -98,21 +103,37 @@ QSize RiuAbstractLegendFrame::minimumSizeHint() const
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RiuAbstractLegendFrame::renderTo( QPainter* painter, const QRect& targetRect ) void RiuAbstractLegendFrame::renderTo( QPainter* painter, const QRect& targetRect )
{ {
QFont font = this->font();
font.setPointSize( RiaApplication::instance()->preferences()->defaultPlotFontSize() );
this->setFont( font );
LayoutInfo layout( QSize( targetRect.width(), targetRect.height() ) ); LayoutInfo layout( QSize( targetRect.width(), targetRect.height() ) );
layoutInfo( &layout ); layoutInfo( &layout );
painter->save(); painter->save();
painter->translate( targetRect.topLeft() ); painter->translate( targetRect.topLeft() );
QPoint titlePos( layout.margins.left(), layout.margins.top() ); painter->setFont( this->font() );
QFontMetrics fontMetrics( this->font() );
QRect boundingRect = fontMetrics.boundingRect( targetRect, Qt::AlignLeft, m_title );
boundingRect.moveTo( titlePos );
painter->drawText( boundingRect, m_title );
std::vector<std::pair<QPoint, QString>> visibleTickLabels = visibleLabels( layout ); QPoint titlePos( layout.margins.left(), layout.margins.top() );
{
painter->save();
QTextDocument td;
td.setDefaultFont( this->font() );
td.setHtml( m_title );
td.drawContents( painter );
painter->restore();
}
std::vector<std::pair<QRect, QString>> visibleTickLabels = visibleLabels( layout );
for ( auto tickLabel : visibleTickLabels ) for ( auto tickLabel : visibleTickLabels )
{ {
painter->drawText( tickLabel.first, tickLabel.second ); painter->save();
painter->translate( tickLabel.first.topLeft() );
QTextDocument td;
td.setDefaultFont( this->font() );
td.setPlainText( tickLabel.second );
td.drawContents( painter );
painter->restore();
} }
// Render color bar as one colored rectangle per color interval // Render color bar as one colored rectangle per color interval
@@ -139,43 +160,22 @@ void RiuAbstractLegendFrame::paintEvent( QPaintEvent* e )
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<std::pair<QPoint, QString>> RiuAbstractLegendFrame::visibleLabels( const LayoutInfo& layout ) const std::vector<std::pair<QRect, QString>> RiuAbstractLegendFrame::visibleLabels( const LayoutInfo& layout ) const
{ {
const int textX = layout.tickEndX + layout.tickTextLeadSpace; std::vector<std::pair<QRect, QString>> visibleTickLabels;
const double overlapTolerance = 1.2 * layout.charHeight; QRect lastRect;
int lastVisibleTextY = 0;
std::vector<std::pair<QPoint, QString>> visibleTickLabels;
int numLabels = labelCount(); int numLabels = labelCount();
for ( int i = 0; i < numLabels; i++ ) for ( int i = 0; i < numLabels; i++ )
{ {
int textY = labelPixelPosY( layout, i ); QRect rect = labelRect( layout, i );
// Always draw first and last tick label. For all others, skip drawing if text ends up if ( !lastRect.isEmpty() && rect.intersects( lastRect ) ) continue;
// 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(); QString valueString = label( i );
lastRect = rect;
if ( std::fabs( static_cast<double>( lastTickY - textY ) ) < overlapTolerance ) visibleTickLabels.push_back( {rect, valueString} );
{
continue;
}
}
QString valueString = label( numLabels - i - 1 );
QPoint pos( textX, textY );
lastVisibleTextY = textY;
visibleTickLabels.push_back( {pos, valueString} );
} }
return visibleTickLabels; return visibleTickLabels;
} }

View File

@@ -65,12 +65,12 @@ protected:
}; };
void paintEvent( QPaintEvent* e ) override; void paintEvent( QPaintEvent* e ) override;
std::vector<std::pair<QPoint, QString>> visibleLabels( const LayoutInfo& layout ) const; std::vector<std::pair<QRect, QString>> visibleLabels( const LayoutInfo& layout ) const;
private: private:
virtual void layoutInfo( LayoutInfo* layout ) const = 0; virtual void layoutInfo( LayoutInfo* layout ) const = 0;
virtual QString label( int index ) const = 0; virtual QString label( int index ) const = 0;
virtual int labelPixelPosY( const LayoutInfo& layout, int index ) const = 0; virtual QRect labelRect( const LayoutInfo& layout, int index ) const = 0;
virtual int labelCount() const = 0; virtual int labelCount() const = 0;
virtual int rectCount() const = 0; virtual int rectCount() const = 0;

View File

@@ -17,6 +17,10 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
#include "RiuAbstractOverlayContentFrame.h" #include "RiuAbstractOverlayContentFrame.h"
#include "RiaApplication.h"
#include "RiaFontCache.h"
#include "RiaPreferences.h"
#include <QLabel> #include <QLabel>
#include <QPainter> #include <QPainter>
#include <QTextDocument> #include <QTextDocument>
@@ -42,9 +46,13 @@ RiuTextOverlayContentFrame::RiuTextOverlayContentFrame( QWidget* parent /*= null
: RiuAbstractOverlayContentFrame( parent ) : RiuAbstractOverlayContentFrame( parent )
{ {
QVBoxLayout* layout = new QVBoxLayout( this ); QVBoxLayout* layout = new QVBoxLayout( this );
layout->setContentsMargins( 8, 8, 8, 8 ); layout->setContentsMargins( 4, 4, 4, 4 );
m_textLabel = new QLabel; m_textLabel = new QLabel;
layout->addWidget( m_textLabel ); layout->addWidget( m_textLabel );
QFont font = m_textLabel->font();
font.setPointSize( RiaApplication::instance()->preferences()->defaultPlotFontSize() );
m_textLabel->setFont( font );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -65,6 +73,7 @@ void RiuTextOverlayContentFrame::renderTo( QPainter* painter, const QRect& targe
painter->setFont( m_textLabel->font() ); painter->setFont( m_textLabel->font() );
QTextDocument td; QTextDocument td;
td.setDefaultFont( m_textLabel->font() );
td.setHtml( m_textLabel->text() ); td.setHtml( m_textLabel->text() );
td.drawContents( painter ); td.drawContents( painter );

View File

@@ -31,7 +31,7 @@ void RiuCategoryLegendFrame::layoutInfo( LayoutInfo* layout ) const
layout->charHeight = fontMetrics.height(); layout->charHeight = fontMetrics.height();
layout->charAscent = fontMetrics.ascent(); layout->charAscent = fontMetrics.ascent();
layout->lineSpacing = ( fontMetrics.lineSpacing() * 3 ) / 2; layout->lineSpacing = fontMetrics.lineSpacing();
layout->margins = QMargins( 8, 8, 8, 8 ); layout->margins = QMargins( 8, 8, 8, 8 );
layout->tickTextLeadSpace = 5; layout->tickTextLeadSpace = 5;
@@ -96,13 +96,13 @@ void RiuCategoryLegendFrame::renderRect( QPainter* painter, const LayoutInfo& la
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
int RiuCategoryLegendFrame::labelPixelPosY( const LayoutInfo& layout, int index ) const QRect RiuCategoryLegendFrame::labelRect( const LayoutInfo& layout, int index ) const
{ {
float categoryHeight = static_cast<float>( layout.colorBarRect.height() ) / labelCount(); float categoryHeight = static_cast<float>( layout.colorBarRect.height() ) / labelCount();
int textY = static_cast<int>( layout.colorBarRect.top() + index * categoryHeight + categoryHeight / 2 ); const int posX = layout.tickEndX + layout.tickTextLeadSpace;
int posY = static_cast<int>( layout.colorBarRect.bottom() - index * categoryHeight );
int offset = layout.charAscent - static_cast<int>( std::ceil( layout.charHeight / 2.0 ) ); int height = std::max( (int)categoryHeight, layout.charHeight );
QString labelI = this->label( index );
textY += offset; int width = this->fontMetrics().boundingRect( labelI ).width();
return textY; return QRect( posX, posY - height, width, height );
} }

View File

@@ -45,7 +45,7 @@ private:
int labelCount() const override; int labelCount() const override;
int rectCount() const override; int rectCount() const override;
void renderRect( QPainter* painter, const LayoutInfo& layout, int rectIndex ) const override; void renderRect( QPainter* painter, const LayoutInfo& layout, int rectIndex ) const override;
int labelPixelPosY( const LayoutInfo& layout, int index ) const override; QRect labelRect( const LayoutInfo& layout, int index ) const override;
private: private:
cvf::cref<caf::CategoryMapper> m_categoryMapper; cvf::cref<caf::CategoryMapper> m_categoryMapper;

View File

@@ -145,14 +145,14 @@ void RiuQwtPlotWidget::setAxisFontsAndAlignment( QwtPlot::Axis axis,
{ {
// Axis number font // Axis number font
QFont axisFont = this->axisFont( axis ); QFont axisFont = this->axisFont( axis );
axisFont.setPointSize( valueFontSize ); axisFont.setPixelSize( valueFontSize );
axisFont.setBold( false ); axisFont.setBold( false );
this->setAxisFont( axis, axisFont ); this->setAxisFont( axis, axisFont );
// Axis title font // Axis title font
QwtText axisTitle = this->axisTitle( axis ); QwtText axisTitle = this->axisTitle( axis );
QFont axisTitleFont = axisTitle.font(); QFont axisTitleFont = axisTitle.font();
axisTitleFont.setPointSize( titleFontSize ); axisTitleFont.setPixelSize( titleFontSize );
axisTitleFont.setBold( titleBold ); axisTitleFont.setBold( titleBold );
axisTitle.setFont( axisTitleFont ); axisTitle.setFont( axisTitleFont );
axisTitle.setRenderFlags( alignment ); axisTitle.setRenderFlags( alignment );
@@ -617,7 +617,7 @@ void RiuQwtPlotWidget::renderTo( QPainter* painter, const QRect& targetRect, dou
QRectF canvasRect = this->plotLayout()->canvasRect(); QRectF canvasRect = this->plotLayout()->canvasRect();
QPoint canvasTopLeftInPlotCoords( canvasRect.topLeft().x() * scaling, canvasRect.topLeft().y() * scaling ); QPoint canvasTopLeftInPlotCoords( canvasRect.topLeft().x() * scaling, canvasRect.topLeft().y() * scaling );
QPoint canvasBottomRightInPlotCoords( canvasRect.bottomRight().x() * scaling, canvasRect.bottomRight().y() * scaling ); QPoint canvasBottomRightInPlotCoords( canvasRect.bottomRight().x(), canvasRect.bottomRight().y() );
QPoint canvasTopLeftInWindowCoords = canvasTopLeftInPlotCoords + plotTopLeftInWindowCoords; QPoint canvasTopLeftInWindowCoords = canvasTopLeftInPlotCoords + plotTopLeftInWindowCoords;
QPoint canvasBottomRightInWindowCoords = canvasBottomRightInPlotCoords + plotTopLeftInWindowCoords; QPoint canvasBottomRightInWindowCoords = canvasBottomRightInPlotCoords + plotTopLeftInWindowCoords;
@@ -641,14 +641,15 @@ void RiuQwtPlotWidget::renderTo( QPainter* painter, const QRect& targetRect, dou
QSize actualSize = desiredSize.expandedTo( minimumSize ); QSize actualSize = desiredSize.expandedTo( minimumSize );
overlayRect.moveTo( overlayTopLeftInWindowCoords ); overlayRect.moveTo( overlayTopLeftInWindowCoords );
overlayRect.setSize( actualSize ); overlayRect.setSize( actualSize );
/* QPoint overlayBottomRightInWindowCoords = overlayRect.bottomRight();
QPoint overlayBottomRightInWindowCoords = overlayRect.bottomRight();
overlayBottomRightInWindowCoords.setX( overlayBottomRightInWindowCoords.setX(
std::min( overlayBottomRightInWindowCoords.x(), std::min( overlayBottomRightInWindowCoords.x(),
canvasBottomRightInPlotCoords.x() - (int)scaling * m_overlayMargins ) ); canvasBottomRightInWindowCoords.x() - (int)scaling * m_overlayMargins ) );
overlayBottomRightInWindowCoords.setY( overlayBottomRightInWindowCoords.setY(
std::min( overlayBottomRightInWindowCoords.y(), std::min( overlayBottomRightInWindowCoords.y(),
canvasBottomRightInPlotCoords.y() - (int)scaling * m_overlayMargins ) ); canvasBottomRightInWindowCoords.y() - (int)scaling * m_overlayMargins ) );
overlayRect.setBottomRight( overlayBottomRightInWindowCoords ); */ overlayRect.moveBottomRight( overlayBottomRightInWindowCoords );
overlayFrame->renderTo( painter, overlayRect ); overlayFrame->renderTo( painter, overlayRect );
} }
} }
@@ -784,26 +785,6 @@ void RiuQwtPlotWidget::updateOverlayFrameLayout()
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::scaleFonts( double scalingFactor )
{
for ( int axisId = static_cast<int>( QwtPlot::yLeft ); axisId < static_cast<int>( axisCnt ); ++axisId )
{
QFont axisFont = this->axisFont( axisId );
axisFont.setPointSize( axisFont.pointSize() * scalingFactor );
this->setAxisFont( axisId, axisFont );
// Axis title font
QwtText axisTitle = this->axisTitle( axisId );
QFont axisTitleFont = axisTitle.font();
axisTitleFont.setPointSize( axisTitleFont.pointSize() * scalingFactor );
axisTitle.setFont( axisTitleFont );
this->setAxisTitle( axisId, axisTitle );
}
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@@ -139,8 +139,6 @@ private:
void updateOverlayFrameLayout(); void updateOverlayFrameLayout();
void scaleFonts( double scalingFactor );
private: private:
caf::PdmPointer<RimPlot> m_plotDefinition; caf::PdmPointer<RimPlot> m_plotDefinition;
QPoint m_clickPosition; QPoint m_clickPosition;

View File

@@ -72,7 +72,7 @@ void RiuScalarMapperLegendFrame::layoutInfo( LayoutInfo* layout ) const
layout->charHeight = fontMetrics.height(); layout->charHeight = fontMetrics.height();
layout->charAscent = fontMetrics.ascent(); layout->charAscent = fontMetrics.ascent();
layout->lineSpacing = ( fontMetrics.lineSpacing() * 3 ) / 2; layout->lineSpacing = fontMetrics.lineSpacing();
layout->margins = QMargins( 8, 8, 8, 8 ); layout->margins = QMargins( 8, 8, 8, 8 );
layout->tickTextLeadSpace = 5; layout->tickTextLeadSpace = 5;
@@ -194,9 +194,14 @@ void RiuScalarMapperLegendFrame::renderRect( QPainter* painter, const LayoutInfo
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
int RiuScalarMapperLegendFrame::labelPixelPosY( const LayoutInfo& layout, int index ) const QRect RiuScalarMapperLegendFrame::labelRect( const LayoutInfo& layout, int index ) const
{ {
int indexFromBottom = labelCount() - index - 1; const int posX = layout.tickEndX + layout.tickTextLeadSpace;
int offset = layout.charAscent - static_cast<int>( std::ceil( layout.charHeight / 2.0 ) );
return layout.colorBarRect.bottom() - layout.tickYPixelPos[indexFromBottom] + offset; int posY = layout.colorBarRect.bottom() - layout.tickYPixelPos[index];
int posYp1 = layout.colorBarRect.bottom() - layout.tickYPixelPos[index + 1];
QString labelI = this->label( index );
int width = this->fontMetrics().boundingRect( labelI ).width() + 4;
int height = std::min( layout.lineSpacing, std::abs( posY - posYp1 ) );
return QRect( posX, posY - height / 2 - layout.charAscent / 2, width, height );
} }

View File

@@ -52,7 +52,7 @@ private:
int labelCount() const override; int labelCount() const override;
int rectCount() const override; int rectCount() const override;
void renderRect( QPainter* painter, const LayoutInfo& layout, int rectIndex ) const override; void renderRect( QPainter* painter, const LayoutInfo& layout, int rectIndex ) const override;
int labelPixelPosY( const LayoutInfo& layout, int index ) const override; QRect labelRect( const LayoutInfo& layout, int index ) const override;
private: private:
cvf::cref<cvf::ScalarMapper> m_scalarMapper; cvf::cref<cvf::ScalarMapper> m_scalarMapper;