Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK
);
- signal_button_press_event().connect (bind (mem_fun (*this, &DnDVBox::button_press), (T *) 0));
- signal_button_release_event().connect (bind (mem_fun (*this, &DnDVBox::button_release), (T *) 0));
+ signal_button_press_event().connect (sigc::bind (mem_fun (*this, &DnDVBox::button_press), (T *) 0));
+ signal_button_release_event().connect (sigc::bind (mem_fun (*this, &DnDVBox::button_release), (T *) 0));
signal_drag_motion().connect (mem_fun (*this, &DnDVBox::drag_motion));
signal_drag_leave().connect (mem_fun (*this, &DnDVBox::drag_leave));
return _selection;
}
- /** Set the `active' child; this is simply a child which is set to have the Gtk
- * STATE_ACTIVE for whatever purposes the client may have.
+ /** Set the `active' child; this is simply a child which is set to have the
+ * visual state "active" for whatever purposes the client may have.
* @param c Child, or 0 for none.
*/
void set_active (T* c) {
sigc::signal<void> SelectionChanged;
private:
+
+ /** @return the bottom y position of a child, pretending any placeholder
+ * is not there.
+ */
+ double bottom_of_child_ignoring_placeholder (T* child) const
+ {
+ Gtk::Allocation const a = child->widget().get_allocation ();
+ double bottom = a.get_y() + a.get_height();
+
+ if (_placeholder) {
+ Gtk::Allocation const b = _placeholder->get_allocation ();
+ if (b.get_y() < a.get_y()) {
+ bottom -= (b.get_height () + _internal_vbox.get_spacing ());
+ }
+ }
+
+ return bottom;
+ }
/** Look at a y coordinate and find the children below y, and the ones either side.
* @param y y position.
/* top of current child */
double top = 0;
/* bottom of current child */
- Gtk::Allocation const a = (*j)->widget().get_allocation();
- double bottom = a.get_y() + a.get_height();
+ double bottom = bottom_of_child_ignoring_placeholder (*j);
while (y >= bottom && j != _children.end()) {
++j;
if (j != _children.end()) {
- Gtk::Allocation const a = (*j)->widget().get_allocation();
- bottom = a.get_y() + a.get_height();
+ bottom = bottom_of_child_ignoring_placeholder (*j);
}
}
++j;
*after = j != _children.end() ? *j : 0;
- return i + ((y - top) / (*at)->widget().get_allocation().get_height());
+ return i + ((y - top) / (bottom - top));
}
void drag_begin (Glib::RefPtr<Gdk::DragContext> const & context, T* child)
/* dropped from ourselves onto ourselves */
- T* child = *((T **) selection_data.get_data());
+ T* child = *((T * const *) selection_data.get_data());
if (drop.first == 0) {
_internal_vbox.reorder_child (child->widget(), -1);
/* whether we're in the top or bottom half of the child that we're over */
bool top_half = (c - int (c)) < 0.5;
- if (top_half && (before == _drag_child || at == _drag_child)) {
+ /* 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 && (at == _drag_child || after == _drag_child)) {
+ 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;
return ButtonRelease (ev, child); /* EMIT SIGNAL */
}
- /** Setup a child's GTK state correctly */
+ /** Setup a child's visual state correctly */
void setup_child_state (T* c)
{
assert (c);
- c->set_visual_state (Selected, selected (c));
+ c->set_visual_state (Selected, (selected (c) || (_active == c)));
}
void clear_selection ()
{
typename std::list<T*>::iterator x = find (_selection.begin(), _selection.end(), child);
if (x != _selection.end()) {
+ T* c = *x;
_selection.erase (x);
- setup_child_state (*x);
+ setup_child_state (c);
}
}