/* * * Copyright (c) 1995 * Knowledge Science Institute, University of Calgary * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. The Knowledge Science Institute makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * */ #ifdef __BCPLUSPLUS__ //---Borland C++ #include #pragma hdrstop #endif #include "graphic.h" #include #if defined(QUICKWIN) #include #endif #include extern int ConnectorTerminalTargetNumber; //global variable to hold the arm hit /****************************************************************************** ************************** class SensitiveGraphic ***************************** ******************************************************************************/ SensitiveGraphic::SensitiveGraphic(GraphicContainer* parent, char* visualClassName) : BehaviouralGraphic(parent,visualClassName) { MTRACE(SensitiveGraphic,SensitiveGraphic) MCONSTRUCTOR_IMP_CODE_VIRTUAL(SensitiveGraphic); MEXIT_CODE(SensitiveGraphic,SensitiveGraphic) } SensitiveGraphic::SensitiveGraphic(const SensitiveGraphic& g, GraphicContainer* parent) : BehaviouralGraphic(g,parent) { MTRACE(SensitiveGraphic,SensitiveGraphic) MCONSTRUCTOR_IMP_CODE_VIRTUAL(SensitiveGraphic); MEXIT_CODE(SensitiveGraphic,SensitiveGraphic) } SensitiveGraphic::~SensitiveGraphic() { MTRACE(SensitiveGraphic,~SensitiveGraphic) MDESTRUCTOR_IMP_CODE_VIRTUAL(SensitiveGraphic); MTRACEOUT(SensitiveGraphic,~SensitiveGraphic) } void SensitiveGraphic::classInvarient(char* file, int line) const { BehaviouralGraphic::classInvarient(file,line); } GraphicContainer* SensitiveGraphic::getParent() const { MENTRY_CODE(SensitiveGraphic,getParent); GraphicContainer* ret = dynamic_cast(Graphic::getParent()); //MASSERT(ret); MEXIT_CODE(SensitiveGraphic,getParent); return ret; } POINT sgMoveOffset, sgOriginalPos; SensitiveGraphic* sgMovingObject; void SensitiveGraphic::trackToBegin(POINT& p) { MENTRY_CODE(SensitiveGraphic,trackToBegin); if (getParent()) getParent()->popToTop((SensitiveGraphic*)this); if (getParent()) getParent()->setCaptureGraphic((SensitiveGraphic*)this); sgMovingObject = this; RECT r = getRect(); sgMoveOffset.x = p.x-r.left; sgMoveOffset.y = p.y-r.top; sgOriginalPos.x = r.left; sgOriginalPos.y = r.top; MEXIT_CODE(SensitiveGraphic,trackToBegin); } void SensitiveGraphic::trackTo(POINT& p) { MENTRY_CODE(SensitiveGraphic,trackTo); POINT q; q.x = p.x-sgMoveOffset.x; q.y = p.y-sgMoveOffset.y; moveTo(q); MEXIT_CODE(SensitiveGraphic,trackTo); } void SensitiveGraphic::trackToEnd(POINT& p) { MENTRY_CODE(SensitiveGraphic,trackToEnd); POINT q; q.x = p.x-sgMoveOffset.x; q.y = p.y-sgMoveOffset.y; Command* cmd = new Command1(GraphicObjectLocator((SensitiveGraphic*)this),CMD_MOVETO,q,sgOriginalPos); dispatch(cmd); if (getParent()) getParent()->setCaptureGraphic(NULL); sgMovingObject = NULL; MEXIT_CODE(SensitiveGraphic,trackToEnd); } void SensitiveGraphic::showMenu(POINT *p) { MENTRY_CODE(SensitiveGraphic,showMenu); POINT pt; if (p) pt = *p; else { RECTANGLE r = getRect(); pt.x = r.right-((r.right-r.left)>>2); pt.y = r.bottom-((r.bottom-r.top)>>2); } MENU menu = doMakeMenu(); char cmdName[CM_MAXNAME]; int cmd = trackPopupMenu(menu,pt,cmdName,CM_MAXNAME); destroyMenu(menu); if (cmd>0) { Command* command = doGenerateCommand(cmd,p,cmdName); if (command) dispatch(command); } MTRACEOUT(SensitiveGraphic,showMenu); } Command* SensitiveGraphic::doGenerateCommand(WORD command, POINT *p, char* cmdName) { MENTRY_CODE(SensitiveGraphic,doGenerateCommand); Command* ret = NULL; switch (command) { case CMD_DELETE: ret = getDeleteCommand(); break; case CMD_RESIZE: ret = getResizeCommand(); break; default: if (command>=CMD_FIRSTSHAPE && cmdName) ret = getSetVisualCommand(cmdName); else error(0,'E',"SensitiveGraphic::doGenerateCommand(%u): unimplemented",command); break; } MTRACEOUT(SensitiveGraphic,doGenerateCommand); return ret; } int SensitiveGraphic::execute(Command* c) { MENTRY_CODE(SensitiveGraphic,execute); int ret = 0; switch (c->id()) { case CMD_DELETE: { if (getParent()) getParent()->queueForPaint(getBoundingRect()); CommandPtr1* rc = dynamic_cast*>(c); if (rc) { rc->setOriginalValue((SensitiveGraphic*)this); //has to be done here and NULLed out in undoing it to prevent the command from destroying it setParent(NULL); //delete this; //this is now owned by the ptr in the command object } else error(0,'E',"SensitiveGraphic::execute: Bad DELETE command, type = %s",typeid(c).name()); } break; case CMD_RESIZE: { Command1* rc = dynamic_cast*>(c); if (rc) resize(&rc->getValue()); else error(0,'E',"SensitiveGraphic::execute: Bad RESIZE command, type = %s",typeid(c).name()); } break; case CMD_CHANGESHAPE: { Command1* sc = dynamic_cast*>(c); if (sc) setVisual(sc->getValue().c_str()); else error(0,'E',"SensitiveGraphic::execute: Bad CHANGE SHAPE command, type = %s",typeid(c).name()); } break; case CMD_MOVETO: { Command1* pc = dynamic_cast*>(c); if (pc) moveTo(pc->getValue()); else error(0,'E',"SensitiveGraphic::undo: Bad MOVE TO command, type = %s",typeid(c).name()); } break; default: ret = -1; break; } MTRACEOUT(SensitiveGraphic,execute); return ret; } int SensitiveGraphic::undo(Command* c) { MENTRY_CODE(SensitiveGraphic,undo); int ret = 0; switch (c->id()) { case CMD_DELETE: error(0,'W',"Cannot undo a deletion!"); ret = -98; break; case CMD_RESIZE: { Command1* rc = dynamic_cast*>(c); if (rc) resize(&rc->getOriginalValue()); else error(0,'E',"SensitiveGraphic::undo: Bad RESIZE command, type = %s",typeid(c).name()); } break; case CMD_CHANGESHAPE: { Command1* sc = dynamic_cast*>(c); if (sc) setVisual(sc->getOriginalValue().c_str()); else error(0,'E',"SensitiveGraphic::undo: Bad CHANGE SHAPE command, type = %s",typeid(c).name()); } break; case CMD_MOVETO: { Command1* pc = dynamic_cast*>(c); if (pc) moveTo(pc->getOriginalValue()); else error(0,'E',"SensitiveGraphic::undo: Bad MOVE TO command, type = %s",typeid(c).name()); } break; default: ret = -1; break; } MTRACEOUT(SensitiveGraphic,undo); return ret; } CURSOR SensitiveGraphic::getCusor(POINT &p) { MENTRY_CODE(SensitiveGraphic,getCusor); error(0,'E',"SensitiveGraphic::getCusor: unimplemented"); MEXIT_CODE(SensitiveGraphic,getCusor); } Command* SensitiveGraphic::getResizeCommand(RECTANGLE *r) { MENTRY_CODE(SensitiveGraphic,getResizeCommand); RECTANGLE origRect = getRect(); Command* cmd = new Command1(GraphicObjectLocator((SensitiveGraphic*)this),CMD_RESIZE,r?*r:trackRectangle(getRect()),origRect); MEXIT_CODE(SensitiveGraphic,getResizeCommand); return cmd; } void SensitiveGraphic::resize(RECTANGLE *r) { MENTRY_CODE(SensitiveGraphic,resize); setRect(r?*r:trackRectangle(getRect())); Shape* s = dynamic_cast(getVisual()); if (s) s->clearFlags(Shape::SH_AUTOSIZE); MEXIT_CODE(SensitiveGraphic,resize); } Command* SensitiveGraphic::getDeleteCommand() { MENTRY_CODE(SensitiveGraphic,getDeleteCommand); Command* cmd = new CommandPtr1(GraphicObjectLocator((SensitiveGraphic*)this),CMD_DELETE,NULL,NULL); MTRACEOUT(SensitiveGraphic,getDeleteCommand); return cmd; } Command* SensitiveGraphic::getMoveToCommand(const POINT& p) { MENTRY_CODE(SensitiveGraphic,getMoveToCommand); Command* cmd = new Command1(GraphicObjectLocator((SensitiveGraphic*)this),CMD_MOVETO,p,*(POINT*)&getRect()); MEXIT_CODE(SensitiveGraphic,getMoveToCommand); return cmd; } Command* SensitiveGraphic::getSetVisualCommand(const char* vName) { MENTRY_CODE(SensitiveGraphic,getSetVisualCommand); Command* cmd = new Command1(GraphicObjectLocator(this),CMD_CHANGESHAPE,vName,VisualClassName); MEXIT_CODE(SensitiveGraphic,getSetVisualCommand); return cmd; } MENU SensitiveGraphic::doMakeMenu() { MENTRY_CODE(SensitiveGraphic,doMakeMenu); MENU m = createPopupMenu(); appendMenu_String(m,CMD_DELETE,"Delete"); MEXIT_CODE(SensitiveGraphic,doMakeMenu); return m; } void SensitiveGraphic::doMouseMove(unsigned int modKeys, POINT& p) { MENTRY_CODE(SensitiveGraphic,doMouseMove); if (sgMovingObject==this) trackTo(p); MEXIT_CODE(SensitiveGraphic,doMouseMove); } void SensitiveGraphic::doLButtonDown(unsigned int modKeys, POINT& p) { MENTRY_CODE(SensitiveGraphic,doLButtonDown); trackToBegin(p); MEXIT_CODE(SensitiveGraphic,doLButtonDown); } void SensitiveGraphic::doLButtonUp(unsigned int modKeys, POINT& p) { MENTRY_CODE(SensitiveGraphic,doLButtonUp); if (sgMovingObject==this) trackToEnd(p); MEXIT_CODE(SensitiveGraphic,doLButtonUp); } void SensitiveGraphic::doLButtonDblClk(unsigned int modKeys, POINT& p) { MENTRY_CODE(SensitiveGraphic,doLButtonDblClk); MEXIT_CODE(SensitiveGraphic,doLButtonDblClk); } void SensitiveGraphic::doRButtonDown(unsigned int modKeys, POINT& p) { MENTRY_CODE(SensitiveGraphic,doRButtonDown); showMenu(&p); MTRACEOUT(SensitiveGraphic,doRButtonDown); //may have been deleted } void SensitiveGraphic::doRButtonUp(unsigned int modKeys, POINT& p) { MENTRY_CODE(SensitiveGraphic,doRButtonUp); MEXIT_CODE(SensitiveGraphic,doRButtonUp); } void SensitiveGraphic::doRButtonDblClk(unsigned int modKeys, POINT& p) { MENTRY_CODE(SensitiveGraphic,doRButtonDblClk); MEXIT_CODE(SensitiveGraphic,doRButtonDblClk); } /****************************************************************************** ************************** class RelationableGraphic ************************** ******************************************************************************/ RelationableGraphic::RelationableGraphic(GraphicContainer* parent, char* visualClassName) : BehaviouralGraphic(parent,visualClassName) { MTRACE(RelationableGraphic,RelationableGraphic) MCONSTRUCTOR_IMP_CODE_VIRTUAL(RelationableGraphic); MEXIT_CODE(RelationableGraphic,RelationableGraphic) } RelationableGraphic::RelationableGraphic(const RelationableGraphic& g, GraphicContainer* parent) : BehaviouralGraphic(g,parent) { MTRACE(RelationableGraphic,RelationableGraphic) MCONSTRUCTOR_IMP_CODE_VIRTUAL(RelationableGraphic); MEXIT_CODE(RelationableGraphic,RelationableGraphic) } RelationableGraphic::~RelationableGraphic() { MTRACE(RelationableGraphic,~RelationableGraphic) MDESTRUCTOR_IMP_CODE_VIRTUAL(RelationableGraphic); MTRACEOUT(RelationableGraphic,~RelationableGraphic) } void RelationableGraphic::classInvarient(char* file, int line) const { BehaviouralGraphic::classInvarient(file,line); } POINT RelationableGraphic::getAttachmentPoint(RECTANGLE& r) { MENTRY_CODE(RelationableGraphic,getAttachmentPoint); POINT ret; RECTANGLE s = getRect(); ret.x = (s.left+s.right)>>1; ret.y = (s.bottom+s.top)>>1; MEXIT_CODE(RelationableGraphic,getAttachmentPoint); return ret; } POINT RelationableGraphic::getAttachmentPoint(POINT& p) { MENTRY_CODE(RelationableGraphic,getAttachmentPoint); POINT ret; RECTANGLE r = getRect(); VisualGraphic::CompassPoints cp; if (p.x <= r.left ) cp = VisualGraphic::W; else if (p.x >= r.right ) cp = VisualGraphic::E; else cp = 0; if (p.y <= r.top ) cp |= VisualGraphic::N; else if (p.y >= r.bottom) cp |= VisualGraphic::S; ret = getVisual()->getEdge(cp); MEXIT_CODE(RelationableGraphic,getAttachmentPoint); return ret; } CompositeCommand* RelationableGraphic::getPartialDeleteCommand() { MENTRY_CODE(RelationableGraphic,getPartialDeleteCommand); CompositeCommand* ccmd = new CompositeCommand(CMD_DELETE); for (list::iterator i=Observers.begin(); i!=Observers.end(); i++) { Maplet* m = dynamic_cast(*i); if (m) { for (int i=m->getArity(); --i>=0; ) { if ((*m)[i]==(RelationableGraphic*)this) ccmd->append(m->getSetConnectionCommand(i,0)); } } } MTRACEOUT(RelationableGraphic,getPartialDeleteCommand); return ccmd; } void RelationableGraphic::notifyChanged(ID_type id) { MENTRY_CODE(RelationableGraphic,notifyChanged); BehaviouralGraphic::notifyChanged(id); if (id==getVisual()->id()) notify(); MENTRY_CODE(RelationableGraphic,notifyChanged); } /****************************************************************************** ************************** class SRGraphic ************************** ******************************************************************************/ SRGraphic::SRGraphic(GraphicContainer* parent, char* visualClassName) : SensitiveGraphic(parent,visualClassName), RelationableGraphic(parent,visualClassName), BehaviouralGraphic(parent,visualClassName) { MTRACE(SRGraphic,SRGraphic) MCONSTRUCTOR_IMP_CODE_VIRTUAL(SRGraphic); MEXIT_CODE(SRGraphic,SRGraphic) } SRGraphic::SRGraphic(const SRGraphic& g, GraphicContainer* parent) : SensitiveGraphic(g,parent), RelationableGraphic(g,parent), BehaviouralGraphic(g,parent) { MTRACE(SRGraphic,SRGraphic) MCONSTRUCTOR_IMP_CODE_VIRTUAL(SRGraphic); MEXIT_CODE(SRGraphic,SRGraphic) } SRGraphic::~SRGraphic() { MTRACE(SRGraphic,~SRGraphic) MDESTRUCTOR_IMP_CODE_VIRTUAL(SRGraphic); MTRACEOUT(SRGraphic,~SRGraphic) } void SRGraphic::classInvarient(char* file, int line) const { SensitiveGraphic::classInvarient(file,line); RelationableGraphic::classInvarient(file,line); } Command* SRGraphic::getDeleteCommand() { MENTRY_CODE(SRGraphic,getDeleteCommand); CompositeCommand* ccmd = RelationableGraphic::getPartialDeleteCommand(); ccmd->append(SensitiveGraphic::getDeleteCommand()); MEXIT_CODE(SRGraphic,getDeleteCommand); return ccmd; } void SRGraphic::notifyChanged(ID_type id) { MENTRY_CODE(SRGraphic,notifyChanged); RelationableGraphic::notifyChanged(id); MENTRY_CODE(SRGraphic,notifyChanged); } /****************************************************************************** ************************** class Maplet ************************** ******************************************************************************/ Maplet::Maplet(GraphicContainer* parent, char* visualClassName, POINT& handle, unsigned short nEndPoints) : BehaviouralGraphic(parent,visualClassName), Terminals(nEndPoints,NULL), TerminalCount(nEndPoints), Handle(handle) { MTRACE(Maplet,Maplet) MCONSTRUCTOR_IMP_CODE(Maplet); MEXIT_CODE(Maplet,Maplet) } Maplet::Maplet(const Maplet& g, GraphicContainer* parent) : BehaviouralGraphic(g,parent), Terminals(g.Terminals), TerminalCount(g.TerminalCount), Handle(g.Handle) { MTRACE(Maplet,Maplet) MCONSTRUCTOR_IMP_CODE(Maplet); MEXIT_CODE(Maplet,Maplet) } Maplet::~Maplet() { MTRACE(Maplet,~Maplet) vector::iterator i; for (i=Terminals.begin(); i!=Terminals.end(); i++) if (*i) (*i)->detachObserver((Maplet*)this); MDESTRUCTOR_IMP_CODE(Maplet); MTRACEOUT(Maplet,~Maplet) } void Maplet::classInvarient(char* file, int line) const { BehaviouralGraphic::classInvarient(file,line); } ostream& Maplet::printOn(ostream& o) const { MENTRY_CODE(Maplet,printOn) BehaviouralGraphic::printOn(o); Connector* s = getConnector(); MASSERT(s); Lexer::writeDelim(o); Lexer::writePoint(o,s->getHandle()); int len = getArity(); Lexer::writeDelim(o); Lexer::writeLong(o,len); for (int i=0; iid()); } MEXIT_CODE(Maplet,printOn) return o; } istream& Maplet::readFrom(istream& i, Version* version) { MENTRY_CODE(Maplet,readFrom) BehaviouralGraphic::readFrom(i,version); Connector* s = getConnector(); MASSERT(s); POINT pt; Lexer::readDelim(i); Lexer::readPoint(i,pt); moveTo(pt); long len; Lexer::readDelim(i); Lexer::readLong(i,len); MASSERT(len==getArity()); for (int j=0; j((*getParent())[id]))) { setConnection(j,rg); } } } MEXIT_CODE(Maplet,readFrom) return i; } Connector* Maplet::getConnector() { MENTRY_CODE(Maplet,getConnector) Connector* c = NULL; if (!Visual && VisualClassName) { setVisual(NULL); } c = dynamic_cast(Visual); MASSERT(c); MEXIT_CODE(Maplet,getConnector) return c; } ERRORCODE Maplet::setVisual(const char* visualClassName) { MENTRY_CODE(Maplet,setVisual) if (visualClassName) { if (VisualClassName) delete VisualClassName; VisualClassName = strdup(visualClassName); } //replace the old Visual VisualGraphic* newVisual = GraphicsFactory::getInstance()->getConnector(VisualClassName,(GraphicContainer*)this); if (Visual) { newVisual->copyFeatures(*Visual); delete Visual; } Visual = newVisual; unsigned int arity = getConnector()->getArity(); //extend the Terminls vector if necessary if (TerminalCountarity; ) { if (Terminals[--TerminalCount]) Terminals[TerminalCount]->detachObserver((Maplet*)this); Terminals[TerminalCount] = NULL; } //connect up the new Visual to any objects for (int i=0; isetEndPoint(i,Terminals[i]->getAttachmentPoint(Handle)); else park(i); } getConnector()->moveTo(Handle); MPOSTCONDITION(arity==TerminalCount); MEXIT_CODE(Maplet,setVisual) return 0; } int Maplet::setConnection(unsigned short index, RelationableGraphic* g) { MENTRY_CODE(Maplet,setConnection) int ret = 0; if (index>=TerminalCount) ret = -1; else if (g!=Terminals[index]) { if (Terminals[index]) Terminals[index]->detachObserver((Maplet*)this); if (g) { getConnector()->setEndPoint(index,g->getAttachmentPoint(Handle)); g->attachObserver((Maplet*)this); Terminals[index] = g; } else { Terminals[index] = g; //g==NULL, must do this first to prevent inf recursion park(index); } } MEXIT_CODE(Maplet,setConnection) return ret; } RelationableGraphic* Maplet::operator[](unsigned short index) { MENTRY_CODE(Maplet,operator[]) RelationableGraphic* ret; if (index::const_iterator i; for (i=c.Terminals.begin(); i!=c.Terminals.end(); i++) { Terminals.push_back((*i)?((RelationableGraphic*)(void*)(*i)->clone()):NULL); } MEXIT_CODE(Maplet,operator=) return *this; } void Maplet::flush() { MENTRY_CODE(Maplet,flush); vector::iterator i; for (i=Terminals.begin(); i!=Terminals.end(); i++) (*i) = NULL; MEXIT_CODE(Maplet,flush); } int Maplet::update(Subject* s) { MENTRY_CODE(Maplet,update); int i; RelationableGraphic* node = dynamic_cast(s); if (node) { for (i=0; isetEndPoint(i,node->getAttachmentPoint(Handle)); } } MEXIT_CODE(Maplet,update); return 0; } int Maplet::subjectDestroyed(const Subject* s) { MENTRY_CODE(Maplet,subjectDestroyed); for (unsigned int i=0; idestructing())) park(i); } } MEXIT_CODE(Maplet,subjectDestroyed); return 0; } void Maplet::moveTo(POINT& p) { MENTRY_CODE(Maplet,moveTo); getConnector()->moveTo(p); Handle.x=p.x; Handle.y=p.y; int i; for (i=0; isetEndPoint(i,Terminals[i]->getAttachmentPoint(Handle)); else park(i); } MEXIT_CODE(Maplet,moveTo); } void Maplet::park(unsigned int index) { MENTRY_CODE(Maplet,moveTo); setConnection(index,NULL); int yOff = ((TerminalCount&1)?10:0) - (((TerminalCount-1)/2)*20); POINT pt = {Handle.x+(index?40:-40), Handle.y+(index?(20*(index-1))+yOff:0)}; getConnector()->setEndPoint(index,pt); MEXIT_CODE(Maplet,moveTo); } Command* Maplet::getSetConnectionCommand(unsigned int index, ID_type relID) { MENTRY_CODE(Maplet,getSetConnectionCommand); Command* cmd = new Command2(GraphicObjectLocator((Maplet*)this),CMD_SETCONNECTION, index, relID, index, (*this)[index]?(*this)[index]->id():0); MEXIT_CODE(Maplet,getSetConnectionCommand); return cmd; } int Maplet::execute(Command* c) { MENTRY_CODE(Maplet,execute); int ret = -143; switch (c->id()) { case CMD_SETCONNECTION: { Command2* sc = dynamic_cast*>(c); if (sc) { if (getParent()) { RelationableGraphic* rg = sc->getValue2()? dynamic_cast((*getParent())[sc->getValue2()]): NULL; setConnection(sc->getValue1(),rg); ret = 0; } else error(0,'E',"Node::execute: SET CONNECTION no parent"); } else error(0,'E',"Node::execute: Bad SET CONNECTION command, type = %s",typeid(c).name()); } break; default: break; } MTRACEOUT(Maplet,execute); return ret; } int Maplet::undo(Command* c) { MENTRY_CODE(Maplet,undo); int ret = -143; switch (c->id()) { case CMD_SETCONNECTION: { Command2* sc = dynamic_cast*>(c); if (sc) { if (getParent()) { RelationableGraphic* rg = sc->getOriginalValue2()? dynamic_cast((*getParent())[sc->getOriginalValue2()]): NULL; setConnection(sc->getOriginalValue1(),rg); ret = 0; } else error(0,'E',"Node::undo: SET CONNECTION no parent"); } else error(0,'E',"Node::undo: Bad SET CONNECTION command, type = %s",typeid(c).name()); } default: break; } MTRACEOUT(Maplet,undo); return ret; } /****************************************************************************** ************************** class Node ************************** ******************************************************************************/ Node::Node(GraphicContainer* parent, char* visualClassName, const char* label, const RECTANGLE* rect) : SRGraphic(parent,visualClassName), BehaviouralGraphic(parent,visualClassName) { MTRACE(Node,Node) MCONSTRUCTOR_IMP_CODE(Node); if (label) setText(label); if (rect) setRect(*rect); MEXIT_CODE(Node,Node) } Node::Node(const Node& g, GraphicContainer* parent) : BehaviouralGraphic(g,parent), SRGraphic(g,parent) { MTRACE(Node,Node) MCONSTRUCTOR_IMP_CODE(Node); setText(g.getText()); MEXIT_CODE(Node,Node) } Node::~Node() { MTRACE(Node,~Node) MDESTRUCTOR_IMP_CODE(Node); MTRACEOUT(Node,~Node) } void Node::classInvarient(char* file, int line) const { SRGraphic::classInvarient(file,line); } ostream& operator<<(ostream& o, RECTANGLE r) { return o << r.left << ' ' << r.top << ' ' << r.right << ' ' << r.bottom; } ostream& Node::printOn(ostream& o) const { MENTRY_CODE(Node,printOn) SRGraphic::printOn(o); Shape* s = getShape(); /* o << ',' << s->getRect() << ',' << ((s->getText())?(s->getText()):"") << ',' << s->getFillColor() << ',' << s->getBorderColor() << ',' << s->getTextColor(); */ Lexer::writeDelim(o); Lexer::writeRectangle(o,s->getRect()); Lexer::writeDelim(o); Lexer::writeQuotedString(o,((s->getText())?(s->getText()):"")); Lexer::writeDelim(o); Lexer::writeUnsigned(o,s->getFillColor()); Lexer::writeDelim(o); Lexer::writeUnsigned(o,s->getBorderColor()); Lexer::writeDelim(o); Lexer::writeUnsigned(o,s->getTextColor()); Lexer::writeDelim(o); Lexer::writeUnsigned(o,s->getFlags()); MEXIT_CODE(Node,printOn) return o; } istream& Node::readFrom(istream& i, Version* version) { MENTRY_CODE(Node,readFrom) SRGraphic::readFrom(i, version); Shape* s = getShape(); RECTANGLE r; Lexer::readDelim(i); if (!Lexer::readRectangle(i,r)) s->setRect(r); string str; Lexer::readDelim(i); if (!Lexer::readQuotedString(i,str)) s->setText(str.c_str()); unsigned long col; Lexer::readDelim(i); if (!Lexer::readUnsigned(i,col)) s->setFillColor(col); Lexer::readDelim(i); if (!Lexer::readUnsigned(i,col)) s->setBorderColor(col); Lexer::readDelim(i); if (!Lexer::readUnsigned(i,col)) s->setTextColor(col); Lexer::readDelim(i); if (!Lexer::readUnsigned(i,col)){s->clearFlags(0xFFFFFFFF); s->setFlags(col);} MEXIT_CODE(Node,readFrom) return i; } Shape* Node::getShape() { MENTRY_CODE(Node,getShape) if (!Visual && VisualClassName) Visual = GraphicsFactory::getInstance()->getShape(VisualClassName,(Node*)this); MASSERT(dynamic_cast(Visual)); MEXIT_CODE(Node,getShape) return dynamic_cast(Visual); } ERRORCODE Node::setVisual(const char* visualClassName) { MENTRY_CODE(Node,setVisual) ERRORCODE ret = 0; if (VisualClassName) delete VisualClassName; VisualClassName = strdup(visualClassName); Shape* newVisual = GraphicsFactory::getInstance()->getShape(visualClassName,(Node*)this); if (Visual) { newVisual->copyFeatures(*Visual); delete Visual; } Visual = newVisual; notify(); MEXIT_CODE(Node,setVisual) return ret; } const char* Node::getText() const { MENTRY_CODE(Node,getText); const char* ret = getShape()->getText(); MEXIT_CODE(Node,getText); return ret; } void Node::setText(const char* c) { MENTRY_CODE(Node,setText); Shape* s = getShape(); s->setText(c); s->setFlags(Shape::SH_RECOMPUTE); //notify(); //this wouldn't be useful here because an consequent resize //wouldn't happen until the next paint() MEXIT_CODE(Node,setText); } MENU Node::doMakeMenu() { MENTRY_CODE(Node,doMakeMenu); MENU m = SRGraphic::doMakeMenu(); appendMenu_Separator(m); appendMenu_String(m,CMD_RESIZE,"Resize"); if (!(getShape()->getFlags()&Shape::SH_AUTOSIZE)) appendMenu_String(m,CMD_AUTOSIZE,"Auto Size"); list* visuals = GraphicsFactory::getInstance()->makeShapeNameList(); if (!visuals->empty()) { MENU shape_menu = createPopupMenu(); list::iterator i; WORD j; for (i=visuals->begin(),j=0; i!=visuals->end(); i++,j++) appendMenu_String(shape_menu,CMD_FIRSTSHAPE+j,(*i).c_str()); appendMenu_Popup(m,shape_menu,"Change Shape"); } delete visuals; appendMenu_String(m,CMD_CHANGELABEL,"Edit Label"); MEXIT_CODE(Node,doMakeMenu); return m; } Command* Node::doGenerateCommand(WORD command, POINT *p, char* cmdName) { MENTRY_CODE(Node,doGenerateCommand); Command* ret; switch (command) { case CMD_CHANGELABEL: ret = getSetTextCommand(); break; case CMD_AUTOSIZE: ret = new Command1(GraphicObjectLocator((Node*)this),CMD_AUTOSIZE,RECTANGLE_EMPTY,getRect()); break; default: ret = SRGraphic::doGenerateCommand(command,p,cmdName); break; } MTRACEOUT(Node,doGenerateCommand); return ret; } int Node::execute(Command* c) { MENTRY_CODE(Node,execute); int ret = 0; switch (c->id()) { case CMD_CHANGELABEL: { Command1* sc = dynamic_cast*>(c); if (sc) { setText(sc->getValue().c_str()); notify(); } else error(0,'E',"Node::execute: Bad CHANGE LABEL command, type = %s",typeid(c).name()); } break; case CMD_AUTOSIZE: { //since we don't need any parameters to execute, we'll skip the type check Shape* s = getShape(); MASSERT(s); s->setFlags(Shape::SH_AUTOSIZE|Shape::SH_RECOMPUTE); queueForPaint(s->getRect()); notify(); } break; default: ret = SRGraphic::execute(c); break; } MTRACEOUT(Node,execute); return ret; } int Node::undo(Command* c) { MENTRY_CODE(Node,execute); int ret = 0; switch (c->id()) { case CMD_CHANGELABEL: { Command1* sc = dynamic_cast*>(c); if (sc) { setText(sc->getOriginalValue().c_str()); notify(); } else error(0,'E',"Node::undo: Bad CHANGE LABEL command, type = %s",typeid(c).name()); } break; case CMD_AUTOSIZE: { Command1* sc = dynamic_cast*>(c); if (sc) { setRect(sc->getOriginalValue()); getShape()->clearFlags(Shape::SH_AUTOSIZE); notify(); } else error(0,'E',"Node::undo: Bad AUTO RESIZE command, type = %s",typeid(c).name()); } break; default: ret = SRGraphic::undo(c); break; } MTRACEOUT(Node,execute); return ret; } Command* Node::getSetTextCommand(char* t) { MENTRY_CODE(Node,getSetTextCommand); Command* cmd; if (!t) { char buf[2000]; strncpy(buf,getText()?getText():"",2000); askUser_string("Edit Label","New Text:",buf,2000); cmd = new Command1(GraphicObjectLocator((Node*)this),CMD_CHANGELABEL,buf,getText()?getText():""); } else cmd = new Command1(GraphicObjectLocator((Node*)this),CMD_CHANGELABEL,t,getText()); MEXIT_CODE(Node,getSetTextCommand); return cmd; } /****************************************************************************** ************************** class SMaplet ************************** ******************************************************************************/ SMaplet::SMaplet(GraphicContainer* parent, char* visualClassName, POINT& handle, unsigned short nEndPoints) : Maplet(parent,visualClassName,handle,nEndPoints), SensitiveGraphic(parent,visualClassName), BehaviouralGraphic(parent,visualClassName) { MTRACE(SMaplet,SMaplet) MCONSTRUCTOR_IMP_CODE(SMaplet); MEXIT_CODE(SMaplet,SMaplet) } SMaplet::SMaplet(const SMaplet& g, GraphicContainer* parent) : SensitiveGraphic(g,parent), BehaviouralGraphic(g,parent), Maplet(g,parent) { MTRACE(SMaplet,SMaplet) MCONSTRUCTOR_IMP_CODE(SMaplet); MEXIT_CODE(SMaplet,SMaplet) } SMaplet::~SMaplet() { MTRACE(SMaplet,~SMaplet) MDESTRUCTOR_IMP_CODE(SMaplet); MTRACEOUT(SMaplet,~SMaplet) } void SMaplet::classInvarient(char* file, int line) const { SensitiveGraphic::classInvarient(file,line); Maplet::classInvarient(file,line); } void SMaplet::trackToBegin(POINT& p) { MENTRY_CODE(SensitiveGraphic,trackToBegin); if (getParent()) { getParent()->popToTop((SensitiveGraphic*)this); getParent()->setCaptureGraphic((SensitiveGraphic*)this); } sgMovingObject = this; sgMoveOffset.x = p.x-Handle.x; sgMoveOffset.y = p.y-Handle.y; sgOriginalPos.x = Handle.x; sgOriginalPos.y = Handle.y; MEXIT_CODE(SMaplet,trackToBegin); } void SMaplet::doLButtonDown(unsigned int modKeys, POINT& p) { MENTRY_CODE(SMaplet,doLButtonDown); int loc = getConnector()->contains(p); if (loc==1) { //move the handle trackToBegin(p); } if (loc>2 && loc<(3+TerminalCount)) { //move anchor loc-3 if (getParent()) { POINT np = trackElasticLine(Handle,p); RelationableGraphic* g = dynamic_cast(getParent()->getHit(np)); if (g) { Command* cmd = getSetConnectionCommand(loc-3,g->id()); dispatch(cmd); } } } MEXIT_CODE(SMaplet,doLButtonDown); } MENU SMaplet::doMakeMenu() { MENTRY_CODE(SMaplet,doMakeMenu); MENU m = SensitiveGraphic::doMakeMenu(); appendMenu_Separator(m); list* visuals = GraphicsFactory::getInstance()->makeConnectorNameList(); if (!visuals->empty()) { MENU shape_menu = createPopupMenu(); list::iterator i; WORD j; for (i=visuals->begin(),j=0; i!=visuals->end(); i++,j++) appendMenu_String(shape_menu,CMD_FIRSTSHAPE+j,(*i).c_str()); appendMenu_Popup(m,shape_menu,"Change Connection Type"); } delete visuals; if (ConnectorTerminalTargetNumber>=0) appendMenu_String(m,CMD_SETCONNECTION,"Unhook Terminal"); MEXIT_CODE(SMaplet,doMakeMenu); return m; } Command* SMaplet::doGenerateCommand(WORD command, POINT *p, char* cmdName) { MENTRY_CODE(SMaplet,doGenerateCommand); Command* ret = NULL; switch (command) { case CMD_SETCONNECTION: if (ConnectorTerminalTargetNumber>=0) ret = getSetConnectionCommand(ConnectorTerminalTargetNumber,0); else { error(0,'E',"SensitiveGraphic::doGenerateCommand: unexpected context"); ret = NULL; } break; default: ret = SensitiveGraphic::doGenerateCommand(command,p,cmdName); break; } MTRACEOUT(SMaplet,doGenerateCommand); return ret; }