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

Last change on this file since 8154 was 8127, checked in by stoecker, 7 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

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
70 d.scaleWidget->setTransformation(
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
[8127]150 d_axisData[axisId]->scaleWidget->setTransformation(
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
195/*!
[8127]196 \return \c True, if a specified axis is enabled
197 \param axisId Axis index
[4271]198*/
199bool QwtPlot::axisEnabled( int axisId ) const
200{
201 if ( axisValid( axisId ) )
202 return d_axisData[axisId]->isEnabled;
203 else
204 return false;
205}
206
207/*!
[8127]208 \return The font of the scale labels for a specified axis
209 \param axisId Axis index
[4271]210*/
211QFont QwtPlot::axisFont( int axisId ) const
212{
213 if ( axisValid( axisId ) )
214 return axisWidget( axisId )->font();
215 else
216 return QFont();
217
218}
219
220/*!
[8127]221 \return The maximum number of major ticks for a specified axis
222 \param axisId Axis index
223 \sa setAxisMaxMajor(), QwtScaleEngine::divideScale()
[4271]224*/
225int QwtPlot::axisMaxMajor( int axisId ) const
226{
227 if ( axisValid( axisId ) )
228 return d_axisData[axisId]->maxMajor;
229 else
230 return 0;
231}
232
233/*!
234 \return the maximum number of minor ticks for a specified axis
[8127]235 \param axisId Axis index
236 \sa setAxisMaxMinor(), QwtScaleEngine::divideScale()
[4271]237*/
238int QwtPlot::axisMaxMinor( int axisId ) const
239{
240 if ( axisValid( axisId ) )
241 return d_axisData[axisId]->maxMinor;
242 else
243 return 0;
244}
245
246/*!
247 \brief Return the scale division of a specified axis
248
[8127]249 axisScaleDiv(axisId).lowerBound(), axisScaleDiv(axisId).upperBound()
[4271]250 are the current limits of the axis scale.
251
[8127]252 \param axisId Axis index
[4271]253 \return Scale division
254
[8127]255 \sa QwtScaleDiv, setAxisScaleDiv(), QwtScaleEngine::divideScale()
[4271]256*/
[8127]257const QwtScaleDiv &QwtPlot::axisScaleDiv( int axisId ) const
[4271]258{
[8127]259 return d_axisData[axisId]->scaleDiv;
[4271]260}
261
262/*!
[8127]263 \brief Return the scale draw of a specified axis
[4271]264
[8127]265 \param axisId Axis index
266 \return Specified scaleDraw for axis, or NULL if axis is invalid.
[4271]267*/
268const QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) const
269{
270 if ( !axisValid( axisId ) )
271 return NULL;
272
273 return axisWidget( axisId )->scaleDraw();
274}
275
276/*!
[8127]277 \brief Return the scale draw of a specified axis
278
279 \param axisId Axis index
280 \return Specified scaleDraw for axis, or NULL if axis is invalid.
[4271]281*/
282QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId )
283{
284 if ( !axisValid( axisId ) )
285 return NULL;
286
287 return axisWidget( axisId )->scaleDraw();
288}
289
290/*!
[8127]291 \brief Return the step size parameter that has been set in setAxisScale.
[4271]292
[8127]293 This doesn't need to be the step size of the current scale.
294
295 \param axisId Axis index
[4271]296 \return step size parameter value
297
[8127]298 \sa setAxisScale(), QwtScaleEngine::divideScale()
[4271]299*/
300double QwtPlot::axisStepSize( int axisId ) const
301{
302 if ( !axisValid( axisId ) )
303 return 0;
304
305 return d_axisData[axisId]->stepSize;
306}
307
308/*!
309 \brief Return the current interval of the specified axis
310
311 This is only a convenience function for axisScaleDiv( axisId )->interval();
312
[8127]313 \param axisId Axis index
[4271]314 \return Scale interval
315
316 \sa QwtScaleDiv, axisScaleDiv()
317*/
318QwtInterval QwtPlot::axisInterval( int axisId ) const
319{
320 if ( !axisValid( axisId ) )
321 return QwtInterval();
322
323 return d_axisData[axisId]->scaleDiv.interval();
324}
325
326/*!
[8127]327 \return Title of a specified axis
328 \param axisId Axis index
[4271]329*/
330QwtText QwtPlot::axisTitle( int axisId ) const
331{
332 if ( axisValid( axisId ) )
333 return axisWidget( axisId )->title();
334 else
335 return QwtText();
336}
337
338/*!
339 \brief Enable or disable a specified axis
340
341 When an axis is disabled, this only means that it is not
342 visible on the screen. Curves, markers and can be attached
343 to disabled axes, and transformation of screen coordinates
344 into values works as normal.
345
346 Only xBottom and yLeft are enabled by default.
[8127]347
348 \param axisId Axis index
[4271]349 \param tf \c true (enabled) or \c false (disabled)
350*/
351void QwtPlot::enableAxis( int axisId, bool tf )
352{
353 if ( axisValid( axisId ) && tf != d_axisData[axisId]->isEnabled )
354 {
355 d_axisData[axisId]->isEnabled = tf;
356 updateLayout();
357 }
358}
359
360/*!
361 Transform the x or y coordinate of a position in the
362 drawing region into a value.
[8127]363
364 \param axisId Axis index
[4271]365 \param pos position
[8127]366
367 \return Position as axis coordinate
368
[4271]369 \warning The position can be an x or a y coordinate,
370 depending on the specified axis.
371*/
372double QwtPlot::invTransform( int axisId, int pos ) const
373{
374 if ( axisValid( axisId ) )
375 return( canvasMap( axisId ).invTransform( pos ) );
376 else
377 return 0.0;
378}
379
380
381/*!
382 \brief Transform a value into a coordinate in the plotting region
[8127]383
384 \param axisId Axis index
[4271]385 \param value value
[8127]386 \return X or Y coordinate in the plotting region corresponding
[4271]387 to the value.
388*/
389double QwtPlot::transform( int axisId, double value ) const
390{
391 if ( axisValid( axisId ) )
392 return( canvasMap( axisId ).transform( value ) );
393 else
394 return 0.0;
395}
396
397/*!
398 \brief Change the font of an axis
[8127]399
400 \param axisId Axis index
401 \param font Font
[4271]402 \warning This function changes the font of the tick labels,
403 not of the axis title.
404*/
[8127]405void QwtPlot::setAxisFont( int axisId, const QFont &font )
[4271]406{
407 if ( axisValid( axisId ) )
[8127]408 axisWidget( axisId )->setFont( font );
[4271]409}
410
411/*!
412 \brief Enable autoscaling for a specified axis
413
414 This member function is used to switch back to autoscaling mode
415 after a fixed scale has been set. Autoscaling is enabled by default.
416
[8127]417 \param axisId Axis index
[4271]418 \param on On/Off
419 \sa setAxisScale(), setAxisScaleDiv(), updateAxes()
420
421 \note The autoscaling flag has no effect until updateAxes() is executed
422 ( called by replot() ).
423*/
424void QwtPlot::setAxisAutoScale( int axisId, bool on )
425{
426 if ( axisValid( axisId ) && ( d_axisData[axisId]->doAutoScale != on ) )
427 {
428 d_axisData[axisId]->doAutoScale = on;
429 autoRefresh();
430 }
431}
432
433/*!
434 \brief Disable autoscaling and specify a fixed scale for a selected axis.
[8127]435
436 In updateAxes() the scale engine calculates a scale division from the
437 specified parameters, that will be assigned to the scale widget. So
438 updates of the scale widget usually happen delayed with the next replot.
439
440 \param axisId Axis index
441 \param min Minimum of the scale
442 \param max Maximum of the scale
[4271]443 \param stepSize Major step size. If <code>step == 0</code>, the step size is
[8127]444 calculated automatically using the maxMajor setting.
445
446 \sa setAxisMaxMajor(), setAxisAutoScale(), axisStepSize(), QwtScaleEngine::divideScale()
[4271]447*/
448void QwtPlot::setAxisScale( int axisId, double min, double max, double stepSize )
449{
450 if ( axisValid( axisId ) )
451 {
452 AxisData &d = *d_axisData[axisId];
453
454 d.doAutoScale = false;
[8127]455 d.isValid = false;
[4271]456
457 d.minValue = min;
458 d.maxValue = max;
459 d.stepSize = stepSize;
460
461 autoRefresh();
462 }
463}
464
465/*!
466 \brief Disable autoscaling and specify a fixed scale for a selected axis.
[8127]467
468 The scale division will be stored locally only until the next call
469 of updateAxes(). So updates of the scale widget usually happen delayed with
470 the next replot.
471
472 \param axisId Axis index
[4271]473 \param scaleDiv Scale division
[8127]474
[4271]475 \sa setAxisScale(), setAxisAutoScale()
476*/
477void QwtPlot::setAxisScaleDiv( int axisId, const QwtScaleDiv &scaleDiv )
478{
479 if ( axisValid( axisId ) )
480 {
481 AxisData &d = *d_axisData[axisId];
482
483 d.doAutoScale = false;
484 d.scaleDiv = scaleDiv;
[8127]485 d.isValid = true;
[4271]486
487 autoRefresh();
488 }
489}
490
491/*!
492 \brief Set a scale draw
493
[8127]494 \param axisId Axis index
495 \param scaleDraw Object responsible for drawing scales.
496
[4271]497 By passing scaleDraw it is possible to extend QwtScaleDraw
498 functionality and let it take place in QwtPlot. Please note
499 that scaleDraw has to be created with new and will be deleted
500 by the corresponding QwtScale member ( like a child object ).
501
502 \sa QwtScaleDraw, QwtScaleWidget
503 \warning The attributes of scaleDraw will be overwritten by those of the
504 previous QwtScaleDraw.
505*/
506
507void QwtPlot::setAxisScaleDraw( int axisId, QwtScaleDraw *scaleDraw )
508{
509 if ( axisValid( axisId ) )
510 {
511 axisWidget( axisId )->setScaleDraw( scaleDraw );
512 autoRefresh();
513 }
514}
515
516/*!
517 Change the alignment of the tick labels
[8127]518
519 \param axisId Axis index
[4271]520 \param alignment Or'd Qt::AlignmentFlags see <qnamespace.h>
[8127]521
[4271]522 \sa QwtScaleDraw::setLabelAlignment()
523*/
524void QwtPlot::setAxisLabelAlignment( int axisId, Qt::Alignment alignment )
525{
526 if ( axisValid( axisId ) )
527 axisWidget( axisId )->setLabelAlignment( alignment );
528}
529
530/*!
531 Rotate all tick labels
[8127]532
533 \param axisId Axis index
[4271]534 \param rotation Angle in degrees. When changing the label rotation,
535 the label alignment might be adjusted too.
[8127]536
[4271]537 \sa QwtScaleDraw::setLabelRotation(), setAxisLabelAlignment()
538*/
539void QwtPlot::setAxisLabelRotation( int axisId, double rotation )
540{
541 if ( axisValid( axisId ) )
542 axisWidget( axisId )->setLabelRotation( rotation );
543}
544
545/*!
546 Set the maximum number of minor scale intervals for a specified axis
547
[8127]548 \param axisId Axis index
549 \param maxMinor Maximum number of minor steps
550
[4271]551 \sa axisMaxMinor()
552*/
553void QwtPlot::setAxisMaxMinor( int axisId, int maxMinor )
554{
555 if ( axisValid( axisId ) )
556 {
557 maxMinor = qBound( 0, maxMinor, 100 );
558
559 AxisData &d = *d_axisData[axisId];
560 if ( maxMinor != d.maxMinor )
561 {
562 d.maxMinor = maxMinor;
[8127]563 d.isValid = false;
[4271]564 autoRefresh();
565 }
566 }
567}
568
569/*!
570 Set the maximum number of major scale intervals for a specified axis
571
[8127]572 \param axisId Axis index
573 \param maxMajor Maximum number of major steps
574
[4271]575 \sa axisMaxMajor()
576*/
577void QwtPlot::setAxisMaxMajor( int axisId, int maxMajor )
578{
579 if ( axisValid( axisId ) )
580 {
581 maxMajor = qBound( 1, maxMajor, 10000 );
582
583 AxisData &d = *d_axisData[axisId];
584 if ( maxMajor != d.maxMajor )
585 {
586 d.maxMajor = maxMajor;
[8127]587 d.isValid = false;
[4271]588 autoRefresh();
589 }
590 }
591}
592
593/*!
594 \brief Change the title of a specified axis
[8127]595
596 \param axisId Axis index
[4271]597 \param title axis title
598*/
599void QwtPlot::setAxisTitle( int axisId, const QString &title )
600{
601 if ( axisValid( axisId ) )
602 axisWidget( axisId )->setTitle( title );
603}
604
605/*!
606 \brief Change the title of a specified axis
[8127]607
608 \param axisId Axis index
609 \param title Axis title
[4271]610*/
611void QwtPlot::setAxisTitle( int axisId, const QwtText &title )
612{
613 if ( axisValid( axisId ) )
614 axisWidget( axisId )->setTitle( title );
615}
616
[8127]617/*!
618 \brief Rebuild the axes scales
619
620 In case of autoscaling the boundaries of a scale are calculated
621 from the bounding rectangles of all plot items, having the
622 QwtPlotItem::AutoScale flag enabled ( QwtScaleEngine::autoScale() ).
623 Then a scale division is calculated ( QwtScaleEngine::didvideScale() )
624 and assigned to scale widget.
625
626 When the scale boundaries have been assigned with setAxisScale() a
627 scale division is calculated ( QwtScaleEngine::didvideScale() )
628 for this interval and assigned to the scale widget.
629
630 When the scale has been set explicitly by setAxisScaleDiv() the
631 locally stored scale division gets assigned to the scale widget.
632
633 The scale widget indicates modifications by emitting a
634 QwtScaleWidget::scaleDivChanged() signal.
635
636 updateAxes() is usually called by replot().
637
638 \sa setAxisAutoScale(), setAxisScale(), setAxisScaleDiv(), replot()
639 QwtPlotItem::boundingRect()
640 */
[4271]641void QwtPlot::updateAxes()
642{
643 // Find bounding interval of the item data
644 // for all axes, where autoscaling is enabled
645
646 QwtInterval intv[axisCnt];
647
648 const QwtPlotItemList& itmList = itemList();
649
650 QwtPlotItemIterator it;
651 for ( it = itmList.begin(); it != itmList.end(); ++it )
652 {
653 const QwtPlotItem *item = *it;
654
655 if ( !item->testItemAttribute( QwtPlotItem::AutoScale ) )
656 continue;
657
658 if ( !item->isVisible() )
659 continue;
660
661 if ( axisAutoScale( item->xAxis() ) || axisAutoScale( item->yAxis() ) )
662 {
663 const QRectF rect = item->boundingRect();
[8127]664
665 if ( rect.width() >= 0.0 )
666 intv[item->xAxis()] |= QwtInterval( rect.left(), rect.right() );
667
668 if ( rect.height() >= 0.0 )
669 intv[item->yAxis()] |= QwtInterval( rect.top(), rect.bottom() );
[4271]670 }
671 }
672
673 // Adjust scales
674
675 for ( int axisId = 0; axisId < axisCnt; axisId++ )
676 {
677 AxisData &d = *d_axisData[axisId];
678
679 double minValue = d.minValue;
680 double maxValue = d.maxValue;
681 double stepSize = d.stepSize;
682
683 if ( d.doAutoScale && intv[axisId].isValid() )
684 {
[8127]685 d.isValid = false;
[4271]686
687 minValue = intv[axisId].minValue();
688 maxValue = intv[axisId].maxValue();
689
690 d.scaleEngine->autoScale( d.maxMajor,
691 minValue, maxValue, stepSize );
692 }
[8127]693 if ( !d.isValid )
[4271]694 {
695 d.scaleDiv = d.scaleEngine->divideScale(
696 minValue, maxValue,
697 d.maxMajor, d.maxMinor, stepSize );
[8127]698 d.isValid = true;
[4271]699 }
700
701 QwtScaleWidget *scaleWidget = axisWidget( axisId );
[8127]702 scaleWidget->setScaleDiv( d.scaleDiv );
[4271]703
704 int startDist, endDist;
705 scaleWidget->getBorderDistHint( startDist, endDist );
706 scaleWidget->setBorderDist( startDist, endDist );
707 }
708
709 for ( it = itmList.begin(); it != itmList.end(); ++it )
710 {
711 QwtPlotItem *item = *it;
[8127]712 if ( item->testItemInterest( QwtPlotItem::ScaleInterest ) )
713 {
714 item->updateScaleDiv( axisScaleDiv( item->xAxis() ),
715 axisScaleDiv( item->yAxis() ) );
716 }
[4271]717 }
718}
719
Note: See TracBrowser for help on using the repository browser.