地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
9.5 KiB

15 years ago
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
15 years ago
* 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_abstract_scale_draw.h"
15 years ago
#include "qwt_math.h"
#include "qwt_text.h"
#include "qwt_painter.h"
#include "qwt_scale_map.h"
#include <qpainter.h>
#include <qpalette.h>
#include <qmap.h>
#include <qlocale.h>
15 years ago
class QwtAbstractScaleDraw::PrivateData
{
public:
PrivateData():
spacing( 4.0 ),
penWidth( 0 ),
minExtent( 0.0 )
{
components = QwtAbstractScaleDraw::Backbone
| QwtAbstractScaleDraw::Ticks
| QwtAbstractScaleDraw::Labels;
tickLength[QwtScaleDiv::MinorTick] = 4.0;
tickLength[QwtScaleDiv::MediumTick] = 6.0;
tickLength[QwtScaleDiv::MajorTick] = 8.0;
15 years ago
}
ScaleComponents components;
15 years ago
QwtScaleMap map;
QwtScaleDiv scaleDiv;
double spacing;
double tickLength[QwtScaleDiv::NTickTypes];
int penWidth;
15 years ago
double minExtent;
15 years ago
QMap<double, QwtText> labelCache;
};
/*!
\brief Constructor
The range of the scale is initialized to [0, 100],
The spacing (distance between ticks and labels) is
set to 4, the tick lengths are set to 4,6 and 8 pixels
*/
QwtAbstractScaleDraw::QwtAbstractScaleDraw()
{
d_data = new QwtAbstractScaleDraw::PrivateData;
}
//! Destructor
QwtAbstractScaleDraw::~QwtAbstractScaleDraw()
{
delete d_data;
}
/*!
15 years ago
En/Disable a component of the scale
\param component Scale component
\param enable On/Off
\sa hasComponent()
15 years ago
*/
void QwtAbstractScaleDraw::enableComponent(
ScaleComponent component, bool enable )
15 years ago
{
if ( enable )
d_data->components |= component;
else
d_data->components &= ~component;
}
/*!
Check if a component is enabled
\param component Component type
\return true, when component is enabled
\sa enableComponent()
15 years ago
*/
bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const
15 years ago
{
return ( d_data->components & component );
15 years ago
}
/*!
Change the scale division
\param scaleDiv New scale division
15 years ago
*/
void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &scaleDiv )
15 years ago
{
d_data->scaleDiv = scaleDiv;
d_data->map.setScaleInterval( scaleDiv.lowerBound(), scaleDiv.upperBound() );
15 years ago
d_data->labelCache.clear();
}
/*!
Change the transformation of the scale
\param transformation New scale transformation
*/
void QwtAbstractScaleDraw::setTransformation(
QwtTransform *transformation )
15 years ago
{
d_data->map.setTransformation( transformation );
15 years ago
}
//! \return Map how to translate between scale and pixel values
const QwtScaleMap &QwtAbstractScaleDraw::scaleMap() const
15 years ago
{
return d_data->map;
}
//! \return Map how to translate between scale and pixel values
QwtScaleMap &QwtAbstractScaleDraw::scaleMap()
15 years ago
{
return d_data->map;
}
//! \return scale division
const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const
{
return d_data->scaleDiv;
15 years ago
}
/*!
\brief Specify the width of the scale pen
\param width Pen width
\sa penWidth()
*/
void QwtAbstractScaleDraw::setPenWidth( int width )
{
if ( width < 0 )
width = 0;
15 years ago
if ( width != d_data->penWidth )
d_data->penWidth = width;
}
15 years ago
/*!
\return Scale pen width
\sa setPenWidth()
15 years ago
*/
int QwtAbstractScaleDraw::penWidth() const
{
return d_data->penWidth;
}
15 years ago
/*!
\brief Draw the scale
\param painter The painter
\param palette Palette, text color is used for the labels,
15 years ago
foreground color for ticks and backbone
*/
void QwtAbstractScaleDraw::draw( QPainter *painter,
const QPalette& palette ) const
15 years ago
{
painter->save();
15 years ago
QPen pen = painter->pen();
pen.setWidth( d_data->penWidth );
pen.setCosmetic( false );
painter->setPen( pen );
15 years ago
if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
{
painter->save();
painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style
const QList<double> &majorTicks =
d_data->scaleDiv.ticks( QwtScaleDiv::MajorTick );
15 years ago
for ( int i = 0; i < majorTicks.count(); i++ )
{
15 years ago
const double v = majorTicks[i];
if ( d_data->scaleDiv.contains( v ) )
drawLabel( painter, v );
15 years ago
}
painter->restore();
}
if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
{
15 years ago
painter->save();
QPen pen = painter->pen();
pen.setColor( palette.color( QPalette::WindowText ) );
pen.setCapStyle( Qt::FlatCap );
painter->setPen( pen );
15 years ago
for ( int tickType = QwtScaleDiv::MinorTick;
tickType < QwtScaleDiv::NTickTypes; tickType++ )
{
const QList<double> &ticks = d_data->scaleDiv.ticks( tickType );
for ( int i = 0; i < ticks.count(); i++ )
{
15 years ago
const double v = ticks[i];
if ( d_data->scaleDiv.contains( v ) )
drawTick( painter, v, d_data->tickLength[tickType] );
15 years ago
}
}
painter->restore();
}
if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
{
15 years ago
painter->save();
QPen pen = painter->pen();
pen.setColor( palette.color( QPalette::WindowText ) );
pen.setCapStyle( Qt::FlatCap );
painter->setPen( pen );
15 years ago
drawBackbone( painter );
15 years ago
painter->restore();
}
painter->restore();
15 years ago
}
/*!
\brief Set the spacing between tick and labels
The spacing is the distance between ticks and labels.
The default spacing is 4 pixels.
\param spacing Spacing
\sa spacing()
15 years ago
*/
void QwtAbstractScaleDraw::setSpacing( double spacing )
15 years ago
{
if ( spacing < 0 )
spacing = 0;
d_data->spacing = spacing;
}
/*!
\brief Get the spacing
The spacing is the distance between ticks and labels.
The default spacing is 4 pixels.
\return Spacing
\sa setSpacing()
15 years ago
*/
double QwtAbstractScaleDraw::spacing() const
15 years ago
{
return d_data->spacing;
}
/*!
\brief Set a minimum for the extent
The extent is calculated from the components of the
15 years ago
scale draw. In situations, where the labels are
changing and the layout depends on the extent (f.e scrolling
a scale), setting an upper limit as minimum extent will
avoid jumps of the layout.
\param minExtent Minimum extent
\sa extent(), minimumExtent()
*/
void QwtAbstractScaleDraw::setMinimumExtent( double minExtent )
15 years ago
{
if ( minExtent < 0.0 )
minExtent = 0.0;
15 years ago
d_data->minExtent = minExtent;
}
/*!
Get the minimum extent
\return Minimum extent
15 years ago
\sa extent(), setMinimumExtent()
*/
double QwtAbstractScaleDraw::minimumExtent() const
15 years ago
{
return d_data->minExtent;
}
/*!
Set the length of the ticks
15 years ago
\param tickType Tick type
\param length New length
\warning the length is limited to [0..1000]
*/
void QwtAbstractScaleDraw::setTickLength(
QwtScaleDiv::TickType tickType, double length )
15 years ago
{
if ( tickType < QwtScaleDiv::MinorTick ||
tickType > QwtScaleDiv::MajorTick )
{
15 years ago
return;
}
if ( length < 0.0 )
length = 0.0;
15 years ago
const double maxTickLen = 1000.0;
15 years ago
if ( length > maxTickLen )
length = maxTickLen;
15 years ago
d_data->tickLength[tickType] = length;
}
/*!
\return Length of the ticks
\sa setTickLength(), maxTickLength()
15 years ago
*/
double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const
15 years ago
{
if ( tickType < QwtScaleDiv::MinorTick ||
tickType > QwtScaleDiv::MajorTick )
{
15 years ago
return 0;
}
return d_data->tickLength[tickType];
}
/*!
\return Length of the longest tick
Useful for layout calculations
\sa tickLength(), setTickLength()
15 years ago
*/
double QwtAbstractScaleDraw::maxTickLength() const
15 years ago
{
double length = 0.0;
for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
length = qMax( length, d_data->tickLength[i] );
return length;
15 years ago
}
/*!
\brief Convert a value into its representing label
15 years ago
The value is converted to a plain text using
QLocale().toString(value).
15 years ago
This method is often overloaded by applications to have individual
labels.
\param value Value
\return Label string.
*/
QwtText QwtAbstractScaleDraw::label( double value ) const
15 years ago
{
return QLocale().toString( value );
15 years ago
}
/*!
\brief Convert a value into its representing label and cache it.
The conversion between value and label is called very often
in the layout and painting code. Unfortunately the
calculation of the label sizes might be slow (really slow
for rich text in Qt4), so it's necessary to cache the labels.
15 years ago
\param font Font
\param value Value
\return Tick label
*/
const QwtText &QwtAbstractScaleDraw::tickLabel(
const QFont &font, double value ) const
15 years ago
{
QMap<double, QwtText>::const_iterator it = d_data->labelCache.find( value );
if ( it == d_data->labelCache.end() )
{
QwtText lbl = label( value );
lbl.setRenderFlags( 0 );
lbl.setLayoutAttribute( QwtText::MinimumLayout );
15 years ago
( void )lbl.textSize( font ); // initialize the internal cache
15 years ago
it = d_data->labelCache.insert( value, lbl );
15 years ago
}
return ( *it );
15 years ago
}
/*!
Invalidate the cache used by tickLabel()
15 years ago
The cache is invalidated, when a new QwtScaleDiv is set. If
the labels need to be changed. while the same QwtScaleDiv is set,
invalidateCache() needs to be called manually.
15 years ago
*/
void QwtAbstractScaleDraw::invalidateCache()
{
d_data->labelCache.clear();
}