~ubuntu-branches/ubuntu/oneiric/qwt/oneiric-proposed

« back to all changes in this revision

Viewing changes to qwt-5.1.1/src/qwt_round_scale_draw.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2008-05-26 10:26:31 UTC
  • mfrom: (1.1.3 upstream) (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526102631-bp95mfccnrb957nx
Tags: 5.1.1-1
New upstream release.

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
// vim: expandtab
 
11
 
 
12
#include <math.h>
 
13
#include <qpen.h>
 
14
#include <qpainter.h>
 
15
#include <qfontmetrics.h>
 
16
#include "qwt_painter.h"
 
17
#include "qwt_scale_div.h"
 
18
#include "qwt_scale_map.h"
 
19
#include "qwt_round_scale_draw.h"
 
20
 
 
21
class QwtRoundScaleDraw::PrivateData
 
22
{
 
23
public:
 
24
    PrivateData():
 
25
        center(50, 50),
 
26
        radius(50),
 
27
        startAngle(-135 * 16),
 
28
        endAngle(135 * 16)
 
29
    {
 
30
    }
 
31
 
 
32
    QPoint center;
 
33
    int radius; 
 
34
 
 
35
    int startAngle;
 
36
    int endAngle;
 
37
};
 
38
 
 
39
/*!
 
40
  \brief Constructor
 
41
 
 
42
  The range of the scale is initialized to [0, 100],
 
43
  The center is set to (50, 50) with a radius of 50.
 
44
  The angle range is set to [-135, 135].
 
45
*/
 
46
QwtRoundScaleDraw::QwtRoundScaleDraw()
 
47
{
 
48
    d_data = new QwtRoundScaleDraw::PrivateData;
 
49
 
 
50
    setRadius(50);
 
51
    scaleMap().setPaintInterval(d_data->startAngle, d_data->endAngle);
 
52
}
 
53
 
 
54
//! Copy constructor
 
55
QwtRoundScaleDraw::QwtRoundScaleDraw(const QwtRoundScaleDraw &other):
 
56
    QwtAbstractScaleDraw(other)
 
57
{
 
58
    d_data = new QwtRoundScaleDraw::PrivateData(*other.d_data);
 
59
}
 
60
 
 
61
 
 
62
//! Destructor
 
63
QwtRoundScaleDraw::~QwtRoundScaleDraw()
 
64
{
 
65
    delete d_data;
 
66
}
 
67
 
 
68
//! Assignment operator
 
69
QwtRoundScaleDraw &QwtRoundScaleDraw::operator=(const QwtRoundScaleDraw &other)
 
70
{
 
71
    *(QwtAbstractScaleDraw*)this = (const QwtAbstractScaleDraw &)other;
 
72
    *d_data = *other.d_data;
 
73
    return *this;
 
74
}
 
75
 
 
76
/*!
 
77
  Change of radius the scale
 
78
 
 
79
  Radius is the radius of the backbone without ticks and labels.
 
80
 
 
81
  \param radius New Radius
 
82
  \sa moveCenter
 
83
*/
 
84
void QwtRoundScaleDraw::setRadius(int radius)
 
85
{
 
86
    d_data->radius = radius;
 
87
}
 
88
 
 
89
/*!
 
90
  Get the radius 
 
91
 
 
92
  Radius is the radius of the backbone without ticks and labels.
 
93
 
 
94
  \sa setRadius(), extent()
 
95
*/
 
96
int QwtRoundScaleDraw::radius() const
 
97
{
 
98
    return d_data->radius;
 
99
}
 
100
 
 
101
/*!
 
102
   Move the center of the scale draw, leaving the radius unchanged
 
103
 
 
104
   \param center New center
 
105
   \sa setRadius
 
106
*/
 
107
void QwtRoundScaleDraw::moveCenter(const QPoint &center)
 
108
{
 
109
    d_data->center = center;
 
110
}
 
111
 
 
112
//! Get the center of the scale
 
113
QPoint QwtRoundScaleDraw::center() const
 
114
{
 
115
    return d_data->center;
 
116
}
 
117
 
 
118
/*!
 
119
  \brief Adjust the baseline circle segment for round scales.
 
120
 
 
121
  The baseline will be drawn from min(angle1,angle2) to max(angle1, angle2).
 
122
  The default setting is [ -135, 135 ].
 
123
  An angle of 0 degrees corresponds to the 12 o'clock position,
 
124
  and positive angles count in a clockwise direction.
 
125
  \param angle1
 
126
  \param angle2 boundaries of the angle interval in degrees.
 
127
  \warning <ul> 
 
128
  <li>The angle range is limited to [-360, 360] degrees. Angles exceeding
 
129
      this range will be clipped.
 
130
  <li>For angles more than 359 degrees above or below min(angle1, angle2),
 
131
      scale marks will not be drawn.
 
132
  <li>If you need a counterclockwise scale, use QwtScaleDiv::setRange
 
133
  </ul>
 
134
*/
 
135
void QwtRoundScaleDraw::setAngleRange(double angle1, double angle2)
 
136
{
 
137
    angle1 = qwtLim(angle1, -360.0, 360.0);
 
138
    angle2 = qwtLim(angle2, -360.0, 360.0);
 
139
 
 
140
    d_data->startAngle = qRound(angle1 * 16.0);
 
141
    d_data->endAngle = qRound(angle2 * 16.0); 
 
142
 
 
143
    if (d_data->startAngle == d_data->endAngle)
 
144
    {
 
145
        d_data->startAngle -= 1;
 
146
        d_data->endAngle += 1;
 
147
    }
 
148
 
 
149
    scaleMap().setPaintInterval(d_data->startAngle, d_data->endAngle);
 
150
}
 
151
 
 
152
/*!
 
153
   Draws the label for a major scale tick
 
154
 
 
155
   \param painter Painter
 
156
   \param value Value
 
157
 
 
158
   \sa drawTick(), drawBackbone()
 
159
*/
 
160
void QwtRoundScaleDraw::drawLabel(QPainter *painter, double value) const
 
161
{
 
162
    const QwtText label = tickLabel(painter->font(), value);
 
163
    if ( label.isEmpty() )
 
164
        return; 
 
165
 
 
166
    const int tval = map().transform(value);
 
167
    if ((tval > d_data->startAngle + 359 * 16)
 
168
        || (tval < d_data->startAngle - 359 * 16))
 
169
    {
 
170
       return; 
 
171
    }
 
172
 
 
173
    double radius = d_data->radius;
 
174
    if ( hasComponent(QwtAbstractScaleDraw::Ticks) ||
 
175
        hasComponent(QwtAbstractScaleDraw::Backbone) )
 
176
    {
 
177
        radius += spacing();
 
178
    }
 
179
 
 
180
    if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
 
181
        radius += majTickLength();
 
182
 
 
183
    const QSize sz = label.textSize(painter->font());
 
184
    const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
 
185
 
 
186
    const int x = d_data->center.x() +
 
187
        qRound((radius + sz.width() / 2.0) * sin(arc));
 
188
    const int y = d_data->center.y() -
 
189
        qRound( (radius + sz.height() / 2.0) * cos(arc));
 
190
 
 
191
    const QRect r(x - sz.width() / 2, y - sz.height() / 2,
 
192
        sz.width(), sz.height() );
 
193
    label.draw(painter, r);
 
194
}
 
195
 
 
196
/*!
 
197
   Draw a tick
 
198
   
 
199
   \param painter Painter
 
200
   \param value Value of the tick
 
201
   \param len Lenght of the tick
 
202
 
 
203
   \sa drawBackbone(), drawLabel() 
 
204
*/
 
205
void QwtRoundScaleDraw::drawTick(QPainter *painter, double value, int len) const
 
206
{
 
207
    if ( len <= 0 )
 
208
        return;
 
209
 
 
210
    const int tval = map().transform(value);
 
211
 
 
212
    const int cx = d_data->center.x();
 
213
    const int cy = d_data->center.y();
 
214
    const int radius = d_data->radius;
 
215
 
 
216
    if ((tval <= d_data->startAngle + 359 * 16)
 
217
        || (tval >= d_data->startAngle - 359 * 16))
 
218
    {
 
219
        const double arc = double(tval) / 16.0 * M_PI / 180.0;
 
220
 
 
221
        const double sinArc = sin(arc);
 
222
        const double cosArc = cos(arc);
 
223
 
 
224
        const int x1 = qRound( cx + radius * sinArc );
 
225
        const int x2 = qRound( cx + (radius + len) * sinArc );
 
226
        const int y1 = qRound( cy - radius * cosArc );
 
227
        const int y2 = qRound( cy - (radius + len) * cosArc );
 
228
 
 
229
        QwtPainter::drawLine(painter, x1, y1, x2, y2);
 
230
    }
 
231
}
 
232
 
 
233
/*!
 
234
   Draws the baseline of the scale
 
235
   \param painter Painter
 
236
 
 
237
   \sa drawTick(), drawLabel()
 
238
*/
 
239
void QwtRoundScaleDraw::drawBackbone(QPainter *painter) const
 
240
{
 
241
    const int a1 = qRound(qwtMin(map().p1(), map().p2()) - 90 * 16);
 
242
    const int a2 = qRound(qwtMax(map().p1(), map().p2()) - 90 * 16);
 
243
 
 
244
    const int radius = d_data->radius;
 
245
    const int x = d_data->center.x() - radius;
 
246
    const int y = d_data->center.y() - radius;
 
247
 
 
248
    painter->drawArc(x, y, 2 * radius, 2 * radius,
 
249
        -a2, a2 - a1 + 1);           // counterclockwise
 
250
}
 
251
 
 
252
/*!
 
253
   Calculate the extent of the scale
 
254
 
 
255
   The extent is the distcance between the baseline to the outermost
 
256
   pixel of the scale draw. radius() + extent() is an upper limit 
 
257
   for the radius of the bounding circle.
 
258
 
 
259
   \param pen Pen that is used for painting backbone and ticks
 
260
   \param font Font used for painting the labels
 
261
 
 
262
   \sa setMinimumExtent(), minimumExtent()
 
263
   \warning The implemented algo is not too smart and
 
264
            calculates only an upper limit, that might be a
 
265
            few pixels too large
 
266
*/
 
267
int QwtRoundScaleDraw::extent(const QPen &pen, const QFont &font) const
 
268
{
 
269
    int d = 0;
 
270
 
 
271
    if ( hasComponent(QwtAbstractScaleDraw::Labels) )
 
272
    {
 
273
        const QwtScaleDiv &sd = scaleDiv();
 
274
        const QwtValueList &ticks = sd.ticks(QwtScaleDiv::MajorTick);
 
275
        for (uint i = 0; i < (uint)ticks.count(); i++)
 
276
        {
 
277
            const double value = ticks[i];
 
278
            if ( !sd.contains(value) )
 
279
                continue;
 
280
 
 
281
            const QwtText label = tickLabel(font, value);
 
282
            if ( label.isEmpty() )
 
283
                continue;
 
284
                
 
285
            const int tval = map().transform(value);
 
286
            if ((tval < d_data->startAngle + 360 * 16)
 
287
                && (tval > d_data->startAngle - 360 * 16))
 
288
            {
 
289
                const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
 
290
 
 
291
                const QSize sz = label.textSize(font);
 
292
                const double off = qwtMax(sz.width(), sz.height());
 
293
 
 
294
                double x = off * sin(arc);
 
295
                double y = off * cos(arc);
 
296
 
 
297
                const int dist = (int)ceil(sqrt(x * x + y * y) + 1 );
 
298
                if ( dist > d )
 
299
                    d = dist;
 
300
            }
 
301
        }
 
302
    }
 
303
 
 
304
    if ( hasComponent(QwtAbstractScaleDraw::Ticks) )
 
305
    {
 
306
        d += majTickLength();
 
307
    }
 
308
 
 
309
    if ( hasComponent(QwtAbstractScaleDraw::Backbone) )
 
310
    {
 
311
        const int pw = qwtMax( 1, pen.width() );  // penwidth can be zero
 
312
        d += pw;
 
313
    }
 
314
 
 
315
    if ( hasComponent(QwtAbstractScaleDraw::Labels) &&
 
316
        ( hasComponent(QwtAbstractScaleDraw::Ticks) || 
 
317
            hasComponent(QwtAbstractScaleDraw::Backbone) ) )
 
318
    {
 
319
        d += spacing();
 
320
    }
 
321
 
 
322
    d = qwtMax(d, minimumExtent());
 
323
 
 
324
    return d;
 
325
}