Changeset View
Changeset View
Standalone View
Standalone View
kstyle/widgets/scrollbar.cpp
- This file was added.
1 | #include "breezestyle.h" | ||||
---|---|---|---|---|---|
2 | | ||||
3 | #include <QScrollBar> | ||||
4 | | ||||
5 | namespace Breeze | ||||
6 | { | ||||
7 | QColor Helper::scrollBarHandleColor(const QPalette &palette, bool mouseOver, bool hasFocus, qreal opacity, AnimationMode mode) const | ||||
8 | { | ||||
9 | QColor color(alphaColor(palette.color(QPalette::WindowText), 0.5)); | ||||
10 | | ||||
11 | // hover takes precedence over focus | ||||
12 | if (mode == AnimationHover) { | ||||
13 | const QColor hover(hoverColor(palette)); | ||||
14 | const QColor focus(focusColor(palette)); | ||||
15 | if (hasFocus) | ||||
16 | color = KColorUtils::mix(focus, hover, opacity); | ||||
17 | else | ||||
18 | color = KColorUtils::mix(color, hover, opacity); | ||||
19 | | ||||
20 | } else if (mouseOver) { | ||||
21 | color = hoverColor(palette); | ||||
22 | | ||||
23 | } else if (mode == AnimationFocus) { | ||||
24 | const QColor focus(focusColor(palette)); | ||||
25 | color = KColorUtils::mix(color, focus, opacity); | ||||
26 | | ||||
27 | } else if (hasFocus) { | ||||
28 | color = focusColor(palette); | ||||
29 | } | ||||
30 | | ||||
31 | return color; | ||||
32 | } | ||||
33 | | ||||
34 | //______________________________________________________________________________ | ||||
35 | void Helper::renderScrollBarHandle(QPainter *painter, const QRect &rect, const QColor &color) const | ||||
36 | { | ||||
37 | // setup painter | ||||
38 | painter->setRenderHint(QPainter::Antialiasing, true); | ||||
39 | | ||||
40 | const QRectF baseRect(rect); | ||||
41 | const qreal radius(0.5 * std::min({baseRect.width(), baseRect.height(), (qreal)Metrics::ScrollBar_SliderWidth})); | ||||
42 | | ||||
43 | // content | ||||
44 | if (color.isValid()) { | ||||
45 | painter->setPen(Qt::NoPen); | ||||
46 | painter->setBrush(color); | ||||
47 | painter->drawRoundedRect(baseRect, radius, radius); | ||||
48 | } | ||||
49 | } | ||||
50 | | ||||
51 | //___________________________________________________________________________________________________________________ | ||||
52 | QRect Style::scrollBarInternalSubControlRect(const QStyleOptionComplex *option, SubControl subControl) const | ||||
53 | { | ||||
54 | const auto &rect = option->rect; | ||||
55 | const State &state(option->state); | ||||
56 | const bool horizontal(state & State_Horizontal); | ||||
57 | | ||||
58 | switch (subControl) { | ||||
59 | case SC_ScrollBarSubLine: { | ||||
60 | int majorSize(scrollBarButtonHeight(_subLineButtons)); | ||||
61 | if (horizontal) | ||||
62 | return visualRect(option, QRect(rect.left(), rect.top(), majorSize, rect.height())); | ||||
63 | else | ||||
64 | return visualRect(option, QRect(rect.left(), rect.top(), rect.width(), majorSize)); | ||||
65 | } | ||||
66 | | ||||
67 | case SC_ScrollBarAddLine: { | ||||
68 | int majorSize(scrollBarButtonHeight(_addLineButtons)); | ||||
69 | if (horizontal) | ||||
70 | return visualRect(option, QRect(rect.right() - majorSize + 1, rect.top(), majorSize, rect.height())); | ||||
71 | else | ||||
72 | return visualRect(option, QRect(rect.left(), rect.bottom() - majorSize + 1, rect.width(), majorSize)); | ||||
73 | } | ||||
74 | | ||||
75 | default: | ||||
76 | return QRect(); | ||||
77 | } | ||||
78 | } | ||||
79 | | ||||
80 | //___________________________________________________________________________________________________________________ | ||||
81 | QRect Style::scrollBarSubControlRect(const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const | ||||
82 | { | ||||
83 | // cast option and check | ||||
84 | const auto sliderOption(qstyleoption_cast<const QStyleOptionSlider *>(option)); | ||||
85 | if (!sliderOption) | ||||
86 | return ParentStyleClass::subControlRect(CC_ScrollBar, option, subControl, widget); | ||||
87 | | ||||
88 | // get relevant state | ||||
89 | const State &state(option->state); | ||||
90 | const bool horizontal(state & State_Horizontal); | ||||
91 | | ||||
92 | switch (subControl) { | ||||
93 | case SC_ScrollBarSubLine: | ||||
94 | case SC_ScrollBarAddLine: | ||||
95 | return scrollBarInternalSubControlRect(option, subControl); | ||||
96 | | ||||
97 | case SC_ScrollBarGroove: { | ||||
98 | auto topRect = visualRect(option, scrollBarInternalSubControlRect(option, SC_ScrollBarSubLine)); | ||||
99 | auto bottomRect = visualRect(option, scrollBarInternalSubControlRect(option, SC_ScrollBarAddLine)); | ||||
100 | | ||||
101 | QPoint topLeftCorner; | ||||
102 | QPoint botRightCorner; | ||||
103 | | ||||
104 | if (horizontal) { | ||||
105 | topLeftCorner = QPoint(topRect.right() + 1, topRect.top()); | ||||
106 | botRightCorner = QPoint(bottomRect.left() - 1, topRect.bottom()); | ||||
107 | | ||||
108 | } else { | ||||
109 | topLeftCorner = QPoint(topRect.left(), topRect.bottom() + 1); | ||||
110 | botRightCorner = QPoint(topRect.right(), bottomRect.top() - 1); | ||||
111 | } | ||||
112 | | ||||
113 | // define rect | ||||
114 | return visualRect(option, QRect(topLeftCorner, botRightCorner)); | ||||
115 | } | ||||
116 | | ||||
117 | case SC_ScrollBarSlider: { | ||||
118 | // handle RTL here to unreflect things if need be | ||||
119 | auto groove = visualRect(option, subControlRect(CC_ScrollBar, option, SC_ScrollBarGroove, widget)); | ||||
120 | | ||||
121 | if (sliderOption->minimum == sliderOption->maximum) | ||||
122 | return groove; | ||||
123 | | ||||
124 | // Figure out how much room there is | ||||
125 | int space(horizontal ? groove.width() : groove.height()); | ||||
126 | | ||||
127 | // Calculate the portion of this space that the slider should occupy | ||||
128 | int sliderSize = space * qreal(sliderOption->pageStep) / (sliderOption->maximum - sliderOption->minimum + sliderOption->pageStep); | ||||
129 | sliderSize = qMax(sliderSize, static_cast<int>(Metrics::ScrollBar_MinSliderHeight)); | ||||
130 | sliderSize = qMin(sliderSize, space); | ||||
131 | | ||||
132 | space -= sliderSize; | ||||
133 | if (space <= 0) | ||||
134 | return groove; | ||||
135 | | ||||
136 | int pos = qRound(qreal(sliderOption->sliderPosition - sliderOption->minimum) / (sliderOption->maximum - sliderOption->minimum) * space); | ||||
137 | if (sliderOption->upsideDown) | ||||
138 | pos = space - pos; | ||||
139 | if (horizontal) | ||||
140 | return visualRect(option, QRect(groove.left() + pos, groove.top(), sliderSize, groove.height())); | ||||
141 | else | ||||
142 | return visualRect(option, QRect(groove.left(), groove.top() + pos, groove.width(), sliderSize)); | ||||
143 | } | ||||
144 | | ||||
145 | case SC_ScrollBarSubPage: { | ||||
146 | // handle RTL here to unreflect things if need be | ||||
147 | auto slider = visualRect(option, subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget)); | ||||
148 | auto groove = visualRect(option, subControlRect(CC_ScrollBar, option, SC_ScrollBarGroove, widget)); | ||||
149 | | ||||
150 | if (horizontal) | ||||
151 | return visualRect(option, QRect(groove.left(), groove.top(), slider.left() - groove.left(), groove.height())); | ||||
152 | else | ||||
153 | return visualRect(option, QRect(groove.left(), groove.top(), groove.width(), slider.top() - groove.top())); | ||||
154 | } | ||||
155 | | ||||
156 | case SC_ScrollBarAddPage: { | ||||
157 | // handle RTL here to unreflect things if need be | ||||
158 | auto slider = visualRect(option, subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget)); | ||||
159 | auto groove = visualRect(option, subControlRect(CC_ScrollBar, option, SC_ScrollBarGroove, widget)); | ||||
160 | | ||||
161 | if (horizontal) | ||||
162 | return visualRect(option, QRect(slider.right() + 1, groove.top(), groove.right() - slider.right(), groove.height())); | ||||
163 | else | ||||
164 | return visualRect(option, QRect(groove.left(), slider.bottom() + 1, groove.width(), groove.bottom() - slider.bottom())); | ||||
165 | } | ||||
166 | | ||||
167 | default: | ||||
168 | return ParentStyleClass::subControlRect(CC_ScrollBar, option, subControl, widget); | ||||
169 | ; | ||||
170 | } | ||||
171 | } | ||||
172 | | ||||
173 | //___________________________________________________________________________________ | ||||
174 | bool Style::drawScrollBarSliderControl(const QStyleOption *option, QPainter *painter, const QWidget *widget) const | ||||
175 | { | ||||
176 | // cast option and check | ||||
177 | const auto sliderOption(qstyleoption_cast<const QStyleOptionSlider *>(option)); | ||||
178 | if (!sliderOption) | ||||
179 | return true; | ||||
180 | | ||||
181 | // copy rect and palette | ||||
182 | const auto &rect(option->rect); | ||||
183 | const auto &palette(option->palette); | ||||
184 | | ||||
185 | // try to understand if anywhere the widget is under mouse, not just the handle, use _animations in case of QWidget, option->styleObject in case of QML | ||||
186 | #if QT_VERSION >= 0x050000 | ||||
187 | bool widgetMouseOver((option->state & State_MouseOver)); | ||||
188 | if (widget) | ||||
189 | widgetMouseOver = _animations->scrollBarEngine().isHovered(widget, QStyle::SC_ScrollBarGroove); | ||||
190 | else if (option->styleObject) | ||||
191 | widgetMouseOver = option->styleObject->property("hover").toBool(); | ||||
192 | #else | ||||
193 | const bool widgetMouseOver(_animations->scrollBarEngine().isHovered(widget, QStyle::SC_ScrollBarGroove)); | ||||
194 | #endif | ||||
195 | | ||||
196 | qreal grooveAnimationOpacity(_animations->scrollBarEngine().opacity(widget, QStyle::SC_ScrollBarGroove)); | ||||
197 | if (grooveAnimationOpacity == AnimationData::OpacityInvalid) | ||||
198 | grooveAnimationOpacity = (widgetMouseOver ? 1 : 0); | ||||
199 | const qreal handleSize = StyleConfigData::animationsEnabled() ? ((Metrics::ScrollBar_SliderWidth / 2.0) * (1 - grooveAnimationOpacity) + Metrics::ScrollBar_SliderWidth * grooveAnimationOpacity) : (int)Metrics::ScrollBar_SliderWidth; | ||||
200 | | ||||
201 | // define handle rect | ||||
202 | QRect handleRect; | ||||
203 | const State &state(option->state); | ||||
204 | const bool horizontal(state & State_Horizontal); | ||||
205 | if (horizontal) | ||||
206 | handleRect = centerRect(rect, rect.width(), handleSize); | ||||
207 | else | ||||
208 | handleRect = centerRect(rect, handleSize, rect.height()); | ||||
209 | | ||||
210 | const bool enabled(state & State_Enabled); | ||||
211 | const bool mouseOver(enabled && (state & State_MouseOver)); | ||||
212 | | ||||
213 | // check focus from relevant parent | ||||
214 | const QWidget *parent(scrollBarParent(widget)); | ||||
215 | const bool hasFocus(enabled && ((widget && widget->hasFocus()) || (parent && parent->hasFocus()))); | ||||
216 | | ||||
217 | // enable animation state | ||||
218 | const bool handleActive(sliderOption->activeSubControls & SC_ScrollBarSlider); | ||||
219 | _animations->scrollBarEngine().updateState(widget, AnimationFocus, hasFocus); | ||||
220 | | ||||
221 | _animations->scrollBarEngine().updateState(widget, AnimationHover, mouseOver && handleActive); | ||||
222 | | ||||
223 | const auto mode(_animations->scrollBarEngine().animationMode(widget, SC_ScrollBarSlider)); | ||||
224 | const qreal opacity(_animations->scrollBarEngine().opacity(widget, SC_ScrollBarSlider)); | ||||
225 | auto color = _helper->scrollBarHandleColor(palette, mouseOver, hasFocus, opacity, mode); | ||||
226 | if (StyleConfigData::animationsEnabled()) { | ||||
227 | color.setAlphaF(color.alphaF() * (0.7 + 0.3 * grooveAnimationOpacity)); | ||||
228 | } | ||||
229 | | ||||
230 | _helper->renderScrollBarHandle(painter, handleRect, color); | ||||
231 | return true; | ||||
232 | } | ||||
233 | | ||||
234 | //___________________________________________________________________________________ | ||||
235 | bool Style::drawScrollBarAddLineControl(const QStyleOption *option, QPainter *painter, const QWidget *widget) const | ||||
236 | { | ||||
237 | // do nothing if no buttons are defined | ||||
238 | if (_addLineButtons == NoButton) | ||||
239 | return true; | ||||
240 | | ||||
241 | // cast option and check | ||||
242 | const auto sliderOption(qstyleoption_cast<const QStyleOptionSlider *>(option)); | ||||
243 | if (!sliderOption) | ||||
244 | return true; | ||||
245 | | ||||
246 | const State &state(option->state); | ||||
247 | const bool horizontal(state & State_Horizontal); | ||||
248 | const bool reverseLayout(option->direction == Qt::RightToLeft); | ||||
249 | | ||||
250 | // adjust rect, based on number of buttons to be drawn | ||||
251 | const auto rect(scrollBarInternalSubControlRect(sliderOption, SC_ScrollBarAddLine)); | ||||
252 | | ||||
253 | QColor color; | ||||
254 | QStyleOptionSlider copy(*sliderOption); | ||||
255 | if (_addLineButtons == DoubleButton) { | ||||
256 | if (horizontal) { | ||||
257 | // Draw the arrows | ||||
258 | const QSize halfSize(rect.width() / 2, rect.height()); | ||||
259 | const QRect leftSubButton(rect.topLeft(), halfSize); | ||||
260 | const QRect rightSubButton(leftSubButton.topRight() + QPoint(1, 0), halfSize); | ||||
261 | | ||||
262 | copy.rect = leftSubButton; | ||||
263 | color = scrollBarArrowColor(©, reverseLayout ? SC_ScrollBarAddLine : SC_ScrollBarSubLine, widget); | ||||
264 | _helper->renderArrow(painter, leftSubButton, color, ArrowLeft); | ||||
265 | | ||||
266 | copy.rect = rightSubButton; | ||||
267 | color = scrollBarArrowColor(©, reverseLayout ? SC_ScrollBarSubLine : SC_ScrollBarAddLine, widget); | ||||
268 | _helper->renderArrow(painter, rightSubButton, color, ArrowRight); | ||||
269 | | ||||
270 | } else { | ||||
271 | const QSize halfSize(rect.width(), rect.height() / 2); | ||||
272 | const QRect topSubButton(rect.topLeft(), halfSize); | ||||
273 | const QRect botSubButton(topSubButton.bottomLeft() + QPoint(0, 1), halfSize); | ||||
274 | | ||||
275 | copy.rect = topSubButton; | ||||
276 | color = scrollBarArrowColor(©, SC_ScrollBarSubLine, widget); | ||||
277 | _helper->renderArrow(painter, topSubButton, color, ArrowUp); | ||||
278 | | ||||
279 | copy.rect = botSubButton; | ||||
280 | color = scrollBarArrowColor(©, SC_ScrollBarAddLine, widget); | ||||
281 | _helper->renderArrow(painter, botSubButton, color, ArrowDown); | ||||
282 | } | ||||
283 | | ||||
284 | } else if (_addLineButtons == SingleButton) { | ||||
285 | copy.rect = rect; | ||||
286 | color = scrollBarArrowColor(©, SC_ScrollBarAddLine, widget); | ||||
287 | if (horizontal) { | ||||
288 | if (reverseLayout) | ||||
289 | _helper->renderArrow(painter, rect, color, ArrowLeft); | ||||
290 | else | ||||
291 | _helper->renderArrow(painter, rect.translated(1, 0), color, ArrowRight); | ||||
292 | | ||||
293 | } else | ||||
294 | _helper->renderArrow(painter, rect.translated(0, 1), color, ArrowDown); | ||||
295 | } | ||||
296 | | ||||
297 | return true; | ||||
298 | } | ||||
299 | | ||||
300 | //___________________________________________________________________________________ | ||||
301 | bool Style::drawScrollBarSubLineControl(const QStyleOption *option, QPainter *painter, const QWidget *widget) const | ||||
302 | { | ||||
303 | // do nothing if no buttons are set | ||||
304 | if (_subLineButtons == NoButton) | ||||
305 | return true; | ||||
306 | | ||||
307 | // cast option and check | ||||
308 | const auto sliderOption(qstyleoption_cast<const QStyleOptionSlider *>(option)); | ||||
309 | if (!sliderOption) | ||||
310 | return true; | ||||
311 | | ||||
312 | const State &state(option->state); | ||||
313 | const bool horizontal(state & State_Horizontal); | ||||
314 | const bool reverseLayout(option->direction == Qt::RightToLeft); | ||||
315 | | ||||
316 | // colors | ||||
317 | const auto &palette(option->palette); | ||||
318 | const auto &background = palette.color(QPalette::Window); | ||||
319 | | ||||
320 | // adjust rect, based on number of buttons to be drawn | ||||
321 | const auto rect(scrollBarInternalSubControlRect(sliderOption, SC_ScrollBarSubLine)); | ||||
322 | | ||||
323 | QColor color; | ||||
324 | QStyleOptionSlider copy(*sliderOption); | ||||
325 | if (_subLineButtons == DoubleButton) { | ||||
326 | if (horizontal) { | ||||
327 | // Draw the arrows | ||||
328 | const QSize halfSize(rect.width() / 2, rect.height()); | ||||
329 | const QRect leftSubButton(rect.topLeft(), halfSize); | ||||
330 | const QRect rightSubButton(leftSubButton.topRight() + QPoint(1, 0), halfSize); | ||||
331 | | ||||
332 | copy.rect = leftSubButton; | ||||
333 | color = scrollBarArrowColor(©, reverseLayout ? SC_ScrollBarAddLine : SC_ScrollBarSubLine, widget); | ||||
334 | _helper->renderArrow(painter, leftSubButton, color, ArrowLeft); | ||||
335 | | ||||
336 | copy.rect = rightSubButton; | ||||
337 | color = scrollBarArrowColor(©, reverseLayout ? SC_ScrollBarSubLine : SC_ScrollBarAddLine, widget); | ||||
338 | _helper->renderArrow(painter, rightSubButton, color, ArrowRight); | ||||
339 | | ||||
340 | } else { | ||||
341 | const QSize halfSize(rect.width(), rect.height() / 2); | ||||
342 | const QRect topSubButton(rect.topLeft(), halfSize); | ||||
343 | const QRect botSubButton(topSubButton.bottomLeft() + QPoint(0, 1), halfSize); | ||||
344 | | ||||
345 | copy.rect = topSubButton; | ||||
346 | color = scrollBarArrowColor(©, SC_ScrollBarSubLine, widget); | ||||
347 | _helper->renderArrow(painter, topSubButton, color, ArrowUp); | ||||
348 | | ||||
349 | copy.rect = botSubButton; | ||||
350 | color = scrollBarArrowColor(©, SC_ScrollBarAddLine, widget); | ||||
351 | _helper->renderArrow(painter, botSubButton, color, ArrowDown); | ||||
352 | } | ||||
353 | | ||||
354 | } else if (_subLineButtons == SingleButton) { | ||||
355 | copy.rect = rect; | ||||
356 | color = scrollBarArrowColor(©, SC_ScrollBarSubLine, widget); | ||||
357 | if (horizontal) { | ||||
358 | if (reverseLayout) | ||||
359 | _helper->renderArrow(painter, rect.translated(1, 0), color, ArrowRight); | ||||
360 | else | ||||
361 | _helper->renderArrow(painter, rect, color, ArrowLeft); | ||||
362 | | ||||
363 | } else | ||||
364 | _helper->renderArrow(painter, rect, color, ArrowUp); | ||||
365 | } | ||||
366 | | ||||
367 | return true; | ||||
368 | } | ||||
369 | | ||||
370 | //______________________________________________________________ | ||||
371 | bool Style::drawScrollBarComplexControl(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const | ||||
372 | { | ||||
373 | // the animation for QStyle::SC_ScrollBarGroove is special: it will animate | ||||
374 | // the opacity of everything else as well, included slider and arrows | ||||
375 | qreal opacity(_animations->scrollBarEngine().opacity(widget, QStyle::SC_ScrollBarGroove)); | ||||
376 | const bool animated(StyleConfigData::animationsEnabled() && _animations->scrollBarEngine().isAnimated(widget, AnimationHover, QStyle::SC_ScrollBarGroove)); | ||||
377 | const bool mouseOver(option->state & State_MouseOver); | ||||
378 | | ||||
379 | if (opacity == AnimationData::OpacityInvalid) | ||||
380 | opacity = 1; | ||||
381 | | ||||
382 | // render full groove directly, rather than using the addPage and subPage control element methods | ||||
383 | if ((!StyleConfigData::animationsEnabled() || mouseOver || animated) && option->subControls & SC_ScrollBarGroove) { | ||||
384 | // retrieve groove rectangle | ||||
385 | auto grooveRect(subControlRect(CC_ScrollBar, option, SC_ScrollBarGroove, widget)); | ||||
386 | | ||||
387 | const auto &palette(option->palette); | ||||
388 | const auto color(_helper->alphaColor(palette.color(QPalette::WindowText), 0.3 * (animated ? opacity : 1))); | ||||
389 | const auto &state(option->state); | ||||
390 | const bool horizontal(state & State_Horizontal); | ||||
391 | | ||||
392 | if (horizontal) | ||||
393 | grooveRect = centerRect(grooveRect, grooveRect.width(), Metrics::ScrollBar_SliderWidth); | ||||
394 | else | ||||
395 | grooveRect = centerRect(grooveRect, Metrics::ScrollBar_SliderWidth, grooveRect.height()); | ||||
396 | | ||||
397 | // render | ||||
398 | _helper->renderScrollBarGroove(painter, grooveRect, color); | ||||
399 | } | ||||
400 | | ||||
401 | // call base class primitive | ||||
402 | ParentStyleClass::drawComplexControl(CC_ScrollBar, option, painter, widget); | ||||
403 | | ||||
404 | return true; | ||||
405 | } | ||||
406 | | ||||
407 | //______________________________________________________________________________ | ||||
408 | const QWidget *Style::scrollBarParent(const QWidget *widget) const | ||||
409 | { | ||||
410 | // check widget and parent | ||||
411 | if (!(widget && widget->parentWidget())) | ||||
412 | return nullptr; | ||||
413 | | ||||
414 | // try cast to scroll area. Must test both parent and grandparent | ||||
415 | QAbstractScrollArea *scrollArea; | ||||
416 | if (!(scrollArea = qobject_cast<QAbstractScrollArea *>(widget->parentWidget()))) { | ||||
417 | scrollArea = qobject_cast<QAbstractScrollArea *>(widget->parentWidget()->parentWidget()); | ||||
418 | } | ||||
419 | | ||||
420 | // check scrollarea | ||||
421 | if (scrollArea && (widget == scrollArea->verticalScrollBar() || widget == scrollArea->horizontalScrollBar())) { | ||||
422 | return scrollArea; | ||||
423 | | ||||
424 | } else if (widget->parentWidget()->inherits("KTextEditor::View")) { | ||||
425 | return widget->parentWidget(); | ||||
426 | | ||||
427 | } else | ||||
428 | return nullptr; | ||||
429 | } | ||||
430 | | ||||
431 | //______________________________________________________________________________ | ||||
432 | QColor Style::scrollBarArrowColor(const QStyleOptionSlider *option, const SubControl &control, const QWidget *widget) const | ||||
433 | { | ||||
434 | const auto &rect(option->rect); | ||||
435 | const auto &palette(option->palette); | ||||
436 | auto color(_helper->arrowColor(palette, QPalette::WindowText)); | ||||
437 | | ||||
438 | bool widgetMouseOver((option->state & State_MouseOver)); | ||||
439 | if (widget) | ||||
440 | widgetMouseOver = widget->underMouse(); | ||||
441 | #if QT_VERSION >= 0x050000 | ||||
442 | // in case this QStyle is used by QQuickControls QStyle wrapper | ||||
443 | else if (option->styleObject) | ||||
444 | widgetMouseOver = option->styleObject->property("hover").toBool(); | ||||
445 | #endif | ||||
446 | | ||||
447 | // check enabled state | ||||
448 | const bool enabled(option->state & State_Enabled); | ||||
449 | if (!enabled) { | ||||
450 | if (StyleConfigData::animationsEnabled()) { | ||||
451 | // finally, global opacity when ScrollBarShowOnMouseOver | ||||
452 | const qreal globalOpacity(_animations->scrollBarEngine().opacity(widget, QStyle::SC_ScrollBarGroove)); | ||||
453 | if (globalOpacity >= 0) | ||||
454 | color.setAlphaF(globalOpacity); | ||||
455 | // no mouse over and no animation in progress, don't draw arrows at all | ||||
456 | else if (!widgetMouseOver) | ||||
457 | return Qt::transparent; | ||||
458 | } | ||||
459 | return color; | ||||
460 | } | ||||
461 | | ||||
462 | if ((control == SC_ScrollBarSubLine && option->sliderValue == option->minimum) || (control == SC_ScrollBarAddLine && option->sliderValue == option->maximum)) { | ||||
463 | // manually disable arrow, to indicate that scrollbar is at limit | ||||
464 | color = _helper->arrowColor(palette, QPalette::Disabled, QPalette::WindowText); | ||||
465 | if (StyleConfigData::animationsEnabled()) { | ||||
466 | // finally, global opacity when ScrollBarShowOnMouseOver | ||||
467 | const qreal globalOpacity(_animations->scrollBarEngine().opacity(widget, QStyle::SC_ScrollBarGroove)); | ||||
468 | if (globalOpacity >= 0) | ||||
469 | color.setAlphaF(globalOpacity); | ||||
470 | // no mouse over and no animation in progress, don't draw arrows at all | ||||
471 | else if (!widgetMouseOver) | ||||
472 | return Qt::transparent; | ||||
473 | } | ||||
474 | return color; | ||||
475 | } | ||||
476 | | ||||
477 | const bool mouseOver(_animations->scrollBarEngine().isHovered(widget, control)); | ||||
478 | const bool animated(_animations->scrollBarEngine().isAnimated(widget, AnimationHover, control)); | ||||
479 | const qreal opacity(_animations->scrollBarEngine().opacity(widget, control)); | ||||
480 | | ||||
481 | // retrieve mouse position from engine | ||||
482 | QPoint position(mouseOver ? _animations->scrollBarEngine().position(widget) : QPoint(-1, -1)); | ||||
483 | if (mouseOver && rect.contains(position)) { | ||||
484 | /* | ||||
485 | * need to update the arrow controlRect on fly because there is no | ||||
486 | * way to get it from the styles directly, outside of repaint events | ||||
487 | */ | ||||
488 | _animations->scrollBarEngine().setSubControlRect(widget, control, rect); | ||||
489 | } | ||||
490 | | ||||
491 | if (rect.intersects(_animations->scrollBarEngine().subControlRect(widget, control))) { | ||||
492 | auto highlight = _helper->hoverColor(palette); | ||||
493 | if (animated) { | ||||
494 | color = KColorUtils::mix(color, highlight, opacity); | ||||
495 | | ||||
496 | } else if (mouseOver) { | ||||
497 | color = highlight; | ||||
498 | } | ||||
499 | } | ||||
500 | | ||||
501 | if (StyleConfigData::animationsEnabled()) { | ||||
502 | // finally, global opacity when ScrollBarShowOnMouseOver | ||||
503 | const qreal globalOpacity(_animations->scrollBarEngine().opacity(widget, QStyle::SC_ScrollBarGroove)); | ||||
504 | if (globalOpacity >= 0) | ||||
505 | color.setAlphaF(globalOpacity); | ||||
506 | // no mouse over and no animation in progress, don't draw arrows at all | ||||
507 | else if (!widgetMouseOver) | ||||
508 | return Qt::transparent; | ||||
509 | } | ||||
510 | | ||||
511 | return color; | ||||
512 | } | ||||
513 | | ||||
514 | } |