TriggerBox: DnD, better version of 8b90ea39a22cl
Move start-drag logic into individual TriggerEntry instances. This allows to use local data in drag_data_get as-is.
This commit is contained in:
parent
4d04849be9
commit
5e3c49f397
|
@ -68,6 +68,7 @@ using namespace PBD;
|
||||||
TriggerEntry::TriggerEntry (Item* item, TriggerReference tr)
|
TriggerEntry::TriggerEntry (Item* item, TriggerReference tr)
|
||||||
: ArdourCanvas::Rectangle (item)
|
: ArdourCanvas::Rectangle (item)
|
||||||
, _grabbed (false)
|
, _grabbed (false)
|
||||||
|
, _drag_active (false)
|
||||||
{
|
{
|
||||||
set_layout_sensitive (true); // why???
|
set_layout_sensitive (true); // why???
|
||||||
|
|
||||||
|
@ -100,17 +101,27 @@ TriggerEntry::TriggerEntry (Item* item, TriggerReference tr)
|
||||||
/* this will trigger a call to on_trigger_changed() */
|
/* this will trigger a call to on_trigger_changed() */
|
||||||
set_trigger (tr);
|
set_trigger (tr);
|
||||||
|
|
||||||
|
/* DnD Source */
|
||||||
|
GtkCanvas* gtkcanvas = static_cast<GtkCanvas*> (canvas ());
|
||||||
|
assert (gtkcanvas);
|
||||||
|
|
||||||
|
gtkcanvas->signal_drag_begin ().connect (sigc::mem_fun (*this, &TriggerEntry::drag_begin));
|
||||||
|
gtkcanvas->signal_drag_end ().connect (sigc::mem_fun (*this, &TriggerEntry::drag_end));
|
||||||
|
gtkcanvas->signal_drag_data_get ().connect (sigc::mem_fun (*this, &TriggerEntry::drag_data_get));
|
||||||
|
|
||||||
/* event handling */
|
/* event handling */
|
||||||
play_button->Event.connect (sigc::mem_fun (*this, &TriggerEntry::play_button_event));
|
play_button->Event.connect (sigc::mem_fun (*this, &TriggerEntry::play_button_event));
|
||||||
name_button->Event.connect (sigc::mem_fun (*this, &TriggerEntry::name_button_event));
|
name_button->Event.connect (sigc::mem_fun (*this, &TriggerEntry::name_button_event));
|
||||||
follow_button->Event.connect (sigc::mem_fun (*this, &TriggerEntry::follow_button_event));
|
follow_button->Event.connect (sigc::mem_fun (*this, &TriggerEntry::follow_button_event));
|
||||||
|
|
||||||
|
Event.connect (sigc::mem_fun (*this, &TriggerEntry::event));
|
||||||
|
|
||||||
/* watch for change in theme */
|
/* watch for change in theme */
|
||||||
UIConfiguration::instance ().ParameterChanged.connect (sigc::mem_fun (*this, &TriggerEntry::ui_parameter_changed));
|
UIConfiguration::instance ().ParameterChanged.connect (sigc::mem_fun (*this, &TriggerEntry::ui_parameter_changed));
|
||||||
set_widget_colors ();
|
set_widget_colors ();
|
||||||
|
|
||||||
/* owner color changes (?) */
|
/* owner color changes (?) */
|
||||||
dynamic_cast<Stripable*> (tref.box->owner ())->presentation_info ().Change.connect (owner_prop_connection, MISSING_INVALIDATOR, boost::bind (&TriggerEntry::owner_prop_change, this, _1), gui_context ());
|
dynamic_cast<Stripable*> (tref.box->owner ())->presentation_info ().Change.connect (_owner_prop_connection, MISSING_INVALIDATOR, boost::bind (&TriggerEntry::owner_prop_change, this, _1), gui_context ());
|
||||||
|
|
||||||
selection_change ();
|
selection_change ();
|
||||||
}
|
}
|
||||||
|
@ -699,12 +710,109 @@ TriggerEntry::follow_button_event (GdkEvent* ev)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TriggerEntry::event (GdkEvent* ev)
|
||||||
|
{
|
||||||
|
if (!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);
|
||||||
|
return true;
|
||||||
|
} 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 (TriggerBoxUI::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
|
||||||
|
TriggerEntry::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
|
||||||
|
TriggerEntry::drag_end (Glib::RefPtr<Gdk::DragContext> const&)
|
||||||
|
{
|
||||||
|
_drag_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TriggerEntry::drag_data_get (Glib::RefPtr<Gdk::DragContext> const&, Gtk::SelectionData& data, guint, guint)
|
||||||
|
{
|
||||||
|
if (!_drag_active) {
|
||||||
|
/* Since the canvas is shared, all TriggerEntry instances
|
||||||
|
* inside a TriggerBox canvas receive this signal.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.get_target () != "x-ardour/region.pbdid") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<Region> region = trigger ()->region ();
|
||||||
|
if (region) {
|
||||||
|
data.set (data.get_target (), region->id ().to_s ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ***************************************************** */
|
/* ***************************************************** */
|
||||||
|
|
||||||
|
Glib::RefPtr<Gtk::TargetList> TriggerBoxUI::_dnd_src;
|
||||||
|
|
||||||
TriggerBoxUI::TriggerBoxUI (ArdourCanvas::Item* parent, TriggerBox& tb)
|
TriggerBoxUI::TriggerBoxUI (ArdourCanvas::Item* parent, TriggerBox& tb)
|
||||||
: Rectangle (parent)
|
: Rectangle (parent)
|
||||||
, _triggerbox (tb)
|
, _triggerbox (tb)
|
||||||
, _drag_active (false)
|
|
||||||
{
|
{
|
||||||
set_layout_sensitive (true); // why???
|
set_layout_sensitive (true); // why???
|
||||||
|
|
||||||
|
@ -715,6 +823,14 @@ TriggerBoxUI::TriggerBoxUI (ArdourCanvas::Item* parent, TriggerBox& tb)
|
||||||
|
|
||||||
_selection_connection = PublicEditor::instance ().get_selection ().TriggersChanged.connect (sigc::mem_fun (*this, &TriggerBoxUI::selection_changed));
|
_selection_connection = PublicEditor::instance ().get_selection ().TriggersChanged.connect (sigc::mem_fun (*this, &TriggerBoxUI::selection_changed));
|
||||||
|
|
||||||
|
/* DnD */
|
||||||
|
|
||||||
|
if (!_dnd_src) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Gtk::TargetEntry> target_table;
|
std::vector<Gtk::TargetEntry> target_table;
|
||||||
target_table.push_back (Gtk::TargetEntry ("x-ardour/region.erl", Gtk::TARGET_SAME_APP));
|
target_table.push_back (Gtk::TargetEntry ("x-ardour/region.erl", Gtk::TARGET_SAME_APP));
|
||||||
target_table.push_back (Gtk::TargetEntry ("x-ardour/region.esl", Gtk::TARGET_SAME_APP));
|
target_table.push_back (Gtk::TargetEntry ("x-ardour/region.esl", Gtk::TARGET_SAME_APP));
|
||||||
|
@ -729,15 +845,6 @@ TriggerBoxUI::TriggerBoxUI (ArdourCanvas::Item* parent, TriggerBox& tb)
|
||||||
gtkcanvas->signal_drag_motion ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_motion));
|
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_leave ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_leave));
|
||||||
gtkcanvas->signal_drag_data_received ().connect (sigc::mem_fun (*this, &TriggerBoxUI::drag_data_received));
|
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 ()
|
TriggerBoxUI::~TriggerBoxUI ()
|
||||||
|
@ -775,8 +882,6 @@ TriggerBoxUI::build ()
|
||||||
|
|
||||||
_slots.push_back (te);
|
_slots.push_back (te);
|
||||||
|
|
||||||
te->Event.connect (sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::event), n));
|
|
||||||
|
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -895,101 +1000,6 @@ TriggerBoxUI::drag_data_received (Glib::RefPtr<Gdk::DragContext> const& context,
|
||||||
context->drag_finish (true, false, time);
|
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 ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ********************************************** */
|
/* ********************************************** */
|
||||||
|
|
||||||
TriggerBoxWidget::TriggerBoxWidget (float w, float h)
|
TriggerBoxWidget::TriggerBoxWidget (float w, float h)
|
||||||
|
|
|
@ -74,20 +74,31 @@ public:
|
||||||
|
|
||||||
void set_widget_colors (TriggerEntry::EnteredState es=NoneEntered);
|
void set_widget_colors (TriggerEntry::EnteredState es=NoneEntered);
|
||||||
|
|
||||||
bool play_button_event (GdkEvent*);
|
|
||||||
bool name_button_event (GdkEvent*);
|
bool name_button_event (GdkEvent*);
|
||||||
bool follow_button_event (GdkEvent*);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _grabbed;
|
bool _grabbed;
|
||||||
double _poly_size;
|
double _poly_size;
|
||||||
double _poly_margin;
|
double _poly_margin;
|
||||||
|
|
||||||
PBD::ScopedConnection owner_prop_connection;
|
int _drag_start_x;
|
||||||
void owner_prop_change (PBD::PropertyChange const&);
|
int _drag_start_y;
|
||||||
void owner_color_changed ();
|
bool _drag_active;
|
||||||
|
|
||||||
|
bool event (GdkEvent*);
|
||||||
|
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);
|
||||||
|
|
||||||
void ui_parameter_changed (std::string const& p);
|
void ui_parameter_changed (std::string const& p);
|
||||||
|
|
||||||
|
bool play_button_event (GdkEvent*);
|
||||||
|
bool follow_button_event (GdkEvent*);
|
||||||
|
|
||||||
|
void owner_prop_change (PBD::PropertyChange const&);
|
||||||
|
void owner_color_changed ();
|
||||||
|
|
||||||
|
PBD::ScopedConnection _owner_prop_connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TriggerBoxUI : public ArdourCanvas::Rectangle
|
class TriggerBoxUI : public ArdourCanvas::Rectangle
|
||||||
|
@ -98,17 +109,18 @@ public:
|
||||||
|
|
||||||
void _size_allocate (ArdourCanvas::Rect const&);
|
void _size_allocate (ArdourCanvas::Rect const&);
|
||||||
|
|
||||||
|
static Glib::RefPtr<Gtk::TargetList> dnd_src ()
|
||||||
|
{
|
||||||
|
return _dnd_src;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<TriggerEntry*> Slots;
|
typedef std::vector<TriggerEntry*> Slots;
|
||||||
|
|
||||||
ARDOUR::TriggerBox& _triggerbox;
|
ARDOUR::TriggerBox& _triggerbox;
|
||||||
Slots _slots;
|
Slots _slots;
|
||||||
|
|
||||||
int _drag_start_x;
|
static Glib::RefPtr<Gtk::TargetList> _dnd_src;
|
||||||
int _drag_start_y;
|
|
||||||
bool _drag_active;
|
|
||||||
|
|
||||||
Glib::RefPtr<Gtk::TargetList> _dnd_src;
|
|
||||||
|
|
||||||
void build ();
|
void build ();
|
||||||
|
|
||||||
|
@ -118,11 +130,6 @@ private:
|
||||||
void drag_leave (Glib::RefPtr<Gdk::DragContext> const&, guint);
|
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);
|
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*);
|
bool triggerbox_event (GdkEvent*);
|
||||||
|
|
||||||
uint64_t slot_at_y (int) const;
|
uint64_t slot_at_y (int) const;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user