+
+ /** Insert a placeholder at a given fractional child position, creating it if necessary.
+ * @param c Fractional child position.
+ * @return index of child that the placeholder represents, or -1 if it is at the end of all children.
+ */
+ int create_or_update_placeholder (double c)
+ {
+ if (_placeholder == 0) {
+ _placeholder = manage (new Gtk::Label (""));
+ _internal_vbox.pack_start (*_placeholder, false, false);
+ _placeholder->show ();
+ }
+
+ /* round up the index, unless we're off the end of the children */
+ int const n = c < 0 ? -1 : int (c + 0.5);
+ _internal_vbox.reorder_child (*_placeholder, n);
+ return n;
+ }
+
+ bool drag_motion (Glib::RefPtr<Gdk::DragContext> const &, int /*x*/, int y, guint)
+ {
+ if (_children.empty ()) {
+ return false;
+ }
+
+ T* before;
+ T* at;
+ T* after;
+
+ /* decide where we currently are */
+ double const c = get_children_around_position (y, &before, &at, &after);
+
+ /* whether we're in the top or bottom half of the child that we're over */
+ bool top_half = (c - int (c)) < 0.5;
+
+ /* Note that when checking on whether to remove a placeholder, we never do
+ so if _drag_child is 0 as this means that the child being dragged is
+ coming from a different DnDVBox, so it will never be the same as any
+ of our children.
+ */
+
+ if (top_half && _drag_child && (before == _drag_child || at == _drag_child)) {
+ /* dropping here would have no effect, so remove the visual cue */
+ remove_placeholder ();
+ return false;
+ }
+
+ if (!top_half && _drag_child && (at == _drag_child || after == _drag_child)) {
+ /* dropping here would have no effect, so remove the visual cue */
+ remove_placeholder ();
+ return false;
+ }
+
+ create_or_update_placeholder (c);
+ return false;
+ }
+
+ void drag_leave (Glib::RefPtr<Gdk::DragContext> const &, guint)
+ {
+ remove_placeholder ();
+ }
+