summaryrefslogtreecommitdiff
path: root/src/libpcp_qwt/src/qwt_round_scale_draw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libpcp_qwt/src/qwt_round_scale_draw.cpp')
-rw-r--r--src/libpcp_qwt/src/qwt_round_scale_draw.cpp309
1 files changed, 309 insertions, 0 deletions
diff --git a/src/libpcp_qwt/src/qwt_round_scale_draw.cpp b/src/libpcp_qwt/src/qwt_round_scale_draw.cpp
new file mode 100644
index 0000000..e59192b
--- /dev/null
+++ b/src/libpcp_qwt/src/qwt_round_scale_draw.cpp
@@ -0,0 +1,309 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997 Josef Wilgen
+ * Copyright (C) 2002 Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_round_scale_draw.h"
+#include "qwt_painter.h"
+#include "qwt_scale_div.h"
+#include "qwt_scale_map.h"
+#include <qpen.h>
+#include <qpainter.h>
+#include <qfontmetrics.h>
+#include <qmath.h>
+
+class QwtRoundScaleDraw::PrivateData
+{
+public:
+ PrivateData():
+ center( 50.0, 50.0 ),
+ radius( 50.0 ),
+ startAngle( -135 * 16 ),
+ endAngle( 135 * 16 )
+ {
+ }
+
+ QPointF center;
+ double radius;
+
+ double startAngle;
+ double endAngle;
+};
+
+/*!
+ \brief Constructor
+
+ The range of the scale is initialized to [0, 100],
+ The center is set to (50, 50) with a radius of 50.
+ The angle range is set to [-135, 135].
+*/
+QwtRoundScaleDraw::QwtRoundScaleDraw()
+{
+ d_data = new QwtRoundScaleDraw::PrivateData;
+
+ setRadius( 50 );
+ scaleMap().setPaintInterval( d_data->startAngle, d_data->endAngle );
+}
+
+//! Destructor
+QwtRoundScaleDraw::~QwtRoundScaleDraw()
+{
+ delete d_data;
+}
+
+/*!
+ Change of radius the scale
+
+ Radius is the radius of the backbone without ticks and labels.
+
+ \param radius New Radius
+ \sa moveCenter()
+*/
+void QwtRoundScaleDraw::setRadius( int radius )
+{
+ d_data->radius = radius;
+}
+
+/*!
+ Get the radius
+
+ Radius is the radius of the backbone without ticks and labels.
+
+ \sa setRadius(), extent()
+*/
+int QwtRoundScaleDraw::radius() const
+{
+ return qCeil( d_data->radius );
+}
+
+/*!
+ Move the center of the scale draw, leaving the radius unchanged
+
+ \param center New center
+ \sa setRadius()
+*/
+void QwtRoundScaleDraw::moveCenter( const QPointF &center )
+{
+ d_data->center = center;
+}
+
+//! Get the center of the scale
+QPointF QwtRoundScaleDraw::center() const
+{
+ return d_data->center;
+}
+
+/*!
+ \brief Adjust the baseline circle segment for round scales.
+
+ The baseline will be drawn from min(angle1,angle2) to max(angle1, angle2).
+ The default setting is [ -135, 135 ].
+ An angle of 0 degrees corresponds to the 12 o'clock position,
+ and positive angles count in a clockwise direction.
+ \param angle1
+ \param angle2 boundaries of the angle interval in degrees.
+ \warning <ul>
+ <li>The angle range is limited to [-360, 360] degrees. Angles exceeding
+ this range will be clipped.
+ <li>For angles more than 359 degrees above or below min(angle1, angle2),
+ scale marks will not be drawn.
+ <li>If you need a counterclockwise scale, use QwtScaleDiv::setRange
+ </ul>
+*/
+void QwtRoundScaleDraw::setAngleRange( double angle1, double angle2 )
+{
+ angle1 = qBound( -360.0, angle1, 360.0 );
+ angle2 = qBound( -360.0, angle2, 360.0 );
+
+ d_data->startAngle = angle1 * 16.0;
+ d_data->endAngle = angle2 * 16.0;
+
+ if ( d_data->startAngle == d_data->endAngle )
+ {
+ d_data->startAngle -= 1;
+ d_data->endAngle += 1;
+ }
+
+ scaleMap().setPaintInterval( d_data->startAngle, d_data->endAngle );
+}
+
+/*!
+ Draws the label for a major scale tick
+
+ \param painter Painter
+ \param value Value
+
+ \sa drawTick(), drawBackbone()
+*/
+void QwtRoundScaleDraw::drawLabel( QPainter *painter, double value ) const
+{
+ const QwtText label = tickLabel( painter->font(), value );
+ if ( label.isEmpty() )
+ return;
+
+ const double tval = scaleMap().transform( value );
+ if ( ( tval > d_data->startAngle + 359 * 16 )
+ || ( tval < d_data->startAngle - 359 * 16 ) )
+ {
+ return;
+ }
+
+ double radius = d_data->radius;
+ if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ||
+ hasComponent( QwtAbstractScaleDraw::Backbone ) )
+ {
+ radius += spacing();
+ }
+
+ if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
+ radius += tickLength( QwtScaleDiv::MajorTick );
+
+ const QSizeF sz = label.textSize( painter->font() );
+ const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
+
+ const double x = d_data->center.x() +
+ ( radius + sz.width() / 2.0 ) * qSin( arc );
+ const double y = d_data->center.y() -
+ ( radius + sz.height() / 2.0 ) * cos( arc );
+
+ const QRectF r( x - sz.width() / 2, y - sz.height() / 2,
+ sz.width(), sz.height() );
+ label.draw( painter, r );
+}
+
+/*!
+ Draw a tick
+
+ \param painter Painter
+ \param value Value of the tick
+ \param len Lenght of the tick
+
+ \sa drawBackbone(), drawLabel()
+*/
+void QwtRoundScaleDraw::drawTick( QPainter *painter, double value, double len ) const
+{
+ if ( len <= 0 )
+ return;
+
+ const double tval = scaleMap().transform( value );
+
+ const double cx = d_data->center.x();
+ const double cy = d_data->center.y();
+ const double radius = d_data->radius;
+
+ if ( ( tval <= d_data->startAngle + 359 * 16 )
+ || ( tval >= d_data->startAngle - 359 * 16 ) )
+ {
+ const double arc = double( tval ) / 16.0 * M_PI / 180.0;
+
+ const double sinArc = qSin( arc );
+ const double cosArc = qCos( arc );
+
+ const double x1 = cx + radius * sinArc;
+ const double x2 = cx + ( radius + len ) * sinArc;
+ const double y1 = cy - radius * cosArc;
+ const double y2 = cy - ( radius + len ) * cosArc;
+
+ QwtPainter::drawLine( painter, x1, y1, x2, y2 );
+ }
+}
+
+/*!
+ Draws the baseline of the scale
+ \param painter Painter
+
+ \sa drawTick(), drawLabel()
+*/
+void QwtRoundScaleDraw::drawBackbone( QPainter *painter ) const
+{
+ const double deg1 = scaleMap().p1();
+ const double deg2 = scaleMap().p2();
+
+ const int a1 = qRound( qMin( deg1, deg2 ) - 90 * 16 );
+ const int a2 = qRound( qMax( deg1, deg2 ) - 90 * 16 );
+
+ const double radius = d_data->radius;
+ const double x = d_data->center.x() - radius;
+ const double y = d_data->center.y() - radius;
+
+ painter->drawArc( QRectF( x, y, 2 * radius, 2 * radius ),
+ -a2, a2 - a1 + 1 ); // counterclockwise
+}
+
+/*!
+ Calculate the extent of the scale
+
+ The extent is the distance between the baseline to the outermost
+ pixel of the scale draw. radius() + extent() is an upper limit
+ for the radius of the bounding circle.
+
+ \param font Font used for painting the labels
+
+ \sa setMinimumExtent(), minimumExtent()
+ \warning The implemented algo is not too smart and
+ calculates only an upper limit, that might be a
+ few pixels too large
+*/
+double QwtRoundScaleDraw::extent( const QFont &font ) const
+{
+ double d = 0.0;
+
+ if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
+ {
+ const QwtScaleDiv &sd = scaleDiv();
+ const QList<double> &ticks = sd.ticks( QwtScaleDiv::MajorTick );
+ for ( int i = 0; i < ticks.count(); i++ )
+ {
+ const double value = ticks[i];
+ if ( !sd.contains( value ) )
+ continue;
+
+ const QwtText label = tickLabel( font, value );
+ if ( label.isEmpty() )
+ continue;
+
+ const double tval = scaleMap().transform( value );
+ if ( ( tval < d_data->startAngle + 360 * 16 )
+ && ( tval > d_data->startAngle - 360 * 16 ) )
+ {
+ const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
+
+ const QSizeF sz = label.textSize( font );
+ const double off = qMax( sz.width(), sz.height() );
+
+ double x = off * qSin( arc );
+ double y = off * qCos( arc );
+
+ const double dist = qSqrt( x * x + y * y );
+ if ( dist > d )
+ d = dist;
+ }
+ }
+ }
+
+ if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
+ {
+ d += maxTickLength();
+ }
+
+ if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
+ {
+ const double pw = qMax( 1, penWidth() ); // penwidth can be zero
+ d += pw;
+ }
+
+ if ( hasComponent( QwtAbstractScaleDraw::Labels ) &&
+ ( hasComponent( QwtAbstractScaleDraw::Ticks ) ||
+ hasComponent( QwtAbstractScaleDraw::Backbone ) ) )
+ {
+ d += spacing();
+ }
+
+ d = qMax( d, minimumExtent() );
+
+ return d;
+}