dw::Table Class Reference

A Widget for rendering tables. More...

#include <table.hh>

List of all members.

Classes

struct  Child
class  TableIterator

Public Member Functions

 Table (bool limitTextWidth)
 ~Table ()
core::Iteratoriterator (core::Content::Type mask, bool atEnd)
 Return an iterator for this widget.
void addCell (Widget *widget, int colspan, int rowspan)
void addRow (core::style::Style *style)
TableCellgetCellRef ()

Static Public Attributes

static int CLASS_ID = -1

Protected Member Functions

void sizeRequestImpl (core::Requisition *requisition)
 See Sizes of Dillo Widgets.
void getExtremesImpl (core::Extremes *extremes)
 See Sizes of Dillo Widgets.
void sizeAllocateImpl (core::Allocation *allocation)
 See Sizes of Dillo Widgets.
void resizeDrawImpl ()
 Called after sizeAllocateImpl() to redraw necessary areas. By default the whole widget is redrawn.
void setWidth (int width)
void setAscent (int ascent)
void setDescent (int descent)
void draw (core::View *view, core::Rectangle *area)
void removeChild (Widget *child)

Private Types

enum  { LEN_AUTO = -1, LEN_ABS = -2 }

Private Member Functions

bool childDefined (int n)
void reallocChildren (int newNumCols, int newNumRows)
void calcCellSizes ()
void forceCalcCellSizes ()
void apportionRowSpan ()
void calcColumnExtremes ()
 Fills dw::Table::colExtremes, only if recalculation is necessary.
void forceCalcColumnExtremes ()
 Fills dw::Table::colExtremes in all cases.
void apportion2 (int totalWidth, int forceTotalWidth)
 Apportionment function for AUTO-length columns. 'extremes' comes filled, 'result' comes defined for percentage columns.
void apportion_percentages2 (int totalWidth, int forceTotalWidth)
void setCumHeight (int row, int value)
void setColWidth (int col, int value)

Private Attributes

bool limitTextWidth
bool rowClosed
int availWidth
int availAscent
int availDescent
int numRows
int numCols
int curRow
int curCol
lout::misc::SimpleVector
< Child * > * 
children
int redrawX
int redrawY
lout::misc::SimpleVector
< core::Extremes > * 
colExtremes
 The extremes of all columns.
lout::misc::SimpleVector< int > * colWidths
 The widths of all columns.
lout::misc::SimpleVector< int > * cumHeight
lout::misc::SimpleVector< int > * rowSpanCells
lout::misc::SimpleVector< int > * colSpanCells
lout::misc::SimpleVector< int > * baseline
lout::misc::SimpleVector
< core::style::Style * > * 
rowStyle
int hasColPercent
lout::misc::SimpleVector< float > * colPercents

Friends

class TableIterator


Detailed Description

A Widget for rendering tables.

Introduction

The dw::Table widget is used to render HTML tables.

Each cell is itself a separate widget. Any widget may be used, however, in dillo, only instances of dw::Textblock and dw::TableCell are used as children of dw::Table.

Sizes

General

The following diagram shows the dependencies between the different functions, which are related to size calculation. Click on the boxes for more information.

inline_dotgraph_12.dot

[A] In this case, the new calculation is not forced, but only done, when necessary.

[B] In this case, the new calculation is allways necessary, since [C] is the case.

[C] Whether this function is called, depends on NEEDS_RESIZE / EXTREMES_CHANGED.

Apportionment

See also:
How to Avoid Rounding Errors
Given two array $e_{i,\min}$ and $e_{i,\max}$, which represent the column minima and maxima, and a total width $W$, apportionment means to calculate column widths $w_{i}$, with

\[e_{i,\min} \le w_{i} \le e_{i,\max}\]

and

\[\sum w_{i} = W\]

There are different algorithms for apportionment, a simple one is recommended in the HTML 4.0.1 specification (http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.5.2.2):

\[w_{i} = e_{i,\min} + {e_{i,\max} - e_{i,\min}\over\sum e_{i,\max} - \sum e_{i,\min}} (W - \sum e_{i,\min})\]

