~showard314/ubuntu/natty/qtiplot/Python2.7_fix

« back to all changes in this revision

Viewing changes to 3rdparty/qwt/playground/polarplot/src/qwt_radial_plot.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2008-04-04 15:11:55 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080404151155-rjp12ziov4tryj0o
Tags: 0.9.4-1
* New upstream release.
* Refresh patches.
* Remove 04_homepage_url patch. Merged upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 
2
 * Qwt Widget Library
 
3
 * Copyright (C) 1997   Josef Wilgen
 
4
 * Copyright (C) 2002   Uwe Rathmann
 
5
 *
 
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
 *****************************************************************************/
 
9
 
 
10
#include <qpainter.h>
 
11
#include <qevent.h>
 
12
#include <qpaintengine.h>
 
13
#include "qwt_painter.h"
 
14
#include "qwt_math.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"
 
20
#if 1
 
21
#include <QDebug>
 
22
#endif
 
23
 
 
24
#if QT_VERSION >= 0x040000
 
25
static void setAntialiasing(QPainter *painter, bool on)
 
26
{
 
27
    QPaintEngine *engine = painter->paintEngine();
 
28
    if ( engine && engine->hasFeature(QPaintEngine::Antialiasing) )
 
29
        painter->setRenderHint(QPainter::Antialiasing, on);
 
30
}
 
31
#else
 
32
static void setAntialiasing(QPainter *, bool)
 
33
{
 
34
}
 
35
#endif
 
36
 
 
37
class QwtRadialPlot::ScaleData
 
38
{
 
39
public:
 
40
    ScaleData():
 
41
        scaleEngine(NULL)
 
42
    {
 
43
    }
 
44
 
 
45
    ~ScaleData()
 
46
    {
 
47
        delete scaleEngine;
 
48
    }
 
49
 
 
50
    bool doAutoScale;
 
51
 
 
52
    double minValue;
 
53
    double maxValue;
 
54
    double stepSize;
 
55
 
 
56
    int maxMajor;
 
57
    int maxMinor;
 
58
 
 
59
    QwtScaleDiv scaleDiv;
 
60
    QwtScaleEngine *scaleEngine;
 
61
    QwtDoubleInterval zoomedInterval;
 
62
};
 
63
 
 
64
class QwtRadialPlot::PrivateData
 
65
{
 
66
public:
 
67
    QRegion::RegionType shape;
 
68
    QBrush canvasBrush;
 
69
 
 
70
    bool autoReplot;
 
71
    double origin;
 
72
 
 
73
    bool isAngleScaleVisible;
 
74
    QwtRoundScaleDraw *angleScaleDraw;
 
75
 
 
76
    ScaleData scaleData[ScaleCount];
 
77
};
 
78
 
 
79
QwtRadialPlot::QwtRadialPlot( QWidget *parent):
 
80
    QWidget(parent)
 
81
{
 
82
    initPlot();
 
83
}
 
84
 
 
85
#if QT_VERSION < 0x040000
 
86
QwtRadialPlot::QwtRadialPlot( QWidget *parent, const char *name):
 
87
    QWidget(parent, name)
 
88
{
 
89
    initPlot();
 
90
}
 
91
#endif
 
92
 
 
93
QwtRadialPlot::~QwtRadialPlot()
 
94
{
 
95
    delete d_data;
 
96
}
 
97
 
 
98
void QwtRadialPlot::setAutoReplot(bool enable)
 
99
{
 
100
    d_data->autoReplot = enable;
 
101
}
 
102
 
 
103
bool QwtRadialPlot::autoReplot() const
 
104
{
 
105
    return d_data->autoReplot;
 
106
}
 
107
 
 
108
void QwtRadialPlot::showAngleScale(bool enable)
 
109
{
 
110
    if ( d_data->isAngleScaleVisible != enable )
 
111
    {
 
112
        d_data->isAngleScaleVisible = enable;
 
113
        update();
 
114
    }
 
115
}
 
116
 
 
117
bool QwtRadialPlot::isAngleScaleVisible() const
 
118
{
 
119
    return d_data->isAngleScaleVisible;
 
120
}
 
121
 
 
122
void QwtRadialPlot::setOrigin(double origin)
 
