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

« back to all changes in this revision

Viewing changes to src/tb/cellrow.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 "cellrow.h"
 
23
#include "cell.h"
 
24
#include "rowcolumnlabel.h"
 
25
#include "linepiece.h"
 
26
#include "rectangle.h"
 
27
#include "inputfile.h"
 
28
#include "outputfile.h"
 
29
#include <stdlib.h>
 
30
 
 
31
CellRow::CellRow(TableViewer *v, unsigned n, int h): CellVector(v,n) {
 
32
        height = h;
 
33
        SetAlignment(v->GetDefaultRowAlignment());
 
34
        CalcLabelPositions();
 
35
}
 
36
 
 
37
void CellRow::CalcLabelPositions() {
 
38
        // distance between row label and the cells.
 
39
        const int LABEL_DIST = 4;
 
40
        RowColumnLabel *l1 = GetLabel1();
 
41
        RowColumnLabel *l2 = GetLabel2();
 
42
        if (l1 && l2) {
 
43
                Point pt;
 
44
                if (cells->count() == 0)
 
45
                        pt = GetViewer()->GetRowTopLeft(GetNumber());
 
46
                else
 
47
                        pt = *(*cells)[0]->GetTopLeft();
 
48
                pt.y += height/2;
 
49
                pt.x -= (l1->GetWidth()/2 + LABEL_DIST);
 
50
                if (GetViewer()->IsShowRowColumnLabels())
 
51
                        l1->UpdatePosition(&pt);
 
52
                else
 
53
                        l1->SetPosition(&pt);
 
54
                pt.x += GetViewer()->GetWidth() + 
 
55
                        l1->GetWidth() + 2*LABEL_DIST;
 
56
                if (GetViewer()->IsShowRowColumnLabels())
 
57
                        l2->UpdatePosition(&pt);
 
58
                else
 
59
                        l2->SetPosition(&pt);
 
60
        }
 
61
}
 
62
 
 
63
void CellRow::UpdateWidth(unsigned colnr) {
 
64
        Point p1, p2, p3;
 
65
        Cell *cell;
 
66
        LinePiece *line;
 
67
        int width;
 
68
        if (colnr == 0 && cells->count() > 0) { // shift first line.
 
69
                cell = (*cells)[0];
 
70
                line = (*lines)[0];
 
71
                p1 = *cell->GetTopLeft();
 
72
                p2.x = p1.x;
 
73
                p2.y = p1.y + height;
 
74
                line->UpdatePoints(&p1, &p2);
 
75
                CalcLabelPositions();
 
76
        }
 
77
        for (unsigned i=colnr; i<cells->count(); i++) {
 
78
                cell = (*cells)[i];
 
79
                line = (*lines)[i+1];
 
80
                width = cell->GetWidth();
 
81
                p1 = *cell->GetTopLeft();
 
82
                if (line) {
 
83
                        p2 = *line->GetBegin();
 
84
                        p2.x = p1.x + width; 
 
85
                        p3 = *line->GetEnd();
 
86
                        p3.x = p1.x + width; 
 
87
                        line->UpdatePoints(&p2, &p3);
 
88
                }
 
89
        }
 
90
}
 
91
 
 
92
void CellRow::UpdatePosition(int delta) {
 
93
        if (delta == 0)
 
94
                return;
 
95
        for (cells->first(); !cells->done(); cells->next()) {
 
96
                Cell *cell = cells->cur();
 
97
                Point pt = *cell->GetPosition();
 
98
                pt.y += delta;
 
99
                cell->UpdatePosition(&pt);
 
100
        }
 
101
        for (lines->first(); !lines->done(); lines->next()) {
 
102
                LinePiece *line = lines->cur();
 
103
                Point pt1 = *line->GetBegin();
 
104
                if (pt1.y + delta >= 0) {
 
105
                        pt1.y += delta;
 
106
                        Point pt2 = *line->GetEnd();
 
107
                        pt2.y += delta;
 
108
                        line->UpdatePoints(&pt1, &pt2);
 
109
                }
 
110
        }
 
111
        CalcLabelPositions();
 
112
}
 
