X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flayout.cpp;h=1cf35c722a3a95476532ec1d35898aa7a0e5b903;hb=58d820ce194de4e78e4718f7cee2159ee0a64925;hp=b8d8fb7d23ad6b196d68550c71f7de6db6f29205;hpb=813a0fc10cf5f7aaa6356cd97a4258fa78b9b87f;p=libs%2Fgltk.git diff --git a/source/layout.cpp b/source/layout.cpp index b8d8fb7..1cf35c7 100644 --- a/source/layout.cpp +++ b/source/layout.cpp @@ -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::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::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::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]; @@ -250,7 +259,7 @@ Layout::ConstraintType Layout::complement(ConstraintType type) void Layout::create_constraint(Widget &src, ConstraintType type, Widget &tgt, int sp) { if(&src==&tgt) - throw invalid_argument("&src==&tgt"); + throw invalid_argument("Layout::create_constraint"); Slot &src_slot = get_slot_for_widget(src); Slot &tgt_slot = get_slot_for_widget(tgt); @@ -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); @@ -343,7 +362,7 @@ void Layout::solve_constraints(int dir, SolveMode mode) 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_vars[dir]+1); - float weight = slots.size(); + float weight = slots.size()+1; unsigned k = n_active_slots*5; for(list::iterator i=slots.begin(); i!=slots.end(); ++i) { @@ -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; @@ -413,14 +439,15 @@ void Layout::solve_constraints(int dir, SolveMode mode) { LinearProgram::Row row = linprog.add_row(); float polarity = ((j->type&SELF_DIM) ? -1 : 1); + float dim_weight = ((j->type&HALF_DIM) ? 0.5f : 1); if(j->type&SELF_POS) row[(*i)->index*5] = polarity; if(j->type&SELF_DIM) - row[(*i)->index*5+1] = polarity; + row[(*i)->index*5+1] = polarity*dim_weight; if(j->type&TARGET_POS) row[j->target.index*5] = -polarity; if(j->type&TARGET_DIM) - row[j->target.index*5+1] = -polarity; + row[j->target.index*5+1] = -polarity*dim_weight; if(j->type&SPACING) row.back() = (j->spacing>=0 ? j->spacing : this->*(ptrs.spacing)); if(j->type&SLACK) @@ -470,13 +497,13 @@ 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)); widget.signal_visibility_changed.connect(sigc::mem_fun(this, &Slot::visibility_changed)); - widget.autosize(); - autosize_geom = widget.get_geometry(); + widget.autosize(autosize_geom); } void Layout::Slot::autosize_changed() @@ -600,10 +627,14 @@ void operator>>(const LexicalConverter &conv, Layout::ConstraintType &ctype) ctype = Layout::FAR_LEFT_OF; else if(str=="ALIGN_TOP") ctype = Layout::ALIGN_TOP; + else if(str=="ALIGN_VCENTER") + ctype = Layout::ALIGN_VCENTER; else if(str=="ALIGN_BOTTOM") ctype = Layout::ALIGN_BOTTOM; else if(str=="ALIGN_RIGHT") ctype = Layout::ALIGN_RIGHT; + else if(str=="ALIGN_HCENTER") + ctype = Layout::ALIGN_HCENTER; else if(str=="ALIGN_LEFT") ctype = Layout::ALIGN_LEFT; else if(str=="COPY_WIDTH")