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