Introduce hooks to encapsulate macro code of MathRow

New hooks (before|after)(Metrics|Draw) are run by the MathRow code
as needed. They are actually also used internally by the MathMacro
code.

The gain is that most traces of explicit macro handling (and
the MathRow::Element::macro member) have been removed from MathRw.cpp.

The next step will be to extend the tokenizing process to allow for
linearizing insets other than macros.
This commit is contained in:
Jean-Marc Lasgouttes 2017-02-01 15:20:06 +01:00
parent f86dacc292
commit 6c13af3f29
5 changed files with 105 additions and 56 deletions

View File

@ -171,6 +171,14 @@ public:
virtual MathClass mathClass() const;
/// Add this inset to a math row. Return true if contents got added
virtual bool addToMathRow(MathRow &, MetricsInfo & mi) const;
/// Hook that is run before metrics computation starts
virtual void beforeMetrics() const {}
/// Hook that is run after metrics computation
virtual void afterMetrics() const {}
/// Hook that is run before actual drawing
virtual void beforeDraw(PainterInfo const &) const {}
/// Hook that is run after drawing
virtual void afterDraw(PainterInfo const &) const {}
/// identifies things that can get scripts
virtual bool isScriptable() const { return false; }

View File

@ -88,7 +88,7 @@ public:
mathMacro_->nesting() == 1 ? 0 : mathMacro_->nesting());
MathRow::Element e_beg(mi, MathRow::BEG_ARG);
e_beg.macro = mathMacro_;
e_beg.inset = this;
e_beg.ar = &mathMacro_->cell(idx_);
mrow.push_back(e_beg);
@ -107,7 +107,7 @@ public:
}
MathRow::Element e_end(mi, MathRow::END_ARG);
e_end.macro = mathMacro_;
e_end.inset = this;
e_end.ar = &mathMacro_->cell(idx_);
mrow.push_back(e_end);
@ -115,20 +115,44 @@ public:
return has_contents;
}
///
void beforeMetrics() const
{
mathMacro_->macro()->unlock();
}
///
void afterMetrics() const
{
mathMacro_->macro()->lock();
}
///
void beforeDraw(PainterInfo const & pi) const
{
// if the macro is being edited, then the painter is in
// monochrome mode.
if (mathMacro_->editMetrics(pi.base.bv))
pi.pain.leaveMonochromeMode();
}
///
void afterDraw(PainterInfo const & pi) const
{
if (mathMacro_->editMetrics(pi.base.bv))
pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend);
}
///
void metrics(MetricsInfo &, Dimension &) const {
// This should never be invoked, since ArgumentProxy insets are linearized
LATTEST(false);
}
///
void draw(PainterInfo &, int, int) const {
// This should never be invoked, since ArgumentProxy insets are linearized
LATTEST(false);
}
///
int kerning(BufferView const * bv) const
{
return displayCell(bv).kerning(bv);
}
///
void draw(PainterInfo &, int, int) const {
// This should never be invoked, since ArgumentProxy insets are linearized
LATTEST(false);
}
// write(), normalize(), infoize() and infoize2() are not needed since
// MathMacro uses the definition and not the expanded cells.
///
@ -316,7 +340,6 @@ bool MathMacro::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
MathRow::Element e_beg(mi, MathRow::BEG_MACRO);
e_beg.inset = this;
e_beg.macro = this;
e_beg.marker = (d->nesting_ == 1 && nargs()) ? marker() : NO_MARKER;
mrow.push_back(e_beg);
@ -335,12 +358,37 @@ bool MathMacro::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
}
MathRow::Element e_end(mi, MathRow::END_MACRO);
e_end.macro = this;
e_end.inset = this;
mrow.push_back(e_end);
return has_contents;
}
void MathMacro::beforeMetrics() const
{
d->macro_->lock();
}
void MathMacro::afterMetrics() const
{
d->macro_->unlock();
}
void MathMacro::beforeDraw(PainterInfo const & pi) const
{
if (d->editing_[pi.base.bv])
pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend);
}
void MathMacro::afterDraw(PainterInfo const & pi) const
{
if (d->editing_[pi.base.bv])
pi.pain.leaveMonochromeMode();
}
Inset * MathMacro::clone() const
{
@ -720,13 +768,14 @@ void MathMacro::draw(PainterInfo & pi, int x, int y) const
pi.pain.rectangle(expx, expy - dim.asc + 1, dim.wid - 3,
dim.height() - 2, Color_mathmacroframe);
} else {
bool drawBox = lyxrc.macro_edit_style == LyXRC::MACRO_EDIT_INLINE_BOX;
bool drawBox = lyxrc.macro_edit_style == LyXRC::MACRO_EDIT_INLINE_BOX
&& d->editing_[pi.base.bv];
// warm up cells
for (size_t i = 0; i < nargs(); ++i)
cell(i).setXY(*pi.base.bv, x, y);
if (drawBox && d->editing_[pi.base.bv]) {
if (drawBox) {
// draw header and rectangle around
FontInfo font = pi.base.font;
augmentFont(font, "lyxtex");
@ -740,16 +789,13 @@ void MathMacro::draw(PainterInfo & pi, int x, int y) const
expx += (dim.wid - d->expanded_.dimension(*pi.base.bv).width()) / 2;
}
if (d->editing_[pi.base.bv]) {
pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend);
d->expanded_.draw(pi, expx, expy);
pi.pain.leaveMonochromeMode();
beforeDraw(pi);
d->expanded_.draw(pi, expx, expy);
afterDraw(pi);
if (drawBox)
pi.pain.rectangle(x, y - dim.asc, dim.wid,
dim.height(), Color_mathmacroframe);
} else
d->expanded_.draw(pi, expx, expy);
if (drawBox)
pi.pain.rectangle(x, y - dim.asc, dim.wid,
dim.height(), Color_mathmacroframe);
}
// edit mode changed?

