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:
parent
38630bc35a
commit
79a389c346
@ -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<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)
|
||||
)
|
||||
if (d->transitionsEnabled() && canAnimate(option)) {
|
||||
{
|
||||
// Retrieve and update the dynamic properties tracking
|
||||
// the previous state of the widget:
|
||||
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());
|
||||
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<const QLineEdit *>(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<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;
|
||||
if (doTransition) {
|
||||
QStyleOption *styleOption = 0;
|
||||
if (const QStyleOptionGroupBox *combo = qstyleoption_cast<const QStyleOptionGroupBox*>(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<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
|
||||
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<QWindowsVistaAnimation *>(d->animation(widget)) ){
|
||||
if (QWindowsVistaAnimation *a =
|
||||
qobject_cast<QWindowsVistaAnimation *>(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<const QTextEdit*>(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<const QStyleOptionFrame *>(option)) {
|
||||
@ -662,7 +673,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
|
||||
break;
|
||||
|
||||
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);
|
||||
} 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<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());
|
||||
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<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 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) ||
|
||||
(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) {
|
||||
case CE_PushButtonBevel:
|
||||
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;
|
||||
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<QWindowsVistaAnimation *>(d->animation(styleObject(option)));
|
||||
|
||||
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);
|
||||
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<QProgressStyleAnimation *>(d->animation(option->styleObject))) {
|
||||
if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(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<QProgressStyleAnimation *>(d->animation(option->styleObject))) {
|
||||
if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(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<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);
|
||||
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<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);
|
||||
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<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);
|
||||
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->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<QWindowsVistaAnimation *>(d->animation(widget))) {
|
||||
delete styleOption;
|
||||
d->startAnimation(t);
|
||||
}
|
||||
if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(styleObject))) {
|
||||
anim->paint(painter, option);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user