[gnome-music/playlists: 1/2] basic layout for SongsList widget



commit 5ba68c551c9d75f6d33e4bb7861744d4caecacbf
Author: Eslam Mostafa <me eslammostafa com>
Date:   Wed Jun 26 19:11:02 2013 +0200

    basic layout for SongsList widget

 data/PlaylistControls.ui       |   40 ++++++++
 data/PlaylistSongs.ui          |  180 ++++++++++++++++++++++++++++++++++++
 data/application.css           |   21 ++++
 data/gnome-music.gresource.xml |    2 +
 src/view.js                    |  200 +++++++++++++++++----------------------
 src/widgets.js                 |  130 ++++++++++++++++++++++++++
 6 files changed, 460 insertions(+), 113 deletions(-)
---
diff --git a/data/PlaylistControls.ui b/data/PlaylistControls.ui
new file mode 100644
index 0000000..fb77c05
--- /dev/null
+++ b/data/PlaylistControls.ui
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <object class="GtkToolbar" id="container">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="toolbar_style">icons</property>
+    <property name="show_arrow">False</property>
+    <style>
+      <class name="inline-toolbar"/>
+    </style>
+    <property name="icon_size">2</property>
+    <child>
+      <object class="GtkToolButton" id="addPlaylist">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">toolbutton1</property>
+        <property name="use_underline">True</property>
+        <property name="icon_name">list-add-symbolic</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="homogeneous">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkToolButton" id="removePlaylist">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">toolbutton1</property>
+        <property name="use_underline">True</property>
+        <property name="icon_name">list-remove-symbolic</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="homogeneous">True</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/data/PlaylistSongs.ui b/data/PlaylistSongs.ui
new file mode 100644
index 0000000..b3697a6
--- /dev/null
+++ b/data/PlaylistSongs.ui
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <object class="GtkBox" id="container">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="margin_left">24</property>
+    <property name="margin_top">18</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkBox" id="box2">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkLabel" id="playlist">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="label">label</property>
+            <property name="ellipsize">middle</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="spacer">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="playlistEditButton">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="focus_on_click">False</property>
+            <style>
+              <class name="circle-button"/>
+            </style>
+            <child>
+              <object class="GtkImage" id="image1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_name">applications-system-symbolic</property>
+                <property name="use_fallback">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label1">
+            <property name="width_request">24</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="box1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="songsCount">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">00</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="songs">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Songs,</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="songsSize">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">size</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="songsDuration">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">duration</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolledwindow">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hscrollbar_policy">never</property>
+        <child>
+          <object class="GtkViewport" id="viewport">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">3</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/data/application.css b/data/application.css
index 0642bcd..c827b4f 100644
--- a/data/application.css
+++ b/data/application.css
@@ -25,6 +25,19 @@
     background-color: #77757A;
 }
 
+.playlist-controls-white{
+    background-color: #d7dad7;
+}
+.playlist-controls-white:selected{
+    background-color: #888A85;
+}
+.playlist-controls-dark{
+    background-color: #282528;
+}
+.playlist-controls-dark:selected{
+    background-color: #77757A;
+}
+
 .songs-list {
     box-shadow: inset 0 -1px shade(@borders, 1.30);
     background-color: @theme_bg_color;
@@ -122,3 +135,11 @@
     color: mix (@theme_fg_color, @theme_bg_color, 0.50);    
 }
 
+.circle-button {
+    border-radius: 15px;
+    border-width: 2px;
+}
+
+.circle-button image {
+    border-radius: 15px;
+}
diff --git a/data/gnome-music.gresource.xml b/data/gnome-music.gresource.xml
index 6e6b91f..cd4259f 100644
--- a/data/gnome-music.gresource.xml
+++ b/data/gnome-music.gresource.xml
@@ -9,5 +9,7 @@
     <file preprocess="xml-stripblanks">PlayerToolbar.ui</file>
     <file preprocess="xml-stripblanks">TrackWidget.ui</file>
     <file preprocess="xml-stripblanks">NoMusic.ui</file>
