X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flayout.cpp;h=d3d015f7305c7ddb70a024c4884ee88cbf3711f2;hb=eb6eee5fabf05abca4a0434c2a8f8f62c900afec;hp=f89e407cf7f4d3b61d08831c0f71693b68b27760;hpb=76a7cd9ed443c1a6451e6fab98f428f7cce48eed;p=libs%2Fgltk.git diff --git a/source/layout.cpp b/source/layout.cpp index f89e407..d3d015f 100644 --- a/source/layout.cpp +++ b/source/layout.cpp @@ -110,6 +110,28 @@ void Layout::set_margin(const Sides &m) update(); } +void Layout::set_spacing(unsigned s) +{ + row_spacing = s; + col_spacing = s; + if(container) + update(); +} + +void Layout::set_row_spacing(unsigned s) +{ + row_spacing = s; + if(container) + update(); +} + +void Layout::set_column_spacing(unsigned s) +{ + col_spacing = s; + if(container) + update(); +} + void Layout::add_widget(Widget &wdg) { if(!container) @@ -181,7 +203,7 @@ Layout::ConstraintType Layout::complement(ConstraintType type) return type; } -void Layout::add_constraint(Widget &src, ConstraintType type, Widget &tgt) +void Layout::create_constraint(Widget &src, ConstraintType type, Widget &tgt, int sp) { if(&src==&tgt) throw invalid_argument("&src==&tgt"); @@ -194,11 +216,23 @@ void Layout::add_constraint(Widget &src, ConstraintType type, Widget &tgt) return; src_slot.constraints.push_back(Constraint(type, tgt_slot)); + src_slot.constraints.back().spacing = sp; tgt_slot.constraints.push_back(Constraint(complement(type), src_slot)); + tgt_slot.constraints.back().spacing = sp; update(); } +void Layout::add_constraint(Widget &src, ConstraintType type, Widget &tgt) +{ + create_constraint(src, type, tgt, -1); +} + +void Layout::add_constraint(Widget &src, ConstraintType type, Widget &tgt, unsigned spacing) +{ + create_constraint(src, type, tgt, spacing); +} + void Layout::set_gravity(Widget &wdg, int h, int v) { Slot &slot = get_slot_for_widget(wdg); @@ -221,19 +255,27 @@ void Layout::set_expand(Widget &wdg, bool h, bool v) void Layout::update() { - solve_constraints(HORIZONTAL); - solve_constraints(VERTICAL); + solve_constraints(HORIZONTAL, UPDATE); + solve_constraints(VERTICAL, UPDATE); for(list::iterator i=slots.begin(); i!=slots.end(); ++i) (*i)->widget.set_geometry((*i)->geom); } -void Layout::solve_constraints(int dir) +void Layout::autosize() +{ + solve_constraints(HORIZONTAL, AUTOSIZE); + solve_constraints(VERTICAL, AUTOSIZE); + + container->set_size(autosize_geom.w, autosize_geom.h); +} + +void Layout::solve_constraints(int dir, SolveMode mode) { Pointers &ptrs = pointers[dir&VERTICAL]; const Geometry &geom = container->get_geometry(); - if(geom.*(ptrs.dim)::iterator i=slots.begin(); i!=slots.end(); ++i) { - linprog.get_objective_row()[(*i)->index*5] = ((*i)->*(ptrs.packing)).gravity/weight; - linprog.get_objective_row()[(*i)->index*5+1] = (((*i)->*(ptrs.packing)).expand ? weight : -1); + LinearProgram::Row objective = linprog.get_objective_row(); + if(mode==AUTOSIZE) + { + objective[(*i)->index*5] = -1; + objective[(*i)->index*5+1] = -1; + } + else + { + objective[(*i)->index*5] = ((*i)->*(ptrs.packing)).gravity/weight; + objective[(*i)->index*5+1] = (((*i)->*(ptrs.packing)).expand ? weight : -1); + } { // Prevent the widget from going past the container's low edge. @@ -255,6 +306,7 @@ void Layout::solve_constraints(int dir) row.back() = margin.*(ptrs.low_margin); } + if(mode==UPDATE) { // Prevent the widget from going past the container's high edge. LinearProgram::Row row = linprog.add_row(); @@ -264,6 +316,16 @@ void Layout::solve_constraints(int dir) row.back() = geom.*(ptrs.dim)-margin.*(ptrs.high_margin); } + 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. */ + LinearProgram::Row row = linprog.add_row(); + row[(*i)->index*5+2] = 1; + row[(*i)->index*5+3] = -1; + } + { /* Only allow the widget's dimension to increase. The geometry has previously been set to the smallest allowable size. */ @@ -289,24 +351,37 @@ void Layout::solve_constraints(int dir) if(j->type&TARGET_DIM) row[j->target.index*5+1] = -1; if(j->type&SPACING) - row.back() = this->*(ptrs.spacing); + row.back() = (j->spacing>=0 ? j->spacing : this->*(ptrs.spacing)); } } if(!linprog.solve()) return; - for(list::iterator i=slots.begin(); i!=slots.end(); ++i) + if(mode==AUTOSIZE) { - (*i)->geom.*(ptrs.pos) = linprog.get_variable((*i)->index*5); - (*i)->geom.*(ptrs.dim) = linprog.get_variable((*i)->index*5+1); + autosize_geom.*(ptrs.dim) = 0; + for(list::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)); + } + } + else + { + for(list::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); + } } } Layout::Constraint::Constraint(ConstraintType t, Slot &s): type(t), - target(s) + target(s), + spacing(-1) { } @@ -336,7 +411,10 @@ void Layout::Slot::autosize_changed() if(autosize_geom.w<=geom.w && autosize_geom.h<=geom.h) widget.set_geometry(geom); else + { + layout.container->signal_autosize_changed.emit(); layout.update(); + } }