[LyX/master] Add ScrollType BOTTOM and TOGGLE for BufferView::scrollToCursor()

Jean-Marc Lasgouttes lasgouttes at lyx.org
Fri Sep 6 12:56:54 UTC 2024


commit 6c20e5db7db662239e8c2bd47fe28d18b27bd729
Author: Jean-Marc Lasgouttes <lasgouttes at lyx.org>
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
  */


More information about the lyx-cvs mailing list