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/.
27 #include "LayoutEngine.h"
28 #include "lyx_forms.h"
30 #include <boost/assert.hpp>
31 #include <boost/bind.hpp>
34 using boost::shared_ptr;
42 bool BoxList::empty() const
48 BoxList::size_type BoxList::size() const
60 shared_ptr<Box> BoxList::push_back(Box const & box)
62 data_.push_back(shared_ptr<Box>(new Box(box)));
67 BoxList::iterator BoxList::begin()
73 BoxList::iterator BoxList::end()
79 BoxList::const_iterator BoxList::begin() const
85 BoxList::const_iterator BoxList::end() const
91 BoxList::iterator BoxList::erase(iterator where)
93 return data_.erase(where);
97 BoxList::iterator BoxList::erase(iterator begin, iterator end)
99 return data_.erase(begin, end);
103 Box::Orientation Box::default_orientation_ = Box::Vertical;
104 Box::Packing Box::default_packing_ = Box::Shrink;
107 Box::Box(dimension_t min_w, dimension_t min_h)
115 orientation_(default_orientation_),
116 packing_(default_packing_),
117 prefered_visibility_(Visible)
121 void Box::setMinimumDimensions(dimension_t min_w, dimension_t min_h)
128 Box::Orientation Box::orientation() const
134 void Box::set(Orientation o)
140 Box::Orientation Box::defaultOrientation()
142 return default_orientation_;
146 void Box::setDefault(Orientation o)
148 default_orientation_ = o;
152 Box::Packing Box::packing() const
158 void Box::set(Packing p)
164 Box::Packing Box::defaultPacking()
166 return default_packing_;
170 void Box::setDefault(Packing p)
172 default_packing_ = p;
176 bool Box::expandable() const
181 if (packing_ == Expand)
184 BoxList::const_iterator it = children_.begin();
185 BoxList::const_iterator const end = children_.end();
186 for (; it != end; ++it) {
187 if ((*it)->visible() && (*it)->packing() == Expand)
195 Box::PreferedVisibility Box::preferedVisibility() const
197 return prefered_visibility_;
201 void Box::set(PreferedVisibility pv)
203 prefered_visibility_ = pv;
204 if (pv == Invisible && visible_)
209 bool Box::visible() const
217 if (prefered_visibility_ == Invisible)
222 for_each(children_.begin(), children_.end(),
223 bind(&Box::show, _1));
231 for_each(children_.begin(), children_.end(),
232 bind(&Box::hide, _1));
236 BoxList & Box::children()
242 BoxList const & Box::children() const
248 Box::dimension_t Box::width() const
254 Box::dimension_t Box::height() const
260 Box::dimension_t Box::xorigin() const
266 Box::dimension_t Box::yorigin() const
272 void Box::updateMetrics()
275 expandMetrics(x_, y_, w_, h_);
279 void Box::shrinkMetrics()
281 dimension_t width = 0;
282 dimension_t height = 0;
284 BoxList::iterator it = children_.begin();
285 BoxList::iterator const end = children_.end();
286 for (; it != end; ++it) {
287 if (!(*it)->visible())
290 (*it)->shrinkMetrics();
291 dimension_t child_width = (*it)->width();
292 dimension_t child_height = (*it)->height();
294 if (orientation_ == Horizontal) {
295 width += child_width;
296 height = std::max(height, child_height);
298 width = std::max(width, child_width);
299 height += child_height;
303 w_ = visible_ ? std::max(min_w_, width) : 0;
304 h_ = visible_ ? std::max(min_h_, height) : 0;
308 void Box::expandMetrics(dimension_t x_in, dimension_t y_in,
309 dimension_t w_avail, dimension_t h_avail)
316 if (orientation_ == Vertical)
317 expandVbox(x_in, y_in, w_avail, h_avail);
319 expandHbox(x_in, y_in, w_avail, h_avail);
323 void Box::expandHbox(dimension_t x_in, dimension_t y_in,
324 dimension_t w_avail, dimension_t h_avail)
326 int nvisible_children = 0;
327 int nexpanded_children = 0;
328 dimension_t w_fixed = 0;
330 BoxList::const_iterator cit = children_.begin();
331 BoxList::const_iterator const cend = children_.end();
332 for (; cit != cend; ++cit) {
333 if ((*cit)->visible()) {
334 nvisible_children += 1;
335 if ((*cit)->expandable())
336 nexpanded_children += 1;
338 w_fixed += (*cit)->width();
342 if (nvisible_children == 0)
345 dimension_t width = 0;
346 dimension_t extra = 0;
347 if (nexpanded_children > 0) {
348 width = w_avail - w_fixed;
349 extra = width / nexpanded_children;
352 dimension_t x_child = x_in;
353 dimension_t y_child = y_in;
354 dimension_t h_child = h_avail;
356 BoxList::iterator it = children_.begin();
357 BoxList::iterator const end = children_.end();
358 for (; it != end; ++it) {
359 if (!(*it)->visible())
362 dimension_t w_child = (*it)->width();
363 if ((*it)->expandable()) {
364 if (nexpanded_children == 1)
365 w_child = std::max(w_child, width);
367 w_child = std::max(w_child, extra);
369 nexpanded_children -= 1;
373 (*it)->expandMetrics(x_child, y_child, w_child, h_child);
379 void Box::expandVbox(dimension_t x_in, dimension_t y_in,
380 dimension_t w_avail, dimension_t h_avail)
382 int nvisible_children = 0;
383 int nexpanded_children = 0;
384 dimension_t h_fixed = 0;
386 BoxList::const_iterator cit = children_.begin();
387 BoxList::const_iterator const cend = children_.end();
388 for (; cit != cend; ++cit) {
389 if ((*cit)->visible()) {
390 nvisible_children += 1;
391 if ((*cit)->expandable())
392 nexpanded_children += 1;
394 h_fixed += (*cit)->height();
398 if (nvisible_children == 0)
401 dimension_t height = 0;
402 dimension_t extra = 0;
403 if (nexpanded_children > 0) {
404 height = h_avail - h_fixed;
405 extra = height / nexpanded_children;
408 dimension_t x_child = x_in;
409 dimension_t y_child = y_in;
410 dimension_t w_child = w_avail;
412 BoxList::iterator it = children_.begin();
413 BoxList::iterator const end = children_.end();
414 for (; it != end; ++it) {
415 if (!(*it)->visible())
418 dimension_t h_child = (*it)->height();
419 if ((*it)->expandable()) {
420 if (nexpanded_children == 1)
421 h_child = std::max(h_child, height);
423 h_child = std::max(h_child, extra);
424 nexpanded_children -= 1;
428 (*it)->expandMetrics(x_child, y_child, w_child, h_child);
434 shared_ptr<Box> WidgetMap::add(FL_OBJECT * ob, BoxList & container,
435 dimension_t min_w, dimension_t min_h)
437 shared_ptr<Box> box = container.push_back(Box(min_w, min_h));
443 void WidgetMap::updateMetrics() const
445 DataMap::const_iterator it = widgets_.begin();
446 DataMap::const_iterator const end = widgets_.end();
447 for (; it != end; ++it) {
448 FL_OBJECT * ob = it->first;
449 Box & box = *it->second;
452 fl_set_object_geometry(ob,
453 box.xorigin(), box.yorigin(),
454 box.width(), box.height());
466 embed(FL_OBJECT * ob, BoxList & container, WidgetMap & widgets, int bw)
468 container.push_back(Box(0, bw));
469 shared_ptr<Box> middle = container.push_back(Box(0, 0));
470 middle->set(Box::Horizontal);
471 container.push_back(Box(0, bw));
473 middle->children().push_back(Box(bw, 0));
474 shared_ptr<Box> center = widgets.add(ob, middle->children(), 0, 0);
475 middle->children().push_back(Box(bw, 0));
480 } // namespace frontend