Layout::Layout():
container(0),
+ n_active_slots(0),
margin(8),
row_spacing(5),
col_spacing(4)
Slot *slot = create_slot(wdg);
for(list<Constraint>::iterator i=slot->constraints.begin(); i!=slot->constraints.end(); ++i)
i->target.constraints.push_back(Constraint(complement(i->type), *slot));
- slot->index = slots.size();
slots.push_back(slot);
+ update_slot_indices();
if(container)
update();
}
return new Slot(*this, wdg);
}
+void Layout::update_slot_indices()
+{
+ n_active_slots = 0;
+ for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
+ {
+ if((*i)->widget.is_visible())
+ (*i)->index = n_active_slots++;
+ else
+ (*i)->index = -1;
+ }
+}
+
Layout::Slot &Layout::get_slot_for_widget(Widget &wdg)
{
for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
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(slots.size()*5+1);
+ LinearProgram linprog(n_active_slots*5+1);
float weight = slots.size();
for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
{
+ if((*i)->index<0)
+ continue;
+
LinearProgram::Row objective = linprog.get_objective_row();
if(mode==AUTOSIZE)
{
constraints are always added in pairs, so it's only necessary to create a
row for one half. */
for(list<Constraint>::iterator j=(*i)->constraints.begin(); j!=(*i)->constraints.end(); ++j)
- if((j->type&1)==dir && j->type!=BELOW && j->type!=LEFT_OF)
+ if(j->target.index>=0 && (j->type&1)==dir && j->type!=BELOW && j->type!=LEFT_OF)
{
LinearProgram::Row row = linprog.add_row();
if(j->type&SELF_POS)
{
autosize_geom.*(ptrs.dim) = 0;
for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
- {
- int high_edge = linprog.get_variable((*i)->index*5)+linprog.get_variable((*i)->index*5+1);
- autosize_geom.*(ptrs.dim) = max(autosize_geom.*(ptrs.dim), high_edge+margin.*(ptrs.high_margin));
- }
+ if((*i)->index>=0)
+ {
+ int high_edge = linprog.get_variable((*i)->index*5)+linprog.get_variable((*i)->index*5+1);
+ autosize_geom.*(ptrs.dim) = max(autosize_geom.*(ptrs.dim), high_edge+margin.*(ptrs.high_margin));
+ }
}
else
{
for(list<Slot *>::iterator i=slots.begin(); i!=slots.end(); ++i)
- {
- (*i)->geom.*(ptrs.pos) = linprog.get_variable((*i)->index*5);
- (*i)->geom.*(ptrs.dim) = linprog.get_variable((*i)->index*5+1);
- }
+ if((*i)->index>=0)
+ {
+ (*i)->geom.*(ptrs.pos) = linprog.get_variable((*i)->index*5);
+ (*i)->geom.*(ptrs.dim) = linprog.get_variable((*i)->index*5+1);
+ }
}
}
{
vert_pack.gravity = 1;
widget.signal_autosize_changed.connect(sigc::mem_fun(this, &Slot::autosize_changed));
+ widget.signal_visibility_changed.connect(sigc::mem_fun(this, &Slot::visibility_changed));
widget.autosize();
autosize_geom = widget.get_geometry();
}
widget.autosize();
autosize_geom = widget.get_geometry();
+ if(!widget.is_visible())
+ return;
+
// If the widget fits in the area it had, just leave it there.
if(autosize_geom.w<=geom.w && autosize_geom.h<=geom.h)
widget.set_geometry(geom);
}
}
+void Layout::Slot::visibility_changed(bool v)
+{
+ layout.update_slot_indices();
+ if(v)
+ {
+ layout.container->signal_autosize_changed.emit();
+ layout.update();
+ }
+}
+
Layout::LinearProgram::LinearProgram(unsigned s):
n_columns(s),
struct Slot: public sigc::trackable
{
Layout &layout;
- unsigned index;
+ int index;
Widget &widget;
Geometry autosize_geom;
Geometry geom;
virtual ~Slot() { }
void autosize_changed();
+ void visibility_changed(bool);
};
enum SolveMode
Container *container;
std::list<Slot *> slots;
+ unsigned n_active_slots;
Sides margin;
unsigned row_spacing;
unsigned col_spacing;
void remove_widget(Widget &);
protected:
virtual Slot *create_slot(Widget &);
+ void update_slot_indices();
Slot &get_slot_for_widget(Widget &);
static ConstraintType complement(ConstraintType);
void create_constraint(Widget &, ConstraintType, Widget &, int);