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"
27 #include <boost/assert.hpp>
34 bool BoxList::empty() const
40 BoxList::size_type BoxList::size() const
52 Box & BoxList::push_back(Box const & box)
59 BoxList::iterator BoxList::begin()
65 BoxList::iterator BoxList::end()
71 BoxList::const_iterator BoxList::begin() const
77 BoxList::const_iterator BoxList::end() const
83 BoxList::iterator BoxList::erase(iterator where)
85 return data_.erase(where);
89 BoxList::iterator BoxList::erase(iterator begin, iterator end)
91 return data_.erase(begin, end);
95 Box::Orientation Box::default_orientation_ = Box::Vertical;
96 Box::Packing Box::default_packing_ = Box::Shrink;
99 Box::Box(dimension_t min_w, dimension_t min_h)
107 orientation_(default_orientation_),
108 packing_(default_packing_),
109 prefered_visibility_(Visible)
113 void Box::setMinimumDimensions(dimension_t min_w, dimension_t min_h)
120 Box::Orientation Box::orientation() const
126 void Box::set(Orientation o)
132 Box::Orientation Box::defaultOrientation()
134 return default_orientation_;
138 void Box::setDefault(Orientation o)
140 default_orientation_ = o;
144 Box::Packing Box::packing() const
150 void Box::set(Packing p)
156 Box::Packing Box::defaultPacking()
158 return default_packing_;
162 void Box::setDefault(Packing p)
164 default_packing_ = p;
168 bool Box::expandable() const
173 if (packing_ == Expand)
176 BoxList::const_iterator it = children_.begin();
177 BoxList::const_iterator const end = children_.end();
178 for (; it != end; ++it) {
179 if (it->visible() && it->packing() == Expand)
187 Box::PreferedVisibility Box::preferedVisibility() const
189 return prefered_visibility_;
193 void Box::set(PreferedVisibility pv)
195 prefered_visibility_ = pv;
196 if (pv == Invisible && visible_)
201 bool Box::visible() const
209 if (prefered_visibility_ == Invisible)
214 BoxList::iterator it = children_.begin();
215 BoxList::iterator const end = children_.end();
216 for (; it != end; ++it)
225 BoxList::iterator it = children_.begin();
226 BoxList::iterator const end = children_.end();
227 for (; it != end; ++it)
232 BoxList & Box::children()
238 BoxList const & Box::children() const
244 Box::dimension_t Box::width() const
250 Box::dimension_t Box::height() const
256 Box::dimension_t Box::xorigin() const
262 Box::dimension_t Box::yorigin() const
268 void Box::updateMetrics()
271 expandMetrics(x_, y_, w_, h_);
275 void Box::shrinkMetrics()
277 dimension_t width = 0;
278 dimension_t height = 0;
280 BoxList::iterator it = children_.begin();
281 BoxList::iterator const end = children_.end();
282 for (; it != end; ++it) {
287 dimension_t child_width = it->width();
288 dimension_t child_height = it->height();
290 if (orientation_ == Horizontal) {
291 width += child_width;
292 height = std::max(height, child_height);
294 width = std::max(width, child_width);
295 height += child_height;
299 w_ = visible_ ? std::max(min_w_, width) : 0;
300 h_ = visible_ ? std::max(min_h_, height) : 0;
304 void Box::expandMetrics(dimension_t x_in, dimension_t y_in,
305 dimension_t w_avail, dimension_t h_avail)
312 if (orientation_ == Vertical)
313 expandVbox(x_in, y_in, w_avail, h_avail);
315 expandHbox(x_in, y_in, w_avail, h_avail);
319 void Box::expandHbox(dimension_t x_in, dimension_t y_in,
320 dimension_t w_avail, dimension_t h_avail)
322 int nvisible_children = 0;
323 int nexpanded_children = 0;
324 dimension_t w_fixed = 0;
326 BoxList::const_iterator cit = children_.begin();
327 BoxList::const_iterator const cend = children_.end();
328 for (; cit != cend; ++cit) {
329 if (cit->visible()) {
330 nvisible_children += 1;
331 if (cit->expandable())
332 nexpanded_children += 1;
334 w_fixed += cit->width();
338 if (nvisible_children == 0)
341 dimension_t width = 0;
342 dimension_t extra = 0;
343 if (nexpanded_children > 0) {
344 width = w_avail - w_fixed;
345 extra = width / nexpanded_children;
348 dimension_t x_child = x_in;
349 dimension_t y_child = y_in;
350 dimension_t h_child = h_avail;
352 BoxList::iterator it = children_.begin();
353 BoxList::iterator const end = children_.end();
354 for (; it != end; ++it) {
358 dimension_t w_child = it->width();
359 if (it->expandable()) {
360 if (nexpanded_children == 1)
361 w_child = std::max(w_child, width);
363 w_child = std::max(w_child, extra);
365 nexpanded_children -= 1;
369 it->expandMetrics(x_child, y_child, w_child, h_child);
375 void Box::expandVbox(dimension_t x_in, dimension_t y_in,
376 dimension_t w_avail, dimension_t h_avail)
378 int nvisible_children = 0;
379 int nexpanded_children = 0;
380 dimension_t h_fixed = 0;
382 BoxList::const_iterator cit = children_.begin();
383 BoxList::const_iterator const cend = children_.end();
384 for (; cit != cend; ++cit) {
385 if (cit->visible()) {
386 nvisible_children += 1;
387 if (cit->expandable())
388 nexpanded_children += 1;
390 h_fixed += cit->height();
394 if (nvisible_children == 0)
397 dimension_t height = 0;
398 dimension_t extra = 0;
399 if (nexpanded_children > 0) {
400 height = h_avail - h_fixed;
401 extra = height / nexpanded_children;
404 dimension_t x_child = x_in;
405 dimension_t y_child = y_in;
406 dimension_t w_child = w_avail;
408 BoxList::iterator it = children_.begin();
409 BoxList::iterator const end = children_.end();
410 for (; it != end; ++it) {
414 dimension_t h_child = it->height();
415 if (it->expandable()) {
416 if (nexpanded_children == 1)
417 h_child = std::max(h_child, height);
419 h_child = std::max(h_child, extra);
420 nexpanded_children -= 1;
424 it->expandMetrics(x_child, y_child, w_child, h_child);
430 Box & WidgetMap::add(FL_OBJECT * ob, BoxList & container,
431 dimension_t min_w, dimension_t min_h)
433 Box & box = container.push_back(Box(min_w, min_h));
439 void WidgetMap::updateMetrics() const
441 DataMap::const_iterator it = widgets_.begin();
442 DataMap::const_iterator const end = widgets_.end();
443 for (; it != end; ++it) {
444 FL_OBJECT * ob = it->first;
445 Box & box = *it->second;
448 fl_set_object_geometry(ob,
449 box.xorigin(), box.yorigin(),
450 box.width(), box.height());
461 Box & embed(FL_OBJECT * ob, BoxList & container, WidgetMap & widgets, int bw)
463 container.push_back(Box(0, bw));
464 Box & middle = container.push_back(Box(0, 0));
465 middle.set(Box::Horizontal);
466 container.push_back(Box(0, bw));
468 middle.children().push_back(Box(bw, 0));
469 Box & center = widgets.add(ob, middle.children(), 0, 0);
470 middle.children().push_back(Box(bw, 0));
475 } // namespace frontend