From d7731cec4fb275291549275d0c674b284c660aa0 Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Mon, 11 Nov 2019 10:46:13 -0300 Subject: [PATCH] Implementing validity signal and oversize input. --- src/dialogs/hostselect.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ src/dialogs/settings/dialog.c | 60 ++++++++++++++++++++++++++++++++++++------------------------ src/dialogs/settings/widget.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ src/include/v3270/settings.h | 7 +++++-- 4 files changed, 188 insertions(+), 50 deletions(-) diff --git a/src/dialogs/hostselect.c b/src/dialogs/hostselect.c index 44f2af5..bd74eb5 100644 --- a/src/dialogs/hostselect.c +++ b/src/dialogs/hostselect.c @@ -118,8 +118,8 @@ }, { - .top = 0, - .left = 6, + .top = 1, + .left = 0, .width = 2, .height = 1, @@ -179,6 +179,18 @@ .tooltip = N_("Port or service name (empty for \"telnet\")."), .max_length = 6, .width_chars = 7, + }, + + { + .top = 1, + .left = 3, + .width = 2, + .height = 1, + + .label = N_( "Oversize" ), + .tooltip = N_("Makes the screen larger than the default for the chosen model number."), + .max_length = 7, + .width_chars = 8, } }; @@ -224,6 +236,30 @@ static void V3270HostSelectWidget_class_init(G_GNUC_UNUSED V3270HostSelectWidget } +static void oversize_changed(GtkEditable *editable, GtkWidget *settings) +{ + const gchar * chars = gtk_editable_get_chars(editable,0,-1); + gboolean valid = TRUE; + char junk; + unsigned int ovc = 0, ovr = 0; + + if(*chars) + { + if(sscanf(chars, "%ux%u%c", &ovc, &ovr, &junk) != 2) + { + valid = FALSE; + debug("Can't parse \"%s\"",chars); + } + else if( (ovc * ovr) > 0x4000) + { + valid = FALSE; + debug("Invalid values on \"%s\"",chars); + } + } + + v3270_settings_set_valid(settings,valid); +} + static void V3270HostSelectWidget_init(V3270HostSelectWidget *widget) { // Cell renderer @@ -258,21 +294,35 @@ static void V3270HostSelectWidget_init(V3270HostSelectWidget *widget) for(entry = 0; entry < G_N_ELEMENTS(entryfields); entry++) { widget->input.entry[entry] = GTK_ENTRY(gtk_entry_new()); - gtk_entry_set_max_length(widget->input.entry[entry],entryfields[entry].max_length); gtk_entry_set_width_chars(widget->input.entry[entry],entryfields[entry].width_chars); - - v3270_grid_attach( - GTK_GRID(connection), - (struct v3270_entry_field *) & entryfields[entry], - GTK_WIDGET(widget->input.entry[entry]) - ); - } + // Custom settings gtk_entry_set_placeholder_text(widget->input.entry[ENTRY_SRVCNAME],"telnet"); gtk_widget_set_hexpand(GTK_WIDGET(widget->input.entry[ENTRY_HOSTNAME]),TRUE); + // Add to containers + v3270_grid_attach( + GTK_GRID(connection), + (struct v3270_entry_field *) & entryfields[0], + GTK_WIDGET(widget->input.entry[0]) + ); + + v3270_grid_attach( + GTK_GRID(connection), + (struct v3270_entry_field *) & entryfields[1], + GTK_WIDGET(widget->input.entry[1]) + ); + + v3270_grid_attach( + GTK_GRID(emulation), + (struct v3270_entry_field *) & entryfields[2], + GTK_WIDGET(widget->input.entry[2]) + ); + + g_signal_connect(G_OBJECT(widget->input.entry[2]),"changed",G_CALLBACK(oversize_changed),widget); + } // SSL checkbox @@ -338,8 +388,8 @@ static void V3270HostSelectWidget_init(V3270HostSelectWidget *widget) static const struct v3270_entry_field descriptor = { - .top = 1, - .left = 0, + .top = 0, + .left = 6, .width = 2, .height = 1, diff --git a/src/dialogs/settings/dialog.c b/src/dialogs/settings/dialog.c index 9239d43..ecb7d1e 100644 --- a/src/dialogs/settings/dialog.c +++ b/src/dialogs/settings/dialog.c @@ -47,6 +47,39 @@ static gboolean on_tab_focus(V3270Settings *settings, GdkEvent G_GNUC_UNUSED(*ev return FALSE; } +static void check_valid(GtkWidget *widget, gboolean *valid) +{ + if(*valid && GTK_IS_V3270_SETTINGS(widget)) + { + if(!v3270_settings_get_valid(widget)) + *valid = FALSE; + } + +} + +static void on_validity(V3270Settings G_GNUC_UNUSED(*settings), gboolean valid, V3270SettingsDialog * dialog) +{ + if(valid) + { + // Check validity of all childs. + gtk_container_foreach( + GTK_CONTAINER(dialog->tabs), + (GtkCallback) check_valid, + &valid + ); + + } + + debug("The current state is %s",valid ? "valid" : "invalid"); + + GtkWidget * button = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY); + + if(button) + gtk_widget_set_sensitive(button,valid); + + +} + static void add(GtkContainer *container, GtkWidget *widget) { g_return_if_fail(GTK_IS_V3270_SETTINGS(widget)); @@ -73,6 +106,7 @@ static void add(GtkContainer *container, GtkWidget *widget) ); g_signal_connect(G_OBJECT(widget), "focus-in-event", G_CALLBACK(on_tab_focus), container); + g_signal_connect(G_OBJECT(widget), "validity", G_CALLBACK(on_validity), container); } @@ -123,33 +157,9 @@ void v3270_settings_dialog_revert(GtkWidget *dialog) } -/* -static void response(GtkDialog *dialog, gint response_id) -{ - if(!terminal) - return; - - -} -*/ - -static void dispose(GObject *object) -{ - debug("%s",__FUNCTION__); - -// V3270SettingsDialog * widget = GTK_V3270_SETTINGS_DIALOG(object); - - - G_OBJECT_CLASS(V3270SettingsDialog_parent_class)->dispose(object); -} - static void V3270SettingsDialog_class_init(V3270SettingsDialogClass *klass) { GTK_CONTAINER_CLASS(klass)->add = add; - - // Object class - G_OBJECT_CLASS(klass)->dispose = dispose; - } static void on_page_changed(GtkNotebook *notebook, GtkWidget G_GNUC_UNUSED(*child), guint G_GNUC_UNUSED(page_num), V3270SettingsDialog G_GNUC_UNUSED(*dialog)) { @@ -220,6 +230,8 @@ void v3270_settings_dialog_set_terminal_widget(GtkWidget *widget, GtkWidget *ter { g_return_if_fail(GTK_IS_V3270_SETTINGS_DIALOG(widget)); + debug("%s(%p,%p)",__FUNCTION__,widget,terminal); + GTK_V3270_SETTINGS_DIALOG(widget)->terminal = terminal; gtk_container_foreach( diff --git a/src/dialogs/settings/widget.c b/src/dialogs/settings/widget.c index c3b35e2..272f826 100644 --- a/src/dialogs/settings/widget.c +++ b/src/dialogs/settings/widget.c @@ -28,12 +28,24 @@ */ #include "../private.h" + #include "../terminal/marshal.h" #include #include #include + static void signal_update_message(GtkWidget *terminal, LIB3270_MESSAGE G_GNUC_UNUSED(id), GtkWidget *settings); + G_DEFINE_TYPE(V3270Settings, V3270Settings, GTK_TYPE_GRID); + enum + { + VALIDITY_SIGNAL, ///< @brief Signal for valid state. + SIGNAL_LAST + }; + + static guint signals[SIGNAL_LAST] = { 0 }; + + /*--[ Implement ]------------------------------------------------------------------------------------*/ static void apply(GtkWidget G_GNUC_UNUSED(*widget), GtkWidget G_GNUC_UNUSED(*terminal)) @@ -58,23 +70,65 @@ static void update_message(GtkWidget G_GNUC_UNUSED(*widget), GtkWidget G_GNUC_UN static void finalize(GObject *object) { - v3270_settings_set_terminal_widget(GTK_WIDGET(object),NULL); + V3270Settings * settings = GTK_V3270_SETTINGS(object); + + if(settings->terminal) + { + // Disconnect terminal widget + // + // (Can't use v3270_settings_set_terminal_widget here) + // + gulong handler = g_signal_handler_find( + settings->terminal, + G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + G_CALLBACK(signal_update_message), + object + ); + + if(handler) + g_signal_handler_disconnect(settings->terminal, handler); + + settings->terminal = NULL; + } + G_OBJECT_CLASS(V3270Settings_parent_class)->finalize(object); } +static void validity(GtkWidget *widget, gboolean state) +{ + +} + static void V3270Settings_class_init(V3270SettingsClass *klass) { + GObjectClass * gobject_class = G_OBJECT_CLASS(klass); + klass->apply = apply; klass->revert = cancel; klass->load = load; + klass->validity = validity; klass->update_message = update_message; - G_OBJECT_CLASS(klass)->finalize = finalize; + gobject_class->finalize = finalize; + + signals[VALIDITY_SIGNAL] = + g_signal_new( I_("validity"), + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (V3270SettingsClass, validity), + NULL, NULL, + v3270_VOID__VOID_BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + } static void V3270Settings_init(V3270Settings *widget) { - widget->terminal = NULL; + widget->terminal = NULL; + widget->valid = FALSE; // https://developer.gnome.org/hig/stable/visual-layout.html.en gtk_grid_set_row_spacing(GTK_GRID(widget),6); @@ -93,6 +147,8 @@ LIB3270_EXPORT void v3270_settings_set_terminal_widget(GtkWidget *widget, GtkWid V3270Settings * settings = GTK_V3270_SETTINGS(widget); + debug("%s(%p,%p)",__FUNCTION__,widget,terminal); + // Return if there's nothing to do. if(settings->terminal == terminal) return; @@ -125,12 +181,19 @@ LIB3270_EXPORT void v3270_settings_set_terminal_widget(GtkWidget *widget, GtkWid // Connect the new widget. g_signal_connect(G_OBJECT(terminal),I_("message_changed"), G_CALLBACK(signal_update_message), widget); + // Set as valid before update message and load contents. + v3270_settings_set_valid(widget,TRUE); + // Update dialog state. GTK_V3270_SETTINGS_GET_CLASS(widget)->update_message(widget,terminal); // Load the dialog contents. GTK_V3270_SETTINGS_GET_CLASS(widget)->load(widget,terminal); } + else + { + v3270_settings_set_valid(widget,FALSE); + } } @@ -144,15 +207,6 @@ LIB3270_EXPORT void v3270_settings_set_terminal_widget(GtkWidget *widget, GtkWid { g_return_if_fail(GTK_IS_V3270_SETTINGS(widget)); GTK_V3270_SETTINGS_GET_CLASS(widget)->apply(widget,GTK_V3270_SETTINGS(widget)->terminal); - - /* - - BUG: The signal should be sent by the dialog! - - V3270Settings * settings = GTK_V3270_SETTINGS(widget); - if(settings && settings->terminal) - v3270_emit_save_settings(settings->terminal); - */ } LIB3270_EXPORT void v3270_settings_revert(GtkWidget *widget) @@ -178,3 +232,22 @@ LIB3270_EXPORT void v3270_settings_set_terminal_widget(GtkWidget *widget, GtkWid g_return_val_if_fail(GTK_IS_V3270_SETTINGS(widget),NULL); return GTK_V3270_SETTINGS(widget)->tooltip; } + + LIB3270_EXPORT gboolean v3270_settings_get_valid(GtkWidget *widget) + { + // Non settings widget is always valid. + g_return_val_if_fail(GTK_IS_V3270_SETTINGS(widget),TRUE); + return GTK_V3270_SETTINGS(widget)->valid; + } + + LIB3270_EXPORT void v3270_settings_set_valid(GtkWidget *widget, gboolean is_valid) + { + V3270Settings * settings = GTK_V3270_SETTINGS(widget); + + if(is_valid != settings->valid) + { + settings->valid = is_valid; + g_signal_emit(widget, signals[VALIDITY_SIGNAL], 0, settings->valid); + } + + } diff --git a/src/include/v3270/settings.h b/src/include/v3270/settings.h index 8038139..9c203ea 100644 --- a/src/include/v3270/settings.h +++ b/src/include/v3270/settings.h @@ -50,6 +50,7 @@ const gchar * label; ///< @brief Label for settings dialog. const gchar * title; ///< @brief Title for settings dialog. const gchar * tooltip; ///< @brief Tooltip for settings dialog. + gboolean valid; ///< @brief True if the settings can be applyed. } V3270Settings; typedef struct _V3270SettingsClass { @@ -59,7 +60,7 @@ void (*apply)(GtkWidget *widget, GtkWidget *terminal); ///< @brief Method for GTK_RESPONSE_APPLY void (*revert)(GtkWidget *widget, GtkWidget *terminal); ///< @brief Method for GTK_RESPONSE_CANCEL void (*update_message)(GtkWidget *widget, GtkWidget *terminal); ///< @brief Lib3270 message has changed. - + void (*validity)(GtkWidget *, gboolean); } V3270SettingsClass; LIB3270_EXPORT GType V3270Settings_get_type(void); @@ -70,6 +71,9 @@ LIB3270_EXPORT void v3270_settings_apply(GtkWidget *widget); LIB3270_EXPORT void v3270_settings_revert(GtkWidget *widget); + LIB3270_EXPORT void v3270_settings_set_valid(GtkWidget *widget, gboolean is_valid); + LIB3270_EXPORT gboolean v3270_settings_get_valid(GtkWidget *widget); + LIB3270_EXPORT const gchar * v3270_settings_get_title(GtkWidget *widget); LIB3270_EXPORT const gchar * v3270_settings_get_label(GtkWidget *widget); LIB3270_EXPORT const gchar * v3270_settings_get_tooltip(GtkWidget *widget); @@ -97,7 +101,6 @@ typedef struct _V3270SettingsDialogClass { GtkDialogClass parent_class; - } V3270SettingsDialogClass; LIB3270_EXPORT GType V3270SettingsDialog_get_type(void); -- libgit2 0.21.2