LCXL: some more small tweaks
[ardour.git] / libs / gtkmm2ext / dndtreeview.cc
1 /*
2     Copyright (C) 2000-2007 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cstdio>
21 #include <iostream>
22
23 #include <gtkmm2ext/dndtreeview.h>
24
25 using namespace std;
26 using namespace sigc;
27 using namespace Gdk;
28 using namespace Gtk;
29 using namespace Glib;
30 using namespace Gtkmm2ext;
31
32 DnDTreeViewBase::DragData DnDTreeViewBase::drag_data;
33
34 DnDTreeViewBase::DnDTreeViewBase ()
35         : TreeView ()
36         , _drag_column (-1)
37 {
38         draggable.push_back (TargetEntry ("GTK_TREE_MODEL_ROW", TARGET_SAME_WIDGET));
39         data_column = -1;
40
41         enable_model_drag_source (draggable);
42         enable_model_drag_dest (draggable);
43
44         suggested_action = Gdk::DragAction (0);
45 }
46
47 void
48 DnDTreeViewBase::on_drag_begin (Glib::RefPtr<Gdk::DragContext> const & context) {
49         if (_drag_column >= 0) {
50                 /* this code is a customized drop-in replacement for
51                  * Gtk::TreeView::on_drag_begin().
52                  * We can use it's cleanup function for the generated Pixmap
53                  */
54
55                 TreeModel::Path path;
56                 TreeViewColumn* column;
57                 int cell_x;
58                 int cell_y;
59
60                 if (!get_path_at_pos ((int)press_start_x, (int)press_start_y, path, column, cell_x, cell_y)) {
61                         return;
62                 }
63
64                 TreeIter iter = get_model()->get_iter (path);
65                 int x_offset, y_offset, width, height;
66
67                 Gdk::Rectangle unused;
68                 TreeViewColumn* clm = get_column(_drag_column);
69
70                 clm->cell_set_cell_data (get_model(), iter, false, false);
71                 clm->cell_get_size (unused, x_offset, y_offset, width, height);
72
73                 Glib::RefPtr<Gdk::Pixmap> pixmap = Gdk::Pixmap::create (get_root_window(), width, height);
74
75                 CellRenderer* cell_renderer = clm->get_first_cell ();
76                 Gdk::Rectangle cell_background (0, 0, width, height);
77                 Gdk::Rectangle cell_size (x_offset, y_offset, width, height);
78
79                 // the cell-renderer only clears the background if
80                 // cell->cell_background_set and priv->cell_background
81                 Gdk::Color clr = get_style()->get_bg(STATE_NORMAL);
82                 // code dup from gtk_cell_renderer_render() to clear the background:
83                 cairo_t *cr = gdk_cairo_create (Glib::unwrap(pixmap));
84                 gdk_cairo_rectangle (cr, (cell_background).gobj());
85                 gdk_cairo_set_source_color (cr, clr.gobj());
86                 cairo_fill (cr);
87                 cairo_destroy (cr);
88
89                 // gtkmm wants a "window", gtk itself is happy with a "drawable",
90                 // cell_renderer->render (pixmap, *this, cell_area, cell_area, cell_area, 0);
91                 // We ain't got no window, so use gtk directly:
92                 gtk_cell_renderer_render (cell_renderer->gobj(),
93                                 Glib::unwrap(pixmap), ((Gtk::Widget*)this)->gobj(),
94                                 (cell_background).gobj(),
95                                 (cell_size).gobj(),
96                                 (cell_size).gobj(),
97                                 ((GtkCellRendererState)(0)));
98
99                 context->set_icon (pixmap->get_colormap(),
100                                 pixmap, Glib::RefPtr<Gdk::Bitmap>(NULL),
101                                 width / 2 + 1, cell_y + 1);
102
103         } else {
104                 Gtk::TreeView::on_drag_begin (context);
105         }
106         start_object_drag ();
107 }
108
109 void
110 DnDTreeViewBase::on_drag_end (Glib::RefPtr<Gdk::DragContext> const & context) {
111         Gtk::TreeView::on_drag_end (context);
112         end_object_drag ();
113 }
114
115 void
116 DnDTreeViewBase::add_drop_targets (list<TargetEntry>& targets)
117 {
118         for (list<TargetEntry>::iterator i = targets.begin(); i != targets.end(); ++i) {
119                 draggable.push_back (*i);
120         }
121
122         enable_model_drag_source (draggable);
123         enable_model_drag_dest (draggable);
124 }
125
126 void
127 DnDTreeViewBase::add_object_drag (int column, string type_name)
128 {
129         draggable.push_back (TargetEntry (type_name, TargetFlags(0)));
130         data_column = column;
131         object_type = type_name;
132
133         enable_model_drag_source (draggable);
134         enable_model_drag_dest (draggable);
135 }
136
137 bool
138 DnDTreeViewBase::on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
139 {
140         suggested_action = Gdk::DragAction (0);
141         drag_data.source = 0;
142         return TreeView::on_drag_drop (context, x, y, time);
143 }