Render table with rowspan, colspan.

Borders, if enabled, adds +1 to cell padding.

--HG--
branch : html-table-rendering
This commit is contained in:
Nimetu 2014-10-14 15:29:06 +03:00
parent a53b9305a2
commit 799705b7ed
2 changed files with 134 additions and 71 deletions

View file

@ -80,6 +80,7 @@ namespace NLGUI
sint32 ColSpan; sint32 ColSpan;
sint32 RowSpan; sint32 RowSpan;
sint32 TableColumnIndex;
// The min height of the cell // The min height of the cell
sint32 Height; sint32 Height;
@ -194,13 +195,14 @@ namespace NLGUI
WidthMax = 0; WidthMax = 0;
WidthWanted = 0; WidthWanted = 0;
TableRatio = 0; TableRatio = 0;
Height = 0; RowSpan = 1;
} }
sint32 Width; sint32 Width;
sint32 Height; sint32 Height;
sint32 WidthWanted; sint32 WidthWanted;
sint32 WidthMax; sint32 WidthMax;
float TableRatio; float TableRatio;
sint32 RowSpan;
}; };
// Table row // Table row

View file

@ -46,6 +46,7 @@ namespace NLGUI
Height = 0; Height = 0;
ColSpan = 1; ColSpan = 1;
RowSpan = 1; RowSpan = 1;
TableColumnIndex = 0;
Group = new CInterfaceGroup(CViewBase::TCtorParam()); Group = new CInterfaceGroup(CViewBase::TCtorParam());
Align = Left; Align = Left;
VAlign = Top; VAlign = Top;
@ -618,7 +619,7 @@ namespace NLGUI
TableRatio = 0.f; TableRatio = 0.f;
ForceWidthMin = 0; ForceWidthMin = 0;
Border=0; Border=0;
BorderColor = CRGBA(127, 127, 127, 255); BorderColor = CRGBA(32, 32, 32, 255);
CellPadding=0; CellPadding=0;
CellSpacing=0; CellSpacing=0;
ContinuousUpdate = false; ContinuousUpdate = false;
@ -752,35 +753,75 @@ namespace NLGUI
// New cell ? // New cell ?
if (cell->NewLine) if (cell->NewLine)
{
while (column < _Columns.size())
{
if (_Columns[column].RowSpan > 1)
_Columns[column].RowSpan--;
column++;
}
column = 0; column = 0;
}
// Resize the array // Resize the array
if (column>=_Columns.size()) if (column>=_Columns.size())
_Columns.resize(column+1); _Columns.resize(column+1);
// Handle rowspan from previous row
while (_Columns[column].RowSpan > 1)
{
_Columns[column].RowSpan--;
column++;
// if previous row had less <TD> elements, then we missing columns
if (column>=_Columns.size())
_Columns.resize(column+1);
}
// remember column index for later use
cell->TableColumnIndex = column;
// new column, set rowspan from current <TD>
_Columns[column].RowSpan = cell->RowSpan;
float colspan = 1.f / cell->ColSpan;
float rowspan = 1.f / cell->RowSpan;
// Update sizes // Update sizes
if (cellWidth > _Columns[column].Width) if (cellWidth*colspan > _Columns[column].Width)
_Columns[column].Width = cellWidth; _Columns[column].Width = cellWidth*colspan;
if (cell->WidthMax > _Columns[column].WidthMax) if (cell->WidthMax*colspan > _Columns[column].WidthMax)
_Columns[column].WidthMax = cell->WidthMax; _Columns[column].WidthMax = cell->WidthMax*colspan;
if (cell->TableRatio > _Columns[column].TableRatio) if (cell->TableRatio*colspan > _Columns[column].TableRatio)
_Columns[column].TableRatio = cell->TableRatio; _Columns[column].TableRatio = cell->TableRatio*colspan;
if (cell->WidthWanted + additionnalWidth > _Columns[column].WidthWanted) if (cell->WidthWanted*colspan + additionnalWidth > _Columns[column].WidthWanted)
_Columns[column].WidthWanted = cell->WidthWanted + additionnalWidth; _Columns[column].WidthWanted = (sint32)(cell->WidthWanted*colspan) + additionnalWidth;
if (cell->Height > _Columns[column].Height)
_Columns[column].Height = cell->Height;
if (_Columns[column].WidthWanted + additionnalWidth) if (_Columns[column].WidthWanted + additionnalWidth)
_Columns[column].WidthMax = _Columns[column].WidthWanted + additionnalWidth; _Columns[column].WidthMax = _Columns[column].WidthWanted + additionnalWidth;
if (_Columns[column].WidthWanted > _Columns[column].Width) if (_Columns[column].WidthWanted > _Columns[column].Width)
_Columns[column].Width = _Columns[column].WidthWanted; _Columns[column].Width = _Columns[column].WidthWanted;
if (cell->ColSpan > 1) {
// copy this info to all spanned columns, create new columns as needed
uint newsize = column + cell->ColSpan - 1;
if (newsize >= _Columns.size())
_Columns.resize(newsize+1);
for(uint span = 0; span < cell->ColSpan -1; span++){
column++;
_Columns[column].Width = _Columns[column-1].Width;
_Columns[column].WidthMax = _Columns[column-1].WidthMax;
_Columns[column].TableRatio = _Columns[column-1].TableRatio;
_Columns[column].WidthWanted = _Columns[column-1].WidthWanted;
_Columns[column].RowSpan = _Columns[column-1].RowSpan;
}
}
// Next column // Next column
column++; column++;
} }
// Width of cells and table borders // Width of cells and table borders
sint32 borderWidth = 2*Border + ((sint32)_Columns.size()+1) * CellSpacing + ((sint32)_Columns.size()*2) * CellPadding; sint32 padding = CellPadding + (Border ? 1 : 0);
sint32 borderWidth = 2*Border + ((sint32)_Columns.size()+1) * CellSpacing + ((sint32)_Columns.size()*2) * padding;
// Get the width // Get the width
sint32 tableWidthMax = ForceWidthMin?ForceWidthMin:_LastParentW; // getWReal(); sint32 tableWidthMax = ForceWidthMin?ForceWidthMin:_LastParentW; // getWReal();
@ -862,7 +903,6 @@ namespace NLGUI
// Some space ? // Some space ?
space = finalWidth - tableWidth; space = finalWidth - tableWidth;
if (space > 0) if (space > 0)
{ {
// Then add in wanted Width cells // Then add in wanted Width cells
@ -952,6 +992,18 @@ namespace NLGUI
} }
} }
} }
// If there is still space left, then sum up column widths
// and add all the remaining space to final column.
if (space > 0)
{
sint32 innerWidth = 0;
for(i=0;i<_Columns.size();i++)
innerWidth += _Columns[i].Width;
if (innerWidth > 0 && finalWidth > innerWidth)
_Columns[_Columns.size()-1].Width += finalWidth - innerWidth;
}
} }
} }
} }
@ -962,7 +1014,8 @@ namespace NLGUI
column = 0; column = 0;
sint32 row = 0; sint32 row = 0;
sint32 currentX = Border + CellSpacing + CellPadding; sint32 currentX = Border + CellSpacing + padding;
_Rows.clear (); _Rows.clear ();
for (i=0; i<_Cells.size(); i++) for (i=0; i<_Cells.size(); i++)
{ {
@ -971,25 +1024,41 @@ namespace NLGUI
if (cell->NewLine) if (cell->NewLine)
{ {
column = 0; column = 0;
currentX = Border + CellSpacing + CellPadding; currentX = Border + CellSpacing + padding;
_Rows.push_back(CRow()); _Rows.push_back(CRow());
} }
if (cell->TableColumnIndex > 0)
{
// we have active rowspan, must add up 'skipped' columns
for( ; column<cell->TableColumnIndex; column++)
currentX += _Columns[column].Width + padding*2 + CellSpacing;
}
// Set the x and width // Set the x and width
// Check align // Check align
sint32 alignmentX = 0; sint32 alignmentX = 0;
sint32 widthReduceX = 0; sint32 widthReduceX = 0;
if (cell->WidthMax < _Columns[column].Width) sint32 columnWidth = _Columns[column].Width;
if (cell->ColSpan > 1)
{
// scan ahead and add up column widths as they might be different
for(int j = 1; j<cell->ColSpan; j++)
columnWidth += CellSpacing + padding*2 + _Columns[column+j].Width;
}
if (cell->WidthMax < columnWidth)
{ {
switch (cell->Align) switch (cell->Align)
{ {
case CGroupCell::Center: case CGroupCell::Center:
alignmentX = (_Columns[column].Width - cell->WidthMax) / 2; alignmentX = (columnWidth - cell->WidthMax) / 2;
widthReduceX = alignmentX * 2; widthReduceX = alignmentX * 2;
break; break;
case CGroupCell::Right: case CGroupCell::Right:
alignmentX = _Columns[column].Width - cell->WidthMax; alignmentX = columnWidth - cell->WidthMax;
widthReduceX = alignmentX; widthReduceX = alignmentX;
break; break;
default: default:
@ -997,11 +1066,11 @@ namespace NLGUI
} }
} }
cell->setX(currentX - CellPadding); cell->setX(currentX - padding);
cell->setW(_Columns[column].Width + CellPadding*2); cell->setW(columnWidth + padding*2);
cell->Group->setX(alignmentX + cell->LeftMargin + CellPadding); cell->Group->setX(alignmentX + cell->LeftMargin + padding);
cell->Group->setW(_Columns[column].Width - widthReduceX); cell->Group->setW(columnWidth - widthReduceX);
cell->Group->CInterfaceElement::updateCoords(); cell->Group->CInterfaceElement::updateCoords();
// Update coords to get H // Update coords to get H
@ -1009,16 +1078,17 @@ namespace NLGUI
cell->Group->updateCoords(); cell->Group->updateCoords();
// Resize the row array // Resize the row array
_Rows.back().Height = std::max(cell->Height, std::max(_Rows.back().Height, (sint32)cell->Group->getH())); float rowspan = 1 / cell->RowSpan;
_Rows.back().Height = std::max((sint32)(cell->Height*rowspan), std::max(_Rows.back().Height, (sint32)(cell->Group->getH()*rowspan)));
// Next column // Next column
currentX += _Columns[column].Width + 2*CellPadding + CellSpacing; currentX += columnWidth + 2*padding + CellSpacing;
column ++; column += cell->ColSpan;
} }
// Set cell Y // Set cell Y
row = 0; row = 0;
sint32 currentY = -(Border + CellSpacing + CellPadding); sint32 currentY = -(Border + CellSpacing + padding);
for (i=0; i<_Cells.size(); i++) for (i=0; i<_Cells.size(); i++)
{ {
// New cell ? // New cell ?
@ -1027,37 +1097,45 @@ namespace NLGUI
{ {
if (_Rows[row].Height != 0) if (_Rows[row].Height != 0)
{ {
currentY -= _Rows[row].Height + 2*CellPadding + CellSpacing; currentY -= _Rows[row].Height + 2*padding + CellSpacing;
} }
row++; row++;
} }
// Check align // Check align
sint32 alignmentY = 0; sint32 alignmentY = 0;
if ((sint32)cell->Group->getH() < _Rows[row].Height) sint32 rowHeight = _Rows[row].Height;
if (cell->RowSpan > 1)
{
// we need to scan down and add up row heights
int k = std::min((sint32)_Rows.size(), row + cell->RowSpan);
for(int j=row+1; j<k; j++)
rowHeight += CellSpacing + padding*2 + _Rows[j].Height;
}
if ((sint32)cell->Group->getH() < rowHeight)
{ {
switch (cell->VAlign) switch (cell->VAlign)
{ {
case CGroupCell::Middle: case CGroupCell::Middle:
alignmentY = (_Rows[row].Height - (sint32)cell->Group->getH()) / 2; alignmentY = (rowHeight - (sint32)cell->Group->getH()) / 2;
break; break;
case CGroupCell::Bottom: case CGroupCell::Bottom:
alignmentY = _Rows[row].Height - (sint32)cell->Group->getH(); alignmentY = rowHeight - (sint32)cell->Group->getH();
break; break;
default: default:
break; break;
} }
} }
cell->setY(currentY + CellPadding); cell->setY(currentY + padding);
cell->setH (_Rows[row].Height + 2*CellPadding); cell->setH (rowHeight + 2*padding);
cell->Group->setY(-(alignmentY + CellPadding)); cell->Group->setY(-(alignmentY + padding));
} }
// Resize the table // Resize the table
setW(finalWidth+borderWidth-_LastParentW); setW(finalWidth+borderWidth-_LastParentW);
if (!_Rows.empty()) if (!_Rows.empty())
currentY -= _Rows[row].Height + CellPadding + CellSpacing + Border; currentY -= _Rows[row].Height + padding + CellSpacing + Border;
setH(-currentY); setH(-currentY);
// All done // All done
@ -1246,53 +1324,35 @@ namespace NLGUI
finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor()); finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor());
finalColor.A = CurrentAlpha; finalColor.A = CurrentAlpha;
// Draw the top and bottom lines // Draw the top line
CViewRenderer &rVR = *CViewRenderer::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance();
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal-border+_HReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor); rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal-border+_HReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor);
// Draw the left and right lines // Draw the left line
sint32 insideHeight = std::max((sint32)0, (sint32)_HReal - (sint32)2*border); sint32 insideHeight = std::max((sint32)0, (sint32)_HReal - (sint32)border);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-border, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor);
// Draw the inside borders // Draw the inside borders
sint32 insideWidth = CellSpacing; if (CellSpacing)
if (insideWidth)
{ {
// Draw the inside verticals
uint i; uint i;
sint32 x = _XReal + border + _Columns[0].Width + 2*CellPadding; sint32 x, y;
for (i=1; i<_Columns.size(); i++) for (i=0; i<_Cells.size(); i++)
{ {
rVR.drawRotFlipBitmap (_RenderLayer, x, _YReal+border, insideWidth, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); CGroupCell *cell = _Cells[i];
x += _Columns[i].Width + 2*CellPadding + insideWidth;
}
// Draw the inside horizontals x = cell->getXReal();
sint32 y = _YReal + _HReal - border - _Rows[0].Height - 2*CellPadding; y = cell->getYReal() - CellSpacing;
if (_Rows[0].Height != 0) // right
{ rVR.drawRotFlipBitmap (_RenderLayer, x + cell->getW(), y, CellSpacing, cell->getH() + CellSpacing, 0, false, rVR.getBlankTextureId(), finalColor);
y -= insideWidth; // bottom
} rVR.drawRotFlipBitmap (_RenderLayer, x, y, cell->getW(), CellSpacing, 0, false, rVR.getBlankTextureId(), finalColor);
for (i=1; i<_Rows.size(); i++)
{
uint j;
x = _XReal + border;
if (_Rows[i].Height != 0)
{
for (j=0; j<_Columns.size(); j++)
{
rVR.drawRotFlipBitmap (_RenderLayer, x, y, _Columns[j].Width + 2*CellPadding, insideWidth, 0, false, rVR.getBlankTextureId(), finalColor);
x += _Columns[j].Width + 2*CellPadding + insideWidth;
}
y -= _Rows[i].Height + insideWidth + 2*CellPadding;
}
}
} }
} }
if (Border) { }
if (Border)
{
CViewRenderer &rVR = *CViewRenderer::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance();
CRGBA borderColorTL; CRGBA borderColorTL;
@ -1305,7 +1365,8 @@ namespace NLGUI
borderColorBR.A = CurrentAlpha; borderColorBR.A = CurrentAlpha;
// beveled table border // beveled table border
for (sint32 i=0; i<Border; i++){ for (sint32 i=0; i<Border; i++)
{
// bottom, left, top, right // bottom, left, top, right
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+i, _WReal-i*2, 1, 0, false, rVR.getBlankTextureId(), borderColorBR); rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+i, _WReal-i*2, 1, 0, false, rVR.getBlankTextureId(), borderColorBR);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+i, 1, _HReal-i*2, 0, false, rVR.getBlankTextureId(), borderColorTL); rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+i, 1, _HReal-i*2, 0, false, rVR.getBlankTextureId(), borderColorTL);