Ardour  9.0-pre0-582-g084a23a80d
dndtreeview.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2015 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2009-2010 Carl Hetherington <carl@carlh.net>
4  * Copyright (C) 2015-2016 Robin Gareus <robin@gareus.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #ifndef __gtkmm2ext_dndtreeview_h__
22 #define __gtkmm2ext_dndtreeview_h__
23 
24 #include <stdint.h>
25 #include <string>
26 #include <gtkmm/treeview.h>
27 #include <gtkmm/treeselection.h>
28 #include <gtkmm/selectiondata.h>
29 
30 #include "gtkmm2ext/visibility.h"
31 
32 namespace Gtkmm2ext {
33 
34 template<class DataType>
35 struct /*LIBGTKMM2EXT_API*/ SerializedObjectPointers {
36  uint32_t size;
37  uint32_t cnt;
38  char type[32];
39  DataType data[0];
40 };
41 
43 {
44  private:
45  public:
48 
49  struct BoolAccumulator {
50  typedef bool result_type;
51  template <class U>
52  result_type operator () (U first, U last) {
53  while (first != last) {
54  if (!*first) {
55  /* break on first slot that returns false */
56  return false;
57  }
58  ++first;
59  }
60  /* no connected slots -> return true */
61  return true;
62  }
63  };
64 
65 
66  sigc::signal4<bool, const Glib::RefPtr<Gdk::DragContext>&, int, int, guint, BoolAccumulator> signal_motion;
67 
68  void add_drop_targets (std::list<Gtk::TargetEntry>&);
69  void add_object_drag (int column, std::string type_name, Gtk::TargetFlags flags = Gtk::TargetFlags (0));
70 
71  void on_drag_begin (Glib::RefPtr<Gdk::DragContext> const & context);
72  void on_drag_end (Glib::RefPtr<Gdk::DragContext> const & context);
73 
75  press_start_x = ev->x;
76  press_start_y = ev->y;
77  return TreeView::on_button_press_event (ev);
78  }
79 
80  void on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& context, guint time) {
81  TreeView::on_drag_leave (context, time);
82  suggested_action = context->get_suggested_action();
83  }
84 
85  bool on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
86  bool on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
87 
88  void set_drag_column (int c) {
89  _drag_column = c;
90  }
91 
92  protected:
93  std::list<Gtk::TargetEntry> draggable;
96  std::string object_type;
97 
98  double press_start_x;
99  double press_start_y;
101 
102  struct DragData {
103  DragData () : source (0) {}
104 
107  std::string object_type;
108  };
109 
111 
113  drag_data.source = this;
114  drag_data.data_column = data_column;
115  drag_data.object_type = object_type;
116  }
117 
118  void end_object_drag () {
119  drag_data.source = 0;
120  drag_data.data_column = -1;
121  drag_data.object_type = "";
122  }
123 };
124 
125 template<class DataType>
126 class /*LIBGTKMM2EXT_API*/ DnDTreeView : public DnDTreeViewBase
127 {
128  public:
131 
132  sigc::signal<void, const Glib::RefPtr<Gdk::DragContext>&, const Gtk::SelectionData&> signal_drop;
133 
134  void on_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time) {
135  if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
136 
137  TreeView::on_drag_data_get (context, selection_data, info, time);
138 
139  } else if (selection_data.get_target() == object_type && drag_data.data_column >= 0) {
140 
141  /* return a pointer to this object, which allows
142  * the receiver to call on_drag_data_received()
143  */
144  void *c = this;
145  selection_data.set (8, (guchar*)&c, sizeof(void*));
146  } else {
147  TreeView::on_drag_data_get (context, selection_data, info, time);
148  }
149  }
150 
151  void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data, guint info, guint time) {
152  if (suggested_action) {
153  /* this is a drag motion callback. just update the status to
154  say that we are still dragging, and that's it.
155  */
157  TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
158  return;
159  }
160 
161  if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
162  TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
163  } else {
164  /* some kind of target type, usually 'object_type' added by the app,
165  * which will be handled by a signal handler */
166  for (std::list<Gtk::TargetEntry>::const_iterator i = draggable.begin(); i != draggable.end (); ++i) {
167  if (selection_data.get_target() == (*i).get_target()) {
168  signal_drop (context, selection_data);
169  context->drag_finish (true, false, time);
170  break;
171  }
172  }
173  }
174  }
175 
181  void get_object_drag_data (std::list<DataType>& l, Gtk::TreeView** source) const {
182 
183  if (drag_data.source == 0 || drag_data.data_column < 0) {
184  return;
185  }
186 
187  Glib::RefPtr<Gtk::TreeModel> model = drag_data.source->get_model();
188  DataType v;
190 
191  for (Gtk::TreeSelection::ListHandle_Path::iterator x = selection.begin(); x != selection.end(); ++x) {
192  model->get_iter (*x)->get_value (drag_data.data_column, v);
193  l.push_back (v);
194  }
195 
196  *source = drag_data.source;
197  }
198 };
199 
200 } // namespace
201 
202 #endif /* __gtkmm2ext_dndtreeview_h__ */
std::string get_target() const
void set(int format, const guint8 *data, int length)
Glib::ListHandle< TreeModel::Path, TreePath_Traits > ListHandle_Path
Glib::RefPtr< TreeModel > get_model()
Glib::RefPtr< TreeSelection > get_selection()
void add_object_drag(int column, std::string type_name, Gtk::TargetFlags flags=Gtk::TargetFlags(0))
std::list< Gtk::TargetEntry > draggable
Definition: dndtreeview.h:93
sigc::signal4< bool, const Glib::RefPtr< Gdk::DragContext > &, int, int, guint, BoolAccumulator > signal_motion
Definition: dndtreeview.h:66
bool on_button_press_event(GdkEventButton *ev)
This is a default handler for the signal signal_button_press_event().
Definition: dndtreeview.h:74
static DragData drag_data
Definition: dndtreeview.h:110
void on_drag_leave(const Glib::RefPtr< Gdk::DragContext > &context, guint time)
This is a default handler for the signal signal_drag_leave().
Definition: dndtreeview.h:80
Gdk::DragAction suggested_action
Definition: dndtreeview.h:94
bool on_drag_drop(const Glib::RefPtr< Gdk::DragContext > &context, int x, int y, guint time)
This is a default handler for the signal signal_drag_drop().
bool on_drag_motion(const Glib::RefPtr< Gdk::DragContext > &context, int x, int y, guint time)
This is a default handler for the signal signal_drag_motion().
void on_drag_begin(Glib::RefPtr< Gdk::DragContext > const &context)
This is a default handler for the signal signal_drag_begin().
void add_drop_targets(std::list< Gtk::TargetEntry > &)
void on_drag_end(Glib::RefPtr< Gdk::DragContext > const &context)
This is a default handler for the signal signal_drag_end().
sigc::signal< void, const Glib::RefPtr< Gdk::DragContext > &, const Gtk::SelectionData & > signal_drop
Definition: dndtreeview.h:132
void on_drag_data_get(const Glib::RefPtr< Gdk::DragContext > &context, Gtk::SelectionData &selection_data, guint info, guint time)
This is a default handler for the signal signal_drag_data_get().
Definition: dndtreeview.h:134
void get_object_drag_data(std::list< DataType > &l, Gtk::TreeView **source) const
Definition: dndtreeview.h:181
void on_drag_data_received(const Glib::RefPtr< Gdk::DragContext > &context, int x, int y, const Gtk::SelectionData &selection_data, guint info, guint time)
This is a default handler for the signal signal_drag_data_received().
Definition: dndtreeview.h:151
DragAction
Definition: dragcontext.h:68
#define LIBGTKMM2EXT_API
Transmitter info
link region and track selection