source: ntrip/trunk/GnssCenter/qwt/qwt_plot_axis.cpp@ 10210

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