FixedTableLayout.cpp [plain text]
#include "config.h"
#include "FixedTableLayout.h"
#include "RenderTable.h"
#include "RenderTableCell.h"
#include "RenderTableCol.h"
#include "RenderTableSection.h"
using namespace std;
namespace WebCore {
FixedTableLayout::FixedTableLayout(RenderTable* table)
: TableLayout(table)
{
}
FixedTableLayout::~FixedTableLayout()
{
}
int FixedTableLayout::calcWidthArray(int tableWidth)
{
int usedWidth = 0;
RenderObject* child = m_table->firstChild();
int cCol = 0;
int nEffCols = m_table->numEffCols();
m_width.resize(nEffCols);
m_width.fill(Length(Auto));
#ifdef DEBUG_LAYOUT
qDebug("FixedTableLayout::calcWidthArray(%d)", tableWidth);
qDebug(" col elements:");
#endif
Length grpWidth;
while (child) {
if (child->isTableCol()) {
RenderTableCol *col = static_cast<RenderTableCol *>(child);
int span = col->span();
if (col->firstChild())
grpWidth = col->style()->width();
else {
Length w = col->style()->width();
if (w.isAuto())
w = grpWidth;
int effWidth = 0;
if (w.isFixed() && w.value() > 0)
effWidth = w.value();
#ifdef DEBUG_LAYOUT
qDebug(" col element: effCol=%d, span=%d: %d w=%d type=%d",
cCol, span, effWidth, w.value, w.type());
#endif
int usedSpan = 0;
int i = 0;
while (usedSpan < span) {
if(cCol + i >= nEffCols) {
m_table->appendColumn(span - usedSpan);
nEffCols++;
m_width.resize(nEffCols);
m_width[nEffCols-1] = Length();
}
int eSpan = m_table->spanOfEffCol(cCol+i);
if ((w.isFixed() || w.isPercent()) && w.value() > 0) {
m_width[cCol+i] = Length(w.value() * eSpan, w.type());
usedWidth += effWidth * eSpan;
#ifdef DEBUG_LAYOUT
qDebug(" setting effCol %d (span=%d) to m_width %d(type=%d)",
cCol+i, eSpan, m_width[cCol+i].value, m_width[cCol+i].type());
#endif
}
usedSpan += eSpan;
i++;
}
cCol += i;
}
} else
break;
RenderObject *next = child->firstChild();
if (!next)
next = child->nextSibling();
if (!next && child->parent()->isTableCol()) {
next = child->parent()->nextSibling();
grpWidth = Length();
}
child = next;
}
#ifdef DEBUG_LAYOUT
qDebug(" first row:");
#endif
RenderTableSection *section = m_table->head;
if (!section)
section = m_table->firstBody;
if (!section)
section = m_table->foot;
if (section) {
cCol = 0;
RenderObject* firstRow = section->firstChild();
child = firstRow ? firstRow->firstChild() : 0;
while (child) {
if (child->isTableCell()) {
RenderTableCell *cell = static_cast<RenderTableCell *>(child);
Length w = cell->styleOrColWidth();
int span = cell->colSpan();
int effWidth = 0;
if ((w.isFixed() || w.isPercent()) && w.value() > 0)
effWidth = w.value();
#ifdef DEBUG_LAYOUT
qDebug(" table cell: effCol=%d, span=%d: %d", cCol, span, effWidth);
#endif
int usedSpan = 0;
int i = 0;
while (usedSpan < span) {
ASSERT(cCol + i < nEffCols);
int eSpan = m_table->spanOfEffCol(cCol+i);
if (m_width[cCol+i].isAuto() && w.type() != Auto) {
m_width[cCol+i] = Length(w.value() * eSpan, w.type());
usedWidth += effWidth*eSpan;
#ifdef DEBUG_LAYOUT
qDebug(" setting effCol %d (span=%d) to m_width %d(type=%d)",
cCol+i, eSpan, m_width[cCol+i].value, m_width[cCol+i].type());
#endif
}
#ifdef DEBUG_LAYOUT
else {
qDebug(" m_width of col %d already defined (span=%d)", cCol, m_table->spanOfEffCol(cCol));
}
#endif
usedSpan += eSpan;
i++;
}
cCol += i;
}
child = child->nextSibling();
}
}
return usedWidth;
}
void FixedTableLayout::calcMinMaxWidth()
{
int bs = m_table->bordersPaddingAndSpacing();
int tableWidth = m_table->style()->width().isFixed() ? m_table->style()->width().value() - bs : 0;
int mw = calcWidthArray(tableWidth) + bs;
m_table->m_minWidth = max(mw, tableWidth);
m_table->m_maxWidth = m_table->m_minWidth;
}
void FixedTableLayout::layout()
{
int tableWidth = m_table->width() - m_table->bordersPaddingAndSpacing();
int available = tableWidth;
int nEffCols = m_table->numEffCols();
int totalPercent = 0;
#ifdef DEBUG_LAYOUT
qDebug("FixedTableLayout::layout: tableWidth=%d, numEffCols=%d", tableWidth, nEffCols);
#endif
Vector<int> calcWidth(nEffCols, -1);
if (available > 0) {
for (int i = 0; i < nEffCols; i++)
if (m_width[i].isPercent())
totalPercent += m_width[i].value();
int base = tableWidth * totalPercent / 100;
if (base > available)
base = available;
else
totalPercent = 100;
#ifdef DEBUG_LAYOUT
qDebug("FixedTableLayout::layout: assigning percent m_width, base=%d, totalPercent=%d", base, totalPercent);
#endif
for (int i = 0; available > 0 && i < nEffCols; i++) {
if (m_width[i].isPercent()) {
int w = base * m_width[i].value() / totalPercent;
available -= w;
calcWidth[i] = w;
}
}
}
for (int i = 0; i < nEffCols; i++) {
if (m_width[i].isFixed()) {
calcWidth[i] = m_width[i].value();
available -= m_width[i].value();
}
}
if (available > 0) {
int totalAuto = 0;
for (int i = 0; i < nEffCols; i++)
if (m_width[i].isAuto())
totalAuto++;
for (int i = 0; available > 0 && i < nEffCols; i++) {
if (m_width[i].isAuto()) {
int w = available / totalAuto;
available -= w;
calcWidth[i] = w;
totalAuto--;
}
}
}
for (int i = 0; i < nEffCols; i++)
if (calcWidth[i] <= 0)
calcWidth[i] = 0;
if (available > 0) {
int total = nEffCols;
int i = nEffCols;
while ( i--) {
int w = available / total;
available -= w;
total--;
calcWidth[i] += w;
}
}
int pos = 0;
int hspacing = m_table->hBorderSpacing();
for (int i = 0; i < nEffCols; i++) {
#ifdef DEBUG_LAYOUT
qDebug("col %d: %d (m_width %d)", i, pos, calcWidth[i]);
#endif
m_table->columnPos[i] = pos;
pos += calcWidth[i] + hspacing;
}
m_table->columnPos[m_table->columnPos.size()-1] = pos;
}
#undef DEBUG_LAYOUT
}