123
{
 
124
        // 0.0 -> 2 * PI
 
125
    if ( d_data->origin != origin )
 
126
    {
 
127
        d_data->origin = origin;
 
128
        autoRefresh();
 
129
    }
 
130
}
 
131
 
 
132
double QwtRadialPlot::origin() const
 
133
{
 
134
    return d_data->origin;
 
135
}
 
136
 
 
137
void QwtRadialPlot::setAngleScaleDraw(QwtRoundScaleDraw *scaleDraw)
 
138
{
 
139
    if ( scaleDraw == NULL || scaleDraw == d_data->angleScaleDraw )
 
140
        return;
 
141
 
 
142
    delete d_data->angleScaleDraw;
 
143
    d_data->angleScaleDraw = scaleDraw;
 
144
    autoRefresh();
 
145
}
 
146
 
 
147
const QwtRoundScaleDraw *QwtRadialPlot::angleScaleDraw() const
 
148
{
 
149
    return d_data->angleScaleDraw;
 
150
}
 
151
 
 
152
QwtRoundScaleDraw *QwtRadialPlot::angleScaleDraw()
 
153
{
 
154
    return d_data->angleScaleDraw;
 
155
}
 
156
 
 
157
void QwtRadialPlot::setScaleMaxMinor(int scaleId, int maxMinor)
 
158
{
 
159
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
160
        return;
 
161
 
 
162
    if ( maxMinor < 0 )
 
163
        maxMinor = 0;
 
164
    if ( maxMinor > 100 )
 
165
        maxMinor = 100;
 
166
 
 
167
    ScaleData &scaleData = d_data->scaleData[scaleId];
 
168
 
 
169
    if ( maxMinor != scaleData.maxMinor )
 
170
    {
 
171
        scaleData.maxMinor = maxMinor;
 
172
        scaleData.scaleDiv.invalidate();
 
173
        autoRefresh();
 
174
    }
 
175
}
 
176
 
 
177
int QwtRadialPlot::scaleMaxMinor(int scaleId) const
 
178
{
 
179
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
180
        return 0;
 
181
 
 
182
    return d_data->scaleData[scaleId].maxMinor;
 
183
}
 
184
 
 
185
void QwtRadialPlot::setScaleMaxMajor(int scaleId, int maxMajor)
 
186
{
 
187
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
188
        return;
 
189
 
 
190
    if ( maxMajor < 1 )
 
191
        maxMajor = 1;
 
192
    if ( maxMajor > 1000 )
 
193
        maxMajor = 10000;
 
194
 
 
195
    ScaleData &scaleData = d_data->scaleData[scaleId];
 
196
    if ( maxMajor != scaleData.maxMinor )
 
197
    {
 
198
        scaleData.maxMajor = maxMajor;
 
199
        scaleData.scaleDiv.invalidate();
 
200
        autoRefresh();
 
201
    }
 
202
}
 
203
 
 
204
int QwtRadialPlot::scaleMaxMajor(int scaleId) const
 
205
{
 
206
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
207
        return 0;
 
208
 
 
209
    return d_data->scaleData[scaleId].maxMajor;
 
210
}
 
211
 
 
212
QwtScaleEngine *QwtRadialPlot::scaleEngine(int scaleId)
 
213
{
 
214
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
215
        return NULL;
 
216
 
 
217
    return d_data->scaleData[scaleId].scaleEngine;
 
218
}
 
219
 
 
220
const QwtScaleEngine *QwtRadialPlot::scaleEngine(int scaleId) const
 
221
{
 
222
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
223
        return NULL;
 
224
 
 
225
    return d_data->scaleData[scaleId].scaleEngine;
 
226
}
 
227
 
 
228
void QwtRadialPlot::setScaleEngine(int scaleId, QwtScaleEngine *scaleEngine)
 
229
{
 
230
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
231
        return;
 
232
 
 
233
    ScaleData &scaleData = d_data->scaleData[scaleId];
 
234
    if (scaleEngine == NULL || scaleEngine == scaleData.scaleEngine )
 
235
        return;
 
236
 
 
237
    delete scaleData.scaleEngine;
 
238
    scaleData.scaleEngine = scaleEngine;
 
239
 
 
240
    scaleData.scaleDiv.invalidate();
 
241
 
 
242
    autoRefresh();
 
243
}
 
