// ************************************************************************* // // Copyleft 2004-2007 Bruno PAGES . // // This file is part of the BOUML Uml Toolkit. // // 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. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // e-mail : bouml@free.fr // home : http://bouml.free.fr // // ************************************************************************* #ifdef WIN32 #pragma warning (disable: 4150) #endif #include #include #include #include "CodSelfLinkCanvas.h" #include "BrowserDiagram.h" #include "Settings.h" #include "CodObjCanvas.h" #include "ColMsg.h" #include "UmlCanvas.h" #include "LabelCanvas.h" #include "ColDiagramView.h" #include "CodAddMsgDialog.h" #include "CodEditMsgDialog.h" #include "SettingsDialog.h" #include "OperationData.h" #include "myio.h" #include "MenuTitle.h" CodSelfLinkCanvas::CodSelfLinkCanvas(UmlCanvas * canvas, CodObjCanvas * o, const QPoint & p, int id) : DiagramCanvas(0, canvas, 0, 0, SELF_LINK_RADIUS * 2, SELF_LINK_RADIUS * 2, id), obj(o) { setZ(o->z() - 0.5); browser_node = canvas->browser_diagram(); connect(DrawingSettings::instance(), SIGNAL(changed()), this, SLOT(modified())); compute_pos(p); if (canvas->paste()) // must not be selected else the move done after if wrong canvas->unselect(this); } CodSelfLinkCanvas::~CodSelfLinkCanvas() { } void CodSelfLinkCanvas::delete_it() { disconnect(DrawingSettings::instance(), SIGNAL(changed()), this, SLOT(modified())); CodMsgSupport::delete_it(((ColDiagramView *) the_canvas()->get_view())->get_msgs()); DiagramCanvas::delete_it(); } void CodSelfLinkCanvas::remove_it(ColMsg * msg) { const BasicData * oper_data = msg->get_operation(); if (unsubscribe(oper_data)) disconnect(oper_data, 0, this, 0); msgs.removeRef(msg); } void CodSelfLinkCanvas::delete_available(bool &, bool & out_model) const { out_model |= TRUE; } void CodSelfLinkCanvas::get_from_to(CodObjCanvas *& from, CodObjCanvas *& to, bool) { from = to = obj; } void CodSelfLinkCanvas::modified() { hide(); update_pos(); show(); canvas()->update(); update_msgs(); package_modified(); } void CodSelfLinkCanvas::update_pos() { QPoint oc = obj->center(); QPoint c(oc.x() + delta_x, oc.y() + delta_y); compute_pos(c); } void CodSelfLinkCanvas::compute_pos(QPoint p) { QPoint obj_center = obj->center(); delta_x = p.x() - obj_center.x(); delta_y = p.y() - obj_center.y(); // goes outside object; while (obj->contains(p.x(), p.y())) { p.setX(p.x() + delta_x); p.setY(p.y() + delta_y); } // move on the border of object QPoint center; QRect r = rect(); obj->shift(center, p); r.moveCenter(center); moveBy(r.x() - x() + 100000, r.y() - y()); angle = compute_angle(delta_x, delta_y); // messages if (label != 0) update_label_pos(); } void CodSelfLinkCanvas::update_label_pos() { if (!label->selected()) label->move_outside(rect(), angle); } void CodSelfLinkCanvas::update_msgs() { // does not unsubscribe & disconnect signals because compute_size may // be called during a signal management, and the signal connection list // cannot be modified in this case msgs.sort(); QListIterator it(msgs); QString nl = "\n"; const QString * pfix = &QString::null; QString s; for (; it.current() != 0; ++it) { const BasicData * oper_data = it.current()->get_operation(); if ((oper_data != 0) && subscribe(oper_data)) { connect(oper_data, SIGNAL(changed()), this, SLOT(modified())); connect(oper_data, SIGNAL(deleted()), this, SLOT(modified())); } CollaborationDiagramSettings dflt = settings; the_canvas()->browser_diagram()->get_collaborationdiagramsettings(dflt); QString m = it.current()->def(dflt.show_hierarchical_rank == UmlYes, dflt.show_full_operations_definition == UmlYes, dflt.drawing_language); if (!m.isEmpty()) { s += *pfix + m; pfix = &nl; } } if (s.isEmpty()) { if (label != 0) { label->delete_it(); label = 0; package_modified(); } } else { if (label == 0) (label = new LabelCanvas(s, the_canvas(), 0, 0))->show(); else if (label->get_name() == s) return; else label->set_name(s); update_label_pos(); canvas()->update(); package_modified(); } } void CodSelfLinkCanvas::moveBy(double dx, double dy) { if (dx > 80000) // compute_pos DiagramCanvas::moveBy(dx - 100000, dy); else if (!selected() || !obj->selected()) { // manual move & not moved by selection QPoint p((int) (center().x() + dx), (int) (center().y() + dy)); compute_pos(p); } } void CodSelfLinkCanvas::draw(QPainter & p) { if (! visible()) return; QPoint ce = center(); p.save(); p.translate(ce.x(), ce.y()); p.rotate(angle); QRect r(-width() / 2, -width() / 4, width() - 1, width() / 2); p.drawEllipse(r); FILE * fp = svg(); if (fp != 0) fprintf(fp, "\n", (int) ce.x(), (int) ce.y(), (int) angle, width() / 2, width() / 4); if (selected()) show_mark(p, r); p.restore(); } UmlCode CodSelfLinkCanvas::type() const { return UmlSelfLink; } void CodSelfLinkCanvas::open() { QPoint dummy; menu(dummy); } void CodSelfLinkCanvas::menu(const QPoint&) { QPopupMenu m; m.insertItem(new MenuTitle("Self link", m.font()), -1); m.insertSeparator(); m.insertItem("Add messages", 1); m.insertSeparator(); m.insertItem("Edit its messages", 2); m.insertItem("Edit all the messages", 3); m.insertSeparator(); m.insertItem("Edit drawing settings", 4); m.insertSeparator(); m.insertItem("Remove from view",5); switch (m.exec(QCursor::pos())) { case 1: { CodAddMsgDialog d(obj, obj, this, (ColDiagramView *) the_canvas()->get_view(), TRUE); d.exec(); } return; case 2: CodEditMsgDialog::exec((ColDiagramView *) the_canvas()->get_view(), msgs); return; case 3: CodEditMsgDialog::exec((ColDiagramView *) the_canvas()->get_view(), ((ColDiagramView *) the_canvas()->get_view())->get_msgs()); return; case 4: { QArray st; settings.complete(st, TRUE); SettingsDialog dialog(&st, 0, FALSE, TRUE); if (dialog.exec() == QDialog::Accepted) modified(); return; } break; case 5: delete_it(); ((ColDiagramView *) the_canvas()->get_view())->update_msgs(); break; default: return; } package_modified(); } const char * CodSelfLinkCanvas::may_start(UmlCode & l) const { return (l == UmlAnchor) ? 0 : "illegal"; } const char * CodSelfLinkCanvas::may_connect(UmlCode & l, const DiagramItem * dest) const { return (l == UmlAnchor) ? dest->may_start(l) : "illegal"; } bool CodSelfLinkCanvas::copyable() const { return selected() && obj->copyable(); } void CodSelfLinkCanvas::save(QTextStream & st, bool ref, QString & warning) const { if (ref) st << "selflinkcanvas_ref " << get_ident(); else { nl_indent(st); st << "selflinkcanvas " << get_ident() << ' '; obj->save(st, TRUE, warning); indent(+1); nl_indent(st); QPoint obj_center = obj->center(); // note : << float bugged in Qt 3.3.3 st << "xy " << (int) (delta_x + obj_center.x()) << ' ' << (int) (delta_y + obj_center.y()); settings.save(st); if (label != 0) { nl_indent(st); st << "forward_label "; save_string(label->get_name(), st); save_xyz(st, label, " xyz"); } indent(-1); } } CodSelfLinkCanvas * CodSelfLinkCanvas::read(char * & st, UmlCanvas * canvas, char * & k) { if (!strcmp(k, "selflinkcanvas_ref")) return ((CodSelfLinkCanvas *) dict_get(read_id(st), "self link canvas", canvas)); else if (!strcmp(k, "selflinkcanvas")) { int id = read_id(st); CodObjCanvas * o = CodObjCanvas::read(st, canvas); read_keyword(st, "xy"); int x = read_unsigned(st); QPoint p(x, read_unsigned(st)); CodSelfLinkCanvas * result = new CodSelfLinkCanvas(canvas, o, p, id); o->set_self_link(result); result->setZ(o->z() - 0.5); k = read_keyword(st); result->settings.read(st, k); // updates k if (!strcmp(k, "forward_label")) { result->label = new LabelCanvas(read_string(st), canvas, 0, 0); if (read_file_format() < 5) { read_keyword(st, "xy"); read_xy(st, result->label); //result->label->setZ(OLD_LABEL_Z); } else { read_keyword(st, "xyz"); read_xyz(st, result->label); } result->label->set_center100(); k = read_keyword(st); } result->show(); return result; } else return 0; } void CodSelfLinkCanvas::history_save(QBuffer & b) const { DiagramCanvas::history_save(b); ::save(delta_x, b); ::save(delta_y, b); ::save(angle, b); } void CodSelfLinkCanvas::history_load(QBuffer & b) { DiagramCanvas::history_load(b); ::load(delta_x, b); ::load(delta_y, b); ::load(angle, b); QListIterator it(msgs); for (; it.current() != 0; ++it) { const BasicData * oper_data = it.current()->get_operation(); if ((oper_data != 0) && subscribe(oper_data)) { connect(oper_data, SIGNAL(changed()), this, SLOT(modified())); connect(oper_data, SIGNAL(deleted()), this, SLOT(modified())); } } } void CodSelfLinkCanvas::history_hide() { DiagramCanvas::setVisible(FALSE); disconnect(DrawingSettings::instance(), SIGNAL(changed()), this, SLOT(modified())); QListIterator it(msgs); for (; it.current() != 0; ++it) { const BasicData * oper_data = it.current()->get_operation(); if ((oper_data != 0) && unsubscribe(oper_data)) disconnect(oper_data, 0, this, 0); } }