Change tracking cue: paint over labels in text and prepare for further work

* Inset::canTrackChange() had two meanings: can it deal with change tracking?
  Will it paint its own CT status? The latter information is now given by
  Inset::canPaintChange().

* Line thickness computation is moved from RowPainter to MetricsBase.

* Painting function for Changes moved to lyx::Change. (One new, that strikes
  diagonally.)
This commit is contained in:
Guillaume Munch 2016-05-22 22:48:28 +01:00
parent e2bc7ffae3
commit 760bca8265
11 changed files with 146 additions and 53 deletions

View File

@ -19,6 +19,7 @@
#include "BufferParams.h"
#include "Encoding.h"
#include "LaTeXFeatures.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "Paragraph.h"
#include "TocBackend.h"
@ -30,6 +31,8 @@
#include "support/mutex.h"
#include "frontends/alert.h"
#include "frontends/FontMetrics.h"
#include "frontends/Painter.h"
#include <ostream>
@ -37,6 +40,9 @@ using namespace std;
namespace lyx {
using frontend::Painter;
using frontend::FontMetrics;
/*
* Class Change has a changetime field that specifies the exact time at which
* a specific change was made. The change time is used as a guidance for the
@ -545,6 +551,46 @@ void Changes::updateBuffer(Buffer const & buf)
}
void Change::paintCue(PainterInfo & pi, double const x1, double const y,
double const x2, FontInfo const & font) const
{
if (!changed())
return;
// Calculate 1/3 height of font
FontMetrics const & fm = theFontMetrics(font);
int const y_bar = deleted() ? y - fm.maxAscent() / 3
: y + 2 * pi.base.solidLineOffset() + pi.base.solidLineThickness();
pi.pain.line(int(x1), y_bar, int(x2), y_bar, color(),
Painter::line_solid, pi.base.solidLineThickness());
}
void Change::paintCue(PainterInfo & pi, double const x1, double const y1,
double const x2, double const y2) const
{
/*
* y1 /
* /
* /
* /
* /
* y2 /_____
* x1 x2
*/
double y = 0;
switch(type) {
case UNCHANGED:
return;
case INSERTED:
y = y2;
break;
case DELETED:
y = y1;
break;
}
pi.pain.line(x1, y2, x2, y, color(), Painter::line_solid,
pi.base.solidLineThickness());
}
} // namespace lyx

View File