244
 
 
245
void QwtRadialPlot::setScale(int scaleId, 
 
246
    double min, double max, double stepSize)
 
247
{
 
248
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
249
        return;
 
250
 
 
251
    ScaleData &scaleData = d_data->scaleData[scaleId];
 
252
 
 
253
    scaleData.scaleDiv.invalidate();
 
254
 
 
255
    scaleData.minValue = min;
 
256
    scaleData.maxValue = max;
 
257
    scaleData.stepSize = stepSize;
 
258
    scaleData.doAutoScale = false;
 
259
 
 
260
    autoRefresh();
 
261
}
 
262
 
 
263
void QwtRadialPlot::setScaleDiv(int scaleId, const QwtScaleDiv &scaleDiv)
 
264
{
 
265
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
266
        return;
 
267
 
 
268
    ScaleData &scaleData = d_data->scaleData[scaleId];
 
269
 
 
270
    scaleData.scaleDiv = scaleDiv;
 
271
    scaleData.doAutoScale = false;
 
272
 
 
273
    autoRefresh();
 
274
}
 
275
 
 
276
const QwtScaleDiv *QwtRadialPlot::scaleDiv(int scaleId) const
 
277
{
 
278
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
279
        return NULL;
 
280
 
 
281
    return &d_data->scaleData[scaleId].scaleDiv;
 
282
}
 
283
 
 
284
QwtScaleDiv *QwtRadialPlot::scaleDiv(int scaleId)
 
285
{
 
286
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
287
        return NULL;
 
288
 
 
289
    return &d_data->scaleData[scaleId].scaleDiv;
 
290
}
 
291
 
 
292
QwtScaleMap QwtRadialPlot::canvasMap(int scaleId) const
 
293
{
 
294
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
295
        return QwtScaleMap();
 
296
 
 
297
    QwtScaleMap map;
 
298
    map.setTransformation(scaleEngine(scaleId)->transformation());
 
299
 
 
300
    const QwtScaleDiv *sd = scaleDiv(scaleId);
 
301
    map.setScaleInterval(sd->lBound(), sd->hBound());
 
302
 
 
303
    if ( scaleId == AngleScale)
 
304
    {
 
305
                const double o = d_data->origin;
 
306
        map.setPaintXInterval(o, o + M_2PI); 
 
307
    }
 
308
    else
 
309
    {
 
310
        const int w = qwtMin(canvasRect().width(), canvasRect().height());
 
311
        map.setPaintInterval(canvasRect().center().x(), 
 
312
            canvasRect().center().x() + w / 2);
 
313
    }
 
314
 
 
315
    return map;
 
316
}
 
317
 
 
318
QSize QwtRadialPlot::sizeHint() const
 
319
{
 
320
    const int extent = scaleExtent();
 
321
    if ( extent > 0 )
 
322
    {
 
323
        const int d = 6 * (extent + 1);
 
324
        return QSize( d, d );
 
325
    }
 
326
 
 
327
    return QSize(400, 400); // something
 
328
}
 
329
 
 
330
QSize QwtRadialPlot::minimumSizeHint() const
 
331
{
 
332
    const int extent = scaleExtent();
 
333
    if ( extent > 0 )
 
334
    {
 
335
        const int d = 3 * (extent + 1);
 
336
        return QSize( d, d );
 
337
    }
 
338
 
 
339
    return QSize();
 
340
}
 
341
 
 
342
bool QwtRadialPlot::event(QEvent *e)
 
343
{
 
344
    bool ok = QWidget::event(e);
 
345
    switch(e->type())
 
346
    {
 
347
#if QT_VERSION >= 0x040000
 
348
        case QEvent::PolishRequest:
 
349
            polish();
 
350
            break;
 
351
#endif
 
352
        default:;
 
353
    }
 
354
    return ok;
 
355
}
 
356
 
 
357
void QwtRadialPlot::paintEvent(QPaintEvent *e)
 
