root/OpenSceneGraph/trunk/src/osgWidget/Box.cpp @ 9287

Revision 9287, 6.1 kB (checked in by robert, 5 years ago)

From Jeremy Moles, updates to osgWidget

Merged my Robert Osfield from OpenSceneGraph-osgWidget-dev.

RevLine 
[8588]1// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
2
3#include <osgWidget/Box>
4
5namespace osgWidget {
6
[9287]7Box::Box(const std::string& name, BoxType bt, bool uniform):
[8588]8Window   (name),
9_boxType (bt),
10_uniform (uniform),
11_lastAdd (0) {
12}
13
14Box::Box(const Box& box, const osg::CopyOp& co):
15Window   (box, co),
16_boxType (box._boxType),
17_uniform (box._uniform),
18_lastAdd (box._lastAdd) {
19}
20
21// TODO: Here's something to consider! If we resize the box by 1 every time, only the
22// first resizable Widget will continue to get larger. This is really silly.
23void Box::_resizeImplementation(point_type w, point_type h) {
[8769]24    // Get the number of Widgets that agree to fill. Also perfom some casting to integers
25    // in case we're being request to resize with pixel perfection.
26    point_type numFill  = _getNumFill();
27    int        iw       = static_cast<int>(w);
28    int        ih       = static_cast<int>(h);
29    int        inumFill = static_cast<int>(numFill);
30    int        wrem     = 0;
31    int        hrem     = 0;
[8588]32
[8769]33    // If we have some widgets that fill, use these variables to keep a running count
34    // of what needs to be added.
35    if(inumFill) {
36        wrem = iw % inumFill;
37        hrem = ih % inumFill;
38    }
[8588]39
[8769]40    // If we have any widgets that agree to fill and there has been an honest resize
41    // request, handle it here. The first case handles resizes where we have AT LEAST
42    // as many pixels to fill as we have objects.
43    if(numFill > 0.0f && (w != 0.0f || h != 0.0f)) {
44        unsigned int cur = 0;
[8588]45
[8769]46        for(Iterator i = begin(); i != end(); i++) if(i->valid() && i->get()->canFill()) {
47            point_type addWidth  = 0.0f;
48            point_type addHeight = 0.0f;
[8588]49
[8769]50            // If our last added-to Widget was the last one, reset it to 0.
51            if(_lastAdd >= size()) _lastAdd = 0;
[8588]52
[8769]53            // We EVENLY give any remaining space to all fillable Widgets. In the
54            // future we may want to be able to specify a fill "percent", which
55            // would be some portion of the total available space.
56            if(_boxType == HORIZONTAL) {
57                if(w) {
58                    addWidth += static_cast<point_type>(iw / inumFill);
[8588]59
[8769]60                    if(cur >= _lastAdd && wrem) {
61                        _lastAdd++;
62                        addWidth++;
63                        wrem--;
64                    }
65                }
[8588]66
[8769]67                if(h) addHeight += h;
68            }
[8588]69
[8769]70            else {
71                if(w) addWidth += w;
[8588]72
[8769]73                if(h) {
74                    addHeight += static_cast<point_type>(ih / inumFill);
[8588]75
[8769]76                    if(cur >= _lastAdd && hrem) {
77                        _lastAdd++;
78                        addHeight++;
79                        hrem--;
80                    }
81                }
82            }
[8588]83
[8769]84            if(addWidth != 0.0f) i->get()->addWidth(addWidth);
[8588]85
[8769]86            if(addHeight != 0.0f) i->get()->addHeight(addHeight);
[8588]87
[8769]88            cur++;
89        }
90    }
[8588]91
[8769]92    // Get the width and height of our largest widgets; these values take
93    // into account the padding, and will be affected by any resizing that occured above.
94    point_type maxWidth  = _getMaxWidgetWidthTotal();
95    point_type maxHeight = _getMaxWidgetHeightTotal();
[8588]96
[8769]97    // Create counters for the various offsets as we position Widgets.
98    point_type xoff = 0.0f;
99    point_type yoff = 0.0f;
100    point_type xadd = 0.0f;
101    point_type yadd = 0.0f;
[8588]102
[8769]103    for(Iterator i = begin(); i != end(); i++) {
104        Widget* widget = i->get();
[8588]105
[8769]106        // This positioning works by setting each Widget's unmodified origin and then
107        // letting Window::_positionWidget calculate the padding/fill.
108        if(_boxType == HORIZONTAL) {
109            // First, lets set it to the proper x offset, ignoring any padding.
110            widget->setOrigin(xoff, 0.0f);
[8588]111
[8769]112            // Immediately reset our xoff for the next iteration.
113            if(_uniform) {           
114                _positionWidget(widget, maxWidth, maxHeight);
[8588]115
[8769]116                xadd = maxWidth;
117            }
[8588]118
[8769]119            else {
120                _positionWidget(widget, widget->getWidthTotal(), maxHeight);
[8588]121
[8769]122                xadd = widget->getWidthTotal();
123            }
124        }
[8588]125
[8769]126        else {
127            widget->setOrigin(0.0f, yoff);
[8588]128
[8769]129            if(_uniform) {
130                _positionWidget(widget, maxWidth, maxHeight);
[8588]131
[8769]132                yadd = maxHeight;
133            }
[8588]134
[8769]135            else {
136                _positionWidget(widget, maxWidth, widget->getHeightTotal());
[8588]137
[8769]138                yadd = widget->getHeightTotal();
139            }
140        }
[8588]141
[8769]142        xoff += xadd;
143        yoff += yadd;
144    }
[8588]145}
146
147Window::Sizes Box::_getWidthImplementation() const {
[8769]148    // The width of a horizontal box is all of the widgets added together.
149    if(_boxType == HORIZONTAL) {
150        // If we're a uniformly sized box, our width is our largest width plus our
151        // largest padding, multiplied times the number of widgets. Our minimum width
152        // is the size of the largest minWidth times the number of widgets.
153        if(_uniform) return Sizes(
154            _getMaxWidgetWidthTotal() * size(),
155            _getMaxWidgetMinWidthTotal() * size()
156        );
[8588]157
[8769]158        // Othweriwse, our width is all of the widths added together, and our minWidth
159        // is all of the minWidths added together.
160        else return Sizes(
161            _accumulate<Plus>(&Widget::getWidthTotal),
162            _accumulate<Plus>(&Widget::getMinWidthTotal)
163        );
164    }
[8588]165
[8769]166    // If we're a vertical Box, our width is the width of the larget Widget in the group.
167    // Our minWidth is the largest minWidth of the Widgets in the group.
168    else return Sizes(
169        _getMaxWidgetWidthTotal(),
170        _getMaxWidgetMinWidthTotal()
171    );
[8588]172}
173
174Window::Sizes Box::_getHeightImplementation() const {
[8769]175    if(_boxType == VERTICAL) {
176        if(_uniform) return Sizes(
177            _getMaxWidgetHeightTotal() * size(),
178            _getMaxWidgetMinHeightTotal() * size()
179        );
180   
181        else return Sizes(
182            _accumulate<Plus>(&Widget::getHeightTotal),
183            _accumulate<Plus>(&Widget::getMinHeightTotal)
184        );
185    }
[8588]186
[8769]187    else return Sizes(
188        _getMaxWidgetHeightTotal(),
189        _getMaxWidgetMinHeightTotal()
190    );
[8588]191}
192
193}
Note: See TracBrowser for help on using the browser.