banshee r3473 - in trunk/banshee: . src/Core/Banshee.Services src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient/Banshee.Gui.Widgets src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio src/Libraries/Hyena.Gui/Hyena.Widgets



Author: abock
Date: Mon Mar 17 22:50:50 2008
New Revision: 3473
URL: http://svn.gnome.org/viewvc/banshee?rev=3473&view=rev

Log:
2008-03-17  Aaron Bockover  <abock gnome org>

    * src/Core/Banshee.Services/Banshee.Sources/MessageAction.cs: Non-GUI
    action that can be attached to a SourceMessage

    * src/Core/Banshee.Services/Banshee.Sources/Source.cs: Added SourceMessage
    support to replace the Message.* properties; supports a stack of messages

    * src/Core/Banshee.Services/Banshee.Sources/SourceMessage.cs: Message
    class replacing all of the Message.* properties

    * src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs:
    * src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs:
    Updated to use the new Source/SourceMessage changes

    * src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedBox.cs:
    * src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedHBox.cs:
    * src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedVBox.cs: Some code
    clean ups and the ability to remove all widgets at once

    * src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs: Minor rendering fix



Added:
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/MessageAction.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/SourceMessage.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
   trunk/banshee/src/Core/Banshee.Services/Makefile.am
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs
   trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/StationSource.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedBox.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedHBox.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedVBox.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp	Mon Mar 17 22:50:50 2008
@@ -127,6 +127,8 @@
     <File name="Banshee.Query/PlaylistQueryValue.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Collection/SelectAllSelection.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Collection.Database/DatabaseAlbumInfo.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Sources/SourceMessage.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Sources/MessageAction.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/Core/Banshee.Services/Banshee.Sources/MessageAction.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/MessageAction.cs	Mon Mar 17 22:50:50 2008
