banshee r3264 - in trunk/banshee: . src/Clients/Nereid/Nereid src/Core/Banshee.Services/Banshee.Library src/Core/Banshee.Services/Banshee.Playlist src/Core/Banshee.Services/Banshee.SmartPlaylist src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient src/Core/Banshee.ThickClient/Banshee.Gui.Widgets src/Core/Banshee.ThickClient/Banshee.Sources.Gui src/Extensions/Banshee.Lastfm src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue src/Libraries/Hyena.Gui src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics src/Libraries/Hyena.Gui/Hyena.Widgets src/Libraries/Hyena/Hyena.Data src/Libraries/Lastfm



Author: abock
Date: Mon Feb 18 22:20:23 2008
New Revision: 3264
URL: http://svn.gnome.org/viewvc/banshee?rev=3264&view=rev

Log:
2008-02-18  Aaron Bockover  <abock gnome org>

    * src/Clients/Nereid/Nereid/ViewContainer.cs: Pack a ConnectedMessageBar

    * src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs:
    * src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceIconResolver.cs:
    Pulled the icon resolver out of SourceRowRenderer since sources may have
    multiple icons and it's useful outside of the renderer

    * src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs:
    Works against a number of standardized Message.* properties that can be
    set on a source's PropertyStore; this allows sources to communicate status
    messages easily to the user

    * src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs:
    Use the new Message.* properties to communicate status messages to the user

    * src/Libraries/Hyena/Hyena.Data/PropertyStore.cs: Added RemoveStartingWith

    * src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Actor.cs: Added a CanExpire
    property; reset the percentage to 0 when it reaches 1 and the actor is
    not allowed to expire

    * src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedImage.cs:
    * src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs: Ported/moved from
    Banshee.Widgets; AnimatedImage works better and uses Hyena.Gui.Theatrics

    * src/Libraries/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs: Send the
    expose events to children

    * src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs:
    * src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs:
    * src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs:
    * src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs:
    * src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs:
    * src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs:
    Updated to reflect the property name change from IconName to Icon.Name



Added:
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceIconResolver.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedImage.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Clients/Nereid/Nereid/ViewContainer.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
   trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
   trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs
   trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs
   trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp
   trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Actor.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.mdp
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am
   trunk/banshee/src/Libraries/Hyena/Hyena.Data/PropertyStore.cs
   trunk/banshee/src/Libraries/Lastfm/Lastfm.mdp

Modified: trunk/banshee/src/Clients/Nereid/Nereid/ViewContainer.cs
==============================================================================
--- trunk/banshee/src/Clients/Nereid/Nereid/ViewContainer.cs	(original)
+++ trunk/banshee/src/Clients/Nereid/Nereid/ViewContainer.cs	Mon Feb 18 22:20:23 2008
@@ -31,6 +31,7 @@
 using Mono.Unix;
 
 using Banshee.Widgets;
+using Banshee.Gui.Widgets;
 using Banshee.Collection;
 
 namespace Nereid
@@ -73,6 +74,7 @@
             search_entry.Show ();
             
             PackStart (header, false, false, 0);
+            PackEnd (new ConnectedMessageBar (), false, true, 0);
         }
         
         private void BuildSearchEntry ()

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Library/LibrarySource.cs	Mon Feb 18 22:20:23 2008
@@ -65,9 +65,9 @@
             DELETE FROM CoreSmartPlaylistEntries WHERE TrackID = ?"
         );
     
