[gnome-clocks/zbrown/world-clocks] alarms: Simplify editor



commit 4a45cdb4b023495995b3f7beef8ef15cffc8ccbd
Author: Zander Brown <zbrown gnome org>
Date:   Fri Aug 9 01:00:48 2019 +0100

    alarms: Simplify editor
    
    Use a popover with full names rather than a row of abbv to select repeats
    
    Also simplifies the internal layout to a GtkBox

 data/gnome-clocks.gresource.xml |   1 +
 data/ui/alarmdaypickerrow.ui    |  27 +++
 data/ui/alarmsetupdialog.ui     | 354 +++++++++++++++++-----------------------
 data/ui/alarmtile.ui            |   1 -
 src/alarm.vala                  | 231 ++++++++++++++++++++------
 src/utils.vala                  | 126 +++++++++-----
 6 files changed, 445 insertions(+), 295 deletions(-)
---
diff --git a/data/gnome-clocks.gresource.xml b/data/gnome-clocks.gresource.xml
index 9f30bc6..89a3e9a 100644
--- a/data/gnome-clocks.gresource.xml
+++ b/data/gnome-clocks.gresource.xml
@@ -12,6 +12,7 @@
     <file preprocess="xml-stripblanks">ui/worldtile.ui</file>
     <file preprocess="xml-stripblanks">ui/alarmringing.ui</file>
     <file preprocess="xml-stripblanks">ui/alarmtile.ui</file>
+    <file preprocess="xml-stripblanks">ui/alarmdaypickerrow.ui</file>
     <file preprocess="xml-stripblanks">ui/alarmsetupdialog.ui</file>
     <file preprocess="xml-stripblanks">ui/alarm.ui</file>
     <file preprocess="xml-stripblanks">ui/stopwatch.ui</file>
diff --git a/data/ui/alarmdaypickerrow.ui b/data/ui/alarmdaypickerrow.ui
new file mode 100644
index 0000000..8c557ce
--- /dev/null
+++ b/data/ui/alarmdaypickerrow.ui
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="ClocksAlarmDayPickerRow" parent="HdyActionRow">
+    <property name="visible">True</property>
+    <property name="title">Repeats</property>
+    <child type="action">
+      <object class="GtkImage" id="icon">
+        <property name="visible">True</property>
+        <property name="valign">center</property>
+        <property name="halign">center</property>
+        <property name="icon-name">pan-down-symbolic</property>
+        <property name="icon-size">1</property>
+      </object>
+    </child>
+    <child type="action">
+      <object class="GtkLabel" id="current">
+        <property name="visible">True</property>
+        <property name="valign">center</property>
+        <property name="label" translatable="yes">No Repeat</property>
+      </object>
+    </child>
+  </template>
+  <object class="GtkPopover" id="popover">
+    <property name="relative-to">icon</property>
+    <signal name="closed" handler="popover_done" swapped="no"/>
+  </object>
+</interface>
diff --git a/data/ui/alarmsetupdialog.ui b/data/ui/alarmsetupdialog.ui
index 9845f67..473a2b1 100644
--- a/data/ui/alarmsetupdialog.ui
+++ b/data/ui/alarmsetupdialog.ui
@@ -77,264 +77,212 @@
           </packing>
         </child>
         <child>
-          <object class="GtkGrid" id="setup_dialog_content">
+          <object class="HdyColumn">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="row_spacing">12</property>
+            <property name="maximum-width">450</property>
             <child>
