[banshee/gtk3] NotificationArea: Add more missing features in GtkNotificationAreaBox



commit e75a6b1969dd84a1c9912e5de4627de5392e3790
Author: Bertrand Lorentz <bertrand lorentz gmail com>
Date:   Fri Jul 22 00:16:01 2011 +0200

    NotificationArea: Add more missing features in GtkNotificationAreaBox
    
    With gtk-sharp 3.0, we can now implement all the features of our
    notification area using Gtk.StatusIcon, in particular the custom
    tooltip. This commit complements what was already done by Olivier
    earlier on.
    
    This might not work perfectly yet, some further testing is needed
    when Banshee is running properly on GTK 3.

 .../GtkNotificationAreaBox.cs                      |  126 ++++++++++++++++++--
 1 files changed, 118 insertions(+), 8 deletions(-)
---
diff --git a/src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/GtkNotificationAreaBox.cs b/src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/GtkNotificationAreaBox.cs
index fa890c3..003ac71 100644
--- a/src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/GtkNotificationAreaBox.cs
+++ b/src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/GtkNotificationAreaBox.cs
@@ -39,11 +39,14 @@ namespace Banshee.NotificationArea
     public class GtkNotificationAreaBox : StatusIcon, INotificationAreaBox
     {
         public event EventHandler Disconnected;
-
         public event EventHandler Activated;
         public event PopupMenuHandler PopupMenuEvent;
-        private TrackInfoPopup custom_tooltip;
 
+        private TrackInfoPopup popup;
+        private bool can_show_popup = false;
+        private bool cursor_over_trayicon = false;
+        private bool hide_delay_started = false;
+        
         public Widget Widget {
             get { return null; }
         }
@@ -57,7 +60,7 @@ namespace Banshee.NotificationArea
             HasTooltip = true;
             base.Activate += delegate {OnActivated ();};
             base.PopupMenu += delegate {OnPopupMenuEvent ();};
-            custom_tooltip = new TrackInfoPopup ();
+            popup = new TrackInfoPopup ();
         }
 
         public void PositionMenu (Menu menu, out int x, out int y, out bool push_in)
@@ -65,26 +68,133 @@ namespace Banshee.NotificationArea
             StatusIcon.PositionMenu (menu, out x, out y, out push_in, Handle);
         }
 
+        private void HidePopup ()
+        {
+            if (popup == null) {
+                return;
+            }
+
+            popup.Hide ();
+            popup.EnterNotifyEvent -= OnPopupEnterNotify;
+            popup.LeaveNotifyEvent -= OnPopupLeaveNotify;
+            popup.Destroy ();
+            popup.Dispose ();
+            popup = null;
+        }
+
+        private void ShowPopup ()
+        {
+            if (popup != null) {
+                return;
+            }
+
+            popup = new TrackInfoPopup ();
+            popup.EnterNotifyEvent += OnPopupEnterNotify;
+            popup.LeaveNotifyEvent += OnPopupLeaveNotify;
+
+            PositionPopup ();
+
+            popup.Show ();
+        }
+
+        private void OnPopupEnterNotify (object o, EnterNotifyEventArgs args)
+        {
+            hide_delay_started = false;
+        }
+
+        private void OnPopupLeaveNotify (object o, LeaveNotifyEventArgs args)
+        {
+            Gdk.Rectangle rect;
+            if (!popup.Intersect (new Gdk.Rectangle ((int)args.Event.X, (int)args.Event.Y, 1, 1), out rect)) {
+                OnLeaveNotifyEvent (o, args);
+            }
+        }
+
+        private void PositionPopup ()
+        {
+            int x, y;
+            Gdk.Screen screen;
+            Gdk.Rectangle area;
+            Orientation orientation;
+
+            GetGeometry (out screen, out area, out orientation);
+
+            Gtk.Requisition popup_min_size, popup_natural_size;
+            popup.GetPreferredSize (out popup_min_size, out popup_natural_size);
+
+            bool on_bottom = area.Bottom + popup_natural_size.Height >= screen.Height;
+
+            y = on_bottom
+                ? area.Top - popup_natural_size.Height - 5
+                : area.Bottom + 5;
+
+            int monitor = screen.GetMonitorAtPoint (area.Left, y);
+            var monitor_rect = screen.GetMonitorGeometry(monitor);
+
+            x = area.Left - (popup_natural_size.Width / 2) + (area.Width / 2);
+
+            if (x + popup_natural_size.Width >= monitor_rect.Right - 5) {
+                x = monitor_rect.Right - popup_natural_size.Width - 5;
+            } else if (x < monitor_rect.Left + 5) {
+                x = monitor_rect.Left + 5;
+            }
+
+            popup.Move (x, y);
+        }
+
+        private void OnEnterNotifyEvent (object o, EnterNotifyEventArgs args)
+        {
+            hide_delay_started = false;
+            cursor_over_trayicon = true;
+            if (can_show_popup) {
+                // only show the popup when the cursor is still over the
+                // tray icon after 500ms
+                GLib.Timeout.Add (500, delegate {
+                    if (cursor_over_trayicon && can_show_popup) {
+                        ShowPopup ();
+                    }
+                    return false;
+                });
+            }
+        }
+
+        private void OnLeaveNotifyEvent (object o, LeaveNotifyEventArgs args)
+        {
+            // Give the user half a second to move the mouse cursor to the popup.
+            if (!hide_delay_started) {
+                hide_delay_started = true;
+                cursor_over_trayicon = false;
+                GLib.Timeout.Add (500, delegate {
+                    if (hide_delay_started) {
+                        hide_delay_started = false;
+                        HidePopup ();
+                    }
+                    return false;
+                });
+            }
+        }
+
         public void OnPlayerEvent (PlayerEventArgs args)
         {
-/*            switch (args.Event) {
+            switch (args.Event) {
                 case PlayerEvent.StartOfStream:
-                    can_show_popup = true;
+                    can_show_popup = false;
                     break;
 
                 case PlayerEvent.EndOfStream:
                     // only hide the popup when we don't play again after 250ms
                     GLib.Timeout.Add (250, delegate {
                         if (ServiceManager.PlayerEngine.CurrentState != PlayerState.Playing) {
+                            can_show_popup = false;
                             HidePopup ();
                          }
                          return false;
                     });
                     break;
-            }*/
+            }
         }
 
-        protected bool OnScrollEvent (Gdk.EventScroll evnt)
+        protected override bool OnScrollEvent (Gdk.EventScroll evnt)
         {
             switch (evnt.Direction) {
                 case Gdk.ScrollDirection.Up:
@@ -145,7 +255,7 @@ namespace Banshee.NotificationArea
 
         protected override bool OnQueryTooltip (int x, int y, bool keyboard_mode, Tooltip tooltip)
         {
-            tooltip.Custom = custom_tooltip;
+            tooltip.Custom = popup;
             return true;
         }
 



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