Merge lp:~victored/noise/new-album-view into lp:~elementary-apps/noise/trunk

Proposed by Victor Martinez
Status: Merged
Approved by: Corentin Noël
Approved revision: 1518
Merged at revision: 1540
Proposed branch: lp:~victored/noise/new-album-view
Merge into: lp:~elementary-apps/noise/trunk
Diff against target: 966 lines (+477/-266) (has conflicts)
14 files modified
core/Utils/Icons.vala (+0/-12)
core/Utils/PixbufUtils.vala (+14/-64)
images/CMakeLists.txt (+5/-0)
plugins/Devices/CDRom/CDView.vala (+1/-1)
src/CMakeLists.txt (+79/-0)
src/Objects/CoverartCache.vala (+2/-4)
src/Views/GridView/GridLayout.vala (+0/-160)
src/Views/GridView/GridView.vala (+6/-16)
src/Widgets/FastView/FastGrid.vala (+7/-5)
src/Widgets/FastView/FastGridModel.vala (+3/-1)
src/Widgets/FastView/TileView/ImageUtils.vala (+51/-0)
src/Widgets/FastView/TileView/TileRenderer.vala (+234/-0)
src/Widgets/FastView/TileView/TileView.vala (+70/-0)
src/Widgets/InfoPanel.vala (+5/-3)
Text conflict in images/CMakeLists.txt
Text conflict in src/CMakeLists.txt
To merge this branch: bzr merge lp:~victored/noise/new-album-view
Reviewer Review Type Date Requested Status
elementary Apps team Pending
Review via email: mp+180679@code.launchpad.net

Commit message

Add fancier album view by using a custom cell renderer in GtkIconView.

Please note that the code used for "smart spacing" has been removed as it only worked before GTK+ 3.4.3. New bugs in GTK+ prevent us from keeping this code around.

Description of the change

As you may have seen, the "smart spacing" code from the album view does not work with new GTK+ versions, due to some bugs in GtkIconView we have not been able to work around. This branch removes that code for the time being and adds a custom cell renderer that makes our icon view more similar to the one used by Shotwell.

To post a comment you must log in.
Revision history for this message
Victor Martinez (victored) wrote :

Please note this code is not supposed to work correctly on Luna, but on GTK+ 3.8 or newer (Ubuntu 13.04).

Revision history for this message
David Gomes (davidgomes) wrote :

We'll merge this when we have Saucy builds and are officially using GTK+ 3.8+-

lp:~victored/noise/new-album-view updated
1518. By Victor Martinez

Fix coding style issue

Revision history for this message
Rico Tzschichholz (ricotz) wrote :

