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_grid.h"
11 #include "qwt_painter.h"
12 #include "qwt_text.h"
13 #include "qwt_scale_map.h"
14 #include "qwt_scale_div.h"
15 #include "qwt_math.h"
16 #include <qpainter.h>
17 #include <qpen.h>
18
19 class QwtPlotGrid::PrivateData
20 {
21 public:
PrivateData()22 PrivateData():
23 xEnabled( true ),
24 yEnabled( true ),
25 xMinEnabled( false ),
26 yMinEnabled( false )
27 {
28 }
29
30 bool xEnabled;
31 bool yEnabled;
32 bool xMinEnabled;
33 bool yMinEnabled;
34
35 QwtScaleDiv xScaleDiv;
36 QwtScaleDiv yScaleDiv;
37
38 QPen majorPen;
39 QPen minorPen;
40 };
41
42 //! Enables major grid, disables minor grid
QwtPlotGrid()43 QwtPlotGrid::QwtPlotGrid():
44 QwtPlotItem( QwtText( "Grid" ) )
45 {
46 d_data = new PrivateData;
47
48 setItemInterest( QwtPlotItem::ScaleInterest, true );
49 setZ( 10.0 );
50 }
51
52 //! Destructor
~QwtPlotGrid()53 QwtPlotGrid::~QwtPlotGrid()
54 {
55 delete d_data;
56 }
57
58 //! \return QwtPlotItem::Rtti_PlotGrid
rtti() const59 int QwtPlotGrid::rtti() const
60 {
61 return QwtPlotItem::Rtti_PlotGrid;
62 }
63
64 /*!
65 \brief Enable or disable vertical grid lines
66 \param on Enable (true) or disable
67
68 \sa Minor grid lines can be enabled or disabled with
69 enableXMin()
70 */
enableX(bool on)71 void QwtPlotGrid::enableX( bool on )
72 {
73 if ( d_data->xEnabled != on )
74 {
75 d_data->xEnabled = on;
76
77 legendChanged();
78 itemChanged();
79 }
80 }
81
82 /*!
83 \brief Enable or disable horizontal grid lines
84 \param on Enable (true) or disable
85 \sa Minor grid lines can be enabled or disabled with enableYMin()
86 */
enableY(bool on)87 void QwtPlotGrid::enableY( bool on )
88 {
89 if ( d_data->yEnabled != on )
90 {
91 d_data->yEnabled = on;
92
93 legendChanged();
94 itemChanged();
95 }
96 }
97
98 /*!
99 \brief Enable or disable minor vertical grid lines.
100 \param on Enable (true) or disable
101 \sa enableX()
102 */
enableXMin(bool on)103 void QwtPlotGrid::enableXMin( bool on )
104 {
105 if ( d_data->xMinEnabled != on )
106 {
107 d_data->xMinEnabled = on;
108
109 legendChanged();
110 itemChanged();
111 }
112 }
113
114 /*!
115 \brief Enable or disable minor horizontal grid lines
116 \param on Enable (true) or disable
117 \sa enableY()
118 */
enableYMin(bool on)119 void QwtPlotGrid::enableYMin( bool on )
120 {
121 if ( d_data->yMinEnabled != on )
122 {
123 d_data->yMinEnabled = on;
124
125 legendChanged();
126 itemChanged();
127 }
128 }
129
130 /*!
131 Assign an x axis scale division
132
133 \param scaleDiv Scale division
134 */
setXDiv(const QwtScaleDiv & scaleDiv)135 void QwtPlotGrid::setXDiv( const QwtScaleDiv &scaleDiv )
136 {
137 if ( d_data->xScaleDiv != scaleDiv )
138 {
139 d_data->xScaleDiv = scaleDiv;
140 itemChanged();
141 }
142 }
143
144 /*!
145 Assign a y axis division
146
147 \param scaleDiv Scale division
148 */
setYDiv(const QwtScaleDiv & scaleDiv)149 void QwtPlotGrid::setYDiv( const QwtScaleDiv &scaleDiv )
150 {
151 if ( d_data->yScaleDiv != scaleDiv )
152 {
153 d_data->yScaleDiv = scaleDiv;
154 itemChanged();
155 }
156 }
157
158 /*!
159 Build and assign a pen for both major and minor grid lines
160
161 In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it
162 non cosmetic ( see QPen::isCosmetic() ). This method has been introduced
163 to hide this incompatibility.
164
165 \param color Pen color
166 \param width Pen width
167 \param style Pen style
168
169 \sa pen(), brush()
170 */
setPen(const QColor & color,qreal width,Qt::PenStyle style)171 void QwtPlotGrid::setPen( const QColor &color, qreal width, Qt::PenStyle style )
172 {
173 setPen( QPen( color, width, style ) );
174 }
175
176 /*!
177 Assign a pen for both major and minor grid lines
178
179 \param pen Pen
180 \sa setMajorPen(), setMinorPen()
181 */
setPen(const QPen & pen)182 void QwtPlotGrid::setPen( const QPen &pen )
183 {
184 if ( d_data->majorPen != pen || d_data->minorPen != pen )
185 {
186 d_data->majorPen = pen;
187 d_data->minorPen = pen;
188
189 legendChanged();
190 itemChanged();
191 }
192 }
193
194 /*!
195 Build and assign a pen for both major grid lines
196
197 In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it
198 non cosmetic ( see QPen::isCosmetic() ). This method has been introduced
199 to hide this incompatibility.
200
201 \param color Pen color
202 \param width Pen width
203 \param style Pen style
204
205 \sa pen(), brush()
206 */
setMajorPen(const QColor & color,qreal width,Qt::PenStyle style)207 void QwtPlotGrid::setMajorPen( const QColor &color, qreal width, Qt::PenStyle style )
208 {
209 setMajorPen( QPen( color, width, style ) );
210 }
211
212 /*!
213 Assign a pen for the major grid lines
214
215 \param pen Pen
216 \sa majorPen(), setMinorPen(), setPen()
217 */
setMajorPen(const QPen & pen)218 void QwtPlotGrid::setMajorPen( const QPen &pen )
219 {
220 if ( d_data->majorPen != pen )
221 {
222 d_data->majorPen = pen;
223
224 legendChanged();
225 itemChanged();
226 }
227 }
228
229 /*!
230 Build and assign a pen for the minor grid lines
231
232 In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it
233 non cosmetic ( see QPen::isCosmetic() ). This method has been introduced
234 to hide this incompatibility.
235
236 \param color Pen color
237 \param width Pen width
238 \param style Pen style
239
240 \sa pen(), brush()
241 */
setMinorPen(const QColor & color,qreal width,Qt::PenStyle style)242 void QwtPlotGrid::setMinorPen( const QColor &color, qreal width, Qt::PenStyle style )
243 {
244 setMinorPen( QPen( color, width, style ) );
245 }
246
247 /*!
248 Assign a pen for the minor grid lines
249
250 \param pen Pen
251 \sa minorPen(), setMajorPen(), setPen()
252 */
setMinorPen(const QPen & pen)253 void QwtPlotGrid::setMinorPen( const QPen &pen )
254 {
255 if ( d_data->minorPen != pen )
256 {
257 d_data->minorPen = pen;
258
259 legendChanged();
260 itemChanged();
261 }
262 }
263
264 /*!
265 \brief Draw the grid
266
267 The grid is drawn into the bounding rectangle such that
268 grid lines begin and end at the rectangle's borders. The X and Y
269 maps are used to map the scale divisions into the drawing region
270 screen.
271
272 \param painter Painter
273 \param xMap X axis map
274 \param yMap Y axis
275 \param canvasRect Contents rectangle of the plot canvas
276 */
draw(QPainter * painter,const QwtScaleMap & xMap,const QwtScaleMap & yMap,const QRectF & canvasRect) const277 void QwtPlotGrid::draw( QPainter *painter,
278 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
279 const QRectF &canvasRect ) const
280 {
281 // draw minor grid lines
282 QPen minorPen = d_data->minorPen;
283 minorPen.setCapStyle( Qt::FlatCap );
284
285 painter->setPen( minorPen );
286
287 if ( d_data->xEnabled && d_data->xMinEnabled )
288 {
289 drawLines( painter, canvasRect, Qt::Vertical, xMap,
290 d_data->xScaleDiv.ticks( QwtScaleDiv::MinorTick ) );
291 drawLines( painter, canvasRect, Qt::Vertical, xMap,
292 d_data->xScaleDiv.ticks( QwtScaleDiv::MediumTick ) );
293 }
294
295 if ( d_data->yEnabled && d_data->yMinEnabled )
296 {
297 drawLines( painter, canvasRect, Qt::Horizontal, yMap,
298 d_data->yScaleDiv.ticks( QwtScaleDiv::MinorTick ) );
299 drawLines( painter, canvasRect, Qt::Horizontal, yMap,
300 d_data->yScaleDiv.ticks( QwtScaleDiv::MediumTick ) );
301 }
302
303 // draw major grid lines
304 QPen majorPen = d_data->majorPen;
305 majorPen.setCapStyle( Qt::FlatCap );
306
307 painter->setPen( majorPen );
308
309 if ( d_data->xEnabled )
310 {
311 drawLines( painter, canvasRect, Qt::Vertical, xMap,
312 d_data->xScaleDiv.ticks( QwtScaleDiv::MajorTick ) );
313 }
314
315 if ( d_data->yEnabled )
316 {
317 drawLines( painter, canvasRect, Qt::Horizontal, yMap,
318 d_data->yScaleDiv.ticks( QwtScaleDiv::MajorTick ) );
319 }
320 }
321
drawLines(QPainter * painter,const QRectF & canvasRect,Qt::Orientation orientation,const QwtScaleMap & scaleMap,const QList<double> & values) const322 void QwtPlotGrid::drawLines( QPainter *painter, const QRectF &canvasRect,
323 Qt::Orientation orientation, const QwtScaleMap &scaleMap,
324 const QList<double> &values ) const
325 {
326 const double x1 = canvasRect.left();
327 const double x2 = canvasRect.right() - 1.0;
328 const double y1 = canvasRect.top();
329 const double y2 = canvasRect.bottom() - 1.0;
330
331 const bool doAlign = QwtPainter::roundingAlignment( painter );
332
333 for ( int i = 0; i < values.count(); i++ )
334 {
335 double value = scaleMap.transform( values[i] );
336 if ( doAlign )
337 value = qRound( value );
338
339 if ( orientation == Qt::Horizontal )
340 {
341 if ( qwtFuzzyGreaterOrEqual( value, y1 ) &&
342 qwtFuzzyLessOrEqual( value, y2 ) )
343 {
344 QwtPainter::drawLine( painter, x1, value, x2, value );
345 }
346 }
347 else
348 {
349 if ( qwtFuzzyGreaterOrEqual( value, x1 ) &&
350 qwtFuzzyLessOrEqual( value, x2 ) )
351 {
352 QwtPainter::drawLine( painter, value, y1, value, y2 );
353 }
354 }
355 }
356 }
357
358 /*!
359 \return the pen for the major grid lines
360 \sa setMajorPen(), setMinorPen(), setPen()
361 */
majorPen() const362 const QPen &QwtPlotGrid::majorPen() const
363 {
364 return d_data->majorPen;
365 }
366
367 /*!
368 \return the pen for the minor grid lines
369 \sa setMinorPen(), setMajorPen(), setPen()
370 */
minorPen() const371 const QPen &QwtPlotGrid::minorPen() const
372 {
373 return d_data->minorPen;
374 }
375
376 /*!
377 \return true if vertical grid lines are enabled
378 \sa enableX()
379 */
xEnabled() const380 bool QwtPlotGrid::xEnabled() const
381 {
382 return d_data->xEnabled;
383 }
384
385 /*!
386 \return true if minor vertical grid lines are enabled
387 \sa enableXMin()
388 */
xMinEnabled() const389 bool QwtPlotGrid::xMinEnabled() const
390 {
391 return d_data->xMinEnabled;
392 }
393
394 /*!
395 \return true if horizontal grid lines are enabled
396 \sa enableY()
397 */
yEnabled() const398 bool QwtPlotGrid::yEnabled() const
399 {
400 return d_data->yEnabled;
401 }
402
403 /*!
404 \return true if minor horizontal grid lines are enabled
405 \sa enableYMin()
406 */
yMinEnabled() const407 bool QwtPlotGrid::yMinEnabled() const
408 {
409 return d_data->yMinEnabled;
410 }
411
412
413 /*! \return the scale division of the x axis */
xScaleDiv() const414 const QwtScaleDiv &QwtPlotGrid::xScaleDiv() const
415 {
416 return d_data->xScaleDiv;
417 }
418
419 /*! \return the scale division of the y axis */
yScaleDiv() const420 const QwtScaleDiv &QwtPlotGrid::yScaleDiv() const
421 {
422 return d_data->yScaleDiv;
423 }
424
425 /*!
426 Update the grid to changes of the axes scale division
427
428 \param xScaleDiv Scale division of the x-axis
429 \param yScaleDiv Scale division of the y-axis
430
431 \sa QwtPlot::updateAxes()
432 */
updateScaleDiv(const QwtScaleDiv & xScaleDiv,const QwtScaleDiv & yScaleDiv)433 void QwtPlotGrid::updateScaleDiv( const QwtScaleDiv& xScaleDiv,
434 const QwtScaleDiv& yScaleDiv )
435 {
436 setXDiv( xScaleDiv );
437 setYDiv( yScaleDiv );
438 }
439