~ubuntu-branches/ubuntu/intrepid/tcm/intrepid

« back to all changes in this revision

Viewing changes to src/sd/bv/transitionarrow.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 1996, 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 "grafport.h"
 
23
#include "inputfile.h"
 
24
#include "outputfile.h"
 
25
#include <math.h>
 
26
#include <stdlib.h>
 
27
#include "transition.h"
 
28
#include "transitionarrow.h"
 
29
#include "diagramviewer.h"
 
30
 
 
31
const int TransitionArrow::HLINELEN = 20;
 
32
const int TransitionArrow::HLINEXOFFSET = 4;
 
33
const int TransitionArrow::HLINEYOFFSET = 2;
 
34
const int TransitionArrow::HLINEDIST = 10;
 
35
 
 
36
TransitionArrow::TransitionArrow(ShapeView *v, Grafport *g, 
 
37
                GShape *node1, GShape *node2, List<Point *> *aline, bool Curved): 
 
38
                        Line(v, g, node1, node2, aline, Curved) {
 
39
        event = new TextShape(v, g, this);
 
40
        event->SetAlignment(TextAlign::LEFT);
 
41
        event->SetDescription("Event");
 
42
        actions = new List<TextShape *>;
 
43
        separator = RIGHT;
 
44
        CalcPosition();
 
45
        SetEnd2(LineEnd::FILLED_ARROW);
 
46
}
 
47
 
 
48
TransitionArrow::TransitionArrow(ShapeView *v, Grafport *g, GShape *node1, 
 
49
        GShape *node2, bool Curved): Line(v, g, node1, node2, Curved) {
 
50
        event = new TextShape(v, g, this);
 
51
        event->SetAlignment(TextAlign::LEFT);
 
52
        event->SetDescription("Event");
 
53
        actions = new List<TextShape *>;
 
54
        separator = RIGHT;
 
55
        SetEnd2(LineEnd::FILLED_ARROW);
 
56
}
 
57
 
 
58
TransitionArrow::TransitionArrow(const TransitionArrow &aline): Line(aline) {
 
59
        hlineFrom = aline.hlineFrom;
 
60
        hlineTo = aline.hlineTo;
 
61
        anchorPoint = aline.anchorPoint;
 
62
        separator = aline.separator;
 
63
        event = new TextShape(*(TextShape *)(aline.event));
 
64
        event->SetParent(this);
 
65
        actions = new List<TextShape *>;
 
66
        for (aline.actions->first(); !aline.actions->done(); aline.actions->next()) {
 
67
                TextShape *a = aline.actions->cur();
 
68
                TextShape *b = new TextShape (*a);
 
69
                b->SetParent(this);
 
70
                actions->add(b);
 
71
        }
 
72
}
 
73
 
 
74
TransitionArrow::~TransitionArrow() {
 
75
        delete event;
 
76
        actions->clear();
 
77
        delete actions;
 
78
}
 
79
 
 
80
void TransitionArrow::DrawShape() {
 
81
        Line::DrawShape();
 
82
        event->Draw();
 
83
        SetDrawAttributes();
 
84
        GetGrafport()->DrawLine(hlineFrom.x, hlineFrom.y, hlineTo.x, hlineTo.y);
 
85
        for (actions->first(); !actions->done(); actions->next())
 
86
                actions->cur()->Draw();
 
87
}
 
