diff --git a/libs/gtkmm2ext/dndtreeview.cc b/libs/gtkmm2ext/dndtreeview.cc index 53b212d711..be53482603 100644 --- a/libs/gtkmm2ext/dndtreeview.cc +++ b/libs/gtkmm2ext/dndtreeview.cc @@ -33,6 +33,7 @@ DnDTreeViewBase::DragData DnDTreeViewBase::drag_data; DnDTreeViewBase::DnDTreeViewBase () : TreeView () + , _drag_column (-1) { draggable.push_back (TargetEntry ("GTK_TREE_MODEL_ROW", TARGET_SAME_WIDGET)); data_column = -1; @@ -43,6 +44,69 @@ DnDTreeViewBase::DnDTreeViewBase () suggested_action = Gdk::DragAction (0); } +void +DnDTreeViewBase::on_drag_begin (Glib::RefPtr const & context) { + if (_drag_column >= 0) { + /* this code is a customized drop-in replacement for + * Gtk::TreeView::on_drag_begin(). + * We can use it's cleanup function for the generated Pixmap + */ + + TreeModel::Path path; + TreeViewColumn* column; + int cell_x; + int cell_y; + + if (!get_path_at_pos ((int)press_start_x, (int)press_start_y, path, column, cell_x, cell_y)) { + return; + } + + TreeIter iter = get_model()->get_iter (path); + int x_offset, y_offset, width, height; + + Gdk::Rectangle unused; + TreeViewColumn* clm = get_column(_drag_column); + + clm->cell_set_cell_data (get_model(), iter, false, false); + clm->cell_get_size (unused, x_offset, y_offset, width, height); + + Glib::RefPtr pixmap = Gdk::Pixmap::create (get_root_window(), width, height); + + CellRenderer* cell_renderer = clm->get_first_cell (); + Gdk::Rectangle cell_background (0, 0, width, height); + Gdk::Rectangle cell_size (x_offset, y_offset, width, height); + + // the cell-renderer only clears the background if + // cell->cell_background_set and priv->cell_background + Gdk::Color clr = get_style()->get_bg(STATE_NORMAL); + // code dup from gtk_cell_renderer_render() to clear the background: + cairo_t *cr = gdk_cairo_create (Glib::unwrap(pixmap)); + gdk_cairo_rectangle (cr, (cell_background).gobj()); + gdk_cairo_set_source_color (cr, clr.gobj()); + cairo_fill (cr); + cairo_destroy (cr); + + // gtkmm wants a "window", gtk itself is happy with a "drawable", + // cell_renderer->render (pixmap, *this, cell_area, cell_area, cell_area, 0); + // We ain't got no window, so use gtk directly: + gtk_cell_renderer_render (cell_renderer->gobj(), + Glib::unwrap(pixmap), ((Gtk::Widget*)this)->gobj(), + (cell_background).gobj(), + (cell_size).gobj(), + (cell_size).gobj(), + ((GtkCellRendererState)(0))); + + context->set_icon (pixmap->get_colormap(), + pixmap, Glib::RefPtr(NULL), + width / 2 + 1, cell_y + 1); + + } else { + Gtk::TreeView::on_drag_begin (context); + } + start_object_drag (); +} + + void DnDTreeViewBase::add_drop_targets (list& targets) { diff --git a/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h b/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h index bf84a17f5e..d36d82f6ee 100644 --- a/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h +++ b/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h @@ -48,9 +48,12 @@ class LIBGTKMM2EXT_API DnDTreeViewBase : public Gtk::TreeView void add_drop_targets (std::list&); void add_object_drag (int column, std::string type_name); - void on_drag_begin (Glib::RefPtr const & context) { - Gtk::TreeView::on_drag_begin (context); - start_object_drag (); + void on_drag_begin (Glib::RefPtr const & context); + + bool on_button_press_event (GdkEventButton *ev) { + press_start_x = ev->x; + press_start_y = ev->y; + return TreeView::on_button_press_event (ev); } void on_drag_leave(const Glib::RefPtr& context, guint time) { @@ -65,12 +68,20 @@ class LIBGTKMM2EXT_API DnDTreeViewBase : public Gtk::TreeView bool on_drag_drop(const Glib::RefPtr& context, int x, int y, guint time); + void set_drag_column (int c) { + _drag_column = c; + } + protected: std::list draggable; Gdk::DragAction suggested_action; int data_column; std::string object_type; + double press_start_x; + double press_start_y; + int _drag_column; + struct DragData { DragData () : source (0) {}