/* * Copyright (C) 2000 Helix Code Inc. * * Authors: Michael Zucchi * * Abstract filter argument class. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library 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 Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "filter-arg.h" static void filter_arg_class_init (FilterArgClass *class); static void filter_arg_init (FilterArg *gspaper); #define _PRIVATE(x) (((FilterArg *)(x))->priv) struct _FilterArgPrivate { GtkWidget *dialogue; /* editor widget */ xmlNodePtr *oldargs; }; static GtkObjectClass *parent_class; enum { CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; guint filter_arg_get_type (void) { static guint type = 0; if (!type) { GtkTypeInfo type_info = { "FilterArg", sizeof (FilterArg), sizeof (FilterArgClass), (GtkClassInitFunc) filter_arg_class_init, (GtkObjectInitFunc) filter_arg_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL }; type = gtk_type_unique (gtk_object_get_type (), &type_info); } return type; } static FilterArg * clone_default(FilterArg *a) { xmlNodePtr values; FilterArg *new = FILTER_ARG ( gtk_type_new (((GtkObject *)a)->klass->type) ); /* clone values */ new->name = g_strdup(a->name); values = filter_arg_values_get_xml(a); filter_arg_values_add_xml(new, values); xmlFreeNodeList(values); return new; } static void write_html_nothing(FilterArg *arg, GtkHTML *html, GtkHTMLStreamHandle *stream) { /* empty */ } static void write_text_nothing(FilterArg *arg, GString *string) { /* empty */ } static void edit_values_nothing(FilterArg *arg) { /* empty */ } static void * edit_value_nothing(FilterArg *arg, void *v) { return v; } static void free_value_nothing(FilterArg *arg, void *v) { /* empty */ } static gint compare_pointers(gpointer a, gpointer b) { return a==b; } static void filter_arg_class_init (FilterArgClass *class) { GtkObjectClass *object_class; object_class = (GtkObjectClass *) class; parent_class = gtk_type_class (gtk_object_get_type ()); class->write_html = write_html_nothing; class->write_text = write_text_nothing; class->edit_values = edit_values_nothing; class->edit_value = edit_value_nothing; class->free_value = free_value_nothing; class->clone = clone_default; signals[CHANGED] = gtk_signal_new ("changed", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (FilterArgClass, changed), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); } static void filter_arg_init (FilterArg *arg) { arg->values = NULL; arg->priv = g_malloc0(sizeof(*arg->priv)); } /** * filter_arg_new: * * Create a new FilterArg widget. * * Return value: A new FilterArg widget. **/ FilterArg * filter_arg_new (char *name) { FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_get_type ())); if (name) a->name = g_strdup(name); return a; } FilterArg * filter_arg_clone (FilterArg *arg) { return ((FilterArgClass *)(arg->object.klass))->clone(arg); } void filter_arg_copy(FilterArg *dst, FilterArg *src) { xmlNodePtr values; g_return_if_fail( ((GtkObject *)src)->klass->type == ((GtkObject *)dst)->klass->type ); /* remove old values */ while (dst->values) { filter_arg_remove(dst, dst->values->data); } /* clone values */ values = filter_arg_values_get_xml(src); filter_arg_values_add_xml(dst, values); xmlFreeNodeList(values); } void filter_arg_add(FilterArg *arg, void *v) { g_return_if_fail(v != NULL); arg->values = g_list_append(arg->values, v); gtk_signal_emit(GTK_OBJECT(arg), signals[CHANGED]); } void filter_arg_remove(FilterArg *arg, void *v) { arg->values = g_list_remove(arg->values, v); ((FilterArgClass *)(arg->object.klass))->free_value(arg, v); gtk_signal_emit(GTK_OBJECT(arg), signals[CHANGED]); } void filter_arg_write_html(FilterArg *arg, GtkHTML *html, GtkHTMLStreamHandle *stream) { ((FilterArgClass *)(arg->object.klass))->write_html(arg, html, stream); } void filter_arg_write_text(FilterArg *arg, GString *string) { int count, i; count = filter_arg_get_count(arg); for (i=0;i1) { g_string_append(string, "or "); } } #if 0 ((FilterArgClass *)(arg->object.klass))->write_text(arg, string); #endif } void filter_arg_edit_values(FilterArg *arg) { void filter_arg_edit_values_1(FilterArg *arg); g_return_if_fail(arg != NULL); #if 1 filter_arg_edit_values_1(arg); #else if (((FilterArgClass *)(arg->object.klass))->edit_values) ((FilterArgClass *)(arg->object.klass))->edit_values(arg); else g_warning("No implementation of virtual method edit_values"); #endif } int filter_arg_edit_value(FilterArg *arg, int index) { return ((FilterArgClass *)(arg->object.klass))->edit_value(arg, index); } xmlNodePtr filter_arg_values_get_xml(FilterArg *arg) { return ((FilterArgClass *)(arg->object.klass))->values_get_xml(arg); } void filter_arg_values_add_xml(FilterArg *arg, xmlNodePtr node) { ((FilterArgClass *)(arg->object.klass))->values_add_xml(arg, node); } /* returns the number of args in the arg list */ int filter_arg_get_count(FilterArg *arg) { int count=0; GList *l; for (l = arg->values;l;l=g_list_next(l)) count++; return count; } void * filter_arg_get_value(FilterArg *arg, int index) { int count=0; GList *l; for (l = arg->values;l && countdata; return NULL; } char * filter_arg_get_value_as_string(FilterArg *arg, int index) { int count=0; GList *l; void *data; data = filter_arg_get_value(arg, index); if (data) { return ((FilterArgClass *)(arg->object.klass))->get_value_as_string(arg, data); } else { return ""; } } struct filter_arg_edit { FilterArg *arg; GtkList *list; GList *items; GnomeDialog *dialogue; GtkWidget *add, *remove, *edit; GtkWidget *item_current; }; static void filter_arg_edit_add(GtkWidget *w, struct filter_arg_edit *edata) { GtkListItem *listitem; GList *items = NULL; int i; printf("adding new item\n"); printf("editing ...\n"); i = filter_arg_edit_value(edata->arg, -1); if (i>=0) { gtk_list_remove_items_no_unref(edata->list, edata->items); listitem = (GtkListItem *)gtk_list_item_new_with_label(filter_arg_get_value_as_string(edata->arg, i)); gtk_object_set_data((GtkObject *)listitem, "arg_i", filter_arg_get_value(edata->arg, i)); edata->items = g_list_append(edata->items, listitem); gtk_widget_show((GtkWidget *)listitem); /* this api is nonsense */ gtk_list_append_items(edata->list, g_list_copy(edata->items)); } } void dump_list(GList *list) { printf("dumping list:\n"); for (;list;list = g_list_next(list)) { printf(" %p %p\n", list, list->data); } } static void fill_list(struct filter_arg_edit *edata) { GList *items = NULL; int i, count; GtkListItem *listitem; gtk_list_remove_items(edata->list, edata->items); g_list_free(edata->items); count = filter_arg_get_count(edata->arg); for (i=0;iarg, i); listitem = (GtkListItem *)gtk_list_item_new_with_label(labeltext); gtk_object_set_data((GtkObject *)listitem, "arg_i", filter_arg_get_value(edata->arg, i)); items = g_list_append(items, listitem); gtk_widget_show(GTK_WIDGET(listitem)); printf("adding item %d\n", i); } printf("items re-added\n"); edata->item_current = NULL; edata->items = items; gtk_list_append_items(edata->list, g_list_copy(edata->items)); } static void filter_arg_edit_edit(GtkWidget *w, struct filter_arg_edit *edata) { char *name; int i; /* yurck */ if (edata->item_current && (name = gtk_object_get_data((GtkObject *)edata->item_current, "arg_i")) && (i = g_list_index(edata->arg->values, name)) >= 0 && (i = filter_arg_edit_value(edata->arg, i)) >= 0) { fill_list(edata); } } static void filter_arg_edit_delete(GtkWidget *w, struct filter_arg_edit *edata) { GtkListItem *listitem; char *name; /* yurck */ if (edata->item_current && (name = gtk_object_get_data((GtkObject *)edata->item_current, "arg_i"))) { filter_arg_remove(edata->arg, name); fill_list(edata); } } static void edit_sensitise(struct filter_arg_edit *edata) { int state = edata->item_current != NULL; gtk_widget_set_sensitive(edata->remove, state); gtk_widget_set_sensitive(edata->edit, state); } static void filter_arg_edit_select(GtkWidget *w, GtkListItem *list, struct filter_arg_edit *edata) { edata->item_current = list; edit_sensitise(edata); printf ("node = %p\n", g_list_find(edata->items, edata->item_current)); } static void filter_arg_edit_unselect(GtkWidget *w, GtkListItem *list, struct filter_arg_edit *edata) { edata->item_current = NULL; edit_sensitise(edata); } static void filter_arg_edit_clicked(GnomeDialog *d, int button, struct filter_arg_edit *edata) { struct _FilterArgPrivate *p = _PRIVATE(edata->arg); printf("window finished\n"); if (button==0) { gtk_signal_emit(GTK_OBJECT(edata->arg), signals[CHANGED]); } else { /* cancel button, restore old values ... */ printf("cancel button\n"); while (edata->arg->values) { filter_arg_remove(edata->arg, edata->arg->values->data); } filter_arg_values_add_xml(edata->arg, p->oldargs); } xmlFreeNodeList(p->oldargs); p->oldargs = NULL; g_free(edata); p->dialogue = NULL; gnome_dialog_close(d); } static void filter_arg_edit_destroy(GnomeDialog *d, struct filter_arg_edit *edata) { struct _FilterArgPrivate *p = _PRIVATE(edata->arg); if (p->oldargs) { while (edata->arg->values) { filter_arg_remove(edata->arg, edata->arg->values->data); } filter_arg_values_add_xml(edata->arg, p->oldargs); xmlFreeNodeList(p->oldargs); p->oldargs = NULL; } if (p->dialogue) { p->dialogue = NULL; gnome_dialog_close(d); } g_free(edata); } void filter_arg_edit_values_1(FilterArg *arg) { GList *vales; GtkList *list; GtkListItem *listitem; int count, i; GnomeDialog *dialogue; GtkHBox *hbox; GtkVBox *vbox; GtkWidget *button; GtkWidget *scrolled_window, *frame; struct filter_arg_edit * edata; struct _FilterArgPrivate *p = _PRIVATE(arg); /* dont show more than 1 editor for each type */ if (p->dialogue) { gdk_window_raise(GTK_WIDGET(p->dialogue)->window); return; } /* copy the current state */ p->oldargs= filter_arg_values_get_xml(arg); edata = g_malloc0(sizeof(*edata)); edata->item_current = NULL; edata->arg = arg; dialogue = (GnomeDialog *)gnome_dialog_new("Edit values", "Ok", "Cancel", 0); edata->dialogue = dialogue; p->dialogue = dialogue; hbox = (GtkHBox *)gtk_hbox_new(FALSE, 0); list = (GtkList *)gtk_list_new(); edata->list = list; edata->items = NULL; fill_list(edata); scrolled_window = gtk_scrolled_window_new(NULL, NULL); frame = gtk_frame_new("Option values"); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), (GtkWidget *)list); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_set_focus_vadjustment(GTK_CONTAINER (list), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window))); gtk_container_add(GTK_CONTAINER(frame), scrolled_window); gtk_widget_set_usize(frame, 200, 300); gtk_box_pack_start((GtkBox *)hbox, frame, TRUE, TRUE, 0); /* buttons */ vbox = (GtkVBox *)gtk_vbox_new(FALSE, 0); button = gtk_button_new_with_label ("Add"); gtk_box_pack_start((GtkBox *)vbox, button, FALSE, TRUE, 0); edata->add = button; button = gtk_button_new_with_label ("Remove"); gtk_box_pack_start((GtkBox *)vbox, button, FALSE, TRUE, 0); edata->remove = button; button = gtk_button_new_with_label ("Edit"); gtk_box_pack_start((GtkBox *)vbox, button, FALSE, TRUE, 0); edata->edit = button; gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)vbox, FALSE, FALSE, 0); gtk_signal_connect((GtkObject *)edata->add, "clicked", filter_arg_edit_add, edata); gtk_signal_connect((GtkObject *)edata->edit, "clicked", filter_arg_edit_edit, edata); gtk_signal_connect((GtkObject *)edata->remove, "clicked", filter_arg_edit_delete, edata); gtk_signal_connect((GtkObject *)edata->list, "select_child", filter_arg_edit_select, edata); gtk_signal_connect((GtkObject *)edata->list, "unselect_child", filter_arg_edit_unselect, edata); gtk_widget_show(GTK_WIDGET(list)); gtk_widget_show_all(GTK_WIDGET(hbox)); gtk_box_pack_start((GtkBox *)dialogue->vbox, (GtkWidget *)hbox, TRUE, TRUE, 0); gtk_signal_connect((GtkObject *)dialogue, "clicked", filter_arg_edit_clicked, edata); gtk_signal_connect((GtkObject *)dialogue, "destroy", filter_arg_edit_destroy, edata); edit_sensitise(edata); gtk_widget_show(dialogue); }