source: ntrip/trunk/BNC/qwt/qwt_plot_axis.cpp@ 9573

Last change on this file since 9573 was 9383, checked in by stoecker, 3 years ago

update to qwt verion 6.1.1 to fix build with newer Qt5

File size: 17.7 KB
RevLine 
[4271]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.h"
11#include "qwt_math.h"
12#include "qwt_scale_widget.h"
13#include "qwt_scale_div.h"
14#include "qwt_scale_engine.h"
15
16class QwtPlot::AxisData
17{
18public:
19 bool isEnabled;
20 bool doAutoScale;
21
22 double minValue;
23 double maxValue;
24 double stepSize;
25
26 int maxMajor;
27 int maxMinor;
28
[8127]29 bool isValid;
30
[4271]31 QwtScaleDiv scaleDiv;
32 QwtScaleEngine *scaleEngine;
33 QwtScaleWidget *scaleWidget;
34};
35
36//! Initialize axes
37void QwtPlot::initAxesData()
38{
39 int axisId;
40
41 for ( axisId = 0; axisId < axisCnt; axisId++ )
42 d_axisData[axisId] = new AxisData;
43
44 d_axisData[yLeft]->scaleWidget =
45 new QwtScaleWidget( QwtScaleDraw::LeftScale, this );
46 d_axisData[yRight]->scaleWidget =
47 new QwtScaleWidget( QwtScaleDraw::RightScale, this );
48 d_axisData[xTop]->scaleWidget =
49 new QwtScaleWidget( QwtScaleDraw::TopScale, this );
50 d_axisData[xBottom]->scaleWidget =
51 new QwtScaleWidget( QwtScaleDraw::BottomScale, this );
52
53 d_axisData[yLeft]->scaleWidget->setObjectName( "QwtPlotAxisYLeft" );
54 d_axisData[yRight]->scaleWidget->setObjectName( "QwtPlotAxisYRight" );
55 d_axisData[xTop]->scaleWidget->setObjectName( "QwtPlotAxisXTop" );
56 d_axisData[xBottom]->scaleWidget->setObjectName( "QwtPlotAxisXBottom" );
57
[8127]58#if 1
59 // better find the font sizes from the application font
[4271]60 QFont fscl( fontInfo().family(), 10 );
61 QFont fttl( fontInfo().family(), 12, QFont::Bold );
[8127]62#endif
[4271]63
64 for ( axisId = 0; axisId < axisCnt; axisId++ )
65 {
66 AxisData &d = *d_axisData[axisId];
67
[8127]68 d.scaleEngine = new QwtLinearScaleEngine;
69
[9383]70 d.scaleWidget->setTransformation(
[8127]71 d.scaleEngine->transformation() );
72
[4271]73 d.scaleWidget->setFont( fscl );
74 d.scaleWidget->setMargin( 2 );
75
76 QwtText text = d.scaleWidget->title();
77 text.setFont( fttl );
78 d.scaleWidget->setTitle( text );
79
80 d.doAutoScale = true;
81
82 d.minValue = 0.0;
83 d.maxValue = 1000.0;
84 d.stepSize = 0.0;
85
86 d.maxMinor = 5;
87 d.maxMajor = 8;
88
89
[8127]90 d.isValid = false;
[4271]91 }
92
93 d_axisData[yLeft]->isEnabled = true;
94 d_axisData[yRight]->isEnabled = false;
95 d_axisData[xBottom]->isEnabled = true;
96 d_axisData[xTop]->isEnabled = false;
97}
98
99void QwtPlot::deleteAxesData()
100{
101 for ( int axisId = 0; axisId < axisCnt; axisId++ )
102 {
103 delete d_axisData[axisId]->scaleEngine;
104 delete d_axisData[axisId];
105 d_axisData[axisId] = NULL;
106 }
107}
108
109/*!
[8127]110 \return Scale widget of the specified axis, or NULL if axisId is invalid.
111 \param axisId Axis index
[4271]112*/
113const QwtScaleWidget *QwtPlot::axisWidget( int axisId ) const
114{
115 if ( axisValid( axisId ) )
116 return d_axisData[axisId]->scaleWidget;
117
118 return NULL;
119}
120
121/*!
[8127]122 \return Scale widget of the specified axis, or NULL if axisId is invalid.
123 \param axisId Axis index
[4271]124*/
125QwtScaleWidget *QwtPlot::axisWidget( int axisId )
126{
127 if ( axisValid( axisId ) )
128 return d_axisData[axisId]->scaleWidget;
129
130 return NULL;
131}
132
133/*!
[8127]134 Change the scale engine for an axis
[4271]135
[8127]136 \param axisId Axis index
[4271]137 \param scaleEngine Scale engine
138
139 \sa axisScaleEngine()
140*/
141void QwtPlot::setAxisScaleEngine( int axisId, QwtScaleEngine *scaleEngine )
142{
143 if ( axisValid( axisId ) && scaleEngine != NULL )
144 {
145 AxisData &d = *d_axisData[axisId];
146
147 delete d.scaleEngine;
148 d.scaleEngine = scaleEngine;
149
[9383]150 d_axisData[axisId]->scaleWidget->setTransformation(
[8127]151 scaleEngine->transformation() );
[4271]152
[8127]153 d.isValid = false;
154
[4271]155 autoRefresh();
156 }
157}
158
159/*!
[8127]160 \param axisId Axis index
[4271]161 \return Scale engine for a specific axis
162*/
163QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId )
164{
165 if ( axisValid( axisId ) )
166 return d_axisData[axisId]->scaleEngine;
167 else
168 return NULL;
169}
170
171/*!
[8127]172 \param axisId Axis index
[4271]173 \return Scale engine for a specific axis
174*/
175const QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId ) const
176{
177 if ( axisValid( axisId ) )
178 return d_axisData[axisId]->scaleEngine;
179 else
180 return NULL;
181}
182/*!
[8127]183 \return \c True, if autoscaling is enabled
184 \param axisId Axis index
[4271]185*/
186bool QwtPlot::axisAutoScale( int axisId ) const
187{
188 if ( axisValid( axisId ) )
189 return d_axisData[axisId]->doAutoScale;
190 else
191 return false;
192}
193
194/*!
[8127]195 \return \c True, if a specified axis is enabled
196 \param axisId Axis index
[4271]197*/
198bool QwtPlot::axisEnabled( int axisId ) const
199{
200 if ( axisValid( axisId ) )
201 return d_axisData[axisId]->isEnabled;
202 else
203 return false;
204}
205
206/*!
[8127]207 \return The font of the scale labels for a specified axis
208 \param axisId Axis index
[4271]209*/
210QFont QwtPlot::axisFont( int axisId ) const
211{
212 if ( axisValid( axisId ) )
213 return axisWidget( axisId )->font();
214 else
215 return QFont();
216
217}
218
219/*!
[8127]220 \return The maximum number of major ticks for a specified axis
221 \param axisId Axis index
222 \sa setAxisMaxMajor(), QwtScaleEngine::divideScale()
[4271]223*/
224int QwtPlot::axisMaxMajor( int axisId ) const
225{
226 if ( axisValid( axisId ) )
227 return d_axisData[axisId]->maxMajor;
228 else
229 return 0;
230}
231
232/*!
233 \return the maximum number of minor ticks for a specified axis
[8127]234 \param axisId Axis index
235 \sa setAxisMaxMinor(), QwtScaleEngine::divideScale()
[4271]236*/
237int QwtPlot::axisMaxMinor( int axisId ) const
238{
239 if ( axisValid( axisId ) )
240 return d_axisData[axisId]->maxMinor;
241 else
242 return 0;
243}
244
245/*!
246 \brief Return the scale division of a specified axis
247
[8127]248 axisScaleDiv(axisId).lowerBound(), axisScaleDiv(axisId).upperBound()
[4271]249 are the current limits of the axis scale.
250
[8127]251 \param axisId Axis index
[4271]252 \return Scale division
253
[8127]254 \sa QwtScaleDiv, setAxisScaleDiv(), QwtScaleEngine::divideScale()
[4271]255*/
[8127]256const QwtScaleDiv &QwtPlot::axisScaleDiv( int axisId ) const
[4271]257{
[8127]258 return d_axisData[axisId]->scaleDiv;
[4271]259}
260
261/*!
[8127]262 \brief Return the scale draw of a specified axis
[4271]263
[8127]264 \param axisId Axis index
265 \return Specified scaleDraw for axis, or NULL if axis is invalid.
[4271]266*/
267const QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) const
268{
269 if ( !axisValid( axisId ) )
270 return NULL;
271
272 return axisWidget( axisId )->scaleDraw();
273}
274
275/*!
[8127]276 \brief Return the scale draw of a specified axis
277
278 \param axisId Axis index
279 \return Specified scaleDraw for axis, or NULL if axis is invalid.
[4271]280*/
281QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId )
282{
283 if ( !axisValid( axisId ) )
284 return NULL;
285
286 return axisWidget( axisId )->scaleDraw();
287}
288
289/*!
[9383]290 \brief Return the step size parameter that has been set in setAxisScale.
[4271]291
[8127]292 This doesn't need to be the step size of the current scale.
293
294 \param axisId Axis index
[4271]295 \return step size parameter value
296
[8127]297 \sa setAxisScale(), QwtScaleEngine::divideScale()
[4271]298*/
299double QwtPlot::axisStepSize( int axisId ) const
300{
301 if ( !axisValid( axisId ) )
302 return 0;
303
304 return d_axisData[axisId]->stepSize;
305}
306
307/*!
308 \brief Return the current interval of the specified axis
309
310 This is only a convenience function for axisScaleDiv( axisId )->interval();
[9383]311
[8127]312 \param axisId Axis index
[4271]313 \return Scale interval
314
315 \sa QwtScaleDiv, axisScaleDiv()
316*/
317QwtInterval QwtPlot::axisInterval( int axisId ) const
318{
319 if ( !axisValid( axisId ) )
320 return QwtInterval();
321
322 return d_axisData[axisId]->scaleDiv.interval();
323}
324
325/*!
[8127]326 \return Title of a specified axis
327 \param axisId Axis index
[4271]328*/
329QwtText QwtPlot::axisTitle( int axisId ) const
330{
331 if ( axisValid( axisId ) )
332 return axisWidget( axisId )->title();
333 else
334 return QwtText();
335}
336
337/*!
338 \brief Enable or disable a specified axis
339
340 When an axis is disabled, this only means that it is not
341 visible on the screen. Curves, markers and can be attached
342 to disabled axes, and transformation of screen coordinates
343 into values works as normal.
344
345 Only xBottom and yLeft are enabled by default.
[8127]346
347 \param axisId Axis index
[4271]348 \param tf \c true (enabled) or \c false (disabled)
349*/
350void QwtPlot::enableAxis( int axisId, bool tf )
351{
352 if ( axisValid( axisId ) && tf != d_axisData[axisId]->isEnabled )
353 {
354 d_axisData[axisId]->isEnabled = tf;
355 updateLayout();
356 }
357}
358
359/*!
360 Transform the x or y coordinate of a position in the
361 drawing region into a value.
[8127]362
363 \param axisId Axis index
[4271]364 \param pos position
[8127]365
366 \return Position as axis coordinate
367
[4271]368 \warning The position can be an x or a y coordinate,
369 depending on the specified axis.
370*/
371double QwtPlot::invTransform( int axisId, int pos ) const
372{
373 if ( axisValid( axisId ) )
374 return( canvasMap( axisId ).invTransform( pos ) );
375 else
376 return 0.0;
377}
378
379
380/*!
381 \brief Transform a value into a coordinate in the plotting region
[8127]382
383 \param axisId Axis index
[4271]384 \param value value
[8127]385 \return X or Y coordinate in the plotting region corresponding
[4271]386 to the value.
387*/
388double QwtPlot::transform( int axisId, double value ) const
389{
390 if ( axisValid( axisId ) )
391 return( canvasMap( axisId ).transform( value ) );
392 else
393 return 0.0;
394}
395
396/*!
397 \brief Change the font of an axis
[8127]398
399 \param axisId Axis index
400 \param font Font
[4271]401 \warning This function changes the font of the tick labels,
402 not of the axis title.
403*/
[8127]404void QwtPlot::setAxisFont( int axisId, const QFont &font )
[4271]405{
406 if ( axisValid( axisId ) )
[8127]407 axisWidget( axisId )->setFont( font );
[4271]408}
409
410/*!
411 \brief Enable autoscaling for a specified axis
412
413 This member function is used to switch back to autoscaling mode
414 after a fixed scale has been set. Autoscaling is enabled by default.
415
[8127]416 \param axisId Axis index
[4271]417 \param on On/Off
418 \sa setAxisScale(), setAxisScaleDiv(), updateAxes()
419
420 \note The autoscaling flag has no effect until updateAxes() is executed
421 ( called by replot() ).
422*/
423void QwtPlot::setAxisAutoScale( int axisId, bool on )
424{
425 if ( axisValid( axisId ) && ( d_axisData[axisId]->doAutoScale != on ) )
426 {
427 d_axisData[axisId]->doAutoScale = on;
428 autoRefresh();
429 }
430}
431
432/*!
433 \brief Disable autoscaling and specify a fixed scale for a selected axis.
[8127]434
[9383]435 In updateAxes() the scale engine calculates a scale division from the
436 specified parameters, that will be assigned to the scale widget. So
[8127]437 updates of the scale widget usually happen delayed with the next replot.
438
439 \param axisId Axis index
440 \param min Minimum of the scale
441 \param max Maximum of the scale
[4271]442 \param stepSize Major step size. If <code>step == 0</code>, the step size is
[8127]443 calculated automatically using the maxMajor setting.
444
445 \sa setAxisMaxMajor(), setAxisAutoScale(), axisStepSize(), QwtScaleEngine::divideScale()
[4271]446*/
447void QwtPlot::setAxisScale( int axisId, double min, double max, double stepSize )
448{
449 if ( axisValid( axisId ) )
450 {
451 AxisData &d = *d_axisData[axisId];
452
453 d.doAutoScale = false;
[8127]454 d.isValid = false;
[4271]455
456 d.minValue = min;
457 d.maxValue = max;
458 d.stepSize = stepSize;
459
460 autoRefresh();
461 }
462}
463
464/*!
465 \brief Disable autoscaling and specify a fixed scale for a selected axis.
[8127]466
467 The scale division will be stored locally only until the next call
[9383]468 of updateAxes(). So updates of the scale widget usually happen delayed with
[8127]469 the next replot.
470
471 \param axisId Axis index
[4271]472 \param scaleDiv Scale division
[8127]473
[4271]474 \sa setAxisScale(), setAxisAutoScale()
475*/
476void QwtPlot::setAxisScaleDiv( int axisId, const QwtScaleDiv &scaleDiv )
477{
478 if ( axisValid( axisId ) )
479 {
480 AxisData &d = *d_axisData[axisId];
481
482 d.doAutoScale = false;
483 d.scaleDiv = scaleDiv;
[8127]484 d.isValid = true;
[4271]485
486 autoRefresh();
487 }
488}
489
490/*!
491 \brief Set a scale draw
492
[8127]493 \param axisId Axis index
494 \param scaleDraw Object responsible for drawing scales.
495
[4271]496 By passing scaleDraw it is possible to extend QwtScaleDraw
497 functionality and let it take place in QwtPlot. Please note
498 that scaleDraw has to be created with new and will be deleted
499 by the corresponding QwtScale member ( like a child object ).
500
501 \sa QwtScaleDraw, QwtScaleWidget
502 \warning The attributes of scaleDraw will be overwritten by those of the
503 previous QwtScaleDraw.
504*/
505
506void QwtPlot::setAxisScaleDraw( int axisId, QwtScaleDraw *scaleDraw )
507{
508 if ( axisValid( axisId ) )
509 {
510 axisWidget( axisId )->setScaleDraw( scaleDraw );
511 autoRefresh();
512 }
513}
514
515/*!
516 Change the alignment of the tick labels
[8127]517
518 \param axisId Axis index
[4271]519 \param alignment Or'd Qt::AlignmentFlags see <qnamespace.h>
[8127]520
[4271]521 \sa QwtScaleDraw::setLabelAlignment()
522*/
523void QwtPlot::setAxisLabelAlignment( int axisId, Qt::Alignment alignment )
524{
525 if ( axisValid( axisId ) )
526 axisWidget( axisId )->setLabelAlignment( alignment );
527}
528
529/*!
530 Rotate all tick labels
[8127]531
532 \param axisId Axis index
[4271]533 \param rotation Angle in degrees. When changing the label rotation,
534 the label alignment might be adjusted too.
[8127]535
[4271]536 \sa QwtScaleDraw::setLabelRotation(), setAxisLabelAlignment()
537*/
538void QwtPlot::setAxisLabelRotation( int axisId, double rotation )
539{
540 if ( axisValid( axisId ) )
541 axisWidget( axisId )->setLabelRotation( rotation );
542}
543
544/*!
545 Set the maximum number of minor scale intervals for a specified axis
546
[8127]547 \param axisId Axis index
548 \param maxMinor Maximum number of minor steps
549
[4271]550 \sa axisMaxMinor()
551*/
552void QwtPlot::setAxisMaxMinor( int axisId, int maxMinor )
553{
554 if ( axisValid( axisId ) )
555 {
556 maxMinor = qBound( 0, maxMinor, 100 );
557
558 AxisData &d = *d_axisData[axisId];
559 if ( maxMinor != d.maxMinor )
560 {
561 d.maxMinor = maxMinor;
[8127]562 d.isValid = false;
[4271]563 autoRefresh();
564 }
565 }
566}
567
568/*!
569 Set the maximum number of major scale intervals for a specified axis
570
[8127]571 \param axisId Axis index
572 \param maxMajor Maximum number of major steps
573
[4271]574 \sa axisMaxMajor()
575*/
576void QwtPlot::setAxisMaxMajor( int axisId, int maxMajor )
577{
578 if ( axisValid( axisId ) )
579 {
580 maxMajor = qBound( 1, maxMajor, 10000 );
581
582 AxisData &d = *d_axisData[axisId];
583 if ( maxMajor != d.maxMajor )
584 {
585 d.maxMajor = maxMajor;
[8127]586 d.isValid = false;
[4271]587 autoRefresh();
588 }
589 }
590}
591
592/*!
593 \brief Change the title of a specified axis
[8127]594
595 \param axisId Axis index
[4271]596 \param title axis title
597*/
598void QwtPlot::setAxisTitle( int axisId, const QString &title )
599{
600 if ( axisValid( axisId ) )
601 axisWidget( axisId )->setTitle( title );
602}
603
604/*!
605 \brief Change the title of a specified axis
[8127]606
607 \param axisId Axis index
608 \param title Axis title
[4271]609*/
610void QwtPlot::setAxisTitle( int axisId, const QwtText &title )
611{
612 if ( axisValid( axisId ) )
613 axisWidget( axisId )->setTitle( title );
614}
615
[9383]616/*!
[8127]617 \brief Rebuild the axes scales
618
[9383]619 In case of autoscaling the boundaries of a scale are calculated
620 from the bounding rectangles of all plot items, having the
621 QwtPlotItem::AutoScale flag enabled ( QwtScaleEngine::autoScale() ).
622 Then a scale division is calculated ( QwtScaleEngine::didvideScale() )
[8127]623 and assigned to scale widget.
624
[9383]625 When the scale boundaries have been assigned with setAxisScale() a
[8127]626 scale division is calculated ( QwtScaleEngine::didvideScale() )
627 for this interval and assigned to the scale widget.
628
[9383]629 When the scale has been set explicitly by setAxisScaleDiv() the
[8127]630 locally stored scale division gets assigned to the scale widget.
631
[9383]632 The scale widget indicates modifications by emitting a
[8127]633 QwtScaleWidget::scaleDivChanged() signal.
634
[9383]635 updateAxes() is usually called by replot().
[8127]636
637 \sa setAxisAutoScale(), setAxisScale(), setAxisScaleDiv(), replot()
638 QwtPlotItem::boundingRect()
639 */
[4271]640void QwtPlot::updateAxes()
641{
642 // Find bounding interval of the item data
643 // for all axes, where autoscaling is enabled
644
645 QwtInterval intv[axisCnt];
646
647 const QwtPlotItemList& itmList = itemList();
648
649 QwtPlotItemIterator it;
650 for ( it = itmList.begin(); it != itmList.end(); ++it )
651 {
652 const QwtPlotItem *item = *it;
653
654 if ( !item->testItemAttribute( QwtPlotItem::AutoScale ) )
655 continue;
656
657 if ( !item->isVisible() )
658 continue;
659
660 if ( axisAutoScale( item->xAxis() ) || axisAutoScale( item->yAxis() ) )
661 {
662 const QRectF rect = item->boundingRect();
[8127]663
664 if ( rect.width() >= 0.0 )
665 intv[item->xAxis()] |= QwtInterval( rect.left(), rect.right() );
666
667 if ( rect.height() >= 0.0 )
668 intv[item->yAxis()] |= QwtInterval( rect.top(), rect.bottom() );
[4271]669 }
670 }
671
672 // Adjust scales
673
674 for ( int axisId = 0; axisId < axisCnt; axisId++ )
675 {
676 AxisData &d = *d_axisData[axisId];
677
678 double minValue = d.minValue;
679 double maxValue = d.maxValue;
680 double stepSize = d.stepSize;
681
682 if ( d.doAutoScale && intv[axisId].isValid() )
683 {
[8127]684 d.isValid = false;
[4271]685
686 minValue = intv[axisId].minValue();
687 maxValue = intv[axisId].maxValue();
688
689 d.scaleEngine->autoScale( d.maxMajor,
690 minValue, maxValue, stepSize );
691 }
[8127]692 if ( !d.isValid )
[4271]693 {
694 d.scaleDiv = d.scaleEngine->divideScale(
695 minValue, maxValue,
696 d.maxMajor, d.maxMinor, stepSize );
[8127]697 d.isValid = true;
[4271]698 }
699
700 QwtScaleWidget *scaleWidget = axisWidget( axisId );
[8127]701 scaleWidget->setScaleDiv( d.scaleDiv );
[4271]702
703 int startDist, endDist;
704 scaleWidget->getBorderDistHint( startDist, endDist );
705 scaleWidget->setBorderDist( startDist, endDist );
706 }
707
708 for ( it = itmList.begin(); it != itmList.end(); ++it )
709 {
710 QwtPlotItem *item = *it;
[8127]711 if ( item->testItemInterest( QwtPlotItem::ScaleInterest ) )
712 {
713 item->updateScaleDiv( axisScaleDiv( item->xAxis() ),
714 axisScaleDiv( item->yAxis() ) );
715 }
[4271]716 }
717}
718
Note: See TracBrowser for help on using the repository browser.