88
 
 
89
void TransitionArrow::UpdateAnchor(const Point *p, const Point *t) {
 
90
        Point pt = anchorPoint;
 
91
        if (IsCurved()) {
 
92
                pt.y += p->y;
 
93
                pt.x += p->x;
 
94
        }
 
95
        else if (separator == LEFT || separator == RIGHT) {
 
96
                // find segment where the anchor point is located.
 
97
                // (void) GetLine(pt.x, pt.y);
 
98
                pt.y += p->y;
 
99
                // shift left <-> RIGHT ?
 
100
                Point dp = *t + *p;
 
101
                if (dp.x < anchorPoint.x)
 
102
                        separator = LEFT;
 
103
                else
 
104
                        separator = RIGHT;
 
105
        }
 
106
        else { 
 
107
                pt.x += p->x;
 
108
                // shift up <-> down ?
 
109
                Point dp = *t + *p;
 
110
                if (dp.y < anchorPoint.y)
 
111
                        separator = UP;
 
112
                else
 
113
                        separator = DOWN;
 
114
        }
 
115
        Undraw();
 
116
        if (IsCurved())
 
117
                anchorPoint = pt;
 
118
        else if (separator == LEFT || separator == RIGHT) {
 
119
                int cx, cy;
 
120
                // make anchorpoint a point on the line.
 
121
                (void) ContainsPtLine(pt.x, pt.y, 
 
122
                        (*GetLine())[GetLineNumber()-1], 
 
123
                        (*GetLine())[GetLineNumber()], cx, cy);
 
124
                anchorPoint = Point(cx, cy);
 
125
        }
 
126
        else
 
127
                anchorPoint = pt;
 
128
        CalcHLinePart();
 
129
        Draw();
 
130
}
 
131
 
 
132
void TransitionArrow::CalcPosition() {
 
133
        Line::CalcPosition();
 
134
        anchorPoint = *GetPosition();
 
135
        CalcSeparator();
 
136
        CalcHLinePart();
 
137
}
 
138
 
 
139
void TransitionArrow::CalcHLinePart() {
 
140
        CalcPositionHLine();
 
141
        CalcPositionEvent();
 
142
        CalcPositionActions();
 
143
}
 
144
 
 
145
void TransitionArrow::CalcSeparator() {
 
146
        double alpha;
 
147
        if (GetWidth() != 0)
 
148
                alpha = atan((double)GetHeight()/(double)GetWidth());
 
149
        else
 
150
                alpha = 2*atan(1);
 
151
        // estimation.
 
152
        // if (fabs(alpha) > 0.5*atan(1)) { 
 
153
        if (fabs(alpha) > atan(1)) { 
 
154
                if (separator == UP || separator == DOWN)
 
155
                        separator = RIGHT;
 
156
        }
 
157
        else {
 
158
                if (separator == LEFT || separator == RIGHT)
 
159
                        separator = UP;
 
160
        }
 
161
}
 
162
 
 
163
 
 
164
void TransitionArrow::CalcPositionHLine() {
 
165
        int d1 = HLineLength();
 
166
        if (separator == RIGHT) { // attach right to line.
 
167
                hlineFrom = anchorPoint;
 
168
                hlineTo = Point(hlineFrom.x + d1, hlineFrom.y);
 
169
        }
 
170
        else if (separator == LEFT) { // attach left to line.
 
171
                hlineTo = anchorPoint;
 
172
                hlineFrom = Point(hlineTo.x - d1, hlineTo.y);
 
173
        }
 
174
        else { // put above/below the line.
 
175
                double alpha = atan((double)GetHeight()/(double)GetWidth());
 
176
 
 
177
                if (separator == UP) {
 
178
                        int d2 = (int)(cos(alpha)*max(HLINEDIST,
 
179
                                 HLINEYOFFSET+actions->count()*GetName()->GetFontHeight()));
 
180
                        d2 += HLINEYOFFSET;
 
181
                        hlineFrom = Point(anchorPoint.x - d1/2, 
 
182
                                anchorPoint.y - d2);
 
183
                        hlineTo = Point(anchorPoint.x + d1/2, 
 
184
                                anchorPoint.y - d2);
 
185
                }
 
186
                else { // separator == DOWN
 
187
                        int textHeight = max(GetName()->GetFontHeight(), 
 
188
                                                event->GetStringHeight());
 
189
                        int d2 = (int)(cos(alpha)*max(HLINEDIST,HLINEYOFFSET+
 
190
                                        textHeight));
 
191
                        d2 += HLINEYOFFSET;
 
192
                        hlineFrom = Point(anchorPoint.x - d1/2, 
 
193
                                anchorPoint.y + d2);
 
194
                        hlineTo = Point(anchorPoint.x + d1/2, 
 
195
                                anchorPoint.y + d2);
 
196
                }
 
197
        }
 
198
        hlineFrom = Point(max(3,hlineFrom.x), max(3,hlineFrom.y)); 
 
199
        hlineTo = Point(max(3,hlineTo.x), max(3,hlineTo.y)); 
 
200
}
 
