TriggerBox: implement basic TriggerSlot DnD

This commit is contained in:
Robin Gareus 2022-01-11 05:20:47 +01:00
parent 96137739a7
commit 8b90ea39a2
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 116 additions and 2 deletions

View File

@ -726,6 +726,7 @@ TriggerEntry::follow_button_event (GdkEvent* ev)
TriggerBoxUI::TriggerBoxUI (ArdourCanvas::Item* parent, TriggerBox& tb)
: Rectangle (parent)
, _triggerbox (tb)
, _drag_active (false)
{
set_layout_sensitive (true); // why???
@ -750,6 +751,15 @@ TriggerBoxUI::TriggerBoxUI (ArdourCanvas::Item* parent, TriggerBox& tb)
gtkcanvas->signal_drag_motion ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_motion));
gtkcanvas->signal_drag_leave ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_leave));
gtkcanvas->signal_drag_data_received ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_data_received));
/* DnD Source */
std::vector<Gtk::TargetEntry> source_table;
source_table.push_back (Gtk::TargetEntry ("x-ardour/region.pbdid", Gtk::TARGET_SAME_APP));
_dnd_src = Gtk::TargetList::create (source_table);
gtkcanvas->signal_drag_begin ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_begin));
gtkcanvas->signal_drag_end ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_end));
gtkcanvas->signal_drag_data_get ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_data_get));
}
TriggerBoxUI::~TriggerBoxUI ()
@ -788,9 +798,7 @@ TriggerBoxUI::build ()
_slots.push_back (te);
#if 0
te->Event.connect (sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::event), n));
#endif
++n;
}
@ -910,6 +918,101 @@ TriggerBoxUI::drag_data_received (Glib::RefPtr<Gdk::DragContext> const& context,
context->drag_finish (true, false, time);
}
bool
TriggerBoxUI::event (GdkEvent* ev, uint64_t n)
{
assert (n < _slots.size ());
if (!_slots[n]->trigger()->region ()) {
return false;
}
switch (ev->type) {
case GDK_2BUTTON_PRESS:
gdk_pointer_ungrab (GDK_CURRENT_TIME);
break;
case GDK_BUTTON_RELEASE:
gdk_pointer_ungrab (GDK_CURRENT_TIME);
break;
case GDK_BUTTON_PRESS:
if (!_drag_active) {
GdkEventButton* bev = (GdkEventButton*)ev;
if (bev->button == 1) {
_drag_start_x = bev->x;
_drag_start_y = bev->y;
gdk_pointer_grab (bev->window, false, GdkEventMask (Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK), NULL, NULL, bev->time);
} else {
_drag_start_x = -1;
_drag_start_y = -1;
}
}
break;
case GDK_MOTION_NOTIFY:
if (!_drag_active) {
int x, y;
Gdk::ModifierType mask;
GtkCanvas* gtkcanvas = static_cast<GtkCanvas*> (canvas ());
gtkcanvas->get_window()->get_pointer (x, y, mask);
if (mask & GDK_BUTTON1_MASK) {
if (gtkcanvas->drag_check_threshold (_drag_start_x, _drag_start_y, x, y)) {
_drag_active = true;
gtkcanvas->drag_begin (_dnd_src, Gdk::ACTION_COPY, 1, ev);
// -> save a reference to the dragged slot, for use in ::drag_begin ::drag_data_get()
return true;
}
}
}
default:
break;
}
return false;
}
void
TriggerBoxUI::drag_begin (Glib::RefPtr<Gdk::DragContext> const& context)
{
#if 0
int width = 130;
int height = 20;
GtkCanvas* gtkcanvas = static_cast<GtkCanvas*> (canvas ());
Glib::RefPtr<Gdk::Pixmap> pixmap = Gdk::Pixmap::create (gtkcanvas->get_root_window(), width, height);
cairo_t *cr = gdk_cairo_create (Glib::unwrap (pixmap));
cairo_set_source_rgb (cr, 1, 0, 0);
cairo_rectangle (cr, 0, 0, width, height);
cairo_fill (cr);
cairo_destroy (cr);
context->set_icon (pixmap->get_colormap(), pixmap, Glib::RefPtr<Gdk::Bitmap>(NULL), width / 2, height / 2);
#endif
}
void
TriggerBoxUI::drag_end (Glib::RefPtr<Gdk::DragContext> const&)
{
_drag_active = false;
}
void
TriggerBoxUI::drag_data_get (Glib::RefPtr<Gdk::DragContext> const&, Gtk::SelectionData& data, guint, guint)
{
if (data.get_target () != "x-ardour/region.pbdid") {
return;
}
boost::shared_ptr<Region> region;
/* use selection, for now */
TriggerSelection ts = PublicEditor::instance ().get_selection ().triggers;
for (auto& te : ts) {
region = te->trigger()->region ();
}
if (region) {
data.set (data.get_target (), region->id ().to_s ());
}
}
void
TriggerBoxUI::start_updating ()
{

View File

@ -102,6 +102,12 @@ private:
ARDOUR::TriggerBox& _triggerbox;
Slots _slots;
int _drag_start_x;
int _drag_start_y;
bool _drag_active;
Glib::RefPtr<Gtk::TargetList> _dnd_src;
void build ();
void rapid_update ();
@ -111,6 +117,11 @@ private:
void drag_leave (Glib::RefPtr<Gdk::DragContext> const&, guint);
void drag_data_received (Glib::RefPtr<Gdk::DragContext> const&, int, int, Gtk::SelectionData const&, guint, guint);
bool event (GdkEvent*, uint64_t n);
void drag_begin (Glib::RefPtr<Gdk::DragContext> const&);
void drag_end (Glib::RefPtr<Gdk::DragContext> const&);
void drag_data_get (Glib::RefPtr<Gdk::DragContext> const&, Gtk::SelectionData&, guint, guint);
bool triggerbox_event (GdkEvent*);
uint64_t slot_at_y (int) const;