[california] Respond to click events in week view all-day cells: Closes bug #730610



commit f9fed9de7a8805a6abfddfe7676989cf60fc67d3
Author: Jim Nelson <jim yorba org>
Date:   Fri May 23 15:57:44 2014 -0700

    Respond to click events in week view all-day cells: Closes bug #730610
    
    Existing events can now be examined, new events created by double-
    clicking on empty space.

 src/Makefile.am                                |    1 +
 src/host/host-main-window.vala                 |    4 +-
 src/view/common/common-events-cell.vala        |   22 +++++---
 src/view/common/common-instance-container.vala |   65 ++++++++++++++++++++++++
 src/view/common/common.vala                    |    2 -
 src/view/view-controllable.vala                |    2 +-
 src/view/week/week-day-pane.vala               |   18 ++++++-
 src/view/week/week-grid.vala                   |   51 +++++++++++-------
 8 files changed, 131 insertions(+), 34 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 6f176ea..0999a5c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -136,6 +136,7 @@ california_VALASOURCES = \
        \
        view/common/common.vala \
        view/common/common-events-cell.vala \
+       view/common/common-instance-container.vala \
        \
        view/month/month.vala \
        view/month/month-cell.vala \
diff --git a/src/host/host-main-window.vala b/src/host/host-main-window.vala
index 87314ee..579f169 100644
--- a/src/host/host-main-window.vala
+++ b/src/host/host-main-window.vala
@@ -283,10 +283,10 @@ public class MainWindow : Gtk.ApplicationWindow {
         create_event(event, relative_to, for_location);
     }
     
