]> git.lyx.org Git - lyx.git/commitdiff
Merge remote-tracking branch 'features/scroll-reloaded'
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Sat, 10 Jan 2015 17:00:13 +0000 (18:00 +0100)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Sat, 10 Jan 2015 17:39:09 +0000 (18:39 +0100)
This implement horizontal scrolling of rows to allow editing insets
(math, tabular...) that are larger then the screen. The scrolling happens
as the cursor moves, in order to make sure that the cursor is always visible.
This effectively closes an 11 years old bug.

This feature is the result of the work of Hashini Senaratne as part of
Google Summer of Code 2013. The code has been cleaned-up for inclusion
and remaining bugs have been fixed.

Fixes bug: #1083.

1  2 
src/BufferView.cpp
src/CursorSlice.h
src/RowPainter.cpp
src/TextMetrics.cpp
src/frontends/qt4/GuiWorkArea.cpp
src/insets/InsetTabular.cpp
src/insets/InsetTabular.h

index e9824097d429d6b6c746b5df24fb3cfdd659c56f,92ce6f634de6f9b5ccfdebd5bfe7f2c56593af6d..9d42f3d64c2c948885335c2027777364e9f48319
@@@ -2889,6 -2868,105 +2904,105 @@@ bool BufferView::cursorInView(Point con
  }
  
  
 -      if (offset < row.x || row.width() <= workWidth())
+ int BufferView::horizScrollOffset() const
+ {
+       return d->horiz_scroll_offset_;
+ }
+ CursorSlice const & BufferView::currentRowSlice() const
+ {
+       return d->current_row_slice_;
+ }
+ CursorSlice const & BufferView::lastRowSlice() const
+ {
+       return d->last_row_slice_;
+ }
+ 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();
+               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();
+       // Since we changed row, the scroll offset is not valid anymore
+       d->horiz_scroll_offset_ = 0;
+       d->current_row_slice_ = rowSlice;
+ }
+ void BufferView::checkCursorScrollOffset(PainterInfo & pi)
+ {
+       CursorSlice rowSlice = d->cursor_.bottom();
+       TextMetrics const & tm = textMetrics(rowSlice.text());
+       // Stop if metrics have not been computed yet, since it means
+       // that there is nothing to do.
+       if (!tm.contains(rowSlice.pit()))
+               return;
+       ParagraphMetrics const & pm = tm.parMetrics(rowSlice.pit());
+       Row const & row = pm.getRow(rowSlice.pos(),
+                                   d->cursor_.boundary()
+                                   && rowSlice == d->cursor_.top());
+       rowSlice.pos() = row.pos();
+       // Set the row on which the cursor lives.
+       setCurrentRowSlice(rowSlice);
+       // Force the recomputation of inset positions
+       bool const drawing = pi.pain.isDrawingEnabled();
+       pi.pain.setDrawingEnabled(false);
+       // No need to care about vertical position.
+       RowPainter rp(pi, buffer().text(), d->cursor_.bottom().pit(), row,
+                     -d->horiz_scroll_offset_, 0);
+       rp.paintText();
+       pi.pain.setDrawingEnabled(drawing);
+       // Current x position of the cursor in pixels
+       int const cur_x = getPos(d->cursor_).x_;
+       // Horizontal scroll offset of the cursor row in pixels
+       int offset = d->horiz_scroll_offset_;
+       int const MARGIN = Length(2, Length::EM).inPixels(workWidth());
+       if (cur_x < offset + MARGIN) {
+               // scroll right
+               offset = cur_x - MARGIN;
+       } else if (cur_x > offset + workWidth() - MARGIN) {
+               // scroll left
+               offset = cur_x - workWidth() + MARGIN;
+       }
++      if (offset < row.left_margin || row.width() <= workWidth())
+               offset = 0;
+       if (offset != d->horiz_scroll_offset_)
+               LYXERR(Debug::PAINTING, "Horiz. scroll offset changed from "
+                      << d->horiz_scroll_offset_ << " to " << offset);
+       if (d->update_strategy_ == NoScreenUpdate
+           && (offset != d->horiz_scroll_offset_
+               || !d->last_row_slice_.empty())) {
+               // FIXME: if one uses SingleParUpdate, then home/end
+               // will not work on long rows. Why?
+               d->update_strategy_ = FullScreenUpdate;
+       }
+       d->horiz_scroll_offset_ = offset;
+ }
  void BufferView::draw(frontend::Painter & pain)
  {
        if (height_ == 0 || width_ == 0)
Simple merge
Simple merge
index b8771b23e6a8d97456bc7b6bc8ac9a5f213441f7,9a6b67d28bdcb4654137367ea7063dec69481ae4..f29202c668644dc6dada33af211f7fd25ac7435b
@@@ -1888,7 -1904,10 +1900,10 @@@ void TextMetrics::drawParagraph(Painter
                // Clear background of this row if paragraph background was not
                // already cleared because of a full repaint.
                if (!pi.full_repaint && row_has_changed) {
-                       pi.pain.fillRectangle(x, y - row.ascent(),
+                       LYXERR(Debug::PAINTING, "Clear rect@("
 -                             << max(row_x, 0) << ", " << y-row.ascent() << ")="
++                             << max(row_x, 0) << ", " << y - row.ascent() << ")="
+                              << width() << " x " << row.height());
+                       pi.pain.fillRectangle(max(row_x, 0), y - row.ascent(),
                                width(), row.height(), pi.background_color);
                }
  
Simple merge
index 6e69a03a7c3f274f8f2485acb596136832772b45,507f30233fd80676d23328228d55fca97ea7a1e4..8f86888df556fe9b2b67affa9c87a53275ba6ab8
@@@ -3456,8 -3456,8 +3456,8 @@@ docstring InsetTableCell::xhtml(XHTMLSt
  
  InsetTabular::InsetTabular(Buffer * buf, row_type rows,
                           col_type columns)
-       : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))), scx_(0),
-       rowselect_(false), colselect_(false)
+       : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))),
 -      rowselect_(false), colselect_(false)
++        rowselect_(false), colselect_(false)
  {
  }
  
Simple merge