diff options
-rw-r--r-- | e-util/ChangeLog | 5 | ||||
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-component-listener.c | 227 | ||||
-rw-r--r-- | e-util/e-component-listener.h | 50 |
4 files changed, 284 insertions, 0 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 9dfc021ecb..bac53db150 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,8 @@ +2002-08-14 Rodrigo Moya <rodrigo@ximian.com> + + * e-component-listener.[ch]: new class for controlling a component, + to detect when it dies. + 2002-08-01 Dan Winship <danw@ximian.com> * e-html-utils.c (is_citation): Remove the logic that assumes diff --git a/e-util/Makefile.am b/e-util/Makefile.am index f7b4bb4d8c..f2283b3a0f 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -22,6 +22,7 @@ eutilinclude_HEADERS = \ e-bonobo-factory-util.h \ e-categories-master-list-wombat.h \ e-categories-config.h \ + e-component-listener.h \ e-corba-utils.h \ e-dialog-utils.h \ e-dialog-widgets.h \ @@ -49,6 +50,7 @@ libeutil_la_SOURCES = \ e-bonobo-factory-util.c \ e-categories-master-list-wombat.c \ e-categories-config.c \ + e-component-listener.c \ e-corba-utils.c \ e-dialog-utils.c \ e-dialog-widgets.c \ diff --git a/e-util/e-component-listener.c b/e-util/e-component-listener.c new file mode 100644 index 0000000000..d58f44e577 --- /dev/null +++ b/e-util/e-component-listener.c @@ -0,0 +1,227 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Component listener. + * + * Author: + * Rodrigo Moya <rodrigo@ximian.com> + * + * Copyright 2002, Ximian, Inc. + */ + +#include <gtk/gtksignal.h> +#include <bonobo/bonobo-exception.h> +#include <bonobo/bonobo-object.h> +#include <gal/util/e-util.h> +#include "e-component-listener.h" +#include <libgnome/gnome-i18n.h> + +#define PARENT_TYPE GTK_TYPE_OBJECT +#define DEFAULT_PING_DELAY 10000 + +struct _EComponentListenerPrivate { + Bonobo_Unknown component; + int ping_delay; + int ping_timeout_id; +}; + +static void e_component_listener_class_init (EComponentListenerClass *klass); +static void e_component_listener_init (EComponentListener *cl); +static void e_component_listener_destroy (GtkObject *object); + +static GtkObjectClass *parent_class = NULL; + +enum { + COMPONENT_DIED, + LAST_SIGNAL +}; + +static guint comp_listener_signals[LAST_SIGNAL]; + +static void +e_component_listener_class_init (EComponentListenerClass *klass) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); + + parent_class = gtk_type_class (PARENT_TYPE); + + object_class->destroy = e_component_listener_destroy; + klass->component_died = NULL; + + comp_listener_signals[COMPONENT_DIED] = + gtk_signal_new ("component_died", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EComponentListenerClass, component_died), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + gtk_object_class_add_signals (object_class, comp_listener_signals, LAST_SIGNAL); +} + +static void +e_component_listener_init (EComponentListener *cl) +{ + /* allocate internal structure */ + cl->priv = g_new (EComponentListenerPrivate, 1); + cl->priv->component = CORBA_OBJECT_NIL; + cl->priv->ping_delay = DEFAULT_PING_DELAY; + cl->priv->ping_timeout_id = -1; +} + +static void +e_component_listener_destroy (GtkObject *object) +{ + EComponentListener *cl = (EComponentListener *) object; + + g_return_if_fail (E_IS_COMPONENT_LISTENER (cl)); + + cl->priv->component = CORBA_OBJECT_NIL; + + if (cl->priv->ping_timeout_id != -1) { + g_source_remove (cl->priv->ping_timeout_id); + cl->priv->ping_timeout_id = -1; + } + + /* free memory */ + g_free (cl->priv); + cl->priv = NULL; + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +GtkType +e_component_listener_get_type (void) +{ + static GtkType type = 0; + + if (!type) { + static const GtkTypeInfo info = { + "EComponentListener", + sizeof (EComponentListener), + sizeof (EComponentListenerClass), + (GtkClassInitFunc) e_component_listener_class_init, + (GtkObjectInitFunc) e_component_listener_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (PARENT_TYPE, &info); + } + + return type; +} + +static gboolean +ping_component_callback (gpointer user_data) +{ + gboolean alive; + int is_nil; + CORBA_Environment ev; + EComponentListener *cl = (EComponentListener *) user_data; + + g_return_val_if_fail (E_IS_COMPONENT_LISTENER (cl), FALSE); + + if (cl->priv->component == CORBA_OBJECT_NIL) + return FALSE; + + CORBA_exception_init (&ev); + is_nil = CORBA_Object_is_nil (cl->priv->component, &ev); + if (BONOBO_EX (&ev)) { + g_message (_("ping_timeout_callback: could not determine if the " + "CORBA object is nil or not")); + goto out; + } + CORBA_exception_free (&ev); + + if (is_nil) + goto out; + + alive = bonobo_unknown_ping (cl->priv->component); + if (alive) + return TRUE; + + out: + /* the component has died, so we notify and close the timeout */ + gtk_signal_emit (GTK_OBJECT (cl), comp_listener_signals[COMPONENT_DIED]); + + cl->priv->component = CORBA_OBJECT_NIL; + cl->priv->ping_timeout_id = -1; + + return FALSE; +} + +static void +setup_ping_timeout (EComponentListener *cl) +{ + if (cl->priv->ping_timeout_id != -1) + g_source_remove (cl->priv->ping_timeout_id); + + cl->priv->ping_timeout_id = g_timeout_add (cl->priv->ping_delay, + ping_component_callback, + cl); +} + +/** + * e_component_listener_new + * @comp: Component to listen for. + * @ping_delay: Delay (in ms) for pinging the component. + * + * Create a new #EComponentListener object, which allows to listen + * for a given component and get notified when that component dies. + * + * Returns: a component listener object. + */ +EComponentListener * +e_component_listener_new (Bonobo_Unknown comp, int ping_delay) +{ + EComponentListener *cl; + + cl = gtk_type_new (E_COMPONENT_LISTENER_TYPE); + cl->priv->component = comp; + + /* set up the timeout function */ + cl->priv->ping_delay = ping_delay > 0 ? ping_delay : DEFAULT_PING_DELAY; + setup_ping_timeout (cl); + + return cl; +} + +/** + * e_component_listener_get_ping_delay + * @cl: A #EComponentListener object. + * + * Get the ping delay being used to listen for an object. + */ +int +e_component_listener_get_ping_delay (EComponentListener *cl) +{ + g_return_val_if_fail (E_IS_COMPONENT_LISTENER (cl), -1); + return cl->priv->ping_delay; +} + +void +e_component_listener_set_ping_delay (EComponentListener *cl, int ping_delay) +{ + g_return_if_fail (E_IS_COMPONENT_LISTENER (cl)); + g_return_if_fail (ping_delay > 0); + + cl->priv->ping_delay = ping_delay; + setup_ping_timeout (cl); +} + +Bonobo_Unknown +e_component_listener_get_component (EComponentListener *cl) +{ + g_return_val_if_fail (E_IS_COMPONENT_LISTENER (cl), CORBA_OBJECT_NIL); + return cl->priv->component; +} + +void +e_component_listener_set_component (EComponentListener *cl, Bonobo_Unknown comp) +{ + g_return_if_fail (E_IS_COMPONENT_LISTENER (cl)); + + cl->priv->component = comp; + setup_ping_timeout (cl); +} diff --git a/e-util/e-component-listener.h b/e-util/e-component-listener.h new file mode 100644 index 0000000000..8194476cf2 --- /dev/null +++ b/e-util/e-component-listener.h @@ -0,0 +1,50 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Component listener + * + * Author: + * Rodrigo Moya <rodrigo@ximian.com> + * + * Copyright 2002, Ximian, Inc. + */ + +#ifndef __E_COMPONENT_LISTENER_H__ +#define __E_COMPONENT_LISTENER_H__ + +#include <bonobo/Bonobo.h> +#include <gtk/gtkobject.h> +#include <libgnome/gnome-defs.h> + +BEGIN_GNOME_DECLS + +#define E_COMPONENT_LISTENER_TYPE (e_component_listener_get_type ()) +#define E_COMPONENT_LISTENER(o) (GTK_CHECK_CAST ((o), E_COMPONENT_LISTENER_TYPE, EComponentListener)) +#define E_COMPONENT_LISTENER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_COMPONENT_LISTENER_TYPE, EComponentListenerClass)) +#define E_IS_COMPONENT_LISTENER(o) (GTK_CHECK_TYPE ((o), E_COMPONENT_LISTENER_TYPE)) +#define E_IS_COMPONENT_LISTENER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_COMPONENT_LISTENER_TYPE)) + +typedef struct _EComponentListenerPrivate EComponentListenerPrivate; + +typedef struct { + GtkObject object; + EComponentListenerPrivate *priv; +} EComponentListener; + +typedef struct { + GtkObjectClass parent_class; + + void (* component_died) (EComponentListener *cl); +} EComponentListenerClass; + +GtkType e_component_listener_get_type (void); +EComponentListener *e_component_listener_new (Bonobo_Unknown comp, int ping_delay); + +int e_component_listener_get_ping_delay (EComponentListener *cl); +void e_component_listener_set_ping_delay (EComponentListener *cl, int ping_delay); +Bonobo_Unknown e_component_listener_get_component (EComponentListener *cl); +void e_component_listener_set_component (EComponentListener *cl, + Bonobo_Unknown comp); + +END_GNOME_DECLS + +#endif |