1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2002 Uwe Rathmann
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
*****************************************************************************/
14
#include "qwt_painter.h"
15
#include "qwt_color_map.h"
16
#include "qwt_scale_widget.h"
17
#include "qwt_scale_map.h"
19
#include "qwt_paint_buffer.h"
20
#include "qwt_scale_div.h"
23
class QwtScaleWidget::PrivateData
29
colorBar.colorMap = NULL;
35
delete colorBar.colorMap;
38
QwtScaleDraw *scaleDraw;
54
QwtDoubleInterval interval;
55
QwtColorMap *colorMap;
60
\brief Create a scale with the position QwtScaleWidget::Left
61
\param parent Parent widget
63
QwtScaleWidget::QwtScaleWidget(QWidget *parent):
66
initScale(QwtScaleDraw::LeftScale);
69
#if QT_VERSION < 0x040000
71
\brief Create a scale with the position QwtScaleWidget::Left
72
\param parent Parent widget
73
\param name Object name
75
QwtScaleWidget::QwtScaleWidget(QWidget *parent, const char *name):
78
initScale(QwtScaleDraw::LeftScale);
84
\param align Alignment.
85
\param parent Parent widget
87
QwtScaleWidget::QwtScaleWidget(
88
QwtScaleDraw::Alignment align, QWidget *parent):
95
QwtScaleWidget::~QwtScaleWidget()
100
//! Initialize the scale
101
void QwtScaleWidget::initScale(QwtScaleDraw::Alignment align)
103
d_data = new PrivateData;
105
#if QT_VERSION < 0x040000
106
setWFlags(Qt::WNoAutoErase);
109
d_data->borderDist[0] = 0;
110
d_data->borderDist[1] = 0;
111
d_data->minBorderDist[0] = 0;
112
d_data->minBorderDist[1] = 0;
114
d_data->penWidth = 0;
115
d_data->titleOffset = 0;
118
d_data->scaleDraw = new QwtScaleDraw;
119
d_data->scaleDraw->setAlignment(align);
120
d_data->scaleDraw->setLength(10);
122
d_data->colorBar.colorMap = new QwtLinearColorMap();
123
d_data->colorBar.isEnabled = false;
124
d_data->colorBar.width = 10;
126
const int flags = Qt::AlignHCenter
127
#if QT_VERSION < 0x040000
128
| Qt::WordBreak | Qt::ExpandTabs;
130
| Qt::TextExpandTabs | Qt::TextWordWrap;
132
d_data->title.setRenderFlags(flags);
133
d_data->title.setFont(font());
135
QSizePolicy policy(QSizePolicy::MinimumExpanding,
137
if ( d_data->scaleDraw->orientation() == Qt::Vertical )
140
setSizePolicy(policy);
142
#if QT_VERSION >= 0x040000
143
setAttribute(Qt::WA_WState_OwnSizePolicy, false);
145
clearWState( WState_OwnSizePolicy );
150
void QwtScaleWidget::setTitle(const QString &title)
152
if ( d_data->title.text() != title )
154
d_data->title.setText(title);
160
\brief Give title new text contents
161
\param title New title
162
\sa QwtScaleWidget::title
163
\warning The title flags are interpreted in
164
direction of the label, AlignTop, AlignBottom can't be set
165
as the title will always be aligned to the scale.
167
void QwtScaleWidget::setTitle(const QwtText &title)
170
const int flags = title.renderFlags() & ~(Qt::AlignTop | Qt::AlignBottom);
171
t.setRenderFlags(flags);
173
if (t != d_data->title)
183
\param alignment New alignment
184
\sa QwtScaleWidget::alignment
186
void QwtScaleWidget::setAlignment(QwtScaleDraw::Alignment alignment)
188
#if QT_VERSION >= 0x040000
189
if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
191
if ( !testWState( WState_OwnSizePolicy ) )
194
QSizePolicy policy(QSizePolicy::MinimumExpanding,
196
if ( d_data->scaleDraw->orientation() == Qt::Vertical )
198
setSizePolicy(policy);
200
#if QT_VERSION >= 0x040000
201
setAttribute(Qt::WA_WState_OwnSizePolicy, false);
203
clearWState( WState_OwnSizePolicy );
207
if (d_data->scaleDraw)
208
d_data->scaleDraw->setAlignment(alignment);
215
\sa QwtScaleWidget::setPosition
217
QwtScaleDraw::Alignment QwtScaleWidget::alignment() const
220
return QwtScaleDraw::LeftScale;
222
return scaleDraw()->alignment();
226
Specify distances of the scale's endpoints from the
227
widget's borders. The actual borders will never be less
228
than minimum border distance.
229
\param dist1 Left or top Distance
230
\param dist2 Right or bottom distance
231
\sa QwtScaleWidget::borderDist
233
void QwtScaleWidget::setBorderDist(int dist1, int dist2)
235
if ( dist1 != d_data->borderDist[0] || dist2 != d_data->borderDist[1] )
237
d_data->borderDist[0] = dist1;
238
d_data->borderDist[1] = dist2;
244
\brief Specify the margin to the colorBar/base line.
246
\sa QwtScaleWidget::margin
248
void QwtScaleWidget::setMargin(int margin)
250
margin = qwtMax( 0, margin );
251
if ( margin != d_data->margin )
253
d_data->margin = margin;
259
\brief Specify the distance between color bar, scale and title
260
\param spacing Spacing
261
\sa QwtScaleWidget::spacing
263
void QwtScaleWidget::setSpacing(int spacing)
265
spacing = qwtMax( 0, spacing );
266
if ( spacing != d_data->spacing )
268
d_data->spacing = spacing;
274
\brief Specify the width of the scale pen
275
\param width Pen width
276
\sa QwtScaleWidget::penWidth
278
void QwtScaleWidget::setPenWidth(int width)
283
if ( width != d_data->penWidth )
285
d_data->penWidth = width;
291
\brief Change the alignment for the labels.
293
\sa QwtScaleDraw::setLabelAlignment(), QwtScaleWidget::setLabelRotation()
295
#if QT_VERSION < 0x040000
296
void QwtScaleWidget::setLabelAlignment(int alignment)
298
void QwtScaleWidget::setLabelAlignment(Qt::Alignment alignment)
301
d_data->scaleDraw->setLabelAlignment(alignment);
306
\brief Change the rotation for the labels.
307
See QwtScaleDraw::setLabelRotation().
308
\sa QwtScaleDraw::setLabelRotation(), QwtScaleWidget::setLabelFlags()
310
void QwtScaleWidget::setLabelRotation(double rotation)
312
d_data->scaleDraw->setLabelRotation(rotation);
317
\brief Set a scale draw
318
sd has to be created with new and will be deleted in
319
QwtScaleWidget::~QwtScale or the next call of QwtScaleWidget::setScaleDraw.
321
void QwtScaleWidget::setScaleDraw(QwtScaleDraw *sd)
323
if ( sd == NULL || sd == d_data->scaleDraw )
326
if ( d_data->scaleDraw )
327
sd->setAlignment(d_data->scaleDraw->alignment());
329
delete d_data->scaleDraw;
330
d_data->scaleDraw = sd;
336
scaleDraw of this scale
337
\sa QwtScaleDraw::setScaleDraw
339
const QwtScaleDraw *QwtScaleWidget::scaleDraw() const
341
return d_data->scaleDraw;
345
scaleDraw of this scale
346
\sa QwtScaleDraw::setScaleDraw
348
QwtScaleDraw *QwtScaleWidget::scaleDraw()
350
return d_data->scaleDraw;
355
\sa QwtScaleWidget::setTitle
357
QwtText QwtScaleWidget::title() const
359
return d_data->title;
363
\return start border distance
364
\sa QwtScaleWidget::setBorderDist
366
int QwtScaleWidget::startBorderDist() const
368
return d_data->borderDist[0];
372
\return end border distance
373
\sa QwtScaleWidget::setBorderDist
375
int QwtScaleWidget::endBorderDist() const
377
return d_data->borderDist[1];
382
\sa QwtScaleWidget::setMargin
384
int QwtScaleWidget::margin() const
386
return d_data->margin;
390
\return distance between scale and title
391
\sa QwtScaleWidget::setMargin
393
int QwtScaleWidget::spacing() const
395
return d_data->spacing;
399
\return Scale pen width
400
\sa QwtScaleWidget::setPenWidth
402
int QwtScaleWidget::penWidth() const
404
return d_data->penWidth;
409
void QwtScaleWidget::paintEvent(QPaintEvent *e)
411
const QRect &ur = e->rect();
414
#if QT_VERSION < 0x040000
415
QwtPaintBuffer paintBuffer(this, ur);
416
draw(paintBuffer.painter());
418
QPainter painter(this);
425
\brief draw the scale
427
void QwtScaleWidget::draw(QPainter *painter) const
431
QPen scalePen = painter->pen();
432
scalePen.setWidth(d_data->penWidth);
433
painter->setPen(scalePen);
435
#if QT_VERSION < 0x040000
436
d_data->scaleDraw->draw(painter, colorGroup());
438
d_data->scaleDraw->draw(painter, palette());
442
if ( d_data->colorBar.isEnabled && d_data->colorBar.width > 0 &&
443
d_data->colorBar.interval.isValid() )
445
drawColorBar(painter, colorBarRect(rect()));
449
if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
451
r.setLeft(r.left() + d_data->borderDist[0]);
452
r.setWidth(r.width() - d_data->borderDist[1]);
456
r.setTop(r.top() + d_data->borderDist[0]);
457
r.setHeight(r.height() - d_data->borderDist[1]);
460
if ( !d_data->title.isEmpty() )
463
switch(d_data->scaleDraw->alignment())
465
case QwtScaleDraw::LeftScale:
466
tr.setRight( r.right() - d_data->titleOffset );
469
case QwtScaleDraw::RightScale:
470
tr.setLeft( r.left() + d_data->titleOffset );
473
case QwtScaleDraw::BottomScale:
474
tr.setTop( r.top() + d_data->titleOffset );
477
case QwtScaleDraw::TopScale:
479
tr.setBottom( r.bottom() - d_data->titleOffset );
483
drawTitle(painter, d_data->scaleDraw->alignment(), tr);
487
QRect QwtScaleWidget::colorBarRect(const QRect& rect) const
491
if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
493
cr.setLeft(cr.left() + d_data->borderDist[0]);
494
cr.setWidth(cr.width() - d_data->borderDist[1] + 1);
498
cr.setTop(cr.top() + d_data->borderDist[0]);
499
cr.setHeight(cr.height() - d_data->borderDist[1] + 1);
502
switch(d_data->scaleDraw->alignment())
504
case QwtScaleDraw::LeftScale:
506
cr.setLeft( cr.right() - d_data->spacing
507
- d_data->colorBar.width + 1 );
508
cr.setWidth(d_data->colorBar.width);
512
case QwtScaleDraw::RightScale:
514
cr.setLeft( cr.left() + d_data->spacing );
515
cr.setWidth(d_data->colorBar.width);
519
case QwtScaleDraw::BottomScale:
521
cr.setTop( cr.top() + d_data->spacing );
522
cr.setHeight(d_data->colorBar.width);
526
case QwtScaleDraw::TopScale:
528
cr.setTop( cr.bottom() - d_data->spacing
529
- d_data->colorBar.width + 1 );
530
cr.setHeight(d_data->colorBar.width);
541
void QwtScaleWidget::resizeEvent(QResizeEvent *)
546
//! Recalculate the scale's geometry and layout based on
547
// the current rect and fonts.
548
// \param update_geometry notify the layout system and call update
549
// to redraw the scale
551
void QwtScaleWidget::layoutScale( bool update_geometry )
554
getBorderDistHint(bd0, bd1);
555
if ( d_data->borderDist[0] > bd0 )
556
bd0 = d_data->borderDist[0];
557
if ( d_data->borderDist[1] > bd1 )
558
bd1 = d_data->borderDist[1];
560
int colorBarWidth = 0;
561
if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
562
colorBarWidth = d_data->colorBar.width + d_data->spacing;
564
const QRect r = rect();
567
if ( d_data->scaleDraw->orientation() == Qt::Vertical )
570
length = r.height() - (bd0 + bd1);
572
if ( d_data->scaleDraw->alignment() == QwtScaleDraw::LeftScale )
573
x = r.right() - d_data->margin - colorBarWidth;
575
x = r.left() + d_data->margin + colorBarWidth;
580
length = r.width() - (bd0 + bd1);
582
if ( d_data->scaleDraw->alignment() == QwtScaleDraw::BottomScale )
583
y = r.top() + d_data->margin + colorBarWidth;
585
y = r.bottom() - d_data->margin - colorBarWidth;
588
d_data->scaleDraw->move(x, y);
589
d_data->scaleDraw->setLength(length);
591
d_data->titleOffset = d_data->margin + d_data->spacing +
593
d_data->scaleDraw->extent(QPen(Qt::black, d_data->penWidth), font());
595
if ( update_geometry )
602
void QwtScaleWidget::drawColorBar(QPainter *painter, const QRect& rect) const
604
if ( !d_data->colorBar.interval.isValid() )
607
const QwtScaleDraw* sd = d_data->scaleDraw;
609
QwtPainter::drawColorBar(painter, *d_data->colorBar.colorMap,
610
d_data->colorBar.interval.normalized(), sd->map(),
611
sd->orientation(), rect);
615
Rotate and paint a title according to its position into a given rectangle.
616
\param painter Painter
617
\param align Alignment
618
\param rect Bounding rectangle
621
void QwtScaleWidget::drawTitle(QPainter *painter,
622
QwtScaleDraw::Alignment align, const QRect &rect) const
626
int flags = d_data->title.renderFlags() &
627
~(Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter);
631
case QwtScaleDraw::LeftScale:
632
flags |= Qt::AlignTop;
634
r.setRect(rect.left(), rect.bottom(), rect.height(), rect.width());
636
case QwtScaleDraw::RightScale:
637
flags |= Qt::AlignTop;
639
r.setRect(rect.right(), rect.top(), rect.height(), rect.width());
641
case QwtScaleDraw::TopScale:
642
flags |= Qt::AlignTop;
646
case QwtScaleDraw::BottomScale:
648
flags |= Qt::AlignBottom;
655
painter->setFont(font());
656
#if QT_VERSION < 0x040000
657
painter->setPen(colorGroup().color(QColorGroup::Text));
659
painter->setPen(palette().color(QPalette::Text));
662
painter->translate(r.x(), r.y());
664
painter->rotate(angle);
666
QwtText title = d_data->title;
667
title.setRenderFlags(flags);
668
title.draw(painter, QRect(0, 0, r.width(), r.height()));
674
\brief Notify a change of the scale
676
This virtual function can be overloaded by derived
677
classes. The default implementation updates the geometry
678
and repaints the widget.
681
void QwtScaleWidget::scaleChange()
689
QSize QwtScaleWidget::sizeHint() const
691
return minimumSizeHint();
695
\return a minimum size hint
697
QSize QwtScaleWidget::minimumSizeHint() const
699
const Qt::Orientation o = d_data->scaleDraw->orientation();
701
// Border Distance cannot be less than the scale borderDistHint
702
// Note, the borderDistHint is already included in minHeight/minWidth
705
getBorderDistHint(mbd1, mbd2);
706
length += qwtMax( 0, d_data->borderDist[0] - mbd1 );
707
length += qwtMax( 0, d_data->borderDist[1] - mbd2 );
708
length += d_data->scaleDraw->minLength(
709
QPen(Qt::black, d_data->penWidth), font());
711
int dim = dimForLength(length, font());
714
// compensate for long titles
716
dim = dimForLength(length, font());
719
QSize size(length + 2, dim);
720
if ( o == Qt::Vertical )
727
\brief Find the height of the title for a given width.
729
\return height Height
732
int QwtScaleWidget::titleHeightForWidth(int width) const
734
return d_data->title.heightForWidth(width, font());
738
\brief Find the minimum dimension for a given length.
739
dim is the height, length the width seen in
740
direction of the title.
741
\param length width for horizontal, height for vertical scales
742
\param scaleFont Font of the scale
743
\return height for horizontal, width for vertical scales
746
int QwtScaleWidget::dimForLength(int length, const QFont &scaleFont) const
748
int dim = d_data->margin;
749
dim += d_data->scaleDraw->extent(
750
QPen(Qt::black, d_data->penWidth), scaleFont);
752
if ( !d_data->title.isEmpty() )
753
dim += titleHeightForWidth(length) + d_data->spacing;
755
if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() )
756
dim += d_data->colorBar.width + d_data->spacing;
762
\brief Calculate a hint for the border distances.
764
This member function calculates the distance
765
of the scale's endpoints from the widget borders which
766
is required for the mark labels to fit into the widget.
767
The maximum of this distance an the minimum border distance
771
<ul> <li>The minimum border distance depends on the font.</ul>
772
\sa setMinBorderDist(), getMinBorderDist(), setBorderDist()
774
void QwtScaleWidget::getBorderDistHint(int &start, int &end) const
776
d_data->scaleDraw->getBorderDistHint(font(), start, end);
778
if ( start < d_data->minBorderDist[0] )
779
start = d_data->minBorderDist[0];
781
if ( end < d_data->minBorderDist[1] )
782
end = d_data->minBorderDist[1];
786
Set a minimum value for the distances of the scale's endpoints from
787
the widget borders. This is useful to avoid that the scales
788
are "jumping", when the tick labels or their positions change
791
\sa getMinBorderDist(), getBorderDistHint()
793
void QwtScaleWidget::setMinBorderDist(int start, int end)
795
d_data->minBorderDist[0] = start;
796
d_data->minBorderDist[1] = end;
800
Get the minimum value for the distances of the scale's endpoints from
803
\sa setMinBorderDist(), getBorderDistHint()
805
void QwtScaleWidget::getMinBorderDist(int &start, int &end) const
807
start = d_data->minBorderDist[0];
808
end = d_data->minBorderDist[1];
811
#if QT_VERSION < 0x040000
814
\brief Notify a change of the font
816
This virtual function may be overloaded by derived widgets.
817
The default implementation resizes the scale and repaints
819
\param oldFont Previous font
821
void QwtScaleWidget::fontChange(const QFont &oldFont)
823
QWidget::fontChange( oldFont );
830
\brief Assign a scale division
832
The scale division determines where to set the tick marks.
834
\param transformation Transformation, needed to translate between
835
scale and pixal values
836
\param scaleDiv Scale Division
837
\sa For more information about scale divisions, see QwtScaleDiv.
839
void QwtScaleWidget::setScaleDiv(
840
QwtScaleTransformation *transformation,
841
const QwtScaleDiv &scaleDiv)
843
QwtScaleDraw *sd = d_data->scaleDraw;
844
if (sd->scaleDiv() != scaleDiv ||
845
sd->map().transformation()->type() != transformation->type() )
847
sd->setTransformation(transformation);
848
sd->setScaleDiv(scaleDiv);
851
emit scaleDivChanged();
854
delete transformation;
857
void QwtScaleWidget::setColorBarEnabled(bool on)
859
if ( on != d_data->colorBar.isEnabled )
861
d_data->colorBar.isEnabled = on;
866
bool QwtScaleWidget::isColorBarEnabled() const
868
return d_data->colorBar.isEnabled;
872
void QwtScaleWidget::setColorBarWidth(int width)
874
if ( width != d_data->colorBar.width )
876
d_data->colorBar.width = width;
877
if ( isColorBarEnabled() )
882
int QwtScaleWidget::colorBarWidth() const
884
return d_data->colorBar.width;
887
QwtDoubleInterval QwtScaleWidget::colorBarInterval() const
889
return d_data->colorBar.interval;
892
void QwtScaleWidget::setColorMap(const QwtDoubleInterval &interval,
893
const QwtColorMap &colorMap)
895
d_data->colorBar.interval = interval;
897
delete d_data->colorBar.colorMap;
898
d_data->colorBar.colorMap = colorMap.copy();
900
if ( isColorBarEnabled() )
904
const QwtColorMap &QwtScaleWidget::colorMap() const
906
return *d_data->colorBar.colorMap;