diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | bd9e6617827818fd043452c08c606f07b78014a0 (patch) | |
tree | 425bb4c3168f9c02f10150f235d2cb998dcc6108 /umbrello/umbrello/umlwidgetcontroller.cpp | |
download | tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.tar.gz tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdesdk@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'umbrello/umbrello/umlwidgetcontroller.cpp')
-rw-r--r-- | umbrello/umbrello/umlwidgetcontroller.cpp | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/umbrello/umbrello/umlwidgetcontroller.cpp b/umbrello/umbrello/umlwidgetcontroller.cpp new file mode 100644 index 00000000..29ca98a1 --- /dev/null +++ b/umbrello/umbrello/umlwidgetcontroller.cpp @@ -0,0 +1,540 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * copyright (C) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "umlwidgetcontroller.h" + +// qt includes +#include <qevent.h> +#include <qpoint.h> + +// kde includes +#include <kcursor.h> +#include <kdebug.h> +#include <klocale.h> + +// app includes +#include "umlwidget.h" +#include "umlwidgetlist.h" +#include "umlnamespace.h" +#include "uml.h" +#include "umldoc.h" +#include "umlview.h" +#include "umlobject.h" +#include "listpopupmenu.h" +#include "classifierwidget.h" +#include "associationwidget.h" +#include "messagewidget.h" + +using namespace Uml; + +UMLWidgetController::UMLWidgetController(UMLWidget *widget) { + m_widget = widget; + + m_pressOffsetX = m_pressOffsetY = 0; + m_oldX = m_oldY = 0; + m_oldW = m_oldH = 0; + m_minSelectedX = m_minSelectedY = m_maxSelectedX = m_maxSelectedY = 0; + + m_shiftPressed = false; + m_leftButtonDown = m_middleButtonDown = m_rightButtonDown = false; + m_inMoveArea = m_inResizeArea = 0; + m_wasSelected = m_moved = m_resized = 0; +} + +UMLWidgetController::~UMLWidgetController() { +} + +void UMLWidgetController::mousePressEvent(QMouseEvent *me) { + // If there is a button pressed already ignore other press events + if (m_leftButtonDown || m_middleButtonDown || m_rightButtonDown) { + return; + } + + if (me->button() == Qt::LeftButton) { + m_leftButtonDown = true; + } else if (me->button() == Qt::RightButton) { + m_rightButtonDown = true; + } else { + m_middleButtonDown = true; + return; + } + + //There is no harm in saving all the values of the widget even when + //they aren't going to be used + saveWidgetValues(me); + + m_oldStatusBarMsg = UMLApp::app()->getStatusBarMsg(); + + if (me->state() == Qt::ShiftButton || me->state() == Qt::ControlButton) { + m_shiftPressed = true; + + if (me->button() == Qt::LeftButton) { + m_inMoveArea = true; + } + + if (!m_widget->m_bSelected) { + selectMultiple(me); + } else if (!m_rightButtonDown) { + m_wasSelected = false; + } + return; + } + + m_shiftPressed = false; + + int count = m_widget->m_pView->getSelectCount(true); + if (me->button() == Qt::LeftButton) { + if (m_widget->m_bSelected && count > 1) { + //Single selection is made in release event if the widget wasn't moved + m_inMoveArea = true; + lastUpdate.start(); + return; + } + + if (isInResizeArea(me)) { + m_inResizeArea = true; + } else { + m_inMoveArea = true; + } + } + + //If widget wasn't selected, or it was selected but with other widgets also selected + if (!m_widget->m_bSelected || count > 1) { + selectSingle(me); + } else if (!m_rightButtonDown) { + m_wasSelected = false; + } +} + +void UMLWidgetController::mouseMoveEvent(QMouseEvent* me) { + if (!m_leftButtonDown) + return; + + if (m_inResizeArea) { + resize(me); + return; + } + + if (!m_moved) { + UMLApp::app()->getDocument()->writeToStatusBar(i18n("Hold shift or ctrl to move in X axis. Hold shift and control to move in Y axis. Right button click to cancel move.")); + + m_moved = true; + //Maybe needed by AssociationWidget + m_widget->m_bStartMove = true; + + setSelectionBounds(); + } + + QPoint position = getPosition(me); + int diffX = position.x() - m_widget->getX(); + int diffY = position.y() - m_widget->getY(); + + if ((me->state() & Qt::ShiftButton) && (me->state() & Qt::ControlButton)) { + //Move in Y axis + diffX = 0; + } else if ((me->state() & Qt::ShiftButton) || (me->state() & Qt::ControlButton)) { + //Move in X axis + diffY = 0; + } + + // kDebug() << "UMLWidgetController::mouseMoveEvent before constrainMovementForAllWidgets:" + // << " diffX=" << diffX << ", diffY=" << diffY << endl; + constrainMovementForAllWidgets(diffX, diffY); + // kDebug() << "UMLWidgetController::mouseMoveEvent after constrainMovementForAllWidgets:" + // << " diffX=" << diffX << ", diffY=" << diffY << endl; + + //Nothing to move + if (diffX == 0 && diffY == 0) { + return; + } + + UMLWidgetListIt it(m_selectedWidgetsList); + UMLWidget* widget; + it.toFirst(); + + bool update = false; + if (lastUpdate.elapsed() > 25) { + update = true; + lastUpdate.restart(); + + m_widget->adjustUnselectedAssocs(m_widget->getX(), m_widget->getY()); + } + + while ((widget = it.current()) != 0) { + ++it; + widget->getWidgetController()->moveWidgetBy(diffX, diffY); + } + // kDebug() << endl; + + // Move any selected associations. + AssociationWidgetList awl = m_widget->m_pView->getSelectedAssocs(); + AssociationWidget *aw = NULL; + for (AssociationWidgetListIt ai(awl); (aw = ai.current()) != NULL; ++ai) { + if (aw->getSelected()) { + aw->moveEntireAssoc(diffX, diffY); + } + } + + m_widget->m_pView->resizeCanvasToItems(); + updateSelectionBounds(diffX, diffY); +} + +void UMLWidgetController::mouseReleaseEvent(QMouseEvent *me) { + if (me->button() != Qt::LeftButton && me->button() != Qt::RightButton) { + if (m_middleButtonDown) { + m_middleButtonDown = false; + resetSelection(); + } + } else if (me->button() == Qt::LeftButton) { + if (m_leftButtonDown) { + m_leftButtonDown = false; + + if (!m_moved && !m_resized) { + if (!m_shiftPressed && (m_widget->m_pView->getSelectCount(true) > 1)) { + selectSingle(me); + } else if (!m_wasSelected) { + deselect(me); + } + } else { + if (m_moved) { + m_moved = false; + + //Ensure associations are updated (the timer could prevent the + //adjustment in the last move event before the release) + UMLWidgetListIt it(m_selectedWidgetsList); + UMLWidget* widget; + it.toFirst(); + while ((widget = it.current()) != 0) { + ++it; + widget->adjustAssocs(widget->getX(), widget->getY()); + } + + m_widget->m_bStartMove = false; + } else { + m_resized = false; + } + + if ((m_inMoveArea && wasPositionChanged()) || + (m_inResizeArea && wasSizeChanged())) { + m_widget->m_pDoc->setModified(true); + } + + UMLApp::app()->getDocument()->writeToStatusBar(m_oldStatusBarMsg); + } + + if (m_inResizeArea) { + m_inResizeArea = false; + m_widget->m_pView->setCursor(KCursor::arrowCursor()); + } else { + m_inMoveArea = false; + } + } + } else if (me->button() == Qt::RightButton) { + if (m_rightButtonDown) { + m_rightButtonDown = false; + showPopupMenu(me); + } else if (m_leftButtonDown) { + //Cancel move/edit + QMouseEvent move(QMouseEvent::MouseMove, + QPoint(m_oldX + m_pressOffsetX, m_oldY + m_pressOffsetY), + Qt::LeftButton, Qt::NoButton); + mouseMoveEvent(&move); + QMouseEvent release(QMouseEvent::MouseButtonRelease, + QPoint(m_oldX + m_pressOffsetX, m_oldY + m_pressOffsetY), + Qt::LeftButton, Qt::NoButton); + mouseReleaseEvent(&release); + } + } + + //TODO Copied from old code. Does it really work as intended? + UMLWidget *bkgnd = m_widget->m_pView->getWidgetAt(me->pos()); + if (bkgnd) { + //kDebug() << "UMLWidgetController::mouseReleaseEvent: setting Z to " + // << bkgnd->getZ() + 1 << endl; + m_widget->setZ(bkgnd->getZ() + 1); + } else { + m_widget->setZ(0); + } +} + +void UMLWidgetController::mouseDoubleClickEvent(QMouseEvent *me) { + if (me->button() != Qt::LeftButton) { + return; + } + + selectSingle(me); + + doMouseDoubleClick(me); +} + +bool UMLWidgetController::isInResizeArea(QMouseEvent *me) { + const int m = 10; + + if (m_widget->m_bResizable && + me->x() >= (m_widget->getX() + m_widget->width() - m) && + me->y() >= (m_widget->getY() + m_widget->height() - m)) { + m_widget->m_pView->setCursor(getResizeCursor()); + return true; + } else { + m_widget->m_pView->setCursor(KCursor::arrowCursor()); + return false; + } +} + +QCursor UMLWidgetController::getResizeCursor() { + return KCursor::sizeFDiagCursor(); +} + +void UMLWidgetController::resizeWidget(int newW, int newH) { + m_widget->setSize(newW, newH); +} + +void UMLWidgetController::moveWidgetBy(int diffX, int diffY) { + m_widget->setX(m_widget->getX() + diffX); + m_widget->setY(m_widget->getY() + diffY); +} + +void UMLWidgetController::constrainMovementForAllWidgets(int &/*diffX*/, int &/*diffY*/) { +} + +void UMLWidgetController::doMouseDoubleClick(QMouseEvent *) { + if (!m_widget || !m_widget->m_pMenu) + return; + m_widget->slotMenuSelection(ListPopupMenu::mt_Properties); +} + +void UMLWidgetController::resetSelection() { + m_widget->m_pView->clearSelected(); + m_widget->m_pView->resetToolbar(); + m_widget->setSelected(false); + + m_wasSelected = false; +} + +void UMLWidgetController::selectSingle(QMouseEvent *me) { + m_widget->m_pView->clearSelected(); + + //Adds the widget to the selected widgets list, but as it has been cleared + //only the current widget is selected + selectMultiple(me); +} + +void UMLWidgetController::selectMultiple(QMouseEvent *me) { + m_widget->m_bSelected = true; + m_widget->setSelected(m_widget->m_bSelected); + m_widget->m_pView->setSelected(m_widget, me); + + m_wasSelected = true; +} + +void UMLWidgetController::deselect(QMouseEvent *me) { + m_widget->m_bSelected = false; + m_widget->setSelected(m_widget->m_bSelected); + m_widget->m_pView->setSelected(m_widget, me); + //m_wasSelected is false implicitly, no need to set it again +} + +void UMLWidgetController::saveWidgetValues(QMouseEvent *me) { + m_pressOffsetX = me->x() - m_widget->getX(); + m_pressOffsetY = me->y() - m_widget->getY(); + + m_oldX = m_widget->getX(); + m_oldY = m_widget->getY(); + + m_oldW = m_widget->width(); + m_oldH = m_widget->height(); +} + +void UMLWidgetController::setSelectionBounds() { + if (m_widget->m_pView->getSelectCount() > 0) { + m_selectedWidgetsList.clear(); + m_widget->m_pView->getSelectedWidgets(m_selectedWidgetsList, false); + + updateSelectionBounds(1, 1); + } +} + +//TODO optimize it +void UMLWidgetController::updateSelectionBounds(int diffX, int diffY) { + if (diffX != 0) { + m_minSelectedX = getSmallestX(m_selectedWidgetsList); + m_maxSelectedX = getBiggestX(m_selectedWidgetsList); + } + if (diffY != 0) { + m_minSelectedY = getSmallestY(m_selectedWidgetsList); + m_maxSelectedY = getBiggestY(m_selectedWidgetsList); + } +} + +void UMLWidgetController::resize(QMouseEvent *me) { + UMLApp::app()->getDocument()->writeToStatusBar(i18n("Hold shift or ctrl to move in X axis. Hold shift and control to move in Y axis. Right button click to cancel resize.")); + + m_resized = true; + + int newW = m_oldW + me->x() - m_widget->getX() - m_pressOffsetX; + int newH = m_oldH + me->y() - m_widget->getY() - m_pressOffsetY; + + if ((me->state() & Qt::ShiftButton) && (me->state() & Qt::ControlButton)) { + //Move in Y axis + newW = m_oldW; + } else if ((me->state() & Qt::ShiftButton) || (me->state() & Qt::ControlButton)) { + //Move in X axis + newH = m_oldH; + } + + m_widget->constrain(newW, newH); + resizeWidget(newW, newH); + m_widget->adjustAssocs(m_widget->getX(), m_widget->getY()); + + m_widget->m_pView->resizeCanvasToItems(); +} + +//TODO refactor with AlignToolbar method. +int UMLWidgetController::getSmallestX(const UMLWidgetList &widgetList) { + UMLWidgetListIt it(widgetList); + UMLWidget* widget; + + widget = it.toFirst(); + // leave function upon empty widget list + if (NULL == widget) return 0; + int smallestX = widget->getX(); + ++it; + + while ((widget = it.current()) != 0) { + ++it; + if (smallestX > widget->getX()) + smallestX = widget->getX(); + } + + return smallestX; +} + +//TODO refactor with AlignToolbar method. +int UMLWidgetController::getSmallestY(const UMLWidgetList &widgetList) { + UMLWidgetListIt it(widgetList); + UMLWidget* widget; + + widget = it.toFirst(); + // leave function upon empty widget list + if (NULL == widget) return 0; + int smallestY = widget->getY(); + ++it; + + while ((widget = it.current()) != 0) { + ++it; + if (smallestY > widget->getY()) + smallestY = widget->getY(); + } + + return smallestY; +} + +//TODO refactor with AlignToolbar method. +int UMLWidgetController::getBiggestX(const UMLWidgetList &widgetList) { + UMLWidgetListIt it(widgetList); + UMLWidget* widget; + + widget = it.toFirst(); + // leave function upon empty widget list + if (NULL == widget) return 0; + int biggestX = widget->getX(); + biggestX += it.current()->getWidth(); + ++it; + + while ((widget = it.current()) != 0) { + ++it; + if (biggestX < widget->getX() + widget->getWidth()) + biggestX = widget->getX() + widget->getWidth(); + } + + return biggestX; +} + +//TODO refactor with AlignToolbar method. +int UMLWidgetController::getBiggestY(const UMLWidgetList &widgetList) { + UMLWidgetListIt it(widgetList); + UMLWidget* widget; + + widget = it.toFirst(); + // leave function upon empty widget list + if (NULL == widget) return 0; + int biggestY = widget->getY(); + biggestY += it.current()->getHeight(); + ++it; + + while ((widget = it.current()) != 0) { + ++it; + if (biggestY < widget->getY() + widget->getHeight()) + biggestY = widget->getY() + widget->getHeight(); + } + + return biggestY; +} + +QPoint UMLWidgetController::getPosition(QMouseEvent* me) { + /* + kDebug() << "UMLWidgetController::getPosition: me->x=" << me->x() + << " m_widget->getX=" << m_widget->getX() << ", m_oldX=" << m_oldX + << ", m_pressOffsetX=" << m_pressOffsetX << endl; + kDebug() << "UMLWidgetController::getPosition: me->y=" << me->y() + << " m_widget->getY=" << m_widget->getY() << ", m_oldY=" << m_oldY + << ", m_pressOffsetY=" << m_pressOffsetY << endl; + */ + int newX = me->x() + m_widget->getX() - m_oldX - m_pressOffsetX; + int newY = me->y() + m_widget->getY() - m_oldY - m_pressOffsetY; + int maxX = m_widget->m_pView->canvas()->width(); + int maxY = m_widget->m_pView->canvas()->height(); + + m_oldX = newX; + m_oldY = newY; + + if (newX + (m_minSelectedX - m_widget->getX()) < 0) { + //kDebug() << "UMLWidgetController::getPosition: got into cond.1" << endl; + newX = m_widget->getX() - m_minSelectedX; + } + if (newY + (m_minSelectedY - m_widget->getY()) < 0) { + //kDebug() << "UMLWidgetController::getPosition: got into cond.2" << endl; + newY = m_widget->getY() - m_minSelectedY; + } + if (newX + (m_maxSelectedX - m_widget->getX()) > maxX) { + //kDebug() << "UMLWidgetController::getPosition: got into cond.3" << endl; + newX = maxX - (m_maxSelectedX - m_widget->getX()); + } + if (newY + (m_maxSelectedY - m_widget->getY()) > maxY) { + //kDebug() << "UMLWidgetController::getPosition: got into cond.4" << endl; + newY = maxY - (m_maxSelectedY - m_widget->getY()); + } + return QPoint(newX, newY); +} + +QPoint UMLWidgetController::getPositionDifference(QMouseEvent* me) { + QPoint newPoint = getPosition(me); + const int diffX = newPoint.x() - m_widget->getX(); + const int diffY = newPoint.y() - m_widget->getY(); + return QPoint(diffX, diffY); +} + +void UMLWidgetController::showPopupMenu(QMouseEvent *me) { + //TODO why this condition? + if (m_widget->m_pMenu) { + return; + } + m_widget->startPopupMenu(me->globalPos()); +} + +bool UMLWidgetController::wasSizeChanged() { + return m_oldW != m_widget->getWidth() || m_oldH != m_widget->getHeight(); +} + +bool UMLWidgetController::wasPositionChanged() { + return m_oldX != m_widget->getX() || m_oldY != m_widget->getY(); +} |