Inheritance: Gtk.Widget
Example #1
0
        public MessageBar() : base(0.0f, 0.5f, 1.0f, 0.0f)
        {
            win = new Window(WindowType.Popup)
            {
                Name = "gtk-tooltips"
            };
            win.EnsureStyle();
            win.StyleSet += delegate {
                Style = win.Style;
            };

            var shell_box = new HBox {
                Spacing = 10
            };

            box = new HBox {
                Spacing = 10
            };

            image = new AnimatedImage();
            try {
                image.Pixbuf      = Gtk.IconTheme.Default.LoadIcon("process-working", 22, IconLookupFlags.NoSvg);
                image.FrameHeight = 22;
                image.FrameWidth  = 22;
                Spinning          = false;
                image.Load();
            } catch {
            }

            label = new WrapLabel();
            label.Show();

            box.PackStart(image, false, false, 0);
            box.PackStart(label, true, true, 0);
            box.Show();

            button_box = new HBox {
                Spacing = 3
            };

            close_button = new Button(new Image(Stock.Close, IconSize.Menu))
            {
                Relief = ReliefStyle.None
            };
            close_button.Clicked += delegate { Hide(); };
            close_button.ShowAll();
            close_button.Hide();

            shell_box.PackStart(box, true, true, 0);
            shell_box.PackStart(button_box, false, false, 0);
            shell_box.PackStart(close_button, false, false, 0);
            shell_box.Show();

            Add(shell_box);

            EnsureStyle();

            BorderWidth = 3;
        }
Example #2
0
        public MessageBar () : base (0.0f, 0.5f, 1.0f, 0.0f)
        {
            win = new Window (WindowType.Popup);
            win.Name = "gtk-tooltips";
            win.EnsureStyle ();
            win.StyleSet += delegate {
                Style = win.Style;
            };

            HBox shell_box = new HBox ();
            shell_box.Spacing = 10;

            box = new HBox ();
            box.Spacing = 10;

            image = new AnimatedImage ();
            try {
                image.Pixbuf = Gtk.IconTheme.Default.LoadIcon ("process-working", 22, IconLookupFlags.NoSvg);
                image.FrameHeight = 22;
                image.FrameWidth = 22;
                Spinning = false;
                image.Load ();
            } catch {
            }

            label = new WrapLabel ();
            label.Show ();

            box.PackStart (image, false, false, 0);
            box.PackStart (label, true, true, 0);
            box.Show ();

            button_box = new HBox ();
            button_box.Spacing = 3;

            close_button = new Button (new Image (Stock.Close, IconSize.Menu));
            close_button.Relief = ReliefStyle.None;
            close_button.Clicked += delegate { Hide (); };
            close_button.ShowAll ();
            close_button.Hide ();

            shell_box.PackStart (box, true, true, 0);
            shell_box.PackStart (button_box, false, false, 0);
            shell_box.PackStart (close_button, false, false, 0);
            shell_box.Show ();

            Add (shell_box);

            EnsureStyle ();

            BorderWidth = 3;
        }