@@ -0,0 +1,84 @@
+//
+// MessageAction.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 Banshee.Sources
+{
+    public class MessageAction
+    {
+        private bool is_stock;
+        private string label;
+        
+        public event EventHandler Activated;
+        
+        public MessageAction (string label) : this (label, false, null)
+        {
+        }
+        
+        public MessageAction (string label, EventHandler handler) : this (label, false, handler)
+        {
+        }
+        
+        public MessageAction (string label, bool isStock) : this (label, isStock, null)
+        {
+        }
+        
+        public MessageAction (string label, bool isStock, EventHandler handler)
+        {
+            this.label = label;
+            this.is_stock = isStock;
+            if (handler != null) {
+                this.Activated += handler;
+            }
+        }
+        
+        public void Activate ()
+        {
+            OnActivated ();
+        }
+        
+        protected virtual void OnActivated ()
+        {
+            EventHandler handler = Activated;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
+        
+        public bool IsStock {
+            get { return is_stock; }
+            set { is_stock = value; }
+        }
+        
+        public string Label {
+            get { return label; }
+            set { label = value; }
+        }
+    }
+}

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	Mon Mar 17 22:50:50 2008
@@ -38,6 +38,7 @@
 using Hyena.Data;
 using Hyena.Query;
 
+using Banshee.Base;
 using Banshee.Collection;
 using Banshee.ServiceStack;
 
@@ -47,11 +48,13 @@
     {
         private Source parent;
         private PropertyStore properties = new PropertyStore ();
+        private List<SourceMessage> messages = new List<SourceMessage> ();
         private List<Source> child_sources = new List<Source> ();
         private ReadOnlyCollection<Source> read_only_children;
 
         public event EventHandler Updated;
         public event EventHandler UserNotifyUpdated;
+        public event EventHandler MessageNotify;
         public event SourceEventHandler ChildSourceAdded;
         public event SourceEventHandler ChildSourceRemoved;
         
@@ -70,6 +73,10 @@
 
             properties.PropertyChanged += OnPropertyChanged;
             read_only_children = new ReadOnlyCollection<Source> (child_sources);
+            
+            if (ApplicationContext.Debugging && ApplicationContext.CommandLine.Contains ("test-source-messages")) {
+                TestMessages ();
+            }
         }
         
         protected void OnSetupComplete ()
@@ -202,6 +209,87 @@
 #endregion
         
 #region Protected Methods
+
+        protected virtual void PushMessage (SourceMessage message)
+        {
+            lock (this) {
+                messages.Insert (0, message);
+            }
+            
+            OnMessageNotify ();
+        }
+        
+        protected virtual SourceMessage PopMessage ()
+        {
+            try {
+                lock (this) {
+                    if (messages.Count > 0) {
+                        SourceMessage message = messages[0];
+                        messages.RemoveAt (0);
+                        return message;
+                    }
+                    
+                    return null;
+                }
+            } finally {
+                OnMessageNotify ();
+            }
+        }
+        
+        private void TestMessages ()
+        {
+            int count = 0;
+            SourceMessage message_3 = null;
+            
+            Application.RunTimeout (5000, delegate {
+                if (count++ > 5) {
+                    if (count == 7) {
+                        RemoveMessage (message_3);
+                    }
+                    PopMessage ();
+                    return true;
+                } else if (count > 10) {
+                    return false;
+                }
+                
+                SourceMessage message = new SourceMessage (this);
+                message.FreezeNotify ();
+                message.Text = String.Format ("Testing message {0}", count);
+                message.IsSpinning = count % 2 == 0;
+                message.CanClose = count % 2 == 1;
+                if (count % 3 == 0) {
+                    for (int i = 2; i < count; i++) {
+                        message.AddAction (new MessageAction (String.Format ("Button {0}", i)));
+                    }
+                }
+                    
+                message.ThawNotify ();
+                PushMessage (message);
+                
+                if (count == 3) {
+                    message_3 = message;
+                }
+                
+                return true;
+            });
+        }
+        
+        protected virtual void RemoveMessage (SourceMessage message)
+        {
+            lock (this) {
+                if (messages.Remove (message)) {
+                    OnMessageNotify ();
+                }
+            }   
+        }
+        
+        protected virtual void OnMessageNotify ()
+        {
+            EventHandler handler = MessageNotify;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
     
         protected virtual void OnChildSourceAdded (Source source)
         {
@@ -257,9 +345,7 @@
         }
         
         string [] ISource.Children {
-            get {
-                return null;
-            }
+            get { return null; }
         }
 
         public Source Parent {
@@ -288,6 +374,10 @@
             get { return properties.GetInteger ("Order"); }
             set { properties.SetInteger ("Order", value); }
         }
+        
+        public SourceMessage CurrentMessage {
+            get { lock (this) { return messages.Count > 0 ? messages[0] : null; } }
+        }
 
         public virtual bool ImplementsCustomSearch {
             get { return false; }

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/SourceMessage.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/SourceMessage.cs	Mon Mar 17 22:50:50 2008
@@ -0,0 +1,149 @@
+//
+// SourceMessage.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 Banshee.Sources
+{
+    public class SourceMessage
+    {
+        private bool updated_when_frozen;
+        private int freeze_count;
+        
+        private List<MessageAction> actions;
+        
+        private Source source;
+        private bool is_spinning;
+        private bool is_hidden;
+        private bool can_close;
+        private string text;
+        private string [] icon_names;
+        
+        public event EventHandler Updated;
+        
+        public SourceMessage (Source source)
+        {
+            this.source = source;
+        }
+        
+        public void AddAction (MessageAction action)
+        {
+            lock (this) {
+                if (actions == null) {
+                    actions = new List<MessageAction> ();
+                }
+                actions.Add (action);
+                OnUpdated ();
+            }
+        }
+        
+        public void ClearActions ()
+        {
+            lock (this) {
+                if (actions != null) {
+                    actions.Clear ();
+                }
+                OnUpdated ();
+            }
+        }
+        
+        public void SetIconName (params string [] name)
+        {
+            icon_names = name;
+        }
+        
+        public string [] IconNames {
+            get { return icon_names; }
+        }
+        
+        public void FreezeNotify ()
+        {
+            lock (this) {
+                System.Threading.Interlocked.Increment (ref freeze_count);
+            }
+        }
+        
+        public void ThawNotify ()
+        {
+            lock (this) {
+                if (freeze_count > 0) {
+                    System.Threading.Interlocked.Decrement (ref freeze_count);
+                }
+                
+                if (freeze_count == 0 && updated_when_frozen) {
+                    OnUpdated ();
+                }
+            }
+        }
+        
+        protected virtual void OnUpdated ()
+        {
+            if (freeze_count != 0) {
+                updated_when_frozen = true;
+                return;
+            }
+            
+            updated_when_frozen = false;
+            
+            EventHandler handler = Updated;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
+        
+        public bool IsSpinning {
+            get { return is_spinning; }
+            set { lock (this) { is_spinning = value; OnUpdated (); } }
+        }
+
+        public bool IsHidden {
+            get { return is_hidden; }
+            set { lock (this) { is_hidden = value; OnUpdated (); } }
+        }
+
+        public bool CanClose {
+            get { return can_close; }
+            set { lock (this) { can_close = value; OnUpdated (); } }
+        }
+        
+        public Source Source {
+            get { return source; }
+            set { lock (this) { source = value; OnUpdated (); } }
+        }
+        
+        public string Text {
+            get { return text; }
+            set { lock (this) { text = value; OnUpdated (); } }  
+        }
+        
+        public IEnumerable<MessageAction> Actions {
+            get { return actions; }
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.Services/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Makefile.am	Mon Mar 17 22:50:50 2008
@@ -114,10 +114,12 @@
 	Banshee.Sources/ISourceManager.cs \
 	Banshee.Sources/ITrackModelSource.cs \
 	Banshee.Sources/IUnmapableSource.cs \
+	Banshee.Sources/MessageAction.cs \
 	Banshee.Sources/PrimarySource.cs \
 	Banshee.Sources/Source.cs \
 	Banshee.Sources/SourceManager.cs \
 	Banshee.Sources/SourceMergeType.cs \
+	Banshee.Sources/SourceMessage.cs \
 	Banshee.Streaming/RadioTrackInfo.cs \
 	Banshee.Web/Browser.cs
 

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedMessageBar.cs	Mon Mar 17 22:50:50 2008
@@ -35,6 +35,7 @@
 
 using Hyena.Widgets;
 using Banshee.Sources.Gui;
+using Banshee.Base;
 
 namespace Banshee.Gui.Widgets
 {
@@ -42,9 +43,23 @@
     {
         private Source source;
         
+        private class ActionButton : Button
+        {
+            private MessageAction action;
+            
+            public ActionButton (MessageAction action) : base (action.Label)
+            {
+                this.action = action;
+            }
+            
+            protected override void OnClicked ()
+            {
+                action.Activate ();
+            }
+        }
+        
         public ConnectedMessageBar ()
         {
-            ButtonClicked += OnActionClicked;
             CloseClicked += OnCloseClicked;
             ServiceManager.SourceManager.ActiveSourceChanged += OnActiveSourceChanged;
             ConnectSource (ServiceManager.SourceManager.ActiveSource);
@@ -57,107 +72,61 @@
             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);
+                this.source.MessageNotify += OnSourceMessageNotify;
+                Update ();
             }
         }
         
-        private void UpdateText (object value, bool removed)
+        private void Update ()
         {
-            string message = removed || value == null ? null : value.ToString ();
-            Message = message;
-            
-            if (message == null || removed || source.Properties.GetBoolean ("Message.IsHidden")) {
-                Hide ();
-            } else {
-                Show ();
-            }
+            ThreadAssist.ProxyToMain (InnerUpdate);
         }
         
-        private void UpdateIcon (bool removed)
+        private void InnerUpdate (object o, EventArgs args)
         {
-            if (removed) {
-                SourceIconResolver.InvalidatePixbufs (source, "Message");
-                Pixbuf = null;
+            if (source == null || source.CurrentMessage == null || source.CurrentMessage.IsHidden) {
+                Hide ();
                 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;
+            Message = source.CurrentMessage.Text;
+            Pixbuf = null;
+            ShowCloseButton = source.CurrentMessage.CanClose;
+            Spinning = source.CurrentMessage.IsSpinning;
+            
+            Pixbuf = source.CurrentMessage.IconNames == null ? null :
+                IconThemeUtils.LoadIcon (22, source.CurrentMessage.IconNames);
+            
+            ClearButtons ();
+            
+            if (source.CurrentMessage.Actions != null) {
+                foreach (MessageAction action in source.CurrentMessage.Actions) {
+                    Button button = new ActionButton (action);
+                    button.UseStock = action.IsStock;
+                    AddButton (button);
+                }
             }
             
-            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);
-            }
+            Show ();
         }
         
         private void OnCloseClicked (object o, EventArgs args)
         {
-            source.Properties.SetBoolean ("Message.IsHidden", true);
+            source.CurrentMessage.IsHidden = true;
         }
         
         private void OnActiveSourceChanged (SourceEventArgs args)
         {
             if (source != null && source != args.Source) {
-                source.Properties.PropertyChanged -= OnSourcePropertyChanged;
+                source.MessageNotify -= OnSourceMessageNotify;
             }
             
             ConnectSource (args.Source);
         }
         
-        private void OnSourcePropertyChanged (object o, PropertyChangeEventArgs args)
+        private void OnSourceMessageNotify (object o, EventArgs 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 ();
-                }
-            }
+            Update ();
         }
     }
 }

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 Mar 17 22:50:50 2008
@@ -55,6 +55,7 @@
         private static string generic_name = Catalog.GetString ("Last.fm Station");
         
         private LastfmTrackListModel track_model;
+        private SourceMessage status_message;
         
         private LastfmSource lastfm;
         public LastfmSource LastfmSource {
@@ -242,38 +243,36 @@
 
         private void SetStatus (string message, bool error, ConnectionState state)
         {
-            ThreadAssist.ProxyToMain (delegate {
-                string status_name = String.Format ("<i>{0}</i>", GLib.Markup.EscapeText (Name));
-                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);
-                    
-                    if (state == ConnectionState.NoAccount || state == ConnectionState.InvalidAccount) {
-                        Properties.SetString ("Message.Action.Label", Catalog.GetString ("Account Settings"));
-                        Properties.Set<EventHandler> ("Message.Action.NotifyHandler", delegate {
-                             lastfm.Actions.ShowLoginDialog ();
-                           });
-                    } else {
-                        Properties.RemoveStartingWith ("Message.Action.");
-                      }
-                } else {
-                    Properties.RemoveStartingWith ("Message.Icon.");
-                    Properties.SetBoolean ("Message.IsSpinning", true);
-                    Properties.RemoveStartingWith ("Message.Action.");
-                }
-                
-                Properties.SetBoolean ("Message.CanClose", true);
-            });
+            if (status_message == null) {
+                status_message = new SourceMessage (this);
+                PushMessage (status_message);
+            }
+            
+            string status_name = String.Format ("<i>{0}</i>", GLib.Markup.EscapeText (Name));
+            
+            status_message.FreezeNotify ();
+            status_message.Text = String.Format (GLib.Markup.EscapeText (message), status_name);
+            status_message.CanClose = !error;
+            status_message.IsSpinning = !error;
+            status_message.SetIconName (error ? "dialog-error" : null);
+            status_message.ClearActions ();
+            
+            if (error && (state == ConnectionState.NoAccount || state == ConnectionState.InvalidAccount)) {
+                status_message.AddAction (new MessageAction (Catalog.GetString ("Account Settings"),
+                    delegate { lastfm.Actions.ShowLoginDialog (); }));
+                status_message.AddAction (new MessageAction (Catalog.GetString ("Join Last.fm"),
+                    delegate { lastfm.Account.SignUp (); }));
+            }
+            
+            status_message.ThawNotify ();
         }
 
         private void HideStatus ()
         {
-            ThreadAssist.ProxyToMain (delegate {
-                Properties.RemoveStartingWith ("Message.");
-            });
+            if (status_message != null) {
+                RemoveMessage (status_message);
+                status_message = null;
+            }
         }
 
         /*public override void ShowPropertiesDialog ()

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedBox.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedBox.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedBox.cs	Mon Mar 17 22:50:50 2008
@@ -36,16 +36,24 @@
 
 namespace Hyena.Gui
 {
-    public abstract class AnimatedBox : Container, IEnumerable<Widget>
+    public abstract class AnimatedBox : Container
     {
         private readonly Stage<AnimatedWidget> stage = new Stage<AnimatedWidget> ();
         private readonly Queue<AnimatedWidget> expired = new Queue<AnimatedWidget> ();
         private readonly LinkedList<AnimatedWidget> children = new LinkedList<AnimatedWidget> ();
-        private readonly object childrenMutex = new object ();
+        private readonly object children_mutex = new object ();
         
-        protected int spacing;
-        protected int startSpacing;
-        protected int endSpacing;
+        private int spacing;
+        
+        private int start_spacing;
+        protected int StartSpacing {
+            get { return start_spacing; }
+        }
+        
+        private int end_spacing;
+        protected int EndSpacing {
+            get { return end_spacing; }
+        }
         
         private uint duration = 500;
         private Easing easing = Easing.Linear;
@@ -77,7 +85,7 @@
                     break;
                 case AnimationState.Going:
                     if (actor.Expired) {
-                        lock (childrenMutex) {
+                        lock (children_mutex) {
                             children.Remove (actor.Target.Node);
                         }
                         expired.Enqueue (actor.Target);
@@ -152,9 +160,9 @@
         
         public void PackStart (Widget widget, uint duration, Easing easing, Blocking blocking)
         {
-            AnimatedWidget animatedWidget = Pack (widget, duration, easing, blocking);
-            lock (childrenMutex) {
-                animatedWidget.Node = children.AddFirst (animatedWidget);
+            AnimatedWidget animated_widget = Pack (widget, duration, easing, blocking);
+            lock (children_mutex) {
+                animated_widget.Node = children.AddFirst (animated_widget);
             }
         }
         
@@ -195,9 +203,9 @@
         
         public void PackEnd (Widget widget, uint duration, Easing easing, Blocking blocking)
         {
-            AnimatedWidget animatedWidget = Pack (widget, duration, easing, blocking);
-            lock (childrenMutex) {
-                animatedWidget.Node = children.AddLast (animatedWidget);
+            AnimatedWidget animated_widget = Pack (widget, duration, easing, blocking);
+            lock (children_mutex) {
+                animated_widget.Node = children.AddLast (animated_widget);
             }
         }
         
@@ -207,11 +215,11 @@
                 throw new ArgumentNullException ("widget");
             }
             
-            AnimatedWidget animatedWidget = new AnimatedWidget (widget, duration, easing, blocking);
-            animatedWidget.Parent = this;
-            animatedWidget.WidgetDestroyed += OnWidgetDestroyed;
-            stage.Add (animatedWidget, duration);
-            return animatedWidget;
+            AnimatedWidget animated_widget = new AnimatedWidget (widget, duration, easing, blocking);
+            animated_widget.Parent = this;
+            animated_widget.WidgetDestroyed += OnWidgetDestroyed;
+            stage.Add (animated_widget, duration);
+            return animated_widget;
         }
         
 #endregion
@@ -264,17 +272,19 @@
                 throw new ArgumentNullException ("widget");
             }
             
-            AnimatedWidget animatedWidget = null;
-            foreach (AnimatedWidget child in this) {
+            AnimatedWidget animated_widget = null;
+            foreach (AnimatedWidget child in Widgets) {
                 if (child.Widget == widget) {
-                    animatedWidget = child;
+                    animated_widget = child;
                     break;
                 }
             }
-            if (animatedWidget == null) {
+            
+            if (animated_widget == null) {
                 throw new ArgumentException ("Cannot remove the specified widget because it has not been added to this container or it has already been removed.", "widget");
             }
-            RemoveCore (animatedWidget, duration, easing, blocking);
+            
+            RemoveCore (animated_widget, duration, easing, blocking);
         }
         
         private void RemoveCore (AnimatedWidget widget)
@@ -288,9 +298,11 @@
                 if (duration != null) {
                     widget.Duration = duration.Value;
                 }
+                
                 if (easing != null) {
                     widget.Easing = easing.Value;
                 }
+                
                 if (blocking != null) {
                     widget.Blocking = blocking.Value;
                 }
@@ -307,6 +319,7 @@
                     } else if (widget.Easing == Easing.ExponentialOut) {
                         widget.Easing = Easing.ExponentialIn;
                     }
+                    
                     widget.AnimationState = AnimationState.Going;
                     stage.Add (widget, widget.Duration);
                 }
@@ -317,28 +330,24 @@
         
 #region Other Public Methods
         
-        public bool Contains (Widget widget)
+        public void RemoveAll ()
         {
-            foreach (AnimatedWidget child in this) {
-                if (child.AnimationState != AnimationState.Going && child.Widget == widget) {
-                    return true;
+            foreach (AnimatedWidget child in Widgets) {
+                if (child.AnimationState != AnimationState.Going) {
+                    RemoveCore (child);
                 }
             }
-            return false;
         }
         
-        public new IEnumerator<Widget> GetEnumerator ()
+        public bool Contains (Widget widget)
         {
-            lock (childrenMutex) {
-                foreach (AnimatedWidget child in children) {
-                    yield return child;
+            foreach (AnimatedWidget child in Widgets) {
+                if (child.AnimationState != AnimationState.Going && child.Widget == widget) {
+                    return true;
                 }
             }
-        }
-        
-        IEnumerator System.Collections.IEnumerable.GetEnumerator ()
-        {
-            return GetEnumerator ();
+            
+            return false;
         }
         
 #endregion
@@ -358,7 +367,7 @@
         
         protected override void ForAll (bool include_internals, Callback callback)
         {
-            foreach (AnimatedWidget child in this) {
+            foreach (AnimatedWidget child in Widgets) {
                 callback (child);
             }
         }
@@ -375,8 +384,8 @@
                 }
                 spacing = value;
                 double half = (double)spacing / 2.0;
-                startSpacing = (int)Math.Floor (half);
-                endSpacing = (int)Math.Ceiling (half);
+                start_spacing = (int)Math.Floor (half);
+                end_spacing = (int)Math.Ceiling (half);
             }
         }
         
@@ -395,6 +404,16 @@
             set { blocking = value; }
         }
         
+        internal IEnumerable<AnimatedWidget> Widgets {
+            get {
+                lock (children_mutex) {
+                    foreach (AnimatedWidget child in children) {
+                        yield return child;
+                    }
+                }
+            }
+        }
+        
 #endregion
         
     }

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedHBox.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedHBox.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedHBox.cs	Mon Mar 17 22:50:50 2008
@@ -38,14 +38,17 @@
         {
             int width = 0;
             int height = 0;
-            foreach (AnimatedWidget widget in this) {
+            
+            foreach (AnimatedWidget widget in Widgets) {
                 Requisition req = widget.SizeRequest ();
-                widget.Size = req.Width + spacing;
+                widget.Size = req.Width + Spacing;
                 width += widget.Value;
+                
                 if (req.Height > height) {
                     height = req.Height;
                 }
             }
+            
             requisition.Width = width;
             requisition.Height = height;
         }
@@ -53,12 +56,15 @@
         protected override void OnSizeAllocated (Rectangle allocation)
         {
             base.OnSizeAllocated (allocation);
-            foreach (AnimatedWidget widget in this) {
+            
+            foreach (AnimatedWidget widget in Widgets) {
                 allocation.Width = widget.Value;
-                widget.Alloc.X = startSpacing;
+                widget.Alloc.X = StartSpacing;
+                
                 if (widget.Blocking == Blocking.Downstage) {
                     widget.Alloc.X += widget.Value - widget.Size;
                 }
+                
                 widget.Alloc.Height = allocation.Height;
                 widget.SizeAllocate (allocation);
                 allocation.X += allocation.Width;

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedVBox.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedVBox.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedVBox.cs	Mon Mar 17 22:50:50 2008
@@ -38,25 +38,28 @@
         {
             int width = 0;
             int height = 0;
-            int rolloverSpacing = 0;
-            foreach (AnimatedWidget widget in this) {
+            int rollover_Spacing = 0;
+            
+            foreach (AnimatedWidget widget in Widgets) {
                 Requisition req = widget.SizeRequest ();
-                widget.Size = req.Height + rolloverSpacing;
-                widget.Alloc.Y = rolloverSpacing;
+                widget.Size = req.Height + rollover_Spacing;
+                widget.Alloc.Y = rollover_Spacing;
+                
                 if (widget.IsFirst) {
                     if (widget.Next != null) {
                         if (widget.AnimationState != AnimationState.Idle) {
-                            widget.Size += spacing;
+                            widget.Size += Spacing;
                         } else {
-                            widget.Size += endSpacing;
-                            rolloverSpacing = startSpacing;
+                            widget.Size += EndSpacing;
+                            rollover_Spacing = StartSpacing;
                         }
                     }
-                } else if (widget.Next != null && widget.Next.IsLast && widget.Next.AnimationState != AnimationState.Idle) {
-                    rolloverSpacing = spacing;
+                } else if (widget.Next != null && widget.Next.IsLast && 
+                    widget.Next.AnimationState != AnimationState.Idle) {
+                    rollover_Spacing = Spacing;
                 } else if (!widget.IsLast) {
-                    widget.Size += endSpacing;
-                    rolloverSpacing = startSpacing;
+                    widget.Size += EndSpacing;
+                    rollover_Spacing = StartSpacing;
                 }
                 
                 height += widget.Value;
@@ -64,6 +67,7 @@
                     width = req.Width;
                 }
             }
+            
             requisition.Width = width;
             requisition.Height = height;
         }
@@ -71,7 +75,7 @@
         protected override void OnSizeAllocated (Rectangle allocation)
         {
             base.OnSizeAllocated (allocation);
-            foreach (AnimatedWidget widget in this) {
+            foreach (AnimatedWidget widget in Widgets) {
                 allocation.Height = widget.Value;
                 if (widget.Blocking == Blocking.Downstage) {
                     widget.Alloc.Y += widget.Value - widget.Size;

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/MessageBar.cs	Mon Mar 17 22:50:50 2008
@@ -37,18 +37,13 @@
     public class MessageBar : Alignment
     {   
         private HBox box;
+        private HBox button_box;
         private AnimatedImage image;
         private Label label;
-        private Button button;
         private Button close_button;
         
         private Theme theme;
         
-        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; }
@@ -77,12 +72,13 @@
             label.Xalign = 0.0f;
             label.Show ();
             
-            button = new Button ();
-            
             box.PackStart (image, false, false, 0);
             box.PackStart (label, true, true, 0);
             box.Show ();
             
+            button_box = new HBox ();
+            button_box.Spacing = 3;
+            
             close_button = new Button (new Image (Stock.Close, IconSize.Menu));
             close_button.Relief = ReliefStyle.None;
             close_button.Clicked += delegate { Hide (); };
@@ -90,6 +86,7 @@
             close_button.Hide ();
             
             shell_box.PackStart (box, true, true, 0);
+            shell_box.PackStart (button_box, false, false, 0);
             shell_box.PackStart (close_button, false, false, 0);
             shell_box.Show ();
             
@@ -103,9 +100,13 @@
         protected override void OnRealized ()
         {
             base.OnRealized ();
-            
             theme = new GtkTheme (this);
-            // theme.RefreshColors ();
+        }
+        
+        protected override void OnSizeAllocated (Gdk.Rectangle allocation)
+        {
+            base.OnSizeAllocated (allocation);
+            QueueDraw ();
         }
         
         protected override bool OnExposeEvent (Gdk.EventExpose evnt)
@@ -113,13 +114,13 @@
             if (!IsDrawable) {
                 return false;
             }
- 
+            
             Cairo.Context cr = Gdk.CairoHelper.Create (evnt.Window);
                 
             try {
                 Gdk.Color color = Style.Background (StateType.Normal);
                 theme.DrawFrame (cr, Allocation, CairoExtensions.GdkColorToCairoColor (color));
-                return base.OnExposeEvent(evnt);
+                return base.OnExposeEvent (evnt);
             } finally {
                 ((IDisposable)cr.Target).Dispose ();
                 ((IDisposable)cr).Dispose ();
@@ -141,43 +142,28 @@
             changing_style = false;
         }
         
-        public string ButtonLabel {
-            set {
-                bool button_is_child = false;
-                foreach (Widget child in box.Children) {
-                    if (child == button) {
-                        button_is_child = true;
-                        break;
-                    }
-                }
-                
-                if (button_is_child && value == null) {
-                    box.Remove (button);
-                }
-                
-                if (value != null) {
-                    button.Label = value;
-                    button.Show ();
-                    
-                    if (!button_is_child) {
-                        box.PackStart (button, false, false, 0);
-                    }
-                }
-                
-                QueueDraw ();
-            }
+        public void RemoveButton (Button button)
+        {
+            button_box.Remove (button);
         }
         
-        public bool ShowCloseButton {
-            set {
-                close_button.Visible = value;
-                QueueDraw ();
+        public void ClearButtons ()
+        {
+            foreach (Widget child in button_box.Children) {
+                button_box.Remove (child);
             }
         }
         
-        public bool ButtonUseStock {
+        public void AddButton (Button button)
+        {
+            button_box.Show ();
+            button.Show ();
+            button_box.PackStart (button, false, false, 0);
+        }
+        
+        public bool ShowCloseButton {
             set {
-                button.UseStock = value;
+                close_button.Visible = value;
                 QueueDraw ();
             }
         }



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