banshee r4556 - in trunk/banshee: . src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor src/Core/Banshee.ThickClient/Banshee.Gui.Widgets src/Libraries/Hyena.Gui src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Tests src/Libraries/Hyena.Gui/Hyena.Widgets tests



Author: abock
Date: Tue Sep 16 23:26:29 2008
New Revision: 4556
URL: http://svn.gnome.org/viewvc/banshee?rev=4556&view=rev

Log:
2008-09-16  Aaron Bockover  <abock gnome org>

    * src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs:
    When the mouse is over the sync all button, tell all the other sync
    buttons to start pulsing

    * src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SyncButton.cs:
    Extend PulsingButton instead of Button

    * src/Libraries/Hyena.Gui/Hyena.Widgets/PulsingButton.cs: New button that
    pulses, it's hot

    * src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Tests/ChoreographerTests.cs:
    Unit tests for the choreographer compositions

    * src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Choreographer.cs: Factored
    out the scaling and pixel rounded from the core compose functions into
    separate methods

    * src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Pulsator.cs: Small Actor<T>
    wrapper that implements pulsing logic

    * src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs:
    * src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs:
    * src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedBox.cs: Updated for
    API changes in Choreographer



Added:
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Pulsator.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Tests/
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Tests/ChoreographerTests.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/PulsingButton.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SyncButton.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Choreographer.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.csproj
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedBox.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am
   trunk/banshee/tests/Makefile.am

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SyncButton.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SyncButton.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SyncButton.cs	Tue Sep 16 23:26:29 2008
@@ -31,9 +31,9 @@
 
 namespace Banshee.Gui.TrackEditor
 {
-    public class SyncButton : Button
+    public class SyncButton : Hyena.Widgets.PulsingButton
     {
-        public SyncButton ()
+        public SyncButton () : base ()
         {
             Image image = new Image (Stock.Copy, IconSize.Menu);
             Add (image);

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs	Tue Sep 16 23:26:29 2008
@@ -34,6 +34,7 @@
 using Gtk;
 
 using Hyena.Gui;
+using Hyena.Widgets;
 
 using Banshee.Collection;
 using Banshee.Collection.Database;
@@ -85,7 +86,7 @@
     
         private Button nav_backward_button;
         private Button nav_forward_button;
-        private Button sync_all_button;
+        private PulsingButton sync_all_button;
         
         private EditorMode mode;
         
@@ -234,11 +235,28 @@
             button_box.Spacing = 6;
                        
             if (TrackCount > 1) {
-                sync_all_button = new Button ();
+                sync_all_button = new PulsingButton ();
+                sync_all_button.FocusInEvent += delegate {
+                    ForeachSyncButton (delegate (SyncButton button) {
+                        button.StartPulsing ();
+                    });
+                };
+                sync_all_button.FocusOutEvent += delegate {
+                    ForeachSyncButton (delegate (SyncButton button) {
+                        button.StopPulsing ();
+                    });
+                };
+                sync_all_button.StateChanged += delegate {
+                    ForeachSyncButton (delegate (SyncButton button) {
+                        if (sync_all_button.State == StateType.Prelight) {
+                            button.StartPulsing ();
+                        } else {
+                            button.StopPulsing ();
+                        }
+                    });
+                };
                 sync_all_button.Clicked += delegate {
-                    for (int i = 0; i < notebook.NPages; i++) {
-                        InvokeFieldSync (notebook.GetNthPage (i) as Container);
-                    }        
+                    InvokeFieldSync ();
                 };
                 
                 Alignment alignment = new Alignment (0.5f, 0.5f, 0.0f, 0.0f);
@@ -267,7 +285,16 @@
             button_box.ShowAll ();
         }
         
-        private void InvokeFieldSync (Container container)
+        private delegate void SyncButtonAction (SyncButton button);
+        
+        private void ForeachSyncButton (SyncButtonAction action)
+        {
+            for (int i = 0; i < notebook.NPages; i++) {
+                ForeachSyncButton (notebook.GetNthPage (i) as Container, action);
+            }     
+        }
+        
+        private void ForeachSyncButton (Container container, SyncButtonAction action)
         {
             if (container == null) {
                 return;
@@ -276,16 +303,23 @@
             foreach (Widget child in container.Children) {
                 SyncButton sync = child as SyncButton;
                 if (sync != null) {
-                    sync.Click ();
+                    action (sync);
                 } else {
                     Container child_container = child as Container;
                     if (child_container != null) {
-                        InvokeFieldSync (child_container);
+                        ForeachSyncButton (child_container, action);
                     }
                 }
             }
         }
         
+        private void InvokeFieldSync ()
+        {
+            ForeachSyncButton (delegate (SyncButton button) {
+                button.Click ();
+            });
+        }
+        
         private int action_area_children_allocated = 0;
         
         private void OnActionAreaChildSizeAllocated (object o, SizeAllocatedArgs args)
@@ -450,5 +484,74 @@
 
 #endregion
 
+#region Saving
+        
+       /* private void OnSaveButtonClicked (object o, EventArgs args)
+        {
+            List<int> primary_sources = new List<int> ();
+            
+            // TODO wrap in db transaction
+            try {
+                DatabaseTrackInfo.NotifySaved = false;
+
+                primary_sources.Clear ();
+                foreach (EditorTrack track in TrackSet) {
+                    SaveTrack (track);
+
+                    if (track.Track is DatabaseTrackInfo) {
+                        int id = (track.Track as DatabaseTrackInfo).PrimarySourceId;
+                        if (!primary_sources.Contains (id)) {
+                            primary_sources.Add (id);
+                        }
+                    }
+                }
+                
+                EventHandler handler = Saved;
+                if (handler != null) {
+                    handler (this, new EventArgs ());
+                }
+
+                // Finally, notify the affected primary sources
+                foreach (int id in primary_sources) {
+                    PrimarySource.GetById (id).NotifyTracksChanged ();
+                }
+            } finally {
+                DatabaseTrackInfo.NotifySaved = true;
+            }
+            
+            Window.Destroy ();
+        }
+        
+        private void SaveTrack (EditorTrack track)
+        {
+            track.Save ();
+            
+            track.Track.Save ();
+                
+            if (LibrarySchema.WriteMetadata.Get ()) {
+                SaveToFile (track);
+            }
+
+            if (LibrarySchema.MoveOnInfoSave.Get ()) {
+                MoveSavedFile (track);
+            }
+
+            if (track.Track == ServiceManager.PlayerEngine.CurrentTrack) {
+                ServiceManager.PlayerEngine.TrackInfoUpdated ();
+            }
+        }
+        
+        private void SaveToFile (EditorTrack track)
+        {
+            Banshee.Kernel.Scheduler.Schedule (new SaveTrackMetadataJob (track.Track), Banshee.Kernel.JobPriority.Highest);
+        }
+
+        private void MoveSavedFile (EditorTrack track)
+        {
+            Banshee.Kernel.Scheduler.Schedule (new MoveOnInfoSaveJob (track.Track), Banshee.Kernel.JobPriority.Highest);
+        }*/
+
+#endregion
+
     }
 }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/UserJobTileHost.cs	Tue Sep 16 23:26:29 2008
@@ -32,6 +32,8 @@
 using Gtk;
 
 using Hyena.Widgets;
+using Hyena.Gui.Theatrics;
+
 using Banshee.Base;
 using Banshee.ServiceStack;
 

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Choreographer.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Choreographer.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Choreographer.cs	Tue Sep 16 23:26:29 2008
@@ -36,7 +36,10 @@
         Upstage,
         Downstage
     }
-    
+}
+
+namespace Hyena.Gui.Theatrics
+{
     public enum Easing
     {
         Linear,
@@ -45,38 +48,59 @@
         QuadraticInOut,
         ExponentialIn,
         ExponentialOut,
-        ExponentialInOut
+        ExponentialInOut,
+        Sine,
     }
-}
-
-namespace Hyena.Gui.Theatrics
-{
+    
     public static class Choreographer
     {
-        public static int Compose (double percent, int size, Easing easing)
+        public static int PixelCompose (double percent, int size, Easing easing)
+        {
+            return (int)Math.Round (Compose (percent, size, easing));
+        }
+        
+        public static double Compose (double percent, double scale, Easing easing)
         {
-            double total = (double)size;
+            return scale * Compose (percent, easing);
+        }
+        
+        public static double Compose (double percent, Easing easing)
+        {
+            if (percent < 0.0 || percent > 1.0) {
+                throw new ArgumentOutOfRangeException ("percent", "must be between 0 and 1 inclusive");
+            }
+        
             switch (easing) {
                 case Easing.QuadraticIn:
-                    return (int)Math.Round (percent * percent * total);
+                    return percent * percent;
+                
                 case Easing.QuadraticOut:
-                    return (int)Math.Round (-total * percent * (percent - 2.0));
+                    return -1.0 * percent * (percent - 2.0);
+                
                 case Easing.QuadraticInOut:
                     percent *= 2.0;
-                    return (percent < 1.0)
-                        ? (int)Math.Round (percent * percent * (total / 2.0))
-                        : (int)Math.Round ((-total / 2.0) * (--percent * (percent - 2.0) - 1.0));
+                    return percent < 1.0
+                        ? percent * percent * 0.5
+                        : -0.5 * (--percent * (percent - 2.0) - 1.0);
+                
                 case Easing.ExponentialIn:
-                    return (int)Math.Round (total * Math.Pow (2.0, 10.0 * (percent - 1.0)));
+                    return Math.Pow (2.0, 10.0 * (percent - 1.0));
+                
                 case Easing.ExponentialOut:
-                    return (int)Math.Round (total * (-Math.Pow (2.0, -10.0 * percent) + 1.0));
+                    return -Math.Pow (2.0, -10.0 * percent) + 1.0;
+                
                 case Easing.ExponentialInOut:
                     percent *= 2.0;
-                    return (percent < 1.0)
-                        ? (int)Math.Round (total/2.0 * Math.Pow (2.0, 10.0 * (percent - 1.0)))
-                        : (int)Math.Round (total/2.0 * (-Math.Pow (2.0, -10.0 * --percent) + 2.0));
+                    return percent < 1.0
+                        ? 0.5 * Math.Pow (2.0, 10.0 * (percent - 1.0))
+                        : 0.5 * (-Math.Pow (2.0, -10.0 * --percent) + 2.0);
+                
+                case Easing.Sine:
+                    return Math.Sin (percent * Math.PI);
+                
+                case Easing.Linear:
                 default:
-                    return (int)Math.Round (percent * total);
+                    return percent;
             }
         }
     }

Added: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Pulsator.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Pulsator.cs	Tue Sep 16 23:26:29 2008
@@ -0,0 +1,116 @@
+//
+// Pulsator.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.Theatrics
+{
+    public class Pulsator<T> where T : class
+    {
+        private Stage<T> stage;
+        public Stage<T> Stage {
+            get { return stage; }
+            set { 
+                if (stage == value) {
+                    return;
+                }
+                
+                if (stage != null) {
+                    stage.ActorStep -= OnActorStep;
+                }
+                
+                stage = value;
+                
+                if (stage != null) {
+                    stage.ActorStep += OnActorStep;
+                }
+            }
+        }
+        
+        private T target;
+        public T Target {
+            get { return target; }
+            set { target = value; }
+        }
+        
+        public double Percent {
+            get { return IsPulsing ? stage[Target].Percent : 0; }
+        }
+        
+        public bool IsPulsing {
+            get { return stage != null && stage.Contains (Target); }
+        }
+        
+        #pragma warning disable 0067
+        // FIXME: This is to mute gmcs: https://bugzilla.novell.com/show_bug.cgi?id=360455
+        public event EventHandler Pulse;
+        #pragma warning restore 0067
+        
+        public Pulsator ()
+        {
+        }
+        
+        public Pulsator (Stage<T> stage) 
+        {
+            Stage = stage;
+        }
+        
+        public void StartPulsing ()
+        {
+            if (!Stage.Contains (Target)) {
+                Stage.Add (Target);
+            }
+            
+            Stage[Target].CanExpire = false;
+        }
+        
+        public void StopPulsing ()
+        {
+            if (Stage.Contains (Target)) {
+                Stage[Target].CanExpire = true;
+            }
+        }
+        
+        private bool OnActorStep (Actor<T> actor)
+        {
+            if (actor.Target == target) {
+                OnPulse ();
+            }
+            
+            return true;
+        }
+        
+        protected virtual void OnPulse ()
+        {
+            EventHandler handler = Pulse;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
+    }
+}

Added: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Tests/ChoreographerTests.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theatrics/Tests/ChoreographerTests.cs	Tue Sep 16 23:26:29 2008
@@ -0,0 +1,116 @@
+//
+// ChoreographerTests.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.
+//
+
+#if ENABLE_TESTS
+
+using System;
+using NUnit.Framework;
+
+using Hyena;
+using Hyena.Gui.Theatrics;
+    
+namespace Hyena.Gui.Theatrics.Tests
+{
+    [TestFixture]
+    public class ChoreographerTests
+    {
+        private void _TestComposeRange (int [] values, Easing easing)
+        {
+            for (double i = 0, n = 100, p = 0, j = 0; i <= n; i += 5, p = i / n, j++) {
+                int value = Choreographer.PixelCompose (p, (int)n, easing);
+                Assert.AreEqual (values[(int)j], value);
+            }
+        }
+    
+        [Test]
+        public void QuadraticInCompose ()
+        {
+            _TestComposeRange (new int [] { 
+                0, 0, 1, 2, 4, 6, 9, 12, 16, 20, 25, 30, 36, 42, 49, 56, 64, 72, 81, 90, 100
+            }, Easing.QuadraticIn);
+        }
+           
+        [Test]
+        public void QuadraticOutCompose ()
+        {
+            _TestComposeRange (new int [] { 
+                0, 10, 19, 28, 36, 44, 51, 58, 64, 70, 75, 80, 84, 88, 91, 94, 96, 98, 99, 100, 100
+            }, Easing.QuadraticOut);
+        }
+           
+        [Test]
+        public void QuadraticInOutCompose ()
+        {
+            _TestComposeRange (new int [] { 
+                0, 1, 2, 4, 8, 12, 18, 24, 32, 40, 50, 60, 68, 76, 82, 88, 92, 96, 98, 100, 100
+            }, Easing.QuadraticInOut);
+        }
+           
+        [Test]
+        public void ExponentialInCompose ()
+        {
+            _TestComposeRange (new int [] { 
+                0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 6, 9, 12, 18, 25, 35, 50, 71, 100
+            }, Easing.ExponentialIn);
+        }
+           
+        [Test]
+        public void ExponentialOutCompose ()
+        {
+            _TestComposeRange (new int [] { 
+                0, 29, 50, 65, 75, 82, 88, 91, 94, 96, 97, 98, 98, 99, 99, 99, 100, 100, 100, 100, 100
+            }, Easing.ExponentialOut);
+        }
+           
+        [Test]
+        public void ExponentialInOutCompose ()
+        {
+            _TestComposeRange (new int [] { 
+                0, 0, 0, 0, 1, 2, 3, 6, 13, 25, 50, 75, 88, 94, 97, 98, 99, 100, 100, 100, 100
+            }, Easing.ExponentialInOut);
+        }
+           
+        [Test]
+        public void LinearCompose ()
+        {
+            _TestComposeRange (new int [] { 
+                0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100
+            }, Easing.Linear);
+        }
+          
+        [Test]
+        public void SineCompose ()
+        {
+            _TestComposeRange (new int [] { 
+                0, 16, 31, 45, 59, 71, 81, 89, 95, 99, 100, 99, 95, 89, 81, 71, 59, 45, 31, 16, 0
+            }, Easing.Sine);
+        }
+    }
+}
+
+#endif

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.csproj
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.csproj	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.csproj	Tue Sep 16 23:26:29 2008
@@ -116,6 +116,9 @@
     <Compile Include="Hyena.Gui\Contrast.cs" />
     <Compile Include="Hyena.Widgets\ImageButton.cs" />
     <Compile Include="Hyena.Data.Gui\ITextCell.cs" />
+    <Compile Include="Hyena.Gui.Theatrics\Tests\ChoreographerTests.cs" />
+    <Compile Include="Hyena.Widgets\PulsingButton.cs" />
+    <Compile Include="Hyena.Gui.Theatrics\Pulsator.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>

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	Tue Sep 16 23:26:29 2008
@@ -114,8 +114,8 @@
                 border_state = AnimationState.Idle;
             } else {
                 double percent = border_state == AnimationState.Coming ? Percent : 1.0 - Percent;
-                start_border = Choreographer.Compose (percent, start_padding, border_easing);
-                end_border = Choreographer.Compose (percent, end_padding, border_easing);
+                start_border = Choreographer.PixelCompose (percent, start_padding, border_easing);
+                end_border = Choreographer.PixelCompose (percent, end_padding, border_easing);
             }
             QueueResizeNoRedraw ();
         }

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs	Tue Sep 16 23:26:29 2008
@@ -139,11 +139,11 @@
             }
             
             if (horizontal) {
-                Width = Choreographer.Compose (percent, widget_alloc.Width + StartPadding + EndPadding, Easing);
+                Width = Choreographer.PixelCompose (percent, widget_alloc.Width + StartPadding + EndPadding, Easing);
                 Height = widget_alloc.Height;
             } else {
                 Width = widget_alloc.Width;
-                Height = Choreographer.Compose (percent, widget_alloc.Height + StartPadding + EndPadding, Easing);
+                Height = Choreographer.PixelCompose (percent, widget_alloc.Height + StartPadding + EndPadding, Easing);
             }
             
             requisition.Width = Width;

