I was sitting around trying to organize some of my plasmoids... and realized that you can't easily make a stack of plasmoids all exactly aligned ... at least not that I could figure out. I thought it would be really cool to be able to snap plasmoids to other plasmoids as well as to virtual "guidelines" created by the bounding boxes of the plasmoids. I spent a few hours and finally got the effect I was looking for. Should work for both moves and resizes. Attached is the patch against kdelibs head. Right now the snap "strength" is hard coded to 3 pixels.
~Roman
From 9f2af11848d6ed72977beb8320c1d503a0f3978d Mon Sep 17 00:00:00 2001 From: Roman Shtylman <shtyl...@gmail.com> Date: Sat, 2 Jan 2010 01:15:26 -0500 Subject: [PATCH] added plasma widget snap plasma widgets snap to other plasma widget's grid lines --- plasma/private/applethandle.cpp | 123 ++++++++++++++++++++++++++++++++++++++- plasma/private/applethandle_p.h | 3 + 2 files changed, 125 insertions(+), 1 deletions(-) diff --git a/plasma/private/applethandle.cpp b/plasma/private/applethandle.cpp index 1f56f5d..4039ec1 100644 --- a/plasma/private/applethandle.cpp +++ b/plasma/private/applethandle.cpp @@ -587,9 +587,29 @@ QPointF _k_projectPoint(QPointF point, QPointF v) return QMatrix(a, b, b, d, 0., 0.).map(point); } +QRectF AppletHandle::maskedBoundingRect() const +{ + if (!m_applet) { + return QRectF(); + } + + //snap to other plasmoid grid + QRectF srect; + if (m_applet->d->background) { + srect = m_applet->d->background->mask().boundingRect(); + } else { + srect = m_applet->boundingRect(); + } + + srect.translate(m_applet->pos()); + + return srect; +} + void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { static const qreal snapAngle = M_PI_2 /* $i 3.14159 / 2.0 */; + static const qreal snapDist = 3; // distance (px) for widget snap if (!m_applet) { QGraphicsItem::mouseMoveEvent(event); @@ -617,6 +637,59 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) if (m_applet) { QPointF mappedPoint = transform().map(QPointF(deltaScene.x(), deltaScene.y())); m_applet->moveBy(mappedPoint.x(), mappedPoint.y()); + + //snap to other plasmoid grid + const QRectF srect = maskedBoundingRect(); + + foreach (Plasma::Applet* applet, m_containment->applets()) { + //make sure we don't match against ourselves + if (applet != m_applet) { + QRectF drect; + + if (applet->d->background) { + drect = applet->d->background->mask().boundingRect(); + } else { + drect = applet->boundingRect(); + } + + drect.translate(applet->pos()); + + const qreal x1 = drect.right() - srect.right(); + const qreal x2 = drect.right() - srect.left(); + const qreal x3 = drect.left() - srect.right(); + const qreal x4 = drect.left() - srect.left(); + + const qreal y1 = drect.bottom() - srect.bottom(); + const qreal y2 = drect.bottom() - srect.top(); + const qreal y3 = drect.top() - srect.bottom(); + const qreal y4 = drect.top() - srect.top(); + + QPointF moveBy; + + if (qAbs(x1) < snapDist) + moveBy.setX(x1); + else if (qAbs(x2) < snapDist) + moveBy.setX(x2); + else if (qAbs(x3) < snapDist) + moveBy.setX(x3); + else if (qAbs(x4) < snapDist) + moveBy.setX(x4); + + if (qAbs(y1) < snapDist) + moveBy.setY(y1); + else if (qAbs(y2) < snapDist) + moveBy.setY(y2); + else if (qAbs(y3) < snapDist) + moveBy.setY(y3); + else if (qAbs(y4) < snapDist) + moveBy.setY(y4); + + if (!moveBy.isNull()) { + m_applet->moveBy(moveBy.x(), moveBy.y()); + break; + } + } + } } } else if (m_pressedButton == ResizeButton || m_pressedButton == RotateButton) { QPointF cursorPoint = event->scenePos(); @@ -701,6 +774,54 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) newAngle = m_angle; } + + //snap to other plasmoid grid + const QRectF srect = maskedBoundingRect(); + const QPointF snapPoint = (m_buttonsOnRight) ? srect.topRight() : srect.topLeft(); + + foreach (Plasma::Applet* applet, m_containment->applets()) { + //make sure we don't match against ourselves + if (applet != m_applet) { + QRectF drect; + if (applet->d->background) { + drect = applet->d->background->mask().boundingRect(); + } else { + drect = applet->boundingRect(); + } + drect.translate(applet->pos()); + + const qreal x1 = drect.right() - snapPoint.x(); + const qreal x2 = drect.left() - snapPoint.x(); + + const qreal y1 = drect.bottom() - snapPoint.y(); + const qreal y2 = drect.top() - snapPoint.y(); + + QPointF moveBy; + if (qAbs(x1) < snapDist) + moveBy.setX(x1); + else if (qAbs(x2) < snapDist) + moveBy.setX(x2); + + if (qAbs(y1) < snapDist) + moveBy.setY(y1); + else if (qAbs(y2) < snapDist) + moveBy.setY(y2); + + if (!moveBy.isNull()) { + + newCenter += moveBy/2; + m_resizeGrabPoint -= moveBy; + + if (m_buttonsOnRight) { + moveBy.setX(-moveBy.x()); + } + + //we have to change the size in the direction of the resize + newSize -= moveBy; + break; + } + } + } // apply size m_applet->resize(newSize.x(), newSize.y()); @@ -708,7 +829,7 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) if (m_pressedButton != RotateButton) { m_applet->setPos(m_containment->mapFromScene(newCenter - newSize/2)); } - + // apply angle QTransform at; at.translate(newSize.x()/2, newSize.y()/2); diff --git a/plasma/private/applethandle_p.h b/plasma/private/applethandle_p.h index d78635f..0267dd9 100644 --- a/plasma/private/applethandle_p.h +++ b/plasma/private/applethandle_p.h @@ -96,6 +96,9 @@ class AppletHandle : public QGraphicsObject ButtonType mapToButton(const QPointF &point) const; void forceDisappear(); int minimumHeight(); + + /** returns the boudning rectangle of the "visible" area */ + QRectF maskedBoundingRect() const; /** * move our applet to another containment -- 1.6.5
_______________________________________________ Plasma-devel mailing list Plasma-devel@kde.org https://mail.kde.org/mailman/listinfo/plasma-devel