fix various handle regressions, including:
* move applet or resize it then move with handle and it pops to a new location * handles unhover too soon * handles don't show on the correct side always * handles are not visually associated well enough with the target applet * icons are hard to see BUG:166149 svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=830264
This commit is contained in:
parent
c89d4239d7
commit
6d5e0b18f5
151
applethandle.cpp
151
applethandle.cpp
@ -47,7 +47,7 @@ namespace Plasma
|
||||
|
||||
qreal _k_angleForPoints(const QPointF ¢er, const QPointF &pt1, const QPointF &pt2);
|
||||
|
||||
AppletHandle::AppletHandle(Containment *parent, Applet *applet)
|
||||
AppletHandle::AppletHandle(Containment *parent, Applet *applet, const QPointF &hoverPos)
|
||||
: QObject(),
|
||||
QGraphicsItem(parent),
|
||||
m_pressedButton(NoButton),
|
||||
@ -62,12 +62,15 @@ AppletHandle::AppletHandle(Containment *parent, Applet *applet)
|
||||
m_scaleHeight(1.0),
|
||||
m_buttonsOnRight(false),
|
||||
m_pendingFade(false),
|
||||
m_topview(0)
|
||||
m_topview(0),
|
||||
m_entryPos(hoverPos)
|
||||
{
|
||||
KColorScheme colorScheme(QPalette::Active, KColorScheme::View, Theme::defaultTheme()->colorScheme());
|
||||
m_gradientColor = colorScheme.background(KColorScheme::NormalBackground).color();
|
||||
|
||||
QTransform originalMatrix = m_applet->transform();
|
||||
m_applet->resetTransform();
|
||||
|
||||
QRectF rect(m_applet->contentsRect());
|
||||
QPointF center = rect.center();
|
||||
originalMatrix.translate(center.x(), center.y());
|
||||
@ -79,9 +82,6 @@ AppletHandle::AppletHandle(Containment *parent, Applet *applet)
|
||||
QPointF(1, 0),
|
||||
QPointF(cosine, sine));
|
||||
|
||||
m_applet->resetTransform();
|
||||
|
||||
calculateSize();
|
||||
m_applet->setParentItem(this);
|
||||
|
||||
rect = QRectF(m_applet->pos(), m_applet->size());
|
||||
@ -91,6 +91,7 @@ AppletHandle::AppletHandle(Containment *parent, Applet *applet)
|
||||
matrix.rotateRadians(m_angle);
|
||||
matrix.translate(-center.x(), -center.y());
|
||||
setTransform(matrix);
|
||||
|
||||
m_hoverTimer = new QTimer(this);
|
||||
m_hoverTimer->setSingleShot(true);
|
||||
m_hoverTimer->setInterval(333);
|
||||
@ -165,6 +166,31 @@ QPainterPath AppletHandle::shape() const
|
||||
}
|
||||
}
|
||||
|
||||
QPainterPath handleRect(const QRectF &rect, int radius, bool onRight)
|
||||
{
|
||||
QPainterPath path;
|
||||
if (onRight) {
|
||||
// make the left side straight
|
||||
path.moveTo(rect.left(), rect.top()); // Top left
|
||||
path.lineTo(rect.right() - radius, rect.top()); // Top side
|
||||
path.quadTo(rect.right(), rect.top(), rect.right(), rect.top() + radius); // Top right corner
|
||||
path.lineTo(rect.right(), rect.bottom() - radius); // Right side
|
||||
path.quadTo(rect.right(), rect.bottom(), rect.right() - radius, rect.bottom()); // Bottom right corner
|
||||
path.lineTo(rect.left(), rect.bottom()); // Bottom side
|
||||
} else {
|
||||
// make the right side straight
|
||||
path.moveTo(QPointF(rect.left(), rect.top() + radius));
|
||||
path.quadTo(rect.left(), rect.top(), rect.left() + radius, rect.top()); // Top left corner
|
||||
path.lineTo(rect.right(), rect.top()); // Top side
|
||||
path.lineTo(rect.right(), rect.bottom()); // Right side
|
||||
path.lineTo(rect.left() + radius, rect.bottom()); // Bottom side
|
||||
path.quadTo(rect.left(), rect.bottom(), rect.left(), rect.bottom() - radius); // Bottom left corner
|
||||
}
|
||||
|
||||
path.closeSubpath();
|
||||
return path;
|
||||
}
|
||||
|
||||
void AppletHandle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(option);
|
||||
@ -174,11 +200,11 @@ void AppletHandle::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
painter->setOpacity(m_opacity);
|
||||
|
||||
painter->save();
|
||||
painter->setOpacity(m_opacity * 0.3);
|
||||
painter->setOpacity(m_opacity * 0.8);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setRenderHints(QPainter::Antialiasing);
|
||||
|
||||
QPainterPath path = PaintUtils::roundedRectangle(m_rect, 10);
|
||||
QPainterPath path = handleRect(m_rect, 10, m_buttonsOnRight);
|
||||
painter->strokePath(path, m_gradientColor);
|
||||
painter->fillPath(path, m_gradientColor.lighter());
|
||||
painter->restore();
|
||||
@ -222,10 +248,7 @@ void AppletHandle::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
painter->drawPixmap(basePoint + shiftC, KIcon("configure").pixmap(ICON_SIZE, ICON_SIZE));
|
||||
}
|
||||
|
||||
//add one step to let space so the user can move the applet
|
||||
basePoint += step;
|
||||
|
||||
basePoint += separator;
|
||||
basePoint = m_rect.bottomLeft() + QPointF((HANDLE_WIDTH - ICON_SIZE) / 2, 0) - step;
|
||||
painter->drawPixmap(basePoint + shiftD, KIcon("edit-delete").pixmap(ICON_SIZE, ICON_SIZE));
|
||||
|
||||
painter->restore();
|
||||
@ -239,29 +262,26 @@ AppletHandle::ButtonType AppletHandle::mapToButton(const QPointF &point) const
|
||||
QPointF separator = step + QPointF(0, ICON_MARGIN);
|
||||
//end duplicate code
|
||||
|
||||
QPolygonF activeArea = QPolygonF(QRectF(basePoint, QSizeF(ICON_SIZE, ICON_SIZE)));
|
||||
QRectF activeArea = QRectF(basePoint, QSizeF(ICON_SIZE, ICON_SIZE));
|
||||
|
||||
if (activeArea.containsPoint(point, Qt::OddEvenFill)) {
|
||||
if (activeArea.contains(point)) {
|
||||
return ResizeButton;
|
||||
}
|
||||
|
||||
activeArea.translate(step);
|
||||
if (activeArea.containsPoint(point, Qt::OddEvenFill)) {
|
||||
if (activeArea.contains(point)) {
|
||||
return RotateButton;
|
||||
}
|
||||
|
||||
if (m_applet && m_applet->hasConfigurationInterface()) {
|
||||
activeArea.translate(step);
|
||||
if (activeArea.containsPoint(point, Qt::OddEvenFill)) {
|
||||
if (activeArea.contains(point)) {
|
||||
return ConfigureButton;
|
||||
}
|
||||
}
|
||||
|
||||
//add one step to let space so the user can move the applet
|
||||
activeArea.translate(step);
|
||||
|
||||
activeArea.translate(separator);
|
||||
if (activeArea.containsPoint(point, Qt::OddEvenFill)) {
|
||||
activeArea.moveTop(m_rect.bottom() - activeArea.height() - ICON_MARGIN);
|
||||
if (activeArea.contains(point)) {
|
||||
return RemoveButton;
|
||||
}
|
||||
|
||||
@ -290,6 +310,10 @@ void AppletHandle::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
m_applet->raise();
|
||||
setZValue(m_applet->zValue());
|
||||
}
|
||||
|
||||
if (m_pressedButton == MoveButton) {
|
||||
m_pos = pos();
|
||||
}
|
||||
event->accept();
|
||||
|
||||
update();
|
||||
@ -328,7 +352,7 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
//kDebug() << "button pressed:" << m_pressedButton << ", fade pending?" << m_pendingFade;
|
||||
|
||||
if (m_pendingFade) {
|
||||
startFading(FadeOut);
|
||||
startFading(FadeOut, m_entryPos);
|
||||
m_pendingFade = false;
|
||||
}
|
||||
|
||||
@ -397,7 +421,7 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
}
|
||||
} else {
|
||||
// test for containment change
|
||||
kDebug() << "testing for containment change, sceneBoundingRect = " << m_containment->sceneBoundingRect();
|
||||
//kDebug() << "testing for containment change, sceneBoundingRect = " << m_containment->sceneBoundingRect();
|
||||
if (!m_containment->sceneBoundingRect().contains(m_applet->scenePos())) {
|
||||
// see which containment it belongs to
|
||||
Corona * corona = qobject_cast<Corona*>(scene());
|
||||
@ -412,9 +436,9 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
if (containments[i]->sceneBoundingRect().contains(pos)) {
|
||||
//kDebug() << "new containment = " << containments[i];
|
||||
kDebug() << "rect = " << containments[i]->sceneBoundingRect();
|
||||
//kDebug() << "rect = " << containments[i]->sceneBoundingRect();
|
||||
// add the applet to the new containment and take it from the old one
|
||||
kDebug() << "moving to other containment with position" << pos;;
|
||||
//kDebug() << "moving to other containment with position" << pos;;
|
||||
switchContainment(containments[i], pos);
|
||||
break;
|
||||
}
|
||||
@ -485,7 +509,7 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
QRect screenRect = QRect(event->screenPos() - m_mousePos,
|
||||
m_applet->screenRect().size());
|
||||
|
||||
kDebug() << "screenRect = " << screenRect;
|
||||
//kDebug() << "screenRect = " << screenRect;
|
||||
|
||||
if (!m_topview) { //create a new toplevel view
|
||||
m_topview = new View(m_containment, -1, 0);
|
||||
@ -671,10 +695,15 @@ void AppletHandle::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
||||
m_hoverTimer->start();
|
||||
}
|
||||
|
||||
void AppletHandle::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
m_leaveTimer->stop();
|
||||
}
|
||||
|
||||
void AppletHandle::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
//kDebug() << "hover leave" << m_pressedButton;
|
||||
m_hoverTimer->stop();
|
||||
|
||||
if (m_pressedButton != NoButton) {
|
||||
@ -697,13 +726,9 @@ bool AppletHandle::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
|
||||
|
||||
void AppletHandle::fadeAnimation(qreal progress)
|
||||
{
|
||||
qreal endOpacity = 1.0;
|
||||
if (m_anim == FadeOut) {
|
||||
endOpacity = 0.0;
|
||||
}
|
||||
|
||||
qreal endOpacity = (m_anim == FadeIn) ? 1.0 : 0.0;
|
||||
m_opacity += (endOpacity - m_opacity) * progress;
|
||||
|
||||
//kDebug() << "progress" << progress << "m_opacity" << m_opacity << endOpacity;
|
||||
if (progress >= 1.0 && m_anim == FadeOut) {
|
||||
emit disappearDone(this);
|
||||
}
|
||||
@ -713,12 +738,12 @@ void AppletHandle::fadeAnimation(qreal progress)
|
||||
|
||||
void AppletHandle::fadeIn()
|
||||
{
|
||||
startFading(FadeIn);
|
||||
startFading(FadeIn, m_entryPos);
|
||||
}
|
||||
|
||||
void AppletHandle::leaveTimeout()
|
||||
{
|
||||
startFading(FadeOut);
|
||||
startFading(FadeOut, m_entryPos);
|
||||
}
|
||||
|
||||
void AppletHandle::appletDestroyed()
|
||||
@ -734,28 +759,61 @@ void AppletHandle::appletResized()
|
||||
update();
|
||||
}
|
||||
|
||||
void AppletHandle::startFading(FadeType anim)
|
||||
void AppletHandle::startFading(FadeType anim, const QPointF &hoverPos)
|
||||
{
|
||||
if (m_animId != 0) {
|
||||
Animator::self()->stopCustomAnimation(m_animId);
|
||||
}
|
||||
|
||||
m_anim = anim;
|
||||
m_hoverTimer->stop();
|
||||
m_leaveTimer->stop();
|
||||
|
||||
m_entryPos = hoverPos;
|
||||
qreal time = 250;
|
||||
|
||||
if (anim == FadeOut && m_hoverTimer->isActive()) {
|
||||
if (!m_applet || (anim == FadeOut && m_hoverTimer->isActive())) {
|
||||
// fading out before we've started fading in
|
||||
m_hoverTimer->stop();
|
||||
fadeAnimation(1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (anim == FadeIn) {
|
||||
//kDebug() << m_entryPos.x() << m_applet->pos().x();
|
||||
prepareGeometryChange();
|
||||
bool wasOnRight = m_buttonsOnRight;
|
||||
m_buttonsOnRight = m_entryPos.x() > (m_applet->size().width() / 2);
|
||||
calculateSize();
|
||||
QPolygonF region = mapToParent(m_rect).intersected(parentWidget()->boundingRect());
|
||||
//kDebug() << region << m_rect << mapToParent(m_rect) << parentWidget()->boundingRect();
|
||||
if (region != mapToParent(m_rect)) {
|
||||
// switch sides
|
||||
//kDebug() << "switch sides";
|
||||
m_buttonsOnRight = !m_buttonsOnRight;
|
||||
calculateSize();
|
||||
QPolygonF region2 = mapToParent(m_rect).intersected(parentWidget()->boundingRect());
|
||||
if (region2 != mapToParent(m_rect)) {
|
||||
// ok, both sides failed to be perfect... which one is more perfect?
|
||||
QRectF f1 = region.boundingRect();
|
||||
QRectF f2 = region2.boundingRect();
|
||||
//kDebug() << "still not a perfect world" << f2.width() << f2.height() << f1.width() << f1.height();
|
||||
if ((f2.width() * f2.height()) < (f1.width() * f1.height())) {
|
||||
//kDebug() << "we did better the first time";
|
||||
m_buttonsOnRight = !m_buttonsOnRight;
|
||||
calculateSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wasOnRight != m_buttonsOnRight && m_anim == FadeIn && anim == FadeIn && m_opacity <= 1) {
|
||||
m_opacity = 0.0;
|
||||
}
|
||||
|
||||
time *= 1.0 - m_opacity;
|
||||
} else {
|
||||
time *= m_opacity;
|
||||
}
|
||||
|
||||
m_anim = anim;
|
||||
m_animId = Animator::self()->customAnimation(40, (int)time, Animator::EaseInOutCurve, this, "fadeAnimation");
|
||||
}
|
||||
|
||||
@ -763,7 +821,7 @@ void AppletHandle::startFading(FadeType anim)
|
||||
void AppletHandle::forceDisappear()
|
||||
{
|
||||
setAcceptsHoverEvents(false);
|
||||
startFading(FadeOut);
|
||||
startFading(FadeOut, m_entryPos);
|
||||
}
|
||||
|
||||
void AppletHandle::calculateSize()
|
||||
@ -777,24 +835,25 @@ void AppletHandle::calculateSize()
|
||||
}
|
||||
|
||||
int top = m_applet->contentsRect().top();
|
||||
if (requiredHeight > m_applet->size().height()) {
|
||||
|
||||
if (requiredHeight > m_applet->contentsRect().height()) {
|
||||
top += (m_applet->contentsRect().height() - requiredHeight) / 2.0;
|
||||
} else {
|
||||
requiredHeight = m_applet->contentsRect().height();
|
||||
}
|
||||
|
||||
if (m_applet->pos().x() <= (HANDLE_WIDTH * 2)) {
|
||||
|
||||
if (m_buttonsOnRight) {
|
||||
//put the rect on the right of the applet
|
||||
m_rect = QRectF(m_applet->size().width(), top, HANDLE_WIDTH, requiredHeight);
|
||||
|
||||
m_buttonsOnRight = true;
|
||||
} else {
|
||||
//put the rect on the left of the applet
|
||||
m_rect = QRectF(- HANDLE_WIDTH, top, HANDLE_WIDTH, requiredHeight);
|
||||
m_rect = QRectF(-HANDLE_WIDTH, top, HANDLE_WIDTH, requiredHeight);
|
||||
}
|
||||
|
||||
m_rect = m_applet->mapToParent(m_rect).boundingRect();
|
||||
m_totalRect = m_rect.united(m_applet->geometry());
|
||||
}
|
||||
|
||||
}
|
||||
} // Plasma Namespace
|
||||
|
||||
#include "applethandle_p.moc"
|
||||
|
@ -40,7 +40,7 @@ class AppletHandle : public QObject, public QGraphicsItem
|
||||
enum FadeType { FadeIn, FadeOut };
|
||||
enum ButtonType { NoButton, MoveButton, RotateButton, ConfigureButton, RemoveButton, ResizeButton };
|
||||
|
||||
AppletHandle(Containment *parent, Applet *applet);
|
||||
AppletHandle(Containment *parent, Applet *applet, const QPointF &hoverPos);
|
||||
virtual ~AppletHandle();
|
||||
|
||||
Applet *applet() const;
|
||||
@ -48,13 +48,14 @@ class AppletHandle : public QObject, public QGraphicsItem
|
||||
QRectF boundingRect() const;
|
||||
QPainterPath shape() const;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
|
||||
void startFading(FadeType anim);
|
||||
void startFading(FadeType anim, const QPointF &hoverPos);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
|
||||
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
|
||||
@ -105,6 +106,7 @@ class AppletHandle : public QObject, public QGraphicsItem
|
||||
View *m_topview;
|
||||
|
||||
QPoint m_mousePos; //mousepos relative to applet
|
||||
QPointF m_entryPos; //where the hover in event occurred
|
||||
QPointF m_pos; //current position of applet in sceneCoords
|
||||
qreal m_zValue; //current zValue of the applet, so it can be restored after drag.
|
||||
};
|
||||
|
@ -843,13 +843,14 @@ bool Containment::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
|
||||
case QEvent::GraphicsSceneHoverEnter:
|
||||
//kDebug() << "got hoverenterEvent" << immutability() << " " << applet->immutability();
|
||||
if (immutability() == Mutable && applet->immutability() == Mutable) {
|
||||
QGraphicsSceneHoverEvent *he = static_cast<QGraphicsSceneHoverEvent*>(event);
|
||||
if (d->handles.contains(applet)) {
|
||||
d->handles[applet]->startFading(AppletHandle::FadeIn);
|
||||
d->handles[applet]->startFading(AppletHandle::FadeIn, he->pos());
|
||||
} else {
|
||||
//kDebug() << "generated applet handle";
|
||||
//TODO: there should be a small delay on showing these. they pop up too quickly/easily
|
||||
// right now
|
||||
AppletHandle *handle = new AppletHandle(this, applet);
|
||||
AppletHandle *handle = new AppletHandle(this, applet, he->pos());
|
||||
d->handles[applet] = handle;
|
||||
connect(handle, SIGNAL(disappearDone(AppletHandle*)),
|
||||
this, SLOT(handleDisappeared(AppletHandle*)));
|
||||
@ -863,7 +864,7 @@ bool Containment::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
|
||||
if (d->handles.contains(applet)) {
|
||||
QGraphicsSceneHoverEvent *he = static_cast<QGraphicsSceneHoverEvent *>(event);
|
||||
if (!d->handles[applet]->boundingRect().contains(d->handles[applet]->mapFromScene(he->scenePos()))) {
|
||||
d->handles[applet]->startFading(AppletHandle::FadeOut);
|
||||
d->handles[applet]->startFading(AppletHandle::FadeOut, he->pos());
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user