diff options
-rw-r--r-- | core/ui.lua | 12 | ||||
-rw-r--r-- | modules/textadept/menu.lua | 38 | ||||
-rw-r--r-- | src/textadept.c | 64 |
3 files changed, 82 insertions, 32 deletions
diff --git a/core/ui.lua b/core/ui.lua index 4cbdab4d..a4ceeac2 100644 --- a/core/ui.lua +++ b/core/ui.lua @@ -10,7 +10,11 @@ local ui = ui -- @field context_menu -- The buffer's context menu, a [`ui.menu()`](#menu). -- This is a low-level field. You probably want to use the higher-level --- `textadept.menu.set_contextmenu()`. +-- `textadept.menu.set_contextmenus()`. +-- @field tab_context_menu +-- The context menu for the buffer's tab, a [`ui.menu()`](#menu). +-- This is a low-level field. You probably want to use the higher-level +-- `textadept.menu.set_contextmenus()`. -- @field clipboard_text (string) -- The text on the clipboard. -- @field statusbar_text (string, Write-only) @@ -437,8 +441,8 @@ local goto_view -- Low-level function for creating a menu from table *menu_table* and returning -- the userdata. -- You probably want to use the higher-level `textadept.menu.set_menubar()` --- or `textadept.menu.set_contextmenu()` functions. Emits a `MENU_CLICKED` event --- when a menu item is selected. +-- or `textadept.menu.set_contextmenus()` functions. Emits a `MENU_CLICKED` +-- event when a menu item is selected. -- @param menu_table A table defining the menu. It is an ordered list of tables -- with a string menu item, integer menu ID, and optional GDK keycode and -- modifier mask. The latter two are used to display key shortcuts in the @@ -449,7 +453,7 @@ local goto_view -- @usage ui.menu{{'_New', 1, string.byte('n'), 4}} -- 'Ctrl+N' -- @see events.MENU_CLICKED -- @see textadept.menu.set_menubar --- @see textadept.menu.set_contextmenu +-- @see textadept.menu.set_contextmenus -- @class function -- @name menu local menu diff --git a/modules/textadept/menu.lua b/modules/textadept/menu.lua index e064e4e0..12ee2d1e 100644 --- a/modules/textadept/menu.lua +++ b/modules/textadept/menu.lua @@ -213,6 +213,16 @@ local context_menu = { {_L['Select _All'], buffer.select_all} } +-- The default tabbar context menu. +local tab_context_menu = { + {_L['_Close'], io.close_buffer}, + SEPARATOR, + {_L['_Save'], io.save_file}, + {_L['Save _As'], io.save_file_as}, + SEPARATOR, + {_L['Re_load'], io.reload_file}, +} + -- Returns the GDK integer keycode and modifier mask for a key sequence. -- This is used for creating menu accelerators. -- @param key_seq The string key sequence. @@ -324,19 +334,34 @@ M.set_menubar(menubar) --- -- Sets `ui.context_menu` from menu item list *menu*. +-- Deprecated in favor of `set_contextmenus()`. +-- @param menu The menu table to create the context menu from. +-- @see set_contextmenus +-- @name set_contextmenu +function M.set_contextmenu(menu) M.set_contextmenus(menu) end + +--- +-- Sets `ui.context_menu` and `ui.tab_context_menu` from menu item lists +-- *buffer_menu* and *tab_menu*, respectively. -- Menu items are tables containing menu text and either a function to call or -- a table containing a function with its parameters to call when an item is -- clicked. Menu items may also be sub-menus, ordered lists of menu items with -- an additional `title` key for the sub-menu's title text. --- @param menu The menu table to create the context menu from. +-- @param buffer_menu Optional menu table to create the buffer context menu +-- from. If `nil`, uses the default context menu. +-- @param tab_menu Optional menu table to create the tabbar context menu from. +-- If `nil`, uses the default tab context menu. -- @see ui.context_menu +-- @see ui.tab_context_menu -- @see ui.menu --- @name set_contextmenu -function M.set_contextmenu(menu) +-- @name set_contextmenus +function M.set_contextmenus(buffer_menu, tab_menu) contextmenu_actions = {} - ui.context_menu = ui.menu(read_menu_table(menu, true)) + ui.context_menu = ui.menu(read_menu_table(buffer_menu or context_menu, true)) + ui.tab_context_menu = ui.menu(read_menu_table(tab_menu or tab_context_menu, + true)) end -if not CURSES then M.set_contextmenu(context_menu) end +if not CURSES then M.set_contextmenus() end --- -- Prompts the user to select a menu command to run. @@ -364,7 +389,8 @@ if not CURSES then -- Set a language-specific context menu or the default one. local function set_language_contextmenu() local lang = _G.buffer:get_lexer() - M.set_contextmenu(_M[lang] and _M[lang].context_menu or context_menu) + M.set_contextmenus(_M[lang] and _M[lang].context_menu, + _M[lang] and _M[lang].tab_context_menu) end events.connect(events.LEXER_LOADED, set_language_contextmenu) events.connect(events.BUFFER_AFTER_SWITCH, set_language_contextmenu) diff --git a/src/textadept.c b/src/textadept.c index 737d20c5..95d763fb 100644 --- a/src/textadept.c +++ b/src/textadept.c @@ -1839,12 +1839,51 @@ static void w_quit_osx(GtkosxApplication*_, void*__) { * the specified buffer. * Generates 'buffer_before_switch' and 'buffer_after_switch' events. */ -static void t_tabchange(GtkNotebook*_, void*__, int page_num, void*___) { +static void t_tabchange(GtkNotebook*_, GtkWidget*__, int page_num, void*___) { if (tab_sync) return; lL_event(lua, "buffer_before_switch", -1); lL_gotodoc(lua, focused_view, page_num + 1, FALSE); lL_event(lua, "buffer_after_switch", -1); } + +/** + * Shows the context menu for a widget based on a mouse event. + * @param L The Lua state. + * @param event An optional GTK mouse button event. + * @param field The ui table field that contains the context menu. + */ +static void lL_showcontextmenu(lua_State *L, void *event, char *field) { + lua_getglobal(L, "ui"); + if (lua_istable(L, -1)) { + lua_getfield(L, -1, field); + if (lua_isuserdata(L, -1)) { + GtkWidget *menu = (GtkWidget *)lua_touserdata(L, -1); + gtk_widget_show_all(menu); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, + event ? ((GdkEventButton *)event)->button : 0, + gdk_event_get_time((GdkEvent *)event)); + } + lua_pop(L, 1); // ui context menu field + } else lua_pop(L, 1); // non-table +} + +/** Signal for a tabbar mouse click. */ +static int t_tabbuttonpress(GtkWidget*_, GdkEventButton *event, void*__) { + if (event->type != GDK_BUTTON_PRESS || event->button != 3) return FALSE; + GtkNotebook *tabs = GTK_NOTEBOOK(tabbar); + for (int i = 0; i < gtk_notebook_get_n_pages(tabs); i++) { + GtkWidget *page = gtk_notebook_get_nth_page(tabs, i); + GtkWidget *label = gtk_notebook_get_tab_label(tabs, page); + int x0, y0; + gdk_window_get_origin(gtk_widget_get_window(label), &x0, &y0); + GtkAllocation allocation; + gtk_widget_get_allocation(label, &allocation); + if (event->x_root > x0 + allocation.x + allocation.width) continue; + gtk_notebook_set_current_page(tabs, i); + return (lL_showcontextmenu(lua, (void *)event, "tab_context_menu"), TRUE); + } + return FALSE; +} #endif // if GTK /** @@ -1900,30 +1939,10 @@ static int s_keypress(GtkWidget*_, GdkEventKey *event, void*__) { event->state & GDK_META_MASK, -1); } -/** - * Shows the context menu for a Scintilla view based on a mouse event. - * @param L The Lua state. - * @param event An optional GTK mouse button event. - */ -static void lL_showcontextmenu(lua_State *L, void *event) { - lua_getglobal(L, "ui"); - if (lua_istable(L, -1)) { - lua_getfield(L, -1, "context_menu"); - if (lua_isuserdata(L, -1)) { - GtkWidget *menu = (GtkWidget *)lua_touserdata(L, -1); - gtk_widget_show_all(menu); - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, - event ? ((GdkEventButton *)event)->button : 0, - gdk_event_get_time((GdkEvent *)event)); - } - lua_pop(L, 1); // ui.context_menu - } else lua_pop(L, 1); // non-table -} - /** Signal for a Scintilla mouse click. */ static int s_buttonpress(GtkWidget*_, GdkEventButton *event, void*__) { if (event->type == GDK_BUTTON_PRESS && event->button == 3) - return (lL_showcontextmenu(lua, (void *)event), TRUE); + return (lL_showcontextmenu(lua, (void *)event, "context_menu"), TRUE); return FALSE; } #endif @@ -2272,6 +2291,7 @@ static void new_window() { tabbar = gtk_notebook_new(); signal(tabbar, "switch-page", t_tabchange); + signal(tabbar, "button-press-event", t_tabbuttonpress); gtk_notebook_set_scrollable(GTK_NOTEBOOK(tabbar), TRUE); gtk_box_pack_start(GTK_BOX(vbox), tabbar, FALSE, FALSE, 0); gtk_widget_set_can_focus(tabbar, FALSE); |