diff options
-rw-r--r-- | plugins/gtkui/ddblistview.c | 63 | ||||
-rw-r--r-- | plugins/gtkui/ddblistview.h | 3 | ||||
-rw-r--r-- | plugins/gtkui/gtkui.c | 1 | ||||
-rw-r--r-- | plugins/gtkui/gtkui.h | 2 | ||||
-rw-r--r-- | plugins/gtkui/plcommon.c | 82 | ||||
-rw-r--r-- | plugins/gtkui/plcommon.h | 2 |
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); |