1
////////////////////////////////////////////////////////////////////////////////
3
// This file is part of Toolkit for Conceptual Modeling (TCM).
4
// (c) copyright 1995, Vrije Universiteit Amsterdam.
5
// Author: Frank Dehne (frank@cs.vu.nl).
7
// TCM 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.
12
// TCM 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.
17
// You should have received a copy of the GNU General Public License
18
// along with TCM; if not, write to the Free Software
19
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21
////////////////////////////////////////////////////////////////////////////////
22
#include "messagedialog.h"
26
#include "arrowtextbox.h"
30
#include "trdiagram.h"
35
#include "diagramchecks.h"
39
TRDiagram::TRDiagram(Config *c, TRWindow *d, TRViewer *v, TRGraph *g):
43
trChecks = new DiagramChecks(this, g);
46
TRDiagram::~TRDiagram() {
50
Thing *TRDiagram::CreateThing(int classNr) {
51
Grafport *g = GetDiagramViewer()->GetGrafport();
52
ShapeView *v = GetDiagramViewer()->GetCurView();
53
TRGraph *tg = (TRGraph *)GetGraph();
56
if (classNr == Code::VIEW)
57
thing = new TRView((TRViewer *)GetDiagramViewer());
59
else if (classNr == Code::ARROW_TEXT_BOX)
60
thing = new ArrowTextBox(v, g, 0, 0);
61
else if (classNr == Code::TEXT_BOX)
62
thing = new TextBox(v, g, 0, 0);
64
else if (classNr == Code::LINE)
65
thing = new Line(v, g, 0, 0, 0);
67
else if (classNr == Code::TEXT_ROOT)
68
thing = new TextRoot(tg);
69
else if (classNr == Code::TEXT_NODE)
70
thing = new TextNode(tg);
71
else if (classNr == Code::COMMENT)
72
thing = new Comment(tg);
74
else if (classNr == Code::TEXT_EDGE)
75
thing = new TextEdge(tg, 0, 0);
77
error("%s, line %d: impl error: "
78
"wrong class number %d\n", __FILE__, __LINE__, classNr);
82
Node *TRDiagram::CreateNode(){
84
TRGraph *tg = (TRGraph *)GetGraph();
85
if (GetNodeType() == Code::TEXT_ROOT)
86
node = new TextRoot(tg);
87
else if (GetNodeType() == Code::TEXT_NODE)
88
node = new TextNode(tg);
89
else if (GetNodeType() == Code::COMMENT)
90
node = new Comment(tg);
92
error("%s, line %d: impl error: "
93
"unknown node type\n", __FILE__, __LINE__);
97
Edge *TRDiagram::CreateEdge(Subject *subj1, Subject *subj2){
98
if (!CheckEdgeConstraints(subj1, subj2))
101
TRGraph *tg = (TRGraph *)GetGraph();
102
if (GetEdgeType() == Code::TEXT_EDGE)
103
edge = new TextEdge(tg, subj1, subj2);
105
error("%s, line %d: impl error: "
106
"unknown edge type\n", __FILE__, __LINE__);
110
NodeShape *TRDiagram::CreateNodeShape(Node *node, int x, int y) {
111
NodeShape *shape = 0;
112
Grafport *g = GetDiagramViewer()->GetGrafport();
113
ShapeView *v = GetDiagramViewer()->GetCurView();
114
if (GetNodeShapeType() == Code::TEXT_BOX)
115
shape = new TextBox(v, g, x, y);
116
else if (GetNodeShapeType() == Code::ARROW_TEXT_BOX)
117
shape = new ArrowTextBox(v, g, x, y);
119
error("%s, line %d: impl error: "
120
"node shape type does not exist\n", __FILE__, __LINE__);
123
shape->SetSubject(node);
124
shape->SetTextShape();
129
Line *TRDiagram::CreateLine(
130
Edge *edge, GShape *from, GShape *to, List<Point *> *l) {
132
Grafport *g = GetDiagramViewer()->GetGrafport();
133
ShapeView *v = GetDiagramViewer()->GetCurView();
134
if (GetLineType() == Code::LINE)
135
line = new Line(v, g, from, to, l, IsCurve());
137
error("%s, line %d: impl error: "
138
"line type does not exist\n", __FILE__, __LINE__);
141
line->SetSubject(edge);
142
line->SetTextShape();
147
void TRDiagram::UpdateNodeType(int num) {
148
((DiagramWindow *)GetMainWindow())->SetNodeName(num);
150
case 1: SetNodeType(Code::TEXT_ROOT);
151
SetNodeShapeType(Code::ARROW_TEXT_BOX);
153
case 2: SetNodeType(Code::TEXT_NODE);
154
SetNodeShapeType(Code::TEXT_BOX);
156
case 3: SetNodeType(Code::COMMENT);
157
SetNodeShapeType(Code::TEXT_BOX);
160
error("%s, line %d: impl error: "
161
" unknown node type selected\n", __FILE__,__LINE__);
165
void TRDiagram::UpdateEdgeType(int num) {
166
((DiagramWindow *)GetMainWindow())->SetEdgeName(num);
168
case 1: SetEdgeType(Code::TEXT_EDGE);
169
SetLineType(Code::LINE);
172
error("%s, line %d: impl error: "
173
"unknown edge type selected\n", __FILE__,__LINE__);
177
bool TRDiagram::CheckEdgeConstraints(Subject *subj1, Subject *subj2) {
178
// Check possible connections (subj-subj-edge matrix).
179
if (!CheckConnection(subj1, subj2))
182
if ((subj1==subj2) || GetGraph()->PathExists(subj1, subj2) ||
183
(FindRoot(subj1) && FindRoot(subj2))) {
184
ShowDialog(MessageDialog::ERROR, "Error",
185
"This connection violates the tree constraint");
191
void TRDiagram::DoLoad(const string *file) {
192
if (IsAppending() && ((TRViewer *)GetDiagramViewer())->IsTreeMode())
193
SetStatus("Append aborted: in view mode");
195
Diagram::DoLoad(file);
198
void TRDiagram::RemoveAll() {
199
Diagram::RemoveAll();
202
void TRDiagram::PlaceShapes() {
203
Diagram::PlaceShapes();
205
GetDiagramViewer()->Refresh();
208
void TRDiagram::Append() {
209
if (!((TRViewer *)GetDiagramViewer())->IsTreeMode())
212
SetStatus("Append aborted: in view mode");
215
void TRDiagram::RecalculateTree() {
216
// recalculate parent-child relationships.
217
List<Subject *> nodes;
218
GetGraph()->GetNodes(&nodes, Code::TEXT_ROOT);
219
for (nodes.first(); !nodes.done(); nodes.next()) {
220
TextNode *node = (TextNode *)(nodes.cur());
221
CalcParents(0, node);
222
// DumpChildren(node, 0);
226
void TRDiagram::CheckDocument() {
229
unsigned total = trChecks->CheckNodeCount(1, INT_MAX, Code::TEXT_ROOT, chkbuf);
231
total += trChecks->CheckReachability(
232
Code::TEXT_ROOT, Code::TEXT_NODE, False, chkbuf);
233
total += trChecks->CheckNamelessNodes(Code::TEXT_ROOT, chkbuf);
234
total += trChecks->CheckNamelessNodes(Code::TEXT_NODE, chkbuf);
235
ReportCheck(total, &chkbuf);
238
void TRDiagram::CalcParents(TextNode *parent, TextNode *node) {
239
List<Subject *> nodes;
240
GetGraph()->GetConnected(&nodes, node);
241
node->SetParent(parent);
243
nodes.remove(parent);
244
for (nodes.first(); !nodes.done(); nodes.next())
245
CalcParents(node, (TextNode *)(nodes.cur()));
248
void TRDiagram::DumpChildren(TextNode *node, unsigned level) {
250
List<Subject *> nodes;
251
GetGraph()->GetConnected(&nodes, node);
252
Node *parent = node->GetParent();
254
nodes.remove(parent);
255
for (nodes.first(); !nodes.done(); nodes.next()) {
256
for (unsigned i=0;i<level;i++)
258
std::cout << "- " << *nodes.cur()->GetName() << '\n';
259
DumpChildren((TextNode *)nodes.cur(), level+1);
263
void TRDiagram::GetChildren(TextNode *node, List<Subject *> *children) {
265
GetGraph()->GetConnected(children, node);
266
Node *parent = node->GetParent();
268
children->remove(parent);
271
void TRDiagram::DrawTreeLayout() {
272
List<Subject *> roots;
273
GetGraph()->GetNodes(&roots, Code::TEXT_ROOT);
274
for (roots.first(); !roots.done(); roots.next()) {
275
TextNode *root = (TextNode *)(roots.cur());
276
CalcParents(0, root);
277
DrawTreeLayout(root);
281
void TRDiagram::DrawTreeLayout(TextNode *parent) {
282
List<Subject *> nodes;
283
List<Shape *> shapes;
285
// find direct children of the parent node.
286
GetChildren(parent, &nodes);
287
if (nodes.count() == 0)
289
// get the shape of the parent.
290
parentShape = GetDiagramViewer()->GetShape(parent);
293
for (nodes.first(); !nodes.done(); nodes.next()) {
294
// do this recursively.
295
DrawTreeLayout(((TextNode *)nodes.cur()));
296
// collect the shapes of the children.
297
Shape *s = GetDiagramViewer()->GetShape(nodes.cur());
302
((TRViewer *)GetDiagramViewer())->DrawTreeFork(parentShape, &shapes);
305
void TRDiagram::UndrawTreeLayout() {
310
bool TRDiagram::FindRoot(Subject *subj) {
311
// return if there is a path to a root.
312
if (subj->GetClassType()==Code::TEXT_ROOT)
314
List<Subject *> roots;
315
GetGraph()->GetNodes(&roots, Code::TEXT_ROOT);
316
// find a root of the node if it exists.
317
for (roots.first(); !roots.done(); roots.next()) {
318
if (GetGraph()->PathExists(subj, (Subject *)(roots.cur())))