aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormitchell <70453897+667e-11@users.noreply.github.com>2007-09-23 14:09:16 -0400
committermitchell <70453897+667e-11@users.noreply.github.com>2007-09-23 14:09:16 -0400
commit80273cd17e8d0b39670c1618a98848a9540e071d (patch)
tree262a51080816d02ec21ab533c595ee3d070e19aa
parent8e30b52bf0da10e091e2d8b93fa362186cc625fe (diff)
downloadtextadept-80273cd17e8d0b39670c1618a98848a9540e071d.tar.gz
textadept-80273cd17e8d0b39670c1618a98848a9540e071d.zip
Added dynamically defined GTK menus and menubar.
-rw-r--r--core/events.lua5
-rw-r--r--src/lua_interface.c79
-rw-r--r--src/textadept.c18
-rw-r--r--src/textadept.h2
4 files changed, 86 insertions, 18 deletions
diff --git a/core/events.lua b/core/events.lua
index e4140c9e..bfd5ef09 100644
--- a/core/events.lua
+++ b/core/events.lua
@@ -60,6 +60,8 @@ module('textadept.events', package.seeall)
-- shift: flag indicating whether or not shift is pressed.
-- control: flag indicating whether or not control is pressed.
-- alt: flag indicating whether or not alt is pressed.
+-- menu_clicked(menu_item)
+-- menu_item: text of the menu item clicked.
local events = textadept.events
@@ -130,6 +132,9 @@ end
function keypress(code, shift, control, alt)
return handle('keypress', code, shift, control, alt)
end
+function menu_clicked(menu_item)
+ return handle('menu_clicked', menu_item)
+end
-- Scintilla notifications.
function char_added(n)
diff --git a/src/lua_interface.c b/src/lua_interface.c
index 6fbb50fa..2029a1a8 100644
--- a/src/lua_interface.c
+++ b/src/lua_interface.c
@@ -41,7 +41,8 @@ LF l_cf_ta_buffer_new(LS *lua),
l_cf_ta_goto_window(LS *lua),
l_cf_view_goto_buffer(LS *lua),
l_cf_pm_focus(LS *lua), l_cf_pm_clear(LS *lua), l_cf_pm_activate(LS *lua),
- l_cf_find_focus(LS *lua);
+ l_cf_find_focus(LS *lua),
+ l_cf_gtkmenu(LS *lua);
const char
*views_dne = "textadept.views doesn't exist or was overridden.",
@@ -73,6 +74,7 @@ void l_init(int argc, char **argv) {
l_cfunc(lua, l_cf_ta_goto_window, "goto_view");
l_cfunc(lua, l_cf_ta_get_split_table, "get_split_table");
l_cfunc(lua, l_cf_ta_focus_command, "focus_command");
+ l_cfunc(lua, l_cf_gtkmenu, "gtkmenu");
l_mt(lua, "_textadept_mt", l_ta_mt_index, l_ta_mt_newindex);
lua_setglobal(lua, "textadept");
lua_pushstring(lua, textadept_home); lua_setglobal(lua, "_HOME");
@@ -303,6 +305,33 @@ void l_close() {
lua_close(lua);
}
+GtkWidget* l_create_gtkmenu(LS *lua, GCallback callback, bool submenu=false) {
+ GtkWidget *menu = gtk_menu_new(), *menu_item = 0, *submenu_root = 0;
+ const char *label;
+ lua_getfield(lua, -1, "title");
+ if (!lua_isnil(lua, -1) || submenu) { // title required for submenu
+ label = !lua_isnil(lua, -1) ? lua_tostring(lua, -1) : "notitle";
+ submenu_root = gtk_menu_item_new_with_mnemonic(label);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenu_root), menu);
+ } lua_pop(lua, 1); // title
+ lua_pushnil(lua);
+ while (lua_next(lua, -2)) {
+ if (lua_type(lua, -2) == LUA_TNUMBER && lua_isstring(lua, -1)) {
+ label = lua_tostring(lua, -1);
+ if (g_str_has_prefix(label, "gtk-"))
+ menu_item = gtk_image_menu_item_new_from_stock(label, NULL);
+ else if (streq(label, "separator"))
+ menu_item = gtk_separator_menu_item_new();
+ else menu_item = gtk_menu_item_new_with_mnemonic(label);
+ g_signal_connect(menu_item, "activate", callback, 0);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ } else if (lua_istable(lua, -1))
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu),
+ l_create_gtkmenu(lua, callback, true));
+ lua_pop(lua, 1); // value
+ } return !submenu_root ? menu : submenu_root;
+}
+
// Notification/signal handlers
bool l_is_ta_table_function(const char *table, const char *function) {
@@ -342,6 +371,12 @@ bool l_handle_signal(const char *s) {
return l_is_ta_table_function("events", s) ? l_call_function(0, 1) : true;
}
+bool l_handle_signal(const char *s, const char *arg) {
+ if (!l_is_ta_table_function("events", s)) return false;
+ lua_pushstring(lua, arg);
+ return l_call_function(1, 1);
+}
+
bool l_handle_keypress(int keyval, GdkEventKey *event) {
if (!l_is_ta_table_function("events", "keypress")) return false;
lua_pushinteger(lua, keyval);
@@ -473,20 +508,8 @@ void l_pm_popup_context_menu(GdkEventButton *event, GCallback callback) {
return;
}
if (l_call_function(1, 1, true) && lua_istable(lua, -1)) {
- GtkWidget *menu = gtk_menu_new();
- lua_pushnil(lua);
- while (lua_next(lua, -2)) {
- GtkWidget *menu_item;
- const char *label = lua_tostring(lua, -1);
- if (g_str_has_prefix(label, "gtk-"))
- menu_item = gtk_image_menu_item_new_from_stock(label, NULL);
- else if (streq(label, "separator"))
- menu_item = gtk_separator_menu_item_new();
- else menu_item = gtk_menu_item_new_with_mnemonic(label);
- g_signal_connect(menu_item, "activate", callback, 0);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
- lua_pop(lua, 1); // value
- } lua_pop(lua, 1); // returned table
+ GtkWidget *menu = l_create_gtkmenu(lua, callback);
+ lua_pop(lua, 1); // returned table
gtk_widget_show_all(menu);
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
event ? event->button : 0,
@@ -751,7 +774,18 @@ LF l_ta_mt_newindex(LS *lua) {
set_docstatusbar_text(lua_tostring(lua, 3));
else if (streq(key, "focused_doc_pointer") || streq(key, "clipboard_text"))
luaL_error(lua, "'%s' is read-only.", key);
- else lua_rawset(lua, 1);
+ else if (streq(key, "menubar")) {
+ const char *errmsg = "textadept.menubar must be a table of menus.";
+ if (!lua_istable(lua, 3)) luaL_error(lua, errmsg);
+ GtkWidget *menubar = gtk_menu_bar_new();
+ lua_pushnil(lua);
+ while (lua_next(lua, 3)) {
+ if (!lua_isuserdata(lua, -1)) luaL_error(lua, errmsg);
+ GtkWidget *menu_item = l_togtkwidget(lua, -1);
+ gtk_menu_bar_append(GTK_MENU_BAR(menubar), menu_item);
+ lua_pop(lua, 1); // value
+ } set_menubar(menubar);
+ } else lua_rawset(lua, 1);
return 0;
}
@@ -946,3 +980,16 @@ LF l_cf_pm_activate(LS *) {
}
LF l_cf_find_focus(LS *) { find_toggle_focus(); return 0; }
+
+static void t_menu_activate(GtkWidget *menu_item, gpointer) {
+ GtkWidget *label = gtk_bin_get_child(GTK_BIN(menu_item));
+ const char *text = gtk_label_get_text(GTK_LABEL(label));
+ l_handle_signal("menu_clicked", text);
+}
+
+LF l_cf_gtkmenu(LS *lua) {
+ luaL_checktype(lua, 1, LUA_TTABLE);
+ GtkWidget *menu = l_create_gtkmenu(lua, G_CALLBACK(t_menu_activate));
+ lua_pushlightuserdata(lua, const_cast<GtkWidget*>(menu));
+ return 1;
+}
diff --git a/src/textadept.c b/src/textadept.c
index 5bdaa477..175ed783 100644
--- a/src/textadept.c
+++ b/src/textadept.c
@@ -5,7 +5,9 @@
#define signal(o, s, c) g_signal_connect(G_OBJECT(o), s, G_CALLBACK(c), 0)
-GtkWidget *window, *statusbar, *docstatusbar, *focused_editor, *command_entry;
+GtkWidget
+ *window, *focused_editor, *command_entry,
+ *menubar, *statusbar, *docstatusbar;
static void c_activated(GtkWidget *widget, gpointer);
static bool c_keypress(GtkWidget *widget, GdkEventKey *event, gpointer);
@@ -30,8 +32,10 @@ void create_ui() {
signal(window, "key_press_event", w_keypress);
GtkWidget *vbox = gtk_vbox_new(false, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
+ menubar = gtk_menu_bar_new();
+ gtk_box_pack_start(GTK_BOX(vbox), menubar, false, false, 0);
GtkWidget *pane = gtk_hpaned_new();
- gtk_container_add(GTK_CONTAINER(vbox), pane);
+ gtk_box_pack_start(GTK_BOX(vbox), pane, true, true, 0);
GtkWidget *pm = pm_create_ui();
gtk_paned_add1(GTK_PANED(pane), pm);
GtkWidget *hbox = gtk_hbox_new(false, 0);
@@ -56,6 +60,7 @@ void create_ui() {
g_object_set(G_OBJECT(statusbar), "width-request", 250, NULL);
gtk_box_pack_start(GTK_BOX(hboxs), statusbar, false, false, 0);
gtk_widget_show_all(window);
+ gtk_widget_hide(menubar); // hide initially
gtk_widget_hide(findbox); // hide initially
gtk_widget_grab_focus(editor);
}
@@ -174,6 +179,15 @@ void resize_split(GtkWidget *editor, int pos, bool increment) {
gtk_paned_set_position(GTK_PANED(pane), pos + (increment ? width : 0));
}
+void set_menubar(GtkWidget *new_menubar) {
+ GtkWidget *vbox = gtk_widget_get_parent(menubar);
+ gtk_container_remove(GTK_CONTAINER(vbox), menubar);
+ menubar = new_menubar;
+ gtk_box_pack_start(GTK_BOX(vbox), menubar, false, false, 0);
+ gtk_box_reorder_child(GTK_BOX(vbox), menubar, 0);
+ gtk_widget_show_all(menubar);
+}
+
void set_statusbar_text(const char *text) {
gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 0);
gtk_statusbar_push(GTK_STATUSBAR(statusbar), 0, text);
diff --git a/src/textadept.h b/src/textadept.h
index 406d0bec..f34c2655 100644
--- a/src/textadept.h
+++ b/src/textadept.h
@@ -37,6 +37,7 @@ void remove_scintilla_buffer(sptr_t doc);
void split_window(GtkWidget *editor, bool vertical=true);
bool unsplit_window(GtkWidget *editor);
void resize_split(GtkWidget *editor, int pos, bool increment=true);
+void set_menubar(GtkWidget *menubar);
void set_statusbar_text(const char *text);
void set_docstatusbar_text(const char *text);
void command_toggle_focus();
@@ -66,6 +67,7 @@ void l_set_buffer_global(ScintillaObject *sci);
void l_handle_error(lua_State *lua, const char *errmsg=0);
bool l_handle_signal(const char *s);
+bool l_handle_signal(const char *s, const char *arg);
bool l_handle_keypress(int keyval, GdkEventKey *event);
void l_handle_completion(const char *command);
void l_handle_scnnotification(SCNotification *n);