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 <qpainter.h>
11 #include <qpen.h>
12 #include "qwt_painter.h"
13 #include "qwt_text.h"
14 #include "qwt_scale_map.h"
15 #include "qwt_scale_div.h"
16 #include "qwt_plot_grid.h"
17 
18 class QwtPlotGrid::PrivateData
19 {
20 public:
PrivateData()21     PrivateData():
22         xEnabled(true),
23         yEnabled(true),
24         xMinEnabled(false),
25         yMinEnabled(false)
26     {
27     }
28 
29     bool xEnabled;
30     bool yEnabled;
31     bool xMinEnabled;
32     bool yMinEnabled;
33 
34     QwtScaleDiv xScaleDiv;
35     QwtScaleDiv yScaleDiv;
36 
37     QPen majPen;
38     QPen minPen;
39 };
40 
41 //! Enables major grid, disables minor grid
QwtPlotGrid()42 QwtPlotGrid::QwtPlotGrid():
43     QwtPlotItem(QwtText("Grid"))
44 {
45     d_data = new PrivateData;
46     setZ(10.0);
47 }
48 
49 //! Destructor
~QwtPlotGrid()50 QwtPlotGrid::~QwtPlotGrid()
51 {
52     delete d_data;
53 }
54 
55 //! \return QwtPlotItem::Rtti_PlotGrid
rtti() const56 int QwtPlotGrid::rtti() const
57 {
58     return QwtPlotItem::Rtti_PlotGrid;
59 }
60 
61 /*!
62   \brief Enable or disable vertical gridlines
63   \param tf Enable (true) or disable
64 
65   \sa Minor gridlines can be enabled or disabled with
66       enableXMin()
67 */
enableX(bool tf)68 void QwtPlotGrid::enableX(bool tf)
69 {
70     if ( d_data->xEnabled != tf )
71     {
72         d_data->xEnabled = tf;
73         itemChanged();
74     }
75 }
76 
77 /*!
78   \brief Enable or disable horizontal gridlines
79   \param tf Enable (true) or disable
80   \sa Minor gridlines can be enabled or disabled with enableYMin()
81 */
enableY(bool tf)82 void QwtPlotGrid::enableY(bool tf)
83 {
84     if ( d_data->yEnabled != tf )
85     {
86         d_data->yEnabled = tf;
87         itemChanged();
88     }
89 }
90 
91 /*!
92   \brief Enable or disable  minor vertical gridlines.
93   \param tf Enable (true) or disable
94   \sa enableX()
95 */
enableXMin(bool tf)96 void QwtPlotGrid::enableXMin(bool tf)
97 {
98     if ( d_data->xMinEnabled != tf )
99     {
100         d_data->xMinEnabled = tf;
101         itemChanged();
102     }
103 }
104 
105 /*!
106   \brief Enable or disable minor horizontal gridlines
107   \param tf Enable (true) or disable
108   \sa enableY()
109 */
enableYMin(bool tf)110 void QwtPlotGrid::enableYMin(bool tf)
111 {
112     if ( d_data->yMinEnabled != tf )
113     {
114         d_data->yMinEnabled = tf;
115         itemChanged();
116     }
117 }
118 
119 /*!
120   Assign an x axis scale division
121 
122   \param scaleDiv Scale division
123 */
setXDiv(const QwtScaleDiv & scaleDiv)124 void QwtPlotGrid::setXDiv(const QwtScaleDiv &scaleDiv)
125 {
126     if ( d_data->xScaleDiv != scaleDiv )
127     {
128         d_data->xScaleDiv = scaleDiv;
129         itemChanged();
130     }
131 }
132 
133 /*!
134   Assign a y axis division
135 
136   \param scaleDiv Scale division
137 */
setYDiv(const QwtScaleDiv & scaleDiv)138 void QwtPlotGrid::setYDiv(const QwtScaleDiv &scaleDiv)
139 {
140     if ( d_data->yScaleDiv != scaleDiv )
141     {
142         d_data->yScaleDiv = scaleDiv;
143         itemChanged();
144     }
145 }
146 
147 /*!
148   Assign a pen for both major and minor gridlines
149 
150   The width of non cosmetic pens is scaled according to the resolution
151   of the paint device.
152 
153   \param pen Pen
154   \sa setMajPen(), setMinPen(), QwtPainter::scaledPen()
155 */
setPen(const QPen & pen)156 void QwtPlotGrid::setPen(const QPen &pen)
157 {
158     if ( d_data->majPen != pen || d_data->minPen != pen )
159     {
160         d_data->majPen = pen;
161         d_data->minPen = pen;
162         itemChanged();
163     }
164 }
165 
166 /*!
167   Assign a pen for the major gridlines
168 
169   The width of non cosmetic pens is scaled according to the resolution
170   of the paint device.
171 
172   \param pen Pen
173   \sa majPen(), setMinPen(), setPen(), QwtPainter::scaledPen()
174 */
setMajPen(const QPen & pen)175 void QwtPlotGrid::setMajPen(const QPen &pen)
176 {
177     if ( d_data->majPen != pen )
178     {
179         d_data->majPen = pen;
180         itemChanged();
181     }
182 }
183 
184 /*!
185   Assign a pen for the minor gridlines
186 
187   The width of non cosmetic pens is scaled according to the resolution
188   of the paint device.
189 
190   \param pen Pen
191   \sa minPen(), setMajPen(), setPen(), QwtPainter::scaledPen()
192 */
setMinPen(const QPen & pen)193 void QwtPlotGrid::setMinPen(const QPen &pen)
194 {
195     if ( d_data->minPen != pen )
196     {
197         d_data->minPen = pen;
198         itemChanged();
199     }
200 }
201 
202 /*!
203   \brief Draw the grid
204 
205   The grid is drawn into the bounding rectangle such that
206   gridlines begin and end at the rectangle's borders. The X and Y
207   maps are used to map the scale divisions into the drawing region
208   screen.
209   \param painter  Painter
210   \param xMap X axis map
211   \param yMap Y axis
212   \param canvasRect Contents rect of the plot canvas
213 */
draw(QPainter * painter,const QwtScaleMap & xMap,const QwtScaleMap & yMap,const QRect & canvasRect) const214 void QwtPlotGrid::draw(QPainter *painter,
215     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
216     const QRect &canvasRect) const
217 {
218     //  draw minor gridlines
219     painter->setPen(QwtPainter::scaledPen(d_data->minPen));
220 
221     if (d_data->xEnabled && d_data->xMinEnabled)
222     {
223         drawLines(painter, canvasRect, Qt::Vertical, xMap,
224             d_data->xScaleDiv.ticks(QwtScaleDiv::MinorTick));
225         drawLines(painter, canvasRect, Qt::Vertical, xMap,
226             d_data->xScaleDiv.ticks(QwtScaleDiv::MediumTick));
227     }
228 
229     if (d_data->yEnabled && d_data->yMinEnabled)
230     {
231         drawLines(painter, canvasRect, Qt::Horizontal, yMap,
232             d_data->yScaleDiv.ticks(QwtScaleDiv::MinorTick));
233         drawLines(painter, canvasRect, Qt::Horizontal, yMap,
234             d_data->yScaleDiv.ticks(QwtScaleDiv::MediumTick));
235     }
236 
237     //  draw major gridlines
238     painter->setPen(QwtPainter::scaledPen(d_data->majPen));
239 
240     if (d_data->xEnabled)
241     {
242         drawLines(painter, canvasRect, Qt::Vertical, xMap,
243             d_data->xScaleDiv.ticks(QwtScaleDiv::MajorTick));
244     }
245 
246     if (d_data->yEnabled)
247     {
248         drawLines(painter, canvasRect, Qt::Horizontal, yMap,
249             d_data->yScaleDiv.ticks(QwtScaleDiv::MajorTick));
250     }
251 }
252 
drawLines(QPainter * painter,const QRect & canvasRect,Qt::Orientation orientation,const QwtScaleMap & scaleMap,const QwtValueList & values) const253 void QwtPlotGrid::drawLines(QPainter *painter, const QRect &canvasRect,
254     Qt::Orientation orientation, const QwtScaleMap &scaleMap,
255     const QwtValueList &values) const
256 {
257     const int x1 = canvasRect.left();
258     const int x2 = canvasRect.right();
259     const int y1 = canvasRect.top();
260     const int y2 = canvasRect.bottom();
261 
262     for (uint i = 0; i < (uint)values.count(); i++)
263     {
264         const int value = scaleMap.transform(values[i]);
265         if ( orientation == Qt::Horizontal )
266         {
267             if ((value >= y1) && (value <= y2))
268                 QwtPainter::drawLine(painter, x1, value, x2, value);
269         }
270         else
271         {
272             if ((value >= x1) && (value <= x2))
273                 QwtPainter::drawLine(painter, value, y1, value, y2);
274         }
275     }
276 }
277 
278 /*!
279   \return the pen for the major gridlines
280   \sa setMajPen(), setMinPen(), setPen()
281 */
majPen() const282 const QPen &QwtPlotGrid::majPen() const
283 {
284     return d_data->majPen;
285 }
286 
287 /*!
288   \return the pen for the minor gridlines
289   \sa setMinPen(), setMajPen(), setPen()
290 */
minPen() const291 const QPen &QwtPlotGrid::minPen() const
292 {
293     return d_data->minPen;
294 }
295 
296 /*!
297   \return true if vertical gridlines are enabled
298   \sa enableX()
299 */
xEnabled() const300 bool QwtPlotGrid::xEnabled() const
301 {
302     return d_data->xEnabled;
303 }
304 
305 /*!
306   \return true if minor vertical gridlines are enabled
307   \sa enableXMin()
308 */
xMinEnabled() const309 bool QwtPlotGrid::xMinEnabled() const
310 {
311     return d_data->xMinEnabled;
312 }
313 
314 /*!
315   \return true if horizontal gridlines are enabled
316   \sa enableY()
317 */
yEnabled() const318 bool QwtPlotGrid::yEnabled() const
319 {
320     return d_data->yEnabled;
321 }
322 
323 /*!
324   \return true if minor horizontal gridlines are enabled
325   \sa enableYMin()
326 */
yMinEnabled() const327 bool QwtPlotGrid::yMinEnabled() const
328 {
329     return d_data->yMinEnabled;
330 }
331 
332 
333 /*! \return the scale division of the x axis */
xScaleDiv() const334 const QwtScaleDiv &QwtPlotGrid::xScaleDiv() const
335 {
336     return d_data->xScaleDiv;
337 }
338 
339 /*! \return the scale division of the y axis */
yScaleDiv() const340 const QwtScaleDiv &QwtPlotGrid::yScaleDiv() const
341 {
342     return d_data->yScaleDiv;
343 }
344 
345 /*!
346    Update the grid to changes of the axes scale division
347 
348    \param xScaleDiv Scale division of the x-axis
349    \param yScaleDiv Scale division of the y-axis
350 
351    \sa QwtPlot::updateAxes()
352 */
updateScaleDiv(const QwtScaleDiv & xScaleDiv,const QwtScaleDiv & yScaleDiv)353 void QwtPlotGrid::updateScaleDiv(const QwtScaleDiv& xScaleDiv,
354     const QwtScaleDiv& yScaleDiv)
355 {
356     setXDiv(xScaleDiv);
357     setYDiv(yScaleDiv);
358 }
359