Qwt User's Guide 6.2.0

qwt_polar_layout.cpp
1 /******************************************************************************
2 * QwtPolar Widget Library
3 * Copyright (C) 2008 Uwe Rathmann
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the Qwt License, Version 1.0
7 *****************************************************************************/
8
9 #include "qwt_polar_layout.h"
10 #include "qwt_polar_plot.h"
11 #include "qwt_polar_canvas.h"
12 #include "qwt_text.h"
13 #include "qwt_text_label.h"
14 #include "qwt_legend.h"
15
16 class QwtPolarLayout::LayoutData
17 {
18 public:
19 void init( const QwtPolarPlot*, const QRectF& rect );
20
21 struct t_legendData
22 {
23 int frameWidth;
24 int hScrollExtent;
25 int vScrollExtent;
26 QSizeF hint;
27 } legend;
28
29 struct t_titleData
30 {
31 QwtText text;
32 int frameWidth;
33 } title;
34
35 struct t_canvasData
36 {
37 int frameWidth;
38 } canvas;
39 };
40
41 void QwtPolarLayout::LayoutData::init(
42 const QwtPolarPlot* plot, const QRectF& rect )
43 {
44 // legend
45
46 if ( plot->plotLayout()->legendPosition() != QwtPolarPlot::ExternalLegend
47 && plot->legend() )
48 {
49 legend.frameWidth = plot->legend()->frameWidth();
50 legend.hScrollExtent =
51 plot->legend()->scrollExtent( Qt::Horizontal );
52 legend.vScrollExtent =
53 plot->legend()->scrollExtent( Qt::Vertical );
54
55 const QSizeF hint = plot->legend()->sizeHint();
56
57 double w = qMin( hint.width(), rect.width() );
58 double h = plot->legend()->heightForWidth( w );
59 if ( h == 0.0 )
60 h = hint.height();
61
62 if ( h > rect.height() )
63 w += legend.hScrollExtent;
64
65 legend.hint = QSizeF( w, h );
66 }
67
68 // title
69
70 title.frameWidth = 0;
71 title.text = QwtText();
72
73 if ( plot->titleLabel() )
74 {
75 const QwtTextLabel* label = plot->titleLabel();
76 title.text = label->text();
77 if ( !( title.text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) )
78 title.text.setFont( label->font() );
79
80 title.frameWidth = plot->titleLabel()->frameWidth();
81 }
82
83 // canvas
84
85 canvas.frameWidth = plot->canvas()->frameWidth();
86 }
87
88 class QwtPolarLayout::PrivateData
89 {
90 public:
91 PrivateData()
92 : margin( 0 )
93 , spacing( 0 )
94 {
95 }
96
97 QRectF titleRect;
98 QRectF legendRect;
99 QRectF canvasRect;
100
101 QwtPolarLayout::LayoutData layoutData;
102
103 QwtPolarPlot::LegendPosition legendPos;
104 double legendRatio;
105
106 unsigned int margin;
107 unsigned int spacing;
108 };
109
114 QwtPolarLayout::QwtPolarLayout()
115 {
116 m_data = new PrivateData;
117
118 setLegendPosition( QwtPolarPlot::BottomLegend );
119 invalidate();
120 }
121
123 QwtPolarLayout::~QwtPolarLayout()
124 {
125 delete m_data;
126 }
127
141 void QwtPolarLayout::setLegendPosition(
142 QwtPolarPlot::LegendPosition pos, double ratio )
143 {
144 if ( ratio > 1.0 )
145 ratio = 1.0;
146
147 switch( pos )
148 {
149 case QwtPolarPlot::TopLegend:
150 case QwtPolarPlot::BottomLegend:
151 {
152 if ( ratio <= 0.0 )
153 ratio = 0.33;
154 m_data->legendRatio = ratio;
155 m_data->legendPos = pos;
156 break;
157 }
158 case QwtPolarPlot::LeftLegend:
159 case QwtPolarPlot::RightLegend:
160 {
161 if ( ratio <= 0.0 )
162 ratio = 0.5;
163 m_data->legendRatio = ratio;
164 m_data->legendPos = pos;
165 break;
166 }
167 case QwtPolarPlot::ExternalLegend:
168 {
169 m_data->legendRatio = ratio; // meaningless
170 m_data->legendPos = pos;
171 break;
172 }
173 default:
174 break;
175 }
176 }
177
186 void QwtPolarLayout::setLegendPosition( QwtPolarPlot::LegendPosition pos )
187 {
188 setLegendPosition( pos, 0.0 );
189 }
190
196 QwtPolarPlot::LegendPosition QwtPolarLayout::legendPosition() const
197 {
198 return m_data->legendPos;
199 }
200
210 void QwtPolarLayout::setLegendRatio( double ratio )
211 {
212 setLegendPosition( legendPosition(), ratio );
213 }
214
219 double QwtPolarLayout::legendRatio() const
220 {
221 return m_data->legendRatio;
222 }
223
229 const QRectF& QwtPolarLayout::titleRect() const
230 {
231 return m_data->titleRect;
232 }
233
239 const QRectF& QwtPolarLayout::legendRect() const
240 {
241 return m_data->legendRect;
242 }
243
248 const QRectF& QwtPolarLayout::canvasRect() const
249 {
250 return m_data->canvasRect;
251 }
252
257 void QwtPolarLayout::invalidate()
258 {
259 m_data->titleRect = m_data->legendRect = m_data->canvasRect = QRect();
260 }
261
269 QRectF QwtPolarLayout::layoutLegend( Options options, QRectF& rect ) const
270 {
271 const QSizeF hint( m_data->layoutData.legend.hint );
272
273 int dim;
274 if ( m_data->legendPos == QwtPolarPlot::LeftLegend
275 || m_data->legendPos == QwtPolarPlot::RightLegend )
276 {
277 // We don't allow vertical legends to take more than
278 // half of the available space.
279
280 dim = qMin( double( hint.width() ), rect.width() * m_data->legendRatio );
281
282 if ( !( options & IgnoreScrollbars ) )
283 {
284 if ( hint.height() > rect.height() )
285 {
286 // The legend will need additional
287 // space for the vertical scrollbar.
288
289 dim += m_data->layoutData.legend.hScrollExtent;
290 }
291 }
292 }
293 else
294 {
295 dim = qMin( double( hint.height() ), rect.height() * m_data->legendRatio );
296 dim = qMax( dim, m_data->layoutData.legend.vScrollExtent );
297 }
298
299 QRectF legendRect = rect;
300 switch( m_data->legendPos )
301 {
302 case QwtPolarPlot::LeftLegend:
303 {
304 legendRect.setWidth( dim );
305 rect.setLeft( legendRect.right() );
306 break;
307 }
308 case QwtPolarPlot::RightLegend:
309 {
310 legendRect.setX( rect.right() - dim + 1 );
311 legendRect.setWidth( dim );
312 rect.setRight( legendRect.left() );
313 break;
314 }
315 case QwtPolarPlot::TopLegend:
316 {
317 legendRect.setHeight( dim );
318 rect.setTop( legendRect.bottom() );
319 break;
320 }
321 case QwtPolarPlot::BottomLegend:
322 {
323 legendRect.setY( rect.bottom() - dim + 1 );
324 legendRect.setHeight( dim );
325 rect.setBottom( legendRect.top() );
326 break;
327 }
328 case QwtPolarPlot::ExternalLegend:
329 break;
330 }
331
332 return legendRect;
333 }
334
344 void QwtPolarLayout::activate( const QwtPolarPlot* plot,
345 const QRectF& boundingRect, Options options )
346 {
347 invalidate();
348
349 QRectF rect( boundingRect ); // undistributed rest of the plot rect
350 rect.adjust( m_data->margin, m_data->margin,
351 -m_data->margin, -m_data->margin );
352
353 // We extract all layout relevant data from the widgets
354 // and save them to m_data->layoutData.
355
356 m_data->layoutData.init( plot, rect );
357 if ( !( options & IgnoreLegend )
358 && m_data->legendPos != QwtPolarPlot::ExternalLegend
359 && plot->legend() && !plot->legend()->isEmpty() )
360 {
361 m_data->legendRect = layoutLegend( options, rect );
362 if ( m_data->layoutData.legend.frameWidth &&
363 !( options & IgnoreFrames ) )
364 {
365 // In case of a frame we have to insert a spacing.
366 // Otherwise the leading of the font separates
367 // legend and scale/canvas
368
369 switch( m_data->legendPos )
370 {
371 case QwtPolarPlot::LeftLegend:
372 rect.setLeft( rect.left() + m_data->spacing );
373 break;
374
375 case QwtPolarPlot::RightLegend:
376 rect.setRight( rect.right() - m_data->spacing );
377 break;
378
379 case QwtPolarPlot::TopLegend:
380 rect.setTop( rect.top() + m_data->spacing );
381 break;
382
383 case QwtPolarPlot::BottomLegend:
384 rect.setBottom( rect.bottom() - m_data->spacing );
385 break;
386
387 case QwtPolarPlot::ExternalLegend:
388 break; // suppress compiler warning
389 }
390 }
391 }
392
393 if ( !( options & IgnoreTitle ) &&
394 !m_data->layoutData.title.text.isEmpty() )
395 {
396 int h = m_data->layoutData.title.text.heightForWidth( rect.width() );
397 if ( !( options & IgnoreFrames ) )
398 h += 2 * m_data->layoutData.title.frameWidth;
399
400 m_data->titleRect = QRectF( rect.x(), rect.y(), rect.width(), h );
401
402 // subtract title
403 rect.setTop( rect.top() + h + m_data->spacing );
404 }
405
406 if ( plot->zoomPos().radius() > 0.0 || plot->zoomFactor() < 1.0 )
407 {
408 // In zoomed state we have no idea about the geometry that
409 // is best for the plot. So we use the complete rectangle
410 // accepting, that there might a lot of space wasted
411 // around the plot.
412
413 m_data->canvasRect = rect;
414 }
415 else
416 {
417 // In full state we know, that we want
418 // to display something circular.
419
420 const int dim = qMin( rect.width(), rect.height() );
421
422 m_data->canvasRect.setX( rect.center().x() - dim / 2 );
423 m_data->canvasRect.setY( rect.y() );
424 m_data->canvasRect.setSize( QSize( dim, dim ) );
425 }
426
427 if ( !m_data->legendRect.isEmpty() )
428 {
429 if ( m_data->legendPos == QwtPolarPlot::LeftLegend
430 || m_data->legendPos == QwtPolarPlot::RightLegend )
431 {
432 // We prefer to align the legend to the canvas - not to
433 // the complete plot - if possible.
434
435 if ( m_data->layoutData.legend.hint.height()
436 < m_data->canvasRect.height() )
437 {
438 m_data->legendRect.setY( m_data->canvasRect.y() );
439 m_data->legendRect.setHeight( m_data->canvasRect.height() );
440 }
441 }
442 }
443 }
QwtAbstractLegend::scrollExtent
virtual int scrollExtent(Qt::Orientation) const
Definition: qwt_abstract_legend.cpp:35
QwtAbstractLegend::isEmpty
virtual bool isEmpty() const =0
QwtPointPolar::radius
double radius() const
Returns the radius.
Definition: qwt_point_polar.h:102
QwtPolarLayout::legendRect
const QRectF & legendRect() const
Definition: qwt_polar_layout.cpp:239
QwtPolarLayout::~QwtPolarLayout
virtual ~QwtPolarLayout()
Destructor.
Definition: qwt_polar_layout.cpp:123
QwtPolarLayout::layoutLegend
QRectF layoutLegend(Options options, QRectF &) const
Definition: qwt_polar_layout.cpp:269
QwtPolarLayout::setLegendRatio
void setLegendRatio(double ratio)
Definition: qwt_polar_layout.cpp:210
QwtPolarLayout::legendRatio
double legendRatio() const
Definition: qwt_polar_layout.cpp:219
QwtPolarLayout::setLegendPosition
void setLegendPosition(QwtPolarPlot::LegendPosition pos, double ratio)
Specify the position of the legend.
Definition: qwt_polar_layout.cpp:141
QwtPolarLayout::invalidate
virtual void invalidate()
Definition: qwt_polar_layout.cpp:257
QwtPolarLayout::legendPosition
QwtPolarPlot::LegendPosition legendPosition() const
Definition: qwt_polar_layout.cpp:196
QwtPolarLayout::activate
virtual void activate(const QwtPolarPlot *, const QRectF &rect, Options options=Options())
Recalculate the geometry of all components.
Definition: qwt_polar_layout.cpp:344
QwtPolarLayout::QwtPolarLayout
QwtPolarLayout()
Constructor.
Definition: qwt_polar_layout.cpp:114
QwtPolarLayout::titleRect
const QRectF & titleRect() const
Definition: qwt_polar_layout.cpp:229
QwtPolarLayout::IgnoreLegend
@ IgnoreLegend
Ignore the legend.
Definition: qwt_polar_layout.h:40
QwtPolarLayout::IgnoreScrollbars
@ IgnoreScrollbars
Ignore the dimension of the scrollbars.
Definition: qwt_polar_layout.h:31
QwtPolarLayout::IgnoreTitle
@ IgnoreTitle
Ignore the title.
Definition: qwt_polar_layout.h:37
QwtPolarLayout::IgnoreFrames
@ IgnoreFrames
Ignore all frames.
Definition: qwt_polar_layout.h:34
QwtPolarLayout::Options
QFlags< Option > Options
Definition: qwt_polar_layout.h:43
QwtPolarLayout::canvasRect
const QRectF & canvasRect() const
Definition: qwt_polar_layout.cpp:248
QwtPolarPlot
A plotting widget, displaying a polar coordinate system.
Definition: qwt_polar_plot.h:47
QwtPolarPlot::plotLayout
QwtPolarLayout * plotLayout()
Definition: qwt_polar_plot.cpp:1274
QwtPolarPlot::zoomPos
QwtPointPolar zoomPos() const
Definition: qwt_polar_plot.cpp:682
QwtPolarPlot::zoomFactor
double zoomFactor() const
Definition: qwt_polar_plot.cpp:691
QwtPolarPlot::legend
QwtAbstractLegend * legend()
Definition: qwt_polar_plot.cpp:286
QwtPolarPlot::canvas
QwtPolarCanvas * canvas()
Definition: qwt_polar_plot.cpp:914
QwtPolarPlot::LegendPosition
LegendPosition
Definition: qwt_polar_plot.h:60
QwtPolarPlot::BottomLegend
@ BottomLegend
The legend will be below the canvas.
Definition: qwt_polar_plot.h:68
QwtPolarPlot::LeftLegend
@ LeftLegend
The legend will be left from the canvas.
Definition: qwt_polar_plot.h:62
QwtPolarPlot::ExternalLegend
@ ExternalLegend
Definition: qwt_polar_plot.h:81
QwtPolarPlot::TopLegend
@ TopLegend
The legend will be between canvas and title.
Definition: qwt_polar_plot.h:71
QwtPolarPlot::RightLegend
@ RightLegend
The legend will be right from the canvas.
Definition: qwt_polar_plot.h:65
QwtPolarPlot::titleLabel
QwtTextLabel * titleLabel()
Definition: qwt_polar_plot.cpp:153
QwtText
A class representing a text.
Definition: qwt_text.h:52
QwtText::PaintUsingTextFont
@ PaintUsingTextFont
The text has an individual font.
Definition: qwt_text.h:117
QwtText::text
QString text() const
Definition: qwt_text.cpp:289
QwtTextLabel
A Widget which displays a QwtText.
Definition: qwt_text_label.h:27
QwtTextLabel::text
const QwtText & text() const
Return the text.
Definition: qwt_text_label.cpp:118