/* * 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 #include #include "rendering/render_box.h" #include "rendering/render_block.h" #include "rendering/render_style.h" #include "misc/tdehtmllayout.h" namespace DOM { class DOMString; } namespace tdehtml { 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 TQColor &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(TQTextStream &stream, const TQString &ind) const; #endif struct ColumnStruct { enum { WidthUndefined = 0xffff }; ColumnStruct() { span = 1; width = WidthUndefined; } ushort span; ushort width; // the calculated position of the column }; TQMemArray columnPos; TQMemArray 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(TQTextStream &stream, const TQString &ind) const; #endif void addCell( RenderTableCell *cell, RenderTableRow *row ); void setCellWidths(); void calcRowHeight(); int layoutRows( int height ); RenderTable *table() const { return static_cast(parent()); } typedef TQMemArray 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 TQMemArray grid; TQMemArray 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(parent()->parent()); } RenderTableSection *section() const { return static_cast(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(TQValueList& 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(TQPainter* 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(parent()->parent()->parent()); } RenderTableSection *section() const { return static_cast(parent()->parent()); } #ifdef ENABLE_DUMP virtual void dump(TQTextStream &stream, const TQString &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(TQTextStream &stream, const TQString& 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