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.
This commit is contained in:
Jean-Marc Lasgouttes 2024-09-05 22:05:38 +02:00
parent 9c443d9651
commit 6c20e5db7d
8 changed files with 69 additions and 21 deletions

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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.

View File

@ -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"

View File

@ -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);

View File

@ -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

View File

@ -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
*/