Add empty rows to grid insets when numbers are too wide

This is done to ensure that numbering never overlaps equations. The
result can be different according to the bufferview, which is why
RowInfo::offset is now a std:map.

Remaing issues (how bad are theese ?):

- the numbering is considered too large when it overlaps the inset
  rect, whereas one could consider the width if the current row
  instead.

- previews may need to be adapted similarly to fit the whole screen width
This commit is contained in:
Jean-Marc Lasgouttes 2019-07-14 21:04:45 +02:00
parent dea245d540
commit ee0bd36a86
3 changed files with 78 additions and 34 deletions

View File

@ -92,7 +92,7 @@ InsetMathGrid::CellInfo::CellInfo()
InsetMathGrid::RowInfo::RowInfo()
: descent(0), ascent(0), offset(0), lines(0), skip(0),
: descent(0), ascent(0), lines(0), skip(0),
allow_newpage(true)
{}
@ -424,10 +424,10 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
rowinfo_[nrows()].descent = 0;
// compute vertical offsets
rowinfo_[0].offset = 0;
rowinfo_[0].offset[&bv] = 0;
for (row_type row = 1; row <= nrows(); ++row) {
rowinfo_[row].offset =
rowinfo_[row - 1].offset +
rowinfo_[row].offset[&bv] =
rowinfo_[row - 1].offset[&bv] +
rowinfo_[row - 1].descent +
rowinfo_[row - 1].skipPixels(mi) +
rowsep() +
@ -442,13 +442,13 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
h = 0;
break;
case 'b':
h = rowinfo_[nrows() - 1].offset;
h = rowinfo_[nrows() - 1].offset[&bv];
break;
default:
h = rowinfo_[nrows() - 1].offset / 2;
h = rowinfo_[nrows() - 1].offset[&bv] / 2;
}
for (row_type row = 0; row <= nrows(); ++row)
rowinfo_[row].offset -= h;
rowinfo_[row].offset[&bv] -= h;
// multicolumn cell widths, as a map from first column to width in a
@ -528,12 +528,12 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
+ vlinesep() * colinfo_[ncols()].lines
+ border();
dim.asc = - rowinfo_[0].offset
dim.asc = - rowinfo_[0].offset[&bv]
+ rowinfo_[0].ascent
+ hlinesep() * rowinfo_[0].lines
+ border();
dim.des = rowinfo_[nrows() - 1].offset
dim.des = rowinfo_[nrows() - 1].offset[&bv]
+ rowinfo_[nrows() - 1].descent
+ hlinesep() * rowinfo_[nrows()].lines
+ border() + 1;
@ -608,9 +608,10 @@ int InsetMathGrid::vLineHOffset(col_type col, unsigned int line) const
}
int InsetMathGrid::hLineVOffset(row_type row, unsigned int line) const
int InsetMathGrid::hLineVOffset(BufferView const & bv, row_type row,
unsigned int line) const
{
return rowinfo_[row].offset
return rowinfo_[row].offset[&bv]
- rowinfo_[row].ascent
- line * hlinesep()
- hlinesep()/2 - rowsep()/2;
@ -625,11 +626,11 @@ void InsetMathGrid::draw(PainterInfo & pi, int x, int y) const
if (cellinfo_[idx].multi != CELL_PART_OF_MULTICOLUMN) {
cell(idx).draw(pi,
x + leftMargin() + cellXOffset(bv, idx),
y + cellYOffset(idx));
y + cellYOffset(bv, idx));
row_type r = row(idx);
int const yy1 = y + hLineVOffset(r, 0);
int const yy2 = y + hLineVOffset(r + 1, rowinfo_[r + 1].lines - 1);
int const yy1 = y + hLineVOffset(bv, r, 0);
int const yy2 = y + hLineVOffset(bv, r + 1, rowinfo_[r + 1].lines - 1);
auto draw_left_borders = [&](col_type c) {
for (unsigned int i = 0; i < colinfo_[c].lines; ++i) {
int const xx = x + vLineHOffset(c, i);
@ -650,15 +651,18 @@ void InsetMathGrid::draw(PainterInfo & pi, int x, int y) const
int const xx1 = x + vLineHOffset(0, 0);
int const xx2 = x + vLineHOffset(ncols(), colinfo_[ncols()].lines - 1);
for (unsigned int i = 0; i < rowinfo_[r].lines; ++i) {
int const yy = y + hLineVOffset(r, i);
int const yy = y + hLineVOffset(bv, r, i);
pi.pain.line(xx1, yy, xx2, yy, Color_foreground);
}
}
}
void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
void InsetMathGrid::metricsT(TextMetricsInfo const & /*mi*/, Dimension & /*dim*/) const
{
// FIXME: this does not compile anymore with offset being a map
// It is not worth fixing it at this point since the code is basically dead.
#if 0
// let the cells adjust themselves
for (idx_type i = 0; i < nargs(); ++i)
if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN)
@ -685,9 +689,9 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
rowinfo_[nrows()].descent = 0;
// compute vertical offsets
rowinfo_[0].offset = 0;
rowinfo_[0].offset[&bv] = 0;
for (row_type row = 1; row <= nrows(); ++row) {
rowinfo_[row].offset =
rowinfo_[row].offset[&bv] =
rowinfo_[row - 1].offset +
rowinfo_[row - 1].descent +
//rowinfo_[row - 1].skipPixels(mi) +
@ -751,6 +755,7 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+ rowinfo_[nrows() - 1].descent
//+ hlinesep() * rowinfo_[nrows()].lines
+ 1;
#endif
}
@ -935,9 +940,9 @@ int InsetMathGrid::cellXOffset(BufferView const & bv, idx_type idx) const
}
int InsetMathGrid::cellYOffset(idx_type idx) const
int InsetMathGrid::cellYOffset(BufferView const & bv, idx_type idx) const
{
return rowinfo_[row(idx)].offset;
return rowinfo_[row(idx)].offset[&bv];
}

