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

« back to all changes in this revision

Viewing changes to src/ui/grafport.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 2001, Universiteit Twente.
 
5
// Author: Frank Dehne (frank@cs.vu.nl), David N. Jansen (dnjansen@cs.utwente.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 "application.h"
 
24
#include <math.h>
 
25
 
 
26
#define square(x) ((x)*(x))
 
27
#define round(x) ((int)((x)+0.5))
 
28
 
 
29
Grafport::Grafport() {
 
30
        zoomValue = 1.0;
 
31
        int f = XFont::HELVETICA;
 
32
        int s = XFont::PLAIN;
 
33
        int p = 12;
 
34
        string foundry = "Adobe";
 
35
        defaultFont = new XFont(&foundry, f, s, p, False);
 
36
        font = defaultFont;
 
37
        backgroundColor = "white";
 
38
        foregroundColor = "black";
 
39
        lineWidth = 1;
 
40
        lineStyle = LineStyle::SOLID;
 
41
        fillStyle = FillStyle::UNFILLED;
 
42
        colors = new List<Color *>;
 
43
}
 
44
 
 
45
Grafport::~Grafport () {
 
46
        delete defaultFont;
 
47
        colors->clear();
 
48
        delete colors;
 
49
}
 
50
 
 
51
void Grafport::InitColors() {
 
52
        List<Color *> *appColors = theApplication->GetColors();
 
53
        for (appColors->first(); !appColors->done(); appColors->next()) {
 
54
                Color *color = new Color(*appColors->cur());
 
55
                color->pixel = 0;
 
56
                color->allocated = False;
 
57
                colors->add(color);
 
58
        }
 
59
}
 
60
 
 
61
unsigned Grafport::CursorPosition(double x, double y,
 
62
        const string *str, double hit_x, double hit_y)
 
63
{
 
64
        int j = 0; // index in string.
 
65
        unsigned n = 1; // number of lines processed.
 
66
        unsigned nLines = str->lines();
 
67
        // the cursor position, closest to hit_x, hit_y.
 
68
        unsigned cursor = 0;
 
69
        int fontHeight = font->GetHeight();
 
70
        double offset = y - (nLines) * fontHeight/2;
 
71
        buf = "";
 
72
        const char *s = str->getstr();
 
73
        // string is non-zero.
 
74
        while (n <= nLines) {
 
75
                char c = s[j];
 
76
                buf.add(c);
 
77
                // end of line ?
 
78
                if (c == '\n' || c == '\r' || c == '\0') {
 
79
                        buf.remove();
 
80
                        double y1 = offset + (n-1) * fontHeight;
 
81
                        double y2 = offset + n * fontHeight;
 
82
                        if (y1 <= hit_y && hit_y <= y2) {
 
83
                                // found right line, look at hit_x;
 
84
                                Point p1 = CursorPosition(x,y,&buf,0);
 
85
                                for (unsigned k = 1; k <= buf.length(); k++) {
 
86
                                        Point p2 = CursorPosition(x,y,&buf,k);
 
87
                                        int mid = (p1.x + p2.x)/2;
 
88
                                        if (hit_x <= mid)
 
89
                                                return min(cursor,
 
90
                                                           str->length());
 
91
                                        else {
 
92
                                                p1 = p2;
 
93
                                                cursor++;
 
94
                                        }
 
95
                                }
 
96
                                return min(cursor, str->length());
 
97
                        }
 
98
                        else
 
99
                                cursor += buf.length()+1;
 
100
                        buf = ""; // another line
 
101
                        n++;
 
102
                }
 
103
                j++;
 
104
        }
 
105
        return min(cursor, str->length());
 
106
}
 
107
 
 
108
Point Grafport::DrawStringsCentered(double x, double y, const string *str,
 
109
                bool ul, int cursor) {
 
110
        int j = 0; // index in string.
 
111
        unsigned n = 1; // number of lines processed.
 
112
        unsigned nLines = str->lines();
 
113
        Point p = Point(static_cast<int>(0.5 + x),
 
114
                                        static_cast<int>(0.5 + y));   // cursor position.
 
115
        int fontHeight = font->GetHeight();
 
116
        double offset = y - (nLines-1) * fontHeight/2;
 
117
        buf = "";
 
118
        const char *s = str->getstr();
 
119
        // string is non-zero.
 
120
        while (n <= nLines) {
 
121
                char c = s[j];
 
122
                buf.add(c);
 
123
                // end of line ?
 
124
                if (c == '\n' || c == '\r' || c == '\0') {
 
125
                        buf.remove();
 
126
                        // draw string in buf
 
127
                        y = offset + (n-1) * fontHeight;
 
128
                        if (ul)
 
129
                                DrawStringCenteredUnderlined(x, y, buf.getstr());
 
130
                        else
 
131
                                DrawStringCentered(x, y, buf.getstr());
 
132
                        // look for cursor position.
 
133
                        if (cursor <= j && cursor >= (int)(j - buf.length()))
 
134
                                p = CursorPosition(x, y, &buf,
 
135
                                                cursor-j+buf.length());
 
136
                        buf = ""; // another line
 
137
                        n++;
 
138
                }
 
139
                j++;
 
140
        }
 
141
        return p;
 
142
}
 
