From 911d13b61087e871cf908d75aec7e779db0a381b Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Tue, 2 Jul 2019 23:48:48 +0200 Subject: [PATCH] contact-editor: fix birthday picker and make it adaptive This fixes the birthday picker and imporves some small bugs. It also makes the picker adaptive by moving the entries to a popover --- src/contacts-contact-editor.vala | 252 +++++++++++++++++++++---------- src/contacts-contact-pane.vala | 2 +- 2 files changed, 177 insertions(+), 77 deletions(-) diff --git a/src/contacts-contact-editor.vala b/src/contacts-contact-editor.vala index f007f0ec..7450ee39 100644 --- a/src/contacts-contact-editor.vala +++ b/src/contacts-contact-editor.vala @@ -19,6 +19,166 @@ using Gtk; using Folks; using Gee; + +public class Contacts.BirthdayEditor : Box { + public bool use_popover { get; set; } + private SpinButton day_spin; + private ComboBoxText month_combo; + private SpinButton year_spin; + private Widget birthday = null; + + public signal void changed (); + delegate void AdjustingDateFn (); + + public DateTime get_birthday () { + return new DateTime.local (year_spin.get_value_as_int (), + month_combo.get_active () + 1, + day_spin.get_value_as_int (), + 0, 0, 0).to_utc (); + } + + private void update() { + if (birthday is MenuButton) { + (birthday as MenuButton).set_label(get_birthday ().to_local ().format ("%x")); + } + } + + construct { + notify["use-popover"].connect(() => { + if (use_popover) { + if (birthday is Grid) { + var grid = birthday as Grid; + foreach (var child in grid.get_children()) { + grid.remove(child); + } + birthday.destroy(); + birthday = null; + create_popover (get_birthday ()); + show_all(); + } + } else { + if (birthday is MenuButton) { + var grid = (birthday as MenuButton).get_popover ().get_child () as Grid; + foreach (var child in grid.get_children()) { + grid.remove(child); + } + birthday.destroy(); + birthday = null; + create_row (); + show_all(); + } + } + }); + } + + public BirthdayEditor (DateTime birthday, bool use_popover) { + this.use_popover = use_popover; + + day_spin = new SpinButton.with_range (1.0, 31.0, 1.0); + day_spin.set_digits (0); + day_spin.numeric = true; + day_spin.set_value ((double)birthday.to_local ().get_day_of_month ()); + + month_combo = new ComboBoxText (); + var january = new DateTime.local (1, 1, 1, 1, 1, 1); + for (int i = 0; i < 12; i++) { + var month = january.add_months (i); + month_combo.append_text (month.format ("%B")); + } + month_combo.set_active (birthday.to_local ().get_month () - 1); + month_combo.hexpand = true; + + year_spin = new SpinButton.with_range (1800, 3000, 1); + year_spin.set_digits (0); + year_spin.numeric = true; + year_spin.set_value ((double)birthday.to_local ().get_year ()); + + if (this.use_popover) { + create_popover (birthday); + } else { + create_row (); + } + + AdjustingDateFn fn = () => { + int[] month_of_31 = {3, 5, 8, 10}; + if (month_combo.get_active () in month_of_31) { + day_spin.set_range (1, 30); + } else if (month_combo.get_active () == 1) { + if (year_spin.get_value_as_int () % 4 == 0 && + year_spin.get_value_as_int () % 100 != 0) { + day_spin.set_range (1, 29); + } else { + day_spin.set_range (1, 28); + } + } + }; + + /* adjusting day_spin value using selected month/year constraints*/ + fn (); + + /* Notify change to upper layer */ + day_spin.value_changed.connect (() => { + changed(); + update(); + }); + month_combo.changed.connect (() => { + changed(); + update(); + + /* adjusting day_spin value using selected month constraints*/ + fn (); + }); + year_spin.value_changed.connect (() => { + changed(); + update(); + + fn (); + }); + } + + private void create_popover(DateTime birthday) { + var box = new Grid (); + box.set_column_spacing (12); + box.set_row_spacing (12); + + var birthday_button = new MenuButton (); + birthday_button.set_label (birthday.to_local ().format ("%x")); + birthday_button.set_hexpand (true); + Label day = new Label(_("Day")); + day.set_halign (Align.END); + box.attach (day, 0, 0); + box.attach (day_spin, 1, 0); + Label month = new Label(_("Month")); + month.set_halign (Align.END); + box.attach (month, 0, 1); + box.attach (month_combo, 1, 1); + Label year = new Label(_("Year")); + year.set_halign (Align.END); + box.attach (year, 0, 2); + box.attach (year_spin, 1, 2); + + box.margin = 12; + box.show_all (); + + var popover = new Popover (birthday_button); + popover.add (box); + + birthday_button.set_popover (popover); + add (birthday_button); + this.birthday = birthday_button; + } + + private void create_row () { + var box = new Grid (); + box.set_column_spacing (12); + box.add (day_spin); + box.add (month_combo); + box.add (year_spin); + add (box); + birthday = box; + } +} + public class Contacts.AddressEditor : Box { public Entry? entries[7]; /* must be the number of elements in postal_element_props */ public PostalAddressFieldDetails details; @@ -105,6 +265,8 @@ public class Contacts.ContactEditor : ContactForm { /* the key of the hash_map is the uid of the persona */ private HashMap> writable_personas; + public bool narrow { get; set; default = true; } + public bool has_birthday_row { get; private set; default = false; } @@ -121,7 +283,6 @@ public class Contacts.ContactEditor : ContactForm { this.writable_personas = new HashMap> (); this.container_grid.size_allocate.connect(on_container_grid_size_allocate); - bool small = false; int old_width = this.get_allocated_width (); Image trash_icon = new Image.from_icon_name ("user-trash-symbolic", IconSize.MENU); string label = _("Remove Contact"); @@ -130,16 +291,16 @@ public class Contacts.ContactEditor : ContactForm { size_allocate.connect(() => { int width = this.get_allocated_width (); if (old_width != width) { - if (!small && width <= RESIZE_WIDTH) { + if (!narrow && width <= RESIZE_WIDTH) { this.avatar.set_display_size (PROFILE_SMALL_SIZE); this.remove_button.image = trash_icon; this.remove_button.label = null; - small = true; - } else if (small && width > RESIZE_WIDTH) { + narrow = true; + } else if (narrow && width > RESIZE_WIDTH) { this.avatar.set_display_size (PROFILE_SIZE); this.remove_button.image = null; this.remove_button.label = label; - small = false; + narrow = false; } old_width = this.get_allocated_width (); } @@ -299,18 +460,8 @@ public class Contacts.ContactEditor : ContactForm { Value get_value_from_birthday (HashMap rows) { var new_value = Value (typeof (DateTime)); foreach (var row_entry in rows.entries) { - var box = container_grid.get_child_at (1, row_entry.key) as Grid; - var day_spin = box.get_child_at (0, 0) as SpinButton; - var combo = box.get_child_at (1, 0) as ComboBoxText; - var year_spin = box.get_child_at (2, 0) as SpinButton; - - var bday = new DateTime.local (year_spin.get_value_as_int (), - combo.get_active () + 1, - day_spin.get_value_as_int (), - 0, 0, 0); - bday = bday.to_utc (); - - new_value.set_boxed (bday); + var box = container_grid.get_child_at (1, row_entry.key) as BirthdayEditor; + new_value.set_boxed (box.get_birthday()); } return new_value; } @@ -501,8 +652,6 @@ public class Contacts.ContactEditor : ContactForm { focus_widget = value_text; } - delegate void AdjustingDateFn(); - void attach_row_for_birthday (string title, AbstractFieldDetails? details, DateTime birthday, int row) { var title_label = new Label (title); title_label.set_hexpand (false); @@ -510,70 +659,21 @@ public class Contacts.ContactEditor : ContactForm { title_label.margin_end = 6; container_grid.attach (title_label, 0, row, 1, 1); - var box = new Grid (); - box.set_column_spacing (12); - var day_spin = new SpinButton.with_range (1.0, 31.0, 1.0); - day_spin.set_digits (0); - day_spin.numeric = true; - day_spin.set_value ((double)birthday.to_local ().get_day_of_month ()); - - var month_combo = new ComboBoxText (); - var january = new DateTime.local (1, 1, 1, 1, 1, 1); - for (int i = 0; i < 12; i++) { - var month = january.add_months (i); - month_combo.append_text (month.format ("%B")); - } - month_combo.set_active (birthday.to_local ().get_month () - 1); - month_combo.hexpand = true; - - var year_spin = new SpinButton.with_range (1800, 3000, 1); - year_spin.set_digits (0); - year_spin.numeric = true; - year_spin.set_value ((double)birthday.to_local ().get_year ()); - - box.add (day_spin); - box.add (month_combo); - box.add (year_spin); - + var box = new BirthdayEditor (birthday, narrow); + bind_property("narrow", box, "use-popover"); container_grid.attach (box, 1, row, 1, 1); + box.changed.connect(() => { + set_field_changed (get_current_row (box)); + }); var delete_button = new Button.from_icon_name ("user-trash-symbolic", IconSize.MENU); delete_button.get_accessible ().set_name (_("Delete field")); container_grid.attach (delete_button, 2, row, 1, 1); - AdjustingDateFn fn = () => { - int[] month_of_31 = {3, 5, 8, 10}; - if (month_combo.get_active () in month_of_31) { - day_spin.set_range (1, 30); - } else if (month_combo.get_active () == 1) { - if (year_spin.get_value_as_int () % 4 == 0 && - year_spin.get_value_as_int () % 100 != 0) { - day_spin.set_range (1, 29); - } else { - day_spin.set_range (1, 28); - } - } - }; - - /* Notify change to upper layer */ - day_spin.changed.connect (() => { - set_field_changed (get_current_row (day_spin)); - }); - month_combo.changed.connect (() => { - set_field_changed (get_current_row (month_combo)); - - /* adjusting day_spin value using selected month constraints*/ - fn (); - }); - year_spin.changed.connect (() => { - set_field_changed (get_current_row (year_spin)); - - fn (); - }); delete_button.clicked.connect (() => { - remove_row (get_current_row (delete_button)); - has_birthday_row = false; - }); + remove_row (get_current_row (delete_button)); + has_birthday_row = false; + }); } void attach_row_for_address (int row, TypeSet type_set, PostalAddressFieldDetails details, string? type = null) { diff --git a/src/contacts-contact-pane.vala b/src/contacts-contact-pane.vala index a905fd12..d4b46af7 100644 --- a/src/contacts-contact-pane.vala +++ b/src/contacts-contact-pane.vala @@ -21,7 +21,7 @@ using Gee; const int PROFILE_SIZE = 128; const int PROFILE_SMALL_SIZE = 95; -const int RESIZE_WIDTH = 450; +const int RESIZE_WIDTH = 600; /** * The ContactPage is the right pane. It consists of 3 possible pages: -- GitLab