forked from aniani/vim
patch 8.1.1443: popup window padding and border not implemented yet
Problem: Popup window padding and border not implemented yet. Solution: Implement padding and border. Add core position and size to popup_getpos().
This commit is contained in:
parent
8caaf82569
commit
2fd8e35e16
@ -90,11 +90,7 @@ Probably 2. is the best choice.
|
||||
|
||||
IMPLEMENTATION:
|
||||
- Code is in popupwin.c
|
||||
- Invoke filter with character before mapping?
|
||||
- Handle screen resize in screenalloc(). (Ben Jackson, #4467)
|
||||
- Why does 'nrformats' leak from the popup window buffer???
|
||||
- Implement padding
|
||||
- Implement border
|
||||
- Make redrawing more efficient and avoid flicker.
|
||||
Store popup info in a mask, use the mask in screen_line()
|
||||
Keep mask until next update_screen(), find differences and redraw affected
|
||||
@ -103,7 +99,8 @@ IMPLEMENTATION:
|
||||
Fix redrawing problem when scrolling non-current window
|
||||
Fix redrawing the statusline on top of a popup
|
||||
- Disable commands, feedkeys(), CTRL-W, etc. in a popup window.
|
||||
Use NOT_IN_POPUP_WINDOW.
|
||||
Use NOT_IN_POPUP_WINDOW for more commands.
|
||||
- Invoke filter with character before mapping?
|
||||
- Figure out the size and position better.
|
||||
if wrapping splits a double-wide character
|
||||
if wrapping inserts indent
|
||||
@ -255,12 +252,19 @@ popup_getpos({id}) *popup_getpos()*
|
||||
with these entries:
|
||||
col screen column of the popup, one-based
|
||||
line screen line of the popup, one-based
|
||||
width width of the popup in screen cells
|
||||
height height of the popup in screen cells
|
||||
width width of the whole popup in screen cells
|
||||
height height of the whole popup in screen cells
|
||||
core_col screen column of the text box
|
||||
core_line screen line of the text box
|
||||
core_width width of the text box in screen cells
|
||||
core_height height of the text box in screen cells
|
||||
visible one if the popup is displayed, zero if hidden
|
||||
Note that these are the actual screen positions. They differ
|
||||
from the values in `popup_getoptions()` for the sizing and
|
||||
positioning mechanism applied.
|
||||
|
||||
The "core_" values exclude the padding and border.
|
||||
|
||||
If popup window {id} is not found an empty Dict is returned.
|
||||
|
||||
|
||||
@ -361,11 +365,10 @@ The second argument of |popup_create()| is a dictionary with options:
|
||||
padding uses the 'wincolor' highlight; Example: [1, 2,
|
||||
1, 3] has 1 line of padding above, 2 columns on the
|
||||
right, 1 line below and 3 columns on the left
|
||||
{not implemented yet}
|
||||
border list with numbers, defining the border thickness
|
||||
above/right/below/left of the popup (similar to CSS);
|
||||
only values of zero and non-zero are recognized;
|
||||
an empty list uses a border of 1 all around
|
||||
{not implemented yet}
|
||||
borderhighlight highlight group name to use for the border
|
||||
{not implemented yet}
|
||||
borderchars list with characters, defining the character to use
|
||||
|
@ -101,6 +101,38 @@ get_pos_options(win_T *wp, dict_T *dict)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_padding_border(dict_T *dict, int *array, char *name, int max_val)
|
||||
{
|
||||
dictitem_T *di;
|
||||
|
||||
vim_memset(array, 0, sizeof(int) * 4);
|
||||
di = dict_find(dict, (char_u *)name, -1);
|
||||
if (di != NULL)
|
||||
{
|
||||
if (di->di_tv.v_type != VAR_LIST)
|
||||
emsg(_(e_listreq));
|
||||
else
|
||||
{
|
||||
list_T *list = di->di_tv.vval.v_list;
|
||||
listitem_T *li;
|
||||
int i;
|
||||
int nr;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
array[i] = 1;
|
||||
if (list != NULL)
|
||||
for (i = 0, li = list->lv_first; i < 4 && i < list->lv_len;
|
||||
++i, li = li->li_next)
|
||||
{
|
||||
nr = (int)tv_get_number(&li->li_tv);
|
||||
if (nr >= 0)
|
||||
array[i] = nr > max_val ? max_val : nr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through the options in "dict" and apply them to buffer "buf" displayed in
|
||||
* popup window "wp".
|
||||
@ -176,6 +208,9 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict, int atcursor)
|
||||
if (callback.cb_name != NULL)
|
||||
set_callback(&wp->w_filter_cb, &callback);
|
||||
}
|
||||
|
||||
get_padding_border(dict, wp->w_popup_padding, "padding", 999);
|
||||
get_padding_border(dict, wp->w_popup_border, "border", 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -700,16 +735,28 @@ f_popup_getpos(typval_T *argvars, typval_T *rettv)
|
||||
dict_T *dict;
|
||||
int id = (int)tv_get_number(argvars);
|
||||
win_T *wp = find_popup_win(id);
|
||||
int top_extra;
|
||||
int left_extra;
|
||||
|
||||
if (rettv_dict_alloc(rettv) == OK)
|
||||
{
|
||||
if (wp == NULL)
|
||||
return; // invalid {id}
|
||||
top_extra = wp->w_popup_border[0] + wp->w_popup_padding[0];
|
||||
left_extra = wp->w_popup_border[3] + wp->w_popup_padding[3];
|
||||
|
||||
dict = rettv->vval.v_dict;
|
||||
|
||||
dict_add_number(dict, "line", wp->w_winrow + 1);
|
||||
dict_add_number(dict, "col", wp->w_wincol + 1);
|
||||
dict_add_number(dict, "width", wp->w_width);
|
||||
dict_add_number(dict, "height", wp->w_height);
|
||||
dict_add_number(dict, "width", wp->w_width + left_extra + wp->w_popup_border[1] + wp->w_popup_padding[1]);
|
||||
dict_add_number(dict, "height", wp->w_height + top_extra + wp->w_popup_border[2] + wp->w_popup_padding[2]);
|
||||
|
||||
dict_add_number(dict, "core_line", wp->w_winrow + 1 + top_extra);
|
||||
dict_add_number(dict, "core_col", wp->w_wincol + 1 + left_extra);
|
||||
dict_add_number(dict, "core_width", wp->w_width);
|
||||
dict_add_number(dict, "core_height", wp->w_height);
|
||||
|
||||
dict_add_number(dict, "visible",
|
||||
(wp->w_popup_flags & POPF_HIDDEN) == 0);
|
||||
}
|
||||
|
148
src/screen.c
148
src/screen.c
@ -991,28 +991,6 @@ update_debug_sign(buf_T *buf, linenr_T lnum)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
static void
|
||||
update_popups(void)
|
||||
{
|
||||
win_T *wp;
|
||||
|
||||
// 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
|
||||
// top.
|
||||
// TODO: don't redraw every popup every time.
|
||||
popup_reset_handled();
|
||||
while ((wp = find_next_popup(TRUE)) != NULL)
|
||||
{
|
||||
// Recompute the position if the text changed.
|
||||
if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
|
||||
popup_adjust_position(wp);
|
||||
|
||||
win_update(wp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get 'wincolor' attribute for window "wp". If not set and "wp" is a popup
|
||||
* window then get the "Pmenu" highlight attribute.
|
||||
@ -1031,6 +1009,132 @@ get_wcr_attr(win_T *wp)
|
||||
return wcr_attr;
|
||||
}
|
||||
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
/*
|
||||
* Return a string of "len" spaces in IObuff.
|
||||
*/
|
||||
static char_u *
|
||||
get_spaces(int len)
|
||||
{
|
||||
vim_memset(IObuff, ' ', (size_t)len);
|
||||
IObuff[len] = NUL;
|
||||
return IObuff;
|
||||
}
|
||||
|
||||
static void
|
||||
update_popups(void)
|
||||
{
|
||||
win_T *wp;
|
||||
int top_off;
|
||||
int left_off;
|
||||
int total_width;
|
||||
int total_height;
|
||||
int popup_attr;
|
||||
int row;
|
||||
|
||||
// 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
|
||||
// top.
|
||||
// TODO: don't redraw every popup every time.
|
||||
popup_reset_handled();
|
||||
while ((wp = find_next_popup(TRUE)) != NULL)
|
||||
{
|
||||
// Recompute the position if the text changed.
|
||||
if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
|
||||
popup_adjust_position(wp);
|
||||
|
||||
// adjust w_winrow and w_wincol for border and padding, since
|
||||
// win_update() doesn't handle them.
|
||||
top_off = wp->w_popup_padding[0] + wp->w_popup_border[0];
|
||||
left_off = wp->w_popup_padding[3] + wp->w_popup_border[3];
|
||||
wp->w_winrow += top_off;
|
||||
wp->w_wincol += left_off;
|
||||
|
||||
// Draw the popup text.
|
||||
win_update(wp);
|
||||
|
||||
wp->w_winrow -= top_off;
|
||||
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];
|
||||
total_height = wp->w_popup_border[0] + wp->w_popup_padding[0]
|
||||
+ wp->w_height + wp->w_popup_padding[2] + wp->w_popup_border[2];
|
||||
popup_attr = get_wcr_attr(wp);
|
||||
|
||||
if (wp->w_popup_border[0] > 0)
|
||||
{
|
||||
// top border
|
||||
screen_fill(wp->w_winrow, wp->w_winrow + 1,
|
||||
wp->w_wincol,
|
||||
wp->w_wincol + total_width,
|
||||
wp->w_popup_border[3] != 0 ? '+' : '-',
|
||||
'-', popup_attr);
|
||||
if (wp->w_popup_border[1] > 0)
|
||||
screen_puts((char_u *)"+", wp->w_winrow,
|
||||
wp->w_wincol + total_width - 1, popup_attr);
|
||||
}
|
||||
|
||||
if (wp->w_popup_padding[0] > 0)
|
||||
{
|
||||
// top padding
|
||||
row = wp->w_winrow + wp->w_popup_border[0];
|
||||
screen_fill(row, row + wp->w_popup_padding[0],
|
||||
wp->w_wincol + wp->w_popup_border[3],
|
||||
wp->w_wincol + total_width - wp->w_popup_border[1],
|
||||
' ', ' ', popup_attr);
|
||||
}
|
||||
|
||||
for (row = wp->w_winrow + wp->w_popup_border[0];
|
||||
row < wp->w_winrow + total_height - wp->w_popup_border[2];
|
||||
++row)
|
||||
{
|
||||
// left border
|
||||
if (wp->w_popup_border[3] > 0)
|
||||
screen_puts((char_u *)"|", row, wp->w_wincol, popup_attr);
|
||||
// left padding
|
||||
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);
|
||||
// right border
|
||||
if (wp->w_popup_border[1] > 0)
|
||||
screen_puts((char_u *)"|", row,
|
||||
wp->w_wincol + total_width - 1, popup_attr);
|
||||
// right padding
|
||||
if (wp->w_popup_padding[1] > 0)
|
||||
screen_puts(get_spaces(wp->w_popup_padding[1]), row,
|
||||
wp->w_wincol + wp->w_popup_border[3]
|
||||
+ wp->w_popup_padding[3] + wp->w_width, popup_attr);
|
||||
}
|
||||
|
||||
if (wp->w_popup_padding[2] > 0)
|
||||
{
|
||||
// bottom padding
|
||||
row = wp->w_winrow + wp->w_popup_border[0]
|
||||
+ wp->w_popup_padding[0] + wp->w_height;
|
||||
screen_fill(row, row + wp->w_popup_padding[2],
|
||||
wp->w_wincol + wp->w_popup_border[3],
|
||||
wp->w_wincol + total_width - wp->w_popup_border[1],
|
||||
' ', ' ', popup_attr);
|
||||
}
|
||||
|
||||
if (wp->w_popup_border[2] > 0)
|
||||
{
|
||||
// bottom border
|
||||
row = wp->w_winrow + total_height - 1;
|
||||
screen_fill(row , row + 1,
|
||||
wp->w_wincol,
|
||||
wp->w_wincol + total_width,
|
||||
wp->w_popup_border[3] != 0 ? '+' : '-',
|
||||
'-', popup_attr);
|
||||
if (wp->w_popup_border[1] > 0)
|
||||
screen_puts((char_u *)"+", row,
|
||||
wp->w_wincol + total_width - 1, popup_attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FEAT_GUI) || defined(PROTO)
|
||||
/*
|
||||
* Update a single window, its status line and maybe the command line msg.
|
||||
|
@ -2888,6 +2888,8 @@ struct window_S
|
||||
int w_maxwidth; // "maxwidth" for popup window
|
||||
int w_wantline; // "line" for popup window
|
||||
int w_wantcol; // "col" for popup window
|
||||
int w_popup_padding[4]; // popup padding top/right/bot/left
|
||||
int w_popup_border[4]; // popup border top/right/bot/left
|
||||
varnumber_T w_popup_last_changedtick; // b:changedtick when position was
|
||||
// computed
|
||||
callback_T w_filter_cb; // popup filter callback
|
||||
|
15
src/testdir/dumps/Test_popupwin_20.dump
Normal file
15
src/testdir/dumps/Test_popupwin_20.dump
Normal file
@ -0,0 +1,15 @@
|
||||
>1+0&#ffffff0| @73
|
||||
|2| |++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@18
|
||||
|3| ||+0#0000001#ffd7ff255|h|e|l@1|o| |b|o|r|d|e|r||| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255|h|e|l@1|o| |p|a|d@1|i|n|g| | +0#0000000#ffffff0@4||+0#0000001#ffd7ff255| @11||| +0#0000000#ffffff0@18
|
||||
|4| |++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4||+0#0000001#ffd7ff255| |h|e|l@1|o| |b|o|t|h| ||| +0#0000000#ffffff0@18
|
||||
|5| @40||+0#0000001#ffd7ff255| @11||| +0#0000000#ffffff0@18
|
||||
|6| |++0#0000001#ffd7ff255|-@8| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@18
|
||||
|7| ||+0#0000001#ffd7ff255|b|o|r|d|e|r| |T|L| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@3|p|a|d@1|i|n|g|s| @2| +0#0000000#ffffff0@37
|
||||
|8| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@37
|
||||
|9| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@37
|
||||
|1|0| @72
|
||||
|1@1| @72
|
||||
|1|2| @72
|
||||
|1|3| @72
|
||||
|1|4| @72
|
||||
@57|1|,|1| @10|T|o|p|
|
@ -56,6 +56,54 @@ func Test_simple_popup()
|
||||
call delete('XtestPopup')
|
||||
endfunc
|
||||
|
||||
func Test_popup_with_border_and_padding()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
call writefile([
|
||||
\ "call setline(1, range(1, 100))",
|
||||
\ "call popup_create('hello border', {'line': 2, 'col': 3, 'border': []})",
|
||||
\ "call popup_create('hello padding', {'line': 2, 'col': 23, 'padding': []})",
|
||||
\ "call popup_create('hello both', {'line': 2, 'col': 43, 'border': [], 'padding': []})",
|
||||
\ "call popup_create('border TL', {'line': 6, 'col': 3, 'border': [1, 0, 0, 4]})",
|
||||
\ "call popup_create('paddings', {'line': 6, 'col': 23, 'padding': [1, 3, 2, 4]})",
|
||||
\], 'XtestPopupBorder')
|
||||
let buf = RunVimInTerminal('-S XtestPopupBorder', {'rows': 15})
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_20', {})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopupBorder')
|
||||
|
||||
let with_border_or_padding = {
|
||||
\ 'line': 2,
|
||||
\ 'core_line': 3,
|
||||
\ 'col': 3,
|
||||
\ 'core_col': 4,
|
||||
\ 'width': 14,
|
||||
\ 'core_width': 12,
|
||||
\ 'height': 3,
|
||||
\ 'core_height': 1,
|
||||
\ 'visible': 1}
|
||||
let winid = popup_create('hello border', {'line': 2, 'col': 3, 'border': []})",
|
||||
call assert_equal(with_border_or_padding, popup_getpos(winid))
|
||||
|
||||
let winid = popup_create('hello paddng', {'line': 2, 'col': 3, 'padding': []})
|
||||
call assert_equal(with_border_or_padding, popup_getpos(winid))
|
||||
|
||||
let winid = popup_create('hello both', {'line': 3, 'col': 8, 'border': [], 'padding': []})
|
||||
call assert_equal({
|
||||
\ 'line': 3,
|
||||
\ 'core_line': 5,
|
||||
\ 'col': 8,
|
||||
\ 'core_col': 10,
|
||||
\ 'width': 14,
|
||||
\ 'core_width': 10,
|
||||
\ 'height': 5,
|
||||
\ 'core_height': 1,
|
||||
\ 'visible': 1}, popup_getpos(winid))
|
||||
endfunc
|
||||
|
||||
func Test_popup_with_syntax_win_execute()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
|
@ -767,6 +767,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1443,
|
||||
/**/
|
||||
1442,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user