]> git.lyx.org Git - lyx.git/blobdiff - src/BufferView.cpp
Fix bug #12772
[lyx.git] / src / BufferView.cpp
index d3cf909ea351fd2c74547bd3f41adc9c85814725..9931c3f3dd949d510dc7017d7bc7e041283ad262 100644 (file)
@@ -186,7 +186,7 @@ bool gotoInset(BufferView * bv, vector<InsetCode> const & codes,
 
        tmpcur.clearSelection();
        bv->setCursor(tmpcur);
-       return bv->scrollToCursor(bv->cursor(), false, true);
+       return bv->scrollToCursor(bv->cursor(), SCROLL_TOP);
 }
 
 
@@ -550,13 +550,13 @@ void BufferView::processUpdateFlags(Update::flags flags)
                if (needsFitCursor()) {
                        // First try to make the selection start visible
                        // (which is just the cursor when there is no selection)
-                       scrollToCursor(d->cursor_.selectionBegin(), false, false);
+                       scrollToCursor(d->cursor_.selectionBegin(), SCROLL_VISIBLE);
                        // Metrics have to be recomputed (maybe again)
                        updateMetrics();
                        // Is the cursor visible? (only useful if cursor is at end of selection)
                        if (needsFitCursor()) {
                                // then try to make cursor visible instead
-                               scrollToCursor(d->cursor_, false, false);
+                               scrollToCursor(d->cursor_, SCROLL_VISIBLE);
                                // Metrics have to be recomputed (maybe again)
                                updateMetrics(flags);
                        }
@@ -750,7 +750,7 @@ void BufferView::scrollDocView(int const pixels, bool update)
        // cut off at the top
        if (pixels <= d->scrollbarParameters_.min) {
                DocIterator dit = doc_iterator_begin(&buffer_);
-               showCursor(dit, false, false, update);
+               showCursor(dit, SCROLL_VISIBLE, update);
                LYXERR(Debug::SCROLLING, "scroll to top");
                return;
        }
@@ -759,7 +759,7 @@ void BufferView::scrollDocView(int const pixels, bool update)
        if (pixels >= d->scrollbarParameters_.max) {
                DocIterator dit = doc_iterator_end(&buffer_);
                dit.backwardPos();
-               showCursor(dit, false, false, update);
+               showCursor(dit, SCROLL_VISIBLE, update);
                LYXERR(Debug::SCROLLING, "scroll to bottom");
                return;
        }
@@ -784,7 +784,7 @@ void BufferView::scrollDocView(int const pixels, bool update)
        DocIterator dit = doc_iterator_begin(&buffer_);
        dit.pit() = i;
        LYXERR(Debug::SCROLLING, "pixels = " << pixels << " -> scroll to pit " << i);
-       showCursor(dit, false, false, update);
+       showCursor(dit, SCROLL_VISIBLE, update);
 }
 
 
@@ -970,34 +970,36 @@ int BufferView::workWidth() const
 
 void BufferView::recenter()
 {
-       showCursor(d->cursor_, true, false, true);
+       showCursor(d->cursor_, SCROLL_CENTER, true);
 }
 
 
 void BufferView::showCursor()
 {
-       showCursor(d->cursor_, false, false, true);
+       showCursor(d->cursor_, SCROLL_VISIBLE, true);
 }
 
 
-void BufferView::showCursor(DocIterator const & dit,
-       bool recenter, bool force, bool update)
+void BufferView::showCursor(DocIterator const & dit, ScrollType how,
+       bool update)
 {
-       if (scrollToCursor(dit, recenter, force) && update)
+       if (scrollToCursor(dit, how) && update)
                processUpdateFlags(Update::Force);
 }
 
 
-bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter, bool force)
+bool BufferView::scrollToCursor(DocIterator const & dit, ScrollType how)
 {
        // We are not properly started yet, delay until resizing is done.
        if (height_ == 0)
                return false;
 
-       if (recenter)
-               LYXERR(Debug::SCROLLING, "recentering and scrolling to cursor");
+       if (how == SCROLL_CENTER)
+               LYXERR(Debug::SCROLLING, "Centering cursor in workarea");
+       else if (how == SCROLL_TOP)
+               LYXERR(Debug::SCROLLING, "Setting cursor to top of workarea");
        else
-               LYXERR(Debug::SCROLLING, "scrolling to cursor");
+               LYXERR(Debug::SCROLLING, "Making sure cursor is visible in workarea");
 
        CursorSlice const & bot = dit.bottom();
        TextMetrics & tm = textMetrics(bot.text());
@@ -1016,7 +1018,7 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter, bo
        else if (bot_pit == tm.last().first + 1)
                tm.newParMetricsDown();
 
-       if (tm.contains(bot_pit) && !force) {
+       if (tm.contains(bot_pit) && how == SCROLL_VISIBLE) {
                ParagraphMetrics const & pm = tm.parMetrics(bot_pit);
                LBUFERR(!pm.rows().empty());
                // FIXME: smooth scrolling doesn't work in mathed.
@@ -1027,14 +1029,12 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter, bo
                Dimension const & row_dim =
                        inner_pm.getRow(cs.pos(), dit.boundary()).dim();
                int scrolled = 0;
-               if (recenter)
-                       scrolled = scroll(ypos - height_/2);
 
                // We try to visualize the whole row, if the row height is larger than
                // the screen height, we scroll to a heuristic value of height_ / 4.
                // FIXME: This heuristic value should be replaced by a recursive search
                // for a row in the inset that can be visualized completely.
-               else if (row_dim.height() > height_) {
+               if (row_dim.height() > height_) {
                        if (ypos < defaultRowHeight())
                                scrolled = scroll(ypos - height_ / 4);
                        else if (ypos > height_ - defaultRowHeight())
@@ -1063,28 +1063,21 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter, bo
                d->inlineCompletionPos_ = DocIterator();
 
        tm.redoParagraph(bot_pit);
-       ParagraphMetrics const & pm = tm.parMetrics(bot_pit);
        int const offset = coordOffset(dit).y_;
-
+       pit_type const old_pit = d->anchor_pit_;
        d->anchor_pit_ = bot_pit;
+
        CursorSlice const & cs = dit.innerTextSlice();
        ParagraphMetrics const & inner_pm =
                textMetrics(cs.text()).parMetrics(cs.pit());
        Dimension const & row_dim =
                inner_pm.getRow(cs.pos(), dit.boundary()).dim();
 
-       if (recenter)
-               d->anchor_ypos_ = height_/2;
-       else if (d->anchor_pit_ == 0)
-               d->anchor_ypos_ = offset + pm.ascent();
-       else if (d->anchor_pit_ == max_pit)
-               d->anchor_ypos_ = height_ - offset - row_dim.descent();
-       else if (offset > height_)
-               d->anchor_ypos_ = height_ - offset - row_dim.descent();
-       else
-               d->anchor_ypos_ = row_dim.ascent();
-
-       return true;
+       int const old_ypos = d->anchor_ypos_;
+       d->anchor_ypos_ = - offset + row_dim.ascent();
+       if (how == SCROLL_CENTER)
+               d->anchor_ypos_ += height_/2 - row_dim.height() / 2;
+       return d->anchor_ypos_ != old_ypos || d->anchor_pit_ != old_pit;
 }
 
 
@@ -1589,7 +1582,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                        success = setCursorFromEntries({id, pos},
                                                                       {id_end, pos_end});
                                }
-                               if (success && scrollToCursor(d->cursor_, false, true))
+                               if (success && scrollToCursor(d->cursor_, SCROLL_TOP))
                                                dr.screenUpdate(Update::Force);
                        } else {
                                // Switch to other buffer view and resend cmd
@@ -3359,8 +3352,8 @@ void BufferView::buildCaretGeometry(bool complet)
        bool const slant = fm.italic() && cur.inTexted() && !cur.selection();
        double const slope = slant ? fm.italicSlope() : 0;
        cg.shapes.push_back(
-               {{iround(p.x_ + dim.asc * slope), p.y_},
-                {iround(p.x_ - dim.des * slope), p.y_ + dim.height()},
+               {{iround(p.x_ + dim.asc * slope),                 p.y_},
+                {iround(p.x_ - dim.des * slope),                 p.y_ + dim.height()},
                 {iround(p.x_ + dir * dim.wid - dim.des * slope), p.y_ + dim.height()},
                 {iround(p.x_ + dir * dim.wid + dim.asc * slope), p.y_}}
                );
@@ -3373,10 +3366,10 @@ void BufferView::buildCaretGeometry(bool complet)
                int const xx = iround(p.x_ - dim.des * slope);
                int const yy = p.y_ + dim.height();
                cg.shapes.push_back(
-                       {{xx, yy - dim.wid},
+                       {{xx,                            yy - dim.wid},
                         {xx + dir * (dim.wid + lx - 1), yy - dim.wid},
                         {xx + dir * (dim.wid + lx - 1), yy},
-                        {xx, yy}}
+                        {xx,                            yy}}
                        );
        }
 
@@ -3389,12 +3382,12 @@ void BufferView::buildCaretGeometry(bool complet)
                // starting position x
                int const xx = p.x_ + dir * dim.wid + sx;
                cg.shapes.push_back(
-                       {{xx, m - d},
-                        {xx + dir * d, m},
-                        {xx, m + d},
-                        {xx, m + d - dim.wid},
+                       {{xx,                     m - d},
+                        {xx + dir * d,           m},
+                        {xx,                     m + d},
+                        {xx,                     m + d - dim.wid},
                         {xx + dir * d - dim.wid, m},
-                        {xx, m - d + dim.wid}}
+                        {xx,                     m - d + dim.wid}}
                        );
        }
 
@@ -3534,6 +3527,12 @@ void BufferView::checkCursorScrollOffset()
 }
 
 
+bool BufferView::busy() const
+{
+       return buffer().undo().activeUndoGroup();
+}
+
+
 void BufferView::draw(frontend::Painter & pain, bool paint_caret)
 {
        if (height_ == 0 || width_ == 0)