[banshee] [MeeGo] Another major panel UI overhaul



commit 7f40bbea0b833cbc14a71cf88cd3edebf8e2005b
Author: Aaron Bockover <abockover novell com>
Date:   Fri Apr 9 20:21:58 2010 -0400

    [MeeGo] Another major panel UI overhaul
    
    The panel has been updated (again) to reflect the latest MeeGo
    look and feel, and better organize some of the features.
    
    MediaPanelContents and MeeGoSourceContents were merged and cleaned
    up a bit as well, so it's easier on my coding eyes.

 src/Extensions/Banshee.MeeGo/Banshee.MeeGo.csproj  |    3 +-
 .../Banshee.MeeGo/MediaPanelContents.cs            |  351 ++++++++++++++++----
 .../Banshee.MeeGo/Banshee.MeeGo/MeeGoPanel.cs      |    9 +-
 .../Banshee.MeeGo/MeeGoSourceContents.cs           |  211 ------------
 .../Banshee.MeeGo/MeeGoTrackInfoDisplay.cs         |    4 +
 .../Banshee.MeeGo/Banshee.MeeGo/PlaybackBox.cs     |   22 +-
 .../Banshee.MeeGo/Banshee.MeeGo/SearchEntry.cs     |    4 +
 src/Extensions/Banshee.MeeGo/Makefile.am           |    3 +-
 8 files changed, 316 insertions(+), 291 deletions(-)
---
diff --git a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo.csproj b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo.csproj
index f6c29e1..4562837 100644
--- a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo.csproj
+++ b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo.csproj
@@ -91,6 +91,7 @@
     <Compile Include="Banshee.MeeGo\PlaybackBox.cs" />
     <Compile Include="Banshee.MeeGo\MeeGoTrackInfoDisplay.cs" />
     <Compile Include="Banshee.MeeGo\MeeGoPanel.cs" />
-    <Compile Include="Banshee.MeeGo\MeeGoSourceContents.cs" />
+    <Compile Include="Banshee.MeeGo\MeeGoTheme.cs" />
+    <Compile Include="Banshee.MeeGo\MeeGoHeaderBox.cs" />
   </ItemGroup>
 </Project>
diff --git a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MediaPanelContents.cs b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MediaPanelContents.cs
index d96a643..67b3fb1 100644
--- a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MediaPanelContents.cs
+++ b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MediaPanelContents.cs
@@ -1,21 +1,21 @@
 //
 // MediaPanelContents.cs
-//
+// 
 // Author:
 //   Aaron Bockover <abockover novell com>
-//
-// Copyright 2009-2010 Novell, Inc.
-//
+// 
+// Copyright 2010 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
@@ -25,12 +25,13 @@
 // THE SOFTWARE.
 
 using System;
-using Gtk;
-using Mono.Unix;
+using System.Collections.Generic;
 
-// using Banshee.PlayQueue;
+using Mono.Unix;
+using Gtk;
 
 using Hyena;
+using Hyena.Data;
 using Hyena.Gui;
 using Hyena.Data.Gui;
 
@@ -39,69 +40,225 @@ using Banshee.Sources;
 using Banshee.Sources.Gui;
 using Banshee.Collection;
 using Banshee.Collection.Gui;