113
 
 
114
void CellRow::UpdateHeight(int h) {
 
115
        if (h == height)
 
116
                return;
 
117
        for (lines->first(); !lines->done(); lines->next()) {
 
118
                LinePiece *line = lines->cur();
 
119
                Point pt = *line->GetEnd();
 
120
                pt.y = pt.y - height + h;
 
121
                line->UpdateEnd(&pt);
 
122
        } 
 
123
        height = h;
 
124
        for (cells->first(); !cells->done(); cells->next()) {
 
125
                Cell *cell = cells->cur();
 
126
                int wd = cell->GetWidth();
 
127
                Point pt = *cell->GetTopLeft();
 
128
                pt.y = pt.y + height/2;
 
129
                pt.x = pt.x + wd/2;
 
130
                cell->Undraw();
 
131
                cell->SetSize(wd, height);
 
132
                cell->SetPosition(&pt);
 
133
                cell->Draw();
 
134
        }
 
135
        CalcLabelPositions();
 
136
}
 
137
 
 
138
Cell *CellRow::HitCell(int x, int y) {
 
139
        if (!cells->first())
 
140
                return 0;
 
141
        Cell *cell = cells->cur();
 
142
        Point pt = *(cell->GetTopLeft());
 
143
        // look for this row.
 
144
        if (y > pt.y && y < pt.y + height) {
 
145
                // ok, look for right column.
 
146
                do {
 
147
                        cell = cells->cur();
 
148
                        int wd = cell->GetWidth();
 
149
                        pt = *(cell->GetTopLeft());
 
150
                        if (x > pt.x && x < pt.x + wd)
 
151
                                return cell;
 
152
                } while (cells->next());
 
153
        }
 
154
        return 0; // not in this row.
 
155
}
 
156
 
 
157
LinePiece *CellRow::HitLinePiece(int x, int y) {
 
158
        if (!lines->first())
 
159
                return 0;
 
160
        LinePiece *line = lines->cur();
 
161
        Point pt = *(line->GetBegin());
 
162
        // look for this row.
 
163
        if (y > pt.y && y < pt.y + height) {
 
164
                do {
 
165
                        line = lines->cur();
 
166
                        pt = *line->GetBegin();
 
167
                        if (x > pt.x-3 && x < pt.x+3)
 
168
                                return line;
 
169
                } while (lines->next());
 
170
        }
 
171
        return 0; // not in this row.
 
172
}
 
173
 
 
174
void CellRow::AddCell(Cell *c, bool redraw) {
 
175
        LineStyle::Type lineStyle = GetViewer()->GetDefaultLineStyle();
 
176
        int lineWidth = GetViewer()->GetDefaultLineWidth();
 
177
        Point from, to;
 
178
        int w = c->GetWidth();
 
179
        int h = c->GetHeight();
 
180
        Point pos = *(c->GetTopLeft());
 
181
        if (!cells->first()) {
 
182
                // create first line.
 
183
                from.x = pos.x;
 
184
                from.y = pos.y;
 
185
                to.x = pos.x;
 
186
                to.y = pos.y + h;
 
187
                LinePiece *l = new LinePiece(GetGrafport(), &from, &to, 
 
188
                                lineStyle, lineWidth);
 
189
                lines->add(l);
 
190
                if (redraw)
 
191
                        l->Draw();
 
192
        }
 
193
        cells->add(c);
 
194
        from.x = pos.x + w;
 
195
        from.y = pos.y;
 
196
        to.x = pos.x + w;
 
197
        to.y = pos.y + h;
 
198
        LinePiece *l2 = new LinePiece(GetGrafport(), &from, &to,
 
199
                                lineStyle, lineWidth);
 
200
        lines->add(l2);
 
201
        if (redraw)
 
202
                l2->Draw();
 
203
}
 
