From: Ben Pfaff Date: Sun, 19 Aug 2012 17:30:36 +0000 (-0700) Subject: psppire-dialog: Add "acceptable" predicate. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;ds=inline;h=c3f06028950f69cd695062fe01a64ba73e164b3e;p=pspp psppire-dialog: Add "acceptable" predicate. PsppireDialog already has a validity predicate that allows a dialog to easily disable "OK" and other buttons when the dialog has not yet been completely filled. It should usually be obvious to the user why this is the case. The upcoming GObjectification of the missing value dialog calls for a different kind of predicate, one where the reason is not obvious to the user (typically because he has just made a typo or does not understand a variable's format). In this case, the user needs more feedback, such as a message explaining the problem. This commit therefore introduces a second kind of predicate, the "accept" predicate. This predicate is only checked when the user clicks on the "OK" button. --- diff --git a/src/ui/gui/psppire-buttonbox.c b/src/ui/gui/psppire-buttonbox.c index ac40058dba..24d82d27d3 100644 --- a/src/ui/gui/psppire-buttonbox.c +++ b/src/ui/gui/psppire-buttonbox.c @@ -215,6 +215,14 @@ close_and_respond (GtkWidget *w, gint response) psppire_dialog_close (dialog); } +static gboolean +is_acceptable (GtkWidget *w) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (w); + + return (PSPPIRE_IS_DIALOG (toplevel) + && psppire_dialog_is_acceptable (PSPPIRE_DIALOG (toplevel))); +} static void close_dialog (GtkWidget *w, gpointer data) @@ -225,27 +233,31 @@ close_dialog (GtkWidget *w, gpointer data) static void continue_button_clicked (GtkWidget *w, gpointer data) { - close_and_respond (w, PSPPIRE_RESPONSE_CONTINUE); + if (is_acceptable (w)) + close_and_respond (w, PSPPIRE_RESPONSE_CONTINUE); } static void ok_button_clicked (GtkWidget *w, gpointer data) { - close_and_respond (w, GTK_RESPONSE_OK); + if (is_acceptable (w)) + close_and_respond (w, GTK_RESPONSE_OK); } static void paste_button_clicked (GtkWidget *w, gpointer data) { - close_and_respond (w, PSPPIRE_RESPONSE_PASTE); + if (is_acceptable (w)) + close_and_respond (w, PSPPIRE_RESPONSE_PASTE); } static void goto_button_clicked (GtkWidget *w, gpointer data) { - close_and_respond (w, PSPPIRE_RESPONSE_GOTO); + if (is_acceptable (w)) + close_and_respond (w, PSPPIRE_RESPONSE_GOTO); } diff --git a/src/ui/gui/psppire-dialog.c b/src/ui/gui/psppire-dialog.c index 7bdcaaecf1..547ff2a4da 100644 --- a/src/ui/gui/psppire-dialog.c +++ b/src/ui/gui/psppire-dialog.c @@ -324,6 +324,8 @@ psppire_dialog_init (PsppireDialog *dialog) dialog->box = NULL; dialog->contents_are_valid = NULL; dialog->validity_data = NULL; + dialog->contents_are_acceptable = NULL; + dialog->acceptable_data = NULL; dialog->slidable = FALSE; g_value_init (&value, orientation_spec->value_type); @@ -547,6 +549,10 @@ psppire_orientation_get_type (void) } +/* Sets a predicate function that is checked after each change that the user + makes to the dialog's state. If the predicate function returns false, then + "OK" and other buttons that accept the dialog's settings will be + disabled. */ void psppire_dialog_set_valid_predicate (PsppireDialog *dialog, ContentsAreValid contents_are_valid, @@ -556,6 +562,30 @@ psppire_dialog_set_valid_predicate (PsppireDialog *dialog, dialog->validity_data = data; } +/* Sets a predicate function that is called after "OK" or another button that + accepts the dialog's settings is pushed. If the predicate function returns + false, then the button push is ignored. (If the predicate function returns + false, then it should take some action to notify the user why the contents + are unacceptable, e.g. pop up a dialog box.) + + An accept predicate is preferred over a validity predicate when the reason + why the dialog settings are unacceptable may not be obvious to the user, so + that the user needs a helpful message to explain. */ +void +psppire_dialog_set_accept_predicate (PsppireDialog *dialog, + ContentsAreValid contents_are_acceptable, + gpointer data) +{ + dialog->contents_are_acceptable = contents_are_acceptable; + dialog->acceptable_data = data; +} + +gboolean +psppire_dialog_is_acceptable (const PsppireDialog *dialog) +{ + return (dialog->contents_are_acceptable == NULL + || dialog->contents_are_acceptable (dialog->acceptable_data)); +} diff --git a/src/ui/gui/psppire-dialog.h b/src/ui/gui/psppire-dialog.h index 3b01557ec7..af56aac1e8 100644 --- a/src/ui/gui/psppire-dialog.h +++ b/src/ui/gui/psppire-dialog.h @@ -63,6 +63,8 @@ struct _PsppireDialog ContentsAreValid contents_are_valid; gpointer validity_data; + ContentsAreValid contents_are_acceptable; + gpointer acceptable_data; gboolean slidable; PsppireOrientation orientation; }; @@ -82,6 +84,10 @@ gint psppire_dialog_run (PsppireDialog *); void psppire_dialog_set_valid_predicate (PsppireDialog *, ContentsAreValid, gpointer ); +void psppire_dialog_set_accept_predicate (PsppireDialog *, + ContentsAreValid, + gpointer ); +gboolean psppire_dialog_is_acceptable (const PsppireDialog *); void psppire_dialog_notify_change (PsppireDialog *);