2 Copyright (C) 2011-2014 Paul Davis
3 Author: Carl Hetherington <cth@carlh.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "canvas/box.h"
23 #include "canvas/rectangle.h"
25 using namespace ArdourCanvas;
27 Box::Box (Canvas* canvas, Orientation o)
31 , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
32 , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
35 self = new Rectangle (this);
36 self->set_outline (false);
37 self->set_fill (false);
40 Box::Box (Item* parent, Orientation o)
44 , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
45 , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
48 self = new Rectangle (this);
49 self->set_outline (false);
50 self->set_fill (false);
54 Box::Box (Item* parent, Duple const & p, Orientation o)
58 , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
59 , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
62 self = new Rectangle (this);
63 self->set_outline (false);
64 self->set_fill (false);
68 Box::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
70 Item::render_children (area, context);
74 Box::compute_bounding_box () const
76 _bounding_box = boost::none;
79 _bounding_box_dirty = false;
83 add_child_bounding_boxes (!collapse_on_hide);
86 Rect r = _bounding_box.get();
88 _bounding_box = r.expand (top_padding + outline_width() + top_margin,
89 right_padding + outline_width() + right_margin,
90 bottom_padding + outline_width() + bottom_margin,
91 left_padding + outline_width() + left_margin);
94 _bounding_box_dirty = false;
98 Box::set_spacing (double s)
104 Box::set_padding (double t, double r, double b, double l)
113 right_padding = last;
117 bottom_padding = last;
125 Box::set_margin (double t, double r, double b, double l)
136 bottom_margin = last;
146 if (_bounding_box_dirty) {
147 compute_bounding_box ();
150 if (!_bounding_box) {
155 Rect r (_bounding_box.get());
157 /* XXX need to shrink by margin */
163 Box::reposition_children ()
165 Duple previous_edge (0, 0);
166 Distance largest_width = 0;
167 Distance largest_height = 0;
171 for (std::list<Item*>::iterator i = _items.begin(); ++i != _items.end(); ++i) {
172 boost::optional<Rect> bb = (*i)->bounding_box();
174 largest_height = std::max (largest_height, bb.get().height());
175 largest_width = std::max (largest_width, bb.get().width());
180 for (std::list<Item*>::iterator i = _items.begin(); ++i != _items.end(); ++i) {
182 (*i)->set_position (previous_edge);
184 if (orientation == Vertical) {
189 shift = largest_height;
191 boost::optional<Rect> bb = (*i)->bounding_box();
193 if (!(*i)->visible()) {
194 /* invisible child */
195 if (!collapse_on_hide) {
196 /* still add in its size */
198 shift += bb.get().height();
203 shift += bb.get().height();
208 previous_edge = previous_edge.translate (Duple (0, spacing + shift));
215 shift = largest_width;
217 boost::optional<Rect> bb = (*i)->bounding_box();
219 if (!(*i)->visible()) {
220 if (!collapse_on_hide) {
222 shift += bb.get().width();
227 shift += bb.get().width();
232 previous_edge = previous_edge.translate (Duple (spacing + shift, 0));
236 _bounding_box_dirty = true;
241 Box::pack_end (Item* i, double extra_padding)
247 /* prepend new child */
249 reposition_children ();
252 Box::pack_start (Item* i, double extra_padding)
258 /* append new child */
260 reposition_children ();
270 Box::child_changed ()
272 /* catch visibility and size changes */
274 Item::child_changed ();
275 reposition_children ();
279 Box::set_collapse_on_hide (bool yn)
281 if (collapse_on_hide != yn) {
282 collapse_on_hide = yn;
283 reposition_children ();
289 VBox::VBox (Canvas* c)
297 VBox::VBox (Item* i, Duple const & position)
298 : Box (i, position, Vertical)
302 HBox::HBox (Canvas* c)
303 : Box (c, Horizontal)
307 : Box (i, Horizontal)
310 HBox::HBox (Item* i, Duple const & position)
311 : Box (i, position, Horizontal)