GtkWidgets validation



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




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