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 }