Mac: Animated expanding scrollbars on 10.8

Change-Id: Ib57d0347a7828ac7582b0fa95adf8d437694cd41
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
bb10
Gabriel de Dietrich 2012-12-03 19:00:03 +01:00 committed by The Qt Project
parent c35e12e876
commit 6f7791f871
2 changed files with 77 additions and 30 deletions

View File

@ -2181,11 +2181,11 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
switch (d->aquaSizeConstrain(opt, widget)) {
case QAquaSizeUnknown:
case QAquaSizeLarge:
ret = 9;
ret = QSysInfo::macVersion() >= QSysInfo::MV_10_8 ? 16 : 9;
break;
case QAquaSizeMini:
case QAquaSizeSmall:
ret = 7;
ret = QSysInfo::macVersion() >= QSysInfo::MV_10_8 ? 14 : 7;
break;
}
break;
@ -4909,6 +4909,11 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient)) {
bool wasActive = false;
CGFloat opacity = 1.0;
CGFloat expandScale = 1.0;
CGFloat expandOffset = -1.0;
bool shouldExpand = false;
const CGFloat maxExpandScale = tdi.kind == kThemeSmallScrollBar ? 11.0 / 7.0 : 13.0 / 9.0;
if (QObject *styleObject = opt->styleObject) {
int oldPos = styleObject->property("_q_stylepos").toInt();
int oldMin = styleObject->property("_q_stylemin").toInt();
@ -4936,23 +4941,24 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
styleObject->setProperty("_q_stylestate", static_cast<int>(slider->state));
styleObject->setProperty("_q_stylecontrols", static_cast<uint>(slider->activeSubControls));
QScrollbarAnimation *anim = qobject_cast<QScrollbarAnimation *>(d->animation(styleObject));
if (transient) {
QFadeOutAnimation *anim = qobject_cast<QFadeOutAnimation *>(d->animation(styleObject));
if (!anim) {
anim = new QFadeOutAnimation(styleObject);
anim = new QScrollbarAnimation(styleObject);
anim->setFadingOut();
d->startAnimation(anim);
} else {
} else if (anim->isFadingOut()) {
// the scrollbar was already fading out while the
// state changed -> restart the fade out animation
anim->setCurrentTime(0);
}
} else {
} else if (anim && anim->isFadingOut()) {
d->stopAnimation(styleObject);
}
}
QFadeOutAnimation *anim = qobject_cast<QFadeOutAnimation *>(d->animation(styleObject));
if (anim) {
QScrollbarAnimation *anim = qobject_cast<QScrollbarAnimation *>(d->animation(styleObject));
if (anim && anim->isFadingOut()) {
// once a scrollbar was active (hovered/pressed), it retains
// the active look even if it's no longer active while fading out
if (oldActiveControls)
@ -4961,6 +4967,24 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
wasActive = anim->wasActive();
opacity = anim->currentValue();
}
shouldExpand = (opt->activeSubControls || wasActive) && QSysInfo::macVersion() >= QSysInfo::MV_10_8;
if (shouldExpand) {
if (!anim && !oldActiveControls) {
// Start expand animation only once and when entering
anim = new QScrollbarAnimation(styleObject);
anim->setExpanding();
d->startAnimation(anim);
}
if (anim && !anim->isFadingOut()) {
expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue();
expandOffset = 5.5 * anim->currentValue() - 1;
} else {
// Keep expanded state after the animation ends, and when fading out
expandScale = maxExpandScale;
expandOffset = 4.5;
}
}
}
const bool isHorizontal = slider->orientation == Qt::Horizontal;
@ -4985,29 +5009,27 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
[scroller setBounds:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())];
[scroller setScrollerStyle:NSScrollerStyleOverlay];
// first we draw only the track, by using a disabled scroller
if (opt->activeSubControls || wasActive) {
CGContextBeginTransparencyLayerWithRect(cg, qt_hirectForQRect(slider->rect),
NULL);
CGContextSetAlpha(cg, opacity);
[scroller setFrame:[scroller bounds]];
[scroller setEnabled:(slider->state & State_Enabled) ? YES : NO];
[scroller drawKnobSlotInRect:[scroller bounds] highlight:NO];
CGContextEndTransparencyLayer(cg);
}
CGContextBeginTransparencyLayerWithRect(cg, qt_hirectForQRect(slider->rect), NULL);
CGContextBeginTransparencyLayer(cg, NULL);
CGContextSetAlpha(cg, opacity);
// Draw the track when hovering
if (opt->activeSubControls || wasActive) {
CGRect rect = [scroller bounds];
if (shouldExpand) {
if (isHorizontal)
rect.origin.y += 4.5 - expandOffset;
else
rect.origin.x += 4.5 - expandOffset;
}
[scroller drawKnobSlotInRect:rect highlight:YES];
}
const qreal length = slider->maximum - slider->minimum + slider->pageStep;
const qreal proportion = slider->pageStep / length;
qreal value = (slider->sliderValue - slider->minimum) / length;
if (isHorizontal && slider->direction == Qt::RightToLeft)
value = 1.0 - value - proportion;
[scroller setEnabled:(slider->state & State_Enabled) ? YES : NO];
[scroller setKnobProportion:1.0];
const int minKnobWidth = 26;
@ -5017,13 +5039,23 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const qreal width = qMax<qreal>(minKnobWidth, plannedWidth);
const qreal totalWidth = slider->rect.width() + plannedWidth - width;
[scroller setFrame:NSMakeRect(0, 0, width, slider->rect.height())];
CGContextTranslateCTM(cg, value * totalWidth, 1);
if (shouldExpand) {
CGContextScaleCTM(cg, 1, expandScale);
CGContextTranslateCTM(cg, value * totalWidth, -expandOffset);
} else {
CGContextTranslateCTM(cg, value * totalWidth, 1);
}
} else {
const qreal plannedHeight = proportion * slider->rect.height();
const qreal height = qMax<qreal>(minKnobWidth, plannedHeight);
const qreal totalHeight = slider->rect.height() + plannedHeight - height;
[scroller setFrame:NSMakeRect(0, 0, slider->rect.width(), height)];
CGContextTranslateCTM(cg, 1, value * totalHeight);
if (shouldExpand) {
CGContextScaleCTM(cg, expandScale, 1);
CGContextTranslateCTM(cg, -expandOffset, value * totalHeight);
} else {
CGContextTranslateCTM(cg, 1, value * totalHeight);
}
}
if (length > 0.0) {
[scroller layout];

View File

@ -211,32 +211,47 @@ public:
#endif
};
class QFadeOutAnimation : public QNumberStyleAnimation
class QScrollbarAnimation : public QNumberStyleAnimation
{
Q_OBJECT
public:
QFadeOutAnimation(QObject *target) : QNumberStyleAnimation(target), _active(false)
QScrollbarAnimation(QObject *target) : QNumberStyleAnimation(target), _active(false)
{ }
bool wasActive() const { return _active; }
void setActive(bool active) { _active = active; }
bool isFadingOut() const { return _isFadingOut; }
void setFadingOut()
{
_isFadingOut = true;
setDuration(QMacStylePrivate::ScrollBarFadeOutDelay + QMacStylePrivate::ScrollBarFadeOutDuration);
setDelay(QMacStylePrivate::ScrollBarFadeOutDelay);
setStartValue(1.0);
setEndValue(0.0);
}
bool wasActive() const { return _active; }
void setActive(bool active) { _active = active; }
void setExpanding()
{
_isFadingOut = false;
setDuration(QMacStylePrivate::ScrollBarFadeOutDuration);
setStartValue(0.0);
setEndValue(1.0);
}
private slots:
void updateCurrentTime(int time)
{
QNumberStyleAnimation::updateCurrentTime(time);
if (qFuzzyIsNull(currentValue()))
if (_isFadingOut && qFuzzyIsNull(currentValue()))
target()->setProperty("visible", false);
}
private:
bool _active;
bool _isFadingOut;
};
QT_END_NAMESPACE