commit 6c20e5db7db662239e8c2bd47fe28d18b27bd729
Author: Jean-Marc Lasgouttes <[email protected]>
Date:   Thu Sep 5 22:05:38 2024 +0200

    Add ScrollType BOTTOM and TOGGLE for BufferView::scrollToCursor()
    
    BOTTOM shows the paragraph containing the cursor at the bottom of the
    work area.
    
    TOGGLE does CENTER, then TOP, BOTTOM and finally cycles to CENTER.
    This is a feature copied from emacs's C-l binding.
    
    Add new argument "caret" to lfun "scroll" that can be used like
      scroll caret center
    
    Change the keys (either C-l, M-l or F5) bound to screen-recenter to
    "scroll caret toggle".
    
    As an experiment, change paragraph-goto to use this scrolling method.
    This can be tested when going to a heading in the outline pane.
---
 lib/bind/cua.bind     |  2 +-
 lib/bind/emacs.bind   |  2 +-
 lib/bind/mac.bind     |  4 ++--
 lib/bind/sciword.bind |  2 +-
 lib/bind/xemacs.bind  |  2 +-
 src/BufferView.cpp    | 55 +++++++++++++++++++++++++++++++++++++++++++++------
 src/BufferView.h      | 18 ++++++++++-------
 src/LyXAction.cpp     |  5 +++--
 8 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/lib/bind/cua.bind b/lib/bind/cua.bind
index 9d3f386091..d0fb3edebe 100644
--- a/lib/bind/cua.bind
+++ b/lib/bind/cua.bind
@@ -120,7 +120,7 @@ Format 5
 \bind "C-F3"                   "search-string-set"
 \bind "C-F4"                   "buffer-close"
 \bind "M-F4"                   "lyx-quit"
-\bind "F5"                     "screen-recenter"
+\bind "F5"                     "scroll caret toggle"
 \bind "C-M-Up"                 "scroll line up"
 \bind "C-M-Down"               "scroll line down"
 \bind "C-M-Prior"              "scroll page up"
diff --git a/lib/bind/emacs.bind b/lib/bind/emacs.bind
index b463cabb36..c5bae46104 100644
--- a/lib/bind/emacs.bind
+++ b/lib/bind/emacs.bind
@@ -42,7 +42,7 @@ Format 5
 \bind "C-i"                    "space-insert hfill"
 \bind "C-j"                    "paragraph-break"
 \bind "C-k"                    "line-delete-forward"
-\bind "C-l"                    "screen-recenter"
+\bind "C-l"                    "scroll caret toggle"
 \bind "C-m"                    "mark-toggle"
 \bind "C-n"                    "down"
 \bind "C-o"                    "inset-toggle"
diff --git a/lib/bind/mac.bind b/lib/bind/mac.bind
index 8fbe012bbd..f2b91235d8 100644
--- a/lib/bind/mac.bind
+++ b/lib/bind/mac.bind
@@ -63,8 +63,8 @@ Format 5
 #  -: "Control-K"                    # Delete from the character in front of 
the cursor to the end of the line/paragraph
 # used by menu.bind - keymap
 #  +: "Control-L"                    # Center the cursor/selection in the 
visible area
-\bind "M-l"                          "screen-recenter"
-\bind "F5"                           "screen-recenter"
+\bind "M-l"                          "scroll caret toggle"
+\bind "F5"                           "scroll caret toggle"
 #  +: "Control-N"                    # Move down one line
 \bind "M-n"                          "down"
 #  +: "Control-O"                    # Insert a new line after the cursor
diff --git a/lib/bind/sciword.bind b/lib/bind/sciword.bind
index 55a146bc9b..78508b9256 100644
--- a/lib/bind/sciword.bind
+++ b/lib/bind/sciword.bind
@@ -79,7 +79,7 @@ Format 5
 #\bind "C-j"   "------"
 
 \bind "C-k"    "line-delete-forward"
-\bind "C-j"                    "screen-recenter"
+\bind "C-j"                    "scroll caret toggle"
 \bind "C-S-I"                  "info-insert"
 
 # Toggle: in text mode, switch to math, and vice versa. Also C-t.
