comparison src/popupwin.c @ 17117:7ef5283ace3c v8.1.1558

patch 8.1.1558: popup_menu() and popup_filter_menu() are not implemented yet commit https://github.com/vim/vim/commit/a730e55cc2d3045a79a340a5af1ad4a749058a32 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jun 16 19:05:31 2019 +0200 patch 8.1.1558: popup_menu() and popup_filter_menu() are not implemented yet Problem: Popup_menu() and popup_filter_menu() are not implemented yet. Solution: Implement the functions. Fix that centering didn't take the border and padding into account.
author Bram Moolenaar <Bram@vim.org>
date Sun, 16 Jun 2019 19:15:05 +0200
parents af861fccc309
children b439e096a011
comparison
equal deleted inserted replaced
17116:3cc7132b7a5c 17117:7ef5283ace3c
649 if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth) 649 if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth)
650 wp->w_width = wp->w_minwidth; 650 wp->w_width = wp->w_minwidth;
651 if (wp->w_width > maxwidth) 651 if (wp->w_width > maxwidth)
652 wp->w_width = maxwidth; 652 wp->w_width = maxwidth;
653 if (center_hor) 653 if (center_hor)
654 wp->w_wincol = (Columns - wp->w_width) / 2; 654 {
655 wp->w_wincol = (Columns - wp->w_width - extra_width) / 2;
656 if (wp->w_wincol < 0)
657 wp->w_wincol = 0;
658 }
655 else if (wp->w_popup_pos == POPPOS_BOTRIGHT 659 else if (wp->w_popup_pos == POPPOS_BOTRIGHT
656 || wp->w_popup_pos == POPPOS_TOPRIGHT) 660 || wp->w_popup_pos == POPPOS_TOPRIGHT)
657 { 661 {
658 // Right aligned: move to the right if needed. 662 // Right aligned: move to the right if needed.
659 // No truncation, because that would change the height. 663 // No truncation, because that would change the height.
669 wp->w_height = wp->w_maxheight; 673 wp->w_height = wp->w_maxheight;
670 if (wp->w_height > Rows - wp->w_winrow) 674 if (wp->w_height > Rows - wp->w_winrow)
671 wp->w_height = Rows - wp->w_winrow; 675 wp->w_height = Rows - wp->w_winrow;
672 676
673 if (center_vert) 677 if (center_vert)
674 wp->w_winrow = (Rows - wp->w_height) / 2; 678 {
679 wp->w_winrow = (Rows - wp->w_height - extra_height) / 2;
680 if (wp->w_winrow < 0)
681 wp->w_winrow = 0;
682 }
675 else if (wp->w_popup_pos == POPPOS_BOTRIGHT 683 else if (wp->w_popup_pos == POPPOS_BOTRIGHT
676 || wp->w_popup_pos == POPPOS_BOTLEFT) 684 || wp->w_popup_pos == POPPOS_BOTLEFT)
677 { 685 {
678 if ((wp->w_height + extra_height) <= wp->w_wantline) 686 if ((wp->w_height + extra_height) <= wp->w_wantline)
679 // bottom aligned: may move down 687 // bottom aligned: may move down
700 typedef enum 708 typedef enum
701 { 709 {
702 TYPE_NORMAL, 710 TYPE_NORMAL,
703 TYPE_ATCURSOR, 711 TYPE_ATCURSOR,
704 TYPE_NOTIFICATION, 712 TYPE_NOTIFICATION,
705 TYPE_DIALOG 713 TYPE_DIALOG,
714 TYPE_MENU
706 } create_type_T; 715 } create_type_T;
707 716
708 /* 717 /*
709 * Make "buf" empty and set the contents to "text". 718 * Make "buf" empty and set the contents to "text".
710 * Used by popup_create() and popup_settext(). 719 * Used by popup_create() and popup_settext().
749 758
750 /* 759 /*
751 * popup_create({text}, {options}) 760 * popup_create({text}, {options})
752 * popup_atcursor({text}, {options}) 761 * popup_atcursor({text}, {options})
753 */ 762 */
754 static void 763 static win_T *
755 popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) 764 popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
756 { 765 {
757 win_T *wp; 766 win_T *wp;
758 buf_T *buf; 767 buf_T *buf;
759 dict_T *d; 768 dict_T *d;
762 // Check arguments look OK. 771 // Check arguments look OK.
763 if (!(argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL) 772 if (!(argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL)
764 && !(argvars[0].v_type == VAR_LIST && argvars[0].vval.v_list != NULL)) 773 && !(argvars[0].v_type == VAR_LIST && argvars[0].vval.v_list != NULL))
765 { 774 {
766 emsg(_(e_listreq)); 775 emsg(_(e_listreq));
767 return; 776 return NULL;
768 } 777 }
769 if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL) 778 if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)
770 { 779 {
771 emsg(_(e_dictreq)); 780 emsg(_(e_dictreq));
772 return; 781 return NULL;
773 } 782 }
774 d = argvars[1].vval.v_dict; 783 d = argvars[1].vval.v_dict;
775 784
776 // Create the window and buffer. 785 // Create the window and buffer.
777 wp = win_alloc_popup_win(); 786 wp = win_alloc_popup_win();
778 if (wp == NULL) 787 if (wp == NULL)
779 return; 788 return NULL;
780 rettv->vval.v_number = wp->w_id; 789 rettv->vval.v_number = wp->w_id;
781 wp->w_popup_pos = POPPOS_TOPLEFT; 790 wp->w_popup_pos = POPPOS_TOPLEFT;
782 791
783 buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_LISTED|BLN_DUMMY); 792 buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_LISTED|BLN_DUMMY);
784 if (buf == NULL) 793 if (buf == NULL)
785 return; 794 return NULL;
786 ml_open(buf); 795 ml_open(buf);
787 796
788 win_init_popup_win(wp, buf); 797 win_init_popup_win(wp, buf);
789 798
790 set_local_options_default(wp); 799 set_local_options_default(wp);
896 set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, 905 set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1,
897 (char_u *)(nr == 0 ? "WarningMsg" : "PopupNotification"), 906 (char_u *)(nr == 0 ? "WarningMsg" : "PopupNotification"),
898 OPT_FREE|OPT_LOCAL, 0); 907 OPT_FREE|OPT_LOCAL, 0);
899 } 908 }
900 909
901 if (type == TYPE_DIALOG) 910 if (type == TYPE_DIALOG || type == TYPE_MENU)
902 { 911 {
903 int i; 912 int i;
904 913
905 wp->w_popup_pos = POPPOS_CENTER; 914 wp->w_popup_pos = POPPOS_CENTER;
906 wp->w_zindex = POPUPWIN_DIALOG_ZINDEX; 915 wp->w_zindex = POPUPWIN_DIALOG_ZINDEX;
910 wp->w_popup_border[i] = 1; 919 wp->w_popup_border[i] = 1;
911 wp->w_popup_padding[i] = 1; 920 wp->w_popup_padding[i] = 1;
912 } 921 }
913 } 922 }
914 923
924 if (type == TYPE_MENU)
925 {
926 typval_T tv;
927 callback_T callback;
928
929 tv.v_type = VAR_STRING;
930 tv.vval.v_string = (char_u *)"popup_filter_menu";
931 callback = get_callback(&tv);
932 if (callback.cb_name != NULL)
933 set_callback(&wp->w_filter_cb, &callback);
934
935 wp->w_p_wrap = 0;
936 }
937
915 // Deal with options. 938 // Deal with options.
916 apply_options(wp, buf, argvars[1].vval.v_dict); 939 apply_options(wp, buf, argvars[1].vval.v_dict);
917 940
918 if (type == TYPE_NOTIFICATION && wp->w_popup_timer == NULL) 941 if (type == TYPE_NOTIFICATION && wp->w_popup_timer == NULL)
919 popup_add_timeout(wp, 3000); 942 popup_add_timeout(wp, 3000);
922 945
923 wp->w_vsep_width = 0; 946 wp->w_vsep_width = 0;
924 947
925 redraw_all_later(NOT_VALID); 948 redraw_all_later(NOT_VALID);
926 popup_mask_refresh = TRUE; 949 popup_mask_refresh = TRUE;
950
951 return wp;
927 } 952 }
928 953
929 /* 954 /*
930 * popup_clear() 955 * popup_clear()
931 */ 956 */
998 1023
999 popup_close(id); 1024 popup_close(id);
1000 } 1025 }
1001 1026
1002 /* 1027 /*
1003 * popup_filter_yesno({text}, {options}) 1028 * In a filter: check if the typed key is a mouse event that is used for
1004 */ 1029 * dragging the popup.
1005 void 1030 */
1006 f_popup_filter_yesno(typval_T *argvars, typval_T *rettv) 1031 static void
1032 filter_handle_drag(win_T *wp, int c, typval_T *rettv)
1033 {
1034 int row = mouse_row;
1035 int col = mouse_col;
1036
1037 if (wp->w_popup_drag
1038 && is_mouse_key(c)
1039 && (wp == popup_dragwin
1040 || wp == mouse_find_win(&row, &col, FIND_POPUP)))
1041 // do not consume the key, allow for dragging the popup
1042 rettv->vval.v_number = 0;
1043 }
1044
1045 static void
1046 popup_highlight_curline(win_T *wp)
1047 {
1048 int id;
1049 char buf[100];
1050
1051 match_delete(wp, 1, FALSE);
1052
1053 id = syn_name2id((char_u *)"PopupSelected");
1054 vim_snprintf(buf, sizeof(buf), "\\%%%dl.*", (int)wp->w_cursor.lnum);
1055 match_add(wp, (char_u *)(id == 0 ? "PmenuSel" : "PopupSelected"),
1056 (char_u *)buf, 10, 1, NULL, NULL);
1057 }
1058
1059 /*
1060 * popup_filter_menu({text}, {options})
1061 */
1062 void
1063 f_popup_filter_menu(typval_T *argvars, typval_T *rettv)
1007 { 1064 {
1008 int id = tv_get_number(&argvars[0]); 1065 int id = tv_get_number(&argvars[0]);
1009 win_T *wp = win_id2wp(id); 1066 win_T *wp = win_id2wp(id);
1010 char_u *key = tv_get_string(&argvars[1]); 1067 char_u *key = tv_get_string(&argvars[1]);
1011 typval_T res; 1068 typval_T res;
1069 int c;
1070 linenr_T old_lnum;
1071
1072 // If the popup has been closed do not consume the key.
1073 if (wp == NULL)
1074 return;
1075
1076 c = *key;
1077 if (c == K_SPECIAL && key[1] != NUL)
1078 c = TO_SPECIAL(key[1], key[2]);
1079
1080 // consume all keys until done
1081 rettv->vval.v_number = 1;
1082 res.v_type = VAR_NUMBER;
1083
1084 old_lnum = wp->w_cursor.lnum;
1085 if ((c == 'k' || c == 'K' || c == K_UP) && wp->w_cursor.lnum > 1)
1086 --wp->w_cursor.lnum;
1087 if ((c == 'j' || c == 'J' || c == K_DOWN)
1088 && wp->w_cursor.lnum < wp->w_buffer->b_ml.ml_line_count)
1089 ++wp->w_cursor.lnum;
1090 if (old_lnum != wp->w_cursor.lnum)
1091 {
1092 popup_highlight_curline(wp);
1093 return;
1094 }
1095
1096 if (c == 'x' || c == 'X' || c == ESC || c == Ctrl_C)
1097 {
1098 // Cancelled, invoke callback with -1
1099 res.vval.v_number = -1;
1100 popup_close_and_callback(wp, &res);
1101 return;
1102 }
1103 if (c == ' ' || c == K_KENTER || c == CAR || c == NL)
1104 {
1105 // Invoke callback with current index.
1106 res.vval.v_number = wp->w_cursor.lnum;
1107 popup_close_and_callback(wp, &res);
1108 return;
1109 }
1110
1111 filter_handle_drag(wp, c, rettv);
1112 }
1113
1114 /*
1115 * popup_filter_yesno({text}, {options})
1116 */
1117 void
1118 f_popup_filter_yesno(typval_T *argvars, typval_T *rettv)
1119 {
1120 int id = tv_get_number(&argvars[0]);
1121 win_T *wp = win_id2wp(id);
1122 char_u *key = tv_get_string(&argvars[1]);
1123 typval_T res;
1124 int c;
1012 1125
1013 // If the popup has been closed don't consume the key. 1126 // If the popup has been closed don't consume the key.
1014 if (wp == NULL) 1127 if (wp == NULL)
1015 return; 1128 return;
1016 1129
1130 c = *key;
1131 if (c == K_SPECIAL && key[1] != NUL)
1132 c = TO_SPECIAL(key[1], key[2]);
1133
1017 // consume all keys until done 1134 // consume all keys until done
1018 rettv->vval.v_number = 1; 1135 rettv->vval.v_number = 1;
1019 1136
1020 if (STRCMP(key, "y") == 0 || STRCMP(key, "Y") == 0) 1137 if (c == 'y' || c == 'Y')
1021 res.vval.v_number = 1; 1138 res.vval.v_number = 1;
1022 else if (STRCMP(key, "n") == 0 || STRCMP(key, "N") == 0 1139 else if (c == 'n' || c == 'N' || c == 'x' || c == 'X' || c == ESC)
1023 || STRCMP(key, "x") == 0 || STRCMP(key, "X") == 0
1024 || STRCMP(key, "\x1b") == 0)
1025 res.vval.v_number = 0; 1140 res.vval.v_number = 0;
1026 else 1141 else
1027 { 1142 {
1028 int c = *key; 1143 filter_handle_drag(wp, c, rettv);
1029 int row = mouse_row;
1030 int col = mouse_col;
1031
1032 if (c == K_SPECIAL && key[1] != NUL)
1033 c = TO_SPECIAL(key[1], key[2]);
1034 if (wp->w_popup_drag
1035 && is_mouse_key(c)
1036 && (wp == popup_dragwin
1037 || wp == mouse_find_win(&row, &col, FIND_POPUP)))
1038 // allow for dragging the popup
1039 rettv->vval.v_number = 0;
1040
1041 // ignore this key
1042 return; 1144 return;
1043 } 1145 }
1044 1146
1045 // Invoke callback 1147 // Invoke callback
1046 res.v_type = VAR_NUMBER; 1148 res.v_type = VAR_NUMBER;
1052 */ 1154 */
1053 void 1155 void
1054 f_popup_dialog(typval_T *argvars, typval_T *rettv) 1156 f_popup_dialog(typval_T *argvars, typval_T *rettv)
1055 { 1157 {
1056 popup_create(argvars, rettv, TYPE_DIALOG); 1158 popup_create(argvars, rettv, TYPE_DIALOG);
1159 }
1160
1161 /*
1162 * popup_menu({text}, {options})
1163 */
1164 void
1165 f_popup_menu(typval_T *argvars, typval_T *rettv)
1166 {
1167 win_T *wp = popup_create(argvars, rettv, TYPE_MENU);
1168
1169 if (wp != NULL)
1170 popup_highlight_curline(wp);
1057 } 1171 }
1058 1172
1059 /* 1173 /*
1060 * popup_notification({text}, {options}) 1174 * popup_notification({text}, {options})
1061 */ 1175 */