[california/wip/734698-agenda] Allow for moving the Agenda chron window back and forth, expand
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/734698-agenda] Allow for moving the Agenda chron window back and forth, expand
- Date: Mon, 8 Dec 2014 22:43:30 +0000 (UTC)
commit b5dab5261c8444a947a9d228cfbdb90981b38936
Author: Jim Nelson <jim yorba org>
Date: Mon Dec 8 14:43:02 2014 -0800
Allow for moving the Agenda chron window back and forth, expand
.../backing-calendar-subscription-manager.vala | 5 +
src/calendar/calendar-span.vala | 38 ++++++++++
src/toolkit/toolkit-listbox-model.vala | 9 ++
src/view/agenda/agenda-controller.vala | 78 ++++++++++++++++++--
src/view/agenda/agenda-event-row.vala | 2 +-
5 files changed, 123 insertions(+), 9 deletions(-)
---
diff --git a/src/backing/backing-calendar-subscription-manager.vala
b/src/backing/backing-calendar-subscription-manager.vala
index b86c78d..68fa314 100644
--- a/src/backing/backing-calendar-subscription-manager.vala
+++ b/src/backing/backing-calendar-subscription-manager.vala
@@ -126,6 +126,11 @@ public class CalendarSubscriptionManager : BaseObject {
* are unguaranteed if called while start_async() is executing.
*
* If expanded_time is within the current window, nothing happens.
+ *
+ * TODO: Currently the subscription manager will expand the range by creating a new
+ * { link CalendarSubscription} for the new dates. This can be inefficient when dealing with
+ * lots of small ranges. A better solution would be to create wider ranges and filter out
+ * events outside of the specified window.
*/
public async void expand_window_async(Calendar.ExactTime expanded_time) {
if (expanded_time in window)
diff --git a/src/calendar/calendar-span.vala b/src/calendar/calendar-span.vala
index 30d2997..e5f2355 100644
--- a/src/calendar/calendar-span.vala
+++ b/src/calendar/calendar-span.vala
@@ -194,6 +194,44 @@ public abstract class Span : BaseObject {
}
/**
+ * Returns a { link DateSpan} that represents this { link Span} with the { link start_date}
+ * set to the supplied { link Date}.
+ *
+ * If the new start_date is the same or later than the { link end_date}, a one-day Span is
+ * returned that matches the supplied Date.
+ *
+ * If the new start date is outside the range of this Span, a DateSpan for this Span is
+ * returned, i.e. this is just like calling { link to_date_span}.
+ *
+ * @see reduce_from_end
+ */
+ public DateSpan reduce_from_start(Calendar.Date new_start_date) {
+ if (!has_date(new_start_date))
+ return to_date_span();
+
+ return new DateSpan(new_start_date, end_date);
+ }
+
+ /**
+ * Returns a { link DateSpan} that represents this { link Span} with the { link end_date}
+ * set to the supplied { link Date}.
+ *
+ * If the new end_date is the same or earlier than the { link start_date}, a one-day Span is
+ * returned that matches the supplied Date.
+ *
+ * If the new end date is outside the range of this Span, a DateSpan for this Span is
+ * returned, i.e. this is just like calling { link to_date_span}.
+ *
+ * @see reduce_from_start
+ */
+ public DateSpan reduce_from_end(Calendar.Date new_end_date) {
+ if (!has_date(new_end_date))
+ return to_date_span();
+
+ return new DateSpan(start_date, new_end_date);
+ }
+
+ /**
* True if the { link Span} contains the specified { link Date}.
*/
public bool has_date(Date date) {
diff --git a/src/toolkit/toolkit-listbox-model.vala b/src/toolkit/toolkit-listbox-model.vala
index 8595bd6..10d92a3 100644
--- a/src/toolkit/toolkit-listbox-model.vala
+++ b/src/toolkit/toolkit-listbox-model.vala
@@ -126,9 +126,18 @@ public class ListBoxModel<G> : BaseObject {
// item -> Gtk.ListBoxRow, with MutableWidget support
Gtk.ListBoxRow row = new Gtk.ListBoxRow();
Gtk.Widget widget = model_presentation(item);
+
+ // allow for external callers to make the ListBoxRow visible via their supplied widget's
+ // visibility flag ... this is necessary because setting the presentation widget to invisible
+ // leaves the row's visible and taking up a little space for border and margin and such
+ widget.bind_property("visible", row, "visible",
+ BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
+
+ // if widget is mutable, watch for that
MutableWidget? mutable = widget as MutableWidget;
if (mutable != null)
mutable.mutated.connect(() => { row.changed(); });
+
row.add(widget);
// mappings
diff --git a/src/view/agenda/agenda-controller.vala b/src/view/agenda/agenda-controller.vala
index 66e0aba..3b85944 100644
--- a/src/view/agenda/agenda-controller.vala
+++ b/src/view/agenda/agenda-controller.vala
@@ -108,13 +108,14 @@ public class Controller : BaseObject, View.Controllable {
* @inheritDoc
*/
public void next() {
+ reduce_subscriptions_start(current_span.start_date.adjust_by(1, Calendar.DateUnit.DAY));
}
/**
* @inheritDoc
*/
public void previous() {
- expand_subscriptions(current_span.start_date.adjust(-1));
+ expand_subscriptions(current_span.start_date.adjust_by(-1, Calendar.DateUnit.DAY));
}
/**
@@ -156,10 +157,28 @@ public class Controller : BaseObject, View.Controllable {
expand_subscriptions(current_span.end_date.adjust_by(1, Calendar.DateUnit.MONTH));
}
+ private Iterable<DateRow> traverse_date_rows() {
+ return traverse<Calendar.Date>(listbox_model.all())
+ .map_nonnull<DateRow>(date => listbox_model.get_widget_for_item(date) as DateRow);
+ }
+
+ // Make existing DateRow widgets visible depending on if they're in the current_span; don't
+ // remove them to allow them to continue to receive event notifications in case the window is
+ // widened again to show them
+ private void show_hide_date_rows() {
+ traverse_date_rows()
+ .iterate(date_row => date_row.visible = date_row.date in current_span);
+ }
+
+ private void clear_date_rows() {
+ traverse_date_rows()
+ .iterate(date_row => listbox_model.remove(date_row.date));
+ }
+
private void reset_subscriptions(Calendar.DateSpan new_span) {
current_span = new_span;
- listbox_model.clear();
+ clear_date_rows();
subscriptions = new Backing.CalendarSubscriptionManager(
current_span.to_exact_time_span(Calendar.Timezone.local));
@@ -177,8 +196,50 @@ public class Controller : BaseObject, View.Controllable {
private void expand_subscriptions(Calendar.Date expansion) {
current_span = current_span.expand(expansion);
- subscriptions.expand_window_async.begin(
- expansion.to_exact_time_span(Calendar.Timezone.local).start_exact_time);
+ // make previously invisible widgets (due to window reduction) visible again if in new span
+ show_hide_date_rows();
+
+ // to avoid adding a lot of little expansions (which is expensive), add them a month at a
+ // time ... first check if subscription expansion even necessary, and if so, on which ends
+ // of the span ... first, convert to DateSpan
+ Calendar.DateSpan sub_span = new Calendar.DateSpan.from_exact_time_span(
+ subscriptions.window.to_timezone(Calendar.Timezone.local));
+
+ bool expanded = false;
+
+ // if necessary, walk the subscription start date back one month from requested date
+ if (!(current_span.start_date in sub_span)) {
+ Calendar.Date new_sub_start = sub_span.start_date.adjust_by(-1, Calendar.DateUnit.MONTH);
+ if (current_span.start_date.compare_to(new_sub_start) < 0)
+ new_sub_start = current_span.start_date;
+
+ subscriptions.expand_window_async.begin(
+ new_sub_start.to_exact_time_span(Calendar.Timezone.local).start_exact_time);
+ expanded = true;
+ }
+
+ // do the same for the subscription end date
+ if (!(current_span.end_date in sub_span)) {
+ Calendar.Date new_sub_end = sub_span.end_date.adjust_by(1, Calendar.DateUnit.MONTH);
+ if (current_span.end_date.compare_to(new_sub_end) > 0)
+ new_sub_end = current_span.end_date;
+
+ subscriptions.expand_window_async.begin(
+ new_sub_end.to_exact_time_span(Calendar.Timezone.local).end_exact_time);
+ expanded = true;
+ }
+
+ if (expanded)
+ debug("Agenda subscription window expanded to %s", subscriptions.window.to_string());
+
+ update_view_details();
+ }
+
+ private void reduce_subscriptions_start(Calendar.Date new_start) {
+ current_span = current_span.reduce_from_start(new_start);
+
+ // make previously invisible widgets (due to window reduction) visible again if in new span
+ show_hide_date_rows();
update_view_details();
}
@@ -203,10 +264,8 @@ public class Controller : BaseObject, View.Controllable {
private void on_calendar_visibility_changed(Object o, ParamSpec pspec) {
Backing.CalendarSource calendar = (Backing.CalendarSource) o;
- foreach (Calendar.Date date in listbox_model.all()) {
- DateRow date_row = (DateRow) listbox_model.get_widget_for_item(date);
- date_row.notify_calendar_visibility_changed(calendar);
- }
+ traverse_date_rows()
+ .iterate(date_row => date_row.notify_calendar_visibility_changed(calendar));
}
private void on_instance_added_or_altered(Component.Instance instance) {
@@ -221,6 +280,9 @@ public class Controller : BaseObject, View.Controllable {
DateRow date_row = (DateRow) listbox_model.get_widget_for_item(date);
date_row.add_event(event);
+
+ // possible to be notified of Event outside of current_span; see reduce_subscriptions()
+ date_row.visible = date in current_span;
}
}
diff --git a/src/view/agenda/agenda-event-row.vala b/src/view/agenda/agenda-event-row.vala
index 6580510..af1d4cc 100644
--- a/src/view/agenda/agenda-event-row.vala
+++ b/src/view/agenda/agenda-event-row.vala
@@ -7,7 +7,7 @@
namespace California.View.Agenda {
[GtkTemplate (ui = "/org/yorba/california/rc/view-agenda-event-row.ui")]
-private class EventRow : Gtk.Box {
+private class EventRow : Gtk.Box, Toolkit.MutableWidget {
private const Calendar.WallTime.PrettyFlag TIME_PRETTY_FLAGS = Calendar.WallTime.PrettyFlag.NONE;
private static Gtk.SizeGroup time_label_size_group;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]