source: ntrip/branches/BNC_2.12/qwtpolar/qwt_polar_layout.cpp @ 7991

Last change on this file since 7991 was 7991, checked in by stuerze, 22 months ago

minor adaptations to allow the successful comilation of BNC on a Rasperry Pi

File size: 11.7 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
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#include <qscrollbar.h>
16
17class QwtPolarLayout::LayoutData
18{
19public:
20    void init( const QwtPolarPlot *, const QRectF &rect );
21
22    struct t_legendData
23    {
24        int frameWidth;
25        int vScrollBarWidth;
26        int hScrollBarHeight;
27        QSizeF hint;
28    } legend;
29
30    struct t_titleData
31    {
32        QwtText text;
33        int frameWidth;
34    } title;
35
36    struct t_canvasData
37    {
38        int frameWidth;
39    } canvas;
40};
41
42void QwtPolarLayout::LayoutData::init(
43    const QwtPolarPlot *plot, const QRectF &rect )
44{
45    // legend
46
47    if ( plot->plotLayout()->legendPosition() != QwtPolarPlot::ExternalLegend
48            && plot->legend() )
49    {
50        legend.frameWidth = plot->legend()->frameWidth();
51        legend.vScrollBarWidth =
52            plot->legend()->verticalScrollBar()->sizeHint().width();
53        legend.hScrollBarHeight =
54            plot->legend()->horizontalScrollBar()->sizeHint().height();
55
56        const QSizeF hint = plot->legend()->sizeHint();
57
58        double w = qMin( hint.width(), rect.width() );
59        double h = plot->legend()->heightForWidth( w );
60        if ( h == 0.0 )
61            h = hint.height();
62
63        if ( h > rect.height() )
64            w += legend.vScrollBarWidth;
65
66        legend.hint = QSizeF( w, h );
67    }
68
69    // title
70
71    title.frameWidth = 0;
72    title.text = QwtText();
73
74    if ( plot->titleLabel() )
75    {
76        const QwtTextLabel *label = plot->titleLabel();
77        title.text = label->text();
78        if ( !( title.text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) )
79            title.text.setFont( label->font() );
80
81        title.frameWidth = plot->titleLabel()->frameWidth();
82    }
83
84    // canvas
85
86    canvas.frameWidth = plot->canvas()->frameWidth();
87}
88
89class QwtPolarLayout::PrivateData
90{
91public:
92    PrivateData():
93        margin( 0 ),
94        spacing( 0 )
95    {
96    }
97
98    QRectF titleRect;
99    QRectF legendRect;
100    QRectF canvasRect;
101
102    QwtPolarLayout::LayoutData layoutData;
103
104    QwtPolarPlot::LegendPosition legendPos;
105    double legendRatio;
106
107    unsigned int margin;
108    unsigned int spacing;
109};
110
111/*!
112  \brief Constructor
113 */
114
115QwtPolarLayout::QwtPolarLayout()
116{
117    d_data = new PrivateData;
118
119    setLegendPosition( QwtPolarPlot::BottomLegend );
120    invalidate();
121}
122
123//! Destructor
124QwtPolarLayout::~QwtPolarLayout()
125{
126    delete d_data;
127}
128
129/*!
130  \brief Specify the position of the legend
131  \param pos The legend's position.
132  \param ratio Ratio between legend and the bounding rect
133               of title, canvas and axes. The legend will be shrinked
134               if it would need more space than the given ratio.
135               The ratio is limited to ]0.0 .. 1.0]. In case of <= 0.0
136               it will be reset to the default ratio.
137               The default vertical/horizontal ratio is 0.33/0.5.
138
139  \sa QwtPolarPlot::setLegendPosition()
140*/
141
142void QwtPolarLayout::setLegendPosition(
143    QwtPolarPlot::LegendPosition pos, double ratio )
144{
145    if ( ratio > 1.0 )
146        ratio = 1.0;
147
148    switch( pos )
149    {
150        case QwtPolarPlot::TopLegend:
151        case QwtPolarPlot::BottomLegend:
152        {
153            if ( ratio <= 0.0 )
154                ratio = 0.33;
155            d_data->legendRatio = ratio;
156            d_data->legendPos = pos;
157            break;
158        }
159        case QwtPolarPlot::LeftLegend:
160        case QwtPolarPlot::RightLegend:
161        {
162            if ( ratio <= 0.0 )
163                ratio = 0.5;
164            d_data->legendRatio = ratio;
165            d_data->legendPos = pos;
166            break;
167        }
168        case QwtPolarPlot::ExternalLegend:
169        {
170            d_data->legendRatio = ratio; // meaningless
171            d_data->legendPos = pos;
172            break;
173        }
174        default:
175            break;
176    }
177}
178
179/*!
180  \brief Specify the position of the legend
181  \param pos The legend's position. Valid values are
182      \c QwtPolarPlot::LeftLegend, \c QwtPolarPlot::RightLegend,
183      \c QwtPolarPlot::TopLegend, \c QwtPolarPlot::BottomLegend.
184
185  \sa QwtPolarPlot::setLegendPosition()
186*/
187void QwtPolarLayout::setLegendPosition( QwtPolarPlot::LegendPosition pos )
188{
189    setLegendPosition( pos, 0.0 );
190}
191
192/*!
193  \return Position of the legend
194  \sa setLegendPosition(), QwtPolarPlot::setLegendPosition(),
195      QwtPolarPlot::legendPosition()
196*/
197QwtPolarPlot::LegendPosition QwtPolarLayout::legendPosition() const
198{
199    return d_data->legendPos;
200}
201
202/*!
203  Specify the relative size of the legend in the plot
204  \param ratio Ratio between legend and the bounding rect
205               of title, canvas and axes. The legend will be shrinked
206               if it would need more space than the given ratio.
207               The ratio is limited to ]0.0 .. 1.0]. In case of <= 0.0
208               it will be reset to the default ratio.
209               The default vertical/horizontal ratio is 0.33/0.5.
210*/
211void QwtPolarLayout::setLegendRatio( double ratio )
212{
213    setLegendPosition( legendPosition(), ratio );
214}
215
216/*!
217  \return The relative size of the legend in the plot.
218  \sa setLegendPosition()
219*/
220double QwtPolarLayout::legendRatio() const
221{
222    return d_data->legendRatio;
223}
224
225/*!
226  \return Geometry for the title
227  \sa activate(), invalidate()
228*/
229
230const QRectF &QwtPolarLayout::titleRect() const
231{
232    return d_data->titleRect;
233}
234
235/*!
236  \return Geometry for the legend
237  \sa activate(), invalidate()
238*/
239
240const QRectF &QwtPolarLayout::legendRect() const
241{
242    return d_data->legendRect;
243}
244
245/*!
246  \return Geometry for the canvas
247  \sa activate(), invalidate()
248*/
249const QRectF &QwtPolarLayout::canvasRect() const
250{
251    return d_data->canvasRect;
252}
253
254/*!
255  Invalidate the geometry of all components.
256  \sa activate()
257*/
258void QwtPolarLayout::invalidate()
259{
260    d_data->titleRect = d_data->legendRect = d_data->canvasRect = QRect();
261}
262
263/*!
264  Find the geometry for the legend
265  \param options Options how to layout the legend
266  \param rect Rectangle where to place the legend
267  \return Geometry for the legend
268*/
269
270QRectF QwtPolarLayout::layoutLegend( Options options, QRectF &rect ) const
271{
272    const QSizeF hint( d_data->layoutData.legend.hint );
273
274    int dim;
275    if ( d_data->legendPos == QwtPolarPlot::LeftLegend
276        || d_data->legendPos == QwtPolarPlot::RightLegend )
277    {
278        // We don't allow vertical legends to take more than
279        // half of the available space.
280
281        dim = qMin( hint.width(), qreal(rect.width() * d_data->legendRatio) );
282
283        if ( !( options & IgnoreScrollbars ) )
284        {
285            if ( hint.height() > rect.height() )
286            {
287                // The legend will need additional
288                // space for the vertical scrollbar.
289
290                dim += d_data->layoutData.legend.vScrollBarWidth;
291            }
292        }
293    }
294    else
295    {
296        dim = qMin( hint.width(), qreal(rect.width() * d_data->legendRatio) );
297        dim = qMax( dim, d_data->layoutData.legend.hScrollBarHeight );
298    }
299
300    QRectF legendRect = rect;
301    switch( d_data->legendPos )
302    {
303        case QwtPolarPlot::LeftLegend:
304        {
305            legendRect.setWidth( dim );
306            rect.setLeft( legendRect.right() );
307            break;
308        }
309        case QwtPolarPlot::RightLegend:
310        {
311            legendRect.setX( rect.right() - dim + 1 );
312            legendRect.setWidth( dim );
313            rect.setRight( legendRect.left() );
314            break;
315        }
316        case QwtPolarPlot::TopLegend:
317        {
318            legendRect.setHeight( dim );
319            rect.setTop( legendRect.bottom() );
320            break;
321        }
322        case QwtPolarPlot::BottomLegend:
323        {
324            legendRect.setY( rect.bottom() - dim + 1 );
325            legendRect.setHeight( dim );
326            rect.setBottom( legendRect.top() );
327            break;
328        }
329        case QwtPolarPlot::ExternalLegend:
330            break;
331    }
332
333    return legendRect;
334}
335
336/*!
337  \brief Recalculate the geometry of all components.
338
339  \param plot Plot to be layout
340  \param boundingRect Rect where to place the components
341  \param options Options
342
343  \sa invalidate(), titleRect(), legendRect(), canvasRect()
344*/
345void QwtPolarLayout::activate( const QwtPolarPlot *plot,
346    const QRectF &boundingRect, Options options )
347{
348    invalidate();
349
350    QRectF rect( boundingRect ); // undistributed rest of the plot rect
351    rect.adjust( d_data->margin, d_data->margin,
352        -d_data->margin, -d_data->margin );
353
354    // We extract all layout relevant data from the widgets
355    // and save them to d_data->layoutData.
356
357    d_data->layoutData.init( plot, rect );
358    if ( !( options & IgnoreLegend )
359        && d_data->legendPos != QwtPolarPlot::ExternalLegend
360        && plot->legend() && !plot->legend()->isEmpty() )
361    {
362        d_data->legendRect = layoutLegend( options, rect );
363        if ( d_data->layoutData.legend.frameWidth &&
364                !( options & IgnoreFrames ) )
365        {
366            // In case of a frame we have to insert a spacing.
367            // Otherwise the leading of the font separates
368            // legend and scale/canvas
369
370            switch( d_data->legendPos )
371            {
372                case QwtPolarPlot::LeftLegend:
373                    rect.setLeft( rect.left() + d_data->spacing );
374                    break;
375
376                case QwtPolarPlot::RightLegend:
377                    rect.setRight( rect.right() - d_data->spacing );
378                    break;
379
380                case QwtPolarPlot::TopLegend:
381                    rect.setTop( rect.top() + d_data->spacing );
382                    break;
383
384                case QwtPolarPlot::BottomLegend:
385                    rect.setBottom( rect.bottom() - d_data->spacing );
386                    break;
387
388                case QwtPolarPlot::ExternalLegend:
389                    break; // suppress compiler warning
390            }
391        }
392    }
393
394    if ( !( options & IgnoreTitle ) &&
395        !d_data->layoutData.title.text.isEmpty() )
396    {
397        int h = d_data->layoutData.title.text.heightForWidth( rect.width() );
398        if ( !( options & IgnoreFrames ) )
399            h += 2 * d_data->layoutData.title.frameWidth;
400
401        d_data->titleRect = QRectF( rect.x(), rect.y(), rect.width(), h );
402
403        // subtract title
404        rect.setTop( rect.top() + h + d_data->spacing );
405    }
406
407    if ( plot->zoomPos().radius() > 0.0 || plot->zoomFactor() < 1.0 )
408    {
409        // In zoomed state we have no idea about the geometry that
410        // is best for the plot. So we use the complete rectangle
411        // accepting, that there might a lot of space wasted
412        // around the plot.
413
414        d_data->canvasRect = rect;
415    }
416    else
417    {
418        // In full state we know, that we want
419        // to display something circular.
420
421        const int dim = qMin( rect.width(), rect.height() );
422
423        d_data->canvasRect.setX( rect.center().x() - dim / 2 );
424        d_data->canvasRect.setY( rect.y() );
425        d_data->canvasRect.setSize( QSize( dim, dim ) );
426    }
427
428    if ( !d_data->legendRect.isEmpty() )
429    {
430        if ( d_data->legendPos == QwtPolarPlot::LeftLegend
431            || d_data->legendPos == QwtPolarPlot::RightLegend )
432        {
433            // We prefer to align the legend to the canvas - not to
434            // the complete plot - if possible.
435
436            if ( d_data->layoutData.legend.hint.height()
437                    < d_data->canvasRect.height() )
438            {
439                d_data->legendRect.setY( d_data->canvasRect.y() );
440                d_data->legendRect.setHeight( d_data->canvasRect.height() );
441            }
442        }
443    }
444}
Note: See TracBrowser for help on using the repository browser.