[california] Don't stack events in Week view with same start/end time: Bug #738980



commit bfa058e54f37fd218fb9124c8923365746fa47f0
Author: Jim Nelson <jim yorba org>
Date:   Wed Oct 22 18:41:58 2014 -0700

    Don't stack events in Week view with same start/end time: Bug #738980
    
    If one event has an end time exactly the same as another's start time,
    they should not be stacked but presented serially in the Week view,
    as technically they don't overlap time-wise.  (In other words, the
    test for time spans coinciding needs to use exclusive, not inclusive,
    end times.)

 src/Makefile.am                               |    1 +
 src/calendar/calendar-exact-time-span.vala    |   17 +++++-
 src/tests/tests-calendar-exact-time-span.vala |   69 +++++++++++++++++++++++++
 src/tests/tests.vala                          |    1 +
 src/view/week/week-day-pane.vala              |    5 ++
 5 files changed, 91 insertions(+), 2 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 270ff7a..1bb8c3b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -116,6 +116,7 @@ california_VALASOURCES = \
        tests/tests.vala \
        tests/tests-calendar-date.vala \
        tests/tests-calendar-exact-time.vala \
+       tests/tests-calendar-exact-time-span.vala \
        tests/tests-calendar-month-of-year.vala \
        tests/tests-calendar-month-span.vala \
        tests/tests-calendar-wall-time.vala \
diff --git a/src/calendar/calendar-exact-time-span.vala b/src/calendar/calendar-exact-time-span.vala
index e26d4f4..355bb8a 100644
--- a/src/calendar/calendar-exact-time-span.vala
+++ b/src/calendar/calendar-exact-time-span.vala
@@ -107,12 +107,25 @@ public class ExactTimeSpan : BaseObject, Gee.Comparable<ExactTimeSpan>, Gee.Hash
             && end_exact_time.compare_to(exact_time) >= 0;
     }
     
+    private static bool coincides_with_compare(Calendar.ExactTime start, Calendar.ExactTime end,
+        Calendar.ExactTime exact_time) {
+        return start.compare_to(exact_time) <= 0 && end.compare_to(exact_time) >= 0;
+    }
+    
     /**
      * Returns true if there's a union between the two { link ExactTimeSpan}s.
+     *
+     * Note that a time span ending at the exact same time as the other starts (with one-second
+     * accuracy) does ''not'' count as overlapping, i.e. the end times are exclusive.
      */
     public bool coincides_with(ExactTimeSpan other) {
-        return contains(other.start_exact_time) || contains(other.end_exact_time)
-            || other.contains(start_exact_time) || other.contains(end_exact_time);
+        Calendar.ExactTime end_excl = end_exact_time.adjust_time(-1, TimeUnit.SECOND);
+        Calendar.ExactTime other_end_excl = other.end_exact_time.adjust_time(-1, TimeUnit.SECOND);
+        
+        return coincides_with_compare(start_exact_time, end_excl, other.start_exact_time)
+            || coincides_with_compare(start_exact_time, end_excl, other_end_excl)
+            || coincides_with_compare(other.start_exact_time, other_end_excl, start_exact_time)
+            || coincides_with_compare(other.start_exact_time, other_end_excl, end_excl);
     }
     
     /**
diff --git a/src/tests/tests-calendar-exact-time-span.vala b/src/tests/tests-calendar-exact-time-span.vala
new file mode 100644
index 0000000..e4653b3
--- /dev/null
+++ b/src/tests/tests-calendar-exact-time-span.vala
@@ -0,0 +1,69 @@
+/* Copyright 2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later).  See the COPYING file in this distribution.
+ */
+
+namespace California.Tests {
+
+internal class CalendarExactTimeSpan : UnitTest.Harness {
+    public CalendarExactTimeSpan() {
+        add_case("coincide-true", coincide_true);
+        add_case("coincide-true-reversed", coincide_true_reversed);
+        add_case("coincide-false", coincide_false);
+        add_case("coincide-false-reversed", coincide_false_reversed);
+        add_case("coincide-end-start-same", coincide_end_start_same);
+        add_case("coincide-start-end-same", coincide_start_end_same);
+        add_case("coincide-same", coincide_same);
+    }
+    
+    protected override void setup() throws Error {
+        Calendar.init();
+    }
+    
+    protected override void teardown() {
+        Calendar.terminate();
+    }
+    
+    private Calendar.ExactTime mktime(string str) {
+        Calendar.WallTime? wall_time = Calendar.WallTime.parse(str, null);
+        assert(wall_time != null);
+        
+        return new Calendar.ExactTime(Calendar.Timezone.local, Calendar.System.today, wall_time);
+    }
+    
+    private Calendar.ExactTimeSpan mkspan(string start, string end) {
+        return new Calendar.ExactTimeSpan(mktime(start), mktime(end));
+    }
+    
+    private bool coincide_true() throws Error {
+        return mkspan("1pm", "2pm").coincides_with(mkspan("1:30pm", "2:30pm"));
+    }
+    
+    private bool coincide_true_reversed() throws Error {
+        return mkspan("1:30pm", "2:30pm").coincides_with(mkspan("1pm", "2pm"));
+    }
+    
+    private bool coincide_false() throws Error {
+        return !mkspan("1pm", "2pm").coincides_with(mkspan("2:30pm", "3:30pm"));
+    }
+    
+    private bool coincide_false_reversed() throws Error {
+        return !mkspan("2:30pm", "3:30pm").coincides_with(mkspan("1pm", "2pm"));
+    }
+    
+    private bool coincide_end_start_same() throws Error {
+        return !mkspan("1pm", "2pm").coincides_with(mkspan("2pm", "3pm"));
+    }
+    
+    private bool coincide_start_end_same() throws Error {
+        return !mkspan("2pm", "3pm").coincides_with(mkspan("1pm", "2pm"));
+    }
+    
+    private bool coincide_same() throws Error {
+        return mkspan("2pm", "3pm").coincides_with(mkspan("2pm", "3pm"));
+    }
+}
+
+}
+
diff --git a/src/tests/tests.vala b/src/tests/tests.vala
index 11a3a47..57c809e 100644
--- a/src/tests/tests.vala
+++ b/src/tests/tests.vala
@@ -18,6 +18,7 @@ public int run(string[] args) {
     UnitTest.Harness.register(new CalendarMonthOfYear());
     UnitTest.Harness.register(new CalendarWallTime());
     UnitTest.Harness.register(new CalendarExactTime());
+    UnitTest.Harness.register(new CalendarExactTimeSpan());
     UnitTest.Harness.register(new QuickAdd());
     UnitTest.Harness.register(new QuickAddRecurring());
     
diff --git a/src/view/week/week-day-pane.vala b/src/view/week/week-day-pane.vala
index d728d72..89b6b74 100644
--- a/src/view/week/week-day-pane.vala
+++ b/src/view/week/week-day-pane.vala
@@ -348,6 +348,11 @@ internal class DayPane : Pane, Common.InstanceContainer {
                 else
                     draw_end_time = Calendar.WallTime.latest;
                 
+                // for purposes of visualization, an event ends one minute inward on both ends; i.e.
+                // an event from 1pm to 2pm is drawn as starting at 1:01pm and ending at 1:59pm
+                draw_start_time = draw_start_time.adjust(1, Calendar.TimeUnit.MINUTE, null);
+                draw_end_time = draw_end_time.adjust(-1, Calendar.TimeUnit.MINUTE, null);
+                
                 int start_x = ctr * rect_width;
                 int start_y = get_line_y(draw_start_time);
                 int end_y = get_line_y(draw_end_time);


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