diff options
-rw-r--r-- | widgets/misc/ChangeLog | 33 | ||||
-rw-r--r-- | widgets/misc/Makefile.am | 2 | ||||
-rw-r--r-- | widgets/misc/e-config-page.c | 154 | ||||
-rw-r--r-- | widgets/misc/e-config-page.h | 76 | ||||
-rw-r--r-- | widgets/misc/e-multi-config-dialog.c | 163 | ||||
-rw-r--r-- | widgets/misc/e-multi-config-dialog.h | 8 | ||||
-rw-r--r-- | widgets/misc/test-multi-config-dialog.c | 8 |
7 files changed, 427 insertions, 17 deletions
diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog index e2d05939f4..e19d91fed5 100644 --- a/widgets/misc/ChangeLog +++ b/widgets/misc/ChangeLog @@ -1,3 +1,36 @@ +2002-03-09 Ettore Perazzoli <ettore@ximian.com> + + * e-multi-config-dialog.c: Rename Page.widget -> Page.page_widget; + it is now an EConfigPage instead of just a GtkWidget. Add + `num_unapplied' to EMultiConfigDialogPrivate. Derive from + GnomeDialog, not GtkWindow. + (update_buttons): New function to update the sensitiveness of the + buttons according to whether all the settings have been applied or + not. + (page_new): Likewise. + (create_page_container): Renamed from `create_page_widget'. + (init): Add Apply/OK/Cancel buttons to the dialog. Init + ->num_unapplied to zero. + (page_changed_callback): New, callback for the page's "changed" + signal. + (e_multi_config_dialog_add_page): Connect the callback, update + ->num_unapplied, update the buttons by calling `update_buttons'. + (ok): New function for handling the OK button. + (apply): New function for handling the Apply button. + (cancel): New function for handling the Cancel button. + (impl_clicked): Implementation for the GnomeDialog's ::clicked + signal. + (class_init): Install. + + * test-multi-config-dialog.c (add_pages): Update to use + EConfigPages instead of plain GtkWidgets. + + * e-multi-config-dialog.c, e-multi-config-dialog.h: Derive from + GnomeDialog, not GtkWindow. + + * e-config-page.c: New. + * e-config-page.h: New. + 2002-03-07 Ettore Perazzoli <ettore@ximian.com> * e-multi-config-dialog.c: Don't display a header in the table on diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index 5d0a474138..0b274552ff 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -27,6 +27,8 @@ libemiscwidgets_a_SOURCES = \ e-charset-picker.h \ e-clipped-label.c \ e-clipped-label.h \ + e-config-page.c \ + e-config-page.h \ e-combo-button.c \ e-combo-button.h \ e-dateedit.c \ diff --git a/widgets/misc/e-config-page.c b/widgets/misc/e-config-page.c new file mode 100644 index 0000000000..7006dc7a11 --- /dev/null +++ b/widgets/misc/e-config-page.c @@ -0,0 +1,154 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-config-page.c + * + * Copyright (C) 2002 Ximian, Inc. + * + * This program 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 program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli <ettore@ximian.com> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "e-config-page.h" + +#include <gal/util/e-util.h> + + +enum { + APPLY, + CHANGED, + LAST_SIGNAL +}; + +#define PARENT_TYPE gtk_event_box_get_type () +static GtkEventBoxClass *parent_class = NULL; +static unsigned int signals[LAST_SIGNAL] = { 0 }; + +struct _EConfigPagePrivate { + gboolean changed; +}; + + +/* GtkObject methods. */ + +static void +impl_destroy (GtkObject *object) +{ + EConfigPage *page; + EConfigPagePrivate *priv; + + page = E_CONFIG_PAGE (object); + priv = page->priv; + + g_free (priv); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +static void +class_init (EConfigPageClass *class) +{ + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (class); + object_class->destroy = impl_destroy; + + parent_class = gtk_type_class (PARENT_TYPE); + + signals[APPLY] = gtk_signal_new ("apply", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EConfigPageClass, apply), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + signals[CHANGED] = gtk_signal_new ("changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EConfigPageClass, changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +init (EConfigPage *config_page) +{ + EConfigPagePrivate *priv; + + priv = g_new (EConfigPagePrivate, 1); + priv->changed = FALSE; + + config_page->priv = priv; +} + + +GtkWidget * +e_config_page_new (void) +{ + GtkWidget *new; + + new = gtk_type_new (e_config_page_get_type ()); + + return new; +} + + +void +e_config_page_apply (EConfigPage *config_page) +{ + EConfigPagePrivate *priv; + + g_return_if_fail (E_IS_CONFIG_PAGE (config_page)); + + priv = config_page->priv; + + gtk_signal_emit (GTK_OBJECT (config_page), signals[APPLY]); + + priv->changed = FALSE; +} + +gboolean +e_config_page_is_applied (EConfigPage *config_page) +{ + g_return_val_if_fail (E_IS_CONFIG_PAGE (config_page), FALSE); + + return ! config_page->priv->changed; +} + +void +e_config_page_changed (EConfigPage *config_page) +{ + EConfigPagePrivate *priv; + + g_return_if_fail (E_IS_CONFIG_PAGE (config_page)); + + priv = config_page->priv; + + if (priv->changed) + return; + + priv->changed = TRUE; + gtk_signal_emit (GTK_OBJECT (config_page), signals[CHANGED]); +} + + +E_MAKE_TYPE (e_config_page, "EConfigPage", EConfigPage, class_init, init, PARENT_TYPE) diff --git a/widgets/misc/e-config-page.h b/widgets/misc/e-config-page.h new file mode 100644 index 0000000000..3cbbc482cc --- /dev/null +++ b/widgets/misc/e-config-page.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-config-page.h + * + * Copyright (C) 2002 Ximian, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli <ettore@ximian.com> + */ + +#ifndef _E_CONFIG_PAGE_H_ +#define _E_CONFIG_PAGE_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnome.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_CONFIG_PAGE (e_config_page_get_type ()) +#define E_CONFIG_PAGE(obj) (GTK_CHECK_CAST ((obj), E_TYPE_CONFIG_PAGE, EConfigPage)) +#define E_CONFIG_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_CONFIG_PAGE, EConfigPageClass)) +#define E_IS_CONFIG_PAGE(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_CONFIG_PAGE)) +#define E_IS_CONFIG_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_CONFIG_PAGE)) + + +typedef struct _EConfigPage EConfigPage; +typedef struct _EConfigPagePrivate EConfigPagePrivate; +typedef struct _EConfigPageClass EConfigPageClass; + +struct _EConfigPage { + GtkEventBox parent; + + EConfigPagePrivate *priv; +}; + +struct _EConfigPageClass { + GtkEventBoxClass parent_class; + + /* Signals. */ + void (* apply) (EConfigPage *config_page); + void (* changed) (EConfigPage *config_page); +}; + + +GtkType e_config_page_get_type (void); +GtkWidget *e_config_page_new (void); + +void e_config_page_apply (EConfigPage *config_page); +gboolean e_config_page_is_applied (EConfigPage *config_page); + +/* Protected. */ +void e_config_page_changed (EConfigPage *config_page); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_CONFIG_PAGE_H_ */ diff --git a/widgets/misc/e-multi-config-dialog.c b/widgets/misc/e-multi-config-dialog.c index ae9cf31c70..5100e1cf9f 100644 --- a/widgets/misc/e-multi-config-dialog.c +++ b/widgets/misc/e-multi-config-dialog.c @@ -34,15 +34,15 @@ #include <gdk-pixbuf/gdk-pixbuf.h> -#define PARENT_TYPE gtk_window_get_type () -static GtkWindowClass *parent_class = NULL; +#define PARENT_TYPE gnome_dialog_get_type () +static GnomeDialogClass *parent_class = NULL; struct _Page { char *title; char *description; GdkPixbuf *icon; - GtkWidget *widget; + EConfigPage *page_widget; }; typedef struct _Page Page; @@ -53,6 +53,8 @@ struct _EMultiConfigDialogPrivate { ETableModel *list_e_table_model; GtkWidget *notebook; + + int num_unapplied; }; @@ -78,13 +80,32 @@ static char *list_e_table_spec = "</ETableSpecification>"; +/* Button handling. */ + +static void +update_buttons (EMultiConfigDialog *dialog) +{ + EMultiConfigDialogPrivate *priv; + + priv = dialog->priv; + + if (priv->num_unapplied > 0) { + gnome_dialog_set_sensitive (GNOME_DIALOG (dialog), 0, TRUE); /* OK */ + gnome_dialog_set_sensitive (GNOME_DIALOG (dialog), 1, TRUE); /* Apply */ + } else { + gnome_dialog_set_sensitive (GNOME_DIALOG (dialog), 0, FALSE); /* OK */ + gnome_dialog_set_sensitive (GNOME_DIALOG (dialog), 1, FALSE); /* Apply */ + } +} + + /* Page handling. */ static Page * page_new (const char *title, const char *description, GdkPixbuf *icon, - GtkWidget *widget) + EConfigPage *page_widget) { Page *new; @@ -92,7 +113,7 @@ page_new (const char *title, new->title = g_strdup (title); new->description = g_strdup (description); new->icon = icon; - new->widget = widget; + new->page_widget = page_widget; if (icon != NULL) gdk_pixbuf_ref (icon); @@ -113,8 +134,8 @@ page_free (Page *page) } static GtkWidget * -create_page_widget (const char *description, - GtkWidget *widget) +create_page_container (const char *description, + GtkWidget *widget) { GtkWidget *vbox; GtkWidget *label; @@ -140,6 +161,62 @@ create_page_widget (const char *description, return vbox; } +/* Page callbacks. */ + +static void +page_changed_callback (EConfigPage *page, + void *data) +{ + EMultiConfigDialog *dialog; + EMultiConfigDialogPrivate *priv; + + dialog = E_MULTI_CONFIG_DIALOG (data); + priv = dialog->priv; + + priv->num_unapplied ++; + + update_buttons (dialog); +} + + +/* Button handling. */ + +static void +cancel (EMultiConfigDialog *dialog) +{ + gnome_dialog_close (GNOME_DIALOG (dialog)); +} + +static void +apply (EMultiConfigDialog *dialog) +{ + EMultiConfigDialogPrivate *priv; + GSList *p; + + priv = dialog->priv; + + for (p = priv->pages; p != NULL; p = p->next) { + const Page *page; + + page = (const Page *) p->data; + + if (! e_config_page_is_applied (page->page_widget)) { + e_config_page_apply (page->page_widget); + priv->num_unapplied --; + } + } + + g_assert (priv->num_unapplied == 0); + update_buttons (dialog); +} + +static void +ok (EMultiConfigDialog *dialog) +{ + apply (dialog); + cancel (dialog); +} + /* ETable mess. */ @@ -265,11 +342,48 @@ impl_destroy (GtkObject *object) } +/* GnomeDialog methods. */ + +static void +impl_clicked (GnomeDialog *dialog, + int button_number) +{ + EMultiConfigDialog *multi_config_dialog; + EMultiConfigDialogPrivate *priv; + + multi_config_dialog = E_MULTI_CONFIG_DIALOG (dialog); + priv = multi_config_dialog->priv; + + switch (button_number) { + case 0: /* OK */ + ok (multi_config_dialog); + break; + case 1: /* Apply */ + apply (multi_config_dialog); + break; + case 2: /* Cancel */ + cancel (multi_config_dialog); + break; + default: + g_assert_not_reached (); + } +} + + +/* GTK+ ctors. */ + static void -class_init (GtkObjectClass *object_class) +class_init (EMultiConfigDialogClass *class) { + GnomeDialogClass *dialog_class; + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (class); object_class->destroy = impl_destroy; + dialog_class = GNOME_DIALOG_CLASS (class); + dialog_class->clicked = impl_clicked; + parent_class = gtk_type_class (PARENT_TYPE); } @@ -278,12 +392,14 @@ init (EMultiConfigDialog *multi_config_dialog) { EMultiConfigDialogPrivate *priv; ETableModel *list_e_table_model; + GtkWidget *gnome_dialog_vbox; GtkWidget *hbox; GtkWidget *notebook; GtkWidget *list_e_table; hbox = gtk_hbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (multi_config_dialog), hbox); + gnome_dialog_vbox = GNOME_DIALOG (multi_config_dialog)->vbox; + gtk_container_add (GTK_CONTAINER (gnome_dialog_vbox), hbox); list_e_table_model = e_table_memory_callbacks_new (table_model_column_count, table_model_value_at, @@ -314,11 +430,24 @@ init (EMultiConfigDialog *multi_config_dialog) gtk_widget_show (notebook); gtk_widget_show (list_e_table); + gnome_dialog_append_buttons (GNOME_DIALOG (multi_config_dialog), + GNOME_STOCK_BUTTON_OK, + GNOME_STOCK_BUTTON_APPLY, + GNOME_STOCK_BUTTON_CANCEL, + NULL); + gnome_dialog_set_default (GNOME_DIALOG (multi_config_dialog), 0); + + gtk_window_set_policy (GTK_WINDOW (multi_config_dialog), + FALSE /* allow_shrink */, + TRUE /* allow_grow */, + FALSE /* auto_shrink */); + priv = g_new (EMultiConfigDialogPrivate, 1); priv->pages = NULL; priv->list_e_table = list_e_table; priv->list_e_table_model = list_e_table_model; priv->notebook = notebook; + priv->num_unapplied = 0; multi_config_dialog->priv = priv; } @@ -340,7 +469,7 @@ e_multi_config_dialog_add_page (EMultiConfigDialog *dialog, const char *title, const char *description, GdkPixbuf *icon, - GtkWidget *widget) + EConfigPage *page_widget) { EMultiConfigDialogPrivate *priv; Page *new_page; @@ -348,11 +477,11 @@ e_multi_config_dialog_add_page (EMultiConfigDialog *dialog, g_return_if_fail (E_IS_MULTI_CONFIG_DIALOG (dialog)); g_return_if_fail (title != NULL); g_return_if_fail (description != NULL); - g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (E_IS_CONFIG_PAGE (page_widget)); priv = dialog->priv; - new_page = page_new (title, description, icon, widget); + new_page = page_new (title, description, icon, page_widget); priv->pages = g_slist_append (priv->pages, new_page); @@ -369,8 +498,16 @@ e_multi_config_dialog_add_page (EMultiConfigDialog *dialog, e_table_memory_insert (E_TABLE_MEMORY (priv->list_e_table_model), -1, new_page->title); gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), - create_page_widget (new_page->description, widget), + create_page_container (new_page->description, GTK_WIDGET (page_widget)), NULL); + + if (! e_config_page_is_applied (page_widget)) + priv->num_unapplied ++; + + gtk_signal_connect (GTK_OBJECT (page_widget), "changed", + GTK_SIGNAL_FUNC (page_changed_callback), dialog); + + update_buttons (dialog); } diff --git a/widgets/misc/e-multi-config-dialog.h b/widgets/misc/e-multi-config-dialog.h index dbcb17455a..a6ef12aad5 100644 --- a/widgets/misc/e-multi-config-dialog.h +++ b/widgets/misc/e-multi-config-dialog.h @@ -27,6 +27,8 @@ #include <config.h> #endif +#include "e-config-page.h" + #include <gtk/gtkwindow.h> #include <gdk-pixbuf/gdk-pixbuf.h> @@ -48,13 +50,13 @@ typedef struct _EMultiConfigDialogPrivate EMultiConfigDialogPrivate; typedef struct _EMultiConfigDialogClass EMultiConfigDialogClass; struct _EMultiConfigDialog { - GtkWindow parent; + GnomeDialog parent; EMultiConfigDialogPrivate *priv; }; struct _EMultiConfigDialogClass { - GtkWindowClass parent_class; + GnomeDialogClass parent_class; }; @@ -65,7 +67,7 @@ void e_multi_config_dialog_add_page (EMultiConfigDialog *dialog, const char *title, const char *description, GdkPixbuf *icon, - GtkWidget *widget); + EConfigPage *page); #ifdef __cplusplus } diff --git a/widgets/misc/test-multi-config-dialog.c b/widgets/misc/test-multi-config-dialog.c index 8882a627a3..94f830fdb4 100644 --- a/widgets/misc/test-multi-config-dialog.c +++ b/widgets/misc/test-multi-config-dialog.c @@ -36,6 +36,7 @@ add_pages (EMultiConfigDialog *multi_config_dialog) for (i = 0; i < NUM_PAGES; i ++) { GtkWidget *widget; + GtkWidget *page; char *string; char *title; char *description; @@ -45,8 +46,13 @@ add_pages (EMultiConfigDialog *multi_config_dialog) title = g_strdup_printf ("Title of page %d", i); widget = gtk_label_new (string); + gtk_widget_show (widget); - e_multi_config_dialog_add_page (multi_config_dialog, title, description, NULL, widget); + page = e_config_page_new (); + gtk_container_add (GTK_CONTAINER (page), widget); + + e_multi_config_dialog_add_page (multi_config_dialog, title, description, NULL, + E_CONFIG_PAGE (page)); g_free (string); g_free (title); |