358
{
 
359
    const QRect &ur = e->rect();
 
360
    if ( ur.isValid() )
 
361
    {
 
362
#if QT_VERSION < 0x040000
 
363
        QwtPaintBuffer paintBuffer(this, ur);
 
364
        QPainter &painter = *paintBuffer.painter();
 
365
#else
 
366
        QPainter painter(this);
 
367
#endif
 
368
        painter.save();
 
369
        drawCanvas(&painter, canvasRect());
 
370
        painter.restore();
 
371
 
 
372
        if ( isAngleScaleVisible() )
 
373
        {
 
374
            painter.save();
 
375
            drawAngleScale(&painter, boundingRect());
 
376
            painter.restore();
 
377
        }
 
378
    }
 
379
}
 
380
 
 
381
void QwtRadialPlot::initPlot()
 
382
{
 
383
#if QT_VERSION < 0x040000
 
384
    setWFlags(Qt::WNoAutoErase);
 
385
#endif
 
386
 
 
387
    d_data = new PrivateData;
 
388
 
 
389
    d_data->autoReplot = false;
 
390
    d_data->isAngleScaleVisible = true;
 
391
    d_data->angleScaleDraw = new QwtRoundScaleDraw();
 
392
    d_data->origin = 0.0;
 
393
    
 
394
    for ( int scaleId = DistanceScale; scaleId <= AngleScale; scaleId++ )
 
395
    {
 
396
        ScaleData &scaleData = d_data->scaleData[scaleId];
 
397
        
 
398
        if ( scaleId == AngleScale )
 
399
        {
 
400
#if 1
 
401
            scaleData.minValue = 0.0;
 
402
            scaleData.maxValue = 360.0;
 
403
            scaleData.stepSize = 15.0;
 
404
#endif
 
405
        }
 
406
        else
 
407
        {
 
408
            scaleData.minValue = 0.0;
 
409
            scaleData.maxValue = 1000.0;
 
410
            scaleData.stepSize = 0.0;
 
411
        }
 
412
 
 
413
        scaleData.doAutoScale = true;
 
414
        
 
415
        scaleData.maxMinor = 5;
 
416
        scaleData.maxMajor = 8;
 
417
        
 
418
        scaleData.scaleEngine = new QwtLinearScaleEngine;
 
419
        scaleData.scaleDiv.invalidate();
 
420
 
 
421
        updateScale(scaleId);
 
422
    }
 
423
 
 
424
    setSizePolicy(QSizePolicy::MinimumExpanding,
 
425
        QSizePolicy::MinimumExpanding);
 
426
}
 
427
 
 
428
void QwtRadialPlot::autoRefresh()
 
429
{
 
430
    if (d_data->autoReplot)
 
431
        replot();
 
432
}
 
433
 
 
434
void QwtRadialPlot::replot()
 
435
{
 
436
    for ( int scaleId = 0; scaleId < ScaleCount; scaleId++ )
 
437
        updateScale(scaleId);
 
438
}
 
439
 
 
440
void QwtRadialPlot::drawAngleScale(QPainter *painter, const QRect &rect) const
 
441
{
 
442
    QwtRoundScaleDraw *scaleDraw = d_data->angleScaleDraw;
 
443
    if ( scaleDraw == NULL )
 
444
        return;
 
445
 
 
446
    const QPoint center = rect.center();
 
447
    int radius = rect.width() / 2;
 
448
    radius -= scaleDraw->extent(QPen(), font()) - 1;
 
449
 
 
450
    painter->setFont(font());
 
451
    scaleDraw->setRadius(radius);
 
452
    scaleDraw->moveCenter(center);
 
453
 
 
454
    const double o = d_data->origin / M_PI * 180.0; // degree
 
455
    scaleDraw->setAngleRange(o + 90.0, o - 270.0);
 
456
 
 
457
#if QT_VERSION < 0x040000
 
458
    QColorGroup cg = colorGroup();
 
459
 
 
460
    const QColor textColor = cg.color(QColorGroup::Text);
 
461
    cg.setColor(QColorGroup::Foreground, textColor);
 
462
 
 
463
    scaleDraw->draw(painter, cg);
 
464
#else
 
465
    QPalette pal = palette();
 
466
 
 
467
    const QColor textColor = pal.color(QPalette::Text);
 
468
    pal.setColor(QPalette::Foreground, textColor); //ticks, backbone
 
469
 
 
470
    setAntialiasing(painter, true);
 
471
    scaleDraw->draw(painter, pal);
 
472
#endif
 
473
}
 
474
 
 
475
void QwtRadialPlot::drawCanvas(QPainter *painter, const QRect &rect) const
 
