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;
48 void MathGridInset::halign(string const & hh)
53 for (int i = 0; i < n; ++i)
54 colinfo_[i].h_align_ = hh[i];
57 void MathGridInset::halign(char h, int col)
59 colinfo_[col].h_align_ = h;
62 char MathGridInset::halign(int col) const
64 return colinfo_[col].h_align_;
67 void MathGridInset::valign(char c)
72 char MathGridInset::valign() const
77 void MathGridInset::metrics(MathStyles st) const
79 // let the cells adjust themselves
80 MathNestInset::metrics(st);
83 // adjust vertical structure
84 for (int row = 0; row < nrows(); ++row) {
87 for (int col = 0; col < ncols(); ++col) {
88 MathXArray const & c = xcell(index(row, col));
89 asc = std::max(asc, c.ascent());
90 desc = std::max(desc, c.descent());
92 rowinfo_[row].ascent_ = asc;
93 rowinfo_[row].descent_ = desc;
96 rowinfo_[row].offset_ =
97 rowinfo_[row - 1].offset_ +
98 rowinfo_[row - 1].descent_ +
100 rowinfo_[row].ascent_;
102 rowinfo_[row].offset_ = 0;
105 // adjust vertical offset
112 h = rowinfo_.back().offset_;
115 h = rowinfo_.back().offset_ / 2;
118 for (int row = 0; row < nrows(); ++row) {
119 rowinfo_[row].offset_ -= h;
120 rowinfo_[row].offset_ += MATH_BORDER;
123 // adjust horizontal structure
124 for (int col = 0; col < ncols(); ++col) {
126 for (int row = 0; row < nrows(); ++row)
127 wid = std::max(wid, xcell(index(row, col)).width());
128 colinfo_[col].width_ = wid;
129 colinfo_[col].offset_ = colinfo_[col].width_;
132 colinfo_[col].offset_ =
133 colinfo_[col - 1].offset_ + colinfo_[col - 1].width_ + MATH_COLSEP;
135 colinfo_[col].offset_ = 0;
137 colinfo_[col].offset_ += MATH_BORDER;
140 width_ = colinfo_.back().offset_ + colinfo_.back().width_;
141 ascent_ = - rowinfo_.front().offset_ + rowinfo_.front().ascent_;
142 descent_ = rowinfo_.back().offset_ + rowinfo_.back().descent_;
145 // Increase ws_[i] for 'R' columns (except the first one)
146 for (int i = 1; i < nc_; ++i)
147 if (h_align_[i] == 'R')
148 ws_[i] += 10 * df_width;
149 // Increase ws_[i] for 'C' column
150 if (h_align_[0] == 'C')
151 if (ws_[0] < 7 * workwidth / 8)
152 ws_[0] = 7 * workwidth / 8;
156 for (cxrow = row_.begin(); cxrow; ++cxrow) {
157 int rg = MATH_COLSEP;
159 for (int i = 0; i < nc_; ++i) {
161 if (cxrow->getTab(i) <= 0) {
162 cxrow->setTab(i, df_width);
165 switch (h_align_[i]) {
170 lf = (ws_[i] - cxrow->getTab(i))/2;
174 lf = ws_[i] - cxrow->getTab(i);
177 if (cxrow == row_.begin())
179 else if (cxrow.is_last())
180 lf = ws_[i] - cxrow->getTab(i);
182 lf = (ws_[i] - cxrow->getTab(i))/2;
185 int const ww = (isvoid) ? lf : lf + cxrow->getTab(i);
186 cxrow->setTab(i, lf + rg);
187 rg = ws_[i] - ww + MATH_COLSEP;
188 if (cxrow == row_.begin())
189 width += ws_[i] + MATH_COLSEP;
191 cxrow->setBaseline(cxrow->getBaseline() - ascent);
197 void MathGridInset::draw(Painter & pain, int x, int y) const
201 for (int idx = 0; idx < nargs(); ++idx)
202 xcell(idx).draw(pain, x + cellXOffset(idx), y + cellYOffset(idx));
206 void MathGridInset::write(std::ostream & os, bool fragile) const
208 for (int row = 0; row < nrows(); ++row) {
209 for (int col = 0; col < ncols(); ++col) {
210 cell(index(row, col)).write(os, fragile);
211 os << eocString(row);
213 os << eolString(row);
218 string MathGridInset::eolString(int row) const
220 if (row == nrows() - 1)
223 // make sure an upcoming '[' does not break anything
224 MathArray const & c = cell(index(row + 1, 0));
225 if (c.size() && (*c.begin())->getChar() == '[')
226 return "\\\\[0pt]\n";
232 string MathGridInset::eocString(int col) const
234 if (col == ncols() - 1)
240 void MathGridInset::addRow(int row)
242 rowinfo_.insert(rowinfo_.begin() + row + 1, RowInfo());
243 cells_.insert(cells_.begin() + (row + 1) * ncols(), ncols(), MathXArray());
246 void MathGridInset::appendRow()
248 rowinfo_.push_back(RowInfo());
249 for (int i = 0; i < ncols(); ++i)
250 cells_.push_back(cells_type::value_type());
254 void MathGridInset::delRow(int row)
259 cells_type::iterator it = cells_.begin() + row * ncols();
260 cells_.erase(it, it + ncols());
262 rowinfo_.erase(rowinfo_.begin() + row);
266 void MathGridInset::addCol(int newcol)
268 int const nc = ncols();
269 int const nr = nrows();
270 cells_type new_cells((nc + 1) * nr);
272 for (int row = 0; row < nr; ++row)
273 for (int col = 0; col < nc; ++col)
274 new_cells[row * (nc + 1) + col + (col > newcol)]
275 = cells_[row * nc + col];
276 std::swap(cells_, new_cells);
278 colinfo_.insert(colinfo_.begin() + newcol, ColInfo());
282 void MathGridInset::delCol(int col)
288 for (int i = 0; i < nargs(); ++i)
289 if (i % ncols() != col)
290 tmpcells.push_back(cells_[i]);
291 std::swap(cells_, tmpcells);
293 colinfo_.erase(colinfo_.begin() + col);
297 int MathGridInset::cellXOffset(int idx) const
300 int x = colinfo_[c].offset_;
301 char align = colinfo_[c].h_align_;
302 if (align == 'r' || align == 'R')
303 x += colinfo_[c].width_ - xcell(idx).width();
304 if (align == 'c' || align == 'C')
305 x += (colinfo_[c].width_ - xcell(idx).width()) / 2;
310 int MathGridInset::cellYOffset(int idx) const
312 return rowinfo_[row(idx)].offset_;
316 bool MathGridInset::idxUp(int & idx, int & pos) const
326 bool MathGridInset::idxDown(int & idx, int & pos) const
328 if (idx >= ncols() * (nrows() - 1))
336 bool MathGridInset::idxLeft(int & idx, int & pos) const
338 // leave matrix if on the left hand edge
342 pos = cell(idx).size();
347 bool MathGridInset::idxRight(int & idx, int & pos) const
349 // leave matrix if on the right hand edge
350 if (col(idx) == ncols() - 1)
358 bool MathGridInset::idxFirst(int & idx, int & pos) const
365 idx = (nrows() - 1) * ncols();
368 idx = (nrows() / 2) * ncols();
375 bool MathGridInset::idxLast(int & idx, int & pos) const
385 idx = (nrows() / 2 + 1) * ncols() - 1;
387 pos = cell(idx).size();
392 void MathGridInset::idxDelete(int & idx, bool & popit, bool & deleteit)
397 // delete entire row if in first cell of empty row
398 if (col(idx) == 0 && nrows() > 1) {
399 bool deleterow = true;
400 for (int i = idx; i < idx + ncols(); ++i)
401 if (cell(i).size()) {
413 // undo effect of Ctrl-Tab (i.e. pull next cell)
414 //if (idx != nargs() - 1)
415 // cell(idx).swap(cell(idx + 1));
419 void MathGridInset::idxDeleteRange(int /*from*/, int /*to*/)
421 // leave this unimplemented unless someone wants to have it.
423 int n = (to - from) / ncols();
424 int r = from / ncols();
427 cells_type::iterator it = cells_.begin() + from;
428 cells_.erase(it, it + n * ncols());
429 rowinfo_.erase(rowinfo_.begin() + r, rowinfo_.begin() + r + n);
435 MathGridInset::RowInfo const & MathGridInset::rowinfo(int i) const
441 MathGridInset::RowInfo & MathGridInset::rowinfo(int i)
447 std::vector<int> MathGridInset::idxBetween(int from, int to) const
449 int r1 = std::min(row(from), row(to));
450 int r2 = std::max(row(from), row(to));
451 int c1 = std::min(col(from), col(to));
452 int c2 = std::max(col(from), col(to));
453 std::vector<int> res;
454 for (int i = r1; i <= r2; ++i)
455 for (int j = c1; j <= c2; ++j)
456 res.push_back(index(i, j));