banshee r3108 - in trunk/banshee: . src/Core/Banshee.Services/Banshee.Playlist src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient/Banshee.Sources.Gui src/Core/Hyena.Gui src/Core/Hyena.Gui/Hyena.Data.Gui src/Core/Hyena.Gui/Hyena.Gui.Theatre src/Core/Hyena.Gui/Hyena.Widgets



Author: abock
Date: Thu Jan 31 03:01:05 2008
New Revision: 3108
URL: http://svn.gnome.org/viewvc/banshee?rev=3108&view=rev

Log:
2008-01-30  Aaron Bockover  <abock gnome org>

    * src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs:
    * src/Core/Banshee.Services/Banshee.Sources/Source.cs:
    Added UserNotifyUpdated event that sources can use to trigger
    notifications or visual cues in the source view

    * src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs:
    * src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs:
    Use the new Hyena theatre stage/actors to animate update notifications on
    source rows in the source views

    * src/Core/Hyena.Gui/Hyena.Data.Gui/ListViewGraphics.cs: Added a method
    for drawing a flat row highlight

    * src/Core/Hyena.Gui/Hyena.Gui.Theatre/Stage.cs: An object that manages
    timeouts for a set of Actors bound to targets of T; used for animating
    collections of objects bound to actors

    * src/Core/Hyena.Gui/Hyena.Gui.Theatre/Actor.cs: An object bound to
    a target of T with life span and percentage properties used for animations

    * src/Core/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs: Remove redundant
    BorderWidth property



Added:
   trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.Theatre/
   trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.Theatre/Actor.cs
   trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.Theatre/Stage.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs
   trunk/banshee/src/Core/Hyena.Gui/Hyena.Data.Gui/ListViewGraphics.cs
   trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.mdp
   trunk/banshee/src/Core/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs
   trunk/banshee/src/Core/Hyena.Gui/Makefile.am

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs	Thu Jan 31 03:01:05 2008
@@ -202,6 +202,7 @@
                 return;
 
             WithTrackSelection (from, AddTrackRange);
+            OnUserNotifyUpdated ();
         }
 
         protected virtual void AddTrackRange (TrackListDatabaseModel from, RangeCollection.Range range)

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	Thu Jan 31 03:01:05 2008
@@ -48,6 +48,7 @@
         private List<Source> child_sources = new List<Source>();
 
         public event EventHandler Updated;
+        public event EventHandler UserNotifyUpdated;
         public event SourceEventHandler ChildSourceAdded;
         public event SourceEventHandler ChildSourceRemoved;
         
@@ -205,6 +206,14 @@
             }
         }
         
+        protected virtual void OnUserNotifyUpdated()
+        {
+            EventHandler handler = UserNotifyUpdated;
+            if(handler != null) {
+                handler(this, EventArgs.Empty);
+            }
+        }
+        
 #endregion
         
 #region Private Methods

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs	Thu Jan 31 03:01:05 2008
@@ -31,6 +31,9 @@
 using Gdk;
 using Pango;
 
+using Hyena.Data.Gui;
+using Hyena.Gui.Theatre;
+
 using Banshee.ServiceStack;
 
 namespace Banshee.Sources.Gui
@@ -93,6 +96,16 @@
             } else if (path != null && path.Equals (view.HighlightedPath)) {
                 view.Graphics.DrawRowSelection (view.Cr, background_area.X + 1, background_area.Y + 1, 
                     background_area.Width - 2, background_area.Height - 2, false);
+            } else if (view.NotifyStage.ActorCount > 0) {
+                TreeIter iter;
+                if (view.Model.GetIter (out iter, path) && view.NotifyStage.Contains (iter)) {
+                    Actor<TreeIter> actor = view.NotifyStage[iter];
+                    Cairo.Color color = view.Graphics.GetWidgetColor (GtkColorClass.Background, StateType.Selected);
+                    color.A = 1.0 - actor.Percent; 
+                    
+                    view.Graphics.DrawFlatRowHighlight (view.Cr, background_area.X + 1, background_area.Y + 1, 
+                        background_area.Width - 2, background_area.Height - 2, color);
+                }
             }
             
             int title_layout_width = 0, title_layout_height = 0;

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs	Thu Jan 31 03:01:05 2008
@@ -27,10 +27,12 @@
 //
 
 using System;
+using System.Collections.Generic;
 using Gtk;
 using Cairo;
 
 using Hyena.Data.Gui;
+using Hyena.Gui.Theatre;
 
 using Banshee.ServiceStack;
 using Banshee.Sources;