-              <object class="GtkGrid" id="time_grid">
+              <object class="GtkBox">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="halign">center</property>
-                <property name="margin_top">12</property>
-                <property name="hexpand">True</property>
-                <property name="column_spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="dummy_label1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_start">6</property>
-                    <property name="margin_end">6</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label">∶</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="top_attach">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkSpinButton" id="m_spinbutton">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="max_length">2</property>
-                    <property name="invisible_char">●</property>
-                    <property name="activates_default">True</property>
-                    <property name="text">0</property>
-                    <property name="xalign">0.5</property>
-                    <property name="input_purpose">number</property>
-                    <property name="orientation">vertical</property>
-                    <property name="adjustment">m_adjustment</property>
-                    <property name="numeric">True</property>
-                    <property name="wrap">True</property>
-                    <signal name="changed" handler="spinbuttons_changed" object="ClocksAlarmSetupDialog" 
swapped="no"/>
-                    <signal name="output" handler="show_leading_zeros" object="ClocksAlarmSetupDialog" 
swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="left_attach">3</property>
-                    <property name="top_attach">0</property>
-                  </packing>
-                </child>
+                <property name="spacing">12</property>
+                <property name="orientation">vertical</property>
                 <child>
-                  <object class="GtkStack" id="am_pm_stack">
+                  <object class="GtkGrid" id="time_grid">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="margin_start">6</property>
-                    <property name="margin_end">6</property>
+                    <property name="halign">center</property>
+                    <property name="margin_top">12</property>
+                    <property name="column_spacing">6</property>
                     <child>
-                      <object class="GtkLabel" id="dummy_label2">
+                      <object class="GtkLabel" id="dummy_label1">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
+                        <property name="margin_start">6</property>
+                        <property name="margin_end">6</property>
                       </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                      </packing>
                     </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">4</property>
-                    <property name="top_attach">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkSpinButton" id="h_spinbutton">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="max_length">2</property>
-                    <property name="invisible_char">●</property>
-                    <property name="activates_default">True</property>
-                    <property name="text">0</property>
-                    <property name="xalign">0.5</property>
-                    <property name="input_purpose">number</property>
-                    <property name="orientation">vertical</property>
-                    <property name="adjustment">h_adjustment</property>
-                    <property name="numeric">True</property>
-                    <property name="wrap">True</property>
-                    <signal name="changed" handler="spinbuttons_changed" object="ClocksAlarmSetupDialog" 
swapped="no"/>
-                    <signal name="output" handler="show_leading_zeros" object="ClocksAlarmSetupDialog" 
swapped="no"/>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">0</property>
-                  </packing>
-                </child>
-                <style>
-                  <class name="clocks-alarm-setup-time"/>
-                </style>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkRevealer" id="label_revealer">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkLabel" id="warn_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">You already have an alarm for this 
time.</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox">
-                <property name="visible">True</property>
-                <property name="margin">6</property>
-                <property name="valign">start</property>
-                <property name="orientation">vertical</property>
-                <property name="halign">center</property>
-                <child>
-                  <object class="GtkListBox" id="listbox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="selection_mode">none</property>
                     <child>
-                      <object class="HdyActionRow">
+                      <object class="GtkLabel" id="label2">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="activatable_widget">name_entry</property>
-                        <property name="title" translatable="yes">Name</property>
-                        <child type="action">
-                          <object class="GtkEntry" id="name_entry">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="valign">center</property>
-                            <property name="hexpand">True</property>
-                            <property name="activates_default">True</property>
-                            <signal name="changed" handler="entry_changed" object="ClocksAlarmSetupDialog" 
swapped="no"/>
-                          </object>
-                        </child>
+                        <property name="can_focus">False</property>
+                        <property name="label">∶</property>
                       </object>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="top_attach">0</property>
+                      </packing>
                     </child>
                     <child>
