~ubuntu-branches/ubuntu/utopic/tcm/utopic

« back to all changes in this revision

Viewing changes to src/dg/diagramviewer.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2003-07-03 20:08:21 UTC
  • Revision ID: james.westby@ubuntu.com-20030703200821-se4xtqx25e5miczi
Tags: upstream-2.20
ImportĀ upstreamĀ versionĀ 2.20

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
////////////////////////////////////////////////////////////////////////////////
 
2
//
 
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).
 
6
//
 
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.
 
11
//
 
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.
 
16
//
 
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
 
20
// 02111-1307, USA.
 
21
////////////////////////////////////////////////////////////////////////////////
 
22
#include "alignnodeshapescmd.h"
 
23
#include "createnodecmd.h"
 
24
#include "createedgecmd.h"
 
25
#include "cutshapescmd.h"
 
26
#include "deleteshapescmd.h"
 
27
#include "deleteallsubjectscmd.h"
 
28
#include "deleteselectedsubjectscmd.h"
 
29
#include "duplicateshapescmd.h"
 
30
#include "addhandlecmd.h"
 
31
#include "deletehandlecmd.h"
 
32
#include "dragtextshapecmd.h"
 
33
#include "dragshapescmd.h"
 
34
#include "findnexttextcmd.h"
 
35
#include "moveallshapescmd.h"
 
36
#include "replacealltextscmd.h"
 
37
#include "replacenexttextcmd.h"
 
38
#include "samesizecmd.h"
 
39
#include "selectareacmd.h"
 
40
#include "sizeshapecentercmd.h"
 
41
#include "sizeshapebordercmd.h"
 
42
#include "updatetextcmd.h"
 
43
#include "updatefontcmd.h"
 
44
#include "updatetextalignmentcmd.h"
 
45
#include "updatelinewidthcmd.h"
 
46
#include "updatelinestylecmd.h"
 
47
#include "updatelinecolorcmd.h"
 
48
#include "updatefillcolorcmd.h"
 
49
#include "updatetextcolorcmd.h"
 
50
#include "updatelineendcmd.h"
 
51
#include "updatecurvecmd.h"
 
52
#include "updatetextunderlinecmd.h"
 
53
#include "reindexcmd.h"
 
54
#include "buffer.h"
 
55
#include "textshapeeditor.h"
 
56
#include "questiondialog.h"
 
57
#include "line.h"
 
58
#include "nodeshape.h"
 
59
#include "node.h"
 
60
#include "key.h"
 
61
#include "diagram.h"
 
62
#include "diagramviewer.h"
 
63
#include "diagramstubs.h"
 
64
#include "lineenddialog.h"
 
65
#include "nodealignmentdialog.h"
 
66
#include "nodeshapedialog.h"
 
67
#include "outputfile.h"
 
68
#include <ctype.h>
 
69
#include <stdlib.h>
 
70
 
 
71
DiagramViewer::DiagramViewer(Config *c, DiagramWindow *w): Viewer(c, w) {
 
72
        diagram = 0;
 
73
        views = new List<ShapeView *>;
 
74
        buffer = new Buffer();
 
75
        SetInlineEditor(new TextShapeEditor(this));
 
76
        grid = new Grid(c, w, this);
 
77
        showIndexes = False;
 
78
        defaultCurve = False;
 
79
        defaultNodeLineStyle = LineStyle::SOLID;
 
80
        defaultEdgeLineStyle = LineStyle::SOLID;
 
81
        defaultLineEnd1 = LineEnd::EMPTY;
 
82
        defaultLineEnd2 = LineEnd::EMPTY;
 
83
        lineEndDialog = new LineEndDialog(w->GetWidget());
 
84
        lineEndDialog->Initialize();
 
85
        ShowDefaultLineEnd();
 
86
        alignDialog = new NodeAlignmentDialog(w->GetWidget());
 
87
        alignDialog->Initialize();
 
88
        ShowDefaultNodeAlignment();
 
89
        nodeShapeDialog = new NodeShapeDialog(w->GetWidget());
 
90
        nodeShapeDialog->Initialize();
 
91
        ShowDefaultNodeShape();
 
92
}
 
93
 
 
94
DiagramViewer::~DiagramViewer() {
 
95
        DeleteAllViews();
 
96
        delete views;
 
97
        delete buffer;
 
98
        delete grid;
 
99
        delete lineEndDialog;
 
100
        delete alignDialog;
 
101
        delete nodeShapeDialog;
 
102
}
 
103
 
 
104
void DiagramViewer::Initialize() {
 
105
        ShapeView *v = new ShapeView(this);
 
106
        views->add(v);
 
107
        SetView(v);
 
108
}
 
109
 
 
110
void DiagramViewer::Draw() {
 
111
        if (curView)
 
112
                curView->Draw();
 
113
}
 
114
 
 
115
void DiagramViewer::Undraw() {
 
116
        if (curView)
 
117
                curView->Undraw();
 
118
}
 
119
 
 
120
void DiagramViewer::DeleteAllViews() {
 
121
        Undraw();
 
122
        views->clear();
 
123
        curView = 0;
 
124
}
 
125
 
 
126
ShapeView *DiagramViewer::GetView(const string *index) {
 
127
        for (views->first(); !views->done(); views->next()) {
 
128
                if (*views->cur()->GetIndex() == *index)
 
129
                        return views->cur();
 
130
        }
 
131
        return 0;
 
132
}
 
133
 
 
134
bool DiagramViewer::HasView(const string *index) {
 
135
        return (GetView(index) != 0);
 
136
}
 
