Fix display of InsetCollapsable with split views

When several bufferviews exist for the same inset, the data that depends on the view width have to be BufferView-dependent. While this is the case for several mutable members of InsetCollapsable, some were missing.

This commit makes button_dim_ (renamed from button_dim) and openinlined_ bv-dependent.

Get rid of the hitButton function.

Remove the bv-independent geometry() method and implement editable() explicitely instead.

Fixes bug #9756.
This commit is contained in:
Jean-Marc Lasgouttes 2016-02-03 10:37:29 +01:00 committed by Richard Heck
parent f23a8fed80
commit fd6ae3539b
2 changed files with 40 additions and 65 deletions

View File

@ -40,7 +40,7 @@ using namespace std;
namespace lyx { namespace lyx {
InsetCollapsable::InsetCollapsable(Buffer * buf, InsetText::UsePlain ltype) InsetCollapsable::InsetCollapsable(Buffer * buf, InsetText::UsePlain ltype)
: InsetText(buf, ltype), status_(Open), openinlined_(false) : InsetText(buf, ltype), status_(Open)
{ {
setDrawFrame(true); setDrawFrame(true);
setFrameColor(Color_collapsableframe); setFrameColor(Color_collapsableframe);
@ -53,7 +53,7 @@ InsetCollapsable::InsetCollapsable(InsetCollapsable const & rhs)
: InsetText(rhs), : InsetText(rhs),
status_(rhs.status_), status_(rhs.status_),
labelstring_(rhs.labelstring_), labelstring_(rhs.labelstring_),
button_dim(rhs.button_dim), button_dim_(rhs.button_dim_),
openinlined_(rhs.openinlined_) openinlined_(rhs.openinlined_)
{} {}
@ -81,7 +81,7 @@ InsetCollapsable::Geometry InsetCollapsable::geometry(BufferView const & bv) con
switch (decoration()) { switch (decoration()) {
case InsetLayout::CLASSIC: case InsetLayout::CLASSIC:
if (status(bv) == Open) if (status(bv) == Open)
return openinlined_ ? LeftButton : TopButton; return openinlined_[&bv] ? LeftButton : TopButton;
return ButtonOnly; return ButtonOnly;
case InsetLayout::MINIMALISTIC: case InsetLayout::MINIMALISTIC:
@ -100,30 +100,6 @@ InsetCollapsable::Geometry InsetCollapsable::geometry(BufferView const & bv) con
} }
InsetCollapsable::Geometry InsetCollapsable::geometry() const
{
switch (decoration()) {
case InsetLayout::CLASSIC:
if (status_ == Open)
return openinlined_ ? LeftButton : TopButton;
return ButtonOnly;
case InsetLayout::MINIMALISTIC:
return status_ == Open ? NoButton : ButtonOnly ;
case InsetLayout::CONGLOMERATE:
return status_ == Open ? SubLabel : Corners ;
case InsetLayout::DEFAULT:
break; // this shouldn't happen
}
// dummy return value to shut down a warning,
// this is dead code.
return NoButton;
}
docstring InsetCollapsable::toolTip(BufferView const & bv, int x, int y) const docstring InsetCollapsable::toolTip(BufferView const & bv, int x, int y) const
{ {
Dimension const dim = dimensionCollapsed(bv); Dimension const dim = dimensionCollapsed(bv);
@ -214,17 +190,16 @@ void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const
case LeftButton: case LeftButton:
case ButtonOnly: case ButtonOnly:
if (hasFixedWidth()){ if (hasFixedWidth()){
int const mindim = button_dim.x2 - button_dim.x1; int const mindim = button_dim_[&bv].x2 - button_dim_[&bv].x1;
if (mi.base.textwidth < mindim) if (mi.base.textwidth < mindim)
mi.base.textwidth = mindim; mi.base.textwidth = mindim;
} }
dim = dimensionCollapsed(bv); dim = dimensionCollapsed(bv);
if (geometry(bv) == TopButton if (geometry(bv) == TopButton || geometry(bv) == LeftButton) {
|| geometry(bv) == LeftButton) {
Dimension textdim; Dimension textdim;
InsetText::metrics(mi, textdim); InsetText::metrics(mi, textdim);
openinlined_ = (textdim.wid + dim.wid) < mi.base.textwidth; openinlined_[&bv] = (textdim.wid + dim.wid) < mi.base.textwidth;
if (openinlined_) { if (openinlined_[&bv]) {
// Correct for button width. // Correct for button width.
dim.wid += textdim.wid; dim.wid += textdim.wid;
dim.des = max(dim.des - textdim.asc + dim.asc, textdim.des); dim.des = max(dim.des - textdim.asc + dim.asc, textdim.des);
@ -265,20 +240,20 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const
if (geometry(bv) == TopButton || if (geometry(bv) == TopButton ||
geometry(bv) == LeftButton || geometry(bv) == LeftButton ||
geometry(bv) == ButtonOnly) { geometry(bv) == ButtonOnly) {
button_dim.x1 = x + 0; button_dim_[&bv].x1 = x + 0;
button_dim.x2 = x + dimc.width(); button_dim_[&bv].x2 = x + dimc.width();
button_dim.y1 = y - dimc.asc; button_dim_[&bv].y1 = y - dimc.asc;
button_dim.y2 = y + dimc.des; button_dim_[&bv].y2 = y + dimc.des;
FontInfo labelfont = getLabelfont(); FontInfo labelfont = getLabelfont();
labelfont.setColor(labelColor()); labelfont.setColor(labelColor());
pi.pain.buttonText(x, y, buttonLabel(bv), labelfont, pi.pain.buttonText(x, y, buttonLabel(bv), labelfont,
mouse_hover_[&bv]); mouse_hover_[&bv]);
} else { } else {
button_dim.x1 = 0; button_dim_[&bv].x1 = 0;
button_dim.y1 = 0; button_dim_[&bv].y1 = 0;
button_dim.x2 = 0; button_dim_[&bv].x2 = 0;
button_dim.y2 = 0; button_dim_[&bv].y2 = 0;
} }
Dimension const textdim = InsetText::dimension(bv); Dimension const textdim = InsetText::dimension(bv);
@ -398,7 +373,13 @@ void InsetCollapsable::cursorPos(BufferView const & bv,
bool InsetCollapsable::editable() const bool InsetCollapsable::editable() const
{ {
return geometry() != ButtonOnly; switch (decoration()) {
case InsetLayout::CLASSIC:
case InsetLayout::MINIMALISTIC:
return status_ == Open;
default:
return true;
}
} }
@ -408,16 +389,9 @@ bool InsetCollapsable::descendable(BufferView const & bv) const
} }
bool InsetCollapsable::hitButton(FuncRequest const & cmd) const bool InsetCollapsable::clickable(BufferView const & bv, int x, int y) const
{ {
return button_dim.contains(cmd.x(), cmd.y()); return button_dim_[&bv].contains(x, y);
}
bool InsetCollapsable::clickable(BufferView const &, int x, int y) const
{
FuncRequest cmd(LFUN_NOACTION, x, y, mouse_button::none);
return hitButton(cmd);
} }
@ -454,8 +428,8 @@ Inset * InsetCollapsable::editXY(Cursor & cur, int x, int y)
{ {
//lyxerr << "InsetCollapsable: edit xy" << endl; //lyxerr << "InsetCollapsable: edit xy" << endl;
if (geometry(cur.bv()) == ButtonOnly if (geometry(cur.bv()) == ButtonOnly
|| (button_dim.contains(x, y) || (button_dim_[&cur.bv()].contains(x, y)
&& geometry(cur.bv()) != NoButton)) && geometry(cur.bv()) != NoButton))
return this; return this;
cur.push(*this); cur.push(*this);
return InsetText::editXY(cur, x, y); return InsetText::editXY(cur, x, y);
@ -467,9 +441,11 @@ void InsetCollapsable::doDispatch(Cursor & cur, FuncRequest & cmd)
//lyxerr << "InsetCollapsable::doDispatch (begin): cmd: " << cmd //lyxerr << "InsetCollapsable::doDispatch (begin): cmd: " << cmd
// << " cur: " << cur << " bvcur: " << cur.bv().cursor() << endl; // << " cur: " << cur << " bvcur: " << cur.bv().cursor() << endl;
bool const hitButton = clickable(cur.bv(), cmd.x(), cmd.y());
switch (cmd.action()) { switch (cmd.action()) {
case LFUN_MOUSE_PRESS: case LFUN_MOUSE_PRESS:
if (hitButton(cmd)) { if (hitButton) {
switch (cmd.button()) { switch (cmd.button()) {
case mouse_button::button1: case mouse_button::button1:
case mouse_button::button3: case mouse_button::button3:
@ -494,7 +470,7 @@ void InsetCollapsable::doDispatch(Cursor & cur, FuncRequest & cmd)
case LFUN_MOUSE_MOTION: case LFUN_MOUSE_MOTION:
case LFUN_MOUSE_DOUBLE: case LFUN_MOUSE_DOUBLE:
case LFUN_MOUSE_TRIPLE: case LFUN_MOUSE_TRIPLE:
if (hitButton(cmd)) if (hitButton)
cur.noScreenUpdate(); cur.noScreenUpdate();
else if (geometry(cur.bv()) != ButtonOnly) else if (geometry(cur.bv()) != ButtonOnly)
InsetText::doDispatch(cur, cmd); InsetText::doDispatch(cur, cmd);
@ -503,7 +479,7 @@ void InsetCollapsable::doDispatch(Cursor & cur, FuncRequest & cmd)
break; break;
case LFUN_MOUSE_RELEASE: case LFUN_MOUSE_RELEASE:
if (!hitButton(cmd)) { if (!hitButton) {
// The mouse click has to be within the inset! // The mouse click has to be within the inset!
if (geometry(cur.bv()) != ButtonOnly) if (geometry(cur.bv()) != ButtonOnly)
InsetText::doDispatch(cur, cmd); InsetText::doDispatch(cur, cmd);

View File

@ -58,18 +58,16 @@ public:
/// return x,y of given position relative to the inset's baseline /// return x,y of given position relative to the inset's baseline
void cursorPos(BufferView const & bv, CursorSlice const & sl, void cursorPos(BufferView const & bv, CursorSlice const & sl,
bool boundary, int & x, int & y) const; bool boundary, int & x, int & y) const;
/// Returns true if (mouse) action is over the inset's button.
/// Always returns false when the inset does not have a
/// button.
bool hitButton(FuncRequest const &) const;
/// ///
docstring const getNewLabel(docstring const & l) const; docstring const getNewLabel(docstring const & l) const;
/// ///
bool editable() const; bool editable() const;
/// ///
bool hasSettings() const { return true; } bool hasSettings() const { return true; }
/// /// Returns true if coordinates are over the inset's button.
bool clickable(BufferView const &, int x, int y) const; /// Always returns false when the inset does not have a
/// button.
bool clickable(BufferView const & bv, int x, int y) const;
/// can we go further down on mouse click? /// can we go further down on mouse click?
bool descendable(BufferView const & bv) const; bool descendable(BufferView const & bv) const;
/// ///
@ -128,8 +126,6 @@ public:
/// (status_), auto_open_[BufferView] and openinlined_, /// (status_), auto_open_[BufferView] and openinlined_,
/// and of course decoration(). /// and of course decoration().
Geometry geometry(BufferView const & bv) const; Geometry geometry(BufferView const & bv) const;
/// Returns the geometry disregarding auto_open_
Geometry geometry() const;
/// ///
bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const; bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;
/// ///
@ -163,10 +159,13 @@ private:
Dimension dimensionCollapsed(BufferView const & bv) const; Dimension dimensionCollapsed(BufferView const & bv) const;
/// ///
docstring labelstring_; docstring labelstring_;
/// FIXME: the variables below should be grouped in a View subclass (as in MVC)
/// ///
mutable Box button_dim; mutable std::map<BufferView const *, Box> button_dim_;
/// a substatus of the Open status, determined automatically in metrics /// a substatus of the Open status, determined automatically in metrics
mutable bool openinlined_; mutable std::map<BufferView const *, bool> openinlined_;
/// the inset will automatically open when the cursor is inside. This is /// the inset will automatically open when the cursor is inside. This is
/// dependent on the bufferview, compare with MathMacro::editing_. /// dependent on the bufferview, compare with MathMacro::editing_.
mutable std::map<BufferView const *, bool> auto_open_; mutable std::map<BufferView const *, bool> auto_open_;