5 #include "math_gridinset.h"
6 #include "support/LOstream.h"
13 int const MATH_COLSEP = 10;
15 int const MATH_ROWSEP = 10;
17 int const MATH_BORDER = 2;
22 MathGridInset::RowInfo::RowInfo()
23 : upperline_(false), lowerline_(false)
27 MathGridInset::ColInfo::ColInfo()
28 : h_align_('c'), leftline_(false), rightline_(false)
32 MathGridInset::MathGridInset(int m, int n)
33 : MathNestInset(m * n), rowinfo_(n), colinfo_(m), v_align_('c')
36 lyxerr << "positve number of columns expected\n";
38 lyxerr << "positve number of rows expected\n";
42 int MathGridInset::index(int row, int col) const
44 return col + ncols() * row;
49 void MathGridInset::halign(string const & hh)
54 for (int i = 0; i < n; ++i)
55 colinfo_[i].h_align_ = hh[i];
59 void MathGridInset::halign(char h, int col)
61 colinfo_[col].h_align_ = h;
65 char MathGridInset::halign(int col) const
67 return colinfo_[col].h_align_;
72 void MathGridInset::valign(char c)
78 char MathGridInset::valign() const
85 void MathGridInset::vskip(LyXLength const & skip, int row)
87 rowinfo_[row].skip_ = skip;
91 LyXLength MathGridInset::vskip(int row) const
93 return rowinfo_[row].skip_;
97 void MathGridInset::metrics(MathStyles st) const
99 // let the cells adjust themselves
100 MathNestInset::metrics(st);
103 // adjust vertical structure
104 for (int row = 0; row < nrows(); ++row) {
107 for (int col = 0; col < ncols(); ++col) {
108 MathXArray const & c = xcell(index(row, col));
109 asc = std::max(asc, c.ascent());
110 desc = std::max(desc, c.descent());
112 rowinfo_[row].ascent_ = asc;
113 rowinfo_[row].descent_ = desc;
116 rowinfo_[row].offset_ =
117 rowinfo_[row - 1].offset_ +
118 rowinfo_[row - 1].descent_ +
120 rowinfo_[row].ascent_;
122 rowinfo_[row].offset_ = 0;
125 // adjust vertical offset
132 h = rowinfo_.back().offset_;
135 h = rowinfo_.back().offset_ / 2;
138 for (int row = 0; row < nrows(); ++row) {
139 rowinfo_[row].offset_ -= h;
140 rowinfo_[row].offset_ += MATH_BORDER;
143 // adjust horizontal structure
144 for (int col = 0; col < ncols(); ++col) {
146 for (int row = 0; row < nrows(); ++row)
147 wid = std::max(wid, xcell(index(row, col)).width());
148 colinfo_[col].width_ = wid;
149 colinfo_[col].offset_ = colinfo_[col].width_;
152 colinfo_[col].offset_ =
153 colinfo_[col - 1].offset_ + colinfo_[col - 1].width_ + MATH_COLSEP;
155 colinfo_[col].offset_ = 0;
157 colinfo_[col].offset_ += MATH_BORDER;
160 width_ = colinfo_.back().offset_ + colinfo_.back().width_;
161 ascent_ = - rowinfo_.front().offset_ + rowinfo_.front().ascent_;
162 descent_ = rowinfo_.back().offset_ + rowinfo_.back().descent_;
165 // Increase ws_[i] for 'R' columns (except the first one)
166 for (int i = 1; i < nc_; ++i)
167 if (h_align_[i] == 'R')
168 ws_[i] += 10 * df_width;
169 // Increase ws_[i] for 'C' column
170 if (h_align_[0] == 'C')
171 if (ws_[0] < 7 * workwidth / 8)
172 ws_[0] = 7 * workwidth / 8;
176 for (cxrow = row_.begin(); cxrow; ++cxrow) {
177 int rg = MATH_COLSEP;
179 for (int i = 0; i < nc_; ++i) {
181 if (cxrow->getTab(i) <= 0) {
182 cxrow->setTab(i, df_width);
185 switch (h_align_[i]) {
190 lf = (ws_[i] - cxrow->getTab(i))/2;
194 lf = ws_[i] - cxrow->getTab(i);
197 if (cxrow == row_.begin())
199 else if (cxrow.is_last())
200 lf = ws_[i] - cxrow->getTab(i);
202 lf = (ws_[i] - cxrow->getTab(i))/2;
205 int const ww = (isvoid) ? lf : lf + cxrow->getTab(i);
206 cxrow->setTab(i, lf + rg);
207 rg = ws_[i] - ww + MATH_COLSEP;
208 if (cxrow == row_.begin())
209 width += ws_[i] + MATH_COLSEP;
211 cxrow->setBaseline(cxrow->getBaseline() - ascent);
217 void MathGridInset::draw(Painter & pain, int x, int y) const
221 for (int idx = 0; idx < nargs(); ++idx)
222 xcell(idx).draw(pain, x + cellXOffset(idx), y + cellYOffset(idx));
226 void MathGridInset::write(std::ostream & os, bool fragile) const
228 for (int row = 0; row < nrows(); ++row) {
229 for (int col = 0; col < ncols(); ++col) {
230 cell(index(row, col)).write(os, fragile);
231 os << eocString(row);
233 os << eolString(row);
238 string MathGridInset::eolString(int row) const
240 if (row == nrows() - 1)
243 if (rowinfo_[row].skip_ != LyXLength())
244 return "\\\\[" + rowinfo_[row].skip_.asLatexString() + "]\n";
246 // make sure an upcoming '[' does not break anything
247 MathArray const & c = cell(index(row + 1, 0));
248 if (c.size() && (*c.begin())->getChar() == '[')
249 return "\\\\[0pt]\n";
255 string MathGridInset::eocString(int col) const
257 if (col == ncols() - 1)
263 void MathGridInset::addRow(int row)
265 rowinfo_.insert(rowinfo_.begin() + row + 1, RowInfo());
266 cells_.insert(cells_.begin() + (row + 1) * ncols(), ncols(), MathXArray());
270 void MathGridInset::appendRow()
272 rowinfo_.push_back(RowInfo());
273 for (int i = 0; i < ncols(); ++i)
274 cells_.push_back(cells_type::value_type());
278 void MathGridInset::delRow(int row)
283 cells_type::iterator it = cells_.begin() + row * ncols();
284 cells_.erase(it, it + ncols());
286 rowinfo_.erase(rowinfo_.begin() + row);
290 void MathGridInset::addCol(int newcol)
292 int const nc = ncols();
293 int const nr = nrows();
294 cells_type new_cells((nc + 1) * nr);
296 for (int row = 0; row < nr; ++row)
297 for (int col = 0; col < nc; ++col)
298 new_cells[row * (nc + 1) + col + (col > newcol)]
299 = cells_[row * nc + col];
300 std::swap(cells_, new_cells);
302 colinfo_.insert(colinfo_.begin() + newcol, ColInfo());
306 void MathGridInset::delCol(int col)
312 for (int i = 0; i < nargs(); ++i)
313 if (i % ncols() != col)
314 tmpcells.push_back(cells_[i]);
315 std::swap(cells_, tmpcells);
317 colinfo_.erase(colinfo_.begin() + col);
321 int MathGridInset::cellXOffset(int idx) const
324 int x = colinfo_[c].offset_;
325 char align = colinfo_[c].h_align_;
326 if (align == 'r' || align == 'R')
327 x += colinfo_[c].width_ - xcell(idx).width();
328 if (align == 'c' || align == 'C')
329 x += (colinfo_[c].width_ - xcell(idx).width()) / 2;
334 int MathGridInset::cellYOffset(int idx) const
336 return rowinfo_[row(idx)].offset_;
340 bool MathGridInset::idxUp(int & idx, int & pos) const
350 bool MathGridInset::idxDown(int & idx, int & pos) const
352 if (idx >= ncols() * (nrows() - 1))
360 bool MathGridInset::idxLeft(int & idx, int & pos) const
362 // leave matrix if on the left hand edge
366 pos = cell(idx).size();
371 bool MathGridInset::idxRight(int & idx, int & pos) const
373 // leave matrix if on the right hand edge
374 if (col(idx) == ncols() - 1)
382 bool MathGridInset::idxFirst(int & idx, int & pos) const
389 idx = (nrows() - 1) * ncols();
392 idx = (nrows() / 2) * ncols();
399 bool MathGridInset::idxLast(int & idx, int & pos) const
409 idx = (nrows() / 2 + 1) * ncols() - 1;
411 pos = cell(idx).size();
416 void MathGridInset::idxDelete(int & idx, bool & popit, bool & deleteit)
421 // delete entire row if in first cell of empty row
422 if (col(idx) == 0 && nrows() > 1) {
423 bool deleterow = true;
424 for (int i = idx; i < idx + ncols(); ++i)
425 if (cell(i).size()) {
437 // undo effect of Ctrl-Tab (i.e. pull next cell)
438 //if (idx != nargs() - 1)
439 // cell(idx).swap(cell(idx + 1));
443 void MathGridInset::idxDeleteRange(int /*from*/, int /*to*/)
445 // leave this unimplemented unless someone wants to have it.
447 int n = (to - from) / ncols();
448 int r = from / ncols();
451 cells_type::iterator it = cells_.begin() + from;
452 cells_.erase(it, it + n * ncols());
453 rowinfo_.erase(rowinfo_.begin() + r, rowinfo_.begin() + r + n);
459 MathGridInset::RowInfo const & MathGridInset::rowinfo(int i) const
465 MathGridInset::RowInfo & MathGridInset::rowinfo(int i)
471 std::vector<int> MathGridInset::idxBetween(int from, int to) const
473 int r1 = std::min(row(from), row(to));
474 int r2 = std::max(row(from), row(to));
475 int c1 = std::min(col(from), col(to));
476 int c2 = std::max(col(from), col(to));
477 std::vector<int> res;
478 for (int i = r1; i <= r2; ++i)
479 for (int j = c1; j <= c2; ++j)
480 res.push_back(index(i, j));