137
 
 
138
bool DiagramViewer::HasView(ShapeView *view) {
 
139
        for (views->first(); !views->done(); views->next()) {
 
140
                if (views->cur() == view)
 
141
                        return True;
 
142
        }
 
143
        return False;
 
144
}
 
145
 
 
146
bool DiagramViewer::AddView(ShapeView *v) {
 
147
        if (!HasView(v->GetIndex())) {
 
148
                views->add(v);
 
149
                // curView = v;
 
150
                return True;
 
151
        }
 
152
        return False;
 
153
}
 
154
 
 
155
void DiagramViewer::UpdateView(ShapeView *v) {
 
156
        Undraw();
 
157
        SetView(v);
 
158
        Draw();
 
159
}
 
160
 
 
161
void DiagramViewer::SetView(ShapeView *v) {
 
162
        if (!check(views->contains(v)))
 
163
                return;
 
164
        curView = v;
 
165
        ((EditWindow *)GetMainWindow())->
 
166
                SetDocumentLevel(v->GetIndex());
 
167
}
 
168
 
 
169
void DiagramViewer::SetGrafport(Grafport *g) {
 
170
        Viewer::SetGrafport(g);
 
171
        for (views->first(); !views->done(); views->next())
 
172
                views->cur()->SetGrafport(g);
 
173
}
 
