Re: GtkWidgets validation
- From: Santiago Capel <bluefish ono com>
- To: gtk-devel-list gnome org, gtk-app-devel-list gnome org
- Subject: Re: GtkWidgets validation
- Date: Wed, 26 Dec 2001 20:11:59 +0100
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]