diff options
Diffstat (limited to 'umbrello/umbrello/objectwidget.cpp')
-rw-r--r-- | umbrello/umbrello/objectwidget.cpp | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/umbrello/umbrello/objectwidget.cpp b/umbrello/umbrello/objectwidget.cpp new file mode 100644 index 00000000..35e7bdde --- /dev/null +++ b/umbrello/umbrello/objectwidget.cpp @@ -0,0 +1,403 @@ +/*************************************************************************** + * * + * 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) 2002-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header file +#include "objectwidget.h" + +// system includes +#include <qpainter.h> +#include <qvalidator.h> +#include <qevent.h> +#include <klocale.h> +#include <kdebug.h> +#include <kinputdialog.h> + +// local includes +#include "objectwidgetcontroller.h" +#include "seqlinewidget.h" +#include "umlview.h" +#include "umldoc.h" +#include "uml.h" +#include "umlobject.h" +#include "listpopupmenu.h" +#include "docwindow.h" +#include "dialogs/classpropdlg.h" + +/** + * The number of pixels margin between the lowest message + * and the bottom of the vertical line + */ +static const int sequenceLineMargin = 20; + +ObjectWidget::ObjectWidget(UMLView * view, UMLObject *o, Uml::IDType lid) + : UMLWidget(view, o) { + init(); + if( lid != Uml::id_None ) + m_nLocalID = lid; + //updateComponentSize(); + // Doing this during loadFromXMI() gives futile updates. + // Instead, it is done afterwards by UMLWidget::activate() +} + +void ObjectWidget::init() { + UMLWidget::setBaseType(Uml::wt_Object); + m_nLocalID = Uml::id_None; + m_InstanceName = ""; + m_bMultipleInstance = false; + m_bDrawAsActor = false; + m_bShowDestruction = false; + messageWidgetList.setAutoDelete(false); + if( m_pView != NULL && m_pView -> getType() == Uml::dt_Sequence ) { + m_pLine = new SeqLineWidget( m_pView, this ); + + //Sets specific widget controller for sequence diagrams + delete m_widgetController; + m_widgetController = new ObjectWidgetController(this); + } else { + m_pLine = NULL; + } +} + +ObjectWidget::~ObjectWidget() {} + +void ObjectWidget::draw(QPainter & p , int offsetX, int offsetY) { + if ( m_bDrawAsActor ) + drawActor( p, offsetX, offsetY ); + else + drawObject( p, offsetX, offsetY ); + + UMLWidget::setPen(p); + if(m_bSelected) + drawSelected(&p, offsetX, offsetY); +} + +void ObjectWidget::slotMenuSelection(int sel) { + QString name = ""; + switch(sel) { + case ListPopupMenu::mt_Rename_Object: + { + bool ok; + QRegExpValidator* validator = new QRegExpValidator(QRegExp(".*"), 0); + name = KInputDialog::getText + (i18n("Rename Object"), + i18n("Enter object name:"), + m_InstanceName, + &ok, + m_pView, + "renameobject", + validator); + if (ok) { + m_InstanceName = name; + updateComponentSize(); + moveEvent( 0 ); + update(); + UMLApp::app()->getDocument()->setModified(true); + } + delete validator; + break; + } + case ListPopupMenu::mt_Properties: + showProperties(); + updateComponentSize(); + moveEvent( 0 ); + update(); + break; + + case ListPopupMenu::mt_Up: + tabUp(); + break; + + case ListPopupMenu::mt_Down: + tabDown(); + break; + + default: + UMLWidget::slotMenuSelection(sel); + break; + } +} + +QSize ObjectWidget::calculateSize() { + int width, height; + const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE); + const int fontHeight = fm.lineSpacing(); + const QString t = m_InstanceName + " : " + m_pObject->getName(); + const int textWidth = fm.width(t); + if ( m_bDrawAsActor ) { + width = textWidth > A_WIDTH?textWidth:A_WIDTH; + height = A_HEIGHT + fontHeight + A_MARGIN; + width += A_MARGIN * 2; + } else { + width = textWidth > O_WIDTH?textWidth:O_WIDTH; + height = fontHeight + O_MARGIN * 2; + width += O_MARGIN * 2; + if (m_bMultipleInstance) { + width += 10; + height += 10; + } + }//end else drawasactor + + return QSize(width, height); +} + +void ObjectWidget::setDrawAsActor( bool drawAsActor ) { + m_bDrawAsActor = drawAsActor; + updateComponentSize(); +} + +void ObjectWidget::setMultipleInstance(bool multiple) { + //make sure only calling this in relation to an object on a collab. diagram + if(m_pView -> getType() != Uml::dt_Collaboration) + return; + m_bMultipleInstance = multiple; + updateComponentSize(); + update(); +} + +bool ObjectWidget::activate(IDChangeLog* ChangeLog /*= 0*/) { + if (! UMLWidget::activate(ChangeLog)) + return false; + if (m_bShowDestruction && m_pLine) + m_pLine->setupDestructionBox(); + moveEvent(0); + return true; +} + +void ObjectWidget::setX( int x ) { + UMLWidget::setX(x); + moveEvent(0); +} + +void ObjectWidget::setY( int y ) { + UMLWidget::setY(y); + moveEvent(0); +} + +void ObjectWidget::moveEvent(QMoveEvent */*m*/) { + emit sigWidgetMoved( m_nLocalID ); + if (m_pLine) { + const int x = getX(); // for debugging: gdb has a problem evaluating getX() etc + const int w = width(); + const int y = getY(); + const int h = height(); + m_pLine->setStartPoint(x + w / 2, y + h); + } +} + +void ObjectWidget::slotColorChanged(Uml::IDType /*viewID*/) { + UMLWidget::setFillColour( m_pView->getFillColor() ); + UMLWidget::setLineColor( m_pView->getLineColor() ); + + if( m_pLine) + m_pLine -> setPen( QPen( UMLWidget::getLineColor(), UMLWidget::getLineWidth(), Qt::DashLine ) ); +} + +void ObjectWidget::cleanup() { + + UMLWidget::cleanup(); + if( m_pLine ) { + m_pLine -> cleanup(); + delete m_pLine; + } +} + +void ObjectWidget::showProperties() { + DocWindow *docwindow = UMLApp::app()->getDocWindow(); + docwindow->updateDocumentation(false); + ClassPropDlg *dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this); + if (dlg->exec()) { + docwindow->showDocumentation(this, true); + UMLApp::app()->getDocument()->setModified(true); + } + dlg->close(true);//wipe from memory +} + +void ObjectWidget::drawObject(QPainter & p, int offsetX, int offsetY) { + + QFont oldFont = p.font(); + QFont font = UMLWidget::getFont(); + font.setUnderline( true ); + p.setFont( font ); + + UMLWidget::setPen(p); + if(UMLWidget::getUseFillColour()) + p.setBrush(UMLWidget::getFillColour()); + else + p.setBrush(m_pView -> viewport() -> backgroundColor()); + const int w = width(); + const int h = height(); + + const QString t = m_InstanceName + " : " + m_pObject -> getName(); + int multiInstOfst = 0; + if ( m_bMultipleInstance ) { + p.drawRect(offsetX + 10, offsetY + 10, w - 10, h - 10); + p.drawRect(offsetX + 5, offsetY + 5, w - 10, h - 10); + multiInstOfst = 10; + } + p.drawRect(offsetX, offsetY, w - multiInstOfst, h - multiInstOfst); + p.setPen(QPen(Qt::black)); + p.drawText(offsetX + O_MARGIN, offsetY + O_MARGIN, + w - O_MARGIN * 2 - multiInstOfst, h - O_MARGIN * 2 - multiInstOfst, + Qt::AlignCenter, t); + + p.setFont( oldFont ); +} + +void ObjectWidget::drawActor(QPainter & p, int offsetX, int offsetY) { + const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE); + + UMLWidget::setPen(p); + if ( UMLWidget::getUseFillColour() ) + p.setBrush( UMLWidget::getFillColour() ); + const int w = width(); + const int textStartY = A_HEIGHT + A_MARGIN; + const int fontHeight = fm.lineSpacing(); + + const int middleX = offsetX + w / 2; + const int thirdH = A_HEIGHT / 3; + + //draw actor + p.drawEllipse(middleX - A_WIDTH / 2, offsetY, A_WIDTH, thirdH);//head + p.drawLine(middleX, offsetY + thirdH, middleX, offsetY + thirdH * 2);//body + p.drawLine(middleX, offsetY + 2 * thirdH, + middleX - A_WIDTH / 2, offsetY + A_HEIGHT);//left leg + p.drawLine(middleX, offsetY + 2 * thirdH, + middleX + A_WIDTH / 2, offsetY + A_HEIGHT);//right leg + p.drawLine(middleX - A_WIDTH / 2, offsetY + thirdH + thirdH / 2, + middleX + A_WIDTH / 2, offsetY + thirdH + thirdH / 2);//arms + //draw text + p.setPen(QPen(Qt::black)); + QString t = m_InstanceName + " : " + m_pObject -> getName(); + p.drawText(offsetX + A_MARGIN, offsetY + textStartY, + w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, t); +} + +void ObjectWidget::tabUp() { + int newY = getY() - height(); + if (newY < topMargin()) + newY = topMargin(); + setY( newY ); + moveEvent( 0 ); + adjustAssocs( getX(), newY); +} + +void ObjectWidget::tabDown() { + int newY = getY() + height(); + setY( newY ); + moveEvent( 0 ); + adjustAssocs( getX(), newY); +} + +int ObjectWidget::topMargin() { + return 80 - height(); +} + +bool ObjectWidget::canTabUp() { + int y = getY(); + //kDebug() << "ObjectWidget::canTabUp: y is " << y << endl; + return (y > topMargin()); +} + +void ObjectWidget::setShowDestruction( bool bShow ) { + m_bShowDestruction = bShow; + if( m_pLine ) + m_pLine -> setupDestructionBox(); +} + +int ObjectWidget::getEndLineY() { + int y = this -> getY() + getHeight(); + if( m_pLine) + y += m_pLine -> getLineLength(); + if ( m_bShowDestruction ) + y += 10; + return y; +} + +void ObjectWidget::messageAdded(MessageWidget* message) { + if (messageWidgetList.containsRef(message) ) { + kError() << "ObjectWidget::messageAdded(" + << message->getName() << ") : duplicate entry !" + << endl; + return ; + } + messageWidgetList.append(message); +} + +void ObjectWidget::messageRemoved(MessageWidget* message) { + if ( messageWidgetList.remove(message) == false ) { + kError() << "ObjectWidget::messageRemoved(" + << message->getName() << ") : missing entry !" + << endl; + return ; + } +} + +void ObjectWidget::slotMessageMoved() { + MessageWidgetListIt iterator(messageWidgetList); + MessageWidget* message; + int lowestMessage = 0; + while ( (message = iterator.current()) != 0 ) { + ++iterator; + int messageHeight = message->getY() + message->getHeight(); + if (lowestMessage < messageHeight) { + lowestMessage = messageHeight; + } + } + m_pLine->setEndOfLine(lowestMessage + sequenceLineMargin); +} + +bool ObjectWidget::messageOverlap(int y, MessageWidget* messageWidget) { + MessageWidgetListIt iterator(messageWidgetList); + MessageWidget* message; + while ( (message = iterator.current()) != 0 ) { + ++iterator; + const int msgY = message->getY(); + const int msgHeight = msgY + message->getHeight(); + if (y >= msgY && y <= msgHeight && message != messageWidget) { + return true; + } + } + return false; +} + +SeqLineWidget *ObjectWidget::getSeqLine() { + return m_pLine; +} + +void ObjectWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) { + QDomElement objectElement = qDoc.createElement( "objectwidget" ); + UMLWidget::saveToXMI( qDoc, objectElement ); + objectElement.setAttribute( "instancename", m_InstanceName ); + objectElement.setAttribute( "drawasactor", m_bDrawAsActor ); + objectElement.setAttribute( "multipleinstance", m_bMultipleInstance ); + objectElement.setAttribute( "localid", ID2STR(m_nLocalID) ); + objectElement.setAttribute( "decon", m_bShowDestruction ); + qElement.appendChild( objectElement ); +} + +bool ObjectWidget::loadFromXMI( QDomElement & qElement ) { + if( !UMLWidget::loadFromXMI( qElement ) ) + return false; + m_InstanceName = qElement.attribute( "instancename", "" ); + QString draw = qElement.attribute( "drawasactor", "0" ); + QString multi = qElement.attribute( "multipleinstance", "0" ); + QString localid = qElement.attribute( "localid", "0" ); + QString decon = qElement.attribute( "decon", "0" ); + + m_bDrawAsActor = (bool)draw.toInt(); + m_bMultipleInstance = (bool)multi.toInt(); + m_nLocalID = STR2ID(localid); + m_bShowDestruction = (bool)decon.toInt(); + return true; + +} + +#include "objectwidget.moc" |