From Jeremy Moles, import of the osgWidget NodeKit, sourced from the original http://osgwidget.googlecode.com/svn/trunk
Notes from Robert Osfield, I've merged osgWidget trunk, and added/changed CMakeLists.txt file to make it suitable for inclusion in the core OSG, and moved imagery/scripts/shaders out into OpenSceneGraph-Data
This commit is contained in:
225
src/osgWidget/Table.cpp
Normal file
225
src/osgWidget/Table.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
|
||||
// $Id: Table.cpp 48 2008-05-05 14:13:20Z cubicool $
|
||||
|
||||
#include <osgWidget/Table>
|
||||
|
||||
namespace osgWidget {
|
||||
|
||||
// TODO: There is a serious, outstanding bug with regards to USING a table before ALL Widgets
|
||||
// are set! FIX THIS!!!
|
||||
|
||||
Table::Table(const std::string& name, unsigned int rows, unsigned int cols):
|
||||
Window (name),
|
||||
_rows (rows),
|
||||
_cols (cols),
|
||||
_lastRowAdd (0),
|
||||
_lastColAdd (0) {
|
||||
_objects.resize(_rows * _cols);
|
||||
}
|
||||
|
||||
Table::Table(const Table& table, const osg::CopyOp& co):
|
||||
Window (table, co),
|
||||
_rows (table._rows),
|
||||
_cols (table._cols),
|
||||
_lastRowAdd (table._lastRowAdd),
|
||||
_lastColAdd (table._lastColAdd) {
|
||||
}
|
||||
|
||||
unsigned int Table::_calculateIndex(unsigned int row, unsigned int col) const {
|
||||
return (row * _cols) + col;
|
||||
}
|
||||
|
||||
void Table::_getRows(CellSizes& rows, Getter get) const {
|
||||
for(unsigned int i = 0; i < _rows; i++) rows.push_back(
|
||||
_compare<Greater>(get, i * _cols, (i * _cols) + _cols)
|
||||
);
|
||||
}
|
||||
|
||||
void Table::_getColumns(CellSizes& cols, Getter get) const {
|
||||
for(unsigned int i = 0; i < _cols; i++) cols.push_back(
|
||||
_compare<Greater>(get, i, 0, _cols)
|
||||
);
|
||||
}
|
||||
|
||||
void Table::_resizeImplementation(point_type width, point_type height) {
|
||||
// We use these vectors so that we don't have to repeatedly call isFillable
|
||||
// all the time. Usage such as this can really generate a lot of moronic,
|
||||
// misinformed opposition, but until std::bit_vector is available, this is
|
||||
// what we get. Deal with it.
|
||||
std::vector<bool> rowFills;
|
||||
std::vector<bool> colFills;
|
||||
|
||||
point_type numRowFills = 0.0f;
|
||||
point_type numColFills = 0.0f;
|
||||
|
||||
// Enumerate each row and determine whether it can fill. If so, increment
|
||||
// our numRowFills variable and set the position in rowFills to "true."
|
||||
for(unsigned int row = 0; row < _rows; row++) {
|
||||
bool fill = isRowVerticallyFillable(row);
|
||||
|
||||
if(fill) numRowFills++;
|
||||
|
||||
rowFills.push_back(fill);
|
||||
}
|
||||
|
||||
// Enumerate each column and determine whether it can fill. If so, increment
|
||||
// our numColFills variable and set the position in colFills to "true."
|
||||
for(unsigned int col = 0; col < _cols; col++) {
|
||||
bool fill = isColumnHorizontallyFillable(col);
|
||||
|
||||
if(fill) numColFills++;
|
||||
|
||||
colFills.push_back(fill);
|
||||
}
|
||||
|
||||
int wrem = 0;
|
||||
int hrem = 0;
|
||||
|
||||
if(numRowFills > 0.0f) {
|
||||
hrem = static_cast<int>(height) % static_cast<int>(numRowFills);
|
||||
|
||||
unsigned int cur = 0;
|
||||
|
||||
for(unsigned int row = 0; row < _rows; row++) {
|
||||
point_type h = height / numRowFills;
|
||||
|
||||
if(cur >= _lastRowAdd && hrem) {
|
||||
_lastRowAdd++;
|
||||
h++;
|
||||
hrem--;
|
||||
}
|
||||
|
||||
if(rowFills[row]) addHeightToRow(row, h);
|
||||
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
|
||||
if(numColFills > 0.0f) {
|
||||
wrem = static_cast<int>(width) % static_cast<int>(numColFills);
|
||||
|
||||
unsigned int cur = 0;
|
||||
|
||||
for(unsigned int col = 0; col < _cols; col++) {
|
||||
point_type w = width / numColFills;
|
||||
|
||||
if(cur >= _lastColAdd && wrem) {
|
||||
_lastColAdd++;
|
||||
w++;
|
||||
wrem--;
|
||||
}
|
||||
|
||||
if(colFills[col]) addWidthToColumn(col, w);
|
||||
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
|
||||
CellSizes rowHeights;
|
||||
CellSizes colWidths;
|
||||
|
||||
getRowHeights(rowHeights);
|
||||
getColumnWidths(colWidths);
|
||||
|
||||
point_type y = 0.0f;
|
||||
|
||||
for(unsigned int row = 0; row < _rows; row++) {
|
||||
point_type x = 0.0f;
|
||||
|
||||
for(unsigned int col = 0; col < _cols; col++) {
|
||||
Widget* widget = _objects[_calculateIndex(row, col)].get();
|
||||
|
||||
if(widget) {
|
||||
widget->setOrigin(x, y);
|
||||
|
||||
_positionWidget(widget, colWidths[col], rowHeights[row]);
|
||||
}
|
||||
|
||||
x += colWidths[col];
|
||||
}
|
||||
|
||||
y += rowHeights[row];
|
||||
}
|
||||
}
|
||||
|
||||
Window::Sizes Table::_getWidthImplementation() const {
|
||||
CellSizes cols;
|
||||
CellSizes minCols;
|
||||
|
||||
getColumnWidths(cols);
|
||||
getColumnMinWidths(minCols);
|
||||
|
||||
return Sizes(
|
||||
std::accumulate(cols.begin(), cols.end(), 0.0f, Plus()),
|
||||
std::accumulate(minCols.begin(), minCols.end(), 0.0f, Plus())
|
||||
);
|
||||
}
|
||||
|
||||
Window::Sizes Table::_getHeightImplementation() const {
|
||||
CellSizes rows;
|
||||
CellSizes minRows;
|
||||
|
||||
getRowHeights(rows);
|
||||
getRowMinHeights(minRows);
|
||||
|
||||
return Sizes(
|
||||
std::accumulate(rows.begin(), rows.end(), 0.0f, Plus()),
|
||||
std::accumulate(minRows.begin(), minRows.end(), 0.0f, Plus())
|
||||
);
|
||||
}
|
||||
|
||||
bool Table::addWidget(Widget* widget) {
|
||||
return addWidget(widget, 0, 0);
|
||||
}
|
||||
|
||||
bool Table::addWidget(Widget* widget, unsigned int row, unsigned int col) {
|
||||
return Window::insertWidget(widget, _calculateIndex(row, col));
|
||||
}
|
||||
|
||||
void Table::getRowHeights(CellSizes& rowHeights) const {
|
||||
_getRows(rowHeights, &Widget::getHeightTotal);
|
||||
}
|
||||
|
||||
void Table::getRowMinHeights(CellSizes& rowMinHeights) const {
|
||||
_getRows(rowMinHeights, &Widget::getMinHeightTotal);
|
||||
}
|
||||
|
||||
void Table::getColumnWidths(CellSizes& colWidths) const {
|
||||
_getColumns(colWidths, &Widget::getWidthTotal);
|
||||
}
|
||||
|
||||
void Table::getColumnMinWidths(CellSizes& colMinWidths) const {
|
||||
_getColumns(colMinWidths, &Widget::getMinWidthTotal);
|
||||
}
|
||||
|
||||
void Table::addHeightToRow(unsigned int row, point_type height) {
|
||||
for(
|
||||
Iterator i = begin() + (row * _cols);
|
||||
i != begin() + ((row * _cols) + _cols);
|
||||
i++
|
||||
) if(i->valid()) i->get()->addHeight(height);
|
||||
}
|
||||
|
||||
void Table::addWidthToColumn(unsigned int col, point_type width) {
|
||||
// See the documentation in include/osgWidget/Window::_forEachApplyOrAssign if you want
|
||||
// to know why we need this variable.
|
||||
unsigned int c = col;
|
||||
|
||||
for(Iterator i = begin() + col; i < end(); c += _cols) {
|
||||
if(i->valid()) i->get()->addWidth(width);
|
||||
|
||||
if((c + _cols) < size()) i += _cols;
|
||||
|
||||
else i = end();
|
||||
}
|
||||
}
|
||||
|
||||
bool Table::isRowVerticallyFillable(unsigned int row) const {
|
||||
return static_cast<point_type>(_cols) == _getNumFill(row * _cols, (row * _cols) + _cols);
|
||||
}
|
||||
|
||||
bool Table::isColumnHorizontallyFillable(unsigned int col) const {
|
||||
return static_cast<point_type>(_rows) == _getNumFill(col, 0, _cols);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user