summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-06-25 05:15:58 +0200
committerBram Moolenaar <Bram@vim.org>2019-06-25 05:15:58 +0200
commit75fb0854e93913c4d2cfcd6ef634173c4d13a093 (patch)
treec2da703ce73474a764e4f7acf6759c705303003c
parente96a2498f9a2d3e93ac07431f6d4afd77f30afdf (diff)
downloadvim-git-8.1.1589.tar.gz
patch 8.1.1589: popup window does not indicate scroll positionv8.1.1589
Problem: Popup window does not indicate scroll position. Solution: Add a scrollbar.
-rw-r--r--runtime/doc/popup.txt12
-rw-r--r--src/popupwin.c59
-rw-r--r--src/structs.h2
-rw-r--r--src/testdir/dumps/Test_popupwin_firstline.dump8
-rw-r--r--src/testdir/dumps/Test_popupwin_scroll_1.dump10
-rw-r--r--src/testdir/dumps/Test_popupwin_scroll_2.dump10
-rw-r--r--src/testdir/dumps/Test_popupwin_scroll_3.dump10
-rw-r--r--src/testdir/dumps/Test_popupwin_scroll_4.dump10
-rw-r--r--src/testdir/test_popupwin.vim32
-rw-r--r--src/version.c2
10 files changed, 143 insertions, 12 deletions
diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt
index d04a6b44e..21af8f9e2 100644
--- a/runtime/doc/popup.txt
+++ b/runtime/doc/popup.txt
@@ -87,9 +87,10 @@ that it is in.
TODO:
-- Why does 'nrformats' leak from the popup window buffer???
- When the lines do not fit show a scrollbar (like in the popup menu).
- Use the mouse wheel for scrolling.
+- Use the mouse wheel for scrolling.
+- Have a way to scroll to the botton. (#4577)
+- Why does 'nrformats' leak from the popup window buffer???
- Disable commands, feedkeys(), CTRL-W, etc. in a popup window.
Use ERROR_IF_POPUP_WINDOW for more commands.
- Add 'balloonpopup': instead of showing text, let the callback open a popup
@@ -347,6 +348,9 @@ popup_notification({text}, {options}) *popup_notification()*
< The PopupNotification highlight group is used instead of
WarningMsg if it is defined.
+ This popup should only be used with the |+timers| feature,
+ otherwise it will not disappear.
+
The position will be adjusted to avoid overlap with other
notifications.
Use {options} to change the properties.
@@ -370,6 +374,7 @@ popup_setoptions({id}, {options}) *popup_setoptions()*
border
borderhighlight
borderchars
+ scrollbar
zindex
mask
time
@@ -475,6 +480,7 @@ The second argument of |popup_create()| is a dictionary with options:
firstline First buffer line to display. When larger than one it
looks like the text scrolled up. When out of range
the last buffer line will at the top of the window.
+ Also see "scrollbar".
hidden When TRUE the popup exists but is not displayed; use
`popup_show()` to unhide it.
{not implemented yet}
@@ -525,6 +531,8 @@ The second argument of |popup_create()| is a dictionary with options:
By default a double line is used all around when
'encoding' is "utf-8" and 'ambiwidth' is "single",
otherwise ASCII characters are used.
+ scrollbar non-zero: show a scrollbar when the text doesn't fit.
+ zero: do not show a scrollbar. Default is non-zero.
zindex Priority for the popup, default 50. Minimum value is
1, maximum value is 32000.
mask A list of lists with coordinates, defining parts of
diff --git a/src/popupwin.c b/src/popupwin.c
index 16ec1a283..aa8bba088 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -287,6 +287,10 @@ apply_general_options(win_T *wp, dict_T *dict)
if (wp->w_firstline < 1)
wp->w_firstline = 1;
+ di = dict_find(dict, (char_u *)"scrollbar", -1);
+ if (di != NULL)
+ wp->w_want_scrollbar = dict_get_number(dict, (char_u *)"scrollbar");
+
str = dict_get_string(dict, (char_u *)"title", FALSE);
if (str != NULL)
{
@@ -733,6 +737,9 @@ popup_adjust_position(win_T *wp)
break;
}
+ wp->w_has_scrollbar = wp->w_want_scrollbar
+ && (wp->w_topline > 1 || lnum <= wp->w_buffer->b_ml.ml_line_count);
+
minwidth = wp->w_minwidth;
if (wp->w_popup_title != NULL && *wp->w_popup_title != NUL)
{
@@ -1047,6 +1054,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
VIM_CLEAR(wp->w_border_highlight[i]);
for (i = 0; i < 8; ++i)
wp->w_border_char[i] = 0;
+ wp->w_want_scrollbar = 1;
// Deal with options.
apply_options(wp, argvars[1].vval.v_dict);
@@ -1483,6 +1491,7 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
dict_T *dict;
int id = (int)tv_get_number(argvars);
win_T *wp = find_popup_win(id);
+ linenr_T old_firstline;
if (wp == NULL)
return; // invalid {id}
@@ -1493,10 +1502,13 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
return;
}
dict = argvars[1].vval.v_dict;
+ old_firstline = wp->w_firstline;
apply_move_options(wp, dict);
apply_general_options(wp, dict);
+ if (old_firstline != wp->w_firstline)
+ redraw_win_later(wp, NOT_VALID);
popup_mask_refresh = TRUE;
popup_adjust_position(wp);
}
@@ -1534,6 +1546,7 @@ f_popup_getpos(typval_T *argvars, typval_T *rettv)
dict_add_number(dict, "core_width", wp->w_width);
dict_add_number(dict, "core_height", wp->w_height);
+ dict_add_number(dict, "scrollbar", wp->w_has_scrollbar);
dict_add_number(dict, "visible",
win_valid(wp) && (wp->w_popup_flags & POPF_HIDDEN) == 0);
}
@@ -1656,6 +1669,7 @@ f_popup_getoptions(typval_T *argvars, typval_T *rettv)
dict_add_number(dict, "maxheight", wp->w_maxheight);
dict_add_number(dict, "maxwidth", wp->w_maxwidth);
dict_add_number(dict, "firstline", wp->w_firstline);
+ dict_add_number(dict, "scrollbar", wp->w_want_scrollbar);
dict_add_number(dict, "zindex", wp->w_zindex);
dict_add_number(dict, "fixed", wp->w_popup_fixed);
dict_add_string(dict, "title", wp->w_popup_title);
@@ -2114,6 +2128,10 @@ update_popups(void (*win_update)(win_T *wp))
char_u buf[MB_MAXBYTES];
int row;
int i;
+ int sb_thumb_top;
+ int sb_thumb_height;
+ int attr_scroll = highlight_attr[HLF_PSB];
+ int attr_thumb = highlight_attr[HLF_PST];
// Find the window with the lowest zindex that hasn't been updated yet,
// so that the window with a higher zindex is drawn later, thus goes on
@@ -2143,7 +2161,8 @@ update_popups(void (*win_update)(win_T *wp))
wp->w_wincol -= left_off;
total_width = wp->w_popup_border[3] + wp->w_popup_padding[3]
- + wp->w_width + wp->w_popup_padding[1] + wp->w_popup_border[1];
+ + wp->w_width + wp->w_popup_padding[1] + wp->w_popup_border[1]
+ + wp->w_has_scrollbar;
total_height = popup_top_extra(wp)
+ wp->w_height + wp->w_popup_padding[2] + wp->w_popup_border[2];
popup_attr = get_wcr_attr(wp);
@@ -2203,7 +2222,8 @@ update_popups(void (*win_update)(win_T *wp))
row = wp->w_winrow + wp->w_popup_border[0];
screen_fill(row, row + top_padding,
wp->w_wincol + wp->w_popup_border[3],
- wp->w_wincol + total_width - wp->w_popup_border[1],
+ wp->w_wincol + total_width - wp->w_popup_border[1]
+ - wp->w_has_scrollbar,
' ', ' ', popup_attr);
}
@@ -2212,10 +2232,24 @@ update_popups(void (*win_update)(win_T *wp))
screen_puts(wp->w_popup_title, wp->w_winrow, wp->w_wincol + 1,
wp->w_popup_border[0] > 0 ? border_attr[0] : popup_attr);
- for (row = wp->w_winrow + wp->w_popup_border[0];
- row < wp->w_winrow + total_height - wp->w_popup_border[2];
- ++row)
+ // Compute scrollbar thumb position and size.
+ if (wp->w_has_scrollbar)
+ {
+ linenr_T linecount = wp->w_buffer->b_ml.ml_line_count;
+
+ sb_thumb_height = wp->w_height * wp->w_height / linecount;
+ if (sb_thumb_height == 0)
+ sb_thumb_height = 1;
+ sb_thumb_top = ((wp->w_topline * (wp->w_height - sb_thumb_height)
+ + (linecount - wp->w_height) / 2))
+ / (linecount - (wp->w_height - sb_thumb_height));
+ }
+
+ for (i = wp->w_popup_border[0];
+ i < total_height - wp->w_popup_border[2]; ++i)
{
+ row = wp->w_winrow + i;
+
// left border
if (wp->w_popup_border[3] > 0)
{
@@ -2226,6 +2260,21 @@ update_popups(void (*win_update)(win_T *wp))
if (wp->w_popup_padding[3] > 0)
screen_puts(get_spaces(wp->w_popup_padding[3]), row,
wp->w_wincol + wp->w_popup_border[3], popup_attr);
+ // scrollbar
+ if (wp->w_has_scrollbar)
+ {
+ int line = i - top_off;
+ int scroll_col = wp->w_wincol + total_width - 1
+ - wp->w_popup_border[1];
+
+ if (line >= 0 && line < wp->w_height)
+ screen_putchar(' ', row, scroll_col,
+ line >= sb_thumb_top
+ && line < sb_thumb_top + sb_thumb_height
+ ? attr_thumb : attr_scroll);
+ else
+ screen_putchar(' ', row, scroll_col, popup_attr);
+ }
// right border
if (wp->w_popup_border[1] > 0)
{
diff --git a/src/structs.h b/src/structs.h
index c664f0eb2..9992e99fd 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2902,6 +2902,8 @@ struct window_S
int w_wantline; // "line" for popup window
int w_wantcol; // "col" for popup window
int w_firstline; // "firstline" for popup window
+ int w_want_scrollbar; // when zero don't use a scrollbar
+ int w_has_scrollbar; // scrollbar displayed
int w_popup_padding[4]; // popup padding top/right/bot/left
int w_popup_border[4]; // popup border top/right/bot/left
char_u *w_border_highlight[4]; // popup border highlight
diff --git a/src/testdir/dumps/Test_popupwin_firstline.dump b/src/testdir/dumps/Test_popupwin_firstline.dump
index 276f4e519..7efcf3ef4 100644
--- a/src/testdir/dumps/Test_popupwin_firstline.dump
+++ b/src/testdir/dumps/Test_popupwin_firstline.dump
@@ -1,10 +1,10 @@
>1+0&#ffffff0| @73
|2| @73
|3| @73
-|4| @33|3+0#0000001#ffd7ff255@4| +0#0000000#ffffff0@34
-|5| @33|4+0#0000001#ffd7ff255@1| @2| +0#0000000#ffffff0@34
-|6| @33|5+0#0000001#ffd7ff255| @3| +0#0000000#ffffff0@34
-|7| @33|6+0#0000001#ffd7ff255@4| +0#0000000#ffffff0@34
+|4| @33|3+0#0000001#ffd7ff255@4| +0#0000000#a8a8a8255| +0&#ffffff0@33
+|5| @33|4+0#0000001#ffd7ff255@1| @2| +0#0000000#0000001| +0&#ffffff0@33
+|6| @33|5+0#0000001#ffd7ff255| @3| +0#0000000#a8a8a8255| +0&#ffffff0@33
+|7| @33|6+0#0000001#ffd7ff255@4| +0#0000000#a8a8a8255| +0&#ffffff0@33
|8| @73
|9| @73
@57|1|,|1| @10|T|o|p|
diff --git a/src/testdir/dumps/Test_popupwin_scroll_1.dump b/src/testdir/dumps/Test_popupwin_scroll_1.dump
new file mode 100644
index 000000000..dd0e0b37e
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_scroll_1.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @73
+|4| @31|o+0#0000001#ffd7ff255|n|e| @4| +0#0000000#0000001| +0&#ffffff0@32
+|5| @31|t+0#0000001#ffd7ff255|w|o| @4| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|6| @31|t+0#0000001#ffd7ff255|h|r|e@1| @2| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|7| @31|f+0#0000001#ffd7ff255|o|u|r| @3| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|8| @73
+|9| @73
+@57|1|,|1| @10|T|o|p|
diff --git a/src/testdir/dumps/Test_popupwin_scroll_2.dump b/src/testdir/dumps/Test_popupwin_scroll_2.dump
new file mode 100644
index 000000000..21d33da4e
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_scroll_2.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @73
+|4| @31|t+0#0000001#ffd7ff255|w|o| @4| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|5| @31|t+0#0000001#ffd7ff255|h|r|e@1| @2| +0#0000000#0000001| +0&#ffffff0@32
+|6| @31|f+0#0000001#ffd7ff255|o|u|r| @3| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|7| @31|f+0#0000001#ffd7ff255|i|v|e| @3| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|8| @73
+|9| @73
+|:|c|a|l@1| |p|o|p|u|p|_|s|e|t|o|p|t|i|o|n|s|(|w|i|n|i|d|,| |{|'|f|i|r|s|t|l|i|n|e|'|:| |2|}|)| @9|1|,|1| @10|T|o|p|
diff --git a/src/testdir/dumps/Test_popupwin_scroll_3.dump b/src/testdir/dumps/Test_popupwin_scroll_3.dump
new file mode 100644
index 000000000..656e058bf
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_scroll_3.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @73
+|4| @31|s+0#0000001#ffd7ff255|i|x| @4| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|5| @31|s+0#0000001#ffd7ff255|e|v|e|n| @2| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|6| @31|e+0#0000001#ffd7ff255|i|g|h|t| @2| +0#0000000#a8a8a8255| +0&#ffffff0@32
+|7| @31|n+0#0000001#ffd7ff255|i|n|e| @3| +0#0000000#0000001| +0&#ffffff0@32
+|8| @73
+|9| @73
+|:|c|a|l@1| |p|o|p|u|p|_|s|e|t|o|p|t|i|o|n|s|(|w|i|n|i|d|,| |{|'|f|i|r|s|t|l|i|n|e|'|:| |6|}|)| @9|1|,|1| @10|T|o|p|
diff --git a/src/testdir/dumps/Test_popupwin_scroll_4.dump b/src/testdir/dumps/Test_popupwin_scroll_4.dump
new file mode 100644
index 000000000..5f35a1f9f
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_scroll_4.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @73
+|4| @73
+|5| @31|n+0#0000001#ffd7ff255|i|n|e| @3| +0#0000000#0000001| +0&#ffffff0@32
+|6| @73
+|7| @73
+|8| @73
+|9| @73
+|:|c|a|l@1| |p|o|p|u|p|_|s|e|t|o|p|t|i|o|n|s|(|w|i|n|i|d|,| |{|'|f|i|r|s|t|l|i|n|e|'|:| |9|}|)| @9|1|,|1| @10|T|o|p|
diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim
index b4bfcef41..1e8f522c9 100644
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -1407,12 +1407,42 @@ func Test_notifications()
call term_sendkeys(buf, ":call popup_notification('another important notification', {})\<CR>")
call VerifyScreenDump(buf, 'Test_popupwin_notify_02', {})
-
" clean up
call StopVimInTerminal(buf)
call delete('XtestNotifications')
endfunc
+func Test_popup_scrollbar()
+ if !CanRunVimInTerminal()
+ throw 'Skipped: cannot make screendumps'
+ endif
+
+ let lines =<< trim END
+ call setline(1, range(1, 20))
+ let winid = popup_create(['one', 'two', 'three', 'four', 'five',
+ \ 'six', 'seven', 'eight', 'nine'], {
+ \ 'minwidth': 8,
+ \ 'maxheight': 4,
+ \ })
+ END
+ call writefile(lines, 'XtestPopupScroll')
+ let buf = RunVimInTerminal('-S XtestPopupScroll', {'rows': 10})
+ call VerifyScreenDump(buf, 'Test_popupwin_scroll_1', {})
+
+ call term_sendkeys(buf, ":call popup_setoptions(winid, {'firstline': 2})\<CR>")
+ call VerifyScreenDump(buf, 'Test_popupwin_scroll_2', {})
+
+ call term_sendkeys(buf, ":call popup_setoptions(winid, {'firstline': 6})\<CR>")
+ call VerifyScreenDump(buf, 'Test_popupwin_scroll_3', {})
+
+ call term_sendkeys(buf, ":call popup_setoptions(winid, {'firstline': 9})\<CR>")
+ call VerifyScreenDump(buf, 'Test_popupwin_scroll_4', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('XtestPopupScroll')
+endfunc
+
func Test_popup_settext()
if !CanRunVimInTerminal()
throw 'Skipped: cannot make screendumps'
diff --git a/src/version.c b/src/version.c
index 3f3d77fd2..34af0de9b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -778,6 +778,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1589,
+/**/
1588,
/**/
1587,