make pane divider placement a little safer
[ardour.git] / libs / gtkmm2ext / pane.cc
index 7f1c4ea7422a41828c7f22dc9f2017d04799892e..31408eb777b154e77a435618f7cc36d6f36f00bc 100644 (file)
@@ -30,7 +30,7 @@ using namespace std;
 Pane::Pane (bool h)
        : horizontal (h)
        , did_move (false)
-       , divider_width (5)
+       , divider_width (2)
 {
        using namespace Gdk;
 
@@ -40,7 +40,7 @@ Pane::Pane (bool h)
        if (horizontal) {
                drag_cursor = Cursor (SB_H_DOUBLE_ARROW);
        } else {
-               drag_cursor = Cursor (SB_H_DOUBLE_ARROW);
+               drag_cursor = Cursor (SB_V_DOUBLE_ARROW);
        }
 }
 
@@ -122,6 +122,12 @@ Pane::add_divider ()
        dividers.push_back (d);
 }
 
+void
+Pane::handle_child_visibility ()
+{
+       reallocate (get_allocation());
+}
+
 void
 Pane::on_add (Widget* w)
 {
@@ -129,6 +135,9 @@ Pane::on_add (Widget* w)
 
        w->set_parent (*this);
 
+       w->signal_show().connect (sigc::mem_fun (*this, &Pane::handle_child_visibility));
+       w->signal_hide().connect (sigc::mem_fun (*this, &Pane::handle_child_visibility));
+
        while (dividers.size() < (children.size() - 1)) {
                add_divider ();
        }
@@ -137,14 +146,14 @@ Pane::on_add (Widget* w)
 void
 Pane::on_remove (Widget* w)
 {
-       w->unparent ();
-
        for (Children::iterator c = children.begin(); c != children.end(); ++c) {
                if (c->w == w) {
                        children.erase (c);
                        break;
                }
        }
+
+       w->unparent ();
 }
 
 void
@@ -182,11 +191,30 @@ Pane::reallocate (Gtk::Allocation const & alloc)
         Children::iterator next;
         Dividers::iterator div;
 
-        for (child = children.begin(), div = dividers.begin(); child != children.end(); ) {
+        child = children.begin();
+
+        /* skip initial hidden children */
+
+        while (child != children.end()) {
+               if (child->w->is_visible()) {
+                       break;
+               }
+               ++child;
+        }
+
+        for (div = dividers.begin(); child != children.end(); ) {
 
                Gtk::Allocation child_alloc;
+
                next = child;
-               ++next;
+
+               /* Move on to next *visible* child */
+
+               while (++next != children.end()) {
+                       if (next->w->is_visible()) {
+                               break;
+                       }
+               }
 
                child_alloc.set_x (xpos);
                child_alloc.set_y (ypos);
@@ -223,13 +251,14 @@ Pane::reallocate (Gtk::Allocation const & alloc)
                }
 
                child->w->size_allocate (child_alloc);
-               ++child;
 
-               if (child == children.end()) {
+               if (next == children.end()) {
                        /* done, no more children, no need for a divider */
                        break;
                }
 
+               child = next;
+
                /* add a divider between children */
 
                Gtk::Allocation divider_allocation;
@@ -250,6 +279,14 @@ Pane::reallocate (Gtk::Allocation const & alloc)
                }
 
                (*div)->size_allocate (divider_allocation);
+               (*div)->show ();
+               ++div;
+        }
+
+        /* hide all remaining dividers */
+
+        while (div != dividers.end()) {
+               (*div)->hide ();
                ++div;
         }
 }
@@ -356,8 +393,6 @@ Pane::handle_motion_event (GdkEventMotion* ev, Divider* d)
 void
 Pane::set_divider (Dividers::size_type div, float fract)
 {
-       bool redraw = false;
-
        Dividers::iterator d = dividers.begin();
 
        while (div--) {
@@ -370,12 +405,10 @@ Pane::set_divider (Dividers::size_type div, float fract)
                }
        }
 
+       fract = max (0.0f, min (1.0f, fract));
+
        if (fract != (*d)->fract) {
                (*d)->fract = fract;
-               redraw = true;
-       }
-
-       if (redraw) {
                /* our size hasn't changed, but our internal allocations have */
                reallocate (get_allocation());
                queue_draw ();