From: Guillaume Munch Date: Mon, 23 May 2016 09:01:29 +0000 (+0100) Subject: Change tracking cue: InsetText and InsetCollapsible X-Git-Tag: 2.3.0alpha1~1343 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=f151b932c248f7d78e54c085cd942d0aa9e4c475;p=features.git Change tracking cue: InsetText and InsetCollapsible * Underline or strike through the label as if it was text (it is). * Strike through deleted InsetText, but let RowPainter handle the case of non-MultiPar text insets. * Change the colour of the frame as a cue, unless its colour is customised (not Color_foreground). (Essentially do the border of CharStyles like Tabular does it already.) * The change info needs to be reset when entering InsetText. Otherwise labels are painted with the change of their n+1-th parent. --- diff --git a/src/insets/InsetCollapsable.cpp b/src/insets/InsetCollapsable.cpp index 294c826466..520d902dcb 100644 --- a/src/insets/InsetCollapsable.cpp +++ b/src/insets/InsetCollapsable.cpp @@ -33,6 +33,7 @@ #include "support/gettext.h" #include "support/lassert.h" #include "support/lstrings.h" +#include "support/RefChanger.h" using namespace std; @@ -228,9 +229,7 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const view_[&bv].auto_open_ = bv.cursor().isInside(this); - FontInfo tmpfont = pi.base.font; - pi.base.font = getFont(); - pi.base.font.realize(tmpfont); + Changer dummy = pi.base.font.change(getFont(), true); // Draw button first -- top, left or only Dimension dimc = dimensionCollapsed(bv); @@ -246,7 +245,11 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const FontInfo labelfont = getLabelfont(); labelfont.setColor(labelColor()); pi.pain.buttonText(x, y, buttonLabel(bv), labelfont, - view_[&bv].mouse_hover_); + view_[&bv].mouse_hover_); + // Draw the change tracking cue on the label, unless RowPainter already + // takes care of it. + if (canPaintChange(bv)) + pi.change_.paintCue(pi, x, y, x + dimc.width(), labelfont); } else { view_[&bv].button_dim_.x1 = 0; view_[&bv].button_dim_.y1 = 0; @@ -257,17 +260,24 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const Dimension const textdim = InsetText::dimension(bv); int const baseline = y; int textx, texty; - switch (geometry(bv)) { + Geometry g = geometry(bv); + switch (g) { case LeftButton: - textx = x + dimc.width(); - texty = baseline; - InsetText::draw(pi, textx, texty); - break; - case TopButton: - textx = x; - texty = baseline + dimc.des + textdim.asc; + case TopButton: { + if (g == LeftButton) { + textx = x + dimc.width(); + texty = baseline; + } else { + textx = x; + texty = baseline + dimc.des + textdim.asc; + } + // Do not draw the cue for INSERTED -- it is already in the button and + // that's enough. + Changer dummy = make_change(pi.change_, Change(), + pi.change_.type == Change::INSERTED); InsetText::draw(pi, textx, texty); break; + } case ButtonOnly: break; case NoButton: @@ -279,38 +289,43 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const case Corners: textx = x; texty = baseline; - const_cast(this)->setDrawFrame(false); - InsetText::draw(pi, textx, texty); - const_cast(this)->setDrawFrame(true); + { // We will take care of the frame and the change tracking cue + // ourselves, below. + Changer dummy = make_change(pi.change_, Change()); + const_cast(this)->setDrawFrame(false); + InsetText::draw(pi, textx, texty); + const_cast(this)->setDrawFrame(true); + } int desc = textdim.descent(); - if (geometry(bv) == Corners) + if (g == Corners) desc -= 3; + // Colour the frame according to the change type. (Like for tables.) + Color colour = pi.change_.changed() ? pi.change_.color() + : Color_foreground; const int xx1 = x + TEXT_TO_INSET_OFFSET - 1; const int xx2 = x + textdim.wid - TEXT_TO_INSET_OFFSET + 1; pi.pain.line(xx1, y + desc - 4, - xx1, y + desc, - Color_foreground); + xx1, y + desc, colour); if (status_ == Open) pi.pain.line(xx1, y + desc, - xx2, y + desc, - Color_foreground); + xx2, y + desc, colour); else { // Make status_ value visible: pi.pain.line(xx1, y + desc, - xx1 + 4, y + desc, - Color_foreground); + xx1 + 4, y + desc, colour); pi.pain.line(xx2 - 4, y + desc, - xx2, y + desc, - Color_foreground); + xx2, y + desc, colour); } pi.pain.line(x + textdim.wid - 3, y + desc, x + textdim.wid - 3, - y + desc - 4, Color_foreground); + y + desc - 4, colour); // the label below the text. Can be toggled. - if (geometry(bv) == SubLabel) { + if (g == SubLabel) { FontInfo font(getLabelfont()); + if (pi.change_.changed()) + font.setPaintColor(colour); font.realize(sane_font); font.decSize(); font.decSize(); @@ -323,20 +338,21 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const buttonLabel(bv), font, Color_none, Color_none); } + int const y1 = y - textdim.asc + 3; // a visual cue when the cursor is inside the inset Cursor const & cur = bv.cursor(); if (cur.isInside(this)) { - y -= textdim.asc; - y += 3; - pi.pain.line(xx1, y + 4, xx1, y, Color_foreground); - pi.pain.line(xx1 + 4, y, xx1, y, Color_foreground); - pi.pain.line(xx2, y + 4, xx2, y, Color_foreground); - pi.pain.line(xx2 - 4, y, xx2, y, Color_foreground); + pi.pain.line(xx1, y1 + 4, xx1, y1, colour); + pi.pain.line(xx1 + 4, y1, xx1, y1, colour); + pi.pain.line(xx2, y1 + 4, xx2, y1, colour); + pi.pain.line(xx2 - 4, y1, xx2, y1, colour); } + // Strike through the inset if deleted and not already handled by + // RowPainter. + if (pi.change_.deleted() && canPaintChange(bv)) + pi.change_.paintCue(pi, xx1, y1, xx2, y + desc); break; } - - pi.base.font = tmpfont; } @@ -618,16 +634,18 @@ string InsetCollapsable::contextMenuName() const bool InsetCollapsable::canPaintChange(BufferView const & bv) const { + // return false to let RowPainter draw the change tracking cue consistently + // with the surrounding text, when the inset is inline: for buttons, for + // non-allowMultiPar insets. switch (geometry(bv)) { case Corners: case SubLabel: + return allowMultiPar(); case ButtonOnly: - // these cases are handled by RowPainter since the inset is inline. return false; default: break; } - // TODO: implement the drawing in the remaining cases return true; } diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp index 7d28020669..99b1381f93 100644 --- a/src/insets/InsetText.cpp +++ b/src/insets/InsetText.cpp @@ -56,13 +56,13 @@ #include "frontends/alert.h" #include "frontends/Painter.h" +#include "support/bind.h" #include "support/convert.h" #include "support/debug.h" #include "support/gettext.h" -#include "support/lstrings.h" - -#include "support/bind.h" #include "support/lassert.h" +#include "support/lstrings.h" +#include "support/RefChanger.h" #include @@ -215,24 +215,48 @@ void InsetText::draw(PainterInfo & pi, int x, int y) const { TextMetrics & tm = pi.base.bv->textMetrics(&text_); + int const w = tm.width() + TEXT_TO_INSET_OFFSET; + int const yframe = y - TEXT_TO_INSET_OFFSET - tm.ascent(); + int const h = tm.height() + 2 * TEXT_TO_INSET_OFFSET; + int const xframe = x + TEXT_TO_INSET_OFFSET / 2; + bool change_drawn = false; if (drawFrame_ || pi.full_repaint) { - int const w = tm.width() + TEXT_TO_INSET_OFFSET; - int const yframe = y - TEXT_TO_INSET_OFFSET - tm.ascent(); - int const h = tm.height() + 2 * TEXT_TO_INSET_OFFSET; - int const xframe = x + TEXT_TO_INSET_OFFSET / 2; if (pi.full_repaint) pi.pain.fillRectangle(xframe, yframe, w, h, pi.backgroundColor(this)); + // Change color of the frame in tracked changes, like for tabulars. + // Only do so if the color is not custom. But do so even if RowPainter + // handles the strike-through already. + Color c; + if (pi.change_.changed() + // Originally, these are the colors with role Text, from role() in + // ColorCache.cpp. The code is duplicated to avoid depending on Qt + // types, and also maybe it need not match in the future. + && (frameColor() == Color_foreground + || frameColor() == Color_cursor + || frameColor() == Color_preview + || frameColor() == Color_tabularline + || frameColor() == Color_previewframe)) { + c = pi.change_.color(); + change_drawn = true; + } else + c = frameColor(); if (drawFrame_) - pi.pain.rectangle(xframe, yframe, w, h, frameColor()); + pi.pain.rectangle(xframe, yframe, w, h, c); } - ColorCode const old_color = pi.background_color; - pi.background_color = pi.backgroundColor(this, false); - - tm.draw(pi, x + TEXT_TO_INSET_OFFSET, y); - - pi.background_color = old_color; + { + Changer dummy = make_change(pi.background_color, + pi.backgroundColor(this, false)); + // The change tracking cue must not be inherited + Changer dummy2 = make_change(pi.change_, Change()); + tm.draw(pi, x + TEXT_TO_INSET_OFFSET, y); + } + if (canPaintChange(*pi.base.bv) && (!change_drawn || pi.change_.deleted())) + // Do not draw the change tracking cue if already done by RowPainter and + // do not draw the cue for INSERTED if the information is already in the + // color of the frame + pi.change_.paintCue(pi, xframe, yframe, xframe + w, yframe + h); } diff --git a/src/insets/InsetText.h b/src/insets/InsetText.h index 3718e1d1d3..8df1bdfce2 100644 --- a/src/insets/InsetText.h +++ b/src/insets/InsetText.h @@ -63,8 +63,8 @@ public: bool editable() const { return true; } /// bool canTrackChanges() const { return true; } - /// - bool canPaintChange(BufferView const &) const { return false; } + /// Rely on RowPainter to draw the cue of inline insets. + bool canPaintChange(BufferView const &) const { return allowMultiPar(); } /// InsetText * asInsetText() { return this; } ///