diff options
author | 2010-02-24 22:24:58 +0100 | |
---|---|---|
committer | 2010-02-24 22:24:58 +0100 | |
commit | f1f2c6a311853bea2c6e1d4b746dc6083395a8d1 (patch) | |
tree | b479082e7bf16b28e43d17bab0d466cb0cfc15ab /plugins/gtkui | |
parent | 48e960ff2cbb08d7a442df93d2113af507ccfe92 (diff) |
playlist grouping WIP
Diffstat (limited to 'plugins/gtkui')
-rw-r--r-- | plugins/gtkui/ddblistview.c | 455 | ||||
-rw-r--r-- | plugins/gtkui/ddblistview.h | 15 | ||||
-rw-r--r-- | plugins/gtkui/gtkui.c | 2 | ||||
-rw-r--r-- | plugins/gtkui/mainplaylist.c | 28 |
4 files changed, 369 insertions, 131 deletions
diff --git a/plugins/gtkui/ddblistview.c b/plugins/gtkui/ddblistview.c index 9965d21d..56afb20b 100644 --- a/plugins/gtkui/ddblistview.c +++ b/plugins/gtkui/ddblistview.c @@ -47,6 +47,9 @@ #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) +#define GROUP_TITLE_HEIGHT 30 +#define SCROLL_STEP 5 + #define trace(...) { fprintf(stderr, __VA_ARGS__); } //#define trace(fmt,...) @@ -75,6 +78,14 @@ struct _DdbListviewColumn { }; typedef struct _DdbListviewColumn DdbListviewColumn; +struct _DdbListviewGroup { + DdbListviewIter head; + uint16_t num_items; + uint8_t _padding; + struct _DdbListviewGroup *next; +}; +typedef struct _DdbListviewGroup DdbListviewGroup; + static void ddb_listview_class_init(DdbListviewClass *klass); static void ddb_listview_init(DdbListview *listview); static void ddb_listview_size_request(GtkWidget *widget, @@ -82,8 +93,6 @@ static void ddb_listview_size_request(GtkWidget *widget, static void ddb_listview_size_allocate(GtkWidget *widget, GtkAllocation *allocation); static void ddb_listview_realize(GtkWidget *widget); -static gboolean ddb_listview_expose(GtkWidget *widget, - GdkEventExpose *event); static void ddb_listview_paint(GtkWidget *widget); static void ddb_listview_destroy(GtkObject *object); @@ -97,11 +106,11 @@ ddb_listview_list_render (DdbListview *ps, int x, int y, int w, int h); void ddb_listview_list_expose (DdbListview *ps, int x, int y, int w, int h); void -ddb_listview_list_render_row_background (DdbListview *ps, int row, DdbListviewIter it); +ddb_listview_list_render_row_background (DdbListview *ps, DdbListviewIter it, int even, int cursor, int x, int y, int w, int h); void -ddb_listview_list_render_row_foreground (DdbListview *ps, int row, DdbListviewIter it); +ddb_listview_list_render_row_foreground (DdbListview *ps, DdbListviewIter it, int even, int cursor, int x, int y, int w, int h); void -ddb_listview_list_render_row (DdbListview *ps, int row, DdbListviewIter it); +ddb_listview_list_render_row (DdbListview *ps, int row, DdbListviewIter it, int expose); void ddb_listview_list_track_dragdrop (DdbListview *ps, int y); void @@ -114,6 +123,8 @@ void ddb_listview_list_set_hscroll (DdbListview *ps, int newscroll); void ddb_listview_set_cursor (DdbListview *pl, int cursor); +int +ddb_listview_get_row_pos (DdbListview *listview, int pos); ////// header functions //// void @@ -305,6 +316,9 @@ ddb_listview_init(DdbListview *listview) listview->prev_header_x = -1; listview->header_prepare = 0; + listview->columns = NULL; + listview->groups = NULL; + GtkWidget *hbox; GtkWidget *vbox; @@ -451,6 +465,14 @@ ddb_listview_destroy(GtkObject *object) void ddb_listview_refresh (DdbListview *listview, uint32_t flags) { + if (flags & DDB_REFRESH_LIST) { + int height = listview->fullheight; + ddb_listview_build_groups (listview); + if (height != listview->fullheight) { + flags |= DDB_REFRESH_VSCROLL; + } + ddb_listview_list_render (listview, 0, 0, listview->list->allocation.width, listview->list->allocation.height); + } if (flags & DDB_REFRESH_VSCROLL) { ddb_listview_list_setup_vscroll (listview); } @@ -460,9 +482,6 @@ ddb_listview_refresh (DdbListview *listview, uint32_t flags) { if (flags & DDB_REFRESH_COLUMNS) { ddb_listview_header_render (listview); } - if (flags & DDB_REFRESH_LIST) { - ddb_listview_list_render (listview, 0, 0, listview->list->allocation.width, listview->list->allocation.height); - } if (flags & DDB_EXPOSE_COLUMNS) { ddb_listview_header_expose (listview, 0, 0, listview->header->allocation.width, listview->header->allocation.height); } @@ -501,55 +520,104 @@ ddb_listview_list_configure_event (GtkWidget *widget, g_object_unref (ps->backbuf); ps->backbuf = NULL; } - ps->nvisiblerows = ceil (widget->allocation.height / (float)ps->rowheight); - ps->nvisiblefullrows = floor (widget->allocation.height / (float)ps->rowheight); ps->backbuf = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, -1); ddb_listview_list_render (ps, 0, 0, widget->allocation.width, widget->allocation.height); return FALSE; } +// returns Y coordinate of an item by its index +int +ddb_listview_get_row_pos (DdbListview *listview, int row_idx) { + int y = 0; + int idx = 0; + DdbListviewGroup *grp = listview->groups; + while (grp) { + if (idx + grp->num_items > row_idx) { + return y + GROUP_TITLE_HEIGHT + (row_idx - idx) * listview->rowheight; + } + y += GROUP_TITLE_HEIGHT + grp->num_items * listview->rowheight; + idx += grp->num_items; + grp = grp->next; + } +} + +// returns -1 if nothing was hit, otherwise returns pointer to a group, and item idx +// item idx may be set to -1 if group title was hit +static int +ddb_listview_list_pickpoint_y (DdbListview *listview, int y, DdbListviewGroup **group, int *group_idx, int *global_idx) { + int idx = 0; + int grp_y = 0; + DdbListviewGroup *grp = listview->groups; + while (grp) { + int h = grp_y + GROUP_TITLE_HEIGHT + grp->num_items * listview->rowheight; + if (y >= grp_y && y < grp_y + h) { + *group = grp; + y -= grp_y; + if (y < GROUP_TITLE_HEIGHT) { + *group_idx = -1; + *global_idx = -1; + } + else { + *group_idx = (y - GROUP_TITLE_HEIGHT) / listview->rowheight; + *global_idx = idx + *group_idx; + } + printf ("pickpoint returns %d/%d\n", *group_idx, *global_idx); + return 0; + } + grp_y += GROUP_TITLE_HEIGHT + grp->num_items * listview->rowheight; + idx += grp->num_items; + grp = grp->next; + } + printf ("pickpoint returns -1\n"); + return -1; +} + void -ddb_listview_list_render (DdbListview *ps, int x, int y, int w, int h) { - if (!ps->backbuf) { +ddb_listview_list_render (DdbListview *listview, int x, int y, int w, int h) { + if (!listview->backbuf) { return; } - draw_begin ((uintptr_t)ps->backbuf); - int row; - int row1; - int row2; - int row2_full; - row1 = max (0, y / ps->rowheight + ps->scrollpos); - int cnt = ps->binding->count (); - row2 = min (cnt, (y+h) / ps->rowheight + ps->scrollpos + 1); - row2_full = (y+h) / ps->rowheight + ps->scrollpos + 1; - // draw background - DdbListviewIter it = ps->binding->get_for_idx (ps->scrollpos); - DdbListviewIter it_copy = it; - if (it_copy) { - REF (it_copy); + int idx = 0; + // find 1st group + DdbListviewGroup *grp = listview->groups; + int grp_y = 0; + while (grp && grp_y + GROUP_TITLE_HEIGHT + grp->num_items * listview->rowheight < y + listview->scrollpos) { + grp_y += GROUP_TITLE_HEIGHT + grp->num_items * listview->rowheight; + idx += grp->num_items; + grp = grp->next; + } + if (!grp) { + return; } - for (row = row1; row < row2_full; row++) { - ddb_listview_list_render_row_background (ps, row, it); - if (it) { - UNREF (it); - it = PL_NEXT (it); + if (listview->list->style->bg_gc[GTK_STATE_NORMAL]) { + gdk_draw_rectangle (listview->backbuf, listview->list->style->bg_gc[GTK_STATE_NORMAL], TRUE, x, y, w, h); + } + draw_begin ((uintptr_t)listview->backbuf); + + while (grp && grp_y < y + h + listview->scrollpos) { + // render title + DdbListviewIter it = grp->head; + listview->binding->ref (it); + int grpheight = GROUP_TITLE_HEIGHT + grp->num_items * listview->rowheight; + printf ("group: %d items, height=%d\n", grp->num_items, grpheight); + if (grp_y + GROUP_TITLE_HEIGHT >= y + listview->scrollpos && grp_y < y + h + listview->scrollpos) { + listview->binding->draw_group_title (listview, listview->backbuf, it, -listview->hscrollpos, grp_y - listview->scrollpos, listview->totalwidth, GROUP_TITLE_HEIGHT); } - } - UNREF (it); - it = it_copy; - int idx = 0; - for (row = row1; row < row2; row++, idx++) { - if (!it) { - break; + for (int i = 0; i < grp->num_items; i++) { + if (grp_y + GROUP_TITLE_HEIGHT + (i+1) * listview->rowheight >= y + listview->scrollpos && grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight< y + h + listview->scrollpos) { + printf ("draw: %d %d | %d,%d - %d x %d\n", (idx + i) & 1, idx == listview->binding->cursor () ? 1 : 0, -listview->hscrollpos, grp_y + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight); + ddb_listview_list_render_row_background (listview, it, i & 1, idx == listview->binding->cursor () ? 1 : 0, -listview->hscrollpos, grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight); + ddb_listview_list_render_row_foreground (listview, it, i & 1, idx == listview->binding->cursor () ? 1 : 0, -listview->hscrollpos, grp_y + GROUP_TITLE_HEIGHT + i * listview->rowheight - listview->scrollpos, listview->totalwidth, listview->rowheight); + } + DdbListviewIter next = listview->binding->next (it); + listview->binding->unref (it); + it = next; } - ddb_listview_list_render_row_foreground (ps, row, it); - DdbListviewIter next = PL_NEXT (it); - UNREF (it); - it = next; - } - UNREF (it); - + idx += grp->num_items; + grp_y += grpheight; + grp = grp->next; + } draw_end (); } @@ -606,31 +674,32 @@ ddb_listview_vscroll_value_changed (GtkRange *widget, gpointer user_data) { DdbListview *ps = DDB_LISTVIEW (gtk_object_get_data (GTK_OBJECT (widget), "owner")); - int newscroll = gtk_range_get_value (GTK_RANGE (widget)); + int newscroll = gtk_range_get_value (GTK_RANGE (widget)) * SCROLL_STEP; if (newscroll != ps->scrollpos) { GtkWidget *widget = ps->list; - int di = newscroll - ps->scrollpos; + int di = (newscroll - ps->scrollpos) * SCROLL_STEP; int d = abs (di); - if (d < ps->nvisiblerows) { + int height = ps->list->allocation.height; + if (d < height) { if (di > 0) { - draw_drawable (ps->backbuf, widget->style->black_gc, ps->backbuf, 0, d * ps->rowheight, 0, 0, widget->allocation.width, widget->allocation.height-d * ps->rowheight); + draw_drawable (ps->backbuf, widget->style->black_gc, ps->backbuf, 0, d, 0, 0, widget->allocation.width, widget->allocation.height-d); int i; ps->scrollpos = newscroll; - int start = ps->nvisiblerows-d-1; - start = max (0, ps->nvisiblerows-d-1); - for (i = start; i <= ps->nvisiblerows; i++) { + int start = height-d-1; + start = max (0, height-d-1); + for (i = start; i <= height; i++) { DdbListviewIter it = ps->binding->get_for_idx (i + ps->scrollpos); - ddb_listview_list_render_row (ps, i+ps->scrollpos, it); + ddb_listview_list_render_row (ps, i+ps->scrollpos, it, 0); UNREF (it); } } else { - draw_drawable (ps->backbuf, widget->style->black_gc, ps->backbuf, 0, 0, 0, d*ps->rowheight, widget->allocation.width, widget->allocation.height); + draw_drawable (ps->backbuf, widget->style->black_gc, ps->backbuf, 0, 0, 0, d, widget->allocation.width, widget->allocation.height); ps->scrollpos = newscroll; int i; for (i = 0; i <= d+1; i++) { DdbListviewIter it = ps->binding->get_for_idx (i+ps->scrollpos); - ddb_listview_list_render_row (ps, i+ps->scrollpos, it); + ddb_listview_list_render_row (ps, i+ps->scrollpos, it, 0); UNREF (it); } } @@ -736,6 +805,8 @@ ddb_listview_list_drag_data_received (GtkWidget *widget, guint time, gpointer user_data) { +// FIXME: port +#if 0 DdbListview *ps = DDB_LISTVIEW (gtk_object_get_data (GTK_OBJECT (widget), "owner")); gchar *ptr=(char*)data->data; if (target_type == 0) { // uris @@ -763,6 +834,7 @@ ddb_listview_list_drag_data_received (GtkWidget *widget, ps->binding->drag_n_drop (drop_before, d, length); } gtk_drag_finish (drag_context, TRUE, FALSE, time); +#endif } gboolean @@ -882,6 +954,20 @@ colhdr_anim_swap (DdbListview *pl, int c1, int c2, int x1, int x2) { void ddb_listview_list_setup_vscroll (DdbListview *ps) { GtkWidget *list = ps->list; + GtkWidget *scroll = ps->scrollbar; + if (ps->fullheight <= ps->list->allocation.height) { + gtk_widget_hide (scroll); + ps->scrollpos = 0; + } + else { + int h = list->allocation.height / SCROLL_STEP + (list->allocation.height % SCROLL_STEP); + int vheight = ps->fullheight / SCROLL_STEP + (ps->fullheight % SCROLL_STEP); + GtkAdjustment *adj = (GtkAdjustment*)gtk_adjustment_new (gtk_range_get_value (GTK_RANGE (scroll)), 0, vheight, 1, h, h); + gtk_range_set_adjustment (GTK_RANGE (scroll), adj); + gtk_widget_show (scroll); + } + +#if 0 int h = list->allocation.height / ps->rowheight; int cnt = ps->binding->count (); int size = cnt; @@ -906,6 +992,7 @@ ddb_listview_list_setup_vscroll (DdbListview *ps) { gtk_range_set_adjustment (GTK_RANGE (scroll), adj); gtk_widget_show (scroll); } +#endif } void @@ -940,38 +1027,84 @@ ddb_listview_list_setup_hscroll (DdbListview *ps) { } } +// returns -1 if row not found +int +ddb_listview_list_get_drawinfo (DdbListview *listview, int row, int *even, int *cursor, int *x, int *y, int *w, int *h) { + printf ("get_di: %d\n", row); + DdbListviewGroup *grp = listview->groups; + int idx = 0; + *y = -listview->scrollpos; + while (grp) { + int grpheight = GROUP_TITLE_HEIGHT + grp->num_items * listview->rowheight; + if (idx <= row && idx + grp->num_items > row) { + // found + *even = (row - idx) & 1; + *cursor = row == listview->binding->cursor (); + *x = -listview->hscrollpos; + *y += GROUP_TITLE_HEIGHT + (row - idx) * listview->rowheight; + *w = listview->totalwidth; + *h = listview->rowheight; + printf ("-- %d %d %d %d\n", *x, *y, *w, *h); + return 0; + } + *y += grpheight; + idx += grp->num_items; + grp = grp->next; + } + return -1; +} + void -ddb_listview_list_render_row (DdbListview *ps, int row, DdbListviewIter it) { - draw_begin ((uintptr_t)ps->backbuf); - ddb_listview_list_render_row_background (ps, row, it); +ddb_listview_list_render_row (DdbListview *listview, int row, DdbListviewIter it, int expose) { + int even; + int cursor; + int x, y, w, h; + if (ddb_listview_list_get_drawinfo (listview, row, &even, &cursor, &x, &y, &w, &h) == -1) { + return; + } + printf ("rendering row @ %d\n", y); + + draw_begin ((uintptr_t)listview->backbuf); + ddb_listview_list_render_row_background (listview, it, even, cursor, x, y, w, h); if (it) { - ddb_listview_list_render_row_foreground (ps, row, it); + ddb_listview_list_render_row_foreground (listview, it, even, cursor, x, y, w, h); } draw_end (); + if (expose) { + draw_drawable (listview->list->window, listview->list->style->black_gc, listview->backbuf, 0, y, 0, y, listview->list->allocation.width, h); + } } void -ddb_listview_list_expose_row (DdbListview *ps, int row, DdbListviewIter it) { - int x, y, w, h; - GtkWidget *widget = ps->list; - x = 0; - y = (row - ps->scrollpos) * ps->rowheight; - w = widget->allocation.width; - h = ps->rowheight; - draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, x, y, x, y, w, h); +ddb_listview_draw_row (DdbListview *listview, int row, DdbListviewIter it) { + ddb_listview_list_render_row (listview, row, it, 1); } +// coords passed are window-relative void -ddb_listview_draw_row (DdbListview *ps, int row, DdbListviewIter it) { - if (row < ps->scrollpos || row >= ps->scrollpos+ps->nvisiblerows) { - return; +ddb_listview_list_render_row_background (DdbListview *ps, DdbListviewIter it, int even, int cursor, int x, int y, int w, int h) { + // draw background + GtkWidget *treeview = theme_treeview; + if (treeview->style->depth == -1) { + return; // drawing was called too early + } + GTK_OBJECT_FLAGS (treeview) |= GTK_HAS_FOCUS; + // clear area -- workaround for New Wave theme +#if 0 + if (ps->list->style->bg_gc[GTK_STATE_NORMAL]) { + gdk_draw_rectangle (ps->backbuf, ps->list->style->bg_gc[GTK_STATE_NORMAL], TRUE, x, y, w, h); + } +#endif + gtk_paint_flat_box (treeview->style, ps->backbuf, (it && ps->binding->is_selected(it)) ? GTK_STATE_SELECTED : GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, treeview, even ? "cell_even_ruled" : "cell_odd_ruled", x, y, w, h); + if (cursor) { + // not all gtk engines/themes render focus rectangle in treeviews + // but we want it anyway + gdk_draw_rectangle (ps->backbuf, treeview->style->fg_gc[GTK_STATE_NORMAL], FALSE, x, y, w-1, h-1); } - ddb_listview_list_render_row (ps, row, it); - ddb_listview_list_expose_row (ps, row, it); } void -ddb_listview_list_render_row_background (DdbListview *ps, int row, DdbListviewIter it) { +ddb_listview_list_render_row_background_old (DdbListview *ps, int row, DdbListviewIter it) { // draw background GtkWidget *treeview = theme_treeview; if (treeview->style->depth == -1) { @@ -995,11 +1128,7 @@ ddb_listview_list_render_row_background (DdbListview *ps, int row, DdbListviewIt } void -ddb_listview_list_render_row_foreground (DdbListview *ps, int row, DdbListviewIter it) { - if (row-ps->scrollpos >= ps->nvisiblerows || row-ps->scrollpos < 0) { -// fprintf (stderr, "WARNING: attempt to draw row outside of screen bounds (%d)\n", row-ps->scrollpos); - return; - } +ddb_listview_list_render_row_foreground (DdbListview *ps, DdbListviewIter it, int even, int cursor, int x, int y, int w, int h) { int width, height; draw_get_canvas_size ((uintptr_t)ps->backbuf, &width, &height); if (it && ps->binding->is_selected (it)) { @@ -1012,12 +1141,11 @@ ddb_listview_list_render_row_foreground (DdbListview *ps, int row, DdbListviewIt float rgb[3] = { clr->red/65535.f, clr->green/65535.f, clr->blue/65535.f }; draw_set_fg_color (rgb); } - int x = -ps->hscrollpos; DdbListviewColumn *c; int cidx = 0; for (c = ps->columns; c; c = c->next, cidx++) { int cw = c->width; - ps->binding->draw_column_data (ps, ps->backbuf, it, row, cidx, x - ps->hscrollpos, row * ps->rowheight - ps->scrollpos * ps->rowheight, cw, ps->rowheight); + ps->binding->draw_column_data (ps, ps->backbuf, it, cidx, x, y, cw, h); x += cw; } } @@ -1082,17 +1210,22 @@ ddb_listview_list_mouse1_pressed (DdbListview *ps, int state, int ex, int ey, do ps->lastpos[0] = ex; ps->lastpos[1] = ey; // select item - int y = ey/ps->rowheight + ps->scrollpos; - if (y < 0 || y >= ps->binding->count ()) { - y = -1; +// int y = ey + ps->scrollpos; + DdbListviewGroup *grp; + int grp_index; + int sel; + if (ddb_listview_list_pickpoint_y (ps, ey + ps->scrollpos, &grp, &grp_index, &sel) == -1) { + return; } + printf ("pickpoint: %p %d %d\n", grp, grp_index, sel); + int cursor = ps->binding->cursor (); if (time - ps->clicktime < 0.5 && fabs(ps->lastpos[0] - ex) < 3 && fabs(ps->lastpos[1] - ey) < 3) { // doubleclick - play this item - if (y != -1 && cursor != -1) { + if (sel != -1 && cursor != -1) { int idx = cursor; DdbListviewIter it = ps->binding->get_for_idx (idx); if (ps->binding->handle_doubleclick && it) { @@ -1111,49 +1244,82 @@ ddb_listview_list_mouse1_pressed (DdbListview *ps, int state, int ex, int ey, do ps->clicktime = time; } - int sel = y; - if (y == -1) { - y = ps->binding->count () - 1; - } +// if (sel == -1) { +// sel = ps->binding->count () - 1; +// } int prev = cursor; - ps->binding->set_cursor (y); - ps->shift_sel_anchor = ps->binding->cursor (); + if (sel != -1) { + ps->binding->set_cursor (sel); + ps->shift_sel_anchor = ps->binding->cursor (); + } // handle multiple selection if (!(state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK))) { - DdbListviewIter it = ps->binding->get_for_idx (sel); - if (!it || !ps->binding->is_selected (it)) { - // reset selection, and set it to single item - ddb_listview_select_single (ps, sel); - ps->areaselect = 1; - ps->areaselect_x = ex; - ps->areaselect_y = ey; - ps->areaselect_dx = -1; - ps->areaselect_dy = -1; - ps->shift_sel_anchor = ps->binding->cursor (); + printf ("single click without modifiers, sel=%d, grp=%p\n", sel, grp); + if (sel == -1 && grp) { + printf ("select group\n"); + DdbListviewIter it; + int idx = 0; + int cnt = -1; + for (it = ps->binding->head (); it; idx++) { + if (it == grp->head) { + cnt = grp->num_items; + } + if (cnt > 0) { + if (!ps->binding->is_selected (it)) { + ps->binding->select (it, 1); + ddb_listview_draw_row (ps, idx, it); + ps->binding->selection_changed (it, idx); + } + cnt--; + } + else { + if (ps->binding->is_selected (it)) { + ps->binding->select (it, 0); + ddb_listview_draw_row (ps, idx, it); + ps->binding->selection_changed (it, idx); + } + } + DdbListviewIter next = ps->binding->next (it); + ps->binding->unref (it); + it = next; + } } else { - ps->dragwait = 1; - DdbListviewIter item = ps->binding->get_for_idx (prev); - ddb_listview_draw_row (ps, prev, item); - UNREF (item); - int cursor = ps->binding->cursor (); - if (cursor != prev) { - DdbListviewIter item = ps->binding->get_for_idx (cursor); - ddb_listview_draw_row (ps, cursor, item); + DdbListviewIter it = ps->binding->get_for_idx (sel); + if (!it || !ps->binding->is_selected (it)) { + // reset selection, and set it to single item + ddb_listview_select_single (ps, sel); + ps->areaselect = 1; + ps->areaselect_x = ex; + ps->areaselect_y = ey; + ps->areaselect_dx = -1; + ps->areaselect_dy = -1; + ps->shift_sel_anchor = ps->binding->cursor (); + } + else { + ps->dragwait = 1; + DdbListviewIter item = ps->binding->get_for_idx (prev); + ddb_listview_draw_row (ps, prev, item); UNREF (item); + int cursor = ps->binding->cursor (); + if (cursor != prev) { + DdbListviewIter item = ps->binding->get_for_idx (cursor); + ddb_listview_draw_row (ps, cursor, item); + UNREF (item); + } } + UNREF (it); } - UNREF (it); } else if (state & GDK_CONTROL_MASK) { // toggle selection - if (y != -1) { - DdbListviewIter it = ps->binding->get_for_idx (y); + if (sel != -1) { + DdbListviewIter it = ps->binding->get_for_idx (sel); if (it) { ps->binding->select (it, 1 - ps->binding->is_selected (it)); - ddb_listview_draw_row (ps, y, it); - ps->binding->selection_changed (it, y); + ddb_listview_draw_row (ps, sel, it); + ps->binding->selection_changed (it, sel); UNREF (it); } } @@ -1430,11 +1596,12 @@ ddb_listview_handle_keypress (DdbListview *ps, int keyval, int state) { if (state & GDK_SHIFT_MASK) { if (cursor != prev) { int newscroll = ps->scrollpos; - if (cursor < ps->scrollpos) { - newscroll = cursor; + int cursor_scroll = ddb_listview_get_row_pos (ps, cursor); + if (cursor_scroll < ps->scrollpos) { + newscroll = cursor_scroll; } - else if (cursor >= ps->scrollpos + ps->nvisiblefullrows) { - newscroll = cursor - ps->nvisiblefullrows + 1; + else if (cursor_scroll >= ps->scrollpos + ps->list->allocation.height) { + newscroll = cursor_scroll - ps->list->allocation.height + 1; if (newscroll < 0) { newscroll = 0; } @@ -1910,6 +2077,7 @@ struct set_cursor_t { static gboolean ddb_listview_set_cursor_cb (gpointer data) { +#if 0 // FIXME: port struct set_cursor_t *sc = (struct set_cursor_t *)data; sc->pl->binding->set_cursor (sc->cursor); ddb_listview_select_single (sc->pl, sc->cursor); @@ -1944,6 +2112,7 @@ ddb_listview_set_cursor_cb (gpointer data) { } free (data); +#endif return FALSE; } @@ -2053,9 +2222,11 @@ ddb_listview_get_iter_from_coord (DdbListview *listview, int x, int y) { void ddb_listview_scroll_to (DdbListview *listview, int pos) { +#if 0 // FIXME: port if (pos < listview->scrollpos || pos >= listview->scrollpos + listview->nvisiblefullrows) { gtk_range_set_value (GTK_RANGE (listview->scrollbar), pos - listview->nvisiblerows/2); } +#endif } int ddb_listview_is_scrolling (DdbListview *listview) { @@ -2237,3 +2408,53 @@ ddb_listview_column_set_info (DdbListview *listview, int col, const char *title, return -1; } /////// end of column management code + +/////// grouping ///// +void +ddb_listview_free_groups (DdbListview *listview) { + DdbListviewGroup *next; + while (listview->groups) { + next = listview->groups->next; + if (listview->groups->head) { + listview->binding->unref (listview->groups->head); + } + free (listview->groups); + listview->groups = next; + } +} + +void +ddb_listview_build_groups (DdbListview *listview) { + ddb_listview_free_groups (listview); + listview->fullheight = 0; + + DdbListviewGroup *grp = NULL; + char str[1024]; + char curr[1024]; + + DdbListviewIter it = listview->binding->head (); + while (it) { + listview->binding->get_group (it, curr, sizeof (curr)); + if (!grp || strcmp (str, curr)) { + strcpy (str, curr); + DdbListviewGroup *newgroup = malloc (sizeof (DdbListviewGroup)); + if (grp) { + grp->next = newgroup; + } + else { + listview->groups = newgroup; + } + grp = newgroup; + memset (grp, 0, sizeof (DdbListviewGroup)); + grp->head = it; + listview->binding->ref (it); + grp->num_items = 0; + listview->fullheight += GROUP_TITLE_HEIGHT; + } + grp->num_items++; + listview->fullheight += listview->rowheight; + DdbListviewIter next = listview->binding->next (it); + listview->binding->unref (it); + it = next; + } +} diff --git a/plugins/gtkui/ddblistview.h b/plugins/gtkui/ddblistview.h index a8146131..91b656d0 100644 --- a/plugins/gtkui/ddblistview.h +++ b/plugins/gtkui/ddblistview.h @@ -65,12 +65,15 @@ typedef struct { void (*select) (DdbListviewIter, int sel); int (*is_selected) (DdbListviewIter); + void (*get_group) (DdbListviewIter it, char *str, int size); + // drag-n-drop void (*drag_n_drop) (DdbListviewIter before, uint32_t *indices, int length); void (*external_drag_n_drop) (DdbListviewIter before, char *mem, int length); // callbacks - void (*draw_column_data) (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter iter, int idx, int column, int x, int y, int width, int height); + void (*draw_group_title) (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter iter, int x, int y, int width, int height); + void (*draw_column_data) (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter iter, int column, 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); @@ -82,6 +85,7 @@ typedef struct { } DdbListviewBinding; struct _DdbListviewColumn; +struct _DdbListviewGroup; struct _DdbListview { GtkTable parent; @@ -104,8 +108,8 @@ struct _DdbListview { int scrollpos; int hscrollpos; double clicktime; // for doubleclick detection - int nvisiblerows; - int nvisiblefullrows; +// int nvisiblerows; +// int nvisiblefullrows; int rowheight; int col_movepos; @@ -138,7 +142,8 @@ struct _DdbListview { int header_prepare; struct _DdbListviewColumn *columns; - struct _DdbListviewColumn *active_column; + struct _DdbListviewGroup *groups; + int fullheight; }; struct _DdbListviewClass { @@ -177,6 +182,8 @@ int ddb_listview_column_get_info (DdbListview *listview, int col, const char **title, int *width, int *align_right, void **user_data); int ddb_listview_column_set_info (DdbListview *listview, int col, const char *title, int width, int align_right, void *user_data); +void +ddb_listview_build_groups (DdbListview *listview); enum { DDB_REFRESH_COLUMNS = 1, diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c index 3a643dfe..8d213ba9 100644 --- a/plugins/gtkui/gtkui.c +++ b/plugins/gtkui/gtkui.c @@ -352,6 +352,7 @@ gtkui_on_activate (DB_event_t *ev, uintptr_t data) { void redraw_queued_tracks (DdbListview *pl, int list) { +#if 0 // FIXME: port DdbListviewIter it = deadbeef->pl_get_for_idx_and_iter (pl->scrollpos, list); int i = ddb_listview_get_vscroll_pos (pl); while (it && i < pl->scrollpos + pl->nvisiblerows) { @@ -366,6 +367,7 @@ redraw_queued_tracks (DdbListview *pl, int list) { if (it) { deadbeef->pl_item_unref (it); } +#endif } static gboolean diff --git a/plugins/gtkui/mainplaylist.c b/plugins/gtkui/mainplaylist.c index afc3daa8..0457ce70 100644 --- a/plugins/gtkui/mainplaylist.c +++ b/plugins/gtkui/mainplaylist.c @@ -297,15 +297,7 @@ void main_selection_changed (DdbListviewIter it, int idx) { ddb_listview_draw_row (search, idx, it); } -void main_draw_column_data (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter it, int idx, int column, int x, int y, int width, int height) { - if (deadbeef->pl_is_group_title ((DB_playItem_t *)it)) { - if (column == 0) { - float clr[] = {0, 0.1, 0.5}; - draw_set_fg_color (clr); - draw_text (x + 5, y + height/2 - draw_get_font_size ()/2 - 2, 1000, 0, ((DB_playItem_t *)it)->fname); - } - return; - } +void main_draw_column_data (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter it, int column, int x, int y, int width, int height) { const char *ctitle; int cwidth; int calign_right; @@ -331,7 +323,7 @@ void main_draw_column_data (DdbListview *listview, GdkDrawable *drawable, DdbLis } else { char text[1024]; - deadbeef->pl_format_title (it, idx, text, sizeof (text), cinf->id, cinf->format); + deadbeef->pl_format_title (it, -1, text, sizeof (text), cinf->id, cinf->format); if (calign_right) { draw_text (x+5, y + height/2 - draw_get_font_size ()/2 - 2, cwidth-10, 1, text); @@ -342,6 +334,14 @@ void main_draw_column_data (DdbListview *listview, GdkDrawable *drawable, DdbLis } } +void main_draw_group_title (DdbListview *listview, GdkDrawable *drawable, DdbListviewIter it, int x, int y, int width, int height) { + char str[1024]; + deadbeef->pl_format_title ((DB_playItem_t *)it, -1, str, sizeof (str), -1, "%a - [%y] %b"); + float clr[] = {0, 0.1, 0.5}; + draw_set_fg_color (clr); + draw_text (x + 5, y + height/2 - draw_get_font_size ()/2 - 2, width-10, 0, str); +} + #if 0 void on_group_by_none_activate (GtkMenuItem *menuitem, @@ -621,6 +621,11 @@ main_is_selected (DdbListviewIter it) { return deadbeef->pl_is_selected ((DB_playItem_t *)it); } +void +main_get_group (DdbListviewIter it, char *str, int size) { + deadbeef->pl_format_title ((DB_playItem_t *)it, -1, str, size, -1, "%a - [%y] %b"); +} + DdbListviewBinding main_binding = { // rows .count = main_get_count, @@ -640,10 +645,13 @@ DdbListviewBinding main_binding = { .is_selected = main_is_selected, .select = main_select, + .get_group = main_get_group, + .drag_n_drop = main_drag_n_drop, .external_drag_n_drop = main_external_drag_n_drop, .draw_column_data = main_draw_column_data, + .draw_group_title = main_draw_group_title, // columns .col_sort = main_col_sort, |