qwt_dial.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_dial.h"
11 #include "qwt_dial_needle.h"
12 #include "qwt_math.h"
13 #include "qwt_scale_engine.h"
14 #include "qwt_scale_map.h"
15 #include "qwt_round_scale_draw.h"
16 #include "qwt_painter.h"
17 #include <qpainter.h>
18 #include <qpalette.h>
19 #include <qpixmap.h>
20 #include <qevent.h>
21 #include <qalgorithms.h>
22 #include <qmath.h>
23 #include <qstyle.h>
24 #include <qstyleoption.h>
25 #include <qapplication.h>
26 
27 static inline double qwtAngleDist( double a1, double a2 )
28 {
29  double dist = qAbs( a2 - a1 );
30  if ( dist > 360.0 )
31  dist -= 360.0;
32 
33  return dist;
34 }
35 
36 static inline bool qwtIsOnArc( double angle, double min, double max )
37 {
38  if ( min < max )
39  {
40  return ( angle >= min ) && ( angle <= max );
41  }
42  else
43  {
44  return ( angle >= min ) || ( angle <= max );
45  }
46 }
47 
48 static inline double qwtBoundedAngle( double min, double angle, double max )
49 {
50  double from = qwtNormalizeDegrees( min );
51  double to = qwtNormalizeDegrees( max );
52 
53  double a;
54 
55  if ( qwtIsOnArc( angle, from, to ) )
56  {
57  a = angle;
58  if ( a < min )
59  a += 360.0;
60  }
61  else
62  {
63  if ( qwtAngleDist( angle, from ) <
64  qwtAngleDist( angle, to ) )
65  {
66  a = min;
67  }
68  else
69  {
70  a = max;
71  }
72  }
73 
74  return a;
75 }
76 
78 {
79 public:
82  lineWidth( 0 ),
83  mode( RotateNeedle ),
84  origin( 90.0 ),
85  minScaleArc( 0.0 ),
86  maxScaleArc( 0.0 ),
87  needle( NULL ),
88  arcOffset( 0.0 ),
89  mouseOffset( 0.0 )
90  {
91  }
92 
94  {
95  delete needle;
96  }
98  int lineWidth;
99 
101 
102  double origin;
103  double minScaleArc;
104  double maxScaleArc;
105 
107 
108  double arcOffset;
109  double mouseOffset;
110 
111  QPixmap pixmapCache;
112 };
113 
126 QwtDial::QwtDial( QWidget* parent ):
127  QwtAbstractSlider( parent )
128 {
129  d_data = new PrivateData;
130 
131  setFocusPolicy( Qt::TabFocus );
132 
133  QPalette p = palette();
134  for ( int i = 0; i < QPalette::NColorGroups; i++ )
135  {
136  const QPalette::ColorGroup colorGroup =
137  static_cast<QPalette::ColorGroup>( i );
138 
139  // Base: background color of the circle inside the frame.
140  // WindowText: background color of the circle inside the scale
141 
142  p.setColor( colorGroup, QPalette::WindowText,
143  p.color( colorGroup, QPalette::Base ) );
144  }
145  setPalette( p );
146 
148  scaleDraw->setRadius( 0 );
149 
150  setScaleDraw( scaleDraw );
151 
152  setScaleArc( 0.0, 360.0 ); // scale as a full circle
153 
154  setScaleMaxMajor( 10 );
155  setScaleMaxMinor( 5 );
156 
157  setValue( 0.0 );
158 }
159 
162 {
163  delete d_data;
164 }
165 
173 {
174  if ( shadow != d_data->frameShadow )
175  {
176  invalidateCache();
177 
178  d_data->frameShadow = shadow;
179  if ( lineWidth() > 0 )
180  update();
181  }
182 }
183 
189 {
190  return d_data->frameShadow;
191 }
192 
200 {
201  if ( lineWidth < 0 )
202  lineWidth = 0;
203 
204  if ( d_data->lineWidth != lineWidth )
205  {
206  invalidateCache();
207 
209  update();
210  }
211 }
212 
217 int QwtDial::lineWidth() const
218 {
219  return d_data->lineWidth;
220 }
221 
226 QRect QwtDial::innerRect() const
227 {
228  const int lw = lineWidth();
229  return boundingRect().adjusted( lw, lw, -lw, -lw );
230 }
231 
237 {
238  const QRect cr = contentsRect();
239 
240  const double dim = qMin( cr.width(), cr.height() );
241 
242  QRect inner( 0, 0, dim, dim );
243  inner.moveCenter( cr.center() );
244 
245  return inner;
246 }
247 
253 {
254  QRect rect = innerRect();
255 
256  const QwtAbstractScaleDraw *sd = scaleDraw();
257  if ( sd )
258  {
259  int scaleDist = qCeil( sd->extent( font() ) );
260  scaleDist++; // margin
261 
262  rect.adjust( scaleDist, scaleDist, -scaleDist, -scaleDist );
263  }
264 
265  return rect;
266 }
267 
281 {
282  if ( mode != d_data->mode )
283  {
284  invalidateCache();
285 
286  d_data->mode = mode;
287  sliderChange();
288  }
289 }
290 
296 {
297  return d_data->mode;
298 }
299 
304 {
305  d_data->pixmapCache = QPixmap();
306 }
307 
312 void QwtDial::paintEvent( QPaintEvent *event )
313 {
314  QPainter painter( this );
315  painter.setClipRegion( event->region() );
316 
317  QStyleOption opt;
318  opt.init(this);
319  style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
320 
321  if ( d_data->mode == QwtDial::RotateScale )
322  {
323  painter.save();
324  painter.setRenderHint( QPainter::Antialiasing, true );
325 
326  drawContents( &painter );
327 
328  painter.restore();
329  }
330 
331  const QRect r = contentsRect();
332  if ( r.size() != d_data->pixmapCache.size() )
333  {
334  d_data->pixmapCache = QwtPainter::backingStore( this, r.size() );
335  d_data->pixmapCache.fill( Qt::transparent );
336 
337  QPainter p( &d_data->pixmapCache );
338  p.setRenderHint( QPainter::Antialiasing, true );
339  p.translate( -r.topLeft() );
340 
341  if ( d_data->mode != QwtDial::RotateScale )
342  drawContents( &p );
343 
344  if ( lineWidth() > 0 )
345  drawFrame( &p );
346 
348  drawNeedle( &p );
349  }
350 
351  painter.drawPixmap( r.topLeft(), d_data->pixmapCache );
352 
354  drawNeedle( &painter );
355 
356  if ( hasFocus() )
357  drawFocusIndicator( &painter );
358 }
359 
364 void QwtDial::drawFocusIndicator( QPainter *painter ) const
365 {
366  QwtPainter::drawFocusRect( painter, this, boundingRect() );
367 }
368 
375 void QwtDial::drawFrame( QPainter *painter )
376 {
378  palette(), lineWidth(), d_data->frameShadow );
379 }
380 
393 void QwtDial::drawContents( QPainter *painter ) const
394 {
395  if ( testAttribute( Qt::WA_NoSystemBackground ) ||
396  palette().brush( QPalette::Base ) !=
397  palette().brush( QPalette::Window ) )
398  {
399  const QRectF br = boundingRect();
400 
401  painter->save();
402  painter->setPen( Qt::NoPen );
403  painter->setBrush( palette().brush( QPalette::Base ) );
404  painter->drawEllipse( br );
405  painter->restore();
406  }
407 
408  const QRectF insideScaleRect = scaleInnerRect();
409  if ( palette().brush( QPalette::WindowText ) !=
410  palette().brush( QPalette::Base ) )
411  {
412  painter->save();
413  painter->setPen( Qt::NoPen );
414  painter->setBrush( palette().brush( QPalette::WindowText ) );
415  painter->drawEllipse( insideScaleRect );
416  painter->restore();
417  }
418 
419  const QPointF center = insideScaleRect.center();
420  const double radius = 0.5 * insideScaleRect.width();
421 
422  painter->save();
423  drawScale( painter, center, radius );
424  painter->restore();
425 
426  painter->save();
427  drawScaleContents( painter, center, radius );
428  painter->restore();
429 }
430 
440 void QwtDial::drawNeedle( QPainter *painter, const QPointF &center,
441  double radius, double direction, QPalette::ColorGroup colorGroup ) const
442 {
443  if ( d_data->needle )
444  {
445  direction = 360.0 - direction; // counter clockwise
446  d_data->needle->draw( painter, center, radius, direction, colorGroup );
447  }
448 }
449 
450 void QwtDial::drawNeedle( QPainter *painter ) const
451 {
452  if ( !isValid() )
453  return;
454 
455  QPalette::ColorGroup colorGroup;
456  if ( isEnabled() )
457  colorGroup = hasFocus() ? QPalette::Active : QPalette::Inactive;
458  else
459  colorGroup = QPalette::Disabled;
460 
461  const QRectF sr = scaleInnerRect();
462 
463  painter->save();
464  painter->setRenderHint( QPainter::Antialiasing, true );
465  drawNeedle( painter, sr.center(), 0.5 * sr.width(),
466  scaleMap().transform( value() ) + 270.0, colorGroup );
467  painter->restore();
468 }
469 
477 void QwtDial::drawScale( QPainter *painter,
478  const QPointF &center, double radius ) const
479 {
480  QwtRoundScaleDraw *sd = const_cast<QwtRoundScaleDraw *>( scaleDraw() );
481  if ( sd == NULL )
482  return;
483 
484  sd->setRadius( radius );
485  sd->moveCenter( center );
486 
487  QPalette pal = palette();
488 
489  const QColor textColor = pal.color( QPalette::Text );
490  pal.setColor( QPalette::WindowText, textColor ); // ticks, backbone
491 
492  painter->setFont( font() );
493  painter->setPen( QPen( textColor, sd->penWidth() ) );
494 
495  painter->setBrush( Qt::red );
496  sd->draw( painter, pal );
497 }
498 
508 void QwtDial::drawScaleContents( QPainter *painter,
509  const QPointF &center, double radius ) const
510 {
511  Q_UNUSED(painter);
512  Q_UNUSED(center);
513  Q_UNUSED(radius);
514 }
515 
525 {
526  if ( needle != d_data->needle )
527  {
528  if ( d_data->needle )
529  delete d_data->needle;
530 
531  d_data->needle = needle;
532  update();
533  }
534 }
535 
541 {
542  return d_data->needle;
543 }
544 
550 {
551  return d_data->needle;
552 }
553 
556 {
557  return static_cast<QwtRoundScaleDraw *>( abstractScaleDraw() );
558 }
559 
562 {
563  return static_cast<const QwtRoundScaleDraw *>( abstractScaleDraw() );
564 }
565 
577 {
578  setAbstractScaleDraw( scaleDraw );
579  sliderChange();
580 }
581 
590 void QwtDial::setScaleArc( double minArc, double maxArc )
591 {
592  if ( minArc != 360.0 && minArc != -360.0 )
593  minArc = ::fmod( minArc, 360.0 );
594  if ( maxArc != 360.0 && maxArc != -360.0 )
595  maxArc = ::fmod( maxArc, 360.0 );
596 
597  double minScaleArc = qMin( minArc, maxArc );
598  double maxScaleArc = qMax( minArc, maxArc );
599 
600  if ( maxScaleArc - minScaleArc > 360.0 )
601  maxScaleArc = minScaleArc + 360.0;
602 
603  if ( ( minScaleArc != d_data->minScaleArc ) ||
604  ( maxScaleArc != d_data->maxScaleArc ) )
605  {
608 
609  invalidateCache();
610  sliderChange();
611  }
612 }
613 
620 void QwtDial::setMinScaleArc( double min )
621 {
622  setScaleArc( min, d_data->maxScaleArc );
623 }
624 
629 double QwtDial::minScaleArc() const
630 {
631  return d_data->minScaleArc;
632 }
633 
640 void QwtDial::setMaxScaleArc( double max )
641 {
642  setScaleArc( d_data->minScaleArc, max );
643 }
644 
649 double QwtDial::maxScaleArc() const
650 {
651  return d_data->maxScaleArc;
652 }
653 
663 {
664  invalidateCache();
665 
666  d_data->origin = origin;
667  sliderChange();
668 }
669 
676 double QwtDial::origin() const
677 {
678  return d_data->origin;
679 }
680 
685 QSize QwtDial::sizeHint() const
686 {
687  int sh = 0;
688  if ( scaleDraw() )
689  sh = qCeil( scaleDraw()->extent( font() ) );
690 
691  const int d = 6 * sh + 2 * lineWidth();
692 
693  QSize hint( d, d );
694  if ( !isReadOnly() )
695  hint = hint.expandedTo( QApplication::globalStrut() );
696 
697  return hint;
698 }
699 
705 {
706  int sh = 0;
707  if ( scaleDraw() )
708  sh = qCeil( scaleDraw()->extent( font() ) );
709 
710  const int d = 3 * sh + 2 * lineWidth();
711 
712  return QSize( d, d );
713 }
714 
723 bool QwtDial::isScrollPosition( const QPoint &pos ) const
724 {
725  const QRegion region( innerRect(), QRegion::Ellipse );
726  if ( region.contains( pos ) && ( pos != innerRect().center() ) )
727  {
728  double angle = QLineF( rect().center(), pos ).angle();
729  if ( d_data->mode == QwtDial::RotateScale )
730  angle = 360.0 - angle;
731 
732  double valueAngle =
733  qwtNormalizeDegrees( 90.0 - scaleMap().transform( value() ) );
734 
735  d_data->mouseOffset = qwtNormalizeDegrees( angle - valueAngle );
736  d_data->arcOffset = scaleMap().p1();
737 
738  return true;
739  }
740 
741  return false;
742 }
743 
753 double QwtDial::scrolledTo( const QPoint &pos ) const
754 {
755  double angle = QLineF( rect().center(), pos ).angle();
756  if ( d_data->mode == QwtDial::RotateScale )
757  {
758  angle += scaleMap().p1() - d_data->arcOffset;
759  angle = 360.0 - angle;
760  }
761 
762  angle = qwtNormalizeDegrees( angle - d_data->mouseOffset );
763  angle = qwtNormalizeDegrees( 90.0 - angle );
764 
765  if ( scaleMap().pDist() >= 360.0 )
766  {
767  if ( angle < scaleMap().p1() )
768  angle += 360.0;
769 
770  if ( !wrapping() )
771  {
772  double boundedAngle = angle;
773 
774  const double arc = angle - scaleMap().transform( value() );
775  if ( qAbs( arc ) > 180.0 )
776  {
777  boundedAngle = ( arc > 0 )
778  ? scaleMap().p1() : scaleMap().p2();
779  }
780 
781  d_data->mouseOffset += ( boundedAngle - angle );
782 
783  angle = boundedAngle;
784  }
785  }
786  else
787  {
788  const double boundedAngle =
789  qwtBoundedAngle( scaleMap().p1(), angle, scaleMap().p2() );
790 
791  if ( !wrapping() )
792  d_data->mouseOffset += ( boundedAngle - angle );
793 
794  angle = boundedAngle;
795  }
796 
797  return scaleMap().invTransform( angle );
798 }
799 
806 void QwtDial::changeEvent( QEvent *event )
807 {
808  switch( event->type() )
809  {
810  case QEvent::EnabledChange:
811  case QEvent::FontChange:
812  case QEvent::StyleChange:
813  case QEvent::PaletteChange:
814  case QEvent::LanguageChange:
815  case QEvent::LocaleChange:
816  {
817  invalidateCache();
818  break;
819  }
820  default:
821  break;
822  }
823 
825 }
826 
831 void QwtDial::wheelEvent( QWheelEvent *event )
832 {
833  const QRegion region( innerRect(), QRegion::Ellipse );
834  if ( region.contains( event->pos() ) )
836 }
837 
838 void QwtDial::setAngleRange( double angle, double span )
839 {
840  QwtRoundScaleDraw *sd = const_cast<QwtRoundScaleDraw *>( scaleDraw() );
841  if ( sd )
842  {
843  angle = qwtNormalizeDegrees( angle - 270.0 );
844  sd->setAngleRange( angle, angle + span );
845  }
846 }
847 
853 {
854  invalidateCache();
856 }
857 
859 {
862 
863  if ( mode() == RotateScale )
864  {
865  const double arc = scaleMap().transform( value() ) - scaleMap().p1();
866  setAngleRange( d_data->origin - arc,
868  }
869 
871 }
A abstract base class for drawing scales.
d
virtual void drawNeedle(QPainter *, const QPointF &, double radius, double direction, QPalette::ColorGroup) const
Definition: qwt_dial.cpp:440
void setAngleRange(double angle, double span)
Definition: qwt_dial.cpp:838
double p1() const
void setScaleArc(double min, double max)
Definition: qwt_dial.cpp:590
The needle is fixed, the scales are rotating.
Definition: qwt_dial.h:91
The needle is rotating.
Definition: qwt_dial.h:88
double p2() const
void setNeedle(QwtDialNeedle *)
Definition: qwt_dial.cpp:524
void setLineWidth(int)
Definition: qwt_dial.cpp:199
static void drawFocusRect(QPainter *, const QWidget *)
Draw a focus rectangle on a widget using its style.
void setAbstractScaleDraw(QwtAbstractScaleDraw *)
Set a scale draw.
virtual void drawFrame(QPainter *p)
Definition: qwt_dial.cpp:375
Mode
Mode controlling whether the needle or the scale is rotating.
Definition: qwt_dial.h:85
int transform(double) const
virtual void wheelEvent(QWheelEvent *)
Definition: qwt_dial.cpp:831
virtual void sliderChange()
Calling update()
QRect boundingRect() const
Definition: qwt_dial.cpp:236
void setValue(double val)
void setMinScaleArc(double min)
Definition: qwt_dial.cpp:620
static bool qwtIsOnArc(double angle, double min, double max)
Definition: qwt_dial.cpp:36
PrivateData * d_data
Definition: qwt_dial.h:164
static void drawRoundFrame(QPainter *, const QRectF &, const QPalette &, int lineWidth, int frameStyle)
virtual void drawFocusIndicator(QPainter *) const
Definition: qwt_dial.cpp:364
void setMode(Mode)
Change the mode of the dial.
Definition: qwt_dial.cpp:280
const QwtScaleMap & scaleMap() const
virtual void wheelEvent(QWheelEvent *)
virtual void setOrigin(double)
Change the origin.
Definition: qwt_dial.cpp:662
virtual QRect scaleInnerRect() const
Definition: qwt_dial.cpp:252
bool wrapping() const
virtual void scaleChange()
virtual void drawContents(QPainter *) const
Draw the contents inside the frame.
Definition: qwt_dial.cpp:393
virtual ~QwtDial()
Destructor.
Definition: qwt_dial.cpp:161
double maxScaleArc() const
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
virtual void sliderChange()
Calling update()
Definition: qwt_dial.cpp:858
void moveCenter(double x, double y)
Move the center of the scale draw, leaving the radius unchanged.
void setScaleMaxMajor(int ticks)
Set the maximum number of major tick intervals.
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
An abstract base class for slider widgets with a scale.
double value() const
int lineWidth() const
Base class for needles that can be used in a QwtDial.
virtual QSize minimumSizeHint() const
Definition: qwt_dial.cpp:704
double origin() const
virtual void drawScale(QPainter *, const QPointF &center, double radius) const
Definition: qwt_dial.cpp:477
Shadow
Frame shadow.
Definition: qwt_dial.h:72
size_t to
Shadow frameShadow() const
const QwtDialNeedle * needle() const
Definition: qwt_dial.cpp:540
virtual bool isScrollPosition(const QPoint &) const
Determine what to do when the user presses a mouse button.
Definition: qwt_dial.cpp:723
virtual QSize sizeHint() const
Definition: qwt_dial.cpp:685
backward::SignalHandling sh
Definition: backward.cpp:31
QwtRoundScaleDraw * scaleDraw()
Definition: qwt_dial.cpp:555
QRect innerRect() const
Definition: qwt_dial.cpp:226
virtual void drawScaleContents(QPainter *painter, const QPointF &center, double radius) const
Definition: qwt_dial.cpp:508
static double qwtBoundedAngle(double min, double angle, double max)
Definition: qwt_dial.cpp:48
const QwtAbstractScaleDraw * abstractScaleDraw() const
void setScaleMaxMinor(int ticks)
Set the maximum number of minor tick intervals.
double invTransform(double p) const
void invalidateCache()
Definition: qwt_dial.cpp:303
void setAngleRange(double angle1, double angle2)
Adjust the baseline circle segment for round scales.
virtual void changeEvent(QEvent *)
QwtDial(QWidget *parent=NULL)
Constructor.
Definition: qwt_dial.cpp:126
virtual void paintEvent(QPaintEvent *)
Definition: qwt_dial.cpp:312
A class for drawing round scales.
virtual double extent(const QFont &font) const =0
virtual void draw(QPainter *, const QPalette &) const
Draw the scale.
double minScaleArc() const
virtual void scaleChange()
Definition: qwt_dial.cpp:852
void setFrameShadow(Shadow)
Definition: qwt_dial.cpp:172
void setScaleDraw(QwtRoundScaleDraw *)
Definition: qwt_dial.cpp:576
virtual double scrolledTo(const QPoint &) const
Determine the value for a new position of the slider handle.
Definition: qwt_dial.cpp:753
Mode mode() const
virtual void draw(QPainter *painter, const QPointF &center, double length, double direction, QPalette::ColorGroup=QPalette::Active) const
static double qwtAngleDist(double a1, double a2)
Definition: qwt_dial.cpp:27
virtual void changeEvent(QEvent *)
Definition: qwt_dial.cpp:806
void setRadius(double radius)
double transform(double s) const
int i
double qwtNormalizeDegrees(double degrees)
Normalize an angle to be int the range [0.0, 360.0[.
Definition: qwt_math.cpp:67
size_t from
QwtDial::Mode mode
Definition: qwt_dial.cpp:100
QFrame::Sunken.
Definition: qwt_dial.h:81
int a
void setMaxScaleArc(double min)
Definition: qwt_dial.cpp:640
static QPixmap backingStore(QWidget *, const QSize &)
QwtDialNeedle * needle
Definition: qwt_dial.cpp:106


plotjuggler
Author(s): Davide Faconti
autogenerated on Sat Jul 6 2019 03:44:17