1/*
2* Copyright 2019 elementary, Inc. (https://elementary.io)
3*
4* This program is free software; you can redistribute it and/or
5* modify it under the terms of the GNU General Public
6* License as published by the Free Software Foundation; either
7* version 3 of the License, or (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12* General Public License for more details.
13*
14* You should have received a copy of the GNU General Public
15* License along with this program; if not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17* Boston, MA 02110-1301 USA
18*
19*/
20
21public class Audience.Widgets.PlaylistItem : Gtk.ListBoxRow {
22    public bool is_playing { get; set; }
23    public string title { get; construct; }
24    public string filename { get; construct; }
25
26    private const Gtk.TargetEntry[] TARGET_ENTRIES = {
27        {"PLAYLIST_ITEM", Gtk.TargetFlags.SAME_APP, 0}
28    };
29
30    public PlaylistItem (string title, string filename) {
31        Object (
32            title: title,
33            filename: filename
34        );
35    }
36
37    construct {
38        var play_icon = new Gtk.Image.from_icon_name ("media-playback-start-symbolic", Gtk.IconSize.BUTTON);
39
40        var play_revealer = new Gtk.Revealer ();
41        play_revealer.transition_type = Gtk.RevealerTransitionType.CROSSFADE;
42        play_revealer.add (play_icon);
43
44        var track_name_label = new Gtk.Label (title);
45        track_name_label.ellipsize = Pango.EllipsizeMode.MIDDLE;
46
47        var grid = new Gtk.Grid ();
48        grid.margin = 3;
49        grid.margin_bottom = grid.margin_top = 6;
50        grid.column_spacing = 6;
51        grid.add (play_revealer);
52        grid.add (track_name_label);
53
54        // Drag source must have a GdkWindow. GTK4 will remove the limitation.
55        var dnd_event_box = new Gtk.EventBox ();
56        dnd_event_box.drag_begin.connect (on_drag_begin);
57        dnd_event_box.drag_data_get.connect (on_drag_data_get);
58        dnd_event_box.add (grid);
59
60        Gtk.drag_source_set (dnd_event_box, Gdk.ModifierType.BUTTON1_MASK, TARGET_ENTRIES, Gdk.DragAction.MOVE);
61
62        set_tooltip_text (title);
63
64        add (dnd_event_box);
65        show_all ();
66
67        bind_property ("is-playing", play_revealer, "reveal-child");
68    }
69
70    private void on_drag_begin (Gtk.Widget widget, Gdk.DragContext context) {
71        var row = (PlaylistItem) widget.get_ancestor (typeof (PlaylistItem));
72
73        Gtk.Allocation alloc;
74        row.get_allocation (out alloc);
75
76        var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, alloc.width, alloc.height);
77        var cr = new Cairo.Context (surface);
78        row.draw (cr);
79
80        int x, y;
81        widget.translate_coordinates (row, 0, 0, out x, out y);
82        surface.set_device_offset (-x, -y);
83        Gtk.drag_set_icon_surface (context, surface);
84    }
85
86    private void on_drag_data_get (Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data,
87        uint target_type, uint time) {
88        uchar[] data = new uchar[(sizeof (PlaylistItem))];
89        ((Gtk.Widget[])data)[0] = widget;
90
91        selection_data.set (
92            Gdk.Atom.intern_static_string ("PLAYLIST_ITEM"), 32, data
93        );
94    }
95}
96