]> git.lyx.org Git - features.git/commitdiff
Change the way scrolled rows are tracked
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Thu, 21 Feb 2019 16:52:36 +0000 (17:52 +0100)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Thu, 18 Jun 2020 12:39:58 +0000 (14:39 +0200)
The goal of this commit is to simplify the logic in TextMetrics::draw.
Now, rows are repainted depending on their changed() status.

Instead of checking whether rows have been scrolled horizontally at
draw time, the code marks the row as changed when testing for
horizontal scrolling.

To this end a new method TestMetrics::setRowChanged is added, that
searches a row in the text metrics cache and marks it changed if
found.

The old code that remembered the previously scrolled row can now be
removed.

src/BufferView.cpp
src/BufferView.h
src/TextMetrics.cpp
src/TextMetrics.h

index a46420e33962385bb7333f43d9ae6424c9c62549..50df1aade24dd36edb09bbe71c10d6d288b418df 100644 (file)
@@ -316,9 +316,6 @@ struct BufferView::Private
        /// a slice pointing to the start of the row where the cursor
        /// is (at last draw time)
        CursorSlice current_row_slice_;
-       /// a slice pointing to the start of the row where cursor was
-       /// at previous draw event
-       CursorSlice last_row_slice_;
 
        // The vertical size of the blinking caret. Only used for math
        // Using it for text could be bad when undo restores the cursor
@@ -3066,30 +3063,24 @@ int BufferView::horizScrollOffset(Text const * text,
 }
 
 
-bool BufferView::hadHorizScrollOffset(Text const * text,
-                                      pit_type pit, pos_type pos) const
-{
-       return !d->last_row_slice_.empty()
-              && &text->inset() == d->last_row_slice_.inset().asInsetText()
-              && pit ==  d->last_row_slice_.pit()
-              && pos ==  d->last_row_slice_.pos();
-}
-
-
 void BufferView::setCurrentRowSlice(CursorSlice const & rowSlice)
 {
        // nothing to do if the cursor was already on this row
-       if (d->current_row_slice_ == rowSlice) {
-               d->last_row_slice_ = CursorSlice();
+       if (d->current_row_slice_ == rowSlice)
                return;
-       }
 
        // if the (previous) current row was scrolled, we have to
        // remember it in order to repaint it next time.
-       if (d->horiz_scroll_offset_ != 0)
-               d->last_row_slice_ = d->current_row_slice_;
-       else
-               d->last_row_slice_ = CursorSlice();
+       if (d->horiz_scroll_offset_ != 0) {
+               // search the old row in cache and mark it changed
+               for (auto & tm_pair : d->text_metrics_) {
+                       if (&tm_pair.first->inset() == rowSlice.inset().asInsetText()) {
+                               tm_pair.second.setRowChanged(rowSlice.pit(), rowSlice.pos());
+                               // We found it, no need to continue.
+                               break;
+                       }
+               }
+       }
 
        // Since we changed row, the scroll offset is not valid anymore
        d->horiz_scroll_offset_ = 0;
@@ -3146,8 +3137,7 @@ void BufferView::checkCursorScrollOffset()
                       << d->horiz_scroll_offset_ << " to " << offset);
 
        if (d->update_strategy_ == NoScreenUpdate
-           && (offset != d->horiz_scroll_offset_
-               || !d->last_row_slice_.empty())) {
+           && offset != d->horiz_scroll_offset_) {
                // FIXME: if one uses SingleParUpdate, then home/end
                // will not work on long rows. Why?
                d->update_strategy_ = FullScreenUpdate;
index 2478e609349857d2ae1ce47c28f8c8891caff053..5bad57ca0ece1d8d88c4017fe9ffd516cb99dc07 100644 (file)
@@ -146,11 +146,6 @@ public:
        int horizScrollOffset(Text const * text,
                              pit_type pit, pos_type pos) const;
 
-       // Returns true if the row of text starting at (pit, pos) was scrolled
-       // at the last draw event.
-       bool hadHorizScrollOffset(Text const * text,
-                              pit_type pit, pos_type pos) const;
-
        /// reset the scrollbar to reflect current view position.
        void updateScrollbar();
        /// return the Scrollbar Parameters.
index 28d0d87b0eed8ee82146e1c7d1dc941f1117770f..88ffa6f874bef6aa8f9badab41a9615235081d01 100644 (file)
@@ -159,6 +159,16 @@ bool TextMetrics::isFirstRow(Row const & row) const
 }
 
 
+void TextMetrics::setRowChanged(pit_type pit, pos_type pos)
+{
+       for (auto & pm_pair : par_metrics_)
+               if (pm_pair.first == pit)
+                       for (Row & row : pm_pair.second.rows())
+                               if (row.pos() == pos)
+                                       row.changed(true);
+}
+
+
 ParagraphMetrics & TextMetrics::parMetrics(pit_type pit, bool redo)
 {
        ParMetricsCache::iterator pmc_it = par_metrics_.find(pit);
@@ -1872,12 +1882,8 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                                row.change(row.end_margin_sel, sel_end.pit() > pit);
                }
 
-               // has row changed since last paint?
-               bool row_has_changed = row.changed()
-                       || bv_->hadHorizScrollOffset(text_, pit, row.pos());
-
                // Take this opportunity to spellcheck the row contents.
-               if (row_has_changed && pi.do_spellcheck && lyxrc.spellcheck_continuously) {
+               if (row.changed() && pi.do_spellcheck && lyxrc.spellcheck_continuously) {
                        text_->getPar(pit).spellCheck();
                }
 
@@ -1885,7 +1891,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
 
                // Don't paint the row if a full repaint has not been requested
                // and if it has not changed.
-               if (!pi.full_repaint && !row_has_changed) {
+               if (!pi.full_repaint && !row.changed()) {
                        // Paint only the insets if the text itself is
                        // unchanged.
                        rp.paintOnlyInsets();
@@ -1896,7 +1902,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
 
                // Clear background of this row if paragraph background was not
                // already cleared because of a full repaint.
-               if (!pi.full_repaint && row_has_changed) {
+               if (!pi.full_repaint && row.changed()) {
                        LYXERR(Debug::PAINTING, "Clear rect@("
                               << max(row_x, 0) << ", " << y - row.ascent() << ")="
                               << width() << " x " << row.height());
@@ -1915,13 +1921,13 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                // Instrumentation for testing row cache (see also
                // 12 lines lower):
                if (lyxerr.debugging(Debug::PAINTING)
-                   && (row.selection() || pi.full_repaint || row_has_changed)) {
+                   && (row.selection() || pi.full_repaint || row.changed())) {
                        string const foreword = text_->isMainText() ? "main text redraw "
                                : "inset text redraw: ";
                        LYXERR0(foreword << "pit=" << pit << " row=" << i
                                << (row.selection() ? " row_selection": "")
                                << (pi.full_repaint ? " full_repaint" : "")
-                               << (row_has_changed ? " row_has_changed" : ""));
+                               << (row.changed() ? " row.changed" : ""));
                }
 
                // Backup full_repaint status and force full repaint
index ba1371fd878409de693d55189e1fdd694faa9ded..26156fa100b48ae8fa439bacbe08f4d0c831dcf5 100644 (file)
@@ -49,6 +49,8 @@ public:
        bool isLastRow(Row const & row) const;
        /// is this row the first in the text?
        bool isFirstRow(Row const & row) const;
+       ///
+       void setRowChanged(pit_type pit, pos_type pos);
 
        ///
        Dimension const & dim() const { return dim_; }