204
 
 
205
void CellRow::DeleteCell(Cell *c, bool redraw) {
 
206
        int pos = cells->find(c);
 
207
        if (!check(pos != -1))
 
208
                return;
 
209
        if (pos == 0) {
 
210
                // delete first cell.
 
211
                LinePiece *line = (*lines)[0];
 
212
                if (redraw)
 
213
                        line->Undraw();
 
214
                lines->removei(0);
 
215
                delete line;
 
216
                if (cells->count() == 1) {  // delete last cell
 
217
                        line = (*lines)[0];
 
218
                        if (redraw)
 
219
                                line->Undraw();
 
220
                        lines->removei(0);
 
221
                        if (redraw)
 
222
                                UndrawLabels();
 
223
                        delete line;
 
224
                }
 
225
        }
 
226
        else {
 
227
                LinePiece *line = (*lines)[pos+1];
 
228
                if (redraw)
 
229
                        line->Undraw();
 
230
                lines->removei(pos+1);
 
231
                delete line;
 
232
        }
 
233
        cells->removei(pos);
 
234
        // move right cells of row left.
 
235
        UpdateWidth(pos);
 
236
}
 
237
 
 
238
void CellRow::InsertCell(Cell *c, unsigned pos, bool redraw) {
 
239
        if (!check(pos <= cells->count()))
 
240
                return;
 
241
        if (pos == cells->count())
 
242
                AddCell(c);
 
243
        // insert cell.
 
244
        cells->insert(c, pos);
 
245
        // create new line piece right to the cell.
 
246
        LineStyle::Type lineStyle = GetViewer()->GetDefaultLineStyle();
 
247
        unsigned lineWidth = GetViewer()->GetDefaultLineWidth();
 
248
        Point pt1 = *c->GetTopLeft();
 
249
        pt1.x += c->GetWidth();
 
250
        Point pt2 = pt1;
 
251
        pt2.y += c->GetHeight();
 
252
        LinePiece *line = new LinePiece(GetGrafport(), &pt1, &pt2, 
 
253
                lineStyle, lineWidth);
 
254
        lines->insert(line, pos+1);
 
255
        if (redraw)
 
256
                line->Draw();
 
257
        // move line pieces of row down.
 
258
        UpdateWidth(pos);
 
259
}
 
260
 
 
261
int CellRow::GetMinimalHeight() {
 
262
        int vh = 0;
 
263
        for (cells->first(); !cells->done(); cells->next()) {
 
264
                int th = cells->cur()->GetTextHeight() + 
 
265
                         2*GetViewer()->GetMarginHeight();
 
266
                if (vh < th)
 
267
                        vh = th;
 
268
        } 
 
269
        return vh;
 
270
}
 
271
 
 
272
bool CellRow::ContainsPt(int x, int y) const {
 
273
        if (HitLabel(x, y))
 
274
                return True;
 
275
        if (cells->count() ==0)
 
276
                return False;
 
277
        Point pt = *(*cells)[0]->GetTopLeft();
 
278
        pt.x = max(0, pt.x - SimpleLabel::MIN_TEXT_WIDTH);
 
279
        int width = GetViewer()->GetWidth();
 
280
        Rectangle rect(pt.x, pt.y, width, height);
 
281
        return rect.Inside(x,y);
 
282
}
 
283
 
 
284
void CellRow::UpdateTextPositions() {
 
285
        List<Cell *> cells2 = *cells;
 
286
        for (cells2.first(); !cells2.done(); cells2.next()) {
 
287
                Cell *cell = cells2.cur();
 
288
                cell->UpdateTextPosition();
 
289
                if (GetViewer()->IsAutoResize())
 
290
                        GetViewer()->RecomputeSizeCell(cell);
 
291
        }
 
292
}
 
293
 
 
294
void CellRow::SetTextSizes() {
 
295
        List<Cell *> cells2 = *cells;
 
296
        for (cells2.first(); !cells2.done(); cells2.next()) {
 
297
                Cell *cell = cells2.cur();
 
298
                cell->SetTextSize();
 
299
                if (GetViewer()->IsAutoResize())
 
300
                        GetViewer()->RecomputeSizeCell(cell);
 
301
        }
 
302
}
 
