00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "objectwidget.h"
00014
00015
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
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
00046
00047
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
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 }
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
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 ) {
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 *) {
00185 emit sigWidgetMoved( m_nLocalID );
00186 if (m_pLine) {
00187 const int x = getX();
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 ) {
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);
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
00268 p.drawEllipse(middleX - A_WIDTH / 2, offsetY, A_WIDTH, thirdH);
00269 p.drawLine(middleX, offsetY + thirdH, middleX, offsetY + thirdH * 2);
00270 p.drawLine(middleX, offsetY + 2 * thirdH,
00271 middleX - A_WIDTH / 2, offsetY + A_HEIGHT);
00272 p.drawLine(middleX, offsetY + 2 * thirdH,
00273 middleX + A_WIDTH / 2, offsetY + A_HEIGHT);
00274 p.drawLine(middleX - A_WIDTH / 2, offsetY + thirdH + thirdH / 2,
00275 middleX + A_WIDTH / 2, offsetY + thirdH + thirdH / 2);
00276
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
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"