From 8d52aa563813f53eeca109c76252d3a258214017 Mon Sep 17 00:00:00 2001 From: Abdelrazak Younes Date: Sat, 15 Sep 2007 12:28:41 +0000 Subject: [PATCH] Give PageDown/Up scrolling a sane behaviour. Does not work with selection yet... * BufferView: - new scroll(), scrollDown() and scrollUp() method for pixel scrolling. - new LFUN_SCREEN_UP/DOWN handling. * TextMetrics: new helper and access methods. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20283 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/BufferView.cpp | 110 ++++++++++++++++++++++++++++++----- src/BufferView.h | 8 ++- src/Text3.cpp | 8 +-- src/TextMetrics.cpp | 42 +++++++++++++ src/TextMetrics.h | 11 ++++ src/mathed/InsetMathNest.cpp | 2 - 6 files changed, 158 insertions(+), 23 deletions(-) diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 9a66db4014..66f64dfe6f 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -592,6 +592,18 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd) break; } + case LFUN_SCREEN_UP: + case LFUN_SCREEN_DOWN: + flag.enabled(true); + break; + + // FIXME: LFUN_SCREEN_DOWN_SELECT should be removed from + // everywhere else before this can enabled: + case LFUN_SCREEN_UP_SELECT: + case LFUN_SCREEN_DOWN_SELECT: + flag.enabled(false); + break; + default: flag.enabled(false); } @@ -935,6 +947,38 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd) break; } + case LFUN_SCREEN_UP: + case LFUN_SCREEN_DOWN: { + Point const p = bv_funcs::getPos(*this, cur, cur.boundary()); + scroll(cmd.action == LFUN_SCREEN_UP? - height_ : height_); + cur.reset(buffer_.inset()); + text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_); + //FIXME: what to do with cur.x_target()? + finishUndo(); + // The metrics are already up to date. see scroll() + updateFlags = Update::None; + break; + } + + case LFUN_SCREEN_UP_SELECT: + case LFUN_SCREEN_DOWN_SELECT: { + cur.selHandle(true); + size_t initial_depth = cur.depth(); + Point const p = bv_funcs::getPos(*this, cur, cur.boundary()); + scroll(cmd.action == LFUN_SCREEN_UP_SELECT? - height_ : height_); + // FIXME: We need to verify if the cursor stayed within an inset... + //cur.reset(buffer_.inset()); + text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_); + finishUndo(); + while (cur.depth() > initial_depth) { + cur.forwardInset(); + } + // FIXME: we need to do a redraw again because of the selection + buffer_.changed(); + updateFlags = Update::Force | Update::FitCursor; + break; + } + default: updateFlags = Update::None; } @@ -1138,20 +1182,60 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0) } -void BufferView::scroll(int /*lines*/) +void BufferView::scroll(int y) { -// Text const * t = buffer_.text(); -// int const line_height = defaultRowHeight(); -// -// // The new absolute coordinate -// int new_top_y = top_y() + lines * line_height; -// -// // Restrict to a valid value -// new_top_y = std::min(t->height() - 4 * line_height, new_top_y); -// new_top_y = std::max(0, new_top_y); -// -// scrollDocView(new_top_y); -// + if (y > 0) + scrollDown(y); + else if (y < 0) + scrollUp(-y); +} + + +void BufferView::scrollDown(int offset) +{ + Text * text = &buffer_.text(); + TextMetrics & tm = text_metrics_[text]; + int ymax = height_ + offset; + while (true) { + std::pair const & last = tm.last(); + int bottom_pos = last.second.position() + last.second.descent(); + if (last.first == text->paragraphs().size() - 1) { + if (bottom_pos <= height_) + return; + offset = min(offset, bottom_pos - height_); + break; + } + if (bottom_pos > ymax) + break; + tm.newParMetricsDown(); + } + offset_ref_ += offset; + updateMetrics(false); + buffer_.changed(); +} + + +void BufferView::scrollUp(int offset) +{ + Text * text = &buffer_.text(); + TextMetrics & tm = text_metrics_[text]; + int ymin = - offset; + while (true) { + std::pair const & first = tm.first(); + int top_pos = first.second.position() - first.second.ascent(); + if (first.first == 0) { + if (top_pos >= 0) + return; + offset = min(offset, - top_pos); + break; + } + if (top_pos < ymin) + break; + tm.newParMetricsUp(); + } + offset_ref_ -= offset; + updateMetrics(false); + buffer_.changed(); } diff --git a/src/BufferView.h b/src/BufferView.h index 4217901c90..c9652b6b5a 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -128,8 +128,12 @@ public: /// center the document view around the cursor. void center(); - /// scroll document by the given number of lines of default height. - void scroll(int lines); + /// scroll down document by the given number of pixels. + void scrollDown(int pixels); + /// scroll up document by the given number of pixels. + void scrollUp(int pixels); + /// scroll document by the given number of pixels. + void scroll(int pixels); /// Scroll the view by a number of pixels. void scrollDocView(int pixels); /// Set the cursor position based on the scrollbar one. diff --git a/src/Text3.cpp b/src/Text3.cpp index c5b17279ce..a7186bc64f 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -440,9 +440,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cursorDownParagraph(cur); break; - case LFUN_SCREEN_UP: case LFUN_SCREEN_UP_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_SCREEN_UP_SELECT); + needsUpdate |= cur.selHandle(true); if (cur.pit() == 0 && cur.textRow().pos() == 0) cur.undispatched(); else { @@ -450,9 +449,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } break; - case LFUN_SCREEN_DOWN: case LFUN_SCREEN_DOWN_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_SCREEN_DOWN_SELECT); + needsUpdate |= cur.selHandle(true); if (cur.pit() == cur.lastpit() && cur.textRow().endpos() == cur.lastpos()) cur.undispatched(); @@ -1853,8 +1851,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_WORD_SELECT: case LFUN_PARAGRAPH_UP: case LFUN_PARAGRAPH_DOWN: - case LFUN_SCREEN_UP: - case LFUN_SCREEN_DOWN: case LFUN_LINE_BEGIN: case LFUN_LINE_END: case LFUN_BREAK_LINE: diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 30769e21a7..0ccfa67026 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -139,6 +139,21 @@ ParagraphMetrics const & TextMetrics::parMetrics(pit_type pit) const } + +pair const & TextMetrics::first() const +{ + pair const & pm = *par_metrics_.begin(); + return pm; +} + + +pair const & TextMetrics::last() const +{ + pair const & pm = *par_metrics_.rbegin(); + return pm; +} + + ParagraphMetrics & TextMetrics::parMetrics(pit_type pit, bool redo) { @@ -1153,6 +1168,33 @@ pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const } +void TextMetrics::newParMetricsDown() +{ + pair const & last = *par_metrics_.rbegin(); + pit_type const pit = last.first + 1; + if (pit == text_->paragraphs().size()) + return; + + // do it and update its position. + redoParagraph(pit); + par_metrics_[pit].setPosition(last.second.position() + + last.second.descent()); +} + + +void TextMetrics::newParMetricsUp() +{ + pair const & first = *par_metrics_.begin(); + if (first.first == 0) + return; + + pit_type const pit = first.first - 1; + // do it and update its position. + redoParagraph(pit); + par_metrics_[pit].setPosition(first.second.position() + - first.second.ascent()); +} + // y is screen coordinate pit_type TextMetrics::getPitNearY(int y) { diff --git a/src/TextMetrics.h b/src/TextMetrics.h index 2d7c09fffa..6571bc72be 100644 --- a/src/TextMetrics.h +++ b/src/TextMetrics.h @@ -48,6 +48,11 @@ public: bool has(pit_type pit) const; /// ParagraphMetrics const & parMetrics(pit_type) const; + /// + std::pair const & first() const; + /// + std::pair const & last() const; + /// int parPosition(pit_type pit) const; @@ -57,9 +62,15 @@ public: Point const & origin() const { return origin_; } + /// compute text metrics. bool metrics(MetricsInfo & mi, Dimension & dim); + /// + void newParMetricsDown(); + /// + void newParMetricsUp(); + /// Gets the fully instantiated font at a given position in a paragraph /// Basically the same routine as Paragraph::getFont() in Paragraph.cpp. /// The difference is that this one is used for displaying, and thus we diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp index 0828da60f4..9006dadc51 100644 --- a/src/mathed/InsetMathNest.cpp +++ b/src/mathed/InsetMathNest.cpp @@ -643,13 +643,11 @@ goto_char_backwards: break; case LFUN_SCREEN_UP_SELECT: - case LFUN_SCREEN_UP: cmd = FuncRequest(LFUN_FINISHED_LEFT); cur.undispatched(); break; case LFUN_SCREEN_DOWN_SELECT: - case LFUN_SCREEN_DOWN: cmd = FuncRequest(LFUN_FINISHED_RIGHT); cur.undispatched(); break; -- 2.39.5