-    private void on_request_create_all_day_event(Calendar.DateSpan initial, Gtk.Widget relative_to,
+    private void on_request_create_all_day_event(Calendar.Span initial, Gtk.Widget relative_to,
         Gdk.Point? for_location) {
         Component.Event event = new Component.Event.blank();
-        event.set_event_date_span(initial);
+        event.set_event_date_span(initial.to_date_span());
         
         create_event(event, relative_to, for_location);
     }
diff --git a/src/view/common/common-events-cell.vala b/src/view/common/common-events-cell.vala
index 4b54ab0..d4e02f6 100644
--- a/src/view/common/common-events-cell.vala
+++ b/src/view/common/common-events-cell.vala
@@ -11,7 +11,7 @@ namespace California.View.Common {
  * time information and summary and a capped bar for all-day or day-spanning events.
  */
 
-internal abstract class EventsCell : Gtk.EventBox {
+internal abstract class EventsCell : Gtk.EventBox, InstanceContainer {
     public const string PROP_DATE = "date";
     public const string PROP_NEIGHBORS = "neighbors";
     public const string PROP_TOP_LINE_TEXT = "top-line-text";
@@ -82,6 +82,16 @@ internal abstract class EventsCell : Gtk.EventBox {
         }
     }
     
+    /**
+     * @inheritDoc
+     */
+    public int event_count { get { return sorted_events.size; } }
+    
+    /**
+     * @inheritDoc
+     */
+    public Calendar.Span contained_span { get { return date; } }
+    
     private Gee.TreeSet<Component.Event> sorted_events = new 
Gee.TreeSet<Component.Event>(all_day_comparator);
     private Gee.HashMap<int, Component.Event> line_to_event = new Gee.HashMap<int, Component.Event>();
     
@@ -177,7 +187,7 @@ internal abstract class EventsCell : Gtk.EventBox {
             this.date = date;
             
             // stored events are now bogus
-            clear();
+            clear_events();
             queue_draw();
         }
         
@@ -190,7 +200,7 @@ internal abstract class EventsCell : Gtk.EventBox {
         }
     }
     
-    public void clear() {
+    public void clear_events() {
         line_to_event.clear();
         
         foreach (Component.Event event in sorted_events.to_array())
@@ -345,12 +355,8 @@ internal abstract class EventsCell : Gtk.EventBox {
         return line_number;
     }
     
-    public bool has_events() {
-        return sorted_events.size > 0;
-    }
-    
     private void on_24hr_changed() {
-        if (has_events())
+        if (has_events)
             queue_draw();
     }
     
diff --git a/src/view/common/common-instance-container.vala b/src/view/common/common-instance-container.vala
new file mode 100644
index 0000000..c0679e2
--- /dev/null
+++ b/src/view/common/common-instance-container.vala
@@ -0,0 +1,65 @@
+/* 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.View.Common {
+
+/**
+ * A Gtk.Widget which displays { link Component.Instance}s.
+ *
+ * This does not require Gtk.Container because what's important is the display mechanism, not a
+ * grouping of Gtk.Widgets, if any.
+ */
+
+public interface InstanceContainer : Gtk.Widget {
+    public const string PROP_EVENT_COUNT = "event-count";
+    public const string PROP_CONTAINED_SPAN = "contained-span";
+    public const string PROP_HAS_EVENTS = "has-events";
+    
+    /**
+     * The number of events held by the { link InstanceContainer}.
+     */
+    public abstract int event_count { get; }
+    
+    /**
+     * The { link Calendar.Span} this { link InstanceContainer} represents.
+     */
+    public abstract Calendar.Span contained_span { get; }
+    
+    /**
+     * True if the { link InstanceContainer} is holding one or more { link Component.Event}s.
+     */
+    public bool has_events { get { return event_count > 0; } }
+    
+    /**
+     * Add a { link Component.Event} to the { link InstanceContainer}.
+     *
+     * If the event is already added to the InstanceContainer, nothing is changed.
+     */
+    public abstract void add_event(Component.Event event);
+    
+    /**
+     * Remove a { link Component.Event} from the { link InstanceContainer}.
+     *
+     * If the event was not previously add to the InstanceContainer, nothing is changed.
+     */
+    public abstract void remove_event(Component.Event event);
+    
+    /**
+     * Clears all { link Component.Event}s from the { link InstanceContainer}.
+     */
+    public abstract void clear_events();
+    
+    /**
+     * Performs a hit-test for the supplied Gdk.Point.
+     *
+     * Returns the { link Component.Event}, if any, at the point.  Coordinates are in the widget's
+     * coordinate system.
+     */
+    public abstract Component.Event? get_event_at(Gdk.Point point);
+}
+
+}
+
diff --git a/src/view/common/common.vala b/src/view/common/common.vala
index 0ae0b55..9006e57 100644
--- a/src/view/common/common.vala
+++ b/src/view/common/common.vala
@@ -15,14 +15,12 @@ public void init() throws Error {
     // unit initialization
     Calendar.init();
     Component.init();
-    Toolkit.init();
 }
 
 public void terminate() {
     if (!Unit.do_terminate(ref init_count))
         return;
     
-    Toolkit.terminate();
     Component.terminate();
     Calendar.terminate();
 }
diff --git a/src/view/view-controllable.vala b/src/view/view-controllable.vala
index c95f9d8..f25b92a 100644
--- a/src/view/view-controllable.vala
+++ b/src/view/view-controllable.vala
@@ -55,7 +55,7 @@ public interface Controllable : Object {
      * Signal from the { link Controllable} that a DATE { link Component.Event} should be
      * created with the specified initial parameters.
      */
-    public signal void request_create_all_day_event(Calendar.DateSpan initial, Gtk.Widget relative_to,
+    public signal void request_create_all_day_event(Calendar.Span initial, Gtk.Widget relative_to,
         Gdk.Point? for_location);
     
     /**
diff --git a/src/view/week/week-day-pane.vala b/src/view/week/week-day-pane.vala
index 9c232b5..6a29494 100644
--- a/src/view/week/week-day-pane.vala
+++ b/src/view/week/week-day-pane.vala
@@ -13,7 +13,7 @@ namespace California.View.Week {
  * @see AllDayCell
  */
 
-internal class DayPane : Pane {
+internal class DayPane : Pane, Common.InstanceContainer {
     public const string PROP_OWNER = "owner";
     public const string PROP_DATE = "date";
     public const string PROP_SELECTED = "selected";
@@ -26,6 +26,16 @@ internal class DayPane : Pane {
     
     public bool selected { get; set; default = false; }
     
+    /**
+     * @inheritDoc
+     */
+    public int event_count { get { return days_events.size; } }
+    
+    /**
+     * @inheritDoc
+     */
+    public Calendar.Span contained_span { get { return date; } }
+    
     private Gee.TreeSet<Component.Event> days_events = new Gee.TreeSet<Component.Event>();
     private uint minutes_timeout_id = 0;
     
@@ -106,6 +116,12 @@ internal class DayPane : Pane {
         queue_draw();
     }
     
+    public void clear_events() {
+        days_events.clear();
+        
+        queue_draw();
+    }
+    
     public Component.Event? get_event_at(Gdk.Point point) {
         Calendar.ExactTime exact_time = new Calendar.ExactTime(Calendar.Timezone.local, date,
             get_wall_time(point.y));
diff --git a/src/view/week/week-grid.vala b/src/view/week/week-grid.vala
index dff191a..bf546f1 100644
--- a/src/view/week/week-grid.vala
+++ b/src/view/week/week-grid.vala
@@ -43,7 +43,7 @@ internal class Grid : Gtk.Box {
     private Gee.HashMap<Calendar.Date, DayPane> date_to_panes = new Gee.HashMap<Calendar.Date, DayPane>();
     private Gee.HashMap<Calendar.Date, AllDayCell> date_to_all_day = new Gee.HashMap<Calendar.Date,
         AllDayCell>();
-    private Toolkit.ButtonConnector day_pane_button_connector = new Toolkit.ButtonConnector();
+    private Toolkit.ButtonConnector instance_container_button_connector = new Toolkit.ButtonConnector();
     private Gtk.ScrolledWindow scrolled_panes;
     private Gtk.Widget right_spacer;
     private bool vadj_init = false;
@@ -103,6 +103,7 @@ internal class Grid : Gtk.Box {
             // All-day cells (for drawing all-day and day-spanning events) go between the date
             // label and the day panes
             AllDayCell all_day_cell = new AllDayCell(this, date);
+            instance_container_button_connector.connect_to(all_day_cell);
             top_grid.attach(all_day_cell, col, 1, 1, 1);
             
             // save mapping
@@ -110,7 +111,7 @@ internal class Grid : Gtk.Box {
             
             DayPane pane = new DayPane(this, date);
             pane.expand = true;
-            day_pane_button_connector.connect_to(pane);
+            instance_container_button_connector.connect_to(pane);
             pane_grid.attach(pane, col, 1, 1, 1);
             
             // save mapping
@@ -133,8 +134,8 @@ internal class Grid : Gtk.Box {
         scrolled_panes.get_vscrollbar().size_allocate.connect(on_realloc_right_spacer);
         
         // connect panes' event signal handlers
-        day_pane_button_connector.clicked.connect(on_day_pane_clicked);
-        day_pane_button_connector.double_clicked.connect(on_day_pane_double_clicked);
+        instance_container_button_connector.clicked.connect(on_instance_container_clicked);
+        instance_container_button_connector.double_clicked.connect(on_instance_container_double_clicked);
         
         // set up calendar subscriptions for the week
         subscriptions = new Backing.CalendarSubscriptionManager(
@@ -293,39 +294,49 @@ internal class Grid : Gtk.Box {
         return date_to_all_day.get(cell_date);
     }
     
-    private void on_day_pane_clicked(Toolkit.ButtonEvent details, bool guaranteed) {
+    private void on_instance_container_clicked(Toolkit.ButtonEvent details, bool guaranteed) {
         // only interested in unguaranteed clicks on the primary mouse button
         if (details.button != Toolkit.Button.PRIMARY || guaranteed)
             return;
         
-        DayPane day_pane = (DayPane) details.widget;
+        Common.InstanceContainer instance_container = (Common.InstanceContainer) details.widget;
         
-        Component.Event? event = day_pane.get_event_at(details.press_point);
+        Component.Event? event = instance_container.get_event_at(details.press_point);
         if (event != null)
-            owner.request_display_event(event, day_pane, details.press_point);
+            owner.request_display_event(event, instance_container, details.press_point);
     }
     
-    private void on_day_pane_double_clicked(Toolkit.ButtonEvent details, bool guaranteed) {
+    private void on_instance_container_double_clicked(Toolkit.ButtonEvent details, bool guaranteed) {
         // only interested in unguaranteed double-clicks on the primary mouse button
         if (details.button != Toolkit.Button.PRIMARY || guaranteed)
             return;
         
-        DayPane day_pane = (DayPane) details.widget;
+        Common.InstanceContainer instance_container = (Common.InstanceContainer) details.widget;
         
         // if an event is at this location, don't process
-        if (day_pane.get_event_at(details.press_point) != null)
+        if (instance_container.get_event_at(details.press_point) != null)
             return;
         
-        // convert click into starting time on the day pane rounded down to the nearest half-hour
-        Calendar.WallTime wall_time = day_pane.get_wall_time(details.press_point.y).round_down(
-            30, Calendar.TimeUnit.MINUTE);
-        
-        Calendar.ExactTime start_time = new Calendar.ExactTime(Calendar.Timezone.local,
-            day_pane.date, wall_time);
+        // if a DayPane, use double-click to determine rounded time of the event's start
+        DayPane? day_pane = instance_container as DayPane;
+        if (day_pane != null) {
+            // convert click into starting time on the day pane rounded down to the nearest half-hour
+            Calendar.WallTime wall_time = day_pane.get_wall_time(details.press_point.y).round_down(
+                30, Calendar.TimeUnit.MINUTE);
+            
+            Calendar.ExactTime start_time = new Calendar.ExactTime(Calendar.Timezone.local,
+                day_pane.date, wall_time);
+            
+            owner.request_create_timed_event(
+                new Calendar.ExactTimeSpan(start_time, start_time.adjust_time(1, Calendar.TimeUnit.HOUR)),
+                day_pane, details.press_point);
+            
+            return;
+        }
         
-        owner.request_create_timed_event(
-            new Calendar.ExactTimeSpan(start_time, start_time.adjust_time(1, Calendar.TimeUnit.HOUR)),
-            day_pane, details.press_point);
+        // otherwise, an all-day-cell, so request an all-day event
+        owner.request_create_all_day_event(instance_container.contained_span, instance_container,
+            details.press_point);
     }
 }
 


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