[california/wip/735942-double-click] First pass, still some timing issues left



commit 65ca3ea3f8c812eaf85a20a6d14742402ef1e2b0
Author: Jim Nelson <jim yorba org>
Date:   Thu Sep 4 18:48:10 2014 -0700

    First pass, still some timing issues left

 src/host/host-main-window.vala            |    7 +++++++
 src/toolkit/toolkit-button-connector.vala |   10 +++++-----
 src/toolkit/toolkit-button-event.vala     |   27 +++++++++++++++++++++++++++
 src/util/util-scheduled.vala              |   12 ++++++++++++
 src/view/month/month-grid.vala            |   15 ++++++++-------
 src/view/view-controllable.vala           |    7 +++++++
 src/view/week/week-grid.vala              |   10 +++++++---
 7 files changed, 73 insertions(+), 15 deletions(-)
---
diff --git a/src/host/host-main-window.vala b/src/host/host-main-window.vala
index c2f439a..0a7342a 100644
--- a/src/host/host-main-window.vala
+++ b/src/host/host-main-window.vala
@@ -297,6 +297,7 @@ public class MainWindow : Gtk.ApplicationWindow {
             current_controller.request_create_timed_event.disconnect(on_request_create_timed_event);
             current_controller.request_create_all_day_event.disconnect(on_request_create_all_day_event);
             current_controller.request_display_event.disconnect(on_request_display_event);
+            current_controller.request_edit_event.disconnect(on_request_edit_event);
             current_controller.notify[View.Controllable.PROP_IS_VIEWING_TODAY].disconnect(
                 on_is_viewing_today_changed);
             
@@ -311,6 +312,7 @@ public class MainWindow : Gtk.ApplicationWindow {
             current_controller.request_create_timed_event.connect(on_request_create_timed_event);
             current_controller.request_create_all_day_event.connect(on_request_create_all_day_event);
             current_controller.request_display_event.connect(on_request_display_event);
+            current_controller.request_edit_event.connect(on_request_edit_event);
             current_controller.notify[View.Controllable.PROP_IS_VIEWING_TODAY].connect(
                 on_is_viewing_today_changed);
             on_is_viewing_today_changed();
@@ -494,6 +496,11 @@ public class MainWindow : Gtk.ApplicationWindow {
         show_deck_popover(relative_to, for_location, deck);
     }
     
+    private void on_request_edit_event(Component.Event event, Gtk.Widget relative_to,
+        Gdk.Point? for_location) {
+        on_edit_event(event, true);
+    }
+    
     private void edit_event(Component.Event event, bool is_update) {
         // use Idle loop so popovers have a chance to hide before bringing up DeckWindow
         Idle.add(() => {
diff --git a/src/toolkit/toolkit-button-connector.vala b/src/toolkit/toolkit-button-connector.vala
index 9fa6bd6..ea9ea68 100644
--- a/src/toolkit/toolkit-button-connector.vala
+++ b/src/toolkit/toolkit-button-connector.vala
@@ -189,6 +189,8 @@ public class ButtonConnector : EventConnector {
                     ButtonEvent? details = button_states.get(widget);
                     if (details == null) {
                         details = new ButtonEvent(widget, event);
+                        details.clicked.connect(synthesize_click);
+                        
                         button_states.set(widget, details);
                     } else {
                         details.update_press(widget, event);
@@ -210,11 +212,8 @@ public class ButtonConnector : EventConnector {
                 // update saved state (if any) with release info and synthesize click
                 if (button_states != null) {
                     ButtonEvent? details = button_states.get(widget);
-                    if (details != null) {
+                    if (details != null)
                         details.update_release(widget, event);
-                        
-                        synthesize_click(details);
-                    }
                 }
             break;
         }
@@ -223,7 +222,8 @@ public class ButtonConnector : EventConnector {
     }
     
     private void synthesize_click(ButtonEvent details) {
-        // use Accept flags to indicate which signal(s) to fire
+        debug("synthesize click");
+        
         bool result = Toolkit.PROPAGATE;
         switch (details.press_type) {
             case Gdk.EventType.BUTTON_PRESS:
diff --git a/src/toolkit/toolkit-button-event.vala b/src/toolkit/toolkit-button-event.vala
index 25319a0..802eaea 100644
--- a/src/toolkit/toolkit-button-event.vala
+++ b/src/toolkit/toolkit-button-event.vala
@@ -97,12 +97,30 @@ public class ButtonEvent : BaseObject {
     private Gdk.Point _release_point = Gdk.Point();
     public Gdk.Point release_point { get { return _release_point; } }
     
+    internal signal void clicked();
+    
+    private Scheduled? scheduled_click = null;
+    
     internal ButtonEvent(Gtk.Widget widget, Gdk.EventButton press_event) {
         this.widget = widget;
         button = Button.from_button_event(press_event);
         press_type = press_event.type;
         _press_point.x = (int) press_event.x;
         _press_point.y = (int) press_event.y;
+        
+        debug("new ButtonEvent %s", press_type.to_string());
+    }
+    
+    ~ButtonEvent() {
+        cancel_click();
+    }
+    
+    private void cancel_click() {
+        if (scheduled_click == null)
+            return;
+        
+        scheduled_click.cancel();
+        scheduled_click = null;
     }
     
     // Update state with the next button press
@@ -113,6 +131,8 @@ public class ButtonEvent : BaseObject {
         press_type = press_event.type;
         _press_point.x = (int) press_event.x;
         _press_point.y = (int) press_event.y;
+        
+        cancel_click();
     }
     
     // Update state with the next button release and start the release timer
@@ -122,6 +142,13 @@ public class ButtonEvent : BaseObject {
         
         _release_point.x = (int) release_event.x;
         _release_point.y = (int) release_event.y;
+        
+        cancel_click();
+        
+        if (press_type == Gdk.EventType.3BUTTON_PRESS)
+            clicked();
+        else
+            scheduled_click = new Scheduled.once_after_msec(125, () => { clicked(); });
     }
     
     public override string to_string() {
diff --git a/src/util/util-scheduled.vala b/src/util/util-scheduled.vala
index 6f5498e..21d5b82 100644
--- a/src/util/util-scheduled.vala
+++ b/src/util/util-scheduled.vala
@@ -120,6 +120,7 @@ public class Scheduled : BaseObject {
         schedule_once = cb;
         
         source_id = Timeout.add(msec, on_once, priority);
+        debug("alloc %u", source_id);
     }
     
     /**
@@ -141,6 +142,7 @@ public class Scheduled : BaseObject {
     }
     
     ~Scheduled() {
+        debug("DTOR");
         cancel();
     }
     
@@ -153,6 +155,8 @@ public class Scheduled : BaseObject {
         if (source_id == 0)
             return;
         
+        debug("canceled %u", source_id);
+        
         Source.remove(source_id);
         source_id = 0;
     }
@@ -176,6 +180,11 @@ public class Scheduled : BaseObject {
     }
     
     private bool on_once() {
+        debug("on_once source_id=%u", source_id);
+        
+        if (is_executing || source_id == 0)
+            return false;
+        
         is_executing = true;
         schedule_once();
         is_executing = false;
@@ -187,6 +196,9 @@ public class Scheduled : BaseObject {
     }
     
     private bool on_continuous() {
+        if (is_executing || source_id == 0)
+            return false;
+        
         is_executing = true;
         Reschedule reschedule = schedule_continuous();
         is_executing = false;
diff --git a/src/view/month/month-grid.vala b/src/view/month/month-grid.vala
index c5a5b46..15e2be8 100644
--- a/src/view/month/month-grid.vala
+++ b/src/view/month/month-grid.vala
@@ -369,13 +369,14 @@ private class Grid : Gtk.Grid {
         if (press_cell != release_cell)
             return Toolkit.PROPAGATE;
         
-        // if an existing event is double-clicked, ignore, as the single click handler is displaying
-        // it (but stop propagation)
-        if (release_cell.get_event_at(release_cell_point) != null)
-            return Toolkit.STOP;
-        
-        owner.request_create_all_day_event(new Calendar.DateSpan(press_cell.date, release_cell.date),
-            release_cell, release_cell_point);
+        // if an existing event is double-clicked, open for editing, otherwise create new event
+        Component.Event? event = release_cell.get_event_at(release_cell_point);
+        if (event != null) {
+            owner.request_edit_event(event, release_cell, release_cell_point);
+        } else {
+            owner.request_create_all_day_event(new Calendar.DateSpan(press_cell.date, release_cell.date),
+                release_cell, release_cell_point);
+        }
         
         return Toolkit.STOP;
     }
diff --git a/src/view/view-controllable.vala b/src/view/view-controllable.vala
index 53ed7de..863a0fa 100644
--- a/src/view/view-controllable.vala
+++ b/src/view/view-controllable.vala
@@ -82,6 +82,13 @@ public interface Controllable : Object {
         Gdk.Point? for_location);
     
     /**
+     * Signal from the { link Controllable} that the { link Component.Event} editor should be
+     * opened.
+     */
+    public signal void request_edit_event(Component.Event event, Gtk.Widget relative_to,
+        Gdk.Point? for_location);
+    
+    /**
      * Returns the { link Container} that should be used to display the { link Controllable}'s
      * contents.
      *
diff --git a/src/view/week/week-grid.vala b/src/view/week/week-grid.vala
index c2141f4..1cc8dd2 100644
--- a/src/view/week/week-grid.vala
+++ b/src/view/week/week-grid.vala
@@ -337,9 +337,13 @@ internal class Grid : Gtk.Box {
         
         Common.InstanceContainer instance_container = (Common.InstanceContainer) details.widget;
         
-        // if an event is at this location, don't process
-        if (instance_container.get_event_at(details.press_point) != null)
-            return Toolkit.PROPAGATE;
+        // if an event is at this location, open for editing
+        Component.Event? event = instance_container.get_event_at(details.press_point);
+        if (event != null) {
+            owner.request_edit_event(event, instance_container, details.release_point);
+            
+            return Toolkit.STOP;
+        }
         
         // if a DayPane, use double-click to determine rounded time of the event's start
         DayPane? day_pane = instance_container as DayPane;


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