You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/umbrello/umbrello/objectwidget.cpp

404 lines
12 KiB

/***************************************************************************
* *
* 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 <tqpainter.h>
#include <tqvalidator.h>
#include <tqevent.h>
#include <tdelocale.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(TQPainter & 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) {
TQString name = "";
switch(sel) {
case ListPopupMenu::mt_Rename_Object:
{
bool ok;
TQRegExpValidator* validator = new TQRegExpValidator(TQRegExp(".*"), 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;
}
}
TQSize ObjectWidget::calculateSize() {
int width, height;
const TQFontMetrics &fm = getFontMetrics(FT_UNDERLINE);
const int fontHeight = fm.lineSpacing();
const TQString 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 TQSize(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(TQMoveEvent */*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( TQPen( UMLWidget::getLineColor(), UMLWidget::getLineWidth(), TQt::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((TQWidget*)UMLApp::app(), this);
if (dlg->exec()) {
docwindow->showDocumentation(this, true);
UMLApp::app()->getDocument()->setModified(true);
}
dlg->close(true);//wipe from memory
}
void ObjectWidget::drawObject(TQPainter & p, int offsetX, int offsetY) {
TQFont oldFont = p.font();
TQFont 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 TQString 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(TQPen(TQt::black));
p.drawText(offsetX + O_MARGIN, offsetY + O_MARGIN,
w - O_MARGIN * 2 - multiInstOfst, h - O_MARGIN * 2 - multiInstOfst,
TQt::AlignCenter, t);
p.setFont( oldFont );
}
void ObjectWidget::drawActor(TQPainter & p, int offsetX, int offsetY) {
const TQFontMetrics &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(TQPen(TQt::black));
TQString t = m_InstanceName + " : " + m_pObject -> getName();
p.drawText(offsetX + A_MARGIN, offsetY + textStartY,
w - A_MARGIN * 2, fontHeight, TQt::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( TQDomDocument & qDoc, TQDomElement & qElement ) {
TQDomElement 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( TQDomElement & qElement ) {
if( !UMLWidget::loadFromXMI( qElement ) )
return false;
m_InstanceName = qElement.attribute( "instancename", "" );
TQString draw = qElement.attribute( "drawasactor", "0" );
TQString multi = qElement.attribute( "multipleinstance", "0" );
TQString localid = qElement.attribute( "localid", "0" );
TQString 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"