@ -32,6 +32,8 @@ class AuthorList;
class Buffer;
class DocIterator;
class OutputParams;
class PainterInfo;
class FontInfo;
class Change {
public:
@ -64,6 +66,20 @@ public:
/// Is this change made by the current author ?
bool currentAuthor() const { return author == 0; }
/// Paint under- or strike-through line
///
/// Text : underline or strike through
/// \param x1 begin
/// \param x2 end
/// \param y baseline
void paintCue(PainterInfo & pi, double const x1, double const y,
double const x2, FontInfo const & font) const;
/// Box : line below or diagonal
/// \param x1,y1 top-left corner
/// \param x2,y2 bottom-right corner
void paintCue(PainterInfo & pi, double const x1, double const y1,
double const x2, double const y2) const;
Type type;
int author;

View File

@ -12,6 +12,7 @@
#include "BufferView.h"
#include "ColorSet.h"
#include "LyXRC.h"
#include "MetricsInfo.h"
#include "insets/Inset.h"
@ -36,15 +37,33 @@ namespace lyx {
/////////////////////////////////////////////////////////////////////////
MetricsBase::MetricsBase()
: bv(0), font(), style(LM_ST_TEXT), fontname("mathnormal"),
textwidth(0)
{}
: bv(0), font(), style(LM_ST_TEXT), fontname("mathnormal"), textwidth(0),
solid_line_thickness_(1), solid_line_offset_(1), dotted_line_thickness_(1)
{
if (lyxrc.zoom >= 200) {
// derive the line thickness from zoom factor
// the zoom is given in percent
// (increase thickness at 250%, 450% etc.)
solid_line_thickness_ = (lyxrc.zoom + 50) / 200;
// adjust line_offset_ too
solid_line_offset_ = 1 + solid_line_thickness_ / 2;
}
if (lyxrc.zoom >= 100) {
// derive the line thickness from zoom factor
// the zoom is given in percent
// (increase thickness at 150%, 250% etc.)
dotted_line_thickness_ = (lyxrc.zoom + 50) / 100;
}
}
MetricsBase::MetricsBase(BufferView * b, FontInfo const & f, int w)
: bv(b), font(f), style(LM_ST_TEXT), fontname("mathnormal"),
textwidth(w)
{}
MetricsBase::MetricsBase(BufferView * b, FontInfo f, int w)
: MetricsBase()
{
bv = b;
font = f;
textwidth = w;
}
Changer MetricsBase::changeFontSet(docstring const & name, bool cond)
@ -80,8 +99,8 @@ Changer MetricsBase::changeFontSet(char const * name, bool cond)
//
/////////////////////////////////////////////////////////////////////////
MetricsInfo::MetricsInfo(BufferView * bv, FontInfo const & font, int textwidth,
MacroContext const & mc)
MetricsInfo::MetricsInfo(BufferView * bv, FontInfo font, int textwidth,
MacroContext const & mc)
: base(bv, font, textwidth), macrocontext(mc)
{}

View File

@ -54,7 +54,7 @@ public:
///
MetricsBase();
///
MetricsBase(BufferView * bv, FontInfo const & font, int textwidth);
MetricsBase(BufferView * bv, FontInfo font, int textwidth);
/// the current view
BufferView * bv;
@ -76,6 +76,16 @@ public:
Changer changeFrac(bool cond = true);
// Temporarily change the style to (script)script style
Changer changeScript(bool cond = true);
///
int solidLineThickness() const { return solid_line_thickness_; }
///
int solidLineOffset() const { return solid_line_offset_; }
///
int dottedLineThickness() const { return dotted_line_thickness_; }
private:
int solid_line_thickness_;
int solid_line_offset_;
int dotted_line_thickness_;
};
@ -88,7 +98,8 @@ public:
///
MetricsInfo();
///
MetricsInfo(BufferView * bv, FontInfo const & font, int textwidth, MacroContext const & mc);
MetricsInfo(BufferView * bv, FontInfo font, int textwidth,
MacroContext const & mc);
///
MetricsBase base;

View File

@ -60,25 +60,8 @@ RowPainter::RowPainter(PainterInfo & pi,
pars_(text.paragraphs()),
row_(row), par_(text.paragraphs()[row.pit()]),
pm_(text_metrics_.parMetrics(row.pit())), change_(pi_.change_),
xo_(x), yo_(y), width_(text_metrics_.width()),
solid_line_thickness_(1), solid_line_offset_(1),
dotted_line_thickness_(1)
xo_(x), yo_(y), width_(text_metrics_.width())
{
if (lyxrc.zoom >= 200) {
// derive the line thickness from zoom factor
// the zoom is given in percent
// (increase thickness at 250%, 450% etc.)
solid_line_thickness_ = (lyxrc.zoom + 50) / 200;
// adjust line_offset_ too
solid_line_offset_ = 1 + solid_line_thickness_ / 2;
}
if (lyxrc.zoom >= 100) {
// derive the line thickness from zoom factor
// the zoom is given in percent
// (increase thickness at 150%, 250% etc.)
dotted_line_thickness_ = (lyxrc.zoom + 50) / 100;
}
x_ = row_.left_margin + xo_;
//lyxerr << "RowPainter: x: " << x_ << " xo: " << xo_ << " yo: " << yo_ << endl;
@ -165,9 +148,10 @@ void RowPainter::paintForeignMark(Row::Element const & e) const
return;
int const desc = e.inset ? e.dim.descent() : 0;
int const y = yo_ + solid_line_offset_ + desc + solid_line_thickness_ / 2;
int const y = yo_ + pi_.base.solidLineOffset()
+ desc + pi_.base.solidLineThickness() / 2;
pi_.pain.line(int(x_), y, int(x_ + e.full_width()), y, Color_language,
Painter::line_solid, solid_line_thickness_);
Painter::line_solid, pi_.base.solidLineThickness());
}
@ -177,8 +161,8 @@ void RowPainter::paintMisspelledMark(Row::Element const & e) const
// to avoid drawing at the same vertical offset
FontMetrics const & fm = theFontMetrics(e.font);
int const thickness = max(fm.lineWidth(), 2);
int const y = yo_ + solid_line_offset_ + solid_line_thickness_
+ (e.change.changed() ? solid_line_thickness_ + 1 : 0)
int const y = yo_ + pi_.base.solidLineOffset() + pi_.base.solidLineThickness()
+ (e.change.changed() ? pi_.base.solidLineThickness() + 1 : 0)
+ 1 + thickness / 2;
//FIXME: this could be computed only once, it is probably not costly.
@ -255,14 +239,7 @@ void RowPainter::paintStringAndSel(Row::Element const & e) const
void RowPainter::paintChange(Row::Element const & e) const
{
if (!e.change.changed())
return;
// Calculate 1/3 height of font
FontMetrics const & fm = theFontMetrics(e.font);
int const y_bar = e.change.deleted() ? yo_ - fm.maxAscent() / 3
: yo_ + 2 * solid_line_offset_ + solid_line_thickness_;
pi_.pain.line(int(x_), y_bar, int(x_ + e.full_width()), y_bar,
e.change.color(), Painter::line_solid, solid_line_thickness_);
e.change.paintCue(pi_, x_, yo_, x_ + e.full_width(), e.font.fontInfo());
}
@ -373,16 +350,17 @@ void RowPainter::paintAppendixStart(int y) const
void RowPainter::paintTooLargeMarks(bool const left, bool const right) const
{
if (left)
pi_.pain.line(dotted_line_thickness_, yo_ - row_.ascent(),
dotted_line_thickness_, yo_ + row_.descent(),
Color_scroll,
Painter::line_onoffdash, dotted_line_thickness_);
pi_.pain.line(pi_.base.dottedLineThickness(), yo_ - row_.ascent(),
pi_.base.dottedLineThickness(), yo_ + row_.descent(),
Color_scroll, Painter::line_onoffdash,
pi_.base.dottedLineThickness());
if (right) {
int const wwidth = pi_.base.bv->workWidth() - dotted_line_thickness_;
int const wwidth =
pi_.base.bv->workWidth() - pi_.base.dottedLineThickness();
pi_.pain.line(wwidth, yo_ - row_.ascent(),
wwidth, yo_ + row_.descent(),
Color_scroll,
Painter::line_onoffdash, dotted_line_thickness_);
Color_scroll, Painter::line_onoffdash,
pi_.base.dottedLineThickness());
}
}
@ -611,8 +589,8 @@ void RowPainter::paintText()
// The line that indicates word in a different language
paintForeignMark(e);
// change tracking (not for insets that track their own changes)
if (e.type != Row::INSET || ! e.inset->canTrackChanges())
// change tracking (not for insets that handle it themselves)
if (e.type != Row::INSET || ! e.inset->canPaintChange(*pi_.base.bv))
paintChange(e);
x_ += e.full_width();

