Re: GtkWidgets validation



This works perfectly now:

I have been hacking a bit more and now IMHO, the validation of widgets is
solved.

You can see it again at:


    http://gtkwidgexts.sourceforge.net/validation/index.html


Santiago Capel escribió:

> Hello all again:
>
> Here is an explanation of the code to implement validation of gtk
> widgets.
> This is just a little sample, but it works fine. It needs only a bit
> more of hacking and a bit of testing, but I think that this is a correct
> way (and low-cost) of getting to the validation of widgets.
>
> The main changes are in the gtkwidget module.
>
> I need to create two new flags lor the widgets. lets say
> GTK_IGNOREACTIVATE and GTK_CAUSESVALIDATION
>
> ** gtkwidget.h **
>
> typedef enum
> {
>   GTK_TOPLEVEL         = 1 << 4,
>     ...
>   GTK_RECEIVES_DEFAULT = 1 << 20
> #ifdef VALIDATE
>   , GTK_IGNOREACTIVATE = 1 << 21
>   , GTK_CAUSESVALIDATION = 1 << 22
> #endif
> } GtkWidgetFlags;
>
> // The flag GTK_CAUSESVALIDATION, when is set by the programmer on a
> widget that get the focus, causes the validate event of the widget that
> has just lost the focus to be emitted.
> // The flag GTK_IGNOREACTIVATE is set and unset internally by gtk. It is
> needed to avoid the emission of the activate event of a control in the
> middle of the validate event of another.
>
> ** gtkwidget.c **
>
> enum {
>   SHOW,
>   HIDE,
>     ...
>   VISIBILITY_NOTIFY_EVENT,
>   DEBUG_MSG,
> #ifdef VALIDATE
>   VALIDATE_EVENT,
> #endif
>   LAST_SIGNAL
> };
>
> // Added a new event to all the widgets. The validate event, which will
> be called when the widget loses the focus and the
> widget that gets the focus has the CAUSESVALIDATION flag set.
>
> static void
> gtk_widget_class_init (GtkWidgetClass *klass)
> {
>   GtkObjectClass *object_class;
>
>     .....
> #ifdef VALIDATE
>   widget_signals[VALIDATE_EVENT] =
>     gtk_signal_new ("validate_event",
>       GTK_RUN_LAST,
>       object_class->type,
>       GTK_SIGNAL_OFFSET (GtkWidgetClass, validate_event),
>       gtk_marshal_BOOL__POINTER,
>       GTK_TYPE_BOOL, 1,
>       GTK_TYPE_GDK_EVENT);
> #endif
>
> //                This is the initialization of the event callback.
>
> #ifdef VALIDATE
>   klass->validate_event = NULL;
> #endif
>   klass->focus_in_event = NULL;
>
> //                For analogy with focus_in_event
> }
>
> // This function makes all of this work!
>
> static void
> gtk_widget_real_grab_focus (GtkWidget *focus_widget)
> {
>   g_return_if_fail (focus_widget != NULL);
>   g_return_if_fail (GTK_IS_WIDGET (focus_widget));
>
>   if (GTK_WIDGET_CAN_FOCUS (focus_widget))
>     {
>       GtkWidget *toplevel;
>       GtkWidget *widget;
>
>       /* clear the current focus setting, break if the current widget
>        * is the focus widget's parent, since containers above that will
>        * be set by the next loop.
>        */
>       toplevel = gtk_widget_get_toplevel (focus_widget);
>       if (GTK_IS_WINDOW (toplevel))
>  {
>    widget = GTK_WINDOW (toplevel)->focus_widget;
>
>    if (widget == focus_widget)
>      {
>        /* We call gtk_window_set_focus() here so that the
>         * toplevel window can request the focus if necessary.
>         * This is needed when the toplevel is a GtkPlug
>         */
>        if (!GTK_WIDGET_HAS_FOCUS (widget))
>               gtk_window_set_focus (GTK_WINDOW (toplevel),
> focus_widget);
>        return;
>      }
>
> #ifdef VALIDATE
>
>    /* Check if the widget that get the focus causes validation */
>     if( GTK_WIDGET_CAUSES_VALIDATION(focus_widget) ) {
>
>         /* Check if the there exists a previously focused widget  */
>        if( widget ) {
>
>         /* Start of the validation process */
>         /* Initialize the return value of the validate event to TRUE,
> Just in case there is no validate event handler for this widget */
>              int validate_return_val = TRUE, foo=9876543210;
>
>              gtk_signal_emit (GTK_OBJECT (widget),
> widget_signals[VALIDATE_EVENT],
>                     &validate_return_val, &foo); /* I don't really know
> what is the fourth parameter for */
>
>              /* See the return value of the validation */
>              if( validate_return_val == FALSE ) { /* The widget is
> invalid */
>
>                     /* Ignore the activate event of the focus that
> wanted to get the focus, as it had never had to get the focus */
>                    GTK_WIDGET_SET_FLAGS(focus_widget,
> GTK_IGNOREACTIVATE);
>                    return; /* don't set the focus to the required widget
> */
>
>              } else {  /* The widget is valid */
>                     /* Unset the IGNOREACTIVATE flag, as now the widget
> is allowed to get the focus */
>                    GTK_WIDGET_UNSET_FLAGS(focus_widget,
> GTK_IGNOREACTIVATE);
>              }
>        }
>
> #endif
>
>     /* The rest of the function doesn't change  */
>
> ** gtkbutton.c **
>
> void
> gtk_button_clicked (GtkButton *button)
> {
>   g_return_if_fail (button != NULL);
>   g_return_if_fail (GTK_IS_BUTTON (button));
>
> #ifdef VALIDATE
>   if( !GTK_WIDGET_IGNOREACTIVATE(GTK_WIDGET(button)) )
> #endif
>     gtk_signal_emit (GTK_OBJECT (button), button_signals[CLICKED]);
> }
>
> Don't emit the activate window while other widget is validating and the
> validation has been unsuccessful.
> This must be done for other widgets that can be focused and activated
> with just one mouse click.
>
> The testgtk program just add a validate event handler to the entry
> widget:
>
> #ifdef VALIDATE
>
> static void
> on_entry_validate_event (GtkEntry *entry,
>     gint *result,
>     gpointer data)
> {
>   if( *gtk_entry_get_text(entry) != 'a') {
>     create_dialog();
>     *result = FALSE;
>   }
> }
>
> #endif
>
> static void
> create_entry (void)
> {
>
>     ....
>
> #ifdef VALIDATE
>   gtk_signal_connect (GTK_OBJECT (entry), "validate_event",
>                       GTK_SIGNAL_FUNC (on_entry_validate_event),
>                       (gpointer)NULL);
> #endif
>
> Regards,
>     Santiago Capel
>
> _______________________________________________
> gtk-devel-list mailing list
> gtk-devel-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-devel-list




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