201
 
 
202
void TransitionArrow::CalcPositionEvent() {
 
203
        Point pt;
 
204
        const string *s = event->GetString();
 
205
        if (*s != "") {
 
206
                pt.x = hlineFrom.x + event->GetStringWidth()/2;
 
207
                pt.y = hlineFrom.y - event->GetStringHeight()/2;
 
208
                pt.y -= 2*HLINEYOFFSET;
 
209
        }
 
210
        else {
 
211
                pt.x = (hlineFrom.x + hlineTo.x)/2;
 
212
                pt.y = hlineFrom.y - event->GetFontHeight()/2;
 
213
        }
 
214
        pt.x += HLINEXOFFSET;
 
215
        event->SetPosition(&pt);
 
216
}
 
217
 
 
218
void TransitionArrow::CalcPositionActions() {
 
219
        Point pt; int w, h;
 
220
        int textHeight = GetName()->GetFontHeight();
 
221
        pt = hlineFrom;
 
222
        pt.y += HLINEYOFFSET + textHeight/2;
 
223
        for (actions->first(); !actions->done(); actions->next()) {
 
224
                w = actions->cur()->GetStringWidth();
 
225
                h = actions->cur()->GetStringHeight();
 
226
                pt.x = hlineFrom.x + w/2 + HLINEXOFFSET;
 
227
                actions->cur()->SetPosition(&pt);
 
228
                pt.y += textHeight;
 
229
        }
 
230
}
 
231
 
 
232
void TransitionArrow::UpdateEvent(const string *c) {
 
233
        if (IsVisible())
 
234
                Undraw();
 
235
        event->SetString(c);
 
236
        CalcHLinePart();
 
237
        if (IsVisible())
 
238
                Draw();
 
239
}
 
240
 
 
241
void TransitionArrow::UpdateAction(const string *s, unsigned n, bool update) {
 
242
        if (IsVisible())
 
243
                Undraw();
 
244
        SetAction(s, n, update);
 
245
        CalcHLinePart();
 
246
        if (IsVisible())
 
247
                Draw();
 
248
}
 
249
 
 
250
void TransitionArrow::SetSelect(bool set) {
 
251
        Line::SetSelect(set);
 
252
}
 
253
 
 
254
bool TransitionArrow::ContainsPt(int x, int y) {
 
255
        if (Line::ContainsPt(x,y))
 
256
                return True;
 
257
        else
 
258
                return HitHLine(x, y);
 
259
}
 
260
 
 
261
bool TransitionArrow::HitHLine(int x, int y) {
 
262
        // point near horizontal line ?
 
263
        int textHeight = GetName()->GetFontHeight();
 
264
        return (x >= hlineFrom.x && x <= hlineTo.x &&
 
265
                y >= hlineFrom.y - textHeight &&
 
266
                y <= hlineFrom.y + textHeight);
 
267
}
 
268
 
 
269
int TransitionArrow::HLineLength() {
 
270
        int max = HLINELEN;
 
271
        int n = event->GetStringWidth()+HLINEXOFFSET;
 
272
        if (n > max)
 
273
                max = n;
 
274
        for (actions->first(); !actions->done(); actions->next()) {
 
275
                n = actions->cur()->GetStringWidth()+HLINEXOFFSET;
 
276
                if (n > max)
 
277
                        max = n;
 
278
        }
 
279
        return max;
 
280
}
 
281
 
 
282
bool TransitionArrow::InTextArea(int x, int y) {
 
283
        if (Line::InTextArea(x,y))
 
284
                return True;
 
285
        else if (event->ContainsPt(x, y))
 
286
                return True;
 
287
        for (actions->first(); !actions->done(); actions->next()) {
 
288
                if (actions->cur()->ContainsPt(x, y))
 
289
                        return True;
 
290
        }
 
291
        return False;
 
292
}
 