@@ -53,6 +55,9 @@
         private ListViewGraphics graphics;
         private Cairo.Context cr;
         
+        private uint user_update_timeout_id = 0;
+        private Stage<TreeIter> notify_stage = new Stage<TreeIter> ();
+        
         private TreeStore store;
         private TreeViewColumn focus_column;
         private TreePath highlight_path;
@@ -120,6 +125,11 @@
             ServiceManager.PlaybackController.SourceChanged += delegate {
                 QueueDraw();
             };
+            
+            notify_stage.ActorStep += delegate (Actor<TreeIter> actor) {
+                Gdk.Rectangle rect = GetBackgroundArea (store.GetPath (actor.Target), focus_column);
+                QueueDrawArea (rect.X, rect.Y, rect.Width, rect.Height);
+            };
         }
         
 #endregion
@@ -326,8 +336,12 @@
                 }
             }
 
-            source.ChildSourceAdded += delegate (SourceEventArgs e) { AddSource (e.Source, iter); };
-            source.ChildSourceRemoved += delegate (SourceEventArgs e) { RemoveSource(e.Source); };
+            // delegate (SourceEventArgs e) { AddSource (e.Source, iter); };
+            // delegate (SourceEventArgs e) { RemoveSource(e.Source); };
+            
+            source.ChildSourceAdded += OnSourceChildSourceAdded; 
+            source.ChildSourceRemoved += OnSourceChildSourceRemoved;
+            source.UserNotifyUpdated += OnSourceUserNotifyUpdated;
            
             if (source.Expanded || (source.AutoExpand != null && source.AutoExpand.Value)) {
                 Expand (iter);
@@ -348,6 +362,10 @@
             if (!iter.Equals (TreeIter.Zero)) {
                 store.Remove (ref iter);
             }
+            
+            source.ChildSourceAdded -= OnSourceChildSourceAdded;
+            source.ChildSourceRemoved -= OnSourceChildSourceRemoved;
+            source.UserNotifyUpdated -= OnSourceUserNotifyUpdated;
 
             UpdateView ();
         }
@@ -365,7 +383,27 @@
                 AddSource (source);
             }
         }
+        
+        private void OnSourceChildSourceAdded (SourceEventArgs args)
+        {
+            AddSource (args.Source, FindSource (args.Source.Parent));
+        }
+        
+        private void OnSourceChildSourceRemoved (SourceEventArgs args)
+        {
+            RemoveSource (args.Source);
+        }
 
+        private void OnSourceUserNotifyUpdated (object o, EventArgs args)
+        {
+            TreeIter iter = FindSource ((Source)o);
+            if (iter.Equals (TreeIter.Zero)) {
+                return;
+            }
+            
+            notify_stage.AddOrReset (iter);
+        }
+        
 #endregion
 
 #region List/View Utility Methods
@@ -502,6 +540,10 @@
         internal ListViewGraphics Graphics {
             get { return graphics; }
         }
+        
+        internal Stage<TreeIter> NotifyStage {
+            get { return notify_stage; }
+        }
 
 #endregion        
 

Modified: trunk/banshee/src/Core/Hyena.Gui/Hyena.Data.Gui/ListViewGraphics.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena.Gui/Hyena.Data.Gui/ListViewGraphics.cs	(original)
+++ trunk/banshee/src/Core/Hyena.Gui/Hyena.Data.Gui/ListViewGraphics.cs	Thu Jan 31 03:01:05 2008
@@ -305,6 +305,13 @@
             CairoExtensions.RoundedRectangle(cr, x + 0.5, y + 0.5, width - 1, height - 1, BorderRadius);
             cr.Stroke();
         }
