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