[california/wip/725783-time] Validate time text entry fields



commit 2b352ec7c917fb4b7dabdb82fae468640ab3b414
Author: Jim Nelson <jim yorba org>
Date:   Tue Aug 5 13:31:13 2014 -0700

    Validate time text entry fields

 src/host/host-date-time-widget.vala    |   53 ++++++++++++++++++++++++++++++++
 src/host/host-event-time-settings.vala |   14 ++++++++
 2 files changed, 67 insertions(+), 0 deletions(-)
---
diff --git a/src/host/host-date-time-widget.vala b/src/host/host-date-time-widget.vala
index f8e247d..3753ace 100644
--- a/src/host/host-date-time-widget.vala
+++ b/src/host/host-date-time-widget.vala
@@ -14,6 +14,7 @@ public class DateTimeWidget : Gtk.Box {
     public const string PROP_WALL_TIME = "wall-time";
     public const string PROP_FLOOR = "floor";
     public const string PROP_CEILING = "ceiling";
+    public const string PROP_OUT_OF_RANGE = "out-of-range";
     
     public bool enable_time { get; set; default = true; }
     
@@ -27,6 +28,12 @@ public class DateTimeWidget : Gtk.Box {
     
     public Calendar.ExactTime? ceiling { get; set; default = null; }
     
+    /**
+     * Indicates if the widgets are filled-in with invalid values or is valid but out of the range
+     * of { link floor} and/or { link ceiling}.
+     */
+    public bool out_of_range { get; private set; default = false; }
+    
     [GtkChild]
     private Gtk.Calendar calendar;
     
@@ -125,6 +132,8 @@ public class DateTimeWidget : Gtk.Box {
         calendar.month_changed.connect(on_calendar_month_or_year_changed);
         calendar.next_year.connect(on_calendar_month_or_year_changed);
         calendar.prev_year.connect(on_calendar_month_or_year_changed);
+        hour_entry.changed.connect(on_time_entry_changed);
+        minutes_entry.changed.connect(on_time_entry_changed);
     }
     
     private void disconnect_widget_signals() {
@@ -134,6 +143,8 @@ public class DateTimeWidget : Gtk.Box {
         calendar.month_changed.disconnect(on_calendar_month_or_year_changed);
         calendar.next_year.disconnect(on_calendar_month_or_year_changed);
         calendar.prev_year.disconnect(on_calendar_month_or_year_changed);
+        hour_entry.changed.disconnect(on_time_entry_changed);
+        minutes_entry.changed.disconnect(on_time_entry_changed);
     }
     
     private bool on_time_adjustment_clicked(Toolkit.ButtonEvent details) {
@@ -257,6 +268,48 @@ public class DateTimeWidget : Gtk.Box {
         connect_widget_signals();
     }
     
+    private void on_time_entry_changed() {
+        Calendar.WallTime new_wall_time;
+        bool valid = validate_time_entries(out new_wall_time);
+        
+        disconnect_property_signals();
+        
+        wall_time = new_wall_time;
+        out_of_range = !valid;
+        
+        connect_property_signals();
+    }
+    
+    private bool validate_time_entries(out Calendar.WallTime new_wall_time) {
+        // maintain current until validated
+        new_wall_time = wall_time;
+        
+        if (String.is_empty(hour_entry.text) || String.is_empty(minutes_entry.text))
+            return false;
+        
+        int hour = int.parse(hour_entry.text);
+        if (!Calendar.System.is_24hr && meridiem_label.label == Calendar.FMT_PM && hour < 12)
+            hour += 12;
+        
+        int min = int.parse(minutes_entry.text);
+        
+        if (hour > Calendar.WallTime.MAX_HOUR || hour < 0 || min > Calendar.WallTime.MAX_MINUTE || min < 0)
+            return false;
+        
+        Calendar.WallTime entry_wall_time = new Calendar.WallTime(hour, min, 0);
+        
+        Calendar.ExactTime entry_time = new Calendar.ExactTime(Calendar.Timezone.local, date, 
entry_wall_time);
+        if (floor != null && entry_time.compare_to(floor) < 0)
+            return false;
+        
+        if (ceiling != null && entry_time.compare_to(ceiling) > 0)
+            return false;
+        
+        new_wall_time = entry_wall_time;
+        
+        return true;
+    }
+    
     private void system_24hr_changed() {
         meridiem_label.visible = meridiem_up.visible = meridiem_down.visible = !Calendar.System.is_24hr;
         meridiem_label.no_show_all = meridiem_up.no_show_all = meridiem_down.no_show_all = 
Calendar.System.is_24hr;
diff --git a/src/host/host-event-time-settings.vala b/src/host/host-event-time-settings.vala
index 5253cc6..a2ea75b 100644
--- a/src/host/host-event-time-settings.vala
+++ b/src/host/host-event-time-settings.vala
@@ -63,6 +63,9 @@ public class EventTimeSettings : Gtk.Box, Toolkit.Card {
     [GtkChild]
     private Gtk.CheckButton all_day_checkbutton;
     
+    [GtkChild]
+    private Gtk.Button ok_button;
+    
     public string card_id { get { return ID; } }
     public string? title { get { return null; } }
     public Gtk.Widget? default_widget { get { return null; } }
@@ -83,6 +86,11 @@ public class EventTimeSettings : Gtk.Box, Toolkit.Card {
         to_widget.notify[DateTimeWidget.PROP_WALL_TIME].connect(on_to_changed);
         all_day_checkbutton.notify["active"].connect(on_update_summary);
         
+        from_widget.bind_property(DateTimeWidget.PROP_OUT_OF_RANGE, ok_button, "sensitive",
+            BindingFlags.SYNC_CREATE, transform_oor_to_sensitive);
+        to_widget.bind_property(DateTimeWidget.PROP_OUT_OF_RANGE, ok_button, "sensitive",
+            BindingFlags.SYNC_CREATE, transform_oor_to_sensitive);
+        
         all_day_checkbutton.bind_property("active", from_widget, DateTimeWidget.PROP_ENABLE_TIME,
             BindingFlags.SYNC_CREATE | BindingFlags.INVERT_BOOLEAN);
         all_day_checkbutton.bind_property("active", to_widget, DateTimeWidget.PROP_ENABLE_TIME,
@@ -95,6 +103,12 @@ public class EventTimeSettings : Gtk.Box, Toolkit.Card {
         Calendar.System.instance.is_24hr_changed.disconnect(on_update_summary);
     }
     
+    private bool transform_oor_to_sensitive(Binding binding, Value source_value, ref Value target_value) {
+        target_value = !to_widget.out_of_range && !from_widget.out_of_range;
+        
+        return true;
+    }
+    
     public void jumped_to(Toolkit.Card? from, Toolkit.Card.Jump reason, Value? message_value) {
         message = (Message) message_value;
         


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