293
 
 
294
TextShape *TransitionArrow::HitTextShape(int x, int y) {
 
295
        if (event->ContainsPt(x, y))
 
296
                return event;
 
297
        for (actions->first(); !actions->done(); actions->next()) {
 
298
                 if (actions->cur()->ContainsPt(x, y))
 
299
                        return actions->cur();
 
300
        } 
 
301
        return 0;
 
302
}
 
303
 
 
304
TextShape *TransitionArrow::ChooseTextShape(int x, int y) {
 
305
        // This is the winner of the "clumsiest function award".
 
306
        int textHeight = GetName()->GetFontHeight();
 
307
        // hit event string.
 
308
        if (event->ContainsPt(x, y))
 
309
                return event;
 
310
        // hit action string.
 
311
        if (actions->first()) {
 
312
                // action text shapes can overlap
 
313
                // make sure that you choose the right one.
 
314
                do {
 
315
                        int pt_y = actions->cur()->GetTopMost();
 
316
                        pt_y += textHeight;
 
317
                        if (actions->cur()->ContainsPt(x,y) && y <= pt_y) {
 
318
                                // return the action.
 
319
                                TextShape *t = actions->cur();
 
320
                                return t;
 
321
                        }
 
322
                        // pt_y += textHeight;
 
323
                } while (actions->next());
 
324
                if (actions->last()) {
 
325
                        if (actions->cur()->ContainsPt(x,y))
 
326
                                return actions->cur();
 
327
                }
 
328
        }
 
329
        // hit hline part ?
 
330
        if (HitHLine(x, y)) {
 
331
                if (y <= hlineFrom.y) {
 
332
                        // above line -> return event.
 
333
                        Point pt = *event->GetPosition();
 
334
                        pt.x -= HLINEXOFFSET;
 
335
                        pt.y -= 2*HLINEYOFFSET;
 
336
                        event->UpdatePosition(&pt);
 
337
                        return event;
 
338
                }
 
339
                else {
 
340
                        // if there are actions return the first one.
 
341
                        if (actions->count() > 0) {
 
342
                                // return the first action.
 
343
                                TextShape *t = (*actions)[0];
 
344
                                return t;
 
345
                        }
 
346
                        // create a new action.
 
347
                        else {
 
348
                                TextShape *t = new TextShape(
 
349
                                        GetView(), GetGrafport(), this);
 
350
                                t->SetAlignment(TextAlign::LEFT);
 
351
                                t->SetSequence(0);
 
352
                                t->SetDescription("Action");
 
353
                                t->SetFont(GetName()->GetFont());
 
354
                                actions->add(t);
 
355
                                CalcPositionActions();
 
356
                                // move the action a bit up.
 
357
                                Point pt = *t->GetPosition();
 
358
                                pt.x = (hlineFrom.x + hlineTo.x)/2;
 
359
                                pt.y -= HLINEYOFFSET;
 
360
                                t->SetPosition(&pt);
 
361
                                return t;
 
362
                        }
 
363
                }
 
364
        }
 
365
        // hit some spot on line (but not the hline or a label).
 
366
        // Recalculate hline position.
 
367
        if (GetViewer()->IsEditing() && GetViewer()->IsInlineEdit())
 
368
                return 0;
 
369
        Point *pt1, *pt2;
 
370
        int xx, yy;
 
371
        if (!GetLine()->first())
 
372
                return 0;
 
373
        else
 
374
                pt1 = GetLine()->cur();
 
375
        SetLineNumber(1);
 
376
        while (GetLine()->next()) {
 
377
                pt2 = GetLine()->cur();
 
378
                if (ContainsPtLine(x, y, pt1, pt2, xx, yy))
 
379
                        break; 
 
380
                pt1 = pt2;
 
381
                if (GetLineNumber() < GetLine()->count()-1)
 
382
                        SetLineNumber(GetLineNumber()+1);
 
383
        }
 
384
        UpdatePosition();
 
385
        // hit (empty ?) event string.
 
386
        if (y <= hlineFrom.y) {
 
387
                return event;
 
388
        }
 
389
        else {
 
390
                if (actions->count() > 0) {
 
391
                        // return last action.
 
392
                        TextShape *t = (*actions)[actions->count()-1];
 
393
                        return t;
 
394
                }
 
395
                else {
 
396
                        // create new action.
 
397
                        TextShape *t = new TextShape(
 
398
                                GetView(), GetGrafport(), this);
 
399
                        t->SetDescription("Action");
 
400
                        t->SetAlignment(TextAlign::LEFT);
 
401
                        t->SetSequence(0);
 
402
                        t->SetFont(GetName()->GetFont());
 
403
                        actions->add(t);
 
404
                        CalcPositionActions();
 
405
                        Point pt = *t->GetPosition();
 
406
                        pt.x = (hlineFrom.x + hlineTo.x)/2;
 
407
                        pt.y -= HLINEYOFFSET;
 
408
                        t->SetPosition(&pt);
 
409
                        return t;
 
410
                }
 
411
        }
 
412
}
 