476
{
 
477
    QwtScaleMap maps[ScaleCount];
 
478
    for ( int scaleId = 0; scaleId < ScaleCount; scaleId++ )
 
479
        maps[scaleId] = canvasMap(scaleId);
 
480
 
 
481
    drawItems(painter, rect, maps);
 
482
}
 
483
 
 
484
void QwtRadialPlot::drawItems(QPainter *painter, const QRect &canvasRect,
 
485
        const QwtScaleMap map[ScaleCount]) const
 
486
{
 
487
    const QwtRadialPlotItemList& itmList = itemList();
 
488
    for ( QwtRadialPlotItemIterator it = itmList.begin();
 
489
        it != itmList.end(); ++it )
 
490
    {
 
491
        QwtRadialPlotItem *item = *it;
 
492
        if ( item && item->isVisible() )
 
493
        {
 
494
            painter->save();
 
495
 
 
496
#if QT_VERSION >= 0x040000
 
497
            painter->setRenderHint(QPainter::Antialiasing,
 
498
                item->testRenderHint(QwtRadialPlotItem::RenderAntialiased) );
 
499
#endif
 
500
 
 
501
            item->draw(painter,
 
502
                map[DistanceScale], map[AngleScale],
 
503
                canvasRect);
 
504
 
 
505
            painter->restore();
 
506
        }
 
507
    }
 
508
}
 
509
 
 
510
void QwtRadialPlot::updateScale(int scaleId)
 
511
{
 
512
    if ( scaleId < 0 || scaleId >= ScaleCount )
 
513
        return;
 
514
 
 
515
    ScaleData &d = d_data->scaleData[scaleId];
 
516
    if ( !d.scaleDiv.isValid() )
 
517
    {
 
518
        d.scaleDiv = d.scaleEngine->divideScale(
 
519
            d.minValue, d.maxValue,
 
520
            d.maxMajor, d.maxMinor, d.stepSize);
 
521
    }
 
522
 
 
523
    QwtRoundScaleDraw *scaleDraw = d_data->angleScaleDraw;
 
524
    if ( scaleDraw )
 
525
    {
 
526
        scaleDraw->setTransformation(d.scaleEngine->transformation());
 
527
        scaleDraw->setScaleDiv(d.scaleDiv);
 
528
    }
 
529
 
 
530
    const QwtRadialPlotItemList& itmList = itemList();
 
531
 
 
532
    QwtRadialPlotItemIterator it;
 
533
 
 
534
    for ( it = itmList.begin(); it != itmList.end(); ++it )
 
535
    {
 
536
        QwtRadialPlotItem *item = *it;
 
537
        item->updateScaleDiv( 
 
538
            *scaleDiv(DistanceScale), *scaleDiv(AngleScale));
 
539
    }
 
540
}
 
541
 
 
542
void QwtRadialPlot::polish()
 
543
{
 
544
    replot();
 
545
 
 
546
#if QT_VERSION < 0x040000
 
547
    QWidget::polish();
 
548
#endif
 
549
}
 
550
 
 
551
QRect QwtRadialPlot::boundingRect() const
 
552
{
 
553
    const int radius = qwtMin(width(), height()) / 2;
 
554
 
 
555
    QRect r(0, 0, 2 * radius, 2 * radius);
 
556
    r.moveCenter(rect().center());
 
557
    return r;
 
558
}
 
559
 
 
560
QRect QwtRadialPlot::canvasRect() const
 
561
{
 
562
    int scaleDist = scaleExtent();
 
563
#if 0
 
564
    if ( scaleDist > 0 )
 
565
        scaleDist++; // margin
 
566
#endif
 
567
    
 
568
    const QRect rect = boundingRect();
 
569
    return QRect(rect.x() + scaleDist, rect.y() + scaleDist,
 
570
        rect.width() - 2 * scaleDist, rect.height() - 2 * scaleDist);
 
571
}
 
572
 
 
573
int QwtRadialPlot::scaleExtent() const
 
574
{
 
575
    if ( isAngleScaleVisible() && d_data->angleScaleDraw )
 
576
        return d_data->angleScaleDraw->extent(QPen(), font());
 
577
 
 
578
    return 0;
 
579
}
 
580