diff --git a/lib/bind/xemacs.bind b/lib/bind/xemacs.bind
index ad36a4f2d6..d130e660fa 100644
--- a/lib/bind/xemacs.bind
+++ b/lib/bind/xemacs.bind
@@ -44,7 +44,7 @@ Format 5
 \bind "C-i"                    "space-insert hfill"
 #bind "C-j"                    "------"
 \bind "C-k"                    "line-delete-forward"
-\bind "C-l"                    "screen-recenter"
+\bind "C-l"                    "scroll caret toggle"
 \bind "C-m"                    "mark-toggle"
 \bind "C-n"                    "down"
 \bind "C-o"                    "inset-toggle"
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index e58612ef49..665f4673d5 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -1015,9 +1015,9 @@ void BufferView::recenter()
 }
 
 
-void BufferView::showCursor()
+void BufferView::showCursor(ScrollType how)
 {
-       showCursor(d->cursor_, SCROLL_VISIBLE);
+       showCursor(d->cursor_, how);
 }
 
 
@@ -1038,6 +1038,10 @@ bool BufferView::scrollToCursor(DocIterator const & dit, 
ScrollType how)
                LYXERR(Debug::SCROLLING, "Centering cursor in workarea");
        else if (how == SCROLL_TOP)
                LYXERR(Debug::SCROLLING, "Setting cursor to top of workarea");