413
 
 
414
bool TransitionArrow::HasTextShape(TextShape *t) const {
 
415
        if (Line::HasTextShape(t))
 
416
                return True;
 
417
        else if (event == t)
 
418
                return True;
 
419
        for (actions->first(); !actions->done(); actions->next())
 
420
                if (actions->cur() == t)
 
421
                        return True;
 
422
        return False;
 
423
}
 
424
 
 
425
 
 
426
int TransitionArrow::GetLeftMost() const {
 
427
        int a = Line::GetLeftMost();
 
428
        int b = event->GetLeftMost();
 
429
        for (actions->first(); !actions->done(); actions->next()) {
 
430
                int c = actions->cur()->GetLeftMost();
 
431
                if (c < b)
 
432
                        b = c;
 
433
        }
 
434
        return min(a, b);
 
435
}
 
436
 
 
437
int TransitionArrow::GetTopMost() const {
 
438
        int a = Line::GetTopMost();
 
439
        int b = event->GetTopMost();
 
440
        for (actions->first(); !actions->done(); actions->next()) {
 
441
                int c = actions->cur()->GetTopMost();
 
442
                if (c < b)
 
443
                        b = c;
 
444
        }
 
445
        return min(a, b);
 
446
}
 
447
 
 
448
int TransitionArrow::GetRightMost() const {
 
449
        int a = Line::GetRightMost();
 
450
        int b = event->GetRightMost();
 
451
        for (actions->first(); !actions->done(); actions->next()) {
 
452
                int c = actions->cur()->GetRightMost();
 
453
                if (c > b)
 
454
                        b = c;
 
455
        } 
 
456
        return max(a, b);
 
457
}
 
458
 
 
459
int TransitionArrow::GetBottomMost() const {
 
460
        int a = Line::GetBottomMost();
 
461
        int b = event->GetBottomMost();
 
462
        for (actions->first(); !actions->done(); actions->next()) {
 
463
                int c = actions->cur()->GetBottomMost();
 
464
                if (c > b)
 
465
                        b = c;
 
466
        } 
 
467
        return max(a, b);
 
468
}
 
469
 
 
470
const char *TransitionArrow::Sep2String(SepType sep) {
 
471
        if (sep == LEFT)
 
472
                return "Left";
 
473
        else if (sep == RIGHT)
 
474
                return "Right";
 
475
        else if (sep == UP)
 
476
                return "Up";
 
477
        else // (sep == DOWN)
 
478
                return "Down";
 
479
}
 
480
 
 
481
TransitionArrow::SepType TransitionArrow::String2Sep(const string *s) {
 
482
        if (*s %= "Left")
 
483
                return LEFT;
 
484
        else if (*s %= "Right")
 
485
                return RIGHT;
 
486
        else if (*s %= "Up")
 
487
                return UP;
 
488
        else // (*s %= "Down")
 
489
                return DOWN;
 
490
}
 
