Commit eae999b7 authored by Oliver Kellogg's avatar Oliver Kellogg
Browse files

Fix for 'Callback message in sequence diagram cannot be resized'

umbrello/umlwidgets/messagewidget.{h,cpp}
- Reimplement UMLWidget::isInResizeArea instead of resizeCursor.
  Reason: In case of a message widget running from right to left, the
  resize area is at the left bottom corner because the message's
  execution specification is also at the left.  Furthermore, the right
  side may be covered up by another message's execution specification.

umbrello/umlwidgets/umlwidget.cpp
- In function mousePressEvent extend debug message to show pos() and
  event->scenePos().
- In function paint(QPainter*,const QStyleOptionGraphicsItem*, QWidget*)
  case (option->state & QStyle::State_Selected)
    case (m_resizable && w >= s+8 && h >= s+8),
  - int horSide initialized to `w' replaces variable `right';
  - if baseType() is wt_Message and the message's role A ObjectWidget is
    to the right of the role B ObjectWidget then set horSide to a small
    value in order to place the resize anchor at the role B object;
  - in calls to painter->drawLine() use horSide in lieu of `right'.

BUG: 429794
parent 56fc8bf3
......@@ -187,14 +187,51 @@ void MessageWidget::updateResizability()
/**
* Overridden from UMLWidget.
* Returns the cursor to be shown when resizing the widget.
* The cursor shown is KCursor::sizeVerCursor().
* Checks if the mouse is in resize area and sets the cursor accordingly.
* The resize area is usually at the right bottom corner of the widget
* except in case of a message widget running from right to left.
* In that case the resize area is at the left bottom corner in order
* to avoid overlap with an execution rectangle at the right.
*
* @return The cursor to be shown when resizing the widget.
* @param me The QMouseEVent to check.
* @return true if the mouse is in resize area, false otherwise.
*/
QCursor MessageWidget::resizeCursor() const
bool MessageWidget::isInResizeArea(QGraphicsSceneMouseEvent *me)
{
return Qt::SizeVerCursor;
if (!m_resizable) {
m_scene->activeView()->setCursor(Qt::ArrowCursor);
DEBUG(DBG_SRC) << "!m_resizable";
return false;
}
qreal m = 7.0;
const qreal w = width();
const qreal h = height();
// If the widget itself is very small then make the resize area small, too.
// Reason: Else it becomes impossible to do a move instead of resize.
if (w - m < m || h - m < m) {
m = 2.0;
}
if (me->scenePos().y() < y() + h - m) {
m_scene->activeView()->setCursor(Qt::ArrowCursor);
DEBUG(DBG_SRC) << "Y condition not satisfied";
return false;
}
int x1 = m_pOw[Uml::RoleType::A]->x();
int x2 = m_pOw[Uml::RoleType::B]->x();
if (x1 < x2 && me->scenePos().x() >= x() + w - m ||
x1 > x2 && me->scenePos().x() >= x() - m) {
m_scene->activeView()->setCursor(Qt::SizeVerCursor);
DEBUG(DBG_SRC) << "X condition is satisfied";
return true;
} else {
m_scene->activeView()->setCursor(Qt::ArrowCursor);
DEBUG(DBG_SRC) << "X condition not satisfied";
return false;
}
}
/**
......@@ -231,9 +268,9 @@ void MessageWidget::resizeWidget(qreal newW, qreal newH)
/**
* Constrains the vertical position of the message widget so it doesn't go
* upper than the bottom side of the lower object.
* The height of the floating text widget in the message is taken in account
* if there is any and isn't empty.
* above the bottom side of the lower object.
* The height of the floating text widget in the message is taken into account
* if there is any and it isn't empty.
*
* @param diffY The difference between current Y position and new Y position.
* @return The new Y position, constrained.
......
......@@ -53,7 +53,7 @@ public:
virtual void setY(qreal y);
//---------- LinkWidget Interface methods implemementation from now on.
//---------- LinkWidget Interface methods implementation from here on.
virtual void lwSetFont (QFont font);
virtual UMLClassifier *operationOwner();
......@@ -74,7 +74,7 @@ public:
virtual void constrainTextPos(qreal &textX, qreal &textY, qreal textWidth, qreal textHeight,
Uml::TextRole::Enum tr);
//---------- End LinkWidget Interface methods implemementation.
//---------- End LinkWidget Interface methods implementation.
/// @return Whether the message is synchronous or asynchronous
Uml::SequenceMessage::Enum sequenceMessageType() const {
......@@ -84,7 +84,7 @@ public:
bool hasObjectWidget(ObjectWidget * w);
ObjectWidget* objectWidget(Uml::RoleType::Enum role);
void setObjectWidget(ObjectWidget * ow, Uml::RoleType::Enum role) ;
void setObjectWidget(ObjectWidget * ow, Uml::RoleType::Enum role);
bool isSelf() const;
......@@ -155,7 +155,7 @@ protected:
virtual void moveWidgetBy(qreal diffX, qreal diffY);
virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
virtual QCursor resizeCursor() const;
virtual bool isInResizeArea(QGraphicsSceneMouseEvent *me);
void setLinkAndTextPos();
......
......@@ -367,8 +367,16 @@ void UMLWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
event->ignore();
return;
}
DEBUG(DBG_SRC) << "widget = " << name() << " / type = " << baseTypeStr()
<< " event->scenePos = " << event->scenePos()
<< " pos = " << pos();
/*
if (! onWidget(event->scenePos())) {
DEBUG(DBG_SRC) << name() << " event->scenePos onWidget = false, ignoring event";
event->ignore();
return;
} */
event->accept();
DEBUG(DBG_SRC) << "widget = " << name() << " / type = " << baseTypeStr();
toForeground();
......@@ -1886,11 +1894,24 @@ void UMLWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
// resize anchor would cover up most of the widget.
if (m_resizable && w >= s+8 && h >= s+8) {
brush.setColor(Qt::red);
const int right = 0 + w;
const int bottom = 0 + h;
painter->drawLine(right - s, 0 + h - 1, 0 + w - 1, 0 + h - s);
painter->drawLine(right - (s*2), bottom - 1, right - 1, bottom - (s*2));
painter->drawLine(right - (s*3), bottom - 1, right - 1, bottom - (s*3));
int horSide = w; // horizontal side default: right side
if (baseType() == wt_Message) {
MessageWidget *msg = asMessageWidget();
int x1 = msg->objectWidget(Uml::RoleType::A)->x();
int x2 = msg->objectWidget(Uml::RoleType::B)->x();
if (x1 > x2) {
// On messages running right to left we use the left side for
// placing the resize anchor because the message's execution
// specification as at the left in this case. Furthermore,
// the right side may be covered up by another message's
// execution specification.
horSide = 17; // execution box width
}
}
painter->drawLine(horSide - s, 0 + h - 1, 0 + w - 1, 0 + h - s);
painter->drawLine(horSide - (s*2), bottom - 1, horSide - 1, bottom - (s*2));
painter->drawLine(horSide - (s*3), bottom - 1, horSide - 1, bottom - (s*3));
} else {
painter->fillRect(0 + w - s, 0 + h - s, s, s, brush);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment