2001-05-12 Gediminas Paulauskas <menesis@delfi.lt> * folder-browser-factory.c: load pixmaps for MessageCopy and MessageForwardAttached. Thanks Wayne Davis <wfdavis@seas.upenn.edu> for a patch. 2001-05-12 Gediminas Paulauskas <menesis@delfi.lt> * evolution-mail.xml: add pixmaps for MessageCopy and MessageForwardAttached. Thanks Wayne Davis <wfdavis@seas.upenn.edu> for a patch. 2001-05-12 Gediminas Paulauskas <menesis@delfi.lt> * po/POTFILES.in: update with new/moved files. also: Removed duplicated DATADIR in mail/Makefile.am fixed warning in e-search-bar.c in my recent code there svn path=/trunk/; revision=9783
526 lines
12 KiB
C
526 lines
12 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||
/*
|
||
* e-search-bar.c
|
||
*
|
||
* Copyright (C) 2000, 2001 Ximian, Inc.
|
||
*
|
||
* Authors:
|
||
* Chris Lahey <clahey@ximian.com>
|
||
* Ettore Perazzoli <ettore@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 <stdio.h> /* printf */
|
||
#include <gtk/gtkdrawingarea.h>
|
||
#include <gtk/gtkeventbox.h>
|
||
#include <gtk/gtkmenuitem.h>
|
||
#include <gtk/gtkoptionmenu.h>
|
||
|
||
#include <gal/widgets/e-unicode.h>
|
||
#include <gal/widgets/e-gui-utils.h>
|
||
|
||
#include <libgnome/gnome-defs.h>
|
||
#include <libgnome/gnome-i18n.h>
|
||
|
||
#include "e-search-bar.h"
|
||
#include "e-dropdown-button.h"
|
||
|
||
|
||
enum {
|
||
QUERY_CHANGED,
|
||
MENU_ACTIVATED,
|
||
|
||
LAST_SIGNAL
|
||
};
|
||
|
||
static gint esb_signals [LAST_SIGNAL] = { 0, };
|
||
|
||
static GtkHBoxClass *parent_class = NULL;
|
||
|
||
/* The arguments we take */
|
||
enum {
|
||
ARG_0,
|
||
ARG_OPTION_CHOICE,
|
||
ARG_TEXT,
|
||
};
|
||
|
||
|
||
/* Signals. */
|
||
|
||
static void
|
||
emit_query_changed (ESearchBar *esb)
|
||
{
|
||
gtk_signal_emit(GTK_OBJECT (esb),
|
||
esb_signals [QUERY_CHANGED]);
|
||
}
|
||
|
||
static void
|
||
emit_menu_activated (ESearchBar *esb, int item)
|
||
{
|
||
gtk_signal_emit(GTK_OBJECT (esb),
|
||
esb_signals [MENU_ACTIVATED],
|
||
item);
|
||
}
|
||
|
||
|
||
/* Callbacks. */
|
||
|
||
static void
|
||
menubar_activated_cb (GtkWidget *widget, ESearchBar *esb)
|
||
{
|
||
int id;
|
||
|
||
id = GPOINTER_TO_INT(gtk_object_get_data (GTK_OBJECT (widget), "EsbMenuId"));
|
||
|
||
emit_menu_activated(esb, id);
|
||
}
|
||
|
||
static void
|
||
option_activated_cb (GtkWidget *widget,
|
||
ESearchBar *esb)
|
||
{
|
||
int id;
|
||
|
||
id = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), "EsbChoiceId"));
|
||
|
||
esb->option_choice = id;
|
||
emit_query_changed (esb);
|
||
}
|
||
|
||
static void
|
||
entry_activated_cb (GtkWidget *widget,
|
||
ESearchBar *esb)
|
||
{
|
||
emit_query_changed (esb);
|
||
}
|
||
|
||
|
||
/* Widgetry creation. */
|
||
|
||
static void add_dropdown(ESearchBar *esb, ESearchBarItem *items)
|
||
{
|
||
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_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
|
||
set_dropdown (ESearchBar *esb,
|
||
ESearchBarItem *items)
|
||
{
|
||
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_UNSET_FLAGS (dropdown, GTK_CAN_FOCUS);
|
||
gtk_widget_show (dropdown);
|
||
|
||
if (esb->dropdown_holder == NULL) {
|
||
|
||
/* So, GtkOptionMenu is stupid; it adds a 1-pixel-wide empty border
|
||
around the button for no reason. So we add a 1-pixel-wide border
|
||
around the button as well, by using an event box. */
|
||
|
||
esb->dropdown_holder = gtk_event_box_new ();
|
||
gtk_container_set_border_width (GTK_CONTAINER (esb->dropdown_holder), 1);
|
||
esb->dropdown = dropdown;
|
||
gtk_container_add (GTK_CONTAINER (esb->dropdown_holder), esb->dropdown);
|
||
gtk_widget_show (esb->dropdown_holder);
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
static void
|
||
set_option(ESearchBar *esb, ESearchBarItem *items)
|
||
{
|
||
GtkWidget *menu;
|
||
GtkRequisition dropdown_requisition;
|
||
GtkRequisition option_requisition;
|
||
int i;
|
||
|
||
if (esb->option) {
|
||
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->option_menu = menu = gtk_menu_new ();
|
||
for (i = 0; items[i].id != -1; i++) {
|
||
GtkWidget *item;
|
||
|
||
if (items[i].text) {
|
||
char *str;
|
||
str = _(items[i].text);
|
||
if (str == items[i].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_menu_append (GTK_MENU (menu), item);
|
||
|
||
gtk_object_set_data (GTK_OBJECT (item), "EsbChoiceId", GINT_TO_POINTER(items[i].id));
|
||
|
||
gtk_signal_connect (GTK_OBJECT (item), "activate",
|
||
GTK_SIGNAL_FUNC (option_activated_cb),
|
||
esb);
|
||
}
|
||
gtk_widget_show_all (menu);
|
||
|
||
gtk_option_menu_set_menu (GTK_OPTION_MENU (esb->option), menu);
|
||
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 void
|
||
add_entry (ESearchBar *esb)
|
||
{
|
||
esb->entry = gtk_entry_new();
|
||
gtk_signal_connect (GTK_OBJECT (esb->entry), "activate",
|
||
GTK_SIGNAL_FUNC (entry_activated_cb), esb);
|
||
gtk_widget_show(esb->entry);
|
||
gtk_box_pack_start(GTK_BOX(esb), esb->entry, TRUE, TRUE, 0);
|
||
}
|
||
|
||
static void
|
||
add_spacer (ESearchBar *esb)
|
||
{
|
||
GtkWidget *spacer;
|
||
|
||
spacer = gtk_drawing_area_new();
|
||
gtk_widget_show(spacer);
|
||
gtk_box_pack_start(GTK_BOX(esb), spacer, FALSE, FALSE, 0);
|
||
|
||
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. */
|
||
|
||
static void
|
||
impl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||
{
|
||
ESearchBar *esb = E_SEARCH_BAR(object);
|
||
|
||
switch (arg_id) {
|
||
case ARG_OPTION_CHOICE:
|
||
GTK_VALUE_ENUM (*arg) = e_search_bar_get_option_choice (esb);
|
||
break;
|
||
|
||
case ARG_TEXT:
|
||
GTK_VALUE_STRING (*arg) = e_search_bar_get_text (esb);
|
||
break;
|
||
|
||
default:
|
||
arg->type = GTK_TYPE_INVALID;
|
||
break;
|
||
}
|
||
}
|
||
|
||
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);
|
||
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;
|
||
|
||
case ARG_TEXT:
|
||
e_utf8_gtk_editable_set_text(GTK_EDITABLE(esb->entry), GTK_VALUE_STRING (*arg));
|
||
emit_query_changed (esb);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void
|
||
impl_destroy (GtkObject *object)
|
||
{
|
||
if (GTK_OBJECT_CLASS(parent_class)->destroy)
|
||
GTK_OBJECT_CLASS(parent_class)->destroy (object);
|
||
}
|
||
|
||
|
||
static void
|
||
class_init (ESearchBarClass *klass)
|
||
{
|
||
GtkObjectClass *object_class;
|
||
|
||
object_class = GTK_OBJECT_CLASS(klass);
|
||
|
||
parent_class = gtk_type_class (gtk_hbox_get_type ());
|
||
|
||
object_class->set_arg = impl_set_arg;
|
||
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,
|
||
GTK_ARG_READWRITE, ARG_TEXT);
|
||
|
||
esb_signals [QUERY_CHANGED] =
|
||
gtk_signal_new ("query_changed",
|
||
GTK_RUN_LAST,
|
||
object_class->type,
|
||
GTK_SIGNAL_OFFSET (ESearchBarClass, 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 (ESearchBarClass, menu_activated),
|
||
gtk_marshal_NONE__INT,
|
||
GTK_TYPE_NONE, 1, GTK_TYPE_INT);
|
||
|
||
gtk_object_class_add_signals (object_class, esb_signals, LAST_SIGNAL);
|
||
}
|
||
|
||
static void
|
||
init (ESearchBar *esb)
|
||
{
|
||
esb->dropdown = NULL;
|
||
esb->option = NULL;
|
||
esb->entry = NULL;
|
||
|
||
esb->option_choice = 0;
|
||
}
|
||
|
||
|
||
/* Object construction. */
|
||
|
||
void
|
||
e_search_bar_construct (ESearchBar *search_bar,
|
||
ESearchBarItem *menu_items,
|
||
ESearchBarItem *option_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);
|
||
g_return_if_fail (option_items != NULL);
|
||
|
||
gtk_box_set_spacing (GTK_BOX (search_bar), 1);
|
||
|
||
e_search_bar_set_menu(search_bar, menu_items);
|
||
|
||
e_search_bar_set_option(search_bar, option_items);
|
||
|
||
add_entry (search_bar);
|
||
|
||
add_spacer (search_bar);
|
||
}
|
||
|
||
void
|
||
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);
|
||
}
|
||
|
||
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
|
||
e_search_bar_set_option(ESearchBar *search_bar, ESearchBarItem *option_items)
|
||
{
|
||
g_return_if_fail (search_bar != NULL);
|
||
g_return_if_fail (E_IS_SEARCH_BAR (search_bar));
|
||
g_return_if_fail (option_items != NULL);
|
||
|
||
((ESearchBarClass *)((GtkObject *)search_bar)->klass)->set_option(search_bar, option_items);
|
||
}
|
||
|
||
GtkWidget *
|
||
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 ()));
|
||
|
||
e_search_bar_construct (E_SEARCH_BAR (widget), menu_items, option_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)
|
||
{
|
||
static GtkType type = 0;
|
||
|
||
if (!type) {
|
||
static const GtkTypeInfo info = {
|
||
"ESearchBar",
|
||
sizeof (ESearchBar),
|
||
sizeof (ESearchBarClass),
|
||
(GtkClassInitFunc) class_init,
|
||
(GtkObjectInitFunc) init,
|
||
/* reserved_1 */ NULL,
|
||
/* reserved_2 */ NULL,
|
||
(GtkClassInitFunc) NULL,
|
||
};
|
||
|
||
type = gtk_type_unique (gtk_hbox_get_type (), &info);
|
||
}
|
||
|
||
return type;
|
||
}
|
||
|
||
/**
|
||
* e_search_bar_get_option_choice:
|
||
* @search_bar: A search bar.
|
||
*
|
||
* Queries the currently selected item in the options menu of a search bar.
|
||
*
|
||
* Return value: Identifier of the selected item in the options menu.
|
||
**/
|
||
int
|
||
e_search_bar_get_option_choice (ESearchBar *search_bar)
|
||
{
|
||
g_return_val_if_fail (search_bar != NULL, -1);
|
||
g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1);
|
||
|
||
return search_bar->option_choice;
|
||
}
|
||
|
||
/**
|
||
* e_search_bar_get_text:
|
||
* @search_bar: A search bar.
|
||
*
|
||
* Queries the text of the entry line in a search bar.
|
||
*
|
||
* Return value: The text string that is in the entry line of the search bar.
|
||
* This must be freed using g_free().
|
||
**/
|
||
char *
|
||
e_search_bar_get_text (ESearchBar *search_bar)
|
||
{
|
||
g_return_val_if_fail (search_bar != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL);
|
||
|
||
return e_utf8_gtk_editable_get_text (GTK_EDITABLE (search_bar->entry));
|
||
}
|