View File

@ -42,14 +42,23 @@ public:
/// the row. Otherwise, just insert the inset.
bool addToMathRow(MathRow &, MetricsInfo & mi) const;
///
void draw(PainterInfo & pi, int x, int y) const;
/// draw selection background
void drawSelection(PainterInfo & pi, int x, int y) const;
void beforeMetrics() const;
///
void afterMetrics() const;
///
void beforeDraw(PainterInfo const &) const;
///
void afterDraw(PainterInfo const &) const;
///
void metrics(MetricsInfo & mi, Dimension & dim) const;
/// was the macro in edit mode when computing metrics?
bool editMetrics(BufferView const * bv) const;
///
void draw(PainterInfo & pi, int x, int y) const;
/// draw selection background
void drawSelection(PainterInfo & pi, int x, int y) const;
///
int kerning(BufferView const * bv) const;
/// get cursor position
void cursorPos(BufferView const & bv, CursorSlice const & sl,

View File

@ -15,7 +15,6 @@
#include "InsetMath.h"
#include "MathClass.h"
#include "MathData.h"
#include "MathMacro.h"
#include "MathSupport.h"
#include "BufferView.h"
@ -39,7 +38,7 @@ namespace lyx {
MathRow::Element::Element(MetricsInfo const & mi, Type t, MathClass mc)
: type(t), mclass(mc), before(0), after(0), macro_nesting(mi.base.macro_nesting),
marker(InsetMath::NO_MARKER), inset(0), compl_unique_to(0),
macro(0), color(Color_red)
color(Color_red)
{}
@ -133,7 +132,7 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
dim.wid = 0;
// In order to compute the dimension of macros and their
// arguments, it is necessary to keep track of them.
map<MathMacro const *, Dimension> dim_macros;
map<InsetMath const *, Dimension> dim_insets;
map<MathData const *, Dimension> dim_arrays;
CoordCache & coords = mi.base.bv->coordCache();
for (Element const & e : elements_) {
@ -148,28 +147,26 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
coords.insets().add(e.inset, d);
break;
case BEG_MACRO:
e.macro->macro()->lock();
e.inset->beforeMetrics();
// Add a macro to current list
dim_macros[e.macro] = Dimension();
dim_insets[e.inset] = Dimension();
break;
case END_MACRO:
LATTEST(dim_macros.find(e.macro) != dim_macros.end());
e.macro->macro()->unlock();
LATTEST(dim_insets.find(e.inset) != dim_insets.end());
e.inset->afterMetrics();
// Cache the dimension of the macro and remove it from
// tracking map.
coords.insets().add(e.macro, dim_macros[e.macro]);
dim_macros.erase(e.macro);
coords.insets().add(e.inset, dim_insets[e.inset]);
dim_insets.erase(e.inset);
break;
// This is basically like macros
case BEG_ARG:
if (e.macro)
e.macro->macro()->unlock();
e.inset->beforeMetrics();
dim_arrays[e.ar] = Dimension();
break;
case END_ARG:
LATTEST(dim_arrays.find(e.ar) != dim_arrays.end());
if (e.macro)
e.macro->macro()->lock();
e.inset->afterMetrics();
coords.arrays().add(e.ar, dim_arrays[e.ar]);
dim_arrays.erase(e.ar);
break;
@ -200,7 +197,7 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
if (!d.empty()) {
dim += d;
// Now add the dimension to current macros and arguments.
for (auto & dim_macro : dim_macros)
for (auto & dim_macro : dim_insets)
dim_macro.second += d;
for (auto & dim_array : dim_arrays)
dim_array.second += d;
@ -212,7 +209,7 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
augmentFont(font, "mathnormal");
dim.wid += mathed_string_width(font, e.compl_text);
}
LATTEST(dim_macros.empty() && dim_arrays.empty());
LATTEST(dim_insets.empty() && dim_arrays.empty());
}
@ -275,25 +272,19 @@ void MathRow::draw(PainterInfo & pi, int x, int const y) const
break;
}
case BEG_MACRO:
coords.insets().add(e.macro, x, y);
coords.insets().add(e.inset, x, y);
drawMarkers(pi, e, x, y);
if (e.macro->editMetrics(pi.base.bv))
pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend);
e.inset->beforeDraw(pi);
break;
case END_MACRO:
if (e.macro->editMetrics(pi.base.bv))
pi.pain.leaveMonochromeMode();
e.inset->afterDraw(pi);
break;
case BEG_ARG:
coords.arrays().add(e.ar, x, y);
// if the macro is being edited, then the painter is in
// monochrome mode.
if (e.macro->editMetrics(pi.base.bv))
pi.pain.leaveMonochromeMode();
e.inset->beforeDraw(pi);
break;
case END_ARG:
if (e.macro->editMetrics(pi.base.bv))
pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend);
e.inset->afterDraw(pi);
break;
case BOX: {
if (e.color == Color_none)
@ -354,8 +345,8 @@ ostream & operator<<(ostream & os, MathRow::Element const & e)
<< "-" << e.after << ">";
break;
case MathRow::BEG_MACRO:
os << "\\" << to_utf8(e.macro->name())
<< "^" << e.macro->nesting() << "[";
os << "\\" << to_utf8(e.inset->name())
<< "^" << e.macro_nesting << "[";
break;
case MathRow::END_MACRO:
os << "]";

View File

@ -30,7 +30,6 @@ class PainterInfo;
class InsetMath;
class MathData;
class MathMacro;
/*
* While for editing purpose it is important that macros are counted
@ -81,10 +80,6 @@ public:
// the number of characters forming the unique part.
size_t compl_unique_to;
/// When type is BEG_MACRO, END_MACRO, BEG_ARG, END_ARG
/// the math macro
MathMacro const * macro;
// type is BEG_ARG, END_ARG
MathData const * ar;