Example #3
0
        private void BuildWindow()
        {
            DefaultWidth = 475;

            BorderWidth = 6;
            ContentArea.Spacing = 12;
            ActionArea.Layout = Gtk.ButtonBoxStyle.End;

            HBox box = new HBox();
            box.BorderWidth = 6;
            box.Spacing = 12;

            Image image = new Image (IconThemeUtils.LoadIcon (48, "podcast"));

            image.Yalign = 0.0f;

            box.PackStart(image, false, true, 0);

            VBox contentBox = new VBox();
            contentBox.Spacing = 12;

            Label header = new Label();
            header.Markup = String.Format (
                "<big><b>{0}</b></big>",
                GLib.Markup.EscapeText (Catalog.GetString ("Subscribe to New Podcast"))
            );

            header.Justify = Justification.Left;
            header.SetAlignment (0.0f, 0.0f);

            var message = new WrapLabel () {
                Markup = Catalog.GetString (
                    "Please enter the URL of the podcast to which you would like to subscribe."
                ),
                Wrap = true
            };

            url_entry = new Entry ();
            url_entry.ActivatesDefault = true;

            // If the user has copied some text to the clipboard that starts with http, set
            // our url entry to it and select it
            Clipboard clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false));
            if (clipboard != null) {
                string pasted = clipboard.WaitForText ();
                if (!String.IsNullOrEmpty (pasted)) {
                    if (pasted.StartsWith ("http")) {
                        url_entry.Text = pasted.Trim ();
                        url_entry.SelectRegion (0, url_entry.Text.Length);
                    }
                }
            }

            contentBox.PackStart (header, true, true, 0);
            contentBox.PackStart (message, true, true, 0);

            var url_box = new HBox () { Spacing = 12 };
            url_box.PackStart (new Label (Catalog.GetString ("URL:")), false, false, 0);
            url_box.PackStart (url_entry, true, true, 0);
            contentBox.PackStart (url_box, false, false, 0);

            var options_label = new Label () {
                Markup = String.Format ("<b>{0}</b>", GLib.Markup.EscapeText (Catalog.GetString ("Subscription Options"))),
                Xalign = 0f
            };
            download_check = new CheckButton (Catalog.GetString ("Download new episodes"));
            archive_check = new CheckButton (Catalog.GetString ("Archive all episodes except the newest one"));
            var options_box = new VBox () { Spacing = 3 };
            options_box.PackStart (options_label, false, false, 0);
            options_box.PackStart (new Gtk.Alignment (0f, 0f, 0f, 0f) { LeftPadding = 12, Child = download_check }, false, false, 0);
            options_box.PackStart (new Gtk.Alignment (0f, 0f, 0f, 0f) { LeftPadding = 12, Child = archive_check }, false, false, 0);
            contentBox.PackStart (options_box, false, false, 0);

            box.PackStart (contentBox, true, true, 0);

            AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, true);
            AddButton (Catalog.GetString ("Subscribe"), ResponseType.Ok, true);

            box.ShowAll ();
            ContentArea.Add (box);
        }