+        
+        public void DrawFlatRowHighlight(Cairo.Context cr, int x, int y, int width, int height, Cairo.Color color)
+        {
+            cr.Color = color;
+            CairoExtensions.RoundedRectangle(cr, x, y, width, height, BorderRadius);
+            cr.Fill();
+        }
                 
         public void DrawRowRule(Cairo.Context cr, int x, int y, int width, int height)
         {

Added: trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.Theatre/Actor.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.Theatre/Actor.cs	Thu Jan 31 03:01:05 2008
@@ -0,0 +1,90 @@
+//
+// Actor.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace Hyena.Gui.Theatre
+{
+    public class Actor<T>
+    {
+        private T target;
+        
+        private DateTime start_time;
+        private uint duration;
+        private double frames;
+        private double percent;
+    
+        public Actor (T target, uint duration)
+        {
+            this.target = target;
+            this.duration = duration;
+            Reset ();
+        }
+        
+        public void Reset ()
+        {
+            start_time = DateTime.Now;
+            frames = 0.0;
+            percent = 0.0;
+        }
+        
+        public virtual void Step ()
+        {
+            percent = (DateTime.Now - start_time).TotalMilliseconds / duration;
+            frames++;
+        }
+
+        public bool Expired {
+            get { return percent >= 1.0; }
+        }
+        
+        public T Target {
+            get { return target; }
+        }
+        
+        public double Duration {
+            get { return duration; }
+        }
+        
+        public DateTime StartTime {
+            get { return start_time; }
+        }
+        
+        public double Frames {
+            get { return frames; }
+        }
+        
+        public double FramesPerSecond {
+            get { return frames / ((double)duration / 1000.0); }
+        }
+        
+        public double Percent {
+            get { return Math.Max (0.0, Math.Min (1.0, percent)); }
+        }
+    }
+}

Added: trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.Theatre/Stage.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.Theatre/Stage.cs	Thu Jan 31 03:01:05 2008
@@ -0,0 +1,235 @@
+//
+// Stage.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace Hyena.Gui.Theatre
+{
+    public class Stage<T>
+    {   
+        public delegate void ActorStepHandler (Actor<T> actor);
+    
+        private Dictionary<T, Actor<T>> actors = new Dictionary<T, Actor<T>> ();
+        private uint timeout_id;
+        
+        private uint update_frequency = 30;
+        private uint default_duration = 1000;
+        private bool playing = true;
+        
+        public event ActorStepHandler ActorStep;
+        public event EventHandler Iteration;
+        
+        public Stage ()
+        {
+        }
+        
+        public Stage (uint actorDuration)
+        {
+            default_duration = actorDuration;
+        }
+        
+        public Actor<T> this[T target] {
+            get {
+                if (actors.ContainsKey (target)) {
+                    return actors[target];
+                }
+                
+                return null;
+            }
+        }
+        
+        public bool Contains (T target)
+        {
+            return actors.ContainsKey (target);
+        }
+        
+        public Actor<T> Add (T target)
+        {
+            lock (this) {
+                return Add (target, default_duration);
+            }
+        }
+        
+        public Actor<T> Add (T target, uint duration)
+        {
+            lock (this) {
+                if (Contains (target)) {
+                    throw new InvalidOperationException ("Stage already contains this actor");
+                }
+                
+                Actor<T> actor = new Actor<T> (target, duration);
+                actors.Add (target, actor);
+                
+                CheckTimeout ();
+                
+                return actor;
+            }
+        }
+        
+        public Actor<T> AddOrReset (T target)
+        {
+            lock (this) {
+                if (Contains (target)) {
+                    Actor<T> actor = this[target];
+                    actor.Reset ();
+                    
+                    CheckTimeout ();
+                    
+                    return actor;
+                }
+                
+                return Add (target);
+            }
+        }
+        
+        public void Reset (T target)
+        {
+            lock (this) {
+                if (!Contains (target)) {
+                    throw new InvalidOperationException ("Stage does not contain this actor");
+                }
+                
+                CheckTimeout ();
+                
+                this[target].Reset ();
+            }
+        }
+        
+        private void CheckTimeout ()
+        {
+            if ((!Playing || actors.Count == 0) && timeout_id > 0) {
+                GLib.Source.Remove (timeout_id);
+                timeout_id = 0;
+                return;
+            } else if (Playing && actors.Count > 0 && timeout_id <= 0) {
+                timeout_id = GLib.Timeout.Add (update_frequency, OnTimeout);
+                return;
+            }
+        }
+        
+        private bool OnTimeout ()
+        {
+            if (!Playing || actors.Count == 0) {
+                timeout_id = 0;
+                return false;
+            }
+            
+            Queue<Actor<T>> expired_actors = new Queue<Actor<T>> ();
+            
+            foreach (KeyValuePair<T, Actor<T>> entry in actors) {
+                entry.Value.Step ();
+                OnActorStep (entry.Value);
+                
+                if (entry.Value.Expired) {
+                    expired_actors.Enqueue (entry.Value);
+                }
+            }
+            
+            while (expired_actors.Count > 0) {
+                actors.Remove (expired_actors.Dequeue ().Target);
+            }
+            
+            OnIteration ();
+            
+            return true;
+        }
+        
+        protected virtual void OnActorStep (Actor<T> actor)
+        {
+            ActorStepHandler handler = ActorStep;
+            if (handler != null) {
+                handler (actor);
+            }
+        }
+        
+        protected virtual void OnIteration ()
+        {
+            EventHandler handler = Iteration;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
+        
+        public void Play ()
+        {
+            lock (this) {
+                Playing = true;
+            }
+        }
+        
+        public void Pause ()
+        {
+            lock (this) {
+                Playing = false;
+            }
+        }
+        
+        public void Exeunt ()
+        {
+            lock (this) {
+                actors.Clear ();
+                CheckTimeout ();
+            }
+        }
+        
+        public uint DefaultActorDuration {
+            get { return default_duration; }
+            set { lock (this) { default_duration = value; } }
+        }
+        
+        public bool Playing {
+            get { return playing; }
+            set {
+                lock (this) {
+                    if (playing == value) {
+                        return;
+                    }
+                
+                    playing = value; 
+                    CheckTimeout ();
+                }
+            }
+        }
+        
+        public uint UpdateFrequency {
+            get { return update_frequency; }
+            set {
+                lock (this) {
+                    bool _playing = Playing;
+                    update_frequency = value;
+                    Playing = _playing;
+                }
+            }
+        }
+        
+        public int ActorCount {
+            get { return actors.Count; }
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.mdp
==============================================================================
--- trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.mdp	(original)
+++ trunk/banshee/src/Core/Hyena.Gui/Hyena.Gui.mdp	Thu Jan 31 03:01:05 2008
@@ -28,9 +28,10 @@
     <File name="Hyena.Gui/GtkUtilities.cs" subtype="Code" buildaction="Compile" />
     <File name="Hyena.Data.Gui/CellContext.cs" subtype="Code" buildaction="Compile" />
     <File name="Hyena.Data.Gui/IHeaderCell.cs" subtype="Code" buildaction="Compile" />
-    <File name="Hyena.Widgets" subtype="Directory" buildaction="Compile" />
     <File name="Hyena.Widgets/ScrolledWindow.cs" subtype="Code" buildaction="Compile" />
     <File name="Hyena.Widgets/RoundedFrame.cs" subtype="Code" buildaction="Compile" />
+    <File name="Hyena.Gui.Theatre/Actor.cs" subtype="Code" buildaction="Compile" />
+    <File name="Hyena.Gui.Theatre/Stage.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

Modified: trunk/banshee/src/Core/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs	(original)
+++ trunk/banshee/src/Core/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs	Thu Jan 31 03:01:05 2008
@@ -39,7 +39,6 @@
     {
         private ListViewGraphics graphics;
         private int frame_width = 4;
-        private int border_width = 0;
         
         private Widget child;
         private Gdk.Rectangle child_allocation;
@@ -73,8 +72,8 @@
                 width = height = 80;
             }
                 
-            SetSizeRequest (width + (border_width + frame_width) * 2, 
-                height + (border_width + frame_width) * 2);
+            SetSizeRequest (width + ((int)BorderWidth + frame_width) * 2, 
+                height + ((int)BorderWidth + frame_width) * 2);
         }
 
         protected override void OnSizeAllocated (Gdk.Rectangle allocation)
@@ -87,11 +86,11 @@
                 return;
             }
                 
-            child_allocation.X = border_width + frame_width;
-            child_allocation.Y = border_width + frame_width;
+            child_allocation.X = (int)BorderWidth + frame_width;
+            child_allocation.Y = (int)BorderWidth + frame_width;
             child_allocation.Width = (int)Math.Max (1, Allocation.Width - child_allocation.X * 2);
             child_allocation.Height = (int)Math.Max (1, Allocation.Height - child_allocation.Y - 
-                border_width - frame_width);
+                (int)BorderWidth - frame_width);
                 
             child_allocation.X += Allocation.X;
             child_allocation.Y += Allocation.Y;
@@ -147,12 +146,5 @@
 
 #endregion
 
-        public int BorderWidth {
-            get { return border_width; }
-            set { 
-                border_width = value;
-                QueueResize ();
-            }
-        }
     }
 }

Modified: trunk/banshee/src/Core/Hyena.Gui/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Hyena.Gui/Makefile.am	(original)
+++ trunk/banshee/src/Core/Hyena.Gui/Makefile.am	Thu Jan 31 03:01:05 2008
@@ -16,6 +16,8 @@
 	Hyena.Data.Gui/SortableColumn.cs \
 	Hyena.Gui.Dialogs/ExceptionDialog.cs \
 	Hyena.Gui.Dialogs/VersionInformationDialog.cs \
+	Hyena.Gui.Theatre/Actor.cs \
+	Hyena.Gui.Theatre/Stage.cs \
 	Hyena.Gui/CairoExtensions.cs \
 	Hyena.Gui/CleanRoomStartup.cs \
 	Hyena.Gui/EntryEraseAction.cs \



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