X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flayout.cpp;h=5ebb55ccf4f8822de2423427d4c795c8d906ecf8;hb=fea22d7bdfae9e2cb70a6c0c1a3f85da531e2de2;hp=993c82f42c7ce0d8f683065d9cf4d01f127cd895;hpb=7a0f255ecf23391f09488ac54fb9b1124827dfa7;p=libs%2Fgltk.git diff --git a/source/layout.cpp b/source/layout.cpp index 993c82f..5ebb55c 100644 --- a/source/layout.cpp +++ b/source/layout.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include "arrangement.h" #include "container.h" #include "layout.h" #include "widget.h" @@ -136,16 +139,45 @@ void Layout::set_column_spacing(unsigned s) update(); } +void Layout::push_arrangement(Arrangement &arr) +{ + arrangement_stack.push_back(&arr); +} + +Arrangement *Layout::get_arrangement() const +{ + if(arrangement_stack.empty()) + return 0; + else + return arrangement_stack.back(); +} + +void Layout::pop_arrangement(Arrangement &arr) +{ + list::iterator begin = find(arrangement_stack.begin(), arrangement_stack.end(), &arr); + if(begin==arrangement_stack.end()) + return; + + while(1) + { + Arrangement *top = arrangement_stack.back(); + arrangement_stack.pop_back(); + if(!arrangement_stack.empty()) + arrangement_stack.back()->arrange(*top); + if(top==&arr) + break; + } +} + void Layout::add_widget(Widget &wdg) { if(!container) throw logic_error("!container"); - Slot *slot = create_slot(wdg); - for(list::iterator i=slot->constraints.begin(); i!=slot->constraints.end(); ++i) - i->target.constraints.push_back(Constraint(complement(i->type), *slot)); - slots.push_back(slot); + slots.push_back(new Slot(*this, wdg)); update_slot_indices(); + if(!arrangement_stack.empty()) + arrangement_stack.back()->arrange(wdg); if(container) update(); } @@ -176,17 +208,12 @@ void Layout::remove_widget(Widget &wdg) } } -Layout::Slot *Layout::create_slot(Widget &wdg) -{ - return new Slot(*this, wdg); -} - void Layout::update_slot_indices() { n_active_slots = 0; for(list::iterator i=slots.begin(); i!=slots.end(); ++i) { - if((*i)->widget.is_visible()) + if((*i)->widget.is_visible() || (*i)->ghost) (*i)->index = n_active_slots++; else (*i)->index = -1; @@ -268,6 +295,19 @@ void Layout::set_expand(Widget &wdg, bool h, bool v) update(); } +void Layout::set_ghost(Widget &wdg, bool g) +{ + Slot &slot = get_slot_for_widget(wdg); + + slot.ghost = g; + + if(!wdg.is_visible()) + { + update_slot_indices(); + update(); + } +} + void Layout::update() { solve_constraints(HORIZONTAL, UPDATE); @@ -277,12 +317,13 @@ void Layout::update() (*i)->widget.set_geometry((*i)->geom); } -void Layout::autosize() +void Layout::autosize(Geometry &geom) { solve_constraints(HORIZONTAL, AUTOSIZE); solve_constraints(VERTICAL, AUTOSIZE); - container->set_size(autosize_geom.w, autosize_geom.h); + geom.w = max(geom.w, autosize_geom.w); + geom.h = max(geom.h, autosize_geom.h); } void Layout::solve_constraints(int dir, SolveMode mode) @@ -299,6 +340,7 @@ void Layout::solve_constraints(int dir, SolveMode mode) remaining three are slack columns; see below for their purposes. */ LinearProgram linprog(n_active_slots*5+n_slack_constraints[dir]+1); float weight = slots.size(); + unsigned k = n_active_slots*5; for(list::iterator i=slots.begin(); i!=slots.end(); ++i) { if((*i)->index<0) @@ -355,7 +397,6 @@ void Layout::solve_constraints(int dir, SolveMode mode) /* Add rows for user-defined constraints. Constraints are always added in pairs, so it's only necessary to create a row for one half. */ - unsigned k = n_active_slots*5; for(list::iterator j=(*i)->constraints.begin(); j!=(*i)->constraints.end(); ++j) if(j->target.index>(*i)->index && (j->type&1)==dir) { @@ -417,7 +458,8 @@ Layout::Packing::Packing(): Layout::Slot::Slot(Layout &l, Widget &w): layout(l), index(0), - widget(w) + widget(w), + ghost(false) { vert_pack.gravity = 1; widget.signal_autosize_changed.connect(sigc::mem_fun(this, &Slot::autosize_changed)); @@ -431,7 +473,7 @@ void Layout::Slot::autosize_changed() widget.autosize(); autosize_geom = widget.get_geometry(); - if(!widget.is_visible()) + if(!widget.is_visible() && !ghost) return; // If the widget fits in the area it had, just leave it there. @@ -447,7 +489,7 @@ void Layout::Slot::autosize_changed() void Layout::Slot::visibility_changed(bool v) { layout.update_slot_indices(); - if(v) + if(v || ghost) { layout.container->signal_autosize_changed.emit(); layout.update(); @@ -455,6 +497,116 @@ void Layout::Slot::visibility_changed(bool v) } +Layout::Loader::Loader(Layout &l, const WidgetMap &wm): + DataFile::ObjectLoader(l), + wdg_map(wm) +{ + add("column_spacing", &Loader::column_spacing); + add("margin", &Loader::margin); + add("row_spacing", &Loader::row_spacing); + add("spacing", &Loader::spacing); + add("widget", &Loader::widget); +} + +void Layout::Loader::column_spacing(unsigned s) +{ + obj.set_column_spacing(s); +} + +void Layout::Loader::margin() +{ + Sides sides; + load_sub(sides); + obj.set_margin(sides); +} + +void Layout::Loader::spacing(unsigned s) +{ + obj.set_spacing(s); +} + +void Layout::Loader::row_spacing(unsigned s) +{ + obj.set_row_spacing(s); +} + +void Layout::Loader::widget(const string &n) +{ + Widget &wdg = *get_item(wdg_map, n); + WidgetLoader ldr(obj, wdg, wdg_map); + load_sub_with(ldr); +} + + +Layout::WidgetLoader::WidgetLoader(Layout &l, Widget &w, const Layout::Loader::WidgetMap &wm): + layout(l), + widget(w), + wdg_map(wm) +{ + add("constraint", &WidgetLoader::constraint); + add("expand", &WidgetLoader::expand); + add("ghost", &WidgetLoader::ghost); + add("gravity", &WidgetLoader::gravity); +} + +void Layout::WidgetLoader::constraint(ConstraintType type, const string &n) +{ + Widget &target = *get_item(wdg_map, n); + layout.add_constraint(widget, type, target); +} + +void Layout::WidgetLoader::expand(bool h, bool v) +{ + layout.set_expand(widget, h, v); +} + +void Layout::WidgetLoader::ghost(bool g) +{ + layout.set_ghost(widget, g); +} + +void Layout::WidgetLoader::gravity(int h, int v) +{ + layout.set_gravity(widget, h, v); +} + + +void operator>>(const LexicalConverter &conv, Layout::ConstraintType &ctype) +{ + const string &str = conv.get(); + if(str=="ABOVE") + ctype = Layout::ABOVE; + else if(str=="BELOW") + ctype = Layout::BELOW; + else if(str=="RIGHT_OF") + ctype = Layout::RIGHT_OF; + else if(str=="LEFT_OF") + ctype = Layout::LEFT_OF; + else if(str=="FAR_ABOVE") + ctype = Layout::FAR_ABOVE; + else if(str=="FAR_BELOW") + ctype = Layout::FAR_BELOW; + else if(str=="FAR_RIGHT_OF") + ctype = Layout::FAR_RIGHT_OF; + else if(str=="FAR_LEFT_OF") + ctype = Layout::FAR_LEFT_OF; + else if(str=="ALIGN_TOP") + ctype = Layout::ALIGN_TOP; + else if(str=="ALIGN_BOTTOM") + ctype = Layout::ALIGN_BOTTOM; + else if(str=="ALIGN_RIGHT") + ctype = Layout::ALIGN_RIGHT; + else if(str=="ALIGN_LEFT") + ctype = Layout::ALIGN_LEFT; + else if(str=="COPY_WIDTH") + ctype = Layout::COPY_WIDTH; + else if(str=="COPY_HEIGHT") + ctype = Layout::COPY_HEIGHT; + else + throw lexical_error(format("conversion of '%s' to ConstraintType", str)); +} + + Layout::LinearProgram::LinearProgram(unsigned s): n_columns(s), n_rows(1),