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

Revision 10764, 6.1 kB (checked in by robert, 4 years ago)

<iterator>, <stdlib.h> and <ctype.h> includes required for QNX compiler

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