-                      <object class="HdyActionRow">
+                      <object class="GtkSpinButton" id="m_spinbutton">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="title" translatable="yes">Repeat</property>
+                        <property name="max_length">2</property>
+                        <property name="invisible_char">●</property>
+                        <property name="activates_default">True</property>
+                        <property name="text">0</property>
+                        <property name="xalign">0.5</property>
+                        <property name="input_purpose">number</property>
+                        <property name="orientation">vertical</property>
+                        <property name="adjustment">m_adjustment</property>
+                        <property name="numeric">True</property>
+                        <property name="wrap">True</property>
+                        <property name="width-request">60</property>
+                        <signal name="changed" handler="spinbuttons_changed" object="ClocksAlarmSetupDialog" 
swapped="no"/>
+                        <signal name="output" handler="show_leading_zeros" object="ClocksAlarmSetupDialog" 
swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="left_attach">3</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkStack" id="am_pm_stack">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_start">6</property>
+                        <property name="margin_end">6</property>
                         <child>
-                          <object class="GtkBox" id="day_buttons_box">
+                          <object class="GtkLabel" id="dummy_label2">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="halign">end</property>
-                            <property name="valign">center</property>
-                            <property name="margin-end">12</property>
-                            <property name="margin-start">12</property>
-                            <property name="margin-bottom">12</property>
-                            <child>
-                              <placeholder/>
-                            </child>
-                            <child>
-                              <placeholder/>
-                            </child>
-                            <child>
-                              <placeholder/>
-                            </child>
-                            <style>
-                              <class name="linked"/>
-                            </style>
                           </object>
                         </child>
                       </object>
+                      <packing>
+                        <property name="left_attach">4</property>
+                        <property name="top_attach">0</property>
+                      </packing>
                     </child>
                     <child>
-                      <object class="HdyActionRow">
+                      <object class="GtkSpinButton" id="h_spinbutton">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="activatable_widget">active_switch</property>
-                        <property name="title" translatable="yes">Active</property>
-                        <child type="action">
-                          <object class="GtkSwitch" id="active_switch">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="halign">start</property>
-                            <property name="valign">center</property>
-                            <signal name="notify::active" handler="active_changed" 
object="ClocksAlarmSetupDialog" swapped="no"/>
-                          </object>
-                        </child>
+                        <property name="max_length">2</property>
+                        <property name="invisible_char">●</property>
+                        <property name="activates_default">True</property>
+                        <property name="text">0</property>
+                        <property name="xalign">0.5</property>
+                        <property name="input_purpose">number</property>
+                        <property name="orientation">vertical</property>
+                        <property name="adjustment">h_adjustment</property>
+                        <property name="numeric">True</property>
+                        <property name="wrap">True</property>
+                        <property name="width-request">60</property>
+                        <signal name="changed" handler="spinbuttons_changed" object="ClocksAlarmSetupDialog" 
swapped="no"/>
+                        <signal name="output" handler="show_leading_zeros" object="ClocksAlarmSetupDialog" 
swapped="no"/>
                       </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
+                      </packing>
                     </child>
+                    <style>
+                      <class name="clocks-alarm-setup-time"/>
+                    </style>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkBox" id="delete_area">
-                    <property name="visible">False</property>
-                    <property name="no-show-all">True</property>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="margin">6</property>
                     <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkSeparator">
-                        <property name="visible">True</property>
-                        <property name="orientation">horizontal</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkListBox">
+                      <object class="GtkListBox" id="listbox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="selection_mode">none</property>
-                        <signal name="row-activated" handler="delete_alarm" swapped="no"/>
                         <child>
-                          <object class="GtkListBoxRow">
+                          <object class="HdyActionRow">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
+                            <property name="activatable_widget">name_entry</property>
+                            <property name="title" translatable="yes">Name</property>
+                            <child type="action">
+                              <object class="GtkEntry" id="name_entry">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="valign">center</property>
+                                <property name="hexpand">True</property>
+                                <property name="activates_default">True</property>
+                                <signal name="changed" handler="entry_changed" 
object="ClocksAlarmSetupDialog" swapped="no"/>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="ClocksAlarmDayPickerRow" id="repeats">
+                            <property name="visible">True</property>
+                            <signal name="days_changed" handler="days_changed" swapped="no" />
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="delete_area">
+                        <property name="visible">False</property>
+                        <property name="no-show-all">True</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkSeparator">
+                            <property name="visible">True</property>
+                            <property name="orientation">horizontal</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkListBox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="selection_mode">none</property>
+                            <signal name="row-activated" handler="delete_alarm" swapped="no"/>
                             <child>
