]> git.lyx.org Git - features.git/blob - src/mathed/math_grid.C
LyX Drinkers United: patch 2
[features.git] / src / mathed / math_grid.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation
5 #endif
6
7 #include "math_grid.h"
8 #include "support/LOstream.h"
9 #include "debug.h"
10 #include "Painter.h"
11
12
13
14 namespace {
15
16 ///
17 int const MATH_COLSEP = 10;
18 ///
19 int const MATH_ROWSEP = 10;
20 ///
21 int const MATH_BORDER = 2;
22
23 }
24
25
26 using namespace std;
27
28
29 MathGridInset::RowInfo::RowInfo()
30         : upperline_(false), lowerline_(false)
31 {}
32
33
34 MathGridInset::ColInfo::ColInfo()
35         : h_align_('c'), leftline_(false), rightline_(false)
36 {}
37
38
39 MathGridInset::MathGridInset(int m, int n, string const & nm, MathInsetTypes ot)
40         : MathInset(nm, ot, m * n), rowinfo_(n), colinfo_(m), v_align_('c')
41 {
42         if (m <= 0)
43                 lyxerr << "positve number of columns expected\n";
44         if (n <= 0)
45                 lyxerr << "positve number of rows expected\n";
46 }
47
48
49 int MathGridInset::index(int row, int col) const
50 {
51         return col + ncols() * row;
52 }
53
54
55 void MathGridInset::halign(string const & hh)
56 {
57         int n = hh.size();
58         if (n > ncols())
59                 n = ncols();
60         for (int i = 0; i < n; ++i)
61                 colinfo_[i].h_align_ = hh[i];
62 }
63
64 void MathGridInset::halign(char h, int col)
65 {
66         colinfo_[col].h_align_ = h;
67 }
68
69 char MathGridInset::halign(int col) const
70 {
71         return colinfo_[col].h_align_;
72 }
73
74 void MathGridInset::valign(char c)
75 {
76         v_align_ = c;
77 }
78
79 char MathGridInset::valign() const
80 {
81         return v_align_;
82 }
83
84 void MathGridInset::Metrics(MathStyles st)
85 {
86         // let the cells adjust themselves
87         MathInset::Metrics(st);
88         size_ = st;
89
90         // adjust vertical structure
91         for (int row = 0; row < nrows(); ++row) {
92                 int asc  = 0;
93                 int desc = 0;
94                 for (int col = 0; col < ncols(); ++col) {
95                         MathXArray const & c = xcell(index(row, col));
96                         asc  = max(asc,  c.ascent());
97                         desc = max(desc, c.descent());
98                 }
99                 rowinfo_[row].ascent_  = asc;
100                 rowinfo_[row].descent_ = desc;
101
102                 if (row) 
103                         rowinfo_[row].offset_ = 
104                                 rowinfo_[row - 1].offset_ +
105                                 rowinfo_[row - 1].descent_ +
106                                 MATH_ROWSEP +
107                                 rowinfo_[row].ascent_;
108                 else 
109                         rowinfo_[row].offset_ = 0;
110         }
111
112         // adjust vertical offset
113         int h = 0;
114         switch (v_align_) {
115         case 't':
116                 h = 0;
117                 break;
118         case 'b':
119                 h = rowinfo_.back().offset_;
120                 break;
121         default:
122                 h = rowinfo_.back().offset_ / 2;
123         }
124
125         for (int row = 0; row < nrows(); ++row) {
126                 rowinfo_[row].offset_ -= h;
127                 rowinfo_[row].offset_ += MATH_BORDER;
128         }
129         
130         // adjust horizontal structure
131         for (int col = 0; col < ncols(); ++col) {
132                 int wid  = 0;
133                 for (int row = 0; row < nrows(); ++row) 
134                         wid = max(wid, xcell(index(row, col)).width());
135                 colinfo_[col].width_  = wid;
136                 colinfo_[col].offset_ = colinfo_[col].width_;
137
138                 if (col) 
139                         colinfo_[col].offset_ =
140                                 colinfo_[col - 1].offset_ + colinfo_[col - 1].width_ + MATH_COLSEP;
141                 else
142                         colinfo_[col].offset_ = 0;
143
144                 colinfo_[col].offset_ += MATH_BORDER;
145         }
146
147         width_   =   colinfo_.back().offset_  + colinfo_.back().width_;
148         ascent_  = - rowinfo_.front().offset_ + rowinfo_.front().ascent_;
149         descent_ =   rowinfo_.back().offset_  + rowinfo_.back().descent_;
150         
151 /*      
152         // Increase ws_[i] for 'R' columns (except the first one)
153         for (int i = 1; i < nc_; ++i)
154                 if (h_align_[i] == 'R')
155                         ws_[i] += 10 * df_width;
156         // Increase ws_[i] for 'C' column
157         if (h_align_[0] == 'C')
158                 if (ws_[0] < 7 * workwidth / 8)
159                         ws_[0] = 7 * workwidth / 8;
160         
161         // Adjust local tabs
162         width = MATH_COLSEP;
163         for (cxrow = row_.begin(); cxrow; ++cxrow) {   
164                 int rg = MATH_COLSEP;
165                 int lf = 0;
166                 for (int i = 0; i < nc_; ++i) {
167                         bool isvoid = false;
168                         if (cxrow->getTab(i) <= 0) {
169                                 cxrow->setTab(i, df_width);
170                                 isvoid = true;
171                         }
172                         switch (h_align_[i]) {
173                         case 'l':
174                                 lf = 0;
175                                 break;
176                         case 'c':
177                                 lf = (ws_[i] - cxrow->getTab(i))/2; 
178                                 break;
179                         case 'r':
180                         case 'R':
181                                 lf = ws_[i] - cxrow->getTab(i);
182                                 break;
183                         case 'C':
184                                 if (cxrow == row_.begin())
185                                         lf = 0;
186                                 else if (cxrow.is_last())
187                                         lf = ws_[i] - cxrow->getTab(i);
188                                 else
189                                         lf = (ws_[i] - cxrow->getTab(i))/2; 
190                                 break;
191                         }
192                         int const ww = (isvoid) ? lf : lf + cxrow->getTab(i);
193                         cxrow->setTab(i, lf + rg);
194                         rg = ws_[i] - ww + MATH_COLSEP;
195                         if (cxrow == row_.begin())
196                                 width += ws_[i] + MATH_COLSEP;
197                 }
198                 cxrow->setBaseline(cxrow->getBaseline() - ascent);
199         }
200 */
201 }
202
203 void MathGridInset::draw(Painter & pain, int x, int y)
204 {
205         xo(x);
206         yo(y);
207         for (int row = 0; row < nrows(); ++row) {
208                 int yy = y + rowinfo_[row].offset_;
209                 for (int col = 0; col < ncols(); ++col) {
210                         int xx = x + colinfo_[col].offset_;
211                         char align = colinfo_[col].h_align_;
212                         if (align == 'r' || align == 'R')
213                                 xx += colinfo_[col].width_ - xcell(index(row, col)).width(); 
214                         if (align == 'c' || align == 'C')
215                                 xx += (colinfo_[col].width_ - xcell(index(row, col)).width()) / 2; 
216                         xcell(index(row, col)).draw(pain, xx, yy);
217                 }
218         }
219 }
220
221
222 void MathGridInset::Write(std::ostream & os, bool fragile) const
223 {
224         for (int row = 0; row < nrows(); ++row) {
225                 if (row)
226                         os << " \\\\\n";
227                 for (int col = 0; col < ncols(); ++col) {
228                         if (col)
229                                 os << " & ";
230                         cell(index(row, col)).Write(os, fragile);
231                 }
232         }
233 }
234
235
236 void MathGridInset::addRow(int row)
237 {
238         rowinfo_.insert(rowinfo_.begin() + row + 1, RowInfo());
239         cells_.insert(cells_.begin() + (row + 1) * ncols(), ncols(), MathXArray());
240 }
241
242 void MathGridInset::appendRow()
243 {
244         rowinfo_.push_back(RowInfo());
245         for (int i = 0; i < ncols(); ++i)
246                 cells_.push_back();
247 }
248
249
250 void MathGridInset::delRow(int row)
251 {
252         if (nrows() == 1)
253                 return;
254
255         lyxerr << "delRow: nr: " << nrows() << "  nc: " << ncols()
256                 << "  row: " << row << "\n";
257
258         cells_type::iterator it = cells_.begin() + row * ncols(); 
259         cells_.erase(it, it + ncols());
260
261         rowinfo_.erase(rowinfo_.begin() + row);
262 }
263
264
265 void MathGridInset::addCol(int newcol)
266 {
267         int nc = ncols();
268         int nr = nrows();
269         cells_type new_cells = cells_type((nc + 1) * nr);
270         
271         for (int row = 0; row < nr; ++row)
272                 for (int col = 0; col < nc; ++col)
273                         new_cells[row * (nc + 1) + col + (col > newcol)]
274                                 = cells_[row * nc + col];
275         swap(cells_, new_cells);
276
277         colinfo_.insert(colinfo_.begin() + newcol);
278 }
279
280
281 void MathGridInset::delCol(int col)
282 {
283         if (ncols() == 1)
284                 return;
285
286         cells_type tmpcells;
287         for (int i = 0; i < nargs(); ++i) 
288                 if (i % ncols() != col)
289                         tmpcells.push_back(cells_[i]);
290         swap(cells_, tmpcells);
291
292         colinfo_.erase(colinfo_.begin() + col);
293 }
294
295
296 bool MathGridInset::idxUp(int & idx, int & pos) const
297 {
298         if (idx < ncols())
299                 return false;
300         idx -= ncols();
301         pos = 0;
302         return true;
303 }
304
305         
306 bool MathGridInset::idxDown(int & idx, int & pos) const
307 {
308         if (idx >= ncols() * (nrows() - 1))
309                 return false;
310         idx += ncols();
311         pos = 0;
312         return true;
313 }
314         
315         
316 bool MathGridInset::idxLeft(int & idx, int & pos) const
317 {
318         // leave matrix if on the left hand edge
319         if (col(idx) == 0)
320                 return false;
321         idx--;
322         pos = cell(idx).size();
323         return true;
324 }
325         
326         
327 bool MathGridInset::idxRight(int & idx, int & pos) const
328 {
329         // leave matrix if on the right hand edge
330         if (col(idx) == ncols() - 1)
331                 return false;
332         idx++;
333         pos = 0;
334         return true;
335 }
336
337
338 bool MathGridInset::idxFirst(int & idx, int & pos) const
339 {
340         switch (v_align_) {
341                 case 't':
342                         idx = 0;
343                         break;
344                 case 'b':
345                         idx = (nrows() - 1) * ncols();
346                         break;
347                 default: 
348                         idx = (nrows() / 2) * ncols();
349         }
350         pos = 0;
351         return true;
352 }
353
354
355 bool MathGridInset::idxLast(int & idx, int & pos) const
356 {
357         switch (v_align_) {
358                 case 't':
359                         idx = ncols() - 1;
360                         break;
361                 case 'b':
362                         idx = nargs() - 1;
363                         break;
364                 default:
365                         idx = (nrows() / 2 + 1) * ncols() - 1;
366         }
367         pos = cell(idx).size();
368         return true;
369 }
370
371
372
373 MathGridInset::RowInfo const & MathGridInset::rowinfo(int i) const
374 {
375         return rowinfo_[i];
376 }
377
378
379 MathGridInset::RowInfo & MathGridInset::rowinfo(int i)
380 {
381         return rowinfo_[i];
382 }