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_glcanvas.h"
11 #include "qwt_plot.h"
12 #include "qwt_painter.h"
13 #include <qevent.h>
14 #include <qpainter.h>
15 #include <qdrawutil.h>
16 #include <qstyle.h>
17 #include <qstyleoption.h>
18
19 #define FIX_GL_TRANSLATION 0
20
qwtBGWidget(QWidget * widget)21 static QWidget *qwtBGWidget( QWidget *widget )
22 {
23 QWidget *w = widget;
24
25 for ( ; w->parentWidget() != NULL; w = w->parentWidget() )
26 {
27 if ( w->autoFillBackground() ||
28 w->testAttribute( Qt::WA_StyledBackground ) )
29 {
30 return w;
31 }
32 }
33
34 return w;
35 }
36
qwtUpdateContentsRect(QwtPlotGLCanvas * canvas)37 static void qwtUpdateContentsRect( QwtPlotGLCanvas *canvas )
38 {
39 const int fw = canvas->frameWidth();
40 canvas->setContentsMargins( fw, fw, fw, fw );
41 }
42
43 class QwtPlotGLCanvas::PrivateData
44 {
45 public:
PrivateData()46 PrivateData():
47 frameStyle( QFrame::Panel | QFrame::Sunken),
48 lineWidth( 2 ),
49 midLineWidth( 0 )
50 {
51 }
52
53 int frameStyle;
54 int lineWidth;
55 int midLineWidth;
56 };
57
58 class QwtPlotGLCanvasFormat: public QGLFormat
59 {
60 public:
QwtPlotGLCanvasFormat()61 QwtPlotGLCanvasFormat():
62 QGLFormat( QGLFormat::defaultFormat() )
63 {
64 setSampleBuffers( true );
65 }
66 };
67
68 /*!
69 \brief Constructor
70
71 \param plot Parent plot widget
72 \sa QwtPlot::setCanvas()
73 */
QwtPlotGLCanvas(QwtPlot * plot)74 QwtPlotGLCanvas::QwtPlotGLCanvas( QwtPlot *plot ):
75 QGLWidget( QwtPlotGLCanvasFormat(), plot )
76 {
77 d_data = new PrivateData;
78
79 #ifndef QT_NO_CURSOR
80 setCursor( Qt::CrossCursor );
81 #endif
82
83 setAutoFillBackground( true );
84 qwtUpdateContentsRect( this );
85 }
86
87 //! Destructor
~QwtPlotGLCanvas()88 QwtPlotGLCanvas::~QwtPlotGLCanvas()
89 {
90 delete d_data;
91 }
92
93 /*!
94 Set the frame style
95
96 \param style The bitwise OR between a shape and a shadow.
97
98 \sa frameStyle(), QFrame::setFrameStyle(),
99 setFrameShadow(), setFrameShape()
100 */
setFrameStyle(int style)101 void QwtPlotGLCanvas::setFrameStyle( int style )
102 {
103 if ( style != d_data->frameStyle )
104 {
105 d_data->frameStyle = style;
106 qwtUpdateContentsRect( this );
107
108 update();
109 }
110 }
111
112 /*!
113 \return The bitwise OR between a frameShape() and a frameShadow()
114 \sa setFrameStyle(), QFrame::frameStyle()
115 */
frameStyle() const116 int QwtPlotGLCanvas::frameStyle() const
117 {
118 return d_data->frameStyle;
119 }
120
121 /*!
122 Set the frame shadow
123
124 \param shadow Frame shadow
125 \sa frameShadow(), setFrameShape(), QFrame::setFrameShadow()
126 */
setFrameShadow(Shadow shadow)127 void QwtPlotGLCanvas::setFrameShadow( Shadow shadow )
128 {
129 setFrameStyle(( d_data->frameStyle & QFrame::Shape_Mask ) | shadow );
130 }
131
132 /*!
133 \return Frame shadow
134 \sa setFrameShadow(), QFrame::setFrameShadow()
135 */
frameShadow() const136 QwtPlotGLCanvas::Shadow QwtPlotGLCanvas::frameShadow() const
137 {
138 return (Shadow) ( d_data->frameStyle & QFrame::Shadow_Mask );
139 }
140
141 /*!
142 Set the frame shape
143
144 \param shape Frame shape
145 \sa frameShape(), setFrameShadow(), QFrame::frameShape()
146 */
setFrameShape(Shape shape)147 void QwtPlotGLCanvas::setFrameShape( Shape shape )
148 {
149 setFrameStyle( ( d_data->frameStyle & QFrame::Shadow_Mask ) | shape );
150 }
151
152 /*!
153 \return Frame shape
154 \sa setFrameShape(), QFrame::frameShape()
155 */
frameShape() const156 QwtPlotGLCanvas::Shape QwtPlotGLCanvas::frameShape() const
157 {
158 return (Shape) ( d_data->frameStyle & QFrame::Shape_Mask );
159 }
160
161 /*!
162 Set the frame line width
163
164 The default line width is 2 pixels.
165
166 \param width Line width of the frame
167 \sa lineWidth(), setMidLineWidth()
168 */
setLineWidth(int width)169 void QwtPlotGLCanvas::setLineWidth( int width )
170 {
171 width = qMax( width, 0 );
172 if ( width != d_data->lineWidth )
173 {
174 d_data->lineWidth = qMax( width, 0 );
175 qwtUpdateContentsRect( this );
176 update();
177 }
178 }
179
180 /*!
181 \return Line width of the frame
182 \sa setLineWidth(), midLineWidth()
183 */
lineWidth() const184 int QwtPlotGLCanvas::lineWidth() const
185 {
186 return d_data->lineWidth;
187 }
188
189 /*!
190 Set the frame mid line width
191
192 The default midline width is 0 pixels.
193
194 \param width Midline width of the frame
195 \sa midLineWidth(), setLineWidth()
196 */
setMidLineWidth(int width)197 void QwtPlotGLCanvas::setMidLineWidth( int width )
198 {
199 width = qMax( width, 0 );
200 if ( width != d_data->midLineWidth )
201 {
202 d_data->midLineWidth = width;
203 qwtUpdateContentsRect( this );
204 update();
205 }
206 }
207
208 /*!
209 \return Midline width of the frame
210 \sa setMidLineWidth(), lineWidth()
211 */
midLineWidth() const212 int QwtPlotGLCanvas::midLineWidth() const
213 {
214 return d_data->midLineWidth;
215 }
216
217 /*!
218 \return Frame width depending on the style, line width and midline width.
219 */
frameWidth() const220 int QwtPlotGLCanvas::frameWidth() const
221 {
222 return ( frameStyle() != NoFrame ) ? d_data->lineWidth : 0;
223 }
224
225 /*!
226 Paint event
227
228 \param event Paint event
229 \sa QwtPlot::drawCanvas()
230 */
paintEvent(QPaintEvent * event)231 void QwtPlotGLCanvas::paintEvent( QPaintEvent *event )
232 {
233 Q_UNUSED( event );
234
235 QPainter painter( this );
236
237 #if FIX_GL_TRANSLATION
238 if ( painter.paintEngine()->type() == QPaintEngine::OpenGL2 )
239 {
240 // work around a translation bug of QPaintEngine::OpenGL2
241 painter.translate( 1, 1 );
242 }
243 #endif
244
245 drawBackground( &painter );
246 drawItems( &painter );
247
248 if ( !testAttribute( Qt::WA_StyledBackground ) )
249 {
250 if ( frameWidth() > 0 )
251 drawBorder( &painter );
252 }
253 }
254 /*!
255 Qt event handler for QEvent::PolishRequest and QEvent::StyleChange
256 \param event Qt Event
257 \return See QGLWidget::event()
258 */
event(QEvent * event)259 bool QwtPlotGLCanvas::event( QEvent *event )
260 {
261 const bool ok = QGLWidget::event( event );
262
263 if ( event->type() == QEvent::PolishRequest ||
264 event->type() == QEvent::StyleChange )
265 {
266 // assuming, that we always have a styled background
267 // when we have a style sheet
268
269 setAttribute( Qt::WA_StyledBackground,
270 testAttribute( Qt::WA_StyleSheet ) );
271 }
272
273 return ok;
274 }
275
276 /*!
277 Draw the plot items
278 \param painter Painter
279
280 \sa QwtPlot::drawCanvas()
281 */
drawItems(QPainter * painter)282 void QwtPlotGLCanvas::drawItems( QPainter *painter )
283 {
284 painter->save();
285
286 painter->setClipRect( contentsRect(), Qt::IntersectClip );
287
288 QwtPlot *plot = qobject_cast< QwtPlot *>( parent() );
289 if ( plot )
290 plot->drawCanvas( painter );
291
292 painter->restore();
293 }
294
295 /*!
296 Draw the background of the canvas
297 \param painter Painter
298 */
drawBackground(QPainter * painter)299 void QwtPlotGLCanvas::drawBackground( QPainter *painter )
300 {
301 painter->save();
302
303 QWidget *w = qwtBGWidget( this );
304
305 const QPoint off = mapTo( w, QPoint() );
306 painter->translate( -off );
307
308 const QRect fillRect = rect().translated( off );
309
310 if ( w->testAttribute( Qt::WA_StyledBackground ) )
311 {
312 painter->setClipRect( fillRect );
313
314 QStyleOption opt;
315 opt.initFrom( w );
316 w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w);
317 }
318 else
319 {
320 painter->fillRect( fillRect,
321 w->palette().brush( w->backgroundRole() ) );
322 }
323
324 painter->restore();
325 }
326
327 /*!
328 Draw the border of the canvas
329 \param painter Painter
330 */
drawBorder(QPainter * painter)331 void QwtPlotGLCanvas::drawBorder( QPainter *painter )
332 {
333 const int fw = frameWidth();
334 if ( fw <= 0 )
335 return;
336
337 if ( frameShadow() == QwtPlotGLCanvas::Plain )
338 {
339 qDrawPlainRect( painter, frameRect(),
340 palette().shadow().color(), lineWidth() );
341 }
342 else
343 {
344 if ( frameShape() == QwtPlotGLCanvas::Box )
345 {
346 qDrawShadeRect( painter, frameRect(), palette(),
347 frameShadow() == Sunken, lineWidth(), midLineWidth() );
348 }
349 else
350 {
351 qDrawShadePanel( painter, frameRect(), palette(),
352 frameShadow() == Sunken, lineWidth() );
353 }
354 }
355 }
356
357 //! Calls repaint()
replot()358 void QwtPlotGLCanvas::replot()
359 {
360 repaint();
361 }
362
363 /*!
364 \return Empty path
365 */
borderPath(const QRect & rect) const366 QPainterPath QwtPlotGLCanvas::borderPath( const QRect &rect ) const
367 {
368 Q_UNUSED( rect );
369 return QPainterPath();
370 }
371
372 //! \return The rectangle where the frame is drawn in.
frameRect() const373 QRect QwtPlotGLCanvas::frameRect() const
374 {
375 const int fw = frameWidth();
376 return contentsRect().adjusted( -fw, -fw, fw, fw );
377 }
378