00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "private/applethandle_p.h"
00021
00022 #include <QApplication>
00023 #include <QBitmap>
00024 #include <QtGui/QGraphicsSceneMouseEvent>
00025 #include <QtGui/QLinearGradient>
00026 #include <QtGui/QPainter>
00027 #include <QtGui/QApplication>
00028
00029 #include <kcolorscheme.h>
00030 #include <kglobalsettings.h>
00031 #include <kicon.h>
00032 #include <kiconloader.h>
00033 #include <kwindowsystem.h>
00034
00035 #include <cmath>
00036 #include <math.h>
00037
00038 #include "applet.h"
00039 #include "applet_p.h"
00040 #include "containment.h"
00041 #include "corona.h"
00042 #include "paintutils.h"
00043 #include "theme.h"
00044 #include "view.h"
00045 #include "framesvg.h"
00046
00047 namespace Plasma
00048 {
00049
00050 qreal _k_distanceForPoint(QPointF point);
00051 qreal _k_pointAngle(QPointF in);
00052 QPointF _k_rotatePoint(QPointF in, qreal rotateAngle);
00053
00054 AppletHandle::AppletHandle(Containment *parent, Applet *applet, const QPointF &hoverPos)
00055 : QObject(),
00056 QGraphicsItem(parent),
00057 m_pressedButton(NoButton),
00058 m_containment(parent),
00059 m_applet(applet),
00060 m_iconSize(16),
00061 m_opacity(0.0),
00062 m_anim(FadeIn),
00063 m_animId(0),
00064 m_angle(0.0),
00065 m_backgroundBuffer(0),
00066 m_currentView(applet->view()),
00067 m_entryPos(hoverPos),
00068 m_buttonsOnRight(false),
00069 m_pendingFade(false)
00070 {
00071 KColorScheme colorScheme(QPalette::Active, KColorScheme::View,
00072 Theme::defaultTheme()->colorScheme());
00073 m_gradientColor = colorScheme.background(KColorScheme::NormalBackground).color();
00074
00075 QTransform originalMatrix = m_applet->transform();
00076 m_applet->resetTransform();
00077
00078 QRectF rect(m_applet->contentsRect());
00079 QPointF center = rect.center();
00080 originalMatrix.translate(center.x(), center.y());
00081
00082 qreal cosine = originalMatrix.m11();
00083 qreal sine = originalMatrix.m12();
00084
00085 m_angle = _k_pointAngle(QPointF(cosine, sine));
00086
00087 m_applet->setParentItem(this);
00088
00089 rect = QRectF(m_applet->pos(), m_applet->size());
00090 center = rect.center();
00091 QTransform matrix;
00092 matrix.translate(center.x(), center.y());
00093 matrix.rotateRadians(m_angle);
00094 matrix.translate(-center.x(), -center.y());
00095 setTransform(matrix);
00096
00097 m_hoverTimer = new QTimer(this);
00098 m_hoverTimer->setSingleShot(true);
00099 m_hoverTimer->setInterval(333);
00100
00101 m_leaveTimer = new QTimer(this);
00102 m_leaveTimer->setSingleShot(true);
00103 m_leaveTimer->setInterval(500);
00104
00105 connect(m_hoverTimer, SIGNAL(timeout()), this, SLOT(fadeIn()));
00106 connect(m_leaveTimer, SIGNAL(timeout()), this, SLOT(leaveTimeout()));
00107 connect(m_applet, SIGNAL(destroyed(QObject*)), this, SLOT(appletDestroyed()));
00108
00109 setAcceptsHoverEvents(true);
00110 m_hoverTimer->start();
00111
00112
00113 m_configureIcons = new Svg(this);
00114 m_configureIcons->setImagePath("widgets/configuration-icons");
00115
00116 m_configureIcons->setContainsMultipleImages(true);
00117
00118 m_background = new FrameSvg(this);
00119 m_background->setImagePath("widgets/background");
00120
00121
00122
00123
00124
00125 m_zValue = m_applet->zValue() - 1;
00126 m_applet->raise();
00127 m_applet->installSceneEventFilter(this);
00128 setZValue(m_applet->zValue());
00129 }
00130
00131 AppletHandle::~AppletHandle()
00132 {
00133 detachApplet();
00134 delete m_backgroundBuffer;
00135 }
00136
00137 Applet *AppletHandle::applet() const
00138 {
00139 return m_applet;
00140 }
00141
00142 void AppletHandle::detachApplet ()
00143 {
00144 if (!m_applet) {
00145 return;
00146 }
00147
00148 disconnect(m_hoverTimer, SIGNAL(timeout()), this, SLOT(fadeIn()));
00149 disconnect(m_leaveTimer, SIGNAL(timeout()), this, SLOT(leaveTimeout()));
00150 m_applet->disconnect(this);
00151
00152 m_applet->removeSceneEventFilter(this);
00153
00154 QRectF appletGeomLocal = m_applet->geometry();
00155 QPointF center = mapToParent(appletGeomLocal.center());
00156 QPointF appletPos = QPointF(center.x()-appletGeomLocal.width()/2, center.y()-appletGeomLocal.height()/2);
00157 m_applet->setPos(appletPos);
00158
00159
00160 QTransform t;
00161 t.translate(appletGeomLocal.width()/2, appletGeomLocal.height()/2);
00162 t.rotateRadians(m_angle);
00163 t.translate(-appletGeomLocal.width()/2, -appletGeomLocal.height()/2);
00164 m_applet->setTransform(t);
00165
00166 m_applet->setParentItem(m_containment);
00167
00168 m_applet->setZValue(m_zValue);
00169
00170 m_applet->update();
00171
00172 m_applet = 0;
00173 }
00174
00175 QRectF Plasma::AppletHandle::boundingRect() const
00176 {
00177 return m_totalRect;
00178 }
00179
00180 QPainterPath AppletHandle::shape() const
00181 {
00182
00183 if (m_applet) {
00184 QPainterPath path = PaintUtils::roundedRectangle(m_decorationRect, 10);
00185 return path.united(m_applet->mapToParent(m_applet->shape()));
00186 } else {
00187 return QGraphicsItem::shape();
00188 }
00189 }
00190
00191 QPainterPath handleRect(const QRectF &rect, int radius, bool onRight)
00192 {
00193 QPainterPath path;
00194 if (onRight) {
00195
00196 path.moveTo(rect.left(), rect.top());
00197 path.lineTo(rect.right() - radius, rect.top());
00198 path.quadTo(rect.right(), rect.top(),
00199 rect.right(), rect.top() + radius);
00200 path.lineTo(rect.right(), rect.bottom() - radius);
00201 path.quadTo(rect.right(), rect.bottom(),
00202 rect.right() - radius, rect.bottom());
00203 path.lineTo(rect.left(), rect.bottom());
00204 } else {
00205
00206 path.moveTo(QPointF(rect.left(), rect.top() + radius));
00207 path.quadTo(rect.left(), rect.top(),
00208 rect.left() + radius, rect.top());
00209 path.lineTo(rect.right(), rect.top());
00210 path.lineTo(rect.right(), rect.bottom());
00211 path.lineTo(rect.left() + radius, rect.bottom());
00212 path.quadTo(rect.left(), rect.bottom(),
00213 rect.left(), rect.bottom() - radius);
00214 }
00215
00216 path.closeSubpath();
00217 return path;
00218 }
00219
00220 void AppletHandle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00221 {
00222 Q_UNUSED(option);
00223 Q_UNUSED(widget);
00224
00225
00226 if (qFuzzyCompare(m_opacity + 1.0, 1.0)) {
00227 if (m_anim == FadeOut) {
00228
00229 QTimer::singleShot(0, this, SLOT(emitDisappear()));
00230 }
00231 return;
00232 }
00233
00234 qreal translation;
00235
00236 if (m_buttonsOnRight) {
00237
00238
00239 translation = -(1 - m_opacity) * m_rect.width();
00240 } else {
00241 translation = (1 - m_opacity) * m_rect.width();
00242 }
00243
00244 painter->translate(translation, 0);
00245
00246 painter->setPen(Qt::NoPen);
00247 painter->setRenderHints(QPainter::Antialiasing);
00248
00249 int iconMargin = m_iconSize / 2;
00250
00251 const QSize pixmapSize(int(m_decorationRect.width()),
00252 int(m_decorationRect.height()) + m_iconSize * 4 + 1);
00253 const QSize iconSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
00254
00255
00256 if (m_animId > 0 || !m_backgroundBuffer || m_backgroundBuffer->size() != pixmapSize) {
00257 QColor transparencyColor = Qt::black;
00258 transparencyColor.setAlphaF(qMin(m_opacity, qreal(0.99)));
00259
00260 QLinearGradient g(QPoint(0, 0), QPoint(m_decorationRect.width(), 0));
00261
00262 if (m_rect.height() > qreal(minimumHeight()) * 1.25) {
00263 if (m_buttonsOnRight) {
00264 qreal opaquePoint =
00265 (m_background->marginSize(LeftMargin) - translation) / m_decorationRect.width();
00266
00267
00268 g.setColorAt(0.0, Qt::transparent);
00269 g.setColorAt(qMax(0.0, opaquePoint - 0.05), Qt::transparent);
00270 g.setColorAt(opaquePoint, transparencyColor);
00271 g.setColorAt(1.0, transparencyColor);
00272 } else {
00273 qreal opaquePoint =
00274 1 - ((m_background->marginSize(RightMargin) + translation) / m_decorationRect.width());
00275 g.setColorAt(1.0, Qt::transparent);
00276 g.setColorAt(opaquePoint, Qt::transparent);
00277 g.setColorAt(qMax(0.0, opaquePoint - 0.05), transparencyColor);
00278 g.setColorAt(0.0, transparencyColor);
00279 }
00280
00281 } else {
00282 g.setColorAt(0.0, transparencyColor);
00283 }
00284
00285 m_background->resizeFrame(m_decorationRect.size());
00286
00287 if (!m_backgroundBuffer || m_backgroundBuffer->size() != pixmapSize) {
00288 delete m_backgroundBuffer;
00289 m_backgroundBuffer = new QPixmap(pixmapSize);
00290 }
00291 m_backgroundBuffer->fill(Qt::transparent);
00292 QPainter buffPainter(m_backgroundBuffer);
00293
00294 m_background->paintFrame(&buffPainter);
00295
00296
00297
00298
00299 QRectF iconRect(QPointF(0, m_decorationRect.height() + 1), iconSize);
00300 if (m_buttonsOnRight) {
00301 iconRect.moveLeft(
00302 pixmapSize.width() - m_iconSize - m_background->marginSize(LeftMargin));
00303 m_configureIcons->paint(&buffPainter, iconRect, "size-diagonal-tr2bl");
00304 } else {
00305 iconRect.moveLeft(m_background->marginSize(RightMargin));
00306 m_configureIcons->paint(&buffPainter, iconRect, "size-diagonal-tl2br");
00307 }
00308
00309 iconRect.translate(0, m_iconSize);
00310 m_configureIcons->paint(&buffPainter, iconRect, "rotate");
00311
00312 if (m_applet && m_applet->hasConfigurationInterface()) {
00313 iconRect.translate(0, m_iconSize);
00314 m_configureIcons->paint(&buffPainter, iconRect, "configure");
00315 }
00316 iconRect.translate(0, m_iconSize);
00317 m_configureIcons->paint(&buffPainter, iconRect, "close");
00318
00319 buffPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00320
00321 buffPainter.fillRect(m_backgroundBuffer->rect(), g);
00322
00323
00324
00325 }
00326
00327 painter->drawPixmap(m_decorationRect.toRect(), *m_backgroundBuffer,
00328 QRect(QPoint(0, 0), m_decorationRect.size().toSize()));
00329
00330
00331 QPointF basePoint = m_rect.topLeft() + QPointF(HANDLE_MARGIN, iconMargin);
00332 QPointF step = QPointF(0, m_iconSize + iconMargin);
00333 QPointF separator = step + QPointF(0, iconMargin);
00334
00335
00336 QPointF shiftC;
00337 QPointF shiftD;
00338 QPointF shiftR;
00339 QPointF shiftM;
00340
00341 switch(m_pressedButton)
00342 {
00343 case ConfigureButton:
00344 shiftC = QPointF(2, 2);
00345 break;
00346 case RemoveButton:
00347 shiftD = QPointF(2, 2);
00348 break;
00349 case RotateButton:
00350 shiftR = QPointF(2, 2);
00351 break;
00352 case ResizeButton:
00353 shiftM = QPointF(2, 2);
00354 break;
00355 default:
00356 break;
00357 }
00358
00359 QRectF sourceIconRect(QPointF(0, m_decorationRect.height() + 1), iconSize);
00360 if (m_buttonsOnRight) {
00361 sourceIconRect.moveLeft(
00362 pixmapSize.width() - m_iconSize - m_background->marginSize(LeftMargin));
00363 } else {
00364 sourceIconRect.moveLeft(m_background->marginSize(RightMargin));
00365 }
00366
00367 if (m_applet && m_applet->aspectRatioMode() != FixedSize) {
00368
00369 painter->drawPixmap(
00370 QRectF(basePoint + shiftM, iconSize), *m_backgroundBuffer, sourceIconRect);
00371 basePoint += step;
00372 }
00373
00374
00375 sourceIconRect.translate(0, m_iconSize);
00376 painter->drawPixmap(QRectF(basePoint + shiftR, iconSize), *m_backgroundBuffer, sourceIconRect);
00377
00378 if (m_applet && m_applet->hasConfigurationInterface()) {
00379 basePoint += step;
00380 sourceIconRect.translate(0, m_iconSize);
00381 painter->drawPixmap(
00382 QRectF(basePoint + shiftC, iconSize), *m_backgroundBuffer, sourceIconRect);
00383 }
00384
00385
00386 basePoint = m_rect.bottomLeft() + QPointF(HANDLE_MARGIN, 0) - step;
00387 sourceIconRect.translate(0, m_iconSize);
00388 painter->drawPixmap(QRectF(basePoint + shiftD, iconSize), *m_backgroundBuffer, sourceIconRect);
00389 }
00390
00391 void AppletHandle::emitDisappear()
00392 {
00393 emit disappearDone(this);
00394 }
00395
00396 AppletHandle::ButtonType AppletHandle::mapToButton(const QPointF &point) const
00397 {
00398 int iconMargin = m_iconSize / 2;
00399
00400 QPointF basePoint = m_rect.topLeft() + QPointF(HANDLE_MARGIN, iconMargin);
00401 QPointF step = QPointF(0, m_iconSize + iconMargin);
00402 QPointF separator = step + QPointF(0, iconMargin);
00403
00404
00405 QRectF activeArea = QRectF(basePoint, QSizeF(m_iconSize, m_iconSize));
00406
00407 if (m_applet && m_applet->aspectRatioMode() != FixedSize) {
00408 if (activeArea.contains(point)) {
00409 return ResizeButton;
00410 }
00411 activeArea.translate(step);
00412 }
00413
00414 if (activeArea.contains(point)) {
00415 return RotateButton;
00416 }
00417
00418 if (m_applet && m_applet->hasConfigurationInterface()) {
00419 activeArea.translate(step);
00420 if (activeArea.contains(point)) {
00421 return ConfigureButton;
00422 }
00423 }
00424
00425 activeArea.moveTop(m_rect.bottom() - activeArea.height() - iconMargin);
00426 if (activeArea.contains(point)) {
00427 return RemoveButton;
00428 }
00429
00430 return MoveButton;
00431
00432 }
00433
00434 void AppletHandle::mousePressEvent(QGraphicsSceneMouseEvent *event)
00435 {
00436
00437 if (!m_applet) {
00438 QGraphicsItem::mousePressEvent(event);
00439 return;
00440 }
00441
00442 if (m_pendingFade) {
00443
00444 return;
00445 }
00446
00447 if (event->button() == Qt::LeftButton) {
00448 m_pressedButton = mapToButton(event->pos());
00449
00450 if (m_pressedButton != NoButton) {
00451 m_applet->raise();
00452 m_zValue = m_applet->zValue();
00453 setZValue(m_zValue);
00454 }
00455
00456 if (m_pressedButton == MoveButton) {
00457 m_pos = pos();
00458 }
00459
00460 if (m_pressedButton == ResizeButton || m_pressedButton == RotateButton) {
00461 m_origAppletCenter = mapToScene(m_applet->geometry().center());
00462 m_origAppletSize = QPointF(m_applet->size().width(), m_applet->size().height());
00463
00464
00465 if (m_buttonsOnRight) {
00466 m_resizeStaticPoint = mapToScene(m_applet->geometry().bottomLeft());
00467 } else {
00468 m_resizeStaticPoint = mapToScene(m_applet->geometry().bottomRight());
00469 }
00470 m_resizeGrabPoint = mapToScene(event->pos());
00471 QPointF cursorRelativeToStatic = m_resizeGrabPoint - m_resizeStaticPoint;
00472
00473
00474 m_rotateAngleOffset = m_angle - _k_pointAngle(mapToScene(event->pos()) - m_origAppletCenter);
00475 }
00476
00477 event->accept();
00478
00479 update();
00480
00481
00482
00483 QPoint localpos = m_currentView->mapFromScene(m_applet->scenePos());
00484 m_mousePos = event->screenPos() - m_currentView->mapToGlobal(localpos);
00485
00486 return;
00487 }
00488
00489 QGraphicsItem::mousePressEvent(event);
00490 }
00491
00492 bool AppletHandle::leaveCurrentView(const QPoint &pos) const
00493 {
00494 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
00495 if (widget->geometry().contains(pos)) {
00496
00497
00498 Plasma::View *v = qobject_cast<Plasma::View *>(widget);
00499 if (v && v != m_currentView && v->containment() != m_containment) {
00500 return true;
00501 }
00502 }
00503 }
00504 return false;
00505 }
00506
00507 void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00508 {
00509
00510
00511 if (m_pendingFade) {
00512 startFading(FadeOut, m_entryPos);
00513 m_pendingFade = false;
00514 }
00515
00516 ButtonType releasedAtButton = mapToButton(event->pos());
00517
00518 if (m_applet && event->button() == Qt::LeftButton) {
00519 switch (m_pressedButton) {
00520 case ConfigureButton:
00521
00522 if (m_pressedButton == releasedAtButton) {
00523 m_applet->showConfigurationInterface();
00524 }
00525 break;
00526 case RemoveButton:
00527 if (m_pressedButton == releasedAtButton) {
00528 forceDisappear();
00529 m_applet->destroy();
00530 }
00531 break;
00532 case MoveButton:
00533 {
00534
00535
00536
00537 if (!m_containment->sceneBoundingRect().contains(m_applet->scenePos())) {
00538
00539 Corona * corona = qobject_cast<Corona*>(scene());
00540 if (corona) {
00541 QList<Containment*> containments = corona->containments();
00542 for (int i = 0; i < containments.size(); ++i) {
00543 QPointF pos;
00544 QGraphicsView *v;
00545 v = containments[i]->view();
00546 if (v) {
00547 pos = v->mapToScene(
00548 v->mapFromGlobal(event->screenPos() - m_mousePos));
00549
00550 if (containments[i]->sceneBoundingRect().contains(pos)) {
00551
00552
00553
00554
00555 switchContainment(containments[i], pos);
00556 break;
00557 }
00558 }
00559 }
00560 }
00561 }
00562 break;
00563 }
00564 default:
00565 break;
00566 }
00567 }
00568
00569 m_pressedButton = NoButton;
00570 update();
00571 }
00572
00573 qreal _k_distanceForPoint(QPointF point)
00574 {
00575 return std::sqrt(point.x() * point.x() + point.y() * point.y());
00576 }
00577
00578 qreal _k_pointAngle(QPointF in)
00579 {
00580 qreal r = sqrt(in.x()*in.x() + in.y()*in.y());
00581 qreal cosine = in.x()/r;
00582 qreal sine = in.y()/r;
00583
00584 if (sine>=0) {
00585 return acos(cosine);
00586 } else {
00587 return -acos(cosine);
00588 }
00589 }
00590
00591 QPointF _k_rotatePoint(QPointF in, qreal rotateAngle)
00592 {
00593 qreal r = sqrt(in.x()*in.x() + in.y()*in.y());
00594 qreal cosine = in.x()/r;
00595 qreal sine = in.y()/r;
00596
00597 qreal angle;
00598 if (sine>=0) {
00599 angle = acos(cosine);
00600 } else {
00601 angle = -acos(cosine);
00602 }
00603
00604 qreal newAngle = angle + rotateAngle;
00605 return QPointF(r*cos(newAngle), r*sin(newAngle));
00606 }
00607
00608 void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00609 {
00610 static const qreal snapAngle = M_PI_2 ;
00611
00612 if (!m_applet) {
00613 QGraphicsItem::mouseMoveEvent(event);
00614 return;
00615 }
00616
00617
00618 QPointF deltaScene = event->scenePos() - event->lastScenePos();
00619
00620 if (m_pressedButton == MoveButton) {
00621 m_pos += deltaScene;
00622 if (leaveCurrentView(event->screenPos())) {
00623 Plasma::View *v = Plasma::View::topLevelViewAt(event->screenPos());
00624 if (v && v != m_currentView) {
00625 Containment *c = v->containment();
00626 QPoint pos = v->mapFromGlobal(event->screenPos());
00627
00628
00629
00630 switchContainment(c, v->mapToScene(pos));
00631 } else {
00632 setPos(m_pos);
00633 }
00634 } else {
00635 setPos(m_pos);
00636 }
00637 } else if (m_pressedButton == ResizeButton || m_pressedButton == RotateButton) {
00638 QPointF cursorPoint = mapToScene(event->pos());
00639
00640
00641 QPointF newSize;
00642 QPointF newCenter;
00643 qreal newAngle;
00644
00645
00646 QSizeF min = m_applet->minimumSize();
00647 QSizeF max = m_applet->maximumSize();
00648
00649
00650 if (min.isEmpty()) {
00651 min = m_applet->boundingRect().size() - m_applet->boundingRect().size();
00652 min += QSizeF(16, 16);
00653 }
00654
00655 if (m_pressedButton == RotateButton) {
00656 newSize = m_origAppletSize;
00657 newCenter = m_origAppletCenter;
00658
00659 QPointF centerRelativePoint = cursorPoint - m_origAppletCenter;
00660 if (_k_distanceForPoint(centerRelativePoint) < 10) {
00661 newAngle = m_angle;
00662 } else {
00663 qreal cursorAngle = _k_pointAngle(centerRelativePoint);
00664 newAngle = m_rotateAngleOffset + cursorAngle;
00665 if (fabs(remainder(newAngle, snapAngle)) < 0.15) {
00666 newAngle = newAngle - remainder(newAngle, snapAngle);
00667 }
00668 }
00669 } else {
00670
00671 QPointF rStaticPoint = _k_rotatePoint(m_resizeStaticPoint, -m_angle);
00672 QPointF rCursorPoint = _k_rotatePoint(cursorPoint, -m_angle);
00673 QPointF rGrabPoint = _k_rotatePoint(m_resizeGrabPoint, -m_angle);
00674
00675 if (m_buttonsOnRight) {
00676 newSize = m_origAppletSize + QPointF(rCursorPoint.x() - rGrabPoint.x(), rGrabPoint.y() - rCursorPoint.y());
00677 } else {
00678 newSize = m_origAppletSize + QPointF(rGrabPoint.x() - rCursorPoint.x(), rGrabPoint.y() - rCursorPoint.y());
00679 }
00680
00681
00682
00683 if ((m_applet->aspectRatioMode() != Plasma::IgnoreAspectRatio &&
00684 !(event->modifiers() & Qt::ControlModifier)) ||
00685 (m_applet->aspectRatioMode() == Plasma::IgnoreAspectRatio &&
00686 (event->modifiers() & Qt::ControlModifier))) {
00687 qreal ox = m_origAppletSize.x();
00688 qreal oy = m_origAppletSize.y();
00689 qreal sx = newSize.x();
00690 qreal sy = newSize.y();
00691
00692 qreal x = ox*(sx*ox+sy*oy)/(ox*ox+oy*oy);
00693 qreal y = (oy/ox)*x;
00694 newSize = QPointF(x, y);
00695
00696
00697 newSize.rx() = qMin(max.width(), qMax(min.width(), newSize.x()));
00698 newSize.ry() = newSize.x()*(oy/ox);
00699 newSize.ry() = qMin(max.height(), qMax(min.height(), newSize.y()));
00700 newSize.rx() = newSize.y()/(oy/ox);
00701 } else {
00702
00703 newSize.rx() = qMin(max.width(), qMax(min.width(), newSize.x()));
00704 newSize.ry() = qMin(max.height(), qMax(min.height(), newSize.y()));
00705 }
00706
00707
00708 if (m_buttonsOnRight) {
00709 newCenter = _k_rotatePoint(QPointF(rStaticPoint.x() + newSize.x()/2, rStaticPoint.y() - newSize.y()/2), m_angle);
00710 } else {
00711 newCenter = _k_rotatePoint(QPointF(rStaticPoint.x() - newSize.x()/2, rStaticPoint.y() - newSize.y()/2), m_angle);
00712 }
00713
00714 newAngle = m_angle;
00715 }
00716
00717
00718 QPointF newHandlePosInScene = newCenter - (m_applet->pos() + newSize/2);
00719 QPointF newHandlePos = parentItem()->mapFromScene(newHandlePosInScene);
00720 setPos(newHandlePos);
00721
00722
00723 m_applet->resize(newSize.x(), newSize.y());
00724
00725
00726 QTransform t;
00727 QPointF appletCenter = m_applet->geometry().center();
00728 t.translate(appletCenter.x(), appletCenter.y());
00729 t.rotateRadians(newAngle);
00730 t.translate(-appletCenter.x(), -appletCenter.y());
00731 setTransform(t);
00732 m_angle = newAngle;
00733
00734 m_applet->update();
00735 } else {
00736 QGraphicsItem::mouseMoveEvent(event);
00737 }
00738 }
00739
00740
00741 void AppletHandle::switchContainment(Containment *containment, const QPointF &pos)
00742 {
00743 m_containment = containment;
00744 Applet *applet = m_applet;
00745 m_applet = 0;
00746 applet->removeSceneEventFilter(this);
00747 forceDisappear();
00748 applet->disconnect(this);
00749 applet->setZValue(m_zValue);
00750 containment->addApplet(applet, containment->mapFromScene(pos), false);
00751 update();
00752 }
00753
00754 QVariant AppletHandle::itemChange(GraphicsItemChange change, const QVariant &value)
00755 {
00756 if (change == ItemPositionHasChanged && m_applet) {
00757 m_applet->updateConstraints(Plasma::LocationConstraint);
00758 }
00759 return QGraphicsItem::itemChange(change, value);
00760 }
00761
00762 void AppletHandle::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
00763 {
00764 Q_UNUSED(event);
00765
00766
00767
00768 m_leaveTimer->stop();
00769
00770
00771 if (m_animId != 0 && m_anim == FadeOut) {
00772 startFading(FadeIn, m_entryPos);
00773 } else {
00774
00775 m_hoverTimer->start();
00776 }
00777 }
00778
00779 void AppletHandle::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
00780 {
00781 Q_UNUSED(event);
00782 m_leaveTimer->stop();
00783 }
00784
00785 void AppletHandle::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
00786 {
00787 Q_UNUSED(event);
00788 m_hoverTimer->stop();
00789
00790 if (m_pressedButton != NoButton) {
00791 m_pendingFade = true;
00792 } else {
00793
00794 m_leaveTimer->start();
00795 }
00796 }
00797
00798 bool AppletHandle::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
00799 {
00800 if (watched == m_applet && event->type() == QEvent::GraphicsSceneHoverLeave) {
00801 hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent*>(event));
00802 }
00803
00804 return false;
00805 }
00806
00807 void AppletHandle::fadeAnimation(qreal progress)
00808 {
00809
00810 if (m_anim == FadeIn) {
00811 m_opacity = progress;
00812 } else {
00813 m_opacity = 1 - progress;
00814 }
00815
00816
00817 if (qFuzzyCompare(progress, qreal(1.0))) {
00818 m_animId = 0;
00819 delete m_backgroundBuffer;
00820 m_backgroundBuffer = 0;
00821 }
00822
00823 update();
00824 }
00825
00826 void AppletHandle::fadeIn()
00827 {
00828 startFading(FadeIn, m_entryPos);
00829 }
00830
00831 void AppletHandle::leaveTimeout()
00832 {
00833 startFading(FadeOut, m_entryPos);
00834 }
00835
00836 void AppletHandle::appletDestroyed()
00837 {
00838 m_applet = 0;
00839 }
00840
00841 void AppletHandle::appletResized()
00842 {
00843 prepareGeometryChange();
00844 calculateSize();
00845 update();
00846 }
00847
00848 void AppletHandle::setHoverPos(const QPointF &hoverPos)
00849 {
00850 m_entryPos = hoverPos;
00851 }
00852
00853 void AppletHandle::startFading(FadeType anim, const QPointF &hoverPos)
00854 {
00855 if (m_animId != 0) {
00856 Animator::self()->stopCustomAnimation(m_animId);
00857 }
00858
00859 m_hoverTimer->stop();
00860 m_leaveTimer->stop();
00861
00862 m_entryPos = hoverPos;
00863 qreal time = 100;
00864
00865 if (!m_applet || (anim == FadeOut && m_hoverTimer->isActive())) {
00866
00867 m_anim = FadeOut;
00868 fadeAnimation(1.0);
00869 return;
00870 }
00871
00872 if (anim == FadeIn) {
00873
00874 prepareGeometryChange();
00875 bool wasOnRight = m_buttonsOnRight;
00876 m_buttonsOnRight = m_entryPos.x() > (m_applet->size().width() / 2);
00877 calculateSize();
00878 QPolygonF region = mapToParent(m_rect).intersected(parentWidget()->boundingRect());
00879
00880 if (region != mapToParent(m_rect)) {
00881
00882
00883 m_buttonsOnRight = !m_buttonsOnRight;
00884 calculateSize();
00885 QPolygonF region2 = mapToParent(m_rect).intersected(parentWidget()->boundingRect());
00886 if (region2 != mapToParent(m_rect)) {
00887
00888 QRectF f1 = region.boundingRect();
00889 QRectF f2 = region2.boundingRect();
00890
00891
00892 if ((f2.width() * f2.height()) < (f1.width() * f1.height())) {
00893
00894 m_buttonsOnRight = !m_buttonsOnRight;
00895 calculateSize();
00896 }
00897 }
00898 }
00899
00900 if (wasOnRight != m_buttonsOnRight &&
00901 m_anim == FadeIn &&
00902 anim == FadeIn &&
00903 m_opacity <= 1) {
00904 m_opacity = 0.0;
00905 }
00906
00907 time *= 1.0 - m_opacity;
00908 } else {
00909 time *= m_opacity;
00910 }
00911
00912 m_anim = anim;
00913
00914 m_animId = Animator::self()->customAnimation(80 * (time / 1000.0), (int)time,
00915 Animator::EaseInCurve, this, "fadeAnimation");
00916 }
00917
00918 void AppletHandle::forceDisappear()
00919 {
00920 setAcceptsHoverEvents(false);
00921 startFading(FadeOut, m_entryPos);
00922 }
00923
00924 int AppletHandle::minimumHeight()
00925 {
00926 int iconMargin = m_iconSize / 2;
00927 int requiredHeight = iconMargin +
00928 (m_iconSize + iconMargin) * 4 +
00929 iconMargin ;
00930
00931 if (m_applet && m_applet->hasConfigurationInterface()) {
00932 requiredHeight += (m_iconSize + iconMargin);
00933 }
00934
00935 return requiredHeight;
00936 }
00937
00938 void AppletHandle::calculateSize()
00939 {
00940 KIconLoader *iconLoader = KIconLoader::global();
00941
00942 m_iconSize = iconLoader->loadIcon("transform-scale", KIconLoader::Small).width();
00943
00944 int handleHeight = qMax(minimumHeight(), int(m_applet->contentsRect().height() * 0.8));
00945 int handleWidth = m_iconSize + 2 * HANDLE_MARGIN;
00946 int top =
00947 m_applet->contentsRect().top() + (m_applet->contentsRect().height() - handleHeight) / 2.0;
00948
00949 qreal marginLeft, marginTop, marginRight, marginBottom;
00950 m_background->getMargins(marginLeft, marginTop, marginRight, marginBottom);
00951
00952 if (m_buttonsOnRight) {
00953
00954 m_rect = QRectF(m_applet->size().width(), top, handleWidth, handleHeight);
00955 } else {
00956
00957 m_rect = QRectF(-handleWidth, top, handleWidth, handleHeight);
00958 }
00959
00960 if (m_applet->contentsRect().height() > qreal(minimumHeight()) * 1.25) {
00961 int addedMargin = marginLeft / 2;
00962
00963
00964
00965
00966
00967
00968 if (!m_applet->shape().contains(m_applet->contentsRect())) {
00969 QPainterPath p;
00970 p.addRect(m_applet->boundingRect());
00971 if (m_applet->shape() != p) {
00972 addedMargin = m_applet->contentsRect().width() / 2;
00973 }
00974 }
00975
00976 if (m_buttonsOnRight) {
00977 marginLeft += addedMargin;
00978 } else {
00979 marginRight += addedMargin;
00980 }
00981 }
00982
00983 m_rect = m_applet->mapToParent(m_rect).boundingRect();
00984 m_decorationRect = m_rect.adjusted(-marginLeft, -marginTop, marginRight, marginBottom);
00985 m_totalRect = m_decorationRect.united(m_applet->geometry());
00986 }
00987
00988 }
00989
00990 #include "applethandle_p.moc"
00991