1#ifndef oxygen_helper_h
2#define oxygen_helper_h
3
4/*
5 * Copyright 2009-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 * Copyright 2007 Fredrik Höglund <fredrik@kde.org>
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License version 2 as published by the Free Software Foundation.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26#include "oxygentileset.h"
27
28#include <KSharedConfig>
29#include <KComponentData>
30#include <KColorScheme>
31
32#include <QtGui/QColor>
33#include <QtGui/QPixmap>
34#include <QtGui/QWidget>
35#include <QtGui/QLinearGradient>
36#include <QtCore/QCache>
37
38#ifdef Q_WS_X11
39#include <X11/Xdefs.h>
40#endif
41
42namespace Oxygen
43{
44
45 template<typename T> class BaseCache: public QCache<quint64, T>
46 {
47
48 public:
49
50 //! constructor
51 BaseCache( int maxCost ):
52 QCache<quint64, T>( maxCost ),
53 _enabled( true )
54 {}
55
56 //! constructor
57 explicit BaseCache( void ):
58 _enabled( true )
59 {}
60
61 //! destructor
62 ~BaseCache( void )
63 {}
64
65 //! enable
66 void setEnabled( bool value )
67 { _enabled = value; }
68
69 //! enable state
70 bool enabled( void ) const
71 { return _enabled; }
72
73 //! access
74 T* object( const quint64& key )
75 { return _enabled ? QCache<quint64, T>::object( key ) : 0; }
76
77 //! max cost
78 void setMaxCost( int cost )
79 {
80 if( cost <= 0 ) {
81
82 QCache<quint64, T>::clear();
83 QCache<quint64, T>::setMaxCost( 1 );
84 setEnabled( false );
85
86 } else {
87
88 setEnabled( true );
89 QCache<quint64, T>::setMaxCost( cost );
90
91 }
92 }
93
94 private:
95
96 //! enable flag
97 bool _enabled;
98
99 };
100
101 template<typename T> class Cache
102 {
103
104 public:
105
106 //! constructor
107 Cache()
108 {}
109
110 //! destructor
111 ~Cache()
112 {}
113
114 //! return cache matching a given key
115 //typedef QCache<quint64, T> Value;
116 typedef BaseCache<T> Value;
117 Value* get( const QColor& color )
118 {
119 const quint64 key = ( color.isValid() ? color.rgba():0 );
120 Value* cache = data_.object( key );
121
122 if ( !cache )
123 {
124 cache = new Value( data_.maxCost() );
125 data_.insert( key, cache );
126 }
127
128 return cache;
129 }
130
131 //! clear
132 void clear( void )
133 { data_.clear(); }
134
135 //! max cache size
136 void setMaxCacheSize( int value )
137 {
138 data_.setMaxCost( value );
139 foreach( quint64 key, data_.keys() )
140 { data_.object( key )->setMaxCost( value ); }
141 }
142
143 private:
144
145 //! data
146 BaseCache<Value> data_;
147
148 };
149
150 //! oxygen style helper class.
151 /*! contains utility functions used at multiple places in both oxygen style and oxygen window decoration */
152 class OXYGEN_EXPORT Helper
153 {
154 public:
155
156 //! constructor
157 explicit Helper( const QByteArray& componentName );
158
159 //! destructor
160 virtual ~Helper()
161 {}
162
163 //! reload configuration
164 virtual void reloadConfig();
165
166 //! pointer to shared config
167 KSharedConfigPtr config() const;
168
169 //! reset all caches
170 virtual void invalidateCaches();
171
172 //! update maximum cache size
173 virtual void setMaxCacheSize( int );
174
175 //!@name window background gradients
176 //@{
177 /*!
178 \par y_shift: shift the background gradient upwards, to fit with the windec
179 \par gradientHeight: the height of the generated gradient.
180 for different heights, the gradient is translated so that it is always at the same position from the bottom
181 */
182 virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QPalette& pal, int y_shift=-23, int gradientHeight = 20 )
183 { renderWindowBackground( p, clipRect, widget, pal.color( widget->window()->backgroundRole() ), y_shift, gradientHeight ); }
184
185 /*!
186 y_shift: shift the background gradient upwards, to fit with the windec
187 gradientHeight: the height of the generated gradient.
188 for different heights, the gradient is translated so that it is always at the same position from the bottom
189 */
190 virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, const QPalette& pal, int y_shift=-23, int gradientHeight = 20 )
191 { renderWindowBackground( p, clipRect, widget, window, pal.color( window->backgroundRole() ), y_shift, gradientHeight ); }
192
193 //! render window background using a given color as a reference
194 virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QColor& color, int y_shift=-23, int gradientHeight = 20 )
195 { renderWindowBackground( p, clipRect, widget, widget->window(), color, y_shift, gradientHeight ); }
196
197 //! render window background using a given color as a reference
198 virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, const QColor& color, int y_shift=-23, int gradientHeight = 20 );
199
200 //! background pixmap
201 bool hasBackgroundPixmap( void ) const
202 { return !_backgroundPixmap.isNull(); }
203
204 //! background pixmap
205 void setBackgroundPixmap( const QPixmap& pixmap )
206 { _backgroundPixmap = pixmap; }
207
208 //! offset
209 void setBackgroundPixmapOffset( const QPoint& offset )
210 { _backgroundPixmapOffset = offset; }
211
212 //! render window background using a given color as a reference
213 virtual void renderBackgroundPixmap( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, int y_shift=-23, int gradientHeight = 20 );
214
215 //@}
216
217 //! dots
218 void renderDot( QPainter*, const QPoint&, const QColor& );
219
220 //! returns true for too 'dark' colors
221 bool lowThreshold( const QColor& color );
222
223 //! returns true for too 'light' colors
224 bool highThreshold( const QColor& color );
225
226 //! add alpha channel multiplier to color
227 static QColor alphaColor( QColor color, qreal alpha );
228
229 //! calculated light color from argument
230 virtual const QColor& calcLightColor( const QColor& color );
231
232 //! calculated dark color from argument
233 virtual const QColor& calcDarkColor( const QColor& color );
234
235 //! calculated shadow color from argument
236 virtual const QColor& calcShadowColor( const QColor& color );
237
238 //! returns menu background color matching position in a given top level widget
239 virtual const QColor& backgroundColor( const QColor& color, const QWidget* w, const QPoint& point )
240 {
241 if( !( w && w->window() ) || checkAutoFillBackground( w ) ) return color;
242 else return backgroundColor( color, w->window()->height(), w->mapTo( w->window(), point ).y() );
243 }
244
245 //! returns menu background color matching position in a top level widget of given height
246 virtual const QColor& backgroundColor( const QColor& color, int height, int y )
247 { return backgroundColor( color, qMin( qreal( 1.0 ), qreal( y )/qMin( 300, 3*height/4 ) ) ); }
248
249 //! color used for background radial gradient
250 virtual const QColor& backgroundRadialColor( const QColor& color );
251
252 //! color used at the top of window background
253 virtual const QColor& backgroundTopColor( const QColor& color );
254
255 //! color used at the bottom of window background
256 virtual const QColor& backgroundBottomColor( const QColor& color );
257
258 //! vertical gradient for window background
259 virtual QPixmap verticalGradient( const QColor& color, int height, int offset = 0 );
260
261 //! radial gradient for window background
262 virtual QPixmap radialGradient( const QColor& color, int width, int height = 20 );
263
264 //! merge background and front color for check marks, arrows, etc. using _contrast
265 virtual const QColor& decoColor( const QColor& background, const QColor& color );
266
267 //! returns a region matching given rect, with rounded corners, based on the multipliers
268 /*! setting any of the multipliers to zero will result in no corners shown on the corresponding side */
269 virtual QRegion roundedMask( const QRect&, int left = 1, int right = 1, int top = 1, int bottom = 1 ) const;
270
271 //! draw frame that mimics some sort of shadows around a panel
272 /*! it is used for menus, detached dock panels and toolbar, as well as window decoration when compositing is disabled */
273 virtual void drawFloatFrame(
274 QPainter* p, const QRect r, const QColor& color,
275 bool drawUglyShadow=true, bool isActive=false,
276 const QColor& frameColor=QColor(),
277 TileSet::Tiles tiles = TileSet::Ring
278 );
279
280 //! draw dividing line
281 virtual void drawSeparator( QPainter*, const QRect&, const QColor&, Qt::Orientation );
282
283 //! default slab
284 virtual TileSet* slab( const QColor& color, qreal shade, int size = 7 )
285 { return slab( color, QColor(), shade, size ); }
286
287 //! default slab (with glow)
288 virtual TileSet* slab( const QColor&, const QColor& glow, qreal shade, int size = 7 );
289
290 //! sunken slab
291 virtual TileSet *slabSunken( const QColor&, int size = 7 );
292
293 //! fill a slab of given size with brush set on painter
294 void fillSlab( QPainter&, const QRect&, int size = 7 ) const;
295
296 //! linear gradient used to fill buttons
297 virtual void fillButtonSlab( QPainter&, const QRect&, const QColor&, bool sunken );
298
299 //! inverse (inner-hole) shadow
300 /*! this method must be public because it is used directly by OxygenStyle to draw dials */
301 void drawInverseShadow( QPainter&, const QColor&, int pad, int size, qreal fuzz ) const;
302
303 //! focus brush
304 const KStatefulBrush& viewFocusBrush( void ) const
305 { return _viewFocusBrush; }
306
307 //! hover brush
308 const KStatefulBrush& viewHoverBrush( void ) const
309 { return _viewHoverBrush; }
310
311 //! negative text brush ( used for close button hover )
312 const KStatefulBrush& viewNegativeTextBrush( void ) const
313 { return _viewNegativeTextBrush; }
314
315 /*!
316 returns first widget in parent chain that sets autoFillBackground to true,
317 or NULL if none
318 */
319 const QWidget* checkAutoFillBackground( const QWidget* ) const;
320
321 //!@name background gradient XProperty
322 //@{
323
324 //! set background gradient hint to widget
325 virtual void setHasBackgroundGradient( WId, bool ) const;
326
327 //! true if background gradient hint is set
328 virtual bool hasBackgroundGradient( WId ) const;
329
330 //! set background pixmap hint to widget
331 virtual void setHasBackgroundPixmap( WId, bool ) const;
332
333 //! true if background pixmap hint is set
334 virtual bool hasBackgroundPixmap( WId ) const;
335
336 //@}
337
338 protected:
339
340 //! return color key for a given color, properly accounting for invalid colors
341 quint64 colorKey( const QColor& color ) const
342 { return color.isValid() ? color.rgba():0; }
343
344 //! generic slab painting (to be stored in tilesets)
345 virtual void drawSlab( QPainter&, const QColor&, qreal shade );
346
347 //! generic outer shadow (to be stored in tilesets)
348 virtual void drawShadow( QPainter&, const QColor&, int size );
349
350 //! generic outer glow (to be stored in tilesets)
351 virtual void drawOuterGlow( QPainter&, const QColor&, int size );
352
353 //! return background adjusted color matching relative vertical position in window
354 const QColor& backgroundColor( const QColor&, qreal ratio );
355
356 //!@name global configuration parameters
357 //@{
358
359 static const qreal _glowBias;
360 static const qreal _slabThickness;
361 static const qreal _shadowGain;
362 qreal _contrast;
363
364 //@}
365
366 //! shortcut to color caches
367 /*! it is made protected because it is also used in the style helper */
368 typedef BaseCache<QColor> ColorCache;
369
370 //! shortcut to pixmap cache
371 typedef BaseCache<QPixmap> PixmapCache;
372
373 private:
374
375 //!@name tileset caches
376 //!@{
377
378 //! slabs
379 Oxygen::Cache<TileSet> _slabCache;
380
381 //! sunken slabs
382 BaseCache<TileSet> _slabSunkenCache;
383
384 //@}
385
386 //!@name brushes
387 //@{
388 KStatefulBrush _viewFocusBrush;
389 KStatefulBrush _viewHoverBrush;
390 KStatefulBrush _viewNegativeTextBrush;
391 //@}
392
393 KComponentData _componentData;
394 KSharedConfigPtr _config;
395 qreal _bgcontrast;
396
397 //!@name color caches
398 //@{
399 ColorCache _decoColorCache;
400 ColorCache _lightColorCache;
401 ColorCache _darkColorCache;
402 ColorCache _shadowColorCache;
403 ColorCache _backgroundTopColorCache;
404 ColorCache _backgroundBottomColorCache;
405 ColorCache _backgroundRadialColorCache;
406 ColorCache _backgroundColorCache;
407 //@}
408
409 PixmapCache _backgroundCache;
410 PixmapCache _dotCache;
411
412 //! high threshold colors
413 typedef QMap<quint32, bool> ColorMap;
414 ColorMap _highThreshold;
415 ColorMap _lowThreshold;
416
417 //! background pixmap
418 QPixmap _backgroundPixmap;
419
420 //! background pixmap offsets
421 QPoint _backgroundPixmapOffset;
422
423 #ifdef Q_WS_X11
424
425 //! set value for given hint
426 void setHasHint( WId, Atom, bool ) const;
427
428 //! value for given hint
429 bool hasHint( WId, Atom ) const;
430
431 //! background gradient hint atom
432 Atom _backgroundGradientAtom;
433
434 //! background gradient hint atom
435 Atom _backgroundPixmapAtom;
436
437 #endif
438 };
439
440}
441
442#endif
443