mirror of
https://github.com/vim/vim.git
synced 2026-05-06 12:26:58 -04:00
patch 9.2.0386: No scroll/scrollbar support in the tabpanel
Problem: No scroll/scrollbar support in the tabpanel Solution: Add support for it (Yasuhiro Matsumoto) closes: #19979 Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
10040bc9cd
commit
2ea4a7c3b7
+18
-1
@@ -1,4 +1,4 @@
|
||||
*options.txt* For Vim version 9.2. Last change: 2026 Apr 20
|
||||
*options.txt* For Vim version 9.2. Last change: 2026 Apr 21
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -9065,6 +9065,23 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
tab panel will not be displayed.
|
||||
(default 20)
|
||||
|
||||
scroll Enable mouse wheel scrolling over the tabpanel
|
||||
area when the tab list exceeds the visible
|
||||
screen height. The scroll step is controlled
|
||||
by 'mousescroll'. When disabled (the default),
|
||||
the tabpanel shows the page containing the
|
||||
current tab, with no way to view tabs outside
|
||||
that page.
|
||||
|
||||
scrollbar Reserve a one-column scrollbar in the tabpanel
|
||||
showing the current scroll position. The
|
||||
scrollbar uses the |hl-PmenuSbar| and
|
||||
|hl-PmenuThumb| highlight groups for the track
|
||||
and thumb respectively. Clicking on the
|
||||
scrollbar column jumps the thumb to that
|
||||
position; the thumb can also be dragged.
|
||||
Implies "scroll".
|
||||
|
||||
vert Use a vertical separator for tabpanel.
|
||||
The vertical separator character is taken from
|
||||
"tpl_vert" in 'fillchars'.
|
||||
|
||||
+32
-1
@@ -1,4 +1,4 @@
|
||||
*tabpage.txt* For Vim version 9.2. Last change: 2026 Feb 14
|
||||
*tabpage.txt* For Vim version 9.2. Last change: 2026 Apr 21
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -482,6 +482,37 @@ The vertical separator character is taken from "tpl_vert" in 'fillchars'.
|
||||
You can customize the appearance of the tab page labels using the highlight
|
||||
groups: |hl-TabPanel| |hl-TabPanelSel| |hl-TabPanelFill|
|
||||
|
||||
SCROLLING IN THE TABPANEL: *tabpanel-scroll*
|
||||
|
||||
When the total height of the tab list exceeds the visible screen height, the
|
||||
tabpanel by default displays the "page" that contains the current tab and
|
||||
offers no way to view tabs outside that page.
|
||||
|
||||
To make the tabpanel scrollable, add "scroll" to 'tabpanelopt': >
|
||||
:set tabpanelopt+=scroll
|
||||
|
||||
With "scroll" enabled, mouse wheel events over the tabpanel area scroll the
|
||||
tab list up or down. The scroll step follows the 'mousescroll' setting.
|
||||
Wheel events inside the tabpanel area are consumed by the tabpanel and do not
|
||||
trigger |<ScrollWheelUp>| or |<ScrollWheelDown>| mappings.
|
||||
|
||||
To additionally show a vertical scrollbar indicating the current scroll
|
||||
position, use "scrollbar": >
|
||||
:set tabpanelopt+=scrollbar
|
||||
|
||||
The "scrollbar" value implies "scroll". A one-column scrollbar is reserved at
|
||||
the edge of the tabpanel; clicking on the scrollbar column moves the thumb to
|
||||
the click position, and the thumb can be dragged to scroll continuously.
|
||||
|
||||
When "vert" is combined with "scrollbar", the scrollbar is drawn next to the
|
||||
vertical separator, on the panel side.
|
||||
|
||||
The scrollbar uses the |hl-PmenuSbar| highlight group for the track and
|
||||
|hl-PmenuThumb| for the thumb.
|
||||
|
||||
The scroll offset is remembered across redraws but is reset when "scroll" or
|
||||
"scrollbar" is toggled off and back on.
|
||||
|
||||
==============================================================================
|
||||
6. Setting 'guitablabel' *setting-guitablabel*
|
||||
|
||||
|
||||
@@ -10889,6 +10889,7 @@ tabpagebuflist() builtin.txt /*tabpagebuflist()*
|
||||
tabpagenr() builtin.txt /*tabpagenr()*
|
||||
tabpagewinnr() builtin.txt /*tabpagewinnr()*
|
||||
tabpanel tabpage.txt /*tabpanel*
|
||||
tabpanel-scroll tabpage.txt /*tabpanel-scroll*
|
||||
tag tagsrch.txt /*tag*
|
||||
tag-! tagsrch.txt /*tag-!*
|
||||
tag-binary-search tagsrch.txt /*tag-binary-search*
|
||||
|
||||
@@ -52616,6 +52616,9 @@ Other ~
|
||||
- Allow mouse clickable regions in the 'statusline', 'tabline' and the
|
||||
'tabpanel' using the |stl-%[FuncName]| atom.
|
||||
- Enable reflow support in the |:terminal|.
|
||||
- Added "scroll" and "scrollbar" sub-options to 'tabpanelopt' so the
|
||||
tabpanel can scroll when the tab list exceeds the visible screen
|
||||
height.
|
||||
|
||||
Platform specific ~
|
||||
-----------------
|
||||
|
||||
+8
-1
@@ -4946,6 +4946,9 @@ build_stl_str_hl_local(
|
||||
maxwid = 50;
|
||||
}
|
||||
}
|
||||
// Keep the uncapped value for %N[FuncName] click-region IDs; the 50
|
||||
// cap below applies only when minwid is used as a padding width.
|
||||
int raw_minwid = minwid * l;
|
||||
minwid = (minwid > 50 ? 50 : minwid) * l;
|
||||
if (*s == '(')
|
||||
{
|
||||
@@ -5306,7 +5309,11 @@ build_stl_str_hl_local(
|
||||
{
|
||||
stl_items[curitem].stl_type = ClickFunc;
|
||||
stl_items[curitem].stl_start = p;
|
||||
stl_items[curitem].stl_minwid = minwid;
|
||||
// The stl_minwid field is overloaded: it may be the
|
||||
// "min" part of %<min>.<max> used for padding, or an
|
||||
// identifier passed to the %N[FuncName] callback. Store
|
||||
// the uncapped value so IDs above 50 are preserved.
|
||||
stl_items[curitem].stl_minwid = raw_minwid;
|
||||
stl_items[curitem].stl_clickfunc =
|
||||
vim_strnsave(s, rb - s);
|
||||
s = rb + 1;
|
||||
|
||||
+54
-1
@@ -240,6 +240,9 @@ do_mouse(
|
||||
int in_status_line; // mouse in status line
|
||||
static int in_tab_line = FALSE; // mouse clicked in tab line
|
||||
static int in_tabpanel = FALSE; // mouse clicked in tabpanel
|
||||
#ifdef FEAT_TABPANEL
|
||||
static bool in_tabpanel_scrollbar = false; // dragging tabpanel scrollbar
|
||||
#endif
|
||||
int in_sep_line; // mouse in vertical separator line
|
||||
int c1, c2;
|
||||
#if defined(FEAT_FOLDING)
|
||||
@@ -346,6 +349,9 @@ do_mouse(
|
||||
got_click = TRUE;
|
||||
in_tab_line = FALSE;
|
||||
in_tabpanel = FALSE;
|
||||
#ifdef FEAT_TABPANEL
|
||||
in_tabpanel_scrollbar = false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -354,15 +360,31 @@ do_mouse(
|
||||
if (!is_drag) // release, reset got_click
|
||||
{
|
||||
got_click = FALSE;
|
||||
if (in_tab_line || in_tabpanel)
|
||||
if (in_tab_line || in_tabpanel
|
||||
#ifdef FEAT_TABPANEL
|
||||
|| in_tabpanel_scrollbar
|
||||
#endif
|
||||
)
|
||||
{
|
||||
in_tab_line = FALSE;
|
||||
in_tabpanel = FALSE;
|
||||
#ifdef FEAT_TABPANEL
|
||||
in_tabpanel_scrollbar = false;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FEAT_TABPANEL
|
||||
// Continue a scrollbar drag before any tab-selection handling.
|
||||
if (is_drag && in_tabpanel_scrollbar)
|
||||
{
|
||||
tabpanel_drag_scrollbar(mouse_row);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// CTRL right mouse button does CTRL-T
|
||||
if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT)
|
||||
{
|
||||
@@ -494,6 +516,15 @@ do_mouse(
|
||||
if (mouse_col < firstwin->w_wincol
|
||||
|| mouse_col >= firstwin->w_wincol + topframe->fr_width)
|
||||
{
|
||||
// A click on the scrollbar column starts a drag interaction and
|
||||
// preempts tab-selection.
|
||||
if (is_click && !is_drag && mouse_on_tabpanel_scrollbar())
|
||||
{
|
||||
in_tabpanel_scrollbar = TRUE;
|
||||
tabpanel_drag_scrollbar(mouse_row);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Dispatch 'tabpanel' %[FuncName] click regions before falling through
|
||||
// to tab-page selection. On drag events fall through to the normal
|
||||
// tab-drag handling.
|
||||
@@ -1276,6 +1307,17 @@ ins_mousescroll(int dir)
|
||||
cap.oap = &oa;
|
||||
cap.arg = dir;
|
||||
|
||||
#ifdef FEAT_TABPANEL
|
||||
if (mouse_row >= 0 && mouse_col >= 0
|
||||
&& (dir == MSCR_UP || dir == MSCR_DOWN)
|
||||
&& mouse_on_tabpanel())
|
||||
{
|
||||
(void)tabpanel_scroll(dir == MSCR_UP ? 1 : -1,
|
||||
mouse_vert_step > 0 ? mouse_vert_step : 3);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case MSCR_UP:
|
||||
@@ -2409,6 +2451,17 @@ nv_mousescroll(cmdarg_T *cap)
|
||||
{
|
||||
win_T *old_curwin = curwin;
|
||||
|
||||
#ifdef FEAT_TABPANEL
|
||||
if (mouse_row >= 0 && mouse_col >= 0
|
||||
&& (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
|
||||
&& mouse_on_tabpanel())
|
||||
{
|
||||
(void)tabpanel_scroll(cap->arg == MSCR_UP ? 1 : -1,
|
||||
mouse_vert_step > 0 ? mouse_vert_step : 3);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mouse_row >= 0 && mouse_col >= 0)
|
||||
{
|
||||
// Find the window at the mouse pointer coordinates.
|
||||
|
||||
@@ -4,4 +4,8 @@ int tabpanel_width(void);
|
||||
int tabpanel_leftcol(void);
|
||||
void draw_tabpanel(void);
|
||||
int get_tabpagenr_on_tabpanel(void);
|
||||
bool mouse_on_tabpanel(void);
|
||||
bool mouse_on_tabpanel_scrollbar(void);
|
||||
bool tabpanel_drag_scrollbar(int screen_row);
|
||||
bool tabpanel_scroll(int dir, int count);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
+213
-16
@@ -20,6 +20,7 @@ static void do_by_tplmode(int tplmode, int col_start, int col_end,
|
||||
static void tabpanel_free_click_regions(void);
|
||||
static void tabpanel_append_click_regions(stl_clickrec_T *clicktab,
|
||||
char_u *buf, int row, int col_start, int col_end, int tabnr);
|
||||
static void draw_tabpanel_scrollbar(int screen_col);
|
||||
|
||||
// set pcurtab_row. don't redraw tabpanel.
|
||||
#define TPLMODE_GET_CURTAB_ROW 0
|
||||
@@ -31,6 +32,7 @@ static void tabpanel_append_click_regions(stl_clickrec_T *clicktab,
|
||||
#define TPL_FILLCHAR ' '
|
||||
|
||||
#define VERT_LEN 1
|
||||
#define SCROLL_LEN 1
|
||||
|
||||
// tpl_align's values
|
||||
#define ALIGN_LEFT 0
|
||||
@@ -40,7 +42,12 @@ static char_u *opt_name = (char_u *)"tabpanel";
|
||||
static int opt_scope = OPT_LOCAL;
|
||||
static int tpl_align = ALIGN_LEFT;
|
||||
static int tpl_columns = 20;
|
||||
static int tpl_is_vert = FALSE;
|
||||
static bool tpl_is_vert = false;
|
||||
static bool tpl_scroll = false;
|
||||
static bool tpl_scrollbar = false;
|
||||
static int tpl_scroll_offset = 0;
|
||||
static int tpl_total_rows = 0;
|
||||
static int tpl_scrollbar_col = -1; // screen column of scrollbar, -1 if none
|
||||
|
||||
typedef struct {
|
||||
win_T *wp;
|
||||
@@ -61,7 +68,9 @@ tabpanelopt_changed(void)
|
||||
char_u *p;
|
||||
int new_align = ALIGN_LEFT;
|
||||
long new_columns = 20;
|
||||
int new_is_vert = FALSE;
|
||||
bool new_is_vert = false;
|
||||
bool new_scroll = false;
|
||||
bool new_scrollbar = false;
|
||||
|
||||
p = p_tplo;
|
||||
while (*p != NUL)
|
||||
@@ -92,7 +101,18 @@ tabpanelopt_changed(void)
|
||||
else if (STRNCMP(p, "vert", 4) == 0)
|
||||
{
|
||||
p += 4;
|
||||
new_is_vert = TRUE;
|
||||
new_is_vert = true;
|
||||
}
|
||||
else if (STRNCMP(p, "scrollbar", 9) == 0)
|
||||
{
|
||||
p += 9;
|
||||
new_scrollbar = true;
|
||||
new_scroll = true;
|
||||
}
|
||||
else if (STRNCMP(p, "scroll", 6) == 0)
|
||||
{
|
||||
p += 6;
|
||||
new_scroll = true;
|
||||
}
|
||||
|
||||
if (*p != ',' && *p != NUL)
|
||||
@@ -104,6 +124,10 @@ tabpanelopt_changed(void)
|
||||
tpl_align = new_align;
|
||||
tpl_columns = new_columns;
|
||||
tpl_is_vert = new_is_vert;
|
||||
if (tpl_scroll != new_scroll)
|
||||
tpl_scroll_offset = 0;
|
||||
tpl_scroll = new_scroll;
|
||||
tpl_scrollbar = new_scrollbar;
|
||||
|
||||
shell_new_columns();
|
||||
return OK;
|
||||
@@ -266,39 +290,65 @@ draw_tabpanel(void)
|
||||
// Reset got_int to avoid build_stl_str_hl() isn't evaluated.
|
||||
got_int = FALSE;
|
||||
|
||||
int sb_len = tpl_scrollbar ? SCROLL_LEN : 0;
|
||||
int sb_screen_col = -1;
|
||||
|
||||
if (tpl_is_vert)
|
||||
{
|
||||
if (is_right)
|
||||
{
|
||||
// draw main contents in tabpanel
|
||||
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, VERT_LEN,
|
||||
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, VERT_LEN + sb_len,
|
||||
maxwidth - VERT_LEN, &curtab_row, NULL);
|
||||
do_by_tplmode(TPLMODE_REDRAW, VERT_LEN, maxwidth, &curtab_row,
|
||||
NULL);
|
||||
do_by_tplmode(TPLMODE_REDRAW, VERT_LEN + sb_len, maxwidth,
|
||||
&curtab_row, NULL);
|
||||
// draw vert separator in tabpanel
|
||||
for (vsrow = 0; vsrow < Rows; vsrow++)
|
||||
screen_putchar(curwin->w_fill_chars.tpl_vert, vsrow,
|
||||
topframe->fr_width, vs_attr);
|
||||
if (tpl_scrollbar)
|
||||
sb_screen_col = topframe->fr_width + VERT_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw main contents in tabpanel
|
||||
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth - VERT_LEN,
|
||||
&curtab_row, NULL);
|
||||
do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth - VERT_LEN,
|
||||
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0,
|
||||
maxwidth - VERT_LEN - sb_len, &curtab_row, NULL);
|
||||
do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth - VERT_LEN - sb_len,
|
||||
&curtab_row, NULL);
|
||||
// draw vert separator in tabpanel
|
||||
for (vsrow = 0; vsrow < Rows; vsrow++)
|
||||
screen_putchar(curwin->w_fill_chars.tpl_vert, vsrow,
|
||||
maxwidth - VERT_LEN, vs_attr);
|
||||
if (tpl_scrollbar)
|
||||
sb_screen_col = maxwidth - VERT_LEN - SCROLL_LEN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth, &curtab_row, NULL);
|
||||
do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth, &curtab_row, NULL);
|
||||
if (is_right)
|
||||
{
|
||||
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, sb_len, maxwidth,
|
||||
&curtab_row, NULL);
|
||||
do_by_tplmode(TPLMODE_REDRAW, sb_len, maxwidth, &curtab_row, NULL);
|
||||
if (tpl_scrollbar)
|
||||
sb_screen_col = topframe->fr_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth - sb_len,
|
||||
&curtab_row, NULL);
|
||||
do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth - sb_len,
|
||||
&curtab_row, NULL);
|
||||
if (tpl_scrollbar)
|
||||
sb_screen_col = maxwidth - SCROLL_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
tpl_scrollbar_col = sb_screen_col;
|
||||
if (sb_screen_col >= 0)
|
||||
draw_tabpanel_scrollbar(sb_screen_col);
|
||||
|
||||
got_int |= saved_got_int;
|
||||
|
||||
// A user function may reset KeyTyped, restore it.
|
||||
@@ -556,8 +606,13 @@ do_by_tplmode(
|
||||
args.col_end = col_end;
|
||||
|
||||
if (tplmode != TPLMODE_GET_CURTAB_ROW && args.maxrow > 0)
|
||||
while (args.offsetrow + args.maxrow <= *pcurtab_row)
|
||||
args.offsetrow += args.maxrow;
|
||||
{
|
||||
if (tpl_scroll)
|
||||
args.offsetrow = tpl_scroll_offset;
|
||||
else
|
||||
while (args.offsetrow + args.maxrow <= *pcurtab_row)
|
||||
args.offsetrow += args.maxrow;
|
||||
}
|
||||
|
||||
tp = first_tabpage;
|
||||
|
||||
@@ -579,8 +634,13 @@ do_by_tplmode(
|
||||
if (tplmode == TPLMODE_GET_CURTAB_ROW)
|
||||
{
|
||||
*pcurtab_row = row;
|
||||
do_unlet((char_u *)"g:actual_curtabpage", TRUE);
|
||||
break;
|
||||
// When scroll mode is active keep iterating so tpl_total_rows
|
||||
// receives the true content height; otherwise bail out early.
|
||||
if (!tpl_scroll)
|
||||
{
|
||||
do_unlet((char_u *)"g:actual_curtabpage", TRUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -608,7 +668,8 @@ do_by_tplmode(
|
||||
stl_hlrec_T *tabtab;
|
||||
stl_clickrec_T *clicktab = NULL;
|
||||
|
||||
if (args.maxrow <= row - args.offsetrow)
|
||||
if (tplmode != TPLMODE_GET_CURTAB_ROW
|
||||
&& args.maxrow <= row - args.offsetrow)
|
||||
break;
|
||||
|
||||
buf[0] = NUL;
|
||||
@@ -677,6 +738,142 @@ do_by_tplmode(
|
||||
// fill the area of TabPanelFill.
|
||||
screen_fill_tailing_area(tplmode, MAX(row - args.offsetrow, 0), args.maxrow,
|
||||
args.col_start, args.col_end, attr_tplf);
|
||||
|
||||
// Capture the true content height during the GET_CURTAB_ROW pass, which
|
||||
// ignores maxrow and therefore walks every tab. REDRAW stops at the
|
||||
// visible edge so its "row" is clamped and unusable here.
|
||||
if (tplmode == TPLMODE_GET_CURTAB_ROW && tpl_scroll)
|
||||
tpl_total_rows = row;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the tabpanel scrollbar (track + thumb) at screen column 'screen_col'.
|
||||
* The scrollbar spans the full screen height. The thumb position and size
|
||||
* are derived from tpl_scroll_offset, tpl_total_rows and Rows.
|
||||
*/
|
||||
static void
|
||||
draw_tabpanel_scrollbar(int screen_col)
|
||||
{
|
||||
int attr_sb = HL_ATTR(HLF_PSB);
|
||||
int attr_thumb = HL_ATTR(HLF_PST);
|
||||
int thumb_top = 0;
|
||||
int thumb_height = 0;
|
||||
|
||||
if (tpl_total_rows > Rows && Rows > 0)
|
||||
{
|
||||
thumb_height = Rows * Rows / tpl_total_rows;
|
||||
if (thumb_height < 1)
|
||||
thumb_height = 1;
|
||||
thumb_top = Rows * tpl_scroll_offset / tpl_total_rows;
|
||||
if (thumb_top + thumb_height > Rows)
|
||||
thumb_top = Rows - thumb_height;
|
||||
if (thumb_top < 0)
|
||||
thumb_top = 0;
|
||||
}
|
||||
|
||||
for (int r = 0; r < Rows; r++)
|
||||
{
|
||||
bool on_thumb = thumb_height > 0
|
||||
&& r >= thumb_top && r < thumb_top + thumb_height;
|
||||
screen_putchar(TPL_FILLCHAR, r, screen_col,
|
||||
on_thumb ? attr_thumb : attr_sb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the mouse is currently positioned over the tabpanel area.
|
||||
*/
|
||||
bool
|
||||
mouse_on_tabpanel(void)
|
||||
{
|
||||
if (tabpanel_width() == 0)
|
||||
return false;
|
||||
return mouse_col < firstwin->w_wincol
|
||||
|| mouse_col >= firstwin->w_wincol + topframe->fr_width;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the mouse is currently on the scrollbar column.
|
||||
* The scrollbar column is tracked by draw_tabpanel() and is -1 when the
|
||||
* scrollbar is not enabled or not yet drawn.
|
||||
*/
|
||||
bool
|
||||
mouse_on_tabpanel_scrollbar(void)
|
||||
{
|
||||
return tpl_scrollbar && tpl_scrollbar_col >= 0
|
||||
&& mouse_col == tpl_scrollbar_col;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the scrollbar thumb so it is vertically centred on screen row
|
||||
* 'screen_row', updating tpl_scroll_offset accordingly. Used for both
|
||||
* initial clicks and subsequent drag events.
|
||||
* Returns true if the event was consumed (offset changed or not).
|
||||
*/
|
||||
bool
|
||||
tabpanel_drag_scrollbar(int screen_row)
|
||||
{
|
||||
int thumb_height;
|
||||
int max_offset;
|
||||
int track_range;
|
||||
int thumb_top;
|
||||
int new_offset;
|
||||
|
||||
if (!tpl_scrollbar || Rows <= 0 || tpl_total_rows <= Rows)
|
||||
return false;
|
||||
|
||||
thumb_height = Rows * Rows / tpl_total_rows;
|
||||
if (thumb_height < 1)
|
||||
thumb_height = 1;
|
||||
track_range = Rows - thumb_height;
|
||||
if (track_range <= 0)
|
||||
return true;
|
||||
|
||||
max_offset = tpl_total_rows - Rows;
|
||||
thumb_top = screen_row - thumb_height / 2;
|
||||
if (thumb_top < 0)
|
||||
thumb_top = 0;
|
||||
if (thumb_top > track_range)
|
||||
thumb_top = track_range;
|
||||
|
||||
new_offset = thumb_top * max_offset / track_range;
|
||||
if (new_offset != tpl_scroll_offset)
|
||||
{
|
||||
tpl_scroll_offset = new_offset;
|
||||
redraw_tabpanel = TRUE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scroll the tabpanel by 'count' rows in direction 'dir' (1 = down, -1 = up).
|
||||
* Returns true if the offset changed and a redraw was scheduled.
|
||||
* Has no effect unless 'tabpanelopt' contains "scroll".
|
||||
*/
|
||||
bool
|
||||
tabpanel_scroll(int dir, int count)
|
||||
{
|
||||
int max_offset;
|
||||
int new_offset;
|
||||
|
||||
if (!tpl_scroll || tabpanel_width() == 0)
|
||||
return false;
|
||||
|
||||
max_offset = tpl_total_rows - Rows;
|
||||
if (max_offset < 0)
|
||||
max_offset = 0;
|
||||
|
||||
new_offset = tpl_scroll_offset + (dir > 0 ? count : -count);
|
||||
if (new_offset < 0)
|
||||
new_offset = 0;
|
||||
if (new_offset > max_offset)
|
||||
new_offset = max_offset;
|
||||
if (new_offset == tpl_scroll_offset)
|
||||
return false;
|
||||
|
||||
tpl_scroll_offset = new_offset;
|
||||
redraw_tabpanel = TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // FEAT_TABPANEL
|
||||
|
||||
@@ -962,8 +962,68 @@ func Test_tabpanel_large_columns()
|
||||
call assert_fails(':set tabpanelopt=columns:-1', 'E474:')
|
||||
endfunc
|
||||
|
||||
func Test_tabpanel_scrollopt_accepted()
|
||||
" 'scroll' / 'scrollbar' must be accepted in 'tabpanelopt'.
|
||||
set tabpanelopt=scroll
|
||||
call assert_equal('scroll', &tabpanelopt)
|
||||
set tabpanelopt=scrollbar
|
||||
call assert_equal('scrollbar', &tabpanelopt)
|
||||
|
||||
" Combination with other values.
|
||||
set tabpanelopt=align:right,scroll
|
||||
call assert_equal('align:right,scroll', &tabpanelopt)
|
||||
set tabpanelopt=columns:15,vert,scrollbar
|
||||
call assert_equal('columns:15,vert,scrollbar', &tabpanelopt)
|
||||
set tabpanelopt=align:right,columns:12,vert,scrollbar
|
||||
call assert_equal('align:right,columns:12,vert,scrollbar', &tabpanelopt)
|
||||
|
||||
" Unknown values must still fail.
|
||||
call assert_fails(':set tabpanelopt=scrol', 'E474:')
|
||||
call assert_fails(':set tabpanelopt=scrollbarx', 'E474:')
|
||||
|
||||
call s:reset()
|
||||
endfunc
|
||||
|
||||
func Test_tabpanel_scroll_many_tabs()
|
||||
let save_lines = &lines
|
||||
let save_showtabpanel = &showtabpanel
|
||||
let save_tabpanelopt = &tabpanelopt
|
||||
|
||||
" Make the screen short so the tab list exceeds the visible height.
|
||||
set lines=8
|
||||
set showtabpanel=2
|
||||
set tabpanelopt=scroll
|
||||
for i in range(20)
|
||||
tabnew
|
||||
endfor
|
||||
|
||||
" Should not crash with many tabs and scroll enabled.
|
||||
redraw!
|
||||
|
||||
" Switching to scrollbar resets the offset but must also not crash.
|
||||
set tabpanelopt=scrollbar
|
||||
redraw!
|
||||
|
||||
" Disabling scroll returns to normal behavior.
|
||||
set tabpanelopt=
|
||||
redraw!
|
||||
|
||||
" Right alignment with scrollbar.
|
||||
set tabpanelopt=align:right,scrollbar
|
||||
redraw!
|
||||
|
||||
" Vertical separator with scrollbar.
|
||||
set tabpanelopt=columns:10,vert,scrollbar
|
||||
redraw!
|
||||
|
||||
" Cleanup.
|
||||
%bwipeout!
|
||||
let &tabpanelopt = save_tabpanelopt
|
||||
let &showtabpanel = save_showtabpanel
|
||||
let &lines = save_lines
|
||||
endfunc
|
||||
|
||||
func Test_tabpanel_variable_height()
|
||||
CheckFeature tabpanel
|
||||
|
||||
let save_lines = &lines
|
||||
let save_showtabpanel = &showtabpanel
|
||||
|
||||
@@ -729,6 +729,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
386,
|
||||
/**/
|
||||
385,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user