303
 
 
304
void CellRow::Write(OutputFile *ofile) {
 
305
        (*ofile) << "Row " << GetNumber() << " {\n";
 
306
        (*ofile) << "\t{ Height " << height << " }\n";
 
307
        string t;
 
308
        TextAlign::Type2String(GetAlignment(), &t);
 
309
        (*ofile) << "\t{ Alignment " << t << " }\n";
 
310
        (*ofile) << "\t{ NumberOfCells " << cells->count() << " }\n";
 
311
        if (cells->first() && lines->first()) { 
 
312
                int i = 0;
 
313
                do {
 
314
                        (*ofile) << "\t# cell " << GetNumber() << "," << i << '\n';
 
315
                        lines->cur()->Write(ofile);
 
316
                        cells->cur()->Write(ofile);
 
317
                        i++;
 
318
                }
 
319
                while (cells->next() && lines->next());
 
320
                if (lines->last())
 
321
                        lines->cur()->Write(ofile);
 
322
        }
 
323
        (*ofile) << "}\n\n";
 
324
}
 
325
 
 
326
void CellRow::WritePartial(OutputFile *ofile, int n, List<int> *columnNumbers) {
 
327
        (*ofile) << "Row " << n << " {\n";
 
328
        (*ofile) << "\t{ Height " << height << " }\n";
 
329
        string t;
 
330
        TextAlign::Type2String(GetAlignment(), &t);
 
331
        (*ofile) << "\t{ Alignment " << t << " }\n";
 
332
        (*ofile) << "\t{ NumberOfCells " << columnNumbers->count() << " }\n";
 
333
        for (columnNumbers->first(); !columnNumbers->done(); 
 
334
                        columnNumbers->next()) {
 
335
                int i = columnNumbers->cur();
 
336
                (*lines)[i]->Write(ofile);
 
337
                (*cells)[i]->Write(ofile);
 
338
        }
 
339
        if (columnNumbers->last())
 
340
                (*lines)[columnNumbers->cur()+1]->Write(ofile);
 
341
        (*ofile) << "}\n\n";
 
342
}
 
343
 
 
344
bool CellRow::Read(InputFile *ifile, unsigned fromColumn, double format) {
 
345
        // read Row
 
346
        if (!ifile->LookupWord("Row"))
 
347
                return False;
 
348
        // read row number.
 
349
        string val;
 
350
        if (!ifile->ReadWord(&val))
 
351
                return False;
 
352
        // read {
 
353
        if (!ifile->LookupChar('{'))
 
354
                return False;
 
355
        // read and update row height (depending on whether the whole 
 
356
        // row is read in or just a part).
 
357
        if (!ifile->ReadAttribute("Height", &val))
 
358
                return False;
 
359
        if (val.toint() != height) {
 
360
                int ht = val.toint();
 
361
                if (fromColumn == 0 || ht > height)
 
362
                        GetViewer()->ResizeRow(this, ht);
 
363
        }       
 
364
        // read and update row alignment (if the whole row is read in).
 
365
        if (!ifile->ReadAttribute("Alignment", &val))
 
366
                return False;
 
367
        if (fromColumn == 0) {
 
368
                if (format <= 1.08)
 
369
                        SetAlignment((TextAlign::Type) val.toint());
 
370
                else
 
371
                        SetAlignment(TextAlign::String2Type(&val));
 
372
        }
 
373
        // read number of cells.
 
374
        if (!ifile->ReadAttribute("NumberOfCells", &val))
 
375
                return False;
 
376
        // read and update cell texts and line types.
 
377
        int n = val.toint(); 
 
378
        for (unsigned i=fromColumn;i<fromColumn+n; i++) {
 
379
                (*lines)[i]->Read(ifile, format);
 
380
                (*cells)[i]->Read(ifile, format);
 
381
        }
 
382
        if (n > 0)
 
383
                (*lines)[fromColumn+n]->Read(ifile, format);
 
384
        // read }
 
385
        if (!ifile->LookupChar('}'))
 
386
                return False;
 
387
        return True;
 
388
}