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

« back to all changes in this revision

Viewing changes to qwt-5.1.0/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
 
}