-                              <object class="GtkLabel">
+                              <object class="GtkListBoxRow">
                                 <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="margin_left">12</property>
-                                <property name="margin_right">12</property>
-                                <property name="margin_top">18</property>
-                                <property name="margin_bottom">18</property>
-                                <property name="label" translatable="yes">Delete Alarm</property>
-                                <style>
-                                  <class name="destructive-action"/>
-                                </style>
+                                <property name="can_focus">True</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="margin_left">12</property>
+                                    <property name="margin_right">12</property>
+                                    <property name="margin_top">18</property>
+                                    <property name="margin_bottom">18</property>
+                                    <property name="label" translatable="yes">Delete Alarm</property>
+                                    <style>
+                                      <class name="destructive-action"/>
+                                    </style>
+                                  </object>
+                                </child>
                               </object>
                             </child>
                           </object>
                         </child>
                       </object>
                     </child>
+                    <style>
+                      <class name="frame"/>
+                    </style>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkRevealer" id="label_revealer">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="warn_label">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">You already have an alarm for this 
time.</property>
+                      </object>
+                    </child>
                   </object>
                 </child>
-                <style>
-                  <class name="frame"/>
-                </style>
               </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">1</property>
-              </packing>
             </child>
           </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
         </child>
       </object>
     </child>
diff --git a/data/ui/alarmtile.ui b/data/ui/alarmtile.ui
index cbf4cd4..45677a1 100644
--- a/data/ui/alarmtile.ui
+++ b/data/ui/alarmtile.ui
@@ -2,7 +2,6 @@
 <interface>
   <template class="ClocksAlarmRow" parent="HdyActionRow">
     <property name="visible">True</property>
-    <property name="can_focus">False</property>
     <child type="action">
       <object class="GtkSwitch" id="toggle">
         <property name="visible">True</property>