Added: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/PulsingButton.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Widgets/PulsingButton.cs	Tue Sep 16 23:26:29 2008
@@ -0,0 +1,127 @@
+//
+// PulsingButton.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 PulsingButton : Button
+    {
+        private static Stage<PulsingButton> default_stage;
+        public static Stage<PulsingButton> DefaultStage {
+            get { 
+                if (default_stage == null) {
+                    default_stage = new Stage<PulsingButton> ();
+                    default_stage.DefaultActorDuration = 1250;
+                }
+                
+                return default_stage;
+            }
+        }
+        
+        private Pulsator<PulsingButton> pulsator = new Pulsator<PulsingButton> ();
+        
+        public Stage<PulsingButton> Stage {
+            get { return pulsator.Stage; }
+            set { pulsator.Stage = value; }
+        }
+        
+        public PulsingButton () : base ()
+        {
+            Setup ();
+        }
+        
+        public PulsingButton (string stock_id) : base (stock_id)
+        {
+            Setup ();
+        }
+        
+        public PulsingButton (Widget widget) : base (widget)
+        {
+            Setup ();
+        }
+        
+        protected PulsingButton (IntPtr raw) : base (raw)
+        {
+            Setup ();
+        }
+        
+        private void Setup ()
+        {
+            Stage = DefaultStage;
+            pulsator.Target = this;
+            pulsator.Pulse += delegate { QueueDraw (); };
+        }
+        
+        protected override bool OnExposeEvent (Gdk.EventExpose evnt)
+        {
+            if (!pulsator.IsPulsing) {
+                return base.OnExposeEvent (evnt);
+            }
+            
+            Cairo.Context cr = Gdk.CairoHelper.Create (GdkWindow);
+            
+            double x = Allocation.X + Allocation.Width / 2;
+            double y = Allocation.Y + Allocation.Height / 2;
+            double r = Math.Min (Allocation.Width, Allocation.Height) / 2;
+            double alpha = Choreographer.Compose (pulsator.Percent, Easing.Sine);
+            
+            Cairo.Color color = CairoExtensions.GdkColorToCairoColor (Style.Background (StateType.Selected));
+            Cairo.RadialGradient fill = new Cairo.RadialGradient (x, y, 0, x, y, r);
+            color.A = alpha;
+            fill.AddColorStop (0, color);
+            fill.AddColorStop (0.5, color);
+            color.A = 0;
+            fill.AddColorStop (1, color);
+            
+            cr.Arc (x, y, r, 0, 2 * Math.PI);
+            cr.Pattern = fill;
+            cr.Fill ();
+            fill.Destroy ();
+            
+            ((IDisposable)cr).Dispose ();
+            return base.OnExposeEvent (evnt);
+        }
+        
+        public void StartPulsing ()
+        {
+            if (IsMapped && Sensitive) {
+                pulsator.StartPulsing ();
+            }
+        }
+        
+        public void StopPulsing ()
+        {
+            pulsator.StopPulsing ();
+        }
+    }
+}

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	Tue Sep 16 23:26:29 2008
@@ -31,8 +31,10 @@
 	Hyena.Gui.Dialogs/VersionInformationDialog.cs \
 	Hyena.Gui.Theatrics/Actor.cs \
 	Hyena.Gui.Theatrics/Choreographer.cs \
