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() InsetMathGrid::RowInfo::RowInfo()
: descent(0), ascent(0), offset(0), lines(0), skip(0), : descent(0), ascent(0), lines(0), skip(0),
allow_newpage(true) allow_newpage(true)
{} {}
@ -424,10 +424,10 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
rowinfo_[nrows()].descent = 0; rowinfo_[nrows()].descent = 0;
// compute vertical offsets // compute vertical offsets
rowinfo_[0].offset = 0; rowinfo_[0].offset[&bv] = 0;
for (row_type row = 1; row <= nrows(); ++row) { for (row_type row = 1; row <= nrows(); ++row) {
rowinfo_[row].offset = rowinfo_[row].offset[&bv] =
rowinfo_[row - 1].offset + rowinfo_[row - 1].offset[&bv] +
rowinfo_[row - 1].descent + rowinfo_[row - 1].descent +
rowinfo_[row - 1].skipPixels(mi) + rowinfo_[row - 1].skipPixels(mi) +
rowsep() + rowsep() +
@ -442,13 +442,13 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
h = 0; h = 0;
break; break;
case 'b': case 'b':
h = rowinfo_[nrows() - 1].offset; h = rowinfo_[nrows() - 1].offset[&bv];
break; break;
default: default:
h = rowinfo_[nrows() - 1].offset / 2; h = rowinfo_[nrows() - 1].offset[&bv] / 2;
} }
for (row_type row = 0; row <= nrows(); ++row) 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 // 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 + vlinesep() * colinfo_[ncols()].lines
+ border(); + border();
dim.asc = - rowinfo_[0].offset dim.asc = - rowinfo_[0].offset[&bv]
+ rowinfo_[0].ascent + rowinfo_[0].ascent
+ hlinesep() * rowinfo_[0].lines + hlinesep() * rowinfo_[0].lines
+ border(); + border();
dim.des = rowinfo_[nrows() - 1].offset dim.des = rowinfo_[nrows() - 1].offset[&bv]
+ rowinfo_[nrows() - 1].descent + rowinfo_[nrows() - 1].descent
+ hlinesep() * rowinfo_[nrows()].lines + hlinesep() * rowinfo_[nrows()].lines
+ border() + 1; + 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 - rowinfo_[row].ascent
- line * hlinesep() - line * hlinesep()
- hlinesep()/2 - rowsep()/2; - 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) { if (cellinfo_[idx].multi != CELL_PART_OF_MULTICOLUMN) {
cell(idx).draw(pi, cell(idx).draw(pi,
x + leftMargin() + cellXOffset(bv, idx), x + leftMargin() + cellXOffset(bv, idx),
y + cellYOffset(idx)); y + cellYOffset(bv, idx));
row_type r = row(idx); row_type r = row(idx);
int const yy1 = y + hLineVOffset(r, 0); int const yy1 = y + hLineVOffset(bv, r, 0);
int const yy2 = y + hLineVOffset(r + 1, rowinfo_[r + 1].lines - 1); int const yy2 = y + hLineVOffset(bv, r + 1, rowinfo_[r + 1].lines - 1);
auto draw_left_borders = [&](col_type c) { auto draw_left_borders = [&](col_type c) {
for (unsigned int i = 0; i < colinfo_[c].lines; ++i) { for (unsigned int i = 0; i < colinfo_[c].lines; ++i) {
int const xx = x + vLineHOffset(c, 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 xx1 = x + vLineHOffset(0, 0);
int const xx2 = x + vLineHOffset(ncols(), colinfo_[ncols()].lines - 1); int const xx2 = x + vLineHOffset(ncols(), colinfo_[ncols()].lines - 1);
for (unsigned int i = 0; i < rowinfo_[r].lines; ++i) { 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); 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 // let the cells adjust themselves
for (idx_type i = 0; i < nargs(); ++i) for (idx_type i = 0; i < nargs(); ++i)
if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) 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; rowinfo_[nrows()].descent = 0;
// compute vertical offsets // compute vertical offsets
rowinfo_[0].offset = 0; rowinfo_[0].offset[&bv] = 0;
for (row_type row = 1; row <= nrows(); ++row) { for (row_type row = 1; row <= nrows(); ++row) {
rowinfo_[row].offset = rowinfo_[row].offset[&bv] =
rowinfo_[row - 1].offset + rowinfo_[row - 1].offset +
rowinfo_[row - 1].descent + rowinfo_[row - 1].descent +
//rowinfo_[row - 1].skipPixels(mi) + //rowinfo_[row - 1].skipPixels(mi) +
@ -751,6 +755,7 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
+ rowinfo_[nrows() - 1].descent + rowinfo_[nrows() - 1].descent
//+ hlinesep() * rowinfo_[nrows()].lines //+ hlinesep() * rowinfo_[nrows()].lines
+ 1; + 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 "InsetMathNest.h"
#include "Length.h" #include "Length.h"
#include <map>
namespace lyx { namespace lyx {
class BufferParams; class BufferParams;
class BufferView;
/** Gridded math inset base class. /** Gridded math inset base class.
* This is the base to all grid-like editable math objects * This is the base to all grid-like editable math objects
@ -59,8 +60,8 @@ public:
mutable int descent; mutable int descent;
/// cached ascent /// cached ascent
mutable int ascent; mutable int ascent;
/// cached offset /// cached offset for each bufferview
mutable int offset; mutable std::map<BufferView const *, int> offset;
/// how many hlines above this row? /// how many hlines above this row?
unsigned int lines; unsigned int lines;
/// parameter to the line break /// parameter to the line break
@ -245,7 +246,7 @@ protected:
/// returns x offset of cell compared to inset /// returns x offset of cell compared to inset
int cellXOffset(BufferView const &, idx_type idx) const; int cellXOffset(BufferView const &, idx_type idx) const;
/// returns y offset of cell compared to inset /// 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 /// Width of cell, taking combined columns into account
int cellWidth(idx_type idx) const; int cellWidth(idx_type idx) const;
/// ///
@ -277,7 +278,7 @@ protected:
/// positions of vertical and horizontal lines /// positions of vertical and horizontal lines
int vLineHOffset(col_type col, unsigned int line) const; 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; } InsetCode lyxCode() const { return MATH_GRID_CODE; }

View File

@ -548,12 +548,39 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
return; return;
} }
Changer dummy1 = mi.base.changeFontSet(standardFont()); {
Changer dummy2 = mi.base.font.changeStyle(display() ? DISPLAY_STYLE Changer dummy1 = mi.base.changeFontSet(standardFont());
: TEXT_STYLE); 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()) { if (display()) {
dim.asc += display_margin; dim.asc += display_margin;
@ -637,21 +664,32 @@ void InsetMathHull::draw(PainterInfo & pi, int x, int y) const
} }
// First draw the numbers // 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 ColorCode color = pi.selected && lyxrc.use_system_colors
? Color_selectiontext : standardColor(); ? Color_selectiontext : standardColor();
bool const really_change_color = pi.base.font.color() == Color_none; bool const really_change_color = pi.base.font.color() == Color_none;
Changer dummy0 = really_change_color ? pi.base.font.changeColor(color) Changer dummy0 = really_change_color ? pi.base.font.changeColor(color)
: Changer(); : Changer();
if (pi.full_repaint && numberedType()) { if (numberedType()) {
LATTEST(pi.leftx <pi.rightx);
BufferParams::MathNumber const math_number = buffer().params().getMathNumber(); BufferParams::MathNumber const math_number = buffer().params().getMathNumber();
for (row_type row = 0; row < nrows(); ++row) { 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); docstring const nl = nicelabel(row);
Dimension dimnl;
mathed_string_dim(pi.base.font, nl, dimnl);
if (math_number == BufferParams::LEFT) { if (math_number == BufferParams::LEFT) {
if (dimnl.wid > x - pi.leftx)
yy += rowinfo(row).descent + dimnl.asc;
pi.draw(pi.leftx, yy, nl); pi.draw(pi.leftx, yy, nl);
} else { } else {
int const l = mathed_string_width(pi.base.font, nl); if (dimnl.wid > pi.rightx - x - dim.wid)
pi.draw(pi.rightx - l, yy, nl); yy += rowinfo(row).descent + dimnl.asc;
pi.draw(pi.rightx - dimnl.wid, yy, nl);
} }
} }
} }