diff --git a/src/alarm.vala b/src/alarm.vala
index 13e0fad..e87553d 100644
--- a/src/alarm.vala
+++ b/src/alarm.vala
@@ -42,6 +42,8 @@ private class Item : Object, ContentItem {
 
     public bool selected { get; set; default = false; }
 
+    public bool editing { get; set; default = false; }
+
     public string id { get; construct set; }
 
     public string name {
@@ -82,7 +84,7 @@ private class Item : Object, ContentItem {
     [CCode (notify = false)]
     public bool active {
         get {
-            return _active;
+            return _active && !this.editing;
         }
 
         set {
@@ -182,7 +184,7 @@ private class Item : Object, ContentItem {
     }
 
     private bool compare_with_item (Item i) {
-        return (this.alarm_time.compare (i.alarm_time) == 0 && this.active && i.active);
+        return (this.alarm_time.compare (i.alarm_time) == 0 && (this.active || this.editing) && i.active);
     }
 
     public bool check_duplicate_alarm (List<Item> alarms) {
@@ -321,6 +323,175 @@ private class Row : Hdy.ActionRow {
     }
 }
 
+[GtkTemplate (ui = "/org/gnome/clocks/ui/alarmdaypickerrow.ui")]
+public class DayPickerRow : Hdy.ActionRow {
+    public bool monday {
+        get {
+            return days[Utils.Weekdays.Day.MON];
+        }
+
+        set {
+            days[Utils.Weekdays.Day.MON] = value;
+            update();
+        }
+    }
+
+    public bool tuesday {
+        get {
+            return days[Utils.Weekdays.Day.TUE];
+        }
+
+        set {
+            days[Utils.Weekdays.Day.TUE] = value;
+            update();
+        }
+    }
+
+    public bool wednesday {
+        get {
+            return days[Utils.Weekdays.Day.WED];
+        }
+
+        set {
+            days[Utils.Weekdays.Day.WED] = value;
+            update();
+        }
+    }
+
+    public bool thursday {
+        get {
+            return days[Utils.Weekdays.Day.THU];
+        }
+
+        set {
+            days[Utils.Weekdays.Day.THU] = value;
+            update();
+        }
+    }
+
+    public bool friday {
+        get {
+            return days[Utils.Weekdays.Day.FRI];
+        }
+
+        set {
+            days[Utils.Weekdays.Day.FRI] = value;
+            update();
+        }
+    }
+
+    public bool saturday {
+        get {
+            return days[Utils.Weekdays.Day.SAT];
+        }
+
+        set {
+            days[Utils.Weekdays.Day.SAT] = value;
+            update();
+        }
+    }
+
+    public bool sunday {
+        get {
+            return days[Utils.Weekdays.Day.SUN];
+        }
+
+        set {
+            days[Utils.Weekdays.Day.SUN] = value;
+            update();
+        }
+    }
+
+    public signal void days_changed ();
+
+    private Utils.Weekdays days = new Utils.Weekdays();
+
+    [GtkChild]
+    private Gtk.Popover popover;
+    [GtkChild]
+    private Gtk.Label current;
+
+    construct {
+        // Create actions to control propeties from menu items
+        var group = new SimpleActionGroup ();
+        group.add_action (new PropertyAction ("day-0", this, "monday"));
+        group.add_action (new PropertyAction ("day-1", this, "tuesday"));
+        group.add_action (new PropertyAction ("day-2", this, "wednesday"));
+        group.add_action (new PropertyAction ("day-3", this, "thursday"));
+        group.add_action (new PropertyAction ("day-4", this, "friday"));
+        group.add_action (new PropertyAction ("day-5", this, "saturday"));
+        group.add_action (new PropertyAction ("day-6", this, "sunday"));
+        insert_action_group ("repeats", group);
+
+        // Create an array with the weekday items with
+        // items[0] referencing the button for Monday, and so on.
+        var items = new GLib.MenuItem[7];
+        for (int i = 0; i < 7; i++) {
+            items[i] = new GLib.MenuItem (((Utils.Weekdays.Day) i).name (), "repeats.day-%i".printf(i));
+        }
+
+        // Add the items, starting with the first day of the week
+        // depending on the locale.
+        var first_weekday = Utils.Weekdays.Day.get_first_weekday ();
+        var menu = new GLib.Menu();
+        for (int i = 0; i < 7; i++) {
+            var day_number = (first_weekday + i) % 7;
+            menu.insert_item (-1, items[day_number]);
+        }
+
+        // Populate the popover with the menu
+        popover.bind_model (menu, null);
+
+        update ();
+    }
+
+    public override void activate () {
+        // Open the popover
+        popover.popup ();
+    }
+
+    [GtkCallback]
+    private void popover_done () {
+        days_changed ();
+    }
+
+    public void load (Utils.Weekdays current_days) {
+        // Copy in the days
+        for (int i = 0; i < 7; i++) {
+            days[(Utils.Weekdays.Day) i] = current_days[(Utils.Weekdays.Day) i];
+        }
+
+        // Make sure the popover updates
+        notify_property ("monday");
+        notify_property ("tuesday");
+        notify_property ("wednesday");
+        notify_property ("thursday");
+        notify_property ("friday");
+        notify_property ("saturday");
+        notify_property ("sunday");
+
+        // Sync the label to the new state
+        update ();
+    }
+
+    public Utils.Weekdays store () {
+        var new_days = new Utils.Weekdays ();
+
+        for (int i = 0; i < 7; i++) {
+            new_days[(Utils.Weekdays.Day) i] = days[(Utils.Weekdays.Day) i];
+        }
+
+        return new_days;
+    }
+
+    private void update () {
+        var repeats = days.get_label();
+        current.label = repeats.length > 0 ? repeats : _("None");
+
+        days_changed ();
+    }
+}
+
 [GtkTemplate (ui = "/org/gnome/clocks/ui/alarmsetupdialog.ui")]
 private class SetupDialog : Hdy.Dialog {
     private Utils.WallClock.Format format;
@@ -335,9 +506,7 @@ private class SetupDialog : Hdy.Dialog {
     private AmPmToggleButton am_pm_button;
     private Gtk.ToggleButton[] day_buttons;
     [GtkChild]
-    private Gtk.Switch active_switch;
-    [GtkChild]
-    private Gtk.Box day_buttons_box;
+    private DayPickerRow repeats;
     [GtkChild]
     private Gtk.Stack am_pm_stack;
     [GtkChild]
@@ -348,6 +517,10 @@ private class SetupDialog : Hdy.Dialog {
     private Gtk.Box delete_area;
     private List<Item> other_alarms;
 
+    static construct {
+        typeof(DayPickerRow).ensure();
+    }
+
     public SetupDialog (Gtk.Window parent, Item? alarm, ListModel all_alarms) {
         Object (transient_for: parent, title: alarm != null ? _("Edit Alarm") : _("New Alarm"), 
use_header_bar: 1);
 
@@ -366,27 +539,6 @@ private class SetupDialog : Hdy.Dialog {
         // Force LTR since we do not want to reverse [hh] : [mm]
         time_grid.set_direction (Gtk.TextDirection.LTR);
 
-        // Create an array with the weekday buttons with
-        // day_buttons[0] referencing the button for Monday, and so on.
-        // Also declare toogled signal connection.
-        day_buttons = new Gtk.ToggleButton[7];
-        for (int i = 0; i < 7; i++) {
-            var button = new Gtk.ToggleButton.with_label (Utils.Weekdays.abbreviation ((Utils.Weekdays.Day) 
i));
-            day_buttons[i] = button;
-
-            day_buttons[i].toggled.connect (() => {
-                avoid_duplicate_alarm ();
-            });
-        }
-
-        // Pack the buttons, starting with the first day of the week
-        // depending on the locale.
-        var first_weekday = Utils.Weekdays.get_first_weekday ();
-        for (int i = 0; i < 7; i++) {
-            var day_number = (first_weekday + i) % 7;
-            day_buttons_box.pack_start (day_buttons[day_number]);
-        }
-
         format = Utils.WallClock.get_default ().format;
         am_pm_button = new AmPmToggleButton ();
         am_pm_button.clicked.connect (() => {
@@ -450,21 +602,14 @@ private class SetupDialog : Hdy.Dialog {
         // Set the name.
         name_entry.set_text (name);
 
-        // Set the toggle buttons for weekdays.
         if (days != null) {
-            for (int i = 0; i < 7; i++) {
-                day_buttons[i].active = days.get ((Utils.Weekdays.Day) i);
-            }
+            repeats.load (days);
         }
-
-        // Set On/Off switch.
-        active_switch.active = active;
     }
 
     // Sets alarm according to the current dialog settings.
     public void apply_to_alarm (Item alarm) {
         var name = name_entry.get_text ();
-        var active = active_switch.active;
         var hour = h_spinbutton.get_value_as_int ();
         var minute = m_spinbutton.get_value_as_int ();
         if (format == Utils.WallClock.Format.TWELVE) {
@@ -478,15 +623,11 @@ private class SetupDialog : Hdy.Dialog {
 
         AlarmTime time = { hour, minute };
 
-        Utils.Weekdays days = new Utils.Weekdays ();
-        for (int i = 0; i < 7; i++) {
-            days.set ((Utils.Weekdays.Day) i, day_buttons[i].active);
-        }
+        var days = repeats.store ();
 
         alarm.freeze_notify ();
 
         alarm.name = name;
-        alarm.active = active;
         alarm.time = time;
         alarm.days = days;
 
@@ -506,17 +647,17 @@ private class SetupDialog : Hdy.Dialog {
     }
 
     [GtkCallback]
-    private void entry_changed (Gtk.Editable editable) {
+    private void days_changed () {
         avoid_duplicate_alarm ();
     }
 
     [GtkCallback]
-    private void spinbuttons_changed (Gtk.Editable editable) {
+    private void entry_changed (Gtk.Editable editable) {
         avoid_duplicate_alarm ();
     }
 
     [GtkCallback]
-    private void active_changed () {
+    private void spinbuttons_changed (Gtk.Editable editable) {
         avoid_duplicate_alarm ();
     }
 
@@ -708,18 +849,16 @@ public class Face : Gtk.Stack, Clocks.Clock {
         var dialog = new SetupDialog ((Gtk.Window) get_toplevel (), alarm, alarms);
 
         // Disable alarm while editing it and remember the original active state.
-        var saved_active = alarm.active;
-        alarm.active = false;
+        alarm.editing = true;
 
         dialog.response.connect ((dialog, response) => {
+            alarm.editing = false;
             if (response == 1) {
                 ((SetupDialog) dialog).apply_to_alarm (alarm);
                 save ();
             } else if (response == 2) {
                 alarms.delete_item (alarm);
                 save ();
-            } else {
-                alarm.active = saved_active;
             }
             dialog.destroy ();
         });
diff --git a/src/utils.vala b/src/utils.vala
index d83f3ca..27cf2e2 100644
--- a/src/utils.vala
+++ b/src/utils.vala
@@ -151,6 +151,9 @@ public class WallClock : Object {
 }
 
 public class Weekdays {
+    private static string[] abbreviations = null;
+    private static string[] names = null;
+
     public enum Day {
         MON,
         TUE,
@@ -158,7 +161,60 @@ public class Weekdays {
         THU,
         FRI,
         SAT,
-        SUN
+        SUN;
+
+        private const string[] plurals = {
+            N_("Mondays"),
+            N_("Tuesdays"),
+            N_("Wednesdays"),
+            N_("Thursdays"),
+            N_("Fridays"),
+            N_("Saturdays"),
+            N_("Sundays")
+        };
+    
+        public string plural () {
+            return _(plurals[this]);
+        }
+    
+        public string abbreviation () {
+            // lazy init because we cannot rely on class init being
+            // called for us (at least in the current version of vala)
+            if (abbreviations == null) {
+                abbreviations = {
+                     (new GLib.DateTime.utc (1, 1, 1, 0, 0, 0)).format ("%a"),
+                     (new GLib.DateTime.utc (1, 1, 2, 0, 0, 0)).format ("%a"),
+                     (new GLib.DateTime.utc (1, 1, 3, 0, 0, 0)).format ("%a"),
+                     (new GLib.DateTime.utc (1, 1, 4, 0, 0, 0)).format ("%a"),
+                     (new GLib.DateTime.utc (1, 1, 5, 0, 0, 0)).format ("%a"),
+                     (new GLib.DateTime.utc (1, 1, 6, 0, 0, 0)).format ("%a"),
+                     (new GLib.DateTime.utc (1, 1, 7, 0, 0, 0)).format ("%a"),
+                };
+            }
+            return abbreviations[this];
+        }
+
+        public string name () {
+            // lazy init because we cannot rely on class init being
+            // called for us (at least in the current version of vala)
+            if (names == null) {
+                names = {
+                     (new GLib.DateTime.utc (1, 1, 1, 0, 0, 0)).format ("%A"),
+                     (new GLib.DateTime.utc (1, 1, 2, 0, 0, 0)).format ("%A"),
+                     (new GLib.DateTime.utc (1, 1, 3, 0, 0, 0)).format ("%A"),
+                     (new GLib.DateTime.utc (1, 1, 4, 0, 0, 0)).format ("%A"),
+                     (new GLib.DateTime.utc (1, 1, 5, 0, 0, 0)).format ("%A"),
+                     (new GLib.DateTime.utc (1, 1, 6, 0, 0, 0)).format ("%A"),
+                     (new GLib.DateTime.utc (1, 1, 7, 0, 0, 0)).format ("%A"),
+                };
+            }
+            return names[this];
+        }
+
+        public static Day get_first_weekday () {
+            var d = clocks_cutils_get_week_start ();
+            return (Day) ((d + 6) % 7);
+        }
     }
 
     private const bool[] WEEKDAYS = {
@@ -169,57 +225,37 @@ public class Weekdays {
         false, false, false, false, false, true, true
     };
 
-    private const string[] PLURALS = {
-        N_("Mondays"),
-        N_("Tuesdays"),
-        N_("Wednesdays"),
-        N_("Thursdays"),
-        N_("Fridays"),
-        N_("Saturdays"),
-        N_("Sundays")
+    const bool[] none = {
+        false, false, false, false, false, false, false
     };
 
-    private static string[] abbreviations = null;
+    const bool[] all = {
+        true, true, true, true, true, true, true
+    };
 
-    public static Day get_first_weekday () {
-        var d = clocks_cutils_get_week_start ();
-        return (Day) ((d + 6) % 7);
-    }
+    private bool[] days = none;
 
-    public static string plural (Day d) {
-        assert (d >= 0 && d < 7);
-        return _(PLURALS[d]);
+    public bool empty {
+        get {
+            return (days_equal (none));
+        }
     }
-
-    public static string abbreviation (Day d) {
-        assert (d >= 0 && d < 7);
-
-        // lazy init because we cannot rely on class init being
-        // called for us (at least in the current version of vala)
-        if (abbreviations == null) {
-            abbreviations = {
-                 (new GLib.DateTime.utc (1, 1, 1, 0, 0, 0)).format ("%a"),
-                 (new GLib.DateTime.utc (1, 1, 2, 0, 0, 0)).format ("%a"),
-                 (new GLib.DateTime.utc (1, 1, 3, 0, 0, 0)).format ("%a"),
-                 (new GLib.DateTime.utc (1, 1, 4, 0, 0, 0)).format ("%a"),
-                 (new GLib.DateTime.utc (1, 1, 5, 0, 0, 0)).format ("%a"),
-                 (new GLib.DateTime.utc (1, 1, 6, 0, 0, 0)).format ("%a"),
-                 (new GLib.DateTime.utc (1, 1, 7, 0, 0, 0)).format ("%a"),
-            };
+    
+    public bool is_weekdays {
+        get {
+            return (days_equal (WEEKDAYS));
         }
-        return abbreviations[d];
     }
-
-    private bool[] days = {
-        false, false, false, false, false, false, false
-    };
-
-    public Weekdays () {
+    
+    public bool is_weekends {
+        get {
+            return (days_equal (WEEKENDS));
+        }
     }
 
-    public bool empty {
+    public bool is_all {
         get {
-            return (days_equal ({false, false, false, false, false, false, false}));
+            return (days_equal (all));
         }
     }
 
@@ -254,7 +290,7 @@ public class Weekdays {
         if (n == 0) {
             r = "";
         } else if (n == 1) {
-            r = plural ((Day) first);
+            r = ((Day) first).plural ();
         } else if (n == 7) {
             r = _("Every Day");
         } else if (days_equal (WEEKDAYS)) {
@@ -264,9 +300,9 @@ public class Weekdays {
         } else {
             string[] abbrs = {};
             for (int i = 0; i < 7; i++) {
-                Day d = (get_first_weekday () + i) % 7;
+                Day d = (Day.get_first_weekday () + i) % 7;
                 if (get (d)) {
-                    abbrs += abbreviation (d);
+                    abbrs += d.abbreviation ();
                 }
             }
             r = string.joinv (", ", abbrs);



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