This one is used currently, but another one will be used soon, which is described below. The rest of this chapter is independent of the exact apportionment algorithm.

When referring to the apportionment function, we will call it $a_i (W, (e_{i,\min}), (e_{i,\min}))$ and write something like this:

\[w_{i} = a_i (W, (e_{i,\min}), (e_{i,\max})) \]

It is implemented by dw::Table::apportion.

Column Extremes

See also:
How to Avoid Rounding Errors
The sizes, which all other sizes depend on, are column extremes, which define, how wide a column may be at min and at max. They are calculated in the following way:

  1. First, only cells with colspan = 1 are regarded:

    \[ e_{\hbox{base},i,\min} = \max \{ e_{\hbox{cell},i,j,\min} \} \]

    \[ e_{\hbox{base},i,\max} = \max \{ e_{\hbox{cell},i,j,\max} \} \]

    only for cells $(i, j)$ with colspan = 1.

  2. Then, $e_{\hbox{span},i,\min}$ (but not $e_{\hbox{span},i,\max}$) are calculated from cells with colspan > 1. (In the following formulas, the cell at $(i_1, j)$ always span from $i_1$ to $i_2$.) If the minimal width of the column exceeds the sum of the column minima calculated in the last step:

    \[e_{\hbox{cell},i_1,j,\min} > \sum_{i=i_1}^{i=i_2} e_{\hbox{base},i,\min}\]

    then the minimal width of this cell is apportioned to the columns:

    • If the minimal width of this cell also exceeds the sum of the column maxima:

      \[e_{\hbox{cell},i_1,j,\min} > \sum_{i=i_1}^{i=i_2} e_{\hbox{base},i,\max}\]

      then $e_{\hbox{cell},i_1,j,\min}$ is apportioned in a simple way:

      \[e_{\hbox{span},i,j,\min} = e_{\hbox{base},i,\max} {e_{\hbox{span},i,j,\min} \over \sum_{i=i_1}^{i=i_2} e_{\hbox{base},i,\max}}\]

    • Otherwise, the apportionment function is used:

      \[e_{\hbox{span},i,j,\min} = a_i (e_{\hbox{cell},i_1,j,\min}, (e_{\hbox{cell},i_1,j,\min} \ldots e_{\hbox{cell},i_2,j,\min}), (e_{\hbox{cell},i_1,j,\max} \ldots e_{\hbox{cell},i_2,j,\max}))\]

    After this, $e_{\hbox{span},i,\min}$ is then the maximum of all $e_{\hbox{span},i,j,\min}$.

  3. Finally, the maximum of both is used.

    \[ e_{i,\min} = \max \{ e_{\hbox{base},i,\min}, e_{\hbox{span},i,\min} \} \]

    \[ e_{i,\max} = \max \{ e_{\hbox{base},i,\max}, e_{i,\min} \} \]

    For the maxima, there is no $e_{\hbox{span},i,\max}$, but it has to be assured, that the maximum is always greater than or equal to the minimum.

Generally, if absolute widths are specified, they are, instead of the results of dw::core::Widget::getExtremes, taken for the minimal and maximal width of a cell (minus the box difference, i.e. the difference between content size and widget size). If the content width specification is smaller than the minimal content width of the widget (determined by dw::core::Widget::getExtremes), the latter is used instead.

If percentage widths are specified, they are also collected, as column maxima. A similar method as for the extremes is used, for cells with colspan > 1:

\[w_{\hbox{span},i,j,\%} = a_i (w_{\hbox{cell},i_1,j,\%}, (e_{\hbox{cell},i_1,j,\min} \ldots e_{\hbox{cell},i_2,j,\min}), (e_{\hbox{cell},i_1,j,\max} \ldots e_{\hbox{cell},i_2,j,\max}))\]

Cell Sizes

Determining the Width of the Table

The total width is

In any case, it is corrected, if it is less than the minimal width (but not if it is greater than the maximal width).

Bug:
The parentheses is not fully clear, look at the old code.
Details on differences because of styles are omitted. Below, this total width is called $W$.