174
 
 
175
void DiagramViewer::Redraw() {
 
176
        Viewer::Redraw();
 
177
        if (grid->IsShowGrid())
 
178
                grid->DrawGrid();
 
179
 
180
 
 
181
void DiagramViewer::CheckShapes() {
 
182
        for (views->first(); !views->done(); views->next()) {
 
183
                if (views->cur()->CheckReferences())
 
184
                        views->cur()->CheckShapes();
 
185
        }
 
186
}
 
187
 
 
188
void DiagramViewer::DeselectAll() {
 
189
        for (views->first(); !views->done(); views->next())
 
190
                views->cur()->DeselectAll();
 
191
}
 
192
 
 
193
bool DiagramViewer::TextMode(TextShape *textShape) {
 
194
        if (IsEditing())
 
195
                return False;
 
196
        
 
197
        string status = "start text editing [";
 
198
        status += *textShape->GetDescription();
 
199
        status += "]";
 
200
        if (!IsInlineEdit()) {
 
201
                SetEditing(True);
 
202
                ((TextShapeEditor *)GetInlineEditor())->StartWindow(textShape);
 
203
                SetStatus(&status);
 
204
                return False;
 
205
        }
 
206
        else if (!IsEditing()) {
 
207
                SetEditing(True);
 
208
                if (IsInlineEdit()) {
 
209
                        SetCursor(MouseCursor::TERM);
 
210
                        ((TextShapeEditor *)GetInlineEditor())->
 
211
                                Start(textShape);
 
212
                }
 
213
                SetStatus(&status);
 
214
                return True;
 
215
        }
 
216
        return False;
 
217
}
 
218
 
 
219
void DiagramViewer::TextModeOff() {
 
220
        if (IsEditing()) {
 
221
                if (IsInlineEdit())
 
222
                        GetInlineEditor()->Stop();
 
223
                SetEditing(False);
 
224
        }
 
225
}
 
226
 
 
227
bool DiagramViewer::GoIntoTextMode(GShape *shape, int x, int y) {
 
228
        if (!shape)
 
229
                return False;
 
230
        if (curView->NrSelected() == 1 && shape == curView->FirstSelected()) {
 
231
                // find right textShape
 
232
                TextShape *textShape = shape->ChooseTextShape(x, y);
 
233
                if (!textShape)
 
234
                        return False;
 
235
                // switch to text input
 
236
                return TextMode(textShape);
 
237
        }
 
238
        return False;
 
239
}
 
240
 
 
241
void DiagramViewer::KeyTyped(int x, int y, int key) {
 
242
        x = int(0.5 + ScaleCorrect(x));
 
243
        y = int(0.5 + ScaleCorrect(y));
 
244
        if (!IsEditing()) {
 
245
                GShape *shape = curView->HitShape(x, y);
 
246
                unsigned char c = (unsigned char)key;
 
247
                if (!shape || Key::EditKey(key) || iscntrl(c) || 
 
248
                    !GoIntoTextMode(shape, x, y))
 
249
                        return;
 
250
        }
 
251
        if (IsInlineEdit())
 
252
                EditText(key);
 
253
}
 
254
 
 
255
void DiagramViewer::SetCursor(int x, int y) {
 
256
        x = int(0.5 + ScaleCorrect(x));
 
257
        y = int(0.5 + ScaleCorrect(y));
 
258
        if (IsInlineEdit()) {
 
259
                // set cursor when text shape is hit, otherwise stop editing.
 
260
                GShape *shape = curView->HitShape(x,y);
 
261
                if (shape) {
 
262
                        TextShape *t = shape->ChooseTextShape(x, y);
 
263
                        if (t && t==((TextShapeEditor *)GetInlineEditor())->
 
264
                                        GetTextShape()){
 
265
                                GetInlineEditor()->SetCursor(x, y);
 
266
                                return;
 
267
                        }
 
268
                }
 
269
                TextModeOff();
 
270
        }
 
271
}
 
272
 
 
273
void DiagramViewer::Select(int x, int y) {
 
274
        if (IsEditing() && IsInlineEdit()) {
 
275
                SetCursor(x, y);
 
276
                return;
 
277
        }
 
278
        x = int(0.5 + ScaleCorrect(x));
 
279
        y = int(0.5 + ScaleCorrect(y));
 
280
        GShape *shape = curView->HitShape(x,y);
 
281
        if (shape) {
 
282
                if (!shape->IsSelected()) {
 
283
                        curView->DeselectAll();
 
284
                        curView->SelectShape(shape);
 
285
                        curView->SetCurrentShapeNr(shape);
 
286
                        SetCursor(MouseCursor::TERM);
 
287
                        SetStatus("select shape");
 
288
                }
 
289
                else if (curView->NrSelected() > 1) 
 
290
                        // make selected shape the first of the selection.
 
291
                        curView->FirstSelectShape(shape);
 
292
                else
 
293
                        GoIntoTextMode(shape, x, y);
 
294
        }
 
295
        else
 
296
                CreateNode(x,y);
 
297
}
 
298
 
 
299
void DiagramViewer::Adjust(int x, int y) {
 
300
        if (IsEditing() && IsInlineEdit()) {
 
301
                TextModeOff();
 
302
                return;
 
303
        }
 
304
        x = int(0.5 + ScaleCorrect(x));
 
305
        y = int(0.5 + ScaleCorrect(y));
 
306
        GShape *shape = curView->HitShape(x, y);
 
307
        if (shape) {
 
308
                if (shape->IsSelected()) {
 
309
                        if (shape->IsLine() && curView->NrSelected() == 1) {
 
310
                                Line *line = (Line *)shape; 
 
311
                                int w = line->HitHandles(x, y);
 
312
                                int np = line->NrPoints()-1;
 
313
                                if (!line->IsCurved() && w > 0 && w < np
 
314
                                                && (np > 3 || line->GetFromShape() != line->GetToShape()) ) {
 
315
                                        SetStatus("delete line handle");
 
316
                                        NewCommand(new DeleteHandleCmd(line, w));
 
317
                                        ExecuteCommand();
 
318
                                        return;
 
319
                                }
 
320
                        }
 
321
                        curView->DeselectShape(shape);
 
322
                        SetStatus("deselect shape");
 
323
                }
 
324
                else {
 
325
                        curView->SelectShape(shape);
 
326
                        SetStatus("add to selection");
 
327
                }
 
328
        }
 
329
        else {
 
330
                curView->DeselectAll();
 
331
        }
 
332
}
 
333
 
 
334
void DiagramViewer::MovingPointer(int x, int y) {
 
335
        if (curView->NrSelected() != 1) {
 
336
                SetCursor(MouseCursor::LEFT_PTR);
 
337
                return;
 
338
        }
 
339
        GShape *shape = curView->FirstSelected();
 
340
        x = int(0.5 + ScaleCorrect(x));
 
341
        y = int(0.5 + ScaleCorrect(y));
 
342
        int w;
 
343
        if ((w = shape->HitHandles(x, y)) >= 0) {
 
344
                if ( ! shape->IsNodeShape() )
 
345
                        SetSizeCursor(0);
 
346
                else
 
347
                        SetSizeCursor(w);
 
348
        }
 
349
        else if (shape->InTextArea(x, y))
 
350
                SetCursor(MouseCursor::TERM);
 
351
        else
 
352
                SetCursor(MouseCursor::LEFT_PTR);
 
353
}
 
354
 
 
355
void DiagramViewer::CreateNode(int x, int y) {
 
356
        NewCommand(new CreateNodeCmd(curView, x, y));
 
357
        ExecuteCommand();
 
358
        SetCursor(MouseCursor::TERM);
 
359
}
 
360
 
 
361
Command *DiagramViewer::Drag(int x, int y) {
 
362
        GShape *shape;
 
363
        Line *line;
 
364
        TextShape *textShape;
 
365
        x = int(0.5 + ScaleCorrect(x));
 
366
        y = int(0.5 + ScaleCorrect(y));
 
367
        int w;
 
368
        // look for text labels (of lines).
 
369
        if ((textShape = curView->HitTextShape(x, y, False))) {
 
370
                return new DragTextShapeCmd(textShape);
 
371
        }
 
372
        // look for line handle
 
373
        else if ((line = curView->HitLineHandle(x, y, w))) {
 
374
                return new DragHandleCmd(line, w);
 
375
        }
 
376
        // look for nodes shapes.
 
377
        else if ((shape = curView->HitNodeShape(x, y))) {
 
378
                if (shape->IsSelected() && (w = shape->HitHandles(x, y)) >= 0) {
 
379
                        return new SizeShapeCenterCmd(shape, w);
 
380
                }
 
381
                else if (shape->IsSelected() && curView->NrSelected() > 1) {
 
382
                        return new DragShapesCmd(curView);
 
383
                }
 
384
                else {
 
385
                        return new DragShapeCmd(shape);
 
386
                }
 
387
        }
 
388
        else if ((line = curView->HitLine(x, y, w))) {
 
389
                if (!line->IsCurved()) {
 
390
                        return new AddHandleCmd(line, x, y, w);
 
391
                }
 
392
        }
 
393
        // otherwise select area
 
394
        return new SelectAreaCmd(curView);
 
395
}
 
396
 
 
397
Command *DiagramViewer::Connect(int x, int y) {
 
398
        GShape *shape;
 
399
        x = int(0.5 + ScaleCorrect(x));
 
400
        y = int(0.5 + ScaleCorrect(y));
 
401
        int w;
 
402
        // look for shape.
 
403
        if (Toolkit::EditorWithInterEdgeConnections(
 
404
                        GetMainWindow()->GetTool())) { 
 
405
                if ((shape = curView->HitShape(x, y))) {
 
406
                        if ( shape->IsNodeShape() && shape->IsSelected() && 
 
407
                            (w = shape->HitHandles(x, y)) >= 0)
 
408
                                return new SizeShapeBorderCmd(shape, w);
 
409
                        else if ( shape->IsNodeShape() || (shape->IsLine() &&
 
410
                                 !((Line*)shape)->IsCurved()) )
 
411
                                return new CreateEdgeCmd(shape);
 
412
                }
 
413
        }
 
414
        else if ((shape = curView->HitNodeShape(x, y))) {
 
415
                if (shape->IsSelected() && (w = shape->HitHandles(x, y)) >= 0)
 
416
                        return new SizeShapeBorderCmd(shape, w);
 
417
                else
 
418
                        return new CreateEdgeCmd(shape);
 
419
        }
 
420
        return 0;
 
421
}
 
422
 
 
423
void DiagramViewer::SelectAll() {
 
424
        SetStatus("action: select all");
 
425
        if (curView->NrOfShapes() > 0) {
 
426
                NewCommand(new SelectAllCmd(curView));
 
427
                ExecuteCommand();
 
428
        }
 
429
        else
 
430
                EmptyShapesMessage();
 
431
}
 
432
 
 
433
void DiagramViewer::AlignNodes(NodeAlign::Type alignType) {
 
434
        SetStatus("action: align node shapes");
 
435
        if (curView->NrSelected() >= 2) {
 
436
                NewCommand(new AlignNodeShapesCmd(curView, 
 
437
                        curView->GetSelection(), alignType));
 
438
                ExecuteCommand();
 
439
        }
 
440
        else {
 
441
                (new MessageDialog(GetMainWindow()->GetWidget(), 
 
442
                        MessageDialog::WARNING))->
 
443
                        Show("Warning", "You need to select two or more nodes");
 
444
                SetStatus("aborted: selection is empty or singleton");
 
445
        }
 
446
}
 
447
 
 
448
void DiagramViewer::FindAll(const string *s, bool sens, bool substr, 
 
449
                bool nameOnly) {
 
450
        if (curView->NrOfShapes() > 0) {
 
451
                NewCommand(new FindAllTextsCmd(curView, s, sens, substr, 
 
452
                        nameOnly));
 
453
                ExecuteCommand();
 
454
        }
 
455
        else
 
456
                EmptyShapesMessage();
 
457
}
 
458
 
 
459
void DiagramViewer::FindNext(const string *s, bool sens, bool substr, 
 
460
                bool nameOnly) {
 
461
        if (curView->NrOfShapes() > 0) {
 
462
                NewCommand(new FindNextTextCmd(curView, s, sens, substr, 
 
463
                        nameOnly));
 
464
                ExecuteCommand();
 
465
        }
 
466
        else
 
467
                EmptyShapesMessage();
 
468
}
 
469
 
 
470
void DiagramViewer::ReplaceNext(const string *s1, const string *s2, 
 
471
                bool sens, bool substr, bool nameOnly) {
 
472
        if (curView->NrOfShapes() > 0) {
 
473
                NewCommand(new ReplaceNextTextCmd(curView, s1, s2, sens, 
 
474
                                substr, nameOnly));
 
475
                ExecuteCommand();
 
476
        }
 
477
        else
 
478
                EmptyShapesMessage();
 
479
}
 
480
 
 
481
void DiagramViewer::ReplaceAll(const string *s1, const string *s2, 
 
482
                bool sens, bool substr, bool nameOnly) {
 
483
        if (curView->NrOfShapes() > 0) {
 
484
                NewCommand(new ReplaceAllTextsCmd(
 
485
                        curView, s1, s2, sens, substr, nameOnly));
 
486
                ExecuteCommand();
 
487
        }
 
488
        else
 
489
                EmptyShapesMessage();
 
490
}
 
491
 
 
492
void DiagramViewer::Cut() {
 
493
        SetStatus("action: cut");
 
494
        if (curView->NrSelected() > 0) {
 
495
                NewCommand(new CutShapesCmd(curView));
 
496
                ExecuteCommand();
 
497
        }
 
498
        else
 
499
                EmptySelectionMessage();
 
500
}
 
501
 
 
502
void DiagramViewer::Copy() {
 
503
        SetStatus("action: copy");
 
504
        if (curView->NrSelected() > 0) {
 
505
                NewCommand(new CopyShapesCmd(curView));
 
506
                ExecuteCommand();
 
507
        }
 
508
        else
 
509
                EmptySelectionMessage();
 
510
}
 
511
 
 
512
void DiagramViewer::Paste() {
 
513
        SetStatus("action: paste");
 
514
        if (!buffer->IsEmpty())
 
515
                NewCommand(new PasteShapesCmd(curView));
 
516
        else {
 
517
                (new MessageDialog(GetMainWindow()->GetWidget(), 
 
518
                        MessageDialog::WARNING))->
 
519
                        Show("Warning", "There is nothing in the paste buffer");
 
520
                SetStatus("aborted: paste buffer is empty");
 
521
        }
 
522
}
 
523
 
 
524
void DiagramViewer::Duplicate() {
 
525
        SetStatus("action: duplicate");
 
526
        if (curView->NrSelected() > 0)
 
527
                NewCommand(new DuplicateShapesCmd(curView));
 
528
        else
 
529
                EmptySelectionMessage();
 
530
}
 
531
 
 
532
void DiagramViewer::DeleteSubjects() {
 
533
        SetStatus("action: delete Subjects");
 
534
        if (curView->NrSelected() > 0) {
 
535
                NewCommand(new DeleteSelectedSubjectsCmd(curView));
 
536
                ExecuteCommand();
 
537
                SetCursor(MouseCursor::LEFT_PTR);
 
538
        }
 
539
        else
 
540
                EmptySelectionMessage();
 
541
}
 
542
 
 
543
void DiagramViewer::DeleteShapes() {
 
544
        SetStatus("action: delete");
 
545
        List<GShape *> *sel = curView->GetSelection();
 
546
        bool duplicates=False;
 
547
        // Check if there are duplicate shapes.
 
548
        if (sel->first()) {
 
549
                for (sel->first(); !sel->done(); sel->next()) {
 
550
                        if (sel->cur()->IsDuplicate())
 
551
                                duplicates=True;
 
552
                }
 
553
                if (duplicates) {
 
554
                        QuestionDialog q(GetMainWindow()->GetWidget(), True);
 
555
                        q.Initialize();
 
556
                        q.SetTitle("delete shapes");
 
557
                        q.SetMessageString(
 
558
                                "Delete all duplicates of selected shapes?");
 
559
                        int answer = q.GetAnswer();
 
560
                        if (answer == QuestionDialog::YES)
 
561
                                DeleteSubjects();
 
562
                        else if (answer == QuestionDialog::NO) {
 
563
                                NewCommand(new DeleteShapesCmd(curView));
 
564
                                ExecuteCommand();
 
565
                                SetCursor(MouseCursor::LEFT_PTR);
 
566
                        }
 
567
                        else { // CANCEL.
 
568
                                SetStatus("canceled: nothing deleted");
 
569
                                return;
 
570
                        }
 
571
                }
 
572
                else
 
573
                        DeleteSubjects();
 
574
        }
 
575
        else
 
576
                EmptySelectionMessage();
 
577
}
 
578
 
 
579
void DiagramViewer::DeleteAll() {
 
580
        SetStatus("action: delete all");
 
581
        if (curView->NrOfShapes() > 0) {
 
582
                QuestionDialog q(GetMainWindow()->GetWidget(), False);
 
583
                q.Initialize();
 
584
                q.SetTitle("delete all");
 
585
                q.SetMessageString("Are you sure you want to delete\n"
 
586
                                   "all subjects in current view?");
 
587
                int answer = q.GetAnswer();
 
588
                if (answer == QuestionDialog::YES) {
 
589
                        NewCommand(new DeleteAllSubjectsCmd(curView));
 
590
                        ExecuteCommand();
 
591
                        SetCursor(MouseCursor::LEFT_PTR);
 
592
                }
 
593
                else if (answer == QuestionDialog::NO)
 
594
                        SetStatus("aborted: nothing is deleted");
 
595
        }
 
596
        else
 
597
                EmptyShapesMessage();
 
598
}
 
599
 
 
600
void DiagramViewer::SameSize() {
 
601
        SetStatus("action: same size");
 
602
        if (curView->NrSelected() >= 2) {
 
603
                NewCommand(new SameSizeCmd(curView));
 
604
                ExecuteCommand();
 
605
        }
 
606
        else {
 
607
                (new MessageDialog(GetMainWindow()->GetWidget(), 
 
608
                        MessageDialog::WARNING))->
 
609
                        Show("Warning", "You need to select two or more nodes");
 
610
                SetStatus("aborted: selection is empty or singleton");
 
611
        }
 
612
}
 
613
 
 
614
void DiagramViewer::UpdateTextAlignmentSelection(TextAlign::Type a) {
 
615
        SetStatus("action: update text alignment");
 
616
        if (curView->NrSelected() > 0) {
 
617
                NewCommand(new UpdateTextAlignmentCmd(curView, a));
 
618
                ExecuteCommand();
 
619
        }
 
620
        else
 
621
                EmptySelectionMessage();
 
622
}
 
623
 
 
624
void DiagramViewer::UpdateLineWidthSelection(unsigned n) {
 
625
        if (curView->NrSelected() > 0) {
 
626
                NewCommand(new UpdateLineWidthCmd(curView, n));
 
627
                ExecuteCommand();
 
628
        }
 
629
        else
 
630
                EmptySelectionMessage();
 
631
}
 
632
 
 
633
void DiagramViewer::UpdateLineStyleSelection(LineStyle::Type s) {
 
634
        if (curView->NrSelected() > 0) {
 
635
                NewCommand(new UpdateLineStyleCmd(curView, s));
 
636
                ExecuteCommand();
 
637
        }
 
638
        else
 
639
                EmptySelectionMessage();
 
640
}
 
641
 
 
642
void DiagramViewer::UpdateLineColorSelection(const string *s) {
 
643
        if (curView->NrSelected() > 0) {
 
644
                NewCommand(new UpdateLineColorCmd(curView, s));
 
645
                ExecuteCommand();
 
646
        }
 
647
        else
 
648
                EmptySelectionMessage();
 
649
}
 
650
 
 
651
void DiagramViewer::UpdateTextColorSelection(const string *s) {
 
652
        if (curView->NrSelected() > 0) {
 
653
                NewCommand(new UpdateTextColorCmd(curView, s));
 
654
                ExecuteCommand();
 
655
        }
 
656
        else
 
657
                EmptySelectionMessage();
 
658
}
 
659
 
 
660
void DiagramViewer::UpdateFillColorSelection(const string *s,
 
661
                FillStyle::Type f) {
 
662
        if (curView->NrSelected() > 0) {
 
663
                NewCommand(new UpdateFillColorCmd(curView, s, f));
 
664
                ExecuteCommand();
 
665
        }
 
666
        else
 
667
                EmptySelectionMessage();
 
668
}
 
669
 
 
670
void DiagramViewer::UpdateFontSelection(int f, int s, int p) {
 
671
        if (curView->NrSelected() > 0) {
 
672
                NewCommand(new UpdateFontCmd(curView, f, s, p));
 
673
                ExecuteCommand();
 
674
        }
 
675
        else
 
676
                EmptySelectionMessage();
 
677
}
 
678
 
 
679
 
 
680
void DiagramViewer::Annotate() {
 
681
        SetStatus("action: annotate subject");
 
682
        if (curView->NrSelected() >= 1) {
 
683
                Subject *subject = curView->FirstSelected()->GetSubject();
 
684
                diagram->AnnotateSubject(subject);
 
685
        }
 
686
        else
 
687
                EmptySelectionMessage();
 
688
}
 
689
 
 
690
void DiagramViewer::MoveAllShapes(Diagram::MoveType t) {
 
691
        if (curView->NrOfShapes() > 0) {
 
692
                NewCommand(new MoveAllShapesCmd(curView, t));
 
693
                ExecuteCommand();
 
694
        }
 
695
        else
 
696
                SetStatus("aborted: empty view");
 
697
}
 
698
 
 
699
void DiagramViewer::UpdateText(TextShape *s, const string *n, const string *o) {
 
700
        if (s) {
 
701
                GShape *p = (GShape *)s->GetParent();
 
702
                if (curView->HasShape(p)) {
 
703
                        NewCommand(new UpdateTextCmd(s, n, o));
 
704
                        ExecuteCommand();
 
705
                }
 
706
                else {
 
707
                        (new MessageDialog(GetMainWindow()->GetWidget(), 
 
708
                          MessageDialog::WARNING))->
 
709
                        Show("Warning", "The shape were this text "
 
710
                                        "belonged to,\nis already deleted");
 
711
                        SetStatus("aborted: shape does not exist");
 
712
                }
 
713
        }
 
714
        else {
 
715
                (new MessageDialog(GetMainWindow()->GetWidget(), 
 
716
                        MessageDialog::WARNING))->
 
717
                Show("Warning", "The text shape of this text,\n"
 
718
                                  "is already deleted");
 
719
                SetStatus("aborted: text shape does not exist");
 
720
        }
 
721
}
 
722
 
 
723
GShape *DiagramViewer::GetShape(Subject *subject) {
 
724
        if (!check(subject))
 
725
                return 0;
 
726
        for (views->first(); !views->done(); views->next()) {
 
727
                ShapeView *view = views->cur();
 
728
                GShape *shape = 0;
 
729
                if (check(view) && (shape = view->GetShape(subject)))
 
730
                        return shape;
 
731
        }
 
732
        return 0;
 
733
}
 
734
 
 
735
void DiagramViewer::GetShapes(Subject *subject, List<GShape *> *s) {
 
736
        if (!check(subject))
 
737
                return;
 
738
        for (views->first(); !views->done(); views->next()) {
 
739
                ShapeView *view = views->cur();
 
740
                if (check(view))
 
741
                        view->GetShapes(subject, s);
 
742
        }
 
743
}
 
744
 
 
745
void DiagramViewer::CalcSizeElements(Point &topLeft, Point &bottomRight) {
 
746
        curView->CalcSizeElements(topLeft, bottomRight); 
 
747
}
 
748
 
 
749
void DiagramViewer::CalcSizeSelection(Point &topLeft, Point &bottomRight) {
 
750
        curView->CalcSizeSelection(topLeft, bottomRight); 
 
751
}
 
752
 
 
753
void DiagramViewer::WriteShapes(OutputFile *f) {
 
754
        (*f) << "# VIEWS AND GRAPHICAL SHAPES\n\n";
 
755
        for (views->first(); !views->done(); views->next()) {
 
756
                views->cur()->Write(f);
 
757
                views->cur()->WriteShapes(f);
 
758
        }
 
759
}
 
760
 
 
761
void DiagramViewer::WriteSelection(OutputFile *f) {
 
762
        List<GShape *> selection (*curView->GetSelection());
 
763
        if (selection.count() == 0)
 
764
                (new MessageDialog(GetMainWindow()->GetWidget(), 
 
765
                        MessageDialog::WARNING))->
 
766
                        Show("Warning", "Wrote an empty document\n"
 
767
                                        "because the selection is empty");
 
768
        List<Subject *> subjects;
 
769
        curView->CompleteLines(&selection);
 
770
        for (selection.first(); !selection.done(); selection.next()) {
 
771
                GShape *s = selection.cur();
 
772
                if (!subjects.contains(s->GetSubject()))
 
773
                        subjects.add(s->GetSubject());
 
774
        }
 
775
        (*f) << "# NODES AND EDGES\n";
 
776
        (*f) << "# (PRODUCED BY SAVE SELECTION)\n\n";
 
777
        for (subjects.first(); !subjects.done(); subjects.next())
 
778
                subjects.cur()->Write(f);
 
779
        (*f) << "# VIEW AND GRAPHICAL SHAPES\n\n";
 
780
        curView->Write(f);
 
781
        for (selection.first(); !selection.done(); selection.next())
 
782
                selection.cur()->Write(f);
 
783
}
 
784
 
 
785
void DiagramViewer::EmptySelectionMessage() {
 
786
        (new MessageDialog(GetMainWindow()->GetWidget(), 
 
787
                MessageDialog::WARNING))->
 
788
                Show("Warning", "Nothing is selected");
 
789
        SetStatus("aborted: selection is empty");
 
790
}
 
791
 
 
792
void DiagramViewer::EmptyShapesMessage() {
 
793
        (new MessageDialog(GetMainWindow()->GetWidget(), 
 
794
                MessageDialog::WARNING))->
 
795
                Show("Warning", "View is empty");
 
796
        SetStatus("aborted: there are no shapes");
 
797
}
 
798
 
 
799
 
 
800
void DiagramViewer::CalcSizeShapes(List<GShape *> *s,
 
801
        Point &topLeft, Point &bottomRight) {
 
802
        if (!s->first()) {
 
803
                topLeft.Set(0, 0);
 
804
                bottomRight.Set(0, 0);
 
805
                return;
 
806
        }
 
807
        const int mval = -10;
 
808
        int x_max=mval, x_min=mval, y_max=mval, y_min=mval;
 
809
        int x, y;
 
810
        do {
 
811
                GShape *shape = s->cur();
 
812
                if (!check(shape))
 
813
                        break;
 
814
                x = shape->GetRightMost() + 3;
 
815
                if (x>x_max || x_max == mval)
 
816
                        x_max = x;
 
817
                x = shape->GetLeftMost() - 3;
 
818
                if (x<x_min || x_min == mval)
 
819
                        x_min = x;
 
820
                y = shape->GetBottomMost() + 3;
 
821
                if (y>y_max || y_max == mval)
 
822
                        y_max = y;
 
823
                y = shape->GetTopMost() - 3;
 
824
                if (y<y_min || y_min == mval)
 
825
                        y_min = y;
 
826
        } while (s->next());
 
827
        x_min = abs(x_min);
 
828
        y_min = abs(y_min);
 
829
        topLeft.Set(x_min, y_min);
 
830
        bottomRight.Set(x_max, y_max);
 
831
}
 
832
 
 
833
void DiagramViewer::ShapePositionUpdate(GShape *shape) {
 
834
        if ( shape->IsNodeShape()
 
835
           && Toolkit::HierarchicEditor(GetMainWindow()->GetTool()) )
 
836
                shape->GetView()->RecalcParent(shape);
 
837
        List<GShape *> shapes;
 
838
        shapes.add(shape);
 
839
        shape->GetView()->CompleteShapes(&shapes);
 
840
        for (shapes.first(); !shapes.done(); shapes.next()) {
 
841
                GShape *s = shapes.cur();
 
842
                if ( s->IsLine() && s != shape )
 
843
                        ((Line *)s)->UpdatePosition();
 
844
        }
 
845
}
 
846
 
 
847
void DiagramViewer::UpdateDuplicationMarks(List<Subject *> *s) {
 
848
        for (s->first(); !s->done(); s->next())
 
849
                UpdateDuplicationMarks(s->cur());
 
850
}
 
851
 
 
852
void DiagramViewer::UpdateDuplicationMarks(Subject *subject) {
 
853
        List<GShape *> shapes;
 
854
        GetShapes(subject, &shapes);
 
855
        bool duplicate = (shapes.count() >= 2);
 
856
        for (shapes.first(); !shapes.done(); shapes.next()) {
 
857
                GShape *shape = shapes.cur();
 
858
                shape->UpdateDuplicate(duplicate);
 
859
        }
 
860
}
 
861
 
 
862
void DiagramViewer::UpdateMoveShapes(List<GShape *> *s, const Point *delta){
 
863
        // move all shapes
 
864
        for (s->first(); !s->done(); s->next())
 
865
                s->cur()->UpdateMove(delta);
 
866
        // move line points.
 
867
        for (s->first(); !s->done(); s->next()) {
 
868
                GShape *shape = s->cur();
 
869
                if ( shape->IsNodeShape() )
 
870
                        ShapePositionUpdate(shape);
 
871
        }
 
872
}
 
873
 
 
874
void DiagramViewer::MoveShapes(List<GShape *> *s, const Point *delta) {
 
875
        // move all shapes
 
876
        for (s->first(); !s->done(); s->next()) {
 
877
                GShape *shape = s->cur();
 
878
                shape->Move(delta);
 
879
        }
 
880
        // move line points.
 
881
        for (s->first(); !s->done(); s->next()) {
 
882
                GShape *shape = s->cur();
 
883
                if ( shape->IsLine() ) {
 
884
                        ((Line *)shape)->CalcEndPoints();
 
885
                        ((Line *)shape)->CalcPosition();
 
886
                }
 
887
        }
 
888
}
 
889
 
 
890
void DiagramViewer::ZoomIn() {
 
891
        SetStatus("action: zoom in");
 
892
}
 
893
 
 
894
void DiagramViewer::ZoomOut() {
 
895
        SetStatus("action: zoom out");
 
896
}
 
897
 
 
898
void DiagramViewer::TopLevel() {
 
899
        SetStatus("action: top level");
 
900
}
 
901
 
 
902
void DiagramViewer::SetIndexes(bool b) {
 
903
        SetStatus("action: show indexes");
 
904
        if (b == IsShowIndexes())
 
905
                return;
 
906
        SetShowIndexes(b);
 
907
        if (IsShowIndexes())
 
908
                SetStatus("indexes are shown");
 
909
        else
 
910
                SetStatus("indexes are hidden");
 
911
/*
 
912
        List<GShape *> *s = GetCurView()->GetShapes();
 
913
        for (s->first(); !s->done(); s->next()) {
 
914
                GShape *shape = s->cur();
 
915
                if ( ! shape->IsNodeShape() )
 
916
                        continue;
 
917
                NodeShape *t = (NodeShape *)shape;
 
918
                if (IsShowIndexes())
 
919
                        t->UpdateIndexLabel(((Node *)t->GetSubject())->
 
920
                                GetIndex());
 
921
                else {
 
922
                        const string empty("");
 
923
                        t->UpdateIndexLabel(&empty);
 
924
                }
 
925
        }
 
926
*/
 
927
}
 
928
 
 
929
void DiagramViewer::Reindex(List<Node *> *nodes) {
 
930
        if (!check(GetDiagram()))
 
931
                return;
 
932
        if (nodes->count() > 0) {
 
933
                NewCommand(new ReindexCmd(GetCurView(), nodes));
 
934
                ExecuteCommand();
 
935
        }
 
936
        else {
 
937
                (new MessageDialog(GetMainWindow()->GetWidget(),
 
938
                                   MessageDialog::WARNING))->
 
939
                        Show("Warning", "There are no nodes to reindex"
 
940
                                        " in this diagram");
 
941
                SetStatus("aborted: no nodes");
 
942
        }
 
943
}
 
944
 
 
945
void DiagramViewer::UpdateLineEnd() {
 
946
        GetMainWindow()->SetStatus("action: update line ends");
 
947
        lineEndDialog->SetTitle("update line ends");
 
948
        lineEndDialog->SetHelpCallback(
 
949
                DiagramStubs::UpdateLineEndDefaultCB, this);
 
950
        lineEndDialog->SetOKCallback(
 
951
                DiagramStubs::UpdateLineEndOKCB, this);
 
952
        lineEndDialog->Popup();
 
953
}
 
954
 
 
955
void DiagramViewer::ShowDefaultLineEnd() {
 
956
        string text1, text2;   
 
957
        LineEnd::Type2String(defaultLineEnd1, &text1);
 
958
        LineEnd::Type2String(defaultLineEnd2, &text2);
 
959
        lineEndDialog->SetValueOfText(0, &text1);
 
960
        lineEndDialog->SetValueOfText(1, &text2);
 
961
}
 
962
 
 
963
void DiagramViewer::UpdateLineEndSelection(LineEnd::Type e1, LineEnd::Type e2) {
 
964
        if (curView->NrSelected() > 0) {
 
965
                NewCommand(new UpdateLineEndCmd(curView, e1, e2));
 
966
                ExecuteCommand();
 
967
        }
 
968
        else
 
969
                EmptySelectionMessage();
 
970
}
 
971
 
 
972
void DiagramViewer::AlignNodeShapes() {
 
973
        SetStatus("action: align node shapes");
 
974
        alignDialog->SetTitle("align node shapes");
 
975
        alignDialog->SetHelpCallback(
 
976
               DiagramStubs::AlignNodeShapesDefaultCB, this);
 
977
        alignDialog->SetOKCallback(
 
978
               DiagramStubs::AlignNodeShapesOKCB, this);
 
979
        alignDialog->Popup();
 
980
}
 
981
 
 
982
void DiagramViewer::ConvertNodeShapes() {
 
983
        SetStatus("action: convert node shapes");
 
984
        nodeShapeDialog->SetTitle("convert node shapes");
 
985
        nodeShapeDialog->SetHelpCallback(
 
986
                DiagramStubs::ConvertNodeShapesDefaultCB, this);
 
987
        nodeShapeDialog->SetOKCallback(
 
988
                DiagramStubs::ConvertNodeShapesOKCB, this);
 
989
        nodeShapeDialog->Popup();
 
990
}
 
991
 
 
992
void DiagramViewer::ShowDefaultNodeAlignment() {
 
993
        alignDialog->SetValue(0, 0);
 
994
}
 
995
 
 
996
void DiagramViewer::ShowDefaultNodeShape() {
 
997
        nodeShapeDialog->SetValue(0, 0);
 
998
}
 
999
 
 
1000
void DiagramViewer::UpdateCurve() {
 
1001
        SetStatus("action: convert from/to curve");
 
1002
        if (curView->NrSelected() > 0) {
 
1003
                NewCommand(new UpdateCurveCmd(curView));
 
1004
                ExecuteCommand();
 
1005
        }
 
1006
        else
 
1007
                EmptySelectionMessage();
 
1008
}
 
1009
 
 
1010
void DiagramViewer::UpdateTextUnderline() {
 
1011
        SetStatus("action: set/unset text underlining");
 
1012
        if (curView->NrSelected() > 0) {
 
1013
                NewCommand(new UpdateTextUnderlineCmd(curView));
 
1014
                ExecuteCommand();
 
1015
        }
 
1016
        else
 
1017
                EmptySelectionMessage();
 
1018
}
 
1019
 
 
1020
 
 
1021
bool DiagramViewer::HasDuplicates() const {
 
1022
        for ( views->first() ; ! views->done() ; views->next() )
 
1023
                if ( views->cur()->HasDuplicates() )
 
1024
                        return True;
 
1025
        return False;
 
1026
}
 
1027
 
 
1028
 
 
1029
void DiagramViewer::RecalcAllParents(bool hierarchicDocument) const {
 
1030
        if ( ! Toolkit::HierarchicEditor(GetMainWindow()->GetTool()) )
 
1031
                hierarchicDocument = False;
 
1032
        for ( views->first() ; ! views->done() ; views->next() )
 
1033
                views->cur()->RecalcAllParents(hierarchicDocument);
 
1034
}