Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / libs / plasma / svgpanel.cpp
blob32fc89d93340fcbd03ca871795a815cbe459700d
1 /*
2 * Copyright 2008 by Aaron Seigo <aseigo@kde.org>
3 * Copyright 2008 Marco Martin <notmart@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Library General Public License as
7 * published by the Free Software Foundation; either version 2, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details
15 * You should have received a copy of the GNU Library General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "svgpanel.h"
23 #include <QPainter>
24 #include <QSize>
26 #include <KDebug>
28 namespace Plasma
31 class SvgPanel::Private
33 public:
34 Private()
35 : bFlags(DrawAllBorders|ContentAtOrigin),
36 cachedBackground(0), pos(0,0)
40 ~Private()
42 delete cachedBackground;
45 BorderFlags bFlags;
46 QPixmap *cachedBackground;
47 Svg *background;
48 QSizeF panelSize;
49 QPointF pos;
51 //measures
52 int topHeight;
53 int leftWidth;
54 int rightWidth;
55 int bottomHeight;
57 //size of the svg where the size of the "center"
58 //element is contentWidth x contentHeight
59 bool noBorderPadding : 1;
60 bool stretchBorders : 1;
63 SvgPanel::SvgPanel(const QString& imagePath, QObject* parent)
64 : QObject(parent),
65 d(new Private)
67 d->background = new Svg(imagePath, this);
68 connect(d->background, SIGNAL(repaintNeeded()), this, SLOT(updateSizes()));
70 updateSizes();
71 d->panelSize = d->background->size();
74 SvgPanel::~SvgPanel()
76 delete d;
79 void SvgPanel::setFile(const QString& imagePath)
81 if (imagePath == d->background->file()) {
82 return;
85 d->background->setFile(imagePath);
86 updateSizes();
89 QString SvgPanel::file() const
91 return d->background->file();
94 void SvgPanel::setBorderFlags(const BorderFlags flags)
96 if (flags == d->bFlags) {
97 return;
100 d->bFlags = flags;
101 updateSizes();
104 SvgPanel::BorderFlags SvgPanel::borderFlags() const
106 return d->bFlags;
109 void SvgPanel::setPos(const QPointF& pos)
111 d->pos = pos;
114 QPointF SvgPanel::pos() const
116 return d->pos;
120 void SvgPanel::resize(const QSizeF& size)
122 if (!size.isValid() || size.width() < 1 || size.height() < 1 || size == d->panelSize) {
123 return;
126 d->panelSize = size;
127 updateSizes();
130 qreal SvgPanel::marginSize(const Plasma::MarginEdge edge) const
132 if (d->noBorderPadding) {
133 return .0;
136 switch (edge) {
137 case Plasma::TopMargin:
138 return d->topHeight;
139 break;
141 case Plasma::LeftMargin:
142 return d->leftWidth;
143 break;
145 case Plasma::RightMargin:
146 return d->rightWidth;
147 break;
149 //Plasma::BottomMargin
150 default:
151 return d->bottomHeight;
152 break;
156 void SvgPanel::paint(QPainter* painter, const QRectF& rect)
158 bool origined = d->bFlags & ContentAtOrigin;
159 const int topWidth = d->background->elementSize("top").width();
160 const int leftHeight = d->background->elementSize("left").height();
161 const int topOffset = origined ? 0 - d->topHeight : 0;
162 const int leftOffset = origined ? 0 - d->leftWidth : 0;
164 if (!d->cachedBackground) {
165 const int contentWidth = d->panelSize.width() - d->leftWidth - d->rightWidth;
166 const int contentHeight = d->panelSize.height() - d->topHeight - d->bottomHeight;
167 int contentTop = 0;
168 int contentLeft = 0;
169 int rightOffset = contentWidth;
170 int bottomOffset = contentHeight;
172 delete d->cachedBackground;
173 d->cachedBackground = new QPixmap(d->leftWidth + contentWidth + d->rightWidth,
174 d->topHeight + contentHeight + d->bottomHeight);
175 d->cachedBackground->fill(Qt::transparent);
176 QPainter p(d->cachedBackground);
177 p.setCompositionMode(QPainter::CompositionMode_Source);
178 p.setRenderHint(QPainter::SmoothPixmapTransform);
180 if (origined) {
181 p.translate(d->leftWidth, d->topHeight);
184 //FIXME: This is a hack to fix a drawing problems with svg files where a thin transparent border is drawn around the svg image.
185 // the transparent border around the svg seems to vary in size depending on the size of the svg and as a result increasing the
186 // svg image by 2 all around didn't resolve the issue. For now it resizes based on the border size.
189 //CENTER
190 if (contentHeight > 0 && contentWidth > 0) {
191 QSizeF scaledSize = QSizeF(d->panelSize.width() -
192 (d->leftWidth + d->rightWidth) +
193 d->panelSize.width()*(((qreal)(d->leftWidth + d->rightWidth)) / d->panelSize.width()),
194 d->panelSize.height() -
195 (d->topHeight + d->bottomHeight) +
196 d->panelSize.height()*(((qreal)(d->topHeight + d->bottomHeight)) / d->panelSize.height()));
198 d->background->resize(scaledSize.width(), scaledSize.height());
199 d->background->paint(&p, QRect(contentLeft - d->leftWidth, contentTop - d->topHeight,
200 contentWidth + d->leftWidth*2, contentHeight + d->topHeight*2),
201 "center");
202 d->background->resize();
205 // Corners
206 if (d->bFlags & DrawTopBorder) {
207 if (!origined) {
208 contentTop = d->topHeight;
209 bottomOffset += d->topHeight;
212 if (d->bFlags & DrawLeftBorder) {
213 d->background->paint(&p, QRect(leftOffset, topOffset, d->leftWidth, d->topHeight), "topleft");
215 if (!origined) {
216 contentLeft = d->leftWidth;
217 rightOffset = contentWidth + d->leftWidth;
221 if (d->bFlags & DrawRightBorder) {
222 d->background->paint(&p, QRect(rightOffset, topOffset, d->rightWidth, d->topHeight), "topright");
226 if (d->bFlags & DrawBottomBorder) {
227 if (d->bFlags & DrawLeftBorder) {
228 d->background->paint(&p, QRect(leftOffset, bottomOffset, d->leftWidth, d->bottomHeight), "bottomleft");
230 if (!origined) {
231 contentLeft = d->leftWidth;
232 rightOffset = contentWidth + d->leftWidth;
236 if (d->bFlags & DrawRightBorder) {
237 d->background->paint(&p, QRect(rightOffset, bottomOffset, d->rightWidth, d->bottomHeight), "bottomright");
241 // Sides
242 if (d->stretchBorders) {
243 if (d->bFlags & DrawLeftBorder) {
244 d->background->paint(&p, QRect(leftOffset, contentTop, d->leftWidth, contentHeight), "left");
247 if (d->bFlags & DrawRightBorder) {
248 d->background->paint(&p, QRect(rightOffset, contentTop, d->rightWidth, contentHeight), "right");
251 if (d->bFlags & DrawTopBorder) {
252 d->background->paint(&p, QRect(contentLeft, topOffset, contentWidth, d->topHeight), "top");
255 if (d->bFlags & DrawBottomBorder) {
256 d->background->paint(&p, QRect(contentLeft, bottomOffset, contentWidth, d->bottomHeight), "bottom");
258 } else {
259 if (d->bFlags & DrawLeftBorder) {
260 QPixmap left(d->leftWidth, leftHeight);
261 left.fill(Qt::transparent);
264 QPainter sidePainter(&left);
265 sidePainter.setCompositionMode(QPainter::CompositionMode_Source);
266 d->background->paint(&sidePainter, QPoint(0, 0), "left");
269 p.drawTiledPixmap(QRect(leftOffset, contentTop, d->leftWidth, contentHeight), left);
272 if (d->bFlags & DrawRightBorder) {
273 QPixmap right(d->rightWidth, leftHeight);
274 right.fill(Qt::transparent);
277 QPainter sidePainter(&right);
278 sidePainter.setCompositionMode(QPainter::CompositionMode_Source);
279 d->background->paint(&sidePainter, QPoint(0, 0), "right");
282 p.drawTiledPixmap(QRect(rightOffset, contentTop, d->rightWidth, contentHeight), right);
285 if (d->bFlags & DrawTopBorder) {
286 QPixmap top(topWidth, d->topHeight);
287 top.fill(Qt::transparent);
290 QPainter sidePainter(&top);
291 sidePainter.setCompositionMode(QPainter::CompositionMode_Source);
292 d->background->paint(&sidePainter, QPoint(0, 0), "top");
295 p.drawTiledPixmap(QRect(contentLeft, topOffset, contentWidth, d->topHeight), top);
298 if (d->bFlags & DrawBottomBorder) {
299 QPixmap bottom(topWidth, d->bottomHeight);
300 bottom.fill(Qt::transparent);
303 QPainter sidePainter(&bottom);
304 sidePainter.setCompositionMode(QPainter::CompositionMode_Source);
305 d->background->paint(&sidePainter, QPoint(0, 0), "bottom");
308 p.drawTiledPixmap(QRect(contentLeft, bottomOffset, contentWidth, d->bottomHeight), bottom);
312 // re-enable this once Qt's svg rendering is un-buggered
313 //resize(contentWidth, contentHeight);
314 //paint(&p, QRect(contentLeft, contentTop, contentWidth, contentHeight), "center");
317 //p2->drawPixmap(paintRect, *cachedBackground, paintRect.translated(-leftOffset,-topOffset));
318 painter->drawPixmap(rect, *d->cachedBackground, rect.translated(-d->pos.x()-leftOffset,-d->pos.y()-topOffset));
321 void SvgPanel::updateSizes()
323 delete d->cachedBackground;
324 d->cachedBackground = 0;
325 d->background->resize();
326 if (d->bFlags & DrawTopBorder) {
327 d->topHeight = d->background->elementSize("top").height();
328 } else {
329 d->topHeight = 0;
332 if (d->bFlags & DrawLeftBorder) {
333 d->leftWidth = d->background->elementSize("left").width();
334 } else {
335 d->leftWidth = 0;
338 if (d->bFlags & DrawRightBorder) {
339 d->rightWidth = d->background->elementSize("right").width();
340 } else {
341 d->rightWidth = 0;
344 if (d->bFlags & DrawBottomBorder) {
345 d->bottomHeight = d->background->elementSize("bottom").height();
346 } else {
347 d->bottomHeight = 0;
350 //since it's rectangular, topWidth and bottomWidth must be the same
351 d->noBorderPadding = d->background->elementExists("hint-no-border-padding");
352 d->stretchBorders = d->background->elementExists("hint-stretch-borders");
353 emit repaintNeeded();
356 } // Plasma namespace
358 #include "svgpanel.moc"