File indexing completed on 2024-05-19 09:28:04
0001 #ifndef oxygen_style_helper_h 0002 #define oxygen_style_helper_h 0003 0004 /* 0005 * SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0006 * SPDX-FileCopyrightText: 2008 Long Huynh Huu <long.upcase@googlemail.com> 0007 * SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net> 0008 * SPDX-FileCopyrightText: 2007 Casper Boemann <cbr@boemann.dk> 0009 * 0010 * SPDX-License-Identifier: LGPL-2.0-only 0011 */ 0012 0013 #include "oxygen.h" 0014 #include "oxygenhelper.h" 0015 0016 #include <KWindowSystem> 0017 0018 #if OXYGEN_HAVE_X11 0019 #include <xcb/xcb.h> 0020 #endif 0021 0022 //* helper class 0023 /** contains utility functions used at multiple places in oxygen style */ 0024 namespace Oxygen 0025 { 0026 0027 class StyleHelper : public Helper 0028 { 0029 public: 0030 //* constructor 0031 explicit StyleHelper(KSharedConfigPtr config); 0032 0033 //* destructor 0034 //* clear cache 0035 void invalidateCaches() override; 0036 0037 //* update maximum cache size 0038 void setMaxCacheSize(int) override; 0039 0040 //* background gradient 0041 void setUseBackgroundGradient(bool value) 0042 { 0043 _useBackgroundGradient = value; 0044 } 0045 0046 //* render window background using a given color as a reference 0047 /** 0048 For the widget style, both the gradient and the background pixmap are rendered in the same method. 0049 All the actual rendering is performed by the base class 0050 */ 0051 using Helper::renderWindowBackground; 0052 void renderWindowBackground(QPainter *, const QRect &, const QWidget *, const QColor &, int y_shift = -23) override; 0053 0054 //* set background gradient hint to widget 0055 void setHasBackgroundGradient(WId, bool) const override; 0056 0057 // render menu background 0058 void renderMenuBackground(QPainter *p, const QRect &clipRect, const QWidget *widget, const QPalette &pal) 0059 { 0060 renderMenuBackground(p, clipRect, widget, pal.color(widget->window()->backgroundRole())); 0061 } 0062 0063 // render menu background 0064 void renderMenuBackground(QPainter *, const QRect &, const QWidget *, const QColor &); 0065 0066 //*@name color utilities 0067 //@{ 0068 0069 //* glow color for buttons (mouse-over takes precedence over focus) 0070 QColor buttonGlowColor(const QPalette &palette, StyleOptions options, qreal opacity, AnimationMode mode) const 0071 { 0072 return buttonGlowColor(palette.currentColorGroup(), options, opacity, mode); 0073 } 0074 0075 //* glow color for frames (focus takes precedence over mouse-over) 0076 QColor frameGlowColor(const QPalette &palette, StyleOptions options, qreal opacity, AnimationMode mode) const 0077 { 0078 return frameGlowColor(palette.currentColorGroup(), options, opacity, mode); 0079 } 0080 0081 //* glow color for arrows (mouse-over takes precedence over focus) 0082 QColor arrowColor(const QPalette &palette, StyleOptions options, qreal opacity, AnimationMode mode) const; 0083 0084 //* glow color for buttons (mouse-over takes precedence over focus) 0085 QColor buttonGlowColor(QPalette::ColorGroup, StyleOptions, qreal, AnimationMode) const; 0086 0087 //* glow color for frames (focus takes precedence over mouse-over) 0088 QColor frameGlowColor(QPalette::ColorGroup, StyleOptions, qreal, AnimationMode) const; 0089 0090 //* returns menu background color matching position in a given menu widget 0091 QColor menuBackgroundColor(const QColor &color, const QWidget *w, const QPoint &point) 0092 { 0093 if (!(w && w->window()) || checkAutoFillBackground(w)) 0094 return color; 0095 else 0096 return menuBackgroundColor(color, w->window()->height(), w->mapTo(w->window(), point).y()); 0097 } 0098 0099 //* returns menu background color matching position in a menu widget of given height 0100 QColor menuBackgroundColor(const QColor &color, int height, int y) 0101 { 0102 return backgroundColor(color, qMin(qreal(1.0), qreal(y) / qMin(200, 3 * height / 4))); 0103 } 0104 0105 //* color 0106 inline QColor calcMidColor(const QColor &color); 0107 0108 //* merge active and inactive palettes based on ratio, for smooth enable state change transition 0109 QPalette disabledPalette(const QPalette &, qreal ratio) const; 0110 0111 //@} 0112 0113 //* overloaded window decoration buttons for MDI windows 0114 QPixmap dockWidgetButton(const QColor &color, bool pressed, int size = 21); 0115 0116 //* round corners( used for Menus, combobox drop-down, detached toolbars and dockwidgets 0117 TileSet roundCorner(const QColor &, int size = 5); 0118 0119 //* groupbox background 0120 TileSet slope(const QColor &, qreal shade, int size = TileSet::DefaultSize); 0121 0122 //*@name slabs 0123 //@{ 0124 0125 //* inverse (inner-hole) shadow 0126 /** this method must be public because it is used directly by OxygenStyle to draw dials */ 0127 void drawInverseShadow(QPainter &, const QColor &, int pad, int size, qreal fuzz) const; 0128 0129 //* fill a slab of given size with brush set on painter 0130 void fillSlab(QPainter &, const QRect &, int size = TileSet::DefaultSize) const; 0131 0132 //* linear gradient used to fill buttons 0133 void fillButtonSlab(QPainter &, const QRect &, const QColor &, bool sunken); 0134 0135 //* default slab 0136 TileSet slab(const QColor &color, qreal shade, int size = TileSet::DefaultSize) 0137 { 0138 return slab(color, QColor(), shade, size); 0139 } 0140 0141 //* default slab (with glow) 0142 TileSet slab(const QColor &, const QColor &glow, qreal shade, int size = TileSet::DefaultSize); 0143 0144 //* sunken slab 0145 TileSet slabSunken(const QColor &, int size = TileSet::DefaultSize); 0146 0147 //* progressbar 0148 TileSet progressBarIndicator(const QPalette &, int); 0149 0150 //* dial 0151 QPixmap dialSlab(const QColor &color, qreal shade, int size = TileSet::DefaultSize) 0152 { 0153 return dialSlab(color, QColor(), shade, size); 0154 } 0155 0156 //* dial 0157 QPixmap dialSlab(const QColor &, const QColor &, qreal shade, int size = TileSet::DefaultSize); 0158 0159 // round slabs 0160 QPixmap roundSlab(const QColor &color, qreal shade, int size = TileSet::DefaultSize) 0161 { 0162 return roundSlab(color, QColor(), shade, size); 0163 } 0164 0165 // round slab 0166 QPixmap roundSlab(const QColor &, const QColor &glow, qreal shade, int size = TileSet::DefaultSize); 0167 0168 //* slider slab 0169 QPixmap sliderSlab(const QColor &, const QColor &glow, bool sunken, qreal shade, int size = TileSet::DefaultSize); 0170 0171 //@} 0172 0173 //* debug frame 0174 void renderDebugFrame(QPainter *, const QRect &) const; 0175 0176 //*@name holes 0177 //@{ 0178 0179 void fillHole(QPainter &, const QRect &, int offset = 2) const; 0180 0181 //* generic hole 0182 void renderHole(QPainter *painter, const QColor &color, const QRect &rect, StyleOptions options = {}, TileSet::Tiles tiles = TileSet::Ring) 0183 { 0184 renderHole(painter, color, rect, options, -1, Oxygen::AnimationNone, tiles); 0185 } 0186 0187 //* generic hole (with animated glow) 0188 void renderHole(QPainter *, const QColor &, const QRect &, StyleOptions, qreal, Oxygen::AnimationMode, TileSet::Tiles = TileSet::Ring); 0189 0190 TileSet holeFlat(const QColor &, qreal shade, bool fill = true, int size = TileSet::DefaultSize); 0191 0192 //* scrollbar hole 0193 TileSet scrollHole(const QColor &, Qt::Orientation orientation, bool smallShadow = false); 0194 0195 //* scrollbar handle 0196 TileSet scrollHandle(const QColor &, const QColor &, int size = TileSet::DefaultSize); 0197 0198 //@} 0199 0200 //* focus rect for flat toolbuttons 0201 TileSet slitFocused(const QColor &); 0202 0203 //* dock frame 0204 TileSet dockFrame(const QColor &, const QColor &); 0205 0206 //* selection 0207 TileSet selection(const QColor &, int height, bool custom); 0208 0209 //* inverse glow 0210 /** this method must be public because it is used directly by OxygenStyle to draw dials */ 0211 void drawInverseGlow(QPainter &, const QColor &, int pad, int size, int rsize) const; 0212 0213 //*@name utility functions 0214 0215 //* returns true if compositing is active 0216 bool compositingActive(void) const; 0217 0218 //* returns true if a given widget supports alpha channel 0219 inline bool hasAlphaChannel(const QWidget *) const; 0220 0221 //* returns true if given widget will get a decoration 0222 bool hasDecoration(const QWidget *) const; 0223 0224 //@} 0225 0226 private: 0227 //*@name holes 0228 //@{ 0229 0230 //* holes 0231 TileSet hole(const QColor &color, int size = TileSet::DefaultSize, StyleOptions options = {}) 0232 { 0233 return hole(color, QColor(), size, options); 0234 } 0235 0236 //* holes 0237 TileSet hole(const QColor &, const QColor &glow, int size = TileSet::DefaultSize, StyleOptions = {}); 0238 0239 //@} 0240 0241 //* generic slab painting (to be stored in tilesets) 0242 void drawSlab(QPainter &, const QColor &, qreal shade); 0243 0244 // round slabs 0245 void drawRoundSlab(QPainter &, const QColor &, qreal); 0246 0247 // slider slabs 0248 void drawSliderSlab(QPainter &, const QColor &, bool sunken, qreal); 0249 0250 //* initialize 0251 void init(void); 0252 0253 //* background grandient 0254 bool _useBackgroundGradient; 0255 0256 Cache<QPixmap> _dialSlabCache; 0257 Cache<QPixmap> _roundSlabCache; 0258 Cache<QPixmap> _sliderSlabCache; 0259 Cache<TileSet> _holeCache; 0260 Cache<TileSet> _scrollHandleCache; 0261 Cache<TileSet> _slabCache; 0262 0263 //* mid color cache 0264 ColorCache _midColorCache; 0265 0266 //* dock button cache 0267 PixmapCache _dockWidgetButtonCache; 0268 0269 using TileSetCache = BaseCache<TileSet>; 0270 TileSetCache _slabSunkenCache; 0271 TileSetCache _cornerCache; 0272 TileSetCache _holeFlatCache; 0273 TileSetCache _slopeCache; 0274 TileSetCache _slitCache; 0275 TileSetCache _dockFrameCache; 0276 TileSetCache _scrollHoleCache; 0277 TileSetCache _selectionCache; 0278 TileSetCache _progressBarCache; 0279 0280 #if OXYGEN_HAVE_X11 0281 0282 //* atom used for compositing manager 0283 xcb_atom_t _compositingManagerAtom; 0284 0285 #endif 0286 }; 0287 0288 //____________________________________________________________________ 0289 QColor StyleHelper::calcMidColor(const QColor &color) 0290 { 0291 const quint64 key(color.rgba()); 0292 if (QColor *cachedColor = _midColorCache.object(key)) { 0293 return *cachedColor; 0294 } 0295 0296 QColor out = KColorScheme::shade(color, KColorScheme::MidShade, _contrast - 1.0); 0297 _midColorCache.insert(key, new QColor(out)); 0298 0299 return out; 0300 } 0301 0302 //____________________________________________________________________ 0303 bool StyleHelper::hasAlphaChannel(const QWidget *widget) const 0304 { 0305 return compositingActive() && widget && widget->testAttribute(Qt::WA_TranslucentBackground); 0306 } 0307 } 0308 #endif