Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / runtime / kstyles / oxygen / elements / scrollbar.cpp
blob56c2837e5a0a5248c1069eb3d08155efb74791f0
1 /*
2 * Copyright 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
3 * Copyright 2007 Casper Boemann <cbr@boemann.dk>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License version 2 as published by the Free Software Foundation.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
20 #include "scrollbar.h"
22 #include <KColorUtils>
23 #include <KColorScheme>
25 #include <QtGui/QPainter>
26 #include <QtGui/QLinearGradient>
28 inline QColor alphaColor(QColor color, double alpha)
30 color.setAlphaF(alpha);
31 return color;
34 OxygenScrollbar::OxygenScrollbar(const QColor &c, double contrast) : color(c),
35 light(KColorScheme::shade(c, KColorScheme::LightShade, contrast - 0.5)),
36 mid(KColorScheme::shade(c, KColorScheme::MidShade, contrast)),
37 dark(KColorScheme::shade(c, KColorScheme::DarkShade, contrast - 0.5)),
38 shadow(KColorScheme::shade(c, KColorScheme::ShadowShade, contrast)),
39 highlight(Qt::white)
41 double y = KColorUtils::luma(color);
42 if (y > KColorUtils::luma(light)) {
43 light = Qt::white;
44 dark = KColorScheme::shade(c, KColorScheme::DarkShade, contrast);
48 void OxygenScrollbar::mask(QPainter &p, const QRectF &rect) const
50 double w = rect.width();
51 double h = rect.height();
53 // drawRoundRect is too bloody hard to control to get the corners perfectly
54 // square (i.e. circles not ellipses), so draw the mask in parts with real
55 // circles
56 p.setBrush(Qt::black); // color doesn't matter
57 p.drawRect(rect.adjusted(7,0,-7,0));
58 p.drawRect(rect.adjusted(0,7,0,-7));
59 p.drawEllipse(QRectF(0,0,14,14));
60 p.drawEllipse(QRectF(w-14,0,14,14));
61 p.drawEllipse(QRectF(0,h-14,14,14));
62 p.drawEllipse(QRectF(w-14,h-14,14,14));
64 // never draw outside the mask
65 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
68 QLinearGradient OxygenScrollbar::baseGradient(double width, Qt::Orientation orient) const
70 double x = 0.0, y1 = width, y2 = width;
71 if (orient == Qt::Vertical)
72 x = width * 0.6;
73 else
74 y2 = width * 0.4;
76 QLinearGradient gradient(0, y1, x, y2);
77 gradient.setColorAt(0.0, color);
78 gradient.setColorAt(1.0, mid);
80 return gradient;
83 QLinearGradient OxygenScrollbar::shineGradient(double width, Qt::Orientation orient) const
85 double x = 0.0, y1 = -width, y2 = -width;
86 if (orient == Qt::Vertical)
87 x = width * 2.0;
88 else
89 y1 = width;
91 QLinearGradient gradient(0, y1, x, y2);
92 gradient.setColorAt(0.0, light);
93 gradient.setColorAt(0.5, alphaColor(color, 0.5));
94 gradient.setColorAt(1.0, color);
96 return gradient;
99 QLinearGradient OxygenScrollbar::shimmerGradient(double offset, Qt::Orientation orient) const
101 double x = 0.0, y = 0.0, xo = 0.0, yo = 0.0;
102 if (orient == Qt::Vertical) {
103 yo = offset;
104 x = 14.4/2.0;
105 y = 43.2/2.0;
106 } else {
107 xo = offset;
108 x = 43.2/2.0;
109 y = -14.4/2.0;
112 // should tile every 48 units, with 1:3 slope
113 QLinearGradient gradient(xo, yo, x+xo, y+yo);
114 gradient.setSpread(QGradient::ReflectSpread);
115 gradient.setColorAt(0.0, alphaColor(dark, 0.40));
116 gradient.setColorAt(0.6, alphaColor(dark, 0.10));
117 gradient.setColorAt(1.0, alphaColor(dark, 0.00));
119 return gradient;
122 QLinearGradient OxygenScrollbar::dimGradient(Qt::Orientation orient) const
124 int x = 0, y = 0;
125 if (orient == Qt::Vertical)
126 y = 3*22;
127 else
128 x = 3*22;
130 QLinearGradient gradient(0, 0, x, y);
131 gradient.setSpread(QGradient::ReflectSpread);
132 gradient.setColorAt(0.00, alphaColor(dark, 1.0));
133 gradient.setColorAt(0.19, alphaColor(dark, 0.3));
134 gradient.setColorAt(0.27, alphaColor(dark, 0.0));
136 return gradient;
139 QPixmap OxygenScrollbar::bevel(int width, int height, double w, double h, int rx, int ry) const
141 QPixmap pixmap(width, height);
142 pixmap.fill(Qt::transparent);
144 QPainter p(&pixmap);
145 p.setRenderHint(QPainter::Antialiasing);
146 p.setPen(Qt::NoPen);
147 p.setWindow(0, 0, int(w), int(h));
149 QRectF rect(0, 0, w, h);
151 // anti-highlight
152 QLinearGradient ahGradient(0, 0, 0, 8);
153 ahGradient.setColorAt(0.0, dark);
154 ahGradient.setColorAt(0.9, dark);
155 ahGradient.setColorAt(1.0, shadow);
156 p.setBrush(ahGradient);
157 p.drawRect(rect);
159 // anti-highlight mask
160 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
161 p.setBrush(Qt::black);
162 p.drawRoundRect(rect.adjusted(0, 1, 0, -1), rx, ry);
164 // bevel
165 QLinearGradient bevelGradient(0, 0, 0, 8);
166 bevelGradient.setColorAt(0.0, alphaColor(highlight, 0.4));
167 bevelGradient.setColorAt(0.6, alphaColor(highlight, 0.4));
168 bevelGradient.setColorAt(1.0, alphaColor(shadow, 0.8));
169 p.setBrush(bevelGradient);
170 p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
171 p.drawRect(rect);
173 // mask
174 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
175 p.setBrush(Qt::black);
176 p.drawRoundRect(rect.adjusted(1, 2.5, -1, -1.4), rx, ry);
178 p.end();
179 return pixmap;
182 TileSet* OxygenScrollbar::vertical(int size, int width, int offset) const
184 int s = size/2;
185 int length = s*22;
186 double w = 12.0 * double(width)/double(s*2);
187 double o = -12.0 * double(offset) / double(size);
188 const int h = 6*22;
190 QPixmap pixmap(width, length);
191 pixmap.fill(Qt::transparent);
193 QPainter p(&pixmap);
194 p.setRenderHint(QPainter::Antialiasing);
195 p.setPen(Qt::NoPen);
196 p.setWindow(0, 0, int(w), h);
197 QRectF rect(0, 0, w, h);
199 // mask; never draw outside this, hence mask() sets SourceAtop
200 mask(p, rect);
202 // base
203 p.setBrush(baseGradient(w, Qt::Vertical));
204 p.drawRect(rect);
206 // shine
207 p.setBrush(shineGradient(w, Qt::Vertical));
208 p.drawRoundRect(QRectF(w- int(w*0.45)-0.5, 0, int(w*0.45), h), 2000.0 / w, 12);
209 p.setClipping(false);
211 // shimmer
212 p.setBrush(shimmerGradient(o, Qt::Vertical));
213 p.drawRect(rect);
215 // dim edges
216 p.setBrush(dimGradient(Qt::Vertical));
217 p.drawRect(rect);
219 // highlight
220 p.setBrush(alphaColor(highlight, 0.2));
221 p.drawRoundRect(QRectF(w-3, 7, 1.5, h-14), 100, 5);
222 p.drawRoundRect(QRectF(1.5, 7, 1.5, h-14), 100, 5);
224 // bevel
225 p.setWindow(0, 0, width, length);
226 p.drawPixmap(0, 0, bevel(width, length, w, h, int(1400.0/w), 9));
228 return new TileSet(pixmap, 1, s*3, width-2, s*16);
231 TileSet* OxygenScrollbar::horizontal(int size, int width, int offset) const
233 int s = size/2;
234 int length = s*22;
235 double h = 12.0 * double(width)/double(s*2);
236 double o = -12.0 * double(offset) / double(size);
237 const int w = 6*22;
239 QPixmap pixmap(length, width);
240 pixmap.fill(Qt::transparent);
242 QPainter p(&pixmap);
243 p.setRenderHint(QPainter::Antialiasing);
244 p.setPen(Qt::NoPen);
245 p.setWindow(0, 0, w, int(h));
246 QRectF rect(0, 0, w, h);
248 // mask; never draw outside this, hence mask() sets SourceAtop
249 mask(p, rect);
251 // base
252 p.setBrush(baseGradient(h, Qt::Horizontal));
253 p.drawRect(rect);
255 // shine
256 p.setBrush(shineGradient(h, Qt::Horizontal));
257 p.drawRoundRect(QRectF(0, 0.5, w, int(h*0.45)), 12, 2000.0 / h);
258 p.setClipping(false);
260 // shimmer
261 p.setBrush(shimmerGradient(o, Qt::Horizontal));
262 p.drawRect(rect);
264 // dim edges
265 p.setBrush(dimGradient(Qt::Horizontal));
266 p.drawRect(rect);
268 // bevel
269 p.setWindow(0, 0, length, width);
270 p.drawPixmap(0, 0, bevel(length, width, w, h, 9, int(1400.0/h)));
272 return new TileSet(pixmap, s*3, 1, s*16, width-2);