File indexing completed on 2024-05-12 04:20:28
0001 /* 0002 * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 0003 * 0004 * This file is part of the KD Chart library. 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "KChartAbstractAreaBase_p.h" 0010 0011 #include <KChartBackgroundAttributes.h> 0012 #include <KChartFrameAttributes.h> 0013 #include <KChartTextAttributes.h> 0014 #include "KChartPainterSaver_p.h" 0015 #include "KChartPrintingParameters.h" 0016 #include "KChartMath_p.h" 0017 0018 #include <QPainter> 0019 #include <QPainterPath> 0020 0021 0022 using namespace KChart; 0023 0024 AbstractAreaBase::Private::Private() : 0025 visible( true ) 0026 { 0027 init(); 0028 } 0029 0030 0031 AbstractAreaBase::Private::~Private() {} 0032 0033 0034 void AbstractAreaBase::Private::init() 0035 { 0036 } 0037 0038 0039 AbstractAreaBase::AbstractAreaBase() : 0040 _d( new Private() ) 0041 { 0042 } 0043 0044 AbstractAreaBase::~AbstractAreaBase() 0045 { 0046 delete _d; _d = nullptr; 0047 } 0048 0049 0050 void AbstractAreaBase::init() 0051 { 0052 } 0053 0054 0055 #define d d_func() 0056 0057 bool AbstractAreaBase::compare( const AbstractAreaBase* other ) const 0058 { 0059 if ( other == this ) return true; 0060 if ( !other ) { 0061 return false; 0062 } 0063 return (frameAttributes() == other->frameAttributes()) && 0064 (backgroundAttributes() == other->backgroundAttributes()); 0065 } 0066 0067 void AbstractAreaBase::alignToReferencePoint( const RelativePosition& position ) 0068 { 0069 Q_UNUSED( position ); 0070 // PENDING(kalle) FIXME 0071 qWarning( "Sorry, not implemented: void AbstractAreaBase::alignToReferencePoint( const RelativePosition& position )" ); 0072 } 0073 0074 void AbstractAreaBase::setFrameAttributes( const FrameAttributes &a ) 0075 { 0076 if ( d->frameAttributes == a ) 0077 return; 0078 0079 d->frameAttributes = a; 0080 positionHasChanged(); 0081 } 0082 0083 FrameAttributes AbstractAreaBase::frameAttributes() const 0084 { 0085 return d->frameAttributes; 0086 } 0087 0088 void AbstractAreaBase::setBackgroundAttributes( const BackgroundAttributes &a ) 0089 { 0090 if ( d->backgroundAttributes == a ) 0091 return; 0092 0093 d->backgroundAttributes = a; 0094 positionHasChanged(); 0095 } 0096 0097 BackgroundAttributes AbstractAreaBase::backgroundAttributes() const 0098 { 0099 return d->backgroundAttributes; 0100 } 0101 0102 0103 /* static */ 0104 void AbstractAreaBase::paintBackgroundAttributes( QPainter& painter, const QRect& rect, 0105 const KChart::BackgroundAttributes& attributes ) 0106 { 0107 if ( !attributes.isVisible() ) return; 0108 0109 /* first draw the brush (may contain a pixmap)*/ 0110 if ( Qt::NoBrush != attributes.brush().style() ) { 0111 KChart::PainterSaver painterSaver( &painter ); 0112 painter.setPen( Qt::NoPen ); 0113 const QPointF newTopLeft( painter.deviceTransform().map( rect.topLeft() ) ); 0114 painter.setBrushOrigin( newTopLeft ); 0115 painter.setBrush( attributes.brush() ); 0116 painter.drawRect( rect.adjusted( 0, 0, -1, -1 ) ); 0117 } 0118 /* next draw the backPixmap over the brush */ 0119 if ( !attributes.pixmap().isNull() && 0120 attributes.pixmapMode() != BackgroundAttributes::BackgroundPixmapModeNone ) { 0121 QPointF ol = rect.topLeft(); 0122 if ( BackgroundAttributes::BackgroundPixmapModeCentered == attributes.pixmapMode() ) 0123 { 0124 ol.setX( rect.center().x() - attributes.pixmap().width() / 2 ); 0125 ol.setY( rect.center().y() - attributes.pixmap().height()/ 2 ); 0126 painter.drawPixmap( ol, attributes.pixmap() ); 0127 } else { 0128 QTransform m; 0129 qreal zW = (qreal)rect.width() / (qreal)attributes.pixmap().width(); 0130 qreal zH = (qreal)rect.height() / (qreal)attributes.pixmap().height(); 0131 switch ( attributes.pixmapMode() ) { 0132 case BackgroundAttributes::BackgroundPixmapModeScaled: 0133 { 0134 qreal z; 0135 z = qMin( zW, zH ); 0136 m.scale( z, z ); 0137 } 0138 break; 0139 case BackgroundAttributes::BackgroundPixmapModeStretched: 0140 m.scale( zW, zH ); 0141 break; 0142 default: 0143 ; // Cannot happen, previously checked 0144 } 0145 QPixmap pm = attributes.pixmap().transformed( m ); 0146 ol.setX( rect.center().x() - pm.width() / 2 ); 0147 ol.setY( rect.center().y() - pm.height()/ 2 ); 0148 painter.drawPixmap( ol, pm ); 0149 } 0150 } 0151 } 0152 0153 /* static */ 0154 void AbstractAreaBase::paintFrameAttributes( QPainter& painter, const QRect& rect, 0155 const KChart::FrameAttributes& attributes ) 0156 { 0157 0158 if ( !attributes.isVisible() ) return; 0159 0160 // Note: We set the brush to NoBrush explicitly here. 0161 // Otherwise we might get a filled rectangle, so any 0162 // previously drawn background would be overwritten by that area. 0163 0164 const QPen oldPen( painter.pen() ); 0165 const QBrush oldBrush( painter.brush() ); 0166 0167 painter.setPen( PrintingParameters::scalePen( attributes.pen() ) ); 0168 painter.setBrush( Qt::NoBrush ); 0169 painter.drawRoundedRect( rect.adjusted( 0, 0, -1, -1 ), attributes.cornerRadius(), attributes.cornerRadius() ); 0170 0171 painter.setBrush( oldBrush ); 0172 painter.setPen( oldPen ); 0173 } 0174 0175 void AbstractAreaBase::paintBackground( QPainter& painter, const QRect& rect ) 0176 { 0177 Q_ASSERT_X ( d != nullptr, "AbstractAreaBase::paintBackground()", 0178 "Private class was not initialized!" ); 0179 0180 PainterSaver painterSaver( &painter ); 0181 0182 const qreal radius = d->frameAttributes.cornerRadius(); 0183 QPainterPath path; 0184 path.addRoundedRect( rect.adjusted( 0, 0, -1, -1 ), radius, radius ); 0185 painter.setClipPath(path); 0186 0187 paintBackgroundAttributes( painter, rect, d->backgroundAttributes ); 0188 } 0189 0190 0191 void AbstractAreaBase::paintFrame( QPainter& painter, const QRect& rect ) 0192 { 0193 Q_ASSERT_X ( d != nullptr, "AbstractAreaBase::paintFrame()", 0194 "Private class was not initialized!" ); 0195 paintFrameAttributes( painter, rect, d->frameAttributes ); 0196 } 0197 0198 0199 void AbstractAreaBase::getFrameLeadings(int& left, int& top, int& right, int& bottom ) const 0200 { 0201 int padding = 0; 0202 if ( d && d->frameAttributes.isVisible() ) { 0203 padding = qMax( d->frameAttributes.padding(), 0 ); 0204 } 0205 left = padding; 0206 top = padding; 0207 right = padding; 0208 bottom = padding; 0209 } 0210 0211 QRect AbstractAreaBase::innerRect() const 0212 { 0213 int left; 0214 int top; 0215 int right; 0216 int bottom; 0217 getFrameLeadings( left, top, right, bottom ); 0218 return QRect ( QPoint( 0, 0 ), areaGeometry().size() ).adjusted( left, top, -right, -bottom ); 0219 } 0220 0221 void AbstractAreaBase::positionHasChanged() 0222 { 0223 // this block left empty intentionally 0224 }