Qwt User's Guide  6.2.0
qwt_plot_layout.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_plot_layout.h"
11 #include "qwt_text.h"
12 #include "qwt_text_label.h"
13 #include "qwt_scale_widget.h"
14 #include "qwt_abstract_legend.h"
15 #include "qwt_math.h"
16 
17 #include <qmargins.h>
18 
19 namespace
20 {
21  class LayoutData
22  {
23  public:
24  struct LegendData
25  {
26  void init( const QwtAbstractLegend* legend )
27  {
28  if ( legend )
29  {
30  frameWidth = legend->frameWidth();
31  hScrollExtent = legend->scrollExtent( Qt::Horizontal );
32  vScrollExtent = legend->scrollExtent( Qt::Vertical );
33 
34  hint = legend->sizeHint();
35  }
36  }
37 
38  QSize legendHint( const QwtAbstractLegend* legend, const QRectF& rect ) const
39  {
40  const int w = qMin( hint.width(), qwtFloor( rect.width() ) );
41 
42  int h = legend->heightForWidth( w );
43  if ( h <= 0 )
44  h = hint.height();
45 
46  return QSize( w, h );
47  }
48 
49  int frameWidth;
50  int hScrollExtent;
51  int vScrollExtent;
52  QSize hint;
53  };
54 
55  struct LabelData
56  {
57  void init( const QwtTextLabel* label )
58  {
59  frameWidth = 0;
60  text = QwtText();
61 
62  if ( label )
63  {
64  text = label->text();
65  if ( !( text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) )
66  text.setFont( label->font() );
67 
68  frameWidth = label->frameWidth();
69  }
70  }
71 
72  QwtText text;
73  int frameWidth;
74  };
75 
76  struct ScaleData
77  {
78  void init( const QwtScaleWidget* axisWidget )
79  {
80  isVisible = true;
81 
82  scaleWidget = axisWidget;
83  scaleFont = axisWidget->font();
84 
85  start = axisWidget->startBorderDist();
86  end = axisWidget->endBorderDist();
87 
88  baseLineOffset = axisWidget->margin();
89 
90  tickOffset = axisWidget->margin();
91  if ( axisWidget->scaleDraw()->hasComponent( QwtAbstractScaleDraw::Ticks ) )
92  tickOffset += axisWidget->scaleDraw()->maxTickLength();
93 
94  dimWithoutTitle = axisWidget->dimForLength( QWIDGETSIZE_MAX, scaleFont );
95  if ( !axisWidget->title().isEmpty() )
96  dimWithoutTitle -= axisWidget->titleHeightForWidth( QWIDGETSIZE_MAX );
97  }
98 
99  void reset()
100  {
101  isVisible = false;
102  start = 0;
103  end = 0;
104  baseLineOffset = 0;
105  tickOffset = 0.0;
106  dimWithoutTitle = 0;
107  }
108 
109  bool isVisible;
110  const QwtScaleWidget* scaleWidget;
111  QFont scaleFont;
112  int start;
113  int end;
114  int baseLineOffset;
115  double tickOffset;
116  int dimWithoutTitle;
117  };
118 
119  struct CanvasData
120  {
121  void init( const QWidget* canvas )
122  {
123  const QMargins m = canvas->contentsMargins();
124 
125  contentsMargins[ QwtAxis::YLeft ] = m.left();
126  contentsMargins[ QwtAxis::XTop ] = m.top();
127  contentsMargins[ QwtAxis::YRight ] = m.right();
128  contentsMargins[ QwtAxis::XBottom ] = m.bottom();
129  }
130 
131  int contentsMargins[ QwtAxis::AxisPositions ];
132  };
133 
134  public:
135  enum Label
136  {
137  Title,
138  Footer,
139 
140  NumLabels
141  };
142 
143  LayoutData( const QwtPlot* );
144  bool hasSymmetricYAxes() const;
145 
146  inline ScaleData& axisData( QwtAxisId axisId )
147  {
148  return m_scaleData[ axisId ];
149  }
150 
151  inline const ScaleData& axisData( QwtAxisId axisId ) const
152  {
153  return m_scaleData[ axisId ];
154  }
155 
156  inline double tickOffset( int axisPos ) const
157  {
158  return axisData( axisPos ).tickOffset;
159  }
160 
161  LegendData legendData;
162  LabelData labelData[ NumLabels ];
163  CanvasData canvasData;
164 
165  private:
166  ScaleData m_scaleData[ QwtAxis::AxisPositions ];
167  };
168 
169  /*
170  Extract all layout relevant data from the plot components
171  */
172  LayoutData::LayoutData( const QwtPlot* plot )
173  {
174  legendData.init( plot->legend() );
175  labelData[ Title ].init( plot->titleLabel() );
176  labelData[ Footer ].init( plot->footerLabel() );
177 
178  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
179  {
180  {
181  const QwtAxisId axisId( axisPos );
182 
183  ScaleData& scaleData = axisData( axisId );
184 
185  if ( plot->isAxisVisible( axisId ) )
186  {
187  const QwtScaleWidget* scaleWidget = plot->axisWidget( axisId );
188  scaleData.init( scaleWidget );
189  }
190  else
191  {
192  scaleData.reset();
193  }
194  }
195  }
196 
197  canvasData.init( plot->canvas() );
198  }
199 
200  bool LayoutData::hasSymmetricYAxes() const
201  {
202  using namespace QwtAxis;
203  return m_scaleData[ YLeft ].isVisible == m_scaleData[ YRight ].isVisible;
204  }
205 }
206 
207 namespace
208 {
209  class LayoutHintData
210  {
211  public:
212  LayoutHintData( const QwtPlot* plot );
213 
214  int alignedSize( const QwtAxisId ) const;
215 
216  inline int yAxesWidth() const
217  {
218  using namespace QwtAxis;
219  return axesWidth( YLeft ) + axesWidth( YRight );
220  }
221 
222  inline int yAxesHeight() const
223  {
224  using namespace QwtAxis;
225  return qMax( axesHeight( YLeft ), axesHeight( YRight ) );
226  }
227 
228  inline int xAxesHeight() const
229  {
230  using namespace QwtAxis;
231  return axesHeight( XTop ) + axesHeight( XBottom );
232  }
233 
234  inline int xAxesWidth() const
235  {
236  using namespace QwtAxis;
237  return qMax( axesWidth( XTop ), axesWidth( XBottom ) );
238  }
239 
240  private:
241 
242  struct ScaleData
243  {
244  ScaleData()
245  {
246  w = h = minLeft = minRight = tickOffset = 0;
247  }
248 
249  int w;
250  int h;
251  int minLeft;
252  int minRight;
253  int tickOffset;
254 
255  };
256 
257  const ScaleData& axisData( QwtAxisId axisId ) const
258  {
259  return m_scaleData[ axisId ];
260  }
261 
262  ScaleData& axisData( QwtAxisId axisId )
263  {
264  return m_scaleData[ axisId ];
265  }
266 
267  inline int axesWidth( int axisPos ) const
268  {
269  return m_scaleData[axisPos].w;
270  }
271 
272  inline int axesHeight( int axisPos ) const
273  {
274  return m_scaleData[axisPos].h;
275  }
276 
277  int m_canvasBorder[QwtAxis::AxisPositions];
278  ScaleData m_scaleData[QwtAxis::AxisPositions];
279  };
280 
281  LayoutHintData::LayoutHintData( const QwtPlot* plot )
282  {
283  using namespace QwtAxis;
284 
285  const QMargins m = plot->canvas()->contentsMargins();
286 
287  int contentsMargins[ 4 ];
288  contentsMargins[ YLeft ] = m.left();
289  contentsMargins[ XTop ] = m.top();
290  contentsMargins[ YRight ] = m.right();
291  contentsMargins[ XBottom ] = m.bottom();
292 
293  for ( int axisPos = 0; axisPos < AxisPositions; axisPos++ )
294  {
295  m_canvasBorder[axisPos] = contentsMargins[axisPos] +
296  plot->plotLayout()->canvasMargin( axisPos ) + 1;
297  {
298  const QwtAxisId axisId( axisPos );
299 
300  if ( plot->isAxisVisible( axisId ) )
301  {
302  const QwtScaleWidget* scl = plot->axisWidget( axisId );
303 
304  const QSize hint = scl->minimumSizeHint();
305 
306  ScaleData& sd = axisData( axisId );
307  sd.w = hint.width();
308  sd.h = hint.height();
309  scl->getBorderDistHint( sd.minLeft, sd.minRight );
310 
311  {
312  sd.tickOffset = scl->margin();
314  sd.tickOffset += qwtCeil( scl->scaleDraw()->maxTickLength() );
315  }
316  }
317  }
318  }
319 
320  for ( int axis = 0; axis < AxisPositions; axis++ )
321  {
322  const int sz = alignedSize( axis );
323 
324  ScaleData& sd = axisData( axis );
325  if ( isXAxis( axis ) )
326  sd.w = sz;
327  else
328  sd.h = sz;
329  }
330  }
331 
332  int LayoutHintData::alignedSize( const QwtAxisId axisId ) const
333  {
334  using namespace QwtAxis;
335 
336  const ScaleData& sd = axisData( axisId );
337 
338  if ( sd.w && isXAxis( axisId ) )
339  {
340  int w = sd.w;
341 
342  if ( const int leftW = axesWidth( YLeft ) )
343  {
344  const int shiftLeft = sd.minLeft - m_canvasBorder[YLeft];
345  if ( shiftLeft > 0 )
346  w -= qMin( shiftLeft, leftW );
347  }
348 
349  if ( const int rightW = axesWidth( YRight ) )
350  {
351  const int shiftRight = sd.minRight - m_canvasBorder[YRight];
352  if ( shiftRight > 0 )
353  w -= qMin( shiftRight, rightW );
354  }
355 
356  return w;
357  }
358 
359  if ( sd.h && isYAxis( axisId ) )
360  {
361  int h = sd.h;
362 
363  if ( axesHeight( XBottom ) )
364  {
365  const int shiftBottom = sd.minLeft - m_canvasBorder[XBottom];
366  if ( shiftBottom > 0 )
367  h -= qMin( shiftBottom, axisData( XBottom ).tickOffset );
368  }
369 
370  if ( axesHeight( XTop ) )
371  {
372  const int shiftTop = sd.minRight - m_canvasBorder[XTop];
373  if ( shiftTop > 0 )
374  h -= qMin( shiftTop, axisData( XTop ).tickOffset );
375  }
376 
377  return h;
378  }
379 
380  return 0;
381  }
382 }
383 
384 namespace
385 {
386  class LayoutEngine
387  {
388  public:
389  struct Dimensions
390  {
391  Dimensions()
392  {
393  dimTitle = dimFooter = 0;
394  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
395  m_dimAxes[axisPos] = 0;
396  }
397 
398  inline int dimAxis( QwtAxisId axisId ) const
399  {
400  return m_dimAxes[ axisId ];
401  }
402 
403  void setDimAxis( QwtAxisId axisId, int dim )
404  {
405  m_dimAxes[ axisId ] = dim;
406  }
407 
408  inline int dimAxes( int axisPos ) const
409  {
410  return m_dimAxes[ axisPos ];
411  }
412 
413  inline int dimYAxes() const
414  {
415  return dimAxes( QwtAxis::YLeft ) + dimAxes( QwtAxis::YRight );
416  }
417 
418  inline int dimXAxes() const
419  {
420  return dimAxes( QwtAxis::XTop ) + dimAxes( QwtAxis::XBottom );
421  }
422 
423  inline QRectF centered( const QRectF& rect, const QRectF& labelRect ) const
424  {
425  QRectF r = labelRect;
426  r.setX( rect.left() + dimAxes( QwtAxis::YLeft ) );
427  r.setWidth( rect.width() - dimYAxes() );
428 
429  return r;
430  }
431 
432  inline QRectF innerRect( const QRectF& rect ) const
433  {
434  QRectF r(
435  rect.x() + dimAxes( QwtAxis::YLeft ),
436  rect.y() + dimAxes( QwtAxis::XTop ),
437  rect.width() - dimYAxes(),
438  rect.height() - dimXAxes() );
439 
440  if ( r.width() < 0 )
441  {
442  r.setX( rect.center().x() );
443  r.setWidth( 0 );
444  }
445  if ( r.height() < 0 )
446  {
447  r.setY( rect.center().y() );
448  r.setHeight( 0 );
449  }
450 
451  return r;
452  }
453 
454  int dimTitle;
455  int dimFooter;
456 
457  private:
458  int m_dimAxes[QwtAxis::AxisPositions];
459  };
460 
461  LayoutEngine()
462  : m_legendPos( QwtPlot::BottomLegend )
463  , m_legendRatio( 1.0 )
464  , m_spacing( 5 )
465  {
466  }
467 
468  QRectF layoutLegend( QwtPlotLayout::Options,
469  const LayoutData::LegendData&, const QRectF&, const QSize& ) const;
470 
471  QRectF alignLegend( const QSize& legendHint,
472  const QRectF& canvasRect, const QRectF& legendRect ) const;
473 
474  void alignScales( QwtPlotLayout::Options,
475  const LayoutData&, QRectF& canvasRect,
476  QRectF scaleRect[QwtAxis::AxisPositions] ) const;
477 
478  Dimensions layoutDimensions( QwtPlotLayout::Options,
479  const LayoutData&, const QRectF& ) const;
480 
481  inline void setSpacing( unsigned int spacing ) { m_spacing = spacing; }
482  inline unsigned int spacing() const { return m_spacing; }
483 
484  inline void setAlignCanvas( int axisPos, bool on ) { m_alignCanvas[ axisPos ] = on; }
485  inline bool alignCanvas( int axisPos ) const { return m_alignCanvas[ axisPos ]; }
486 
487  inline void setCanvasMargin( int axisPos, int margin ) { m_canvasMargin[ axisPos ] = margin; }
488  inline int canvasMargin( int axisPos ) const { return m_canvasMargin[ axisPos ]; }
489 
490  inline void setLegendPos( QwtPlot::LegendPosition pos ) { m_legendPos = pos; }
491  inline QwtPlot::LegendPosition legendPos() const { return m_legendPos; }
492 
493  inline void setLegendRatio( double ratio ) { m_legendRatio = ratio; }
494  inline double legendRatio() const { return m_legendRatio; }
495 
496  private:
497  int heightForWidth( LayoutData::Label, const LayoutData&,
498  QwtPlotLayout::Options, double width, int axesWidth ) const;
499 
500  QwtPlot::LegendPosition m_legendPos;
501  double m_legendRatio;
502 
503  unsigned int m_canvasMargin[QwtAxis::AxisPositions];
504  bool m_alignCanvas[QwtAxis::AxisPositions];
505 
506  unsigned int m_spacing;
507  };
508 }
509 
510 QRectF LayoutEngine::layoutLegend( QwtPlotLayout::Options options,
511  const LayoutData::LegendData& legendData,
512  const QRectF& rect, const QSize& legendHint ) const
513 {
514  int dim;
515  if ( m_legendPos == QwtPlot::LeftLegend
516  || m_legendPos == QwtPlot::RightLegend )
517  {
518  // We don't allow vertical legends to take more than
519  // half of the available space.
520 
521  dim = qMin( legendHint.width(), int( rect.width() * m_legendRatio ) );
522 
523  if ( !( options & QwtPlotLayout::IgnoreScrollbars ) )
524  {
525  if ( legendHint.height() > rect.height() )
526  {
527  // The legend will need additional
528  // space for the vertical scrollbar.
529 
530  dim += legendData.hScrollExtent;
531  }
532  }
533  }
534  else
535  {
536  dim = qMin( legendHint.height(), int( rect.height() * m_legendRatio ) );
537  dim = qMax( dim, legendData.vScrollExtent );
538  }
539 
540  QRectF legendRect = rect;
541  switch ( m_legendPos )
542  {
543  case QwtPlot::LeftLegend:
544  {
545  legendRect.setWidth( dim );
546  break;
547  }
549  {
550  legendRect.setX( rect.right() - dim );
551  legendRect.setWidth( dim );
552  break;
553  }
554  case QwtPlot::TopLegend:
555  {
556  legendRect.setHeight( dim );
557  break;
558  }
560  {
561  legendRect.setY( rect.bottom() - dim );
562  legendRect.setHeight( dim );
563  break;
564  }
565  }
566 
567  return legendRect;
568 }
569 
570 QRectF LayoutEngine::alignLegend( const QSize& legendHint,
571  const QRectF& canvasRect, const QRectF& legendRect ) const
572 {
573  QRectF alignedRect = legendRect;
574 
575  if ( m_legendPos == QwtPlot::BottomLegend
576  || m_legendPos == QwtPlot::TopLegend )
577  {
578  if ( legendHint.width() < canvasRect.width() )
579  {
580  alignedRect.setX( canvasRect.x() );
581  alignedRect.setWidth( canvasRect.width() );
582  }
583  }
584  else
585  {
586  if ( legendHint.height() < canvasRect.height() )
587  {
588  alignedRect.setY( canvasRect.y() );
589  alignedRect.setHeight( canvasRect.height() );
590  }
591  }
592 
593  return alignedRect;
594 }
595 
596 int LayoutEngine::heightForWidth(
597  LayoutData::Label labelType, const LayoutData& layoutData,
598  QwtPlotLayout::Options options,
599  double width, int axesWidth ) const
600 {
601  const LayoutData::LabelData& labelData = layoutData.labelData[ labelType ];
602 
603  if ( labelData.text.isEmpty() )
604  return 0;
605 
606  double w = width;
607 
608  if ( !layoutData.hasSymmetricYAxes() )
609  {
610  // center to the canvas
611  w -= axesWidth;
612  }
613 
614  int d = qwtCeil( labelData.text.heightForWidth( w ) );
615  if ( !( options & QwtPlotLayout::IgnoreFrames ) )
616  d += 2 * labelData.frameWidth;
617 
618  return d;
619 }
620 
621 LayoutEngine::Dimensions LayoutEngine::layoutDimensions( QwtPlotLayout::Options options,
622  const LayoutData& layoutData, const QRectF& rect ) const
623 {
624  using namespace QwtAxis;
625 
626  Dimensions dimensions;
627 
628  int backboneOffset[AxisPositions];
629  for ( int axisPos = 0; axisPos < AxisPositions; axisPos++ )
630  {
631  backboneOffset[axisPos] = 0;
632  if ( !( options & QwtPlotLayout::IgnoreFrames ) )
633  backboneOffset[axisPos] += layoutData.canvasData.contentsMargins[axisPos];
634 
635  if ( !m_alignCanvas[axisPos] )
636  backboneOffset[axisPos] += m_canvasMargin[axisPos];
637  }
638 
639  bool done = false;
640  while ( !done )
641  {
642  done = true;
643 
644  // the size for the 4 axis depend on each other. Expanding
645  // the height of a horizontal axis will shrink the height
646  // for the vertical axis, shrinking the height of a vertical
647  // axis will result in a line break what will expand the
648  // width and results in shrinking the width of a horizontal
649  // axis what might result in a line break of a horizontal
650  // axis ... . So we loop as long until no size changes.
651 
652  if ( !( options & QwtPlotLayout::IgnoreTitle ) )
653  {
654  const int d = heightForWidth(
655  LayoutData::Title, layoutData, options,
656  rect.width(), dimensions.dimYAxes() );
657 
658  if ( d > dimensions.dimTitle )
659  {
660  dimensions.dimTitle = d;
661  done = false;
662  }
663  }
664 
665  if ( !( options & QwtPlotLayout::IgnoreFooter ) )
666  {
667  const int d = heightForWidth(
668  LayoutData::Footer, layoutData, options,
669  rect.width(), dimensions.dimYAxes() );
670 
671  if ( d > dimensions.dimFooter )
672  {
673  dimensions.dimFooter = d;
674  done = false;
675  }
676  }
677 
678  for ( int axisPos = 0; axisPos < AxisPositions; axisPos++ )
679  {
680  {
681  const QwtAxisId axisId( axisPos );
682 
683  const LayoutData::ScaleData& scaleData = layoutData.axisData( axisId );
684 
685  if ( scaleData.isVisible )
686  {
687  double length;
688  if ( isXAxis( axisPos ) )
689  {
690  length = rect.width() - dimensions.dimYAxes();
691  length -= scaleData.start + scaleData.end;
692 
693  if ( dimensions.dimAxes( YRight ) > 0 )
694  length -= 1;
695 
696  length += qMin( dimensions.dimAxes( YLeft ),
697  scaleData.start - backboneOffset[YLeft] );
698 
699  length += qMin( dimensions.dimAxes( YRight ),
700  scaleData.end - backboneOffset[YRight] );
701  }
702  else // y axis
703  {
704  length = rect.height() - dimensions.dimXAxes();
705  length -= scaleData.start + scaleData.end;
706  length -= 1;
707 
708  if ( dimensions.dimAxes( XBottom ) <= 0 )
709  length -= 1;
710 
711  if ( dimensions.dimAxes( XTop ) <= 0 )
712  length -= 1;
713 
714  /*
715  The tick labels of the y axes are always left/right from the
716  backbone/ticks of the x axes - but we have to take care,
717  that the labels don't overlap.
718  */
719  if ( dimensions.dimAxes( XBottom ) > 0 )
720  {
721  length += qMin(
722  layoutData.tickOffset( XBottom ),
723  double( scaleData.start - backboneOffset[XBottom] ) );
724  }
725 
726  if ( dimensions.dimAxes( XTop ) > 0 )
727  {
728  length += qMin(
729  layoutData.tickOffset( XTop ),
730  double( scaleData.end - backboneOffset[XTop] ) );
731  }
732 
733  if ( dimensions.dimTitle > 0 )
734  length -= dimensions.dimTitle + m_spacing;
735  }
736 
737  int d = scaleData.dimWithoutTitle;
738  if ( !scaleData.scaleWidget->title().isEmpty() )
739  {
740  d += scaleData.scaleWidget->titleHeightForWidth( qwtFloor( length ) );
741  }
742 
743 
744  if ( d > dimensions.dimAxis( axisId ) )
745  {
746  dimensions.setDimAxis( axisId, d );
747  done = false;
748  }
749  }
750  }
751  }
752  }
753 
754  return dimensions;
755 }
756 
757 void LayoutEngine::alignScales( QwtPlotLayout::Options options,
758  const LayoutData& layoutData, QRectF& canvasRect,
759  QRectF scaleRect[QwtAxis::AxisPositions] ) const
760 {
761  using namespace QwtAxis;
762 
763  int backboneOffset[AxisPositions];
764  for ( int axisPos = 0; axisPos < AxisPositions; axisPos++ )
765  {
766  backboneOffset[axisPos] = 0;
767 
768  if ( !m_alignCanvas[axisPos] )
769  {
770  backboneOffset[axisPos] += m_canvasMargin[axisPos];
771  }
772 
773  if ( !( options & QwtPlotLayout::IgnoreFrames ) )
774  {
775  backboneOffset[axisPos] +=
776  layoutData.canvasData.contentsMargins[axisPos];
777  }
778  }
779 
780  for ( int axisPos = 0; axisPos < AxisPositions; axisPos++ )
781  {
782  {
783  QRectF& axisRect = scaleRect[axisPos];
784  if ( !axisRect.isValid() )
785  continue;
786 
787  const QwtAxisId axisId( axisPos );
788 
789  const int startDist = layoutData.axisData( axisId ).start;
790  const int endDist = layoutData.axisData( axisId ).end;
791 
792  if ( isXAxis( axisPos ) )
793  {
794  const QRectF& leftScaleRect = scaleRect[YLeft];
795  const int leftOffset = backboneOffset[YLeft] - startDist;
796 
797  if ( leftScaleRect.isValid() )
798  {
799  const double dx = leftOffset + leftScaleRect.width();
800  if ( m_alignCanvas[YLeft] && dx < 0.0 )
801  {
802  /*
803  The axis needs more space than the width
804  of the left scale.
805  */
806  const double cLeft = canvasRect.left(); // qreal -> double
807  canvasRect.setLeft( qwtMaxF( cLeft, axisRect.left() - dx ) );
808  }
809  else
810  {
811  const double minLeft = leftScaleRect.left();
812  const double left = axisRect.left() + leftOffset;
813  axisRect.setLeft( qwtMaxF( left, minLeft ) );
814  }
815  }
816  else
817  {
818  if ( m_alignCanvas[YLeft] && leftOffset < 0 )
819  {
820  canvasRect.setLeft( qwtMaxF( canvasRect.left(),
821  axisRect.left() - leftOffset ) );
822  }
823  else
824  {
825  if ( leftOffset > 0 )
826  axisRect.setLeft( axisRect.left() + leftOffset );
827  }
828  }
829 
830  const QRectF& rightScaleRect = scaleRect[YRight];
831  const int rightOffset = backboneOffset[YRight] - endDist + 1;
832 
833  if ( rightScaleRect.isValid() )
834  {
835  const double dx = rightOffset + rightScaleRect.width();
836  if ( m_alignCanvas[YRight] && dx < 0 )
837  {
838  /*
839  The axis needs more space than the width
840  of the right scale.
841  */
842  const double cRight = canvasRect.right(); // qreal -> double
843  canvasRect.setRight( qwtMinF( cRight, axisRect.right() + dx ) );
844  }
845 
846  const double maxRight = rightScaleRect.right();
847  const double right = axisRect.right() - rightOffset;
848  axisRect.setRight( qwtMinF( right, maxRight ) );
849  }
850  else
851  {
852  if ( m_alignCanvas[YRight] && rightOffset < 0 )
853  {
854  canvasRect.setRight( qwtMinF( canvasRect.right(),
855  axisRect.right() + rightOffset ) );
856  }
857  else
858  {
859  if ( rightOffset > 0 )
860  axisRect.setRight( axisRect.right() - rightOffset );
861  }
862  }
863  }
864  else // y axes
865  {
866  const QRectF& bottomScaleRect = scaleRect[XBottom];
867  const int bottomOffset = backboneOffset[XBottom] - endDist + 1;
868 
869  if ( bottomScaleRect.isValid() )
870  {
871  const double dy = bottomOffset + bottomScaleRect.height();
872  if ( m_alignCanvas[XBottom] && dy < 0 )
873  {
874  /*
875  The axis needs more space than the height
876  of the bottom scale.
877  */
878  const double cBottom = canvasRect.bottom(); // qreal -> double
879  canvasRect.setBottom( qwtMinF( cBottom, axisRect.bottom() + dy ) );
880  }
881  else
882  {
883  const double maxBottom = bottomScaleRect.top() +
884  layoutData.tickOffset( XBottom );
885  const double bottom = axisRect.bottom() - bottomOffset;
886  axisRect.setBottom( qwtMinF( bottom, maxBottom ) );
887  }
888  }
889  else
890  {
891  if ( m_alignCanvas[XBottom] && bottomOffset < 0 )
892  {
893  canvasRect.setBottom( qwtMinF( canvasRect.bottom(),
894  axisRect.bottom() + bottomOffset ) );
895  }
896  else
897  {
898  if ( bottomOffset > 0 )
899  axisRect.setBottom( axisRect.bottom() - bottomOffset );
900  }
901  }
902 
903  const QRectF& topScaleRect = scaleRect[XTop];
904  const int topOffset = backboneOffset[XTop] - startDist;
905 
906  if ( topScaleRect.isValid() )
907  {
908  const double dy = topOffset + topScaleRect.height();
909  if ( m_alignCanvas[XTop] && dy < 0 )
910  {
911  /*
912  The axis needs more space than the height
913  of the top scale.
914  */
915  const double cTop = canvasRect.top(); // qreal -> double
916  canvasRect.setTop( qwtMaxF( cTop, axisRect.top() - dy ) );
917  }
918  else
919  {
920  const double minTop = topScaleRect.bottom() -
921  layoutData.tickOffset( XTop );
922 
923  const double top = axisRect.top() + topOffset;
924  axisRect.setTop( qwtMaxF( top, minTop ) );
925  }
926  }
927  else
928  {
929  if ( m_alignCanvas[XTop] && topOffset < 0 )
930  {
931  canvasRect.setTop( qwtMaxF( canvasRect.top(),
932  axisRect.top() - topOffset ) );
933  }
934  else
935  {
936  if ( topOffset > 0 )
937  axisRect.setTop( axisRect.top() + topOffset );
938  }
939  }
940  }
941  }
942  }
943 
944  /*
945  The canvas has been aligned to the scale with largest
946  border distances. Now we have to realign the other scale.
947  */
948 
949  for ( int axisPos = 0; axisPos < AxisPositions; axisPos++ )
950  {
951  {
952  const QwtAxisId axisId( axisPos );
953 
954  QRectF& sRect = scaleRect[axisPos];
955  const LayoutData::ScaleData& axisData = layoutData.axisData( axisId );
956 
957  if ( !sRect.isValid() )
958  continue;
959 
960  if ( isXAxis( axisPos ) )
961  {
962  if ( m_alignCanvas[YLeft] )
963  {
964  double y = canvasRect.left() - axisData.start;
965  if ( !( options & QwtPlotLayout::IgnoreFrames ) )
966  y += layoutData.canvasData.contentsMargins[YLeft];
967 
968  sRect.setLeft( y );
969  }
970 
971  if ( m_alignCanvas[YRight] )
972  {
973  double y = canvasRect.right() - 1 + axisData.end;
974  if ( !( options & QwtPlotLayout::IgnoreFrames ) )
975  y -= layoutData.canvasData.contentsMargins[YRight];
976 
977  sRect.setRight( y );
978  }
979 
980  if ( m_alignCanvas[axisPos] )
981  {
982  if ( axisPos == XTop )
983  sRect.setBottom( canvasRect.top() );
984  else
985  sRect.setTop( canvasRect.bottom() );
986  }
987  }
988  else
989  {
990  if ( m_alignCanvas[XTop] )
991  {
992  double x = canvasRect.top() - axisData.start;
993  if ( !( options & QwtPlotLayout::IgnoreFrames ) )
994  x += layoutData.canvasData.contentsMargins[XTop];
995 
996  sRect.setTop( x );
997  }
998 
999  if ( m_alignCanvas[XBottom] )
1000  {
1001  double x = canvasRect.bottom() - 1 + axisData.end;
1002  if ( !( options & QwtPlotLayout::IgnoreFrames ) )
1003  x -= layoutData.canvasData.contentsMargins[XBottom];
1004 
1005  sRect.setBottom( x );
1006  }
1007 
1008  if ( m_alignCanvas[axisPos] )
1009  {
1010  if ( axisPos == YLeft )
1011  sRect.setRight( canvasRect.left() );
1012  else
1013  sRect.setLeft( canvasRect.right() );
1014  }
1015  }
1016  }
1017  }
1018 }
1019 
1020 class QwtPlotLayout::PrivateData
1021 {
1022  public:
1023  QRectF titleRect;
1024  QRectF footerRect;
1025  QRectF legendRect;
1026  QRectF scaleRects[QwtAxis::AxisPositions];
1027  QRectF canvasRect;
1028 
1029  LayoutEngine engine;
1030 };
1031 
1037 {
1038  m_data = new PrivateData;
1039 
1040  setLegendPosition( QwtPlot::BottomLegend );
1041  setCanvasMargin( 4 );
1042  setAlignCanvasToScales( false );
1043 
1044  invalidate();
1045 }
1046 
1049 {
1050  delete m_data;
1051 }
1052 
1066 void QwtPlotLayout::setCanvasMargin( int margin, int axisPos )
1067 {
1068  if ( margin < -1 )
1069  margin = -1;
1070 
1071  LayoutEngine& engine = m_data->engine;
1072 
1073  if ( axisPos == -1 )
1074  {
1075  for ( axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
1076  engine.setCanvasMargin( axisPos, margin );
1077  }
1078  else if ( QwtAxis::isValid( axisPos ) )
1079  {
1080  engine.setCanvasMargin( axisPos, margin );
1081  }
1082 }
1083 
1089 int QwtPlotLayout::canvasMargin( int axisPos ) const
1090 {
1091  if ( !QwtAxis::isValid( axisPos ) )
1092  return 0;
1093 
1094  return m_data->engine.canvasMargin( axisPos );
1095 }
1096 
1104 {
1105  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
1106  m_data->engine.setAlignCanvas( axisPos, on );
1107 }
1108 
1126 void QwtPlotLayout::setAlignCanvasToScale( int axisPos, bool on )
1127 {
1128  if ( QwtAxis::isValid( axisPos ) )
1129  m_data->engine.setAlignCanvas( axisPos, on );
1130 }
1131 
1141 bool QwtPlotLayout::alignCanvasToScale( int axisPos ) const
1142 {
1143  if ( !QwtAxis::isValid( axisPos ) )
1144  return false;
1145 
1146  return m_data->engine.alignCanvas( axisPos );
1147 }
1148 
1156 void QwtPlotLayout::setSpacing( int spacing )
1157 {
1158  m_data->engine.setSpacing( qMax( 0, spacing ) );
1159 }
1160 
1166 {
1167  return m_data->engine.spacing();
1168 }
1169 
1184 {
1185  if ( ratio > 1.0 )
1186  ratio = 1.0;
1187 
1188  LayoutEngine& engine = m_data->engine;
1189 
1190  switch ( pos )
1191  {
1192  case QwtPlot::TopLegend:
1193  case QwtPlot::BottomLegend:
1194  {
1195  if ( ratio <= 0.0 )
1196  ratio = 0.33;
1197 
1198  engine.setLegendRatio( ratio );
1199  engine.setLegendPos( pos );
1200 
1201  break;
1202  }
1203  case QwtPlot::LeftLegend:
1204  case QwtPlot::RightLegend:
1205  {
1206  if ( ratio <= 0.0 )
1207  ratio = 0.5;
1208 
1209  engine.setLegendRatio( ratio );
1210  engine.setLegendPos( pos );
1211 
1212  break;
1213  }
1214  default:
1215  break;
1216  }
1217 }
1218 
1228 {
1229  setLegendPosition( pos, 0.0 );
1230 }
1231 
1238 {
1239  return m_data->engine.legendPos();
1240 }
1241 
1251 void QwtPlotLayout::setLegendRatio( double ratio )
1252 {
1253  setLegendPosition( legendPosition(), ratio );
1254 }
1255 
1261 {
1262  return m_data->engine.legendRatio();
1263 }
1264 
1273 void QwtPlotLayout::setTitleRect( const QRectF& rect )
1274 {
1275  m_data->titleRect = rect;
1276 }
1277 
1283 {
1284  return m_data->titleRect;
1285 }
1286 
1295 void QwtPlotLayout::setFooterRect( const QRectF& rect )
1296 {
1297  m_data->footerRect = rect;
1298 }
1299 
1305 {
1306  return m_data->footerRect;
1307 }
1308 
1319 void QwtPlotLayout::setLegendRect( const QRectF& rect )
1320 {
1321  m_data->legendRect = rect;
1322 }
1323 
1329 {
1330  return m_data->legendRect;
1331 }
1332 
1344 void QwtPlotLayout::setScaleRect( QwtAxisId axisId, const QRectF& rect )
1345 {
1346  if ( QwtAxis::isValid( axisId ) )
1347  m_data->scaleRects[axisId] = rect;
1348 }
1349 
1355 QRectF QwtPlotLayout::scaleRect( QwtAxisId axisId ) const
1356 {
1357  if ( QwtAxis::isValid( axisId ) )
1358  return m_data->scaleRects[axisId];
1359 
1360  return QRectF();
1361 }
1362 
1371 void QwtPlotLayout::setCanvasRect( const QRectF& rect )
1372 {
1373  m_data->canvasRect = rect;
1374 }
1375 
1381 {
1382  return m_data->canvasRect;
1383 }
1384 
1390 {
1391  m_data->titleRect = m_data->footerRect =
1392  m_data->legendRect = m_data->canvasRect = QRectF();
1393 
1394  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
1395  m_data->scaleRects[axisPos] = QRect();
1396 }
1397 
1404 QSize QwtPlotLayout::minimumSizeHint( const QwtPlot* plot ) const
1405 {
1406  LayoutHintData hintData( plot );
1407 
1408  const int xAxesWidth = hintData.xAxesWidth();
1409  const int yAxesHeight = hintData.yAxesHeight();
1410 
1411  const QWidget* canvas = plot->canvas();
1412 
1413  const QMargins m = canvas->contentsMargins();
1414  const QSize minCanvasSize = canvas->minimumSize();
1415 
1416  int w = hintData.yAxesWidth();
1417  int cw = xAxesWidth + m.left() + 1 + m.right() + 1;
1418  w += qMax( cw, minCanvasSize.width() );
1419 
1420  int h = hintData.xAxesHeight();
1421  int ch = yAxesHeight + m.top() + 1 + m.bottom() + 1;
1422  h += qMax( ch, minCanvasSize.height() );
1423 
1424  const QwtTextLabel* labels[2];
1425  labels[0] = plot->titleLabel();
1426  labels[1] = plot->footerLabel();
1427 
1428  for ( int i = 0; i < 2; i++ )
1429  {
1430  const QwtTextLabel* label = labels[i];
1431  if ( label && !label->text().isEmpty() )
1432  {
1433  // we center on the plot canvas.
1434  const bool centerOnCanvas = !( plot->isAxisVisible( QwtAxis::YLeft )
1435  && plot->isAxisVisible( QwtAxis::YRight ) );
1436 
1437  int labelW = w;
1438  if ( centerOnCanvas )
1439  {
1440  labelW -= hintData.yAxesWidth();
1441  }
1442 
1443  int labelH = label->heightForWidth( labelW );
1444  if ( labelH > labelW ) // Compensate for a long title
1445  {
1446  w = labelW = labelH;
1447  if ( centerOnCanvas )
1448  w += hintData.yAxesWidth();
1449 
1450  labelH = label->heightForWidth( labelW );
1451  }
1452  h += labelH + spacing();
1453  }
1454  }
1455 
1456  // Compute the legend contribution
1457 
1458  const QwtAbstractLegend* legend = plot->legend();
1459  if ( legend && !legend->isEmpty() )
1460  {
1461  const LayoutEngine& engine = m_data->engine;
1462 
1463  if ( engine.legendPos() == QwtPlot::LeftLegend
1464  || engine.legendPos() == QwtPlot::RightLegend )
1465  {
1466  int legendW = legend->sizeHint().width();
1467  int legendH = legend->heightForWidth( legendW );
1468 
1469  if ( legend->frameWidth() > 0 )
1470  w += spacing();
1471 
1472  if ( legendH > h )
1473  legendW += legend->scrollExtent( Qt::Horizontal );
1474 
1475  if ( engine.legendRatio() < 1.0 )
1476  legendW = qMin( legendW, int( w / ( 1.0 - engine.legendRatio() ) ) );
1477 
1478  w += legendW + spacing();
1479  }
1480  else
1481  {
1482  int legendW = qMin( legend->sizeHint().width(), w );
1483  int legendH = legend->heightForWidth( legendW );
1484 
1485  if ( legend->frameWidth() > 0 )
1486  h += spacing();
1487 
1488  if ( engine.legendRatio() < 1.0 )
1489  legendH = qMin( legendH, int( h / ( 1.0 - engine.legendRatio() ) ) );
1490 
1491  h += legendH + spacing();
1492  }
1493  }
1494 
1495  return QSize( w, h );
1496 }
1497 
1509  const QRectF& plotRect, Options options )
1510 {
1511  invalidate();
1512 
1513  QRectF rect( plotRect ); // undistributed rest of the plot rect
1514 
1515  // We extract all layout relevant parameters from the widgets,
1516  // and save them to m_data->layoutData.
1517 
1518  LayoutData layoutData( plot );
1519 
1520  QSize legendHint;
1521 
1522  if ( !( options & IgnoreLegend )
1523  && plot->legend() && !plot->legend()->isEmpty() )
1524  {
1525  legendHint = layoutData.legendData.legendHint( plot->legend(), rect );
1526 
1527  m_data->legendRect = m_data->engine.layoutLegend(
1528  options, layoutData.legendData, rect, legendHint );
1529 
1530  // subtract m_data->legendRect from rect
1531 
1532  const QRegion region( rect.toRect() );
1533  rect = region.subtracted( m_data->legendRect.toRect() ).boundingRect();
1534 
1535  switch ( m_data->engine.legendPos() )
1536  {
1537  case QwtPlot::LeftLegend:
1538  {
1539  rect.setLeft( rect.left() + spacing() );
1540  break;
1541  }
1542  case QwtPlot::RightLegend:
1543  {
1544  rect.setRight( rect.right() - spacing() );
1545  break;
1546  }
1547  case QwtPlot::TopLegend:
1548  {
1549  rect.setTop( rect.top() + spacing() );
1550  break;
1551  }
1552  case QwtPlot::BottomLegend:
1553  {
1554  rect.setBottom( rect.bottom() - spacing() );
1555  break;
1556  }
1557  }
1558  }
1559 
1560  /*
1561  +---+-----------+---+
1562  | Title |
1563  +---+-----------+---+
1564  | | Axis | |
1565  +---+-----------+---+
1566  | A | | A |
1567  | x | Canvas | x |
1568  | i | | i |
1569  | s | | s |
1570  +---+-----------+---+
1571  | | Axis | |
1572  +---+-----------+---+
1573  | Footer |
1574  +---+-----------+---+
1575  */
1576 
1577  // title, footer and axes include text labels. The height of each
1578  // label depends on its line breaks, that depend on the width
1579  // for the label. A line break in a horizontal text will reduce
1580  // the available width for vertical texts and vice versa.
1581  // layoutDimensions finds the height/width for title, footer and axes
1582  // including all line breaks.
1583 
1584  using namespace QwtAxis;
1585 
1586  const LayoutEngine::Dimensions dimensions =
1587  m_data->engine.layoutDimensions( options, layoutData, rect );
1588 
1589  if ( dimensions.dimTitle > 0 )
1590  {
1591  QRectF& labelRect = m_data->titleRect;
1592 
1593  labelRect.setRect( rect.left(), rect.top(), rect.width(), dimensions.dimTitle );
1594 
1595  rect.setTop( labelRect.bottom() + spacing() );
1596 
1597  if ( !layoutData.hasSymmetricYAxes() )
1598  {
1599  // if only one of the y axes is missing we align
1600  // the title centered to the canvas
1601 
1602  labelRect = dimensions.centered( rect, labelRect );
1603  }
1604  }
1605 
1606  if ( dimensions.dimFooter > 0 )
1607  {
1608  QRectF& labelRect = m_data->footerRect;
1609 
1610  labelRect.setRect( rect.left(), rect.bottom() - dimensions.dimFooter,
1611  rect.width(), dimensions.dimFooter );
1612 
1613  rect.setBottom( labelRect.top() - spacing() );
1614 
1615  if ( !layoutData.hasSymmetricYAxes() )
1616  {
1617  // if only one of the y axes is missing we align
1618  // the footer centered to the canvas
1619 
1620  labelRect = dimensions.centered( rect, labelRect );
1621  }
1622  }
1623 
1624  m_data->canvasRect = dimensions.innerRect( rect );
1625 
1626  for ( int axisPos = 0; axisPos < AxisPositions; axisPos++ )
1627  {
1628  // set the rects for the axes
1629 
1630  const int pos = 0;
1631  {
1632  const QwtAxisId axisId( axisPos );
1633 
1634  if ( dimensions.dimAxis( axisId ) )
1635  {
1636  const int dim = dimensions.dimAxis( axisId );
1637 
1638  const QRectF& canvasRect = m_data->canvasRect;
1639 
1640  QRectF& scaleRect = m_data->scaleRects[axisId];
1641  scaleRect = canvasRect;
1642 
1643  switch ( axisPos )
1644  {
1645  case YLeft:
1646  {
1647  scaleRect.setX( canvasRect.left() - pos - dim );
1648  scaleRect.setWidth( dim );
1649  break;
1650  }
1651  case YRight:
1652  {
1653  scaleRect.setX( canvasRect.right() + pos );
1654  scaleRect.setWidth( dim );
1655  break;
1656  }
1657  case XBottom:
1658  {
1659  scaleRect.setY( canvasRect.bottom() + pos );
1660  scaleRect.setHeight( dim );
1661  break;
1662  }
1663  case XTop:
1664  {
1665  scaleRect.setY( canvasRect.top() - pos - dim );
1666  scaleRect.setHeight( dim );
1667  break;
1668  }
1669  }
1670  scaleRect = scaleRect.normalized();
1671  }
1672  }
1673  }
1674 
1675  // +---+-----------+---+
1676  // | <- Axis -> |
1677  // +-^-+-----------+-^-+
1678  // | | | | | |
1679  // | | | |
1680  // | A | | A |
1681  // | x | Canvas | x |
1682  // | i | | i |
1683  // | s | | s |
1684  // | | | |
1685  // | | | | | |
1686  // +-V-+-----------+-V-+
1687  // | <- Axis -> |
1688  // +---+-----------+---+
1689 
1690  // The ticks of the axes - not the labels above - should
1691  // be aligned to the canvas. So we try to use the empty
1692  // corners to extend the axes, so that the label texts
1693  // left/right of the min/max ticks are moved into them.
1694 
1695  m_data->engine.alignScales( options, layoutData,
1696  m_data->canvasRect, m_data->scaleRects );
1697 
1698  if ( !m_data->legendRect.isEmpty() )
1699  {
1700  // We prefer to align the legend to the canvas - not to
1701  // the complete plot - if possible.
1702 
1703  m_data->legendRect = m_data->engine.alignLegend(
1704  legendHint, m_data->canvasRect, m_data->legendRect );
1705  }
1706 }
Abstract base class for legend widgets.
virtual int scrollExtent(Qt::Orientation) const
virtual bool isEmpty() const =0
bool hasComponent(ScaleComponent) const
A 2-D plotting widget.
Definition: qwt_plot.h:79
LegendPosition
Definition: qwt_plot.h:94
@ TopLegend
The legend will be above the title.
Definition: qwt_plot.h:105
@ LeftLegend
The legend will be left from the QwtAxis::YLeft axis.
Definition: qwt_plot.h:96
@ RightLegend
The legend will be right from the QwtAxis::YRight axis.
Definition: qwt_plot.h:99
@ BottomLegend
The legend will be below the footer.
Definition: qwt_plot.h:102
QWidget * canvas()
Definition: qwt_plot.cpp:463
QwtTextLabel * footerLabel()
Definition: qwt_plot.cpp:401
bool isAxisVisible(QwtAxisId) const
QwtPlotLayout * plotLayout()
Definition: qwt_plot.cpp:430
QwtAbstractLegend * legend()
Definition: qwt_plot.cpp:445
const QwtScaleWidget * axisWidget(QwtAxisId) const
QwtTextLabel * titleLabel()
Definition: qwt_plot.cpp:357
QRectF titleRect() const
void setCanvasMargin(int margin, int axis=-1)
void setLegendPosition(QwtPlot::LegendPosition pos, double ratio)
Specify the position of the legend.
void setAlignCanvasToScales(bool)
Set the align-canvas-to-axis-scales flag for all axes.
QRectF footerRect() const
int spacing() const
int canvasMargin(int axisId) const
QRectF legendRect() const
virtual ~QwtPlotLayout()
Destructor.
virtual void invalidate()
QwtPlot::LegendPosition legendPosition() const
bool alignCanvasToScale(int axisId) const
virtual QSize minimumSizeHint(const QwtPlot *) const
void setLegendRect(const QRectF &)
Set the geometry for the legend.
QRectF scaleRect(QwtAxisId) const
void setFooterRect(const QRectF &)
Set the geometry for the footer.
void setTitleRect(const QRectF &)
Set the geometry for the title.
double legendRatio() const
QFlags< Option > Options
void setLegendRatio(double ratio)
QRectF canvasRect() const
void setCanvasRect(const QRectF &)
Set the geometry for the canvas.
void setScaleRect(QwtAxisId, const QRectF &)
Set the geometry for an axis.
QwtPlotLayout()
Constructor.
@ IgnoreTitle
Ignore the title.
@ IgnoreFooter
Ignore the footer.
@ IgnoreFrames
Ignore all frames.
virtual void activate(const QwtPlot *, const QRectF &plotRect, Options options=Options())
Recalculate the geometry of all components.
void setAlignCanvasToScale(int axisId, bool)
A Widget which contains a scale.
int startBorderDist() const
QwtText title() const
const QwtScaleDraw * scaleDraw() const
int endBorderDist() const
void getBorderDistHint(int &start, int &end) const
Calculate a hint for the border distances.
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 ...
virtual QSize minimumSizeHint() const override
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
@ PaintUsingTextFont
The text has an individual font.
Definition: qwt_text.h:117
bool isEmpty() const
Definition: qwt_text.cpp:739
void setFont(const QFont &)
Definition: qwt_text.cpp:329
A Widget which displays a QwtText.
virtual int heightForWidth(int) const override
const QwtText & text() const
Return the text.
bool isYAxis(int axisPos)
Definition: qwt_axis.h:57
@ YRight
Y axis right of the canvas.
Definition: qwt_axis.h:27
@ XTop
X axis above the canvas.
Definition: qwt_axis.h:33
@ XBottom
X axis below the canvas.
Definition: qwt_axis.h:30
@ YLeft
Y axis left of the canvas.
Definition: qwt_axis.h:24
bool isValid(int axisPos)
Definition: qwt_axis.h:45
bool isXAxis(int axisPos)
Definition: qwt_axis.h:51