Remove widget dependencies on Vista style animations

This patch will make it possible to get animations on
desktop components without using the widget pointer.

Change-Id: I2d2eca111dab0d96f276ff3627505c0652c4b4e5
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
This commit is contained in:
Jens Bache-Wiig 2012-10-23 18:34:25 +02:00 committed by The Qt Project
parent 38630bc35a
commit 79a389c346

View File

@ -144,6 +144,20 @@ bool QWindowsVistaStylePrivate::useVista()
(QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))); (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)));
} }
/* \internal
Checks and returns the style object
*/
inline QObject *styleObject(const QStyleOption *option) {
return option ? option->styleObject : 0;
}
bool canAnimate(const QStyleOption *option) {
return option
&& option->styleObject
&& !option->styleObject->property("_q_no_animation").toBool();
}
/*! /*!
\class QWindowsVistaStyle \class QWindowsVistaStyle
\brief The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows Vista. \brief The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows Vista.
@ -353,30 +367,26 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
return; return;
} }
if (d->transitionsEnabled() && canAnimate(option)) {
{
QRect oldRect; QRect oldRect;
QRect newRect; QRect newRect;
if (widget && d->transitionsEnabled()) /* widgets that support state transitions : */
{ if ( element == PE_FrameLineEdit
/* all widgets that supports state transitions : */ || element == PE_IndicatorRadioButton
if ( || element == PE_IndicatorCheckBox)
#ifndef QT_NO_LINEEDIT
(qobject_cast<const QLineEdit*>(widget) && element == PE_FrameLineEdit) ||
#endif // QT_NO_LINEEDIT
(qobject_cast<const QRadioButton*>(widget)&& element == PE_IndicatorRadioButton) ||
(qobject_cast<const QCheckBox*>(widget) && element == PE_IndicatorCheckBox) ||
(qobject_cast<const QGroupBox *>(widget)&& element == PE_IndicatorCheckBox) ||
(qobject_cast<const QToolButton*>(widget) && element == PE_PanelButtonBevel)
)
{ {
// Retrieve and update the dynamic properties tracking // Retrieve and update the dynamic properties tracking
// the previous state of the widget: // the previous state of the widget:
QWidget *w = const_cast<QWidget *> (widget); QObject *styleObject = option->styleObject;
int oldState = w->property("_q_stylestate").toInt(); styleObject->setProperty("_q_no_animation", true);
oldRect = w->property("_q_stylerect").toRect();
newRect = w->rect(); int oldState = styleObject->property("_q_stylestate").toInt();
w->setProperty("_q_stylestate", (int)option->state); oldRect = styleObject->property("_q_stylerect").toRect();
w->setProperty("_q_stylerect", w->rect()); newRect = option->rect;
styleObject->setProperty("_q_stylestate", (int)option->state);
styleObject->setProperty("_q_stylerect", option->rect);
bool doTransition = oldState && bool doTransition = oldState &&
((state & State_Sunken) != (oldState & State_Sunken) || ((state & State_Sunken) != (oldState & State_Sunken) ||
@ -386,51 +396,50 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
if (oldRect != newRect || if (oldRect != newRect ||
(state & State_Enabled) != (oldState & State_Enabled) || (state & State_Enabled) != (oldState & State_Enabled) ||
(state & State_Active) != (oldState & State_Active)) (state & State_Active) != (oldState & State_Active))
d->stopAnimation(widget); d->stopAnimation(styleObject);
#ifndef QT_NO_LINEEDIT if (option->state & State_ReadOnly && element == PE_FrameLineEdit) // Do not animate read only line edits
if (const QLineEdit *edit = qobject_cast<const QLineEdit *>(widget))
if (edit->isReadOnly() && element == PE_FrameLineEdit) // Do not animate read only line edits
doTransition = false; doTransition = false;
#endif // QT_NO_LINEEDIT
if (doTransition) { if (doTransition) {
QStyleOption *styleOption = 0;
if (const QStyleOptionGroupBox *combo = qstyleoption_cast<const QStyleOptionGroupBox*>(option))
styleOption = new QStyleOptionGroupBox(*combo);
else
styleOption = new QStyleOption(*option);
styleOption->state = (QStyle::State)oldState;
styleOption->rect = QRect(QPoint(0,0), newRect.size());
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject));
QWindowsVistaTransition *t = new QWindowsVistaTransition(styleObject);
// We create separate images for the initial and final transition states and store them in the // We create separate images for the initial and final transition states and store them in the
// Transition object. // Transition object.
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
QStyleOption opt = *option;
opt.rect.setRect(0, 0, option->rect.width(), option->rect.height());
opt.state = (QStyle::State)oldState;
startImage.fill(0); startImage.fill(0);
QPainter startPainter(&startImage); QPainter startPainter(&startImage);
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget)); QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
QWindowsVistaTransition *t = new QWindowsVistaTransition(w); endImage.fill(0);
QPainter endPainter(&endImage);
// If we have a running animation on the widget already, we will use that to paint the initial // If we have a running animation on the widget already, we will use that to paint the initial
// state of the new transition, this ensures a smooth transition from a current animation such as a // state of the new transition, this ensures a smooth transition from a current animation such as a
// pulsating default button into the intended target state. // pulsating default button into the intended target state.
if (!anim) if (!anim)
proxy()->drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0 proxy()->drawPrimitive(element, styleOption, &startPainter, widget);
else // this ensures that we do not recurse in the animation logic above else
anim->paint(&startPainter, &opt); anim->paint(&startPainter, styleOption);
d->startAnimation(t);
t->setStartImage(startImage); t->setStartImage(startImage);
// The end state of the transition is simply the result we would have painted // The end state of the transition is simply the result we would have painted
// if the style was not animated. // if the style was not animated.
styleOption->state = option->state;
drawPrimitive(element, styleOption, &endPainter, widget);
QPainter endPainter(&endImage);
endImage.fill(0);
QStyleOption opt2 = opt;
opt2.state = option->state;
proxy()->drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0
// this ensures that we do not recurse in the animation logic above
t->setEndImage(endImage); t->setEndImage(endImage);
HTHEME theme; HTHEME theme;
@ -478,10 +487,15 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
t->setDuration(duration); t->setDuration(duration);
} }
t->setStartTime(QTime::currentTime()); t->setStartTime(QTime::currentTime());
}
}
} // End of animation part
delete styleOption;
d->startAnimation(t);
}
styleObject->setProperty("_q_no_animation", false);
}
} // End of animation part
}
QRect rect = option->rect; QRect rect = option->rect;
@ -546,7 +560,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
case PE_IndicatorCheckBox: case PE_IndicatorCheckBox:
case PE_IndicatorRadioButton: case PE_IndicatorRadioButton:
{ {
if (QWindowsVistaAnimation *a = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget)) ){ if (QWindowsVistaAnimation *a =
qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option)))){
a->paint(painter, option); a->paint(painter, option);
} else { } else {
QWindowsXPStyle::drawPrimitive(element, option, painter, widget); QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
@ -563,14 +578,12 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
d->drawBackground(theme); d->drawBackground(theme);
} }
break; break;
case PE_Frame: case PE_Frame: {
#ifndef QT_NO_TEXTEDIT
if (const QTextEdit *edit = qobject_cast<const QTextEdit*>(widget)) {
painter->save(); painter->save();
int stateId = ETS_NORMAL; int stateId = ETS_NORMAL;
if (!(state & State_Enabled)) if (!(state & State_Enabled))
stateId = ETS_DISABLED; stateId = ETS_DISABLED;
else if (edit->isReadOnly()) else if (state & State_ReadOnly)
stateId = ETS_READONLY; stateId = ETS_READONLY;
else if (state & State_HasFocus) else if (state & State_HasFocus)
stateId = ETS_SELECTED; stateId = ETS_SELECTED;
@ -589,9 +602,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
} }
d->drawBackground(theme); d->drawBackground(theme);
painter->restore(); painter->restore();
} else }
#endif // QT_NO_TEXTEDIT
QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
break; break;
case PE_PanelLineEdit: case PE_PanelLineEdit:
@ -662,7 +673,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
break; break;
case PE_FrameLineEdit: case PE_FrameLineEdit:
if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget))) { if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option)))) {
anim->paint(painter, option); anim->paint(painter, option);
} else { } else {
QPainter *p = painter; QPainter *p = painter;
@ -928,60 +939,74 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
int partId = 0; int partId = 0;
int stateId = 0; int stateId = 0;
if (d->transitionsEnabled() && canAnimate(option))
{
if (element == CE_PushButtonBevel) {
QRect oldRect; QRect oldRect;
QRect newRect; QRect newRect;
if (d->transitionsEnabled() && widget) { QObject *styleObject = option->styleObject;
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
if ((qobject_cast<const QPushButton*>(widget) && element == CE_PushButtonBevel))
{
QWidget *w = const_cast<QWidget *> (widget);
int oldState = w->property("_q_stylestate").toInt();
oldRect = w->property("_q_stylerect").toRect();
newRect = w->rect();
w->setProperty("_q_stylestate", (int)option->state);
w->setProperty("_q_stylerect", w->rect());
bool wasDefault = w->property("_q_isdefault").toBool(); int oldState = styleObject->property("_q_stylestate").toInt();
bool isDefault = button->features & QStyleOptionButton::DefaultButton; oldRect = styleObject->property("_q_stylerect").toRect();
w->setProperty("_q_isdefault", isDefault); newRect = option->rect;
styleObject->setProperty("_q_stylestate", (int)option->state);
styleObject->setProperty("_q_stylerect", option->rect);
bool wasDefault = false;
bool isDefault = false;
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
wasDefault = styleObject->property("_q_isdefault").toBool();
isDefault = button->features & QStyleOptionButton::DefaultButton;
styleObject->setProperty("_q_isdefault", isDefault);
}
bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) || bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
(state & State_On) != (oldState & State_On) || (state & State_On) != (oldState & State_On) ||
(state & State_MouseOver) != (oldState & State_MouseOver)); (state & State_MouseOver) != (oldState & State_MouseOver));
if (oldRect != newRect || (wasDefault && !isDefault)) if (oldRect != newRect || (wasDefault && !isDefault)) {
{
doTransition = false; doTransition = false;
d->stopAnimation(widget); d->stopAnimation(styleObject);
} }
if (doTransition) { if (doTransition) {
styleObject->setProperty("_q_no_animation", true);
QWindowsVistaTransition *t = new QWindowsVistaTransition(styleObject);
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject));
QStyleOption *styleOption = 0;
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option))
styleOption = new QStyleOptionComboBox(*combo);
else if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option))
styleOption = new QStyleOptionButton(*button);
else
styleOption = new QStyleOption(*option);
styleOption->state = (QStyle::State)oldState;
styleOption->rect = QRect(QPoint(0,0), newRect.size());
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget));
QStyleOptionButton opt = *button;
opt.state = (QStyle::State)oldState;
startImage.fill(0); startImage.fill(0);
QWindowsVistaTransition *t = new QWindowsVistaTransition(w);
QPainter startPainter(&startImage); QPainter startPainter(&startImage);
// Use current state of existing animation if already one is running
if (!anim) { if (!anim) {
proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */); proxy()->drawControl(element, styleOption, &startPainter, widget);
} else { } else {
anim->paint(&startPainter, &opt); anim->paint(&startPainter, styleOption);
d->stopAnimation(widget); d->stopAnimation(styleObject);
} }
t->setStartImage(startImage); t->setStartImage(startImage);
d->startAnimation(t); QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
endImage.fill(0); endImage.fill(0);
QPainter endPainter(&endImage); QPainter endPainter(&endImage);
proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */); styleOption->state = option->state;
proxy()->drawControl(element, styleOption, &endPainter, widget);
t->setEndImage(endImage); t->setEndImage(endImage);
int duration = 0; int duration = 0;
HTHEME theme = pOpenThemeData(0, L"Button"); HTHEME theme = pOpenThemeData(0, L"Button");
@ -992,18 +1017,24 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
else else
t->setDuration(0); t->setDuration(0);
t->setStartTime(QTime::currentTime()); t->setStartTime(QTime::currentTime());
styleObject->setProperty("_q_no_animation", false);
delete styleOption;
d->startAnimation(t);
} }
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject));
if (anim) {
anim->paint(painter, option);
return;
} }
} }
} }
switch (element) { switch (element) {
case CE_PushButtonBevel: case CE_PushButtonBevel:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
{ {
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget));
if (anim && (btn->state & State_Enabled)) {
anim->paint(painter, option);
} else {
themeNumber = QWindowsXPStylePrivate::ButtonTheme; themeNumber = QWindowsXPStylePrivate::ButtonTheme;
partId = BP_PUSHBUTTON; partId = BP_PUSHBUTTON;
if (btn->features & QStyleOptionButton::CommandLinkButton) if (btn->features & QStyleOptionButton::CommandLinkButton)
@ -1024,17 +1055,19 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (!justFlat) { if (!justFlat) {
if (widget && d->transitionsEnabled() && (btn->features & QStyleOptionButton::DefaultButton) && if (d->transitionsEnabled() && (btn->features & QStyleOptionButton::DefaultButton) &&
!(state & (State_Sunken | State_On)) && !(state & State_MouseOver) && !(state & (State_Sunken | State_On)) && !(state & State_MouseOver) &&
(state & State_Enabled) && (state & State_Active)) (state & State_Enabled) && (state & State_Active))
{ {
if (!anim && widget) { QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject(option)));
if (!anim) {
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
startImage.fill(0); startImage.fill(0);
QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
alternateImage.fill(0); alternateImage.fill(0);
QWindowsVistaPulse *pulse = new QWindowsVistaPulse(const_cast<QWidget*>(widget)); QWindowsVistaPulse *pulse = new QWindowsVistaPulse(styleObject(option));
QPainter startPainter(&startImage); QPainter startPainter(&startImage);
stateId = PBS_DEFAULTED; stateId = PBS_DEFAULTED;
@ -1061,12 +1094,11 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
} }
} }
else { else {
d->stopAnimation(widget);
XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect); XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
d->drawBackground(theme); d->drawBackground(theme);
} }
} }
}
if (btn->features & QStyleOptionButton::HasMenu) { if (btn->features & QStyleOptionButton::HasMenu) {
int mbiw = 0, mbih = 0; int mbiw = 0, mbih = 0;
XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme, XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme,
@ -1102,10 +1134,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
} }
if (isIndeterminate || (bar->progress > 0 && (bar->progress < bar->maximum) && d->transitionsEnabled())) { if (isIndeterminate || (bar->progress > 0 && (bar->progress < bar->maximum) && d->transitionsEnabled())) {
if (!d->animation(option->styleObject)) if (!d->animation(styleObject(option)))
d->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject)); d->startAnimation(new QProgressStyleAnimation(d->animationFps, styleObject(option)));
} else { } else {
d->stopAnimation(option->styleObject); d->stopAnimation(styleObject(option));
} }
XPThemeData theme(widget, painter, XPThemeData theme(widget, painter,
@ -1116,7 +1148,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QTime current = QTime::currentTime(); QTime current = QTime::currentTime();
if (isIndeterminate) { if (isIndeterminate) {
if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(option->styleObject))) { if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(styleObject(option)))) {
int glowSize = 120; int glowSize = 120;
int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
int animOffset = a->startTime().msecsTo(current) / 4; int animOffset = a->startTime().msecsTo(current) / 4;
@ -1186,7 +1218,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
} }
d->drawBackground(theme); d->drawBackground(theme);
if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(option->styleObject))) { if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(styleObject(option)))) {
int glowSize = 140; int glowSize = 140;
int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
int animOffset = a->startTime().msecsTo(current) / 4; int animOffset = a->startTime().msecsTo(current) / 4;
@ -1195,7 +1227,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (bar->progress < bar->maximum) if (bar->progress < bar->maximum)
a->setStartTime(QTime::currentTime()); a->setStartTime(QTime::currentTime());
else else
d->stopAnimation(option->styleObject); //we stop the glow motion only after it has d->stopAnimation(styleObject(option)); //we stop the glow motion only after it has
//moved out of view //moved out of view
} }
painter->save(); painter->save();
@ -1592,38 +1624,33 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow()) if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
flags |= State_MouseOver; flags |= State_MouseOver;
if (d->transitionsEnabled() && widget) { if (d->transitionsEnabled() && canAnimate(option))
if ((qobject_cast<const QScrollBar *>(widget) && control == CC_ScrollBar)
#ifndef QT_NO_SPINBOX
|| (qobject_cast<const QAbstractSpinBox*>(widget) && control == CC_SpinBox)
#endif // QT_NO_SPINBOX
#ifndef QT_NO_COMBOBOX
|| (qobject_cast<const QComboBox*>(widget) && control == CC_ComboBox)
#endif // QT_NO_COMBOBOX
)
{ {
QWidget *w = const_cast<QWidget *> (widget);
int oldState = w->property("_q_stylestate").toInt(); if (control == CC_ScrollBar || control == CC_SpinBox ) {
int oldActiveControls = w->property("_q_stylecontrols").toInt();
QRect oldRect = w->property("_q_stylerect").toRect(); QObject *styleObject = option->styleObject; // Can be widget or qquickitem
w->setProperty("_q_stylestate", (int)option->state);
w->setProperty("_q_stylecontrols", (int)option->activeSubControls); int oldState = styleObject->property("_q_stylestate").toInt();
w->setProperty("_q_stylerect", w->rect()); int oldActiveControls = styleObject->property("_q_stylecontrols").toInt();
QRect oldRect = styleObject->property("_q_stylerect").toRect();
styleObject->setProperty("_q_stylestate", (int)option->state);
styleObject->setProperty("_q_stylecontrols", (int)option->activeSubControls);
styleObject->setProperty("_q_stylerect", option->rect);
bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) || bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
(state & State_On) != (oldState & State_On) || (state & State_On) != (oldState & State_On) ||
(state & State_MouseOver) != (oldState & State_MouseOver) || (state & State_MouseOver) != (oldState & State_MouseOver) ||
oldActiveControls != option->activeSubControls); oldActiveControls != option->activeSubControls);
if (qstyleoption_cast<const QStyleOptionSlider *>(option)) { if (qstyleoption_cast<const QStyleOptionSlider *>(option)) {
QRect oldSliderPos = w->property("_q_stylesliderpos").toRect(); QRect oldSliderPos = styleObject->property("_q_stylesliderpos").toRect();
QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
w->setProperty("_q_stylesliderpos", currentPos); styleObject->setProperty("_q_stylesliderpos", currentPos);
if (oldSliderPos != currentPos) { if (oldSliderPos != currentPos) {
doTransition = false; doTransition = false;
d->stopAnimation(widget); d->stopAnimation(styleObject);
} }
} else if (control == CC_SpinBox) { } else if (control == CC_SpinBox) {
//spinboxes have a transition when focus changes //spinboxes have a transition when focus changes
@ -1633,58 +1660,51 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
if (oldRect != option->rect) { if (oldRect != option->rect) {
doTransition = false; doTransition = false;
d->stopAnimation(widget); d->stopAnimation(styleObject);
} }
if (doTransition) { if (doTransition) {
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
startImage.fill(0);
QPainter startPainter(&startImage);
QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget));
QWindowsVistaTransition *t = new QWindowsVistaTransition(w);
if (!anim) {
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) {
//Combo boxes are special cased to avoid cleartype issues
startImage.fill(0);
QPainter startPainter(&startImage);
QStyleOptionComboBox startCombo = *combo;
startCombo.state = (QStyle::State)oldState;
startCombo.activeSubControls = (QStyle::SubControl)oldActiveControls;
proxy()->drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */);
t->setStartImage(startImage);
} else if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
//This is a workaround for the direct3d engine as it currently has some issues with grabWindow
startImage.fill(0);
QPainter startPainter(&startImage);
QStyleOptionSlider startSlider = *slider;
startSlider.state = (QStyle::State)oldState;
startSlider.activeSubControls = (QStyle::SubControl)oldActiveControls;
proxy()->drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */);
t->setStartImage(startImage);
} else {
QPoint offset(0, 0);
QWindow *window = widget->windowHandle();
if (!window) {
if (const QWidget *nativeParent = widget->nativeParentWidget()) {
offset = widget->mapTo(nativeParent, offset);
window = nativeParent->windowHandle();
}
}
if (window && window->handle()) {
const QPixmap pixmap = window->screen()->grabWindow(window->winId(),
offset.x(), offset.y(), option->rect.width(), option->rect.height());
t->setStartImage(pixmap.toImage());
}
}
} else {
startImage.fill(0);
QPainter startPainter(&startImage);
anim->paint(&startPainter, option);
t->setStartImage(startImage);
}
d->startAnimation(t);
endImage.fill(0); endImage.fill(0);
QPainter endPainter(&endImage); QPainter endPainter(&endImage);
proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject));
QWindowsVistaTransition *t = new QWindowsVistaTransition(styleObject);
// Draw the image that ends the animation by using the current styleoption
QStyleOptionComplex *styleOption = 0;
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option))
styleOption = new QStyleOptionSlider(*slider);
else if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox*>(option))
styleOption = new QStyleOptionSpinBox(*spinbox);
else
styleOption = new QStyleOptionComplex(*option);
styleOption->rect = QRect(QPoint(0,0), option->rect.size());
styleObject->setProperty("_q_no_animation", true);
// Draw transition source
if (!anim) {
styleOption->state = (QStyle::State)oldState;
styleOption->activeSubControls = (QStyle::SubControl)oldActiveControls;
proxy()->drawComplexControl(control, styleOption, &startPainter, widget);
} else {
anim->paint(&startPainter, option);
}
t->setStartImage(startImage);
// Draw transition target
styleOption->state = option->state;
styleOption->activeSubControls = option->activeSubControls;
proxy()->drawComplexControl(control, styleOption, &endPainter, widget);
styleObject->setProperty("_q_no_animation", false);
t->setEndImage(endImage); t->setEndImage(endImage);
t->setStartTime(QTime::currentTime()); t->setStartTime(QTime::currentTime());
@ -1692,13 +1712,14 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
t->setDuration(150); t->setDuration(150);
else else
t->setDuration(500); t->setDuration(500);
}
if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget))) { delete styleOption;
d->startAnimation(t);
}
if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject))) {
anim->paint(painter, option); anim->paint(painter, option);
return; return;
} }
} }
} }