2 * Copyright 2008 Aaron Seigo <aseigo@kde.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "panelappletoverlay.h"
22 #include <QApplication>
23 #include <QGraphicsLinearLayout>
27 #include <KGlobalSettings>
30 #include <Plasma/Applet>
31 #include <Plasma/Containment>
32 #include <Plasma/PaintUtils>
33 #include <Plasma/Theme>
34 #include <Plasma/View>
36 class AppletMoveSpacer
: public QGraphicsWidget
39 AppletMoveSpacer(Plasma::Applet
*applet
)
40 : QGraphicsWidget(applet
->containment()),
46 void paint(QPainter
*painter
, const QStyleOptionGraphicsItem
*option
, QWidget
* widget
= 0)
52 results in odd painting corruption
53 if (collidesWithItem(m_applet, Qt::IntersectsItemBoundingRect)) {
54 painter->fillRect(contentsRect(), Qt::transparent);
59 //TODO: make this a pretty gradient?
60 painter
->setRenderHint(QPainter::Antialiasing
);
61 QPainterPath p
= Plasma::PaintUtils::roundedRectangle(contentsRect().adjusted(1, 1, -2, -2), 4);
62 QColor c
= Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor
);
65 painter
->fillPath(p
, c
);
69 QGraphicsWidget
*m_applet
;
72 PanelAppletOverlay::PanelAppletOverlay(Plasma::Applet
*applet
, QWidget
*parent
)
76 m_layout(static_cast<QGraphicsLinearLayout
*>(applet
->containment()->layout())), // ++assumptions;
81 for (; i
< m_layout
->count(); ++i
) {
82 QGraphicsWidget
*w
= dynamic_cast<QGraphicsWidget
*>(m_layout
->itemAt(i
));
92 connect(m_applet
, SIGNAL(destroyed(QObject
*)), this, SLOT(deleteLater()));
93 connect(m_applet
, SIGNAL(geometryChanged()), this, SLOT(delaySyncGeometry()));
96 PanelAppletOverlay::~PanelAppletOverlay()
100 m_layout
->removeItem(m_spacer
);
103 m_spacer
->deleteLater();
108 void PanelAppletOverlay::paintEvent(QPaintEvent
*event
)
115 bool hovered
= op
.state
& QStyle::State_MouseOver
;
116 bool mover
= mouseGrabber() == this;
117 if (!hovered
|| mover
) {
122 KIcon
icon("transform-move");
126 if (m_orientation
== Qt::Horizontal
) {
127 iconSize
= qMin(qMin(height(), int(m_applet
->size().width())), 64);
128 iconRect
= QRect(rect().center() - QPoint(iconSize
/ 2, iconSize
/ 2), QSize(iconSize
, iconSize
));
130 iconSize
= qMin(qMin(width(), int(m_applet
->size().height())), 64);
131 iconRect
= QRect(rect().center() - QPoint(iconSize
/ 2, iconSize
/ 2), QSize(iconSize
, iconSize
));
134 p
.drawPixmap(iconRect
, icon
.pixmap(iconSize
, iconSize
));
137 void PanelAppletOverlay::mousePressEvent(QMouseEvent
*event
)
141 //kDebug() << m_clickDrag;
143 setMouseTracking(false);
149 if (event
->button() != Qt::LeftButton
) {
150 //kDebug() << "sending even to" << (QWidget*)parent();
151 Plasma::View
*view
= dynamic_cast<Plasma::View
*>(parent());
153 if (view
&& view
->containment()) {
154 view
->containment()->showContextMenu(mapToParent(event
->pos()), event
->globalPos());
162 m_spacer
= new AppletMoveSpacer(m_applet
);
164 m_layout
->removeItem(m_spacer
);
167 m_origin
= mapToParent(event
->pos());
168 m_spacer
->setMinimumSize(m_applet
->geometry().size());
169 m_spacer
->setMaximumSize(m_applet
->geometry().size());
170 m_layout
->removeItem(m_applet
);
171 m_layout
->insertItem(m_index
, m_spacer
);
172 m_applet
->setZValue(m_applet
->zValue() + 1);
174 if (m_orientation
== Qt::Horizontal
) {
175 m_offset
= geometry().x() - m_origin
.x();
177 m_offset
= geometry().y() - m_origin
.y();
183 void PanelAppletOverlay::mouseMoveEvent(QMouseEvent
*event
)
189 Plasma::FormFactor f
= m_applet
->formFactor();
191 if ( ((f
!= Plasma::Horizontal
&& f
!= Plasma::Vertical
) && rect().intersects(m_applet
->rect().toRect())) ||
192 ((f
== Plasma::Horizontal
|| f
== Plasma::Vertical
) && !rect().contains(event
->globalPos())) ) {
193 Plasma::View
*view
= Plasma::View::topLevelViewAt(event
->globalPos());
194 kDebug() << "checking view" << view
<< m_applet
->view();
200 QPointF pos
= view
->mapFromGlobal(event
->globalPos());
201 if (view
!= m_applet
->view()) {
202 Plasma::Containment
*c
= view
->containment();
208 m_layout
->removeItem(m_spacer
);
209 m_spacer
->deleteLater();
213 QPointF pos
= m_applet
->view()->mapFromGlobal(event
->globalPos());
214 QRectF g
= m_applet
->geometry();
215 pos
+= QPoint(m_offset
, m_offset
);
217 m_applet
->setGeometry(g
);
218 m_layout
->removeItem(m_spacer
);
219 m_spacer
->deleteLater();
222 c
->addApplet(m_applet
, pos
, false);
229 m_spacer
= new AppletMoveSpacer(m_applet
);
230 m_spacer
->setMinimumSize(m_applet
->geometry().size());
231 m_spacer
->setMaximumSize(m_applet
->geometry().size());
232 m_layout
->removeItem(m_applet
);
233 m_layout
->insertItem(m_index
, m_spacer
);
236 QPoint p
= mapToParent(event
->pos());
237 QRectF g
= m_applet
->geometry();
239 //kDebug() << p << g << "<-- movin'?";
240 if (m_orientation
== Qt::Horizontal
) {
241 g
.moveLeft(p
.x() + m_offset
);
243 g
.moveTop(p
.y() + m_offset
);
246 m_applet
->setGeometry(g
);
248 // swap items if we pass completely over the next/previous item or cross
249 // more than halfway across it, whichever comes first
250 if (m_orientation
== Qt::Horizontal
) {
251 //kDebug() << m_prevGeom << g << m_nextGeom;
252 if (m_prevGeom
.isValid() && g
.left() <= m_prevGeom
.left()) {
254 } else if (m_nextGeom
.isValid() && g
.right() >= m_nextGeom
.right()) {
257 } else if (m_prevGeom
.isValid() && g
.top() <= m_prevGeom
.top()) {
259 } else if (m_nextGeom
.isValid() && g
.bottom() >= m_nextGeom
.bottom()) {
263 //kDebug() << "=================================";
266 void PanelAppletOverlay::mouseReleaseEvent(QMouseEvent
*event
)
274 if (!m_origin
.isNull()) {
275 //kDebug() << m_clickDrag << m_origin << mapToParent(event->pos());
276 if (m_orientation
== Qt::Horizontal
) {
277 m_clickDrag
= abs(mapToParent(event
->pos()).x() - m_origin
.x()) < KGlobalSettings::dndEventDelay();
279 m_clickDrag
= abs(mapToParent(event
->pos()).y() - m_origin
.y()) < KGlobalSettings::dndEventDelay();
283 //kDebug() << "click dragging." << this << mouseGrabber();
284 setMouseTracking(true);
285 event
->setAccepted(false);
292 m_layout
->removeItem(m_spacer
);
293 m_spacer
->deleteLater();
296 m_layout
->insertItem(m_index
, m_applet
);
297 m_applet
->setZValue(m_applet
->zValue() - 1);
300 void PanelAppletOverlay::enterEvent(QEvent
*event
)
306 void PanelAppletOverlay::leaveEvent(QEvent
*event
)
312 void PanelAppletOverlay::swapWithPrevious()
318 m_prevGeom
= m_layout
->itemAt(m_index
- 1)->geometry();
320 m_prevGeom
= QRectF();
323 m_nextGeom
= m_layout
->itemAt(m_index
+ 1)->geometry();
324 m_layout
->removeItem(m_spacer
);
325 m_layout
->insertItem(m_index
, m_spacer
);
328 void PanelAppletOverlay::swapWithNext()
333 if (m_index
< m_layout
->count() - 1) {
334 m_nextGeom
= m_layout
->itemAt(m_index
+ 1)->geometry();
336 m_nextGeom
= QRectF();
339 m_prevGeom
= m_layout
->itemAt(m_index
- 1)->geometry();
340 m_layout
->removeItem(m_spacer
);
341 m_layout
->insertItem(m_index
, m_spacer
);
344 void PanelAppletOverlay::delaySyncGeometry()
346 // we need to do this because it gets called in a round-about-way
347 // from our own mouseMoveEvent. if we call syncGeometry directly,
348 // we end up with a maze of duplicated and confused mouseMoveEvents
349 // of which only half are real (the other half being caused by the
350 // immediate call to syncGeometry!)
351 QTimer::singleShot(0, this, SLOT(syncGeometry()));
354 void PanelAppletOverlay::syncGeometry()
361 setGeometry(m_applet
->geometry().toRect());
364 m_prevGeom
= m_layout
->itemAt(m_index
- 1)->geometry();
366 m_prevGeom
= QRectF();
369 //kDebug() << m_index << m_layout->count();
370 if (m_index
< m_layout
->count() - 1) {
371 m_nextGeom
= m_layout
->itemAt(m_index
+ 1)->geometry();
373 m_nextGeom
= QRectF();
377 void PanelAppletOverlay::syncOrientation()
379 m_orientation
= m_applet
->formFactor() == Plasma::Horizontal
? Qt::Horizontal
: Qt::Vertical
;
382 #include "panelappletoverlay.moc"