[geary/wip/714104-refine-account-dialog: 8/15] Ensure new accounts can be created by hitting Enter.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/714104-refine-account-dialog: 8/15] Ensure new accounts can be created by hitting Enter.
- Date: Fri, 19 Oct 2018 23:50:34 +0000 (UTC)
commit 5a98bfd1b1e856d97c7c77f9beb7ecf0f4e8e8b6
Author: Michael Gratton <mike vee net>
Date: Sat Sep 8 20:53:38 2018 +1000
Ensure new accounts can be created by hitting Enter.
src/client/accounts/accounts-editor-add-pane.vala | 44 ++++++++++++++------
src/client/components/components-validator.vala | 50 +++++++++++++----------
2 files changed, 60 insertions(+), 34 deletions(-)
---
diff --git a/src/client/accounts/accounts-editor-add-pane.vala
b/src/client/accounts/accounts-editor-add-pane.vala
index 405d26ca..e763678c 100644
--- a/src/client/accounts/accounts-editor-add-pane.vala
+++ b/src/client/accounts/accounts-editor-add-pane.vala
@@ -68,6 +68,8 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
private LoginRow smtp_login = new LoginRow();
private PasswordRow smtp_password = new PasswordRow();
+ private bool controls_valid = false;
+
internal EditorAddPane(Editor editor, Geary.ServiceProvider provider) {
this.editor = editor;
@@ -101,20 +103,28 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
this.details_list.add(this.real_name);
this.details_list.add(this.email);
- this.real_name.validator.notify["state"].connect(on_validated);
- this.email.validator.notify["state"].connect(on_validated);
+ this.real_name.validator.state_changed.connect(on_validated);
+ this.real_name.value.activate.connect(on_activated);
+ this.email.validator.state_changed.connect(on_validated);
+ this.email.value.activate.connect(on_activated);
this.email.value.changed.connect(on_email_changed);
- this.imap_hostname.validator.notify["state"].connect(on_validated);
+ this.imap_hostname.validator.state_changed.connect(on_validated);
+ this.imap_hostname.value.activate.connect(on_activated);
this.imap_tls.hide();
- this.imap_login.validator.notify["state"].connect(on_validated);
- this.imap_password.validator.notify["state"].connect(on_validated);
+ this.imap_login.validator.state_changed.connect(on_validated);
+ this.imap_login.value.activate.connect(on_activated);
+ this.imap_password.validator.state_changed.connect(on_validated);
+ this.imap_password.value.activate.connect(on_activated);
- this.smtp_hostname.validator.notify["state"].connect(on_validated);
+ this.smtp_hostname.validator.state_changed.connect(on_validated);
+ this.smtp_hostname.value.activate.connect(on_activated);
this.smtp_tls.hide();
this.smtp_auth.value.changed.connect(on_smtp_auth_changed);
- this.smtp_login.validator.notify["state"].connect(on_validated);
- this.smtp_password.validator.notify["state"].connect(on_validated);
+ this.smtp_login.validator.state_changed.connect(on_validated);
+ this.smtp_login.value.activate.connect(on_activated);
+ this.smtp_password.validator.state_changed.connect(on_validated);
+ this.smtp_password.value.activate.connect(on_activated);
if (provider == Geary.ServiceProvider.OTHER) {
this.receiving_list.add(this.imap_hostname);
@@ -346,22 +356,32 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
}
private void check_validation() {
- bool is_valid = true;
+ bool controls_valid = true;
foreach (Gtk.ListBox list in new Gtk.ListBox[] {
this.details_list, this.receiving_list, this.sending_list
}) {
list.foreach((child) => {
AddPaneRow? validatable = child as AddPaneRow;
if (validatable != null && !validatable.validator.is_valid) {
- is_valid = false;
+ controls_valid = false;
}
});
}
- this.create_button.set_sensitive(is_valid);
+ this.create_button.set_sensitive(controls_valid);
+ this.controls_valid = controls_valid;
}
- private void on_validated() {
+ private void on_validated(Components.Validator.Trigger reason) {
check_validation();
+ if (this.controls_valid && reason == Components.Validator.Trigger.ACTIVATED) {
+ this.create_button.clicked();
+ }
+ }
+
+ private void on_activated() {
+ if (this.controls_valid) {
+ this.create_button.clicked();
+ }
}
private void on_email_changed() {
diff --git a/src/client/components/components-validator.vala b/src/client/components/components-validator.vala
index 4432c1b8..ee500a59 100644
--- a/src/client/components/components-validator.vala
+++ b/src/client/components/components-validator.vala
@@ -47,11 +47,13 @@ public class Components.Validator : GLib.Object {
}
/** The cause of a validity check being required. */
- protected enum Trigger {
+ public enum Trigger {
/** The entry's contents changed */
CHANGED,
- /** The user performed an action indicating they are done. */
- COMPLETE;
+ /** The entry lost the keyboard focus. */
+ LOST_FOCUS,
+ /** The user activated the entry. */
+ ACTIVATED;
}
/** Defines the UI state for a specific validity. */
@@ -100,6 +102,10 @@ public class Components.Validator : GLib.Object {
private Geary.TimeoutManager ui_update_timer;
+ /** Fired when the validation state changes. */
+ public signal void state_changed(Trigger reason, Validity prev_state);
+
+
public Validator(Gtk.Entry target) {
this.target = target;
@@ -157,7 +163,7 @@ public class Components.Validator : GLib.Object {
* By default, this always returns {@link Validity.VALID}, making
* it useful for required, but otherwise free-form fields only.
*/
- protected virtual Validity validate(string value, Trigger cause) {
+ protected virtual Validity validate(string value, Trigger reason) {
return Validity.VALID;
}
@@ -168,14 +174,20 @@ public class Components.Validator : GLib.Object {
* CPU-intensive or long-running validation routine and it has
* completed validating a value. See {@link validate} for details.
*/
- protected void update_state(Validity new_state) {
+ protected void update_state(Validity new_state, Trigger reason) {
if (this.state != new_state) {
Validity old_state = this.state;
+ // Fire the signal after updating the state but before
+ // updating the UI so listeners can update UI settings
+ // first if needed.
this.state = new_state;
- if (new_state == Validity.VALID) {
- // Update the UI straight away when going valid to
- // provide instant feedback
+ state_changed(reason, old_state);
+
+ if (new_state == Validity.VALID || reason != Trigger.CHANGED) {
+ // Update the UI straight away when going valid or
+ // when editing is complete to provide instant
+ // feedback
update_ui(new_state);
} else {
if (old_state == Validity.EMPTY) {
@@ -194,23 +206,17 @@ public class Components.Validator : GLib.Object {
}
}
- private void validate_entry(Trigger cause) {
+ private void validate_entry(Trigger reason) {
string value = this.target.get_text();
Validity new_state = this.state;
if (Geary.String.is_empty_or_whitespace(value)) {
new_state = this.is_required
? Validity.EMPTY : Validity.INDETERMINATE;
} else {
- new_state = validate(value, cause);
+ new_state = validate(value, reason);
}
- update_state(new_state);
-
- if (cause == Trigger.COMPLETE) {
- // Update the UI instantly since we know the user is done
- // editing it an will want instant feedback.
- update_ui(this.state);
- }
+ update_state(new_state, reason);
}
private void update_ui(Validity state) {
@@ -256,7 +262,7 @@ public class Components.Validator : GLib.Object {
}
private void on_activate() {
- validate_entry(Trigger.COMPLETE);
+ validate_entry(Trigger.ACTIVATED);
}
private void on_update_ui() {
@@ -275,7 +281,7 @@ public class Components.Validator : GLib.Object {
// the focused widget any more, rather than the whole window
// having lost focus.
if (!this.target.is_focus) {
- validate_entry(Trigger.COMPLETE);
+ validate_entry(Trigger.LOST_FOCUS);
}
return Gdk.EVENT_PROPAGATE;
}
@@ -302,7 +308,7 @@ public class Components.EmailValidator : Validator {
protected override Validator.Validity validate(string value,
- Validator.Trigger cause) {
+ Validator.Trigger reason) {
return Geary.RFC822.MailboxAddress.is_valid_address(value)
? Validator.Validity.VALID : Validator.Validity.INVALID;
}
@@ -384,12 +390,12 @@ public class Components.NetworkAddressValidator : Validator {
try {
this.resolver.lookup_by_name_async.end(res);
this.validated_address = address;
- update_state(Validator.Validity.VALID);
+ update_state(Validator.Validity.VALID, reason);
} catch (GLib.IOError.CANCELLED err) {
this.validated_address = null;
} catch (GLib.Error err) {
this.validated_address = null;
- update_state(Validator.Validity.INVALID);
+ update_state(Validator.Validity.INVALID, reason);
}
this.cancellable = null;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]