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