forked from aniani/vim
patch 8.1.1548: popup_dialog() is not implemented
Problem: Popup_dialog() is not implemented. Solution: Implement popup_dialog() and popup_filter_yesno().
This commit is contained in:
@@ -103,10 +103,10 @@ TODO:
|
|||||||
- When drawing on top half a double-wide character, display ">" or "<" in the
|
- When drawing on top half a double-wide character, display ">" or "<" in the
|
||||||
incomplete cell.
|
incomplete cell.
|
||||||
- Can the buffer be re-used, to avoid using up lots of buffer numbers?
|
- Can the buffer be re-used, to avoid using up lots of buffer numbers?
|
||||||
|
- Use a popup window for the "info" item of completion instead of using a
|
||||||
|
preview window.
|
||||||
- Implement:
|
- Implement:
|
||||||
popup_dialog({text}, {options})
|
|
||||||
popup_filter_menu({id}, {key})
|
popup_filter_menu({id}, {key})
|
||||||
popup_filter_yesno({id}, {key})
|
|
||||||
popup_menu({text}, {options})
|
popup_menu({text}, {options})
|
||||||
popup_setoptions({id}, {options})
|
popup_setoptions({id}, {options})
|
||||||
flip option
|
flip option
|
||||||
@@ -196,16 +196,23 @@ popup_create({text}, {options}) *popup_create()*
|
|||||||
|
|
||||||
|
|
||||||
popup_dialog({text}, {options}) *popup_dialog()*
|
popup_dialog({text}, {options}) *popup_dialog()*
|
||||||
{not implemented yet}
|
|
||||||
Just like |popup_create()| but with these default options: >
|
Just like |popup_create()| but with these default options: >
|
||||||
call popup_create({text}, {
|
call popup_create({text}, {
|
||||||
\ 'pos': 'center',
|
\ 'pos': 'center',
|
||||||
\ 'zindex': 200,
|
\ 'zindex': 200,
|
||||||
|
\ 'drag': 1,
|
||||||
\ 'border': [],
|
\ 'border': [],
|
||||||
\ 'padding': [],
|
\ 'padding': [],
|
||||||
\})
|
\})
|
||||||
< Use {options} to change the properties. E.g. add a 'filter'
|
< Use {options} to change the properties. E.g. add a 'filter'
|
||||||
option with value 'popup_filter_yesno'.
|
option with value 'popup_filter_yesno'. Example: >
|
||||||
|
call popup_create('do you want to quit (Yes/no)?', {
|
||||||
|
\ 'filter': 'popup_filter_yesno',
|
||||||
|
\ 'callback': 'QuitCallback',
|
||||||
|
\ })
|
||||||
|
|
||||||
|
< By default the dialog can be dragged, so that text below it
|
||||||
|
can be read if needed.
|
||||||
|
|
||||||
|
|
||||||
popup_filter_menu({id}, {key}) *popup_filter_menu()*
|
popup_filter_menu({id}, {key}) *popup_filter_menu()*
|
||||||
@@ -218,12 +225,12 @@ popup_filter_menu({id}, {key}) *popup_filter_menu()*
|
|||||||
|
|
||||||
|
|
||||||
popup_filter_yesno({id}, {key}) *popup_filter_yesno()*
|
popup_filter_yesno({id}, {key}) *popup_filter_yesno()*
|
||||||
{not implemented yet}
|
|
||||||
Filter that can be used for a popup. It handles only the keys
|
Filter that can be used for a popup. It handles only the keys
|
||||||
'y', 'Y' and 'n' or 'N'. Invokes the "callback" of the
|
'y', 'Y' and 'n' or 'N'. Invokes the "callback" of the
|
||||||
popup menu with the 1 for 'y' or 'Y' and zero for 'n' or 'N'
|
popup menu with the 1 for 'y' or 'Y' and zero for 'n' or 'N'
|
||||||
as the second argument. Pressing Esc and CTRL-C works like
|
as the second argument. Pressing Esc and 'x' works like
|
||||||
pressing 'n'. Other keys are ignored.
|
pressing 'n'. CTRL-C invokes the callback with -1. Other
|
||||||
|
keys are ignored.
|
||||||
|
|
||||||
|
|
||||||
popup_getoptions({id}) *popup_getoptions()*
|
popup_getoptions({id}) *popup_getoptions()*
|
||||||
@@ -301,7 +308,7 @@ popup_notification({text}, {options}) *popup_notification()*
|
|||||||
\ 'minwidth': 20,
|
\ 'minwidth': 20,
|
||||||
\ 'time': 3000,
|
\ 'time': 3000,
|
||||||
\ 'tabpage': -1,
|
\ 'tabpage': -1,
|
||||||
\ 'zindex': 200,
|
\ 'zindex': 300,
|
||||||
\ 'drag': 1,
|
\ 'drag': 1,
|
||||||
\ 'highlight': 'WarningMsg',
|
\ 'highlight': 'WarningMsg',
|
||||||
\ 'border': [],
|
\ 'border': [],
|
||||||
@@ -521,7 +528,7 @@ filter is also called. The filter of the popup window with the highest zindex
|
|||||||
is called first.
|
is called first.
|
||||||
|
|
||||||
The filter function is called with two arguments: the ID of the popup and the
|
The filter function is called with two arguments: the ID of the popup and the
|
||||||
key, e.g.: >
|
key as a string, e.g.: >
|
||||||
func MyFilter(winid, key)
|
func MyFilter(winid, key)
|
||||||
if a:key == "\<F2>"
|
if a:key == "\<F2>"
|
||||||
" do something
|
" do something
|
||||||
@@ -556,15 +563,14 @@ Vim recognizes the Esc key. If you do use Esc, it is recommended to set the
|
|||||||
|
|
||||||
POPUP CALLBACK *popup-callback*
|
POPUP CALLBACK *popup-callback*
|
||||||
|
|
||||||
A callback that is invoked when the popup closes. Used by
|
A callback that is invoked when the popup closes.
|
||||||
|popup_filter_menu()|.
|
|
||||||
|
|
||||||
The callback is invoked with two arguments: the ID of the popup window and the
|
The callback is invoked with two arguments: the ID of the popup window and the
|
||||||
result, which could be an index in the popup lines, or whatever was passed as
|
result, which could be an index in the popup lines, or whatever was passed as
|
||||||
the second argument of `popup_close()`.
|
the second argument of `popup_close()`.
|
||||||
|
|
||||||
If the popup is closed because the cursor moved, the number -1 is passed to
|
If the popup is force-closed, e.g. because the cursor moved or CTRL-C was
|
||||||
the callback.
|
pressed, the number -1 is passed to the callback.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
3. Examples *popup-examples*
|
3. Examples *popup-examples*
|
||||||
|
@@ -815,6 +815,8 @@ static struct fst
|
|||||||
{"popup_clear", 0, 0, f_popup_clear},
|
{"popup_clear", 0, 0, f_popup_clear},
|
||||||
{"popup_close", 1, 2, f_popup_close},
|
{"popup_close", 1, 2, f_popup_close},
|
||||||
{"popup_create", 2, 2, f_popup_create},
|
{"popup_create", 2, 2, f_popup_create},
|
||||||
|
{"popup_dialog", 2, 2, f_popup_dialog},
|
||||||
|
{"popup_filter_yesno", 2, 2, f_popup_filter_yesno},
|
||||||
{"popup_getoptions", 1, 1, f_popup_getoptions},
|
{"popup_getoptions", 1, 1, f_popup_getoptions},
|
||||||
{"popup_getpos", 1, 1, f_popup_getpos},
|
{"popup_getpos", 1, 1, f_popup_getpos},
|
||||||
{"popup_hide", 1, 1, f_popup_hide},
|
{"popup_hide", 1, 1, f_popup_hide},
|
||||||
|
@@ -600,6 +600,7 @@ EXTERN int aucmd_win_used INIT(= FALSE); /* aucmd_win is being used */
|
|||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
EXTERN win_T *first_popupwin; // first global popup window
|
EXTERN win_T *first_popupwin; // first global popup window
|
||||||
|
EXTERN win_T *popup_dragwin INIT(= NULL); // popup window being dragged
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
145
src/popupwin.c
145
src/popupwin.c
@@ -201,6 +201,10 @@ popup_start_drag(win_T *wp)
|
|||||||
drag_start_wantcol = wp->w_wincol + 1;
|
drag_start_wantcol = wp->w_wincol + 1;
|
||||||
else
|
else
|
||||||
drag_start_wantcol = wp->w_wantcol;
|
drag_start_wantcol = wp->w_wantcol;
|
||||||
|
|
||||||
|
// Stop centering the popup
|
||||||
|
if (wp->w_popup_pos == POPPOS_CENTER)
|
||||||
|
wp->w_popup_pos = POPPOS_TOPLEFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -301,6 +305,8 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict)
|
|||||||
wp->w_p_wrap = nr != 0;
|
wp->w_p_wrap = nr != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
di = dict_find(dict, (char_u *)"drag", -1);
|
||||||
|
if (di != NULL)
|
||||||
wp->w_popup_drag = dict_get_number(dict, (char_u *)"drag");
|
wp->w_popup_drag = dict_get_number(dict, (char_u *)"drag");
|
||||||
|
|
||||||
di = dict_find(dict, (char_u *)"callback", -1);
|
di = dict_find(dict, (char_u *)"callback", -1);
|
||||||
@@ -692,13 +698,13 @@ typedef enum
|
|||||||
{
|
{
|
||||||
TYPE_NORMAL,
|
TYPE_NORMAL,
|
||||||
TYPE_ATCURSOR,
|
TYPE_ATCURSOR,
|
||||||
TYPE_NOTIFICATION
|
TYPE_NOTIFICATION,
|
||||||
|
TYPE_DIALOG
|
||||||
} create_type_T;
|
} create_type_T;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* popup_create({text}, {options})
|
* popup_create({text}, {options})
|
||||||
* popup_atcursor({text}, {options})
|
* popup_atcursor({text}, {options})
|
||||||
* When called from f_popup_atcursor() "type" is TYPE_ATCURSOR.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
|
popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
|
||||||
@@ -871,6 +877,20 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
|
|||||||
OPT_FREE|OPT_LOCAL, 0);
|
OPT_FREE|OPT_LOCAL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == TYPE_DIALOG)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
wp->w_popup_pos = POPPOS_CENTER;
|
||||||
|
wp->w_zindex = POPUPWIN_DIALOG_ZINDEX;
|
||||||
|
wp->w_popup_drag = 1;
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
wp->w_popup_border[i] = 1;
|
||||||
|
wp->w_popup_padding[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Deal with options.
|
// Deal with options.
|
||||||
apply_options(wp, buf, argvars[1].vval.v_dict);
|
apply_options(wp, buf, argvars[1].vval.v_dict);
|
||||||
|
|
||||||
@@ -912,33 +932,6 @@ f_popup_atcursor(typval_T *argvars, typval_T *rettv)
|
|||||||
popup_create(argvars, rettv, TYPE_ATCURSOR);
|
popup_create(argvars, rettv, TYPE_ATCURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* popup_notification({text}, {options})
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
f_popup_notification(typval_T *argvars, typval_T *rettv)
|
|
||||||
{
|
|
||||||
popup_create(argvars, rettv, TYPE_NOTIFICATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the popup window with window-ID "id".
|
|
||||||
* If the popup window does not exist NULL is returned.
|
|
||||||
* If the window is not a popup window, and error message is given.
|
|
||||||
*/
|
|
||||||
static win_T *
|
|
||||||
find_popup_win(int id)
|
|
||||||
{
|
|
||||||
win_T *wp = win_id2wp(id);
|
|
||||||
|
|
||||||
if (wp != NULL && !bt_popup(wp->w_buffer))
|
|
||||||
{
|
|
||||||
semsg(_("E993: window %d is not a popup window"), id);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return wp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoke the close callback for window "wp" with value "result".
|
* Invoke the close callback for window "wp" with value "result".
|
||||||
* Careful: The callback may make "wp" invalid!
|
* Careful: The callback may make "wp" invalid!
|
||||||
@@ -985,6 +978,90 @@ popup_close_and_callback(win_T *wp, typval_T *arg)
|
|||||||
popup_close(id);
|
popup_close(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* popup_filter_yesno({text}, {options})
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
f_popup_filter_yesno(typval_T *argvars, typval_T *rettv)
|
||||||
|
{
|
||||||
|
int id = tv_get_number(&argvars[0]);
|
||||||
|
win_T *wp = win_id2wp(id);
|
||||||
|
char_u *key = tv_get_string(&argvars[1]);
|
||||||
|
typval_T res;
|
||||||
|
|
||||||
|
// If the popup has been closed don't consume the key.
|
||||||
|
if (wp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// consume all keys until done
|
||||||
|
rettv->vval.v_number = 1;
|
||||||
|
|
||||||
|
if (STRCMP(key, "y") == 0 || STRCMP(key, "Y") == 0)
|
||||||
|
res.vval.v_number = 1;
|
||||||
|
else if (STRCMP(key, "n") == 0 || STRCMP(key, "N") == 0
|
||||||
|
|| STRCMP(key, "x") == 0 || STRCMP(key, "X") == 0
|
||||||
|
|| STRCMP(key, "\x1b") == 0)
|
||||||
|
res.vval.v_number = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int c = *key;
|
||||||
|
int row = mouse_row;
|
||||||
|
int col = mouse_col;
|
||||||
|
|
||||||
|
if (c == K_SPECIAL && key[1] != NUL)
|
||||||
|
c = TO_SPECIAL(key[1], key[2]);
|
||||||
|
if (wp->w_popup_drag
|
||||||
|
&& is_mouse_key(c)
|
||||||
|
&& (wp == popup_dragwin
|
||||||
|
|| wp == mouse_find_win(&row, &col, FIND_POPUP)))
|
||||||
|
// allow for dragging the popup
|
||||||
|
rettv->vval.v_number = 0;
|
||||||
|
|
||||||
|
// ignore this key
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke callback
|
||||||
|
res.v_type = VAR_NUMBER;
|
||||||
|
popup_close_and_callback(wp, &res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* popup_dialog({text}, {options})
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
f_popup_dialog(typval_T *argvars, typval_T *rettv)
|
||||||
|
{
|
||||||
|
popup_create(argvars, rettv, TYPE_DIALOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* popup_notification({text}, {options})
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
f_popup_notification(typval_T *argvars, typval_T *rettv)
|
||||||
|
{
|
||||||
|
popup_create(argvars, rettv, TYPE_NOTIFICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the popup window with window-ID "id".
|
||||||
|
* If the popup window does not exist NULL is returned.
|
||||||
|
* If the window is not a popup window, and error message is given.
|
||||||
|
*/
|
||||||
|
static win_T *
|
||||||
|
find_popup_win(int id)
|
||||||
|
{
|
||||||
|
win_T *wp = win_id2wp(id);
|
||||||
|
|
||||||
|
if (wp != NULL && !bt_popup(wp->w_buffer))
|
||||||
|
{
|
||||||
|
semsg(_("E993: window %d is not a popup window"), id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return wp;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* popup_close({id})
|
* popup_close({id})
|
||||||
*/
|
*/
|
||||||
@@ -1299,6 +1376,15 @@ invoke_popup_filter(win_T *wp, int c)
|
|||||||
typval_T argv[3];
|
typval_T argv[3];
|
||||||
char_u buf[NUMBUFLEN];
|
char_u buf[NUMBUFLEN];
|
||||||
|
|
||||||
|
// Emergency exit: CTRL-C closes the popup.
|
||||||
|
if (c == Ctrl_C)
|
||||||
|
{
|
||||||
|
rettv.v_type = VAR_NUMBER;
|
||||||
|
rettv.vval.v_number = -1;
|
||||||
|
popup_close_and_callback(wp, &rettv);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
argv[0].v_type = VAR_NUMBER;
|
argv[0].v_type = VAR_NUMBER;
|
||||||
argv[0].vval.v_number = (varnumber_T)wp->w_id;
|
argv[0].vval.v_number = (varnumber_T)wp->w_id;
|
||||||
|
|
||||||
@@ -1310,6 +1396,7 @@ invoke_popup_filter(win_T *wp, int c)
|
|||||||
|
|
||||||
argv[2].v_type = VAR_UNKNOWN;
|
argv[2].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
|
// NOTE: The callback might close the popup, thus make "wp" invalid.
|
||||||
call_callback(&wp->w_filter_cb, -1,
|
call_callback(&wp->w_filter_cb, -1,
|
||||||
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
||||||
res = tv_get_number(&rettv);
|
res = tv_get_number(&rettv);
|
||||||
|
@@ -8,6 +8,8 @@ void popup_adjust_position(win_T *wp);
|
|||||||
void f_popup_clear(typval_T *argvars, typval_T *rettv);
|
void f_popup_clear(typval_T *argvars, typval_T *rettv);
|
||||||
void f_popup_create(typval_T *argvars, typval_T *rettv);
|
void f_popup_create(typval_T *argvars, typval_T *rettv);
|
||||||
void f_popup_atcursor(typval_T *argvars, typval_T *rettv);
|
void f_popup_atcursor(typval_T *argvars, typval_T *rettv);
|
||||||
|
void f_popup_filter_yesno(typval_T *argvars, typval_T *rettv);
|
||||||
|
void f_popup_dialog(typval_T *argvars, typval_T *rettv);
|
||||||
void f_popup_notification(typval_T *argvars, typval_T *rettv);
|
void f_popup_notification(typval_T *argvars, typval_T *rettv);
|
||||||
void f_popup_close(typval_T *argvars, typval_T *rettv);
|
void f_popup_close(typval_T *argvars, typval_T *rettv);
|
||||||
void f_popup_hide(typval_T *argvars, typval_T *rettv);
|
void f_popup_hide(typval_T *argvars, typval_T *rettv);
|
||||||
|
@@ -1998,7 +1998,8 @@ typedef enum {
|
|||||||
|
|
||||||
# define POPUPWIN_DEFAULT_ZINDEX 50
|
# define POPUPWIN_DEFAULT_ZINDEX 50
|
||||||
# define POPUPMENU_ZINDEX 100
|
# define POPUPMENU_ZINDEX 100
|
||||||
# define POPUPWIN_NOTIFICATION_ZINDEX 200
|
# define POPUPWIN_DIALOG_ZINDEX 200
|
||||||
|
# define POPUPWIN_NOTIFICATION_ZINDEX 300
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -870,6 +870,36 @@ func Test_popup_filter()
|
|||||||
call popup_clear()
|
call popup_clear()
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func ShowDialog(key, result)
|
||||||
|
let s:cb_res = 999
|
||||||
|
let winid = popup_dialog('do you want to quit (Yes/no)?', {
|
||||||
|
\ 'filter': 'popup_filter_yesno',
|
||||||
|
\ 'callback': 'QuitCallback',
|
||||||
|
\ })
|
||||||
|
redraw
|
||||||
|
call feedkeys(a:key, "xt")
|
||||||
|
call assert_equal(winid, s:cb_winid)
|
||||||
|
call assert_equal(a:result, s:cb_res)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_popup_dialog()
|
||||||
|
func QuitCallback(id, res)
|
||||||
|
let s:cb_winid = a:id
|
||||||
|
let s:cb_res = a:res
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
let winid = ShowDialog("y", 1)
|
||||||
|
let winid = ShowDialog("Y", 1)
|
||||||
|
let winid = ShowDialog("n", 0)
|
||||||
|
let winid = ShowDialog("N", 0)
|
||||||
|
let winid = ShowDialog("x", 0)
|
||||||
|
let winid = ShowDialog("X", 0)
|
||||||
|
let winid = ShowDialog("\<Esc>", 0)
|
||||||
|
let winid = ShowDialog("\<C-C>", -1)
|
||||||
|
|
||||||
|
delfunc QuitCallback
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_popup_close_callback()
|
func Test_popup_close_callback()
|
||||||
func PopupDone(id, result)
|
func PopupDone(id, result)
|
||||||
let g:result = a:result
|
let g:result = a:result
|
||||||
|
@@ -777,6 +777,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1548,
|
||||||
/**/
|
/**/
|
||||||
1547,
|
1547,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user