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
);
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
)),
41 double y
= KColorUtils::luma(color
);
42 if (y
> KColorUtils::luma(light
)) {
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
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
)
76 QLinearGradient
gradient(0, y1
, x
, y2
);
77 gradient
.setColorAt(0.0, color
);
78 gradient
.setColorAt(1.0, mid
);
83 QLinearGradient
OxygenScrollbar::shineGradient(double width
, Qt::Orientation orient
) const
85 double x
= 0.0, y1
= -width
, y2
= -width
;
86 if (orient
== Qt::Vertical
)
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
);
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
) {
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));
122 QLinearGradient
OxygenScrollbar::dimGradient(Qt::Orientation orient
) const
125 if (orient
== Qt::Vertical
)
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));
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
);
145 p
.setRenderHint(QPainter::Antialiasing
);
147 p
.setWindow(0, 0, int(w
), int(h
));
149 QRectF
rect(0, 0, w
, h
);
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
);
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
);
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
);
174 p
.setCompositionMode(QPainter::CompositionMode_DestinationOut
);
175 p
.setBrush(Qt::black
);
176 p
.drawRoundRect(rect
.adjusted(1, 2.5, -1, -1.4), rx
, ry
);
182 TileSet
* OxygenScrollbar::vertical(int size
, int width
, int offset
) const
186 double w
= 12.0 * double(width
)/double(s
*2);
187 double o
= -12.0 * double(offset
) / double(size
);
190 QPixmap
pixmap(width
, length
);
191 pixmap
.fill(Qt::transparent
);
194 p
.setRenderHint(QPainter::Antialiasing
);
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
203 p
.setBrush(baseGradient(w
, Qt::Vertical
));
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);
212 p
.setBrush(shimmerGradient(o
, Qt::Vertical
));
216 p
.setBrush(dimGradient(Qt::Vertical
));
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);
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
235 double h
= 12.0 * double(width
)/double(s
*2);
236 double o
= -12.0 * double(offset
) / double(size
);
239 QPixmap
pixmap(length
, width
);
240 pixmap
.fill(Qt::transparent
);
243 p
.setRenderHint(QPainter::Antialiasing
);
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
252 p
.setBrush(baseGradient(h
, Qt::Horizontal
));
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);
261 p
.setBrush(shimmerGradient(o
, Qt::Horizontal
));
265 p
.setBrush(dimGradient(Qt::Horizontal
));
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);