diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index d58e76e0431..87c67dc84be 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -144,6 +144,20 @@ bool QWindowsVistaStylePrivate::useVista() (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 \brief The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows Vista. @@ -328,17 +342,17 @@ void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option) transition has completed. During this time, the result will be retrieved by the Animation::paint(...) function and not by the style itself. - + To determine if a transition should occur, the style needs to know the previous state of the widget as well as the current one. This is solved by updating dynamic properties on the widget every time the function is called. - + Transitions interrupting existing transitions should always be smooth, so whenever a hover-transition is started on a pulsating button, it uses the current frame of the pulse-animation as the starting image for the hover transition. - + */ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const @@ -353,135 +367,135 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt return; } - QRect oldRect; - QRect newRect; - - if (widget && d->transitionsEnabled()) - { - /* all widgets that supports state transitions : */ - if ( -#ifndef QT_NO_LINEEDIT - (qobject_cast(widget) && element == PE_FrameLineEdit) || -#endif // QT_NO_LINEEDIT - (qobject_cast(widget)&& element == PE_IndicatorRadioButton) || - (qobject_cast(widget) && element == PE_IndicatorCheckBox) || - (qobject_cast(widget)&& element == PE_IndicatorCheckBox) || - (qobject_cast(widget) && element == PE_PanelButtonBevel) - ) + if (d->transitionsEnabled() && canAnimate(option)) { { - // Retrieve and update the dynamic properties tracking - // the previous state of the widget: - QWidget *w = const_cast (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()); + QRect oldRect; + QRect newRect; - bool doTransition = oldState && - ((state & State_Sunken) != (oldState & State_Sunken) || - (state & State_On) != (oldState & State_On) || - (state & State_MouseOver) != (oldState & State_MouseOver)); + /* widgets that support state transitions : */ + if ( element == PE_FrameLineEdit + || element == PE_IndicatorRadioButton + || 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 || - (state & State_Enabled) != (oldState & State_Enabled) || - (state & State_Active) != (oldState & State_Active)) - d->stopAnimation(widget); + int oldState = styleObject->property("_q_stylestate").toInt(); + oldRect = styleObject->property("_q_stylerect").toRect(); + newRect = option->rect; + styleObject->setProperty("_q_stylestate", (int)option->state); + styleObject->setProperty("_q_stylerect", option->rect); -#ifndef QT_NO_LINEEDIT - if (const QLineEdit *edit = qobject_cast(widget)) - if (edit->isReadOnly() && element == PE_FrameLineEdit) // Do not animate read only line edits + bool doTransition = oldState && + ((state & State_Sunken) != (oldState & State_Sunken) || + (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; -#endif // QT_NO_LINEEDIT - if (doTransition) { - - // 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); - 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(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; + if (doTransition) { + QStyleOption *styleOption = 0; + if (const QStyleOptionGroupBox *combo = qstyleoption_cast(option)) + styleOption = new QStyleOptionGroupBox(*combo); else - fromState = ETS_NORMAL; + styleOption = new QStyleOption(*option); - if (state & State_MouseOver) - toState = ETS_HOT; - else if (state & State_HasFocus) - toState = ETS_FOCUSED; + styleOption->state = (QStyle::State)oldState; + styleOption->rect = QRect(QPoint(0,0), newRect.size()); + + QWindowsVistaAnimation *anim = qobject_cast(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 - toState = ETS_NORMAL; + anim->paint(&startPainter, styleOption); - } 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; + t->setStartImage(startImage); - fromState = buttonStateId(oldState, partId); - toState = buttonStateId(option->state, partId); + // The end state of the transition is simply the result we would have painted + // 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); } - - // 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()); + styleObject->setProperty("_q_no_animation", false); } - } - } // End of animation part + } // End of animation part + } QRect rect = option->rect; @@ -546,7 +560,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt case PE_IndicatorCheckBox: case PE_IndicatorRadioButton: { - if (QWindowsVistaAnimation *a = qobject_cast(d->animation(widget)) ){ + if (QWindowsVistaAnimation *a = + qobject_cast(d->animation(styleObject(option)))){ a->paint(painter, option); } else { QWindowsXPStyle::drawPrimitive(element, option, painter, widget); @@ -563,36 +578,32 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt d->drawBackground(theme); } break; - case PE_Frame: -#ifndef QT_NO_TEXTEDIT - if (const QTextEdit *edit = qobject_cast(widget)) { - painter->save(); - int stateId = ETS_NORMAL; - if (!(state & State_Enabled)) - stateId = ETS_DISABLED; - else if (edit->isReadOnly()) - stateId = ETS_READONLY; - else if (state & State_HasFocus) - stateId = ETS_SELECTED; - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::EditTheme, - EP_EDITBORDER_HVSCROLL, stateId, option->rect); - uint resolve_mask = option->palette.resolve(); - if (resolve_mask & (1 << QPalette::Base)) { - // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping - int borderSize = 1; - pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); - QRegion clipRegion = option->rect; - QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize); - clipRegion ^= content; - painter->setClipRegion(clipRegion); - } - d->drawBackground(theme); - painter->restore(); - } else -#endif // QT_NO_TEXTEDIT - QWindowsXPStyle::drawPrimitive(element, option, painter, widget); - break; + case PE_Frame: { + painter->save(); + int stateId = ETS_NORMAL; + if (!(state & State_Enabled)) + stateId = ETS_DISABLED; + else if (state & State_ReadOnly) + stateId = ETS_READONLY; + else if (state & State_HasFocus) + stateId = ETS_SELECTED; + XPThemeData theme(widget, painter, + QWindowsXPStylePrivate::EditTheme, + EP_EDITBORDER_HVSCROLL, stateId, option->rect); + uint resolve_mask = option->palette.resolve(); + if (resolve_mask & (1 << QPalette::Base)) { + // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping + int borderSize = 1; + pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); + QRegion clipRegion = option->rect; + QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize); + clipRegion ^= content; + painter->setClipRegion(clipRegion); + } + d->drawBackground(theme); + painter->restore(); + } + break; case PE_PanelLineEdit: if (const QStyleOptionFrame *panel = qstyleoption_cast(option)) { @@ -662,7 +673,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt break; case PE_FrameLineEdit: - if (QWindowsVistaAnimation *anim = qobject_cast(d->animation(widget))) { + if (QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject(option)))) { anim->paint(painter, option); } else { QPainter *p = painter; @@ -928,145 +939,166 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption int partId = 0; int stateId = 0; - QRect oldRect; - QRect newRect; + if (d->transitionsEnabled() && canAnimate(option)) + { + if (element == CE_PushButtonBevel) { + QRect oldRect; + QRect newRect; - if (d->transitionsEnabled() && widget) { - if (const QStyleOptionButton *button = qstyleoption_cast(option)) { - if ((qobject_cast(widget) && element == CE_PushButtonBevel)) - { - QWidget *w = const_cast (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()); + QObject *styleObject = option->styleObject; - bool wasDefault = w->property("_q_isdefault").toBool(); - bool isDefault = button->features & QStyleOptionButton::DefaultButton; - w->setProperty("_q_isdefault", isDefault); + int oldState = styleObject->property("_q_stylestate").toInt(); + oldRect = styleObject->property("_q_stylerect").toRect(); + newRect = option->rect; + styleObject->setProperty("_q_stylestate", (int)option->state); + styleObject->setProperty("_q_stylerect", option->rect); - 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(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(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 wasDefault = false; + bool isDefault = false; + if (const QStyleOptionButton *button = qstyleoption_cast(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) || + (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(d->animation(styleObject)); + QStyleOption *styleOption = 0; + if (const QStyleOptionComboBox *combo = qstyleoption_cast(option)) + styleOption = new QStyleOptionComboBox(*combo); + else if (const QStyleOptionButton *button = qstyleoption_cast(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(d->animation(styleObject)); + if (anim) { + anim->paint(painter, option); + return; + } + } } switch (element) { case CE_PushButtonBevel: if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { - QWindowsVistaAnimation *anim = qobject_cast(d->animation(widget)); - if (anim && (btn->state & State_Enabled)) { - anim->paint(painter, option); - } else { - themeNumber = QWindowsXPStylePrivate::ButtonTheme; - partId = BP_PUSHBUTTON; - if (btn->features & QStyleOptionButton::CommandLinkButton) - partId = BP_COMMANDLINK; - bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken)); - if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat)) - stateId = PBS_DISABLED; - else if (justFlat) - ; - else if (flags & (State_Sunken | State_On)) - stateId = PBS_PRESSED; - else if (flags & State_MouseOver) - stateId = PBS_HOT; - else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active)) - stateId = PBS_DEFAULTED; - else - stateId = PBS_NORMAL; + themeNumber = QWindowsXPStylePrivate::ButtonTheme; + partId = BP_PUSHBUTTON; + if (btn->features & QStyleOptionButton::CommandLinkButton) + partId = BP_COMMANDLINK; + bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken)); + if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat)) + stateId = PBS_DISABLED; + else if (justFlat) + ; + else if (flags & (State_Sunken | State_On)) + stateId = PBS_PRESSED; + else if (flags & State_MouseOver) + stateId = PBS_HOT; + 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_Enabled) && (state & State_Active)) - { - if (!anim && widget) { - QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - startImage.fill(0); - QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - alternateImage.fill(0); + (state & State_Enabled) && (state & State_Active)) + { + QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject(option))); - QWindowsVistaPulse *pulse = new QWindowsVistaPulse(const_cast(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); - stateId = PBS_DEFAULTED; - XPThemeData theme(widget, &startPainter, themeNumber, partId, stateId, rect); - d->drawBackground(theme); + QWindowsVistaPulse *pulse = new QWindowsVistaPulse(styleObject(option)); - QPainter alternatePainter(&alternateImage); - theme.stateId = PBS_DEFAULTED_ANIMATING; - theme.painter = &alternatePainter; - d->drawBackground(theme); - pulse->setPrimaryImage(startImage); - pulse->setAlternateImage(alternateImage); - pulse->setStartTime(QTime::currentTime()); - pulse->setDuration(2000); - d->startAnimation(pulse); - anim = pulse; - } + QPainter startPainter(&startImage); + stateId = PBS_DEFAULTED; + XPThemeData theme(widget, &startPainter, themeNumber, partId, stateId, rect); + d->drawBackground(theme); - if (anim) - anim->paint(painter, option); - else { - XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect); - d->drawBackground(theme); - } + QPainter alternatePainter(&alternateImage); + theme.stateId = PBS_DEFAULTED_ANIMATING; + theme.painter = &alternatePainter; + 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 { - d->stopAnimation(widget); XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect); d->drawBackground(theme); } } + else { + XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect); + d->drawBackground(theme); + } } + if (btn->features & QStyleOptionButton::HasMenu) { int mbiw = 0, mbih = 0; 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 (!d->animation(option->styleObject)) - d->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject)); + if (!d->animation(styleObject(option))) + d->startAnimation(new QProgressStyleAnimation(d->animationFps, styleObject(option))); } else { - d->stopAnimation(option->styleObject); + d->stopAnimation(styleObject(option)); } XPThemeData theme(widget, painter, @@ -1116,7 +1148,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QTime current = QTime::currentTime(); if (isIndeterminate) { - if (QProgressStyleAnimation *a = qobject_cast(d->animation(option->styleObject))) { + if (QProgressStyleAnimation *a = qobject_cast(d->animation(styleObject(option)))) { int glowSize = 120; int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); int animOffset = a->startTime().msecsTo(current) / 4; @@ -1186,7 +1218,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } d->drawBackground(theme); - if (QProgressStyleAnimation *a = qobject_cast(d->animation(option->styleObject))) { + if (QProgressStyleAnimation *a = qobject_cast(d->animation(styleObject(option)))) { int glowSize = 140; int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); int animOffset = a->startTime().msecsTo(current) / 4; @@ -1195,7 +1227,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption if (bar->progress < bar->maximum) a->setStartTime(QTime::currentTime()); 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 } painter->save(); @@ -1592,38 +1624,33 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow()) flags |= State_MouseOver; - if (d->transitionsEnabled() && widget) { - if ((qobject_cast(widget) && control == CC_ScrollBar) -#ifndef QT_NO_SPINBOX - || (qobject_cast(widget) && control == CC_SpinBox) -#endif // QT_NO_SPINBOX -#ifndef QT_NO_COMBOBOX - || (qobject_cast(widget) && control == CC_ComboBox) -#endif // QT_NO_COMBOBOX - ) - { - QWidget *w = const_cast (widget); + if (d->transitionsEnabled() && canAnimate(option)) + { - int oldState = w->property("_q_stylestate").toInt(); - int oldActiveControls = w->property("_q_stylecontrols").toInt(); - QRect oldRect = w->property("_q_stylerect").toRect(); - w->setProperty("_q_stylestate", (int)option->state); - w->setProperty("_q_stylecontrols", (int)option->activeSubControls); - w->setProperty("_q_stylerect", w->rect()); + if (control == CC_ScrollBar || control == CC_SpinBox ) { + + QObject *styleObject = option->styleObject; // Can be widget or qquickitem + + int oldState = styleObject->property("_q_stylestate").toInt(); + 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) || (state & State_On) != (oldState & State_On) || (state & State_MouseOver) != (oldState & State_MouseOver) || - oldActiveControls != option->activeSubControls); - + oldActiveControls != option->activeSubControls); if (qstyleoption_cast(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); - w->setProperty("_q_stylesliderpos", currentPos); + styleObject->setProperty("_q_stylesliderpos", currentPos); if (oldSliderPos != currentPos) { doTransition = false; - d->stopAnimation(widget); + d->stopAnimation(styleObject); } } else if (control == CC_SpinBox) { //spinboxes have a transition when focus changes @@ -1633,58 +1660,51 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle if (oldRect != option->rect) { doTransition = false; - d->stopAnimation(widget); + d->stopAnimation(styleObject); } if (doTransition) { QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + startImage.fill(0); + QPainter startPainter(&startImage); + QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - QWindowsVistaAnimation *anim = qobject_cast(d->animation(widget)); - QWindowsVistaTransition *t = new QWindowsVistaTransition(w); - if (!anim) { - if (const QStyleOptionComboBox *combo = qstyleoption_cast(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(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); QPainter endPainter(&endImage); - proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */); + + QWindowsVistaAnimation *anim = qobject_cast(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(option)) + styleOption = new QStyleOptionSlider(*slider); + else if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(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->setStartTime(QTime::currentTime()); @@ -1692,13 +1712,14 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle t->setDuration(150); else t->setDuration(500); - } - if (QWindowsVistaAnimation *anim = qobject_cast(d->animation(widget))) { + delete styleOption; + d->startAnimation(t); + } + if (QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject))) { anim->paint(painter, option); return; } - } }