1/*
2 * Copyright 2008 by Aaron Seigo <aseigo@kde.org>
3 * Copyright 2008 Marco Martin <notmart@gmail.com>
4 *
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.
9 *
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
14 *
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.
19 */
20
21#ifndef PLASMA_FRAMESVG_H
22#define PLASMA_FRAMESVG_H
23
24#include <QtCore/QObject>
25#include <QtGui/QPixmap>
26
27#include <plasma/plasma_export.h>
28
29#include <plasma/plasma.h>
30#include <plasma/svg.h>
31
32class QPainter;
33class QPoint;
34class QPointF;
35class QRect;
36class QRectF;
37class QSize;
38class QSizeF;
39class QMatrix;
40
41namespace Plasma
42{
43
44class FrameSvgPrivate;
45
46/**
47 * @class FrameSvg plasma/framesvg.h <Plasma/FrameSvg>
48 *
49 * @short Provides an SVG with borders.
50 *
51 * When using SVG images for a background of an object that may change
52 * its aspect ratio, such as a dialog, simply scaling a single image
53 * may not be enough.
54 *
55 * FrameSvg allows SVGs to provide several elements for borders as well
56 * as a central element, each of which are scaled individually. These
57 * elements should be named
58 *
59 * - @c center - the central element, which will be scaled in both directions
60 * - @c top - the top border; the height is fixed, but it will be scaled
61 * horizontally to the same width as @c center
62 * - @c bottom - the bottom border; scaled in the same way as @c top
63 * - @c left - the left border; the width is fixed, but it will be scaled
64 * vertically to the same height as @c center
65 * - @c right - the right border; scaled in the same way as @c left
66 * - @c topleft - fixed size; must be the same height as @c top and the same
67 * width as @c left
68 * - @c bottomleft, @c topright, @c bottomright - similar to @c topleft
69 *
70 * @c center must exist, but all the others are optional. @c topleft and
71 * @c topright will be ignored if @c top does not exist, and similarly for
72 * @c bottomleft and @c bottomright.
73 *
74 * @see Plasma::Svg
75 **/
76class PLASMA_EXPORT FrameSvg : public Svg
77{
78 Q_OBJECT
79
80 Q_FLAGS(EnabledBorders)
81 Q_PROPERTY(EnabledBorders enabledBorders READ enabledBorders WRITE setEnabledBorders)
82
83 public:
84 /**
85 * These flags represents what borders should be drawn
86 */
87 enum EnabledBorder {
88 NoBorder = 0,
89 TopBorder = 1,
90 BottomBorder = 2,
91 LeftBorder = 4,
92 RightBorder = 8,
93 AllBorders = TopBorder | BottomBorder | LeftBorder | RightBorder
94 };
95 Q_DECLARE_FLAGS(EnabledBorders, EnabledBorder)
96
97 /**
98 * Constructs a new FrameSvg that paints the proper named subelements
99 * as borders. It may also be used as a regular Plasma::Svg object
100 * for direct access to elements in the Svg.
101 *
102 * @param parent options QObject to parent this to
103 *
104 * @related Plasma::Theme
105 */
106 explicit FrameSvg(QObject *parent = 0);
107 ~FrameSvg();
108
109 /**
110 * Loads a new Svg
111 * @param imagePath the new file
112 */
113 Q_INVOKABLE void setImagePath(const QString &path);
114
115 /**
116 * Sets what borders should be painted
117 * @param flags borders we want to paint
118 */
119 void setEnabledBorders(const EnabledBorders borders);
120
121 /**
122 * Convenience method to get the enabled borders
123 * @return what borders are painted
124 */
125 EnabledBorders enabledBorders() const;
126
127 /**
128 * Resize the frame maintaining the same border size
129 * @param size the new size of the frame
130 */
131 Q_INVOKABLE void resizeFrame(const QSizeF &size);
132
133 /**
134 * @returns the size of the frame
135 */
136 Q_INVOKABLE QSizeF frameSize() const;
137
138 /**
139 * Returns the margin size given the margin edge we want
140 * @param edge the margin edge we want, top, bottom, left or right
141 * @return the margin size
142 */
143 Q_INVOKABLE qreal marginSize(const Plasma::MarginEdge edge) const;
144
145 /**
146 * Convenience method that extracts the size of the four margins
147 * in the four output parameters
148 * @param left left margin size
149 * @param top top margin size
150 * @param right right margin size
151 * @param bottom bottom margin size
152 */
153 Q_INVOKABLE void getMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const;
154
155 /**
156 * @return the rectangle of the center element, taking the margins into account.
157 */
158 Q_INVOKABLE QRectF contentsRect() const;
159
160 /**
161 * Sets the prefix (@see setElementPrefix) to 'north', 'south', 'west' and 'east'
162 * when the location is TopEdge, BottomEdge, LeftEdge and RightEdge,
163 * respectively. Clears the prefix in other cases.
164 *
165 * The prefix must exist in the SVG document, which means that this can only be
166 * called successfully after setImagePath is called.
167 * @param location location in the UI this frame will be drawn
168 */
169 Q_INVOKABLE void setElementPrefix(Plasma::Location location);
170
171 /**
172 * Sets the prefix for the SVG elements to be used for painting. For example,
173 * if prefix is 'active', then instead of using the 'top' element of the SVG
174 * file to paint the top border, 'active-top' element will be used. The same
175 * goes for other SVG elements.
176 *
177 * If the elements with prefixes are not present, the default ones are used.
178 * (for the sake of speed, the test is present only for the 'center' element)
179 *
180 * Setting the prefix manually resets the location to Floating.
181 *
182 * The prefix must exist in the SVG document, which means that this can only be
183 * called successfully after setImagePath is called.
184 *
185 * @param prefix prefix for the SVG elements that make up the frame
186 */
187 Q_INVOKABLE void setElementPrefix(const QString & prefix);
188
189 /**
190 * @return true if the svg has the necessary elements with the given prefix
191 * to draw a frame
192 * @param prefix the given prefix we want to check if drawable
193 */
194 Q_INVOKABLE bool hasElementPrefix(const QString & prefix) const;
195
196 /**
197 * This is an overloaded method provided for convenience equivalent to
198 * hasElementPrefix("north"), hasElementPrefix("south")
199 * hasElementPrefix("west") and hasElementPrefix("east")
200 * @return true if the svg has the necessary elements with the given prefix
201 * to draw a frame.
202 * @param location the given prefix we want to check if drawable
203 */
204 Q_INVOKABLE bool hasElementPrefix(Plasma::Location location) const;
205
206 /**
207 * Returns the prefix for SVG elements of the FrameSvg
208 * @return the prefix
209 */
210 Q_INVOKABLE QString prefix();
211
212 /**
213 * Returns a mask that tightly contains the fully opaque areas of the svg
214 * @return a region of opaque areas
215 */
216 Q_INVOKABLE QRegion mask() const;
217
218 /**
219 * @return a pixmap whose alpha channel is the opacity of the frame. It may be the frame itself or a special frame with the mask- prefix
220 */
221 QPixmap alphaMask() const;
222
223 /**
224 * Sets whether saving all the rendered prefixes in a cache or not
225 * @param cache if use the cache or not
226 */
227 Q_INVOKABLE void setCacheAllRenderedFrames(bool cache);
228
229 /**
230 * @return if all the different prefixes should be kept in a cache when rendered
231 */
232 Q_INVOKABLE bool cacheAllRenderedFrames() const;
233
234 /**
235 * Deletes the internal cache freeing memory: use this if you want to switch the rendered
236 * element and you don't plan to switch back to the previous one for a long time and you
237 * used setUsingRenderingCache(true)
238 */
239 Q_INVOKABLE void clearCache();
240
241 /**
242 * Returns a pixmap of the SVG represented by this object.
243 *
244 * @param elelementId the ID string of the element to render, or an empty
245 * string for the whole SVG (the default)
246 * @return a QPixmap of the rendered SVG
247 */
248 Q_INVOKABLE QPixmap framePixmap();
249
250 /**
251 * Paints the loaded SVG with the elements that represents the border
252 * @param painter the QPainter to use
253 * @param target the target rectangle on the paint device
254 * @param source the portion rectangle of the source image
255 */
256 Q_INVOKABLE void paintFrame(QPainter *painter, const QRectF &target,
257 const QRectF &source = QRectF());
258
259 /**
260 * Paints the loaded SVG with the elements that represents the border
261 * This is an overloaded member provided for convenience
262 * @param painter the QPainter to use
263 * @param pos where to paint the svg
264 */
265 Q_INVOKABLE void paintFrame(QPainter *painter, const QPointF &pos = QPointF(0, 0));
266
267 private:
268 FrameSvgPrivate *const d;
269 friend class Applet;
270
271 Q_PRIVATE_SLOT(d, void updateSizes())
272 Q_PRIVATE_SLOT(d, void updateNeeded())
273};
274
275} // Plasma namespace
276
277Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::FrameSvg::EnabledBorders)
278
279#endif // multiple inclusion guard
280