Add static meta-data for x-ardour/region.pbdid DnD

During drag-motion callbacks the data to be dragged is n/a.
However we like to discriminate if drop is possible.

When dragging regions, the data-type of the region to be dragged
is unknown, so different `x-ardour/region` targets are not an
option, either.

Until a better option is presented, a static global is used
to set the data-type for region.pbdid drags.
This commit is contained in:
Robin Gareus 2022-01-19 05:05:57 +01:00
parent 62a098811c
commit 50bccb44d5
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
6 changed files with 53 additions and 23 deletions

View File

@ -1211,26 +1211,18 @@ Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context,
if (can_drop) {
if (target == "x-ardour/region.pbdid") {
#if 0
// TODO check drag_source::drag_data_get() -> SelectionData& region
if (tv.first == 0 && region) {
if (tv.first == 0 && pbdid_dragged_dt != DataType::NIL) {
/* drop to drop-zone */
context->drag_status (context->get_suggested_action(), time);
context->drag_status (Gdk::ACTION_COPY, time);
return true;
}
if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 && dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
(boost::dynamic_pointer_cast<MidiRegion> (region) != 0 && dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
if ((pbdid_dragged_dt == DataType::AUDIO && dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
(pbdid_dragged_dt == DataType::MIDI && dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
/* audio to audio OR MIDI to MIDI */
context->drag_status (context->get_suggested_action(), time);
context->drag_status (Gdk::ACTION_COPY, time);
return true;
}
#else
/* region drop always works */
context->drag_status (context->get_suggested_action(), time);
#endif
return true;
} else {
/* DND originating from outside ardour
*

View File

@ -31,6 +31,8 @@ const int PublicEditor::horizontal_spacing = 6;
sigc::signal<void> PublicEditor::DropDownKeys;
ARDOUR::DataType PublicEditor::pbdid_dragged_dt = ARDOUR::DataType::NIL;
PublicEditor::PublicEditor (Gtk::Widget& content)
: Tabbable (content, _("Editor"), X_("editor"))
{

View File

@ -425,6 +425,9 @@ public:
: action (a), target (tgt) {}
};
/* data-type of [region] object currently dragged with x-ardour/region.pbdid */
static ARDOUR::DataType pbdid_dragged_dt;
std::map<std::string,RegionAction> region_action_map;
Glib::RefPtr<Gtk::ActionGroup> editor_actions;

View File

@ -48,6 +48,7 @@
#include "gui_thread.h"
#include "keyboard.h"
#include "main_clock.h"
#include "public_editor.h"
#include "region_list_base.h"
#include "ui_config.h"
#include "utils.h"
@ -82,8 +83,10 @@ RegionListBase::RegionListBase ()
_model = TreeStore::create (_columns);
_model->set_sort_column (0, SORT_ASCENDING);
_display.add_object_drag (_columns.region.index (), "x-ardour/region.pbdid", Gtk::TARGET_SAME_APP);
_display.add_object_drag (-1, "x-ardour/region.pbdid", Gtk::TARGET_SAME_APP);
_display.set_drag_column (_columns.name.index ());
_display.signal_drag_begin ().connect (sigc::mem_fun (*this, &RegionListBase::drag_begin));
_display.signal_drag_end ().connect (sigc::mem_fun (*this, &RegionListBase::drag_end));
_display.signal_drag_data_get ().connect (sigc::mem_fun (*this, &RegionListBase::drag_data_get));
_display.set_model (_model);
@ -226,19 +229,37 @@ RegionListBase::leave_notify (GdkEventCrossing*)
return false;
}
void
RegionListBase::drag_begin (Glib::RefPtr<Gdk::DragContext> const&)
{
if (_display.get_selection ()->count_selected_rows () == 0) {
PublicEditor::instance ().pbdid_dragged_dt = DataType::NIL;
}
TreeView::Selection::ListHandle_Path rows = _display.get_selection ()->get_selected_rows ();
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin (); i != rows.end (); ++i) {
boost::shared_ptr<Region> region = (*_model->get_iter (*i))[_columns.region];
PublicEditor::instance ().pbdid_dragged_dt = region->data_type ();
break;
}
}
void
RegionListBase::drag_end (Glib::RefPtr<Gdk::DragContext> const&)
{
PublicEditor::instance ().pbdid_dragged_dt = DataType::NIL;
}
void
RegionListBase::drag_data_get (Glib::RefPtr<Gdk::DragContext> const&, Gtk::SelectionData& data, guint, guint)
{
if (data.get_target () != "x-ardour/region.pbdid") {
return;
}
list<boost::shared_ptr<ARDOUR::Region>> regions;
TreeView* source;
_display.get_object_drag_data (regions, &source);
if (!regions.empty ()) {
data.set (data.get_target (), regions.front ()->id ().to_s ());
TreeView::Selection::ListHandle_Path rows = _display.get_selection ()->get_selected_rows ();
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin (); i != rows.end (); ++i) {
boost::shared_ptr<Region> region = (*_model->get_iter (*i))[_columns.region];
data.set (data.get_target (), region->id ().to_s ());
break;
}
}

View File

@ -214,6 +214,8 @@ protected:
void clock_format_changed ();
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);
virtual bool list_region (boost::shared_ptr<ARDOUR::Region>) const;

View File

@ -801,12 +801,21 @@ TriggerEntry::drag_begin (Glib::RefPtr<Gdk::DragContext> const& context)
/* ctx leaves scope, cr is destroyed, and pixmap surface is flush()ed */
}
boost::shared_ptr<Region> region = trigger ()->region ();
if (region) {
PublicEditor::instance ().pbdid_dragged_dt = region->data_type ();
} else {
PublicEditor::instance ().pbdid_dragged_dt = DataType::NIL;
}
context->set_icon (pixmap->get_colormap (), pixmap, Glib::RefPtr<Gdk::Bitmap> (NULL), width / 2, height / 2);
}
void
TriggerEntry::drag_end (Glib::RefPtr<Gdk::DragContext> const&)
{
if (_drag_active) {
PublicEditor::instance ().pbdid_dragged_dt = DataType::NIL;
}
_drag_active = false;
}
@ -942,8 +951,9 @@ TriggerBoxUI::slot_at_y (int y) const
bool
TriggerBoxUI::drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int, int y, guint time)
{
bool can_drop = true;
uint64_t n = slot_at_y (y);
bool can_drop = PublicEditor::instance ().pbdid_dragged_dt == _triggerbox.data_type ();
uint64_t n = slot_at_y (y);
if (n >= _slots.size ()) {
assert (0);
can_drop = false;