mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-26 19:25:39 +00:00
Move selection painting closer to row painting. Single row painting is now possible for selection.
* Row: - setSelection(): set selection begin and end for this row. - sel_beg, sel_end: new public members. * BufferView::draw() - do not trigger a full repaint for selection. - use TextMetrics::draw() instead of hand calling TextMetrics::drawParagraph(). * InsetText::draw(): don't call TextMetrics::drawSelection(). * InsetMathMBox::drawSelection(): remove. * TextMetrics: - drawSelection(): simplify a bit. Now private. - redoParagraph(): memorize Row selection status. - x2pos(): fix crash when selecting with PageDown. - draw(): fill-in the ParPos cache before everything else and not in drawParagraph(). - drawParagraph(): take care of row selection painting. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20066 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
9044e9d68a
commit
eed6514dd0
@ -1539,8 +1539,7 @@ void BufferView::draw(frontend::Painter & pain)
|
|||||||
// FIXME: We should also distinguish DecorationUpdate to avoid text
|
// FIXME: We should also distinguish DecorationUpdate to avoid text
|
||||||
// drawing if possible. This is not possible to do easily right now
|
// drawing if possible. This is not possible to do easily right now
|
||||||
// because of the single backing pixmap.
|
// because of the single backing pixmap.
|
||||||
pi.full_repaint = select
|
pi.full_repaint = metrics_info_.update_strategy != SingleParUpdate;
|
||||||
|| metrics_info_.update_strategy != SingleParUpdate;
|
|
||||||
|
|
||||||
if (pi.full_repaint)
|
if (pi.full_repaint)
|
||||||
// Clear background (if not delegated to rows)
|
// Clear background (if not delegated to rows)
|
||||||
@ -1548,20 +1547,13 @@ void BufferView::draw(frontend::Painter & pain)
|
|||||||
metrics_info_.y2 - metrics_info_.y1,
|
metrics_info_.y2 - metrics_info_.y1,
|
||||||
buffer_.inset().backgroundColor());
|
buffer_.inset().backgroundColor());
|
||||||
|
|
||||||
TextMetrics const & tm = text_metrics_[&text];
|
|
||||||
|
|
||||||
if (select)
|
|
||||||
tm.drawSelection(pi, 0, 0);
|
|
||||||
|
|
||||||
int yy = metrics_info_.y1;
|
|
||||||
// draw contents
|
|
||||||
LYXERR(Debug::PAINTING) << "\t\t*** START DRAWING ***" << endl;
|
LYXERR(Debug::PAINTING) << "\t\t*** START DRAWING ***" << endl;
|
||||||
for (pit_type pit = metrics_info_.p1; pit <= metrics_info_.p2; ++pit) {
|
TextMetrics const & tm = text_metrics_[&text];
|
||||||
ParagraphMetrics const & pm = tm.parMetrics(pit);
|
if (!pi.full_repaint)
|
||||||
yy += pm.ascent();
|
tm.drawParagraph(pi, metrics_info_.p1, 0,
|
||||||
tm.drawParagraph(pi, pit, 0, yy);
|
metrics_info_.y1 + tm.parMetrics(metrics_info_.p1).ascent());
|
||||||
yy += pm.descent();
|
else
|
||||||
}
|
tm.draw(pi, 0, metrics_info_.y1 + tm.parMetrics(metrics_info_.p1).ascent());
|
||||||
LYXERR(Debug::PAINTING) << "\n\t\t*** END DRAWING ***" << endl;
|
LYXERR(Debug::PAINTING) << "\n\t\t*** END DRAWING ***" << endl;
|
||||||
|
|
||||||
// and grey out above (should not happen later)
|
// and grey out above (should not happen later)
|
||||||
|
32
src/Row.cpp
32
src/Row.cpp
@ -25,13 +25,13 @@ namespace lyx {
|
|||||||
|
|
||||||
Row::Row()
|
Row::Row()
|
||||||
: changed_(false), crc_(0), pos_(0), end_(0), separator(0), hfill(0),
|
: changed_(false), crc_(0), pos_(0), end_(0), separator(0), hfill(0),
|
||||||
label_hfill(0), x(0)
|
label_hfill(0), x(0), sel_beg(-1), sel_end(-1)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
Row::Row(pos_type pos)
|
Row::Row(pos_type pos)
|
||||||
: changed_(false), crc_(0), pos_(pos), end_(0), separator(0), hfill(0),
|
: changed_(false), crc_(0), pos_(pos), end_(0), separator(0), hfill(0),
|
||||||
label_hfill(0), x(0)
|
label_hfill(0), x(0), sel_beg(-1), sel_end(-1)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -61,6 +61,34 @@ void Row::endpos(pos_type p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Row::setSelection(pos_type beg, pos_type end)
|
||||||
|
{
|
||||||
|
pos_type sel_beg_b = sel_beg;
|
||||||
|
if (pos_ >= beg && pos_ <= end)
|
||||||
|
sel_beg = pos_;
|
||||||
|
else if (beg > pos_ && beg <= end_)
|
||||||
|
sel_beg = beg;
|
||||||
|
else
|
||||||
|
sel_beg = -1;
|
||||||
|
|
||||||
|
pos_type sel_end_b = sel_end;
|
||||||
|
if (end_ >= beg && end_ <= end)
|
||||||
|
sel_end = end_;
|
||||||
|
else if (end < end_ && end >= pos_)
|
||||||
|
sel_end = end;
|
||||||
|
else
|
||||||
|
sel_end = -1;
|
||||||
|
/*
|
||||||
|
&& ((rit->pos() >= beg.pos() && rit->pos() <= end.pos())
|
||||||
|
|| (rit->endpos() >= beg.pos() && rit->endpos() <= end.pos())
|
||||||
|
|| (beg.pos() >= rit->pos() && beg.pos() <= rit->endpos())
|
||||||
|
|| (end.pos() >= rit->pos() && end.pos() <= rit->endpos()));
|
||||||
|
*/
|
||||||
|
changed_ |= sel_beg_b != sel_beg;
|
||||||
|
changed_ |= sel_end_b != sel_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Row::dump(const char * s) const
|
void Row::dump(const char * s) const
|
||||||
{
|
{
|
||||||
lyxerr << s << " pos: " << pos_ << " end: " << end_
|
lyxerr << s << " pos: " << pos_ << " end: " << end_
|
||||||
|
@ -39,6 +39,9 @@ public:
|
|||||||
void setChanged(bool c) { changed_ = c; }
|
void setChanged(bool c) { changed_ = c; }
|
||||||
///
|
///
|
||||||
void setCrc(size_type crc);
|
void setCrc(size_type crc);
|
||||||
|
///
|
||||||
|
void setSelection(pos_type sel_beg, pos_type sel_end);
|
||||||
|
|
||||||
///
|
///
|
||||||
void pos(pos_type p);
|
void pos(pos_type p);
|
||||||
///
|
///
|
||||||
@ -71,6 +74,11 @@ public:
|
|||||||
double label_hfill;
|
double label_hfill;
|
||||||
/// the x position of the row
|
/// the x position of the row
|
||||||
double x;
|
double x;
|
||||||
|
///
|
||||||
|
pos_type sel_beg;
|
||||||
|
///
|
||||||
|
pos_type sel_end;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// has the Row appearance changed since last drawing?
|
/// has the Row appearance changed since last drawing?
|
||||||
|
@ -361,6 +361,28 @@ bool TextMetrics::redoParagraph(pit_type const pit)
|
|||||||
changed |= (old_dim != dim);
|
changed |= (old_dim != dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cursor const & cur = bv_->cursor();
|
||||||
|
DocIterator sel_beg = cur.selectionBegin();
|
||||||
|
DocIterator sel_end = cur.selectionEnd();
|
||||||
|
bool selection = cur.selection()
|
||||||
|
// This is out text.
|
||||||
|
&& cur.text() == text_
|
||||||
|
// if the anchor is outside, this is not our selection
|
||||||
|
&& cur.anchor().text() == text_
|
||||||
|
&& pit >= sel_beg.pit() && pit <= sel_end.pit();
|
||||||
|
|
||||||
|
// We care only about visible selection.
|
||||||
|
if (selection) {
|
||||||
|
if (pit != sel_beg.pit()) {
|
||||||
|
sel_beg.pit() = pit;
|
||||||
|
sel_beg.pos() = 0;
|
||||||
|
}
|
||||||
|
if (pit != sel_end.pit()) {
|
||||||
|
sel_end.pit() = pit;
|
||||||
|
sel_end.pos() = sel_end.lastpos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
par.setBeginOfBody();
|
par.setBeginOfBody();
|
||||||
pos_type first = 0;
|
pos_type first = 0;
|
||||||
size_t row_index = 0;
|
size_t row_index = 0;
|
||||||
@ -383,6 +405,10 @@ bool TextMetrics::redoParagraph(pit_type const pit)
|
|||||||
row.setChanged(false);
|
row.setChanged(false);
|
||||||
row.pos(first);
|
row.pos(first);
|
||||||
row.endpos(end);
|
row.endpos(end);
|
||||||
|
if (selection)
|
||||||
|
row.setSelection(sel_beg.pos(), sel_end.pos());
|
||||||
|
else
|
||||||
|
row.setSelection(-1, -1);
|
||||||
row.setDimension(dim);
|
row.setDimension(dim);
|
||||||
computeRowMetrics(pit, row);
|
computeRowMetrics(pit, row);
|
||||||
pm.computeRowSignature(row, bparams);
|
pm.computeRowSignature(row, bparams);
|
||||||
@ -1094,8 +1120,12 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
|||||||
|
|
||||||
pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const
|
pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const
|
||||||
{
|
{
|
||||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
// We play safe and use parMetrics(pit) to make sure the
|
||||||
BOOST_ASSERT(!pm.rows().empty());
|
// ParagraphMetrics will be redone and OK to use if needed.
|
||||||
|
// Otherwise we would use an empty ParagraphMetrics in
|
||||||
|
// upDownInText() while in selection mode.
|
||||||
|
ParagraphMetrics const & pm = parMetrics(pit);
|
||||||
|
|
||||||
BOOST_ASSERT(row < int(pm.rows().size()));
|
BOOST_ASSERT(row < int(pm.rows().size()));
|
||||||
bool bound = false;
|
bool bound = false;
|
||||||
Row const & r = pm.rows()[row];
|
Row const & r = pm.rows()[row];
|
||||||
@ -1772,13 +1802,18 @@ void TextMetrics::draw(PainterInfo & pi, int x, int y) const
|
|||||||
if (par_metrics_.empty())
|
if (par_metrics_.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
CoordCache::InnerParPosCache & ppcache = bv_->coordCache().parPos()[text_];
|
||||||
|
|
||||||
ParMetricsCache::const_iterator it = par_metrics_.begin();
|
ParMetricsCache::const_iterator it = par_metrics_.begin();
|
||||||
ParMetricsCache::const_iterator const end = par_metrics_.end();
|
ParMetricsCache::const_iterator const pm_end = par_metrics_.end();
|
||||||
y -= it->second.ascent();
|
y -= it->second.ascent();
|
||||||
for (; it != end; ++it) {
|
for (; it != pm_end; ++it) {
|
||||||
ParagraphMetrics const & pmi = it->second;
|
ParagraphMetrics const & pmi = it->second;
|
||||||
y += pmi.ascent();
|
y += pmi.ascent();
|
||||||
drawParagraph(pi, it->first, x, y);
|
pit_type const pit = it->first;
|
||||||
|
// Save the paragraph position in the cache.
|
||||||
|
ppcache[pit] = Point(x, y);
|
||||||
|
drawParagraph(pi, pit, x, y);
|
||||||
y += pmi.descent();
|
y += pmi.descent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1789,8 +1824,6 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
|
|||||||
// lyxerr << " paintPar: pit: " << pit << " at y: " << y << endl;
|
// lyxerr << " paintPar: pit: " << pit << " at y: " << y << endl;
|
||||||
int const ww = bv_->workHeight();
|
int const ww = bv_->workHeight();
|
||||||
|
|
||||||
bv_->coordCache().parPos()[text_][pit] = Point(x, y);
|
|
||||||
|
|
||||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
ParagraphMetrics const & pm = par_metrics_[pit];
|
||||||
if (pm.rows().empty())
|
if (pm.rows().empty())
|
||||||
return;
|
return;
|
||||||
@ -1813,7 +1846,9 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
|
|||||||
// Row signature; has row changed since last paint?
|
// Row signature; has row changed since last paint?
|
||||||
bool row_has_changed = rit->changed();
|
bool row_has_changed = rit->changed();
|
||||||
|
|
||||||
if (!pi.full_repaint && !row_has_changed) {
|
bool row_selection = rit->sel_beg != -1 && rit->sel_end != -1;
|
||||||
|
|
||||||
|
if (!row_selection && !pi.full_repaint && !row_has_changed) {
|
||||||
// Paint the only the insets if the text itself is
|
// Paint the only the insets if the text itself is
|
||||||
// unchanged.
|
// unchanged.
|
||||||
rp.paintOnlyInsets();
|
rp.paintOnlyInsets();
|
||||||
@ -1825,11 +1860,25 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
|
|||||||
// changed.
|
// changed.
|
||||||
// Clear background of this row
|
// Clear background of this row
|
||||||
// (if paragraph background was not cleared)
|
// (if paragraph background was not cleared)
|
||||||
if (!pi.full_repaint && row_has_changed) {
|
if (row_selection || (!pi.full_repaint && row_has_changed)) {
|
||||||
pi.pain.fillRectangle(x, y - rit->ascent(),
|
pi.pain.fillRectangle(x, y - rit->ascent(),
|
||||||
width(), rit->height(),
|
width(), rit->height(),
|
||||||
Color_color(Color::color(pi.background_color)));
|
Color_color(Color::color(pi.background_color)));
|
||||||
}
|
}
|
||||||
|
if (row_selection) {
|
||||||
|
lyxerr << "row selected" << endl;
|
||||||
|
DocIterator beg = bv_->cursor().selectionBegin();
|
||||||
|
DocIterator end = bv_->cursor().selectionEnd();
|
||||||
|
beg.pit() = pit;
|
||||||
|
beg.pos() = rit->sel_beg;
|
||||||
|
if (pit == end.pit()) {
|
||||||
|
end.pos() = rit->sel_end;
|
||||||
|
} else {
|
||||||
|
end.pit() = pit + 1;
|
||||||
|
end.pos() = 0;
|
||||||
|
}
|
||||||
|
drawSelection(pi, beg, end, x);
|
||||||
|
}
|
||||||
|
|
||||||
// Instrumentation for testing row cache (see also
|
// Instrumentation for testing row cache (see also
|
||||||
// 12 lines lower):
|
// 12 lines lower):
|
||||||
@ -1866,40 +1915,9 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
|
|||||||
|
|
||||||
|
|
||||||
// only used for inset right now. should also be used for main text
|
// only used for inset right now. should also be used for main text
|
||||||
void TextMetrics::drawSelection(PainterInfo & pi, int x, int) const
|
void TextMetrics::drawSelection(PainterInfo & pi,
|
||||||
|
DocIterator const & beg, DocIterator const & end, int x) const
|
||||||
{
|
{
|
||||||
Cursor & cur = bv_->cursor();
|
|
||||||
if (!cur.selection())
|
|
||||||
return;
|
|
||||||
if (!ptr_cmp(cur.text(), text_))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//if the anchor is outside, this is not our selection
|
|
||||||
if (!ptr_cmp(cur.anchor().text(), text_))
|
|
||||||
return;
|
|
||||||
|
|
||||||
LYXERR(Debug::DEBUG)
|
|
||||||
<< BOOST_CURRENT_FUNCTION
|
|
||||||
<< "draw selection at " << x
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
DocIterator beg = cur.selectionBegin();
|
|
||||||
DocIterator end = cur.selectionEnd();
|
|
||||||
|
|
||||||
// the selection doesn't touch the visible screen?
|
|
||||||
if (bv_funcs::status(bv_, beg) == bv_funcs::CUR_BELOW
|
|
||||||
|| bv_funcs::status(bv_, end) == bv_funcs::CUR_ABOVE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (beg.pit() < par_metrics_.begin()->first) {
|
|
||||||
beg.pit() = par_metrics_.begin()->first;
|
|
||||||
beg.pos() = 0;
|
|
||||||
}
|
|
||||||
if (end.pit() > par_metrics_.rbegin()->first) {
|
|
||||||
end.pit() = par_metrics_.rbegin()->first;
|
|
||||||
end.pos() = end.lastpos();
|
|
||||||
}
|
|
||||||
|
|
||||||
ParagraphMetrics const & pm1 = par_metrics_[beg.pit()];
|
ParagraphMetrics const & pm1 = par_metrics_[beg.pit()];
|
||||||
ParagraphMetrics const & pm2 = par_metrics_[end.pit()];
|
ParagraphMetrics const & pm2 = par_metrics_[end.pit()];
|
||||||
Row const & row1 = pm1.getRow(beg.pos(), beg.boundary());
|
Row const & row1 = pm1.getRow(beg.pos(), beg.boundary());
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
TextMetrics(BufferView *, Text *);
|
TextMetrics(BufferView *, Text *);
|
||||||
///
|
///
|
||||||
ParagraphMetrics const & parMetrics(pit_type) const;
|
ParagraphMetrics const & parMetrics(pit_type) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
Dimension const & dimension() const;
|
Dimension const & dimension() const;
|
||||||
Dimension const & dimension();
|
Dimension const & dimension();
|
||||||
@ -107,8 +108,6 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
void draw(PainterInfo & pi, int x, int y) const;
|
void draw(PainterInfo & pi, int x, int y) const;
|
||||||
/// draw textselection
|
|
||||||
void drawSelection(PainterInfo & pi, int x, int y) const;
|
|
||||||
|
|
||||||
void drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) const;
|
void drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) const;
|
||||||
|
|
||||||
@ -116,6 +115,13 @@ private:
|
|||||||
///
|
///
|
||||||
ParagraphMetrics & parMetrics(pit_type, bool redo_paragraph);
|
ParagraphMetrics & parMetrics(pit_type, bool redo_paragraph);
|
||||||
|
|
||||||
|
/// draw textselection.
|
||||||
|
/// FIXME: simplify to just to single row painting.
|
||||||
|
void drawSelection(PainterInfo & pi,
|
||||||
|
DocIterator const & beg, ///< selection begin.
|
||||||
|
DocIterator const & end, ///< selection end.
|
||||||
|
int x) const;
|
||||||
|
|
||||||
/// the minimum space a manual label needs on the screen in pixels
|
/// the minimum space a manual label needs on the screen in pixels
|
||||||
int labelFill(pit_type const pit, Row const & row) const;
|
int labelFill(pit_type const pit, Row const & row) const;
|
||||||
|
|
||||||
|
@ -195,7 +195,6 @@ void InsetText::draw(PainterInfo & pi, int x, int y) const
|
|||||||
if (drawFrame_)
|
if (drawFrame_)
|
||||||
pi.pain.rectangle(x, y - a, w, h, frameColor());
|
pi.pain.rectangle(x, y - a, w, h, frameColor());
|
||||||
}
|
}
|
||||||
tm.drawSelection(pi, x + border_, y);
|
|
||||||
tm.draw(pi, x + border_, y);
|
tm.draw(pi, x + border_, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +122,4 @@ void InsetMathMBox::cursorPos(BufferView const & bv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InsetMathMBox::drawSelection(PainterInfo & pi, int x, int y) const
|
|
||||||
{
|
|
||||||
pi.base.bv->textMetrics(&text_).drawSelection(pi, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace lyx
|
} // namespace lyx
|
||||||
|
@ -38,8 +38,6 @@ public:
|
|||||||
/// draw according to cached metrics
|
/// draw according to cached metrics
|
||||||
void draw(PainterInfo &, int x, int y) const;
|
void draw(PainterInfo &, int x, int y) const;
|
||||||
///
|
///
|
||||||
void drawSelection(PainterInfo & pi, int x, int y) const;
|
|
||||||
///
|
|
||||||
bool inMathed() const { return false; }
|
bool inMathed() const { return false; }
|
||||||
///
|
///
|
||||||
bool isActive() const { return true; }
|
bool isActive() const { return true; }
|
||||||
|
Loading…
Reference in New Issue
Block a user