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

Re: Emitting a keypress event



Havoc Pennington wrote:

> Kent Schumacher <kent@structural-wood.com> writes:
> > OK, this is good.  Any thoughts on how to have different types of activate?
> >
> > My widgets minimally need to be able to bring up an assistant and force an update
> > to dependent widgets.  Both of these actions need to be invokable via menu-item,
> > toolbar-button, and keypress.
> >
>
> You'll need to implement this yourself, GTK doesn't support it. There
> are several ways you could do it. The focus widget is stored in
> GtkWindow::focus_widget, I don't know that that field is public, but
> it probably won't kill anyone if you use it.
>
> Once you have the focus widget, you can either switch on its type
> (easiest, I think)

A typical instance of my application has several hundred focusable
widgets. There are dozens of types of focusable widgets and they
are used in several different contexts.  Each focusable widget needs
to respond to at least two seperate types of activations, and I expect
to be adding more as the application is used in a production setting.
This (the switch) doesn't scale up very well.

> or you could add a "user signal"
> (gtk_object_class_user_signal_new()) to each object, and emit that
> signal by name in order to activate the widget.
>
> For example you could add a user signal to GtkButtonClass,
> GtkMenuItemClass, etc. called "show_assistant" and then you would
> connect to show_assistant on each instance of these object types and
> show the assistant in your signal handler.
>
> User signals are sort of a cheapo subclassing-on-the-fly technique,
> you could also do a full-blown subclass of these widgets that adds
> your functionality.
>
> Havoc

OK, this is a very good idea, and one that I will probably use frequently.
HOWEVER (grin)...

I think the idea of having an emittable signal that allows the emitter to
pass data to the signal handler is a generally good thing.  In the specific
instance of my application it allows me to collapse multiple handlers into
a single handler, eliminating a lot of code (and therefore sources of bugs).
The patch is simple, and does not break gtk 1.2 binary compatability (thanks
to someone's forethought in adding signal padding in gtkwidget.h).

Here's the patch - if there is such a thing, I am *officially* requesting that this
patch be applied to the gtk source tree.  The patch is against gtk 1.2.7.  Sorry
if the patch isn't correct - it's my first time...

*** gtkwidget.h   Mon Feb 28 15:14:34 2000
--- gtkwidget.h   Tue Feb 29 07:45:35 2000
***************
*** 389,396 ****
    void (* debug_msg)        (GtkWidget         *widget,
                const gchar          *string);

    /* Padding for future expandsion */
-   GtkFunction pad1;
    GtkFunction pad2;
    GtkFunction pad3;
    GtkFunction pad4;
--- 389,398 ----
    void (* debug_msg)        (GtkWidget         *widget,
                const gchar          *string);

+   void (* user_action)          (GtkWidget      *widget,
+                gpointer       *emit_data);
+
    /* Padding for future expandsion */
    GtkFunction pad2;
    GtkFunction pad3;
    GtkFunction pad4;
***************
*** 635,640 ****
--- 637,645 ----
                   guint     *path_length,
                   gchar    **path,
                   gchar    **path_reversed);
+
+ void        gtk_widget_user_action      (GtkWidget *widget,
+                  gpointer act_data);

  #if defined (GTK_TRACE_OBJECTS) && defined (__GNUC__)
  #  define gtk_widget_ref gtk_object_ref
*** gtkwidget.c.original   Mon Feb 28 15:14:30 2000
--- gtkwidget.c   Mon Feb 28 15:17:50 2000
***************
*** 97,102 ****
--- 97,103 ----
    NO_EXPOSE_EVENT,
    VISIBILITY_NOTIFY_EVENT,
    DEBUG_MSG,
+   USER_ACTION,
    LAST_SIGNAL
  };

***************
*** 717,722 ****
--- 718,732 ----
          GTK_TYPE_NONE, 1,
          GTK_TYPE_STRING);

+   widget_signals[USER_ACTION] =
+     gtk_signal_new ("user_action",
+         GTK_RUN_LAST | GTK_RUN_ACTION,
+         object_class->type,
+         GTK_SIGNAL_OFFSET (GtkWidgetClass, user_action),
+         gtk_marshal_NONE__POINTER,
+         GTK_TYPE_NONE, 1,
+         GTK_TYPE_POINTER);
+
    gtk_object_class_add_signals (object_class, widget_signals, LAST_SIGNAL);

    object_class->set_arg = gtk_widget_set_arg;
***************
*** 779,784 ****
--- 789,796 ----
    klass->no_expose_event = NULL;

    klass->debug_msg = gtk_widget_debug_msg;
+
+   klass->user_action = NULL;
  }

  static void
***************
*** 4980,4982 ****
--- 4992,5004 ----
        g_strreverse (*path_p);
      }
  }
+
+ void
+ gtk_widget_user_action (GtkWidget *widget, gpointer act_data)
+ {
+   g_return_if_fail (widget != NULL);
+   g_return_if_fail (GTK_IS_WIDGET (widget));
+
+   gtk_signal_emit (GTK_OBJECT (widget), widget_signals[USER_ACTION], act_data);
+ }
+




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