10#include "qwt_plot_abstract_canvas.h"
12#include "qwt_painter.h"
13#include "qwt_null_paintdevice.h"
17#include <qpainterpath.h>
19#include <qstyleoption.h>
26 explicit QwtStyleSheetRecorder(
const QSize& size )
31 virtual void updateState(
const QPaintEngineState& state ) QWT_OVERRIDE
33 if ( state.state() & QPaintEngine::DirtyPen )
37 if ( state.state() & QPaintEngine::DirtyBrush )
39 m_brush = state.brush();
41 if ( state.state() & QPaintEngine::DirtyBrushOrigin )
43 m_origin = state.brushOrigin();
47 virtual void drawRects(
const QRectF* rects,
int count ) QWT_OVERRIDE
49 for (
int i = 0; i < count; i++ )
50 border.rectList += rects[i];
53 virtual void drawRects(
const QRect* rects,
int count ) QWT_OVERRIDE
55 for (
int i = 0; i < count; i++ )
56 border.rectList += rects[i];
59 virtual void drawPath(
const QPainterPath& path ) QWT_OVERRIDE
61 const QRectF rect( QPointF( 0.0, 0.0 ), m_size );
62 if ( path.controlPointRect().contains( rect.center() ) )
64 setCornerRects( path );
65 alignCornerRects( rect );
67 background.path = path;
68 background.brush = m_brush;
69 background.origin = m_origin;
73 border.pathList += path;
77 void setCornerRects(
const QPainterPath& path )
79 QPointF pos( 0.0, 0.0 );
81 for (
int i = 0; i < path.elementCount(); i++ )
83 QPainterPath::Element el = path.elementAt(i);
86 case QPainterPath::MoveToElement:
87 case QPainterPath::LineToElement:
93 case QPainterPath::CurveToElement:
95 QRectF r( pos, QPointF( el.x, el.y ) );
96 clipRects += r.normalized();
103 case QPainterPath::CurveToDataElement:
105 if ( clipRects.size() > 0 )
107 QRectF r = clipRects.last();
109 qwtMinF( r.left(), el.x ),
110 qwtMinF( r.top(), el.y ),
111 qwtMaxF( r.right(), el.x ),
112 qwtMaxF( r.bottom(), el.y )
114 clipRects.last() = r.normalized();
123 virtual QSize sizeMetrics() const QWT_OVERRIDE
129 void alignCornerRects(
const QRectF& rect )
131 for (
int i = 0; i < clipRects.size(); i++ )
133 QRectF& r = clipRects[i];
134 if ( r.center().x() < rect.center().x() )
135 r.setLeft( rect.left() );
137 r.setRight( rect.right() );
139 if ( r.center().y() < rect.center().y() )
140 r.setTop( rect.top() );
142 r.setBottom( rect.bottom() );
173static void qwtUpdateContentsRect(
int fw, QWidget* canvas )
175 canvas->setContentsMargins( fw, fw, fw, fw );
178static void qwtFillRegion( QPainter* painter,
const QRegion& region )
180#if QT_VERSION >= 0x050800
181 for ( QRegion::const_iterator it = region.cbegin();
182 it != region.cend(); ++it )
184 painter->drawRect( *it );
187 painter->drawRects( region.rects() );
191static void qwtDrawBackground( QPainter* painter, QWidget* canvas )
195 QPainterPath borderClip;
197 ( void )QMetaObject::invokeMethod(
198 canvas,
"borderPath", Qt::DirectConnection,
199 Q_RETURN_ARG( QPainterPath, borderClip ), Q_ARG( QRect, canvas->rect() ) );
201 if ( !borderClip.isEmpty() )
202 painter->setClipPath( borderClip, Qt::IntersectClip );
204 const QBrush& brush = canvas->palette().brush( canvas->backgroundRole() );
206 if ( brush.style() == Qt::TexturePattern )
208 QPixmap pm( canvas->size() );
210 painter->drawPixmap( 0, 0, pm );
212 else if ( brush.gradient() )
214 const bool fillClipRegion =
215 brush.gradient()->coordinateMode() != QGradient::ObjectBoundingMode;
217 painter->setPen( Qt::NoPen );
218 painter->setBrush( brush );
220 if ( fillClipRegion )
221 qwtFillRegion( painter, painter->clipRegion() );
223 painter->drawRect( canvas->rect() );
227 painter->setPen( Qt::NoPen );
228 painter->setBrush( brush );
229 qwtFillRegion( painter, painter->clipRegion() );
235static inline void qwtDrawStyledBackground(
236 QWidget* w, QPainter* painter )
240 w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w);
243static QWidget* qwtBackgroundWidget( QWidget* w )
245 if ( w->parentWidget() == NULL )
248 if ( w->autoFillBackground() )
250 const QBrush brush = w->palette().brush( w->backgroundRole() );
251 if ( brush.color().alpha() > 0 )
255 if ( w->testAttribute( Qt::WA_StyledBackground ) )
257 QImage image( 1, 1, QImage::Format_ARGB32 );
258 image.fill( Qt::transparent );
260 QPainter painter( &image );
261 painter.translate( -w->rect().center() );
262 qwtDrawStyledBackground( w, &painter );
265 if ( qAlpha( image.pixel( 0, 0 ) ) != 0 )
269 return qwtBackgroundWidget( w->parentWidget() );
272static void qwtFillBackground( QPainter* painter,
275 if ( fillRects.isEmpty() )
279 if ( painter->hasClipping() )
280 clipRegion = painter->transform().map( painter->clipRegion() );
282 clipRegion = widget->contentsRect();
287 QWidget* bgWidget = qwtBackgroundWidget( widget->parentWidget() );
289 for (
int i = 0; i < fillRects.size(); i++ )
291 const QRect rect = fillRects[i].toAlignedRect();
292 if ( clipRegion.intersects( rect ) )
294 QPixmap pm( rect.size() );
296 painter->drawPixmap( rect, pm );
301static void qwtFillBackground( QPainter* painter, QWidget* canvas )
305 if ( canvas->testAttribute( Qt::WA_StyledBackground ) )
307 QwtStyleSheetRecorder recorder( canvas->size() );
309 QPainter p( &recorder );
310 qwtDrawStyledBackground( canvas, &p );
313 if ( recorder.background.brush.isOpaque() )
314 rects = recorder.clipRects;
316 rects += canvas->rect();
320 const double borderRadius = canvas->property(
"borderRadius" ).toDouble();
321 if ( borderRadius > 0.0 )
323 QSizeF sz( borderRadius, borderRadius );
325 const QRectF r = canvas->rect();
326 rects += QRectF( r.topLeft(), sz );
327 rects += QRectF( r.topRight() - QPointF( borderRadius, 0 ), sz );
328 rects += QRectF( r.bottomRight() - QPointF( borderRadius, borderRadius ), sz );
329 rects += QRectF( r.bottomLeft() - QPointF( 0, borderRadius ), sz );
333 qwtFillBackground( painter, canvas, rects);
336static inline void qwtRevertPath( QPainterPath& path )
338 if ( path.elementCount() == 4 )
340 QPainterPath::Element el0 = path.elementAt(0);
341 QPainterPath::Element el3 = path.elementAt(3);
343 path.setElementPositionAt( 0, el3.x, el3.y );
344 path.setElementPositionAt( 3, el0.x, el0.y );
348static QPainterPath qwtCombinePathList(
const QRectF& rect,
351 if ( pathList.isEmpty() )
352 return QPainterPath();
354 QPainterPath ordered[8];
356 for (
int i = 0; i < pathList.size(); i++ )
359 QPainterPath subPath = pathList[i];
361 const QRectF br = pathList[i].controlPointRect();
362 if ( br.center().x() < rect.center().x() )
364 if ( br.center().y() < rect.center().y() )
366 if ( qAbs( br.top() - rect.top() ) <
367 qAbs( br.left() - rect.left() ) )
378 if ( qAbs( br.bottom() - rect.bottom() ) <
379 qAbs( br.left() - rect.left() ) )
389 if ( subPath.currentPosition().y() > br.center().y() )
390 qwtRevertPath( subPath );
394 if ( br.center().y() < rect.center().y() )
396 if ( qAbs( br.top() - rect.top() ) <
397 qAbs( br.right() - rect.right() ) )
408 if ( qAbs( br.bottom() - rect.bottom() ) <
409 qAbs( br.right() - rect.right() ) )
418 if ( subPath.currentPosition().y() < br.center().y() )
419 qwtRevertPath( subPath );
421 ordered[index] = subPath;
424 for (
int i = 0; i < 4; i++ )
426 if ( ordered[ 2 * i].isEmpty() != ordered[2 * i + 1].isEmpty() )
429 return QPainterPath();
434 const QPolygonF corners( rect );
439 for (
int i = 0; i < 4; i++ )
441 if ( ordered[2 * i].isEmpty() )
443 path.lineTo( corners[i] );
447 path.connectPath( ordered[2 * i] );
448 path.connectPath( ordered[2 * i + 1] );
455 return path.simplified();
461static QPainterPath qwtBorderPath(
const QWidget* canvas,
const QRect& rect )
463 if ( canvas->testAttribute(Qt::WA_StyledBackground ) )
465 QwtStyleSheetRecorder recorder( rect.size() );
467 QPainter painter( &recorder );
470 opt.initFrom( canvas );
472 canvas->style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, canvas );
476 if ( !recorder.background.path.isEmpty() )
477 return recorder.background.path;
479 if ( !recorder.border.rectList.isEmpty() )
480 return qwtCombinePathList( rect, recorder.border.pathList );
484 const double borderRadius = canvas->property(
"borderRadius" ).toDouble();
486 if ( borderRadius > 0.0 )
488 double fw2 = canvas->property(
"frameWidth" ).toInt() * 0.5;
489 QRectF r = QRectF(rect).adjusted( fw2, fw2, -fw2, -fw2 );
492 path.addRoundedRect( r, borderRadius, borderRadius );
497 return QPainterPath();
500class QwtPlotAbstractCanvas::PrivateData
507 styleSheet.hasBorder =
false;
516 QPainterPath borderPath;
519 struct StyleSheetBackground
527 QWidget* canvasWidget;
536 m_data =
new PrivateData;
554 return qobject_cast< QwtPlot* >( m_data->canvasWidget->parent() );
560 return qobject_cast< const QwtPlot* >( m_data->canvasWidget->parent() );
580 return m_data->focusIndicator;
589 const int margin = 1;
591 QRect focusRect = m_data->canvasWidget->contentsRect();
592 focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin,
593 focusRect.width() - 2 * margin, focusRect.height() - 2 * margin );
606 m_data->borderRadius = qwtMaxF( 0.0, radius );
615 return m_data->borderRadius;
632 if ( m_data->borderRadius > 0 )
634 const int frameWidth = w->property(
"frameWidth" ).toInt();
635 if ( frameWidth > 0 )
637 const int frameShape = w->property(
"frameShape" ).toInt();
638 const int frameShadow = w->property(
"frameShadow" ).toInt();
640 const QRectF frameRect = w->property(
"frameRect" ).toRect();
643 m_data->borderRadius, m_data->borderRadius,
644 w->palette(), frameWidth, frameShape | frameShadow );
649 const int frameShape = w->property(
"frameShape" ).toInt();
650 const int frameShadow = w->property(
"frameShadow" ).toInt();
652#if QT_VERSION < 0x050000
653 QStyleOptionFrameV3 opt;
655 QStyleOptionFrame opt;
659 opt.frameShape = QFrame::Shape(
int( opt.frameShape ) | frameShape );
666 case QFrame::StyledPanel:
669 opt.lineWidth = w->property(
"lineWidth" ).toInt();
670 opt.midLineWidth = w->property(
"midLineWidth" ).toInt();
675 opt.lineWidth = w->property(
"frameWidth" ).toInt();
680 if ( frameShadow == QFrame::Sunken )
681 opt.state |= QStyle::State_Sunken;
682 else if ( frameShadow == QFrame::Raised )
683 opt.state |= QStyle::State_Raised;
685 w->style()->drawControl(QStyle::CE_ShapedFrame, &opt, painter, w );
708 if ( w->autoFillBackground() )
710 const QRect canvasRect = w->rect();
714 painter->setPen( Qt::NoPen );
715 painter->setBrush( w->palette().brush( w->backgroundRole() ) );
717 const QRect frameRect = w->property(
"frameRect" ).toRect();
718 if (
borderRadius() > 0.0 && ( canvasRect == frameRect ) )
720 const int frameWidth = w->property(
"frameWidth" ).toInt();
721 if ( frameWidth > 0 )
724 painter->drawRect( canvasRect );
728 painter->setRenderHint( QPainter::Antialiasing,
true );
734 painter->drawRect( canvasRect );
748 if ( hackStyledBackground )
762 if ( !m_data->styleSheet.hasBorder ||
763 m_data->styleSheet.borderPath.isEmpty() )
766 hackStyledBackground =
false;
772 if ( hackStyledBackground )
777 painter->setPen( Qt::NoPen );
778 painter->setBrush( m_data->styleSheet.background.brush );
779 painter->setBrushOrigin( m_data->styleSheet.background.origin );
780 painter->setClipPath( m_data->styleSheet.borderPath );
781 painter->drawRect( w->contentsRect() );
788 QStyleOptionFrame opt;
790 w->style()->drawPrimitive( QStyle::PE_Frame, &opt, painter, w);
796 w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w );
809 if ( !m_data->styleSheet.borderPath.isEmpty() )
811 painter->setClipPath(
812 m_data->styleSheet.borderPath, Qt::IntersectClip );
818 const QRect frameRect = w->property(
"frameRect" ).toRect();
823 painter->setClipRect( w->contentsRect(), Qt::IntersectClip );
827 QwtPlot*
plot = qobject_cast< QwtPlot* >( w->parent() );
839 if ( !w->testAttribute( Qt::WA_StyledBackground ) )
842 QwtStyleSheetRecorder recorder( w->size() );
844 QPainter painter( &recorder );
848 w->style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, w);
852 m_data->styleSheet.hasBorder = !recorder.border.rectList.isEmpty();
853 m_data->styleSheet.cornerRects = recorder.clipRects;
855 if ( recorder.background.path.isEmpty() )
857 if ( !recorder.border.rectList.isEmpty() )
859 m_data->styleSheet.borderPath =
860 qwtCombinePathList( w->rect(), recorder.border.pathList );
865 m_data->styleSheet.borderPath = recorder.background.path;
866 m_data->styleSheet.background.brush = recorder.background.brush;
867 m_data->styleSheet.background.origin = recorder.background.origin;
874 return m_data->canvasWidget;
880 return m_data->canvasWidget;
883class QwtPlotAbstractGLCanvas::PrivateData
887 frameStyle( QFrame::Panel | QFrame::Sunken),
907 m_data =
new PrivateData;
929 if (
bool( m_data->paintAttributes & attribute ) == on )
934 m_data->paintAttributes |= attribute;
938 m_data->paintAttributes &= ~attribute;
954 return m_data->paintAttributes & attribute;
967 if ( style != m_data->frameStyle )
969 m_data->frameStyle = style;
982 return m_data->frameStyle;
993 setFrameStyle( ( m_data->frameStyle & QFrame::Shape_Mask ) | shadow );
1002 return (QFrame::Shadow) ( m_data->frameStyle & QFrame::Shadow_Mask );
1013 setFrameStyle( ( m_data->frameStyle & QFrame::Shadow_Mask ) | shape );
1022 return (QFrame::Shape) ( m_data->frameStyle & QFrame::Shape_Mask );
1035 width = qMax( width, 0 );
1036 if ( width != m_data->lineWidth )
1038 m_data->lineWidth = qMax( width, 0 );
1050 return m_data->lineWidth;
1063 width = qMax( width, 0 );
1064 if ( width != m_data->midLineWidth )
1066 m_data->midLineWidth = width;
1078 return m_data->midLineWidth;
1086 return (
frameStyle() != QFrame::NoFrame ) ? m_data->lineWidth : 0;
1099 w->repaint( w->contentsRect() );
1101 w->update( w->contentsRect() );
1108 return canvasWidget()->contentsRect().adjusted( -fw, -fw, fw, fw );
1114#if FIX_GL_TRANSLATION
1115 if ( painter->paintEngine()->type() == QPaintEngine::OpenGL2 )
1118 painter->translate( 1, 1 );
1122 if (
canvasWidget()->testAttribute( Qt::WA_StyledBackground ) )
A null paint device doing nothing.
static void drawRoundedFrame(QPainter *, const QRectF &, qreal xRadius, qreal yRadius, const QPalette &, int lineWidth, int frameStyle)
static void drawFocusRect(QPainter *, const QWidget *)
Draw a focus rectangle on a widget using its style.
static void fillPixmap(const QWidget *, QPixmap &, const QPoint &offset=QPoint())
Base class for all type of plot canvases.
void fillBackground(QPainter *)
Helper function for the derived plot canvas.
QwtPlot * plot()
Return parent plot widget.
virtual void drawBackground(QPainter *)
Helper function for the derived plot canvas.
void drawUnstyled(QPainter *)
Helper function for the derived plot canvas.
void setFocusIndicator(FocusIndicator)
virtual ~QwtPlotAbstractCanvas()
Destructor.
FocusIndicator focusIndicator() const
void updateStyleSheetInfo()
Update the cached information about the current style sheet.
double borderRadius() const
QPainterPath canvasBorderPath(const QRect &rect) const
virtual void drawBorder(QPainter *)
QwtPlotAbstractCanvas(QWidget *canvasWidget)
Constructor.
void drawCanvas(QPainter *)
Draw the plot to the canvas.
void drawStyled(QPainter *, bool)
Helper function for the derived plot canvas.
virtual void drawFocusIndicator(QPainter *)
void setBorderRadius(double)
FocusIndicator
Focus indicator The default setting is NoFocusIndicator.
@ NoFocusIndicator
Don't paint a focus indicator.
QwtPlotAbstractGLCanvas(QWidget *canvasWidget)
Constructor.
bool testPaintAttribute(PaintAttribute) const
void setPaintAttribute(PaintAttribute, bool on=true)
Changing the paint attributes.
QFrame::Shadow frameShadow() const
void setMidLineWidth(int)
virtual void invalidateBackingStore()=0
Invalidate the internal backing store.
PaintAttribute
Paint attributes.
@ BackingStore
Paint double buffered reusing the content of the pixmap buffer when possible.
void setFrameShape(QFrame::Shape)
QFrame::Shape frameShape() const
virtual ~QwtPlotAbstractGLCanvas()
Destructor.
void setFrameShadow(QFrame::Shadow)
QFlags< PaintAttribute > PaintAttributes
Paint attributes.
void setFrameStyle(int style)
void draw(QPainter *)
Helper function for the derived plot canvas.
virtual void drawCanvas(QPainter *)