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