umbrello API Documentation

objectwidget.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
00007  *                                                                         *
00008  *   copyright (C) 2002-2007                                               *
00009  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00010  ***************************************************************************/
00011 
00012 // own header file
00013 #include "objectwidget.h"
00014 
00015 // system includes
00016 #include <qpainter.h>
00017 #include <qvalidator.h>
00018 #include <qevent.h>
00019 #include <klocale.h>
00020 #include <kdebug.h>
00021 #include <kinputdialog.h>
00022 
00023 // local includes
00024 #include "objectwidgetcontroller.h"
00025 #include "seqlinewidget.h"
00026 #include "umlview.h"
00027 #include "umldoc.h"
00028 #include "uml.h"
00029 #include "umlobject.h"
00030 #include "listpopupmenu.h"
00031 #include "docwindow.h"
00032 #include "dialogs/classpropdlg.h"
00033 
00038 static const int sequenceLineMargin = 20;
00039 
00040 ObjectWidget::ObjectWidget(UMLView * view, UMLObject *o, Uml::IDType lid)
00041         : UMLWidget(view, o) {
00042     init();
00043     if( lid != Uml::id_None )
00044         m_nLocalID = lid;
00045     //updateComponentSize();
00046     //                  Doing this during loadFromXMI() gives futile updates.
00047     //                  Instead, it is done afterwards by UMLWidget::activate()
00048 }
00049 
00050 void ObjectWidget::init() {
00051     UMLWidget::setBaseType(Uml::wt_Object);
00052     m_nLocalID = Uml::id_None;
00053     m_InstanceName = "";
00054     m_bMultipleInstance = false;
00055     m_bDrawAsActor = false;
00056     m_bShowDestruction = false;
00057     messageWidgetList.setAutoDelete(false);
00058     if( m_pView != NULL && m_pView -> getType() == Uml::dt_Sequence ) {
00059         m_pLine = new SeqLineWidget( m_pView, this );
00060 
00061         //Sets specific widget controller for sequence diagrams
00062         delete m_widgetController;
00063         m_widgetController = new ObjectWidgetController(this);
00064     } else {
00065         m_pLine = NULL;
00066     }
00067 }
00068 
00069 ObjectWidget::~ObjectWidget() {}
00070 
00071 void ObjectWidget::draw(QPainter & p , int offsetX, int offsetY) {
00072     if ( m_bDrawAsActor )
00073         drawActor( p, offsetX, offsetY );
00074     else
00075         drawObject( p, offsetX, offsetY );
00076 
00077     UMLWidget::setPen(p);
00078     if(m_bSelected)
00079         drawSelected(&p, offsetX, offsetY);
00080 }
00081 
00082 void ObjectWidget::slotMenuSelection(int sel) {
00083     QString name = "";
00084     switch(sel) {
00085     case ListPopupMenu::mt_Rename_Object:
00086         {
00087             bool ok;
00088             QRegExpValidator* validator = new QRegExpValidator(QRegExp(".*"), 0);
00089             name = KInputDialog::getText
00090                    (i18n("Rename Object"),
00091                     i18n("Enter object name:"),
00092                     m_InstanceName,
00093                     &ok,
00094                     m_pView,
00095                     "renameobject",
00096                     validator);
00097             if (ok) {
00098                 m_InstanceName = name;
00099                 updateComponentSize();
00100                 moveEvent( 0 );
00101                 update();
00102                 UMLApp::app()->getDocument()->setModified(true);
00103             }
00104             delete validator;
00105             break;
00106         }
00107     case ListPopupMenu::mt_Properties:
00108         showProperties();
00109         updateComponentSize();
00110         moveEvent( 0 );
00111         update();
00112         break;
00113 
00114     case ListPopupMenu::mt_Up:
00115         tabUp();
00116         break;
00117 
00118     case ListPopupMenu::mt_Down:
00119         tabDown();
00120         break;
00121 
00122     default:
00123         UMLWidget::slotMenuSelection(sel);
00124         break;
00125     }
00126 }
00127 
00128 QSize ObjectWidget::calculateSize() {
00129     int width, height;
00130     const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
00131     const int fontHeight  = fm.lineSpacing();
00132     const QString t = m_InstanceName + " : " + m_pObject->getName();
00133     const int textWidth = fm.width(t);
00134     if ( m_bDrawAsActor ) {
00135         width = textWidth > A_WIDTH?textWidth:A_WIDTH;
00136         height = A_HEIGHT + fontHeight + A_MARGIN;
00137         width += A_MARGIN * 2;
00138     } else {
00139         width = textWidth > O_WIDTH?textWidth:O_WIDTH;
00140         height = fontHeight + O_MARGIN * 2;
00141         width += O_MARGIN * 2;
00142         if (m_bMultipleInstance) {
00143             width += 10;
00144             height += 10;
00145         }
00146     }//end else drawasactor
00147 
00148     return QSize(width, height);
00149 }
00150 
00151 void ObjectWidget::setDrawAsActor( bool drawAsActor ) {
00152     m_bDrawAsActor = drawAsActor;
00153     updateComponentSize();
00154 }
00155 
00156 void ObjectWidget::setMultipleInstance(bool multiple) {
00157     //make sure only calling this in relation to an object on a collab. diagram
00158     if(m_pView -> getType() != Uml::dt_Collaboration)
00159         return;
00160     m_bMultipleInstance = multiple;
00161     updateComponentSize();
00162     update();
00163 }
00164 
00165 bool ObjectWidget::activate(IDChangeLog* ChangeLog /*= 0*/) {
00166     if (! UMLWidget::activate(ChangeLog))
00167         return false;
00168     if (m_bShowDestruction && m_pLine)
00169         m_pLine->setupDestructionBox();
00170     moveEvent(0);
00171     return true;
00172 }
00173 
00174 void ObjectWidget::setX( int x ) {
00175     UMLWidget::setX(x);
00176     moveEvent(0);
00177 }
00178 
00179 void ObjectWidget::setY( int y ) {
00180     UMLWidget::setY(y);
00181     moveEvent(0);
00182 }
00183 
00184 void ObjectWidget::moveEvent(QMoveEvent */*m*/) {
00185     emit sigWidgetMoved( m_nLocalID );
00186     if (m_pLine) {
00187         const int x = getX();    // for debugging: gdb has a problem evaluating getX() etc
00188         const int w = width();
00189         const int y = getY();
00190         const int h = height();
00191         m_pLine->setStartPoint(x + w / 2, y + h);
00192     }
00193 }
00194 
00195 void ObjectWidget::slotColorChanged(Uml::IDType /*viewID*/) {
00196     UMLWidget::setFillColour( m_pView->getFillColor() );
00197     UMLWidget::setLineColor( m_pView->getLineColor() );
00198 
00199     if( m_pLine)
00200         m_pLine -> setPen( QPen( UMLWidget::getLineColor(), UMLWidget::getLineWidth(), Qt::DashLine ) );
00201 }
00202 
00203 void ObjectWidget::cleanup() {
00204 
00205     UMLWidget::cleanup();
00206     if( m_pLine ) {
00207         m_pLine -> cleanup();
00208         delete m_pLine;
00209     }
00210 }
00211 
00212 void ObjectWidget::showProperties() {
00213     DocWindow *docwindow = UMLApp::app()->getDocWindow();
00214     docwindow->updateDocumentation(false);
00215     ClassPropDlg *dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this);
00216     if (dlg->exec()) {
00217         docwindow->showDocumentation(this, true);
00218         UMLApp::app()->getDocument()->setModified(true);
00219     }
00220     dlg->close(true);//wipe from memory
00221 }
00222 
00223 void ObjectWidget::drawObject(QPainter & p, int offsetX, int offsetY) {
00224 
00225     QFont oldFont = p.font();
00226     QFont font = UMLWidget::getFont();
00227     font.setUnderline( true );
00228     p.setFont( font );
00229 
00230     UMLWidget::setPen(p);
00231     if(UMLWidget::getUseFillColour())
00232         p.setBrush(UMLWidget::getFillColour());
00233     else
00234         p.setBrush(m_pView -> viewport() -> backgroundColor());
00235     const int w = width();
00236     const int h = height();
00237 
00238     const QString t = m_InstanceName + " : " + m_pObject -> getName();
00239     int multiInstOfst = 0;
00240     if ( m_bMultipleInstance ) {
00241         p.drawRect(offsetX + 10, offsetY + 10, w - 10, h - 10);
00242         p.drawRect(offsetX + 5, offsetY + 5, w - 10, h - 10);
00243         multiInstOfst = 10;
00244     }
00245     p.drawRect(offsetX, offsetY, w - multiInstOfst, h - multiInstOfst);
00246     p.setPen(QPen(Qt::black));
00247     p.drawText(offsetX + O_MARGIN, offsetY + O_MARGIN,
00248                w - O_MARGIN * 2 - multiInstOfst, h - O_MARGIN * 2 - multiInstOfst,
00249                Qt::AlignCenter, t);
00250 
00251     p.setFont( oldFont );
00252 }
00253 
00254 void ObjectWidget::drawActor(QPainter & p, int offsetX, int offsetY) {
00255     const QFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
00256 
00257     UMLWidget::setPen(p);
00258     if ( UMLWidget::getUseFillColour() )
00259         p.setBrush( UMLWidget::getFillColour() );
00260     const int w = width();
00261     const int textStartY = A_HEIGHT + A_MARGIN;
00262     const int fontHeight  = fm.lineSpacing();
00263 
00264     const int middleX = offsetX + w / 2;
00265     const int thirdH = A_HEIGHT / 3;
00266 
00267     //draw actor
00268     p.drawEllipse(middleX - A_WIDTH / 2, offsetY,  A_WIDTH, thirdH);//head
00269     p.drawLine(middleX, offsetY + thirdH, middleX, offsetY + thirdH * 2);//body
00270     p.drawLine(middleX, offsetY + 2 * thirdH,
00271                middleX - A_WIDTH / 2, offsetY + A_HEIGHT);//left leg
00272     p.drawLine(middleX, offsetY +  2 * thirdH,
00273                middleX + A_WIDTH / 2, offsetY + A_HEIGHT);//right leg
00274     p.drawLine(middleX - A_WIDTH / 2, offsetY + thirdH + thirdH / 2,
00275                middleX + A_WIDTH / 2, offsetY + thirdH + thirdH / 2);//arms
00276     //draw text
00277     p.setPen(QPen(Qt::black));
00278     QString t = m_InstanceName + " : " + m_pObject -> getName();
00279     p.drawText(offsetX + A_MARGIN, offsetY + textStartY,
00280                w - A_MARGIN * 2, fontHeight, Qt::AlignCenter, t);
00281 }
00282 
00283 void ObjectWidget::tabUp() {
00284     int newY = getY() - height();
00285     if (newY < topMargin())
00286         newY = topMargin();
00287     setY( newY );
00288     moveEvent( 0 );
00289     adjustAssocs( getX(), newY);
00290 }
00291 
00292 void ObjectWidget::tabDown() {
00293     int newY = getY() + height();
00294     setY( newY );
00295     moveEvent( 0 );
00296     adjustAssocs( getX(), newY);
00297 }
00298 
00299 int ObjectWidget::topMargin() {
00300     return 80 - height();
00301 }
00302 
00303 bool ObjectWidget::canTabUp() {
00304     int y = getY();
00305     //kDebug() << "ObjectWidget::canTabUp: y is " << y << endl;
00306     return (y > topMargin());
00307 }
00308 
00309 void ObjectWidget::setShowDestruction( bool bShow ) {
00310     m_bShowDestruction = bShow;
00311     if( m_pLine )
00312         m_pLine -> setupDestructionBox();
00313 }
00314 
00315 int ObjectWidget::getEndLineY() {
00316     int y = this -> getY() + getHeight();
00317     if( m_pLine)
00318         y += m_pLine -> getLineLength();
00319     if ( m_bShowDestruction )
00320         y += 10;
00321     return y;
00322 }
00323 
00324 void ObjectWidget::messageAdded(MessageWidget* message) {
00325     if (messageWidgetList.containsRef(message) ) {
00326         kError() << "ObjectWidget::messageAdded("
00327                   << message->getName() << ") : duplicate entry !"
00328                   << endl;
00329         return ;
00330     }
00331     messageWidgetList.append(message);
00332 }
00333 
00334 void ObjectWidget::messageRemoved(MessageWidget* message) {
00335     if ( messageWidgetList.remove(message) == false ) {
00336         kError() << "ObjectWidget::messageRemoved("
00337                   << message->getName() << ") : missing entry !"
00338                   << endl;
00339         return ;
00340     }
00341 }
00342 
00343 void ObjectWidget::slotMessageMoved() {
00344     MessageWidgetListIt iterator(messageWidgetList);
00345     MessageWidget* message;
00346     int lowestMessage = 0;
00347     while ( (message = iterator.current()) != 0 ) {
00348         ++iterator;
00349         int messageHeight = message->getY() + message->getHeight();
00350         if (lowestMessage < messageHeight) {
00351             lowestMessage = messageHeight;
00352         }
00353     }
00354     m_pLine->setEndOfLine(lowestMessage + sequenceLineMargin);
00355 }
00356 
00357 bool ObjectWidget::messageOverlap(int y, MessageWidget* messageWidget) {
00358     MessageWidgetListIt iterator(messageWidgetList);
00359     MessageWidget* message;
00360     while ( (message = iterator.current()) != 0 ) {
00361         ++iterator;
00362         const int msgY = message->getY();
00363         const int msgHeight = msgY + message->getHeight();
00364         if (y >= msgY && y <= msgHeight && message != messageWidget) {
00365             return true;
00366         }
00367     }
00368     return false;
00369 }
00370 
00371 SeqLineWidget *ObjectWidget::getSeqLine() {
00372     return m_pLine;
00373 }
00374 
00375 void ObjectWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
00376     QDomElement objectElement = qDoc.createElement( "objectwidget" );
00377     UMLWidget::saveToXMI( qDoc, objectElement );
00378     objectElement.setAttribute( "instancename", m_InstanceName );
00379     objectElement.setAttribute( "drawasactor", m_bDrawAsActor );
00380     objectElement.setAttribute( "multipleinstance", m_bMultipleInstance );
00381     objectElement.setAttribute( "localid", ID2STR(m_nLocalID) );
00382     objectElement.setAttribute( "decon", m_bShowDestruction );
00383     qElement.appendChild( objectElement );
00384 }
00385 
00386 bool ObjectWidget::loadFromXMI( QDomElement & qElement ) {
00387     if( !UMLWidget::loadFromXMI( qElement ) )
00388         return false;
00389     m_InstanceName = qElement.attribute( "instancename", "" );
00390     QString draw = qElement.attribute( "drawasactor", "0" );
00391     QString multi = qElement.attribute( "multipleinstance", "0" );
00392     QString localid = qElement.attribute( "localid", "0" );
00393     QString decon = qElement.attribute( "decon", "0" );
00394 
00395     m_bDrawAsActor = (bool)draw.toInt();
00396     m_bMultipleInstance = (bool)multi.toInt();
00397     m_nLocalID = STR2ID(localid);
00398     m_bShowDestruction = (bool)decon.toInt();
00399     return true;
00400 
00401 }
00402 
00403 #include "objectwidget.moc"
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:07:58 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003