source: ntrip/branches/BNC_2.11.0/qwt/qwt_plot_marker.cpp@ 9484

Last change on this file since 9484 was 4271, checked in by mervart, 13 years ago
File size: 14.1 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_marker.h"
11#include "qwt_painter.h"
12#include "qwt_scale_map.h"
13#include "qwt_symbol.h"
14#include "qwt_text.h"
15#include "qwt_math.h"
16#include "qwt_legend.h"
17#include "qwt_legend_item.h"
18#include <qpainter.h>
19
20class QwtPlotMarker::PrivateData
21{
22public:
23 PrivateData():
24 labelAlignment( Qt::AlignCenter ),
25 labelOrientation( Qt::Horizontal ),
26 spacing( 2 ),
27 symbol( NULL ),
28 style( QwtPlotMarker::NoLine ),
29 xValue( 0.0 ),
30 yValue( 0.0 )
31 {
32 }
33
34 ~PrivateData()
35 {
36 delete symbol;
37 }
38
39 QwtText label;
40 Qt::Alignment labelAlignment;
41 Qt::Orientation labelOrientation;
42 int spacing;
43
44 QPen pen;
45 const QwtSymbol *symbol;
46 LineStyle style;
47
48 double xValue;
49 double yValue;
50};
51
52//! Sets alignment to Qt::AlignCenter, and style to QwtPlotMarker::NoLine
53QwtPlotMarker::QwtPlotMarker():
54 QwtPlotItem( QwtText( "Marker" ) )
55{
56 d_data = new PrivateData;
57 setZ( 30.0 );
58}
59
60//! Destructor
61QwtPlotMarker::~QwtPlotMarker()
62{
63 delete d_data;
64}
65
66//! \return QwtPlotItem::Rtti_PlotMarker
67int QwtPlotMarker::rtti() const
68{
69 return QwtPlotItem::Rtti_PlotMarker;
70}
71
72//! Return Value
73QPointF QwtPlotMarker::value() const
74{
75 return QPointF( d_data->xValue, d_data->yValue );
76}
77
78//! Return x Value
79double QwtPlotMarker::xValue() const
80{
81 return d_data->xValue;
82}
83
84//! Return y Value
85double QwtPlotMarker::yValue() const
86{
87 return d_data->yValue;
88}
89
90//! Set Value
91void QwtPlotMarker::setValue( const QPointF& pos )
92{
93 setValue( pos.x(), pos.y() );
94}
95
96//! Set Value
97void QwtPlotMarker::setValue( double x, double y )
98{
99 if ( x != d_data->xValue || y != d_data->yValue )
100 {
101 d_data->xValue = x;
102 d_data->yValue = y;
103 itemChanged();
104 }
105}
106
107//! Set X Value
108void QwtPlotMarker::setXValue( double x )
109{
110 setValue( x, d_data->yValue );
111}
112
113//! Set Y Value
114void QwtPlotMarker::setYValue( double y )
115{
116 setValue( d_data->xValue, y );
117}
118
119/*!
120 Draw the marker
121
122 \param painter Painter
123 \param xMap x Scale Map
124 \param yMap y Scale Map
125 \param canvasRect Contents rect of the canvas in painter coordinates
126*/
127void QwtPlotMarker::draw( QPainter *painter,
128 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
129 const QRectF &canvasRect ) const
130{
131 const QPointF pos( xMap.transform( d_data->xValue ),
132 yMap.transform( d_data->yValue ) );
133
134 // draw lines
135
136 drawLines( painter, canvasRect, pos );
137
138 // draw symbol
139 if ( d_data->symbol &&
140 ( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
141 {
142 d_data->symbol->drawSymbol( painter, pos );
143 }
144
145 drawLabel( painter, canvasRect, pos );
146}
147
148/*!
149 Draw the lines marker
150
151 \param painter Painter
152 \param canvasRect Contents rect of the canvas in painter coordinates
153 \param pos Position of the marker, translated into widget coordinates
154
155 \sa drawLabel(), QwtSymbol::drawSymbol()
156*/
157void QwtPlotMarker::drawLines( QPainter *painter,
158 const QRectF &canvasRect, const QPointF &pos ) const
159{
160 if ( d_data->style == NoLine )
161 return;
162
163 const bool doAlign = QwtPainter::roundingAlignment( painter );
164
165 painter->setPen( d_data->pen );
166 if ( d_data->style == QwtPlotMarker::HLine ||
167 d_data->style == QwtPlotMarker::Cross )
168 {
169 double y = pos.y();
170 if ( doAlign )
171 y = qRound( y );
172
173 QwtPainter::drawLine( painter, canvasRect.left(),
174 y, canvasRect.right() - 1.0, y );
175 }
176 if ( d_data->style == QwtPlotMarker::VLine ||
177 d_data->style == QwtPlotMarker::Cross )
178 {
179 double x = pos.x();
180 if ( doAlign )
181 x = qRound( x );
182
183 QwtPainter::drawLine( painter, x,
184 canvasRect.top(), x, canvasRect.bottom() - 1.0 );
185 }
186}
187
188/*!
189 Align and draw the text label of the marker
190
191 \param painter Painter
192 \param canvasRect Contents rect of the canvas in painter coordinates
193 \param pos Position of the marker, translated into widget coordinates
194
195 \sa drawLabel(), QwtSymbol::drawSymbol()
196*/
197void QwtPlotMarker::drawLabel( QPainter *painter,
198 const QRectF &canvasRect, const QPointF &pos ) const
199{
200 if ( d_data->label.isEmpty() )
201 return;
202
203 Qt::Alignment align = d_data->labelAlignment;
204 QPointF alignPos = pos;
205
206 QSizeF symbolOff( 0, 0 );
207
208 switch ( d_data->style )
209 {
210 case QwtPlotMarker::VLine:
211 {
212 // In VLine-style the y-position is pointless and
213 // the alignment flags are relative to the canvas
214
215 if ( d_data->labelAlignment & Qt::AlignTop )
216 {
217 alignPos.setY( canvasRect.top() );
218 align &= ~Qt::AlignTop;
219 align |= Qt::AlignBottom;
220 }
221 else if ( d_data->labelAlignment & Qt::AlignBottom )
222 {
223 // In HLine-style the x-position is pointless and
224 // the alignment flags are relative to the canvas
225
226 alignPos.setY( canvasRect.bottom() - 1 );
227 align &= ~Qt::AlignBottom;
228 align |= Qt::AlignTop;
229 }
230 else
231 {
232 alignPos.setY( canvasRect.center().y() );
233 }
234 break;
235 }
236 case QwtPlotMarker::HLine:
237 {
238 if ( d_data->labelAlignment & Qt::AlignLeft )
239 {
240 alignPos.setX( canvasRect.left() );
241 align &= ~Qt::AlignLeft;
242 align |= Qt::AlignRight;
243 }
244 else if ( d_data->labelAlignment & Qt::AlignRight )
245 {
246 alignPos.setX( canvasRect.right() - 1 );
247 align &= ~Qt::AlignRight;
248 align |= Qt::AlignLeft;
249 }
250 else
251 {
252 alignPos.setX( canvasRect.center().x() );
253 }
254 break;
255 }
256 default:
257 {
258 if ( d_data->symbol &&
259 ( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
260 {
261 symbolOff = d_data->symbol->size() + QSizeF( 1, 1 );
262 symbolOff /= 2;
263 }
264 }
265 }
266
267 qreal pw2 = d_data->pen.widthF() / 2.0;
268 if ( pw2 == 0.0 )
269 pw2 = 0.5;
270
271 const int spacing = d_data->spacing;
272
273 const qreal xOff = qMax( pw2, symbolOff.width() );
274 const qreal yOff = qMax( pw2, symbolOff.height() );
275
276 const QSizeF textSize = d_data->label.textSize( painter->font() );
277
278 if ( align & Qt::AlignLeft )
279 {
280 alignPos.rx() -= xOff + spacing;
281 if ( d_data->labelOrientation == Qt::Vertical )
282 alignPos.rx() -= textSize.height();
283 else
284 alignPos.rx() -= textSize.width();
285 }
286 else if ( align & Qt::AlignRight )
287 {
288 alignPos.rx() += xOff + spacing;
289 }
290 else
291 {
292 if ( d_data->labelOrientation == Qt::Vertical )
293 alignPos.rx() -= textSize.height() / 2;
294 else
295 alignPos.rx() -= textSize.width() / 2;
296 }
297
298 if ( align & Qt::AlignTop )
299 {
300 alignPos.ry() -= yOff + spacing;
301 if ( d_data->labelOrientation != Qt::Vertical )
302 alignPos.ry() -= textSize.height();
303 }
304 else if ( align & Qt::AlignBottom )
305 {
306 alignPos.ry() += yOff + spacing;
307 if ( d_data->labelOrientation == Qt::Vertical )
308 alignPos.ry() += textSize.width();
309 }
310 else
311 {
312 if ( d_data->labelOrientation == Qt::Vertical )
313 alignPos.ry() += textSize.width() / 2;
314 else
315 alignPos.ry() -= textSize.height() / 2;
316 }
317
318 painter->translate( alignPos.x(), alignPos.y() );
319 if ( d_data->labelOrientation == Qt::Vertical )
320 painter->rotate( -90.0 );
321
322 const QRectF textRect( 0, 0, textSize.width(), textSize.height() );
323 d_data->label.draw( painter, textRect );
324}
325
326/*!
327 \brief Set the line style
328 \param style Line style.
329 \sa lineStyle()
330*/
331void QwtPlotMarker::setLineStyle( LineStyle style )
332{
333 if ( style != d_data->style )
334 {
335 d_data->style = style;
336 itemChanged();
337 }
338}
339
340/*!
341 \return the line style
342 \sa setLineStyle()
343*/
344QwtPlotMarker::LineStyle QwtPlotMarker::lineStyle() const
345{
346 return d_data->style;
347}
348
349/*!
350 \brief Assign a symbol
351 \param symbol New symbol
352 \sa symbol()
353*/
354void QwtPlotMarker::setSymbol( const QwtSymbol *symbol )
355{
356 if ( symbol != d_data->symbol )
357 {
358 delete d_data->symbol;
359 d_data->symbol = symbol;
360 itemChanged();
361 }
362}
363
364/*!
365 \return the symbol
366 \sa setSymbol(), QwtSymbol
367*/
368const QwtSymbol *QwtPlotMarker::symbol() const
369{
370 return d_data->symbol;
371}
372
373/*!
374 \brief Set the label
375 \param label label text
376 \sa label()
377*/
378void QwtPlotMarker::setLabel( const QwtText& label )
379{
380 if ( label != d_data->label )
381 {
382 d_data->label = label;
383 itemChanged();
384 }
385}
386
387/*!
388 \return the label
389 \sa setLabel()
390*/
391QwtText QwtPlotMarker::label() const
392{
393 return d_data->label;
394}
395
396/*!
397 \brief Set the alignment of the label
398
399 In case of QwtPlotMarker::HLine the alignment is relative to the
400 y position of the marker, but the horizontal flags correspond to the
401 canvas rectangle. In case of QwtPlotMarker::VLine the alignment is
402 relative to the x position of the marker, but the vertical flags
403 correspond to the canvas rectangle.
404
405 In all other styles the alignment is relative to the marker's position.
406
407 \param align Alignment.
408 \sa labelAlignment(), labelOrientation()
409*/
410void QwtPlotMarker::setLabelAlignment( Qt::Alignment align )
411{
412 if ( align != d_data->labelAlignment )
413 {
414 d_data->labelAlignment = align;
415 itemChanged();
416 }
417}
418
419/*!
420 \return the label alignment
421 \sa setLabelAlignment(), setLabelOrientation()
422*/
423Qt::Alignment QwtPlotMarker::labelAlignment() const
424{
425 return d_data->labelAlignment;
426}
427
428/*!
429 \brief Set the orientation of the label
430
431 When orientation is Qt::Vertical the label is rotated by 90.0 degrees
432 ( from bottom to top ).
433
434 \param orientation Orientation of the label
435
436 \sa labelOrientation(), setLabelAlignment()
437*/
438void QwtPlotMarker::setLabelOrientation( Qt::Orientation orientation )
439{
440 if ( orientation != d_data->labelOrientation )
441 {
442 d_data->labelOrientation = orientation;
443 itemChanged();
444 }
445}
446
447/*!
448 \return the label orientation
449 \sa setLabelOrientation(), labelAlignment()
450*/
451Qt::Orientation QwtPlotMarker::labelOrientation() const
452{
453 return d_data->labelOrientation;
454}
455
456/*!
457 \brief Set the spacing
458
459 When the label is not centered on the marker position, the spacing
460 is the distance between the position and the label.
461
462 \param spacing Spacing
463 \sa spacing(), setLabelAlignment()
464*/
465void QwtPlotMarker::setSpacing( int spacing )
466{
467 if ( spacing < 0 )
468 spacing = 0;
469
470 if ( spacing == d_data->spacing )
471 return;
472
473 d_data->spacing = spacing;
474 itemChanged();
475}
476
477/*!
478 \return the spacing
479 \sa setSpacing()
480*/
481int QwtPlotMarker::spacing() const
482{
483 return d_data->spacing;
484}
485
486/*!
487 Specify a pen for the line.
488
489 \param pen New pen
490 \sa linePen()
491*/
492void QwtPlotMarker::setLinePen( const QPen &pen )
493{
494 if ( pen != d_data->pen )
495 {
496 d_data->pen = pen;
497 itemChanged();
498 }
499}
500
501/*!
502 \return the line pen
503 \sa setLinePen()
504*/
505const QPen &QwtPlotMarker::linePen() const
506{
507 return d_data->pen;
508}
509
510QRectF QwtPlotMarker::boundingRect() const
511{
512 return QRectF( d_data->xValue, d_data->yValue, 0.0, 0.0 );
513}
514
515/*!
516 \brief Update the widget that represents the item on the legend
517
518 \param legend Legend
519 \sa drawLegendIdentifier(), legendItem(), itemChanged(), QwtLegend()
520
521 \note In the default setting QwtPlotItem::Legend is disabled
522*/
523void QwtPlotMarker::updateLegend( QwtLegend *legend ) const
524{
525 if ( legend && testItemAttribute( QwtPlotItem::Legend )
526 && d_data->symbol && d_data->symbol->style() != QwtSymbol::NoSymbol )
527 {
528 QWidget *lgdItem = legend->find( this );
529 if ( lgdItem == NULL )
530 {
531 lgdItem = legendItem();
532 if ( lgdItem )
533 legend->insert( this, lgdItem );
534 }
535
536 QwtLegendItem *l = qobject_cast<QwtLegendItem *>( lgdItem );
537 if ( l )
538 l->setIdentifierSize( d_data->symbol->boundingSize() );
539 }
540
541 QwtPlotItem::updateLegend( legend );
542}
543
544/*!
545 \brief Draw the identifier representing the marker on the legend
546
547 \param painter Painter
548 \param rect Bounding rectangle for the identifier
549
550 \sa updateLegend(), QwtPlotItem::Legend
551*/
552void QwtPlotMarker::drawLegendIdentifier(
553 QPainter *painter, const QRectF &rect ) const
554{
555 if ( rect.isEmpty() )
556 return;
557
558 painter->save();
559 painter->setClipRect( rect, Qt::IntersectClip );
560
561 if ( d_data->style != QwtPlotMarker::NoLine )
562 {
563 painter->setPen( d_data->pen );
564
565 if ( d_data->style == QwtPlotMarker::HLine ||
566 d_data->style == QwtPlotMarker::Cross )
567 {
568 QwtPainter::drawLine( painter, rect.left(), rect.center().y(),
569 rect.right(), rect.center().y() );
570 }
571
572 if ( d_data->style == QwtPlotMarker::VLine ||
573 d_data->style == QwtPlotMarker::Cross )
574 {
575 QwtPainter::drawLine( painter, rect.center().x(), rect.top(),
576 rect.center().x(), rect.bottom() );
577 }
578 }
579
580 if ( d_data->symbol && d_data->symbol->style() != QwtSymbol::NoSymbol )
581 {
582 QSize symbolSize = d_data->symbol->boundingSize();
583 symbolSize -= QSize( 2, 2 );
584
585 // scale the symbol size down if it doesn't fit into rect.
586
587 double xRatio = 1.0;
588 if ( rect.width() < symbolSize.width() )
589 xRatio = rect.width() / symbolSize.width();
590 double yRatio = 1.0;
591 if ( rect.height() < symbolSize.height() )
592 yRatio = rect.height() / symbolSize.height();
593
594 const double ratio = qMin( xRatio, yRatio );
595
596 painter->scale( ratio, ratio );
597 d_data->symbol->drawSymbol( painter, rect.center() / ratio );
598 }
599
600 painter->restore();
601}
602
Note: See TracBrowser for help on using the repository browser.