Evaluating percentages

The following algorithms are used to solve collisions between different size specifications (absolute and percentage). Generally, inherent sizes and specified absolute sizes are preferred.

  1. First, calculate the sum of the minimal widths, for columns, where no percentage width has been specified. The difference to the total width is at max available to the columns with percentage width specifications:

    \[W_{\hbox{columns}_\%,\hbox{available}} = W - \sum e_{i,\min}\]

    with only those columns $i$ with no percentage width specification.

  2. Then, calculate the sum of the widths, which the columns with percentage width specification would allocate, when fully adhering to them:

    \[W_{\hbox{columns}_\%,\hbox{best}} = W \sum w_{i,\%}\]

    with only those columns $i$ with a percentage width specification.

  3. Two cases are distinguished:

    • $W_{\hbox{columns}_\%,\hbox{available}} \ge W_{\hbox{columns}_\%,\hbox{best}}$: In this case, the percentage widths can be used without any modification, by setting the extremes:

      \[e_{i,\min} = e_{i,\max} = W w_{i,\%}\]

      for only those columns $i$ with a percentage width specification.

    • $W_{\hbox{columns}_\%,\hbox{available}} < W_{\hbox{columns}_\%,\hbox{best}}$: In this case, the widths for these columns must be cut down:

      \[e_{i,\min} = e_{i,\max} = w_{i,\%} {W_{\hbox{columns}_\%,\hbox{available}} \over w_{\hbox{total},\%}}\]

      with

      \[w_{\hbox{total},\%} = \sum w_{i,\%}\]

      in both cases for only those columns $i$ with a percentage width specification.

($e_{i,\min}$ and $e_{i,\max}$ are set temporarily here, the notation should be a bit clearer.)

Column Widths

The column widths are now simply calculated by applying the apportionment function.

Row Heights

...

Alternative Apportionment Algorithm

The algorithm described here tends to result in more homogeneous column widths.

The following rule leads to well-defined $w_{i}$: All columns $i$ have have the same width $w$, except:

Furthermore, $w$ is

Of course, $\sum w_{i} = W$ must be the case.

Based on an initial value $w = {W\over n}$, $w$ can iteratively adjusted, based on these rules.

Borders, Paddings, Spacing

Currently, DwTable supports only the separated borders model (see CSS specification). Borders, paddings, spacing is done by creating dw::core::style::Style structures with values equivalent to following CSS:

 TABLE {
   border:           outset table-border;
   border-collapse:  separate;
   border-spacing:   table-cellspacing;
   background-color: table-bgcolor;
 }

 TD TH {
   border:           inset table-border;
   padding:          table-cellspacing;
   background-color: td/th-bgcolor;
 }
 

Here, foo-bar refers to the attribute bar of the tag foo foo. Look at the HTML parser for more details.


Member Enumeration Documentation

anonymous enum [private]

hasColPercent becomes true when any cell specifies a percentage width. A negative value in colPercents means LEN_AUTO or LEN_ABS.

Enumerator:
LEN_AUTO 
LEN_ABS 


Constructor & Destructor Documentation

dw::Table::Table ( bool  limitTextWidth  ) 

dw::Table::~Table (  ) 


Member Function Documentation

void dw::Table::addCell ( Widget *  widget,
int  colspan,
int  rowspan 
)

void dw::Table::addRow ( core::style::Style style  ) 

void dw::Table::apportion2 ( int  totalWidth,
int  forceTotalWidth 
) [private]

void dw::Table::apportion_percentages2 ( int  totalWidth,
int  forceTotalWidth 
) [private]

void dw::Table::apportionRowSpan (  )  [private]

void dw::Table::calcCellSizes (  )  [private]

void dw::Table::calcColumnExtremes (  )  [private]

Fills dw::Table::colExtremes, only if recalculation is necessary.

Bug:
Some parts are missing.

References dw::core::Widget::extremesChanged(), and forceCalcColumnExtremes().

bool dw::Table::childDefined ( int  n  )  [inline, private]

void dw::Table::draw ( core::View view,
core::Rectangle area 
) [protected, virtual]

