mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Only display a blue rectangle for editable empty insets
Empty insets should use a minimal amount of space, especially when they are part of a built-in macro in lib/symbols. With this change, blue rectangles signal actually editable places. Empty macros in editable data are shown as grey boxes, but they do not appear when further nested. This is done by adding a new type BOX of MathRow::Element object and a MetricsInfo::macro_nesting that keeps track of macros (and is reset to 0 in editable macro arguments).
This commit is contained in:
parent
0b5c2a8507
commit
f3f9b083d1
@ -32,6 +32,8 @@ public:
|
||||
void operator+=(Dimension const & dim);
|
||||
/// set to empty box
|
||||
void clear() { wid = asc = des = 0; }
|
||||
/// check if box is empty
|
||||
bool empty() const { return wid == 0 && asc == 0 && wid == 0; }
|
||||
/// get height
|
||||
int height() const { return asc + des; }
|
||||
/// get ascent
|
||||
|
@ -88,7 +88,7 @@ Changer MetricsBase::changeFontSet(string const & name, bool cond)
|
||||
|
||||
MetricsInfo::MetricsInfo(BufferView * bv, FontInfo font, int textwidth,
|
||||
MacroContext const & mc)
|
||||
: base(bv, font, textwidth), macrocontext(mc)
|
||||
: base(bv, font, textwidth), macro_nesting(0), macrocontext(mc)
|
||||
{}
|
||||
|
||||
|
||||
|
@ -101,6 +101,8 @@ public:
|
||||
|
||||
///
|
||||
MetricsBase base;
|
||||
/// count wether the current mathdata is nested in macro(s)
|
||||
int macro_nesting;
|
||||
/// The context to resolve macros
|
||||
MacroContext const & macrocontext;
|
||||
};
|
||||
|
@ -56,9 +56,9 @@ MathClass InsetMath::mathClass() const
|
||||
}
|
||||
|
||||
|
||||
bool InsetMath::addToMathRow(MathRow & mrow, MetricsInfo const &) const
|
||||
bool InsetMath::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
|
||||
{
|
||||
MathRow::Element e;
|
||||
MathRow::Element e(MathRow::INSET, mi);
|
||||
e.inset = this;
|
||||
e.mclass = mathClass();
|
||||
mrow.push_back(e);
|
||||
|
@ -167,7 +167,7 @@ public:
|
||||
/// The class of the math object (used primarily for spacing)
|
||||
virtual MathClass mathClass() const;
|
||||
/// Add this inset to a math row. Return true if contents got added
|
||||
virtual bool addToMathRow(MathRow &, MetricsInfo const & mi) const;
|
||||
virtual bool addToMathRow(MathRow &, MetricsInfo & mi) const;
|
||||
|
||||
/// identifies things that can get scripts
|
||||
virtual bool isScriptable() const { return false; }
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "mathed/InsetMathUnknown.h"
|
||||
|
||||
#include "frontends/FontMetrics.h"
|
||||
#include "frontends/Painter.h"
|
||||
|
||||
#include "support/debug.h"
|
||||
#include "support/docstream.h"
|
||||
@ -217,7 +216,7 @@ void MathData::touch() const
|
||||
}
|
||||
|
||||
|
||||
bool MathData::addToMathRow(MathRow & mrow, MetricsInfo const & mi) const
|
||||
bool MathData::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
|
||||
{
|
||||
bool has_contents = false;
|
||||
BufferView * bv = mi.base.bv;
|
||||
@ -275,12 +274,6 @@ void MathData::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
slevel_ = (4 * xascent) / 5;
|
||||
sshift_ = xascent / 4;
|
||||
|
||||
if (empty()) {
|
||||
// Cache the dimension.
|
||||
mi.base.bv->coordCache().arrays().add(this, dim);
|
||||
return;
|
||||
}
|
||||
|
||||
MathRow mrow(mi, this);
|
||||
mrow_cache_[mi.base.bv] = mrow;
|
||||
mrow.metrics(mi, dim);
|
||||
@ -299,11 +292,6 @@ void MathData::draw(PainterInfo & pi, int const x, int const y) const
|
||||
|
||||
Dimension const & dim = bv.coordCache().getArrays().dim(this);
|
||||
|
||||
if (empty()) {
|
||||
pi.pain.rectangle(x, y - dim.ascent(), dim.width(), dim.height(), Color_mathline);
|
||||
return;
|
||||
}
|
||||
|
||||
// don't draw outside the workarea
|
||||
if (y + dim.descent() <= 0
|
||||
|| y - dim.ascent() >= bv.workHeight()
|
||||
|
@ -122,7 +122,7 @@ public:
|
||||
MathAtom const & operator[](pos_type) const;
|
||||
|
||||
/// Add this array to a math row. Return true if contents got added
|
||||
bool addToMathRow(MathRow &, MetricsInfo const & mi) const;
|
||||
bool addToMathRow(MathRow &, MetricsInfo & mi) const;
|
||||
|
||||
/// rebuild cached metrics information
|
||||
void metrics(MetricsInfo & mi, Dimension & dim) const;
|
||||
|
@ -68,28 +68,49 @@ public:
|
||||
///
|
||||
InsetCode lyxCode() const { return ARGUMENT_PROXY_CODE; }
|
||||
///
|
||||
bool addToMathRow(MathRow & mrow, MetricsInfo const & mi) const
|
||||
bool addToMathRow(MathRow & mrow, MetricsInfo & mi) const
|
||||
{
|
||||
MathRow::Element e(MathRow::BEG_ARG);
|
||||
e.macro = mathMacro_;
|
||||
e.ar = &mathMacro_->cell(idx_);
|
||||
mrow.push_back(e);
|
||||
// macro arguments are in macros
|
||||
LATTEST(mi.macro_nesting > 0);
|
||||
if (mi.macro_nesting == 1)
|
||||
mi.macro_nesting = 0;
|
||||
|
||||
MathRow::Element e_beg(MathRow::BEG_ARG, mi);
|
||||
e_beg.macro = mathMacro_;
|
||||
e_beg.ar = &mathMacro_->cell(idx_);
|
||||
mrow.push_back(e_beg);
|
||||
|
||||
mathMacro_->macro()->unlock();
|
||||
bool const has_contents = mathMacro_->cell(idx_).addToMathRow(mrow, mi);
|
||||
bool has_contents = mathMacro_->cell(idx_).addToMathRow(mrow, mi);
|
||||
mathMacro_->macro()->lock();
|
||||
|
||||
e.type = MathRow::END_ARG;
|
||||
mrow.push_back(e);
|
||||
// if there was no contents, and the contents is editable,
|
||||
// then we insert a box instead.
|
||||
if (!has_contents && mi.macro_nesting == 0) {
|
||||
MathRow::Element e(MathRow::BOX, mi);
|
||||
e.color = Color_mathline;
|
||||
mrow.push_back(e);
|
||||
has_contents = true;
|
||||
}
|
||||
|
||||
if (has_contents)
|
||||
return true;
|
||||
// if there was no contents, then we insert the empty macro inset
|
||||
// instead.
|
||||
return InsetMath::addToMathRow(mrow, mi);
|
||||
if (mi.macro_nesting == 0)
|
||||
mi.macro_nesting = 1;
|
||||
|
||||
MathRow::Element e_end(MathRow::END_ARG, mi);
|
||||
e_end.macro = mathMacro_;
|
||||
e_end.ar = &mathMacro_->cell(idx_);
|
||||
|
||||
mrow.push_back(e_end);
|
||||
|
||||
return has_contents;
|
||||
}
|
||||
///
|
||||
void metrics(MetricsInfo & mi, Dimension & dim) const {
|
||||
// macro arguments are in macros
|
||||
LATTEST(mi.macro_nesting > 0);
|
||||
if (mi.macro_nesting == 1)
|
||||
mi.macro_nesting = 0;
|
||||
|
||||
mathMacro_->macro()->unlock();
|
||||
mathMacro_->cell(idx_).metrics(mi, dim);
|
||||
|
||||
@ -98,6 +119,8 @@ public:
|
||||
def_.metrics(mi, dim);
|
||||
|
||||
mathMacro_->macro()->lock();
|
||||
if (mi.macro_nesting == 0)
|
||||
mi.macro_nesting = 1;
|
||||
}
|
||||
// write(), normalize(), infoize() and infoize2() are not needed since
|
||||
// MathMacro uses the definition and not the expanded cells.
|
||||
@ -287,31 +310,42 @@ MathMacro::~MathMacro()
|
||||
}
|
||||
|
||||
|
||||
bool MathMacro::addToMathRow(MathRow & mrow, MetricsInfo const & mi) const
|
||||
bool MathMacro::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
|
||||
{
|
||||
// set edit mode for which we will have calculated row.
|
||||
// This is the same as what is done in metrics().
|
||||
d->editing_[mi.base.bv] = editMode(mi.base.bv);
|
||||
|
||||
if (displayMode() == MathMacro::DISPLAY_NORMAL
|
||||
&& !d->editing_[mi.base.bv]) {
|
||||
MathRow::Element e(MathRow::BEG_MACRO);
|
||||
e.macro = this;
|
||||
if (displayMode() != MathMacro::DISPLAY_NORMAL
|
||||
|| d->editing_[mi.base.bv])
|
||||
return InsetMath::addToMathRow(mrow, mi);
|
||||
|
||||
MathRow::Element e_beg(MathRow::BEG_MACRO, mi);
|
||||
e_beg.macro = this;
|
||||
mrow.push_back(e_beg);
|
||||
|
||||
++mi.macro_nesting;
|
||||
|
||||
d->macro_->lock();
|
||||
bool has_contents = d->expanded_.addToMathRow(mrow, mi);
|
||||
d->macro_->unlock();
|
||||
|
||||
// if there was no contents and the array is editable, then we
|
||||
// insert a grey box instead.
|
||||
if (!has_contents && mi.macro_nesting == 1) {
|
||||
MathRow::Element e(MathRow::BOX, mi);
|
||||
e.color = Color_mathmacroblend;
|
||||
mrow.push_back(e);
|
||||
|
||||
d->macro_->lock();
|
||||
bool const has_contents = d->expanded_.addToMathRow(mrow, mi);
|
||||
d->macro_->unlock();
|
||||
|
||||
e.type = MathRow::END_MACRO;
|
||||
mrow.push_back(e);
|
||||
|
||||
if (has_contents)
|
||||
return true;
|
||||
// if there was no contents, then we insert the empty macro inset
|
||||
// instead.
|
||||
has_contents = true;
|
||||
}
|
||||
return InsetMath::addToMathRow(mrow, mi);
|
||||
|
||||
--mi.macro_nesting;
|
||||
|
||||
MathRow::Element e_end(MathRow::END_MACRO, mi);
|
||||
e_end.macro = this;
|
||||
mrow.push_back(e_end);
|
||||
|
||||
return has_contents;
|
||||
}
|
||||
|
||||
|
||||
@ -407,6 +441,9 @@ bool MathMacro::editMetrics(BufferView const * bv) const
|
||||
|
||||
void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
{
|
||||
// the macro contents is not editable (except the arguments)
|
||||
++mi.macro_nesting;
|
||||
|
||||
// set edit mode for which we will have calculated metrics. But only
|
||||
d->editing_[mi.base.bv] = editMode(mi.base.bv);
|
||||
|
||||
@ -495,6 +532,9 @@ void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
dim.des += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// restore macro nesting
|
||||
--mi.macro_nesting;
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
///
|
||||
/// If the macro is in normal edit mode, dissolve its contents in
|
||||
/// the row. Otherwise, just insert the inset.
|
||||
bool addToMathRow(MathRow &, MetricsInfo const & mi) const;
|
||||
bool addToMathRow(MathRow &, MetricsInfo & mi) const;
|
||||
///
|
||||
void draw(PainterInfo & pi, int x, int y) const;
|
||||
/// draw selection background
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "CoordCache.h"
|
||||
#include "MetricsInfo.h"
|
||||
|
||||
#include "frontends/FontMetrics.h"
|
||||
#include "frontends/Painter.h"
|
||||
|
||||
#include "support/debug.h"
|
||||
@ -35,26 +36,33 @@ using namespace std;
|
||||
namespace lyx {
|
||||
|
||||
|
||||
MathRow::Element::Element(Type t, MathClass const mc)
|
||||
: type(t),
|
||||
inset(0), mclass(mc), before(0), after(0), compl_unique_to(0),
|
||||
macro(0)
|
||||
MathRow::Element::Element(Type t, MetricsInfo &mi)
|
||||
: type(t), macro_nesting(mi.macro_nesting),
|
||||
inset(0), mclass(MC_ORD), before(0), after(0), compl_unique_to(0),
|
||||
macro(0), color(Color_red)
|
||||
{}
|
||||
|
||||
|
||||
MathRow::MathRow(MetricsInfo const & mi, MathData const * ar)
|
||||
MathRow::MathRow(MetricsInfo & mi, MathData const * ar)
|
||||
{
|
||||
if (ar->empty())
|
||||
return;
|
||||
|
||||
// First there is a dummy element of type "open"
|
||||
push_back(Element(BEGIN, MC_OPEN));
|
||||
push_back(Element(BEGIN, mi));
|
||||
back().mclass = MC_OPEN;
|
||||
|
||||
// Then insert the MathData argument
|
||||
ar->addToMathRow(*this, mi);
|
||||
bool const has_contents = ar->addToMathRow(*this, mi);
|
||||
|
||||
// empty arrays are visible when they are editable
|
||||
// we reserve the necessary space anyway (even if nothing gets drawn)
|
||||
if (!has_contents) {
|
||||
Element e(BOX, mi);
|
||||
e.color = Color_mathline;
|
||||
push_back(e);
|
||||
}
|
||||
|
||||
// Finally there is a dummy element of type "close"
|
||||
push_back(Element(END, MC_CLOSE));
|
||||
push_back(Element(END, mi));
|
||||
back().mclass = MC_CLOSE;
|
||||
|
||||
/* Do spacing only in math mode. This test is a bit clumsy,
|
||||
* but it is used in other places for guessing the current mode.
|
||||
@ -120,9 +128,9 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
map<MathMacro const *, Dimension> dim_macros;
|
||||
map<MathData const *, Dimension> dim_arrays;
|
||||
CoordCache & coords = mi.base.bv->coordCache();
|
||||
|
||||
for (Element const & e : elements_) {
|
||||
Dimension d;
|
||||
mi.macro_nesting = e.macro_nesting;
|
||||
switch (e.type) {
|
||||
case BEGIN:
|
||||
case END:
|
||||
@ -131,12 +139,6 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
e.inset->metrics(mi, d);
|
||||
d.wid += e.before + e.after;
|
||||
coords.insets().add(e.inset, d);
|
||||
dim += d;
|
||||
// Now add the dimension to current macros and arguments.
|
||||
for (auto & dim_macro : dim_macros)
|
||||
dim_macro.second += d;
|
||||
for (auto & dim_array : dim_arrays)
|
||||
dim_array.second += d;
|
||||
break;
|
||||
case BEG_MACRO:
|
||||
e.macro->macro()->lock();
|
||||
@ -164,6 +166,19 @@ void MathRow::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
coords.arrays().add(e.ar, dim_arrays[e.ar]);
|
||||
dim_arrays.erase(e.ar);
|
||||
break;
|
||||
case BOX:
|
||||
d = theFontMetrics(mi.base.font).dimension('I');
|
||||
d.wid += e.before + e.after;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!d.empty()) {
|
||||
dim += d;
|
||||
// Now add the dimension to current macros and arguments.
|
||||
for (auto & dim_macro : dim_macros)
|
||||
dim_macro.second += d;
|
||||
for (auto & dim_array : dim_arrays)
|
||||
dim_array.second += d;
|
||||
}
|
||||
|
||||
if (e.compl_text.empty())
|
||||
@ -180,7 +195,6 @@ void MathRow::draw(PainterInfo & pi, int x, int const y) const
|
||||
{
|
||||
CoordCache & coords = pi.base.bv->coordCache();
|
||||
for (Element const & e : elements_) {
|
||||
Dimension d;
|
||||
switch (e.type) {
|
||||
case INSET: {
|
||||
// This is hackish: the math inset does not know that space
|
||||
@ -211,6 +225,15 @@ void MathRow::draw(PainterInfo & pi, int x, int const y) const
|
||||
if (e.macro->editMetrics(pi.base.bv))
|
||||
pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend);
|
||||
break;
|
||||
case BOX: {
|
||||
Dimension const d = theFontMetrics(pi.base.font).dimension('I');
|
||||
// the box is not visible in non-editable context (except for grey macro boxes).
|
||||
if (e.macro_nesting == 0 || e.color == Color_mathmacroblend)
|
||||
pi.pain.rectangle(x + e.before, y - d.ascent(),
|
||||
d.width(), d.height(), e.color);
|
||||
x += d.wid;
|
||||
break;
|
||||
}
|
||||
case BEGIN:
|
||||
case END:
|
||||
case END_MACRO:
|
||||
@ -277,6 +300,9 @@ ostream & operator<<(ostream & os, MathRow::Element const & e)
|
||||
case MathRow::END_ARG:
|
||||
os << ")";
|
||||
break;
|
||||
case MathRow::BOX:
|
||||
os << "@";
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#include "MathClass.h"
|
||||
|
||||
#include "ColorCode.h"
|
||||
|
||||
#include "support/docstring.h"
|
||||
|
||||
#include <vector>
|
||||
@ -51,16 +53,19 @@ public:
|
||||
END_ARG, // a macro argument ends here
|
||||
BEGIN, // dummy element before row
|
||||
END, // dummy element after row
|
||||
BOX // an empty box
|
||||
};
|
||||
|
||||
// An elements, together with its spacing
|
||||
struct Element
|
||||
{
|
||||
///
|
||||
Element(Type t = INSET, MathClass const mc = MC_ORD);
|
||||
Element(Type t, MetricsInfo & mi);
|
||||
|
||||
/// Classifies the contents of the object
|
||||
Type type;
|
||||
/// count wether the current mathdata is nested in macro(s)
|
||||
int macro_nesting;
|
||||
|
||||
/// When type is INSET
|
||||
/// the math inset
|
||||
@ -80,6 +85,9 @@ public:
|
||||
|
||||
// type is BEG_ARG, END_ARG
|
||||
MathData const * ar;
|
||||
|
||||
// type is BOX
|
||||
ColorCode color;
|
||||
};
|
||||
|
||||
///
|
||||
@ -105,7 +113,7 @@ public:
|
||||
|
||||
// create the math row by unwinding all macros in the MathData and
|
||||
// compute the spacings.
|
||||
MathRow(MetricsInfo const & mi, MathData const * ar);
|
||||
MathRow(MetricsInfo & mi, MathData const * ar);
|
||||
|
||||
//
|
||||
void metrics(MetricsInfo & mi, Dimension & dim) const;
|
||||
|
Loading…
Reference in New Issue
Block a user