qwt_polar_layout.cpp
/******************************************************************************
* QwtPolar Widget Library
* Copyright (C) 2008 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_polar_layout.h"
#include "qwt_polar_plot.h"
#include "qwt_polar_canvas.h"
#include "qwt_text.h"
#include "qwt_text_label.h"
#include "qwt_legend.h"
class QwtPolarLayout::LayoutData
{
public:
void init( const QwtPolarPlot*, const QRectF& rect );
struct t_legendData
{
int frameWidth;
int hScrollExtent;
int vScrollExtent;
QSizeF hint;
} legend;
struct t_titleData
{
QwtText text;
int frameWidth;
} title;
struct t_canvasData
{
int frameWidth;
} canvas;
};
void QwtPolarLayout::LayoutData::init(
const QwtPolarPlot* plot, const QRectF& rect )
{
// legend
if ( plot->plotLayout()->legendPosition() != QwtPolarPlot::ExternalLegend
&& plot->legend() )
{
legend.frameWidth = plot->legend()->frameWidth();
legend.hScrollExtent =
plot->legend()->scrollExtent( Qt::Horizontal );
legend.vScrollExtent =
plot->legend()->scrollExtent( Qt::Vertical );
const QSizeF hint = plot->legend()->sizeHint();
double w = qMin( hint.width(), rect.width() );
double h = plot->legend()->heightForWidth( w );
if ( h == 0.0 )
h = hint.height();
if ( h > rect.height() )
w += legend.hScrollExtent;
legend.hint = QSizeF( w, h );
}
// title
title.frameWidth = 0;
title.text = QwtText();
if ( plot->titleLabel() )
{
const QwtTextLabel* label = plot->titleLabel();
title.text = label->text();
if ( !( title.text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) )
title.text.setFont( label->font() );
title.frameWidth = plot->titleLabel()->frameWidth();
}
// canvas
canvas.frameWidth = plot->canvas()->frameWidth();
}
class QwtPolarLayout::PrivateData
{
public:
PrivateData()
: margin( 0 )
, spacing( 0 )
{
}
QRectF titleRect;
QRectF legendRect;
QRectF canvasRect;
QwtPolarLayout::LayoutData layoutData;
QwtPolarPlot::LegendPosition legendPos;
double legendRatio;
unsigned int margin;
unsigned int spacing;
};
QwtPolarLayout::QwtPolarLayout()
{
m_data = new PrivateData;
setLegendPosition( QwtPolarPlot::BottomLegend );
invalidate();
}
QwtPolarLayout::~QwtPolarLayout()
{
delete m_data;
}
void QwtPolarLayout::setLegendPosition(
QwtPolarPlot::LegendPosition pos, double ratio )
{
if ( ratio > 1.0 )
ratio = 1.0;
switch( pos )
{
case QwtPolarPlot::TopLegend:
case QwtPolarPlot::BottomLegend:
{
if ( ratio <= 0.0 )
ratio = 0.33;
m_data->legendRatio = ratio;
m_data->legendPos = pos;
break;
}
case QwtPolarPlot::LeftLegend:
case QwtPolarPlot::RightLegend:
{
if ( ratio <= 0.0 )
ratio = 0.5;
m_data->legendRatio = ratio;
m_data->legendPos = pos;
break;
}
case QwtPolarPlot::ExternalLegend:
{
m_data->legendRatio = ratio; // meaningless
m_data->legendPos = pos;
break;
}
default:
break;
}
}
void QwtPolarLayout::setLegendPosition( QwtPolarPlot::LegendPosition pos )
{
setLegendPosition( pos, 0.0 );
}
QwtPolarPlot::LegendPosition QwtPolarLayout::legendPosition() const
{
return m_data->legendPos;
}
void QwtPolarLayout::setLegendRatio( double ratio )
{
setLegendPosition( legendPosition(), ratio );
}
double QwtPolarLayout::legendRatio() const
{
return m_data->legendRatio;
}
const QRectF& QwtPolarLayout::titleRect() const
{
return m_data->titleRect;
}
const QRectF& QwtPolarLayout::legendRect() const
{
return m_data->legendRect;
}
const QRectF& QwtPolarLayout::canvasRect() const
{
return m_data->canvasRect;
}
void QwtPolarLayout::invalidate()
{
m_data->titleRect = m_data->legendRect = m_data->canvasRect = QRect();
}
QRectF QwtPolarLayout::layoutLegend( Options options, QRectF& rect ) const
{
const QSizeF hint( m_data->layoutData.legend.hint );
int dim;
if ( m_data->legendPos == QwtPolarPlot::LeftLegend
|| m_data->legendPos == QwtPolarPlot::RightLegend )
{
// We don't allow vertical legends to take more than
// half of the available space.
dim = qMin( double( hint.width() ), rect.width() * m_data->legendRatio );
if ( !( options & IgnoreScrollbars ) )
{
if ( hint.height() > rect.height() )
{
// The legend will need additional
// space for the vertical scrollbar.
dim += m_data->layoutData.legend.hScrollExtent;
}
}
}
else
{
dim = qMin( double( hint.height() ), rect.height() * m_data->legendRatio );
dim = qMax( dim, m_data->layoutData.legend.vScrollExtent );
}
QRectF legendRect = rect;
switch( m_data->legendPos )
{
case QwtPolarPlot::LeftLegend:
{
legendRect.setWidth( dim );
rect.setLeft( legendRect.right() );
break;
}
case QwtPolarPlot::RightLegend:
{
legendRect.setX( rect.right() - dim + 1 );
legendRect.setWidth( dim );
rect.setRight( legendRect.left() );
break;
}
case QwtPolarPlot::TopLegend:
{
legendRect.setHeight( dim );
rect.setTop( legendRect.bottom() );
break;
}
case QwtPolarPlot::BottomLegend:
{
legendRect.setY( rect.bottom() - dim + 1 );
legendRect.setHeight( dim );
rect.setBottom( legendRect.top() );
break;
}
case QwtPolarPlot::ExternalLegend:
break;
}
return legendRect;
}
void QwtPolarLayout::activate( const QwtPolarPlot* plot,
const QRectF& boundingRect, Options options )
{
invalidate();
QRectF rect( boundingRect ); // undistributed rest of the plot rect
rect.adjust( m_data->margin, m_data->margin,
-m_data->margin, -m_data->margin );
// We extract all layout relevant data from the widgets
// and save them to m_data->layoutData.
m_data->layoutData.init( plot, rect );
if ( !( options & IgnoreLegend )
&& m_data->legendPos != QwtPolarPlot::ExternalLegend
&& plot->legend() && !plot->legend()->isEmpty() )
{
m_data->legendRect = layoutLegend( options, rect );
if ( m_data->layoutData.legend.frameWidth &&
!( options & IgnoreFrames ) )
{
// In case of a frame we have to insert a spacing.
// Otherwise the leading of the font separates
// legend and scale/canvas
switch( m_data->legendPos )
{
case QwtPolarPlot::LeftLegend:
rect.setLeft( rect.left() + m_data->spacing );
break;
case QwtPolarPlot::RightLegend:
rect.setRight( rect.right() - m_data->spacing );
break;
case QwtPolarPlot::TopLegend:
rect.setTop( rect.top() + m_data->spacing );
break;
case QwtPolarPlot::BottomLegend:
rect.setBottom( rect.bottom() - m_data->spacing );
break;
case QwtPolarPlot::ExternalLegend:
break; // suppress compiler warning
}
}
}
if ( !( options & IgnoreTitle ) &&
!m_data->layoutData.title.text.isEmpty() )
{
int h = m_data->layoutData.title.text.heightForWidth( rect.width() );
if ( !( options & IgnoreFrames ) )
h += 2 * m_data->layoutData.title.frameWidth;
m_data->titleRect = QRectF( rect.x(), rect.y(), rect.width(), h );
// subtract title
rect.setTop( rect.top() + h + m_data->spacing );
}
if ( plot->zoomPos().radius() > 0.0 || plot->zoomFactor() < 1.0 )
{
// In zoomed state we have no idea about the geometry that
// is best for the plot. So we use the complete rectangle
// accepting, that there might a lot of space wasted
// around the plot.
m_data->canvasRect = rect;
}
else
{
// In full state we know, that we want
// to display something circular.
const int dim = qMin( rect.width(), rect.height() );
m_data->canvasRect.setX( rect.center().x() - dim / 2 );
m_data->canvasRect.setY( rect.y() );
m_data->canvasRect.setSize( QSize( dim, dim ) );
}
if ( !m_data->legendRect.isEmpty() )
{
if ( m_data->legendPos == QwtPolarPlot::LeftLegend
|| m_data->legendPos == QwtPolarPlot::RightLegend )
{
// We prefer to align the legend to the canvas - not to
// the complete plot - if possible.
if ( m_data->layoutData.legend.hint.height()
< m_data->canvasRect.height() )
{
m_data->legendRect.setY( m_data->canvasRect.y() );
m_data->legendRect.setHeight( m_data->canvasRect.height() );
}
}
}
}
QwtAbstractLegend::scrollExtent
virtual int scrollExtent(Qt::Orientation) const
Definition: qwt_abstract_legend.cpp:35
QwtAbstractLegend::isEmpty
virtual bool isEmpty() const =0
QwtPointPolar::radius
double radius() const
Returns the radius.
Definition: qwt_point_polar.h:102
QwtPolarLayout::legendRect
const QRectF & legendRect() const
Definition: qwt_polar_layout.cpp:239
QwtPolarLayout::~QwtPolarLayout
virtual ~QwtPolarLayout()
Destructor.
Definition: qwt_polar_layout.cpp:123
QwtPolarLayout::layoutLegend
QRectF layoutLegend(Options options, QRectF &) const
Definition: qwt_polar_layout.cpp:269
QwtPolarLayout::setLegendRatio
void setLegendRatio(double ratio)
Definition: qwt_polar_layout.cpp:210
QwtPolarLayout::legendRatio
double legendRatio() const
Definition: qwt_polar_layout.cpp:219
QwtPolarLayout::setLegendPosition
void setLegendPosition(QwtPolarPlot::LegendPosition pos, double ratio)
Specify the position of the legend.
Definition: qwt_polar_layout.cpp:141
QwtPolarLayout::invalidate
virtual void invalidate()
Definition: qwt_polar_layout.cpp:257
QwtPolarLayout::legendPosition
QwtPolarPlot::LegendPosition legendPosition() const
Definition: qwt_polar_layout.cpp:196
QwtPolarLayout::activate
virtual void activate(const QwtPolarPlot *, const QRectF &rect, Options options=Options())
Recalculate the geometry of all components.
Definition: qwt_polar_layout.cpp:344
QwtPolarLayout::QwtPolarLayout
QwtPolarLayout()
Constructor.
Definition: qwt_polar_layout.cpp:114
QwtPolarLayout::titleRect
const QRectF & titleRect() const
Definition: qwt_polar_layout.cpp:229
QwtPolarLayout::IgnoreLegend
@ IgnoreLegend
Ignore the legend.
Definition: qwt_polar_layout.h:40
QwtPolarLayout::IgnoreScrollbars
@ IgnoreScrollbars
Ignore the dimension of the scrollbars.
Definition: qwt_polar_layout.h:31
QwtPolarLayout::IgnoreTitle
@ IgnoreTitle
Ignore the title.
Definition: qwt_polar_layout.h:37
QwtPolarLayout::IgnoreFrames
@ IgnoreFrames
Ignore all frames.
Definition: qwt_polar_layout.h:34
QwtPolarLayout::Options
QFlags< Option > Options
Definition: qwt_polar_layout.h:43
QwtPolarLayout::canvasRect
const QRectF & canvasRect() const
Definition: qwt_polar_layout.cpp:248
QwtPolarPlot
A plotting widget, displaying a polar coordinate system.
Definition: qwt_polar_plot.h:47
QwtPolarPlot::plotLayout
QwtPolarLayout * plotLayout()
Definition: qwt_polar_plot.cpp:1274
QwtPolarPlot::zoomPos
QwtPointPolar zoomPos() const
Definition: qwt_polar_plot.cpp:682
QwtPolarPlot::zoomFactor
double zoomFactor() const
Definition: qwt_polar_plot.cpp:691
QwtPolarPlot::legend
QwtAbstractLegend * legend()
Definition: qwt_polar_plot.cpp:286
QwtPolarPlot::canvas
QwtPolarCanvas * canvas()
Definition: qwt_polar_plot.cpp:914
QwtPolarPlot::LegendPosition
LegendPosition
Definition: qwt_polar_plot.h:60
QwtPolarPlot::BottomLegend
@ BottomLegend
The legend will be below the canvas.
Definition: qwt_polar_plot.h:68
QwtPolarPlot::LeftLegend
@ LeftLegend
The legend will be left from the canvas.
Definition: qwt_polar_plot.h:62
QwtPolarPlot::ExternalLegend
@ ExternalLegend
Definition: qwt_polar_plot.h:81
QwtPolarPlot::TopLegend
@ TopLegend
The legend will be between canvas and title.
Definition: qwt_polar_plot.h:71
QwtPolarPlot::RightLegend
@ RightLegend
The legend will be right from the canvas.
Definition: qwt_polar_plot.h:65
QwtPolarPlot::titleLabel
QwtTextLabel * titleLabel()
Definition: qwt_polar_plot.cpp:153
QwtText
A class representing a text.
Definition: qwt_text.h:52
QwtText::PaintUsingTextFont
@ PaintUsingTextFont
The text has an individual font.
Definition: qwt_text.h:117
QwtText::text
QString text() const
Definition: qwt_text.cpp:289
QwtTextLabel
A Widget which displays a QwtText.
Definition: qwt_text_label.h:27
QwtTextLabel::text
const QwtText & text() const
Return the text.
Definition: qwt_text_label.cpp:118