View File

@ -97,9 +97,6 @@ private:
int const yo_; // current baseline
double x_;
int width_;
int solid_line_thickness_;
int solid_line_offset_;
int dotted_line_thickness_;
};
} // namespace lyx

View File

@ -352,6 +352,9 @@ public:
/// does this contain text that can be change track marked in DVI?
virtual bool canTrackChanges() const { return false; }
/// Will this inset paint its own change tracking status (in the parent
/// paragraph) or will it let RowPainter handle it?
virtual bool canPaintChange(BufferView const &) const { return false; }
/// return true if the inset should be removed automatically
virtual bool autoDelete() const;

View File

@ -615,4 +615,21 @@ string InsetCollapsable::contextMenuName() const
return "context-collapsable";
}
bool InsetCollapsable::canPaintChange(BufferView const & bv) const
{
switch (geometry(bv)) {
case Corners:
case SubLabel:
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;
}
} // namespace lyx

View File

@ -127,6 +127,8 @@ public:
/// and of course decoration().
Geometry geometry(BufferView const & bv) const;
///
bool canPaintChange(BufferView const & bv) const;
///
bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;
///
bool setMouseHover(BufferView const * bv, bool mouse_hover) const;

View File

@ -877,6 +877,8 @@ public:
bool allowSpellCheck() const { return true; }
///
bool canTrackChanges() const { return true; }
///
bool canPaintChange(BufferView const &) const { return true; }
/** returns false if, when outputing LaTeX, font changes should
be closed before generating this inset. This is needed for
insets that may contain several paragraphs */

View File

@ -64,6 +64,8 @@ public:
///
bool canTrackChanges() const { return true; }
///
bool canPaintChange(BufferView const &) const { return false; }
///
InsetText * asInsetText() { return this; }
///
InsetText const * asInsetText() const { return this; }