summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/gtkui/ddblistview.c63
-rw-r--r--plugins/gtkui/ddblistview.h3
-rw-r--r--plugins/gtkui/gtkui.c1
-rw-r--r--plugins/gtkui/gtkui.h2
-rw-r--r--plugins/gtkui/plcommon.c82
-rw-r--r--plugins/gtkui/plcommon.h2
6 files changed, 124 insertions, 29 deletions
diff --git a/plugins/gtkui/ddblistview.c b/plugins/gtkui/ddblistview.c
index 8f10e4b0..a7ebaa15 100644
--- a/plugins/gtkui/ddblistview.c
+++ b/plugins/gtkui/ddblistview.c
@@ -90,7 +90,7 @@ ddb_listview_list_render (DdbListview *ps, cairo_t *cr, int x, int y, int w, int
void
ddb_listview_list_render_row_background (DdbListview *ps, cairo_t *cr, DdbListviewIter it, int even, int cursor, int x, int y, int w, int h);
void
-ddb_listview_list_render_row_foreground (DdbListview *ps, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int even, int cursor, int group_y, int x, int y, int w, int h);
+ddb_listview_list_render_row_foreground (DdbListview *ps, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int even, int cursor, int group_y, int group_height, int group_pinned, int grp_next_y, int x, int y, int w, int h);
void
ddb_listview_list_track_dragdrop (DdbListview *ps, int y);
int
@@ -681,6 +681,7 @@ ddb_listview_list_render (DdbListview *listview, cairo_t *cr, int x, int y, int
// find 1st group
DdbListviewGroup *grp = listview->groups;
int grp_y = 0;
+ int grp_next_y = 0;
while (grp && grp_y + grp->height < y + listview->scrollpos) {
grp_y += grp->height;
idx += grp->num_items + 1;
@@ -691,10 +692,16 @@ ddb_listview_list_render (DdbListview *listview, cairo_t *cr, int x, int y, int
draw_begin (&listview->listctx, cr);
int ii = 0;
+ if (grp) {
+ grp->pinned = 1;
+ }
while (grp && grp_y < y + h + listview->scrollpos) {
// render title
DdbListviewIter it = grp->head;
int grpheight = grp->height;
+ int pushback = 0;
+ int group_idx = idx;
+
if (grp_y >= y + h + listview->scrollpos) {
break;
}
@@ -705,6 +712,7 @@ ddb_listview_list_render (DdbListview *listview, cairo_t *cr, int x, int y, int
listview->binding->draw_group_title (listview, cr, it, -listview->hscrollpos, grp_y - listview->scrollpos, listview->totalwidth, listview->grouptitle_height);
}
}
+
for (int i = 0; i < grp->num_items; i++) {
ii++;
// if (grp_y + listview->grouptitle_height + (i+1) * listview->rowheight >= y + h + listview->scrollpos) {
@@ -713,6 +721,10 @@ ddb_listview_list_render (DdbListview *listview, cairo_t *cr, int x, int y, int
if (grp_y + listview->grouptitle_height + i * listview->rowheight >= y + h + listview->scrollpos) {
break;
}
+ grp_next_y = grp_y + grpheight;
+ if (grp->pinned == 1 && GROUPS_PINNED && grp_next_y - listview->scrollpos <= listview->grouptitle_height) {
+ pushback = listview->grouptitle_height - (grp_next_y - listview->scrollpos);
+ }
if (grp_y + listview->grouptitle_height + (i+1) * listview->rowheight >= y + listview->scrollpos
&& grp_y + listview->grouptitle_height + i * listview->rowheight < y + h + listview->scrollpos) {
GtkStyle *st = gtk_widget_get_style (listview->list);
@@ -720,7 +732,13 @@ ddb_listview_list_render (DdbListview *listview, cairo_t *cr, int x, int y, int
cairo_rectangle (cr, -listview->hscrollpos, grp_y + listview->grouptitle_height + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight);
cairo_fill (cr);
ddb_listview_list_render_row_background (listview, cr, it, (idx + 1 + i) & 1, (abs_idx+i) == listview->binding->cursor () ? 1 : 0, -listview->hscrollpos, grp_y + listview->grouptitle_height + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight);
- ddb_listview_list_render_row_foreground (listview, cr, it, grp->head, (idx + 1 + i) & 1, (idx+i) == listview->binding->cursor () ? 1 : 0, i * listview->rowheight, -listview->hscrollpos, grp_y + listview->grouptitle_height + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight);
+ ddb_listview_list_render_row_foreground (listview, cr, it, grp->head, (idx + 1 + i) & 1, (idx+i) == listview->binding->cursor () ? 1 : 0, i * listview->rowheight, grp->height, grp->pinned, grp_next_y - listview->scrollpos, -listview->hscrollpos, grp_y + listview->grouptitle_height + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight);
+ }
+ if (grp->pinned == 1 && GROUPS_PINNED) {
+ ddb_listview_list_render_row_background (listview, cr, NULL, group_idx & 1, 0, -listview->hscrollpos, y, listview->totalwidth, listview->grouptitle_height);
+ if (listview->binding->draw_group_title && listview->grouptitle_height > 0) {
+ listview->binding->draw_group_title (listview, cr, it, -listview->hscrollpos, y - pushback, listview->totalwidth, listview->grouptitle_height);
+ }
}
DdbListviewIter next = listview->binding->next (it);
listview->binding->unref (it);
@@ -729,12 +747,11 @@ ddb_listview_list_render (DdbListview *listview, cairo_t *cr, int x, int y, int
break; // sanity check, in case groups were not rebuilt yet
}
}
- if (it) {
- listview->binding->unref (it);
- }
+
idx += grp->num_items + 1;
abs_idx += grp->num_items;
+ DdbListviewIter prev = listview->binding->prev (it);
int filler = grpheight - (listview->grouptitle_height + listview->rowheight * grp->num_items);
if (filler > 0) {
int theming = !gtkui_override_listview_colors ();
@@ -752,13 +769,33 @@ ddb_listview_list_render (DdbListview *listview, cairo_t *cr, int x, int y, int
cairo_rectangle (cr, x, grp_y - listview->scrollpos + listview->grouptitle_height + listview->rowheight * grp->num_items, w, filler);
cairo_fill (cr);
}
-
-
- ddb_listview_list_render_row_foreground (listview, cr, NULL, grp->head, 0, 0, grp->num_items * listview->rowheight, -listview->hscrollpos, grp_y - listview->scrollpos + listview->grouptitle_height + listview->rowheight * grp->num_items, listview->totalwidth, filler);
+ ddb_listview_list_render_row_foreground (listview, cr, NULL, grp->head, 0, 0, grp->num_items * listview->rowheight, grp->height, grp->pinned, grp_next_y - listview->scrollpos, -listview->hscrollpos, grp_y - listview->scrollpos + listview->grouptitle_height + listview->rowheight * grp->num_items, listview->totalwidth, filler);
+ if (grp->pinned == 1 && GROUPS_PINNED) {
+ ddb_listview_list_render_row_background (listview, cr, NULL, group_idx & 1, 0, -listview->hscrollpos, y, listview->totalwidth, listview->grouptitle_height);
+ if (listview->binding->draw_group_title && listview->grouptitle_height > 0) {
+ listview->binding->draw_group_title (listview, cr, prev, -listview->hscrollpos, y - pushback, listview->totalwidth, listview->grouptitle_height);
+ }
+ }
+ }
+ if (prev) {
+ listview->binding->unref (prev);
+ }
+ if (it) {
+ listview->binding->unref (it);
}
-
grp_y += grpheight;
- grp = grp->next;
+ if (grp->pinned == 1) {
+ grp = grp->next;
+ if (grp) {
+ grp->pinned = 2;
+ }
+ }
+ else {
+ grp = grp->next;
+ if (grp) {
+ grp->pinned = 0;
+ }
+ }
}
if (grp_y < y + h + listview->scrollpos) {
int hh = y + h - (grp_y - listview->scrollpos);
@@ -1307,7 +1344,7 @@ ddb_listview_list_render_row_background (DdbListview *ps, cairo_t *cr, DdbListvi
}
void
-ddb_listview_list_render_row_foreground (DdbListview *ps, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int even, int cursor, int group_y, int x, int y, int w, int h) {
+ddb_listview_list_render_row_foreground (DdbListview *ps, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int even, int cursor, int group_y, int group_height, int group_pinned, int grp_next_y, int x, int y, int w, int h) {
int width, height;
GtkAllocation a;
gtk_widget_get_allocation (ps->list, &a);
@@ -1327,7 +1364,7 @@ ddb_listview_list_render_row_foreground (DdbListview *ps, cairo_t *cr, DdbListvi
int cidx = 0;
for (c = ps->columns; c; c = c->next, cidx++) {
int cw = c->width;
- ps->binding->draw_column_data (ps, cr, it, ps->grouptitle_height > 0 ? group_it : NULL, cidx, group_y, x, y, cw, h);
+ ps->binding->draw_column_data (ps, cr, it, ps->grouptitle_height > 0 ? group_it : NULL, cidx, group_y, group_height, group_pinned, grp_next_y, x, y, cw, h);
x += cw;
}
}
@@ -1392,7 +1429,7 @@ ddb_listview_click_selection (DdbListview *ps, int ex, int ey, DdbListviewGroup
it = next;
}
}
- else if (sel == -1 && grp) {
+ else if ((sel == -1 && grp) || (ey <= ps->grouptitle_height && GROUPS_PINNED)) {
// clicked group title, select group
DdbListviewIter it;
int idx = 0;
diff --git a/plugins/gtkui/ddblistview.h b/plugins/gtkui/ddblistview.h
index 3e54bc07..26822d04 100644
--- a/plugins/gtkui/ddblistview.h
+++ b/plugins/gtkui/ddblistview.h
@@ -48,6 +48,7 @@ struct _DdbListviewGroup {
DdbListviewIter head;
int32_t height;
int32_t num_items;
+ int pinned;
struct _DdbListviewGroup *next;
};
@@ -84,7 +85,7 @@ typedef struct {
// callbacks
void (*draw_group_title) (DdbListview *listview, cairo_t *drawable, DdbListviewIter iter, int x, int y, int width, int height);
- void (*draw_column_data) (DdbListview *listview, cairo_t *drawable, DdbListviewIter iter, DdbListviewIter group_iter, int column, int group_y, int x, int y, int width, int height);
+ void (*draw_column_data) (DdbListview *listview, cairo_t *drawable, DdbListviewIter iter, DdbListviewIter group_iter, int column, int group_y, int group_height, int group_pinned, int grp_next_y, int x, int y, int width, int height);
void (*list_context_menu) (DdbListview *listview, DdbListviewIter iter, int idx);
void (*header_context_menu) (DdbListview *listview, int col);
void (*handle_doubleclick) (DdbListview *listview, DdbListviewIter iter, int idx);
diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c
index 1e63b337..86d12993 100644
--- a/plugins/gtkui/gtkui.c
+++ b/plugins/gtkui/gtkui.c
@@ -854,6 +854,7 @@ gtkui_message (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) {
break;
case DB_EV_CONFIGCHANGED:
g_idle_add (gtkui_on_configchanged, NULL);
+ GROUPS_PINNED = deadbeef->conf_get_int ("playlist.pin.groups",0);
break;
case DB_EV_OUTPUTCHANGED:
g_idle_add (outputchanged_cb, NULL);
diff --git a/plugins/gtkui/gtkui.h b/plugins/gtkui/gtkui.h
index f0d21eab..b2f86938 100644
--- a/plugins/gtkui/gtkui.h
+++ b/plugins/gtkui/gtkui.h
@@ -39,6 +39,8 @@ extern int gtkui_is_retina;
struct _GSList;
+int GROUPS_PINNED;
+
// misc utility functions
void
diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c
index 20c2ea5c..993394fd 100644
--- a/plugins/gtkui/plcommon.c
+++ b/plugins/gtkui/plcommon.c
@@ -85,6 +85,16 @@ redraw_playlist (void *user_data) {
g_idle_add (redraw_playlist_cb, user_data);
}
+static gboolean
+redraw_playlist_single_cb (gpointer user_data) {
+ gtk_widget_queue_draw (GTK_WIDGET(user_data));
+ return FALSE;
+}
+
+static void
+redraw_playlist_single (void *user_data) {
+ g_idle_add (redraw_playlist_cb, user_data);
+}
#define ART_PADDING_HORZ 8
#define ART_PADDING_VERT 0
@@ -138,7 +148,7 @@ deferred_cover_load_cb (void *ctx) {
return FALSE;
}
-void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int column, int group_y, int x, int y, int width, int height) {
+void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int column, int group_y, int group_height, int group_pinned, int grp_next_y, int x, int y, int width, int height) {
const char *ctitle;
int cwidth;
int calign_right;
@@ -148,6 +158,7 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D
if (res == -1) {
return;
}
+
DB_playItem_t *playing_track = deadbeef->streamer_get_playing_track ();
int theming = !gtkui_override_listview_colors ();
@@ -212,24 +223,40 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D
}
int h = cwidth - group_y;
h = min (height, art_h);
- GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, art_width, NULL, NULL);
+
+ GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, art_width, redraw_playlist_single, listview);
if (pixbuf) {
- int pw = real_art_width;
- int ph = pw;
+ int pw = gdk_pixbuf_get_width (pixbuf);
+ int ph;
+ if (group_pinned == 1 && GROUPS_PINNED) {
+ ph = group_height;
+ }
+ else {
+ ph = gdk_pixbuf_get_height (pixbuf);
+ }
+
if (sy < ph)
{
- ph -= sy;
- ph = min (ph, h);
- cairo_rectangle (cr, x + ART_PADDING_HORZ, art_y, pw, ph);
- cairo_save (cr);
- cairo_translate (cr, ((x + ART_PADDING_HORZ)-0), ((art_y)-sy));
- cairo_scale (cr, (float)art_scale, (float)art_scale);
- gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
- cairo_pattern_set_filter (cairo_get_source(cr), art_width == real_art_width ? CAIRO_FILTER_GAUSSIAN : CAIRO_FILTER_FAST);
+ pw = min (art_width, pw);
+ if (group_pinned == 1 && GROUPS_PINNED) {
+ int ph_real = gdk_pixbuf_get_height (pixbuf);
+ if (grp_next_y <= ph_real + listview->grouptitle_height) {
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, (x + ART_PADDING_HORZ)-0, grp_next_y - ph_real);
+ cairo_rectangle (cr, x + ART_PADDING_HORZ, grp_next_y - ph_real, pw, ph);
+ }
+ else {
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, (x + ART_PADDING_HORZ)-0, listview->grouptitle_height);
+ cairo_rectangle (cr, x + ART_PADDING_HORZ, listview->grouptitle_height, pw, ph);
+ }
+ }
+ else {
+ ph -= sy;
+ ph = min (ph, h);
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, (x + ART_PADDING_HORZ)-0, (art_y)-sy);
+ cairo_rectangle (cr, x + ART_PADDING_HORZ, art_y, pw, ph);
+ }
cairo_fill (cr);
- cairo_restore (cr);
}
- g_object_unref (pixbuf);
}
}
}
@@ -745,6 +772,23 @@ on_group_by_none_activate (GtkMenuItem *menuitem,
}
void
+on_pin_groups_active (GtkMenuItem *menuitem,
+ gpointer user_data)
+{
+ gboolean act = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem));
+ int old_val = deadbeef->conf_get_int ("playlist.pin.groups", 0);
+ deadbeef->conf_set_int ("playlist.pin.groups", 1-old_val);
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
+ gtk_check_menu_item_toggled(menuitem);
+ ddb_playlist_t *plt = deadbeef->plt_get_curr ();
+ if (plt) {
+ deadbeef->plt_modified (plt);
+ deadbeef->plt_unref(plt);
+ }
+ main_refresh ();
+}
+
+void
on_group_by_artist_date_album_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
@@ -1068,6 +1112,7 @@ create_headermenu (int groupby)
GtkWidget *remove_column;
GtkWidget *separator;
GtkWidget *group_by;
+ GtkWidget *pin_groups;
GtkWidget *group_by_menu;
GtkWidget *none;
GtkWidget *artist_date_album;
@@ -1094,6 +1139,11 @@ create_headermenu (int groupby)
gtk_container_add (GTK_CONTAINER (headermenu), separator);
gtk_widget_set_sensitive (separator, FALSE);
+ pin_groups = gtk_check_menu_item_new_with_mnemonic(_("Pin groups when scrolling"));
+ gtk_widget_show (pin_groups);
+ gtk_container_add (GTK_CONTAINER (headermenu), pin_groups);
+ gtk_check_menu_item_set_active (pin_groups, (gboolean)deadbeef->conf_get_int("playlist.pin.groups",0));
+
group_by = gtk_menu_item_new_with_mnemonic (_("Group by"));
gtk_widget_show (group_by);
gtk_container_add (GTK_CONTAINER (headermenu), group_by);
@@ -1121,6 +1171,10 @@ create_headermenu (int groupby)
G_CALLBACK (on_group_by_none_activate),
NULL);
+ g_signal_connect ((gpointer) pin_groups, "activate",
+ G_CALLBACK (on_pin_groups_active),
+ NULL);
+
g_signal_connect ((gpointer) artist_date_album, "activate",
G_CALLBACK (on_group_by_artist_date_album_activate),
NULL);
diff --git a/plugins/gtkui/plcommon.h b/plugins/gtkui/plcommon.h
index fb8fb385..3f82a732 100644
--- a/plugins/gtkui/plcommon.h
+++ b/plugins/gtkui/plcommon.h
@@ -35,7 +35,7 @@ write_column_config (const char *name, int idx, const char *title, int width, in
void
rewrite_column_config (DdbListview *listview, const char *name);
-void draw_column_data (DdbListview *listview, cairo_t *drawable, DdbListviewIter it, DdbListviewIter group_it, int column, int group_y, int x, int y, int width, int height);
+void draw_column_data (DdbListview *listview, cairo_t *drawable, DdbListviewIter it, DdbListviewIter group_it, int column, int group_y, int group_height, int group_pinned, int grp_next_y, int x, int y, int width, int height);
void
list_context_menu (DdbListview *listview, DdbListviewIter it, int idx);