aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--widgets/misc/ChangeLog33
-rw-r--r--widgets/misc/Makefile.am2
-rw-r--r--widgets/misc/e-config-page.c154
-rw-r--r--widgets/misc/e-config-page.h76
-rw-r--r--widgets/misc/e-multi-config-dialog.c163
-rw-r--r--widgets/misc/e-multi-config-dialog.h8
-rw-r--r--widgets/misc/test-multi-config-dialog.c8
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);