+       else if (how == SCROLL_BOTTOM)
+               LYXERR(Debug::SCROLLING, "Setting cursor to bottom of 
workarea");
+       else if (how == SCROLL_TOGGLE)
+               LYXERR(Debug::SCROLLING, "Alternate cursor position between 
center, top and bottom");
        else
                LYXERR(Debug::SCROLLING, "Making sure cursor is visible in 
workarea");
 
@@ -1115,6 +1119,7 @@ bool BufferView::scrollToCursor(DocIterator const & dit, 
ScrollType how)
        int const ypos_center = height_/2 - row_dim.height() / 2 + 
row_dim.ascent() - offset;
        int const ypos_top = (offset > height_) ? height_ - offset - 
defaultRowHeight()
                                                : defaultRowHeight() * 2;
+       int const ypos_bottom = height_ - offset - defaultRowHeight();
 
        // Select the right one.
        d->anchor_pit_ = bot_pit;
@@ -1125,7 +1130,24 @@ bool BufferView::scrollToCursor(DocIterator const & dit, 
ScrollType how)
        case SCROLL_TOP:
        case SCROLL_VISIBLE:
                d->anchor_ypos_ = ypos_top;
-               // more to come: BOTTOM, TOGGLE
+               break;
+       case SCROLL_BOTTOM:
+               d->anchor_ypos_ = ypos_bottom;
+               break;
+       case SCROLL_TOGGLE: {
+               ParagraphMetrics const & bot_pm = tm.parMetrics(bot_pit);
+               if (!bot_pm.hasPosition()) {
+                       d->anchor_ypos_ = ypos_center;
+                       break;
+               }
+               int const ypos = bot_pm.position();
+               if (ypos == ypos_center)
+                       d->anchor_ypos_ = ypos_top;
+               else if (ypos == ypos_top)
+                       d->anchor_ypos_ = ypos_bottom;
+               else
+                       d->anchor_ypos_ = ypos_center;
+       }
        }
 
        return d->anchor_ypos_ != old_ypos || d->anchor_pit_ != old_pit;
@@ -1657,7 +1679,7 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
                                        success = setCursorFromEntries({id, 
pos},
                                                                       {id_end, 
pos_end});
                                }
-                               if (success && scrollToCursor(d->cursor_, 
SCROLL_TOP))
+                               if (success && scrollToCursor(d->cursor_, 
SCROLL_TOGGLE))
                                                dr.screenUpdate(Update::Force);
                        } else {
                                // Switch to other buffer view and resend cmd
@@ -2164,6 +2186,27 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
 
        case LFUN_SCROLL: {
                string const scroll_type = cmd.getArg(0);
+               if (scroll_type == "caret") {
+                       string const where = cmd.getArg(1);
+                       ScrollType how;
+                       if (where == "top")
+                               how = SCROLL_TOP;
+                       else if (where == "center")
+                               how = SCROLL_CENTER;
+                       else if (where == "bottom")
+                               how = SCROLL_BOTTOM;
+                       else if (where == "toggle")
+                               how = SCROLL_TOGGLE;
+                       else if (where == "visible")
+                               how = SCROLL_VISIBLE;
+                       else {
+                               dispatched = false;
+                               break;
+                       }
+                       showCursor(how);
+                       break;
+               }
+
                int scroll_step = 0;
                if (scroll_type == "line")
                        scroll_step = d->scrollbarParameters_.single_step;
@@ -2171,7 +2214,7 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
                        scroll_step = d->scrollbarParameters_.page_step;
                else {
                        dispatched = false;
-                       return;
+                       break;
                }
 
                string const scroll_quantity = cmd.getArg(1);
@@ -2184,7 +2227,7 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
                        scroll(scroll_step * convert<int>(scroll_quantity));
                else {
                        dispatched = false;
-                       return;
+                       break;
                }
 
                dr.screenUpdate(Update::ForceDraw);
diff --git a/src/BufferView.h b/src/BufferView.h
index e67895fa50..24d3ce8950 100644
--- a/src/BufferView.h
+++ b/src/BufferView.h
@@ -61,10 +61,14 @@ enum CursorStatus {
 enum ScrollType {
        // Make sure row if visible (do nothing if it is visible already)
        SCROLL_VISIBLE,
-       // Force cursor to be on top of screen
+       // Cursor on top of screen
        SCROLL_TOP,
-       // Force cursor to be at center of screen
-       SCROLL_CENTER
+       // Cursor at center of screen
+       SCROLL_CENTER,
+       // Cursor at bottom of the screen
+       SCROLL_BOTTOM,
+       // Alternate between center, top, bottom, center, etc.
+       SCROLL_TOGGLE
 };
 
 /// Scrollbar Parameters.
@@ -213,18 +217,18 @@ public:
        /// Ensure that the BufferView cursor is visible.
        /// This method will automatically scroll and update the BufferView
        /// (metrics+drawing) if needed.
-       void showCursor();
+       /// \param how: where the cursor should appear (visible, top, center...)
+       void showCursor(ScrollType how = SCROLL_VISIBLE);
 
        /// Ensure the passed cursor \p dit is visible.
        /// This method will automatically scroll and update the BufferView
        /// (metrics+drawing) if needed.
-       /// \param how: where the cursor should appear (visible/top/center)
+       /// \param how: where the cursor should appear (visible, top, center...)
        void showCursor(DocIterator const & dit, ScrollType how);
        /// Scroll to the cursor.
        /// This only updates the anchor vertical position, but does not
        /// recompute metrics nor trigger a screen refresh.
-       /// \param how: where the cursor should appear (visible/top/center)
-       /// \return true if screen was scrolled
+       /// \param how: where the cursor should appear (visible, top, center...)
        bool scrollToCursor(DocIterator const & dit, ScrollType how);
        /// scroll the view by the given number of pixels. This only
        /// updates the anchor vertical position, but does not recompute
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 489002364c..d7db81fe2e 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -3657,8 +3657,9 @@ void LyXAction::init()
  * \li Action: Scroll the buffer view.
  * \li Notion: Only scrolls the screen up or down; does not move the cursor.
  * \li Syntax: scroll <TYPE> <QUANTITY>
- * \li Params: <TYPE>:  line|page\n
-               <QUANTITY>: up|down|<number>
+ * \li Params: <TYPE>:  line|page|caret\n
+               <QUANTITY>: top|center|bottom|toggle [if <TYPE> is caret]
+               <QUANTITY>: up|down|<number>  [otherwise]
  * \li Origin: Abdel, Dec 27 2007
  * \endvar
  */
-- 
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to