143
 
 
144
Point Grafport::DrawStringsLeft(double topLeftx, double topLefty,
 
145
                const string *str, bool ul, int cursor) {
 
146
        int j = 0; // index in string.
 
147
        unsigned n = 1; // number of lines processed.
 
148
        unsigned nLines = str->lines();
 
149
        topLefty += font->GetAscent();
 
150
        Point p = Point(static_cast<int>(0.5 + topLeftx),
 
151
                                        static_cast<int>(0.5 + topLefty));   // cursor position.
 
152
        int fontHeight = font->GetHeight();
 
153
        buf = "";
 
154
        const char *s = str->getstr();
 
155
        // string is non-zero.
 
156
        while (n <= nLines) {
 
157
                char c = s[j];
 
158
                buf.add(c);
 
159
                // end of line ?
 
160
                if (c == '\n' || c == '\r' || c == '\0') {
 
161
                        buf.remove();
 
162
                        // draw string in buf
 
163
                        if (ul)
 
164
                                DrawStringLeftUnderlined(
 
165
                                        topLeftx, topLefty, buf.getstr());
 
166
                        else
 
167
                                DrawStringLeft(
 
168
                                        topLeftx, topLefty, buf.getstr());
 
169
                        // look for cursor position.
 
170
                        if (cursor <= j && cursor >= (int)(j - buf.length()))
 
171
                                p = CursorPosition(
 
172
                                        topLeftx+font->StringWidth(&buf)/2,
 
173
                                        topLefty-font->GetDescent(), &buf,
 
174
                                        cursor-j+buf.length());
 
175
                        topLefty += fontHeight;
 
176
                        buf = "";       // another line
 
177
                        n++;
 
178
                }
 
179
                j++;
 
180
        }
 
181
        return p;
 
182
}
 
183
 
 
184
Point Grafport::DrawStringsRight(double topRightx, double topRighty,
 
185
                const string *str, bool ul, int cursor) {
 
186
        int j = 0; // index in string.
 
187
        unsigned n = 1; // number of lines processed.
 
188
        unsigned nLines = str->lines();
 
189
        topRighty += font->GetAscent();
 
190
        Point p = Point(static_cast<int>(0.5 + topRightx),
 
191
                                        static_cast<int>(0.5 + topRighty));   // cursor position.
 
192
        int fontHeight = font->GetHeight();
 
193
        buf = "";
 
194
        const char *s = str->getstr();
 
195
        // string is non-zero.
 
196
        while (n <= nLines) {
 
197
                char c = s[j];
 
198
                buf.add(c);
 
199
                // end of line ?
 
200
                if (c == '\n' || c == '\r' || c == '\0') {
 
201
                        buf.remove();
 
202
                        // int x = topRightx - font->StringWidth(&buf);
 
203
                        // draw string in buf
 
204
                        if (ul)
 
205
                                DrawStringRightUnderlined(
 
206
                                        topRightx, topRighty, buf.getstr());
 
207
                        else
 
208
                                DrawStringRight(
 
209
                                        topRightx, topRighty, buf.getstr());
 
210
                        // look for cursor position.
 
211
                        if (cursor <= j && cursor >= (int)(j - buf.length()))
 
212
                                p = CursorPosition(
 
213
                                        topRightx-font->StringWidth(&buf)/2,
 
214
                                        topRighty-font->GetDescent(), &buf,
 
215
                                        cursor-j+buf.length());
 
216
                        topRighty += fontHeight;
 
217
                        buf = "";       // another line
 
218
                        n++;
 
219
                }
 
220
                j++;
 
221
        }
 
222
        return p;
 
223
}
 
224
 
 
225
Point Grafport::CursorPosition(double x, double y, const string *text, int cursor) {
 
226
        string str;
 
227
        for(int i=0; i<cursor; i++)
 
228
                str.add((*text)[i]);
 
229
        int width = font->StringWidth(&str);
 
230
        int base = font->GetHeight()/2 - font->GetDescent();
 
231
        double str_x;
 
232
        if (font->IsScalable())
 
233
                str_x = x - font->StringWidth(text)/2 + width;
 
234
        else
 
235
                str_x = x - ZoomCorrect(font->StringWidth(text)/2 - width);
 
236
        return Point(static_cast<int>(0.5 + str_x),
 
237
                                 static_cast<int>(0.5 + y+base));
 
238
}
 