491
 
 
492
void TransitionArrow::WriteMembers(OutputFile *ofile) {
 
493
        Line::WriteMembers(ofile);
 
494
        (*ofile) << "\t{ AnchorPoint " << anchorPoint << " }\n";
 
495
        (*ofile) << "\t{ Separator " << Sep2String(separator) << " }\n";
 
496
        (*ofile) << "\t{ LineNumber " << GetLineNumber() << " }\n";
 
497
}
 
498
 
 
499
bool TransitionArrow::ReadMembers(InputFile *ifile, double format) {
 
500
        string val1, val2;
 
501
        if (!Line::ReadMembers(ifile, format))
 
502
                return False;
 
503
        if (format <= 1.10) {
 
504
                if (!ifile->ReadAttribute2("HLineFrom", &val1, &val2))
 
505
                        return False;
 
506
                hlineFrom = Point(val1.toint(), val2.toint());
 
507
                if (!ifile->ReadAttribute2("HLineTo", &val1, &val2))
 
508
                        return False;
 
509
                hlineTo = Point(val1.toint(), val2.toint());
 
510
        }
 
511
        else { // (format >= 1.11)
 
512
                if (!ifile->ReadAttribute2("AnchorPoint", &val1, &val2))
 
513
                        return False;
 
514
                anchorPoint = Point(val1.toint(), val2.toint());
 
515
                if (!ifile->ReadAttribute("Separator", &val1))
 
516
                        return False;
 
517
                separator = String2Sep(&val1);
 
518
                if (!ifile->ReadAttribute("LineNumber", &val1))
 
519
                        return False;
 
520
                SetLineNumber(val1.toint());
 
521
        }
 
522
        return True;
 
523
}
 
524
 
 
525
bool TransitionArrow::SetAssocSubject(AssocList *al) {
 
526
        if (!Line::SetAssocSubject(al))
 
527
                return False;
 
528
        if (check(GetSubject() && 
 
529
                  GetSubject()->GetClassType() == Code::TRANSITION))
 
530
                return True;
 
531
        SetSubject(0);
 
532
        return False;
 
533
}
 
534
 
 
535
void TransitionArrow::SetTextShape() {
 
536
        int n = GetLineNumber(); // line number has to stay unaltered.
 
537
        Line::SetTextShape();
 
538
        SetLineNumber(max(1, min(n, GetLine()->count()-1)));
 
539
        if (check(GetSubject() && GetSubject()->GetClassType() == Code::TRANSITION))
 
540
                event->SetString(((Transition *)GetSubject())->GetEvent());
 
541
        event->SetParent(this);
 
542
        actions->clear();
 
543
        if (!check(GetSubject()))
 
544
                return;
 
545
        unsigned numItems = ((Transition *)GetSubject())->NrActions();
 
546
        for (unsigned i=0; i<numItems; i++) {
 
547
                TextShape *t = new TextShape(GetView(), GetGrafport(), this);
 
548
                t->SetDescription("Action");
 
549
                t->SetFont(GetName()->GetFont());
 
550
                t->SetAlignment(TextAlign::LEFT);
 
551
                t->SetSequence(i);
 
552
                t->SetString(((Transition *)GetSubject())->GetAction(i));
 
553
                t->SetParent(this);
 
554
                actions->add(t);
 
555
        }
 
556
        CalcHLinePart();
 
557
}
 
558
 
 
559
void TransitionArrow::SetGrafport(Grafport *g) {
 
560
        Line::SetGrafport(g);
 
561
        for (actions->first(); !actions->done(); actions->next()) 
 
562
                actions->cur()->SetGrafport(g);
 
563
        event->SetGrafport(g);
 
564
}
 
565
 
 
566
void TransitionArrow::SetView(ShapeView *v) {
 
567
        Line::SetView(v);
 
568
        for (actions->first(); !actions->done(); actions->next()) 
 
569
                actions->cur()->SetView(v);
 
570
        event->SetView(v);
 
571
}
 