+    <file preprocess="xml-stripblanks">PlaylistControls.ui</file>
+    <file preprocess="xml-stripblanks">PlaylistSongs.ui</file>
   </gresource>
 </gresources>
diff --git a/src/view.js b/src/view.js
index 5c26220..9ede6a8 100644
--- a/src/view.js
+++ b/src/view.js
@@ -319,33 +319,11 @@ const Songs = new Lang.Class({
         this.countQuery = Query.songs_count;
         this._items = {};
         this.isStarred = null;
-        this.view.set_view_type(Gd.MainViewType.LIST);
-        this.view.get_generic_view().get_style_context().add_class("songs-list")
+        this.view = new Widgets.SongsList(player);
         this._iconHeight = 32;
         this._iconWidth = 32;
         this._symbolicIcon = albumArtCache.makeDefaultIcon(this._iconHeight, this._iconWidth)
-        this._addListRenderers();
         this.player = player;
-        this.player.connect('playlist-item-changed', Lang.bind(this, this.updateModel));
-    },
-
-    _onItemActivated: function (widget, id, path) {
-        var iter = this._model.get_iter(path)[1]
-        if (this._model.get_value(iter, 8) != errorIconName) {
-            this.player.setPlaylist("Songs", null, this._model, iter, 5);
-            this.player.setPlaying(true);
-        }
-    },
-
-    updateModel: function(player, playlist, currentIter){
-        if (playlist != this._model){
-            return false;}
-        if (this.iterToClean){
-            this._model.set_value(this.iterToClean, 10, false);
-        }
-        this._model.set_value(currentIter, 10, true);
-        this.iterToClean = currentIter.copy();
-        return false;
     },
 
     _addItem: function(source, param, item) {
@@ -375,87 +353,6 @@ const Songs = new Lang.Class({
         }
     },
 
-    _addListRenderers: function() {
-        let listWidget = this.view.get_generic_view();
-        let cols = listWidget.get_columns();
-        let cells = cols[0].get_cells();
-        cells[2].visible = false;
-        let nowPlayingSymbolRenderer = new Gtk.CellRendererPixbuf();
-        var columnNowPlaying = new Gtk.TreeViewColumn();
-        nowPlayingSymbolRenderer.xalign = 1.0;
-        columnNowPlaying.pack_start(nowPlayingSymbolRenderer, false);
-        columnNowPlaying.fixed_width = 24;
-        columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "visible", 10);
-        columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "icon_name", 8);
-        listWidget.insert_column(columnNowPlaying, 0);
-
-        let titleRenderer = new Gtk.CellRendererText({ xpad: 0 });
-        listWidget.add_renderer(titleRenderer,Lang.bind(this,function (col,cell,model,iter) {
-            let item = model.get_value(iter,5);
-            titleRenderer.xalign = 0.0;
-            titleRenderer.yalign = 0.5;
-            titleRenderer.height = 48;
-            titleRenderer.ellipsize = Pango.EllipsizeMode.END;
-            titleRenderer.text = item.get_title();
-        }))
-        let starRenderer = new Gtk.CellRendererPixbuf({xpad: 32});
-        listWidget.add_renderer(starRenderer,Lang.bind(this,function (col,cell,model,iter) {
-            let showstar = model.get_value(iter, 9);
-            if(showstar){
-            starRenderer.icon_name = starIconName;
-
-            }
-            else
-            starRenderer.pixbuf = null;
-        }))
-
-        let durationRenderer =
-            new Gd.StyledTextRenderer({ xpad: 32 });
-        durationRenderer.add_class('dim-label');
-        listWidget.add_renderer(durationRenderer, Lang.bind(this,
-            function(col, cell, model, iter) {
-                let item = model.get_value(iter, 5);
-                if (item) {
-                    let duration = item.get_duration ();
-                    var minutes = parseInt(duration / 60);
-                    var seconds = duration % 60;
-                    var time = null
-                    if (seconds < 10)
-                        time =  minutes + ":0" + seconds;
-                    else
-                        time = minutes + ":" + seconds;
-                    durationRenderer.xalign = 1.0;
-                    durationRenderer.text = time;
-                }
-            }));
-
-        let artistRenderer =
-            new Gd.StyledTextRenderer({ xpad: 32});
-        artistRenderer.add_class('dim-label');
-        artistRenderer.ellipsize = Pango.EllipsizeMode.END;
-        listWidget.add_renderer(artistRenderer, Lang.bind(this,
-            function(col, cell, model, iter) {
-                let item = model.get_value(iter, 5);
-                if (item) {
-                    artistRenderer.ellipsize = Pango.EllipsizeMode.END;
-                    artistRenderer.text = item.get_string(Grl.METADATA_KEY_ARTIST);
-                }
-            }));
-        let typeRenderer =
-            new Gd.StyledTextRenderer({ xpad: 32});
-        typeRenderer.add_class('dim-label');
-        typeRenderer.ellipsize = Pango.EllipsizeMode.END;
-        listWidget.add_renderer(typeRenderer, Lang.bind(this,
-            function(col, cell, model, iter) {
-                let item = model.get_value(iter, 5);
-                if (item) {
-                    typeRenderer.ellipsize = Pango.EllipsizeMode.END;
-                    typeRenderer.text = item.get_string(Grl.METADATA_KEY_ALBUM);
-                }
-            }));
-
-    },
-
     populate: function() {
         if (grilo.tracker != null)
             grilo.populateSongs (this._offset, Lang.bind(this, this._addItem, null));
@@ -463,15 +360,6 @@ const Songs = new Lang.Class({
 
 });
 
-const Playlists = new Lang.Class({
-    Name: "PlaylistsView",
-    Extends: ViewContainer,
-
-    _init: function(header_bar, player) {
-        this.parent("Playlists", header_bar);
-    },
-});
-
 const Artists = new Lang.Class({
     Name: "ArtistsView",
     Extends: ViewContainer,
@@ -579,4 +467,90 @@ const Artists = new Lang.Class({
             //FIXME: We're emitting this too early, need to wait for all artists to be filled in
         }
     },
+
+});
+
+const Playlists = new Lang.Class({
+    Name: "PlaylistsView",
+    Extends: ViewContainer,
+
+    _init: function(header_bar, player) {
+        this.parent("Playlists", header_bar, true);
+        this.player= player;
+        this.view.set_view_type(Gd.MainViewType.LIST);
+        this.view.set_hexpand(false);
+        this.view.get_style_context().add_class("artist-panel");
+        this.view.get_generic_view().get_selection().set_mode(Gtk.SelectionMode.SINGLE);
+        this._songsListWidget = new Widgets.SongsList(this.player);
+        /*let builder = new Gtk.Builder();
+        builder.add_from_resource('/org/gnome/music/PlaylistControls.ui');
+        let controls = builder.get_object('container');*/
+        this._grid.attach(new Gtk.Separator(), 0, 1, 1, 1);
+        //this._grid.attach(controls, 0, 2, 1, 1);
+        this._grid.attach(new Gtk.Separator({orientation: Gtk.Orientation.VERTICAL}), 1, 0, 1, 3);
+        this._grid.attach(this._songsListWidget, 2, 0, 2, 3);
+        this._addListRenderers();
+        if(Gtk.Settings.get_default().gtk_application_prefer_dark_theme) {
+            this.view.get_generic_view().get_style_context().add_class("artist-panel-dark");
+            //controls.get_style_context().add_class("playlist-controls-dark");
+        } else {
+            this.view.get_generic_view().get_style_context().add_class("artist-panel-white");
+            //controls.get_style_context().add_class("playlist-controls-white");
+        }
+        this.show_all();
+    },
+    _addListRenderers: function() {
+        let listWidget = this.view.get_generic_view();
+
+        var cols = listWidget.get_columns()
+        var cells = cols[0].get_cells()
+        cells[2].visible = false
+
+        let typeRenderer =
+            new Gd.StyledTextRenderer({ xpad: 0 });
+        typeRenderer.ellipsize = 3;
+        typeRenderer.xalign = 0.0;
+        typeRenderer.yalign = 0.5;
+        typeRenderer.height = 48;
+        typeRenderer.width = 220;
+        listWidget.add_renderer(typeRenderer, Lang.bind(this,
+            function(col, cell, model, iter) {
+                typeRenderer.text = model.get_value(iter, 0);
+            }));
+    },
+
+    _onItemActivated: function (widget, id, path) {
+        let iter = this._model.get_iter (path)[1];
+        let playlist = this._model.get_value (iter, 0);
+        //this._playlistLabel.set_text(playlist);
+        let url = this._playlists[playlist.toLowerCase()]['url'];
+        this._songsListWidget.update(playlist, this._playlists[playlist.toLowerCase()]);
+    },
+
+    _addItem: function (source, param, item) {
+        this._offset += 1;
+        if (item == null)
+            return
+        var playlist = "Unknown"
+        if (item.get_title() != null)
+            playlist = item.get_title();
+        if (item.get_string(Grl.METADATA_KEY_TITLE) != null)
+            playlist = item.get_string(Grl.METADATA_KEY_TITLE)
+        var url = item.get_string(Grl.METADATA_KEY_URL)
+        if (this._playlists[playlist.toLowerCase()] == undefined) {
+            var iter = this._model.append();
+            this._playlists[playlist.toLowerCase()] = {"iter": iter, "url": url}
+            this._model.set(
+                iter,
+                [0, 1, 2, 3],
+                [playlist, playlist, playlist, playlist]
+            );
+        }
+    },
+
+    populate: function () {
+        if(grilo.tracker != null) {
+            grilo.populatePlaylists(this._offset, Lang.bind(this, this._addItem, null));
+        }
+    },
 });
diff --git a/src/widgets.js b/src/widgets.js
index 5c3b2ba..1806b43 100644
--- a/src/widgets.js
+++ b/src/widgets.js
@@ -632,3 +632,133 @@ const ArtistAlbumWidget = new Lang.Class({
 
 });
 Signals.addSignalMethods(ArtistAlbumWidget.prototype);
+
+const SongsList = new Lang.Class({
+    Name: "SongsList",
+    Extends: Gd.MainView,
+
+    _init: function(player){
+        this.parent();
+        this.set_shadow_type(Gtk.ShadowType.NONE);
+        this.player = player;
+        this.set_view_type(Gd.MainViewType.LIST);
+        this.get_generic_view().get_style_context().add_class("songs-list")
+        this._model = Gtk.ListStore.new([
+            GObject.TYPE_STRING,
+            GObject.TYPE_STRING,
+            GObject.TYPE_STRING,
+            GObject.TYPE_STRING,
+            GdkPixbuf.Pixbuf,
+            GObject.TYPE_OBJECT,
+            GObject.TYPE_BOOLEAN,
+            GObject.TYPE_STRING,
+            GObject.TYPE_BOOLEAN,
+            GObject.TYPE_BOOLEAN
+        ]);
+        this.set_model(this._model);
+        this._addListRenderers();
+        this.show_all();
+        this.connect('item-activated', Lang.bind(this, this._onItemActivated));
+        this.player.connect('playlist-item-changed', Lang.bind(this, this.updateModel));
+    },
+
+    updateModel: function(player, playlist, currentIter){
+        if (playlist != this._model){
+            return false;}
+        if (this.iterToClean){
+            this._model.set_value(this.iterToClean, 9, false);
+        }
+        this._model.set_value(currentIter, 9, true);
+        this.iterToClean = currentIter.copy();
+        return false;
+    },
+
+    _onItemActivated: function (widget, id, path) {
+        var iter = this._model.get_iter(path)[1]
+        if (this._model.get_value(iter, 7) != errorIconName) {
+            this.player.setPlaylist("Playlist", null, this._model, iter, 5);
+            this.player.setPlaying(true);
+        }
+    },
+
+    _addListRenderers: function() {
+        let listWidget = this.get_generic_view();
+        let cols = listWidget.get_columns();
+        let cells = cols[0].get_cells();
+        cells[2].visible = false;
+        let nowPlayingSymbolRenderer = new Gtk.CellRendererPixbuf();
+        var columnNowPlaying = new Gtk.TreeViewColumn();
+        nowPlayingSymbolRenderer.xalign = 1.0;
+        columnNowPlaying.pack_start(nowPlayingSymbolRenderer, false);
+        columnNowPlaying.fixed_width = 24;
+        columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "visible", 9);
+        columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "icon_name", 7);
+        listWidget.insert_column(columnNowPlaying, 0);
+
+        let titleRenderer = new Gtk.CellRendererText({ xpad: 0 });
+        listWidget.add_renderer(titleRenderer,Lang.bind(this,function (col,cell,model,iter) {
+            let item = model.get_value(iter,5);
+            titleRenderer.xalign = 0.0;
+            titleRenderer.yalign = 0.5;
+            titleRenderer.height = 48;
+            titleRenderer.ellipsize = Pango.EllipsizeMode.END;
+            titleRenderer.text = item.get_title();
+        }))
+        let starRenderer = new Gtk.CellRendererPixbuf({xpad: 32});
+        listWidget.add_renderer(starRenderer,Lang.bind(this,function (col,cell,model,iter) {
+            let showstar = model.get_value(iter,8);
+            if(showstar){
+            starRenderer.icon_name = starIconName;
+
+            }
+            else
+            starRenderer.pixbuf = null;
+        }))
+
+        let durationRenderer =
+            new Gd.StyledTextRenderer({ xpad: 32 });
+        durationRenderer.add_class('dim-label');
+        listWidget.add_renderer(durationRenderer, Lang.bind(this,
+            function(col, cell, model, iter) {
+                let item = model.get_value(iter, 5);
+                if (item) {
+                    let duration = item.get_duration ();
+                    var minutes = parseInt(duration / 60);
+                    var seconds = duration % 60;
+                    var time = null
+                    if (seconds < 10)
+                        time =  minutes + ":0" + seconds;
+                    else
+                        time = minutes + ":" + seconds;
+                    durationRenderer.xalign = 1.0;
+                    durationRenderer.text = time;
+                }
+            }));
+
+        let artistRenderer =
+            new Gd.StyledTextRenderer({ xpad: 32});
+        artistRenderer.add_class('dim-label');
+        artistRenderer.ellipsize = Pango.EllipsizeMode.END;
+        listWidget.add_renderer(artistRenderer, Lang.bind(this,
+            function(col, cell, model, iter) {
+                let item = model.get_value(iter, 5);
+                if (item) {
+                    artistRenderer.ellipsize = Pango.EllipsizeMode.END;
+                    artistRenderer.text = item.get_string(Grl.METADATA_KEY_ARTIST);
+                }
+            }));
+        let typeRenderer =
+            new Gd.StyledTextRenderer({ xpad: 32});
+        typeRenderer.add_class('dim-label');
+        typeRenderer.ellipsize = Pango.EllipsizeMode.END;
+        listWidget.add_renderer(typeRenderer, Lang.bind(this,
+            function(col, cell, model, iter) {
+                let item = model.get_value(iter, 5);
+                if (item) {
+                    typeRenderer.ellipsize = Pango.EllipsizeMode.END;
+                    typeRenderer.text = item.get_string(Grl.METADATA_KEY_ALBUM);
+                }
+            }));
+
+    },
+});


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