2 #include "math_parboxinset.h"
3 #include "math_mathmlstream.h"
4 #include "math_streamstr.h"
10 MathParboxInset::MathParboxInset()
11 : MathNestInset(1), lyx_width_(0), tex_width_("0mm"),
14 lyxerr << "constructing MathParboxInset\n";
18 MathInset * MathParboxInset::clone() const
20 return new MathParboxInset(*this);
24 void MathParboxInset::setPosition(string const & p)
26 position_ = p.size() > 0 ? p[0] : 'c';
30 void MathParboxInset::setWidth(string const & w)
33 lyx_width_ = LyXLength(w).inBP();
34 lyxerr << "setting " << w << " to " << lyx_width_ << " pixel\n";
38 int MathParboxInset::screenrows() const
44 int MathParboxInset::pos2row(pos_type pos) const
46 for (int r = 0, n = rows_.size(); r < n; ++r)
47 if (pos >= rows_[r].begin && pos <= rows_[r].end)
49 lyxerr << "illegal row for pos " << pos << "\n";
54 void MathParboxInset::getPos(idx_type idx, pos_type pos, int & x, int & y) const
56 int const r = pos2row(pos);
57 MathXArray const & ar = cells_[idx];
58 x = ar.xo() + ar.pos2x(rows_[r].begin, pos, rows_[r].glue);
59 y = ar.yo() + rows_[r].yo;
60 // move cursor visually into empty cells ("blue rectangles");
63 //lyxerr << "getPos cursor at pos " << pos << " in row " << r
64 // << " x: " << x << " y: " << y << "\n";
68 bool MathParboxInset::idxUpDown(idx_type & idx, pos_type & pos, bool up) const
70 // try to move only one screen row up or down if possible
71 int row = pos2row(pos);
72 int const x = cells_[idx].pos2x(rows_[row].begin, pos, rows_[row].glue);
79 if (row == screenrows())
82 pos = xcell(0).x2pos(rows_[row].begin, x, rows_[row].glue);
87 void MathParboxInset::metrics(MathMetricsInfo & mi) const
89 MathFontSetChanger dummy(mi.base, "textnormal");
91 // we do our own metrics fiddling
97 dim_ = xcell(0).metrics(mi);
101 vector<Dimension> dims;
102 xcell(0).metricsExternal(mi, dims);
107 safe.clear(mi.base.font);
108 curr.clear(mi.base.font);
112 for (size_type i = 0, n = cell(0).size(); i < n; ++i) {
113 //lyxerr << "at pos: " << i << " of " << n << " safepos: " << safepos
114 // << " curr: " << curr << " safe: " << safe
115 // << " spaces: " << spaces << endl;
119 // <char> <char> <char> <space> <char> <char> <char>
120 // ................... <safe>
121 // ..........................<curr>
122 // ....................<safepos>
124 // Special handling of spaces. We reached a safe position for breaking.
125 if (cell(0)[i]->getChar() == ' ') {
126 //lyxerr << "reached safe pos\n";
127 // we don't count the space into the safe pos
129 // we reset to this safepos if the next chunk does not fit
132 // restart chunk with size of the space
133 curr.clear(mi.base.font);
138 // This is a regular char. Go on if we either don't care for
139 // the width limit or have not reached that limit.
141 if (curr.w + safe.w <= lyx_width_)
144 // We passed the limit. Create a row entry.
145 //lyxerr << "passed limit\n";
148 // but we had a space break before this position.
149 // so retreat to this position
150 int glue = lyx_width_ - safe.w + dims[safepos].w;
152 row.glue = glue / spaces;
154 row.end = safepos; // this is position of the safe space
155 i = safepos; // i gets incremented at end of loop
156 begin = i + 1; // next chunk starts after the space
157 //lyxerr << "... but had safe pos. glue: " << row.glue << "\n";
158 //lyxerr << " safe.w: " << safe.w
159 // << " dim.w: " << dims[safepos].w << " spaces: " << spaces << "\n";
162 lyxerr << "... without safe pos\n";
163 // This item is too large and it is the only one.
164 // We have no choice but to produce an overfull box.
165 row.dim = curr; // safe should be 0.
166 row.glue = 0; // does not matter
172 yo += row.dim.height();
173 rows_.push_back(row);
174 // in any case, start the new row with empty boxes
175 curr.clear(mi.base.font);
176 safe.clear(mi.base.font);
178 // last row: put in everything else
183 row.end = cell(0).size();
184 row.glue = 0; // last line is left aligned
186 rows_.push_back(row);
190 dim_.a = rows_.front().dim.a;
191 dim_.d = rows_.back().dim.d + yo;
193 xcell(0).setDim(dim_);
198 void MathParboxInset::draw(MathPainterInfo & pi, int x, int y) const
200 MathFontSetChanger dummy(pi.base, "textnormal");
202 xcell(0).draw(pi, x + 1, y);
204 xcell(0).drawExternal(pi, x + 1, y, rows_);
206 drawMarkers2(pi, x, y);
210 void MathParboxInset::drawSelection(MathPainterInfo & pi,
211 idx_type, pos_type pos1, idx_type, pos_type pos2) const
213 int row1 = pos2row(pos1);
214 int row2 = pos2row(pos2);
217 MathXArray & c = xcell(0);
218 int x1 = c.xo() + c.pos2x(i1.pos_);
219 int y1 = c.yo() - c.ascent();
220 int x2 = c.xo() + c.pos2x(i2.pos_);
221 int y2 = c.yo() + c.descent();
222 pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
224 vector<MathInset::idx_type> indices = idxBetween(idx1, idx2);
225 for (unsigned i = 0; i < indices.size(); ++i) {
226 MathXArray & c = i1.xcell(indices[i]);
228 int y1 = c.yo() - c.ascent();
229 int x2 = c.xo() + c.width();
230 int y2 = c.yo() + c.descent();
231 pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
238 void MathParboxInset::write(WriteStream & os) const
241 if (position_ != 'c')
242 os << '[' << position_ << ']';
243 os << '{' << tex_width_ << "}{" << cell(0) << '}';
247 void MathParboxInset::infoize(std::ostream & os) const
249 os << "Box: Parbox " << tex_width_;