4 * This file is part of LyX, the document processor.
5 * Licence details can be found in the file COPYING.
7 * \author Angus Leeming
9 * Full author contact details are available in file CREDITS.
11 * A generic layout engine.
13 * Draws heavily on the GTK+ files gtkbox.[ch], gtkhbox.[ch],
14 * for both inspiration and implementation,
15 * and from which this notice is taken:
17 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 #include "LayoutEngine.h"
26 #include "lyx_forms.h"
28 #include <boost/assert.hpp>
29 #include <boost/bind.hpp>
32 using boost::shared_ptr;
40 bool BoxList::empty() const
46 BoxList::size_type BoxList::size() const
58 shared_ptr<Box> BoxList::push_back(Box const & box)
60 data_.push_back(shared_ptr<Box>(new Box(box)));
65 BoxList::iterator BoxList::begin()
71 BoxList::iterator BoxList::end()
77 BoxList::const_iterator BoxList::begin() const
83 BoxList::const_iterator BoxList::end() const
89 BoxList::iterator BoxList::erase(iterator where)
91 return data_.erase(where);
95 BoxList::iterator BoxList::erase(iterator begin, iterator end)
97 return data_.erase(begin, end);
101 Box::Orientation Box::default_orientation_ = Box::Vertical;
102 Box::Packing Box::default_packing_ = Box::Shrink;
105 Box::Box(dimension_t min_w, dimension_t min_h)
113 orientation_(default_orientation_),
114 packing_(default_packing_),
115 prefered_visibility_(Visible)
119 void Box::setMinimumDimensions(dimension_t min_w, dimension_t min_h)
126 Box::Orientation Box::orientation() const
132 void Box::set(Orientation o)
138 Box::Orientation Box::defaultOrientation()
140 return default_orientation_;
144 void Box::setDefault(Orientation o)
146 default_orientation_ = o;
150 Box::Packing Box::packing() const
156 void Box::set(Packing p)
162 Box::Packing Box::defaultPacking()
164 return default_packing_;
168 void Box::setDefault(Packing p)
170 default_packing_ = p;
174 bool Box::expandable() const
179 if (packing_ == Expand)
182 BoxList::const_iterator it = children_.begin();
183 BoxList::const_iterator const end = children_.end();
184 for (; it != end; ++it) {
185 if ((*it)->visible() && (*it)->packing() == Expand)
193 Box::PreferedVisibility Box::preferedVisibility() const
195 return prefered_visibility_;
199 void Box::set(PreferedVisibility pv)
201 prefered_visibility_ = pv;
202 if (pv == Invisible && visible_)
207 bool Box::visible() const
215 if (prefered_visibility_ == Invisible)
220 for_each(children_.begin(), children_.end(),
221 bind(&Box::show, _1));
229 for_each(children_.begin(), children_.end(),
230 bind(&Box::hide, _1));
234 BoxList & Box::children()
240 BoxList const & Box::children() const
246 Box::dimension_t Box::width() const
252 Box::dimension_t Box::height() const
258 Box::dimension_t Box::xorigin() const
264 Box::dimension_t Box::yorigin() const
270 void Box::updateMetrics()
273 expandMetrics(x_, y_, w_, h_);
277 void Box::shrinkMetrics()
279 dimension_t width = 0;
280 dimension_t height = 0;
282 BoxList::iterator it = children_.begin();
283 BoxList::iterator const end = children_.end();
284 for (; it != end; ++it) {
285 if (!(*it)->visible())
288 (*it)->shrinkMetrics();
289 dimension_t child_width = (*it)->width();
290 dimension_t child_height = (*it)->height();
292 if (orientation_ == Horizontal) {
293 width += child_width;
294 height = std::max(height, child_height);
296 width = std::max(width, child_width);
297 height += child_height;
301 w_ = visible_ ? std::max(min_w_, width) : 0;
302 h_ = visible_ ? std::max(min_h_, height) : 0;
306 void Box::expandMetrics(dimension_t x_in, dimension_t y_in,
307 dimension_t w_avail, dimension_t h_avail)
314 if (orientation_ == Vertical)
315 expandVbox(x_in, y_in, w_avail, h_avail);
317 expandHbox(x_in, y_in, w_avail, h_avail);
321 void Box::expandHbox(dimension_t x_in, dimension_t y_in,
322 dimension_t w_avail, dimension_t h_avail)
324 int nvisible_children = 0;
325 int nexpanded_children = 0;
326 dimension_t w_fixed = 0;
328 BoxList::const_iterator cit = children_.begin();
329 BoxList::const_iterator const cend = children_.end();
330 for (; cit != cend; ++cit) {
331 if ((*cit)->visible()) {
332 nvisible_children += 1;
333 if ((*cit)->expandable())
334 nexpanded_children += 1;
336 w_fixed += (*cit)->width();
340 if (nvisible_children == 0)
343 dimension_t width = 0;
344 dimension_t extra = 0;
345 if (nexpanded_children > 0) {
346 width = w_avail - w_fixed;
347 extra = width / nexpanded_children;
350 dimension_t x_child = x_in;
351 dimension_t y_child = y_in;
352 dimension_t h_child = h_avail;
354 BoxList::iterator it = children_.begin();
355 BoxList::iterator const end = children_.end();
356 for (; it != end; ++it) {
357 if (!(*it)->visible())
360 dimension_t w_child = (*it)->width();
361 if ((*it)->expandable()) {
362 if (nexpanded_children == 1)
363 w_child = std::max(w_child, width);
365 w_child = std::max(w_child, extra);
367 nexpanded_children -= 1;
371 (*it)->expandMetrics(x_child, y_child, w_child, h_child);
377 void Box::expandVbox(dimension_t x_in, dimension_t y_in,
378 dimension_t w_avail, dimension_t h_avail)
380 int nvisible_children = 0;
381 int nexpanded_children = 0;
382 dimension_t h_fixed = 0;
384 BoxList::const_iterator cit = children_.begin();
385 BoxList::const_iterator const cend = children_.end();
386 for (; cit != cend; ++cit) {
387 if ((*cit)->visible()) {
388 nvisible_children += 1;
389 if ((*cit)->expandable())
390 nexpanded_children += 1;
392 h_fixed += (*cit)->height();
396 if (nvisible_children == 0)
399 dimension_t height = 0;
400 dimension_t extra = 0;
401 if (nexpanded_children > 0) {
402 height = h_avail - h_fixed;
403 extra = height / nexpanded_children;
406 dimension_t x_child = x_in;
407 dimension_t y_child = y_in;
408 dimension_t w_child = w_avail;
410 BoxList::iterator it = children_.begin();
411 BoxList::iterator const end = children_.end();
412 for (; it != end; ++it) {
413 if (!(*it)->visible())
416 dimension_t h_child = (*it)->height();
417 if ((*it)->expandable()) {
418 if (nexpanded_children == 1)
419 h_child = std::max(h_child, height);
421 h_child = std::max(h_child, extra);
422 nexpanded_children -= 1;
426 (*it)->expandMetrics(x_child, y_child, w_child, h_child);
432 shared_ptr<Box> WidgetMap::add(FL_OBJECT * ob, BoxList & container,
433 dimension_t min_w, dimension_t min_h)
435 shared_ptr<Box> box = container.push_back(Box(min_w, min_h));
441 void WidgetMap::updateMetrics() const
443 DataMap::const_iterator it = widgets_.begin();
444 DataMap::const_iterator const end = widgets_.end();
445 for (; it != end; ++it) {
446 FL_OBJECT * ob = it->first;
447 Box & box = *it->second;
450 fl_set_object_geometry(ob,
451 box.xorigin(), box.yorigin(),
452 box.width(), box.height());
464 embed(FL_OBJECT * ob, BoxList & container, WidgetMap & widgets, int bw)
466 container.push_back(Box(0, bw));
467 shared_ptr<Box> middle = container.push_back(Box(0, 0));
468 middle->set(Box::Horizontal);
469 container.push_back(Box(0, bw));
471 middle->children().push_back(Box(bw, 0));
472 shared_ptr<Box> center = widgets.add(ob, middle->children(), 0, 0);
473 middle->children().push_back(Box(bw, 0));
478 } // namespace frontend