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 }