Example #4
0
        private Widget BuildCenter()
        {
            var vbox = new VBox()
            {
                Spacing = 2
            };

            // Search entry/button
            var search_box = new HBox()
            {
                Spacing = 6, BorderWidth = 4
            };
            var entry = new SearchEntry()
            {
                Visible      = true,
                EmptyMessage = String.Format(Catalog.GetString("Search..."))
            };

            source.Properties.Set <SearchEntry> ("Nereid.SearchEntry", entry);

            // Make the search entry text nice and big
            var font = entry.StyleContext.GetFont(StateFlags.Normal).Copy();

            font.Size = (int)(font.Size * Pango.Scale.XLarge);
            entry.OverrideFont(font);
            font.Dispose();

            var button = new Hyena.Widgets.ImageButton(Catalog.GetString("_Go"), Stock.Find);

            entry.Activated += (o, a) => { button.Activate(); };
            button.Clicked  += (o, a) => source.SetSearch(new SearchDescription(null, entry.Query, IA.Sort.DownloadsDesc, null));

            search_box.PackStart(entry, true, true, 0);
            search_box.PackStart(button, false, false, 0);

            var example_searches = new SearchDescription [] {
                new SearchDescription(Catalog.GetString("Staff Picks"), "pick:1", IA.Sort.WeekDesc, null),
                new SearchDescription(Catalog.GetString("Creative Commons"), "license:creativecommons", IA.Sort.DownloadsDesc, null),
                new SearchDescription(Catalog.GetString("History"), "subject:history", IA.Sort.DownloadsDesc, null),
                new SearchDescription(Catalog.GetString("Classic Cartoons"), "", IA.Sort.DateCreatedAsc, IA.MediaType.Get("animationandcartoons")),
                new SearchDescription(Catalog.GetString("Speeches"), "subject:speeches OR title:speech", IA.Sort.DownloadsDesc, null),
                new SearchDescription(Catalog.GetString("For Children"), "subject:children", IA.Sort.DownloadsDesc, null),
                new SearchDescription(Catalog.GetString("Poetry"), "subject:poetry", IA.Sort.DownloadsDesc, null),
                new SearchDescription(Catalog.GetString("Creator is United States"), "creator:\"United States\"", IA.Sort.DownloadsDesc, null),
                new SearchDescription(Catalog.GetString("Old Movies"), "", IA.Sort.DateCreatedAsc, IA.MediaType.Get("moviesandfilms")),
                new SearchDescription(Catalog.GetString("New From LibriVox"), "publisher:LibriVox", IA.Sort.DateAddedDesc, IA.MediaType.Get("audio")),
                new SearchDescription(Catalog.GetString("Old Texts"), "", IA.Sort.DateCreatedAsc, IA.MediaType.Get("texts")),
                new SearchDescription(Catalog.GetString("Charlie Chaplin"), "\"Charlie Chaplin\"", IA.Sort.DownloadsDesc, null),
                new SearchDescription(Catalog.GetString("NASA"), "NASA", IA.Sort.DownloadsDesc, null),
                new SearchDescription(Catalog.GetString("Library of Congress"), "creator:\"Library of Congress\"", IA.Sort.DownloadsDesc, null)
            };

            var examples = new FlowBox()
            {
                Spacing = 0
            };

            examples.Add(PaddingBox(new Label()
            {
                Markup = Catalog.GetString("Examples:")
            }));

            foreach (var search in example_searches)
            {
                var this_search = search;
                var link        = CreateLink(search.Name, search.Query);
                link.TooltipText = search.Query;
                link.Clicked    += (o, a) => source.SetSearch(this_search);
                examples.Add(link);
            }

            // Intro text and visit button
            var intro_label = new Hyena.Widgets.WrapLabel()
            {
                Markup = Catalog.GetString("The Internet Archive, a 501(c)(3) non-profit, is building a digital library of Internet sites and other cultural artifacts in digital form. Like a paper library, we provide free access to researchers, historians, scholars, and the general public.")
            };

            var visit_button = new LinkButton("http://archive.org/", Catalog.GetString("Visit the Internet Archive online at archive.org"));

            visit_button.Clicked += (o, a) => Banshee.Web.Browser.Open("http://archive.org/");
            visit_button.Xalign   = 0f;
            var visit_box = new HBox();

            visit_box.PackStart(visit_button, false, false, 0);
            visit_box.PackStart(new Label()
            {
                Visible = true
            }, true, true, 0);

            // Packing
            vbox.PackStart(search_box, false, false, 0);
            vbox.PackStart(examples, false, false, 0);
            vbox.PackStart(PaddingBox(new HSeparator()), false, false, 6);
            vbox.PackStart(PaddingBox(intro_label), false, false, 0);
            vbox.PackStart(visit_box, false, false, 0);

            return(vbox);
        }
