1 /*
2 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3 *
4 * This file is part of the KD Chart library.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "KChartAbstractAreaBase.h"
21 #include "KChartAbstractAreaBase_p.h"
22
23 #include <KChartBackgroundAttributes.h>
24 #include <KChartFrameAttributes.h>
25 #include <KChartTextAttributes.h>
26 #include "KChartPainterSaver_p.h"
27 #include "KChartPrintingParameters.h"
28 #include "KChartMath_p.h"
29
30 #include <QPainter>
31 #include <QPainterPath>
32
33
34 using namespace KChart;
35
Private()36 AbstractAreaBase::Private::Private() :
37 visible( true )
38 {
39 init();
40 }
41
42
~Private()43 AbstractAreaBase::Private::~Private() {}
44
45
init()46 void AbstractAreaBase::Private::init()
47 {
48 }
49
50
AbstractAreaBase()51 AbstractAreaBase::AbstractAreaBase() :
52 _d( new Private() )
53 {
54 }
55
~AbstractAreaBase()56 AbstractAreaBase::~AbstractAreaBase()
57 {
58 delete _d; _d = nullptr;
59 }
60
61
init()62 void AbstractAreaBase::init()
63 {
64 }
65
66
67 #define d d_func()
68
compare(const AbstractAreaBase * other) const69 bool AbstractAreaBase::compare( const AbstractAreaBase* other ) const
70 {
71 if ( other == this ) return true;
72 if ( !other ) {
73 return false;
74 }
75 return (frameAttributes() == other->frameAttributes()) &&
76 (backgroundAttributes() == other->backgroundAttributes());
77 }
78
alignToReferencePoint(const RelativePosition & position)79 void AbstractAreaBase::alignToReferencePoint( const RelativePosition& position )
80 {
81 Q_UNUSED( position );
82 // PENDING(kalle) FIXME
83 qWarning( "Sorry, not implemented: void AbstractAreaBase::alignToReferencePoint( const RelativePosition& position )" );
84 }
85
setFrameAttributes(const FrameAttributes & a)86 void AbstractAreaBase::setFrameAttributes( const FrameAttributes &a )
87 {
88 if ( d->frameAttributes == a )
89 return;
90
91 d->frameAttributes = a;
92 positionHasChanged();
93 }
94
frameAttributes() const95 FrameAttributes AbstractAreaBase::frameAttributes() const
96 {
97 return d->frameAttributes;
98 }
99
setBackgroundAttributes(const BackgroundAttributes & a)100 void AbstractAreaBase::setBackgroundAttributes( const BackgroundAttributes &a )
101 {
102 if ( d->backgroundAttributes == a )
103 return;
104
105 d->backgroundAttributes = a;
106 positionHasChanged();
107 }
108
backgroundAttributes() const109 BackgroundAttributes AbstractAreaBase::backgroundAttributes() const
110 {
111 return d->backgroundAttributes;
112 }
113
114
115 /* static */
paintBackgroundAttributes(QPainter & painter,const QRect & rect,const KChart::BackgroundAttributes & attributes)116 void AbstractAreaBase::paintBackgroundAttributes( QPainter& painter, const QRect& rect,
117 const KChart::BackgroundAttributes& attributes )
118 {
119 if ( !attributes.isVisible() ) return;
120
121 /* first draw the brush (may contain a pixmap)*/
122 if ( Qt::NoBrush != attributes.brush().style() ) {
123 KChart::PainterSaver painterSaver( &painter );
124 painter.setPen( Qt::NoPen );
125 const QPointF newTopLeft( painter.deviceMatrix().map( rect.topLeft() ) );
126 painter.setBrushOrigin( newTopLeft );
127 painter.setBrush( attributes.brush() );
128 painter.drawRect( rect.adjusted( 0, 0, -1, -1 ) );
129 }
130 /* next draw the backPixmap over the brush */
131 if ( !attributes.pixmap().isNull() &&
132 attributes.pixmapMode() != BackgroundAttributes::BackgroundPixmapModeNone ) {
133 QPointF ol = rect.topLeft();
134 if ( BackgroundAttributes::BackgroundPixmapModeCentered == attributes.pixmapMode() )
135 {
136 ol.setX( rect.center().x() - attributes.pixmap().width() / 2 );
137 ol.setY( rect.center().y() - attributes.pixmap().height()/ 2 );
138 painter.drawPixmap( ol, attributes.pixmap() );
139 } else {
140 QMatrix m;
141 qreal zW = (qreal)rect.width() / (qreal)attributes.pixmap().width();
142 qreal zH = (qreal)rect.height() / (qreal)attributes.pixmap().height();
143 switch ( attributes.pixmapMode() ) {
144 case BackgroundAttributes::BackgroundPixmapModeScaled:
145 {
146 qreal z;
147 z = qMin( zW, zH );
148 m.scale( z, z );
149 }
150 break;
151 case BackgroundAttributes::BackgroundPixmapModeStretched:
152 m.scale( zW, zH );
153 break;
154 default:
155 ; // Cannot happen, previously checked
156 }
157 QPixmap pm = attributes.pixmap().transformed( m );
158 ol.setX( rect.center().x() - pm.width() / 2 );
159 ol.setY( rect.center().y() - pm.height()/ 2 );
160 painter.drawPixmap( ol, pm );
161 }
162 }
163 }
164
165 /* static */
paintFrameAttributes(QPainter & painter,const QRect & rect,const KChart::FrameAttributes & attributes)166 void AbstractAreaBase::paintFrameAttributes( QPainter& painter, const QRect& rect,
167 const KChart::FrameAttributes& attributes )
168 {
169
170 if ( !attributes.isVisible() ) return;
171
172 // Note: We set the brush to NoBrush explicitly here.
173 // Otherwise we might get a filled rectangle, so any
174 // previously drawn background would be overwritten by that area.
175
176 const QPen oldPen( painter.pen() );
177 const QBrush oldBrush( painter.brush() );
178
179 painter.setPen( PrintingParameters::scalePen( attributes.pen() ) );
180 painter.setBrush( Qt::NoBrush );
181 painter.drawRoundedRect( rect.adjusted( 0, 0, -1, -1 ), attributes.cornerRadius(), attributes.cornerRadius() );
182
183 painter.setBrush( oldBrush );
184 painter.setPen( oldPen );
185 }
186
paintBackground(QPainter & painter,const QRect & rect)187 void AbstractAreaBase::paintBackground( QPainter& painter, const QRect& rect )
188 {
189 Q_ASSERT_X ( d != nullptr, "AbstractAreaBase::paintBackground()",
190 "Private class was not initialized!" );
191
192 PainterSaver painterSaver( &painter );
193
194 const qreal radius = d->frameAttributes.cornerRadius();
195 QPainterPath path;
196 path.addRoundedRect( rect.adjusted( 0, 0, -1, -1 ), radius, radius );
197 painter.setClipPath(path);
198
199 paintBackgroundAttributes( painter, rect, d->backgroundAttributes );
200 }
201
202
paintFrame(QPainter & painter,const QRect & rect)203 void AbstractAreaBase::paintFrame( QPainter& painter, const QRect& rect )
204 {
205 Q_ASSERT_X ( d != nullptr, "AbstractAreaBase::paintFrame()",
206 "Private class was not initialized!" );
207 paintFrameAttributes( painter, rect, d->frameAttributes );
208 }
209
210
getFrameLeadings(int & left,int & top,int & right,int & bottom) const211 void AbstractAreaBase::getFrameLeadings(int& left, int& top, int& right, int& bottom ) const
212 {
213 int padding = 0;
214 if ( d && d->frameAttributes.isVisible() ) {
215 padding = qMax( d->frameAttributes.padding(), 0 );
216 }
217 left = padding;
218 top = padding;
219 right = padding;
220 bottom = padding;
221 }
222
innerRect() const223 QRect AbstractAreaBase::innerRect() const
224 {
225 int left;
226 int top;
227 int right;
228 int bottom;
229 getFrameLeadings( left, top, right, bottom );
230 return QRect ( QPoint( 0, 0 ), areaGeometry().size() ).adjusted( left, top, -right, -bottom );
231 }
232
positionHasChanged()233 void AbstractAreaBase::positionHasChanged()
234 {
235 // this bloc left empty intentionally
236 }
237