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