summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2006-09-20 16:24:24 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2006-09-20 16:24:24 +0000
commit41bc62b35b8194fd607aa2541e2057abd680078a (patch)
tree6f49ccdc649438f75eb7beb9a2019d94a94fbf37
parentd89e7ff299727139f98c9b1a72d93ca538bdb177 (diff)
fixes for drag-n-drop broken by use of boost::shared_ptr<T>
git-svn-id: svn://localhost/ardour2/trunk@923 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/SConscript19
-rw-r--r--gtk2_ardour/editor.h21
-rw-r--r--gtk2_ardour/editor_canvas.cc5
-rw-r--r--gtk2_ardour/redirect_box.cc6
-rw-r--r--gtk2_ardour/redirect_box.h4
-rw-r--r--libs/gtkmm2ext/dndtreeview.cc85
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/dndtreeview.h148
7 files changed, 155 insertions, 133 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
index c1eba1ea1d..eb82230e49 100644
--- a/gtk2_ardour/SConscript
+++ b/gtk2_ardour/SConscript
@@ -7,6 +7,7 @@ import glob
Import('env install_prefix final_prefix config_prefix libraries i18n version')
gtkardour = env.Copy()
+gtkmmtests = env.Copy()
#
# this defines the version number of the GTK interface to ardour
@@ -49,6 +50,19 @@ gtkardour.Merge ([
libraries['jack']
])
+gtkmmtests.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+
+gtkmmtests.Merge ([
+ libraries['gtkmm2'],
+ libraries['glib2'],
+ libraries['glibmm2'],
+ libraries['pangomm'],
+ libraries['atkmm'],
+ libraries['gdkmm2'],
+ libraries['sigc2'],
+ libraries['gtk2']
+])
+
if gtkardour['DMALLOC']:
gtkardour.Merge([libraries['dmalloc']])
gtkardour.Append(CCFLAGS='-DUSE_DMALLOC')
@@ -213,6 +227,10 @@ stest_files=Split("""
stest.cc
""")
+tt_files=Split ("""
+tt.cc
+""")
+
extra_sources = []
vst_files = [ 'vst_pluginui.cc' ]
@@ -249,6 +267,7 @@ ardourlib = gtkardour.SharedLibrary(target = 'ardourgtk', source = gtkardour_fil
mtest = gtkardour.Program(target = 'mtest', source = mtest_files)
itest = gtkardour.Program(target = 'itest', source = itest_files)
rcu = gtkardour.Program(target = 'rcu', source = rcu_files)
+tt = gtkmmtests.Program(target = 'tt', source = tt_files)
my_subst_dict = { }
my_subst_dict['%INSTALL_PREFIX%'] = install_prefix
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index dacfde8327..f5fb65e7e9 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -702,14 +702,15 @@ class Editor : public PublicEditor
}
Gtk::TreeModelColumn<Glib::ustring> name;
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Region> > region;
- Gtk::TreeModelColumn<Gdk::Color> color_;
+ Gtk::TreeModelColumn<Gdk::Color> color_;
};
- RegionListDisplayModelColumns region_list_columns;
- Gtkmm2ext::DnDTreeView region_list_display;
- Glib::RefPtr<Gtk::TreeStore> region_list_model;
- Glib::RefPtr<Gtk::ToggleAction> toggle_full_region_list_action;
- Glib::RefPtr<Gtk::ToggleAction> toggle_show_auto_regions_action;
+ RegionListDisplayModelColumns region_list_columns;
+ Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Region> > region_list_display;
+
+ Glib::RefPtr<Gtk::TreeStore> region_list_model;
+ Glib::RefPtr<Gtk::ToggleAction> toggle_full_region_list_action;
+ Glib::RefPtr<Gtk::ToggleAction> toggle_show_auto_regions_action;
void region_list_selection_changed ();
bool region_list_selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
@@ -772,7 +773,7 @@ class Editor : public PublicEditor
NamedSelectionDisplayModelColumns named_selection_columns;
Glib::RefPtr<Gtk::TreeStore> named_selection_model;
- Gtkmm2ext::DnDTreeView named_selection_display;
+ Gtkmm2ext::DnDTreeView<ARDOUR::NamedSelection*> named_selection_display;
Gtk::ScrolledWindow named_selection_scroller;
void name_selection();
@@ -1429,9 +1430,9 @@ class Editor : public PublicEditor
Glib::RefPtr<Gtk::TreeSelection> route_display_selection;
gint route_list_compare_func (Gtk::TreeModel::iterator, Gtk::TreeModel::iterator);
- Gtkmm2ext::DnDTreeView route_list_display;
- Gtk::ScrolledWindow route_list_scroller;
- Gtk::Menu* route_list_menu;
+ Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Route> > route_list_display;
+ Gtk::ScrolledWindow route_list_scroller;
+ Gtk::Menu* route_list_menu;
bool route_list_display_button_press (GdkEventButton*);
bool route_list_selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index 6798242642..26995c39ef 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -488,11 +488,12 @@ Editor::drop_regions (const RefPtr<Gdk::DragContext>& context,
const SelectionData& data,
guint info, guint time)
{
- const DnDTreeView::SerializedObjectPointers* sr = reinterpret_cast<const DnDTreeView::SerializedObjectPointers*> (data.get_data());
+ const SerializedObjectPointers<boost::shared_ptr<Region> >* sr =
+ reinterpret_cast<const SerializedObjectPointers<boost::shared_ptr<Region> > *> (data.get_data());
for (uint32_t i = 0; i < sr->cnt; ++i) {
- boost::shared_ptr<Region> r (reinterpret_cast<Region*> (sr->ptr[i]));
+ boost::shared_ptr<Region> r = sr->data[i];
boost::shared_ptr<AudioRegion> ar;
if ((ar = boost::dynamic_pointer_cast<AudioRegion>(r)) != 0) {
diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc
index 48562f1ffb..fcd04c9bd7 100644
--- a/gtk2_ardour/redirect_box.cc
+++ b/gtk2_ardour/redirect_box.cc
@@ -156,9 +156,9 @@ RedirectBox::~RedirectBox ()
}
void
-RedirectBox::object_drop (string type, uint32_t cnt, void** ptr)
+RedirectBox::object_drop (string type, uint32_t cnt, const boost::shared_ptr<Redirect>* ptr)
{
- if (type != "redirects" || cnt == 0 || ptr == 0) {
+ if (type != "redirects" || cnt == 0 || !ptr) {
return;
}
@@ -167,7 +167,7 @@ RedirectBox::object_drop (string type, uint32_t cnt, void** ptr)
list<boost::shared_ptr<Redirect> > redirects;
for (uint32_t n = 0; n < cnt; ++n) {
- redirects.push_back (boost::shared_ptr<Redirect> ((Redirect*) ptr[n]));
+ redirects.push_back (ptr[n]);
}
paste_redirect_list (redirects);
diff --git a/gtk2_ardour/redirect_box.h b/gtk2_ardour/redirect_box.h
index 51c17cad51..ead3b0dfb8 100644
--- a/gtk2_ardour/redirect_box.h
+++ b/gtk2_ardour/redirect_box.h
@@ -119,10 +119,10 @@ class RedirectBox : public Gtk::HBox
Gtk::EventBox redirect_eventbox;
Gtk::HBox redirect_hpacker;
- Gtkmm2ext::DnDTreeView redirect_display;
+ Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Redirect> > redirect_display;
Gtk::ScrolledWindow redirect_scroller;
- void object_drop (std::string type, uint32_t cnt, void**);
+ void object_drop (std::string type, uint32_t cnt, const boost::shared_ptr<ARDOUR::Redirect>*);
Width _width;
diff --git a/libs/gtkmm2ext/dndtreeview.cc b/libs/gtkmm2ext/dndtreeview.cc
index 83955861cf..7baedd4121 100644
--- a/libs/gtkmm2ext/dndtreeview.cc
+++ b/libs/gtkmm2ext/dndtreeview.cc
@@ -10,7 +10,7 @@ using namespace Gtk;
using namespace Glib;
using namespace Gtkmm2ext;
-DnDTreeView::DnDTreeView ()
+DnDTreeViewBase::DnDTreeViewBase ()
: TreeView ()
{
draggable.push_back (TargetEntry ("GTK_TREE_MODEL_ROW", TARGET_SAME_WIDGET));
@@ -23,7 +23,7 @@ DnDTreeView::DnDTreeView ()
}
void
-DnDTreeView::add_drop_targets (list<TargetEntry>& targets)
+DnDTreeViewBase::add_drop_targets (list<TargetEntry>& targets)
{
for (list<TargetEntry>::iterator i = targets.begin(); i != targets.end(); ++i) {
draggable.push_back (*i);
@@ -33,7 +33,7 @@ DnDTreeView::add_drop_targets (list<TargetEntry>& targets)
}
void
-DnDTreeView::add_object_drag (int column, string type_name)
+DnDTreeViewBase::add_object_drag (int column, string type_name)
{
draggable.push_back (TargetEntry (type_name, TargetFlags(0)));
data_column = column;
@@ -42,86 +42,11 @@ DnDTreeView::add_object_drag (int column, string type_name)
enable_model_drag_dest (draggable);
}
-DnDTreeView::SerializedObjectPointers*
-DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHandle_Path* selection, ustring type)
-{
- uint32_t cnt = selection->size();
- uint32_t sz = (sizeof (void*) * cnt) + sizeof (SerializedObjectPointers);
-
- cerr << "lets plan to serialize " << cnt << " from selection\n";
-
- char* buf = new char[sz];
- SerializedObjectPointers* sr = new (buf) SerializedObjectPointers;
-
- sr->cnt = cnt;
- sr->size = sz;
-
- snprintf (sr->type, sizeof (sr->type), "%s", type.c_str());
-
- cnt = 0;
-
- for (TreeSelection::ListHandle_Path::iterator x = selection->begin(); x != selection->end(); ++x, ++cnt) {
- cerr << "getting next item\n";
- TreeModel::Row row = *(model->get_iter (*x));
- row.get_value (data_column, sr->ptr[cnt]);
- }
-
- cerr << "returning an SR with size = " << sr->size << endl;
- return sr;
-}
-
-void
-DnDTreeView::on_drag_data_get(const RefPtr<DragContext>& context, SelectionData& selection_data, guint info, guint time)
-{
- if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
-
- TreeView::on_drag_data_get (context, selection_data, info, time);
-
- } else if (data_column >= 0) {
-
- Gtk::TreeSelection::ListHandle_Path selection = get_selection()->get_selected_rows ();
- SerializedObjectPointers* sr = serialize_pointers (get_model(), &selection, selection_data.get_target());
- selection_data.set (8, (guchar*)sr, sr->size);
-
- cerr << "selection data set to contain " << sr->size << endl;
- }
-}
-
-void
-DnDTreeView::on_drag_data_received(const RefPtr<DragContext>& context, int x, int y, const SelectionData& selection_data, guint info, guint time)
-{
- if (suggested_action) {
- /* this is a drag motion callback. just update the status to
- say that we are still dragging, and that's it.
- */
- suggested_action = Gdk::DragAction (0);
- TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
- return;
- }
-
- if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
-
- TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
-
- } else if (data_column >= 0) {
-
- /* object D-n-D */
-
- const SerializedObjectPointers* sr = reinterpret_cast<const SerializedObjectPointers *>(selection_data.get_data());
-
- if (sr) {
- signal_object_drop (sr->type, sr->cnt, const_cast<void**>(sr->ptr));
- }
-
- } else {
- /* some kind of target type added by the app, which will be handled by a signal handler */
- }
-}
-
bool
-DnDTreeView::on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
+DnDTreeViewBase::on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
{
suggested_action = Gdk::DragAction (0);
return TreeView::on_drag_drop (context, x, y, time);
}
+
diff --git a/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h b/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
index 82bb7651b9..f8beb75873 100644
--- a/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
+++ b/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
@@ -9,60 +9,136 @@
namespace Gtkmm2ext {
-class DnDTreeView : public Gtk::TreeView
-{
+template<class DataType>
+struct SerializedObjectPointers {
+ uint32_t size;
+ uint32_t cnt;
+ char type[32];
+ DataType data[0];
+};
+class DnDTreeViewBase : public Gtk::TreeView
+{
private:
public:
- DnDTreeView ();
- ~DnDTreeView() {}
+ DnDTreeViewBase ();
+ ~DnDTreeViewBase() {}
- /* this is the structure pointed to if add_object_drag() is called
- and a drop happens on a destination which has declared itself
- willing to accept a target of the type named in the call
- to add_object_drag().
- */
-
- struct SerializedObjectPointers {
- uint32_t size;
- uint32_t cnt;
- char type[32];
- void* ptr[0];
- };
-
void add_drop_targets (std::list<Gtk::TargetEntry>&);
void add_object_drag (int column, std::string type_name);
- sigc::signal<void,std::string,uint32_t,void**> signal_object_drop;
- void on_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context) {
- TreeView::on_drag_begin (context);
- }
- void on_drag_end(const Glib::RefPtr<Gdk::DragContext>& context) {
- TreeView::on_drag_end (context);
- }
- void on_drag_data_delete(const Glib::RefPtr<Gdk::DragContext>& context) {
- TreeView::on_drag_data_delete (context);
- }
void on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& context, guint time) {
- suggested_action = context->get_suggested_action();
- TreeView::on_drag_leave (context, time);
+ suggested_action = context->get_suggested_action();
+ TreeView::on_drag_leave (context, time);
}
+
bool on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time) {
suggested_action = context->get_suggested_action();
return TreeView::on_drag_motion (context, x, y, time);
}
+
bool on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
- void on_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time);
- void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data, guint info, guint time);
- private:
+ protected:
std::list<Gtk::TargetEntry> draggable;
Gdk::DragAction suggested_action;
int data_column;
-
- SerializedObjectPointers* serialize_pointers (Glib::RefPtr<Gtk::TreeModel> m,
- Gtk::TreeSelection::ListHandle_Path*,
- Glib::ustring type);
+};
+
+template<class DataType>
+class DnDTreeView : public DnDTreeViewBase
+{
+ public:
+ DnDTreeView() {}
+ ~DnDTreeView() {}
+
+ sigc::signal<void,std::string,uint32_t,const DataType*> signal_object_drop;
+
+ void on_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time) {
+ if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
+
+ TreeView::on_drag_data_get (context, selection_data, info, time);
+
+ } else if (data_column >= 0) {
+
+ Gtk::TreeSelection::ListHandle_Path selection = get_selection()->get_selected_rows ();
+ SerializedObjectPointers<DataType>* sr = serialize_pointers (get_model(), &selection, selection_data.get_target());
+ selection_data.set (8, (guchar*)sr, sr->size);
+ }
+ }
+
+ void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data, guint info, guint time) {
+ if (suggested_action) {
+ /* this is a drag motion callback. just update the status to
+ say that we are still dragging, and that's it.
+ */
+ suggested_action = Gdk::DragAction (0);
+ TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
+ return;
+ }
+
+ if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
+
+ TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
+
+ } else if (data_column >= 0) {
+
+ /* object D-n-D */
+
+ const void* data = selection_data.get_data();
+ const SerializedObjectPointers<DataType>* sr = reinterpret_cast<const SerializedObjectPointers<DataType> *>(data);
+
+ if (sr) {
+ signal_object_drop (sr->type, sr->cnt, sr->data);
+ }
+
+ } else {
+ /* some kind of target type added by the app, which will be handled by a signal handler */
+ }
+ }
+
+ private:
+
+ SerializedObjectPointers<DataType>* serialize_pointers (Glib::RefPtr<Gtk::TreeModel> model,
+ Gtk::TreeSelection::ListHandle_Path* selection,
+ Glib::ustring type) {
+
+ /* this nasty chunk of code is here because X's DnD protocol (probably other graphics UI's too)
+ requires that we package up the entire data collection for DnD in a single contiguous region
+ (so that it can be trivially copied between address spaces). We don't know the type of DataType so
+ we have to mix-and-match C and C++ programming techniques here to get the right result.
+
+ The C trick is to use the "someType foo[0];" declaration trick to create a zero-sized array at the
+ end of a SerializedObjectPointers<DataType object. Then we allocate a raw memory buffer that extends
+ past that array and thus provides space for however many DataType items we actually want to pass
+ around.
+
+ The C++ trick is to use the placement operator new() syntax to initialize that extra
+ memory properly.
+ */
+
+ uint32_t cnt = selection->size();
+ uint32_t sz = (sizeof (DataType) * cnt) + sizeof (SerializedObjectPointers<DataType>);
+
+ char* buf = new char[sz];
+ SerializedObjectPointers<DataType>* sr = (SerializedObjectPointers<DataType>*) buf;
+
+ for (uint32_t i = 0; i < cnt; ++i) {
+ new ((void *) &sr->data[i]) DataType ();
+ }
+
+ sr->cnt = cnt;
+ sr->size = sz;
+ snprintf (sr->type, sizeof (sr->type), "%s", type.c_str());
+
+ cnt = 0;
+
+ for (Gtk::TreeSelection::ListHandle_Path::iterator x = selection->begin(); x != selection->end(); ++x, ++cnt) {
+ model->get_iter (*x)->get_value (data_column, sr->data[cnt]);
+ }
+
+ return sr;
+ }
};
} // namespace