239
 
 
240
 
 
241
void Grafport::DrawRectangles(const Rectangle *rects, int n){
 
242
        for (int i=0; i<n; i++)
 
243
                DrawRectangle(rects[i].x,rects[i].y,
 
244
                                rects[i].width,rects[i].height);
 
245
}
 
246
 
 
247
 
 
248
void Grafport::FillRectangles(const Rectangle *rects, int n){
 
249
        for (int i=0; i<n; i++)
 
250
                FillRectangle(rects[i].x,rects[i].y,
 
251
                                rects[i].width,rects[i].height);
 
252
}
 
253
 
 
254
 
 
255
Color *Grafport::LookupColor(const string *colorName) {
 
256
        for (colors->first(); !colors->done(); colors->next()) {
 
257
                Color *color = colors->cur();
 
258
                if (color->name %= *colorName)
 
259
                        return color;
 
260
        }
 
261
        return 0;
 
262
}
 
263
 
 
264
Color *Grafport::LookupColor(const char *colorName) {
 
265
        string x = colorName;
 
266
        return LookupColor(&x);
 
267
}
 
268
 
 
269
void Grafport::AddColor(Color *c) {
 
270
        colors->add(new Color(*c));
 
271
}
 
272
 
 
273
void Grafport::AddColor(const string *name, unsigned long pixel) {
 
274
        Color *color = new Color(*name, pixel);
 
275
        colors->add(color);
 
276
}
 
277
 
 
278
void Grafport::AddColor(const char *name, unsigned long pixel) {
 
279
        string x = name;
 
280
        AddColor(&x, pixel);
 
281
}
 
282
 
 
283
 
 
284
void Grafport::RecalcPolygon(const Point *points, int nrPoints, Point *newPoints, int d) {
 
285
        // it is a regular polygon.
 
286
        Point p0 = points[0];
 
287
        Point pN;
 
288
        if (nrPoints % 2 == 0)
 
289
                pN = points[nrPoints/2];
 
290
        else {
 
291
                Point pN1 = points[nrPoints/2];
 
292
                Point pN2 = points[1+nrPoints/2];
 
293
                pN.x = (pN1.x + pN2.x) / 2;
 
294
                pN.y = (pN1.y + pN2.y) / 2;
 
295
        }
 
296
        Point pM;
 
297
        pM.x = (p0.x + pN.x) / 2;
 
298
        pM.y = (p0.y + pN.y) / 2;
 
299
        for (int i = 0; i < nrPoints; i++) {
 
300
                Point p = points[i];
 
301
                if (p.x < pM.x)
 
302
                        p.x += d;
 
303
                else if (p.x > pM.x)
 
304
                        p.x -= d;
 
305
                if (p.y < pM.y)
 
306
                        p.y += d;
 
307
                else if (p.y > pM.y)
 
308
                        p.y -= d;
 
309
                newPoints[i] = p;
 
310
        }
 
311
}
 
312
 
 
313
 
 
314
void Grafport::DrawArc(double x, double y, double w, double h,
 
315
        int arc1, int arc2)
 
316
{
 
317
        if ( GetLineStyle() != LineStyle::DUAL ) {
 
318
                DrawSimpleArc(x, y, w, h, arc1, arc2);
 
319
                return;
 
320
        }
 
321
        double delta = ZoomCorrect(GetLineWidth());
 
322
        double delta2 = 2.0 * delta;
 
323
        DrawSimpleArc(x - delta, y - delta, w + delta2, h + delta2,
 
324
                arc1, arc2);
 
325
        if ( w > delta2 && h > delta2 )
 
326
                DrawSimpleArc(x + delta, y + delta,
 
327
                        w - delta2, h - delta2, arc1, arc2);
 
328
}
 
329
 
 
330
 
 
331
void Grafport::DrawLine(double x1, double y1,
 
332
        double x2, double y2)
 
333
{
 
334
        DPoint points[2];
 
335
        points[0].x = x1;
 
336
        points[0].y = y1;
 
337
        points[1].x = x2;
 
338
        points[1].y = y2;
 
339
        DrawOpenPolygon(points, 2);
 
340
}
 
341
 
 
342
 
 
343
static void RecalcPolygon(const DPoint *points, DPoint *right,
 
344
        DPoint *left, double delta, int n)
 
