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
////////////////////////////////////////////////////////////////////////////////
28
#include "messagedialog.h"
29
#include "replacedialog.h"
30
#include "texteditdialog.h"
31
#include "externalentity.h"
32
#include "dataprocess.h"
33
#include "datastore.h"
34
#include "splitmergenode.h"
35
#include "bidirectionaldataflow.h"
36
#include "dfdiagram.h"
40
#include "horizontalbar.h"
46
DFDiagram::DFDiagram(Config *c, DFWindow *d, DFViewer *v, DFGraph *g):
50
GetReplaceDialog()->ManageNameOnlyToggle(True);
52
dfChecks = new DFChecks(this,g);
53
minispecDialog = new TextEditDialog(GetMainWindow()->GetWidget());
54
minispecDialog->Initialize();
55
minispecDialog->SetTitle("Minispec Editor");
56
minispecDialog->SetCancelCallback(0, 0);
57
minispecDialog->SetOKCallback(DFStubs::MinispecOKCB, this);
58
minispecDialog->SetTextSize(12, 60);
61
DFDiagram::~DFDiagram() {
62
delete minispecDialog;
66
Thing *DFDiagram::CreateThing(int classNr) {
67
Grafport *g = GetDiagramViewer()->GetGrafport();
68
ShapeView *v = GetDiagramViewer()->GetCurView();
69
DFGraph *dg = (DFGraph *)GetGraph();
72
if (classNr == Code::VIEW)
73
thing = new ShapeView(GetDiagramViewer());
75
else if (classNr == Code::SQUARE)
76
thing = new Square(v, g, 0, 0);
77
else if (classNr == Code::HORIZONTAL_BAR)
78
thing = new HorizontalBar(v, g, 0, 0);
79
else if (classNr == Code::CIRCLE) {
80
Circle *c = new Circle(v, g, 0, 0);
81
c->SetFixedIndexLabel(False);
84
else if (classNr == Code::BLACK_DOT)
85
thing = new BlackDot(v, g, 0, 0);
86
else if (classNr == Code::TEXT_BOX)
87
thing = new TextBox(v, g, 0, 0);
89
else if (classNr == Code::LINE)
90
thing = new Line(v, g, 0, 0, 0);
91
else if (classNr == Code::ARROW) {
92
Line *line = new Line(v, g, 0, 0, 0);
93
line->SetEnd1(LineEnd::EMPTY);
94
line->SetEnd2(LineEnd::FILLED_ARROW);
97
else if (classNr == Code::DOUBLE_ARROW) {
98
Line *line = new Line(v, g, 0, 0, 0);
99
line->SetEnd1(LineEnd::FILLED_ARROW);
100
line->SetEnd2(LineEnd::FILLED_ARROW);
104
else if (classNr == Code::EXTERNAL_ENTITY)
105
thing = new ExternalEntity(dg);
106
else if (classNr == Code::DATA_STORE)
107
thing = new DataStore(dg);
108
else if (classNr == Code::DATA_PROCESS)
109
thing = new DataProcess(dg);
110
else if (classNr == Code::SPLIT_MERGE_NODE)
111
thing = new SplitMergeNode(dg);
112
else if (classNr == Code::COMMENT)
113
thing = new Comment(dg);
115
else if (classNr == Code::DATA_FLOW)
116
thing = new DataFlow(dg, 0, 0);
117
else if (classNr == Code::BIDIRECTIONAL_DATA_FLOW)
118
thing = new BidirectionalDataFlow(dg, 0, 0);
120
error("%s, line %d: impl error: "
121
"wrong class number %d\n", __FILE__, __LINE__, classNr);
125
Node *DFDiagram::CreateNode(){
127
DFGraph *dg = (DFGraph *)GetGraph();
128
if (GetNodeType() == Code::EXTERNAL_ENTITY)
129
node = new ExternalEntity(dg);
130
else if (GetNodeType() == Code::DATA_PROCESS)
131
node = new DataProcess(dg);
132
else if (GetNodeType() == Code::DATA_STORE)
133
node = new DataStore(dg);
134
else if (GetNodeType() == Code::SPLIT_MERGE_NODE)
135
node = new SplitMergeNode(dg);
136
else if (GetNodeType() == Code::COMMENT)
137
node = new Comment(dg);
139
error("%s, line %d: unknown node type\n",
145
Edge *DFDiagram::CreateEdge(Subject *subj1, Subject *subj2){
146
if (!CheckEdgeConstraints(subj1, subj2))
149
DFGraph *dg = (DFGraph *)GetGraph();
150
if (GetEdgeType() == Code::DATA_FLOW)
151
edge = new DataFlow(dg, subj1, subj2);
152
else if (GetEdgeType() == Code::BIDIRECTIONAL_DATA_FLOW)
153
edge = new BidirectionalDataFlow(dg, subj1, subj2);
155
error("%s, line %d: unknown edge type\n", __FILE__, __LINE__);
159
NodeShape *DFDiagram::CreateNodeShape(Node *node, int x, int y) {
160
NodeShape *shape = 0;
161
Grafport *g = GetDiagramViewer()->GetGrafport();
162
ShapeView *v = GetDiagramViewer()->GetCurView();
163
if (GetNodeShapeType() == Code::HORIZONTAL_BAR)
164
shape = new HorizontalBar(v, g, x, y);
165
else if (GetNodeShapeType() == Code::CIRCLE) {
166
Circle *c = new Circle(v, g, x, y);
167
c->SetFixedIndexLabel(False);
170
else if (GetNodeShapeType() == Code::SQUARE)
171
shape = new Square(v, g, x, y);
172
else if (GetNodeShapeType() == Code::BLACK_DOT)
173
shape = new BlackDot(v, g, x, y);
174
else if (GetNodeShapeType() == Code::TEXT_BOX)
175
shape = new TextBox(v, g, x, y);
177
error("%s, line %d: impl error: "
178
"node shape type does not exist\n", __FILE__, __LINE__);
180
shape->SetSubject(node);
181
shape->SetTextShape();
186
Line *DFDiagram::CreateLine(
187
Edge *edge, GShape *from, GShape *to, List<Point *> *l) {
188
Grafport *g = GetDiagramViewer()->GetGrafport();
189
ShapeView *v = GetDiagramViewer()->GetCurView();
191
if (GetLineType() == Code::LINE)
192
line = new Line(v, g, from, to, l, IsCurve());
194
error("%s, line %d: impl error: "
195
"line type does not exist\n", __FILE__, __LINE__);
198
line->SetSubject(edge);
199
line->SetTextShape();
200
line->SetEnd1(GetLineEnd1());
201
line->SetEnd2(GetLineEnd2());
206
void DFDiagram::UpdateNodeType(int num) {
207
((DiagramWindow *)GetMainWindow())->SetNodeName(num);
209
case 1: SetNodeType(Code::DATA_PROCESS);
210
SetNodeShapeType(Code::CIRCLE);
212
case 2: SetNodeType(Code::DATA_STORE);
213
SetNodeShapeType(Code::HORIZONTAL_BAR);
215
case 3: SetNodeType(Code::EXTERNAL_ENTITY);
216
SetNodeShapeType(Code::SQUARE);
218
case 4: SetNodeType(Code::SPLIT_MERGE_NODE);
219
SetNodeShapeType(Code::BLACK_DOT);
221
case 5: SetNodeType(Code::COMMENT);
222
SetNodeShapeType(Code::TEXT_BOX);
225
error("%s, line %d: impl error: "
226
"unknown node type selected\n", __FILE__,__LINE__);
230
void DFDiagram::UpdateEdgeType(int num) {
231
((DiagramWindow *)GetMainWindow())->SetEdgeName(num);
232
SetLineType(Code::LINE);
234
case 1: SetEdgeType(Code::DATA_FLOW);
235
SetLineEnd1(LineEnd::EMPTY);
236
SetLineEnd2(LineEnd::FILLED_ARROW);
238
case 2: SetEdgeType(Code::BIDIRECTIONAL_DATA_FLOW);
239
SetLineEnd1(LineEnd::FILLED_ARROW);
240
SetLineEnd2(LineEnd::FILLED_ARROW);
243
error("%s, line %d: impl error: "
244
"unknown edge type selected\n", __FILE__,__LINE__);
248
bool DFDiagram::CheckEdgeConstraints(Subject *subj1, Subject *subj2) {
249
// Check possible connections (subj-subj-edge matrix).
250
if (!CheckConnection(subj1, subj2))
252
if (subj1 == subj2) {
253
ShowDialog(MessageDialog::ERROR, "Error",
254
"Cannot add a flow from and to the same node.");
257
int subj1Type = subj1->GetClassType();
258
int subj2Type = subj2->GetClassType();
259
// Cannot connect a data process with a splitmerge node
260
// when they are already connected (even in the opposite direction).
261
if ((GetEdgeType()==Code::DATA_FLOW||
262
GetEdgeType()==Code::CONTINUOUS_DATA_FLOW) &&
263
(subj1Type==Code::DATA_PROCESS &&
264
subj2Type==Code::SPLIT_MERGE_NODE ||
265
subj1Type==Code::SPLIT_MERGE_NODE &&
266
subj2Type==Code::DATA_PROCESS) &&
267
(GetGraph()->IsConnected(subj2, subj1) ||
268
GetGraph()->IsConnected(subj1, subj2))) {
269
ShowDialog(MessageDialog::ERROR, "Error",
270
"Cannot add another data flow here. ");
276
bool DFDiagram::HasIndexNode(int code) {
277
return (code == Code::DATA_PROCESS || code == Code::CONTROL_PROCESS);
280
bool DFDiagram::HasIndexShape(int code) {
281
return (code == Code::CIRCLE);
284
void DFDiagram::EditMinispec(Subject *s) {
285
if (s->GetClassType() != Code::DATA_PROCESS) {
286
ShowDialog(MessageDialog::ERROR, "Not a data process",
287
"Only data processes can have a minispec");
290
if (minispecDialog->IsManaged()) {
291
ShowDialog(MessageDialog::WARNING, "Warning",
292
"You can only open one minispec editor at a time.");
295
editProcess = (DataProcess *)s;
296
if (editProcess->IsProcessGroup()) {
297
ShowDialog(MessageDialog::ERROR, "A process group",
298
"This data process is a process group,\n"
299
"so it cannot have a minispec");
303
const string *n = editProcess->GetIndex();
304
const string *spec = editProcess->GetMinispec();
305
string x = "Minispec of process ";
306
string title = x + *n;
307
minispecDialog->SetTitle(&title);
308
minispecDialog->SetTextString(spec);
309
minispecDialog->Popup();
312
void DFDiagram::SetMinispec() {
313
SetStatus("action: Update minispec");
314
if (!check(editProcess))
317
minispecDialog->GetTextString(&t);
318
editProcess->SetMinispec(&t);
321
void DFDiagram::SetDiagram(const string *dfd) {
322
DFGraph *dg = (DFGraph *)GetGraph();
324
if (((*dfd == "") || DFProcess::CorrectIndex(&sdfd)) &&
326
dg->SetIndexPrefix(&sdfd);
327
((DFWindow *)GetMainWindow())->SetDiagram(dfd);
330
string txt = "diagram " + sdfd + " is the current diagram";
334
const string s = *dg->GetIndexPrefix();
335
((DFWindow *)GetMainWindow())->SetDiagram(&s);
338
txt += "' wrong syntax for \na data flow diagram index";
339
ShowDialog(MessageDialog::ERROR, "Error", &txt);
343
void DFDiagram::CheckDocument() {
346
total += dfChecks->CheckNamelessNodes(Code::DATA_PROCESS, chkbuf);
347
total += dfChecks->CheckNamelessNodes(Code::DATA_STORE, chkbuf);
348
total += dfChecks->CheckNamelessNodes(Code::EXTERNAL_ENTITY, chkbuf);
349
total += dfChecks->CheckNamelessFlows(Code::DATA_FLOW,
350
Code::EXTERNAL_ENTITY, Code::DATA_PROCESS, chkbuf);
351
total += dfChecks->CheckNamelessFlows(Code::DATA_FLOW,
352
Code::DATA_PROCESS, Code::EXTERNAL_ENTITY, chkbuf);
353
total += dfChecks->CheckNamelessFlows(Code::DATA_FLOW,
354
Code::DATA_PROCESS, Code::DATA_PROCESS, chkbuf);
355
total += dfChecks->CheckDoubleNodes(Code::DATA_PROCESS, chkbuf);
356
total += dfChecks->CheckDoubleNodes(Code::DATA_STORE, chkbuf);
357
total += dfChecks->CheckDoubleNodes(Code::EXTERNAL_ENTITY, chkbuf);
358
total += dfChecks->CheckDoubleIndexes(chkbuf);
359
total += dfChecks->CheckDataProcessCoherence(chkbuf);
360
total += dfChecks->CheckConnected(Code::DATA_STORE, False, chkbuf);
361
total += dfChecks->CheckConnected(Code::EXTERNAL_ENTITY, False, chkbuf);
362
total += dfChecks->CheckSplitMergeNodeCoherence(chkbuf);
363
total += dfChecks->CheckNamelessSplitMergeEdges(chkbuf);
364
total += dfChecks->CheckMinispecs(chkbuf);
365
ReportCheck(total, &chkbuf);