You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
525 lines
16 KiB
525 lines
16 KiB
15 years ago
|
/*
|
||
|
* This file is part of the DOM implementation for KDE.
|
||
|
*
|
||
|
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
|
||
|
* (C) 1997 Torben Weis (weis@kde.org)
|
||
|
* (C) 1998 Waldo Bastian (bastian@kde.org)
|
||
|
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
|
||
|
* (C) 1999 Antti Koivisto (koivisto@kde.org)
|
||
|
* (C) 2003 Apple Computer, Inc.
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Library General Public
|
||
|
* License as published by the Free Software Foundation; either
|
||
|
* version 2 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* This library is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Library General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Library General Public License
|
||
|
* along with this library; see the file COPYING.LIB. If not, write to
|
||
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||
|
* Boston, MA 02110-1301, USA.
|
||
|
*
|
||
|
*/
|
||
|
#ifndef RENDER_TABLE_H
|
||
|
#define RENDER_TABLE_H
|
||
|
|
||
|
#include <qcolor.h>
|
||
|
#include <qptrvector.h>
|
||
|
|
||
|
#include "rendering/render_box.h"
|
||
|
#include "rendering/render_block.h"
|
||
|
#include "rendering/render_style.h"
|
||
|
|
||
|
#include "misc/khtmllayout.h"
|
||
|
|
||
|
namespace DOM {
|
||
|
class DOMString;
|
||
|
}
|
||
|
|
||
|
namespace khtml {
|
||
|
|
||
|
class RenderTable;
|
||
|
class RenderTableSection;
|
||
|
class RenderTableRow;
|
||
|
class RenderTableCell;
|
||
|
class RenderTableCol;
|
||
|
class TableLayout;
|
||
|
|
||
|
class RenderTable : public RenderBlock
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
RenderTable(DOM::NodeImpl* node);
|
||
|
~RenderTable();
|
||
|
|
||
|
virtual const char *renderName() const { return "RenderTable"; }
|
||
|
|
||
|
virtual void setStyle(RenderStyle *style);
|
||
|
|
||
|
virtual bool isTable() const { return true; }
|
||
|
|
||
|
int getColumnPos(int col) const
|
||
|
{ return columnPos[col]; }
|
||
|
|
||
|
int borderHSpacing() const { return hspacing; }
|
||
|
int borderVSpacing() const { return vspacing; }
|
||
|
|
||
|
bool collapseBorders() const { return style()->borderCollapse(); }
|
||
|
int borderLeft() const;
|
||
|
int borderRight() const;
|
||
|
int borderTop() const;
|
||
|
int borderBottom() const;
|
||
|
int paddingLeft() const { return collapseBorders() ? 0 : RenderBlock::paddingLeft(); }
|
||
|
int paddingRight() const { return collapseBorders() ? 0 : RenderBlock::paddingRight(); }
|
||
|
int paddingTop() const { return collapseBorders() ? 0 : RenderBlock::paddingTop(); }
|
||
|
int paddingBottom() const { return collapseBorders() ? 0 : RenderBlock::paddingBottom(); }
|
||
|
|
||
|
const QColor &bgColor() const { return style()->backgroundColor(); }
|
||
|
|
||
|
uint cellPadding() const { return padding; }
|
||
|
void setCellPadding( uint p ) { padding = p; }
|
||
|
|
||
|
// overrides
|
||
|
virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
|
||
|
virtual void paint( PaintInfo&, int tx, int ty);
|
||
|
virtual void paintBoxDecorations(PaintInfo&, int _tx, int _ty);
|
||
|
virtual void layout();
|
||
|
virtual void calcMinMaxWidth();
|
||
|
virtual void close();
|
||
|
|
||
|
virtual short lineHeight(bool b) const;
|
||
|
virtual short baselinePosition(bool b) const;
|
||
|
|
||
|
virtual void setCellWidths( );
|
||
|
|
||
|
virtual void calcWidth();
|
||
|
|
||
|
virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
|
||
|
DOM::NodeImpl*& node, int & offset,
|
||
|
SelPointState & );
|
||
|
|
||
|
#ifdef ENABLE_DUMP
|
||
|
virtual void dump(QTextStream &stream, const QString &ind) const;
|
||
|
#endif
|
||
|
struct ColumnStruct {
|
||
|
enum {
|
||
|
WidthUndefined = 0xffff
|
||
|
};
|
||
|
ColumnStruct() {
|
||
|
span = 1;
|
||
|
width = WidthUndefined;
|
||
|
}
|
||
|
ushort span;
|
||
|
ushort width; // the calculated position of the column
|
||
|
};
|
||
|
|
||
|
QMemArray<int> columnPos;
|
||
|
QMemArray<ColumnStruct> columns;
|
||
|
|
||
|
void splitColumn( int pos, int firstSpan );
|
||
|
void appendColumn( int span );
|
||
|
int numEffCols() const { return columns.size(); }
|
||
|
int spanOfEffCol( int effCol ) const { return columns[effCol].span; }
|
||
|
int colToEffCol( int col ) const {
|
||
|
int c = 0;
|
||
|
int i = 0;
|
||
|
while ( c < col && i < (int)columns.size() ) {
|
||
|
c += columns[i].span;
|
||
|
i++;
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
int effColToCol( int effCol ) const {
|
||
|
int c = 0;
|
||
|
for ( int i = 0; i < effCol; i++ )
|
||
|
c += columns[i].span;
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
int bordersPaddingAndSpacing() const {
|
||
|
return borderLeft() + borderRight() +
|
||
|
(collapseBorders() ? 0 : (paddingLeft() + paddingRight() + (numEffCols()+1) * borderHSpacing()));
|
||
|
}
|
||
|
|
||
|
RenderTableCol *colElement( int col );
|
||
|
|
||
|
void setNeedSectionRecalc() { needSectionRecalc = true; }
|
||
|
|
||
|
virtual RenderObject* removeChildNode(RenderObject* child);
|
||
|
|
||
|
RenderTableSection* sectionAbove(const RenderTableSection*, bool skipEmptySections = false) const;
|
||
|
RenderTableSection* sectionBelow(const RenderTableSection*, bool skipEmptySections = false) const;
|
||
|
|
||
|
RenderTableCell* cellAbove(const RenderTableCell* cell) const;
|
||
|
RenderTableCell* cellBelow(const RenderTableCell* cell) const;
|
||
|
RenderTableCell* cellLeft(const RenderTableCell* cell) const;
|
||
|
RenderTableCell* cellRight(const RenderTableCell* cell) const;
|
||
|
|
||
|
CollapsedBorderValue* currentBorderStyle() { return m_currentBorder; }
|
||
|
|
||
|
RenderTableSection *firstBodySection() const { return firstBody; }
|
||
|
RenderFlow* caption() const { return tCaption; }
|
||
|
|
||
|
protected:
|
||
|
|
||
|
void recalcSections();
|
||
|
|
||
|
friend class AutoTableLayout;
|
||
|
friend class FixedTableLayout;
|
||
|
|
||
|
RenderFlow *tCaption;
|
||
|
RenderTableSection *head;
|
||
|
RenderTableSection *foot;
|
||
|
RenderTableSection *firstBody;
|
||
|
|
||
|
TableLayout *tableLayout;
|
||
|
|
||
|
CollapsedBorderValue* m_currentBorder;
|
||
|
|
||
|
bool has_col_elems : 1;
|
||
|
uint needSectionRecalc : 1;
|
||
|
uint padding : 22;
|
||
|
|
||
|
ushort hspacing;
|
||
|
ushort vspacing;
|
||
|
|
||
|
friend class TableSectionIterator;
|
||
|
};
|
||
|
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
class RenderTableSection : public RenderBox
|
||
|
{
|
||
|
public:
|
||
|
RenderTableSection(DOM::NodeImpl* node);
|
||
|
~RenderTableSection();
|
||
|
virtual void detach();
|
||
|
|
||
|
virtual void setStyle(RenderStyle *style);
|
||
|
|
||
|
virtual const char *renderName() const { return "RenderTableSection"; }
|
||
|
|
||
|
// overrides
|
||
|
virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
|
||
|
virtual bool isTableSection() const { return true; }
|
||
|
|
||
|
virtual short lineHeight(bool) const { return 0; }
|
||
|
virtual void position(InlineBox*, int, int, bool) {}
|
||
|
|
||
|
virtual short width() const;
|
||
|
|
||
|
virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
|
||
|
DOM::NodeImpl*& node, int & offset,
|
||
|
SelPointState & );
|
||
|
|
||
|
#ifdef ENABLE_DUMP
|
||
|
virtual void dump(QTextStream &stream, const QString &ind) const;
|
||
|
#endif
|
||
|
|
||
|
void addCell( RenderTableCell *cell, RenderTableRow *row );
|
||
|
|
||
|
void setCellWidths();
|
||
|
void calcRowHeight();
|
||
|
int layoutRows( int height );
|
||
|
|
||
|
RenderTable *table() const { return static_cast<RenderTable *>(parent()); }
|
||
|
|
||
|
typedef QMemArray<RenderTableCell *> Row;
|
||
|
struct RowStruct {
|
||
|
Row *row;
|
||
|
RenderTableRow* rowRenderer;
|
||
|
int baseLine;
|
||
|
Length height;
|
||
|
bool needFlex;
|
||
|
};
|
||
|
|
||
|
RenderTableCell *&cellAt( int row, int col ) {
|
||
|
return (*(grid[row].row))[col];
|
||
|
}
|
||
|
RenderTableCell *cellAt( int row, int col ) const {
|
||
|
return (*(grid[row].row))[col];
|
||
|
}
|
||
|
|
||
|
virtual int lowestPosition(bool includeOverflowInterior, bool includeSelf) const;
|
||
|
virtual int rightmostPosition(bool includeOverflowInterior, bool includeSelf) const;
|
||
|
virtual int leftmostPosition(bool includeOverflowInterior, bool includeSelf) const;
|
||
|
virtual int highestPosition(bool includeOverflowInterior, bool includeSelf) const;
|
||
|
|
||
|
int borderLeft() const { return table()->collapseBorders() ? 0 : RenderBox::borderLeft(); }
|
||
|
int borderRight() const { return table()->collapseBorders() ? 0 : RenderBox::borderRight(); }
|
||
|
int borderTop() const { return table()->collapseBorders() ? 0 : RenderBox::borderTop(); }
|
||
|
int borderBottom() const { return table()->collapseBorders() ? 0 : RenderBox::borderBottom(); }
|
||
|
|
||
|
virtual void paint( PaintInfo& i, int tx, int ty);
|
||
|
|
||
|
int numRows() const { return grid.size(); }
|
||
|
int getBaseline(int row) {return grid[row].baseLine;}
|
||
|
|
||
|
void setNeedCellRecalc() {
|
||
|
needCellRecalc = true;
|
||
|
table()->setNeedSectionRecalc();
|
||
|
}
|
||
|
|
||
|
virtual RenderObject* removeChildNode(RenderObject* child);
|
||
|
|
||
|
virtual bool canClear(RenderObject *child, PageBreakLevel level);
|
||
|
void addSpaceAt(int pos, int dy);
|
||
|
|
||
|
virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside);
|
||
|
|
||
|
// this gets a cell grid data structure. changing the number of
|
||
|
// columns is done by the table
|
||
|
QMemArray<RowStruct> grid;
|
||
|
QMemArray<int> rowPos;
|
||
|
|
||
|
signed short cRow;
|
||
|
ushort cCol;
|
||
|
bool needCellRecalc;
|
||
|
|
||
|
void recalcCells();
|
||
|
protected:
|
||
|
void ensureRows( int numRows );
|
||
|
void clearGrid();
|
||
|
bool emptyRow(int rowNum);
|
||
|
bool flexCellChildren(RenderObject* p) const;
|
||
|
|
||
|
|
||
|
friend class TableSectionIterator;
|
||
|
};
|
||
|
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
class RenderTableRow : public RenderContainer
|
||
|
{
|
||
|
public:
|
||
|
RenderTableRow(DOM::NodeImpl* node);
|
||
|
|
||
|
virtual void detach();
|
||
|
|
||
|
virtual void setStyle( RenderStyle* );
|
||
|
virtual const char *renderName() const { return "RenderTableRow"; }
|
||
|
virtual bool isTableRow() const { return true; }
|
||
|
virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
|
||
|
|
||
|
virtual short offsetWidth() const;
|
||
|
virtual int offsetHeight() const;
|
||
|
virtual int offsetLeft() const;
|
||
|
virtual int offsetTop() const;
|
||
|
|
||
|
virtual short lineHeight( bool ) const { return 0; }
|
||
|
virtual void position(InlineBox*, int, int, bool) {}
|
||
|
|
||
|
virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside);
|
||
|
|
||
|
virtual void layout();
|
||
|
|
||
|
virtual RenderObject* removeChildNode(RenderObject* child);
|
||
|
|
||
|
// The only time rows get a layer is when they have transparency.
|
||
|
virtual bool requiresLayer() const { return /* style()->opacity() < 1.0f; */ false ; }
|
||
|
virtual void paint(PaintInfo& i, int tx, int ty);
|
||
|
|
||
|
void paintRow( PaintInfo& i, int tx, int ty, int w, int h);
|
||
|
|
||
|
RenderTable *table() const { return static_cast<RenderTable *>(parent()->parent()); }
|
||
|
RenderTableSection *section() const { return static_cast<RenderTableSection *>(parent()); }
|
||
|
};
|
||
|
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
class RenderTableCell : public RenderBlock
|
||
|
{
|
||
|
public:
|
||
|
RenderTableCell(DOM::NodeImpl* node);
|
||
|
|
||
|
virtual void layout();
|
||
|
virtual void detach();
|
||
|
|
||
|
virtual const char *renderName() const { return "RenderTableCell"; }
|
||
|
virtual bool isTableCell() const { return true; }
|
||
|
|
||
|
// ### FIX these two...
|
||
|
long cellIndex() const { return 0; }
|
||
|
void setCellIndex( long ) { }
|
||
|
|
||
|
unsigned short colSpan() const { return cSpan; }
|
||
|
void setColSpan( unsigned short c ) { cSpan = c; }
|
||
|
|
||
|
unsigned short rowSpan() const { return rSpan; }
|
||
|
void setRowSpan( unsigned short r ) { rSpan = r; }
|
||
|
|
||
|
int col() const { return _col; }
|
||
|
void setCol(int col) { _col = col; }
|
||
|
int row() const { return _row; }
|
||
|
void setRow(int r) { _row = r; }
|
||
|
|
||
|
Length styleOrColWidth();
|
||
|
|
||
|
// overrides
|
||
|
virtual void calcMinMaxWidth();
|
||
|
virtual void calcWidth();
|
||
|
virtual void setWidth( int width );
|
||
|
virtual void setStyle( RenderStyle *style );
|
||
|
virtual bool requiresLayer() const;
|
||
|
|
||
|
int borderLeft() const;
|
||
|
int borderRight() const;
|
||
|
int borderTop() const;
|
||
|
int borderBottom() const;
|
||
|
|
||
|
CollapsedBorderValue collapsedLeftBorder() const;
|
||
|
CollapsedBorderValue collapsedRightBorder() const;
|
||
|
CollapsedBorderValue collapsedTopBorder() const;
|
||
|
CollapsedBorderValue collapsedBottomBorder() const;
|
||
|
virtual void collectBorders(QValueList<CollapsedBorderValue>& borderStyles);
|
||
|
|
||
|
virtual void updateFromElement();
|
||
|
|
||
|
void setCellTopExtra(int p) { _topExtra = p; }
|
||
|
void setCellBottomExtra(int p) { _bottomExtra = p; }
|
||
|
int cellTopExtra() const { return _topExtra; }
|
||
|
int cellBottomExtra() const { return _bottomExtra; }
|
||
|
|
||
|
int pageTopAfter(int x) const;
|
||
|
|
||
|
virtual void paint( PaintInfo& i, int tx, int ty);
|
||
|
|
||
|
void paintCollapsedBorder(QPainter* p, int x, int y, int w, int h);
|
||
|
void paintBackgroundsBehindCell(PaintInfo& i, int _tx, int _ty, RenderObject* backgroundObject);
|
||
|
|
||
|
virtual void close();
|
||
|
|
||
|
// lie position to outside observers
|
||
|
virtual int yPos() const { return m_y + _topExtra; }
|
||
|
|
||
|
virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
|
||
|
virtual bool absolutePosition(int &xPos, int &yPos, bool f = false) const;
|
||
|
|
||
|
virtual short baselinePosition( bool = false ) const;
|
||
|
|
||
|
virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside);
|
||
|
|
||
|
RenderTable *table() const { return static_cast<RenderTable *>(parent()->parent()->parent()); }
|
||
|
RenderTableSection *section() const { return static_cast<RenderTableSection *>(parent()->parent()); }
|
||
|
|
||
|
#ifdef ENABLE_DUMP
|
||
|
virtual void dump(QTextStream &stream, const QString &ind) const;
|
||
|
#endif
|
||
|
|
||
|
bool widthChanged() {
|
||
|
bool retval = m_widthChanged;
|
||
|
m_widthChanged = false;
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
int cellPercentageHeight() const
|
||
|
{ return m_percentageHeight; }
|
||
|
void setCellPercentageHeight(int h)
|
||
|
{ m_percentageHeight = h; }
|
||
|
bool hasFlexedAnonymous() const
|
||
|
{ return m_hasFlexedAnonymous; }
|
||
|
void setHasFlexedAnonymous(bool b=true)
|
||
|
{ m_hasFlexedAnonymous = b; }
|
||
|
|
||
|
protected:
|
||
|
virtual void paintBoxDecorations(PaintInfo& p, int _tx, int _ty);
|
||
|
virtual int borderTopExtra() const { return _topExtra; }
|
||
|
virtual int borderBottomExtra() const { return _bottomExtra; }
|
||
|
|
||
|
short _row;
|
||
|
short _col;
|
||
|
ushort rSpan;
|
||
|
ushort cSpan;
|
||
|
int _topExtra;
|
||
|
signed int _bottomExtra : 30;
|
||
|
bool m_widthChanged : 1;
|
||
|
bool m_hasFlexedAnonymous : 1;
|
||
|
int m_percentageHeight;
|
||
|
};
|
||
|
|
||
|
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
class RenderTableCol : public RenderContainer
|
||
|
{
|
||
|
public:
|
||
|
RenderTableCol(DOM::NodeImpl* node);
|
||
|
|
||
|
virtual const char *renderName() const { return "RenderTableCol"; }
|
||
|
|
||
|
virtual bool isTableCol() const { return true; }
|
||
|
|
||
|
virtual short lineHeight( bool ) const { return 0; }
|
||
|
virtual void position(InlineBox*, int, int, bool) {}
|
||
|
virtual void layout() {}
|
||
|
virtual bool requiresLayer() const { return false; }
|
||
|
|
||
|
virtual void updateFromElement();
|
||
|
|
||
|
#ifdef ENABLE_DUMP
|
||
|
virtual void dump(QTextStream &stream, const QString& ind) const;
|
||
|
#endif
|
||
|
|
||
|
int span() const { return m_span; }
|
||
|
void setSpan( int s ) { m_span = s; }
|
||
|
|
||
|
private:
|
||
|
int m_span;
|
||
|
};
|
||
|
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
/** This class provides an iterator to iterate through the sections of a
|
||
|
* render table in their visual order.
|
||
|
*
|
||
|
* In HTML, sections are specified in the order of THEAD, TFOOT, and TBODY.
|
||
|
* Visually, TBODY sections appear between THEAD and TFOOT, which this iterator
|
||
|
* takes into regard.
|
||
|
* @author Leo Savernik
|
||
|
* @internal
|
||
|
* @since 3.2
|
||
|
*/
|
||
|
class TableSectionIterator {
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* Initializes a new iterator
|
||
|
* @param table table whose sections to iterate
|
||
|
* @param fromEnd @p true, begin with last section, @p false, begin with
|
||
|
* first section.
|
||
|
*/
|
||
|
TableSectionIterator(RenderTable *table, bool fromEnd = false);
|
||
|
|
||
|
/**
|
||
|
* Initializes a new iterator
|
||
|
* @param start table section to start with.
|
||
|
*/
|
||
|
TableSectionIterator(RenderTableSection *start) : sec(start) {}
|
||
|
|
||
|
/**
|
||
|
* Uninitialized iterator.
|
||
|
*/
|
||
|
TableSectionIterator() {}
|
||
|
|
||
|
/** Returns the current section, or @p 0 if the end has been reached.
|
||
|
*/
|
||
|
RenderTableSection *operator *() const { return sec; }
|
||
|
|
||
|
/** Moves to the next section in visual order. */
|
||
|
TableSectionIterator &operator ++();
|
||
|
|
||
|
/** Moves to the previous section in visual order. */
|
||
|
TableSectionIterator &operator --();
|
||
|
|
||
|
private:
|
||
|
RenderTableSection *sec;
|
||
|
};
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
|