1 /*
2     DeaDBeeF -- the music player
3     Copyright (C) 2009-2015 Alexey Yakovenko and other contributors
4 
5     This software is provided 'as-is', without any express or implied
6     warranty.  In no event will the authors be held liable for any damages
7     arising from the use of this software.
8 
9     Permission is granted to anyone to use this software for any purpose,
10     including commercial applications, and to alter it and redistribute it
11     freely, subject to the following restrictions:
12 
13     1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17 
18     2. Altered source versions must be plainly marked as such, and must not be
19      misrepresented as being the original software.
20 
21     3. This notice may not be removed or altered from any source distribution.
22 */
23 
24 #ifndef __DDBLISTVIEW_H
25 #define __DDBLISTVIEW_H
26 
27 #include <gtk/gtk.h>
28 #include <sys/time.h>
29 #include <stdint.h>
30 #include "drawing.h"
31 #include "../../deadbeef.h"
32 
33 // drag and drop targets
34 #define TARGET_PLAYITEMS "DDB_PLAYITEM_LIST"
35 enum {
36     TARGET_URILIST,
37     TARGET_SAMEWIDGET,
38 };
39 
40 G_BEGIN_DECLS
41 
42 #define DDB_TYPE_LISTVIEW (ddb_listview_get_type ())
43 #define DDB_LISTVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), DDB_TYPE_LISTVIEW, DdbListview))
44 #define DDB_LISTVIEW_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST((obj), DDB_TYPE_LISTVIEW, DdbListviewClass))
45 #define DDB_IS_LISTVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DDB_TYPE_LISTVIEW))
46 #define DDB_IS_LISTVIEW_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), DDB_TYPE_LISTVIEW))
47 #define DDB_LISTVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DDB_TYPE_LISTVIEW, DdbListviewClass))
48 
49 typedef struct {
50     int id; // predefined col type
51     char *format;
52     char *bytecode;
53 } col_info_t;
54 
55 typedef struct _DdbListview DdbListview;
56 typedef struct _DdbListviewClass DdbListviewClass;
57 
58 typedef void * DdbListviewIter;
59 typedef void * DdbPlaylistHandle;
60 
61 struct _DdbListviewGroup {
62     DdbListviewIter head;
63     int32_t height;
64     int32_t min_height;
65     int32_t num_items;
66     int pinned;
67     struct _DdbListviewGroup *next;
68 };
69 
70 typedef struct _DdbListviewGroup DdbListviewGroup;
71 //typedef void * DdbListviewColIter;
72 
73 typedef struct {
74     // rows
75     int (*count) (void);
76     int (*sel_count) (void);
77 
78     int (*cursor) (void);
79     void (*set_cursor) (int cursor);
80 
81     DdbListviewIter (*head) (void);
82     DdbListviewIter (*tail) (void);
83     DdbListviewIter (*next) (DdbListviewIter);
84     DdbListviewIter (*prev) (DdbListviewIter);
85 
86     DdbListviewIter (*get_for_idx) (int idx);
87     int (*get_idx) (DdbListviewIter);
88 
89     void (*ref) (DdbListviewIter);
90     void (*unref) (DdbListviewIter);
91 
92     void (*select) (DdbListviewIter, int sel);
93     int (*is_selected) (DdbListviewIter);
94 
95     int (*get_group) (DdbListview *listview, DdbListviewIter it, char *str, int size);
96 
97     // drag-n-drop
98     void (*drag_n_drop) (DdbListviewIter before, DdbPlaylistHandle playlist_from, uint32_t *indices, int length, int copy);
99     void (*external_drag_n_drop) (DdbListviewIter before, char *mem, int length);
100 
101     // callbacks
102     void (*draw_group_title) (DdbListview *listview, cairo_t *drawable, DdbListviewIter iter, int pl_iter, int x, int y, int width, int height);
103     void (*draw_album_art) (DdbListview *listview, cairo_t *drawable, DdbListviewIter group_iter, int column, int group_pinned, int grp_next_y, int x, int y, int width, int height);
104     void (*draw_column_data) (DdbListview *listview, cairo_t *drawable, DdbListviewIter iter, int idx, int column, int pl_iter, int x, int y, int width, int height);
105     void (*list_context_menu) (DdbListview *listview, DdbListviewIter iter, int idx);
106     void (*header_context_menu) (DdbListview *listview, int col);
107     void (*handle_doubleclick) (DdbListview *listview, DdbListviewIter iter, int idx);
108     void (*selection_changed) (DdbListview *listview, DdbListviewIter it, int idx);
109     void (*delete_selected) (void);
110     void (*groups_changed) (DdbListview *listview, const char *format);
111     void (*columns_changed) (DdbListview *listview);
112     void (*col_sort) (int col, int sort_order, void *user_data);
113     void (*col_free_user_data) (void *user_data);
114     void (*vscroll_changed) (int pos);
115     void (*cursor_changed) (int pos);
116     int (*modification_idx) (void);
117 } DdbListviewBinding;
118 
119 struct _DdbListviewColumn;
120 struct _DdbListviewGroup;
121 
122 struct _DdbListview {
123     GtkTable parent;
124 
125     // interaction with client
126     DdbListviewBinding *binding;
127 
128     // cached gtk/gdk object pointers
129     GtkWidget *list;
130     GtkWidget *header;
131     GtkWidget *scrollbar;
132     GtkWidget *hscrollbar;
133 
134     int totalwidth; // width of listview, including invisible (scrollable) part
135     const char *title; // unique id, used for config writing, etc
136     int lastpos[2]; // last mouse position (for list widget)
137     // current state
138     int scrollpos;
139     int hscrollpos;
140     int rowheight;
141 
142     int col_movepos;
143 
144     int drag_motion_y;
145 
146     int ref_point; // idx of anchor when columns are resized
147     int ref_point_offset; // y pixel-coordinate of anchor relative to view
148 
149     // scrolling
150     int scroll_mode; // 0=select, 1=dragndrop
151     int scroll_pointer_y;
152     float scroll_direction;
153     int scroll_active;
154     struct timeval tm_prevscroll;
155     float scroll_sleep_time;
156 
157     // selection
158     int areaselect; // boolean, whether area selection is active (1), or not (0)
159     int areaselect_y; // pixel-coordinate of anchor click relative to playlist origin
160     int dragwait; // set to 1 when mouse was pressed down on already selected track, but not moved since (so we're waiting for dnd to begin)
161     int drag_source_playlist;
162     int shift_sel_anchor;
163 
164     // header
165     int header_dragging;
166     int header_sizing;
167     int header_dragpt[2];
168     float last_header_motion_ev; //is it subject to remove?
169     int prev_header_x;
170     int header_prepare;
171     int header_width; // previous width before resize
172     int col_autoresize;
173 
174     struct _DdbListviewColumn *columns;
175     gboolean lock_columns;
176 
177     ddb_playlist_t *plt; // current playlist (refcounted), must be unreffed with the group
178     struct _DdbListviewGroup *groups;
179     int groups_build_idx; // must be the same as playlist modification idx
180     int fullheight;
181     int block_redraw_on_scroll;
182     int grouptitle_height;
183     int calculated_grouptitle_height;
184 
185     // previous area selection range
186     int area_selection_start;
187     int area_selection_end;
188 
189     GdkCursor *cursor_sz;
190     GdkCursor *cursor_drag;
191 
192     // drawing contexts
193     drawctx_t listctx;
194     drawctx_t grpctx;
195     drawctx_t hdrctx;
196 
197     // cover art size
198     int cover_size;
199     int new_cover_size;
200     guint cover_refresh_timeout_id;
201 
202     // group format string that's supposed to get parsed by tf
203     char *group_format;
204     // tf bytecode for group title
205     char *group_title_bytecode;
206 
207     guint tf_redraw_timeout_id;
208     int tf_redraw_track_idx;
209     DdbListviewIter tf_redraw_track;
210 };
211 
212 struct _DdbListviewClass {
213   GtkTableClass parent_class;
214 };
215 
216 GType ddb_listview_get_type(void);
217 
218 GtkWidget * ddb_listview_new();
219 
220 void
221 ddb_listview_set_binding (DdbListview *listview, DdbListviewBinding *binding);
222 void
223 ddb_listview_draw_row (DdbListview *listview, int idx, DdbListviewIter iter);
224 int
225 ddb_listview_get_vscroll_pos (DdbListview *listview);
226 int
227 ddb_listview_get_hscroll_pos (DdbListview *listview);
228 DdbListviewIter
229 ddb_listview_get_iter_from_coord (DdbListview *listview, int x, int y);
230 int
231 ddb_listview_handle_keypress (DdbListview *ps, int keyval, int state);
232 void
233 ddb_listview_set_cursor (DdbListview *pl, int cursor);
234 void
235 ddb_listview_set_cursor_noscroll (DdbListview *pl, int cursor);
236 void
237 ddb_listview_scroll_to (DdbListview *listview, int rowpos);
238 void
239 ddb_listview_set_vscroll (DdbListview *listview, int scroll);
240 int
241 ddb_listview_is_scrolling (DdbListview *listview);
242 int
243 ddb_listview_column_get_count (DdbListview *listview);
244 void
245 ddb_listview_column_append (DdbListview *listview, const char *title, int width, int align_right, int minheight, int color_override, GdkColor color, void *user_data);
246 void
247 ddb_listview_column_insert (DdbListview *listview, int before, const char *title, int width, int align_right, int minheight, int color_override, GdkColor color, void *user_data);
248 void
249 ddb_listview_column_remove (DdbListview *listview, int idx);
250 int
251 ddb_listview_column_get_info (DdbListview *listview, int col, const char **title, int *width, int *align_right, int *minheight, int *color_override, GdkColor *color, void **user_data);
252 int
253 ddb_listview_column_set_info (DdbListview *listview, int col, const char *title, int width, int align_right, int minheight, int color_override, GdkColor color, void *user_data);
254 void
255 ddb_listview_show_header (DdbListview *listview, int show);
256 void
257 ddb_listview_init_autoresize (DdbListview *ps, int totalwidth);
258 
259 enum {
260     DDB_REFRESH_COLUMNS = 1,
261     DDB_REFRESH_HSCROLL = 2,
262     DDB_REFRESH_VSCROLL = 4,
263     DDB_REFRESH_LIST    = 8,
264     DDB_LIST_CHANGED    = 16,
265 };
266 
267 void ddb_listview_refresh (DdbListview *listview, uint32_t flags);
268 
269 gboolean
270 ddb_listview_list_drag_drop                  (GtkWidget       *widget,
271                                         GdkDragContext  *drag_context,
272                                         gint             x,
273                                         gint             y,
274                                         guint            time,
275                                         gpointer         user_data);
276 
277 void
278 ddb_listview_list_drag_data_get              (GtkWidget       *widget,
279                                         GdkDragContext  *drag_context,
280                                         GtkSelectionData *data,
281                                         guint            info,
282                                         guint            time,
283                                         gpointer         user_data);
284 
285 void
286 ddb_listview_list_drag_end                   (GtkWidget       *widget,
287                                         GdkDragContext  *drag_context,
288                                         gpointer         user_data);
289 
290 void
291 ddb_listview_list_drag_data_received         (GtkWidget       *widget,
292                                         GdkDragContext  *drag_context,
293                                         gint             x,
294                                         gint             y,
295                                         GtkSelectionData *data,
296                                         guint            target_type,
297                                         guint            time,
298                                         gpointer         user_data);
299 
300 void
301 ddb_listview_list_drag_leave                 (GtkWidget       *widget,
302                                         GdkDragContext  *drag_context,
303                                         guint            time,
304                                         gpointer         user_data);
305 
306 void
307 ddb_listview_list_drag_end                   (GtkWidget       *widget,
308                                         GdkDragContext  *drag_context,
309                                         gpointer         user_data);
310 
311 void
312 ddb_listview_clear_sort (DdbListview *listview);
313 
314 void
315 ddb_listview_lock_columns (DdbListview *lv, gboolean lock);
316 
317 int
318 ddb_listview_get_row_pos (DdbListview *listview, int row_idx);
319 
320 void
321 ddb_listview_groupcheck (DdbListview *listview);
322 
323 int
324 ddb_listview_is_album_art_column (DdbListview *listview, int x);
325 
326 int
327 ddb_listview_is_album_art_column_idx (DdbListview *listview, int cidx);
328 
329 void
330 ddb_listview_update_fonts (DdbListview *ps);
331 
332 void
333 ddb_listview_header_update_fonts (DdbListview *ps);
334 
335 void
336 ddb_listview_cancel_autoredraw (DdbListview *listview);
337 
338 G_END_DECLS
339 
340 #endif // __DDBLISTVIEW_H
341