diff options
-rw-r--r-- | widgets/misc/ChangeLog | 33 | ||||
-rw-r--r-- | widgets/misc/Makefile.am | 2 | ||||
-rw-r--r-- | widgets/misc/e-filter-bar.c | 439 | ||||
-rw-r--r-- | widgets/misc/e-filter-bar.h | 107 | ||||
-rw-r--r-- | widgets/misc/e-search-bar.c | 110 | ||||
-rw-r--r-- | widgets/misc/e-search-bar.h | 10 |
6 files changed, 672 insertions, 29 deletions
diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog index 7724bcffcb..8d4c3917c6 100644 --- a/widgets/misc/ChangeLog +++ b/widgets/misc/ChangeLog @@ -1,3 +1,36 @@ +2001-03-01 Not Zed <NotZed@Ximian.com> + + * e-filter-bar.c: New type of search bar that interacts with + filter contexts to save filters etc. Still probably needs a + little cleanpu. + +2001-02-28 Not Zed <NotZed@Ximian.com> + + * e-search-bar.c (add_dropdown): Save the dropdown menu in the + struct too. Sigh, this is only so we can scan its content later, + ick. + (e_search_bar_set_menu_sensitive): New function to se tthe + sentisitivty of menyu items based on id. + (find_id): New function to find the row and widget for a specific + id. + (add_option): Renamed to set_option. + (add_dropdown): Renamed to set_dropdown. + (add_dropdown): ?New function to add a single item. + (set_dropdown): Call add_dropdown to add each item. + (e_search_bar_add_menu): New public function to add a single item. + +2001-02-27 Not Zed <NotZed@Ximian.com> + + * Makefile.am (libemiscwidgets_a_SOURCES): Added filter-bar.[ch]. + + * e-search-bar.c (class_init): Init virtual functions. + (e_search_bar_set_option): + (e_search_bar_set_menu): virtualise calling. + (e_search_bar_construct): Call virtual functions to setup menus. + + * e-search-bar.h (struct _ESearchBarClass): Virtualise + add_dropdown/add_option, so certain base options can be created. + 2001-02-25 Damon Chaplin <damon@ximian.com> * e-cell-date-edit.[hc]: new files to implement an ECell for showing diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index bdd397c5d4..401aac64a0 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -23,6 +23,8 @@ libemiscwidgets_a_SOURCES = \ e-dateedit.h \ e-dropdown-button.c \ e-dropdown-button.h \ + e-filter-bar.c \ + e-filter-bar.h \ e-messagebox.c \ e-messagebox.h \ e-search-bar.c \ diff --git a/widgets/misc/e-filter-bar.c b/widgets/misc/e-filter-bar.c new file mode 100644 index 0000000000..6679059963 --- /dev/null +++ b/widgets/misc/e-filter-bar.c @@ -0,0 +1,439 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-search-bar.c + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: + * Michael Zucchi <notzed@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> + +#include <gtk/gtk.h> + +#include "e-dropdown-button.h" +#include "e-filter-bar.h" + +#include <gal/widgets/e-unicode.h> +#include <gal/widgets/e-gui-utils.h> + + +enum { + LAST_SIGNAL +}; + +/*static gint esb_signals [LAST_SIGNAL] = { 0, };*/ + +static ESearchBarClass *parent_class = NULL; + +/* The arguments we take */ +enum { + ARG_0, + ARG_QUERY, +}; + + +/* Callbacks. */ + +/* rule editor thingy */ +static void rule_editor_destroyed(GtkWidget *w, EFilterBar *efb) +{ + efb->save_dialogue = NULL; + e_search_bar_set_menu_sensitive((ESearchBar *)efb, E_FILTERBAR_SAVE_ID, TRUE); +} + +static void rule_editor_clicked(GtkWidget *w, int button, void *data) +{ + EFilterBar *efb = data; + ESearchBarItem item; + FilterRule *rule; + + switch(button) { + case 0: + rule = gtk_object_get_data((GtkObject *)w, "rule"); + if (rule) { + item.text = rule->name; + item.id = efb->menu_base + efb->menu_rules->len; + + g_ptr_array_add(efb->menu_rules, rule); + + rule_context_add_rule(efb->context, rule); + /* FIXME: check return */ + rule_context_save(efb->context, efb->userrules); + e_search_bar_add_menu((ESearchBar *)efb, &item); + } + case 1: + gnome_dialog_close((GnomeDialog *)w); + break; + case -1: + } +} + +static void rule_advanced_clicked(GtkWidget *w, int button, void *data) +{ + EFilterBar *efb = data; + FilterRule *rule; + + switch(button) { + case 0: /* 'ok' */ + case 1: + rule = gtk_object_get_data((GtkObject *)w, "rule"); + if (rule) { + efb->current_query = rule; + gtk_object_ref((GtkObject *)rule); + gtk_signal_emit_by_name((GtkObject *)efb, "query_changed"); + } + if (button == 1) + rule_editor_clicked(w, 0, data); + case 2: + gnome_dialog_close((GnomeDialog *)w); + break; + case -1: + } +} + +static void +menubar_activated (ESearchBar *esb, int id, void *data) +{ + EFilterBar *efb = (EFilterBar *)esb; + + switch(id) { + case E_FILTERBAR_RESET_ID: + printf("Reset menu\n"); + efb->current_query = NULL; + gtk_object_set((GtkObject *)esb, "option_choice", efb->option_base, NULL); + gtk_object_set((GtkObject *)esb, "text", NULL, NULL); + gtk_widget_set_sensitive(esb->entry, TRUE); + break; + case E_FILTERBAR_SAVE_ID: + if (efb->current_query && !efb->save_dialogue) { + GtkWidget *w; + GnomeDialog *gd; + FilterRule *rule; + + rule = filter_rule_clone(efb->current_query, efb->context); + + w = filter_rule_get_widget(rule, efb->context); + filter_rule_set_source(rule, FILTER_SOURCE_INCOMING); + gd = (GnomeDialog *)gnome_dialog_new(_("Save Search"), + GNOME_STOCK_BUTTON_OK, + GNOME_STOCK_BUTTON_CANCEL, + NULL); + efb->save_dialogue = (GtkWidget *)gd; + gnome_dialog_set_default (gd, 0); + + gtk_window_set_policy(GTK_WINDOW(gd), FALSE, TRUE, FALSE); + /*gtk_window_set_default_size (GTK_WINDOW (gd), 500, 500);*/ + gtk_box_pack_start((GtkBox *)gd->vbox, w, TRUE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + gtk_object_ref((GtkObject *)rule); + gtk_object_set_data_full((GtkObject *)gd, "rule", rule, (GtkDestroyNotify)gtk_object_unref); + gtk_signal_connect((GtkObject *)gd, "clicked", rule_editor_clicked, efb); + gtk_signal_connect((GtkObject *)gd, "destroy", rule_editor_destroyed, efb); + + e_search_bar_set_menu_sensitive(esb, E_FILTERBAR_SAVE_ID, FALSE); + gtk_widget_set_sensitive(esb->entry, FALSE); + + gtk_widget_show((GtkWidget *)gd); + } + + printf("Save menu\n"); + break; + default: + if (id >= efb->menu_base && id < efb->menu_base + efb->menu_rules->len) { + GString *out = g_string_new(""); + printf("Selected rule: %s\n", ((FilterRule *)efb->menu_rules->pdata[id - efb->menu_base])->name); + filter_rule_build_code(efb->menu_rules->pdata[id - efb->menu_base], out); + printf("query: '%s'\n", out->str); + g_string_free(out, 1); + + efb->current_query = (FilterRule *)efb->menu_rules->pdata[id - efb->menu_base]; + efb->setquery = TRUE; + gtk_object_set((GtkObject *)esb, "option_choice", E_FILTERBAR_ADVANCED_ID, NULL); + + gtk_widget_set_sensitive(esb->entry, FALSE); + } else { + gtk_widget_set_sensitive(esb->entry, TRUE); + return; + } + } + + gtk_signal_emit_stop_by_name((GtkObject *)esb, "menu_activated"); +} + +static void +option_changed (ESearchBar *esb, void *data) +{ + EFilterBar *efb = (EFilterBar *)esb; + int id = esb->option_choice; + char *query; + + printf("option changed, id = %d\n", id); + + switch(id) { + case E_FILTERBAR_ADVANCED_ID: { + printf("Advanced search!\n"); + + if (!efb->save_dialogue && !efb->setquery) { + GtkWidget *w; + GnomeDialog *gd; + FilterRule *rule; + + if (efb->current_query) + rule = filter_rule_clone(efb->current_query, efb->context); + else + rule = filter_rule_new(); + + w = filter_rule_get_widget(rule, efb->context); + filter_rule_set_source(rule, FILTER_SOURCE_INCOMING); + gd = (GnomeDialog *)gnome_dialog_new(_("Advanced Search"), + GNOME_STOCK_BUTTON_OK, + _("Save"), + GNOME_STOCK_BUTTON_CANCEL, + NULL); + efb->save_dialogue = (GtkWidget *)gd; + gnome_dialog_set_default (gd, 0); + + gtk_window_set_policy(GTK_WINDOW(gd), FALSE, TRUE, FALSE); + /*gtk_window_set_default_size (GTK_WINDOW (gd), 500, 500);*/ + gtk_box_pack_start((GtkBox *)gd->vbox, w, TRUE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + gtk_object_ref((GtkObject *)rule); + gtk_object_set_data_full((GtkObject *)gd, "rule", rule, (GtkDestroyNotify)gtk_object_unref); + gtk_signal_connect((GtkObject *)gd, "clicked", rule_advanced_clicked, efb); + gtk_signal_connect((GtkObject *)gd, "destroy", rule_editor_destroyed, efb); + + e_search_bar_set_menu_sensitive(esb, E_FILTERBAR_SAVE_ID, FALSE); + gtk_widget_set_sensitive(esb->entry, FALSE); + + gtk_widget_show((GtkWidget *)gd); + } + } break; + default: + if (id >= efb->option_base && id < efb->option_base + efb->option_rules->len) { + efb->current_query = (FilterRule *)efb->option_rules->pdata[id - efb->option_base]; + if (efb->config) { + gtk_object_get((GtkObject *)esb, "text", &query, NULL); + efb->config(efb, efb->current_query, id, query, efb->config_data); + g_free(query); + } + gtk_widget_set_sensitive(esb->entry, TRUE); + } else { + gtk_widget_set_sensitive(esb->entry, FALSE); + efb->current_query = NULL; + } + } + efb->setquery = FALSE; +} + +static GArray *build_items(ESearchBar *esb, ESearchBarItem *items, int type, int *start, GPtrArray *rules) +{ + FilterRule *rule = NULL; + EFilterBar *efb = (EFilterBar *)esb; + int id = 0, i; + GArray *menu = g_array_new(FALSE, FALSE, sizeof(ESearchBarItem)); + ESearchBarItem item; + char *source; + + /* find a unique starting point for the id's of our items */ + for (i=0;items[i].id != -1;i++) { + if (items[i].id >= id) + id = items[i].id+1; + } + + /* add the user menus */ + g_array_append_vals(menu, items, i); + + *start = id; + + if (type == 0) { + /* and add ours */ + item.id = 0; + item.text = NULL; + g_array_append_vals(menu, &item, 1); + source = FILTER_SOURCE_INCOMING; + } else { + source = FILTER_SOURCE_DEMAND; + } + + while ( (rule = rule_context_next_rule(efb->context, rule, source)) ) { + item.id = id++; + item.text = rule->name; + g_array_append_vals(menu, &item, 1); + g_ptr_array_add(rules, rule); + } + + /* always add on the advanced menu */ + if (type == 1) { + item.id = E_FILTERBAR_ADVANCED_ID; + item.text = _("Advanced ..."); + g_array_append_vals(menu, &item, 1); + } + + item.id = -1; + item.text = NULL; + g_array_append_vals(menu, &item, 1); + + return menu; +} + +/* Virtual methods */ +static void +set_menu(ESearchBar *esb, ESearchBarItem *items) +{ + GArray *menu; + EFilterBar *efb = (EFilterBar *)esb; + + g_ptr_array_set_size(efb->menu_rules, 0); + menu = build_items(esb, items, 0, &efb->menu_base, efb->menu_rules); + ((ESearchBarClass *)parent_class)->set_menu(esb, (ESearchBarItem *)menu->data); + g_array_free(menu, TRUE); +} + +static void +set_option(ESearchBar *esb, ESearchBarItem *items) +{ + GArray *menu; + EFilterBar *efb = (EFilterBar *)esb; + + g_ptr_array_set_size(efb->option_rules, 0); + menu = build_items(esb, items, 1, &efb->option_base, efb->option_rules); + ((ESearchBarClass *)parent_class)->set_option(esb, (ESearchBarItem *)menu->data); + g_array_free(menu, TRUE); +} + + +/* GtkObject methods. */ + +static void +impl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + EFilterBar *efb = E_FILTER_BAR(object); + + switch (arg_id) { + case ARG_QUERY: + if (efb->current_query) { + GString *out = g_string_new(""); + + filter_rule_build_code(efb->current_query, out); + GTK_VALUE_STRING(*arg) = out->str; + g_string_free(out, FALSE); + } else { + GTK_VALUE_STRING(*arg) = NULL; + } + break; + } +} + + +static void +class_init (EFilterBarClass *klass) +{ + GtkObjectClass *object_class; + ESearchBarClass *esb_class = (ESearchBarClass *)klass; + + object_class = GTK_OBJECT_CLASS(klass); + + parent_class = gtk_type_class(e_search_bar_get_type()); + + object_class->get_arg = impl_get_arg; + + esb_class->set_menu = set_menu; + esb_class->set_option = set_option; + + gtk_object_add_arg_type ("EFilterBar::query", GTK_TYPE_STRING, GTK_ARG_READABLE, ARG_QUERY); + +#if 0 + esb_signals [QUERY_CHANGED] = + gtk_signal_new ("query_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EFilterBarClass, query_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + esb_signals [MENU_ACTIVATED] = + gtk_signal_new ("menu_activated", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EFilterBarClass, menu_activated), + gtk_marshal_NONE__INT, + GTK_TYPE_NONE, 1, GTK_TYPE_INT); + + gtk_object_class_add_signals (object_class, esb_signals, LAST_SIGNAL); +#endif +} + +static void +init (EFilterBar *efb) +{ + gtk_signal_connect((GtkObject *)efb, "menu_activated", menubar_activated, NULL); + gtk_signal_connect((GtkObject *)efb, "query_changed", option_changed, NULL); + + efb->menu_rules = g_ptr_array_new(); + efb->option_rules = g_ptr_array_new(); +} + + +/* Object construction. */ + +EFilterBar *e_filter_bar_new (RuleContext *context, const char *systemrules, const char *userrules, EFilterBarConfigRule config, void *data) +{ + EFilterBar *bar; + ESearchBarItem item = { NULL, -1 }; + + bar = gtk_type_new(e_filter_bar_get_type()); + + bar->context = context; + gtk_object_ref((GtkObject *)context); + bar->systemrules = g_strdup(systemrules); + bar->userrules = g_strdup(userrules); + rule_context_load(context, systemrules, userrules); + + bar->config = config; + bar->config_data = data; + + e_search_bar_construct((ESearchBar *)bar, &item, &item); + + return bar; +} + +GtkType +e_filter_bar_get_type (void) +{ + static GtkType type = 0; + + if (!type) { + static const GtkTypeInfo info = { + "EFilterBar", + sizeof (EFilterBar), + sizeof (EFilterBarClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (e_search_bar_get_type (), &info); + } + + return type; +} + diff --git a/widgets/misc/e-filter-bar.h b/widgets/misc/e-filter-bar.h new file mode 100644 index 0000000000..8f4d60079b --- /dev/null +++ b/widgets/misc/e-filter-bar.h @@ -0,0 +1,107 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* e-filter-bar.h + * Copyright (C) 2001 Ximian Inc. + * Author: Michael Zucchi <notzed@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __E_FILTER_BAR_H__ +#define __E_FILTER_BAR_H__ + +#include <gtk/gtk.h> +#include "e-search-bar.h" + +#include "filter/rule-context.h" +#include "filter/filter-rule.h" + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +/* EFilterBar - A filter rule driven search bar. + * + * The following arguments are available: + * + * name type read/write description + * --------------------------------------------------------------------------------- + * query string R String representing query. + */ + +#define E_FILTER_BAR_TYPE (e_filter_bar_get_type ()) +#define E_FILTER_BAR(obj) (GTK_CHECK_CAST ((obj), E_FILTER_BAR_TYPE, EFilterBar)) +#define E_FILTER_BAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_FILTER_BAR_TYPE, EFilterBarClass)) +#define E_IS_FILTER_BAR(obj) (GTK_CHECK_TYPE ((obj), E_FILTER_BAR_TYPE)) +#define E_IS_FILTER_BAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_FILTER_BAR_TYPE)) + +typedef struct _EFilterBar EFilterBar; +typedef struct _EFilterBarClass EFilterBarClass; + +typedef void (*EFilterBarConfigRule)(EFilterBar *, FilterRule *rule, int id, const char *query, void *data); + +struct _EFilterBar +{ + ESearchBar parent; + + int menu_base, option_base; + GPtrArray *menu_rules, *option_rules; + + GtkWidget *save_dialogue; /* current save dialogue (so we dont pop up multiple ones) */ + + FilterRule *current_query; /* as it says */ + int setquery; /* true when we're setting a query directly to advanced, so dont popup the dialogue */ + + RuleContext *context; + char *systemrules; + char *userrules; + + EFilterBarConfigRule config; + void *config_data; +}; + +struct _EFilterBarClass +{ + ESearchBarClass parent_class; +}; + +/* "preset" items */ +enum { + /* preset menu options */ + E_FILTERBAR_RESET_ID = -2, + E_FILTERBAR_SAVE_ID = -3, + E_FILTERBAR_EDIT_ID = -4, + + /* preset option options */ + E_FILTERBAR_ADVANCED_ID = -5, + + E_FILTERBAR_LAST_ID = -6, +}; + +#define E_FILTERBAR_SAVE { N_("Save As ..."), E_FILTERBAR_SAVE_ID } +#define E_FILTERBAR_RESET { N_("Show All"), E_FILTERBAR_RESET_ID } +#define E_FILTERBAR_EDIT { N_("Edit ..."), E_FILTERBAR_EDIT_ID } +#define E_FILTERBAR_ADVANCED { N_("Advanced ..."), E_FILTERBAR_ADVANCED_ID } + + +GtkType e_filter_bar_get_type (void); +EFilterBar*e_filter_bar_new (RuleContext *, const char *sys, const char *user, EFilterBarConfigRule config, void *data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __E_FILTER_BAR_H__ */ diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c index c1d69161c6..30eaf0947f 100644 --- a/widgets/misc/e-search-bar.c +++ b/widgets/misc/e-search-bar.c @@ -105,31 +105,36 @@ entry_activated_cb (GtkWidget *widget, /* Widgetry creation. */ +static void add_dropdown(ESearchBar *esb, ESearchBarItem *items) +{ + GtkWidget *menu = esb->dropdown_menu; + GtkWidget *item; + + if (items->text) + item = gtk_menu_item_new_with_label (_(items->text)); + else + item = gtk_menu_item_new(); + + 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 -add_dropdown (ESearchBar *esb, +set_dropdown (ESearchBar *esb, ESearchBarItem *items) { GtkWidget *menu; GtkWidget *dropdown; int i; - menu = gtk_menu_new (); - for (i = 0; items[i].id != -1; i++) { - GtkWidget *item; + menu = esb->dropdown_menu = gtk_menu_new (); + for (i = 0; items[i].id != -1; i++) + add_dropdown(esb, items+i); - if (items[i].text) - item = gtk_menu_item_new_with_label (_(items[i].text)); - else - item = gtk_menu_item_new(); - - gtk_menu_append (GTK_MENU (menu), item); - - gtk_object_set_data (GTK_OBJECT (item), "EsbMenuId", GINT_TO_POINTER(items[i].id)); - - gtk_signal_connect (GTK_OBJECT (item), "activate", - GTK_SIGNAL_FUNC (menubar_activated_cb), - esb); - } gtk_widget_show_all (menu); dropdown = e_dropdown_button_new (_("Sear_ch"), GTK_MENU (menu)); @@ -150,7 +155,6 @@ add_dropdown (ESearchBar *esb, gtk_box_pack_start(GTK_BOX(esb), esb->dropdown_holder, FALSE, FALSE, 0); } else { - gtk_container_remove(GTK_CONTAINER(esb->dropdown_holder), esb->dropdown); gtk_widget_destroy(esb->dropdown); esb->dropdown = dropdown; gtk_container_add (GTK_CONTAINER (esb->dropdown_holder), esb->dropdown); @@ -158,7 +162,7 @@ add_dropdown (ESearchBar *esb, } static void -add_option(ESearchBar *esb, ESearchBarItem *items) +set_option(ESearchBar *esb, ESearchBarItem *items) { GtkWidget *menu; GtkRequisition dropdown_requisition; @@ -166,15 +170,14 @@ add_option(ESearchBar *esb, ESearchBarItem *items) int i; if (esb->option) { - gtk_option_menu_remove_menu((GtkOptionMenu *)esb->option); - gtk_widget_destroy(esb->menu); + gtk_widget_destroy(esb->option_menu); } else { esb->option = gtk_option_menu_new(); gtk_widget_show(esb->option); gtk_box_pack_start(GTK_BOX(esb), esb->option, FALSE, FALSE, 0); } - esb->menu = menu = gtk_menu_new (); + esb->option_menu = menu = gtk_menu_new (); for (i = 0; items[i].id != -1; i++) { GtkWidget *item; @@ -230,6 +233,29 @@ add_spacer (ESearchBar *esb) gtk_widget_set_usize(spacer, 19, 1); } +static int +find_id(GtkWidget *menu, int idin, const char *type, GtkWidget **widget) +{ + GList *l = GTK_MENU_SHELL(menu)->children; + int row = -1, i = 0, id; + + if (widget) + *widget = NULL; + while (l) { + id = GPOINTER_TO_INT(gtk_object_get_data(l->data, type)); + printf("comparing id %d to query %d\n", id, idin); + if (id == idin) { + row = i; + if (widget) + *widget = l->data; + break; + } + i++; + l = l->next; + } + return row; +} + /* GtkObject methods. */ @@ -257,11 +283,15 @@ static void impl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) { ESearchBar *esb = E_SEARCH_BAR(object); + int row; switch (arg_id) { case ARG_OPTION_CHOICE: - esb->option_choice = GTK_VALUE_ENUM (*arg); - gtk_option_menu_set_history (GTK_OPTION_MENU (esb->option), esb->option_choice); + esb->option_choice = GTK_VALUE_ENUM(*arg); + row = find_id(esb->option_menu, esb->option_choice, "EsbChoiceId", NULL); + if (row == -1) + row = 0; + gtk_option_menu_set_history (GTK_OPTION_MENU (esb->option), row); emit_query_changed (esb); break; @@ -296,6 +326,9 @@ class_init (ESearchBarClass *klass) object_class->get_arg = impl_get_arg; object_class->destroy = impl_destroy; + klass->set_menu = set_dropdown; + klass->set_option = set_option; + gtk_object_add_arg_type ("ESearchBar::option_choice", GTK_TYPE_ENUM, GTK_ARG_READWRITE, ARG_OPTION_CHOICE); gtk_object_add_arg_type ("ESearchBar::text", GTK_TYPE_STRING, @@ -345,9 +378,9 @@ e_search_bar_construct (ESearchBar *search_bar, gtk_box_set_spacing (GTK_BOX (search_bar), 1); - add_dropdown (search_bar, menu_items); + e_search_bar_set_menu(search_bar, menu_items); - add_option (search_bar, option_items); + e_search_bar_set_option(search_bar, option_items); add_entry (search_bar); @@ -361,7 +394,17 @@ e_search_bar_set_menu(ESearchBar *search_bar, ESearchBarItem *menu_items) g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); g_return_if_fail (menu_items != NULL); - add_dropdown (search_bar, menu_items); + ((ESearchBarClass *)((GtkObject *)search_bar)->klass)->set_menu(search_bar, menu_items); +} + +void +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); + + add_dropdown(search_bar, menu_item); } void @@ -371,7 +414,7 @@ e_search_bar_set_option(ESearchBar *search_bar, ESearchBarItem *option_items) g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); g_return_if_fail (option_items != NULL); - add_option (search_bar, option_items); + ((ESearchBarClass *)((GtkObject *)search_bar)->klass)->set_option(search_bar, option_items); } GtkWidget * @@ -390,6 +433,17 @@ e_search_bar_new (ESearchBarItem *menu_items, return widget; } +void +e_search_bar_set_menu_sensitive(ESearchBar *esb, int id, gboolean state) +{ + int row; + GtkWidget *widget; + + row = find_id(esb->dropdown_menu, id, "EsbMenuId", &widget); + if (row != -1) + gtk_widget_set_sensitive(widget, state); +} + GtkType e_search_bar_get_type (void) { diff --git a/widgets/misc/e-search-bar.h b/widgets/misc/e-search-bar.h index 222501d2fe..36b80fafc2 100644 --- a/widgets/misc/e-search-bar.h +++ b/widgets/misc/e-search-bar.h @@ -63,7 +63,8 @@ struct _ESearchBar /* PRIVATE */ GtkWidget *dropdown_holder; /* holds the dropdown */ - GtkWidget *menu; + GtkWidget *option_menu; + GtkWidget *dropdown_menu; int option_choice; }; @@ -72,6 +73,9 @@ struct _ESearchBarClass { GtkHBoxClass parent_class; + void (*set_menu) (ESearchBar *, ESearchBarItem *); + void (*set_option) (ESearchBar *, ESearchBarItem *); + void (*query_changed) (ESearchBar *search); void (*menu_activated) (ESearchBar *search, int item); }; @@ -79,6 +83,8 @@ struct _ESearchBarClass GtkType e_search_bar_get_type (void); void e_search_bar_set_menu (ESearchBar *search_bar, ESearchBarItem *menu_items); +void e_search_bar_add_menu (ESearchBar *search_bar, ESearchBarItem *menu_item); + void e_search_bar_set_option (ESearchBar *search_bar, ESearchBarItem *option_items); void e_search_bar_construct (ESearchBar *search_bar, ESearchBarItem *menu_items, @@ -86,6 +92,8 @@ void e_search_bar_construct (ESearchBar *search_bar, GtkWidget *e_search_bar_new (ESearchBarItem *menu_items, ESearchBarItem *option_items); +void e_search_bar_set_menu_sensitive(ESearchBar *search_bar, int id, gboolean state); + #ifdef __cplusplus } #endif /* __cplusplus */ |