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,135 +367,135 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
return; return;
} }
QRect oldRect; if (d->transitionsEnabled() && canAnimate(option)) {
QRect newRect;
if (widget && d->transitionsEnabled())
{
/* all widgets that supports state transitions : */
if (
#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 QRect oldRect;
// the previous state of the widget: QRect newRect;
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 doTransition = oldState && /* widgets that support state transitions : */
((state & State_Sunken) != (oldState & State_Sunken) || if ( element == PE_FrameLineEdit
(state & State_On) != (oldState & State_On) || || element == PE_IndicatorRadioButton
(state & State_MouseOver) != (oldState & State_MouseOver)); || element == PE_IndicatorCheckBox)
{
// Retrieve and update the dynamic properties tracking
// the previous state of the widget:
QObject *styleObject = option->styleObject;
styleObject->setProperty("_q_no_animation", true);
if (oldRect != newRect || int oldState = styleObject->property("_q_stylestate").toInt();
(state & State_Enabled) != (oldState & State_Enabled) || oldRect = styleObject->property("_q_stylerect").toRect();
(state & State_Active) != (oldState & State_Active)) newRect = option->rect;
d->stopAnimation(widget); styleObject->setProperty("_q_stylestate", (int)option->state);
styleObject->setProperty("_q_stylerect", option->rect);
#ifndef QT_NO_LINEEDIT bool doTransition = oldState &&
if (const QLineEdit *edit = qobject_cast<const QLineEdit *>(widget)) ((state & State_Sunken) != (oldState & State_Sunken) ||
if (edit->isReadOnly() && element == PE_FrameLineEdit) // Do not animate read only line edits (state & State_On) != (oldState & State_On) ||
(state & State_MouseOver) != (oldState & State_MouseOver));
if (oldRect != newRect ||
(state & State_Enabled) != (oldState & State_Enabled) ||
(state & State_Active) != (oldState & State_Active))
d->stopAnimation(styleObject);
if (option->state & State_ReadOnly && 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;
// We create separate images for the initial and final transition states and store them in the if (const QStyleOptionGroupBox *combo = qstyleoption_cast<const QStyleOptionGroupBox*>(option))
// Transition object. styleOption = new QStyleOptionGroupBox(*combo);
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);
QPainter startPainter(&startImage);
QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget));
QWindowsVistaTransition *t = new QWindowsVistaTransition(w);
// 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
// pulsating default button into the intended target state.
if (!anim)
proxy()->drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0
else // this ensures that we do not recurse in the animation logic above
anim->paint(&startPainter, &opt);
d->startAnimation(t);
t->setStartImage(startImage);
// The end state of the transition is simply the result we would have painted
// if the style was not animated.
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);
HTHEME theme;
int partId;
int duration;
int fromState = 0;
int toState = 0;
//translate state flags to UXTHEME states :
if (element == PE_FrameLineEdit) {
theme = pOpenThemeData(0, L"Edit");
partId = EP_EDITBORDER_NOSCROLL;
if (oldState & State_MouseOver)
fromState = ETS_HOT;
else if (oldState & State_HasFocus)
fromState = ETS_FOCUSED;
else else
fromState = ETS_NORMAL; styleOption = new QStyleOption(*option);
if (state & State_MouseOver) styleOption->state = (QStyle::State)oldState;
toState = ETS_HOT; styleOption->rect = QRect(QPoint(0,0), newRect.size());
else if (state & State_HasFocus)
toState = ETS_FOCUSED; 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
// Transition object.
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
startImage.fill(0);
QPainter startPainter(&startImage);
QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
endImage.fill(0);
QPainter endPainter(&endImage);
// 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
// pulsating default button into the intended target state.
if (!anim)
proxy()->drawPrimitive(element, styleOption, &startPainter, widget);
else else
toState = ETS_NORMAL; anim->paint(&startPainter, styleOption);
} else { t->setStartImage(startImage);
theme = pOpenThemeData(0, L"Button");
if (element == PE_IndicatorRadioButton)
partId = BP_RADIOBUTTON;
else if (element == PE_IndicatorCheckBox)
partId = BP_CHECKBOX;
else
partId = BP_PUSHBUTTON;
fromState = buttonStateId(oldState, partId); // The end state of the transition is simply the result we would have painted
toState = buttonStateId(option->state, partId); // if the style was not animated.
styleOption->state = option->state;
drawPrimitive(element, styleOption, &endPainter, widget);
t->setEndImage(endImage);
HTHEME theme;
int partId;
int duration;
int fromState = 0;
int toState = 0;
//translate state flags to UXTHEME states :
if (element == PE_FrameLineEdit) {
theme = pOpenThemeData(0, L"Edit");
partId = EP_EDITBORDER_NOSCROLL;
if (oldState & State_MouseOver)
fromState = ETS_HOT;
else if (oldState & State_HasFocus)
fromState = ETS_FOCUSED;
else
fromState = ETS_NORMAL;
if (state & State_MouseOver)
toState = ETS_HOT;
else if (state & State_HasFocus)
toState = ETS_FOCUSED;
else
toState = ETS_NORMAL;
} else {
theme = pOpenThemeData(0, L"Button");
if (element == PE_IndicatorRadioButton)
partId = BP_RADIOBUTTON;
else if (element == PE_IndicatorCheckBox)
partId = BP_CHECKBOX;
else
partId = BP_PUSHBUTTON;
fromState = buttonStateId(oldState, partId);
toState = buttonStateId(option->state, partId);
}
// Retrieve the transition time between the states from the system.
if (theme && pGetThemeTransitionDuration(theme, partId, fromState, toState,
TMT_TRANSITIONDURATIONS, &duration) == S_OK)
{
t->setDuration(duration);
}
t->setStartTime(QTime::currentTime());
delete styleOption;
d->startAnimation(t);
} }
styleObject->setProperty("_q_no_animation", false);
// Retrieve the transition time between the states from the system.
if (theme && pGetThemeTransitionDuration(theme, partId, fromState, toState,
TMT_TRANSITIONDURATIONS, &duration) == S_OK)
{
t->setDuration(duration);
}
t->setStartTime(QTime::currentTime());
} }
}
} // End of animation part
} // 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,36 +578,32 @@ 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 painter->save();
if (const QTextEdit *edit = qobject_cast<const QTextEdit*>(widget)) { int stateId = ETS_NORMAL;
painter->save(); if (!(state & State_Enabled))
int stateId = ETS_NORMAL; stateId = ETS_DISABLED;
if (!(state & State_Enabled)) else if (state & State_ReadOnly)
stateId = ETS_DISABLED; stateId = ETS_READONLY;
else if (edit->isReadOnly()) else if (state & State_HasFocus)
stateId = ETS_READONLY; stateId = ETS_SELECTED;
else if (state & State_HasFocus) XPThemeData theme(widget, painter,
stateId = ETS_SELECTED; QWindowsXPStylePrivate::EditTheme,
XPThemeData theme(widget, painter, EP_EDITBORDER_HVSCROLL, stateId, option->rect);
QWindowsXPStylePrivate::EditTheme, uint resolve_mask = option->palette.resolve();
EP_EDITBORDER_HVSCROLL, stateId, option->rect); if (resolve_mask & (1 << QPalette::Base)) {
uint resolve_mask = option->palette.resolve(); // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping
if (resolve_mask & (1 << QPalette::Base)) { int borderSize = 1;
// Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize);
int borderSize = 1; QRegion clipRegion = option->rect;
pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize);
QRegion clipRegion = option->rect; clipRegion ^= content;
QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize); painter->setClipRegion(clipRegion);
clipRegion ^= content; }
painter->setClipRegion(clipRegion); d->drawBackground(theme);
} painter->restore();
d->drawBackground(theme); }
painter->restore(); break;
} else
#endif // QT_NO_TEXTEDIT
QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
break;
case PE_PanelLineEdit: case PE_PanelLineEdit:
if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) { if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
@ -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,145 +939,166 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
int partId = 0; int partId = 0;
int stateId = 0; int stateId = 0;
QRect oldRect; if (d->transitionsEnabled() && canAnimate(option))
QRect newRect; {
if (element == CE_PushButtonBevel) {
QRect oldRect;
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 doTransition = ((state & State_Sunken) != (oldState & State_Sunken) || bool wasDefault = false;
(state & State_On) != (oldState & State_On) || bool isDefault = false;
(state & State_MouseOver) != (oldState & State_MouseOver)); if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
wasDefault = styleObject->property("_q_isdefault").toBool();
if (oldRect != newRect || (wasDefault && !isDefault)) isDefault = button->features & QStyleOptionButton::DefaultButton;
{ styleObject->setProperty("_q_isdefault", isDefault);
doTransition = false;
d->stopAnimation(widget);
}
if (doTransition) {
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);
QWindowsVistaTransition *t = new QWindowsVistaTransition(w);
QPainter startPainter(&startImage);
if (!anim) {
proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */);
} else {
anim->paint(&startPainter, &opt);
d->stopAnimation(widget);
}
t->setStartImage(startImage);
d->startAnimation(t);
endImage.fill(0);
QPainter endPainter(&endImage);
proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */);
t->setEndImage(endImage);
int duration = 0;
HTHEME theme = pOpenThemeData(0, L"Button");
int fromState = buttonStateId(oldState, BP_PUSHBUTTON);
int toState = buttonStateId(option->state, BP_PUSHBUTTON);
if (pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK)
t->setDuration(duration);
else
t->setDuration(0);
t->setStartTime(QTime::currentTime());
}
} }
bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
(state & State_On) != (oldState & State_On) ||
(state & State_MouseOver) != (oldState & State_MouseOver));
if (oldRect != newRect || (wasDefault && !isDefault)) {
doTransition = false;
d->stopAnimation(styleObject);
}
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);
startImage.fill(0);
QPainter startPainter(&startImage);
// Use current state of existing animation if already one is running
if (!anim) {
proxy()->drawControl(element, styleOption, &startPainter, widget);
} else {
anim->paint(&startPainter, styleOption);
d->stopAnimation(styleObject);
}
t->setStartImage(startImage);
QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
endImage.fill(0);
QPainter endPainter(&endImage);
styleOption->state = option->state;
proxy()->drawControl(element, styleOption, &endPainter, widget);
t->setEndImage(endImage);
int duration = 0;
HTHEME theme = pOpenThemeData(0, L"Button");
int fromState = buttonStateId(oldState, BP_PUSHBUTTON);
int toState = buttonStateId(option->state, BP_PUSHBUTTON);
if (pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK)
t->setDuration(duration);
else
t->setDuration(0);
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)); themeNumber = QWindowsXPStylePrivate::ButtonTheme;
if (anim && (btn->state & State_Enabled)) { partId = BP_PUSHBUTTON;
anim->paint(painter, option); if (btn->features & QStyleOptionButton::CommandLinkButton)
} else { partId = BP_COMMANDLINK;
themeNumber = QWindowsXPStylePrivate::ButtonTheme; bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken));
partId = BP_PUSHBUTTON; if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat))
if (btn->features & QStyleOptionButton::CommandLinkButton) stateId = PBS_DISABLED;
partId = BP_COMMANDLINK; else if (justFlat)
bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken)); ;
if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat)) else if (flags & (State_Sunken | State_On))
stateId = PBS_DISABLED; stateId = PBS_PRESSED;
else if (justFlat) else if (flags & State_MouseOver)
; stateId = PBS_HOT;
else if (flags & (State_Sunken | State_On)) else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active))
stateId = PBS_PRESSED; stateId = PBS_DEFAULTED;
else if (flags & State_MouseOver) else
stateId = PBS_HOT; stateId = PBS_NORMAL;
else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active))
stateId = PBS_DEFAULTED;
else
stateId = PBS_NORMAL;
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)));
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
startImage.fill(0);
QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
alternateImage.fill(0);
QWindowsVistaPulse *pulse = new QWindowsVistaPulse(const_cast<QWidget*>(widget)); if (!anim) {
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
startImage.fill(0);
QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
alternateImage.fill(0);
QPainter startPainter(&startImage); QWindowsVistaPulse *pulse = new QWindowsVistaPulse(styleObject(option));
stateId = PBS_DEFAULTED;
XPThemeData theme(widget, &startPainter, themeNumber, partId, stateId, rect);
d->drawBackground(theme);
QPainter alternatePainter(&alternateImage); QPainter startPainter(&startImage);
theme.stateId = PBS_DEFAULTED_ANIMATING; stateId = PBS_DEFAULTED;
theme.painter = &alternatePainter; XPThemeData theme(widget, &startPainter, themeNumber, partId, stateId, rect);
d->drawBackground(theme); d->drawBackground(theme);
pulse->setPrimaryImage(startImage);
pulse->setAlternateImage(alternateImage);
pulse->setStartTime(QTime::currentTime());
pulse->setDuration(2000);
d->startAnimation(pulse);
anim = pulse;
}
if (anim) QPainter alternatePainter(&alternateImage);
anim->paint(painter, option); theme.stateId = PBS_DEFAULTED_ANIMATING;
else { theme.painter = &alternatePainter;
XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect); d->drawBackground(theme);
d->drawBackground(theme); pulse->setPrimaryImage(startImage);
} pulse->setAlternateImage(alternateImage);
pulse->setStartTime(QTime::currentTime());
pulse->setDuration(2000);
d->startAnimation(pulse);
anim = pulse;
} }
if (anim)
anim->paint(painter, option);
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);
} }
} }
else {
XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect);
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;
} }
} }
} }