From 813a0fc10cf5f7aaa6356cd97a4258fa78b9b87f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 7 Nov 2013 10:25:58 +0200 Subject: [PATCH] Better method of implementing zero gravity --- source/layout.cpp | 33 ++++++++++++++++++++++----------- source/layout.h | 2 +- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/source/layout.cpp b/source/layout.cpp index bee972d..b8d8fb7 100644 --- a/source/layout.cpp +++ b/source/layout.cpp @@ -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::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::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::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; } { diff --git a/source/layout.h b/source/layout.h index 9c4e2a0..043d92c 100644 --- a/source/layout.h +++ b/source/layout.h @@ -172,7 +172,7 @@ private: Container *container; std::list slots; unsigned n_active_slots; - unsigned n_slack_constraints[2]; + unsigned n_slack_vars[2]; Sides margin; unsigned row_spacing; unsigned col_spacing; -- 2.43.0