-using Banshee.Collection.Database;
+using Banshee.MediaEngine;
+using Banshee.Gui.Widgets;
 
 namespace Banshee.MeeGo
 {
-    public class MediaPanelContents : VBox
+    public class MediaPanelContents : Table, ITrackModelSourceContents
     {
+        private ArtistListView artist_view;
+        private AlbumListView album_view;
+        private TerseTrackListView track_view;
+
         private SourceComboBox source_combo_box;
-        private HBox header_box;
         private SearchEntry search_entry;
-        private MeeGoSourceContents source_contents;
+        private MeeGoTrackInfoDisplay track_info_display;
+
+        private ISource source;
+        private Dictionary<object, double> model_positions = new Dictionary<object, double> ();
 
-        public MediaPanelContents ()
+        protected MediaPanelContents (IntPtr raw) : base (raw)
         {
-            BorderWidth = 12;
-            Spacing = 12;
+        }
 
-            var header_label = new Label {
-                Markup = String.Format ("<span font_desc=\"Droid Bold\" size=\"22000\" foreground=\"#606eff\">{0}</span>",
-                    GLib.Markup.EscapeText (Catalog.GetString ("Media"))),
-                Xalign = 0.0f
-            };
+        public MediaPanelContents () : base (2, 2, false)
+        {
+            BorderWidth = 5;
+            RowSpacing = 6;
+            ColumnSpacing = 7;
+            RedrawOnAllocate = true;
+            AppPaintable = true;
+
+            BuildHeader ();
+            BuildLibrary ();
+            BuildNowPlaying ();
+            ConnectEvents ();
+
+            SetSource (ServiceManager.SourceManager.ActiveSource);
+        }
+
+        private void ConnectEvents ()
+        {
+            ServiceManager.SourceManager.ActiveSourceChanged += OnActiveSourceChanged;
 
-            PackStart (header_label, false, false, 0);
+            ServiceManager.PlayerEngine.ConnectEvent ((args) => track_info_display.Visible =
+                ServiceManager.PlayerEngine.CurrentState != PlayerState.Idle,
+                PlayerEvent.StateChange | PlayerEvent.StartOfStream);
+
+            source_combo_box.Model.Filter = (source) =>
+                source == ServiceManager.SourceManager.MusicLibrary ||
+                source.Parent == ServiceManager.SourceManager.MusicLibrary ||
+                source.GetType ().FullName == "Banshee.PlayQueue.PlayQueueSource";
+            source_combo_box.Model.Refresh ();
+            source_combo_box.UpdateActiveSource ();
+
+            search_entry.Changed += OnSearchEntryChanged;
+
+            artist_view.SelectionProxy.Changed += OnBrowserViewSelectionChanged;
+            album_view.SelectionProxy.Changed += OnBrowserViewSelectionChanged;
+        }
+
+#region UI Construction
+
+        private void BuildHeader ()
+        {
+            Attach (new Label {
+                    Markup = String.Format ("<span font_desc=\"Droid Sans Bold\" " +
+                        "size=\"x-large\" foreground=\"#606eff\">{0}</span>",
+                        GLib.Markup.EscapeText (Catalog.GetString ("Media"))),
+                    Xalign = 0.0f
+                },
+                0, 2, 0, 1,
+                AttachOptions.Fill | AttachOptions.Expand,
+                AttachOptions.Shrink, 10, 0);
+        }
+
+        private void BuildLibrary ()
+        {
+            var box = new MeeGoHeaderBox () { Title = Catalog.GetString ("Library") };
 
-            header_box = new HBox () {
+            // Build the Library Header
+            var header = new HBox () {
                 Spacing = 5,
                 BorderWidth = 5
             };
 
-            header_box.PackStart (source_combo_box = new SourceComboBox (), false, false, 0);
-
-            var button = new Button (new Image () {
+            var app_button = new Button (new Image () {
                 IconSize = (int)IconSize.LargeToolbar,
                 IconName = "media-player-banshee"
             }) {
                 TooltipText = Catalog.GetString ("Launch the Banshee Media Player")
             };
-
-            button.Clicked += (o, e) => {
+            app_button.Clicked += (o, e) => {
                 ServiceManager.SourceManager.SetActiveSource (ServiceManager.SourceManager.MusicLibrary);
                 ServiceManager.Get<MeeGoService> ().PresentPrimaryInterface ();
             };
 
-            header_box.PackStart (button, false, false, 0);
-            header_box.PackStart (search_entry = new SearchEntry (), true, true, 0);
-            header_box.PackStart (new PlaybackBox (), false, false, 0);
+            header.PackStart (source_combo_box = new SourceComboBox (), false, false, 0);
+            header.PackStart (app_button, false, false, 0);
+            header.PackStart (search_entry = new SearchEntry (), true, true, 0);
+            box.PackStartHighlighted (header, false, false, 0, MeeGoHeaderBox.HighlightFlags.Background);
+
+            // Build the Library Views
+            var views = new HBox () { Spacing = 10 };
+            views.PackStart (SetupView (artist_view = new ArtistListView () {
+                    Name = "meego-panel-artists",
+                    WidthRequest = 150,
+                    DoNotRenderNullModel = true
+                }), false, false, 0);
+            views.PackStart (SetupView (album_view = new AlbumListView () {
+                    Name = "meego-panel-albums",
+                    DoNotRenderNullModel = true
+                }), true, true, 0);
+            box.PackStart (views, true, true, 0);
+
+            Attach (box, 0, 1, 1, 2,
+                AttachOptions.Expand | AttachOptions.Fill,
+                AttachOptions.Expand | AttachOptions.Fill,
+                0, 0);
+        }
 
-            PackStart (header_box, false, false, 0);
-            PackStart (source_contents = new MeeGoSourceContents (), true, true, 0);
+        private void BuildNowPlaying ()
+        {
+            var box = new MeeGoHeaderBox () { Title = Catalog.GetString ("Now Playing") };
 
-            ShowAll ();
+            var seek_slider = new ConnectedSeekSlider (SeekSliderLayout.Horizontal);
+            seek_slider.StreamPositionLabel.FormatString = "<small>{0}</small>";
 
-            source_combo_box.Model.Filter = (source) =>
-                source == ServiceManager.SourceManager.MusicLibrary ||
-                source.Parent == ServiceManager.SourceManager.MusicLibrary ||
-                source.GetType ().FullName == "Banshee.PlayQueue.PlayQueueSource";
-            source_combo_box.Model.Refresh ();
-            source_combo_box.UpdateActiveSource ();
+            track_info_display = new MeeGoTrackInfoDisplay () {
+                HeightRequest = 64,
+                NoShowAll = true
+            };
 
-            search_entry.Changed += OnSearchEntryChanged;
+            track_view = new TerseTrackListView () {
+                Name = "meego-panel-tracks",
+                WidthRequest = 220
+            };
+            track_view.ColumnController.Insert (new Column (null, "indicator",
+                new ColumnCellStatusIndicator (null), 0.05, true, 20, 20), 0);
+
+            box.PackStartHighlighted (track_info_display, false, false, 0, MeeGoHeaderBox.HighlightFlags.Background);
+            box.PackStartHighlighted (seek_slider, false, false, 0, MeeGoHeaderBox.HighlightFlags.Background);
+            box.PackStart (SetupView (track_view), true, true, 0);
+            box.PackStartHighlighted (new PlaybackBox (), false, false, 0, MeeGoHeaderBox.HighlightFlags.TopLine);
+
+            Attach (box, 1, 2, 1, 2,
+                AttachOptions.Shrink,
+                AttachOptions.Expand | AttachOptions.Fill,
+                0, 0);
+        }
 
-            source_contents.SetSource (ServiceManager.SourceManager.ActiveSource);
-            ServiceManager.SourceManager.ActiveSourceChanged += OnActiveSourceChanged;
+        private ScrolledWindow SetupView (Widget view)
+        {
+            var scrolled = new ScrolledWindow () {
+                VscrollbarPolicy = PolicyType.Automatic,
+                HscrollbarPolicy = PolicyType.Never,
+                ShadowType = ShadowType.None
+            };
+            scrolled.Add (view);
+            return scrolled;
+        }
+
+#endregion
+
+#region Background Rendering
+
+        protected override void OnParentSet (Widget previous)
+        {
+            base.OnParentSet (previous);
+
+            if (Parent != null) {
+                Parent.ModifyBg (StateType.Normal, Style.White);
+            }
+        }
+
+        protected override bool OnExposeEvent (Gdk.EventExpose evnt)
+        {
+            if (!Visible || !IsMapped) {
+                return true;
+            }
+
+            RenderBackground (evnt.Window, evnt.Region);
+            foreach (var child in Children) {
+                PropagateExpose (child, evnt);
+            }
+
+            return true;
+        }
+
+        private void RenderBackground (Gdk.Window window, Gdk.Region region)
+        {
+            var cr = Gdk.CairoHelper.Create (window);
+
+            var grad = new Cairo.LinearGradient (0, 0, 0, Allocation.Height);
+            grad.AddColorStop (0, CairoExtensions.RgbToColor (0xffffff));
+            grad.AddColorStop (1, CairoExtensions.RgbToColor (0xc3c3c3));
+            cr.Pattern = grad;
+            cr.Rectangle (0, 0, Allocation.Width, Allocation.Height);
+            cr.Fill ();
+            grad.Destroy ();
+
+            CairoExtensions.DisposeContext (cr);
+        }
+
+#endregion
+
+#region Event Handlers
+
+        private void OnBrowserViewSelectionChanged (object o, EventArgs args)
+        {
+            // Scroll the raising filter view to the top if "all" is selected
+            var selection = (Hyena.Collections.Selection)o;
+            if (!selection.AllSelected) {
+                return;
+            }
+
+            if (artist_view.Selection == selection) {
+                artist_view.ScrollTo (0);
+            } else if (album_view.Selection == selection) {
+                album_view.ScrollTo (0);
+            }
         }
 
         private void OnSearchEntryChanged (object o, EventArgs args)
@@ -129,52 +286,110 @@ namespace Banshee.MeeGo
                     search_entry.ActivateFilter ((int)source.FilterType);
                 }
 
-                source_contents.ResetSource ();
-                source_contents.SetSource (source);
+                ResetSource ();
+                SetSource (source);
 
                 search_entry.Ready = true;
             });
         }
 
-        protected override void OnParentSet (Widget previous)
+#endregion
+
+#region View<->Model binding
+
+        private void SetModel<T> (IListModel<T> model)
         {
-            base.OnParentSet (previous);
+            ListView<T> view = FindListView <T> ();
+            if (view != null) {
+                SetModel (view, model);
+            } else {
+                Hyena.Log.DebugFormat ("Unable to find view for model {0}", model);
+            }
+        }
 
-            if (Parent != null) {
-                Parent.ModifyBg (StateType.Normal, Style.White);
+        private void SetModel<T> (ListView<T> view, IListModel<T> model)
+        {
+            if (view.Model != null) {
+                model_positions[view.Model] = view.Vadjustment.Value;
             }
+
+            if (model == null) {
+                view.SetModel (null);
+                return;
+            }
+
+            if (!model_positions.ContainsKey (model)) {
+                model_positions[model] = 0.0;
+            }
+
+            view.SetModel (model, model_positions[model]);
         }
 
-        protected override bool OnExposeEvent (Gdk.EventExpose evnt)
+        private ListView<T> FindListView<T> ()
         {
-            if (!Visible || !IsMapped) {
-                return true;
+            foreach (var view in new IListView [] { artist_view, album_view, track_view }) {
+                if (view is ListView<T>) {
+                    return (ListView<T>)view;
+                }
             }
+            return null;
+        }
 
-            RenderBackground (evnt.Window, evnt.Region);
-            foreach (var child in Children) {
-                PropagateExpose (child, evnt);
+#endregion
+
+#region ISourceContents
+
+        public bool SetSource (ISource source)
+        {
+            var track_source = source as ITrackModelSource;
+            var filterable_source = source as IFilterableSource;
+            if (track_source == null) {
+                return false;
+            }
+
+            this.source = source;
+
+            SetModel (track_view, track_source.TrackModel);
+
+            if (filterable_source != null && filterable_source.CurrentFilters != null) {
+                foreach (var model in filterable_source.CurrentFilters) {
+                    if (model is IListModel<ArtistInfo>) {
+                        SetModel (artist_view, (model as IListModel<ArtistInfo>));
+                    } else if (model is IListModel<AlbumInfo>) {
+                        SetModel (album_view, (model as IListModel<AlbumInfo>));
+                    }
+                }
             }
 
             return true;
         }
 
-        private void RenderBackground (Gdk.Window window, Gdk.Region region)
+        public void ResetSource ()
         {
-            var cr = Gdk.CairoHelper.Create (window);
-            cr.Color = new Cairo.Color (0xe7 / (double)0xff,
-                0xea / (double)0xff, 0xfd / (double)0xff);
+            source = null;
+            SetModel (track_view, null);
+            SetModel (artist_view, null);
+            SetModel (album_view, null);
+            track_view.HeaderVisible = false;
+        }
 
-            CairoExtensions.RoundedRectangle (cr,
-                header_box.Allocation.X,
-                header_box.Allocation.Y,
-                header_box.Allocation.Width,
-                header_box.Allocation.Height,
-                5);
+        public ISource Source {
+            get { return source; }
+        }
 
-            cr.Fill ();
+        public Widget Widget {
+            get { return this; }
+        }
 
-            CairoExtensions.DisposeContext (cr);
+#endregion
+
+#region ITrackModelSourceContents
+
+        public IListView<TrackInfo> TrackView {
+            get { return track_view; }
         }
+
+#endregion
+
     }
-}
+}
\ No newline at end of file
diff --git a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MeeGoPanel.cs b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MeeGoPanel.cs
index efd3daf..2f0401e 100644
--- a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MeeGoPanel.cs
+++ b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MeeGoPanel.cs
@@ -31,6 +31,7 @@ using MeeGo.Panel;
 
 using Hyena;
 using Banshee.Base;
+using Banshee.ServiceStack;
 
 namespace Banshee.MeeGo
 {
@@ -53,13 +54,17 @@ namespace Banshee.MeeGo
             Instance = this;
             Enabled = true;
 
+            Hyena.Gui.Theming.ThemeEngine.SetCurrentTheme<MeeGoTheme> ();
+
             var timer = Log.DebugTimerStart ();
 
             try {
                 Log.Debug ("Attempting to create MeeGo toolbar panel");
                 embedded_panel = new PanelGtk ("banshee", "media", null, "media-button", true);
-                while (Application.EventsPending ()) {
-                    Application.RunIteration ();
+                embedded_panel.ShowBeginEvent += (o, e) =>
+                    ServiceManager.SourceManager.SetActiveSource (ServiceManager.SourceManager.MusicLibrary);
+                while (Gtk.Application.EventsPending ()) {
+                    Gtk.Application.RunIteration ();
                 }
             } catch (Exception e) {
                 if (!(e is DllNotFoundException)) {
diff --git a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MeeGoTrackInfoDisplay.cs b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MeeGoTrackInfoDisplay.cs
index e18bc5b..886fcf5 100644
--- a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MeeGoTrackInfoDisplay.cs
+++ b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/MeeGoTrackInfoDisplay.cs
@@ -37,6 +37,10 @@ namespace Banshee.MeeGo
     {
         private Regex line_three_split;
 
+        protected MeeGoTrackInfoDisplay (IntPtr raw) : base (raw)
+        {
+        }
+
         public MeeGoTrackInfoDisplay () : base ()
         {
         }
diff --git a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/PlaybackBox.cs b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/PlaybackBox.cs
index 1debcbf..2b33336 100644
--- a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/PlaybackBox.cs
+++ b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/PlaybackBox.cs
@@ -34,19 +34,25 @@ using Banshee.ServiceStack;
 
 namespace Banshee.MeeGo
 {
-    public class PlaybackBox : HBox
+    public class PlaybackBox : Alignment
     {
-        public PlaybackBox ()
+        protected PlaybackBox (IntPtr raw) : base (raw)
         {
+        }
+
+        public PlaybackBox () : base (0.5f, 0.5f, 0.0f, 0.0f)
+        {
+            var box = new HBox ();
             var action_service = ServiceManager.Get<InterfaceActionService> ();
 
-            PackStart (action_service.PlaybackActions["PreviousAction"].CreateToolItem (), false, false, 0);
-            PackStart (action_service.PlaybackActions["PlayPauseAction"].CreateToolItem (), false, false, 0);
-            PackStart (new NextButton (action_service, true), false, false, 0);
+            TopPadding = 6;
+
+            box.PackStart (action_service.PlaybackActions["PreviousAction"].CreateToolItem (), false, false, 0);
+            box.PackStart (action_service.PlaybackActions["PlayPauseAction"].CreateToolItem (), false, false, 0);
+            box.PackStart (new NextButton (action_service), false, false, 0);
+            box.PackStart (new RepeatActionButton (true), false, false, 0);
 
-            var seek_slider = new ConnectedSeekSlider ();
-            seek_slider.Show ();
-            PackStart (seek_slider, false, false, 0);
+            Add (box);
         }
     }
 }
diff --git a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/SearchEntry.cs b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/SearchEntry.cs
index 722112f..33459d2 100644
--- a/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/SearchEntry.cs
+++ b/src/Extensions/Banshee.MeeGo/Banshee.MeeGo/SearchEntry.cs
@@ -37,6 +37,10 @@ namespace Banshee.MeeGo
 {
     public class SearchEntry : Banshee.Widgets.SearchEntry
     {
+        protected SearchEntry (IntPtr raw) : base (raw)
+        {
+        }
+
         public SearchEntry ()
         {
             BuildSearchEntry ();
diff --git a/src/Extensions/Banshee.MeeGo/Makefile.am b/src/Extensions/Banshee.MeeGo/Makefile.am
index 6792c4b..29cfcdf 100644
--- a/src/Extensions/Banshee.MeeGo/Makefile.am
+++ b/src/Extensions/Banshee.MeeGo/Makefile.am
@@ -7,9 +7,10 @@ INSTALL_DIR = $(EXTENSIONS_INSTALL_DIR)
 
 SOURCES =  \
 	Banshee.MeeGo/MediaPanelContents.cs \
+	Banshee.MeeGo/MeeGoHeaderBox.cs \
 	Banshee.MeeGo/MeeGoPanel.cs \
 	Banshee.MeeGo/MeeGoService.cs \
-	Banshee.MeeGo/MeeGoSourceContents.cs \
+	Banshee.MeeGo/MeeGoTheme.cs \
 	Banshee.MeeGo/MeeGoTrackInfoDisplay.cs \
 	Banshee.MeeGo/PlaybackBox.cs \
 	Banshee.MeeGo/SearchEntry.cs \



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