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

Last change on this file since 9828 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
Line 
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
29 bool isValid;
30
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
58#if 1
59 // better find the font sizes from the application font
60 QFont fscl( fontInfo().family(), 10 );
61 QFont fttl( fontInfo().family(), 12, QFont::Bold );
62#endif
63
64 for ( axisId = 0; axisId < axisCnt; axisId++ )
65 {
66 AxisData &d = *d_axisData[axisId];
67
68 d.scaleEngine = new QwtLinearScaleEngine;
69
70 d.scaleWidget->setTransformation(
71 d.scaleEngine->transformation() );
72
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
90 d.isValid = false;
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/*!
110 \return Scale widget of the specified axis, or NULL if axisId is invalid.
111 \param axisId Axis index
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/*!
122 \return Scale widget of the specified axis, or NULL if axisId is invalid.
123 \param axisId Axis index
124*/
125QwtScaleWidget *QwtPlot::axisWidget( int axisId )
126{
127 if ( axisValid( axisId ) )
128 return d_axisData[axisId]->scaleWidget;
129
130 return NULL;
131}
132
133/*!
134 Change the scale engine for an axis
135
136 \param axisId Axis index
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
150 d_axisData[axisId]->scaleWidget->setTransformation(
151 scaleEngine->transformation() );
152
153 d.isValid = false;
154
155 autoRefresh();
156 }
157}
158
159/*!
160 \param axisId Axis index
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/*!
172 \param axisId Axis index
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/*!
183 \return \c True, if autoscaling is enabled
184 \param axisId Axis index
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/*!
195 \return \c True, if a specified axis is enabled
196 \param axisId Axis index
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/*!
207 \return The font of the scale labels for a specified axis
208 \param axisId Axis index
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/*!
220 \return The maximum number of major ticks for a specified axis
221 \param axisId Axis index
222 \sa setAxisMaxMajor(), QwtScaleEngine::divideScale()
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
234 \param axisId Axis index
235 \sa setAxisMaxMinor(), QwtScaleEngine::divideScale()
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
248 axisScaleDiv(axisId).lowerBound(), axisScaleDiv(axisId).upperBound()
249 are the current limits of the axis scale.
250
251 \param axisId Axis index
252 \return Scale division
253
254 \sa QwtScaleDiv, setAxisScaleDiv(), QwtScaleEngine::divideScale()
255*/
256const QwtScaleDiv &QwtPlot::axisScaleDiv( int axisId ) const
257{
258 return d_axisData[axisId]->scaleDiv;
259}
260
261/*!
262 \brief Return the scale draw of a specified axis
263
264 \param axisId Axis index
265 \return Specified scaleDraw for axis, or NULL if axis is invalid.
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/*!
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.
280*/
281QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId )
282{
283 if ( !axisValid( axisId ) )
284 return NULL;
285
286 return axisWidget( axisId )->scaleDraw();
287}
288
289/*!
290 \brief Return the step size parameter that has been set in setAxisScale.
291
292 This doesn't need to be the step size of the current scale.
293
294 \param axisId Axis index
295 \return step size parameter value
296
297 \sa setAxisScale(), QwtScaleEngine::divideScale()
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();
311
312 \param axisId Axis index
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/*!
326 \return Title of a specified axis
327 \param axisId Axis index
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.
346
347 \param axisId Axis index
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.
362
363 \param axisId Axis index
364 \param pos position
365
366 \return Position as axis coordinate
367
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
382
383 \param axisId Axis index
384 \param value value
385 \return X or Y coordinate in the plotting region corresponding
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
398
399 \param axisId Axis index
400 \param font Font
401 \warning This function changes the font of the tick labels,
402 not of the axis title.
403*/
404void QwtPlot::setAxisFont( int axisId, const QFont &font )
405{
406 if ( axisValid( axisId ) )
407 axisWidget( axisId )->setFont( font );
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
416 \param axisId Axis index
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.
434
435 In updateAxes() the scale engine calculates a scale division from the
436 specified parameters, that will be assigned to the scale widget. So
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
442 \param stepSize Major step size. If <code>step == 0</code>, the step size is
443 calculated automatically using the maxMajor setting.
444
445 \sa setAxisMaxMajor(), setAxisAutoScale(), axisStepSize(), QwtScaleEngine::divideScale()
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;
454 d.isValid = false;
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.
466
467 The scale division will be stored locally only until the next call
468 of updateAxes(). So updates of the scale widget usually happen delayed with
469 the next replot.
470
471 \param axisId Axis index
472 \param scaleDiv Scale division
473
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;
484 d.isValid = true;
485
486 autoRefresh();
487 }
488}
489
490/*!
491 \brief Set a scale draw
492
493 \param axisId Axis index
494 \param scaleDraw Object responsible for drawing scales.
495
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
517
518 \param axisId Axis index
519 \param alignment Or'd Qt::AlignmentFlags see <qnamespace.h>
520
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
531
532 \param axisId Axis index
533 \param rotation Angle in degrees. When changing the label rotation,
534 the label alignment might be adjusted too.
535
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
547 \param axisId Axis index
548 \param maxMinor Maximum number of minor steps
549
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;
562 d.isValid = false;
563 autoRefresh();
564 }
565 }
566}
567
568/*!
569 Set the maximum number of major scale intervals for a specified axis
570
571 \param axisId Axis index
572 \param maxMajor Maximum number of major steps
573
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;
586 d.isValid = false;
587 autoRefresh();
588 }
589 }
590}
591
592/*!
593 \brief Change the title of a specified axis
594
595 \param axisId Axis index
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
606
607 \param axisId Axis index
608 \param title Axis title
609*/
610void QwtPlot::setAxisTitle( int axisId, const QwtText &title )
611{
612 if ( axisValid( axisId ) )
613 axisWidget( axisId )->setTitle( title );
614}
615
616/*!
617 \brief Rebuild the axes scales
618
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() )
623 and assigned to scale widget.
624
625 When the scale boundaries have been assigned with setAxisScale() a
626 scale division is calculated ( QwtScaleEngine::didvideScale() )
627 for this interval and assigned to the scale widget.
628
629 When the scale has been set explicitly by setAxisScaleDiv() the
630 locally stored scale division gets assigned to the scale widget.
631
632 The scale widget indicates modifications by emitting a
633 QwtScaleWidget::scaleDivChanged() signal.
634
635 updateAxes() is usually called by replot().
636
637 \sa setAxisAutoScale(), setAxisScale(), setAxisScaleDiv(), replot()
638 QwtPlotItem::boundingRect()
639 */
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();
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() );
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 {
684 d.isValid = false;
685
686 minValue = intv[axisId].minValue();
687 maxValue = intv[axisId].maxValue();
688
689 d.scaleEngine->autoScale( d.maxMajor,
690 minValue, maxValue, stepSize );
691 }
692 if ( !d.isValid )
693 {
694 d.scaleDiv = d.scaleEngine->divideScale(
695 minValue, maxValue,
696 d.maxMajor, d.maxMinor, stepSize );
697 d.isValid = true;
698 }
699
700 QwtScaleWidget *scaleWidget = axisWidget( axisId );
701 scaleWidget->setScaleDiv( d.scaleDiv );
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;
711 if ( item->testItemInterest( QwtPlotItem::ScaleInterest ) )
712 {
713 item->updateScaleDiv( axisScaleDiv( item->xAxis() ),
714 axisScaleDiv( item->yAxis() ) );
715 }
716 }
717}
718
Note: See TracBrowser for help on using the repository browser.