Example #5
0
        private Widget BuildCenter ()
        {
            var vbox = new VBox () { Spacing = 2 };

            // Search entry/button
            var search_box = new HBox () { Spacing = 6, BorderWidth = 4 };
            var entry = new SearchEntry () {
                Visible = true,
                EmptyMessage = String.Format (Catalog.GetString ("Search..."))
            };

            source.Properties.Set<SearchEntry> ("Nereid.SearchEntry", entry);

            // Make the search entry text nice and big
            var font = entry.InnerEntry.Style.FontDescription.Copy ();
            font.Size = (int) (font.Size * Pango.Scale.XLarge);
            entry.InnerEntry.ModifyFont (font);
            font.Dispose ();

            var button = new Hyena.Widgets.ImageButton (Catalog.GetString ("_Go"), Stock.Find);
            entry.Activated += (o, a) => { button.Activate (); };
            button.Clicked += (o, a) => source.SetSearch (new SearchDescription (null, entry.Query, IA.Sort.DownloadsDesc, null));

            search_box.PackStart (entry, true, true, 0);
            search_box.PackStart (button, false, false, 0);

            var example_searches = new SearchDescription [] {
                new SearchDescription (Catalog.GetString ("Staff Picks"), "pick:1", IA.Sort.WeekDesc, null),
                new SearchDescription (Catalog.GetString ("Creative Commons"), "license:creativecommons", IA.Sort.DownloadsDesc, null),
                new SearchDescription (Catalog.GetString ("History"), "subject:history", IA.Sort.DownloadsDesc, null),
                new SearchDescription (Catalog.GetString ("Classic Cartoons"), "", IA.Sort.DateCreatedAsc, IA.MediaType.Get ("animationandcartoons")),
                new SearchDescription (Catalog.GetString ("Speeches"), "subject:speeches OR title:speech", IA.Sort.DownloadsDesc, null),
                new SearchDescription (Catalog.GetString ("For Children"), "subject:children", IA.Sort.DownloadsDesc, null),
                new SearchDescription (Catalog.GetString ("Poetry"), "subject:poetry", IA.Sort.DownloadsDesc, null),
                new SearchDescription (Catalog.GetString ("Creator is United States"), "creator:\"United States\"", IA.Sort.DownloadsDesc, null),
                new SearchDescription (Catalog.GetString ("Old Movies"), "", IA.Sort.DateCreatedAsc, IA.MediaType.Get ("moviesandfilms")),
                new SearchDescription (Catalog.GetString ("New From LibriVox"), "publisher:LibriVox", IA.Sort.DateAddedDesc, IA.MediaType.Get ("audio")),
                new SearchDescription (Catalog.GetString ("Old Texts"), "", IA.Sort.DateCreatedAsc, IA.MediaType.Get ("texts")),
                new SearchDescription (Catalog.GetString ("Charlie Chaplin"), "\"Charlie Chaplin\"", IA.Sort.DownloadsDesc, null),
                new SearchDescription (Catalog.GetString ("NASA"), "NASA", IA.Sort.DownloadsDesc, null),
                new SearchDescription (Catalog.GetString ("Library of Congress"), "creator:\"Library of Congress\"", IA.Sort.DownloadsDesc, null)
            };

            var examples = new FlowBox () { Spacing = 0 };
            examples.Add (PaddingBox (new Label () { Markup = "Examples:" }));

            foreach (var search in example_searches) {
                var this_search = search;
                var link = CreateLink (search.Name, search.Query);
                link.TooltipText = search.Query;
                link.Clicked += (o, a) => source.SetSearch (this_search);
                examples.Add (link);
            }

            // Intro text and visit button
            var intro_label = new Hyena.Widgets.WrapLabel () {
                Markup = Catalog.GetString ("The Internet Archive, a 501(c)(3) non-profit, is building a digital library of Internet sites and other cultural artifacts in digital form. Like a paper library, we provide free access to researchers, historians, scholars, and the general public.")
            };

            var visit_button = new LinkButton ("http://archive.org/", Catalog.GetString ("Visit the Internet Archive online at archive.org"));
            visit_button.Clicked += (o, a) => Banshee.Web.Browser.Open ("http://archive.org/");
            visit_button.Xalign = 0f;
            var visit_box = new HBox ();
            visit_box.PackStart (visit_button, false, false, 0);
            visit_box.PackStart (new Label () { Visible = true }, true, true, 0);

            // Packing
            vbox.PackStart (search_box, false, false, 0);
            vbox.PackStart (examples, false, false, 0);
            vbox.PackStart (PaddingBox (new HSeparator ()), false, false, 6);
            vbox.PackStart (PaddingBox (intro_label), false, false, 0);
            vbox.PackStart (visit_box, false, false, 0);

            return vbox;
        }
        private void BuildWidgets ()
        {
            var hbox = new HBox () { Spacing = 12 };

            // Left box - cover art, title, etc
            var left_box = new VBox () { BorderWidth = 12, Spacing = 12 };

            // Cover art
            cover = new BookCover (this) {
                WidthRequest = 300,
                HeightRequest = 300
            };

            var editable_cover = CoverArtEditor.For (
                cover, (x, y) => true,
                () => library.TrackModel[0],
                UpdateCover
            );

            // Title
            title_label = new WrapLabel ();

            resume_button = new ImageButton ("", null, IconSize.LargeToolbar);
            resume_button.ImageWidget.Stock = Stock.MediaPlay;
            resume_button.LabelWidget.Xalign = 0;
            resume_button.Spacing = 6;

            // FIXME the left padding on this is not right
            rating_entry = new RatingEntry () {
                AlwaysShowEmptyStars = true,
                HasFrame = false
            };
            var rating = new HBox ();
            rating.PackStart (rating_entry, false, false, 0);

            // Packing
            left_box.PackStart (editable_cover, false, false,  0);
            left_box.PackStart (title_label, false, false,  0);
            left_box.PackStart (resume_button, false, false,  0);
            //left_box.PackStart (rating, false, false,  0);

            hbox.PackStart (left_box, false, false, 0);

            // Right box - track list
            track_list = new BaseTrackListView () {
                HeaderVisible = true,
                IsEverReorderable = false
            };

            var columns = new DefaultColumnController ();
            var file_columns = new ColumnController ();
            var disc_column = DefaultColumnController.Create (
                    BansheeQuery.DiscNumberField, 0.02, false, new ColumnCellPositiveInt (null, false, 2, 2));

            file_columns.AddRange (
                columns.IndicatorColumn,
                disc_column,
                columns.TitleColumn,
                columns.DurationColumn
            );
            file_columns.SortColumn = columns.DiscNumberAndCountColumn;

            foreach (var col in file_columns) {
                col.Visible = true;
            }

            var track_sw = new Gtk.ScrolledWindow () {
                Child = track_list,
                ShadowType = ShadowType.None
            };

            track_list.ColumnController = file_columns;

            hbox.PackEnd (track_sw, true, true, 0);

            Child = hbox;
        }
        private void BuildWindow ()
        {
            DefaultWidth = 475;

            BorderWidth = 6;
            VBox.Spacing = 12;
            ActionArea.Layout = Gtk.ButtonBoxStyle.End;

            HBox box = new HBox();
            box.BorderWidth = 6;
            box.Spacing = 12;

            Image image = new Image (IconThemeUtils.LoadIcon (48, "podcast"));

            image.Yalign = 0.0f;

            box.PackStart(image, false, true, 0);

            VBox contentBox = new VBox();
            contentBox.Spacing = 12;

            Label header = new Label();
            header.Markup = String.Format (
                "<big><b>{0}</b></big>",
                GLib.Markup.EscapeText (Catalog.GetString ("Subscribe to New Podcast"))
            );

            header.Justify = Justification.Left;
            header.SetAlignment (0.0f, 0.0f);

            WrapLabel message = new WrapLabel ();
            message.Markup = Catalog.GetString (
                "Please enter the URL of the podcast to which you would like to subscribe."
            );

            message.Wrap = true;

            VBox sync_vbox = new VBox ();

            VBox expander_children = new VBox();
            //expander_children.BorderWidth = 6;
            expander_children.Spacing = 6;

            Label sync_text = new Label (
                Catalog.GetString ("When new episodes are available:  ")
            );

            sync_text.SetAlignment (0.0f, 0.0f);
            sync_text.Justify = Justification.Left;

            syncCombo = new SyncPreferenceComboBox ();

            expander_children.PackStart (sync_text, true, true, 0);
            expander_children.PackStart (syncCombo, true, true, 0);

            sync_vbox.Add (expander_children);

            url_entry = new Entry ();
            url_entry.ActivatesDefault = true;

            // If the user has copied some text to the clipboard that starts with http, set
            // our url entry to it and select it
            Clipboard clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false));
            if (clipboard != null) {
                string pasted = clipboard.WaitForText ();
                if (!String.IsNullOrEmpty (pasted)) {
                    if (pasted.StartsWith ("http")) {
                        url_entry.Text = pasted.Trim ();
                        url_entry.SelectRegion (0, url_entry.Text.Length);
                    }
                }
            }

            Table table = new Table (1, 2, false);
            table.RowSpacing = 6;
            table.ColumnSpacing = 12;

            table.Attach (
                new Label (Catalog.GetString ("URL:")), 0, 1, 0, 1,
                AttachOptions.Shrink, AttachOptions.Shrink, 0, 0
            );

            table.Attach (
                url_entry, 1, 2, 0, 1,
                AttachOptions.Expand | AttachOptions.Fill,
                AttachOptions.Shrink, 0, 0
            );

            table.Attach (
                sync_vbox, 0, 2, 1, 2,
                AttachOptions.Expand | AttachOptions.Fill,
                AttachOptions.Shrink, 0, 0
            );

            contentBox.PackStart (header, true, true, 0);
            contentBox.PackStart (message, true, true, 0);

            contentBox.PackStart (table, true, true, 0);

            box.PackStart (contentBox, true, true, 0);

            AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, true);
            AddButton (Catalog.GetString ("Subscribe"), ResponseType.Ok, true);

            box.ShowAll ();
            VBox.Add (box);
        }
