qwt_scale_widget.cpp
Go to the documentation of this file.
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 #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 
28 {
29 public:
31  scaleDraw( NULL )
32  {
33  colorBar.colorMap = NULL;
34  }
35 
37  {
38  delete scaleDraw;
39  delete colorBar.colorMap;
40  }
41 
43 
44  int borderDist[2];
45  int minBorderDist[2];
47  int margin;
48 
50  int spacing;
52 
54 
55  struct t_colorBar
56  {
57  bool isEnabled;
58  int width;
61  } colorBar;
62 };
63 
68 QwtScaleWidget::QwtScaleWidget( QWidget *parent ):
69  QWidget( parent )
70 {
72 }
73 
80  QwtScaleDraw::Alignment align, QWidget *parent ):
81  QWidget( parent )
82 {
83  initScale( align );
84 }
85 
88 {
89  delete d_data;
90 }
91 
94 {
95  d_data = new PrivateData;
96 
97  if ( align == QwtScaleDraw::RightScale )
99 
100  d_data->borderDist[0] = 0;
101  d_data->borderDist[1] = 0;
102  d_data->minBorderDist[0] = 0;
103  d_data->minBorderDist[1] = 0;
104  d_data->margin = 4;
105  d_data->titleOffset = 0;
106  d_data->spacing = 2;
107 
109  d_data->scaleDraw->setAlignment( align );
110  d_data->scaleDraw->setLength( 10 );
111 
113  QwtLinearScaleEngine().divideScale( 0.0, 100.0, 10, 5 ) );
114 
116  d_data->colorBar.isEnabled = false;
117  d_data->colorBar.width = 10;
118 
119  const int flags = Qt::AlignHCenter
120  | Qt::TextExpandTabs | Qt::TextWordWrap;
121  d_data->title.setRenderFlags( flags );
122  d_data->title.setFont( font() );
123 
124  QSizePolicy policy( QSizePolicy::MinimumExpanding,
125  QSizePolicy::Fixed );
126  if ( d_data->scaleDraw->orientation() == Qt::Vertical )
127  policy.transpose();
128 
129  setSizePolicy( policy );
130 
131  setAttribute( Qt::WA_WState_OwnSizePolicy, false );
132 }
133 
143 {
144  if ( ( ( d_data->layoutFlags & flag ) != 0 ) != on )
145  {
146  if ( on )
147  d_data->layoutFlags |= flag;
148  else
149  d_data->layoutFlags &= ~flag;
150 
151  update();
152  }
153 }
154 
163 {
164  return ( d_data->layoutFlags & flag );
165 }
166 
173 void QwtScaleWidget::setTitle( const QString &title )
174 {
175  if ( d_data->title.text() != title )
176  {
177  d_data->title.setText( title );
178  layoutScale();
179  }
180 }
181 
192 {
193  QwtText t = title;
194  const int flags = title.renderFlags() & ~( Qt::AlignTop | Qt::AlignBottom );
195  t.setRenderFlags( flags );
196 
197  if ( t != d_data->title )
198  {
199  d_data->title = t;
200  layoutScale();
201  }
202 }
203 
211 {
212  if ( d_data->scaleDraw )
213  d_data->scaleDraw->setAlignment( alignment );
214 
215  if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
216  {
217  QSizePolicy policy( QSizePolicy::MinimumExpanding,
218  QSizePolicy::Fixed );
219  if ( d_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 
251 void QwtScaleWidget::setBorderDist( int dist1, int dist2 )
252 {
253  if ( dist1 != d_data->borderDist[0] || dist2 != d_data->borderDist[1] )
254  {
255  d_data->borderDist[0] = dist1;
256  d_data->borderDist[1] = dist2;
257  layoutScale();
258  }
259 }
260 
267 {
268  margin = qMax( 0, margin );
269  if ( margin != d_data->margin )
270  {
271  d_data->margin = margin;
272  layoutScale();
273  }
274 }
275 
282 {
283  spacing = qMax( 0, spacing );
284  if ( spacing != d_data->spacing )
285  {
287  layoutScale();
288  }
289 }
290 
297 {
298  d_data->scaleDraw->setLabelAlignment( alignment );
299  layoutScale();
300 }
301 
309 void QwtScaleWidget::setLabelRotation( double rotation )
310 {
311  d_data->scaleDraw->setLabelRotation( rotation );
312  layoutScale();
313 }
314 
327 {
328  if ( ( scaleDraw == NULL ) || ( scaleDraw == d_data->scaleDraw ) )
329  return;
330 
331  const QwtScaleDraw* sd = d_data->scaleDraw;
332  if ( sd )
333  {
334  scaleDraw->setAlignment( sd->alignment() );
335  scaleDraw->setScaleDiv( sd->scaleDiv() );
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 d_data->scaleDraw;
346 
347  layoutScale();
348 }
349 
355 {
356  return d_data->scaleDraw;
357 }
358 
364 {
365  return d_data->scaleDraw;
366 }
367 
373 {
374  return d_data->title;
375 }
376 
382 {
383  return d_data->borderDist[0];
384 }
385 
391 {
392  return d_data->borderDist[1];
393 }
394 
400 {
401  return d_data->margin;
402 }
403 
409 {
410  return d_data->spacing;
411 }
412 
416 void 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 
431 void QwtScaleWidget::draw( QPainter *painter ) const
432 {
433  d_data->scaleDraw->draw( painter, palette() );
434 
435  if ( d_data->colorBar.isEnabled && d_data->colorBar.width > 0 &&
437  {
438  drawColorBar( painter, colorBarRect( contentsRect() ) );
439  }
440 
441  QRect r = contentsRect();
442  if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
443  {
444  r.setLeft( r.left() + d_data->borderDist[0] );
445  r.setWidth( r.width() - d_data->borderDist[1] );
446  }
447  else
448  {
449  r.setTop( r.top() + d_data->borderDist[0] );
450  r.setHeight( r.height() - d_data->borderDist[1] );
451  }
452 
453  if ( !d_data->title.isEmpty() )
454  drawTitle( painter, d_data->scaleDraw->alignment(), r );
455 }
456 
463 QRectF QwtScaleWidget::colorBarRect( const QRectF& rect ) const
464 {
465  QRectF cr = rect;
466 
467  if ( d_data->scaleDraw->orientation() == Qt::Horizontal )
468  {
469  cr.setLeft( cr.left() + d_data->borderDist[0] );
470  cr.setWidth( cr.width() - d_data->borderDist[1] + 1 );
471  }
472  else
473  {
474  cr.setTop( cr.top() + d_data->borderDist[0] );
475  cr.setHeight( cr.height() - d_data->borderDist[1] + 1 );
476  }
477 
478  switch ( d_data->scaleDraw->alignment() )
479  {
481  {
482  cr.setLeft( cr.right() - d_data->margin
483  - d_data->colorBar.width );
484  cr.setWidth( d_data->colorBar.width );
485  break;
486  }
487 
489  {
490  cr.setLeft( cr.left() + d_data->margin );
491  cr.setWidth( d_data->colorBar.width );
492  break;
493  }
494 
496  {
497  cr.setTop( cr.top() + d_data->margin );
498  cr.setHeight( d_data->colorBar.width );
499  break;
500  }
501 
503  {
504  cr.setTop( cr.bottom() - d_data->margin
505  - d_data->colorBar.width );
506  cr.setHeight( d_data->colorBar.width );
507  break;
508  }
509  }
510 
511  return cr;
512 }
513 
520 void QwtScaleWidget::changeEvent( QEvent *event )
521 {
522  if ( event->type() == QEvent::LocaleChange )
523  {
525  }
526 
527  QWidget::changeEvent( event );
528 }
529 
534 void QwtScaleWidget::resizeEvent( QResizeEvent *event )
535 {
536  Q_UNUSED( event );
537  layoutScale( false );
538 }
539 
548 void QwtScaleWidget::layoutScale( bool update_geometry )
549 {
550  int bd0, bd1;
551  getBorderDistHint( bd0, bd1 );
552  if ( d_data->borderDist[0] > bd0 )
553  bd0 = d_data->borderDist[0];
554  if ( d_data->borderDist[1] > bd1 )
555  bd1 = d_data->borderDist[1];
556 
557  int colorBarWidth = 0;
559  colorBarWidth = d_data->colorBar.width + d_data->spacing;
560 
561  const QRectF r = contentsRect();
562  double x, y, length;
563 
564  if ( d_data->scaleDraw->orientation() == Qt::Vertical )
565  {
566  y = r.top() + bd0;
567  length = r.height() - ( bd0 + bd1 );
568 
570  x = r.right() - 1.0 - d_data->margin - colorBarWidth;
571  else
572  x = r.left() + d_data->margin + colorBarWidth;
573  }
574  else
575  {
576  x = r.left() + bd0;
577  length = r.width() - ( bd0 + bd1 );
578 
580  y = r.top() + d_data->margin + colorBarWidth;
581  else
582  y = r.bottom() - 1.0 - d_data->margin - colorBarWidth;
583  }
584 
585  d_data->scaleDraw->move( x, y );
586  d_data->scaleDraw->setLength( length );
587 
588  const int extent = qwtCeil( d_data->scaleDraw->extent( font() ) );
589 
591  d_data->margin + d_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 
625 void QwtScaleWidget::drawColorBar( QPainter *painter, const QRectF& rect ) const
626 {
627  if ( !d_data->colorBar.interval.isValid() )
628  return;
629 
630  const QwtScaleDraw* sd = d_data->scaleDraw;
631 
634  sd->orientation(), rect );
635 }
636 
645 void QwtScaleWidget::drawTitle( QPainter *painter,
646  QwtScaleDraw::Alignment align, const QRectF &rect ) const
647 {
648  QRectF r = rect;
649  double angle;
650  int flags = d_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() - d_data->titleOffset );
660  break;
661 
663  angle = -90.0;
664  flags |= Qt::AlignTop;
665  r.setRect( r.left() + d_data->titleOffset, r.bottom(),
666  r.height(), r.width() - d_data->titleOffset );
667  break;
668 
670  angle = 0.0;
671  flags |= Qt::AlignBottom;
672  r.setTop( r.top() + d_data->titleOffset );
673  break;
674 
676  default:
677  angle = 0.0;
678  flags |= Qt::AlignTop;
679  r.setBottom( r.bottom() - d_data->titleOffset );
680  break;
681  }
682 
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 
703  title.setRenderFlags( flags );
704  title.draw( painter, QRectF( 0.0, 0.0, r.width(), r.height() ) );
705 
706  painter->restore();
707 }
708 
718 {
719  layoutScale();
720 }
721 
726 {
727  return minimumSizeHint();
728 }
729 
734 {
735  const Qt::Orientation o = d_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, d_data->borderDist[0] - mbd1 );
743  length += qMax( 0, d_data->borderDist[1] - mbd2 );
744  length += d_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( d_data->title.heightForWidth( width, font() ) );
771 }
772 
782 int QwtScaleWidget::dimForLength( int length, const QFont &scaleFont ) const
783 {
784  const int extent = qwtCeil( d_data->scaleDraw->extent( scaleFont ) );
785 
786  int dim = d_data->margin + extent + 1;
787 
788  if ( !d_data->title.isEmpty() )
789  dim += titleHeightForWidth( length ) + d_data->spacing;
790 
792  dim += d_data->colorBar.width + d_data->spacing;
793 
794  return dim;
795 }
796 
815 void QwtScaleWidget::getBorderDistHint( int &start, int &end ) const
816 {
817  d_data->scaleDraw->getBorderDistHint( font(), start, end );
818 
819  if ( start < d_data->minBorderDist[0] )
820  start = d_data->minBorderDist[0];
821 
822  if ( end < d_data->minBorderDist[1] )
823  end = d_data->minBorderDist[1];
824 }
825 
836 void QwtScaleWidget::setMinBorderDist( int start, int end )
837 {
838  d_data->minBorderDist[0] = start;
839  d_data->minBorderDist[1] = end;
840 }
841 
853 void QwtScaleWidget::getMinBorderDist( int &start, int &end ) const
854 {
855  start = d_data->minBorderDist[0];
856  end = d_data->minBorderDist[1];
857 }
858 
868 {
870  if ( sd->scaleDiv() != scaleDiv )
871  {
872  sd->setScaleDiv( scaleDiv );
873  layoutScale();
874 
875  Q_EMIT scaleDivChanged();
876  }
877 }
878 
886 {
887  d_data->scaleDraw->setTransformation( transformation );
888  layoutScale();
889 }
890 
896 {
897  if ( on != d_data->colorBar.isEnabled )
898  {
899  d_data->colorBar.isEnabled = on;
900  layoutScale();
901  }
902 }
903 
909 {
910  return d_data->colorBar.isEnabled;
911 }
912 
920 {
921  if ( width != d_data->colorBar.width )
922  {
923  d_data->colorBar.width = width;
924  if ( isColorBarEnabled() )
925  layoutScale();
926  }
927 }
928 
934 {
935  return d_data->colorBar.width;
936 }
937 
943 {
944  return d_data->colorBar.interval;
945 }
946 
957  const QwtInterval &interval, QwtColorMap *colorMap )
958 {
959  d_data->colorBar.interval = interval;
960 
961  if ( colorMap != d_data->colorBar.colorMap )
962  {
963  delete d_data->colorBar.colorMap;
965  }
966 
967  if ( isColorBarEnabled() )
968  layoutScale();
969 }
970 
976 {
977  return d_data->colorBar.colorMap;
978 }
979 
980 #if QWT_MOC_INCLUDE
981 #include "moc_qwt_scale_widget.cpp"
982 #endif
Definition: format.h:1173
void scaleDivChanged()
Signal emitted, whenever the scale division changes.
QwtInterval normalized() const
Normalize the limits of the interval.
void setAlignment(Alignment)
void setLength(double length)
void setColorBarEnabled(bool)
virtual ~QwtScaleWidget()
Destructor.
void setFont(const QFont &)
Definition: qwt_text.cpp:306
void setColorMap(const QwtInterval &, QwtColorMap *)
void initScale(QwtScaleDraw::Alignment)
Initialize the scale.
int renderFlags() const
Definition: qwt_text.cpp:294
A class representing an interval.
Definition: qwt_interval.h:22
void setRenderFlags(int)
Change the render flags.
Definition: qwt_text.cpp:281
void setText(const QString &, QwtText::TextFormat textFormat=AutoText)
Definition: qwt_text.cpp:254
QwtScaleWidget::LayoutFlags layoutFlags
int margin() const
The scale is above.
static void drawColorBar(QPainter *, const QwtColorMap &, const QwtInterval &, const QwtScaleMap &, Qt::Orientation, const QRectF &)
int titleHeightForWidth(int width) const
Find the height of the title for a given width.
virtual QwtTransform * copy() const =0
Virtualized copy operation.
void setScaleDiv(const QwtScaleDiv &)
Assign a scale division.
void setLabelAlignment(Qt::Alignment)
Change the alignment for the labels.
void draw(QPainter *painter, const QRectF &rect) const
Definition: qwt_text.cpp:592
A class representing a scale division.
Definition: qwt_scale_div.h:33
const QwtScaleMap & scaleMap() const
void setMargin(int)
Specify the margin to the colorBar/base line.
const QwtScaleDraw * scaleDraw() const
void getBorderDistHint(const QFont &, int &start, int &end) const
Determine the minimum border distance.
void setLabelRotation(double rotation)
Change the rotation for the labels. See QwtScaleDraw::setLabelRotation().
LayoutFlag
Layout flags of the title.
QwtScaleDraw::Alignment alignment() const
int minLength(const QFont &) const
void setAlignment(QwtScaleDraw::Alignment)
virtual QSize minimumSizeHint() const QWT_OVERRIDE
PrivateData * d_data
double heightForWidth(double width) const
Definition: qwt_text.cpp:499
int startBorderDist() const
virtual QSize sizeHint() const QWT_OVERRIDE
void getMinBorderDist(int &start, int &end) const
void draw(QPainter *) const
draw the scale
Alignment alignment() const
The scale is left.
QwtInterval colorBarInterval() const
void setTitle(const QString &title)
virtual void paintEvent(QPaintEvent *) QWT_OVERRIDE
paintEvent
QRectF colorBarRect(const QRectF &) const
void drawTitle(QPainter *, QwtScaleDraw::Alignment, const QRectF &rect) const
struct QwtScaleWidget::PrivateData::t_colorBar colorBar
const QwtScaleDiv & scaleDiv() const
bool isEmpty() const
Definition: qwt_text.cpp:716
bool isValid() const
Definition: qwt_interval.h:208
A transformation between coordinate systems.
Definition: qwt_transform.h:35
virtual void resizeEvent(QResizeEvent *) QWT_OVERRIDE
A class representing a text.
Definition: qwt_text.h:51
void setMinBorderDist(int start, int end)
QString text() const
Definition: qwt_text.cpp:266
QwtColorMap is used to map values into colors.
Definition: qwt_color_map.h:34
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 ...
bool testLayoutFlag(LayoutFlag) const
void setScaleDiv(const QwtScaleDiv &)
void setColorBarWidth(int)
void setLabelRotation(double rotation)
virtual void changeEvent(QEvent *) QWT_OVERRIDE
const QwtTransform * transformation() const
Get the transformation.
QwtLinearColorMap builds a color map from color stops.
Definition: qwt_color_map.h:96
Qt::Orientation orientation() const
int endBorderDist() const
int spacing() const
int colorBarWidth() const
virtual void draw(QPainter *, const QPalette &) const
Draw the scale.
void setBorderDist(int dist1, int dist2)
QwtScaleWidget(QWidget *parent=NULL)
Create a scale with the position QwtScaleWidget::Left.
void setLayoutFlag(LayoutFlag, bool on)
bool isColorBarEnabled() const
The scale is right.
QFlags< LayoutFlag > LayoutFlags
Layout flags of the title.
void getBorderDistHint(int &start, int &end) const
Calculate a hint for the border distances.
virtual double extent(const QFont &) const QWT_OVERRIDE
void setTransformation(QwtTransform *)
void layoutScale(bool update_geometry=true)
A class for drawing scales.
A scale engine for linear scales.
void setTransformation(QwtTransform *)
QwtText title() const
void setScaleDraw(QwtScaleDraw *)
void scaleChange()
Notify a change of the scale.
void drawColorBar(QPainter *, const QRectF &) const
const QwtColorMap * colorMap() const
void setLabelAlignment(Qt::Alignment)
Change the label flags.
int qwtCeil(qreal value)
Definition: qwt_math.h:262
The scale is below.
void setSpacing(int)
Specify the distance between color bar, scale and title.
void move(double x, double y)


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10