PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/diagram/CodSelfLinkCanvas.cpp

http://github.com/gregsmirnov/bouml
C++ | 438 lines | 313 code | 90 blank | 35 comment | 60 complexity | c0852ab7fc739e31aac4ee585a4074a9 MD5 | raw file
Possible License(s): GPL-2.0
  1. // *************************************************************************
  2. //
  3. // Copyright 2004-2010 Bruno PAGES .
  4. //
  5. // This file is part of the BOUML Uml Toolkit.
  6. //
  7. // This program is free software; you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation; either version 2 of the License, or
  10. // (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program; if not, write to the Free Software
  19. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. //
  21. // e-mail : bouml@free.fr
  22. // home : http://bouml.free.fr
  23. //
  24. // *************************************************************************
  25. #include <qpainter.h>
  26. #include <qcursor.h>
  27. #include <qpopupmenu.h>
  28. #include "CodSelfLinkCanvas.h"
  29. #include "BrowserDiagram.h"
  30. #include "Settings.h"
  31. #include "CodObjCanvas.h"
  32. #include "ColMsg.h"
  33. #include "UmlCanvas.h"
  34. #include "LabelCanvas.h"
  35. #include "ColDiagramView.h"
  36. #include "CodAddMsgDialog.h"
  37. #include "CodEditMsgDialog.h"
  38. #include "SettingsDialog.h"
  39. #include "OperationData.h"
  40. #include "myio.h"
  41. #include "MenuTitle.h"
  42. #include "translate.h"
  43. CodSelfLinkCanvas::CodSelfLinkCanvas(UmlCanvas * canvas, CodObjCanvas * o,
  44. const QPoint & p, int id)
  45. : DiagramCanvas(0, canvas, 0, 0, SELF_LINK_RADIUS * 2,
  46. SELF_LINK_RADIUS * 2, id),
  47. obj(o) {
  48. setZ(o->z() - 0.5);
  49. browser_node = canvas->browser_diagram();
  50. connect(DrawingSettings::instance(), SIGNAL(changed()), this, SLOT(modified()));
  51. compute_pos(p);
  52. if (canvas->paste())
  53. // must not be selected else the move done after if wrong
  54. canvas->unselect(this);
  55. }
  56. CodSelfLinkCanvas::~CodSelfLinkCanvas() {
  57. }
  58. void CodSelfLinkCanvas::delete_it() {
  59. disconnect(DrawingSettings::instance(), SIGNAL(changed()), this, SLOT(modified()));
  60. CodMsgSupport::delete_it(((ColDiagramView *) the_canvas()->get_view())->get_msgs());
  61. DiagramCanvas::delete_it();
  62. }
  63. void CodSelfLinkCanvas::remove_it(ColMsg * msg) {
  64. const BasicData * oper_data = msg->get_operation();
  65. if (unsubscribe(oper_data))
  66. disconnect(oper_data, 0, this, 0);
  67. msgs.removeRef(msg);
  68. }
  69. void CodSelfLinkCanvas::delete_available(BooL &, BooL & out_model) const {
  70. out_model |= TRUE;
  71. }
  72. void CodSelfLinkCanvas::get_from_to(CodObjCanvas *& from,
  73. CodObjCanvas *& to,
  74. bool) {
  75. from = to = obj;
  76. }
  77. void CodSelfLinkCanvas::modified() {
  78. hide();
  79. update_pos();
  80. show();
  81. canvas()->update();
  82. update_msgs();
  83. package_modified();
  84. }
  85. void CodSelfLinkCanvas::update_pos() {
  86. QPoint oc = obj->center();
  87. QPoint c(oc.x() + delta_x, oc.y() + delta_y);
  88. compute_pos(c);
  89. }
  90. void CodSelfLinkCanvas::compute_pos(QPoint p) {
  91. QPoint obj_center = obj->center();
  92. delta_x = p.x() - obj_center.x();
  93. delta_y = p.y() - obj_center.y();
  94. // goes outside object;
  95. while (obj->contains(p.x(), p.y())) {
  96. p.setX(p.x() + delta_x);
  97. p.setY(p.y() + delta_y);
  98. }
  99. // move on the border of object
  100. QPoint center;
  101. QRect r = rect();
  102. obj->shift(center, p, FALSE);
  103. r.moveCenter(center);
  104. moveBy(r.x() - x() + 100000, r.y() - y());
  105. angle = compute_angle(delta_x, delta_y);
  106. // messages
  107. if (label != 0)
  108. update_label_pos();
  109. }
  110. void CodSelfLinkCanvas::update_label_pos() {
  111. if (!label->selected())
  112. label->move_outside(rect(), angle);
  113. }
  114. void CodSelfLinkCanvas::update_msgs() {
  115. // does not unsubscribe & disconnect signals because compute_size may
  116. // be called during a signal management, and the signal connection list
  117. // cannot be modified in this case
  118. QString s;
  119. if (! msgs.isEmpty()) {
  120. msgs.sort();
  121. CollaborationDiagramSettings dflt = settings;
  122. the_canvas()->browser_diagram()->get_collaborationdiagramsettings(dflt);
  123. QListIterator<ColMsg> it(msgs);
  124. QString nl = "\n";
  125. const QString * pfix = &QString::null;
  126. for (; it.current() != 0; ++it) {
  127. const BasicData * oper_data = it.current()->get_operation();
  128. if ((oper_data != 0) && subscribe(oper_data)) {
  129. connect(oper_data, SIGNAL(changed()), this, SLOT(modified()));
  130. connect(oper_data, SIGNAL(deleted()), this, SLOT(modified()));
  131. }
  132. QString m = it.current()->def(dflt.show_hierarchical_rank == UmlYes,
  133. dflt.show_full_operations_definition == UmlYes,
  134. dflt.drawing_language,
  135. dflt.show_msg_context_mode);
  136. if (!m.isEmpty()) {
  137. s += *pfix + m;
  138. pfix = &nl;
  139. }
  140. }
  141. }
  142. if (s.isEmpty()) {
  143. if (label != 0) {
  144. label->delete_it();
  145. label = 0;
  146. package_modified();
  147. }
  148. }
  149. else {
  150. if (label == 0)
  151. (label = new LabelCanvas(s, the_canvas(), 0, 0))->show();
  152. else if (label->get_name() == s)
  153. return;
  154. else
  155. label->set_name(s);
  156. update_label_pos();
  157. canvas()->update();
  158. package_modified();
  159. }
  160. }
  161. void CodSelfLinkCanvas::moveBy(double dx, double dy) {
  162. if (dx > 80000)
  163. // compute_pos
  164. DiagramCanvas::moveBy(dx - 100000, dy);
  165. else if (!selected() || !obj->selected()) {
  166. // manual move & not moved by selection
  167. QPoint p((int) (center().x() + dx), (int) (center().y() + dy));
  168. compute_pos(p);
  169. }
  170. }
  171. void CodSelfLinkCanvas::draw(QPainter & p) {
  172. if (! visible()) return;
  173. QPoint ce = center();
  174. p.save();
  175. p.translate(ce.x(), ce.y());
  176. p.rotate(angle);
  177. QRect r(-width() / 2, -width() / 4, width() - 1, width() / 2);
  178. p.drawEllipse(r);
  179. FILE * fp = svg();
  180. if (fp != 0)
  181. fprintf(fp, "<ellipse fill=\"none\" stroke=\"black\" stroke-opacity=\"1\" transform=\"translate(%d %d) rotate(%d)\" rx=\"%d\" ry=\"%d\" />\n",
  182. (int) ce.x(), (int) ce.y(), (int) angle, width() / 2, width() / 4);
  183. if (selected())
  184. show_mark(p, r);
  185. p.restore();
  186. }
  187. UmlCode CodSelfLinkCanvas::type() const {
  188. return UmlSelfLink;
  189. }
  190. void CodSelfLinkCanvas::open() {
  191. QPoint dummy;
  192. menu(dummy);
  193. }
  194. void CodSelfLinkCanvas::menu(const QPoint&) {
  195. QPopupMenu m;
  196. m.insertItem(new MenuTitle(TR("Self link"), m.font()), -1);
  197. m.insertSeparator();
  198. m.insertItem(TR("Add messages"), 1);
  199. m.insertSeparator();
  200. m.insertItem(TR("Edit its messages"), 2);
  201. m.insertItem(TR("Edit all the messages"), 3);
  202. m.insertSeparator();
  203. m.insertItem(TR("Edit drawing settings"), 4);
  204. m.insertSeparator();
  205. m.insertItem(TR("Remove from diagram"),5);
  206. switch (m.exec(QCursor::pos())) {
  207. case 1:
  208. {
  209. CodAddMsgDialog d(obj, obj, this, (ColDiagramView *) the_canvas()->get_view(),
  210. TRUE);
  211. d.exec();
  212. }
  213. return;
  214. case 2:
  215. CodEditMsgDialog::exec((ColDiagramView *) the_canvas()->get_view(), msgs);
  216. return;
  217. case 3:
  218. CodEditMsgDialog::exec((ColDiagramView *) the_canvas()->get_view(),
  219. ((ColDiagramView *) the_canvas()->get_view())->get_msgs());
  220. return;
  221. case 4:
  222. for (;;) {
  223. StateSpecVector st;
  224. settings.complete_msg(st);
  225. SettingsDialog dialog(&st, 0, FALSE);
  226. if (dialog.exec() == QDialog::Accepted)
  227. modified();
  228. if (!dialog.redo())
  229. return;
  230. }
  231. break;
  232. case 5:
  233. delete_it();
  234. ((ColDiagramView *) the_canvas()->get_view())->update_msgs();
  235. break;
  236. default:
  237. return;
  238. }
  239. package_modified();
  240. }
  241. QString CodSelfLinkCanvas::may_start(UmlCode & l) const {
  242. return (l == UmlAnchor) ? 0 : TR("illegal");
  243. }
  244. QString CodSelfLinkCanvas::may_connect(UmlCode & l, const DiagramItem * dest) const {
  245. return (l == UmlAnchor) ? dest->may_start(l) : TR("illegal");
  246. }
  247. bool CodSelfLinkCanvas::copyable() const {
  248. return selected() && obj->copyable();
  249. }
  250. bool CodSelfLinkCanvas::represents(BrowserNode * bn) {
  251. return supports(bn);
  252. }
  253. void CodSelfLinkCanvas::save(QTextStream & st, bool ref, QString & warning) const {
  254. if (ref)
  255. st << "selflinkcanvas_ref " << get_ident();
  256. else {
  257. nl_indent(st);
  258. st << "selflinkcanvas " << get_ident() << ' ';
  259. obj->save(st, TRUE, warning);
  260. indent(+1);
  261. nl_indent(st);
  262. QPoint obj_center = obj->center();
  263. #ifdef FORCE_INT_COORD
  264. // note : << float bugged in Qt 3.3.3
  265. st << "xy " << (int) (delta_x + obj_center.x())
  266. << ' ' << (int) (delta_y + obj_center.y());
  267. #else
  268. QString sx, sy;
  269. st << "xy " << sx.setNum(delta_x + obj_center.x())
  270. << ' ' << sy.setNum(delta_y + obj_center.y());
  271. #endif
  272. settings.save_msg(st);
  273. if (label != 0) {
  274. nl_indent(st);
  275. st << "forward_label ";
  276. save_string(label->get_name(), st);
  277. save_xyz(st, label, " xyz");
  278. }
  279. indent(-1);
  280. }
  281. }
  282. CodSelfLinkCanvas * CodSelfLinkCanvas::read(char * & st, UmlCanvas * canvas,
  283. char * & k)
  284. {
  285. if (!strcmp(k, "selflinkcanvas_ref"))
  286. return ((CodSelfLinkCanvas *) dict_get(read_id(st), "self link canvas", canvas));
  287. else if (!strcmp(k, "selflinkcanvas")) {
  288. int id = read_id(st);
  289. CodObjCanvas * o = CodObjCanvas::read(st, canvas);
  290. read_keyword(st, "xy");
  291. int x = read_unsigned(st);
  292. QPoint p(x, read_unsigned(st));
  293. CodSelfLinkCanvas * result =
  294. new CodSelfLinkCanvas(canvas, o, p, id);
  295. o->set_self_link(result);
  296. result->setZ(o->z() - 0.5);
  297. k = read_keyword(st);
  298. result->settings.read(st, k); // updates k
  299. if (!strcmp(k, "forward_label")) {
  300. result->label = new LabelCanvas(read_string(st), canvas, 0, 0);
  301. if (read_file_format() < 5) {
  302. read_keyword(st, "xy");
  303. read_xy(st, result->label);
  304. //result->label->setZ(OLD_LABEL_Z);
  305. }
  306. else {
  307. read_keyword(st, "xyz");
  308. read_xyz(st, result->label);
  309. }
  310. result->label->set_center100();
  311. k = read_keyword(st);
  312. }
  313. result->show();
  314. return result;
  315. }
  316. else
  317. return 0;
  318. }
  319. void CodSelfLinkCanvas::history_save(QBuffer & b) const {
  320. DiagramCanvas::history_save(b);
  321. ::save(delta_x, b);
  322. ::save(delta_y, b);
  323. ::save(angle, b);
  324. }
  325. void CodSelfLinkCanvas::history_load(QBuffer & b) {
  326. DiagramCanvas::history_load(b);
  327. ::load(delta_x, b);
  328. ::load(delta_y, b);
  329. ::load(angle, b);
  330. QListIterator<ColMsg> it(msgs);
  331. for (; it.current() != 0; ++it) {
  332. const BasicData * oper_data = it.current()->get_operation();
  333. if ((oper_data != 0) && subscribe(oper_data)) {
  334. connect(oper_data, SIGNAL(changed()), this, SLOT(modified()));
  335. connect(oper_data, SIGNAL(deleted()), this, SLOT(modified()));
  336. }
  337. }
  338. }
  339. void CodSelfLinkCanvas::history_hide() {
  340. DiagramCanvas::setVisible(FALSE);
  341. disconnect(DrawingSettings::instance(), SIGNAL(changed()), this, SLOT(modified()));
  342. QListIterator<ColMsg> it(msgs);
  343. for (; it.current() != 0; ++it) {
  344. const BasicData * oper_data = it.current()->get_operation();
  345. if ((oper_data != 0) && unsubscribe(oper_data))
  346. disconnect(oper_data, 0, this, 0);
  347. }
  348. }