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
*****************************************************************************/
12
#include <qpaintengine.h>
13
#include "qwt_painter.h"
15
#include "qwt_scale_engine.h"
16
#include "qwt_scale_div.h"
17
#include "qwt_round_scale_draw.h"
18
#include "qwt_round_scale_draw.h"
19
#include "qwt_radial_plot.h"
24
#if QT_VERSION >= 0x040000
25
static void setAntialiasing(QPainter *painter, bool on)
27
QPaintEngine *engine = painter->paintEngine();
28
if ( engine && engine->hasFeature(QPaintEngine::Antialiasing) )
29
painter->setRenderHint(QPainter::Antialiasing, on);
32
static void setAntialiasing(QPainter *, bool)
37
class QwtRadialPlot::ScaleData
60
QwtScaleEngine *scaleEngine;
61
QwtDoubleInterval zoomedInterval;
64
class QwtRadialPlot::PrivateData
67
QRegion::RegionType shape;
73
bool isAngleScaleVisible;
74
QwtRoundScaleDraw *angleScaleDraw;
76
ScaleData scaleData[ScaleCount];
79
QwtRadialPlot::QwtRadialPlot( QWidget *parent):
85
#if QT_VERSION < 0x040000
86
QwtRadialPlot::QwtRadialPlot( QWidget *parent, const char *name):
93
QwtRadialPlot::~QwtRadialPlot()
98
void QwtRadialPlot::setAutoReplot(bool enable)
100
d_data->autoReplot = enable;
103
bool QwtRadialPlot::autoReplot() const
105
return d_data->autoReplot;
108
void QwtRadialPlot::showAngleScale(bool enable)
110
if ( d_data->isAngleScaleVisible != enable )
112
d_data->isAngleScaleVisible = enable;
117
bool QwtRadialPlot::isAngleScaleVisible() const
119
return d_data->isAngleScaleVisible;
122
void QwtRadialPlot::setOrigin(double origin)
125
if ( d_data->origin != origin )
127
d_data->origin = origin;
132
double QwtRadialPlot::origin() const
134
return d_data->origin;
137
void QwtRadialPlot::setAngleScaleDraw(QwtRoundScaleDraw *scaleDraw)
139
if ( scaleDraw == NULL || scaleDraw == d_data->angleScaleDraw )
142
delete d_data->angleScaleDraw;
143
d_data->angleScaleDraw = scaleDraw;
147
const QwtRoundScaleDraw *QwtRadialPlot::angleScaleDraw() const
149
return d_data->angleScaleDraw;
152
QwtRoundScaleDraw *QwtRadialPlot::angleScaleDraw()
154
return d_data->angleScaleDraw;
157
void QwtRadialPlot::setScaleMaxMinor(int scaleId, int maxMinor)
159
if ( scaleId < 0 || scaleId >= ScaleCount )
164
if ( maxMinor > 100 )
167
ScaleData &scaleData = d_data->scaleData[scaleId];
169
if ( maxMinor != scaleData.maxMinor )
171
scaleData.maxMinor = maxMinor;
172
scaleData.scaleDiv.invalidate();
177
int QwtRadialPlot::scaleMaxMinor(int scaleId) const
179
if ( scaleId < 0 || scaleId >= ScaleCount )
182
return d_data->scaleData[scaleId].maxMinor;
185
void QwtRadialPlot::setScaleMaxMajor(int scaleId, int maxMajor)
187
if ( scaleId < 0 || scaleId >= ScaleCount )
192
if ( maxMajor > 1000 )
195
ScaleData &scaleData = d_data->scaleData[scaleId];
196
if ( maxMajor != scaleData.maxMinor )
198
scaleData.maxMajor = maxMajor;
199
scaleData.scaleDiv.invalidate();
204
int QwtRadialPlot::scaleMaxMajor(int scaleId) const
206
if ( scaleId < 0 || scaleId >= ScaleCount )
209
return d_data->scaleData[scaleId].maxMajor;
212
QwtScaleEngine *QwtRadialPlot::scaleEngine(int scaleId)
214
if ( scaleId < 0 || scaleId >= ScaleCount )
217
return d_data->scaleData[scaleId].scaleEngine;
220
const QwtScaleEngine *QwtRadialPlot::scaleEngine(int scaleId) const
222
if ( scaleId < 0 || scaleId >= ScaleCount )
225
return d_data->scaleData[scaleId].scaleEngine;
228
void QwtRadialPlot::setScaleEngine(int scaleId, QwtScaleEngine *scaleEngine)
230
if ( scaleId < 0 || scaleId >= ScaleCount )
233
ScaleData &scaleData = d_data->scaleData[scaleId];
234
if (scaleEngine == NULL || scaleEngine == scaleData.scaleEngine )
237
delete scaleData.scaleEngine;
238
scaleData.scaleEngine = scaleEngine;
240
scaleData.scaleDiv.invalidate();
245
void QwtRadialPlot::setScale(int scaleId,
246
double min, double max, double stepSize)
248
if ( scaleId < 0 || scaleId >= ScaleCount )
251
ScaleData &scaleData = d_data->scaleData[scaleId];
253
scaleData.scaleDiv.invalidate();
255
scaleData.minValue = min;
256
scaleData.maxValue = max;
257
scaleData.stepSize = stepSize;
258
scaleData.doAutoScale = false;
263
void QwtRadialPlot::setScaleDiv(int scaleId, const QwtScaleDiv &scaleDiv)
265
if ( scaleId < 0 || scaleId >= ScaleCount )
268
ScaleData &scaleData = d_data->scaleData[scaleId];
270
scaleData.scaleDiv = scaleDiv;
271
scaleData.doAutoScale = false;
276
const QwtScaleDiv *QwtRadialPlot::scaleDiv(int scaleId) const
278
if ( scaleId < 0 || scaleId >= ScaleCount )
281
return &d_data->scaleData[scaleId].scaleDiv;
284
QwtScaleDiv *QwtRadialPlot::scaleDiv(int scaleId)
286
if ( scaleId < 0 || scaleId >= ScaleCount )
289
return &d_data->scaleData[scaleId].scaleDiv;
292
QwtScaleMap QwtRadialPlot::canvasMap(int scaleId) const
294
if ( scaleId < 0 || scaleId >= ScaleCount )
295
return QwtScaleMap();
298
map.setTransformation(scaleEngine(scaleId)->transformation());
300
const QwtScaleDiv *sd = scaleDiv(scaleId);
301
map.setScaleInterval(sd->lBound(), sd->hBound());
303
if ( scaleId == AngleScale)
305
const double o = d_data->origin;
306
map.setPaintXInterval(o, o + M_2PI);
310
const int w = qwtMin(canvasRect().width(), canvasRect().height());
311
map.setPaintInterval(canvasRect().center().x(),
312
canvasRect().center().x() + w / 2);
318
QSize QwtRadialPlot::sizeHint() const
320
const int extent = scaleExtent();
323
const int d = 6 * (extent + 1);
324
return QSize( d, d );
327
return QSize(400, 400); // something
330
QSize QwtRadialPlot::minimumSizeHint() const
332
const int extent = scaleExtent();
335
const int d = 3 * (extent + 1);
336
return QSize( d, d );
342
bool QwtRadialPlot::event(QEvent *e)
344
bool ok = QWidget::event(e);
347
#if QT_VERSION >= 0x040000
348
case QEvent::PolishRequest:
357
void QwtRadialPlot::paintEvent(QPaintEvent *e)
359
const QRect &ur = e->rect();
362
#if QT_VERSION < 0x040000
363
QwtPaintBuffer paintBuffer(this, ur);
364
QPainter &painter = *paintBuffer.painter();
366
QPainter painter(this);
369
drawCanvas(&painter, canvasRect());
372
if ( isAngleScaleVisible() )
375
drawAngleScale(&painter, boundingRect());
381
void QwtRadialPlot::initPlot()
383
#if QT_VERSION < 0x040000
384
setWFlags(Qt::WNoAutoErase);
387
d_data = new PrivateData;
389
d_data->autoReplot = false;
390
d_data->isAngleScaleVisible = true;
391
d_data->angleScaleDraw = new QwtRoundScaleDraw();
392
d_data->origin = 0.0;
394
for ( int scaleId = DistanceScale; scaleId <= AngleScale; scaleId++ )
396
ScaleData &scaleData = d_data->scaleData[scaleId];
398
if ( scaleId == AngleScale )
401
scaleData.minValue = 0.0;
402
scaleData.maxValue = 360.0;
403
scaleData.stepSize = 15.0;
408
scaleData.minValue = 0.0;
409
scaleData.maxValue = 1000.0;
410
scaleData.stepSize = 0.0;
413
scaleData.doAutoScale = true;
415
scaleData.maxMinor = 5;
416
scaleData.maxMajor = 8;
418
scaleData.scaleEngine = new QwtLinearScaleEngine;
419
scaleData.scaleDiv.invalidate();
421
updateScale(scaleId);
424
setSizePolicy(QSizePolicy::MinimumExpanding,
425
QSizePolicy::MinimumExpanding);
428
void QwtRadialPlot::autoRefresh()
430
if (d_data->autoReplot)
434
void QwtRadialPlot::replot()
436
for ( int scaleId = 0; scaleId < ScaleCount; scaleId++ )
437
updateScale(scaleId);
440
void QwtRadialPlot::drawAngleScale(QPainter *painter, const QRect &rect) const
442
QwtRoundScaleDraw *scaleDraw = d_data->angleScaleDraw;
443
if ( scaleDraw == NULL )
446
const QPoint center = rect.center();
447
int radius = rect.width() / 2;
448
radius -= scaleDraw->extent(QPen(), font()) - 1;
450
painter->setFont(font());
451
scaleDraw->setRadius(radius);
452
scaleDraw->moveCenter(center);
454
const double o = d_data->origin / M_PI * 180.0; // degree
455
scaleDraw->setAngleRange(o + 90.0, o - 270.0);
457
#if QT_VERSION < 0x040000
458
QColorGroup cg = colorGroup();
460
const QColor textColor = cg.color(QColorGroup::Text);
461
cg.setColor(QColorGroup::Foreground, textColor);
463
scaleDraw->draw(painter, cg);
465
QPalette pal = palette();
467
const QColor textColor = pal.color(QPalette::Text);
468
pal.setColor(QPalette::Foreground, textColor); //ticks, backbone
470
setAntialiasing(painter, true);
471
scaleDraw->draw(painter, pal);
475
void QwtRadialPlot::drawCanvas(QPainter *painter, const QRect &rect) const
477
QwtScaleMap maps[ScaleCount];
478
for ( int scaleId = 0; scaleId < ScaleCount; scaleId++ )
479
maps[scaleId] = canvasMap(scaleId);
481
drawItems(painter, rect, maps);
484
void QwtRadialPlot::drawItems(QPainter *painter, const QRect &canvasRect,
485
const QwtScaleMap map[ScaleCount]) const
487
const QwtRadialPlotItemList& itmList = itemList();
488
for ( QwtRadialPlotItemIterator it = itmList.begin();
489
it != itmList.end(); ++it )
491
QwtRadialPlotItem *item = *it;
492
if ( item && item->isVisible() )
496
#if QT_VERSION >= 0x040000
497
painter->setRenderHint(QPainter::Antialiasing,
498
item->testRenderHint(QwtRadialPlotItem::RenderAntialiased) );
502
map[DistanceScale], map[AngleScale],
510
void QwtRadialPlot::updateScale(int scaleId)
512
if ( scaleId < 0 || scaleId >= ScaleCount )
515
ScaleData &d = d_data->scaleData[scaleId];
516
if ( !d.scaleDiv.isValid() )
518
d.scaleDiv = d.scaleEngine->divideScale(
519
d.minValue, d.maxValue,
520
d.maxMajor, d.maxMinor, d.stepSize);
523
QwtRoundScaleDraw *scaleDraw = d_data->angleScaleDraw;
526
scaleDraw->setTransformation(d.scaleEngine->transformation());
527
scaleDraw->setScaleDiv(d.scaleDiv);
530
const QwtRadialPlotItemList& itmList = itemList();
532
QwtRadialPlotItemIterator it;
534
for ( it = itmList.begin(); it != itmList.end(); ++it )
536
QwtRadialPlotItem *item = *it;
537
item->updateScaleDiv(
538
*scaleDiv(DistanceScale), *scaleDiv(AngleScale));
542
void QwtRadialPlot::polish()
546
#if QT_VERSION < 0x040000
551
QRect QwtRadialPlot::boundingRect() const
553
const int radius = qwtMin(width(), height()) / 2;
555
QRect r(0, 0, 2 * radius, 2 * radius);
556
r.moveCenter(rect().center());
560
QRect QwtRadialPlot::canvasRect() const
562
int scaleDist = scaleExtent();
565
scaleDist++; // margin
568
const QRect rect = boundingRect();
569
return QRect(rect.x() + scaleDist, rect.y() + scaleDist,
570
rect.width() - 2 * scaleDist, rect.height() - 2 * scaleDist);
573
int QwtRadialPlot::scaleExtent() const
575
if ( isAngleScaleVisible() && d_data->angleScaleDraw )
576
return d_data->angleScaleDraw->extent(QPen(), font());