]> git.tdb.fi Git - libs/gltk.git/blobdiff - source/layout.cpp
Support floating widgets in layouts
[libs/gltk.git] / source / layout.cpp
index 5df7bc1f77d2a16f87a02f80e4eea6892a2d3564..02e1ec4479dd17643dbbc8056b8b578c8bac0adb 100644 (file)
@@ -211,22 +211,31 @@ void Layout::remove_widget(Widget &wdg)
 void Layout::update_slot_indices()
 {
        n_active_slots = 0;
+       unsigned n_floating = 0;
        for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
        {
                if((*i)->widget.is_visible() || (*i)->ghost)
+               {
                        (*i)->index = n_active_slots++;
+                       if((*i)->floating)
+                               ++n_floating;
+               }
                else
                        (*i)->index = -1;
        }
 
-       n_slack_vars[0] = 0;
-       n_slack_vars[1] = 0;
+       n_slack_vars[0] = n_floating*2;
+       n_slack_vars[1] = n_floating*2;
        for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
                if((*i)->index>=0)
                {
-                       for(unsigned j=0; j<2; ++j)
-                               if(((*i)->*(pointers[j].packing)).gravity==0)
-                                       n_slack_vars[j] += 2;
+                       if(!(*i)->floating)
+                       {
+                               for(unsigned j=0; j<2; ++j)
+                                       if(((*i)->*(pointers[j].packing)).gravity==0)
+                                               n_slack_vars[j] += 2;
+                       }
+
                        for(list<Constraint>::iterator j=(*i)->constraints.begin(); j!=(*i)->constraints.end(); ++j)
                                if(j->target.index>(*i)->index && (j->type&SLACK))
                                        ++n_slack_vars[j->type&1];
@@ -312,6 +321,16 @@ void Layout::set_ghost(Widget &wdg, bool g)
        }
 }
 
+void Layout::set_floating(Widget &wdg, bool f)
+{
+       Slot &slot = get_slot_for_widget(wdg);
+
+       slot.floating = f;
+
+       update_slot_indices();
+       update();
+}
+
 void Layout::update()
 {
        solve_constraints(HORIZONTAL, UPDATE);
@@ -358,7 +377,8 @@ void Layout::solve_constraints(int dir, SolveMode mode)
                }
                else
                {
-                       objective[(*i)->index*5] = ((*i)->*(ptrs.packing)).gravity/weight;
+                       if(!(*i)->floating)
+                               objective[(*i)->index*5] = ((*i)->*(ptrs.packing)).gravity/weight;
                        objective[(*i)->index*5+1] = (((*i)->*(ptrs.packing)).expand ? weight : -1);
                }
 
@@ -380,18 +400,24 @@ void Layout::solve_constraints(int dir, SolveMode mode)
                        row.back() = geom.*(ptrs.dim)-margin.*(ptrs.high_margin);
                }
 
-               if(((*i)->*(ptrs.packing)).gravity==0)
+               if((*i)->floating || ((*i)->*(ptrs.packing)).gravity==0)
                {
-                       /* Try to keep the widget as close to the center of the container
-                       as possible.  Since linear programs can't express absolute values
-                       directly, use two opposing slack variables that are optimized for
-                       a low value. */
+                       /* Try to keep the widget as close to a target position as possible.
+                       Since linear programs can't express absolute values directly, use two
+                       opposing slack variables that are optimized for a low value. */
+                       float a = ((*i)->*(ptrs.packing)).gravity*0.5+0.5;
                        LinearProgram::Row row = linprog.add_row();
                        row[(*i)->index*5] = 1;
-                       row[(*i)->index*5+1] = 0.5;
+                       row[(*i)->index*5+1] = a;
                        row[k] = 1;
                        row[k+1] = -1;
-                       row.back() = geom.*(ptrs.dim)/2;
+                       if((*i)->floating)
+                       {
+                               const Geometry &cgeom = (*i)->widget.get_geometry();
+                               row.back() = cgeom.*(ptrs.pos)+cgeom.*(ptrs.dim)*a;
+                       }
+                       else
+                               row.back() = geom.*(ptrs.dim)/2;
                        objective[k] = -1;
                        objective[k+1] = -1;
                        k += 2;
@@ -470,7 +496,8 @@ Layout::Slot::Slot(Layout &l, Widget &w):
        layout(l),
        index(0),
        widget(w),
-       ghost(false)
+       ghost(false),
+       floating(false)
 {
        vert_pack.gravity = 1;
        widget.signal_autosize_changed.connect(sigc::mem_fun(this, &Slot::autosize_changed));