]> git.tdb.fi Git - libs/gltk.git/commitdiff
Better method of implementing zero gravity
authorMikko Rasa <tdb@tdb.fi>
Thu, 7 Nov 2013 08:25:58 +0000 (10:25 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 7 Nov 2013 08:25:58 +0000 (10:25 +0200)
source/layout.cpp
source/layout.h

index bee972d903ab242415f992767247e425e9109922..b8d8fb7d23ad6b196d68550c71f7de6db6f29205 100644 (file)
@@ -92,8 +92,8 @@ Layout::Layout():
        row_spacing(5),
        col_spacing(4)
 {
-       n_slack_constraints[0] = 0;
-       n_slack_constraints[1] = 0;
+       n_slack_vars[0] = 0;
+       n_slack_vars[1] = 0;
 }
 
 Layout::~Layout()
@@ -219,14 +219,17 @@ void Layout::update_slot_indices()
                        (*i)->index = -1;
        }
 
-       n_slack_constraints[0] = 0;
-       n_slack_constraints[1] = 0;
+       n_slack_vars[0] = 0;
+       n_slack_vars[1] = 0;
        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;
                        for(list<Constraint>::iterator j=(*i)->constraints.begin(); j!=(*i)->constraints.end(); ++j)
                                if(j->target.index>(*i)->index && (j->type&SLACK))
-                                       ++n_slack_constraints[j->type&1];
+                                       ++n_slack_vars[j->type&1];
                }
 }
 
@@ -282,6 +285,7 @@ void Layout::set_gravity(Widget &wdg, int h, int v)
        slot.horiz_pack.gravity = h;
        slot.vert_pack.gravity = v;
 
+       update_slot_indices();
        update();
 }
 
@@ -338,7 +342,7 @@ void Layout::solve_constraints(int dir, SolveMode mode)
        five columns for each widget, and one constant column.  The first and second
        columns of a widget are its position and dimension, respectively.  The
        remaining three are slack columns; see below for their purposes. */
-       LinearProgram linprog(n_active_slots*5+n_slack_constraints[dir]+1);
+       LinearProgram linprog(n_active_slots*5+n_slack_vars[dir]+1);
        float weight = slots.size();
        unsigned k = n_active_slots*5;
        for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
@@ -378,12 +382,19 @@ void Layout::solve_constraints(int dir, SolveMode mode)
 
                if(((*i)->*(ptrs.packing)).gravity==0)
                {
-                       /* This forces the widget's distance from the left and right edge of
-                       the container to be equal.  It's a bit of a hack, but more time and
-                       thought is needed for a better solution. */
+                       /* 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. */
                        LinearProgram::Row row = linprog.add_row();
-                       row[(*i)->index*5+2] = 1;
-                       row[(*i)->index*5+3] = -1;
+                       row[(*i)->index*5] = 1;
+                       row[(*i)->index*5+1] = 0.5;
+                       row[k] = 1;
+                       row[k+1] = -1;
+                       row.back() = geom.*(ptrs.dim)/2;
+                       objective[k] = -1;
+                       objective[k+1] = -1;
+                       k += 2;
                }
 
                {
index 9c4e2a07e6525b73e15783c0df17d397f739ad1d..043d92cc1554b738092ce3ad771fcf5bb3cc5049 100644 (file)
@@ -172,7 +172,7 @@ private:
        Container *container;
        std::list<Slot *> slots;
        unsigned n_active_slots;
-       unsigned n_slack_constraints[2];
+       unsigned n_slack_vars[2];
        Sides margin;
        unsigned row_spacing;
        unsigned col_spacing;