13
0

Treeview Drag: allow to use single column as drag-widget

This commit is contained in:
Robin Gareus 2015-12-24 17:26:06 +01:00
parent 646bcc6885
commit 3ff674d583
2 changed files with 78 additions and 3 deletions

View File

@ -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<Gdk::DragContext> 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<Gdk::Pixmap> 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<Gdk::Bitmap>(NULL),
width / 2 + 1, cell_y + 1);
} else {
Gtk::TreeView::on_drag_begin (context);
}
start_object_drag ();
}
void
DnDTreeViewBase::add_drop_targets (list<TargetEntry>& targets)
{

View File

@ -48,9 +48,12 @@ class LIBGTKMM2EXT_API DnDTreeViewBase : public Gtk::TreeView
void add_drop_targets (std::list<Gtk::TargetEntry>&);
void add_object_drag (int column, std::string type_name);
void on_drag_begin (Glib::RefPtr<Gdk::DragContext> const & context) {
Gtk::TreeView::on_drag_begin (context);
start_object_drag ();
void on_drag_begin (Glib::RefPtr<Gdk::DragContext> 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<Gdk::DragContext>& context, guint time) {
@ -65,12 +68,20 @@ class LIBGTKMM2EXT_API DnDTreeViewBase : public Gtk::TreeView
bool on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
void set_drag_column (int c) {
_drag_column = c;
}
protected:
std::list<Gtk::TargetEntry> 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) {}