Changeset View
Changeset View
Standalone View
Standalone View
kstyle/widgets/slider.cpp
- This file was added.
1 | #include "breezestyle.h" | ||||
---|---|---|---|---|---|
2 | | ||||
3 | namespace Breeze | ||||
4 | { | ||||
5 | QColor Helper::sliderOutlineColor(const QPalette &palette, bool mouseOver, bool hasFocus, qreal opacity, AnimationMode mode) const | ||||
6 | { | ||||
7 | QColor outline(KColorUtils::mix(palette.color(QPalette::Window), palette.color(QPalette::WindowText), 0.4)); | ||||
8 | | ||||
9 | // hover takes precedence over focus | ||||
10 | if (mode == AnimationHover) { | ||||
11 | const QColor hover(hoverColor(palette)); | ||||
12 | const QColor focus(focusColor(palette)); | ||||
13 | if (hasFocus) | ||||
14 | outline = KColorUtils::mix(focus, hover, opacity); | ||||
15 | else | ||||
16 | outline = KColorUtils::mix(outline, hover, opacity); | ||||
17 | | ||||
18 | } else if (mouseOver) { | ||||
19 | outline = hoverColor(palette); | ||||
20 | | ||||
21 | } else if (mode == AnimationFocus) { | ||||
22 | const QColor focus(focusColor(palette)); | ||||
23 | outline = KColorUtils::mix(outline, focus, opacity); | ||||
24 | | ||||
25 | } else if (hasFocus) { | ||||
26 | outline = focusColor(palette); | ||||
27 | } | ||||
28 | | ||||
29 | return outline; | ||||
30 | } | ||||
31 | | ||||
32 | //______________________________________________________________________________ | ||||
33 | void Helper::renderSliderGroove(QPainter *painter, const QRect &rect, const QColor &color) const | ||||
34 | { | ||||
35 | // setup painter | ||||
36 | painter->setRenderHint(QPainter::Antialiasing, true); | ||||
37 | | ||||
38 | const QRectF baseRect(rect); | ||||
39 | const qreal radius(0.5 * Metrics::Slider_GrooveThickness); | ||||
40 | | ||||
41 | // content | ||||
42 | if (color.isValid()) { | ||||
43 | painter->setPen(Qt::NoPen); | ||||
44 | painter->setBrush(color); | ||||
45 | painter->drawRoundedRect(baseRect, radius, radius); | ||||
46 | } | ||||
47 | } | ||||
48 | | ||||
49 | //______________________________________________________________________________ | ||||
50 | void Helper::renderSliderHandle(QPainter *painter, const QRect &rect, const QColor &color, const QColor &outline, const QColor &shadow, bool sunken) const | ||||
51 | { | ||||
52 | // setup painter | ||||
53 | painter->setRenderHint(QPainter::Antialiasing, true); | ||||
54 | | ||||
55 | // copy rect | ||||
56 | QRectF frameRect(rect); | ||||
57 | frameRect.adjust(1, 1, -1, -1); | ||||
58 | | ||||
59 | // shadow | ||||
60 | if (shadow.isValid() && !sunken) { | ||||
61 | painter->setPen(QPen(shadow, 2)); | ||||
62 | painter->setBrush(Qt::NoBrush); | ||||
63 | painter->drawEllipse(shadowRect(frameRect)); | ||||
64 | } | ||||
65 | | ||||
66 | // set pen | ||||
67 | if (outline.isValid()) { | ||||
68 | painter->setPen(outline); | ||||
69 | frameRect.adjust(0.5, 0.5, -0.5, -0.5); | ||||
70 | | ||||
71 | } else | ||||
72 | painter->setPen(Qt::NoPen); | ||||
73 | | ||||
74 | // set brush | ||||
75 | if (color.isValid()) | ||||
76 | painter->setBrush(color); | ||||
77 | else | ||||
78 | painter->setBrush(Qt::NoBrush); | ||||
79 | | ||||
80 | // render | ||||
81 | painter->drawEllipse(frameRect); | ||||
82 | } | ||||
83 | | ||||
84 | //___________________________________________________________________________________________________________________ | ||||
85 | QRect Style::sliderSubControlRect(const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const | ||||
86 | { | ||||
87 | // cast option and check | ||||
88 | const auto sliderOption(qstyleoption_cast<const QStyleOptionSlider *>(option)); | ||||
89 | if (!sliderOption) | ||||
90 | return ParentStyleClass::subControlRect(CC_Slider, option, subControl, widget); | ||||
91 | | ||||
92 | switch (subControl) { | ||||
93 | case SC_SliderGroove: { | ||||
94 | // direction | ||||
95 | const bool horizontal(sliderOption->orientation == Qt::Horizontal); | ||||
96 | | ||||
97 | // get base class rect | ||||
98 | auto grooveRect(ParentStyleClass::subControlRect(CC_Slider, option, subControl, widget)); | ||||
99 | grooveRect = insideMargin(grooveRect, pixelMetric(PM_DefaultFrameWidth, option, widget)); | ||||
100 | | ||||
101 | // centering | ||||
102 | if (horizontal) | ||||
103 | grooveRect = centerRect(grooveRect, grooveRect.width(), Metrics::Slider_GrooveThickness); | ||||
104 | else | ||||
105 | grooveRect = centerRect(grooveRect, Metrics::Slider_GrooveThickness, grooveRect.height()); | ||||
106 | return grooveRect; | ||||
107 | } | ||||
108 | | ||||
109 | default: | ||||
110 | return ParentStyleClass::subControlRect(CC_Slider, option, subControl, widget); | ||||
111 | } | ||||
112 | } | ||||
113 | | ||||
114 | //______________________________________________________________ | ||||
115 | QSize Style::sliderSizeFromContents(const QStyleOption *option, const QSize &contentsSize, const QWidget *) const | ||||
116 | { | ||||
117 | // cast option and check | ||||
118 | const auto sliderOption(qstyleoption_cast<const QStyleOptionSlider *>(option)); | ||||
119 | if (!sliderOption) | ||||
120 | return contentsSize; | ||||
121 | | ||||
122 | // store tick position and orientation | ||||
123 | const QSlider::TickPosition &tickPosition(sliderOption->tickPosition); | ||||
124 | const bool horizontal(sliderOption->orientation == Qt::Horizontal); | ||||
125 | const bool disableTicks(!StyleConfigData::sliderDrawTickMarks()); | ||||
126 | | ||||
127 | // do nothing if no ticks are requested | ||||
128 | if (tickPosition == QSlider::NoTicks) | ||||
129 | return contentsSize; | ||||
130 | | ||||
131 | /* | ||||
132 | * Qt adds its own tick length directly inside QSlider. | ||||
133 | * Take it out and replace by ours, if needed | ||||
134 | */ | ||||
135 | const int tickLength(disableTicks ? 0 : (Metrics::Slider_TickLength + Metrics::Slider_TickMarginWidth + (Metrics::Slider_GrooveThickness - Metrics::Slider_ControlThickness) / 2)); | ||||
136 | | ||||
137 | const int builtInTickLength(5); | ||||
138 | | ||||
139 | QSize size(contentsSize); | ||||
140 | if (horizontal) { | ||||
141 | if (tickPosition & QSlider::TicksAbove) | ||||
142 | size.rheight() += tickLength - builtInTickLength; | ||||
143 | if (tickPosition & QSlider::TicksBelow) | ||||
144 | size.rheight() += tickLength - builtInTickLength; | ||||
145 | | ||||
146 | } else { | ||||
147 | if (tickPosition & QSlider::TicksAbove) | ||||
148 | size.rwidth() += tickLength - builtInTickLength; | ||||
149 | if (tickPosition & QSlider::TicksBelow) | ||||
150 | size.rwidth() += tickLength - builtInTickLength; | ||||
151 | } | ||||
152 | | ||||
153 | return size; | ||||
154 | } | ||||
155 | | ||||
156 | //______________________________________________________________ | ||||
157 | bool Style::drawSliderComplexControl(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const | ||||
158 | { | ||||
159 | // cast option and check | ||||
160 | const auto sliderOption(qstyleoption_cast<const QStyleOptionSlider *>(option)); | ||||
161 | if (!sliderOption) | ||||
162 | return true; | ||||
163 | | ||||
164 | // copy rect and palette | ||||
165 | const auto &rect(option->rect); | ||||
166 | const auto &palette(option->palette); | ||||
167 | | ||||
168 | // copy state | ||||
169 | const State &state(option->state); | ||||
170 | const bool enabled(state & State_Enabled); | ||||
171 | const bool mouseOver(enabled && (state & State_MouseOver)); | ||||
172 | const bool hasFocus(enabled && (state & State_HasFocus)); | ||||
173 | | ||||
174 | // direction | ||||
175 | const bool horizontal(sliderOption->orientation == Qt::Horizontal); | ||||
176 | | ||||
177 | // tickmarks | ||||
178 | if (StyleConfigData::sliderDrawTickMarks() && (sliderOption->subControls & SC_SliderTickmarks)) { | ||||
179 | const bool upsideDown(sliderOption->upsideDown); | ||||
180 | const int tickPosition(sliderOption->tickPosition); | ||||
181 | const int available(pixelMetric(PM_SliderSpaceAvailable, option, widget)); | ||||
182 | int interval = sliderOption->tickInterval; | ||||
183 | if (interval < 1) | ||||
184 | interval = sliderOption->pageStep; | ||||
185 | if (interval >= 1) { | ||||
186 | const int fudge(pixelMetric(PM_SliderLength, option, widget) / 2); | ||||
187 | int current(sliderOption->minimum); | ||||
188 | | ||||
189 | // store tick lines | ||||
190 | const auto grooveRect(subControlRect(CC_Slider, sliderOption, SC_SliderGroove, widget)); | ||||
191 | QList<QLine> tickLines; | ||||
192 | if (horizontal) { | ||||
193 | if (tickPosition & QSlider::TicksAbove) | ||||
194 | tickLines.append(QLine(rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.top() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength)); | ||||
195 | if (tickPosition & QSlider::TicksBelow) | ||||
196 | tickLines.append(QLine(rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth, rect.left(), grooveRect.bottom() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength)); | ||||
197 | | ||||
198 | } else { | ||||
199 | if (tickPosition & QSlider::TicksAbove) | ||||
200 | tickLines.append(QLine(grooveRect.left() - Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.left() - Metrics::Slider_TickMarginWidth - Metrics::Slider_TickLength, rect.top())); | ||||
201 | if (tickPosition & QSlider::TicksBelow) | ||||
202 | tickLines.append(QLine(grooveRect.right() + Metrics::Slider_TickMarginWidth, rect.top(), grooveRect.right() + Metrics::Slider_TickMarginWidth + Metrics::Slider_TickLength, rect.top())); | ||||
203 | } | ||||
204 | | ||||
205 | // colors | ||||
206 | const auto base(_helper->separatorColor(palette)); | ||||
207 | const auto &highlight = palette.color(QPalette::Highlight); | ||||
208 | | ||||
209 | while (current <= sliderOption->maximum) { | ||||
210 | // adjust color | ||||
211 | const auto color((enabled && current <= sliderOption->sliderPosition) ? highlight : base); | ||||
212 | painter->setPen(color); | ||||
213 | | ||||
214 | // calculate positions and draw lines | ||||
215 | int position(sliderPositionFromValue(sliderOption->minimum, sliderOption->maximum, current, available) + fudge); | ||||
216 | foreach (const QLine &tickLine, tickLines) { | ||||
217 | if (horizontal) | ||||
218 | painter->drawLine(tickLine.translated(upsideDown ? (rect.width() - position) : position, 0)); | ||||
219 | else | ||||
220 | painter->drawLine(tickLine.translated(0, upsideDown ? (rect.height() - position) : position)); | ||||
221 | } | ||||
222 | | ||||
223 | // go to next position | ||||
224 | current += interval; | ||||
225 | } | ||||
226 | } | ||||
227 | } | ||||
228 | | ||||
229 | // groove | ||||
230 | if (sliderOption->subControls & SC_SliderGroove) { | ||||
231 | // retrieve groove rect | ||||
232 | auto grooveRect(subControlRect(CC_Slider, sliderOption, SC_SliderGroove, widget)); | ||||
233 | | ||||
234 | // base color | ||||
235 | const auto grooveColor(_helper->alphaColor(palette.color(QPalette::WindowText), 0.3)); | ||||
236 | | ||||
237 | if (!enabled) | ||||
238 | _helper->renderSliderGroove(painter, grooveRect, grooveColor); | ||||
239 | else { | ||||
240 | const bool upsideDown(sliderOption->upsideDown); | ||||
241 | | ||||
242 | // handle rect | ||||
243 | auto handleRect(subControlRect(CC_Slider, sliderOption, SC_SliderHandle, widget)); | ||||
244 | | ||||
245 | // highlight color | ||||
246 | const auto &highlight = palette.color(QPalette::Highlight); | ||||
247 | | ||||
248 | if (sliderOption->orientation == Qt::Horizontal) { | ||||
249 | auto leftRect(grooveRect); | ||||
250 | leftRect.setRight(handleRect.right() - Metrics::Slider_ControlThickness / 2); | ||||
251 | _helper->renderSliderGroove(painter, leftRect, upsideDown ? grooveColor : highlight); | ||||
252 | | ||||
253 | auto rightRect(grooveRect); | ||||
254 | rightRect.setLeft(handleRect.left() + Metrics::Slider_ControlThickness / 2); | ||||
255 | _helper->renderSliderGroove(painter, rightRect, upsideDown ? highlight : grooveColor); | ||||
256 | | ||||
257 | } else { | ||||
258 | auto topRect(grooveRect); | ||||
259 | topRect.setBottom(handleRect.bottom() - Metrics::Slider_ControlThickness / 2); | ||||
260 | _helper->renderSliderGroove(painter, topRect, upsideDown ? grooveColor : highlight); | ||||
261 | | ||||
262 | auto bottomRect(grooveRect); | ||||
263 | bottomRect.setTop(handleRect.top() + Metrics::Slider_ControlThickness / 2); | ||||
264 | _helper->renderSliderGroove(painter, bottomRect, upsideDown ? highlight : grooveColor); | ||||
265 | } | ||||
266 | } | ||||
267 | } | ||||
268 | | ||||
269 | // handle | ||||
270 | if (sliderOption->subControls & SC_SliderHandle) { | ||||
271 | // get rect and center | ||||
272 | auto handleRect(subControlRect(CC_Slider, sliderOption, SC_SliderHandle, widget)); | ||||
273 | | ||||
274 | // handle state | ||||
275 | const bool handleActive(sliderOption->activeSubControls & SC_SliderHandle); | ||||
276 | const bool sunken(state & (State_On | State_Sunken)); | ||||
277 | | ||||
278 | // animation state | ||||
279 | _animations->widgetStateEngine().updateState(widget, AnimationHover, handleActive && mouseOver); | ||||
280 | _animations->widgetStateEngine().updateState(widget, AnimationFocus, hasFocus); | ||||
281 | const AnimationMode mode(_animations->widgetStateEngine().buttonAnimationMode(widget)); | ||||
282 | const qreal opacity(_animations->widgetStateEngine().buttonOpacity(widget)); | ||||
283 | | ||||
284 | // define colors | ||||
285 | const auto &background = palette.color(QPalette::Button); | ||||
286 | const auto outline(_helper->sliderOutlineColor(palette, handleActive && mouseOver, hasFocus, opacity, mode)); | ||||
287 | const auto shadow(_helper->shadowColor(palette)); | ||||
288 | | ||||
289 | // render | ||||
290 | _helper->renderSliderHandle(painter, handleRect, background, outline, shadow, sunken); | ||||
291 | } | ||||
292 | | ||||
293 | return true; | ||||
294 | } | ||||
295 | | ||||
296 | } |