private void HandleActiveSourceChanged(SourceEventArgs args)
        {
            artwork_manager = ServiceManager.Get <ArtworkManager> ();

            if (!artwork_manager.IsCachedSize(image_size))
            {
                artwork_manager.AddCachedSize(image_size);
            }
            if (artwork_manager != null)
            {
                artwork_manager.ChangeCacheSize(ImageSize, GetAllAlbumsCount() + 3);
            }

            artwork_initialized = true;

            ServiceManager.SourceManager.ActiveSourceChanged -= HandleActiveSourceChanged;
        }
        private void HandleActiveSourceChanged(SourceEventArgs args)
        {
            artwork_manager = ServiceManager.Get<ArtworkManager> ();

            if (!artwork_manager.IsCachedSize (image_size)) {
                artwork_manager.AddCachedSize (image_size);
            }
            if (artwork_manager != null) {
                artwork_manager.ChangeCacheSize (ImageSize, GetAllAlbumsCount () + 3);
            }

            artwork_initialized = true;

            ServiceManager.SourceManager.ActiveSourceChanged -= HandleActiveSourceChanged;
        }
        public override void Render(CellContext context, double cellWidth, double cellHeight)
        {
            if (!artwork_initialized) {
                artwork_manager = ServiceManager.Get<ArtworkManager> ();

                if (!artwork_manager.IsCachedSize (image_size)) {
                    artwork_manager.AddCachedSize (image_size);
                }
                if (artwork_manager != null) {
                    artwork_manager.ChangeCacheSize (ImageSize, GetAllAlbumsCount () + 3);
                }

                artwork_initialized = true;
            }

            bool is_queryalble_source = ServiceManager.SourceManager.ActiveSource is PrimarySource;
            is_queryalble_source = is_queryalble_source || ServiceManager.SourceManager.ActiveSource is PlaylistSource;
            is_queryalble_source = is_queryalble_source || ServiceManager.SourceManager.ActiveSource is SmartPlaylistSource;

            if (BoundObject == null) {
                return;
            }

            if (!(BoundObject is ArtistInfo)) {
                throw new InvalidCastException ("ColumnCellArtist can only bind to ArtistInfo objects");
            }
            var artist = (ArtistInfo)BoundObject;

            DatabaseArtistInfo db_artist = DatabaseArtistInfo.FindOrCreate (artist.Name, artist.NameSort);

            AlbumInfo[] albums = GetAlbums (db_artist.DbId);
            int album_count = albums.Length;

            string pattern = Catalog.GetString ("All Artists ({0})")
                .Replace ("(", "\\(")
                .Replace (")", "\\)")
                .Replace ("{0}", "[0-9]+");

            if (!String.IsNullOrEmpty (artist.Name) && System.Text.RegularExpressions.Regex.IsMatch (artist.Name, pattern)) {
                album_count = GetAllAlbumsCount ();
            }

            ImageSurface image = null;
            var images = new List<ImageSurface> ();

            int non_empty = 0;
            for (int i = 0; i < albums.Length && non_empty < 3; i++) {
                if (artwork_manager != null) {
                    ImageSurface sur = artwork_manager.LookupScaleSurface (albums [i].ArtworkId, image_size, true);
                    images.Add (sur);
                    if (sur != null) {
                        non_empty++;
                    }
                }
            }

            //bringing non-empty images to the front
            images.Sort (delegate (ImageSurface a, ImageSurface b) {
                if (a == null && b != null) return -1;
                if (a != null && b == null) return 1;
                return 0;
            });

            if (images.Count > 3) {
                images.RemoveRange (3, images.Count - 3);
            }

            bool is_default = false;
            if (images.Count == 0) {
                image = default_cover_image;
                is_default = true;
            } else {
                image = images[images.Count - 1];
            }

            int image_render_size = image_size;
            int x = image_spacing;
            int y = image_spacing;

            if (use_small_images) {
                x = image_spacing / 2;
                y = image_spacing / 2;
            }

            const int y_image_spacing = 1;
            int x_offset = (use_small_images ? album_spacing_small : album_spacing_normal);
            if (images.Count > 1)
                x_offset *= 2;
            int y_offset = (images.Count > 1) ? y_image_spacing * 2 : y_image_spacing;

            for (int i = 0; i < images.Count - 1; i++) {
                int move_x = x + ((i) * (use_small_images ? album_spacing_small : album_spacing_normal));
                int move_y = y + ((i) * y_image_spacing);
                ArtworkRenderer.RenderThumbnail (context.Context, images[i], false, move_x, move_y,
                    image_render_size, image_render_size, !is_default, context.Theme.Context.Radius, true, new Color (1.0, 1.0, 1.0, 1.0));
            }

            if (images.Count > 0) {
                ArtworkRenderer.RenderThumbnail (context.Context, image, false, x + x_offset, y + y_offset,
                    image_render_size, image_render_size, !is_default, context.Theme.Context.Radius, true, new Color (1.0, 1.0, 1.0, 1.0));
            } else {
                ArtworkRenderer.RenderThumbnail (context.Context, image, false, x + x_offset, y + y_offset,
                    image_render_size, image_render_size, !is_default, context.Theme.Context.Radius);
            }

            int fl_width = 0, fl_height = 0, sl_width = 0, sl_height = 0;
            context.Widget.StyleContext.Save ();
            context.Widget.StyleContext.AddClass ("entry");
            Color text_color = CairoExtensions.GdkRGBAToCairoColor (context.Widget.StyleContext.GetColor (context.State));
            context.Widget.StyleContext.Restore ();
            text_color.A = 0.75;

            Pango.Layout layout = context.Layout;
            layout.Width = (int)((cellWidth - cellHeight - x - 10) * Pango.Scale.PangoScale);
            layout.Ellipsize = Pango.EllipsizeMode.End;
            layout.FontDescription.Weight = Pango.Weight.Bold;

            // Compute the layout sizes for both lines for centering on the cell
            int old_size = layout.FontDescription.Size;

            layout.SetText (artist.DisplayName);
            layout.GetPixelSize (out fl_width, out fl_height);

            layout.FontDescription.Weight = Pango.Weight.Normal;
            layout.FontDescription.Size = (int)(old_size * Pango.Scale.Small);
            layout.FontDescription.Style = Pango.Style.Italic;

            string album_string_singular = Catalog.GetString ("Album");
            string album_string_plural = Catalog.GetString ("Albums");

            layout.SetText (album_count + " " + ((album_count == 1) ? album_string_singular : album_string_plural));
            layout.GetPixelSize (out sl_width, out sl_height);

            // Calculate the layout positioning
            x = ((int)cellHeight - x) + (use_small_images ? album_spacing_small : album_spacing_normal) + 8;
            y = use_small_images ? (int)((cellHeight - (fl_height)) / 2) : (int)((cellHeight - (fl_height + sl_height)) / 2);

            // Render the second line first since we have that state already
            if (album_count > 0 && is_queryalble_source) {
                if (use_small_images) {
                    context.Context.MoveTo (cellWidth - sl_width - image_spacing, y + image_spacing / 2);
                } else {
                    context.Context.MoveTo (x, y + fl_height);
                }
                context.Context.SetSourceColor (text_color);
                if (!use_small_images || fl_width + x + sl_width <= cellWidth) {
                    Pango.CairoHelper.ShowLayout (context.Context, layout);
                }
            }

            // Render the first line, resetting the state
            layout.SetText (artist.DisplayName);
            layout.FontDescription.Weight = Pango.Weight.Bold;
            layout.FontDescription.Size = old_size;
            layout.FontDescription.Style = Pango.Style.Normal;

            layout.SetText (artist.DisplayName);

            context.Context.MoveTo (x, y);
            text_color.A = 1;
            context.Context.SetSourceColor (text_color);
            Pango.CairoHelper.ShowLayout (context.Context, layout);
        }
        public override void Render(CellContext context, double cellWidth, double cellHeight)
        {
            if (!artwork_initialized)
            {
                artwork_manager = ServiceManager.Get <ArtworkManager> ();

                if (!artwork_manager.IsCachedSize(image_size))
                {
                    artwork_manager.AddCachedSize(image_size);
                }
                if (artwork_manager != null)
                {
                    artwork_manager.ChangeCacheSize(ImageSize, GetAllAlbumsCount() + 3);
                }

                artwork_initialized = true;
            }

            bool is_queryalble_source = ServiceManager.SourceManager.ActiveSource is PrimarySource;

            is_queryalble_source = is_queryalble_source || ServiceManager.SourceManager.ActiveSource is PlaylistSource;
            is_queryalble_source = is_queryalble_source || ServiceManager.SourceManager.ActiveSource is SmartPlaylistSource;

            if (BoundObject == null)
            {
                return;
            }

            if (!(BoundObject is ArtistInfo))
            {
                throw new InvalidCastException("ColumnCellArtist can only bind to ArtistInfo objects");
            }
            var artist = (ArtistInfo)BoundObject;

            DatabaseArtistInfo db_artist = DatabaseArtistInfo.FindOrCreate(artist.Name, artist.NameSort);

            AlbumInfo[] albums      = GetAlbums(db_artist.DbId);
            int         album_count = albums.Length;

            string pattern = Catalog.GetString("All Artists ({0})")
                             .Replace("(", "\\(")
                             .Replace(")", "\\)")
                             .Replace("{0}", "[0-9]+");

            if (!String.IsNullOrEmpty(artist.Name) && System.Text.RegularExpressions.Regex.IsMatch(artist.Name, pattern))
            {
                album_count = GetAllAlbumsCount();
            }

            ImageSurface image  = null;
            var          images = new List <ImageSurface> ();

            int non_empty = 0;

            for (int i = 0; i < albums.Length && non_empty < 3; i++)
            {
                if (artwork_manager != null)
                {
                    ImageSurface sur = artwork_manager.LookupScaleSurface(albums [i].ArtworkId, image_size, true);
                    images.Add(sur);
                    if (sur != null)
                    {
                        non_empty++;
                    }
                }
            }

            //bringing non-empty images to the front
            images.Sort(delegate(ImageSurface a, ImageSurface b) {
                if (a == null && b != null)
                {
                    return(-1);
                }
                if (a != null && b == null)
                {
                    return(1);
                }
                return(0);
            });

            if (images.Count > 3)
            {
                images.RemoveRange(3, images.Count - 3);
            }

            bool is_default = false;

            if (images.Count == 0)
            {
                image      = default_cover_image;
                is_default = true;
            }
            else
            {
                image = images[images.Count - 1];
            }

            int image_render_size = image_size;
            int x = image_spacing;
            int y = image_spacing;

            if (use_small_images)
            {
                x = image_spacing / 2;
                y = image_spacing / 2;
            }

            const int y_image_spacing = 1;
            int       x_offset        = (use_small_images ? album_spacing_small : album_spacing_normal);

            if (images.Count > 1)
            {
                x_offset *= 2;
            }
            int y_offset = (images.Count > 1) ? y_image_spacing * 2 : y_image_spacing;

            for (int i = 0; i < images.Count - 1; i++)
            {
                int move_x = x + ((i) * (use_small_images ? album_spacing_small : album_spacing_normal));
                int move_y = y + ((i) * y_image_spacing);
                ArtworkRenderer.RenderThumbnail(context.Context, images[i], false, move_x, move_y,
                                                image_render_size, image_render_size, !is_default, context.Theme.Context.Radius, true, new Color(1.0, 1.0, 1.0, 1.0));
            }

            if (images.Count > 0)
            {
                ArtworkRenderer.RenderThumbnail(context.Context, image, false, x + x_offset, y + y_offset,
                                                image_render_size, image_render_size, !is_default, context.Theme.Context.Radius, true, new Color(1.0, 1.0, 1.0, 1.0));
            }
            else
            {
                ArtworkRenderer.RenderThumbnail(context.Context, image, false, x + x_offset, y + y_offset,
                                                image_render_size, image_render_size, !is_default, context.Theme.Context.Radius);
            }

            int fl_width = 0, fl_height = 0, sl_width = 0, sl_height = 0;

            context.Widget.StyleContext.Save();
            context.Widget.StyleContext.AddClass("entry");
            Color text_color = CairoExtensions.GdkRGBAToCairoColor(context.Widget.StyleContext.GetColor(context.State));

            context.Widget.StyleContext.Restore();
            text_color.A = 0.75;

            Pango.Layout layout = context.Layout;
            layout.Width     = (int)((cellWidth - cellHeight - x - 10) * Pango.Scale.PangoScale);
            layout.Ellipsize = Pango.EllipsizeMode.End;
            layout.FontDescription.Weight = Pango.Weight.Bold;

            // Compute the layout sizes for both lines for centering on the cell
            int old_size = layout.FontDescription.Size;

            layout.SetText(artist.DisplayName);
            layout.GetPixelSize(out fl_width, out fl_height);

            layout.FontDescription.Weight = Pango.Weight.Normal;
            layout.FontDescription.Size   = (int)(old_size * Pango.Scale.Small);
            layout.FontDescription.Style  = Pango.Style.Italic;

            string album_string_singular = Catalog.GetString("Album");
            string album_string_plural   = Catalog.GetString("Albums");

            layout.SetText(album_count + " " + ((album_count == 1) ? album_string_singular : album_string_plural));
            layout.GetPixelSize(out sl_width, out sl_height);

            // Calculate the layout positioning
            x = ((int)cellHeight - x) + (use_small_images ? album_spacing_small : album_spacing_normal) + 8;
            y = use_small_images ? (int)((cellHeight - (fl_height)) / 2) : (int)((cellHeight - (fl_height + sl_height)) / 2);

            // Render the second line first since we have that state already
            if (album_count > 0 && is_queryalble_source)
            {
                if (use_small_images)
                {
                    context.Context.MoveTo(cellWidth - sl_width - image_spacing, y + image_spacing / 2);
                }
                else
                {
                    context.Context.MoveTo(x, y + fl_height);
                }
                context.Context.SetSourceColor(text_color);
                if (!use_small_images || fl_width + x + sl_width <= cellWidth)
                {
                    Pango.CairoHelper.ShowLayout(context.Context, layout);
                }
            }

            // Render the first line, resetting the state
            layout.SetText(artist.DisplayName);
            layout.FontDescription.Weight = Pango.Weight.Bold;
            layout.FontDescription.Size   = old_size;
            layout.FontDescription.Style  = Pango.Style.Normal;

            layout.SetText(artist.DisplayName);

            context.Context.MoveTo(x, y);
            text_color.A = 1;
            context.Context.SetSourceColor(text_color);
            Pango.CairoHelper.ShowLayout(context.Context, layout);
        }