added files
[ardour.git] / libs / gtkmm2ext / dndtreeview.cc
1 #include <cstdio>
2
3 #include <gtkmm2ext/dndtreeview.h>
4
5 using namespace std;
6 using namespace sigc;
7 using namespace Gdk;
8 using namespace Gtk;
9 using namespace Glib;
10 using namespace Gtkmm2ext;
11
12 DnDTreeView::DnDTreeView ()
13         : TreeView ()
14 {
15         draggable.push_back (TargetEntry ("GTK_TREE_MODEL_ROW", TARGET_SAME_WIDGET));
16         
17         enable_model_drag_source (draggable);
18         enable_model_drag_dest (draggable);
19         
20         suggested_action = Gdk::DragAction (0);
21 }
22
23 void
24 DnDTreeView::add_object_drag (int column, string type_name)
25 {
26         draggable.push_back (TargetEntry (type_name, TargetFlags(0)));
27         data_column = column;
28
29         enable_model_drag_source (draggable);
30         enable_model_drag_dest (draggable);
31 }
32
33 DnDTreeView::SerializedObjectPointers* 
34 DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHandle_Path* selection, ustring type)
35 {
36         uint32_t cnt = selection->size();
37         uint32_t sz = (sizeof (void*) * cnt) + sizeof (SerializedObjectPointers);
38
39         char* buf = new char[sz];
40         SerializedObjectPointers* sr = new (buf) SerializedObjectPointers;
41         
42         sr->cnt = cnt;
43         sr->size = sz;
44
45         snprintf (sr->type, sizeof (sr->type), "%s", type.c_str());
46
47         cnt = 0;
48
49         for (TreeSelection::ListHandle_Path::iterator x = selection->begin(); x != selection->end(); ++x, ++cnt) {
50                 TreeModel::Row row = *(model->get_iter (*x));
51                 row.get_value (data_column, sr->ptr[cnt]);
52         }
53         
54         return sr;
55 }
56
57 void
58 DnDTreeView::on_drag_data_get(const RefPtr<DragContext>& context, SelectionData& selection_data, guint info, guint time)
59 {
60         if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
61                 
62                 TreeView::on_drag_data_get (context, selection_data, info, time);
63                 
64         } else {
65                 
66                 Gtk::TreeSelection::ListHandle_Path selection = get_selection()->get_selected_rows ();
67                 SerializedObjectPointers* sr = serialize_pointers (get_model(), &selection, selection_data.get_target());
68                 selection_data.set (8, (guchar*)sr, sr->size);
69                 
70         }
71 }
72
73 void 
74 DnDTreeView::on_drag_data_received(const RefPtr<DragContext>& context, int x, int y, const SelectionData& selection_data, guint info, guint time)
75 {
76         if (suggested_action) {
77                 /* this is a drag motion callback. just update the status to
78                    say that we are still dragging, and that's it.
79                 */
80                 suggested_action = Gdk::DragAction (0);
81                 TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
82                 return;
83         }
84         
85         if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
86                 
87                 TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
88                 
89         } else {
90                 /* object D-n-D */
91                 
92                 const SerializedObjectPointers* sr = reinterpret_cast<const SerializedObjectPointers *>(selection_data.get_data());
93                 
94                 if (sr) {
95                         signal_object_drop (sr->type, sr->cnt, const_cast<void**>(sr->ptr));
96                 }
97                 
98                 context->drag_finish (true, false, time);
99                 
100         }
101 }
102
103