Mercurial > pidgin.yaz
diff finch/libgnt/gntmenu.c @ 15818:0e3a8505ebbe
renamed gaim-text to finch
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sun, 18 Mar 2007 19:38:15 +0000 |
parents | |
children | f00f2e283ffb |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/libgnt/gntmenu.c Sun Mar 18 19:38:15 2007 +0000 @@ -0,0 +1,317 @@ +#include "gntmenu.h" +#include "gntmenuitemcheck.h" + +#include <string.h> + +enum +{ + SIGS = 1, +}; + +static GntTreeClass *parent_class = NULL; + +static void (*org_draw)(GntWidget *wid); +static void (*org_destroy)(GntWidget *wid); +static void (*org_map)(GntWidget *wid); +static gboolean (*org_key_pressed)(GntWidget *w, const char *t); + +static void +gnt_menu_draw(GntWidget *widget) +{ + GntMenu *menu = GNT_MENU(widget); + GList *iter; + chtype type; + int i; + + if (menu->type == GNT_MENU_TOPLEVEL) { + wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + werase(widget->window); + + for (i = 0, iter = menu->list; iter; iter = iter->next, i++) { + GntMenuItem *item = GNT_MENUITEM(iter->data); + type = ' ' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT); + if (i == menu->selected) + type |= A_REVERSE; + item->priv.x = getcurx(widget->window) + widget->priv.x; + item->priv.y = getcury(widget->window) + widget->priv.y + 1; + wbkgdset(widget->window, type); + wprintw(widget->window, " %s ", item->text); + } + } else { + org_draw(widget); + } + + GNTDEBUG; +} + +static void +gnt_menu_size_request(GntWidget *widget) +{ + GntMenu *menu = GNT_MENU(widget); + + if (menu->type == GNT_MENU_TOPLEVEL) { + widget->priv.height = 1; + widget->priv.width = getmaxx(stdscr); + } else { + widget->priv.height = g_list_length(menu->list) + 2; + widget->priv.width = 25; /* XXX: */ + } +} + +static void +menu_tree_add(GntMenu *menu, GntMenuItem *item, GntMenuItem *parent) +{ + if (GNT_IS_MENUITEM_CHECK(item)) { + gnt_tree_add_choice(GNT_TREE(menu), item, + gnt_tree_create_row(GNT_TREE(menu), item->text, " "), parent, NULL); + gnt_tree_set_choice(GNT_TREE(menu), item, gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item))); + } else + gnt_tree_add_row_last(GNT_TREE(menu), item, + gnt_tree_create_row(GNT_TREE(menu), item->text, item->submenu ? ">" : " "), parent); + + if (0 && item->submenu) { + GntMenu *sub = GNT_MENU(item->submenu); + GList *iter; + for (iter = sub->list; iter; iter = iter->next) { + GntMenuItem *it = GNT_MENUITEM(iter->data); + menu_tree_add(menu, it, item); + } + } +} + +static void +gnt_menu_map(GntWidget *widget) +{ + GntMenu *menu = GNT_MENU(widget); + + if (menu->type == GNT_MENU_TOPLEVEL) { + gnt_widget_size_request(widget); + } else { + /* Populate the tree */ + GList *iter; + gnt_tree_remove_all(GNT_TREE(widget)); + for (iter = menu->list; iter; iter = iter->next) { + GntMenuItem *item = GNT_MENUITEM(iter->data); + menu_tree_add(menu, item, NULL); + } + org_map(widget); + gnt_tree_adjust_columns(GNT_TREE(widget)); + } + GNTDEBUG; +} + +static void +menuitem_activate(GntMenu *menu, GntMenuItem *item) +{ + if (item) { + if (item->submenu) { + GntMenu *sub = GNT_MENU(item->submenu); + menu->submenu = sub; + sub->type = GNT_MENU_POPUP; /* Submenus are *never* toplevel */ + sub->parentmenu = menu; + if (menu->type != GNT_MENU_TOPLEVEL) { + GntWidget *widget = GNT_WIDGET(menu); + item->priv.x = widget->priv.x + widget->priv.width - 1; + item->priv.y = widget->priv.y + gnt_tree_get_selection_visible_line(GNT_TREE(menu)); + } + gnt_widget_set_position(GNT_WIDGET(sub), item->priv.x, item->priv.y); + GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(sub), GNT_WIDGET_INVISIBLE); + gnt_widget_draw(GNT_WIDGET(sub)); + } else if (item->callback) { + item->callback(item, item->callbackdata); + while (menu) { + gnt_widget_hide(GNT_WIDGET(menu)); + menu = menu->parentmenu; + } + } + } +} + +static gboolean +gnt_menu_key_pressed(GntWidget *widget, const char *text) +{ + GntMenu *menu = GNT_MENU(widget); + int current = menu->selected; + + if (menu->submenu) { + do menu = menu->submenu; while (menu->submenu); + return (gnt_widget_key_pressed(GNT_WIDGET(menu), text)); + } + + if (text[0] == 27 && text[1] == 0) { + /* Escape closes menu */ + GntMenu *par = menu->parentmenu; + if (par != NULL) { + par->submenu = NULL; + gnt_widget_hide(widget); + } else + gnt_widget_hide(widget); + return TRUE; + } + + if (menu->type == GNT_MENU_TOPLEVEL) { + if (strcmp(text, GNT_KEY_LEFT) == 0) { + menu->selected--; + if (menu->selected < 0) + menu->selected = g_list_length(menu->list) - 1; + } else if (strcmp(text, GNT_KEY_RIGHT) == 0) { + menu->selected++; + if (menu->selected >= g_list_length(menu->list)) + menu->selected = 0; + } else if (strcmp(text, GNT_KEY_ENTER) == 0) { + gnt_widget_activate(widget); + } + + if (current != menu->selected) { + gnt_widget_draw(widget); + return TRUE; + } + } else { + return org_key_pressed(widget, text); + } + + return FALSE; +} + +static void +gnt_menu_destroy(GntWidget *widget) +{ + GntMenu *menu = GNT_MENU(widget); + g_list_foreach(menu->list, (GFunc)g_object_unref, NULL); + g_list_free(menu->list); + org_destroy(widget); +} + +static void +gnt_menu_toggled(GntTree *tree, gpointer key) +{ + GntMenuItem *item = GNT_MENUITEM(key); + GntMenu *menu = GNT_MENU(tree); + gboolean check = gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item)); + gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(item), !check); + if (item->callback) + item->callback(item, item->callbackdata); + while (menu) { + gnt_widget_hide(GNT_WIDGET(menu)); + menu = menu->parentmenu; + } +} + +static void +gnt_menu_activate(GntWidget *widget) +{ + GntMenu *menu = GNT_MENU(widget); + GntMenuItem *item; + + if (menu->type == GNT_MENU_TOPLEVEL) { + item = g_list_nth_data(menu->list, menu->selected); + } else { + item = gnt_tree_get_selection_data(GNT_TREE(menu)); + } + + if (item) { + if (GNT_IS_MENUITEM_CHECK(item)) + gnt_menu_toggled(GNT_TREE(widget), item); + else + menuitem_activate(menu, item); + } +} + +static void +gnt_menu_hide(GntWidget *widget) +{ + GntMenu *menu = GNT_MENU(widget); + if (menu->parentmenu) + menu->parentmenu->submenu = NULL; +} + +static void +gnt_menu_class_init(GntMenuClass *klass) +{ + GntWidgetClass *wid_class = GNT_WIDGET_CLASS(klass); + parent_class = GNT_TREE_CLASS(klass); + + org_destroy = wid_class->destroy; + org_map = wid_class->map; + org_draw = wid_class->draw; + org_key_pressed = wid_class->key_pressed; + + wid_class->destroy = gnt_menu_destroy; + wid_class->draw = gnt_menu_draw; + wid_class->map = gnt_menu_map; + wid_class->size_request = gnt_menu_size_request; + wid_class->key_pressed = gnt_menu_key_pressed; + wid_class->activate = gnt_menu_activate; + wid_class->hide = gnt_menu_hide; + + parent_class->toggled = gnt_menu_toggled; + + GNTDEBUG; +} + +static void +gnt_menu_init(GTypeInstance *instance, gpointer class) +{ + GntWidget *widget = GNT_WIDGET(instance); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | + GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_TRANSIENT); + GNTDEBUG; +} + +/****************************************************************************** + * GntMenu API + *****************************************************************************/ +GType +gnt_menu_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntMenuClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_menu_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntMenu), + 0, /* n_preallocs */ + gnt_menu_init, /* instance_init */ + NULL /* value_table */ + }; + + type = g_type_register_static(GNT_TYPE_TREE, + "GntMenu", + &info, 0); + } + + return type; +} + +GntWidget *gnt_menu_new(GntMenuType type) +{ + GntWidget *widget = g_object_new(GNT_TYPE_MENU, NULL); + GntMenu *menu = GNT_MENU(widget); + menu->list = NULL; + menu->selected = 0; + menu->type = type; + + if (type == GNT_MENU_TOPLEVEL) { + widget->priv.x = 0; + widget->priv.y = 0; + } else { + GNT_TREE(widget)->show_separator = FALSE; + _gnt_tree_init_internals(GNT_TREE(widget), 2); + gnt_tree_set_col_width(GNT_TREE(widget), 1, 1); /* The second column is to indicate that it has a submenu */ + GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER); + } + + return widget; +} + +void gnt_menu_add_item(GntMenu *menu, GntMenuItem *item) +{ + menu->list = g_list_append(menu->list, item); +} +