/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 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
*****************************************************************************/
// vim: expandtab
#include <qscrollbar.h>
#include "qwt_text.h"
#include "qwt_text_label.h"
#include "qwt_plot_canvas.h"
#include "qwt_scale_widget.h"
#include "qwt_legend.h"
#include "qwt_plot_layout.h"
class QwtPlotLayout::LayoutData
{
public:
void init(const QwtPlot *, const QRect &rect);
struct t_legendData
{
int frameWidth;
int vScrollBarWidth;
int hScrollBarHeight;
QSize hint;
} legend;
struct t_titleData
{
QwtText text;
int frameWidth;
} title;
struct t_scaleData
{
bool isEnabled;
const QwtScaleWidget *scaleWidget;
QFont scaleFont;
int start;
int end;
int baseLineOffset;
int tickOffset;
int dimWithoutTitle;
} scale[QwtPlot::axisCnt];
struct t_canvasData
{
int frameWidth;
} canvas;
};
/*
Extract all layout relevant data from the plot components
*/
void QwtPlotLayout::LayoutData::init(const QwtPlot *plot, const QRect &rect)
{
// legend
if ( plot->plotLayout()->legendPosition() != QwtPlot::ExternalLegend
&& plot->legend() )
{
legend.frameWidth = plot->legend()->frameWidth();
legend.vScrollBarWidth =
plot->legend()->verticalScrollBar()->sizeHint().width();
legend.hScrollBarHeight =
plot->legend()->horizontalScrollBar()->sizeHint().height();
const QSize hint = plot->legend()->sizeHint();
int w = qwtMin(hint.width(), rect.width());
int h = plot->legend()->heightForWidth(w);
if ( h == 0 )
h = hint.height();
if ( h > rect.height() )
w += legend.vScrollBarWidth;
legend.hint = QSize(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();
}
// scales
for (int axis = 0; axis < QwtPlot::axisCnt; axis++ )
{
if ( plot->axisEnabled(axis) )
{
const QwtScaleWidget *scaleWidget = plot->axisWidget(axis);
scale[axis].isEnabled = true;
scale[axis].scaleWidget = scaleWidget;
scale[axis].scaleFont = scaleWidget->font();
scale[axis].start = scaleWidget->startBorderDist();
scale[axis].end = scaleWidget->endBorderDist();
scale[axis].baseLineOffset = scaleWidget->margin();
scale[axis].tickOffset = scaleWidget->margin();
if ( scaleWidget->scaleDraw()->hasComponent(
QwtAbstractScaleDraw::Ticks) )
{
scale[axis].tickOffset +=
(int)scaleWidget->scaleDraw()->majTickLength();
}
scale[axis].dimWithoutTitle = scaleWidget->dimForLength(
QWIDGETSIZE_MAX, scale[axis].scaleFont);
if ( !scaleWidget->title().isEmpty() )
{
scale[axis].dimWithoutTitle -=
scaleWidget->titleHeightForWidth(QWIDGETSIZE_MAX);
}
}
else
{
scale[axis].isEnabled = false;
scale[axis].start = 0;
scale[axis].end = 0;
scale[axis].baseLineOffset = 0;
scale[axis].tickOffset = 0;
scale[axis].dimWithoutTitle = 0;
}
}
// canvas
canvas.frameWidth = plot->canvas()->frameWidth();
}
class QwtPlotLayout::PrivateData
{
public:
PrivateData():
margin(0),
spacing(5),
alignCanvasToScales(false)
{
}
QRect titleRect;
QRect legendRect;
QRect scaleRect[QwtPlot::axisCnt];
QRect canvasRect;
QwtPlotLayout::LayoutData layoutData;
QwtPlot::LegendPosition legendPos;
double legendRatio;
unsigned int margin;
unsigned int spacing;
unsigned int canvasMargin[QwtPlot::axisCnt];
bool alignCanvasToScales;
};
/*!
\brief Constructor
*/
QwtPlotLayout::QwtPlotLayout()
{
d_data = new PrivateData;
setLegendPosition(QwtPlot::BottomLegend);
setCanvasMargin(4);
invalidate();
}
//! Destructor
QwtPlotLayout::~QwtPlotLayout()
{
delete d_data;
}
/*!
Change the margin of the plot. The margin is the space
around all components.
\param margin new margin
\sa margin(), setSpacing(),
QwtPlot::setMargin()
*/
void QwtPlotLayout::setMargin(int margin)
{
if ( margin < 0 )
margin = 0;
d_data->margin = margin;
}
/*!
\return margin
\sa setMargin(), spacing(), QwtPlot::margin()
*/
int QwtPlotLayout::margin() const
{
return d_data->margin;
}
/*!
Change a margin of the canvas. The margin is the space
above/below the scale ticks. A negative margin will
be set to -1, excluding the borders of the scales.
\param margin New margin
\param axis One of QwtPlot::Axis. Specifies where the position of the margin.
-1 means margin at all borders.
\sa canvasMargin()
\warning The margin will have no effect when alignCanvasToScales is true
*/
void QwtPlotLayout::setCanvasMargin(int margin, int axis)
{
if ( margin < -1 )
margin = -1;
if ( axis == -1 )
{
for (axis = 0; axis < QwtPlot::axisCnt; axis++)
d_data->canvasMargin[axis] = margin;
}
else if ( axis >= 0 || axis < QwtPlot::axisCnt )
d_data->canvasMargin[axis] = margin;
}
/*!
\return Margin around the scale tick borders
\sa setCanvasMargin()
*/
int QwtPlotLayout::canvasMargin(int axis) const
{
if ( axis < 0 || axis >= QwtPlot::axisCnt )
return 0;
return d_data->canvasMargin[axis];
}
/*!
Change the align-canvas-to-axis-scales setting. The canvas may:
- extend beyond the axis scale ends to maximize its size,
- align with the axis scale ends to control its size.
\param alignCanvasToScales New align-canvas-to-axis-scales setting
\sa setCanvasMargin()
\note In this context the term 'scale' means the backbone of a scale.
\warning In case of alignCanvasToScales == true canvasMargin will have
no effect
*/
void QwtPlotLayout::setAlignCanvasToScales(bool alignCanvasToScales)
{
d_data->alignCanvasToScales = alignCanvasToScales;
}
/*!
Return the align-canvas-to-axis-scales setting. The canvas may:
- extend beyond the axis scale ends to maximize its size
- align with the axis scale ends to control its size.
\return align-canvas-to-axis-scales setting
\sa setAlignCanvasToScales, setCanvasMargin()
\note In this context the term 'scale' means the backbone of a scale.
*/
bool QwtPlotLayout::alignCanvasToScales() const
{
return d_data->alignCanvasToScales;
}
/*!
Change the spacing of the plot. The spacing is the distance
between the plot components.
\param spacing new spacing
\sa setMargin(), spacing()
*/
void QwtPlotLayout::setSpacing(int spacing)
{
d_data->spacing = qwtMax(0, spacing);
}
/*!
\return spacing
\sa margin(), setSpacing()
*/
int QwtPlotLayout::spacing() const
{
return d_data->spacing;
}
/*!
\brief