banshee r4404 - in branches/banshee/abock/src: Core/Banshee.Core/Banshee.Collection Core/Banshee.Core/Resources Core/Banshee.Services/Banshee.Collection.Database Core/Banshee.ThickClient Core/Banshee.ThickClient/Banshee.Gui Core/Banshee.ThickClient/Banshee.Gui.TrackEditor Libraries/Hyena.Gui/Hyena.Gui Libraries/Hyena.Gui/Hyena.Widgets Libraries/Hyena/Hyena



Author: abock
Date: Wed Aug 20 05:59:42 2008
New Revision: 4404
URL: http://svn.gnome.org/viewvc/banshee?rev=4404&view=rev

Log:
Initial branch checkin of work in progress of the new track editor

Added:
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/BasicTrackDetailsPage.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/EditorTrackInfo.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/EditorUtilities.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/ExtraTrackDetailsPage.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/FieldPage.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/IEditorField.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/ITrackEditorPage.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/LyricsPage.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/RangeEntry.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/RatingEntry.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SpinButtonEntry.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TextEntry.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TextViewEntry.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TitleEntry.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
Modified:
   branches/banshee/abock/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
   branches/banshee/abock/src/Core/Banshee.Core/Resources/translators.xml
   branches/banshee/abock/src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml
   branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
   branches/banshee/abock/src/Core/Banshee.ThickClient/Makefile.am
   branches/banshee/abock/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs
   branches/banshee/abock/src/Libraries/Hyena.Gui/Hyena.Widgets/RatingEntry.cs
   branches/banshee/abock/src/Libraries/Hyena/Hyena/StringUtil.cs

Modified: branches/banshee/abock/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs
==============================================================================
--- branches/banshee/abock/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs	(original)
+++ branches/banshee/abock/src/Core/Banshee.Core/Banshee.Collection/TrackInfo.cs	Wed Aug 20 05:59:42 2008
@@ -28,6 +28,7 @@
 
 using System;
 using System.IO;
+using System.Reflection;
 using System.Collections.Generic;
 using Mono.Unix;
 
@@ -40,6 +41,15 @@
 {
     public class TrackInfo : CacheableItem, ITrackInfo
     {
+        public class ExportableAttribute : Attribute
+        {
+            private string export_name;
+            public string ExportName {
+                get { return export_name; }
+                set { export_name = value; }
+            }
+        }
+    
         public delegate bool IsPlayingHandler (TrackInfo track);
         public static IsPlayingHandler IsPlayingMethod;
             
@@ -130,64 +140,77 @@
             get { return (IsPlayingMethod != null) ? IsPlayingMethod (this) : false; }
         }
 
+        [Exportable (ExportName = "URI")]
         public virtual SafeUri Uri {
             get { return uri; }
             set { uri = value; }
         }
 
+        [Exportable]
         public SafeUri MoreInfoUri {
             get { return more_info_uri; }
             set { more_info_uri = value; }
         }
 
+        [Exportable]
         public virtual string MimeType {
             get { return mimetype; }
             set { mimetype = value; }
         }
 
+        [Exportable]
         public virtual long FileSize {
             get { return filesize; }
             set { filesize = value; }
         }
 
+        [Exportable (ExportName = "artist")]
         public virtual string ArtistName {
             get { return artist_name; }
             set { artist_name = value; }
         }
 
+        [Exportable (ExportName = "album")]
         public virtual string AlbumTitle {
             get { return album_title; }
             set { album_title = value; }
         }
 
+        [Exportable]
         public virtual string AlbumArtist {
             get { return album_artist ?? (IsCompilation ? Catalog.GetString ("Various Artists") : ArtistName); }
             set { album_artist = value; }
         }
         
+        [Exportable]
         public virtual bool IsCompilation {
             get { return is_compilation; }
             set { is_compilation = value; }
         }
 
+        [Exportable (ExportName = "name")]
         public virtual string TrackTitle {
             get { return track_title; }
             set { track_title = value; }
         }
         
+        [Exportable]
         public virtual string MusicBrainzId {
             get { return musicbrainz_id; }
             set { musicbrainz_id = value; }
         }
         
+        [Exportable]
         public virtual string ArtistMusicBrainzId {
             get { return null; }
         }
         
+        [Exportable]
         public virtual string AlbumMusicBrainzId {
             get { return null; }
         }
         
+        [Exportable]
         public virtual DateTime ReleaseDate {
             get { return release_date; }
             set { release_date = value; }
@@ -229,111 +252,131 @@
             } 
         }     
         
-        
         public virtual string ArtworkId { 
             get { return CoverArtSpec.CreateArtistAlbumId (AlbumArtist, AlbumTitle); }
         }
 
+        [Exportable]
         public virtual string Genre {
             get { return genre; }
             set { genre = value; }
         }
 
+        [Exportable]
         public virtual int TrackNumber {
             get { return track_number; }
             set { track_number = value; }
         }
 
+        [Exportable]
         public virtual int TrackCount {
             get { return TrackNumber > track_count ? TrackNumber : track_count; }
             set { track_count = value; }
         }
 
+        [Exportable]
         public virtual int DiscNumber {
             get { return disc_number; }
             set { disc_number = value; }
         }
-
+        
+        [Exportable]
         public virtual int DiscCount {
             get { return DiscNumber > disc_count ? DiscNumber : disc_count; }
             set { disc_count = value; }
         }
 
+        [Exportable]
         public virtual int Year {
             get { return year; }
             set { year = value; }
         }
 
+        [Exportable]
         public virtual string Composer {
             get { return composer; }
             set { composer = value; }
         }
 
+        [Exportable]
         public virtual string Conductor {
             get { return conductor; }
             set { conductor = value; }
         }
-
+        
+        [Exportable]
         public virtual string Grouping {
             get { return grouping; }
             set { grouping = value; }
         }
-
+        
+        [Exportable]
         public virtual string Copyright {
             get { return copyright; }
             set { copyright = value; }
         }
 
+        [Exportable]        
         public virtual string LicenseUri {
             get { return license_uri; }
             set { license_uri = value; }
         }
 
+        [Exportable]
         public virtual string Comment {
             get { return comment; }
             set { comment = value; }
         }
 
+        [Exportable]
         public virtual int Rating {
             get { return rating; }
             set { rating = value; }
         }
         
+        [Exportable]
         public virtual int Bpm {
             get { return bpm; }
             set { bpm = value; }
         }
 
