diff --git a/libs/canvas/canvas/cbox.h b/libs/canvas/canvas/cbox.h index e3c7932dd9..ccfc614fa1 100644 --- a/libs/canvas/canvas/cbox.h +++ b/libs/canvas/canvas/cbox.h @@ -50,14 +50,15 @@ public: BoxConstrainedItem* pack_start (Item*, PackOptions primary_axis_packing = PackOptions (0), PackOptions secondary_axis_packing = PackOptions (PackExpand|PackFill)); BoxConstrainedItem* pack_end (Item*, PackOptions primary_axis_packing = PackOptions (0), PackOptions secondary_axis_packing = PackOptions (PackExpand|PackFill)); + void add_vertical_box_constraints (kiwi::Solver& solver, BoxConstrainedItem* ci, BoxConstrainedItem* prev, double expanded_size, double main_dimenion, double second_dimension, double alloc_dimension); + void add_horizontal_box_constraints (kiwi::Solver& solver, BoxConstrainedItem* ci, BoxConstrainedItem* prev, double expanded_size, double main_dimenion, double second_dimension, double alloc_dimension); + void set_collapse_on_hide (bool); void set_homogenous (bool); void preferred_size(Duple& minimum, Duple& natural) const; void size_allocate (Rect const &); - ConstrainedItem* add_constrained (Item*); - protected: Orientation orientation; diff --git a/libs/canvas/canvas/constrained_item.h b/libs/canvas/canvas/constrained_item.h index 38b4591cc4..06aa65d510 100644 --- a/libs/canvas/canvas/constrained_item.h +++ b/libs/canvas/canvas/constrained_item.h @@ -46,12 +46,17 @@ class /* LIBCANVAS_API */ ConstrainedItem kiwi::Variable& width () { return _width; } kiwi::Variable& height () { return _height; } + kiwi::Variable& center_x () { return _center_x; } + kiwi::Variable& center_y () { return _center_y; } + void constrained (ConstraintPacker const & parent); virtual bool involved (kiwi::Constraint const &) const; std::vector const & constraints() const { return _constraints; } void add_constraint (kiwi::Constraint const & c) { _constraints.push_back (c); } + virtual void dump (std::ostream&); + protected: Item& _item; std::vector _constraints; @@ -63,7 +68,10 @@ class /* LIBCANVAS_API */ ConstrainedItem kiwi::Variable _width; kiwi::Variable _height; - virtual void dump (std::ostream&); + /* derived */ + + kiwi::Variable _center_x; + kiwi::Variable _center_y; }; class /* LIBCANVAS_API */ BoxConstrainedItem : public ConstrainedItem @@ -74,8 +82,6 @@ class /* LIBCANVAS_API */ BoxConstrainedItem : public ConstrainedItem virtual bool involved (kiwi::Constraint const &) const; - kiwi::Variable& center_x () { return _center_x; } - kiwi::Variable& center_y () { return _center_y; } kiwi::Variable& left_margin () { return _left_margin; } kiwi::Variable& right_margin () { return _right_margin; } kiwi::Variable& top_margin () { return _top_margin; } @@ -98,8 +104,6 @@ class /* LIBCANVAS_API */ BoxConstrainedItem : public ConstrainedItem void dump (std::ostream&); private: - kiwi::Variable _center_x; - kiwi::Variable _center_y; kiwi::Variable _left_margin; kiwi::Variable _right_margin; kiwi::Variable _top_margin; diff --git a/libs/canvas/cbox.cc b/libs/canvas/cbox.cc index 112e206a15..503fdecc72 100644 --- a/libs/canvas/cbox.cc +++ b/libs/canvas/cbox.cc @@ -128,12 +128,6 @@ cBox::remove (Item* item) ConstraintPacker::remove (item); } -ConstrainedItem* -cBox::add_constrained (Item* item) -{ - return pack (item, PackOptions (0), PackOptions (PackExpand|PackFill)); -} - BoxConstrainedItem* cBox::pack_start (Item* item, PackOptions primary_axis_opts, PackOptions secondary_axis_opts) { @@ -168,13 +162,11 @@ cBox::preferred_size (Duple& min, Duple& natural) const Distance largest_opposite = 0; Duple i_min, i_natural; - cerr << "cbox::prefsize (" << (orientation == Vertical ? " vert) " : " horiz) ") << endl; - for (Order::const_iterator o = order.begin(); o != order.end(); ++o) { (*o)->item().preferred_size (i_min, i_natural); - cerr << '\t' << (*o)->item().whoami() << " min " << i_min << " nat " << i_natural << endl; + // cerr << '\t' << (*o)->item().whoami() << " min " << i_min << " nat " << i_natural << endl; if ((*o)->primary_axis_pack_options() & PackExpand) { n_expanding++; @@ -183,9 +175,6 @@ cBox::preferred_size (Duple& min, Duple& natural) const if (i_natural.height() > largest) { largest = i_natural.height(); } - if (i_natural.width() > largest) { - largest_opposite = i_natural.width(); - } } else { if (i_natural.width() > largest) { largest = i_natural.width(); @@ -199,36 +188,43 @@ cBox::preferred_size (Duple& min, Duple& natural) const n_nonexpanding++; if (orientation == Vertical) { - if (i_natural.height() > 0) { - non_expanding_used += i_natural.height(); - } else { - non_expanding_used += i_min.height(); - } + non_expanding_used += i_natural.height(); } else { - if (i_natural.width() > 0) { - non_expanding_used += i_natural.width(); - } else { - non_expanding_used += i_min.width(); - } + non_expanding_used += i_natural.width(); } } + + /* determine the maximum size for the opposite axis. All items + * will be this size or less on this axis + */ + + if (orientation == Vertical) { + if (i_natural.width() > largest_opposite) { + largest_opposite = i_natural.width(); + } + } else { + if (i_natural.height() > largest_opposite) { + largest_opposite = i_natural.height(); + } + } + total++; } Duple r; if (orientation == Vertical) { - cerr << "+++ vertical box, neu = " << non_expanding_used << " largest = " << largest << " opp " << largest_opposite << " total " << total << endl; - min.x = non_expanding_used + (n_expanding * largest_opposite) + _left_margin + _right_margin + ((total - 1) * _spacing); + // cerr << "+++ vertical box, neu = " << non_expanding_used << " neuo " << non_expanding_used_opposite << " largest = " << largest << " opp " << largest_opposite << " total " << total << endl; min.y = non_expanding_used + (n_expanding * largest) + _top_margin + _bottom_margin + ((total - 1) * _spacing); + min.x = largest_opposite + _left_margin + _right_margin; } else { - cerr << "+++ horiz box, neu = " << non_expanding_used << " largest = " << largest << " opp " << largest_opposite << " total " << total << endl; + // cerr << "+++ horiz box, neu = " << non_expanding_used << " neuo " << non_expanding_used_opposite << " largest = " << largest << " opp " << largest_opposite << " total " << total << endl; min.x = non_expanding_used + (n_expanding * largest) + _left_margin + _right_margin + ((total - 1) * _spacing); - min.y = non_expanding_used + (n_expanding * largest_opposite) + _top_margin + _bottom_margin + ((total - 1) * _spacing); + min.y = largest_opposite + _top_margin + _bottom_margin; } - cerr << "++++ " << whoami() << " rpref " << min << endl; + // cerr << whoami() << " preferred-size = " << min << endl; natural = min; } @@ -274,205 +270,53 @@ cBox::size_allocate (Rect const & r) expanded_size = (r.width() - _left_margin - _right_margin - ((total - 1) * _spacing) - non_expanding_used) / n_expanding; } - cerr << "\n\n\n" << whoami() << " SIZE-ALLOC " << r << " expanded items (" << n_expanding << ")will be " << expanded_size << " neu " << non_expanding_used << " t = " << total << " s " << _spacing << '\n'; + // cerr << "\n\n\n" << whoami() << " SIZE-ALLOC " << r << " expanded items (" << n_expanding << ")will be " << expanded_size << " neu " << non_expanding_used << " t = " << total << " s " << _spacing << '\n'; - Order::size_type n = 0; Order::iterator prev = order.end(); + try { - for (Order::iterator o = order.begin(); o != order.end(); ++o, ++n) { + for (Order::iterator o = order.begin(); o != order.end(); ++o) { Duple min, natural; + (*o)->item().preferred_size (min, natural); - cerr << "\t" << (*o)->item().whoami() << " min " << min << " nat " << natural << endl; - - /* setup center_{x,y} variables in case calling/using - * code wants to use them for additional constraints - */ - - solver.addConstraint ((*o)->center_x() == (*o)->left() + ((*o)->width() / 2.)); - solver.addConstraint ((*o)->center_y() == (*o)->top() + ((*o)->height() / 2.)); - - /* Add constraints that will size the item within this box */ - if (orientation == Vertical) { - - /* set up constraints for expand/fill options, done by - * adjusting height and margins of each item - */ - - if ((*o)->primary_axis_pack_options() & PackExpand) { - - /* item will take up more than it's natural - * size, if space is available - */ - - if ((*o)->primary_axis_pack_options() & PackFill) { - - /* item is expanding to fill all - * available space and wants that space - * for itself. - */ - - solver.addConstraint ((*o)->height() == expanded_size | kiwi::strength::strong); - solver.addConstraint ((*o)->top_padding() == 0. | kiwi::strength::strong); - solver.addConstraint ((*o)->bottom_padding() == 0. | kiwi::strength::strong); - - } else { - - /* item is expanding to fill all - * available space and wants that space - * as padding - */ - - solver.addConstraint ((*o)->height() == natural.height()); - solver.addConstraint ((*o)->top_padding() + (*o)->bottom_padding() + (*o)->height() == expanded_size | kiwi::strength::strong); - solver.addConstraint ((*o)->bottom_padding() == (*o)->top_padding() | kiwi::strength::strong); - } - - } else { - - /* item is not going to expand to fill - * available space. just give it's preferred - * height. - */ - - cerr << (*o)->item().whoami() << " will use natural height of " << natural.height() << endl; - solver.addConstraint ((*o)->height() == natural.height()); - solver.addConstraint ((*o)->top_padding() == 0.); - solver.addConstraint ((*o)->bottom_padding() == 0.); - } - - - /* now set upper left corner of the item */ - - if (n == 0) { - - /* first item */ - - solver.addConstraint ((*o)->top() == _top_margin + (*o)->top_padding() | kiwi::strength::strong); - - } else { - /* subsequent items */ - - solver.addConstraint ((*o)->top() == (*prev)->bottom() + (*prev)->bottom_padding() + (*o)->top_padding() + _spacing | kiwi::strength::strong); - } - - /* set the side-effect variables and/or constants */ - - solver.addConstraint ((*o)->left() + (*o)->width() == (*o)->right()| kiwi::strength::strong); - solver.addConstraint ((*o)->bottom() == (*o)->top() + (*o)->height()); - solver.addConstraint ((*o)->left() == _left_margin + (*o)->left_padding() | kiwi::strength::strong); - - if (!((*o)->secondary_axis_pack_options() & PackExpand) && natural.width() > 0) { - cerr << "\t\t also using natural width of " << natural.width() << endl; - solver.addConstraint ((*o)->width() == natural.width()); - } else { - cerr << "\t\t also using container width of " << r.width() << endl; - solver.addConstraint ((*o)->width() == r.width() - (_left_margin + _right_margin + (*o)->right_padding()) | kiwi::strength::strong); - } - - + add_vertical_box_constraints (solver, *o, prev == order.end() ? 0 : *prev, expanded_size, natural.height(), natural.width(), r.width()); } else { - - /* set up constraints for expand/fill options, done by - * adjusting width and margins of each item - */ - - if ((*o)->primary_axis_pack_options() & PackExpand) { - - /* item will take up more than it's natural - * size, if space is available - */ - - if ((*o)->primary_axis_pack_options() & PackFill) { - - /* item is expanding to fill all - * available space and wants that space - * for itself. - */ - - solver.addConstraint ((*o)->width() == expanded_size | kiwi::strength::strong); - solver.addConstraint ((*o)->left_padding() == 0. | kiwi::strength::strong); - solver.addConstraint ((*o)->right_padding() == 0. | kiwi::strength::strong); - - } else { - - /* item is expanding to fill all - * available space and wants that space - * as padding - */ - - solver.addConstraint ((*o)->width() == natural.width()); - solver.addConstraint ((*o)->left_padding() + (*o)->right_padding() + (*o)->width() == expanded_size | kiwi::strength::strong); - solver.addConstraint ((*o)->left_padding() == (*o)->right_padding() | kiwi::strength::strong); - } - - } else { - - /* item is not going to expand to fill - * available space. just give it's preferred - * width. - */ - - solver.addConstraint ((*o)->width() == natural.width()); - solver.addConstraint ((*o)->left_padding() == 0.); - solver.addConstraint ((*o)->right_padding() == 0.); - } - - - /* now set upper left corner of the item */ - - if (n == 0) { - - /* first item */ - - solver.addConstraint ((*o)->left() == _left_margin + (*o)->left_padding() | kiwi::strength::strong); - - } else { - /* subsequent items */ - - solver.addConstraint ((*o)->left() == (*prev)->right() + (*prev)->right_padding() + (*o)->left_padding() + _spacing | kiwi::strength::strong); - } - - /* set the side-effect variables and/or constants */ - - solver.addConstraint ((*o)->bottom() == (*o)->top() + (*o)->height()); - solver.addConstraint ((*o)->right() == (*o)->left() + (*o)->width()); - solver.addConstraint ((*o)->top() == _top_margin + (*o)->top_padding() | kiwi::strength::strong); - - if (!((*o)->secondary_axis_pack_options() & PackExpand) && natural.height() > 0) { - cerr << "\t\tand natural height of " << natural.height() << endl; - solver.addConstraint ((*o)->height() == natural.height()); - } else { - cerr << "\t\tand container height of " << r.height() << endl; - solver.addConstraint ((*o)->height() == r.height() - (_top_margin + _bottom_margin + (*o)->bottom_padding()) | kiwi::strength::strong); - } - } - - /* Add constraints that come with the item */ - - std::vector const & constraints ((*o)->constraints()); - - for (std::vector::const_iterator c = constraints.begin(); c != constraints.end(); ++c) { - solver.addConstraint (*c); + add_horizontal_box_constraints (solver, *o, prev == order.end() ? 0 : *prev, expanded_size, natural.width(), natural.height(), r.height()); } prev = o; } + /* There maybe items that were not pack_start()'ed or + * pack_end()'ed into this box, but just added with + * constraints. Find all items in the box, and add any + * constraints that come with them. + */ + + for (ConstrainedItemMap::const_iterator x = constrained_map.begin(); x != constrained_map.end(); ++x) { + + std::vector const & constraints (x->second->constraints()); + + for (std::vector::const_iterator c = constraints.begin(); c != constraints.end(); ++c) { + solver.addConstraint (*c); + } + } + + } catch (std::exception& e) { cerr << "Setting up sovler failed: " << e.what() << endl; return; } - solver.updateVariables (); //solver.dump (cerr); - for (Order::iterator o = order.begin(); o != order.end(); ++o, ++n) { - (*o)->dump (cerr); - } + //for (ConstrainedItemMap::const_iterator o = constrained_map.begin(); o != constrained_map.end(); ++o) { + //o->second->dump (cerr); + //} apply (&solver); @@ -484,3 +328,126 @@ void cBox::child_changed (bool bbox_changed) { } + +/* It would be nice to do this with templates or even by passing ptr-to-method, + * but both of them interfere with the similarly meta-programming-ish nature of + * the way that kiwi builds Constraint objects from expressions. So a macro it + * is ... + */ + +#define add_box_constraints(\ + solver, \ + bci, \ + prev, \ + expanded_size, \ + natural_main_dimension, \ + natural_second_dimension, \ + alloc_second_dimension, \ + m_main_dimension, \ + m_second_dimension, \ + m_trailing, \ + m_leading, \ + m_trailing_padding, \ + m_leading_padding, \ + m_second_trailing, \ + m_second_leading, \ + m_second_trailing_padding, \ + m_second_leading_padding) \ + \ + /* Add constraints that will size the item within this box */ \ + \ + /* set up constraints for expand/fill options, done by \ + * adjusting height and margins of each item \ + */ \ + \ + if (bci->primary_axis_pack_options() & PackExpand) { \ + \ + /* item will take up more than it's natural \ + * size, if space is available \ + */ \ + \ + if (bci->primary_axis_pack_options() & PackFill) { \ + \ + /* item is expanding to fill all \ + * available space and wants that space \ + * for itself. \ + */ \ + \ + solver.addConstraint (bci->m_main_dimension() == expanded_size | kiwi::strength::strong); \ + solver.addConstraint (bci->m_trailing_padding() == 0. | kiwi::strength::strong); \ + solver.addConstraint (bci->m_leading_padding() == 0. | kiwi::strength::strong); \ + \ + } else { \ + \ + /* item is expanding to fill all \ + * available space and wants that space \ + * as padding \ + */ \ + \ + solver.addConstraint (bci->m_main_dimension() == natural_main_dimension); \ + solver.addConstraint (bci->m_trailing_padding() + bci->m_leading_padding() + bci->m_main_dimension() == expanded_size | kiwi::strength::strong); \ + solver.addConstraint (bci->m_leading_padding() == bci->m_trailing_padding() | kiwi::strength::strong); \ + } \ + \ + } else { \ + \ + /* item is not going to expand to fill \ + * available space. just give it's preferred \ + * height. \ + */ \ + \ + /* cerr << bci->item().whoami() << " will usenatural height of " << natural.height() << endl; */ \ + \ + solver.addConstraint (bci->m_main_dimension() == natural_main_dimension); \ + solver.addConstraint (bci->m_trailing_padding() == 0.); \ + solver.addConstraint (bci->m_leading_padding() == 0.); \ + } \ + \ + /* now set upper upper edge of the item */ \ + \ + if (prev == 0) { \ + \ + /* first item */ \ + \ + solver.addConstraint (bci->m_trailing() == _top_margin + bci->m_trailing_padding() | kiwi::strength::strong); \ + \ + } else { \ + /* subsequent items */ \ + \ + solver.addConstraint (bci->m_trailing() == prev->m_leading() + prev->m_leading_padding() + bci->m_trailing_padding() + _spacing | kiwi::strength::strong); \ + } \ + \ + solver.addConstraint (bci->m_leading() == bci->m_trailing() + bci->m_main_dimension()); \ + \ + /* set the side-effect variables and/or constants */ \ + \ + solver.addConstraint (bci->m_second_trailing_padding() == 0 | kiwi::strength::weak); \ + solver.addConstraint (bci->m_second_leading_padding() == 0 | kiwi::strength::weak); \ + \ + solver.addConstraint (bci->m_second_trailing() + bci->m_second_dimension() == bci->m_second_leading()); \ + solver.addConstraint (bci->m_second_trailing() == _left_margin + bci->m_second_trailing_padding() | kiwi::strength::strong); \ + \ + if (!(bci->secondary_axis_pack_options() & PackExpand) && natural_second_dimension > 0) { \ + solver.addConstraint (bci->m_second_dimension() == natural_second_dimension); \ + } else { \ + solver.addConstraint (bci->m_second_dimension() == alloc_second_dimension - (_left_margin + _right_margin + bci->m_second_leading_padding()) | kiwi::strength::strong); \ + } + + +void +cBox::add_vertical_box_constraints (kiwi::Solver& solver, BoxConstrainedItem* ci, BoxConstrainedItem* prev, double expanded_size, double main_dimension, double second_dimension, double alloc_dimension) +{ + add_box_constraints (solver, ci, prev, expanded_size, main_dimension, second_dimension, alloc_dimension, + height, width, + top, bottom, top_padding, bottom_padding, + left, right, left_padding, right_padding); +} + +void +cBox::add_horizontal_box_constraints (kiwi::Solver& solver, BoxConstrainedItem* ci, BoxConstrainedItem* prev, double expanded_size, double main_dimension, double second_dimension, double alloc_dimension) +{ + add_box_constraints (solver, ci, prev, expanded_size, main_dimension, second_dimension, alloc_dimension, + width, height, + left, right, left_padding, right_padding, + top, bottom, top_padding, bottom_padding); +} diff --git a/libs/canvas/constrained_item.cc b/libs/canvas/constrained_item.cc index d8ea940e88..6e3388513f 100644 --- a/libs/canvas/constrained_item.cc +++ b/libs/canvas/constrained_item.cc @@ -37,7 +37,15 @@ ConstrainedItem::ConstrainedItem (Item& i) , _bottom (_item.name + " bottom") , _width (_item.name + " width") , _height (_item.name + " height") + , _center_x (_item.name + " center_x") + , _center_y (_item.name + " center_y") { + /* setup center_{x,y} variables in case calling/using + * code wants to use them for additional constraints + */ + + _constraints.push_back (center_x() == left() + (width() / 2.)); + _constraints.push_back (center_y() == top() + (height() / 2.)); } ConstrainedItem::~ConstrainedItem () @@ -50,8 +58,8 @@ ConstrainedItem::constrained (ConstraintPacker const & parent) /* our variables should be set. Deliver computed size to item */ Rect r (_left.value(), _top.value(), _right.value(), _bottom.value()); - dump (cerr); - cerr << _item.whatami() << '/' << _item.name << " constrained-alloc " << r << endl; + //dump (cerr); + // cerr << _item.whoami() << " constrained-alloc " << r << endl; _item.size_allocate (r); } @@ -59,14 +67,15 @@ ConstrainedItem::constrained (ConstraintPacker const & parent) void ConstrainedItem::dump (std::ostream& out) { - out << _item.name << " value dump:\n\n"; - - out << '\t' << "left: " << _left.value() << '\n'; - out << '\t' << "right: " << _right.value() << '\n'; - out << '\t' << "top: " << _top.value() << '\n'; - out << '\t' << "bottom: " << _bottom.value() << '\n'; - out << '\t' << "width: " << _width.value() << '\n'; - out << '\t' << "height: " << _height.value() << '\n'; + out << _item.name << " value dump:\n" + << '\t' << "left: " << _left.value() << '\n' + << '\t' << "right: " << _right.value() << '\n' + << '\t' << "top: " << _top.value() << '\n' + << '\t' << "bottom: " << _bottom.value() << '\n' + << '\t' << "width: " << _width.value() << '\n' + << '\t' << "height: " << _height.value() << '\n' + << '\t' << "center_x: " << _center_x.value() << '\n' + << '\t' << "center_y: " << _center_y.value() << '\n'; } bool @@ -77,7 +86,9 @@ ConstrainedItem::involved (Constraint const & c) const c.involves (_top) || c.involves (_bottom) || c.involves (_width) || - c.involves (_height)) { + c.involves (_height) || + c.involves (_center_x) || + c.involves (_center_y)) { return true; } @@ -88,12 +99,14 @@ ConstrainedItem::involved (Constraint const & c) const BoxConstrainedItem::BoxConstrainedItem (Item& parent, PackOptions primary_axis_opts, PackOptions secondary_axis_opts) : ConstrainedItem (parent) - , _center_x (_item.name + " center_x") - , _center_y (_item.name + " center_y") , _left_margin (_item.name + " left_margin") , _right_margin (_item.name + " right_margin") , _top_margin (_item.name + " top_margin") , _bottom_margin (_item.name + " bottom_margin") + , _left_padding (_item.name + " left_padding") + , _right_padding (_item.name + " right_padding") + , _top_padding (_item.name + " top_padding") + , _bottom_padding (_item.name + " bottom_padding") , _primary_axis_pack_options (primary_axis_opts) , _secondary_axis_pack_options (secondary_axis_opts) { @@ -110,9 +123,7 @@ BoxConstrainedItem::involved (Constraint const & c) const return true; } - if (c.involves (_center_x) || - c.involves (_center_y) || - c.involves (_left_margin) || + if (c.involves (_left_margin) || c.involves (_right_margin) || c.involves (_top_margin) || c.involves (_bottom_margin)) { @@ -127,16 +138,12 @@ BoxConstrainedItem::dump (std::ostream& out) { ConstrainedItem::dump (out); - out << '\t' << "center_x: " << _center_x.value() << '\n'; - out << '\t' << "center_y: " << _center_y.value() << '\n'; - out << '\t' << "left_margin: " << _left_margin.value() << '\n'; - out << '\t' << "right_margin: " << _right_margin.value() << '\n'; - out << '\t' << "top_margin: " << _top_margin.value() << '\n'; - out << '\t' << "bottom_margin: " << _bottom_margin.value() << '\n'; - - out << '\t' << "right_padding: " << _right_padding.value() << '\n'; - out << '\t' << "left_padding: " << _left_padding.value() << '\n'; - out << '\t' << "top_padding: " << _top_padding.value() << '\n'; - out << '\t' << "bottom_padding: " << _bottom_padding.value() << '\n'; + out << '\t' << "left_margin: " << _left_margin.value() << '\n' + << '\t' << "right_margin: " << _right_margin.value() << '\n' + << '\t' << "top_margin: " << _top_margin.value() << '\n' + << '\t' << "bottom_margin: " << _bottom_margin.value() << '\n' + << '\t' << "right_padding: " << _right_padding.value() << '\n' + << '\t' << "left_padding: " << _left_padding.value() << '\n' + << '\t' << "top_padding: " << _top_padding.value() << '\n' + << '\t' << "bottom_padding: " << _bottom_padding.value() << '\n'; } -