If noise doesn't work as expected with gtk+3.0 < 3.8 after this change then the dependency should have been bumped.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'core/Utils/Icons.vala'
--- core/Utils/Icons.vala 2013-02-26 21:56:08 +0000
+++ core/Utils/Icons.vala 2013-09-26 03:02:55 +0000
@@ -33,15 +33,8 @@
33 * A place to store icon information and pixbufs.33 * A place to store icon information and pixbufs.
34 */34 */
35public class Noise.Icons {35public class Noise.Icons {
36
37 /**
38 * Size of the cover art used in the album view
39 **/
40 public const int ALBUM_VIEW_IMAGE_SIZE = 168;
41 public const int DEFAULT_ALBUM_ART_SIZE = 138;36 public const int DEFAULT_ALBUM_ART_SIZE = 138;
4237
43 public static Gdk.Pixbuf DEFAULT_ALBUM_SHADOW_PIXBUF { get; private set; }
44
45 public static Icon DEFAULT_ALBUM_ART { get; private set; default = new Icon ("albumart"); }38 public static Icon DEFAULT_ALBUM_ART { get; private set; default = new Icon ("albumart"); }
46 public static Icon DEFAULT_ALBUM_ART_2 { get; private set; default = new Icon ("albumart_2"); }39 public static Icon DEFAULT_ALBUM_ART_2 { get; private set; default = new Icon ("albumart_2"); }
47 public static Icon MUSIC_FOLDER { get; private set; default = new Icon ("folder-music"); }40 public static Icon MUSIC_FOLDER { get; private set; default = new Icon ("folder-music"); }
@@ -83,11 +76,6 @@
83 public static Icon LIST_ADD_SYMBOLIC { get; private set; default = new Icon ("list-add-symbolic"); }76 public static Icon LIST_ADD_SYMBOLIC { get; private set; default = new Icon ("list-add-symbolic"); }
84 public static Icon REFRESH_SYMBOLIC { get; private set; default = new Icon ("view-refresh-symbolic"); }77 public static Icon REFRESH_SYMBOLIC { get; private set; default = new Icon ("view-refresh-symbolic"); }
8578
86 static construct {
87 var default_shadow = new Icon ("albumart-shadow");
88 DEFAULT_ALBUM_SHADOW_PIXBUF = default_shadow.render_at_size (ALBUM_VIEW_IMAGE_SIZE);
89 }
90
91 /**79 /**
92 * This is needed until vala really supports initialization of static members.80 * This is needed until vala really supports initialization of static members.
93 * See https://bugzilla.gnome.org/show_bug.cgi?id=54318981 * See https://bugzilla.gnome.org/show_bug.cgi?id=543189
9482
=== modified file 'core/Utils/PixbufUtils.vala'
--- core/Utils/PixbufUtils.vala 2013-06-12 18:04:28 +0000
+++ core/Utils/PixbufUtils.vala 2013-09-26 03:02:55 +0000
@@ -22,75 +22,25 @@
22 */22 */
2323
24namespace Noise.PixbufUtils {24namespace Noise.PixbufUtils {
25
26 /**
27 * @param pixbuf original image
28 * @param stretch whether to strech the image inside the square or keep the original dimensions
29 * @return original pixbuf + drop shadow
30 **/
31 public Gdk.Pixbuf? get_pixbuf_shadow (Gdk.Pixbuf pixbuf, int surface_size, bool stretch = true) {
32 const int SHADOW_SIZE = 15;
33
34 int S_WIDTH = (stretch)? surface_size: pixbuf.width;
35 int S_HEIGHT = (stretch)? surface_size : pixbuf.height;
36
37 var buffer_surface = new Granite.Drawing.BufferSurface (S_WIDTH, S_HEIGHT);
38
39 // paint shadow
40 buffer_surface.context.rectangle (0, 0, S_WIDTH, S_HEIGHT);
41
42 if (stretch)
43 Gdk.cairo_set_source_pixbuf (buffer_surface.context,
44 Icons.DEFAULT_ALBUM_SHADOW_PIXBUF.scale_simple (S_WIDTH, S_HEIGHT, Gdk.InterpType.BILINEAR), 0, 0);
45 else
46 Gdk.cairo_set_source_pixbuf (buffer_surface.context, Icons.DEFAULT_ALBUM_SHADOW_PIXBUF, 0, 0);
47
48 buffer_surface.context.paint();
49
50 S_WIDTH -= 2 * SHADOW_SIZE;
51 S_HEIGHT -= 2 * SHADOW_SIZE;
52
53 // paint original pixbuf
54 var source_pixbuf = pixbuf;
55 if (pixbuf.width != S_WIDTH || pixbuf.height != S_HEIGHT)
56 source_pixbuf = pixbuf.scale_simple (S_WIDTH, S_HEIGHT, Gdk.InterpType.BILINEAR);
57
58 Gdk.cairo_set_source_pixbuf (buffer_surface.context, source_pixbuf,
59 SHADOW_SIZE, SHADOW_SIZE - 2); // 2px vertical offset
60 buffer_surface.context.paint();
61
62 return buffer_surface.load_to_pixbuf();
63 }
64
65 /**25 /**
66 * @param surface_size size of the new pixbuf. Set a value of 0 to use the pixbuf's default size.26 * @param surface_size size of the new pixbuf. Set a value of 0 to use the pixbuf's default size.
67 **/27 **/
68 public Gdk.Pixbuf? render_pixbuf_shadow (Gdk.Pixbuf pixbuf,28 public Gdk.Pixbuf? render_pixbuf_shadow (Gdk.Pixbuf pixbuf, int shadow_size = 5, double alpha = 0.75) {
69 int surface_size = Icons.ALBUM_VIEW_IMAGE_SIZE,29 int width = pixbuf.width;
70 int shadow_size = 5, double alpha = 0.75)30 int height = pixbuf.height;
71 {31 int shadow_padding = 2 * shadow_size;
72 int S_WIDTH = (surface_size > 0)? surface_size : pixbuf.width;32
73 int S_HEIGHT = (surface_size > 0)? surface_size : pixbuf.height;33 var buffer_surface = new Granite.Drawing.BufferSurface (width + shadow_padding,
7434 height + shadow_padding);
75 var buffer_surface = new Granite.Drawing.BufferSurface (S_WIDTH, S_HEIGHT);35
7636 buffer_surface.context.rectangle (shadow_size, shadow_size, width, height);
77 S_WIDTH -= 2 * shadow_size;
78 S_HEIGHT -= 2 * shadow_size;
79
80 buffer_surface.context.rectangle (shadow_size, shadow_size, S_WIDTH, S_HEIGHT);
81 buffer_surface.context.set_source_rgba (0, 0, 0, alpha);37 buffer_surface.context.set_source_rgba (0, 0, 0, alpha);
82 buffer_surface.context.fill();38 buffer_surface.context.fill ();
83
84 buffer_surface.fast_blur (2, 3);39 buffer_surface.fast_blur (2, 3);
8540 Gdk.cairo_set_source_pixbuf (buffer_surface.context, pixbuf, shadow_size, shadow_size);
86 Gdk.cairo_set_source_pixbuf (buffer_surface.context,41 buffer_surface.context.paint ();
87 pixbuf.scale_simple (S_WIDTH, S_HEIGHT, Gdk.InterpType.BILINEAR),42
88 shadow_size,43 return buffer_surface.load_to_pixbuf ();
89 shadow_size);
90
91 buffer_surface.context.paint();
92
93 return buffer_surface.load_to_pixbuf();
94 }44 }
9545
96 public async Gdk.Pixbuf? get_pixbuf_from_file_async (File file, Cancellable? c = null) throws Error {46 public async Gdk.Pixbuf? get_pixbuf_from_file_async (File file, Cancellable? c = null) throws Error {
9747
=== modified file 'images/CMakeLists.txt'
--- images/CMakeLists.txt 2013-09-16 07:12:31 +0000
+++ images/CMakeLists.txt 2013-09-26 03:02:55 +0000
@@ -21,9 +21,14 @@
21# Default album image and album shadow. These would not be found by the icon renderer if21# Default album image and album shadow. These would not be found by the icon renderer if
22# they were installed to the hicolor sub-directory, since their dimensions are not the ones22# they were installed to the hicolor sub-directory, since their dimensions are not the ones
23# GTK+ expects to find in a normal icon theme. They work fine in the root icon dir though.23# GTK+ expects to find in a normal icon theme. They work fine in the root icon dir though.
24<<<<<<< TREE
24set (GENERIC_IMAGES25set (GENERIC_IMAGES
25 icons/albumart.svg26 icons/albumart.svg
26 icons/albumart-shadow.png27 icons/albumart-shadow.png
28=======
29set(GENERIC_IMAGES
30 icons/albumart.svg
31>>>>>>> MERGE-SOURCE
27)32)
2833
29install (FILES ${GENERIC_IMAGES} DESTINATION ${ICON_DIR})34install (FILES ${GENERIC_IMAGES} DESTINATION ${ICON_DIR})
3035
=== removed file 'images/icons/albumart-shadow.png'
31Binary files images/icons/albumart-shadow.png 2013-07-12 19:29:23 +0000 and images/icons/albumart-shadow.png 1970-01-01 00:00:00 +0000 differ36Binary files images/icons/albumart-shadow.png 2013-07-12 19:29:23 +0000 and images/icons/albumart-shadow.png 1970-01-01 00:00:00 +0000 differ
=== modified file 'plugins/Devices/CDRom/CDView.vala'
--- plugins/Devices/CDRom/CDView.vala 2013-04-29 18:26:03 +0000
+++ plugins/Devices/CDRom/CDView.vala 2013-09-26 03:02:55 +0000
@@ -57,7 +57,7 @@
57 }57 }
58 58
59 var default_pix = Icons.DEFAULT_ALBUM_ART.render_at_size (Icons.DEFAULT_ALBUM_ART_SIZE);59 var default_pix = Icons.DEFAULT_ALBUM_ART.render_at_size (Icons.DEFAULT_ALBUM_ART_SIZE);
60 default_pix = PixbufUtils.get_pixbuf_shadow (default_pix, Icons.ALBUM_VIEW_IMAGE_SIZE);60 default_pix = PixbufUtils.render_pixbuf_shadow (default_pix);
61 61
62 album_image = new Gtk.Image.from_pixbuf (default_pix);62 album_image = new Gtk.Image.from_pixbuf (default_pix);
63 album_image.halign = Gtk.Align.CENTER;63 album_image.halign = Gtk.Align.CENTER;
6464
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2013-09-16 07:12:31 +0000
+++ src/CMakeLists.txt 2013-09-26 03:02:55 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
1set (CLIENT_SOURCE2set (CLIENT_SOURCE
2 main.vala3 main.vala
3 Noise.vala4 Noise.vala
@@ -71,6 +72,84 @@
71 Dialogs/SetMusicFolderConfirmation.vala72 Dialogs/SetMusicFolderConfirmation.vala
72 Dialogs/TransferFromDeviceDialog.vala73 Dialogs/TransferFromDeviceDialog.vala
73 Dialogs/SyncWarningDialog.vala74 Dialogs/SyncWarningDialog.vala
75=======
76set(CLIENT_SOURCE
77 main.vala
78 Noise.vala
79 LibraryWindow.vala
80 LocalLibrary.vala
81 PlaybackManager.vala
82 FileOperator.vala
83 Objects/LyricFetcher.vala
84 Objects/MediaInfo.vala
85 Objects/AlbumInfo.vala
86 Objects/ArtistInfo.vala
87 Objects/TrackInfo.vala
88 Objects/MediaArtCache.vala
89 Objects/CoverartCache.vala
90 Objects/MediaKeyListener.vala
91 Widgets/NavigationArrows.vala
92 Widgets/SmartAlbumRenderer.vala
93 Widgets/TopDisplay.vala
94 Widgets/InfoPanel.vala
95 Widgets/EmbeddedAlert.vala
96 Widgets/SimpleOptionChooser.vala
97 Widgets/PresetList.vala
98 Widgets/SideBar.vala
99 Widgets/SourceListView.vala
100 Widgets/StatusBar.vala
101 Widgets/RatingWidget.vala
102 Widgets/SpaceWidget.vala
103 Widgets/FixedBin.vala
104 Widgets/ViewSelector.vala
105 Widgets/FastView/TileView/ImageUtils.vala
106 Widgets/FastView/TileView/TileRenderer.vala
107 Widgets/FastView/TileView/TileView.vala
108 Widgets/FastView/FastGrid.vala
109 Widgets/FastView/FastGridModel.vala
110 Widgets/FastView/FastList.vala
111 Widgets/FastView/FastListModel.vala
112 DataBase/DataBaseManager.vala
113 DataBase/DataBaseUpdater.vala
114 DataBase/Tables.vala
115 GStreamer/GStreamerTagger.vala
116 GStreamer/Streamer.vala
117 GStreamer/CoverImport.vala
118 Views/ViewContainer.vala
119 Views/Wrappers/ViewWrapper.vala
120 Views/Wrappers/MusicViewWrapper.vala
121 Views/Wrappers/DeviceViewWrapper.vala
122 Views/Wrappers/PlaylistViewWrapper.vala
123 Views/Wrappers/ReadOnlyPlaylistViewWrapper.vala
124 Views/DeviceView.vala
125 Views/DeviceSummaryWidget.vala
126 Views/ContentView.vala
127 Views/ViewTextOverlay.vala
128 Views/GridView/GridLayout.vala
129 Views/GridView/GridView.vala
130 Views/GridView/PopupListView.vala
131 Views/ListView/ListView.vala
132 Views/ListView/ColumnBrowser/BrowserColumnModel.vala
133 Views/ListView/ColumnBrowser/BrowserColumn.vala
134 Views/ListView/ColumnBrowser/ColumnBrowser.vala
135 Views/ListView/ColumnBrowser/MusicColumnBrowser.vala
136 Views/ListView/Lists/ListColumn.vala
137 Views/ListView/Lists/TreeViewSetup.vala
138 Views/ListView/Lists/CellDataFunctionHelper.vala
139 Views/ListView/Lists/GenericList.vala
140 Views/ListView/Lists/MusicListView.vala
141 Dialogs/EqualizerWindow.vala
142 Dialogs/SmartPlaylistEditor.vala
143 Dialogs/PreferencesWindow.vala
144 Dialogs/InstallGstreamerPluginsDialog.vala
145 Dialogs/MediaEditor.vala
146 Dialogs/FileNotFoundDialog.vala
147 Dialogs/RemoveFilesDialog.vala
148 Dialogs/NotImportedWindow.vala
149 Dialogs/SetMusicFolderConfirmation.vala
150 Dialogs/TransferFromDeviceDialog.vala
151 Dialogs/SyncWarningDialog.vala
152>>>>>>> MERGE-SOURCE
74)153)
75154
76set (CLIENT_VALAC_OPTIONS155set (CLIENT_VALAC_OPTIONS
77156
=== modified file 'src/Objects/CoverartCache.vala'
--- src/Objects/CoverartCache.vala 2012-11-03 18:52:31 +0000
+++ src/Objects/CoverartCache.vala 2013-09-26 03:02:55 +0000
@@ -55,11 +55,9 @@
55 default_image = filter_func (default_pix);55 default_image = filter_func (default_pix);
56 }56 }
5757
58 /**
59 * Adds a shadow to every image.
60 */
61 protected override Gdk.Pixbuf? filter_func (Gdk.Pixbuf pix) {58 protected override Gdk.Pixbuf? filter_func (Gdk.Pixbuf pix) {
62 return PixbufUtils.get_pixbuf_shadow (pix, Icons.ALBUM_VIEW_IMAGE_SIZE);59 int size = Icons.DEFAULT_ALBUM_ART_SIZE;
60 return pix.scale_simple (size, size, Gdk.InterpType.BILINEAR);
63 }61 }
6462
65 protected override string get_key (Media m) {63 protected override string get_key (Media m) {
6664
=== modified file 'src/Views/GridView/GridLayout.vala'
--- src/Views/GridView/GridLayout.vala 2013-05-22 20:42:53 +0000
+++ src/Views/GridView/GridLayout.vala 2013-09-26 03:02:55 +0000
@@ -17,23 +17,11 @@
17 */17 */
1818
19public abstract class Noise.GridLayout : ViewTextOverlay {19public abstract class Noise.GridLayout : ViewTextOverlay {
20
21 public ViewWrapper parent_view_wrapper { get; protected set; }20 public ViewWrapper parent_view_wrapper { get; protected set; }
2221
23 private FastGrid icon_view;22 private FastGrid icon_view;
24 private Gtk.ScrolledWindow scroll;23 private Gtk.ScrolledWindow scroll;
2524
26 // Spacing Workarounds
27#if !GTK_ICON_VIEW_BUG_IS_FIXED
28 private Gtk.EventBox vpadding_box;
29 private Gtk.EventBox hpadding_box;
30#endif
31
32 private const string STYLESHEET = "*:selected{background-color:@transparent;}";
33 private const int ITEM_PADDING = 0;
34 private const int MIN_SPACING = 6;
35 private const int ITEM_WIDTH = Icons.ALBUM_VIEW_IMAGE_SIZE;
36
37 public GridLayout (ViewWrapper view_wrapper) {25 public GridLayout (ViewWrapper view_wrapper) {
38 parent_view_wrapper = view_wrapper;26 parent_view_wrapper = view_wrapper;
39 build_ui ();27 build_ui ();
@@ -88,59 +76,7 @@
8876
89 icon_view.set_columns (-1);77 icon_view.set_columns (-1);
9078
91// Should be defined for GTK+ 3.4.3 or later
92#if !GTK_ICON_VIEW_BUG_IS_FIXED
93
94 var wrapper_vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
95 var wrapper_hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);
96
97 vpadding_box = new Gtk.EventBox();
98 hpadding_box = new Gtk.EventBox();
99
100 vpadding_box.get_style_context().add_class(Gtk.STYLE_CLASS_VIEW);
101 hpadding_box.get_style_context().add_class(Gtk.STYLE_CLASS_VIEW);
102 this.get_style_context().add_class(Gtk.STYLE_CLASS_VIEW);
103
104 vpadding_box.get_style_context().add_class (Granite.StyleClass.CONTENT_VIEW);
105 hpadding_box.get_style_context().add_class (Granite.StyleClass.CONTENT_VIEW);
106 this.get_style_context().add_class (Granite.StyleClass.CONTENT_VIEW);
107
108 vpadding_box.set_size_request (-1, MIN_SPACING + ITEM_PADDING);
109 hpadding_box.set_size_request (MIN_SPACING + ITEM_PADDING, -1);
110
111 vpadding_box.button_press_event.connect ( () => {
112 item_activated (null);
113 return false;
114 });
115
116 hpadding_box.button_press_event.connect ( () => {
117 item_activated (null);
118 return false;
119 });
120
121
122 wrapper_vbox.pack_start (vpadding_box, false, false, 0);
123 wrapper_vbox.pack_start (wrapper_hbox, true, true, 0);
124 wrapper_hbox.pack_start (hpadding_box, false, false, 0);
125 wrapper_hbox.pack_start (icon_view, true, true, 0);
126
127 scroll.add_with_viewport (wrapper_vbox);
128
129 icon_view.margin = 0;
130
131#else
132
133 scroll.add (icon_view);79 scroll.add (icon_view);
134 icon_view.margin = MIN_SPACING;
135
136#endif
137
138
139 icon_view.item_width = ITEM_WIDTH;
140 icon_view.item_padding = ITEM_PADDING;
141 icon_view.spacing = 0;
142 icon_view.row_spacing = MIN_SPACING;
143 icon_view.column_spacing = MIN_SPACING;
14480
145 icon_view.add_events (Gdk.EventMask.POINTER_MOTION_MASK);81 icon_view.add_events (Gdk.EventMask.POINTER_MOTION_MASK);
146 icon_view.motion_notify_event.connect (on_motion_notify);82 icon_view.motion_notify_event.connect (on_motion_notify);
@@ -150,24 +86,9 @@
150 icon_view.button_release_event.connect (on_button_release);86 icon_view.button_release_event.connect (on_button_release);
151 icon_view.item_activated.connect (on_item_activated);87 icon_view.item_activated.connect (on_item_activated);
15288
153 int MIN_N_ITEMS = 2; // we will allocate horizontal space for at least two items
154 int TOTAL_ITEM_WIDTH = ITEM_WIDTH + 2 * ITEM_PADDING;
155 int TOTAL_MARGIN = MIN_N_ITEMS * (MIN_SPACING + ITEM_PADDING);
156 int MIDDLE_SPACE = MIN_N_ITEMS * MIN_SPACING;
157
158 scroll.min_content_width = MIN_N_ITEMS * TOTAL_ITEM_WIDTH + TOTAL_MARGIN + MIDDLE_SPACE;
159
160 set_theming ();
161 scroll.get_hadjustment ().changed.connect (on_resize);
162
163 show_all ();89 show_all ();
164 }90 }
16591
166 private void set_theming () {
167 // Change background color
168 Granite.Widgets.Utils.set_theming (icon_view, STYLESHEET, null, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
169 }
170
171 private void on_item_activated (Gtk.TreePath? path) {92 private void on_item_activated (Gtk.TreePath? path) {
172 if (path == null)93 if (path == null)
173 item_activated (null);94 item_activated (null);
@@ -218,85 +139,4 @@
218 set_cursor ((int)ev.x, (int)ev.y);139 set_cursor ((int)ev.x, (int)ev.y);
219 return false;140 return false;
220 }141 }
221
222
223 /**
224 * Smart spacing
225 */
226 private bool waiting_resize = false;
227
228 private void on_resize () {
229 if (waiting_resize)
230 return;
231
232 waiting_resize = true;
233
234 int priority = parent_view_wrapper.is_current_wrapper ? Priority.HIGH_IDLE : Priority.LOW;
235
236 Idle.add_full (priority , () => {
237 update_spacing ();
238 waiting_resize = false;
239 return false;
240 });
241 }
242
243 private int get_current_width () {
244 return (int) scroll.get_hadjustment ().page_size;
245 }
246
247 private void update_spacing () {
248 if (!visible)
249 return;
250
251 int new_width = get_current_width ();
252
253 int TOTAL_WIDTH = new_width; // width of view wrapper, not scrolled window!
254 int TOTAL_ITEM_WIDTH = ITEM_WIDTH + 2 * ITEM_PADDING;
255
256 // Calculate the number of columns
257 float n = (float)(TOTAL_WIDTH - MIN_SPACING) / (float)(TOTAL_ITEM_WIDTH + MIN_SPACING);
258 int n_columns = (int) GLib.Math.truncf (n);
259
260 if (n_columns < 1)
261 return;
262
263 icon_view.set_columns (n_columns);
264
265 // We don't want to adjust the spacing if the row is not full
266 if (icon_view.get_table ().size () < n_columns)
267 return;
268
269 // You're not supposed to understand this.
270 float spacing = (float)(TOTAL_WIDTH - n_columns * (ITEM_WIDTH + 1) - 2 * n_columns * ITEM_PADDING) / (float)(n_columns + 1);
271 int new_spacing = (int) GLib.Math.roundf (spacing);
272
273 if (new_spacing < 0)
274 return;
275
276 if (TOTAL_WIDTH < 750)
277 -- new_spacing;
278
279 // apply new spacing
280 set_spacing (new_spacing);
281 }
282
283 private void set_spacing (int spacing) {
284 if (spacing < 0)
285 return;
286
287 int item_offset = ITEM_PADDING / icon_view.columns;
288 int item_spacing = spacing - ((item_offset > 0) ? item_offset : 1);
289
290 icon_view.set_column_spacing (item_spacing);
291 icon_view.set_row_spacing (item_spacing);
292
293 int margin_width = spacing + ITEM_PADDING;
294
295#if GTK_ICON_VIEW_BUG_IS_FIXED
296 icon_view.set_margin (margin_width);
297#else
298 vpadding_box.set_size_request (-1, margin_width);
299 hpadding_box.set_size_request (margin_width, -1);
300#endif
301 }
302}142}
303143
=== modified file 'src/Views/GridView/GridView.vala'
--- src/Views/GridView/GridView.vala 2013-06-02 17:35:04 +0000
+++ src/Views/GridView/GridView.vala 2013-09-26 03:02:55 +0000
@@ -18,10 +18,6 @@
18 */18 */
1919
20public class Noise.GridView : ContentView, GridLayout {20public class Noise.GridView : ContentView, GridLayout {
21
22 private string TEXT_MARKUP = "%s\n<span foreground=\"#999\">%s</span>";
23 private string TOOLTIP_MARKUP = "<span size=\"large\"><b>%s</b></span>\n%s";
24
25 // The window used to present album contents21 // The window used to present album contents
26 private static PopupListView? _popup = null;22 private static PopupListView? _popup = null;
27 public PopupListView popup_list_view {23 public PopupListView popup_list_view {
@@ -329,22 +325,16 @@
329 // replace the current album-related media fields.325 // replace the current album-related media fields.
330 return CoverartCache.instance.get_album_cover (album);326 return CoverartCache.instance.get_album_cover (album);
331327
332 case FastGrid.Column.MARKUP:328 case FastGrid.Column.TITLE:
333 string name = album.get_display_name ();329 return album.get_display_name ();
334 string artist = album.get_display_artist ();330
335331 case FastGrid.Column.SUBTITLE:
336 if (name.length > 25)332 return album.get_display_artist ();
337 name = name.substring (0, 21) + "…";
338 if (artist.length > 25)
339 artist = artist.substring (0, 21) + "…";
340
341 return Markup.printf_escaped (TEXT_MARKUP, name, artist);
342333
343 case FastGrid.Column.TOOLTIP:334 case FastGrid.Column.TOOLTIP:
344 string name = album.get_display_name ();335 string name = album.get_display_name ();
345 string artist = album.get_display_artist ();336 string artist = album.get_display_artist ();
346337 return Markup.printf_escaped ("<span size=\"large\"><b>%s</b></span>\n%s", name, artist);
347 return Markup.printf_escaped (TOOLTIP_MARKUP, name, artist);
348 }338 }
349339
350 assert_not_reached ();340 assert_not_reached ();
351341
=== modified file 'src/Widgets/FastView/FastGrid.vala'
--- src/Widgets/FastView/FastGrid.vala 2013-05-22 20:42:53 +0000
+++ src/Widgets/FastView/FastGrid.vala 2013-09-26 03:02:55 +0000
@@ -21,11 +21,12 @@
2121
22using Gtk;22using Gtk;
2323
24public class Noise.FastGrid : IconView {24public class Noise.FastGrid : Widgets.TileView {
2525
26 public enum Column {26 public enum Column {
27 PIXBUF,27 PIXBUF,
28 MARKUP,28 TITLE,
29 SUBTITLE,
29 TOOLTIP,30 TOOLTIP,
30 N_COLUMNS31 N_COLUMNS
31 }32 }
@@ -50,9 +51,10 @@
50 set_table (table, true);51 set_table (table, true);
51 set_model (fm);52 set_model (fm);
5253
53 set_pixbuf_column (Column.PIXBUF);54 image_column = Column.PIXBUF;
54 set_markup_column (Column.MARKUP);55 title_column = Column.TITLE;
55 set_tooltip_column (Column.TOOLTIP);56 subtitle_column = Column.SUBTITLE;
57 tooltip_column = Column.TOOLTIP;
56 }58 }
5759
58 public void set_search_func (ViewSearchFunc func) {60 public void set_search_func (ViewSearchFunc func) {
5961
=== modified file 'src/Widgets/FastView/FastGridModel.vala'
--- src/Widgets/FastView/FastGridModel.vala 2012-10-27 16:25:32 +0000
+++ src/Widgets/FastView/FastGridModel.vala 2013-09-26 03:02:55 +0000
@@ -28,6 +28,8 @@
28 return typeof(string);28 return typeof(string);
29 else if(col == 2)29 else if(col == 2)
30 return typeof(string);30 return typeof(string);
31 else if(col == 3)
32 return typeof(string);
31 else33 else
32 return typeof(GLib.Object);34 return typeof(GLib.Object);
33 }35 }
@@ -49,7 +51,7 @@
49 }51 }
5052
51 public int get_n_columns () {53 public int get_n_columns () {
52 return 4;54 return 5;
53 }55 }
5456
55 public TreePath? get_path (TreeIter iter) {57 public TreePath? get_path (TreeIter iter) {
5658
=== added directory 'src/Widgets/FastView/TileView'
=== added file 'src/Widgets/FastView/TileView/ImageUtils.vala'
--- src/Widgets/FastView/TileView/ImageUtils.vala 1970-01-01 00:00:00 +0000
+++ src/Widgets/FastView/TileView/ImageUtils.vala 2013-09-26 03:02:55 +0000
@@ -0,0 +1,51 @@
1/**
2 * Copyright 2009-2013 Yorba Foundation
3 *
4 * This software is licensed under the GNU Lesser General Public License
5 * (version 3 or later). See the COPYING file in this distribution.
6 *
7 * (Code taken from Shotwell Photo Manager: shotwell/src/util/image.vala)
8 */
9
10namespace Noise.ImageUtils {
11 internal void shift_colors (Gdk.Pixbuf pixbuf, int red, int green, int blue, int alpha) {
12 assert (red >= -255 && red <= 255);
13 assert (green >= -255 && green <= 255);
14 assert (blue >= -255 && blue <= 255);
15 assert (alpha >= -255 && alpha <= 255);
16
17 int width = pixbuf.get_width ();
18 int height = pixbuf.get_height ();
19 int rowstride = pixbuf.get_rowstride ();
20 int channels = pixbuf.get_n_channels ();
21 uchar *pixels = pixbuf.get_pixels ();
22
23 assert (channels >= 3);
24 assert (pixbuf.get_colorspace () == Gdk.Colorspace.RGB);
25 assert (pixbuf.get_bits_per_sample () == 8);
26
27 for (int y = 0; y < height; y++) {
28 int y_offset = y * rowstride;
29
30 for (int x = 0; x < width; x++) {
31 int offset = y_offset + (x * channels);
32
33 if (red != 0)
34 pixels[offset] = shift_color_byte (pixels[offset], red);
35
36 if (green != 0)
37 pixels[offset + 1] = shift_color_byte (pixels[offset + 1], green);
38
39 if (blue != 0)
40 pixels[offset + 2] = shift_color_byte (pixels[offset + 2], blue);
41
42 if (alpha != 0 && channels >= 4)
43 pixels[offset + 3] = shift_color_byte (pixels[offset + 3], alpha);
44 }
45 }
46 }
47
48 internal inline uchar shift_color_byte (int b, int shift) {
49 return (uchar) (b + shift).clamp (0, 255);
50 }
51}
052
=== added file 'src/Widgets/FastView/TileView/TileRenderer.vala'
--- src/Widgets/FastView/TileView/TileRenderer.vala 1970-01-01 00:00:00 +0000
+++ src/Widgets/FastView/TileView/TileRenderer.vala 2013-09-26 03:02:55 +0000
@@ -0,0 +1,234 @@
1/**
2 * Copyright 2013 elementary
3 *
4 * This software is licensed under the GNU Lesser General Public License
5 * (version 3 or later). See the COPYING file in this distribution.
6 */
7
8internal class Noise.Widgets.TileRenderer : Gtk.CellRenderer {
9 public Gdk.Pixbuf pixbuf { get; set; }
10 public string title { get; set; }
11 public string subtitle { get; set; }
12
13 private const int BRIGHTEN_SHIFT = 0x18;
14 private const int IMAGE_SHADOW_MARGIN = 12;
15 private const int IMAGE_SHADOW_RADIUS = 4;
16 private const double IMAGE_SHADOW_ALPHA = 0.65;
17
18 private int last_image_width = 0;
19 private int last_image_height = 0;
20 private Granite.Drawing.BufferSurface shadow_buffer;
21 private Pango.Rectangle title_text_logical_rect;
22 private Pango.Rectangle subtitle_text_logical_rect;
23 private Pango.Layout title_text_layout;
24 private Pango.Layout subtitle_text_layout;
25 private Gtk.Border margin;
26 private Gtk.Border padding;
27 private Gtk.Border border;
28
29 [Deprecated (replacement = "Gtk.CellRenderer.get_preferred_size", since = "")]
30 public override void get_size (Gtk.Widget widget, Gdk.Rectangle? cell_area,
31 out int x_offset, out int y_offset,
32 out int width, out int height)
33 {
34 x_offset = y_offset = width = height = 0;
35 }
36
37 public override Gtk.SizeRequestMode get_request_mode () {
38 return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH;
39 }
40
41 public override void get_preferred_width (Gtk.Widget widget,
42 out int minimum_size,
43 out int natural_size)
44 {
45 update_layout_properties (widget);
46
47 int width = compute_total_image_width ()
48 + margin.left + margin.right
49 + padding.left + padding.right
50 + border.left + border.right
51 + 2 * (int) xpad;
52
53 minimum_size = natural_size = width;
54 }
55
56 public override void get_preferred_height_for_width (Gtk.Widget widget, int width,
57 out int minimum_height,
58 out int natural_height)
59 {
60 update_layout_properties (widget);
61
62 int height = compute_total_image_height ()
63 + title_text_logical_rect.height
64 + subtitle_text_logical_rect.height
65 + margin.top + margin.bottom
66 + padding.top + padding.bottom
67 + border.top + border.bottom
68 + 2 * (int) ypad;
69
70 minimum_height = natural_height = height;
71 }
72
73 public override void render (Cairo.Context cr, Gtk.Widget widget, Gdk.Rectangle bg_area,
74 Gdk.Rectangle cell_area, Gtk.CellRendererState flags)
75 {
76 update_layout_properties (widget);
77
78 Gdk.Rectangle aligned_area = get_aligned_area (widget, flags, cell_area);
79
80 int x = aligned_area.x;
81 int y = aligned_area.y;
82 int width = aligned_area.width;
83 int height = aligned_area.height;
84
85 // Apply margin
86 x += margin.right;
87 y += margin.top;
88 width -= margin.left + margin.right;
89 height -= margin.top + margin.bottom;
90
91 var ctx = widget.get_style_context ();
92
93 // Apply border width and padding offsets
94 x += border.right + padding.right;
95 y += border.top + padding.top;
96
97 width -= border.left + border.right + padding.left + padding.right;
98 height -= border.top + border.bottom + padding.top + padding.bottom;
99
100 render_image (ctx, cr, x, ref y, width, flags);
101 render_title (ctx, cr, x, ref y, width);
102 render_subtitle (ctx, cr, x, y, width);
103 }
104
105 private void render_image (Gtk.StyleContext ctx, Cairo.Context cr, int x,
106 ref int y, int width, Gtk.CellRendererState flags)
107 {
108 int image_width = compute_total_image_width ();
109 int image_height = compute_total_image_height ();
110 int offset = IMAGE_SHADOW_MARGIN;
111
112 // this cell renderer is not optimized for pixbufs of different dimensions
113 if (shadow_buffer == null || image_width != last_image_width
114 || image_height != last_image_height)
115 {
116 shadow_buffer = new Granite.Drawing.BufferSurface (image_width, image_height);
117
118 var context = shadow_buffer.context;
119 context.rectangle (offset, offset, pixbuf.width, pixbuf.height);
120 context.set_source_rgba (0, 0, 0, IMAGE_SHADOW_ALPHA);
121 context.fill ();
122 shadow_buffer.exponential_blur (IMAGE_SHADOW_RADIUS);
123
124 last_image_width = image_width;
125 last_image_height = image_height;
126 }
127
128 x += (width - image_width) / 2;
129
130 cr.set_source_surface (shadow_buffer.surface, x, y);
131 cr.paint ();
132
133 Gdk.Pixbuf image;
134 if (should_brighten_image (flags))
135 image = get_brightened_pixbuf (pixbuf);
136 else
137 image = pixbuf;
138
139 ctx.render_icon (cr, image, x + offset, y + offset);
140
141 if (should_draw_highlight (flags)) {
142 ctx.add_class (Gtk.STYLE_CLASS_IMAGE);
143 ctx.render_frame (cr, x + offset - border.left,
144 y + offset - border.top,
145 pixbuf.width + border.left + border.right,
146 pixbuf.height + border.top + border.bottom);
147 }
148
149 y += image_height;
150 }
151
152 private void render_title (Gtk.StyleContext ctx, Cairo.Context cr, int x,
153 ref int y, int width)
154 {
155 // Center title layout horizontally
156 int offset = (width - title_text_logical_rect.width) / 2;
157 x += title_text_logical_rect.x + int.max (0, offset);
158
159 ctx.add_class ("title-text");
160 ctx.render_layout (cr, x, y, title_text_layout);
161 ctx.remove_class ("title-text");
162
163 y += title_text_logical_rect.height;
164 }
165
166 private void render_subtitle (Gtk.StyleContext ctx, Cairo.Context cr, int x,
167 int y, int width)
168 {
169 // Center title layout horizontally
170 int offset = (width - subtitle_text_logical_rect.width) / 2;
171 x += subtitle_text_logical_rect.x + int.max (0, offset);
172
173 ctx.render_layout (cr, x, y, subtitle_text_layout);
174 }
175
176 private void update_layout_properties (Gtk.Widget widget) {
177 var ctx = widget.get_style_context ();
178 var state = ctx.get_state ();
179
180 ctx.save ();
181 ctx.add_class (Gtk.STYLE_CLASS_IMAGE);
182 margin = ctx.get_margin (state);
183 padding = ctx.get_padding (state);
184 border = ctx.get_border (state);
185
186 subtitle_text_layout = widget.create_pango_layout (subtitle);
187 unowned Pango.FontDescription font_description;
188 ctx.get (state, Gtk.STYLE_PROPERTY_FONT, out font_description);
189 subtitle_text_layout.set_font_description (font_description);
190 subtitle_text_layout.set_ellipsize (Pango.EllipsizeMode.END);
191 subtitle_text_layout.set_alignment (Pango.Alignment.LEFT);
192 int text_width = pixbuf.width * Pango.SCALE;
193 subtitle_text_layout.set_width (text_width);
194
195 ctx.add_class ("title-text");
196 title_text_layout = widget.create_pango_layout (title);
197 ctx.get (state, Gtk.STYLE_PROPERTY_FONT, out font_description);
198 title_text_layout.set_font_description (font_description);
199 title_text_layout.set_width (text_width);
200 title_text_layout.set_ellipsize (Pango.EllipsizeMode.END);
201 title_text_layout.set_alignment (Pango.Alignment.LEFT);
202 ctx.restore ();
203
204 Pango.Rectangle ink_rect;
205 title_text_layout.get_pixel_extents (out ink_rect, out title_text_logical_rect);
206 subtitle_text_layout.get_pixel_extents (out ink_rect, out subtitle_text_logical_rect);
207 }
208
209 private int compute_total_image_width () {
210 return pixbuf != null ? pixbuf.width + 2 * IMAGE_SHADOW_MARGIN : 0;
211 }
212
213 private int compute_total_image_height () {
214 return pixbuf != null ? pixbuf.height + 2 * IMAGE_SHADOW_MARGIN : 0;
215 }
216
217 private static bool should_brighten_image (Gtk.CellRendererState flags) {
218 return (flags & Gtk.CellRendererState.PRELIT) != 0;
219 }
220
221 private static bool should_draw_highlight (Gtk.CellRendererState flags) {
222 return (flags & Gtk.CellRendererState.SELECTED) != 0;
223 }
224
225 private static Gdk.Pixbuf? get_brightened_pixbuf (Gdk.Pixbuf pixbuf) {
226 if (pixbuf == null)
227 return null;
228
229 // create a new lightened pixbuf to display
230 var brightened = pixbuf.copy ();
231 ImageUtils.shift_colors (brightened, BRIGHTEN_SHIFT, BRIGHTEN_SHIFT, BRIGHTEN_SHIFT, 0);
232 return brightened;
233 }
234}
0235
=== added file 'src/Widgets/FastView/TileView/TileView.vala'
--- src/Widgets/FastView/TileView/TileView.vala 1970-01-01 00:00:00 +0000
+++ src/Widgets/FastView/TileView/TileView.vala 2013-09-26 03:02:55 +0000
@@ -0,0 +1,70 @@
1/**
2 * Copyright 2013 elementary
3 *
4 * This software is licensed under the GNU Lesser General Public License
5 * (version 3 or later). See the COPYING file in this distribution.
6 */
7
8public class Noise.Widgets.TileView : Gtk.IconView {
9 private const string STYLESHEET = """
10 /* general background color and texture */
11 .tile-view {
12 color: alpha(@fg_color, 0.95);
13 background-color: @base_color;
14 }
15
16 /* workaround: suppress default cell borders for icon view */
17 .tile-view.cell {
18 background-image: none;
19 background-color: @transparent;
20 border-width: 0;
21 border-style: solid;
22 border-color: @transparent;
23 box-shadow: inset 0 0 @transparent;
24 }
25
26 /* image selection frame */
27 .tile-view.cell.image {
28 border-width: 3px;
29 border-radius: 3px;
30 border-color: alpha(@selected_bg_color, 0.95);
31 }
32
33 /* apply bold font to titles */
34 .tile-view.cell.title-text {
35 font-weight: bold;
36 color: @fg_color;
37 }
38 """;
39
40 private Gtk.CellRenderer cell_renderer = new TileRenderer ();
41
42 public int image_column {
43 set {
44 add_attribute (cell_renderer, "pixbuf", value);
45 }
46 }
47
48 public int title_column {
49 set {
50 add_attribute (cell_renderer, "title", value);
51 }
52 }
53
54 public int subtitle_column {
55 set {
56 add_attribute (cell_renderer, "subtitle", value);
57 }
58 }
59
60 public TileView () {
61 pack_start (cell_renderer, false);
62 apply_default_theme ();
63 }
64
65 private void apply_default_theme () {
66 get_style_context ().remove_class (Gtk.STYLE_CLASS_VIEW);
67 Granite.Widgets.Utils.set_theming (this, STYLESHEET, "tile-view",
68 Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
69 }
70}
071
=== modified file 'src/Widgets/InfoPanel.vala'
--- src/Widgets/InfoPanel.vala 2013-02-26 21:56:08 +0000
+++ src/Widgets/InfoPanel.vala 2013-09-26 03:02:55 +0000
@@ -63,7 +63,6 @@
63 title = new Gtk.Label("");63 title = new Gtk.Label("");
64 artist = new Gtk.Label("");64 artist = new Gtk.Label("");
65 coverArt = new Gtk.Image();65 coverArt = new Gtk.Image();
66 coverArt.set_size_request (Icons.ALBUM_VIEW_IMAGE_SIZE, Icons.ALBUM_VIEW_IMAGE_SIZE);
67 rating = new Granite.Widgets.Rating (true, Gtk.IconSize.MENU, true); // centered = true66 rating = new Granite.Widgets.Rating (true, Gtk.IconSize.MENU, true); // centered = true
68 album = new Gtk.Label("");67 album = new Gtk.Label("");
69 year_label = new Gtk.Label("");68 year_label = new Gtk.Label("");
@@ -138,8 +137,11 @@
138 }137 }
139 138
140 private void update_cover_art () {139 private void update_cover_art () {
141 if (current_media != null)140 if (current_media != null) {
142 coverArt.set_from_pixbuf (CoverartCache.instance.get_cover (current_media));141 var cover_art = CoverartCache.instance.get_cover (current_media);
142 var cover_art_with_shadow = PixbufUtils.render_pixbuf_shadow (cover_art);
143 coverArt.set_from_pixbuf (cover_art_with_shadow);
144 }
143 }145 }
144 146
145 private void ratingChanged (int new_rating) {147 private void ratingChanged (int new_rating) {

Subscribers

People subscribed via source and target branches