Re: "Bottlenecking" connections



On Sat, 2001-08-25 at 13:32, Thomas Mailund wrote:

> A (potential) problem with that solution is the tight copling between
> dispatcher and operations. Sometimes you need the dispatcher to know
> about the operations so it can chose which operations to call,
> othertimes you just want it to broadcast an event to whoever is
> listening.  The later solution you can achive by letting the
> dispatcher signal rather than call functions, and then let the
> operations listen for that signal.(*)

Though now that I think about it, actually coding this is a bit
cumbersome...


> 	/mailund
> 
> (*) I can hack up an example of that if it is unclear what I am trying
> to explain here.
> 

and so I have.  (The attached code).

Setting up a signal to work as I suggested required writing a new class,
which requires a lot more code than its worth for such a small
example...and that can't be right.

Now, I have been away from gtk+ for quite some time, so there could
easilly be a lot better way of doing what I did here that I am just not
aware of, if this is the case I'd love to hear about it.

	/mailund

-- 
Give a monkey a brain and he'll swear he's the center of the universe.
#include <gtk/gtk.h>


/* --- DEFINING NEW CLASS ------------------------------------------ */

#define TYPE_DISPATCHER (dispatcher_get_type ())
#define DISPATCHER(obj) (GTK_CHECK_CAST (obj, dispatcher_get_type (), Dispatcher))
#define DISPATCHER_CLASS(klass) (GTK_CHECK_CLASS_CAST (klass, dispatcher_get_type (), DispatcherClass))
#define IS_DISPATCHER(obj) (GTK_CHECK_TYPE (obj, dispatcher_get_type ()))
#define IS_DISPATCHER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), TYPE_DISPATCHER))

typedef struct _Dispatcher        Dispatcher;
typedef struct _DispatcherClass   DispatcherClass;

struct _Dispatcher {
  GtkObject object;
};

struct _DispatcherClass {
  GtkObjectClass object_class;
};

guint          dispatcher_get_type           (void);


/* object stuff */
static void   dispatcher_class_init          (DispatcherClass    *klass);
static void   dispatcher_init                (Dispatcher         *dispatcher);
static void   dispatcher_destroy             (GtkObject          *object);

static GtkObjectClass *parent_class = NULL;

guint
dispatcher_get_type ()
{
  static guint dispatcher_type = 0;

  if (!dispatcher_type)
    {
      GtkTypeInfo dispatcher_info =
      {
	"Dispatcher",
	sizeof (Dispatcher),
	sizeof (DispatcherClass),
	(GtkClassInitFunc) dispatcher_class_init,
	(GtkObjectInitFunc) dispatcher_init,
	(GtkArgSetFunc) NULL,
        (GtkArgGetFunc) NULL,
        (GtkClassInitFunc) NULL,
      };

      dispatcher_type =
	gtk_type_unique (gtk_object_get_type (), &dispatcher_info);
    }

  return dispatcher_type;
}

enum {
  TICKLED_1,
  TICKLED_2,
  TICKLED_3,
  LAST_SIGNAL
};
static guint dispatcher_signals[LAST_SIGNAL] = { 0 };


static void
dispatcher_class_init (DispatcherClass *class)
{
  GtkObjectClass *object_class;

  object_class = (GtkObjectClass*) class;

  /* init local data */
  parent_class = gtk_type_class (gtk_object_get_type ());

  object_class->destroy = dispatcher_destroy;

  /* set up signals */
  dispatcher_signals[TICKLED_1] =
    gtk_signal_new ("tickled_1",
		    GTK_RUN_FIRST,
		    object_class->type,
		    0,		/* offset.  We don't have a class
                                   signal handler */
		    gtk_marshal_NONE__NONE,
		    GTK_TYPE_NONE, 0);
  dispatcher_signals[TICKLED_2] =
    gtk_signal_new ("tickled_2",
		    GTK_RUN_FIRST,
		    object_class->type,
		    0,		/* offset.  We don't have a class
                                   signal handler */
		    gtk_marshal_NONE__NONE,
		    GTK_TYPE_NONE, 0);
  dispatcher_signals[TICKLED_3] =
    gtk_signal_new ("tickled_3",
		    GTK_RUN_FIRST,
		    object_class->type,
		    0,		/* offset.  We don't have a class
                                   signal handler */
		    gtk_marshal_NONE__NONE,
		    GTK_TYPE_NONE, 0);



  gtk_object_class_add_signals (object_class, dispatcher_signals, LAST_SIGNAL);
}

static void
dispatcher_init (Dispatcher *dispatcher)
{
  return;
}

static void
dispatcher_destroy (GtkObject *object)
{
  g_return_if_fail (object != NULL);
  g_return_if_fail (IS_DISPATCHER (object));

  GTK_OBJECT_CLASS(parent_class)->destroy (object);
}


/* --- THE APPLICATION CODE ---------------------------------------- */

static void
op_1_1 (void)
{
  g_print ("op 1 1\n");
}

static void
op_1_2 (void)
{
  g_print ("op 1 2\n");
}

static void
op_2 (void)
{
  g_print ("op 2\n");
}

static void
op_3 (void)
{
  g_print ("op 3\n");
}


static gboolean blocked = FALSE;
static Dispatcher *dispatcher;
static void
dispatch(GtkWidget *dummy, int op_id)
{
  if (!blocked)
    {
      switch (op_id)
	{
	case 1:
	  gtk_signal_emit (GTK_OBJECT (dispatcher),
			   dispatcher_signals[TICKLED_1]);
	  break;
	case 2:
	  gtk_signal_emit (GTK_OBJECT (dispatcher),
			   dispatcher_signals[TICKLED_2]);
	  break;
	case 3:
	  gtk_signal_emit (GTK_OBJECT (dispatcher),
			   dispatcher_signals[TICKLED_3]);
	  break;
	}
    }
}

static void
toggle_block(void)
{
  blocked = ! blocked;
}

int
main(int argc, char *argv[])
{
  GtkWidget *win;
  GtkWidget *vbox;
  GtkWidget *button;

  gtk_init (&argc, &argv);

  win = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  vbox = gtk_vbox_new (TRUE, 0);
  gtk_container_add (GTK_CONTAINER (win), vbox);

  button = gtk_button_new_with_label ("op 1");
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (dispatch),
		      GINT_TO_POINTER (1));

  button = gtk_button_new_with_label ("op 2");
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (dispatch),
		      GINT_TO_POINTER (2));

  button = gtk_button_new_with_label ("op 3");
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (dispatch),
		      GINT_TO_POINTER (3));

  button = gtk_button_new_with_label ("toggle block");
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (toggle_block),
		      NULL);


  /* setup dispatcher */
  dispatcher = DISPATCHER (gtk_object_new (TYPE_DISPATCHER, NULL));

  /* and connect signals */
  gtk_signal_connect (GTK_OBJECT (dispatcher), "tickled_1",
		      GTK_SIGNAL_FUNC (op_1_1), NULL);
  gtk_signal_connect (GTK_OBJECT (dispatcher), "tickled_1",
		      GTK_SIGNAL_FUNC (op_1_2), NULL);
  gtk_signal_connect (GTK_OBJECT (dispatcher), "tickled_2",
		      GTK_SIGNAL_FUNC (op_2), NULL);
  gtk_signal_connect (GTK_OBJECT (dispatcher), "tickled_3",
		      GTK_SIGNAL_FUNC (op_3), NULL);


  gtk_widget_show_all (win);

  gtk_main ();

  return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]