345
{
 
346
        if ( n < 2 )
 
347
                return;
 
348
        --n;
 
349
        bool closed = points[0] == points[n];
 
350
        double dx1 = points[1].x - points[0].x;
 
351
        double dy1 = points[1].y - points[0].y;
 
352
        double d1 = ! dx1 && ! dy1 ? 0.0
 
353
                : delta / sqrt(square(dx1) + square(dy1));
 
354
        if ( ! closed ) {
 
355
                right[0].x = points[0].x - dy1 * d1;
 
356
                left[0].x = points[0].x + dy1 * d1;
 
357
                right[0].y = points[0].y + dx1 * d1;
 
358
                left[0].y = points[0].y - dx1 * d1;
 
359
        }
 
360
        int i = 1;
 
361
        for ( ;; ) {
 
362
                right[i].x = points[i].x - dy1 * d1;
 
363
                left[i].x = points[i].x + dy1 * d1;
 
364
                right[i].y = points[i].y + dx1 * d1;
 
365
                left[i].y = points[i].y - dx1 * d1;
 
366
                double dx2, dy2;
 
367
                if ( i >= n ) {
 
368
                        if ( ! closed )
 
369
                                break;
 
370
                        dx2 = points[1].x - points[0].x;
 
371
                        dy2 = points[1].y - points[0].y;
 
372
                } else {
 
373
                        dx2 = points[i+1].x - points[i].x;
 
374
                        dy2 = points[i+1].y - points[i].y;
 
375
                }
 
376
                double d2 = ! dx2 && ! dy2 ? 0.0
 
377
                        : delta / sqrt(square(dx2) + square(dy2));
 
378
                //     ( dx1   dx2 )
 
379
                // A = (           )
 
380
                //     ( dy1   dy2 )
 
381
                double det = dx1 * dy2 - dx2 * dy1;
 
382
                if ( det ) {
 
383
                        double b1 = dy2 * d2 - dy1 * d1;
 
384
                        double b2 = dx1 * d1 - dx2 * d2;
 
385
                        double t = (b1 * dy2 - b2 * dx2) / det;
 
386
                        right[i].x -= dx1 * t;
 
387
                        left[i].x += dx1 * t;
 
388
                        right[i].y -= dy1 * t;
 
389
                        left[i].y += dy1 * t;
 
390
                }
 
391
                if ( i >= n ) {
 
392
                        right[0] = right[i];
 
393
                        left[0] = left[i];
 
394
                        break;
 
395
                }
 
396
                dx1 = dx2;
 
397
                dy1 = dy2;
 
398
                d1 = d2;
 
399
                i++;
 
400
        }
 
401
}
 
402
 
 
403
 
 
404
void Grafport::DrawOpenPolygon(const DPoint *points, int n) {
 
405
        if ( n < 2 )
 
406
                return;
 
407
        if ( GetLineStyle() != LineStyle::DUAL) {
 
408
                DrawSimplePolygon(points, n);
 
409
                return;
 
410
        }
 
411
        DPoint *p1 = new DPoint[n], *p2 = new DPoint[n];
 
412
        ::RecalcPolygon(points, p1, p2, ZoomCorrect(GetLineWidth()), n);
 
413
        DrawSimplePolygon(p1, n);
 
414
        DrawSimplePolygon(p2, n);
 
415
        delete[/* n */] p1;
 
416
        delete[/* n */] p2;
 
417
}
 
418
 
 
419
 
 
420
void Grafport::DrawCurve(const DPoint *p)
 
421
{
 
422
        if ( GetLineStyle() != LineStyle::DUAL) {
 
423
                DrawSimpleCurve(p);
 
424
                return;
 
425
        }
 
426
        DPoint p1[4], p2[4];
 
427
        ::RecalcPolygon(p, p1, p2, ZoomCorrect(GetLineWidth()), 4);
 
428
        DrawSimpleCurve(p1);
 
429
        DrawSimpleCurve(p2);
 
430
}
 
431
 
 
432
 
 
433
// This function is incorrect because it assumes that DrawSimpleCurve draws
 
434
// a spline that contains points[0], points[1], points[2] and points[3].
 
435
///* virtual */ void Grafport::DrawSimpleArc(
 
436
//      double x, double y,
 
437
//      double w, double h, int arc1, int arc2)
 
438
//{
 
439
//      w *= 0.5;
 
440
//      h *= 0.5;
 
441
//      x += w;
 
442
//      y += h;
 
443
//      DPoint points[4];
 
444
//      double a1 = arc1 * (PI / 180);
 
445
//      double a2 = arc2 * (PI / 180);
 
446
//      points[0].Set(x + w * cos(a1), y - h * sin(a1));
 
447
//      points[1].Set(x + w * cos((a1 * 2.0 + a2) / 3.0),
 
448
//              y - h * sin((a1 * 2.0 + a2) / 3.0));
 
449
//      points[2].Set(x + w * cos((a1 + a2 * 2.0) / 3.0),
 
450
//              y - h * sin(a1 + a2 * 2.0) / 3.0));
 
451
//      points[3].Set(x + w * cos(a2), y - h * sin(a2));
 
452
//      DrawSimpleCurve(points);
 
453
//}