View File

@ -15,11 +15,12 @@
#include "InsetMathNest.h"
#include "Length.h"
#include <map>
namespace lyx {
class BufferParams;
class BufferView;
/** Gridded math inset base class.
* This is the base to all grid-like editable math objects
@ -59,8 +60,8 @@ public:
mutable int descent;
/// cached ascent
mutable int ascent;
/// cached offset
mutable int offset;
/// cached offset for each bufferview
mutable std::map<BufferView const *, int> offset;
/// how many hlines above this row?
unsigned int lines;
/// parameter to the line break
@ -245,7 +246,7 @@ protected:
/// returns x offset of cell compared to inset
int cellXOffset(BufferView const &, idx_type idx) const;
/// returns y offset of cell compared to inset
int cellYOffset(idx_type idx) const;
int cellYOffset(BufferView const &, idx_type idx) const;
/// Width of cell, taking combined columns into account
int cellWidth(idx_type idx) const;
///
@ -277,7 +278,7 @@ protected:
/// positions of vertical and horizontal lines
int vLineHOffset(col_type col, unsigned int line) const;
int hLineVOffset(row_type row, unsigned int line) const;
int hLineVOffset(BufferView const &, row_type row, unsigned int line) const;
///
InsetCode lyxCode() const { return MATH_GRID_CODE; }

View File

@ -548,12 +548,39 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
return;
}
Changer dummy1 = mi.base.changeFontSet(standardFont());
Changer dummy2 = mi.base.font.changeStyle(display() ? DISPLAY_STYLE
: TEXT_STYLE);
{
Changer dummy1 = mi.base.changeFontSet(standardFont());
Changer dummy2 = mi.base.font.changeStyle(display() ? DISPLAY_STYLE
: TEXT_STYLE);
// let the cells adjust themselves
InsetMathGrid::metrics(mi, dim);
}
// Check whether the numbering interferes with the equations
if (numberedType()) {
BufferParams::MathNumber const math_number = buffer().params().getMathNumber();
int extra_offset = 0;
for (row_type row = 0; row < nrows(); ++row) {
rowinfo(row).offset[mi.base.bv] += extra_offset;
if (!numbered(row))
continue;
docstring const nl = nicelabel(row);
Dimension dimnl;
mathed_string_dim(mi.base.font, nl, dimnl);
int const ind = indent(*mi.base.bv);
int const x = ind ? ind : (mi.base.textwidth - dim.wid) / 2;
// for some reason metrics does not trigger at the
// same point as draw, and therefore we use >= instead of >
if ((math_number == BufferParams::LEFT && dimnl.wid >= x)
|| (math_number == BufferParams::RIGHT
&& dimnl.wid >= mi.base.textwidth - x - dim.wid)) {
extra_offset += dimnl.height();
}
}
dim.des += extra_offset;
}
// let the cells adjust themselves
InsetMathGrid::metrics(mi, dim);
if (display()) {
dim.asc += display_margin;
@ -637,21 +664,32 @@ void InsetMathHull::draw(PainterInfo & pi, int x, int y) const
}
// First draw the numbers
if (!pi.full_repaint)
pi.pain.fillRectangle(pi.leftx, y - dim.asc,
pi.rightx - pi.leftx, dim.height(),
pi.background_color);
ColorCode color = pi.selected && lyxrc.use_system_colors
? Color_selectiontext : standardColor();
bool const really_change_color = pi.base.font.color() == Color_none;
Changer dummy0 = really_change_color ? pi.base.font.changeColor(color)
: Changer();
if (pi.full_repaint && numberedType()) {
if (numberedType()) {
LATTEST(pi.leftx <pi.rightx);
BufferParams::MathNumber const math_number = buffer().params().getMathNumber();
for (row_type row = 0; row < nrows(); ++row) {
int const yy = y + rowinfo(row).offset;
int yy = y + rowinfo(row).offset[bv];
docstring const nl = nicelabel(row);
Dimension dimnl;
mathed_string_dim(pi.base.font, nl, dimnl);
if (math_number == BufferParams::LEFT) {
if (dimnl.wid > x - pi.leftx)
yy += rowinfo(row).descent + dimnl.asc;
pi.draw(pi.leftx, yy, nl);
} else {
int const l = mathed_string_width(pi.base.font, nl);
pi.draw(pi.rightx - l, yy, nl);
if (dimnl.wid > pi.rightx - x - dim.wid)
yy += rowinfo(row).descent + dimnl.asc;
pi.draw(pi.rightx - dimnl.wid, yy, nl);
}
}
}