+	Hyena.Gui.Theatrics/Pulsator.cs \
 	Hyena.Gui.Theatrics/SingleActorStage.cs \
 	Hyena.Gui.Theatrics/Stage.cs \
+	Hyena.Gui.Theatrics/Tests/ChoreographerTests.cs \
 	Hyena.Gui.Theming/GtkColors.cs \
 	Hyena.Gui.Theming/GtkTheme.cs \
 	Hyena.Gui.Theming/Theme.cs \
@@ -74,6 +76,7 @@
 	Hyena.Widgets/ImageButton.cs \
 	Hyena.Widgets/MenuButton.cs \
 	Hyena.Widgets/MessageBar.cs \
+	Hyena.Widgets/PulsingButton.cs \
 	Hyena.Widgets/RatingEntry.cs \
 	Hyena.Widgets/RatingMenuItem.cs \
 	Hyena.Widgets/RoundedFrame.cs \

Modified: trunk/banshee/tests/Makefile.am
==============================================================================
--- trunk/banshee/tests/Makefile.am	(original)
+++ trunk/banshee/tests/Makefile.am	Tue Sep 16 23:26:29 2008
@@ -4,12 +4,14 @@
 
 TEST_ASSEMBLIES = \
 	Hyena.dll \
+	Hyena.Gui.dll \
 	Migo.dll \
 	Banshee.Core.dll \
 	Banshee.Services.dll \
 	Banshee.Dap.Mtp.dll
 
-RUNNER = for asm in $${TEST_ASSEMBLIES}; do echo -e "\033[1mRunning tests on $${asm}...\033[0m"; TZ=America/Chicago LC_ALL=it_IT LANG=it_IT nunit-console2 /nologo $$asm; done
+ENV_OPTIONS = TZ=America/Chicago LC_ALL=it_IT LANG=it_IT
+RUNNER = for asm in $${TEST_ASSEMBLIES}; do echo -e "\033[1mRunning tests on $${asm}...\033[0m"; $(ENV_OPTIONS) nunit-console2 /nologo $$asm; done
 
 test:
 	@pushd $(DIR_BIN) &>/dev/null; \



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