diff options
Diffstat (limited to 'widgets/misc/e-search-bar.c')
-rw-r--r-- | widgets/misc/e-search-bar.c | 406 |
1 files changed, 109 insertions, 297 deletions
diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c index cbf7984f05..c07c98fad2 100644 --- a/widgets/misc/e-search-bar.c +++ b/widgets/misc/e-search-bar.c @@ -39,11 +39,8 @@ #include <libgnome/gnome-defs.h> #include <libgnome/gnome-i18n.h> -#include <bonobo/bonobo-ui-util.h> - -#include <stdlib.h> - #include "e-search-bar.h" +#include "e-dropdown-button.h" enum { @@ -97,140 +94,15 @@ emit_menu_activated (ESearchBar *esb, int item) } -/* Utility functions. */ - -static void -update_sensitivity (ESearchBar *search_bar) -{ - const char *text; - - text = gtk_entry_get_text (GTK_ENTRY (search_bar->entry)); - - if (text != NULL && text[0] != '\0') { - if (search_bar->ui_component != NULL) - bonobo_ui_component_set_prop (search_bar->ui_component, - "/commands/ESearchBar:FindNow", - "sensitive", "1", NULL); - gtk_widget_set_sensitive (search_bar->activate_button, TRUE); - } else { - if (search_bar->ui_component != NULL) - bonobo_ui_component_set_prop (search_bar->ui_component, - "/commands/ESearchBar:FindNow", - "sensitive", "0", NULL); - gtk_widget_set_sensitive (search_bar->activate_button, FALSE); - } -} - -static char * -verb_name_from_id (int id) -{ - return g_strdup_printf ("ESearchBar:Activate:%d", id); -} - -/* This implements the "clear" action, i.e. clears the text and then emits - * ::search_activated. */ - -static void -clear_search (ESearchBar *esb) -{ - e_search_bar_set_text (esb, ""); - emit_search_activated (esb); -} - -/* Frees an array of subitem information */ -static void -free_subitems (ESearchBarSubitem *subitems) -{ - ESearchBarSubitem *s; - - g_assert (subitems != NULL); - - for (s = subitems; s->id != -1; s++) { - if (s->text) - g_free (s->text); - } - - g_free (subitems); -} - -static void -free_menu_items (ESearchBar *esb) -{ - GSList *p; - - if (esb->menu_items == NULL) - return; - - for (p = esb->menu_items; p != NULL; p = p->next) { - ESearchBarItem *item; - - item = (ESearchBarItem *) p->data; - - /* (No submitems for the menu_items, so no need to free that - member.) */ - - g_free (item->text); - g_free (item); - } - - g_slist_free (esb->menu_items); - esb->menu_items = NULL; -} - - -/* Callbacks -- Standard verbs. */ - -static void -search_now_verb_cb (BonoboUIComponent *ui_component, - void *data, - const char *verb_name) -{ - ESearchBar *esb; - - esb = E_SEARCH_BAR (data); - emit_search_activated (esb); -} - -static void -clear_verb_cb (BonoboUIComponent *ui_component, - void *data, - const char *verb_name) -{ - ESearchBar *esb; - - esb = E_SEARCH_BAR (data); - clear_search (esb); -} - -static void -setup_standard_verbs (ESearchBar *search_bar) -{ - bonobo_ui_component_add_verb (search_bar->ui_component, "ESearchBar:Clear", - clear_verb_cb, search_bar); - bonobo_ui_component_add_verb (search_bar->ui_component, "ESearchBar:FindNow", - search_now_verb_cb, search_bar); - - /* Make sure the entries are created with the correct sensitivity. */ - update_sensitivity (search_bar); -} - -/* Callbacks -- The verbs for all the definable items. */ +/* Callbacks. */ static void -search_verb_cb (BonoboUIComponent *ui_component, - void *data, - const char *verb_name) +menubar_activated_cb (GtkWidget *widget, ESearchBar *esb) { - ESearchBar *esb; - const char *p; int id; - esb = E_SEARCH_BAR (data); - - p = strrchr (verb_name, ':'); - g_assert (p != NULL); + id = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), "EsbMenuId")); - id = atoi (p + 1); emit_menu_activated (esb, id); } @@ -242,13 +114,6 @@ entry_activated_cb (GtkWidget *widget, } static void -entry_changed_cb (GtkWidget *widget, - ESearchBar *esb) -{ - update_sensitivity (esb); -} - -static void subitem_activated_cb (GtkWidget *widget, ESearchBar *esb) { gint id, subid; @@ -280,8 +145,6 @@ activate_by_subitems (ESearchBar *esb, gint item_id, ESearchBarSubitem *subitems esb->entry = gtk_entry_new(); gtk_widget_set_usize (esb->entry, 4, -1); gtk_object_ref (GTK_OBJECT (esb->entry)); - gtk_signal_connect (GTK_OBJECT (esb->entry), "changed", - GTK_SIGNAL_FUNC (entry_changed_cb), esb); gtk_signal_connect (GTK_OBJECT (esb->entry), "activate", GTK_SIGNAL_FUNC (entry_activated_cb), esb); gtk_container_add (GTK_CONTAINER (esb->entry_box), esb->entry); @@ -386,19 +249,11 @@ option_activated_cb (GtkWidget *widget, } static void -activate_button_clicked_cb (GtkWidget *widget, - ESearchBar *esb) +activate_button_clicked_cb (GtkWidget *widget, ESearchBar *esb) { emit_search_activated (esb); } -static void -clear_button_clicked_cb (GtkWidget *widget, - ESearchBar *esb) -{ - clear_search (esb); -} - /* Widgetry creation. */ @@ -444,88 +299,79 @@ copy_subitems (ESearchBarSubitem *subitems) } static void -append_xml_menu_item (GString *xml, - const char *name, - const char *label, - const char *verb, - const char *accelerator) +add_dropdown (ESearchBar *esb, ESearchBarItem *items) { - char *encoded_label; - - encoded_label = bonobo_ui_util_encode_str (label); - g_string_sprintfa (xml, "<menuitem name=\"%s\" verb=\"%s\" label=\"%s\"", - name, verb, encoded_label); - g_free (encoded_label); - - if (accelerator != NULL) - g_string_sprintfa (xml, " accel=\"%s\"", accelerator); - - g_string_sprintfa (xml, "/>"); + GtkWidget *menu = esb->dropdown_menu; + GtkWidget *item; + + if (items->text) { + char *str; + str = _(items->text); + if (str == items->text) { + /* It may be english string, or utf8 rule name */ + item = e_utf8_gtk_menu_item_new_with_label (GTK_MENU (menu), str); + } else + item = gtk_menu_item_new_with_label (str); + } else { + item = gtk_menu_item_new(); + gtk_widget_set_sensitive (item, FALSE); + } + + gtk_widget_show (item); + gtk_menu_append (GTK_MENU (menu), item); + gtk_object_set_data (GTK_OBJECT (item), "EsbMenuId", GINT_TO_POINTER (items->id)); + gtk_signal_connect (GTK_OBJECT (item), "activate", + GTK_SIGNAL_FUNC (menubar_activated_cb), + esb); } static void -update_bonobo_menus (ESearchBar *esb) +set_dropdown (ESearchBar *esb, + ESearchBarItem *items) { - GString *xml; - GSList *p; - char *verb_name; - - bonobo_ui_component_rm (esb->ui_component, "/menu/Search/SearchBar", NULL); - - xml = g_string_new ("<placeholder name=\"SearchBar\">"); - - append_xml_menu_item (xml, "FindNow", _("_Find Now"), "ESearchBar:FindNow", NULL); - append_xml_menu_item (xml, "Clear", _("_Clear"), "ESearchBar:Clear", "*Control**Shift*b"); - - for (p = esb->menu_items; p != NULL; p = p->next) { - const ESearchBarItem *item; - - item = (const ESearchBarItem *) p->data; - - verb_name = verb_name_from_id (item->id); - bonobo_ui_component_add_verb (esb->ui_component, verb_name, search_verb_cb, esb); - - if (item->text == NULL) - g_string_append (xml, "<separator/>"); - else - append_xml_menu_item (xml, verb_name, item->text, verb_name, NULL); + GtkWidget *menu; + GtkWidget *dropdown; + int i; + + menu = esb->dropdown_menu = gtk_menu_new (); + for (i = 0; items[i].id != -1; i++) + add_dropdown (esb, items + i); + + gtk_widget_show_all (menu); + + dropdown = e_dropdown_button_new (_("Sear_ch"), GTK_MENU (menu)); + gtk_widget_show (dropdown); + + if (esb->dropdown_holder == NULL) { + /* See the comment in `put_in_spacer_widget()' to understand + why we have to do this. */ + + esb->dropdown_holder = put_in_spacer_widget (dropdown); + esb->dropdown = dropdown; + gtk_widget_show (esb->dropdown_holder); - g_free (verb_name); + gtk_box_pack_start (GTK_BOX (esb), esb->dropdown_holder, FALSE, FALSE, 0); + } else { + gtk_widget_destroy (esb->dropdown); + esb->dropdown = dropdown; + gtk_container_add (GTK_CONTAINER (esb->dropdown_holder), esb->dropdown); } - - g_string_sprintfa (xml, "</placeholder>"); - - bonobo_ui_component_set (esb->ui_component, "/menu/Search", xml->str, NULL); - - g_string_free (xml, TRUE); } +/* Frees an array of subitem information */ static void -set_menu (ESearchBar *esb, - ESearchBarItem *items) +free_subitems (ESearchBarSubitem *subitems) { - int i; - - free_menu_items (esb); - - if (items == NULL) - return; - - for (i = 0; items[i].id != -1; i++) { - ESearchBarItem *new_item; - - g_assert (items[i].subitems == NULL); + ESearchBarSubitem *s; - new_item = g_new (ESearchBarItem, 1); - new_item->text = g_strdup (items[i].text); - new_item->id = items[i].id; - new_item->subitems = NULL; + g_assert (subitems != NULL); - esb->menu_items = g_slist_append (esb->menu_items, new_item); + for (s = subitems; s->id != -1; s++) { + if (s->text) + g_free (s->text); } - if (esb->ui_component != NULL) - update_bonobo_menus (esb); + g_free (subitems); } /* Callback used when an option item is destroyed. We have to destroy its @@ -547,6 +393,8 @@ static void set_option (ESearchBar *esb, ESearchBarItem *items) { GtkWidget *menu; + GtkRequisition dropdown_requisition; + GtkRequisition option_requisition; int i; if (esb->option) { @@ -600,36 +448,41 @@ set_option (ESearchBar *esb, ESearchBarItem *items) gtk_option_menu_set_history (GTK_OPTION_MENU (esb->option), 0); gtk_widget_set_sensitive (esb->option, TRUE); + + /* Set the minimum height of this widget to that of the dropdown + button, for a better look. */ + g_assert (esb->dropdown != NULL); + + gtk_widget_size_request (esb->dropdown, &dropdown_requisition); + gtk_widget_size_request (esb->option, &option_requisition); + + gtk_container_set_border_width (GTK_CONTAINER (esb->dropdown), GTK_CONTAINER (esb->option)->border_width); } -static GtkWidget * -add_button (ESearchBar *esb, - const char *text, - GtkSignalFunc callback) +static void +add_activate_button (ESearchBar *esb) { GtkWidget *label; GtkWidget *holder; - GtkWidget *button; - label = gtk_label_new (text); - gtk_misc_set_padding (GTK_MISC (label), 2, 0); + label = gtk_label_new (_("Find Now")); + gtk_misc_set_padding(GTK_MISC(label), 2, 0); gtk_widget_show (label); /* See the comment in `put_in_spacer_widget()' to understand why we have to do this. */ - button = gtk_button_new (); - gtk_widget_show (button); - gtk_container_add (GTK_CONTAINER (button), label); + esb->activate_button = gtk_button_new (); + gtk_widget_show (esb->activate_button); + gtk_container_add (GTK_CONTAINER (esb->activate_button), label); - holder = put_in_spacer_widget (button); + holder = put_in_spacer_widget (esb->activate_button); gtk_widget_show (holder); - gtk_signal_connect (GTK_OBJECT (button), "clicked", callback, esb); + gtk_signal_connect (GTK_OBJECT (esb->activate_button), "clicked", + GTK_SIGNAL_FUNC (activate_button_clicked_cb), esb); - gtk_box_pack_end (GTK_BOX (esb), holder, FALSE, FALSE, 1); - - return button; + gtk_box_pack_start (GTK_BOX (esb), holder, FALSE, FALSE, 0); } static int @@ -711,14 +564,9 @@ impl_destroy (GtkObject *object) g_return_if_fail (object != NULL); g_return_if_fail (E_IS_SEARCH_BAR (object)); - - /* These three we do need to unref, because we explicitly hold + + /* These two we do need to unref, because we explicitly hold references to them. */ - - if (esb->ui_component != NULL) { - bonobo_object_unref (BONOBO_OBJECT (esb->ui_component)); - esb->ui_component = NULL; - } if (esb->entry) gtk_object_unref (GTK_OBJECT (esb->entry)); if (esb->suboption) @@ -728,8 +576,6 @@ impl_destroy (GtkObject *object) gtk_idle_remove (esb->pending_activate); esb->pending_activate = 0; } - - free_menu_items (esb); if (GTK_OBJECT_CLASS (parent_class)->destroy) GTK_OBJECT_CLASS (parent_class)->destroy (object); @@ -749,7 +595,7 @@ class_init (ESearchBarClass *klass) object_class->get_arg = impl_get_arg; object_class->destroy = impl_destroy; - klass->set_menu = set_menu; + klass->set_menu = set_dropdown; klass->set_option = set_option; gtk_object_add_arg_type ("ESearchBar::item_id", GTK_TYPE_ENUM, @@ -789,24 +635,12 @@ class_init (ESearchBarClass *klass) static void init (ESearchBar *esb) { - esb->ui_component = NULL; - esb->menu_items = NULL; - - esb->option = NULL; - esb->entry = NULL; - esb->suboption = NULL; + esb->dropdown = NULL; + esb->option = NULL; + esb->entry = NULL; - esb->option_menu = NULL; - esb->suboption_menu = NULL; - esb->dropdown_menu = NULL; - esb->activate_button = NULL; - esb->clear_button = NULL; - esb->entry_box = NULL; - - esb->pending_activate = 0; - - esb->item_id = 0; - esb->subitem_id = 0; + esb->item_id = 0; + esb->subitem_id = 0; } @@ -828,15 +662,11 @@ e_search_bar_construct (ESearchBar *search_bar, { g_return_if_fail (search_bar != NULL); g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + g_return_if_fail (menu_items != NULL); g_return_if_fail (option_items != NULL); - + gtk_box_set_spacing (GTK_BOX (search_bar), 1); - search_bar->clear_button = add_button (search_bar, _("Clear"), - GTK_SIGNAL_FUNC (clear_button_clicked_cb)); - search_bar->activate_button = add_button (search_bar, _("Find Now"), - GTK_SIGNAL_FUNC (activate_button_clicked_cb)); - e_search_bar_set_menu (search_bar, menu_items); search_bar->entry_box = gtk_hbox_new (0, FALSE); @@ -846,6 +676,8 @@ e_search_bar_construct (ESearchBar *search_bar, gtk_widget_show (search_bar->entry_box); gtk_box_pack_start (GTK_BOX(search_bar), search_bar->entry_box, TRUE, TRUE, 0); + add_activate_button (search_bar); + /* * If the default choice for the option menu has subitems, then we need to * activate the search immediately. However, the developer won't have @@ -865,6 +697,7 @@ e_search_bar_set_menu (ESearchBar *search_bar, ESearchBarItem *menu_items) { g_return_if_fail (search_bar != NULL); g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + g_return_if_fail (menu_items != NULL); ((ESearchBarClass *)((GtkObject *)search_bar)->klass)->set_menu (search_bar, menu_items); } @@ -874,8 +707,9 @@ e_search_bar_add_menu (ESearchBar *search_bar, ESearchBarItem *menu_item) { g_return_if_fail (search_bar != NULL); g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + g_return_if_fail (menu_item != NULL); - set_menu (search_bar, menu_item); + add_dropdown (search_bar, menu_item); } void @@ -937,7 +771,8 @@ e_search_bar_new (ESearchBarItem *menu_items, ESearchBarItem *option_items) { GtkWidget *widget; - + + g_return_val_if_fail (menu_items != NULL, NULL); g_return_val_if_fail (option_items != NULL, NULL); widget = GTK_WIDGET (gtk_type_new (e_search_bar_get_type ())); @@ -948,37 +783,14 @@ e_search_bar_new (ESearchBarItem *menu_items, } void -e_search_bar_set_ui_component (ESearchBar *search_bar, - BonoboUIComponent *ui_component) -{ - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - - if (search_bar->ui_component != NULL) - bonobo_object_unref (BONOBO_OBJECT (search_bar->ui_component)); - - search_bar->ui_component = ui_component; - if (ui_component != NULL) { - bonobo_object_ref (BONOBO_OBJECT (ui_component)); - setup_standard_verbs (search_bar); - update_bonobo_menus (search_bar); - } -} - -void -e_search_bar_set_menu_sensitive (ESearchBar *search_bar, int id, gboolean state) +e_search_bar_set_menu_sensitive (ESearchBar *esb, int id, gboolean state) { - char *verb_name; - char *path; - - verb_name = verb_name_from_id (id); - path = g_strconcat ("/commands/", verb_name, NULL); - g_free (verb_name); - - bonobo_ui_component_set_prop (search_bar->ui_component, path, - "sensitive", state ? "1" : "0", - NULL); - - g_free (path); + int row; + GtkWidget *widget; + + row = find_id (esb->dropdown_menu, id, "EsbMenuId", &widget); + if (row != -1) + gtk_widget_set_sensitive (widget, state); } GtkType |