+        [Exportable]
         public virtual int BitRate {
             get { return bit_rate; }
             set { bit_rate = value; }
         }
 
+        [Exportable]
         public virtual int PlayCount {
             get { return play_count; }
             set { play_count = value; }
         }
 
+        [Exportable]
         public virtual int SkipCount {
             get { return skip_count; }
             set { skip_count = value; }
         }
 
+        [Exportable (ExportName = "length")]
         public virtual TimeSpan Duration {
             get { return duration; }
             set { duration = value; }
         }
         
+        [Exportable]
         public virtual DateTime DateAdded {
             get { return date_added; }
             set { date_added = value; }
         }
 
+        [Exportable]
         public virtual DateTime LastPlayed {
             get { return last_played; }
             set { last_played = value; }
         }
 
+        [Exportable]
         public virtual DateTime LastSkipped {
             get { return last_skipped; }
             set { last_skipped = value; }
@@ -363,6 +406,8 @@
         }
 
         private TrackMediaAttributes media_attributes = TrackMediaAttributes.Default;
+        
+        [Exportable]
         public virtual TrackMediaAttributes MediaAttributes {
             get { return media_attributes; }
             set { media_attributes = value; }
@@ -384,25 +429,62 @@
                 return Catalog.GetString ("Item");
             }
         }
+        
+        public static void ExportableMerge (TrackInfo source, TrackInfo dest)
+        {
+            foreach (PropertyInfo property in typeof (TrackInfo).GetProperties (BindingFlags.Public | BindingFlags.Instance)) {
+                try {
+                    object [] exportable_attrs = property.GetCustomAttributes (typeof (TrackInfo.ExportableAttribute), true);
+                    if (exportable_attrs != null && exportable_attrs.Length > 0 && property.CanWrite) {
+                        property.SetValue (dest, property.GetValue (source, null), null);
+                    }
+                } catch (Exception e) {
+                    Log.Exception (e);
+                }
+            }
+        }
 
         // Generates a{sv} of self according to http://wiki.xmms2.xmms.se/index.php/Media_Player_Interfaces#.22Metadata.22
         public IDictionary<string, object> GenerateExportable ()
         {
             Dictionary<string, object> dict = new Dictionary<string, object> ();
             
-            // Properties specified by the XMMS2 player spec
-            dict.Add ("URI", Uri == null ? String.Empty : Uri.AbsoluteUri);
-            dict.Add ("length", Duration.TotalSeconds);
-            dict.Add ("name", TrackTitle);
-            dict.Add ("artist", ArtistName);
-            dict.Add ("album", AlbumTitle);
-            
-            // Our own
-            dict.Add ("track-number", TrackNumber);
-            dict.Add ("track-count", TrackCount);
-            dict.Add ("disc", DiscNumber);
-            dict.Add ("year", year);
-            dict.Add ("rating", rating);
+            foreach (PropertyInfo property in GetType ().GetProperties (BindingFlags.Public | BindingFlags.Instance)) {
+                object [] exportable_attrs = property.GetCustomAttributes (typeof (TrackInfo.ExportableAttribute), true);
+                if (exportable_attrs == null || exportable_attrs.Length == 0) {
+                    continue;
+                }
+                
+                string export_name = ((ExportableAttribute)exportable_attrs[0]).ExportName
+                    ?? StringUtil.CamelCaseToUnderCase (property.Name, '-');
+                
+                object value = property.GetValue (this, null);
+                if (String.IsNullOrEmpty (export_name) || value == null) {
+                    continue;
+                }
+                
+                if (value is TimeSpan) {
+                    value = ((TimeSpan)value).TotalSeconds;
+                } else if (value is DateTime) {
+                    DateTime date = (DateTime)value;
+                    value = date == DateTime.MinValue ? 0l : DateTimeUtil.ToTimeT (date);
+                } else if (value is SafeUri) {
+                    value = ((SafeUri)value).AbsoluteUri;
+                } else if (value is TrackMediaAttributes) {
+                    value = value.ToString ();
+                } else if (!(
+                    value is ushort || value is short || 
+                    value is uint || value is int ||
+                    value is ulong || value is long ||
+                    value is float || value is double ||
+                    value is bool || value is string)) {
+                    Log.WarningFormat ("Invalid property in {0} marked as [Exportable]: ({1} is a {2})", 
+                        property.DeclaringType, property.Name, value.GetType ());
+                    continue;
+                }
+                
+                dict.Add (export_name, value);
+            }
             
             return dict;
         }

Modified: branches/banshee/abock/src/Core/Banshee.Core/Resources/translators.xml
==============================================================================
--- branches/banshee/abock/src/Core/Banshee.Core/Resources/translators.xml	(original)
+++ branches/banshee/abock/src/Core/Banshee.Core/Resources/translators.xml	Wed Aug 20 05:59:42 2008
@@ -100,7 +100,7 @@
   <language code="pa" name="Panjabi">
     <person>A S Alam</person>
   </language>
-  <language code="pl" name="Tomasz Dominikowski">
+  <language code="pl" name="Aviary.pl">
     <person>Tomasz Dominikowski</person>
   </language>
   <language code="pt" name="Portuguese">

Modified: branches/banshee/abock/src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs
==============================================================================
--- branches/banshee/abock/src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs	(original)
+++ branches/banshee/abock/src/Core/Banshee.Services/Banshee.Collection.Database/CachedList.cs	Wed Aug 20 05:59:42 2008
@@ -98,13 +98,17 @@
         {
             ServiceManager.DbConnection.Execute ("DELETE FROM CoreCache WHERE ModelId = ?", CacheId);
         }
+        
+        public T this[int index] {
+            get { return cache.GetValue (index); }
+        }
 
         public long CacheId {
             get { return cache.CacheId; }
         }
 
