1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2002 Uwe Rathmann
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the Qwt License, Version 1.0
8
*****************************************************************************/
13
#if QT_VERSION < 0x040000
14
#include <qpaintdevicemetrics.h>
16
#include <qpaintengine.h>
18
#include "qwt_painter.h"
19
#include "qwt_legend_item.h"
21
#include "qwt_plot_canvas.h"
22
#include "qwt_plot_layout.h"
23
#include "qwt_legend.h"
24
#include "qwt_dyngrid_layout.h"
25
#include "qwt_scale_widget.h"
26
#include "qwt_scale_engine.h"
28
#include "qwt_text_label.h"
32
\brief Print the plot to a \c QPaintDevice (\c QPrinter)
33
This function prints the contents of a QwtPlot instance to
34
\c QPaintDevice object. The size is derived from its device
37
\param paintDev device to paint on, often a printer
38
\param pfilter print filter
40
\sa QwtPlotPrintFilter
43
void QwtPlot::print(QPaintDevice &paintDev,
44
const QwtPlotPrintFilter &pfilter) const
46
#if QT_VERSION < 0x040000
47
QPaintDeviceMetrics mpr(&paintDev);
51
int w = paintDev.width();
52
int h = paintDev.height();
55
QRect rect(0, 0, w, h);
56
double aspect = double(rect.width())/double(rect.height());
58
rect.setHeight(int(aspect*rect.width()));
60
QPainter p(&paintDev);
61
print(&p, rect, pfilter);
65
\brief Paint the plot into a given rectangle.
66
Paint the contents of a QwtPlot instance into a given rectangle.
68
\param painter Painter
69
\param plotRect Bounding rectangle
70
\param pfilter Print filter
71
\sa QwtPlotPrintFilter
73
void QwtPlot::print(QPainter *painter, const QRect &plotRect,
74
const QwtPlotPrintFilter &pfilter) const
78
if ( painter == 0 || !painter->isActive() ||
79
!plotRect.isValid() || size().isNull() )
85
PDF: In Qt4 ( <= 4.3.2 ) the scales are painted in gray instead of
86
black. See http://trolltech.com/developer/task-tracker/index_html?id=184671&method=entry
87
The dummy lines below work around the problem.
89
const QPen pen = painter->pen();
90
painter->setPen(QPen(Qt::black, 1));
94
// All paint operations need to be scaled according to
95
// the paint device metrics.
97
QwtPainter::setMetricsMap(this, painter->device());
98
const QwtMetricsMap &metricsMap = QwtPainter::metricsMap();
100
// It is almost impossible to integrate into the Qt layout
101
// framework, when using different fonts for printing
102
// and screen. To avoid writing different and Qt unconform
103
// layout engines we change the widget attributes, print and
104
// reset the widget attributes again. This way we produce a lot of
105
// useless layout events ...
107
pfilter.apply((QwtPlot *)this);
109
int baseLineDists[QwtPlot::axisCnt];
110
if ( pfilter.options() & QwtPlotPrintFilter::PrintFrameWithScales )
112
for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
114
QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
117
baseLineDists[axisId] = scaleWidget->margin();
118
scaleWidget->setMargin(0);
122
// Calculate the layout for the print.
124
int layoutOptions = QwtPlotLayout::IgnoreScrollbars
125
| QwtPlotLayout::IgnoreFrames;
126
if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) )
127
layoutOptions |= QwtPlotLayout::IgnoreMargin;
128
if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) )
129
layoutOptions |= QwtPlotLayout::IgnoreLegend;
131
((QwtPlot *)this)->plotLayout()->activate(this,
132
QwtPainter::metricsMap().deviceToLayout(plotRect),
135
if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle)
136
&& (!titleLabel()->text().isEmpty()))
138
printTitle(painter, plotLayout()->titleRect());
141
if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend)
142
&& legend() && !legend()->isEmpty() )
144
printLegend(painter, plotLayout()->legendRect());
147
for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
149
QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
152
int baseDist = scaleWidget->margin();
154
int startDist, endDist;
155
scaleWidget->getBorderDistHint(startDist, endDist);
157
printScale(painter, axisId, startDist, endDist,
158
baseDist, plotLayout()->scaleRect(axisId));
162
QRect canvasRect = plotLayout()->canvasRect();
165
The border of the bounding rect needs to ba scaled to
166
layout coordinates, so that it is aligned to the axes
168
QRect boundingRect( canvasRect.left() - 1, canvasRect.top() - 1,
169
canvasRect.width() + 2, canvasRect.height() + 2);
170
boundingRect = metricsMap.layoutToDevice(boundingRect);
171
boundingRect.setWidth(boundingRect.width() - 1);
172
boundingRect.setHeight(boundingRect.height() - 1);
174
canvasRect = metricsMap.layoutToDevice(canvasRect);
176
// When using QwtPainter all sizes where computed in pixel
177
// coordinates and scaled by QwtPainter later. This limits
178
// the precision to screen resolution. A better solution
179
// is to scale the maps and print in unlimited resolution.
181
QwtScaleMap map[axisCnt];
182
for (axisId = 0; axisId < axisCnt; axisId++)
184
map[axisId].setTransformation(axisScaleEngine(axisId)->transformation());
186
const QwtScaleDiv &scaleDiv = *axisScaleDiv(axisId);
187
map[axisId].setScaleInterval(scaleDiv.lBound(), scaleDiv.hBound());
190
if ( axisEnabled(axisId) )
192
const int sDist = axisWidget(axisId)->startBorderDist();
193
const int eDist = axisWidget(axisId)->endBorderDist();
194
const QRect &scaleRect = plotLayout()->scaleRect(axisId);
196
if ( axisId == xTop || axisId == xBottom )
198
from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist);
199
to = metricsMap.layoutToDeviceX(scaleRect.right() + 1 - eDist);
203
from = metricsMap.layoutToDeviceY(scaleRect.bottom() + 1 - eDist );
204
to = metricsMap.layoutToDeviceY(scaleRect.top() + sDist);
209
const int margin = plotLayout()->canvasMargin(axisId);
210
if ( axisId == yLeft || axisId == yRight )
212
from = metricsMap.layoutToDeviceX(canvasRect.bottom() - margin);
213
to = metricsMap.layoutToDeviceX(canvasRect.top() + margin);
217
from = metricsMap.layoutToDeviceY(canvasRect.left() + margin);
218
to = metricsMap.layoutToDeviceY(canvasRect.right() - margin);
221
map[axisId].setPaintXInterval(from, to);
224
// The canvas maps are already scaled.
225
QwtPainter::setMetricsMap(painter->device(), painter->device());
226
printCanvas(painter, boundingRect, canvasRect, map, pfilter);
227
QwtPainter::resetMetricsMap();
229
((QwtPlot *)this)->plotLayout()->invalidate();
231
// reset all widgets with their original attributes.
232
if ( pfilter.options() & QwtPlotPrintFilter::PrintFrameWithScales )
234
// restore the previous base line dists
236
for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
238
QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
240
scaleWidget->setMargin(baseLineDists[axisId]);
244
pfilter.reset((QwtPlot *)this);
250
Print the title into a given rectangle.
252
\param painter Painter
253
\param rect Bounding rectangle
256
void QwtPlot::printTitle(QPainter *painter, const QRect &rect) const
258
painter->setFont(titleLabel()->font());
261
#if QT_VERSION < 0x040000
262
titleLabel()->palette().color(
263
QPalette::Active, QColorGroup::Text);
265
titleLabel()->palette().color(
266
QPalette::Active, QPalette::Text);
269
painter->setPen(color);
270
titleLabel()->text().draw(painter, rect);
274
Print the legend into a given rectangle.
276
\param painter Painter
277
\param rect Bounding rectangle
280
void QwtPlot::printLegend(QPainter *painter, const QRect &rect) const
282
if ( !legend() || legend()->isEmpty() )
285
QLayout *l = legend()->contentsWidget()->layout();
286
if ( l == 0 || !l->inherits("QwtDynGridLayout") )
289
QwtDynGridLayout *legendLayout = (QwtDynGridLayout *)l;
291
uint numCols = legendLayout->columnsForWidth(rect.width());
292
#if QT_VERSION < 0x040000
293
QValueList<QRect> itemRects =
294
legendLayout->layoutItems(rect, numCols);
296
QList<QRect> itemRects =
297
legendLayout->layoutItems(rect, numCols);
302
#if QT_VERSION < 0x040000
303
QLayoutIterator layoutIterator = legendLayout->iterator();
304
for ( QLayoutItem *item = layoutIterator.current();
305
item != 0; item = ++layoutIterator)
308
for ( int i = 0; i < legendLayout->count(); i++ )
310
QLayoutItem *item = legendLayout->itemAt(i);
312
QWidget *w = item->widget();
316
painter->setClipping(true);
317
QwtPainter::setClipRect(painter, itemRects[index]);
319
printLegendItem(painter, w, itemRects[index]);
328
Print the legend item into a given rectangle.
330
\param painter Painter
331
\param w Widget representing a legend item
332
\param rect Bounding rectangle
335
void QwtPlot::printLegendItem(QPainter *painter,
336
const QWidget *w, const QRect &rect) const
338
if ( w->inherits("QwtLegendItem") )
340
QwtLegendItem *item = (QwtLegendItem *)w;
342
painter->setFont(item->font());
343
item->drawItem(painter, rect);
348
\brief Paint a scale into a given rectangle.
349
Paint the scale into a given rectangle.
351
\param painter Painter
353
\param startDist Start border distance
354
\param endDist End border distance
355
\param baseDist Base distance
356
\param rect Bounding rectangle
359
void QwtPlot::printScale(QPainter *painter,
360
int axisId, int startDist, int endDist, int baseDist,
361
const QRect &rect) const
363
if (!axisEnabled(axisId))
366
const QwtScaleWidget *scaleWidget = axisWidget(axisId);
367
if ( scaleWidget->isColorBarEnabled()
368
&& scaleWidget->colorBarWidth() > 0)
370
const QwtMetricsMap map = QwtPainter::metricsMap();
372
QRect r = map.layoutToScreen(rect);
373
r.setWidth(r.width() - 1);
374
r.setHeight(r.height() - 1);
376
scaleWidget->drawColorBar(painter, scaleWidget->colorBarRect(r));
378
const int off = scaleWidget->colorBarWidth() + scaleWidget->spacing();
379
if ( scaleWidget->scaleDraw()->orientation() == Qt::Horizontal )
380
baseDist += map.screenToLayoutY(off);
382
baseDist += map.screenToLayoutX(off);
385
QwtScaleDraw::Alignment align;
392
x = rect.right() - baseDist;
393
y = rect.y() + startDist;
394
w = rect.height() - startDist - endDist;
395
align = QwtScaleDraw::LeftScale;
400
x = rect.left() + baseDist;
401
y = rect.y() + startDist;
402
w = rect.height() - startDist - endDist;
403
align = QwtScaleDraw::RightScale;
408
x = rect.left() + startDist;
409
y = rect.bottom() - baseDist;
410
w = rect.width() - startDist - endDist;
411
align = QwtScaleDraw::TopScale;
416
x = rect.left() + startDist;
417
y = rect.top() + baseDist;
418
w = rect.width() - startDist - endDist;
419
align = QwtScaleDraw::BottomScale;
426
scaleWidget->drawTitle(painter, align, rect);
429
painter->setFont(scaleWidget->font());
431
QPen pen = painter->pen();
432
pen.setWidth(scaleWidget->penWidth());
433
painter->setPen(pen);
435
QwtScaleDraw *sd = (QwtScaleDraw *)scaleWidget->scaleDraw();
436
const QPoint sdPos = sd->pos();
437
const int sdLength = sd->length();
442
#if QT_VERSION < 0x040000
443
sd->draw(painter, scaleWidget->palette().active());
445
QPalette palette = scaleWidget->palette();
446
palette.setCurrentColorGroup(QPalette::Active);
447
sd->draw(painter, palette);
449
// reset previous values
451
sd->setLength(sdLength);
457
Print the canvas into a given rectangle.
459
\param painter Painter
460
\param map Maps mapping between plot and paint device coordinates
461
\param boundingRect Bounding rectangle
462
\param canvasRect Canvas rectangle
463
\param pfilter Print filter
464
\sa QwtPlotPrintFilter
467
void QwtPlot::printCanvas(QPainter *painter,
468
const QRect &boundingRect, const QRect &canvasRect,
469
const QwtScaleMap map[axisCnt], const QwtPlotPrintFilter &pfilter) const
471
if ( pfilter.options() & QwtPlotPrintFilter::PrintBackground )
474
#if QT_VERSION >= 0x040000
475
bgBrush = canvas()->palette().brush(backgroundRole());
477
QColorGroup::ColorRole role =
478
QPalette::backgroundRoleFromMode( backgroundMode() );
479
bgBrush = canvas()->colorGroup().brush( role );
481
QRect r = boundingRect;
482
if ( !(pfilter.options() & QwtPlotPrintFilter::PrintFrameWithScales) )
485
#if QT_VERSION >= 0x040000
486
// Unfortunately the paint engines do no always the same
487
switch(painter->paintEngine()->type() )
489
case QPaintEngine::Raster:
490
case QPaintEngine::X11:
493
r.setWidth(r.width() - 1);
494
r.setHeight(r.height() - 1);
498
if ( painter->device()->isExtDev() )
500
r.setWidth(r.width() - 1);
501
r.setHeight(r.height() - 1);
506
QwtPainter::fillRect(painter, r, bgBrush);
509
if ( pfilter.options() & QwtPlotPrintFilter::PrintFrameWithScales )
512
painter->setPen(QPen(Qt::black));
513
painter->setBrush(QBrush(Qt::NoBrush));
514
QwtPainter::drawRect(painter, boundingRect);
518
painter->setClipping(true);
519
QwtPainter::setClipRect(painter, canvasRect);
521
drawItems(painter, canvasRect, map, pfilter);