Example #8
0
        private void BuildInfoBox()
        {
            var frame = new Hyena.Widgets.RoundedFrame();
            var vbox  = new VBox();

            vbox.Spacing     = 6;
            vbox.BorderWidth = 2;

            // Description
            var desc = new Hyena.Widgets.WrapLabel()
            {
                Markup = String.Format("{0}", GLib.Markup.EscapeText(Hyena.StringUtil.RemoveHtml(details.Description)))
            };

            var desc_expander = CreateSection(Catalog.GetString("Description"), desc);

            // Details
            var table = new Banshee.Gui.TrackEditor.StatisticsPage()
            {
                ShadowType  = ShadowType.None,
                BorderWidth = 0
            };

            table.NameRenderer.Scale  = Pango.Scale.Medium;
            table.ValueRenderer.Scale = Pango.Scale.Medium;

            // Keep the table from needing to vertically scroll

            /*table.Child.SizeRequested += (o, a) => {
             *  table.SetSizeRequest (a.Requisition.Width, a.Requisition.Height);
             * };*/

            AddToTable(table, Catalog.GetString("Creator:"), details.Creator);
            AddToTable(table, Catalog.GetString("Venue:"), details.Venue);
            AddToTable(table, Catalog.GetString("Location:"), details.Coverage);
            if (details.DateCreated != DateTime.MinValue)
            {
                AddToTable(table, Catalog.GetString("Date:"), details.DateCreated);
            }
            else
            {
                AddToTable(table, Catalog.GetString("Year:"), details.Year);
            }
            AddToTable(table, Catalog.GetString("Publisher:"), details.Publisher);
            AddToTable(table, Catalog.GetString("Keywords:"), details.Subject);
            AddToTable(table, Catalog.GetString("License URL:"), details.LicenseUrl);
            AddToTable(table, Catalog.GetString("Language:"), details.Language);

            table.AddSeparator();

            AddToTable(table, Catalog.GetString("Downloads, overall:"), details.DownloadsAllTime);
            AddToTable(table, Catalog.GetString("Downloads, past month:"), details.DownloadsLastMonth);
            AddToTable(table, Catalog.GetString("Downloads, past week:"), details.DownloadsLastWeek);

            table.AddSeparator();

            AddToTable(table, Catalog.GetString("Added:"), details.DateAdded);
            AddToTable(table, Catalog.GetString("Added by:"), details.AddedBy);
            AddToTable(table, Catalog.GetString("Collections:"), details.Collections);
            AddToTable(table, Catalog.GetString("Source:"), details.Source);
            AddToTable(table, Catalog.GetString("Contributor:"), details.Contributor);
            AddToTable(table, Catalog.GetString("Recorded by:"), details.Taper);
            AddToTable(table, Catalog.GetString("Lineage:"), details.Lineage);
            AddToTable(table, Catalog.GetString("Transferred by:"), details.Transferer);

            var details_expander = CreateSection(Catalog.GetString("Details"), table);

            // Reviews
            Section reviews = null;

            if (details.NumReviews > 0)
            {
                string [] stars =
                {
                    "\u2606\u2606\u2606\u2606\u2606",
                    "\u2605\u2606\u2606\u2606\u2606",
                    "\u2605\u2605\u2606\u2606\u2606",
                    "\u2605\u2605\u2605\u2606\u2606",
                    "\u2605\u2605\u2605\u2605\u2606",
                    "\u2605\u2605\u2605\u2605\u2605"
                };

                var reviews_box = new VBox()
                {
                    Spacing = 12, BorderWidth = 0
                };
                reviews = CreateSection(Catalog.GetString("Reviews"), reviews_box);

                var avg_label = new Label(String.Format(Catalog.GetPluralString(
                                                            // Translators: {0} is the number of reviewers, {1} is the average rating (not really relevant if there's only 1)
                                                            "{0} reviewer", "{0} reviewers, avg {1}", details.NumReviews),
                                                        details.NumReviews, stars[Math.Max(0, Math.Min(5, (int)Math.Round(details.AvgRating)))]
                                                        ));
                avg_label.TooltipText = String.Format("{0:N2}", details.AvgRating);
                avg_label.Xalign      = 1.0f;
                reviews.Header.Box.PackEnd(avg_label, false, false, 0);

                var sb = new System.Text.StringBuilder();
                foreach (var review in details.Reviews)
                {
                    //sb.Append ("<small>");

                    var review_txt = new Hyena.Widgets.WrapLabel();

                    var title = review.Title;
                    if (title != null)
                    {
                        sb.AppendFormat("<b>{0}</b>\n", GLib.Markup.EscapeText(title));
                    }

                    // Translators: {0} is the unicode-stars-rating, {1} is the name of a person who reviewed this item, and {1} is a date/time string
                    sb.AppendFormat(Catalog.GetString("{0} by {1} on {2}"),
                                    stars[Math.Max(0, Math.Min(5, review.Stars))],
                                    GLib.Markup.EscapeText(review.Reviewer),
                                    GLib.Markup.EscapeText(review.DateReviewed.ToLocalTime().ToShortDateString())
                                    );

                    var body = review.Body;
                    if (body != null)
                    {
                        body = body.Replace("\r\n", "\n");
                        body = body.Replace("\n\n", "\n");
                        sb.Append("\n");
                        sb.Append(GLib.Markup.EscapeText(body));
                    }

                    //sb.Append ("</small>");
                    review_txt.Markup = sb.ToString();
                    sb.Length         = 0;

                    reviews_box.PackStart(review_txt, false, false, 0);
                }
            }

            // Packing
            vbox.PackStart(desc_expander, true, true, 0);
            vbox.PackStart(details_expander, true, true, 0);
            if (reviews != null)
            {
                vbox.PackStart(reviews, true, true, 0);
            }

            string write_review_url    = String.Format("http://www.archive.org/write-review.php?identifier={0}", item.Id);
            var    write_review_button = new LinkButton(write_review_url, Catalog.GetString("Write your own review"));

            write_review_button.Clicked += (o, a) => Banshee.Web.Browser.Open(write_review_url);
            write_review_button.Xalign   = 0f;
            vbox.PackStart(write_review_button, false, false, 0);

            var vbox2 = new VBox();

            vbox2.PackStart(vbox, false, false, 0);

            var sw = new Gtk.ScrolledWindow()
            {
                ShadowType = ShadowType.None
            };

            sw.AddWithViewport(vbox2);
            (sw.Child as Viewport).ShadowType = ShadowType.None;
            frame.Child = sw;
            frame.ShowAll();

            sw.Child.OverrideBackgroundColor(StateFlags.Normal, StyleContext.GetBackgroundColor(StateFlags.Normal));
            sw.Child.OverrideColor(StateFlags.Normal, StyleContext.GetColor(StateFlags.Normal));
            StyleUpdated += delegate {
                sw.Child.OverrideBackgroundColor(StateFlags.Normal, StyleContext.GetBackgroundColor(StateFlags.Normal));
                sw.Child.OverrideColor(StateFlags.Normal, StyleContext.GetColor(StateFlags.Normal));
            };

            PackStart(frame, true, true, 0);
        }