-        public long Count {
-            get { return cache.Count; }
+        public int Count {
+            get { return (int)cache.Count; }
         }
 
         public IEnumerator<T> GetEnumerator ()

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/BasicTrackDetailsPage.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/BasicTrackDetailsPage.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,167 @@
+//
+// BasicTrackDetailsPage.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 Mono.Unix;
+using Gtk;
+
+using Banshee.Collection;
+
+namespace Banshee.Gui.TrackEditor
+{
+    public class BasicTrackDetailsPage : FieldPage, ITrackEditorPage
+    {
+        private CheckButton enable_compilation = new CheckButton ();
+        
+        public int Order {
+            get { return 10; }
+        }
+                                    
+        public string Title {
+            get { return Catalog.GetString ("Track Details"); }
+        }
+        
+        public override void LoadTrack (EditorTrackInfo track)
+        {
+            base.LoadTrack (track);
+            enable_compilation.Active = track.IsCompilation;
+            OnEnableCompilationToggled (enable_compilation, EventArgs.Empty);
+        }
+
+        protected override void AddFields ()
+        {
+            HBox box = new HBox ();
+            VBox left = EditorUtilities.CreateVBox ();
+            VBox right = EditorUtilities.CreateVBox ();
+            
+            box.PackStart (left, true, true, 0);
+            box.PackStart (new VSeparator (), false, false, 12);
+            box.PackStart (right, false, false, 0);
+            box.ShowAll ();
+            
+            PackStart (box, false, false, 0);
+            
+            // Left
+            
+            AddField (left, new TitleEntry (), 
+                delegate { return Catalog.GetString ("Track Title:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TitleEntry)widget).Text = track.TrackTitle; },
+                delegate (EditorTrackInfo track, Widget widget) { track.TrackTitle = ((TitleEntry)widget).Text; }
+            );
+            
+            AddField (left, new TextEntry (), 
+                delegate { return Catalog.GetString ("Track Artist:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.ArtistName; },
+                delegate (EditorTrackInfo track, Widget widget) { track.ArtistName = ((TextEntry)widget).Text; }
+            );
+            
+            enable_compilation.Toggled += OnEnableCompilationToggled;
+            AddField (left, enable_compilation, new TextEntry (),
+                delegate (EditorTrackInfo track, Widget widget) { 
+                    ((CheckButton)widget).Label = Catalog.GetString ("Album Artist (part of a compilation):"); 
+                    return null; 
+                },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.AlbumArtist; },
+                delegate (EditorTrackInfo track, Widget widget) { track.AlbumArtist = ((TextEntry)widget).Text; }
+            );
+            
+            AddField (left, new TextEntry (), 
+                delegate { return Catalog.GetString ("Album Title:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.AlbumTitle; },
+                delegate (EditorTrackInfo track, Widget widget) { track.AlbumTitle = ((TextEntry)widget).Text; }
+            );
+            
+            AddField (left, new TextEntry (), 
+                delegate { return Catalog.GetString ("Genre:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.Genre; },
+                delegate (EditorTrackInfo track, Widget widget) { track.Genre = ((TextEntry)widget).Text; }
+            );
+            
+            // Right
+            
+            AddField (right, new RangeEntry (Catalog.GetString ("of")), 
+                delegate { return Catalog.GetString ("Track Number:"); },
+                delegate (EditorTrackInfo track, Widget widget) {
+                    RangeEntry entry = (RangeEntry)widget;
+                    entry.From.Value = track.TrackNumber;
+                    entry.To.Value = track.TrackCount;
+                },
+                delegate (EditorTrackInfo track, Widget widget) {
+                    RangeEntry entry = (RangeEntry)widget;
+                    track.TrackNumber = (int)entry.From.Value;
+                    track.TrackCount = (int)entry.To.Value;
+                }
+            );
+            
+            AddField (right, new RangeEntry (Catalog.GetString ("of")), 
+                delegate { return Catalog.GetString ("Disc Number:"); },
+                delegate (EditorTrackInfo track, Widget widget) {
+                    RangeEntry entry = (RangeEntry)widget;
+                    entry.From.Value = track.DiscNumber;
+                    entry.To.Value = track.DiscCount;
+                },
+                delegate (EditorTrackInfo track, Widget widget) {
+                    RangeEntry entry = (RangeEntry)widget;
+                    track.DiscNumber = (int)entry.From.Value;
+                    track.DiscCount = (int)entry.To.Value;
+                }
+            );
+            
+            Label year_label = EditorUtilities.CreateLabel (null);
+            enable_compilation.SizeAllocated += delegate { year_label.HeightRequest = enable_compilation.Allocation.Height; };
+            AddField (right, year_label, new SpinButtonEntry (1000, 3000, 1),
+                delegate { return Catalog.GetString ("Year:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((SpinButtonEntry)widget).Value = track.Year; },
+                delegate (EditorTrackInfo track, Widget widget) { track.Year = (int)((SpinButtonEntry)widget).Value; },
+                false
+            );
+            
+            AddField (right, new RatingEntry (), 
+                delegate { return Catalog.GetString ("Rating:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((RatingEntry)widget).Value = track.Rating; },
+                delegate (EditorTrackInfo track, Widget widget) { track.Rating = ((RatingEntry)widget).Value; },
+                false
+            );
+        }
+        
+        private void OnEnableCompilationToggled (object o, EventArgs args)
+        {
+            CheckButton check = (CheckButton)o;
+            
+            if (CurrentTrack != null) {
+                CurrentTrack.IsCompilation = check.Active;
+            }
+            
+            foreach (Widget child in ((Container)check.Parent).Children) {
+                if (child != check) {
+                    child.Sensitive = check.Active;
+                }
+            }
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/EditorTrackInfo.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/EditorTrackInfo.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,48 @@
+//
+// EditorTrackInfo.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 Banshee.Collection;
+
+namespace Banshee.Gui.TrackEditor
+{
+    public class EditorTrackInfo : TrackInfo
+    {
+        public EditorTrackInfo (TrackInfo sourceTrack)
+        {
+            source_track = sourceTrack;
+            TrackInfo.ExportableMerge (source_track, this);
+        }
+        
+        private TrackInfo source_track;
+        public TrackInfo SourceTrack {
+            get { return source_track; }
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/EditorUtilities.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/EditorUtilities.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,76 @@
+//
+// EditorUtilities.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 Banshee.Gui.TrackEditor
+{
+    public static class EditorUtilities
+    {
+        public const int RowSpacing = 5;
+                
+        public static Label CreateLabel (string text)
+        {
+            Label label = new Label ();
+            label.Text = text;
+            label.Xalign = 0.0f;
+            return label;
+        }
+    
+        public static VBox CreateVBox ()
+        {
+            VBox box = new VBox ();
+            box.Spacing = RowSpacing;
+            return box;
+        }
+
+        public static TextEntry CreateEntry (int charWidth)
+        {
+            TextEntry entry = new TextEntry ();
+            entry.WidthChars = charWidth;
+            return entry;
+        }
+        
+        public static Button CreateSyncButton ()
+        {
+            return CreateSmallStockButton (Stock.Copy);
+        }
+        
+        public static Button CreateSmallStockButton (string stock)
+        {
+            Button button = new Button ();
+            Image image = new Image (stock, IconSize.Menu);
+            button.Add (image);
+            button.Relief = ReliefStyle.None;
+            image.Show ();
+            return button;
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/ExtraTrackDetailsPage.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/ExtraTrackDetailsPage.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,92 @@
+//
+// ExtraTrackDetailsPage.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 Mono.Unix;
+using Gtk;
+
+using Banshee.Collection;
+
+namespace Banshee.Gui.TrackEditor
+{
+    public class ExtraTrackDetailsPage : FieldPage, ITrackEditorPage
+    {        
+        public int Order {
+            get { return 20; }
+        }
+                                    
+        public string Title {
+            get { return Catalog.GetString ("More Details"); }
+        }
+        
+        protected override void AddFields ()
+        {
+            AddField (this, new TextEntry (), 
+                delegate { return Catalog.GetString ("Composer:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.Composer; },
+                delegate (EditorTrackInfo track, Widget widget) {  track.Composer = ((TextEntry)widget).Text; }
+            );
+            
+            AddField (this, new TextEntry (), 
+                delegate { return Catalog.GetString ("Conductor:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.Conductor; },
+                delegate (EditorTrackInfo track, Widget widget) { track.Conductor = ((TextEntry)widget).Text; }
+            );
+            
+            HBox box = new HBox ();
+            box.Spacing = 12;
+            box.Show ();
+            PackStart (box, false, false, 0);
+            
+            AddField (box, new TextEntry (), 
+                delegate { return Catalog.GetString ("Grouping:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.Grouping; },
+                delegate (EditorTrackInfo track, Widget widget) { track.Grouping = ((TextEntry)widget).Text; }
+            );
+            
+            AddField (box, new SpinButtonEntry (0, 500, 1), 
+                delegate { return Catalog.GetString ("Beats Per Minute:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((SpinButtonEntry)widget).Value = track.Bpm; },
+                delegate (EditorTrackInfo track, Widget widget) { track.Bpm = (int)((SpinButtonEntry)widget).Value; },
+                false
+            );
+            
+            AddField (this, new TextEntry (), 
+                delegate { return Catalog.GetString ("Copyright:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextEntry)widget).Text = track.Copyright; },
+                delegate (EditorTrackInfo track, Widget widget) { track.Copyright = ((TextEntry)widget).Text; }
+            );
+            
+            AddField (this, new TextViewEntry (), 
+                delegate { return Catalog.GetString ("Comment:"); },
+                delegate (EditorTrackInfo track, Widget widget) { ((TextViewEntry)widget).Text = track.Comment; },
+                delegate (EditorTrackInfo track, Widget widget) { track.Comment = ((TextEntry)widget).Text; }
+            );
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/FieldPage.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/FieldPage.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,183 @@
+//
+// FieldPage.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;
+
+using Gtk;
+
+using Banshee.Collection;
+
+namespace Banshee.Gui.TrackEditor
+{
+    public class FieldPage : VBox
+    {
+        public delegate string FieldLabelClosure (EditorTrackInfo track, Widget widget);
+        public delegate void FieldValueClosure (EditorTrackInfo track, Widget widget);
+        
+        private TrackEditorDialog dialog;
+        protected TrackEditorDialog Dialog {
+            get { return dialog; }
+        }
+        
+        private EditorTrackInfo current_track;
+        protected EditorTrackInfo CurrentTrack {
+            get { return current_track; }
+        }
+        
+        private struct FieldSlot
+        {
+            public Widget Label;
+            public Widget Field;
+            public Button SyncButton;
+            public FieldLabelClosure LabelClosure;
+            public FieldValueClosure ReadClosure;
+            public FieldValueClosure WriteClosure;
+        }
+        
+        private List<FieldSlot> field_slots = new List<FieldSlot> ();
+        
+        public FieldPage ()
+        {
+            Spacing = EditorUtilities.RowSpacing;
+        }
+        
+        public void Initialize (TrackEditorDialog dialog)
+        {
+            this.dialog = dialog;
+            AddFields ();
+        }
+        
+        protected virtual void AddFields ()
+        {
+        }
+        
+        public virtual bool MultipleTracks {
+            get { return dialog.TrackCount > 1; }
+        }
+        
+        public virtual Widget Widget {
+            get { return this; }
+        }
+    
+        public void AddField (Box parent, Widget field, FieldLabelClosure labelClosure, 
+            FieldValueClosure readClosure, FieldValueClosure writeClosure)
+        {
+            AddField (parent, EditorUtilities.CreateLabel (String.Empty), field, 
+                labelClosure, readClosure, writeClosure, true);
+        }
+        
+        public void AddField (Box parent, Widget field, FieldLabelClosure labelClosure, 
+            FieldValueClosure readClosure, FieldValueClosure writeClosure, bool expand)
+        {
+            AddField (parent, EditorUtilities.CreateLabel (String.Empty), field, 
+                labelClosure, readClosure, writeClosure, expand);
+        }
+        
+        public void AddField (Box parent, Widget label, Widget field, FieldLabelClosure labelClosure, 
+            FieldValueClosure readClosure, FieldValueClosure writeClosure)
+        {
+            AddField (parent, label, field, labelClosure, readClosure, writeClosure, true);
+        }
+        
+        public void AddField (Box parent, Widget label, Widget field, FieldLabelClosure labelClosure, 
+            FieldValueClosure readClosure, FieldValueClosure writeClosure, bool expand)
+        {
+            FieldSlot slot = new FieldSlot ();
+            
+            slot.Label = label;
+            slot.Field = field;
+            slot.LabelClosure = labelClosure;
+            slot.ReadClosure = readClosure;
+            slot.WriteClosure = writeClosure;
+            if (MultipleTracks) {
+                slot.SyncButton = EditorUtilities.CreateSyncButton ();
+            }
+            
+            field_slots.Add (slot);
+            
+            Table table = new Table (1, 1, false);
+            table.ColumnSpacing = 1;
+            
+            table.Attach (field, 0, 1, 1, 2, 
+                AttachOptions.Expand | AttachOptions.Fill, 
+                AttachOptions.Fill, 0, 0);
+                
+            IEditorField editor_field = field as IEditorField;
+            if (editor_field != null) {
+                editor_field.Changed += delegate {
+                    if (CurrentTrack != null) {
+                        slot.WriteClosure (CurrentTrack, slot.Field);
+                    }
+                };
+            }
+            
+            if (MultipleTracks) {
+                table.Attach (slot.SyncButton, 1, 2, 1, 2, 
+                    AttachOptions.Fill, 
+                    AttachOptions.Fill, 0, 0);
+            }
+            
+            table.Attach (label, 0, table.NColumns, 0, 1,
+                AttachOptions.Fill | AttachOptions.Expand, 
+                AttachOptions.Fill, 0, 0);
+                
+            table.ShowAll ();
+            
+            if (expand) {
+                parent.PackStart (table, false, false, 0);
+            } else {
+                HBox shrink = new HBox ();
+                shrink.Show ();
+                shrink.PackStart (table, false, false, 0);
+                parent.PackStart (shrink, false, false, 0);
+            }
+        }
+        
+        public virtual void LoadTrack (EditorTrackInfo track)
+        {
+            current_track = null;
+            
+            foreach (FieldSlot slot in field_slots) {
+                UpdateLabel (track, slot);
+                slot.ReadClosure (track, slot.Field);
+            }
+            
+            current_track = track;
+        }
+        
+        private void UpdateLabel (EditorTrackInfo track, FieldSlot slot)
+        {
+            string value = slot.LabelClosure (track, slot.Label);
+            Label label = slot.Label as Label;
+            if (value != null && label != null) {
+                label.Text = value;
+            }
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/IEditorField.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/IEditorField.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,37 @@
+//
+// IEditorField.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.Gui.TrackEditor
+{
+    public interface IEditorField
+    {
+        event EventHandler Changed;
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/ITrackEditorPage.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/ITrackEditorPage.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,44 @@
+//
+// TrackEditorPage.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 Banshee.Collection;
+
+namespace Banshee.Gui.TrackEditor
+{
+    public interface ITrackEditorPage
+    {
+        void Initialize (TrackEditorDialog dialog);
+        void LoadTrack (EditorTrackInfo track);
+        
+        int Order { get; }
+        string Title { get; }
+        Gtk.Widget Widget { get; }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/LyricsPage.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/LyricsPage.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,61 @@
+//
+// LyricsPage.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 Mono.Unix;
+using Gtk;
+
+using Banshee.Collection;
+
+namespace Banshee.Gui.TrackEditor
+{
+    public class LyricsPage : FieldPage, ITrackEditorPage
+    {    
+        private TextViewEntry lyrics_entry;
+            
+        public int Order {
+            get { return 30; }
+        }
+                                    
+        public string Title {
+            get { return Catalog.GetString ("Lyrics"); }
+        }
+        
+        public override void LoadTrack (EditorTrackInfo track)
+        {
+            BorderWidth = 2;
+            lyrics_entry.Text = "Not supported";
+        }
+        
+        protected override void AddFields ()
+        {
+            PackStart (lyrics_entry = new TextViewEntry (), true, true, 0);
+            lyrics_entry.Show ();
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/RangeEntry.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/RangeEntry.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,70 @@
+//
+// RangeEntry.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 Banshee.Gui.TrackEditor
+{
+    public class RangeEntry : HBox, IEditorField
+    {
+        public event EventHandler Changed;
+    
+        private SpinButton from_entry;
+        public SpinButton From {
+            get { return from_entry; }
+        }
+        
+        private SpinButton to_entry;
+        public SpinButton To {
+            get { return to_entry; }
+        }
+    
+        public RangeEntry (string rangeLabel)
+        {
+            PackStart (from_entry = new SpinButton (0, 99, 1), true, true, 0);
+            PackStart (new Label (rangeLabel), false, false, 6);
+            PackStart (to_entry = new SpinButton (0, 99, 1), true, true, 0);
+            ShowAll ();
+            
+            from_entry.WidthChars = 2;
+            to_entry.WidthChars = 2;
+            
+            from_entry.Changed += OnChanged;
+            to_entry.Changed += OnChanged;
+        }
+        
+        private void OnChanged (object o, EventArgs args)
+        {
+            EventHandler handler = Changed;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/RatingEntry.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/RatingEntry.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,41 @@
+//
+// RatingEditorField.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 Banshee.Gui.TrackEditor
+{
+    public class RatingEntry : Hyena.Widgets.RatingEntry, IEditorField
+    {
+        public RatingEntry ()
+        {
+            AlwaysShowEmptyStars = true;
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SpinButtonEntry.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/SpinButtonEntry.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,40 @@
+//
+// SpinButtonEntry.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 Banshee.Gui.TrackEditor
+{
+    public class SpinButtonEntry : SpinButton, IEditorField
+    {
+        public SpinButtonEntry (double min, double max, double step) : base (min, max, step)
+        {
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TextEntry.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TextEntry.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,41 @@
+//
+// TextEntry.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 Banshee.Gui.TrackEditor
+{
+    public class TextEntry : Entry, IEditorField
+    {
+        public new string Text {
+            get { return base.Text; }
+            set { base.Text = value ?? String.Empty; }
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TextViewEntry.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TextViewEntry.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,69 @@
+//
+// TextViewEntry.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 Banshee.Gui.TrackEditor
+{
+    public class TextViewEntry : ScrolledWindow, IEditorField
+    {
+        public event EventHandler Changed;
+        
+        private TextView entry;
+        public TextView TextView {
+            get { return entry; }
+        }
+        
+        public string Text {
+            get { return entry.Buffer.Text; }
+            set { entry.Buffer.Text = value ?? String.Empty; }
+        }
+
+        public TextViewEntry ()
+        {
+            VscrollbarPolicy = PolicyType.Automatic;
+            HscrollbarPolicy = PolicyType.Never;
+            ShadowType = ShadowType.In;
+            
+            Add (entry = new TextView ());
+            entry.AcceptsTab = false;
+            entry.Show ();
+            entry.Buffer.Changed += OnChanged;
+        }
+                
+        private void OnChanged (object o, EventArgs args)
+        {
+            EventHandler handler = Changed;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
+    }
+}
+            
\ No newline at end of file

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TitleEntry.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TitleEntry.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,72 @@
+//
+// TitleEntry.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 Banshee.Gui.TrackEditor
+{
+    public class TitleEntry : HBox, IEditorField
+    {
+        public event EventHandler Changed;
+        
+        private TextEntry entry;
+        private Button forward_button;
+        
+        public TitleEntry ()
+        {
+            entry = new TextEntry ();
+            entry.Changed += OnChanged;
+            entry.Show ();
+            
+            forward_button = EditorUtilities.CreateSmallStockButton (Stock.GoForward);
+            forward_button.Show ();
+            
+            Spacing = 1;
+            PackStart (entry, true, true, 0);
+            PackStart (forward_button, false, false, 0);
+        }
+                
+        private void OnChanged (object o, EventArgs args)
+        {
+            EventHandler handler = Changed;
+            if (handler != null) {
+                handler (this, EventArgs.Empty);
+            }
+        }
+    
+        public TextEntry Entry {
+            get { return entry; }
+        }
+        
+        public string Text {
+            get { return entry.Text; }
+            set { entry.Text = value; }
+        }
+    }
+}

Added: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs
==============================================================================
--- (empty file)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui.TrackEditor/TrackEditorDialog.cs	Wed Aug 20 05:59:42 2008
@@ -0,0 +1,284 @@
+//
+// TrackEditorDialog.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;
+
+using Mono.Unix;
+using Mono.Addins;
+using Gtk;
+
+using Banshee.Collection;
+using Banshee.Collection.Database;
+
+using Banshee.Gui.Dialogs;
+
+namespace Banshee.Gui.TrackEditor
+{
+    public class TrackEditorDialog : BansheeDialog
+    {
+        private VBox main_vbox;
+    
+        private Image header_image;
+        private Label header_title_label;
+        private Label header_artist_label;
+        private Label header_album_label;
+        
+        private Notebook notebook;
+    
+        private Button nav_backward_button;
+        private Button nav_forward_button;
+        
+        private List<ITrackEditorPage> pages = new List<ITrackEditorPage> ();
+        
+        public TrackEditorDialog (TrackListModel model) : base (Catalog.GetString ("Track Editor"))
+        {
+            LoadTrackModel (model);
+        
+            AddStockButton (Stock.Cancel, ResponseType.Cancel);
+            AddStockButton (Stock.Save, ResponseType.Ok);
+            AddNavigationButtons ();
+            
+            BorderWidth = 6;
+            WidthRequest = 525;
+            
+            main_vbox = new VBox ();
+            main_vbox.Spacing = 10;
+            main_vbox.BorderWidth = 6;
+            main_vbox.Show ();
+            VBox.PackStart (main_vbox, true, true, 0);
+            
+            BuildHeader ();
+            BuildNotebook ();
+            
+            LoadTrackToEditor ();
+        }
+        
+#region UI Building
+
+        private void AddNavigationButtons ()
+        {
+            if (TrackCount <= 1) {
+                return;
+            }
+            
+            nav_backward_button = new Button (Stock.GoBack);
+            nav_backward_button.UseStock = true;
+            nav_backward_button.Clicked += delegate { NavigateBackward (); };
+            nav_backward_button.Show ();
+            
+            nav_forward_button = new Button (Stock.GoForward);
+            nav_forward_button.UseStock = true;
+            nav_forward_button.Clicked += delegate { NavigateForward (); };
+            nav_forward_button.Show ();
+            
+            ActionArea.PackStart (nav_backward_button, false, false, 0);
+            ActionArea.PackStart (nav_forward_button, false, false, 0);
+            ActionArea.SetChildSecondary (nav_backward_button, true);
+            ActionArea.SetChildSecondary (nav_forward_button, true);
+        }
+        
+        private void BuildHeader ()
+        {
+            Table header = new Table (3, 3, false);
+            header.ColumnSpacing = 5;
+            
+            header_image = new Image ();
+            header_image.IconName = "media-optical";
+            header_image.PixelSize = 64;
+            header.Attach (header_image, 0, 1, 0, 3,
+                AttachOptions.Shrink, AttachOptions.Expand, 0, 0);
+            
+            AddHeaderRow (header, 0, Catalog.GetString ("Title:"), out header_title_label);
+            AddHeaderRow (header, 1, Catalog.GetString ("Artist:"), out header_artist_label);
+            AddHeaderRow (header, 2, Catalog.GetString ("Album:"), out header_album_label);
+          
+            header.ShowAll ();
+            main_vbox.PackStart (header, false, false, 0);
+        }
+        
+        private void AddHeaderRow (Table header, uint row, string title, out Label label)
+        {
+            Label title_label = new Label ();
+            title_label.Markup = String.Format ("<b>{0}</b>", GLib.Markup.EscapeText (title));
+            title_label.Xalign = 0.0f;
+            header.Attach (title_label, 1, 2, row, row + 1,
+                AttachOptions.Fill, AttachOptions.Expand, 0, 0);
+            
+            label = new Label ();
+            label.Xalign = 0.0f;
+            header.Attach (label, 2, 3, row, row + 1, 
+                AttachOptions.Fill | AttachOptions.Expand, AttachOptions.Expand, 0, 0);
+        }
+        
+        private void BuildNotebook ()
+        {
+            notebook = new Notebook ();
+            notebook.Show ();
+            
+            foreach (TypeExtensionNode node in AddinManager.GetExtensionNodes ("/Banshee/Gui/TrackEditor/NotebookPage")) {
+                try {
+                    ITrackEditorPage page = (ITrackEditorPage)node.CreateInstance ();
+                    pages.Add (page);
+                    page.Initialize (this);
+                    page.Widget.Show ();
+                } catch (Exception e) {
+                    Hyena.Log.Exception ("Invalid NotebookPage extension node. Should implement ITrackEditorPage.", e);
+                }
+            }
+            
+            pages.Sort (delegate (ITrackEditorPage a, ITrackEditorPage b) { return a.Order.CompareTo (b.Order); });
+            foreach (ITrackEditorPage page in pages) {
+                Container container = page.Widget as Container;
+                if (container == null) {
+                    VBox box = new VBox ();
+                    box.PackStart (page.Widget, true, true, 0);
+                    container = box;
+                }
+                container.BorderWidth = 12;
+                notebook.AppendPage (container, new Label (page.Title));
+            }
+            
+            BuildHelp ();
+            main_vbox.PackStart (notebook, true, true, 0);
+        }
+        
+        private void BuildHelp ()
+        {
+            HBox box = new HBox ();
+            box.Spacing = 2;
+            Image image = new Image (Stock.Help, IconSize.Menu);
+            Label label = new Label (Catalog.GetString ("Help"));
+            box.PackStart (image, false, false, 0);
+            box.PackStart (label, true, true, 0);
+            box.ShowAll ();
+            
+            Image help = new Image ();
+            help.Pixbuf = Gdk.Pixbuf.LoadFromResource ("jcastro.png");
+            help.Show ();
+            notebook.AppendPage (help, box);
+            
+            notebook.SetTabLabelPacking (help, false, false, PackType.End);
+        }
+
+#endregion
+        
+#region Track Model/Changes API
+        
+        private CachedList<DatabaseTrackInfo> db_selection;
+        private List<TrackInfo> memory_selection;
+        private Dictionary<TrackInfo, EditorTrackInfo> edit_map = new Dictionary<TrackInfo, EditorTrackInfo> ();
+        private int current_track_index;
+        
+        protected void LoadTrackModel (TrackListModel model)
+        {
+            DatabaseTrackListModel db_model = model as DatabaseTrackListModel;
+            if (db_model != null) {
+                db_selection = CachedList<DatabaseTrackInfo>.CreateFromModelSelection (db_model);
+            } else {
+                memory_selection = new List<TrackInfo> ();
+                foreach (TrackInfo track in model.SelectedItems) {
+                    memory_selection.Add (track);
+                }
+            }
+        }
+        
+        private void LoadTrackToEditor ()
+        {
+            TrackInfo current_track = GetTrack (current_track_index);
+            EditorTrackInfo editor_track = null;
+            
+            if (current_track == null) {
+                // Something bad happened here
+                return;
+            }
+            
+            if (!edit_map.TryGetValue (current_track, out editor_track)) {
+                editor_track = new EditorTrackInfo (current_track);
+                edit_map.Add (current_track, editor_track);
+            }
+            
+            // Update the Header
+            header_title_label.Text = current_track.DisplayTrackTitle;
+            header_artist_label.Text = current_track.DisplayArtistName;
+            header_album_label.Text = current_track.DisplayAlbumTitle;
+            
+            foreach (ITrackEditorPage page in pages) {
+                page.LoadTrack (editor_track);
+            }
+            
+            // Update Navigation
+            if (TrackCount > 0 && nav_backward_button != null && nav_forward_button != null) {
+                nav_backward_button.Sensitive = CanGoBackward;
+                nav_forward_button.Sensitive = CanGoForward;
+            }
+        }
+        
+        private TrackInfo GetTrack (int index)
+        {
+            return db_selection != null ? db_selection[index] : memory_selection[index];
+        }
+        
+        protected void NavigateForward ()
+        {
+            if (current_track_index < TrackCount - 1) {
+                current_track_index++;
+            }
+            
+            LoadTrackToEditor ();
+        }
+        
+        protected void NavigateBackward ()
+        {
+            if (current_track_index > 0) {
+                current_track_index--;
+            }
+            
+            LoadTrackToEditor ();
+        }
+        
+        public int TrackCount {
+            get { return db_selection != null ? db_selection.Count : memory_selection.Count; }
+        }
+        
+        protected int CurrentTrackIndex {
+            get { return current_track_index; }
+        }
+        
+        protected bool CanGoBackward {
+            get { return current_track_index > 0; }
+        }
+        
+        protected bool CanGoForward {
+            get { return current_track_index >= 0 && current_track_index < TrackCount - 1; }
+        }
+
+#endregion
+
+    }
+}

Modified: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
==============================================================================
--- branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs	(original)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs	Wed Aug 20 05:59:42 2008
@@ -280,7 +280,13 @@
                 if (handler != null) {
                     handler ();
                 } else {
-                    new TrackEditor (current_source.TrackModel.SelectedItems);
+                    Banshee.Gui.TrackEditor.TrackEditorDialog track_editor =    
+                        new Banshee.Gui.TrackEditor.TrackEditorDialog (current_source.TrackModel);
+                    try {
+                        track_editor.Run ();
+                    } finally {
+                        track_editor.Destroy ();
+                    }
                 }
             }
         }

Modified: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml
==============================================================================
--- branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml	(original)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml	Wed Aug 20 05:59:42 2008
@@ -12,12 +12,22 @@
     <Addin id="Banshee.Services" version="1.0" />
   </Dependencies>
 
+  <!-- Internal Extensions -->
+  
   <Extension path="/Banshee/Library/ImportSource">
     <ImportSource class="Banshee.Library.Gui.FolderImportSource"/>
     <ImportSource class="Banshee.Library.Gui.PhotoFolderImportSource"/>
     <ImportSource class="Banshee.Library.Gui.FileImportSource"/>
   </Extension>
-
+  
+  <Extension path="/Banshee/Gui/TrackEditor/NotebookPage">
+    <TrackEditorPage class="Banshee.Gui.TrackEditor.BasicTrackDetailsPage"/>
+    <TrackEditorPage class="Banshee.Gui.TrackEditor.ExtraTrackDetailsPage"/>
+    <TrackEditorPage class="Banshee.Gui.TrackEditor.LyricsPage"/>
+  </Extension>
+  
+  <!-- Exported Extension Points -->
+  
   <ExtensionPoint path="/Banshee/ThickClient/ActionGroup">
     <Description>Defines a new GTK+ action group, possibly in conjunction with a Source extension.</Description>
     <ExtensionNode name="ActionGroup"/>
@@ -28,4 +38,9 @@
     <ExtensionNode name="SourceView"/>
   </ExtensionPoint>
   
+  <ExtensionPoint path="/Banshee/Gui/TrackEditor/NotebookPage">
+    <Description>Defines a new notebook page for the track editor.</Description>
+    <ExtensionNode name="TrackEditorPage"/>
+  </ExtensionPoint>
+  
 </Addin>

Modified: branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
==============================================================================
--- branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	(original)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	Wed Aug 20 05:59:42 2008
@@ -120,6 +120,21 @@
     <File name="Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Library.Gui/PhotoFolderImportSource.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/TrackEditorDialog.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/ITrackEditorPage.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/BasicTrackDetailsPage.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/EditorUtilities.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/TitleEntry.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/ExtraTrackDetailsPage.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/RangeEntry.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/RatingEntry.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/TextViewEntry.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/FieldPage.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/TextEntry.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/SpinButtonEntry.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/LyricsPage.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/EditorTrackInfo.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.TrackEditor/IEditorField.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Project" localcopy="False" refto="Hyena.Gui" />

Modified: branches/banshee/abock/src/Core/Banshee.ThickClient/Makefile.am
==============================================================================
--- branches/banshee/abock/src/Core/Banshee.ThickClient/Makefile.am	(original)
+++ branches/banshee/abock/src/Core/Banshee.ThickClient/Makefile.am	Wed Aug 20 05:59:42 2008
@@ -47,6 +47,21 @@
 	Banshee.Gui.DragDrop/DragDropList.cs \
 	Banshee.Gui.DragDrop/DragDropTarget.cs \
 	Banshee.Gui.DragDrop/DragDropUtilities.cs \
+	Banshee.Gui.TrackEditor/BasicTrackDetailsPage.cs \
+	Banshee.Gui.TrackEditor/EditorTrackInfo.cs \
+	Banshee.Gui.TrackEditor/EditorUtilities.cs \
+	Banshee.Gui.TrackEditor/ExtraTrackDetailsPage.cs \
+	Banshee.Gui.TrackEditor/FieldPage.cs \
+	Banshee.Gui.TrackEditor/IEditorField.cs \
+	Banshee.Gui.TrackEditor/ITrackEditorPage.cs \
+	Banshee.Gui.TrackEditor/LyricsPage.cs \
+	Banshee.Gui.TrackEditor/RangeEntry.cs \
+	Banshee.Gui.TrackEditor/RatingEntry.cs \
+	Banshee.Gui.TrackEditor/SpinButtonEntry.cs \
+	Banshee.Gui.TrackEditor/TextEntry.cs \
+	Banshee.Gui.TrackEditor/TextViewEntry.cs \
+	Banshee.Gui.TrackEditor/TitleEntry.cs \
+	Banshee.Gui.TrackEditor/TrackEditorDialog.cs \
 	Banshee.Gui.Widgets/ArtworkPopup.cs \
 	Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs \
 	Banshee.Gui.Widgets/ConnectedMessageBar.cs \

Modified: branches/banshee/abock/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs
==============================================================================
--- branches/banshee/abock/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs	(original)
+++ branches/banshee/abock/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs	Wed Aug 20 05:59:42 2008
@@ -114,6 +114,11 @@
             Gdk.Colormap.System.AllocColor (ref color, true, true);
             return color;
         }
-
+        
+        public static T StyleGetProperty<T> (Widget widget, string property, T default_value)
+        {
+            object result = widget.StyleGetProperty (property);
+            return result != null && result.GetType () == typeof (T) ? (T)result : default_value;
+        }
     }
 }

Modified: branches/banshee/abock/src/Libraries/Hyena.Gui/Hyena.Widgets/RatingEntry.cs
==============================================================================
--- branches/banshee/abock/src/Libraries/Hyena.Gui/Hyena.Widgets/RatingEntry.cs	(original)
+++ branches/banshee/abock/src/Libraries/Hyena.Gui/Hyena.Widgets/RatingEntry.cs	Wed Aug 20 05:59:42 2008
@@ -168,6 +168,8 @@
             event_window = new Gdk.Window (GdkWindow, attributes, attributes_mask);
             event_window.UserData = Handle;
             
+            Style = Gtk.Rc.GetStyleByPaths (Settings, "*.GtkEntry", "*.GtkEntry", GType);
+            
             base.OnRealized ();
         }
          
@@ -176,7 +178,7 @@
             WidgetFlags &= ~WidgetFlags.Realized;
             
             event_window.UserData = IntPtr.Zero;
-            event_window.Destroy ();
+            Hyena.Gui.GtkWorkarounds.WindowDestroy (event_window);
             event_window = null;
             
             base.OnUnrealized ();
@@ -193,7 +195,7 @@
             WidgetFlags &= ~WidgetFlags.Mapped;
             event_window.Hide ();
         }
-        
+
         private bool changing_style;
         protected override void OnStyleSet (Style previous_style)
         {
@@ -201,11 +203,11 @@
                 return;
             }
             
+            base.OnStyleSet (previous_style);
+            
             changing_style = true;
             focus_width = (int)StyleGetProperty ("focus-line-width");
             interior_focus = (bool)StyleGetProperty ("interior-focus");
-            
-            ModifyBg (StateType.Normal, Style.Base (StateType.Normal));
             changing_style = false;
         }
         
@@ -245,15 +247,16 @@
             }
             
             if (HasFrame) {
-                int y_mid = (Allocation.Height - renderer.Height) / 2;
-                Gtk.Style.PaintFlatBox (Style, GdkWindow, StateType.Normal, ShadowType.None, evnt.Area, this, "entry", 
+                int y_mid = (int)Math.Round ((Allocation.Height - renderer.Height) / 2.0);
+                Gtk.Style.PaintFlatBox (Style, GdkWindow, State, ShadowType.None, evnt.Area, this, "entry", 
                     Allocation.X, Allocation.Y + y_mid, Allocation.Width, renderer.Height);
-                Gtk.Style.PaintShadow (Style, GdkWindow, StateType.Normal, ShadowType.In,
+                Gtk.Style.PaintShadow (Style, GdkWindow, State, ShadowType.In,
                     evnt.Area, this, "entry", Allocation.X, Allocation.Y + y_mid, Allocation.Width, renderer.Height);
             }
             
             Cairo.Context cr = Gdk.CairoHelper.Create (GdkWindow);
-            renderer.Render (cr, Allocation, CairoExtensions.GdkColorToCairoColor (Style.Foreground (State)), 
+            renderer.Render (cr, Allocation, 
+                CairoExtensions.GdkColorToCairoColor (HasFrame ? Style.Text (State) : Style.Foreground (State)), 
                 AlwaysShowEmptyStars || (PreviewOnHover && hover_value >= renderer.MinRating), hover_value,
                 State == StateType.Insensitive ? 1 : 0.90, 
                 State == StateType.Insensitive ? 1 : 0.65, 

Modified: branches/banshee/abock/src/Libraries/Hyena/Hyena/StringUtil.cs
==============================================================================
--- branches/banshee/abock/src/Libraries/Hyena/Hyena/StringUtil.cs	(original)
+++ branches/banshee/abock/src/Libraries/Hyena/Hyena/StringUtil.cs	Wed Aug 20 05:59:42 2008
@@ -63,6 +63,11 @@
         
         public static string CamelCaseToUnderCase (string s)
         {
+            return CamelCaseToUnderCase (s, '_');
+        }
+        
+        public static string CamelCaseToUnderCase (string s, char underscore)
+        {
             if (String.IsNullOrEmpty (s)) {
                 return null;
             }
@@ -77,7 +82,7 @@
 
                 undercase.Append (tokens[i].ToLower ());
                 if (i < tokens.Length - 2) {
-                    undercase.Append ('_');
+                    undercase.Append (underscore);
                 }
             }
             



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