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
|
||||
// drawing if possible. This is not possible to do easily right now
|
||||
// because of the single backing pixmap.
|
||||
pi.full_repaint = select
|
||||
|| metrics_info_.update_strategy != SingleParUpdate;
|
||||
pi.full_repaint = metrics_info_.update_strategy != SingleParUpdate;
|
||||
|
||||
if (pi.full_repaint)
|
||||
// Clear background (if not delegated to rows)
|
||||
@ -1548,20 +1547,13 @@ void BufferView::draw(frontend::Painter & pain)
|
||||
metrics_info_.y2 - metrics_info_.y1,
|
||||
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;
|
||||
for (pit_type pit = metrics_info_.p1; pit <= metrics_info_.p2; ++pit) {
|
||||
ParagraphMetrics const & pm = tm.parMetrics(pit);
|
||||
yy += pm.ascent();
|
||||
tm.drawParagraph(pi, pit, 0, yy);
|
||||
yy += pm.descent();
|
||||
}
|
||||
TextMetrics const & tm = text_metrics_[&text];
|
||||
if (!pi.full_repaint)
|
||||
tm.drawParagraph(pi, metrics_info_.p1, 0,
|
||||
metrics_info_.y1 + tm.parMetrics(metrics_info_.p1).ascent());
|
||||
else
|
||||
tm.draw(pi, 0, metrics_info_.y1 + tm.parMetrics(metrics_info_.p1).ascent());
|
||||
LYXERR(Debug::PAINTING) << "\n\t\t*** END DRAWING ***" << endl;
|
||||
|
||||
// and grey out above (should not happen later)
|
||||
|
32
src/Row.cpp
32
src/Row.cpp
@ -25,13 +25,13 @@ namespace lyx {
|
||||
|
||||
Row::Row()
|
||||
: 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)
|
||||
: 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
|
||||
{
|
||||
lyxerr << s << " pos: " << pos_ << " end: " << end_
|
||||
|
@ -39,6 +39,9 @@ public:
|
||||
void setChanged(bool c) { changed_ = c; }
|
||||
///
|
||||
void setCrc(size_type crc);
|
||||
///
|
||||
void setSelection(pos_type sel_beg, pos_type sel_end);
|
||||
|
||||
///
|
||||
void pos(pos_type p);
|
||||
///
|
||||
@ -71,6 +74,11 @@ public:
|
||||
double label_hfill;
|
||||
/// the x position of the row
|
||||
double x;
|
||||
///
|
||||
pos_type sel_beg;
|
||||
///
|
||||
pos_type sel_end;
|
||||
|
||||
|
||||
private:
|
||||
/// has the Row appearance changed since last drawing?
|
||||
|
@ -361,6 +361,28 @@ bool TextMetrics::redoParagraph(pit_type const pit)
|
||||
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();
|
||||
pos_type first = 0;
|
||||
size_t row_index = 0;
|
||||
@ -383,6 +405,10 @@ bool TextMetrics::redoParagraph(pit_type const pit)
|
||||
row.setChanged(false);
|
||||
row.pos(first);
|
||||
row.endpos(end);
|
||||
if (selection)
|
||||
row.setSelection(sel_beg.pos(), sel_end.pos());
|
||||
else
|
||||
row.setSelection(-1, -1);
|
||||
row.setDimension(dim);
|
||||
computeRowMetrics(pit, row);
|
||||
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
|
||||
{
|
||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
||||
BOOST_ASSERT(!pm.rows().empty());
|
||||
// We play safe and use parMetrics(pit) to make sure the
|
||||
// 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()));
|
||||
bool bound = false;
|
||||
Row const & r = pm.rows()[row];
|
||||
@ -1772,13 +1802,18 @@ void TextMetrics::draw(PainterInfo & pi, int x, int y) const
|
||||
if (par_metrics_.empty())
|
||||
return;
|
||||
|
||||
CoordCache::InnerParPosCache & ppcache = bv_->coordCache().parPos()[text_];
|
||||
|
||||
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();
|
||||
for (; it != end; ++it) {
|
||||
for (; it != pm_end; ++it) {
|
||||
ParagraphMetrics const & pmi = it->second;
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
int const ww = bv_->workHeight();
|
||||
|
||||
bv_->coordCache().parPos()[text_][pit] = Point(x, y);
|
||||
|
||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
||||
if (pm.rows().empty())
|
||||
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?
|
||||
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
|
||||
// unchanged.
|
||||
rp.paintOnlyInsets();
|
||||
@ -1825,11 +1860,25 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co
|
||||
// changed.
|
||||
// Clear background of this row
|
||||
// (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(),
|
||||
width(), rit->height(),
|
||||
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
|
||||
// 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
|
||||
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 & pm2 = par_metrics_[end.pit()];
|
||||
Row const & row1 = pm1.getRow(beg.pos(), beg.boundary());
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
TextMetrics(BufferView *, Text *);
|
||||
///
|
||||
ParagraphMetrics const & parMetrics(pit_type) const;
|
||||
|
||||
///
|
||||
Dimension const & dimension() const;
|
||||
Dimension const & dimension();
|
||||
@ -107,8 +108,6 @@ public:
|
||||
|
||||
///
|
||||
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;
|
||||
|
||||
@ -116,6 +115,13 @@ private:
|
||||
///
|
||||
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
|
||||
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_)
|
||||
pi.pain.rectangle(x, y - a, w, h, frameColor());
|
||||
}
|
||||
tm.drawSelection(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
|
||||
|
@ -38,8 +38,6 @@ public:
|
||||
/// draw according to cached metrics
|
||||
void draw(PainterInfo &, int x, int y) const;
|
||||
///
|
||||
void drawSelection(PainterInfo & pi, int x, int y) const;
|
||||
///
|
||||
bool inMathed() const { return false; }
|
||||
///
|
||||
bool isActive() const { return true; }
|
||||
|
Loading…
Reference in New Issue
Block a user