-        public LibrarySource () : base (Catalog.GetString("Library"), Catalog.GetString ("Library"), "Library", 1)
+        public LibrarySource () : base (Catalog.GetString ("Library"), Catalog.GetString ("Library"), "Library", 1)
         {
-            Properties.SetStringList ("IconName", "go-home", "user-home", "source-library");
+            Properties.SetStringList ("Icon.Name", "go-home", "user-home", "source-library");
             Properties.SetString ("GtkActionPath", "/LibraryContextMenu");
             AfterInitialized ();
 

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	Mon Feb 18 22:20:23 2008
@@ -105,7 +105,7 @@
         public PlaylistSource (string name, int? dbid, int sortColumn, int sortType) 
             : base (generic_name, name, dbid, sortColumn, sortType)
         {
-            Properties.SetString ("IconName", "source-playlist");
+            Properties.SetString ("Icon.Name", "source-playlist");
             Properties.SetString ("RemoveTracksActionLabel", Catalog.GetString ("Remove From Playlist"));
             Properties.SetString ("UnmapSourceActionLabel", Catalog.GetString ("Delete Playlist"));
             DbId = dbid;

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.SmartPlaylist/SmartPlaylistSource.cs	Mon Feb 18 22:20:23 2008
@@ -197,7 +197,7 @@
 
         protected void InstallProperties ()
         {
-            Properties.SetString ("IconName", "source-smart-playlist");
+            Properties.SetString ("Icon.Name", "source-smart-playlist");
             Properties.SetString ("SourcePropertiesActionLabel", properties_label);
             Properties.SetString ("UnmapSourceActionLabel", Catalog.GetString ("Delete Smart Playlist"));
         }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/ErrorSource.cs	Mon Feb 18 22:20:23 2008
@@ -46,7 +46,7 @@
 
         public ErrorSource (string name) : base (name, name, 0)
         {
-            Properties.SetStringList ("IconName", "dialog-error", "gtk-dialog-error");
+            Properties.SetStringList ("Icon.Name", "dialog-error", "gtk-dialog-error");
         }
         
         private void OnReloaded ()

Added: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs	Mon Feb 18 22:20:23 2008
@@ -0,0 +1,161 @@
+//
+// ConnectedMessageBar.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 Gtk;
+
+using Hyena.Data;
+using Banshee.Sources;
+using Banshee.ServiceStack;
+
+using Hyena.Widgets;
+using Banshee.Sources.Gui;
+
+namespace Banshee.Gui.Widgets
+{
+    public class ConnectedMessageBar : MessageBar
+    {
+        private Source source;
+        
+        public ConnectedMessageBar ()
+        {
+            ButtonClicked += OnActionClicked;
+            CloseClicked += OnCloseClicked;
+            ServiceManager.SourceManager.ActiveSourceChanged += OnActiveSourceChanged;
+            ConnectSource (ServiceManager.SourceManager.ActiveSource);
+        }
+        
+        private void ConnectSource (Source source)
+        {
+            this.source = source;
+            
+            if (this.source != null) {
+                this.source.Properties.PropertyChanged += OnSourcePropertyChanged;
+                
+                UpdateText (this.source.Properties.GetString ("Message.Text"), false);
+                UpdateClose (this.source.Properties.GetBoolean ("Message.CanClose"), false);
+                UpdateAction (false);
+                UpdateIcon (false);
+                UpdateSpinner (this.source.Properties.GetBoolean ("Message.IsSpinning"), false);
+            }
+        }
+        
+        private void UpdateText (object value, bool removed)
+        {
+            string message = removed || value == null ? null : value.ToString ();
+            Message = message;
+            
+            if (message == null || removed || source.Properties.GetBoolean ("Message.IsHidden")) {
+                Hide ();
+            } else {
+                Show ();
+            }
+        }
+        
+        private void UpdateIcon (bool removed)
+        {
+            if (removed) {
+                SourceIconResolver.InvalidatePixbufs (source, "Message");
+                Pixbuf = null;
+                return;
+            }
+            
+            Pixbuf = SourceIconResolver.ResolveIcon (source, "Message");
+        }
+        
+        private void UpdateClose (bool value, bool removed)
+        {
+            ShowCloseButton = value && !removed; 
+        }
+        
+        private void UpdateAction (bool removed)
+        {
+            if (removed) {
+                ButtonLabel = null; 
+                return;
+            }
+            
+            ButtonLabel = source.Properties.GetString ("Message.Action.Label");
+            ButtonUseStock = source.Properties.GetBoolean ("Message.Action.IsStock");
+        }
+        
+        private void UpdateSpinner (bool value, bool removed)
+        {
+            Spinning = value && !removed; 
+        }
+        
+        private void OnActionClicked (object o, EventArgs args)
+        {
+            EventHandler handler = source.Properties.Get<EventHandler> ("Message.Action.NotifyHandler");
+            if (handler != null) {
+                handler (o, args);
+            }
+        }
+        
+        private void OnCloseClicked (object o, EventArgs args)
+        {
+            source.Properties.SetBoolean ("Message.IsHidden", true);
+        }
+        
+        private void OnActiveSourceChanged (SourceEventArgs args)
+        {
+            if (source != null && source != args.Source) {
+                source.Properties.PropertyChanged -= OnSourcePropertyChanged;
+            }
+            
+            ConnectSource (args.Source);
+        }
+        
+        private void OnSourcePropertyChanged (object o, PropertyChangeEventArgs args)
+        {
+            if (!args.PropertyName.StartsWith ("Message.")) {
+                return;
+            }
+            
+            if (args.PropertyName == "Message.Text") {
+                UpdateText (args.NewValue, args.Removed);
+            } else if (args.PropertyName == "Message.Icon.Name") {
+                SourceIconResolver.InvalidatePixbufs (source, "Message");
+                UpdateIcon (args.Removed);
+            } else if (args.PropertyName == "Message.CanClose") {
+                UpdateClose (args.NewValue == null ? false : (bool)args.NewValue, args.Removed);
+            } else if (args.PropertyName.StartsWith ("Message.Action.")) {
+                UpdateAction (args.Removed);
+            } else if (args.PropertyName == "Message.IsSpinning") {
+                UpdateSpinner (args.NewValue == null ? false : (bool)args.NewValue, args.Removed);
+            } else if (args.PropertyName == "Message.IsHidden") {
+                bool value = args.NewValue == null ? false : (bool)args.NewValue;
+                if (args.Removed || !value) {
+                    UpdateText (this.source.Properties.GetString ("Message.Text"), false);
+                } else if (value) {
+                    Hide ();
+                }
+            }
+        }
+    }
+}

Added: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceIconResolver.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceIconResolver.cs	Mon Feb 18 22:20:23 2008
@@ -0,0 +1,100 @@
+//
+// SourceIconResolver.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.Reflection;
+
+using Banshee.Gui;
+
+namespace Banshee.Sources.Gui
+{
+    public static class SourceIconResolver
+    {
+        public static Gdk.Pixbuf ResolveIcon (Source source)
+        {
+            return ResolveIcon (source, 22, null);
+        }
+        
+        public static Gdk.Pixbuf ResolveIcon (Source source, string @namespace)
+        {
+            return ResolveIcon (source, 22, @namespace);
+        }
+    
+        public static Gdk.Pixbuf ResolveIcon (Source source, int size)
+        {
+            return ResolveIcon (source, size, null);
+        }
+        
+        public static Gdk.Pixbuf ResolveIcon (Source source, int size, string @namespace)
+        {
+            string name_property = @namespace == null 
+                ? "Icon.Name" 
+                : String.Format ("{0}.Icon.Name", @namespace);
+                
+            string pixbuf_property = @namespace == null 
+                ? String.Format ("Icon.Pixbuf_{0}", size)
+                : String.Format ("{0}.Icon.Pixbuf_{1}", @namespace, size);
+        
+            Gdk.Pixbuf icon = source.Properties.Get<Gdk.Pixbuf> (pixbuf_property);
+            
+            if (icon != null) {
+                return icon;
+            }
+            
+            Type icon_type = source.Properties.GetType (name_property);
+            Assembly asm = source.Properties.Get<Assembly> ("ResourceAssembly");
+            
+            if (icon_type == typeof (string)) {
+                icon = IconThemeUtils.LoadIcon (asm, size, source.Properties.GetString (name_property));
+            } else if (icon_type == typeof (string [])) {
+                icon = IconThemeUtils.LoadIcon (asm, size, source.Properties.GetStringList (name_property));
+            }
+
+            if (icon == null) {
+                icon = Banshee.Gui.IconThemeUtils.LoadIcon (size, "image-missing");
+            }
+                
+            if (icon != null) {
+                source.Properties.Set<Gdk.Pixbuf> (pixbuf_property, icon);
+            }
+            
+            return icon;
+        }
+        
+        public static void InvalidatePixbufs (Source source)
+        {
+            InvalidatePixbufs (source, null);
+        }
+        
+        public static void InvalidatePixbufs (Source source, string @namespace)
+        {
+            string property = @namespace == null ? "Icon.Pixbuf" : String.Format ("{0}.Icon.Pixbuf", @namespace);
+            source.Properties.RemoveStartingWith (property);
+        }
+    }
+}

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	Mon Feb 18 22:20:23 2008
@@ -27,7 +27,7 @@
 //
 
 using System;
-using System.Reflection;
+
 using Gtk;
 using Gdk;
 using Pango;
@@ -113,7 +113,7 @@
             
             bool hide_counts = source.Count <= 0;
             
-            Pixbuf icon = ResolveSourceIcon (source);
+            Pixbuf icon = SourceIconResolver.ResolveIcon (source);
             
             FontDescription fd = widget.PangoContext.FontDescription.Copy ();
             fd.Weight = (ISource)ServiceManager.PlaybackController.Source == (ISource)source 
@@ -182,33 +182,6 @@
             return area.Y + (int)Math.Round ((double)(area.Height - height) / 2.0) + 1;
         }
         
-        private Gdk.Pixbuf ResolveSourceIcon (Source source)
-        {
-            Gdk.Pixbuf icon = source.Properties.Get<Gdk.Pixbuf> ("IconPixbuf");
-            
-            if (icon != null) {
-                return icon;
-            }
-            
-            Type icon_type = source.Properties.GetType ("IconName");
-            Assembly asm = source.Properties.Get<Assembly> ("ResourceAssembly");
-            if(icon_type == typeof (string)) {
-                icon = Banshee.Gui.IconThemeUtils.LoadIcon (asm, 22, source.Properties.GetString ("IconName"));
-            } else if (icon_type == typeof (string [])) {
-                icon = Banshee.Gui.IconThemeUtils.LoadIcon (asm, 22, source.Properties.GetStringList ("IconName"));
-            }
-
-            if (icon == null) {
-                icon = Banshee.Gui.IconThemeUtils.LoadIcon (22, "image-missing");
-            }
-                
-            if (icon != null) {
-                source.Properties.Set<Gdk.Pixbuf> ("IconPixbuf", icon);
-            }
-            
-            return icon;
-        }
-        
         public override CellEditable StartEditing (Gdk.Event evnt , Widget widget, string path, 
             Gdk.Rectangle background_area, Gdk.Rectangle cell_area, CellRendererState flags)
         {

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	Mon Feb 18 22:20:23 2008
@@ -88,6 +88,8 @@
     <File name="Banshee.Collection.Gui/PersistentColumnController.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Gui.Widgets/PlaylistMenuItem.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Query.Gui/SmartPlaylistQueryValueEntry.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.Widgets/ConnectedMessageBar.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Sources.Gui/SourceIconResolver.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Project" localcopy="False" refto="Hyena.Gui" />

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	Mon Feb 18 22:20:23 2008
@@ -41,6 +41,7 @@
 	Banshee.Gui.DragDrop/DragDropTarget.cs \
 	Banshee.Gui.DragDrop/DragDropUtilities.cs \
 	Banshee.Gui.Widgets/ArtworkPopup.cs \
+	Banshee.Gui.Widgets/ConnectedMessageBar.cs \
 	Banshee.Gui.Widgets/ConnectedSeekSlider.cs \
 	Banshee.Gui.Widgets/ConnectedVolumeButton.cs \
 	Banshee.Gui.Widgets/PlaylistMenuItem.cs \
@@ -69,6 +70,7 @@
 	Banshee.Query.Gui/SmartPlaylistQueryValueEntry.cs \
 	Banshee.SmartPlaylist.Gui/Editor.cs \
 	Banshee.Sources.Gui/CellEditEntry.cs \
+	Banshee.Sources.Gui/SourceIconResolver.cs \
 	Banshee.Sources.Gui/SourceRowRenderer.cs \
 	Banshee.Sources.Gui/SourceView.cs \
 	Banshee.Sources.Gui/SourceView_DragAndDrop.cs

Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSource.cs	Mon Feb 18 22:20:23 2008
@@ -81,7 +81,7 @@
 
             Properties.SetString ("ActiveSourceUIResource", "ActiveSourceUI.xml");
             Properties.SetString ("GtkActionPath", "/LastfmSourcePopup");
-            Properties.SetString ("IconName", "audioscrobbler");
+            Properties.SetString ("Icon.Name", "audioscrobbler");
             Properties.SetString ("SourcePropertiesActionLabel", Catalog.GetString ("Edit Last.fm Settings"));
 
             actions = new LastfmActions (this);

Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs	Mon Feb 18 22:20:23 2008
@@ -52,15 +52,10 @@
 {
     public class StationSource : Source, ITrackModelSource, IUnmapableSource, IDisposable
     {
-        //private static readonly Gdk.Pixbuf refresh_pixbuf = IconThemeUtils.LoadIcon (22, Stock.Refresh);
-        //private static readonly Gdk.Pixbuf error_pixbuf = IconThemeUtils.LoadIcon (22, Stock.DialogError);
-
         private static string generic_name = Catalog.GetString ("Last.fm Station");
         
         private LastfmTrackListModel track_model;
         
-        //private HighlightMessageArea status_bar;
-
         private LastfmSource lastfm;
         public LastfmSource LastfmSource {
             get { return lastfm; }
@@ -79,7 +74,7 @@
                 type = value;
 
                 if (type.IconName != null)
-                    Properties.SetString ("IconName", type.IconName);
+                    Properties.SetString ("Icon.Name", type.IconName);
             }
         }
 
@@ -134,11 +129,6 @@
             Properties.SetString ("SourcePropertiesActionLabel", Catalog.GetString ("Edit Last.fm Station"));
             Properties.SetString ("UnmapSourceActionLabel", Catalog.GetString ("Delete Last.fm Station"));
 
-            //box = new VBox ();
-            //status_bar = new HighlightMessageArea ();
-            //status_bar.BorderWidth = 5;
-            //status_bar.LeftPadding = 15;
-            //status_bar.Hide ();
             UpdateUI (lastfm.Connection.State);
         }
 
@@ -191,14 +181,8 @@
             //shuffle = (action_service.GlobalActions ["ShuffleAction"] as ToggleAction).Active;
             //(action_service.GlobalActions ["ShuffleAction"] as ToggleAction).Active = false;
             //Globals.ActionManager["ShuffleAction"].Sensitive = false;
- 
-            /*if (show_status)
-                status_bar.Show ();
-            else
-                status_bar.Hide ();*/
 
             //action_service.GlobalActions ["PreviousAction"].Sensitive = false;
-            //InterfaceElements.MainContainer.PackEnd (status_bar, false, false, 0);
 
             // We lazy load the Last.fm connection, so if we're not already connected, do it
             if (lastfm.Connection.State == ConnectionState.Connected)
@@ -226,7 +210,6 @@
             //Globals.ActionManager["ShuffleAction"].Sensitive = true;
 
             //Globals.ActionManager["PreviousAction"].Sensitive = true;
-            //InterfaceElements.MainContainer.Remove (status_bar);
         }
 
         // Last.fm requires you to 'tune' to a station before requesting a track list/playing it
@@ -252,25 +235,30 @@
             }
         }
 
