[gnome-contacts/wip/sorted] Track prelighted rows



commit 36aefcf17c87557fcca1ee2b83ab93721a8dff3d
Author: Alexander Larsson <alexl redhat com>
Date:   Thu May 10 16:03:47 2012 +0200

    Track prelighted rows
    
    This needs us to be a widget window, otherwise we can't track prelight
    when inside inferior windows.

 src/contacts-sorted.vala |  121 +++++++++++++++++++++++++++++----------------
 1 files changed, 78 insertions(+), 43 deletions(-)
---
diff --git a/src/contacts-sorted.vala b/src/contacts-sorted.vala
index 40e6b1a..ca8a196 100644
--- a/src/contacts-sorted.vala
+++ b/src/contacts-sorted.vala
@@ -72,33 +72,74 @@ public class Contacts.Sorted : Container {
   NeedSeparatorFunc? need_separator_func;
   CreateSeparatorFunc? create_separator_func;
   UpdateSeparatorFunc? update_separator_func;
-  protected Gdk.Window event_window;
   unowned ChildInfo? selected_child;
+  unowned ChildInfo? prelight_child;
 
   private int do_sort (ChildInfo? a, ChildInfo? b) {
     return sort_func (a.widget, b.widget);
   }
 
   public Sorted () {
-    set_has_window (false);
+    set_has_window (true);
     set_redraw_on_allocate (false);
 
     children = new Sequence<ChildInfo?>();
     child_hash = new HashMap<unowned Widget, unowned ChildInfo?> ();
   }
 
+  unowned ChildInfo? find_child_at_y (int y) {
+    unowned ChildInfo? child_info = null;
+    for (var iter = children.get_begin_iter (); !iter.is_end (); iter = iter.next ()) {
+      unowned ChildInfo? info = iter.get ();
+      if (y >= info.y && y < info.y + info.height) {
+	child_info = info;
+	break;
+      }
+    }
+    return child_info;
+  }
+
+  private void update_prelight (ChildInfo? child) {
+    if (child != prelight_child) {
+      prelight_child = child;
+      queue_draw ();
+    }
+  }
+
+  public override bool enter_notify_event (Gdk.EventCrossing event) {
+    if (event.window != get_window ())
+      return false;
+
+    unowned ChildInfo? child = find_child_at_y ((int)event.y);
+    update_prelight (child);
+
+    return false;
+  }
+
+  public override bool leave_notify_event (Gdk.EventCrossing event) {
+    if (event.window != get_window ())
+      return false;
+
+    if (event.detail != Gdk.NotifyType.INFERIOR) {
+      update_prelight (null);
+    } else {
+      unowned ChildInfo? child = find_child_at_y ((int)event.y);
+      update_prelight (child);
+    }
+
+    return false;
+  }
+
+  public override bool motion_notify_event (Gdk.EventMotion event) {
+    unowned ChildInfo? child = find_child_at_y ((int)event.y);
+    update_prelight (child);
+    return false;
+  }
+
   public override bool button_press_event (Gdk.EventButton event) {
     if (event.button == 1) {
-      var y = event.y;
-      unowned ChildInfo? child_info = null;
-      for (var iter = children.get_begin_iter (); !iter.is_end (); iter = iter.next ()) {
-	unowned ChildInfo? info = iter.get ();
-	if (y >= info.y && y < info.y + info.height) {
-	  child_info = info;
-	  break;
-	}
-      }
-      selected_child = child_info;
+      unowned ChildInfo? child = find_child_at_y ((int)event.y);
+      selected_child = child;
 
       child_selected (selected_child != null ? selected_child.widget : null);
       queue_draw ();
@@ -126,6 +167,13 @@ public class Contacts.Sorted : Container {
 			     allocation.width, selected_child.height);
     }
 
+    if (prelight_child != null && prelight_child != selected_child) {
+      context.set_state (StateFlags.PRELIGHT);
+      Gtk.render_background (context, cr,
+			     0, prelight_child.y,
+			     allocation.width, prelight_child.height);
+    }
+
     context.restore ();
 
     base.draw (cr);
@@ -144,23 +192,19 @@ public class Contacts.Sorted : Container {
     attributes.width = allocation.width;
     attributes.height = allocation.height;
     attributes.window_type = Gdk.WindowType.CHILD;
-    attributes.event_mask = this.get_events () | Gdk.EventMask.EXPOSURE_MASK | Gdk.EventMask.BUTTON_PRESS_MASK;
-
-    var window = get_parent_window ();
+    attributes.event_mask = this.get_events () |
+                       Gdk.EventMask.ENTER_NOTIFY_MASK |
+		       Gdk.EventMask.LEAVE_NOTIFY_MASK |
+		       Gdk.EventMask.POINTER_MOTION_MASK |
+		       Gdk.EventMask.EXPOSURE_MASK |
+		       Gdk.EventMask.BUTTON_PRESS_MASK;
+
+    attributes.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT;
+    var window = new Gdk.Window (get_parent_window (), attributes,
+				 Gdk.WindowAttributesType.X |
+				 Gdk.WindowAttributesType.Y);
+    window.set_user_data (this);
     this.set_window (window);
-
-    attributes.wclass = Gdk.WindowWindowClass.INPUT_ONLY;
-    event_window = new Gdk.Window (window, attributes,
-				   Gdk.WindowAttributesType.X |
-				   Gdk.WindowAttributesType.Y);
-    event_window.set_user_data (this);
-  }
-
-  public override void unrealize () {
-    event_window.set_user_data (null);
-    event_window.destroy ();
-    event_window = null;
-    base.unrealize ();
   }
 
   private void apply_filter (Widget child) {
@@ -292,16 +336,6 @@ public class Contacts.Sorted : Container {
     resort ();
   }
 
-  public override void map () {
-    event_window.show ();
-    base.map ();
-  }
-
-  public override void unmap () {
-    event_window.hide ();
-    base.unmap ();
-  }
-
   private unowned ChildInfo? lookup_info (Widget widget) {
     return child_hash.get (widget);
   }
@@ -454,11 +488,12 @@ public class Contacts.Sorted : Container {
 
     set_allocation (allocation);
 
-    if (event_window != null)
-      event_window.move_resize (allocation.x,
-				allocation.y,
-				allocation.width,
-				allocation.height);
+    var window = get_window();
+    if (window != null)
+      window.move_resize (allocation.x,
+			  allocation.y,
+			  allocation.width,
+			  allocation.height);
 
     child_allocation.x = allocation.x;
     child_allocation.y = allocation.y;



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