qwt_plot_rescaler.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_plot_rescaler.h"
11 #include "qwt_plot.h"
12 #include "qwt_scale_div.h"
13 #include "qwt_interval.h"
14 #include "qwt_plot_canvas.h"
15 
16 #include <qmargins.h>
17 #include <qevent.h>
18 
20 {
21 public:
23  aspectRatio( 1.0 ),
25  {
26  }
27 
28  double aspectRatio;
32 };
33 
35 {
36 public:
38  referenceAxis( QwtPlot::xBottom ),
40  isEnabled( false ),
41  inReplot( 0 )
42  {
43  }
44 
48  bool isEnabled;
49 
50  mutable int inReplot;
51 };
52 
63  int referenceAxis, RescalePolicy policy ):
64  QObject( canvas )
65 {
66  d_data = new PrivateData;
68  d_data->rescalePolicy = policy;
69 
70  setEnabled( true );
71 }
72 
75 {
76  delete d_data;
77 }
78 
89 {
90  if ( d_data->isEnabled != on )
91  {
92  d_data->isEnabled = on;
93 
94  QWidget *w = canvas();
95  if ( w )
96  {
97  if ( d_data->isEnabled )
98  w->installEventFilter( this );
99  else
100  w->removeEventFilter( this );
101  }
102  }
103 }
104 
110 {
111  return d_data->isEnabled;
112 }
113 
121 {
122  d_data->rescalePolicy = policy;
123 }
124 
130 {
131  return d_data->rescalePolicy;
132 }
133 
141 {
142  d_data->referenceAxis = axis;
143 }
144 
150 {
151  return d_data->referenceAxis;
152 }
153 
161  ExpandingDirection direction )
162 {
163  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
164  setExpandingDirection( axis, direction );
165 }
166 
175  int axis, ExpandingDirection direction )
176 {
177  if ( axis >= 0 && axis < QwtPlot::axisCnt )
178  d_data->axisData[axis].expandingDirection = direction;
179 }
180 
189 {
190  if ( axis >= 0 && axis < QwtPlot::axisCnt )
191  return d_data->axisData[axis].expandingDirection;
192 
193  return ExpandBoth;
194 }
195 
204 {
205  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
206  setAspectRatio( axis, ratio );
207 }
208 
217 void QwtPlotRescaler::setAspectRatio( int axis, double ratio )
218 {
219  if ( ratio < 0.0 )
220  ratio = 0.0;
221 
222  if ( axis >= 0 && axis < QwtPlot::axisCnt )
223  d_data->axisData[axis].aspectRatio = ratio;
224 }
225 
232 double QwtPlotRescaler::aspectRatio( int axis ) const
233 {
234  if ( axis >= 0 && axis < QwtPlot::axisCnt )
235  return d_data->axisData[axis].aspectRatio;
236 
237  return 0.0;
238 }
239 
251  const QwtInterval &interval )
252 {
253  if ( axis >= 0 && axis < QwtPlot::axisCnt )
255 }
256 
263 {
264  if ( axis >= 0 && axis < QwtPlot::axisCnt )
265  return d_data->axisData[axis].intervalHint;
266 
267  return QwtInterval();
268 }
269 
272 {
273  return qobject_cast<QWidget *>( parent() );
274 }
275 
277 const QWidget *QwtPlotRescaler::canvas() const
278 {
279  return qobject_cast<const QWidget *>( parent() );
280 }
281 
284 {
285  QWidget *w = canvas();
286  if ( w )
287  w = w->parentWidget();
288 
289  return qobject_cast<QwtPlot *>( w );
290 }
291 
294 {
295  const QWidget *w = canvas();
296  if ( w )
297  w = w->parentWidget();
298 
299  return qobject_cast<const QwtPlot *>( w );
300 }
301 
303 bool QwtPlotRescaler::eventFilter( QObject *object, QEvent *event )
304 {
305  if ( object && object == canvas() )
306  {
307  switch ( event->type() )
308  {
309  case QEvent::Resize:
310  {
311  canvasResizeEvent( static_cast<QResizeEvent *>( event ) );
312  break;
313  }
314  case QEvent::PolishRequest:
315  {
316  rescale();
317  break;
318  }
319  default:;
320  }
321  }
322 
323  return false;
324 }
325 
332 void QwtPlotRescaler::canvasResizeEvent( QResizeEvent* event )
333 {
334  const QMargins m = canvas()->contentsMargins();
335  const QSize marginSize( m.left() + m.right(), m.top() + m.bottom() );
336 
337  const QSize newSize = event->size() - marginSize;
338  const QSize oldSize = event->oldSize() - marginSize;
339 
340  rescale( oldSize, newSize );
341 }
342 
345 {
346  const QSize size = canvas()->contentsRect().size();
347  rescale( size, size );
348 }
349 
357  const QSize &oldSize, const QSize &newSize ) const
358 {
359  if ( newSize.isEmpty() )
360  return;
361 
362  QwtInterval intervals[QwtPlot::axisCnt];
363  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
364  intervals[axis] = interval( axis );
365 
366  const int refAxis = referenceAxis();
367  intervals[refAxis] = expandScale( refAxis, oldSize, newSize );
368 
369  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
370  {
371  if ( aspectRatio( axis ) > 0.0 && axis != refAxis )
372  intervals[axis] = syncScale( axis, intervals[refAxis], newSize );
373  }
374 
375  updateScales( intervals );
376 }
377 
388  const QSize &oldSize, const QSize &newSize ) const
389 {
390  const QwtInterval oldInterval = interval( axis );
391 
392  QwtInterval expanded = oldInterval;
393  switch ( rescalePolicy() )
394  {
395  case Fixed:
396  {
397  break; // do nothing
398  }
399  case Expanding:
400  {
401  if ( !oldSize.isEmpty() )
402  {
403  double width = oldInterval.width();
404  if ( orientation( axis ) == Qt::Horizontal )
405  width *= double( newSize.width() ) / oldSize.width();
406  else
407  width *= double( newSize.height() ) / oldSize.height();
408 
409  expanded = expandInterval( oldInterval,
410  width, expandingDirection( axis ) );
411  }
412  break;
413  }
414  case Fitting:
415  {
416  double dist = 0.0;
417  for ( int ax = 0; ax < QwtPlot::axisCnt; ax++ )
418  {
419  const double d = pixelDist( ax, newSize );
420  if ( d > dist )
421  dist = d;
422  }
423  if ( dist > 0.0 )
424  {
425  double width;
426  if ( orientation( axis ) == Qt::Horizontal )
427  width = newSize.width() * dist;
428  else
429  width = newSize.height() * dist;
430 
431  expanded = expandInterval( intervalHint( axis ),
432  width, expandingDirection( axis ) );
433  }
434  break;
435  }
436  }
437 
438  return expanded;
439 }
440 
451  const QwtInterval& reference, const QSize &size ) const
452 {
453  double dist;
454  if ( orientation( referenceAxis() ) == Qt::Horizontal )
455  dist = reference.width() / size.width();
456  else
457  dist = reference.width() / size.height();
458 
459  if ( orientation( axis ) == Qt::Horizontal )
460  dist *= size.width();
461  else
462  dist *= size.height();
463 
464  dist /= aspectRatio( axis );
465 
466  QwtInterval intv;
467  if ( rescalePolicy() == Fitting )
468  intv = intervalHint( axis );
469  else
470  intv = interval( axis );
471 
472  intv = expandInterval( intv, dist, expandingDirection( axis ) );
473 
474  return intv;
475 }
476 
481 Qt::Orientation QwtPlotRescaler::orientation( int axis ) const
482 {
483  if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight )
484  return Qt::Vertical;
485 
486  return Qt::Horizontal;
487 }
488 
494 {
495  if ( axis < 0 || axis >= QwtPlot::axisCnt )
496  return QwtInterval();
497 
498  return plot()->axisScaleDiv( axis ).interval().normalized();
499 }
500 
511  const QwtInterval &interval, double width,
512  ExpandingDirection direction ) const
513 {
514  QwtInterval expanded = interval;
515 
516  switch ( direction )
517  {
518  case ExpandUp:
519  expanded.setMinValue( interval.minValue() );
520  expanded.setMaxValue( interval.minValue() + width );
521  break;
522 
523  case ExpandDown:
524  expanded.setMaxValue( interval.maxValue() );
525  expanded.setMinValue( interval.maxValue() - width );
526  break;
527 
528  case ExpandBoth:
529  default:
530  expanded.setMinValue( interval.minValue() +
531  interval.width() / 2.0 - width / 2.0 );
532  expanded.setMaxValue( expanded.minValue() + width );
533  }
534  return expanded;
535 }
536 
537 double QwtPlotRescaler::pixelDist( int axis, const QSize &size ) const
538 {
539  const QwtInterval intv = intervalHint( axis );
540 
541  double dist = 0.0;
542  if ( !intv.isNull() )
543  {
544  if ( axis == referenceAxis() )
545  dist = intv.width();
546  else
547  {
548  const double r = aspectRatio( axis );
549  if ( r > 0.0 )
550  dist = intv.width() * r;
551  }
552  }
553 
554  if ( dist > 0.0 )
555  {
556  if ( orientation( axis ) == Qt::Horizontal )
557  dist /= size.width();
558  else
559  dist /= size.height();
560  }
561 
562  return dist;
563 }
564 
571  QwtInterval intervals[QwtPlot::axisCnt] ) const
572 {
573  if ( d_data->inReplot >= 5 )
574  {
575  return;
576  }
577 
578  QwtPlot *plt = const_cast<QwtPlot *>( plot() );
579 
580  const bool doReplot = plt->autoReplot();
581  plt->setAutoReplot( false );
582 
583  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
584  {
585  if ( axis == referenceAxis() || aspectRatio( axis ) > 0.0 )
586  {
587  double v1 = intervals[axis].minValue();
588  double v2 = intervals[axis].maxValue();
589 
590  if ( !plt->axisScaleDiv( axis ).isIncreasing() )
591  qSwap( v1, v2 );
592 
593  if ( d_data->inReplot >= 1 )
594  d_data->axisData[axis].scaleDiv = plt->axisScaleDiv( axis );
595 
596  if ( d_data->inReplot >= 2 )
597  {
599  for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
600  ticks[i] = d_data->axisData[axis].scaleDiv.ticks( i );
601 
602  plt->setAxisScaleDiv( axis, QwtScaleDiv( v1, v2, ticks ) );
603  }
604  else
605  {
606  plt->setAxisScale( axis, v1, v2 );
607  }
608  }
609  }
610 
611  QwtPlotCanvas *canvas = qobject_cast<QwtPlotCanvas *>( plt->canvas() );
612 
613  bool immediatePaint = false;
614  if ( canvas )
615  {
616  immediatePaint = canvas->testPaintAttribute( QwtPlotCanvas::ImmediatePaint );
618  }
619 
620  plt->setAutoReplot( doReplot );
621 
622  d_data->inReplot++;
623  plt->replot();
624  d_data->inReplot--;
625 
626  if ( canvas && immediatePaint )
627  {
629  }
630 }
631 
632 #if QWT_MOC_INCLUDE
633 #include "moc_qwt_plot_rescaler.cpp"
634 #endif
const QwtScaleDiv & axisScaleDiv(int axisId) const
Return the scale division of a specified axis.
void setRescalePolicy(RescalePolicy)
QwtInterval normalized() const
Normalize the limits of the interval.
A class representing an interval.
Definition: qwt_interval.h:22
virtual void canvasResizeEvent(QResizeEvent *)
void setReferenceAxis(int axis)
Number of axes.
Definition: qwt_plot.h:109
QwtInterval interval(int axis) const
MQTTClient d
Definition: test10.c:1656
double minValue() const
Definition: qwt_interval.h:190
QwtInterval expandInterval(const QwtInterval &, double width, ExpandingDirection) const
void setAutoReplot(bool=true)
Set or reset the autoReplot option.
Definition: qwt_plot.cpp:307
Y axis right of the canvas.
Definition: qwt_plot.h:100
virtual void replot()
Redraw the plot.
Definition: qwt_plot.cpp:539
double aspectRatio(int axis) const
A class representing a scale division.
Definition: qwt_scale_div.h:33
Canvas of a QwtPlot.
A 2-D plotting widget.
Definition: qwt_plot.h:75
double maxValue() const
Definition: qwt_interval.h:196
bool testPaintAttribute(PaintAttribute) const
Y axis left of the canvas.
Definition: qwt_plot.h:97
int referenceAxis() const
virtual QwtInterval expandScale(int axis, const QSize &oldSize, const QSize &newSize) const
void setAxisScaleDiv(int axisId, const QwtScaleDiv &)
Disable autoscaling and specify a fixed scale for a selected axis.
QwtPlotRescaler::AxisData axisData[QwtPlot::axisCnt]
QwtPlotRescaler(QWidget *canvas, int referenceAxis=QwtPlot::xBottom, RescalePolicy=Expanding)
QwtInterval intervalHint(int axis) const
The lower limit of the scale is adjusted.
bool autoReplot
Definition: qwt_plot.h:81
void setExpandingDirection(ExpandingDirection)
PrivateData * d_data
void setEnabled(bool)
En/disable the rescaler.
bool isNull() const
Definition: qwt_interval.h:312
Both limits of the scale are adjusted.
virtual ~QwtPlotRescaler()
Destructor.
basic_reference< false > reference
Definition: forward.hpp:610
void rescale() const
Adjust the plot axes scales.
QwtPlotRescaler takes care of fixed aspect ratios for plot scales.
void setPaintAttribute(PaintAttribute, bool on=true)
Changing the paint attributes.
Number of valid tick types.
Definition: qwt_scale_div.h:52
void setAxisScale(int axisId, double min, double max, double stepSize=0)
Disable autoscaling and specify a fixed scale for a selected axis.
ExpandingDirection expandingDirection(int axis) const
bool isIncreasing() const
Check if the scale division is increasing( lowerBound() <= upperBound() )
QwtPlotRescaler::ExpandingDirection expandingDirection
void setMinValue(double)
Definition: qwt_interval.h:174
bool isEnabled() const
QWidget * canvas()
Definition: qwt_plot.cpp:460
Qt::Orientation orientation(int axis) const
The upper limit of the scale is adjusted.
void setAspectRatio(double ratio)
QwtInterval interval() const
virtual void updateScales(QwtInterval intervals[QwtPlot::axisCnt]) const
double width() const
Return the width of an interval.
Definition: qwt_interval.h:225
QList< double > ticks(int tickType) const
double pixelDist(int axis, const QSize &) const
void setMaxValue(double)
Definition: qwt_interval.h:184
virtual QwtInterval syncScale(int axis, const QwtInterval &reference, const QSize &size) const
virtual bool eventFilter(QObject *, QEvent *) QWT_OVERRIDE
Event filter for the plot canvas.
RescalePolicy rescalePolicy() const
void setIntervalHint(int axis, const QwtInterval &)


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