[banshee] ThickClient: ArtistList renderers support via addins (bgo#646765)



commit c3a33c9afade783dbc25bf265ad2b3277c3cf958
Author: Frank Ziegler <funtastix googlemail com>
Date:   Fri Jul 18 17:13:11 2014 +0200

    ThickClient: ArtistList renderers support via addins (bgo#646765)
    
    The first two b-c-e extensions that will make use of this are:
    - FanArt
    - ArtistListCovers
    
    Signed-off-by: Andrés G. Aragoneses <knocte gmail com>

 .../Banshee.Collection.Gui/ArtistListView.cs       |   79 +++++-
 .../Banshee.Collection.Gui/ColumnCellArtistText.cs |   69 ++++
 .../Banshee.Collection.Gui/IArtistListRenderer.cs  |   42 +++
 .../Banshee.Gui/ArtistListActions.cs               |  337 ++++++++++++++++++++
 .../Banshee.Gui/InterfaceActionService.cs          |   10 +-
 .../Banshee.ThickClient.addin.xml                  |   10 +
 .../Banshee.ThickClient/Banshee.ThickClient.csproj |    3 +
 src/Core/Banshee.ThickClient/Makefile.am           |    3 +
 8 files changed, 547 insertions(+), 6 deletions(-)
---
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtistListView.cs 
b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtistListView.cs
index 23b9a12..2565620 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtistListView.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ArtistListView.cs
@@ -3,8 +3,10 @@
 //
 // Author:
 //   Aaron Bockover <abockover novell com>
+//   Frank Ziegler <funtastix googlemail com>
 //
 // Copyright (C) 2007 Novell, Inc.
+// Copyright (C) 2013 Frank Ziegler
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -28,23 +30,90 @@
 
 using System;
 
-using Hyena.Data;
-using Hyena.Data.Gui;
-
 using Banshee.Collection;
 using Banshee.ServiceStack;
 using Banshee.Gui;
+using Banshee.MediaEngine;
+
+using Gtk;
 
 namespace Banshee.Collection.Gui
 {
     public class ArtistListView : TrackFilterListView<ArtistInfo>
     {
         protected ArtistListView (IntPtr ptr) : base () {}
+        private IArtistListRenderer renderer = null;
+        private readonly InterfaceActionService action_service = null;
 
         public ArtistListView () : base ()
         {
-            column_controller.Add (new Column ("Artist", new ColumnCellText ("DisplayName", true), 1.0));
-            ColumnController = column_controller;
+            action_service = ServiceManager.Get<InterfaceActionService> ();
+
+            renderer = action_service.ArtistListActions.ArtistListRenderer;
+
+            if (renderer == null) {
+                renderer = new ColumnCellArtistText ();
+            }
+            UpdateRenderer ();
+
+            ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent, PlayerEvent.TrackInfoUpdated);
+            Banshee.Metadata.MetadataService.Instance.ArtworkUpdated += OnArtworkUpdated;
+
+            action_service.ArtistListActions.ArtistListModeChanged += HandleArtistListModeChanged;
+        }
+
+        private void HandleArtistListModeChanged (object sender, ArtistListModeChangedEventArgs args)
+        {
+            this.renderer = args.Renderer;
+            UpdateRenderer ();
+        }
+
+        protected override void Dispose (bool disposing)
+        {
+            if (disposing) {
+                ServiceManager.PlayerEngine.DisconnectEvent (OnPlayerEvent);
+                Banshee.Metadata.MetadataService.Instance.ArtworkUpdated -= OnArtworkUpdated;
+                action_service.ArtistListActions.ArtistListModeChanged -= HandleArtistListModeChanged;
+            }
+            base.Dispose (disposing);
+        }
+
+        protected override Gdk.Size OnMeasureChild ()
+        {
+            return new Gdk.Size (0, renderer.ComputeRowHeight (this));
+        }
+
+        private void UpdateRenderer ()
+        {
+            column_controller.Clear ();
+            ColumnController = renderer.ColumnController;
+            QueueResize ();
+        }
+
+        private void OnPlayerEvent (PlayerEventArgs args)
+        {
+            QueueDraw ();
+        }
+
+        private void OnArtworkUpdated (IBasicTrackInfo track)
+        {
+            QueueDraw ();
+        }
+
+        protected override bool OnFocusInEvent (Gdk.EventFocus evnt)
+        {
+            action_service.ArtistListActions ["ArtistListMenuAction"].Visible =
+                action_service.ArtistListActions.ListActions ().Length > 2;
+            return base.OnFocusInEvent (evnt);
+        }
+
+        protected override bool OnFocusOutEvent (Gdk.EventFocus evnt)
+        {
+            var focus = ServiceManager.Get<GtkElementsService> ().PrimaryWindow.Focus;
+            if (focus != this) {
+                action_service.ArtistListActions ["ArtistListMenuAction"].Visible = false;
+            }
+            return base.OnFocusOutEvent (evnt);
         }
 
         // TODO add context menu for artists/albums...probably need a Banshee.Gui/ArtistActions.cs file.  
Should
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellArtistText.cs 
b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellArtistText.cs
new file mode 100644
index 0000000..e8ce1ec
--- /dev/null
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/ColumnCellArtistText.cs
@@ -0,0 +1,69 @@
+//
+// ColumnArtistCellText.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//   Frank Ziegler <funtastix googlemail com>
+//
+// Copyright (C) 2007 Novell, Inc.
+// Copyright (C) 2013 Frank Ziegler
+//
+// 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 Gtk;
+
+using Hyena.Data.Gui;
+
+using Banshee.I18n;
+
+namespace Banshee.Collection.Gui
+{
+    public class ColumnCellArtistText : ColumnCellText, IArtistListRenderer
+    {
+        private readonly ColumnController column_controller;
+        private readonly string name = Catalog.GetString ("Default Text Artist List");
+
+        public ColumnCellArtistText () : base ("DisplayName", true)
+        {
+            column_controller = new ColumnController ();
+            var current_layout = new Column ("Artist", this, 1.0);
+            column_controller.Add (current_layout);
+        }
+
+        public string Name {
+            get { return name; }
+        }
+
+        public ColumnController ColumnController {
+            get { return column_controller; }
+        }
+
+        public int ComputeRowHeight (Widget widget)
+        {
+            int w_width, row_height;
+            using (var layout = new Pango.Layout (widget.PangoContext)) {
+                layout.SetText ("W");
+                layout.GetPixelSize (out w_width, out row_height);
+                return row_height + 8;
+            }
+        }
+    }
+}
diff --git a/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/IArtistListRenderer.cs 
b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/IArtistListRenderer.cs
new file mode 100644
index 0000000..b8f1660
--- /dev/null
+++ b/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/IArtistListRenderer.cs
@@ -0,0 +1,42 @@
+//
+// IArtistListRenderer.cs
+//
+// Author:
+//   Frank Ziegler <funtastix googlemail com>
+//
+// Copyright (C) 2013 Frank Ziegler
+//
+// 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 Gtk;
+using Hyena.Data.Gui;
+
+namespace Banshee.Collection.Gui
+{
+    public interface IArtistListRenderer
+    {
+        string Name { get; }
+
+        int ComputeRowHeight (Widget widget);
+
+        ColumnController ColumnController { get; }
+    }
+}
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui/ArtistListActions.cs 
b/src/Core/Banshee.ThickClient/Banshee.Gui/ArtistListActions.cs
new file mode 100644
index 0000000..45e2e7d
--- /dev/null
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui/ArtistListActions.cs
@@ -0,0 +1,337 @@
+//
+// ArtistListActions.cs
+//
+// Authors:
+//   Aaron Bockover <abockover novell com>
+//   Alexander Hixon <hixon alexander mediati org>
+//   Frank Ziegler <funtastix googlemail com>
+//
+// Copyright (C) 2007-2008 Novell, Inc.
+// Copyright (C) 2013 Frank Ziegler
+//
+// 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;
+using System.Collections.Generic;
+
+using Mono.Addins;
+using Mono.Unix;
+
+using Gtk;
+
+using Hyena;
+using Hyena.Widgets;
+
+using Banshee.Collection.Gui;
+using Banshee.Widgets;
+using Banshee.Configuration;
+using Banshee.ServiceStack;
+
+namespace Banshee.Gui
+{
+    public class ArtistListModeChangedEventArgs : EventArgs
+    {
+        public IArtistListRenderer Renderer { get; set; }
+    }
+
+    public class ArtistListActions : BansheeActionGroup, IEnumerable<RadioAction>
+    {
+        private class ArtistListActionProxy : CustomActionProxy
+        {
+            private ArtistListActions actions;
+            private ComplexMenuItem last_item;
+
+            public ArtistListActions ListActions {
+                set {
+                    value.ArtistListModeChanged += (o, args) => {
+                        if (last_item != null) {
+                            actions.AttachSubmenu (last_item);
+                        }
+                    };
+                    actions = value;
+                }
+            }
+
+            public ArtistListActionProxy (UIManager ui, Gtk.Action action) : base (ui, action)
+            {
+            }
+
+            protected override void InsertProxy (Gtk.Action menuAction, Widget parent, Widget afterItem)
+            {
+                int position = 0;
+                Widget item = null;
+                if (parent is MenuItem || parent is Menu) {
+                    Menu parent_menu = ((parent is MenuItem) ? (parent as MenuItem).Submenu : parent) as 
Menu;
+                    position = (afterItem != null) ? Array.IndexOf (parent_menu.Children, afterItem as 
MenuItem) + 1 : 0;
+                    item = GetNewMenuItem ();
+                    if (item != null) {
+                        var separator1 = new SeparatorMenuItem ();
+                        var separator2 = new SeparatorMenuItem ();
+                        //fix for separators that potentially already exist below the insert position
+                        bool alreadyHasSeparator2 = ((parent_menu.Children [position]) as SeparatorMenuItem 
!= null);
+                        parent_menu.Insert (separator2, position);
+                        parent_menu.Insert (item, position);
+                        parent_menu.Insert (separator1, position);
+                        item.Shown += (o, e) => {
+                            separator1.Show ();
+                            if (!alreadyHasSeparator2) {
+                                separator2.Show ();
+                            }
+                        };
+                        item.Hidden += (o, e) => {
+                            separator1.Hide ();
+                            separator2.Hide ();
+                        };
+                    }
+                }
+                var activatable = item as IActivatable;
+                if (activatable != null) {
+                    activatable.RelatedAction = action;
+                }
+            }
+
+            protected override ComplexMenuItem GetNewMenuItem ()
+            {
+                var item = new ComplexMenuItem ();
+                var box = new HBox ();
+                box.Spacing = 5;
+
+                var label = new Label (Catalog.GetString ("Artist List View"));
+                box.PackStart (label, false, false, 0);
+                label.Show ();
+
+                box.ShowAll ();
+                item.Add (box);
+
+                last_item = item;
+
+                actions.AttachSubmenu (item);
+
+                return item;
+            }
+        }
+
+        private bool service_manager_startup_finished = false;
+        private ArtistListActionProxy artist_list_proxy;
+        private RadioAction active_action;
+        private List<IArtistListRenderer> renderers = new List<IArtistListRenderer> ();
+        private Dictionary<int, String> rendererActions = new Dictionary<int, String> ();
+        private Dictionary<TypeExtensionNode, IArtistListRenderer> node_map = new 
Dictionary<TypeExtensionNode, IArtistListRenderer> ();
+
+        public event EventHandler<ArtistListModeChangedEventArgs> ArtistListModeChanged;
+
+        public Action<IArtistListRenderer> ArtistListModeAdded;
+        public Action<IArtistListRenderer> ArtistListModeRemoved;
+
+        public RadioAction Active {
+            get { return active_action; }
+            set {
+                active_action = value;
+                SetRenderer (renderers [active_action.Value]);
+            }
+        }
+
+        public ArtistListActions () : base ("ArtistList")
+        {
+            ServiceManager.StartupFinished += delegate {
+                service_manager_startup_finished = true;
+            };
+
+            Add (new [] {
+                new ActionEntry ("ArtistListMenuAction", null, Catalog.GetString ("_ArtistList"),
+                                 null, null, null)
+            });
+
+            this ["ArtistListMenuAction"].Visible = false;
+
+            AddinManager.AddExtensionNodeHandler ("/Banshee/Gui/ArtistListView", OnExtensionChanged);
+
+            Actions.UIManager.ActionsChanged += HandleActionsChanged;
+        }
+
+        private void HandleActionsChanged (object sender, EventArgs e)
+        {
+            if (Actions.UIManager.GetAction ("/MainMenu/ViewMenu") != null) {
+                artist_list_proxy = new ArtistListActionProxy (Actions.UIManager, this 
["ArtistListMenuAction"]);
+                artist_list_proxy.ListActions = this;
+                artist_list_proxy.AddPath ("/MainMenu/ViewMenu", "FullScreen");
+                artist_list_proxy.AddPath ("/TrackContextMenu", "AddToPlaylist");
+                Actions.UIManager.ActionsChanged -= HandleActionsChanged;
+            }
+        }
+
+        private void OnExtensionChanged (object o, ExtensionNodeEventArgs args)
+        {
+            var tnode = (TypeExtensionNode)args.ExtensionNode;
+            IArtistListRenderer changed_renderer = null;
+
+            if (args.Change == ExtensionChange.Add) {
+                lock (renderers) {
+                    try {
+                        changed_renderer = (IArtistListRenderer)tnode.CreateInstance ();
+                        renderers.Add (changed_renderer);
+                        node_map [tnode] = changed_renderer;
+                    } catch (Exception e) {
+                        Log.Error (String.Format ("Failed to load ArtistListRenderer extension: {0}", 
args.Path), e);
+                    }
+                }
+
+                if (changed_renderer != null) {
+                    var handler = ArtistListModeAdded;
+                    if (handler != null) {
+                        handler (changed_renderer);
+                    }
+                    if (service_manager_startup_finished) {
+                        SetRenderer (changed_renderer);
+                    }
+                }
+            } else {
+                lock (renderers) {
+                    if (node_map.ContainsKey (tnode)) {
+                        changed_renderer = node_map [tnode];
+                        node_map.Remove (tnode);
+                        renderers.Remove (changed_renderer);
+                        if (this.renderer == changed_renderer) {
+                            SetRenderer (renderers [0]);
+                        }
+                    }
+                }
+
+                if (changed_renderer != null) {
+                    var handler = ArtistListModeRemoved;
+                    if (handler != null) {
+                        handler (changed_renderer);
+                    }
+                }
+            }
+            UpdateActions ();
+        }
+
+        private void UpdateActions ()
+        {
+            // Clear out the old options
+            foreach (string id in rendererActions.Values) {
+                Remove (id);
+            }
+            rendererActions.Clear ();
+
+            var radio_group = new RadioActionEntry [renderers.Count];
+            int i = 0;
+
+            // Add all the renderer options
+            foreach (var rendererIterator in renderers) {
+                string action_name = rendererIterator.GetType ().FullName;
+                int id = rendererActions.Count;
+                rendererActions [id] = action_name;
+                radio_group [i++] = new RadioActionEntry (
+                    action_name, null,
+                    rendererIterator.Name, null,
+                    rendererIterator.Name,
+                    id
+                );
+            }
+
+            Add (radio_group, 0, OnActionChanged);
+
+            var radio_action = this [ArtistListMode.Get ()] as RadioAction;
+            if (renderers.Count > 0 && radio_action != null) {
+                this.renderer = renderers [radio_action.Value];
+
+                if (this.renderer == null) {
+                    SetRenderer (renderers [0]);
+                }
+
+                var action = this [this.renderer.GetType ().FullName];
+                if (action is RadioAction) {
+                    Active = (RadioAction)action;
+                }
+
+                Active.Activate ();
+            }
+        }
+
+        private IArtistListRenderer renderer;
+
+        private void SetRenderer (IArtistListRenderer renderer)
+        {
+            this.renderer = renderer;
+            ArtistListMode.Set (renderer.GetType ().FullName);
+
+            ThreadAssist.ProxyToMain (() => {
+                var handler = ArtistListModeChanged;
+                if (handler != null) {
+                    handler (this, new ArtistListModeChangedEventArgs { Renderer = renderer });
+                }
+            });
+        }
+
+        public IArtistListRenderer ArtistListRenderer {
+            get { return this.renderer; }
+        }
+
+        private void OnActionChanged (object o, ChangedArgs args)
+        {
+            Active = args.Current;
+        }
+
+        private void AttachSubmenu (ComplexMenuItem item)
+        {
+            MenuItem parent = item;
+            parent.Submenu = CreateMenu ();
+        }
+
+        private Menu CreateMenu ()
+        {
+            var menu = new Gtk.Menu ();
+            bool separator = false;
+            foreach (RadioAction action in this) {
+                menu.Append (action.CreateMenuItem ());
+                if (!separator) {
+                    separator = true;
+                    menu.Append (new SeparatorMenuItem ());
+                }
+            }
+
+            menu.ShowAll ();
+            return menu;
+        }
+
+        public IEnumerator<RadioAction> GetEnumerator ()
+        {
+            foreach (string id in rendererActions.Values) {
+                yield return (RadioAction)this [id];
+            }
+        }
+
+        IEnumerator IEnumerable.GetEnumerator ()
+        {
+            return GetEnumerator ();
+        }
+
+        public static readonly SchemaEntry<string> ArtistListMode = new SchemaEntry<string> (
+            "player_window", "artist_list_view_type",
+            typeof (ColumnCellArtistText).FullName,
+            "Artist List View Type",
+            "The view type chosen for the artist list"
+        );
+    }
+}
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs 
b/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs
index 15d6870..b0f697c 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs
@@ -1,10 +1,12 @@
 //
 // InterfaceActionService.cs
 //
-// Author:
+// Authors:
 //   Aaron Bockover <abockover novell com>
+//   Frank Ziegler <funtastix googlemail com>
 //
 // Copyright (C) 2006-2007 Novell, Inc.
+// Copyright (C) 2013 Frank Ziegler
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -53,6 +55,7 @@ namespace Banshee.Gui
         private TrackActions    track_actions;
         private SourceActions   source_actions;
 
+        private ArtistListActions artist_list_actions;
         private BansheeActionGroup active_source_actions;
         private List<uint> active_source_uis = new List<uint> ();
 
@@ -68,6 +71,7 @@ namespace Banshee.Gui
             AddActionGroup (playback_actions    = new PlaybackActions ());
             AddActionGroup (track_actions       = new TrackActions ());
             AddActionGroup (source_actions      = new SourceActions ());
+            AddActionGroup (artist_list_actions = new ArtistListActions ());
             UIManager.AddUiFromResource ("core-ui-actions-layout.xml");
 
             AddinManager.AddExtensionNodeHandler ("/Banshee/ThickClient/ActionGroup", OnExtensionChanged);
@@ -163,6 +167,10 @@ namespace Banshee.Gui
             get { return view_actions; }
         }
 
+        public ArtistListActions ArtistListActions {
+            get { return artist_list_actions; }
+        }
+
         string IService.ServiceName {
             get { return "InterfaceActionService"; }
         }
diff --git a/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml 
b/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml
index 42505f1..40cc46e 100644
--- a/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml
+++ b/src/Core/Banshee.ThickClient/Banshee.ThickClient.addin.xml
@@ -65,4 +65,14 @@
     <Description>Defines an extension that provides a custom (possibly native) file chooser 
dialog.</Description>
     <ExtensionNode name="NativeFileChooserDialog"/>
   </ExtensionPoint>
+
+  <ExtensionPoint path="/Banshee/Gui/ArtistListView">
+    <Description>Defines an extension that provides a custom rendering for the artist list 
cells.</Description>
+    <ExtensionNode name="ArtistListRenderer"/>
+  </ExtensionPoint>
+
+  <Extension path="/Banshee/Gui/ArtistListView">
+    <ArtistListRenderer class="Banshee.Collection.Gui.ColumnCellArtistText"/>
+  </Extension>
+
 </Addin>
diff --git a/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj 
b/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
index e8100a6..e5d7689 100644
--- a/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
+++ b/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
@@ -285,6 +285,9 @@
     <Compile Include="Banshee.Gui.Widgets\Tests\TrackInfoDisplayTests.cs" />
     <Compile Include="Banshee.Gui.Dialogs\GtkFileChooserDialog.cs" />
     <Compile Include="Banshee.Gui\WindowConfiguration.cs" />
+    <Compile Include="Banshee.Gui\ArtistListActions.cs" />
+    <Compile Include="Banshee.Collection.Gui\ColumnCellArtistText.cs" />
+    <Compile Include="Banshee.Collection.Gui\IArtistListRenderer.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>
diff --git a/src/Core/Banshee.ThickClient/Makefile.am b/src/Core/Banshee.ThickClient/Makefile.am
index 557fbba..16b2b05 100644
--- a/src/Core/Banshee.ThickClient/Makefile.am
+++ b/src/Core/Banshee.ThickClient/Makefile.am
@@ -16,6 +16,7 @@ SOURCES =  \
        Banshee.Collection.Gui/ArtworkRenderer.cs \
        Banshee.Collection.Gui/BaseTrackListView.cs \
        Banshee.Collection.Gui/ColumnCellAlbum.cs \
+       Banshee.Collection.Gui/ColumnCellArtistText.cs \
        Banshee.Collection.Gui/ColumnCellCreativeCommons.cs \
        Banshee.Collection.Gui/ColumnCellDateTime.cs \
        Banshee.Collection.Gui/ColumnCellDiscAndCount.cs \
@@ -31,6 +32,7 @@ SOURCES =  \
        Banshee.Collection.Gui/CoverArtEditor.cs \
        Banshee.Collection.Gui/DataViewChildAlbum.cs \
        Banshee.Collection.Gui/DefaultColumnController.cs \
+       Banshee.Collection.Gui/IArtistListRenderer.cs \
        Banshee.Collection.Gui/PersistentColumnController.cs \
        Banshee.Collection.Gui/QueryFilterView.cs \
        Banshee.Collection.Gui/SearchableListView.cs \
@@ -106,6 +108,7 @@ SOURCES =  \
        Banshee.Gui.Widgets/TrackInfoDisplay.cs \
        Banshee.Gui.Widgets/UserJobTile.cs \
        Banshee.Gui.Widgets/UserJobTileHost.cs \
+       Banshee.Gui/ArtistListActions.cs \
        Banshee.Gui/BansheeActionGroup.cs \
        Banshee.Gui/BansheeDbFormatMigratorMonitor.cs \
        Banshee.Gui/BansheeIconFactory.cs \


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