1 | #ifndef oxygen_style_helper_h |
2 | #define oxygen_style_helper_h |
3 | |
4 | /* |
5 | * Copyright 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr> |
6 | * Copyright 2008 Long Huynh Huu <long.upcase@googlemail.com> |
7 | * Copyright 2007 Matthew Woehlke <mw_triad@users.sourceforge.net> |
8 | * Copyright 2007 Casper Boemann <cbr@boemann.dk> |
9 | * |
10 | * This library is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU Library General Public |
12 | * License version 2 as published by the Free Software Foundation. |
13 | * |
14 | * This library is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | * Library General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Library General Public License |
20 | * along with this library; see the file COPYING.LIB. If not, write to |
21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
22 | * Boston, MA 02110-1301, USA. |
23 | */ |
24 | |
25 | #include "oxygenhelper.h" |
26 | #include "oxygenanimationmodes.h" |
27 | |
28 | #include <KWindowSystem> |
29 | #include <KDebug> |
30 | |
31 | #ifdef Q_WS_X11 |
32 | #include <QtGui/QX11Info> |
33 | #include <X11/Xdefs.h> |
34 | #endif |
35 | |
36 | //! helper class |
37 | /*! contains utility functions used at multiple places in oxygen style */ |
38 | namespace Oxygen |
39 | { |
40 | |
41 | enum HoleOption |
42 | { |
43 | HoleFocus = 0x1, |
44 | HoleHover = 0x2, |
45 | HoleOutline = 0x4, |
46 | HoleContrast = 0x8 |
47 | }; |
48 | |
49 | Q_DECLARE_FLAGS(HoleOptions, HoleOption) |
50 | |
51 | class StyleHelper : public Helper |
52 | { |
53 | public: |
54 | |
55 | //! constructor |
56 | explicit StyleHelper( const QByteArray &componentName ); |
57 | |
58 | //! destructor |
59 | virtual ~StyleHelper() {} |
60 | |
61 | //! dynamically allocated debug area |
62 | int debugArea( void ) const |
63 | { return _debugArea; } |
64 | |
65 | //! clear cache |
66 | virtual void invalidateCaches(); |
67 | |
68 | //! update maximum cache size |
69 | virtual void setMaxCacheSize( int ); |
70 | |
71 | //! background gradient |
72 | virtual void setUseBackgroundGradient( bool value ) |
73 | { _useBackgroundGradient = value; } |
74 | |
75 | //! render window background using a given color as a reference |
76 | /*! |
77 | For the widget style, both the gradient and the background pixmap are rendered in the same method. |
78 | All the actual rendering is performed by the base class |
79 | */ |
80 | using Helper::renderWindowBackground; |
81 | virtual void renderWindowBackground( QPainter*, const QRect&, const QWidget*, const QColor&, int y_shift=-23, int gradientHeight = 20 ); |
82 | |
83 | //! set background gradient hint to widget |
84 | virtual void setHasBackgroundGradient( WId, bool ) const; |
85 | |
86 | // render menu background |
87 | void ( QPainter* p, const QRect& clipRect, const QWidget* widget, const QPalette& pal ) |
88 | { renderMenuBackground( p, clipRect, widget, pal.color( widget->window()->backgroundRole() ) ); } |
89 | |
90 | // render menu background |
91 | void ( QPainter*, const QRect&, const QWidget*, const QColor& ); |
92 | |
93 | //! returns menu background color matching position in a given menu widget |
94 | virtual const QColor& ( const QColor& color, const QWidget* w, const QPoint& point ) |
95 | { |
96 | if( !( w && w->window() ) || checkAutoFillBackground( w ) ) return color; |
97 | else return menuBackgroundColor( color, w->window()->height(), w->mapTo( w->window(), point ).y() ); |
98 | } |
99 | |
100 | //! returns menu background color matching position in a menu widget of given height |
101 | virtual const QColor& ( const QColor& color, int height, int y ) |
102 | { return backgroundColor( color, qMin( qreal( 1.0 ), qreal( y )/qMin( 200, 3*height/4 ) ) ); } |
103 | |
104 | //! color |
105 | inline const QColor& calcMidColor( const QColor& color ); |
106 | |
107 | //! merge active and inactive palettes based on ratio, for smooth enable state change transition |
108 | QPalette mergePalettes( const QPalette&, qreal ratio ) const; |
109 | |
110 | //! overloaded window decoration buttons for MDI windows |
111 | virtual QPixmap dockWidgetButton( const QColor& color, bool pressed, int size = 21 ); |
112 | |
113 | //! round corners( used for Menus, combobox drop-down, detached toolbars and dockwidgets |
114 | TileSet *roundCorner( const QColor&, int size = 5 ); |
115 | |
116 | //! groupbox background |
117 | TileSet *slope( const QColor&, qreal shade, int size = 7 ); |
118 | |
119 | //!@name slabs |
120 | //@{ |
121 | |
122 | //! progressbar |
123 | TileSet *progressBarIndicator( const QPalette&, int ); |
124 | |
125 | //! dial |
126 | QPixmap dialSlab( const QColor& color, qreal shade, int size = 7 ) |
127 | { return dialSlab( color, QColor(), shade, size ); } |
128 | |
129 | //! dial |
130 | QPixmap dialSlab( const QColor&, const QColor&, qreal shade, int size = 7 ); |
131 | |
132 | // round slabs |
133 | QPixmap roundSlab( const QColor& color, qreal shade, int size = 7 ) |
134 | { return roundSlab( color, QColor(), shade, size ); } |
135 | |
136 | // round slab |
137 | QPixmap roundSlab( const QColor&, const QColor& glow, qreal shade, int size = 7 ); |
138 | |
139 | //! slider slab |
140 | QPixmap sliderSlab( const QColor&, const QColor& glow, bool sunken, qreal shade, int size = 7 ); |
141 | |
142 | //@} |
143 | |
144 | //!@name holes |
145 | //@{ |
146 | |
147 | void fillHole( QPainter&, const QRect&, int size = 7 ) const; |
148 | |
149 | //! generic hole |
150 | void renderHole( QPainter *p, const QColor& color, const QRect &r, |
151 | HoleOptions options = 0, |
152 | TileSet::Tiles tiles = TileSet::Ring ) |
153 | { renderHole( p, color, r, options, -1, Oxygen::AnimationNone, tiles ); } |
154 | |
155 | //! generic hole (with animated glow) |
156 | void renderHole( |
157 | QPainter*, const QColor&, const QRect &r, |
158 | HoleOptions, |
159 | qreal opacity, Oxygen::AnimationMode animationMode, |
160 | TileSet::Tiles = TileSet::Ring ); |
161 | |
162 | TileSet *holeFlat( const QColor&, qreal shade, bool fill = true, int size = 7 ); |
163 | |
164 | //! scrollbar hole |
165 | TileSet *scrollHole( const QColor&, Qt::Orientation orientation, bool smallShadow = false ); |
166 | |
167 | //! scrollbar handle |
168 | TileSet *scrollHandle( const QColor&, const QColor&, int size = 7 ); |
169 | |
170 | //@} |
171 | |
172 | //! scrollbar groove |
173 | TileSet *groove( const QColor&, int size = 7 ); |
174 | |
175 | //! focus rect for flat toolbuttons |
176 | TileSet *slitFocused( const QColor& ); |
177 | |
178 | //! dock frame |
179 | TileSet *dockFrame( const QColor&, const QColor& ); |
180 | |
181 | //! selection |
182 | TileSet *selection( const QColor&, int height, bool custom ); |
183 | |
184 | //! inverse glow |
185 | /*! this method must be public because it is used directly by OxygenStyle to draw dials */ |
186 | void drawInverseGlow( QPainter&, const QColor&, int pad, int size, int rsize ) const; |
187 | |
188 | //!@name utility functions |
189 | |
190 | //! returns true if compositing is active |
191 | bool compositingActive( void ) const; |
192 | |
193 | //! returns true if a given widget supports alpha channel |
194 | inline bool hasAlphaChannel( const QWidget* ) const; |
195 | |
196 | //! returns true if given widget will get a decoration |
197 | bool hasDecoration( const QWidget* ) const; |
198 | |
199 | //@} |
200 | |
201 | protected: |
202 | |
203 | //!@name holes |
204 | //@{ |
205 | |
206 | //! holes |
207 | TileSet *hole( const QColor& color, int size = 7, HoleOptions options = 0 ) |
208 | { return hole( color, QColor(), size, options ); } |
209 | |
210 | //! holes |
211 | TileSet *hole( const QColor&, const QColor& glow, int size = 7, HoleOptions = 0 ); |
212 | |
213 | //@} |
214 | |
215 | // round slabs |
216 | void drawRoundSlab( QPainter&, const QColor&, qreal ); |
217 | |
218 | // slider slabs |
219 | void drawSliderSlab( QPainter&, const QColor&, bool sunken, qreal ); |
220 | |
221 | private: |
222 | |
223 | //! dynamically allocated debug area |
224 | int _debugArea; |
225 | |
226 | //! background grandient |
227 | bool _useBackgroundGradient; |
228 | |
229 | Cache<QPixmap> _dialSlabCache; |
230 | Cache<QPixmap> _roundSlabCache; |
231 | Cache<QPixmap> _sliderSlabCache; |
232 | Cache<TileSet> _holeCache; |
233 | Cache<TileSet> _scrollHandleCache; |
234 | |
235 | //! mid color cache |
236 | ColorCache _midColorCache; |
237 | |
238 | //! dock button cache |
239 | PixmapCache _dockWidgetButtonCache; |
240 | |
241 | typedef BaseCache<TileSet> TileSetCache; |
242 | TileSetCache _cornerCache; |
243 | TileSetCache _holeFlatCache; |
244 | TileSetCache _slopeCache; |
245 | TileSetCache _grooveCache; |
246 | TileSetCache _slitCache; |
247 | TileSetCache _dockFrameCache; |
248 | TileSetCache _scrollHoleCache; |
249 | TileSetCache _selectionCache; |
250 | TileSetCache _progressBarCache; |
251 | |
252 | #ifdef Q_WS_X11 |
253 | |
254 | //! background gradient hint atom |
255 | Atom _compositingManagerAtom; |
256 | |
257 | #endif |
258 | |
259 | }; |
260 | |
261 | //____________________________________________________________________ |
262 | const QColor& StyleHelper::calcMidColor( const QColor& color ) |
263 | { |
264 | const quint64 key( color.rgba() ); |
265 | QColor* out( _midColorCache.object( key ) ); |
266 | if( !out ) |
267 | { |
268 | out = new QColor( KColorScheme::shade( color, KColorScheme::MidShade, _contrast - 1.0 ) ); |
269 | _midColorCache.insert( key, out ); |
270 | } |
271 | |
272 | return *out; |
273 | } |
274 | |
275 | //____________________________________________________________________ |
276 | bool StyleHelper::hasAlphaChannel( const QWidget* widget ) const |
277 | { |
278 | |
279 | #ifdef Q_WS_X11 |
280 | if( compositingActive() ) |
281 | { |
282 | |
283 | if( widget ) return widget->x11Info().depth() == 32; |
284 | else return QX11Info().appDepth() == 32; |
285 | |
286 | } else return false; |
287 | |
288 | #else |
289 | return compositingActive(); |
290 | #endif |
291 | |
292 | } |
293 | |
294 | } |
295 | #endif |
296 | |