root/OpenSceneGraph/trunk/src/osgWidget/Table.cpp @ 13041

Revision 13041, 6.0 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
2
3#include <osgWidget/Table>
4
5namespace osgWidget {
6
7// TODO: There is a serious, outstanding bug with regards to USING a table before ALL Widgets
8// are set! FIX THIS!!!
9
10Table::Table(const std::string& name, unsigned int rows, unsigned int cols):
11Window      (name),
12_rows       (rows),
13_cols       (cols),
14_lastRowAdd (0),
15_lastColAdd (0) {
16    _objects.resize(_rows * _cols);
17}
18
19Table::Table(const Table& table, const osg::CopyOp& co):
20Window      (table, co),
21_rows       (table._rows),
22_cols       (table._cols),
23_lastRowAdd (table._lastRowAdd),
24_lastColAdd (table._lastColAdd) {
25}
26
27unsigned int Table::_calculateIndex(unsigned int row, unsigned int col) const {
28    return (row * _cols) + col;
29}
30
31void Table::_getRows(CellSizes& rows, Getter get) const {
32    for(unsigned int i = 0; i < _rows; i++) rows.push_back(
33        _compare<Greater>(get, i * _cols, (i * _cols) + _cols)
34    );
35}
36
37void Table::_getColumns(CellSizes& cols, Getter get) const {
38    for(unsigned int i = 0; i < _cols; i++) cols.push_back(
39        _compare<Greater>(get, i, 0, _cols)
40    );
41}
42
43void Table::_resizeImplementation(point_type width, point_type height) {
44    // We use these vectors so that we don't have to repeatedly call isFillable
45    // all the time. Usage such as this can really generate a lot of moronic,
46    // misinformed opposition, but until std::bit_vector is available, this is
47    // what we get. Deal with it.
48    std::vector<bool> rowFills;
49    std::vector<bool> colFills;
50
51    point_type numRowFills = 0.0f;
52    point_type numColFills = 0.0f;
53
54    // Enumerate each row and determine whether it can fill. If so, increment
55    // our numRowFills variable and set the position in rowFills to "true."
56    for(unsigned int row = 0; row < _rows; row++) {
57        bool fill = isRowVerticallyFillable(row);
58
59        if(fill) numRowFills++;
60
61        rowFills.push_back(fill);
62    }
63
64    // Enumerate each column and determine whether it can fill. If so, increment
65    // our numColFills variable and set the position in colFills to "true."
66    for(unsigned int col = 0; col < _cols; col++) {
67        bool fill = isColumnHorizontallyFillable(col);
68
69        if(fill) numColFills++;
70
71        colFills.push_back(fill);
72    }
73
74    int wrem = 0;
75    int hrem = 0;
76
77    if(numRowFills > 0.0f) {
78        hrem = static_cast<int>(height) % static_cast<int>(numRowFills);
79
80        unsigned int cur = 0;
81
82        for(unsigned int row = 0; row < _rows; row++) {
83            point_type h = height / numRowFills;
84
85            if(cur >= _lastRowAdd && hrem) {
86                _lastRowAdd++;
87                h++;
88                hrem--;
89            }
90
91            if(rowFills[row]) addHeightToRow(row, h);
92
93            cur++;
94        }
95    }
96
97    if(numColFills > 0.0f) {
98        wrem = static_cast<int>(width) % static_cast<int>(numColFills);
99
100        unsigned int cur = 0;
101
102        for(unsigned int col = 0; col < _cols; col++) {
103            point_type w = width / numColFills;
104
105            if(cur >= _lastColAdd && wrem) {
106                _lastColAdd++;
107                w++;
108                wrem--;
109            }
110
111            if(colFills[col]) addWidthToColumn(col, w);
112
113            cur++;
114        }
115    }
116
117    CellSizes rowHeights;
118    CellSizes colWidths;
119
120    getRowHeights(rowHeights);
121    getColumnWidths(colWidths);
122
123    point_type y = 0.0f;
124
125    for(unsigned int row = 0; row < _rows; row++) {
126        point_type x = 0.0f;
127
128        for(unsigned int col = 0; col < _cols; col++) {
129            Widget* widget = _objects[_calculateIndex(row, col)].get();
130
131            if(widget) {
132                widget->setOrigin(x, y);
133
134                _positionWidget(widget, colWidths[col], rowHeights[row]);
135            }
136
137            x += colWidths[col];
138        }
139
140        y += rowHeights[row];
141    }
142}
143
144Window::Sizes Table::_getWidthImplementation() const {
145    CellSizes cols;
146    CellSizes minCols;
147
148    getColumnWidths(cols);
149    getColumnMinWidths(minCols);
150
151    return Sizes(
152        std::accumulate(cols.begin(), cols.end(), 0.0f, Plus()),
153        std::accumulate(minCols.begin(), minCols.end(), 0.0f, Plus())
154    );
155}
156
157Window::Sizes Table::_getHeightImplementation() const {
158    CellSizes rows;
159    CellSizes minRows;
160
161    getRowHeights(rows);
162    getRowMinHeights(minRows);
163
164    return Sizes(
165        std::accumulate(rows.begin(), rows.end(), 0.0f, Plus()),
166        std::accumulate(minRows.begin(), minRows.end(), 0.0f, Plus())
167    );
168}
169
170bool Table::addWidget(Widget* widget) {
171    return addWidget(widget, 0, 0);
172}
173
174bool Table::addWidget(Widget* widget, unsigned int row, unsigned int col) {
175    return Window::insertWidget(widget, _calculateIndex(row, col));
176}
177
178void Table::getRowHeights(CellSizes& rowHeights) const {
179    _getRows(rowHeights, &Widget::getHeightTotal);
180}
181
182void Table::getRowMinHeights(CellSizes& rowMinHeights) const {
183    _getRows(rowMinHeights, &Widget::getMinHeightTotal);
184}
185
186void Table::getColumnWidths(CellSizes& colWidths) const {
187    _getColumns(colWidths, &Widget::getWidthTotal);
188}
189
190void Table::getColumnMinWidths(CellSizes& colMinWidths) const {
191    _getColumns(colMinWidths, &Widget::getMinWidthTotal);
192}
193
194void Table::addHeightToRow(unsigned int row, point_type height) {
195    for(
196        Iterator i = begin() + (row * _cols);
197        i != begin() + ((row * _cols) + _cols);
198        i++
199    ) if(i->valid()) i->get()->addHeight(height);
200}
201
202void Table::addWidthToColumn(unsigned int col, point_type width) {
203    // See the documentation in include/osgWidget/Window::_forEachApplyOrAssign if you want
204    // to know why we need this variable.
205    unsigned int c = col;
206
207    for(Iterator i = begin() + col; i < end(); c += _cols) {
208        if(i->valid()) i->get()->addWidth(width);
209
210        if((c + _cols) < size()) i += _cols;
211
212        else i = end();
213    }
214}
215
216bool Table::isRowVerticallyFillable(unsigned int row) const {
217    return static_cast<point_type>(_cols) == _getNumFill(row * _cols, (row * _cols) + _cols);
218}
219
220bool Table::isColumnHorizontallyFillable(unsigned int col) const {
221    return static_cast<point_type>(_rows) == _getNumFill(col, 0, _cols);
222}
223
224}
Note: See TracBrowser for help on using the browser.