void dw::Table::forceCalcCellSizes (  )  [private]

void dw::Table::forceCalcColumnExtremes (  )  [private]

TableCell * dw::Table::getCellRef (  ) 

void dw::Table::getExtremesImpl ( core::Extremes extremes  )  [protected, virtual]

core::Iterator * dw::Table::iterator ( core::Content::Type  mask,
bool  atEnd 
) [virtual]

Return an iterator for this widget.

mask can narrow the types returned by the iterator, this can enhance performance quite much, e.g. when only searching for child widgets.

With atEnd == false, the iterator starts before the beginning, i.e. the first call of dw::core::Iterator::next will let the iterator point on the first piece of contents. Likewise, With atEnd == true, the iterator starts after the last piece of contents, call dw::core::Iterator::prev in this case.

Implements dw::core::Widget.

References TableIterator.

void dw::Table::reallocChildren ( int  newNumCols,
int  newNumRows 
) [private]

void dw::Table::removeChild ( Widget *  child  )  [protected]

Bug:
Not implemented.

void dw::Table::resizeDrawImpl (  )  [protected, virtual]

Called after sizeAllocateImpl() to redraw necessary areas. By default the whole widget is redrawn.

Reimplemented from dw::core::Widget.

References dw::core::Widget::allocation, dw::core::Widget::getHeight(), dw::core::Widget::queueDrawArea(), redrawX, and redrawY.

void dw::Table::setAscent ( int  ascent  )  [protected, virtual]

Reimplemented from dw::core::Widget.

References availAscent, and dw::core::Widget::queueResize().

void dw::Table::setColWidth ( int  col,
int  value 
) [inline, private]

void dw::Table::setCumHeight ( int  row,
int  value 
) [inline, private]

void dw::Table::setDescent ( int  descent  )  [protected, virtual]

Reimplemented from dw::core::Widget.

References availDescent, and dw::core::Widget::queueResize().

void dw::Table::setWidth ( int  width  )  [protected, virtual]

void dw::Table::sizeAllocateImpl ( core::Allocation allocation  )  [protected, virtual]

void dw::Table::sizeRequestImpl ( core::Requisition requisition  )  [protected, virtual]


Friends And Related Function Documentation

friend class TableIterator [friend]

Referenced by iterator().


Member Data Documentation

int dw::Table::availAscent [private]

Referenced by setAscent(), and Table().

int dw::Table::availDescent [private]

Referenced by setDescent(), and Table().

int dw::Table::availWidth [private]

Referenced by forceCalcCellSizes(), Table(), and ~Table().

int dw::Table::CLASS_ID = -1 [static]

Reimplemented from dw::core::Widget.

Referenced by Table().

If a Cell has colspan > 1, it goes into this array

Referenced by forceCalcColumnExtremes(), Table(), and ~Table().

Row cumulative height array: cumHeight->size() is numRows + 1, cumHeight->get(0) is 0, cumHeight->get(numRows) is the total table height.

Referenced by apportionRowSpan(), draw(), forceCalcCellSizes(), setCumHeight(), sizeAllocateImpl(), sizeRequestImpl(), Table(), and ~Table().

int dw::Table::curCol [private]

int dw::Table::curRow [private]

Referenced by addCell(), addRow(), and Table().

int dw::Table::hasColPercent [private]

bool dw::Table::limitTextWidth [private]

Referenced by setWidth().

int dw::Table::numCols [private]

int dw::Table::numRows [private]

int dw::Table::redrawX [private]

Referenced by resizeDrawImpl(), setColWidth(), and Table().

int dw::Table::redrawY [private]

Referenced by resizeDrawImpl(), setCumHeight(), and Table().

bool dw::Table::rowClosed [private]

Referenced by addCell(), addRow(), and Table().

If a Cell has rowspan > 1, it goes into this array

Referenced by apportionRowSpan(), forceCalcCellSizes(), Table(), and ~Table().


The documentation for this class was generated from the following files:

Generated on Wed Sep 7 02:00:37 2011 for Dillo by  doxygen 1.5.9