Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
qwt_scale_widget.cpp
1/******************************************************************************
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#include "qwt_scale_widget.h"
11#include "qwt_painter.h"
12#include "qwt_color_map.h"
13#include "qwt_scale_map.h"
14#include "qwt_math.h"
15#include "qwt_scale_div.h"
16#include "qwt_text.h"
17#include "qwt_interval.h"
18#include "qwt_scale_engine.h"
19
20#include <qpainter.h>
21#include <qevent.h>
22#include <qstyle.h>
23#include <qstyleoption.h>
24#include <qapplication.h>
25#include <qmargins.h>
26
27class QwtScaleWidget::PrivateData
28{
29 public:
30 PrivateData()
31 : scaleDraw( NULL )
32 {
33 colorBar.colorMap = NULL;
34 }
35
36 ~PrivateData()
37 {
38 delete scaleDraw;
39 delete colorBar.colorMap;
40 }
41
42 QwtScaleDraw* scaleDraw;
43
44 int borderDist[2];
45 int minBorderDist[2];
46 int scaleLength;
47 int margin;
48
49 int titleOffset;
50 int spacing;
51 QwtText title;
52
54
55 struct t_colorBar
56 {
57 bool isEnabled;
58 int width;
59 QwtInterval interval;
60 QwtColorMap* colorMap;
61 } colorBar;
62};
63
69 : QWidget( parent )
70{
71 initScale( QwtScaleDraw::LeftScale );
72}
73
80 : QWidget( parent )
81{
82 initScale( align );
83}
84
87{
88 delete m_data;
89}
90
92void QwtScaleWidget::initScale( QwtScaleDraw::Alignment align )
93{
94 m_data = new PrivateData;
95
96 if ( align == QwtScaleDraw::RightScale )
97 m_data->layoutFlags |= TitleInverted;
98
99 m_data->borderDist[0] = 0;
100 m_data->borderDist[1] = 0;
101 m_data->minBorderDist[0] = 0;
102 m_data->minBorderDist[1] = 0;
103 m_data->margin = 4;
104 m_data->titleOffset = 0;
105 m_data->spacing = 2;
106
107 m_data->scaleDraw = new QwtScaleDraw;
108 m_data->scaleDraw->setAlignment( align );
109 m_data->scaleDraw->setLength( 10 );
110
111 m_data->scaleDraw->setScaleDiv(
112 QwtLinearScaleEngine().divideScale( 0.0, 100.0, 10, 5 ) );
113
114 m_data->colorBar.colorMap = new QwtLinearColorMap();
115 m_data->colorBar.isEnabled = false;
116 m_data->colorBar.width = 10;
117
118 const int flags = Qt::AlignHCenter
119 | Qt::TextExpandTabs | Qt::TextWordWrap;
120 m_data->title.setRenderFlags( flags );
121 m_data->title.setFont( font() );
122
123 QSizePolicy policy( QSizePolicy::MinimumExpanding,
124 QSizePolicy::Fixed );
125 if ( m_data->scaleDraw->orientation() == Qt::Vertical )
126 policy.transpose();
127
128 setSizePolicy( policy );
129
130 setAttribute( Qt::WA_WState_OwnSizePolicy, false );
131}
132
142{
143 if ( ( ( m_data->layoutFlags & flag ) != 0 ) != on )
144 {
145 if ( on )
146 m_data->layoutFlags |= flag;
147 else
148 m_data->layoutFlags &= ~flag;
149
150 update();
151 }
152}
153
162{
163 return ( m_data->layoutFlags & flag );
164}
165
172void QwtScaleWidget::setTitle( const QString& title )
173{
174 if ( m_data->title.text() != title )
175 {
176 m_data->title.setText( title );
177 layoutScale();
178 }
179}
180
191{
192 QwtText t = title;
193 const int flags = title.renderFlags() & ~( Qt::AlignTop | Qt::AlignBottom );
194 t.setRenderFlags( flags );
195
196 if ( t != m_data->title )
197 {
198 m_data->title = t;
199 layoutScale();
200 }
201}
202
210{
211 if ( m_data->scaleDraw == NULL )
212 return;
213
214 m_data->scaleDraw->setAlignment( alignment );
215
216 if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
217 {
218 QSizePolicy policy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
219 if ( m_data->scaleDraw->orientation() == Qt::Vertical )
220 policy.transpose();
221
222 setSizePolicy( policy );
223
224 setAttribute( Qt::WA_WState_OwnSizePolicy, false );
225 }
226
227 layoutScale();
228}
229
230
236{
237 if ( !scaleDraw() )
239
240 return scaleDraw()->alignment();
241}
242
251void QwtScaleWidget::setBorderDist( int dist1, int dist2 )
252{
253 if ( dist1 != m_data->borderDist[0] || dist2 != m_data->borderDist[1] )
254 {
255 m_data->borderDist[0] = dist1;
256 m_data->borderDist[1] = dist2;
257 layoutScale();
258 }
259}
260
267{
268 margin = qMax( 0, margin );
269 if ( margin != m_data->margin )
270 {
271 m_data->margin = margin;
272 layoutScale();
273 }
274}
275
281void QwtScaleWidget::setSpacing( int spacing )
282{
283 spacing = qMax( 0, spacing );
284 if ( spacing != m_data->spacing )
285 {
286 m_data->spacing = spacing;
287 layoutScale();
288 }
289}
290
296void QwtScaleWidget::setLabelAlignment( Qt::Alignment alignment )
297{
298 m_data->scaleDraw->setLabelAlignment( alignment );
299 layoutScale();
300}
301
309void QwtScaleWidget::setLabelRotation( double rotation )
310{
311 m_data->scaleDraw->setLabelRotation( rotation );
312 layoutScale();
313}
314
327{
328 if ( ( scaleDraw == NULL ) || ( scaleDraw == m_data->scaleDraw ) )
329 return;
330
331 const QwtScaleDraw* sd = m_data->scaleDraw;
332 if ( sd )
333 {
336
337 QwtTransform* transform = NULL;
338 if ( sd->scaleMap().transformation() )
339 transform = sd->scaleMap().transformation()->copy();
340
341 scaleDraw->setTransformation( transform );
342 }
343
344 delete m_data->scaleDraw;
345 m_data->scaleDraw = scaleDraw;
346
347 layoutScale();
348}
349
355{
356 return m_data->scaleDraw;
357}
358
364{
365 return m_data->scaleDraw;
366}
367
373{
374 return m_data->title;
375}
376
382{
383 return m_data->borderDist[0];
384}
385
391{
392 return m_data->borderDist[1];
393}
394
400{
401 return m_data->margin;
402}
403
409{
410 return m_data->spacing;
411}
412
416void QwtScaleWidget::paintEvent( QPaintEvent* event )
417{
418 QPainter painter( this );
419 painter.setClipRegion( event->region() );
420
421 QStyleOption opt;
422 opt.initFrom(this);
423 style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
424
425 draw( &painter );
426}
427
431void QwtScaleWidget::draw( QPainter* painter ) const
432{
433 m_data->scaleDraw->draw( painter, palette() );
434
435 if ( m_data->colorBar.isEnabled && m_data->colorBar.width > 0 &&
436 m_data->colorBar.interval.isValid() )
437 {
438 drawColorBar( painter, colorBarRect( contentsRect() ) );
439 }
440
441 QRect r = contentsRect();
442 if ( m_data->scaleDraw->orientation() == Qt::Horizontal )
443 {
444 r.setLeft( r.left() + m_data->borderDist[0] );
445 r.setWidth( r.width() - m_data->borderDist[1] );
446 }
447 else
448 {
449 r.setTop( r.top() + m_data->borderDist[0] );
450 r.setHeight( r.height() - m_data->borderDist[1] );
451 }
452
453 if ( !m_data->title.isEmpty() )
454 drawTitle( painter, m_data->scaleDraw->alignment(), r );
455}
456
463QRectF QwtScaleWidget::colorBarRect( const QRectF& rect ) const
464{
465 QRectF cr = rect;
466
467 if ( m_data->scaleDraw->orientation() == Qt::Horizontal )
468 {
469 cr.setLeft( cr.left() + m_data->borderDist[0] );
470 cr.setWidth( cr.width() - m_data->borderDist[1] + 1 );
471 }
472 else
473 {
474 cr.setTop( cr.top() + m_data->borderDist[0] );
475 cr.setHeight( cr.height() - m_data->borderDist[1] + 1 );
476 }
477
478 switch ( m_data->scaleDraw->alignment() )
479 {
481 {
482 cr.setLeft( cr.right() - m_data->margin
483 - m_data->colorBar.width );
484 cr.setWidth( m_data->colorBar.width );
485 break;
486 }
487
489 {
490 cr.setLeft( cr.left() + m_data->margin );
491 cr.setWidth( m_data->colorBar.width );
492 break;
493 }
494
496 {
497 cr.setTop( cr.top() + m_data->margin );
498 cr.setHeight( m_data->colorBar.width );
499 break;
500 }
501
503 {
504 cr.setTop( cr.bottom() - m_data->margin
505 - m_data->colorBar.width );
506 cr.setHeight( m_data->colorBar.width );
507 break;
508 }
509 }
510
511 return cr;
512}
513
520void QwtScaleWidget::changeEvent( QEvent* event )
521{
522 if ( event->type() == QEvent::LocaleChange )
523 {
524 m_data->scaleDraw->invalidateCache();
525 }
526
527 QWidget::changeEvent( event );
528}
529
534void QwtScaleWidget::resizeEvent( QResizeEvent* event )
535{
536 Q_UNUSED( event );
537 layoutScale( false );
538}
539
548void QwtScaleWidget::layoutScale( bool update_geometry )
549{
550 int bd0, bd1;
551 getBorderDistHint( bd0, bd1 );
552 if ( m_data->borderDist[0] > bd0 )
553 bd0 = m_data->borderDist[0];
554 if ( m_data->borderDist[1] > bd1 )
555 bd1 = m_data->borderDist[1];
556
557 int colorBarWidth = 0;
558 if ( m_data->colorBar.isEnabled && m_data->colorBar.interval.isValid() )
559 colorBarWidth = m_data->colorBar.width + m_data->spacing;
560
561 const QRectF r = contentsRect();
562 double x, y, length;
563
564 if ( m_data->scaleDraw->orientation() == Qt::Vertical )
565 {
566 y = r.top() + bd0;
567 length = r.height() - ( bd0 + bd1 );
568
569 if ( m_data->scaleDraw->alignment() == QwtScaleDraw::LeftScale )
570 x = r.right() - 1.0 - m_data->margin - colorBarWidth;
571 else
572 x = r.left() + m_data->margin + colorBarWidth;
573 }
574 else
575 {
576 x = r.left() + bd0;
577 length = r.width() - ( bd0 + bd1 );
578
579 if ( m_data->scaleDraw->alignment() == QwtScaleDraw::BottomScale )
580 y = r.top() + m_data->margin + colorBarWidth;
581 else
582 y = r.bottom() - 1.0 - m_data->margin - colorBarWidth;
583 }
584
585 m_data->scaleDraw->move( x, y );
586 m_data->scaleDraw->setLength( length );
587
588 const int extent = qwtCeil( m_data->scaleDraw->extent( font() ) );
589
590 m_data->titleOffset =
591 m_data->margin + m_data->spacing + colorBarWidth + extent;
592
593 if ( update_geometry )
594 {
595 updateGeometry();
596
597#if 1
598 /*
599 for some reason updateGeometry does not send a LayoutRequest event
600 when the parent is not visible and has no layout
601 */
602
603 if ( QWidget* w = parentWidget() )
604 {
605 if ( !w->isVisible() && w->layout() == NULL )
606 {
607 if ( w->testAttribute( Qt::WA_WState_Polished ) )
608 QApplication::postEvent( w, new QEvent( QEvent::LayoutRequest ) );
609 }
610 }
611#endif
612
613 update();
614 }
615}
616
625void QwtScaleWidget::drawColorBar( QPainter* painter, const QRectF& rect ) const
626{
627 if ( !m_data->colorBar.interval.isValid() )
628 return;
629
630 const QwtScaleDraw* sd = m_data->scaleDraw;
631
632 QwtPainter::drawColorBar( painter, *m_data->colorBar.colorMap,
633 m_data->colorBar.interval.normalized(), sd->scaleMap(),
634 sd->orientation(), rect );
635}
636
645void QwtScaleWidget::drawTitle( QPainter* painter,
646 QwtScaleDraw::Alignment align, const QRectF& rect ) const
647{
648 QRectF r = rect;
649 double angle;
650 int flags = m_data->title.renderFlags() &
651 ~( Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter );
652
653 switch ( align )
654 {
656 angle = -90.0;
657 flags |= Qt::AlignTop;
658 r.setRect( r.left(), r.bottom(),
659 r.height(), r.width() - m_data->titleOffset );
660 break;
661
663 angle = -90.0;
664 flags |= Qt::AlignTop;
665 r.setRect( r.left() + m_data->titleOffset, r.bottom(),
666 r.height(), r.width() - m_data->titleOffset );
667 break;
668
670 angle = 0.0;
671 flags |= Qt::AlignBottom;
672 r.setTop( r.top() + m_data->titleOffset );
673 break;
674
676 default:
677 angle = 0.0;
678 flags |= Qt::AlignTop;
679 r.setBottom( r.bottom() - m_data->titleOffset );
680 break;
681 }
682
683 if ( m_data->layoutFlags & TitleInverted )
684 {
685 if ( align == QwtScaleDraw::LeftScale
686 || align == QwtScaleDraw::RightScale )
687 {
688 angle = -angle;
689 r.setRect( r.x() + r.height(), r.y() - r.width(),
690 r.width(), r.height() );
691 }
692 }
693
694 painter->save();
695 painter->setFont( font() );
696 painter->setPen( palette().color( QPalette::Text ) );
697
698 painter->translate( r.x(), r.y() );
699 if ( angle != 0.0 )
700 painter->rotate( angle );
701
702 QwtText title = m_data->title;
703 title.setRenderFlags( flags );
704 title.draw( painter, QRectF( 0.0, 0.0, r.width(), r.height() ) );
705
706 painter->restore();
707}
708
721
726{
727 return minimumSizeHint();
728}
729
734{
735 const Qt::Orientation o = m_data->scaleDraw->orientation();
736
737 // Border Distance cannot be less than the scale borderDistHint
738 // Note, the borderDistHint is already included in minHeight/minWidth
739 int length = 0;
740 int mbd1, mbd2;
741 getBorderDistHint( mbd1, mbd2 );
742 length += qMax( 0, m_data->borderDist[0] - mbd1 );
743 length += qMax( 0, m_data->borderDist[1] - mbd2 );
744 length += m_data->scaleDraw->minLength( font() );
745
746 int dim = dimForLength( length, font() );
747 if ( length < dim )
748 {
749 // compensate for long titles
750 length = dim;
751 dim = dimForLength( length, font() );
752 }
753
754 QSize size( length + 2, dim );
755 if ( o == Qt::Vertical )
756 size.transpose();
757
758 const QMargins m = contentsMargins();
759 return size + QSize( m.left() + m.right(), m.top() + m.bottom() );
760}
761
769{
770 return qwtCeil( m_data->title.heightForWidth( width, font() ) );
771}
772
782int QwtScaleWidget::dimForLength( int length, const QFont& scaleFont ) const
783{
784 const int extent = qwtCeil( m_data->scaleDraw->extent( scaleFont ) );
785
786 int dim = m_data->margin + extent + 1;
787
788 if ( !m_data->title.isEmpty() )
789 dim += titleHeightForWidth( length ) + m_data->spacing;
790
791 if ( m_data->colorBar.isEnabled && m_data->colorBar.interval.isValid() )
792 dim += m_data->colorBar.width + m_data->spacing;
793
794 return dim;
795}
796
815void QwtScaleWidget::getBorderDistHint( int& start, int& end ) const
816{
817 m_data->scaleDraw->getBorderDistHint( font(), start, end );
818
819 if ( start < m_data->minBorderDist[0] )
820 start = m_data->minBorderDist[0];
821
822 if ( end < m_data->minBorderDist[1] )
823 end = m_data->minBorderDist[1];
824}
825
836void QwtScaleWidget::setMinBorderDist( int start, int end )
837{
838 m_data->minBorderDist[0] = start;
839 m_data->minBorderDist[1] = end;
840}
841
853void QwtScaleWidget::getMinBorderDist( int& start, int& end ) const
854{
855 start = m_data->minBorderDist[0];
856 end = m_data->minBorderDist[1];
857}
858
868{
869 QwtScaleDraw* sd = m_data->scaleDraw;
870 if ( sd->scaleDiv() != scaleDiv )
871 {
872 sd->setScaleDiv( scaleDiv );
873 layoutScale();
874
875 Q_EMIT scaleDivChanged();
876 }
877}
878
886{
887 m_data->scaleDraw->setTransformation( transformation );
888 layoutScale();
889}
890
896{
897 if ( on != m_data->colorBar.isEnabled )
898 {
899 m_data->colorBar.isEnabled = on;
900 layoutScale();
901 }
902}
903
909{
910 return m_data->colorBar.isEnabled;
911}
912
920{
921 if ( width != m_data->colorBar.width )
922 {
923 m_data->colorBar.width = width;
924 if ( isColorBarEnabled() )
925 layoutScale();
926 }
927}
928
934{
935 return m_data->colorBar.width;
936}
937
943{
944 return m_data->colorBar.interval;
945}
946
957 const QwtInterval& interval, QwtColorMap* colorMap )
958{
959 m_data->colorBar.interval = interval;
960
961 if ( colorMap != m_data->colorBar.colorMap )
962 {
963 delete m_data->colorBar.colorMap;
964 m_data->colorBar.colorMap = colorMap;
965 }
966
967 if ( isColorBarEnabled() )
968 layoutScale();
969}
970
976{
977 return m_data->colorBar.colorMap;
978}
979
980#include "moc_qwt_scale_widget.cpp"
void setScaleDiv(const QwtScaleDiv &)
const QwtScaleMap & scaleMap() const
void setTransformation(QwtTransform *)
virtual void draw(QPainter *, const QPalette &) const
Draw the scale.
const QwtScaleDiv & scaleDiv() const
QwtColorMap is used to map values into colors.
A class representing an interval.
QwtInterval normalized() const
Normalize the limits of the interval.
bool isValid() const
QwtLinearColorMap builds a color map from color stops.
A scale engine for linear scales.
static void drawColorBar(QPainter *, const QwtColorMap &, const QwtInterval &, const QwtScaleMap &, Qt::Orientation, const QRectF &)
A class representing a scale division.
A class for drawing scales.
void setLength(double length)
void move(double x, double y)
virtual double extent(const QFont &) const override
void getBorderDistHint(const QFont &, int &start, int &end) const
Determine the minimum border distance.
void setLabelAlignment(Qt::Alignment)
Change the label flags.
int minLength(const QFont &) const
void setAlignment(Alignment)
Alignment alignment() const
Qt::Orientation orientation() const
void setLabelRotation(double rotation)
@ BottomScale
The scale is below.
@ TopScale
The scale is above.
@ RightScale
The scale is right.
@ LeftScale
The scale is left.
const QwtTransform * transformation() const
Get the transformation.
int startBorderDist() const
void drawColorBar(QPainter *, const QRectF &) const
QwtScaleDraw::Alignment alignment() const
QFlags< LayoutFlag > LayoutFlags
QwtText title() const
const QwtColorMap * colorMap() const
void setTitle(const QString &title)
const QwtScaleDraw * scaleDraw() const
void setMargin(int)
Specify the margin to the colorBar/base line.
void setColorMap(const QwtInterval &, QwtColorMap *)
void draw(QPainter *) const
draw the scale
void setMinBorderDist(int start, int end)
virtual QSize sizeHint() const override
virtual void changeEvent(QEvent *) override
void scaleDivChanged()
Signal emitted, whenever the scale division changes.
bool isColorBarEnabled() const
bool testLayoutFlag(LayoutFlag) const
void drawTitle(QPainter *, QwtScaleDraw::Alignment, const QRectF &rect) const
void setLayoutFlag(LayoutFlag, bool on)
void setTransformation(QwtTransform *)
int endBorderDist() const
virtual ~QwtScaleWidget()
Destructor.
void setLabelAlignment(Qt::Alignment)
Change the alignment for the labels.
void layoutScale(bool update_geometry=true)
LayoutFlag
Layout flags of the title.
virtual void paintEvent(QPaintEvent *) override
paintEvent
void getBorderDistHint(int &start, int &end) const
Calculate a hint for the border distances.
QRectF colorBarRect(const QRectF &) const
void setAlignment(QwtScaleDraw::Alignment)
int dimForLength(int length, const QFont &scaleFont) const
Find the minimum dimension for a given length. dim is the height, length the width seen in direction ...
void setBorderDist(int dist1, int dist2)
int colorBarWidth() const
void getMinBorderDist(int &start, int &end) const
virtual QSize minimumSizeHint() const override
QwtScaleWidget(QWidget *parent=NULL)
Create a scale with the position QwtScaleWidget::Left.
QwtInterval colorBarInterval() const
void setSpacing(int)
Specify the distance between color bar, scale and title.
void setLabelRotation(double rotation)
Change the rotation for the labels. See QwtScaleDraw::setLabelRotation().
void setScaleDiv(const QwtScaleDiv &)
Assign a scale division.
void setColorBarEnabled(bool)
void scaleChange()
Notify a change of the scale.
virtual void resizeEvent(QResizeEvent *) override
void setScaleDraw(QwtScaleDraw *)
int titleHeightForWidth(int width) const
Find the height of the title for a given width.
A class representing a text.
Definition qwt_text.h:52
int renderFlags() const
Definition qwt_text.cpp:317
void setText(const QString &, QwtText::TextFormat textFormat=AutoText)
Definition qwt_text.cpp:277
bool isEmpty() const
Definition qwt_text.cpp:739
void setFont(const QFont &)
Definition qwt_text.cpp:329
void draw(QPainter *painter, const QRectF &rect) const
Definition qwt_text.cpp:615
QString text() const
Definition qwt_text.cpp:289
double heightForWidth(double width) const
Definition qwt_text.cpp:522
void setRenderFlags(int)
Change the render flags.
Definition qwt_text.cpp:304
A transformation between coordinate systems.
virtual QwtTransform * copy() const =0
Virtualized copy operation.