572
 
 
573
void TransitionArrow::SetFont(XFont *ft) {
 
574
        Line::SetFont(ft);
 
575
        for (actions->first(); !actions->done(); actions->next())
 
576
                actions->cur()->SetFont(ft);
 
577
        event->SetFont(ft);
 
578
        CalcHLinePart();
 
579
}
 
580
 
 
581
void TransitionArrow::SetTextColor(const string *c) {
 
582
        Line::SetTextColor(c);
 
583
        for (actions->first(); !actions->done(); actions->next())
 
584
                actions->cur()->SetColor(c);
 
585
        event->SetColor(c);
 
586
}
 
587
 
 
588
void TransitionArrow::SetAction(const string *s, unsigned n, bool update) {
 
589
        if (update) {
 
590
                if (n > actions->count())
 
591
                        error("%s, line %d: impl error: "
 
592
                          "illegal action nr %d\n", __FILE__, __LINE__, n);
 
593
                else if (n == actions->count()) {
 
594
                        // insert new action.
 
595
                        TextShape *t = new TextShape(GetView(), GetGrafport(), this);
 
596
                        t->SetDescription("Action");
 
597
                        t->SetAlignment(TextAlign::LEFT);
 
598
                        t->SetSequence(n);
 
599
                        t->SetFont(GetName()->GetFont());
 
600
                        actions->add(t);
 
601
                }
 
602
                if (*s != "")
 
603
                        // update existing action
 
604
                        (*actions)[n]->SetString(s);
 
605
                else {
 
606
                        // delete existing action
 
607
                        unsigned i = actions->count() -1;
 
608
                        for (unsigned j = n; j < i; j++) {
 
609
                                const string *nm = (*actions)[j+1]->GetString();
 
610
                                (*actions)[j]->SetString(nm);
 
611
                        }
 
612
                        TextShape *x = (*actions)[i];
 
613
                        actions->removei(i);
 
614
                        delete x;
 
615
                }
 
616
        }
 
617
        else {
 
618
                if (n > actions->count())
 
619
                        error("%s, line %d: impl error: "
 
620
                          "illegal action nr %d\n", __FILE__, __LINE__, n);
 
621
                else if (*s != "") {
 
622
                        // insert new action.
 
623
                        TextShape *t = new TextShape(GetView(), GetGrafport(), this);
 
624
                        t->SetDescription("Action");
 
625
                        t->SetAlignment(TextAlign::LEFT);
 
626
                        t->SetSequence(n);
 
627
                        t->SetString(s);
 
628
                        t->SetFont(GetName()->GetFont());
 
629
                        actions->insert(t, n);
 
630
                        for (unsigned i=n+1; i<actions->count(); i++)
 
631
                                (*actions)[i]->SetSequence(i);
 
632
                }
 
633
                // ignore empty strings;
 
634
        }
 
635
}
 
636
 
 
637
bool TransitionArrow::HasString(const string *s, bool sens, bool sub) const {
 
638
        if (*s != "" && event->HasString(s, sens, sub))
 
639
                return True;
 
640
        for (actions->first(); !actions->done(); actions->next()) {
 
641
                if (actions->cur()->HasString(s, sens, sub))
 
642
                        return True;
 
643
        }
 
644
        return False;
 
645
}
 
646
 
 
647
bool TransitionArrow::HasString(const string *s, bool sens, bool sub, 
 
648
                        List<TextShape *> *list) {
 
649
        if (*s == "")
 
650
                return 0;
 
651
        bool b = event->HasString(s, sens, sub, list);
 
652
        List<TextShape *> actions2 (*actions);
 
653
        for (actions2.first(); !actions2.done(); actions2.next())
 
654
                b += actions2.cur()->HasString(s, sens, sub, list);
 
655
        return b;
 
656
}
 
657
 
 
658
void TransitionArrow::MoveRaw(const Point *delta) {
 
659
        Line::MoveRaw(delta);
 
660
        for (actions->first(); !actions->done(); actions->next())
 
661
                actions->cur()->Move(delta);
 
662
        event->Move(delta);
 
663
        anchorPoint = anchorPoint+*delta;
 
664
        CalcPositionHLine();
 
665
}