-        bool show_status = false;
         private void SetStatus (string message, bool error)
         {
-            /*ThreadAssist.ProxyToMain (delegate {
-                show_status = true;
+            ThreadAssist.ProxyToMain (delegate {
                 string status_name = String.Format ("<i>{0}</i>", GLib.Markup.EscapeText (Name));
-                status_bar.Message = String.Format ("<big>{0}</big>", String.Format (GLib.Markup.EscapeText (message), status_name));
-                status_bar.Pixbuf = error ? error_pixbuf : refresh_pixbuf;
-                status_bar.ShowCloseButton = true;
-                status_bar.Show ();
-            });*/
+                Properties.SetString ("Message.Text", String.Format ("{0}", 
+                    String.Format (GLib.Markup.EscapeText (message), status_name)));
+                
+                if (error) {
+                    Properties.SetString ("Message.Icon.Name", "dialog-error");
+                    Properties.SetBoolean ("Message.IsSpinning", false);
+                } else {
+                    Properties.RemoveStartingWith ("Message.Icon.");
+                    Properties.SetBoolean ("Message.IsSpinning", true);
+                }
+                
+                Properties.SetBoolean ("Message.CanClose", true);
+            });
         }
 
         private void HideStatus ()
         {
-            /*ThreadAssist.ProxyToMain (delegate {
-                show_status = false;
-                status_bar.Hide ();
-            });*/
+            ThreadAssist.ProxyToMain (delegate {
+                Properties.RemoveStartingWith ("Message.");
+            });
         }
 
         /*public override void ShowPropertiesDialog ()

Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp	(original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp	Mon Feb 18 22:20:23 2008
@@ -36,4 +36,4 @@
   <DeploymentInformation strategy="File">
     <excludeFiles />
   </DeploymentInformation>
-</Project>
+</Project>
\ No newline at end of file

Modified: trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueSource.cs	Mon Feb 18 22:20:23 2008
@@ -60,7 +60,7 @@
             BindToDatabase ();
             
             Order = 0;
-            Properties.SetString ("IconName", "audio-x-generic");
+            Properties.SetString ("Icon.Name", "audio-x-generic");
             Properties.SetString ("RemoveTracksActionLabel", Catalog.GetString ("Remove From Play Queue"));
             
             ((TrackListDatabaseModel)TrackModel).ForcedSortQuery = "CorePlaylistEntries.EntryID ASC";

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Actor.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Actor.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Actor.cs	Mon Feb 18 22:20:23 2008
@@ -38,6 +38,7 @@
         private uint duration;
         private double frames;
         private double percent;
+        private bool can_expire = true;
     
         public Actor (T target, uint duration)
         {
@@ -55,12 +56,21 @@
         
         public virtual void Step ()
         {
+            if (!CanExpire && percent >= 1.0) {
+                Reset ();
+            }
+            
             percent = (DateTime.Now - start_time).TotalMilliseconds / duration;
             frames++;
         }
 
         public bool Expired {
-            get { return percent >= 1.0; }
+            get { return CanExpire && percent >= 1.0; }
+        }
+        
+        public bool CanExpire {
+            get { return can_expire; }
+            set { can_expire = value; }
         }
         
         public T Target {

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.mdp
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.mdp	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.mdp	Mon Feb 18 22:20:23 2008
@@ -48,6 +48,8 @@
     <File name="Hyena.Query.Gui/FileSizeQueryValueEntry.cs" subtype="Code" buildaction="Compile" />
     <File name="Hyena.Query.Gui/QueryLimitBox.cs" subtype="Code" buildaction="Compile" />
     <File name="Hyena.Query.Gui/QueryTermsBox.cs" subtype="Code" buildaction="Compile" />
+    <File name="Hyena.Widgets/MessageBar.cs" subtype="Code" buildaction="Compile" />
+    <File name="Hyena.Widgets/AnimatedImage.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

Added: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedImage.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedImage.cs	Mon Feb 18 22:20:23 2008
@@ -0,0 +1,151 @@
+//
+// AnimatedImage.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 Gtk;
+
+using Hyena.Gui;
+using Hyena.Gui.Theatrics;
+
+namespace Hyena.Widgets
+{
+    public class AnimatedImage : Image
+    {
+        private Gdk.Pixbuf pixbuf;
+        private Gdk.Pixbuf inactive_pixbuf;
+        private Gdk.Pixbuf [] frames;
+        private int frame_width;
+        private int frame_height;
+        private int max_frames;
+        
+        private SingleActorStage stage = new SingleActorStage ();
+        
+        public AnimatedImage ()
+        {
+            stage.Iteration += OnIteration;
+            stage.Reset ();
+            stage.Actor.CanExpire = false;
+        }
+        
+        public void Load ()
+        {
+            ExtractFrames ();
+            base.Pixbuf = frames[0];
+        }
+        
+        private void OnIteration (object o, EventArgs args)
+        {
+            if (frames == null || frames.Length == 0) {
+                return;
+            } else if (frames.Length == 1) {
+                base.Pixbuf = frames[0];
+                return;
+            }
+            
+            // The first frame is the idle frame, so skip it when animating
+            int index = (int)Math.Round ((double)(frames.Length - 2) * stage.Actor.Percent) + 1;
+            if (base.Pixbuf != frames[index]) {
+                base.Pixbuf = frames[index];
+            }
+        }
+        
+        private void ExtractFrames ()
+        {
+            if (pixbuf == null) {
+                throw new ApplicationException ("No source pixbuf specified");
+            } else if (pixbuf.Width % frame_width != 0 || pixbuf.Height % frame_height != 0) {
+                throw new ApplicationException ("Invalid frame dimensions");
+            }
+            
+            int rows = pixbuf.Height / frame_height;
+            int cols = pixbuf.Width / frame_width;
+            int frame_count = rows * cols;
+            
+            frames = new Gdk.Pixbuf[max_frames > 0 ? max_frames : frame_count];
+            
+            for (int y = 0, n = 0; y < rows; y++) {
+                for (int x = 0; x < cols; x++, n++) {
+                    frames[n] = new Gdk.Pixbuf (pixbuf, x * frame_width, y * frame_height, 
+                        frame_width, frame_height);
+                    
+                    if (max_frames > 0 && n >= max_frames - 1) {
+                        return;
+                    }
+                }
+            }
+        }
+        
+        public bool Active {
+            get { return stage.Playing; }
+            set { 
+                if (value) {
+                    stage.Play ();
+                } else {
+                    stage.Pause ();
+                    if (inactive_pixbuf != null) {
+                        base.Pixbuf = inactive_pixbuf;
+                    } else if (frames != null && frames.Length > 1) {
+                        base.Pixbuf = frames[0];
+                    } else {
+                        base.Pixbuf = null;
+                    }
+                }
+            }
+        }
+        
+        public int FrameWidth {
+            get { return frame_width; }
+            set { frame_width = value; }
+        }
+        
+        public int FrameHeight {
+            get { return frame_height; }
+            set { frame_height = value; }
+        }
+        
+        public int MaxFrames {
+            get { return max_frames; }
+            set { max_frames = value; }
+        }
+        
+        public new Gdk.Pixbuf Pixbuf {
+            get { return pixbuf; }
+            set { pixbuf = value; }
+        }
+        
+        public Gdk.Pixbuf InactivePixbuf {
+            get { return inactive_pixbuf; }
+            set {
+                inactive_pixbuf = value;
+                if (!Active) {
+                    base.Pixbuf = value;
+                }
+            }
+        }
+    }
+}

Added: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs	Mon Feb 18 22:20:23 2008
@@ -0,0 +1,177 @@
+//
+// MessageBar.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 Gtk;
+
+namespace Hyena.Widgets
+{
+    public class MessageBar : Alignment
+    {   
+        private HBox box;
+        private AnimatedImage image;
+        private Label label;
+        private Button button;
+        private Button close_button;
+        
+        public event EventHandler ButtonClicked {
+            add { button.Clicked += value; }
+            remove { button.Clicked -= value; }
+        }
+        
+        public event EventHandler CloseClicked {
+            add { close_button.Clicked += value; }
+            remove { close_button.Clicked -= value; }
+        }
+        
+        public MessageBar () : base (0.0f, 0.5f, 1.0f, 0.0f)
+        {
+            HBox shell_box = new HBox ();
+            shell_box.Spacing = 10;
+        
+            box = new HBox ();
+            box.Spacing = 10;
+            
+            image = new AnimatedImage ();
+            image.Pixbuf = Gtk.IconTheme.Default.LoadIcon ("process-working", 22, IconLookupFlags.NoSvg);
+            image.FrameHeight = 22;
+            image.FrameWidth = 22;
+            Spinning = false;
+            image.Load ();
+            
+            label = new Label ();
+            label.Xalign = 0.0f;
+            label.Show ();
+            
+            button = new Button ();
+            
+            box.PackStart (image, false, false, 0);
+            box.PackStart (label, true, true, 0);
+            box.Show ();
+            
+            close_button = new Button (new Image (Stock.Close, IconSize.Menu));
+            close_button.Relief = ReliefStyle.None;
+            close_button.Clicked += delegate { Hide (); };
+            close_button.ShowAll ();
+            close_button.Hide ();
+            
+            shell_box.PackStart (box, true, true, 0);
+            shell_box.PackStart (close_button, false, false, 0);
+            shell_box.Show ();
+            
+            Add (shell_box);
+            
+            EnsureStyle ();
+        }
+
+        protected override bool OnExposeEvent (Gdk.EventExpose evnt)
+        {
+            GdkWindow.DrawRectangle (Style.BackgroundGC (StateType.Normal), true, Allocation);
+                
+            Gtk.Style.PaintFlatBox (Style, GdkWindow, StateType.Normal, ShadowType.Out,
+                Gdk.Rectangle.Zero, this, "tooltip", Allocation.X, Allocation.Y, 
+                Allocation.Width, Allocation.Height);
+            
+            base.OnExposeEvent (evnt);
+            return true;
+        }
+      
+        private bool changing_style = false;
+        protected override void OnStyleSet (Gtk.Style previousStyle)
+        {
+            if (changing_style) {
+                return;
+            }
+            
+            changing_style = true;
+            Window win = new Window (WindowType.Popup);
+            win.Name = "gtk-tooltips";
+            win.EnsureStyle ();
+            Style = win.Style;
+            changing_style = false;
+        }
+        
+        public string ButtonLabel {
+            set {
+                bool should_remove = false;
+                foreach (Widget child in box.Children) {
+                    if (child == button) {
+                        should_remove = true;
+                        break;
+                    }
+                }
+                
+                if (should_remove && value == null) {
+                    box.Remove (button);
+                }
+                
+                if (value != null) {
+                    button.Label = value;
+                    button.Show ();
+                    box.PackStart (button, false, false, 0);
+                }
+                
+                QueueDraw ();
+            }
+        }
+        
+        public bool ShowCloseButton {
+            set {
+                close_button.Visible = value;
+                QueueDraw ();
+            }
+        }
+        
+        public bool ButtonUseStock {
+            set {
+                button.UseStock = value;
+                QueueDraw ();
+            }
+        }
+        
+        public string Message {
+            set {
+                label.Markup = value;
+                QueueDraw ();
+            }
+        }
+        
+        public Gdk.Pixbuf Pixbuf {
+            set {
+                image.InactivePixbuf = value;
+                image.Visible = value != null || Spinning;
+                QueueDraw ();
+            }
+        }
+        
+        public bool Spinning {
+            get { return image.Active; }
+            set { image.Active = value; }
+        }
+    }
+}

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/RoundedFrame.cs	Mon Feb 18 22:20:23 2008
@@ -43,7 +43,6 @@
         private Widget child;
         private Gdk.Rectangle child_allocation;
         
-    
         public RoundedFrame ()
         {
         }
@@ -115,6 +114,9 @@
                 
             try {
                 DrawFrame (cr, evnt.Area);
+                if (child != null) {
+                    PropagateExpose (child, evnt);
+                }
                 return false;
             } finally {
                 ((IDisposable)cr.Target).Dispose ();

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am	Mon Feb 18 22:20:23 2008
@@ -40,6 +40,8 @@
 	Hyena.Query.Gui/QueryTermsBox.cs \
 	Hyena.Query.Gui/QueryValueEntry.cs \
 	Hyena.Query.Gui/StringQueryValueEntry.cs \
+	Hyena.Widgets/AnimatedImage.cs \
+	Hyena.Widgets/MessageBar.cs \
 	Hyena.Widgets/RoundedFrame.cs \
 	Hyena.Widgets/ScrolledWindow.cs
 

Modified: trunk/banshee/src/Libraries/Hyena/Hyena.Data/PropertyStore.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena.Data/PropertyStore.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena.Data/PropertyStore.cs	Mon Feb 18 22:20:23 2008
@@ -103,6 +103,27 @@
             }
         }
         
+        public void RemoveStartingWith (string prefix)
+        {
+            lock(this) {
+                Queue<string> to_remove = null;
+                
+                foreach (KeyValuePair<string, object> item in object_store) {
+                    if (item.Key.StartsWith (prefix)) {
+                        if (to_remove == null) {
+                            to_remove = new Queue<string> ();
+                        }
+                        
+                        to_remove.Enqueue (item.Key);
+                    }
+                }
+                
+                while (to_remove != null && to_remove.Count > 0) {
+                    Remove (to_remove.Dequeue ());
+                }
+            }
+        }
+        
         public void Set<T>(string name, T value)
         {
             lock(this) {

Modified: trunk/banshee/src/Libraries/Lastfm/Lastfm.mdp
==============================================================================
--- trunk/banshee/src/Libraries/Lastfm/Lastfm.mdp	(original)
+++ trunk/banshee/src/Libraries/Lastfm/Lastfm.mdp	Mon Feb 18 22:20:23 2008
@@ -18,4 +18,4 @@
     <ProjectReference type="Gac" localcopy="True" refto="gnome-sharp, Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <ProjectReference type="Project" localcopy="True" refto="Hyena" />
   </References>
-</Project>
+</Project>
\ No newline at end of file



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