1/*
2 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3 *           (C) 1997 Torben Weis (weis@kde.org)
4 *           (C) 1998 Waldo Bastian (bastian@kde.org)
5 *           (C) 1999 Lars Knoll (knoll@kde.org)
6 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
7 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
8 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB.  If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26#include "config.h"
27#include "core/rendering/RenderTableCol.h"
28
29#include "core/HTMLNames.h"
30#include "core/html/HTMLTableColElement.h"
31#include "core/rendering/RenderTable.h"
32#include "core/rendering/RenderTableCell.h"
33
34namespace blink {
35
36using namespace HTMLNames;
37
38RenderTableCol::RenderTableCol(Element* element)
39    : RenderBox(element)
40    , m_span(1)
41{
42    // init RenderObject attributes
43    setInline(true); // our object is not Inline
44    updateFromElement();
45}
46
47void RenderTableCol::trace(Visitor* visitor)
48{
49    visitor->trace(m_children);
50    RenderBox::trace(visitor);
51}
52
53void RenderTableCol::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
54{
55    RenderBox::styleDidChange(diff, oldStyle);
56
57    // If border was changed, notify table.
58    if (parent()) {
59        RenderTable* table = this->table();
60        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
61            table->invalidateCollapsedBorders();
62    }
63}
64
65void RenderTableCol::updateFromElement()
66{
67    unsigned oldSpan = m_span;
68    Node* n = node();
69    if (isHTMLTableColElement(n)) {
70        HTMLTableColElement& tc = toHTMLTableColElement(*n);
71        m_span = tc.span();
72    } else
73        m_span = !(style() && style()->display() == TABLE_COLUMN_GROUP);
74    if (m_span != oldSpan && style() && parent())
75        setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
76}
77
78void RenderTableCol::insertedIntoTree()
79{
80    RenderBox::insertedIntoTree();
81    table()->addColumn(this);
82}
83
84void RenderTableCol::willBeRemovedFromTree()
85{
86    RenderBox::willBeRemovedFromTree();
87    table()->removeColumn(this);
88}
89
90bool RenderTableCol::isChildAllowed(RenderObject* child, RenderStyle* style) const
91{
92    // We cannot use isTableColumn here as style() may return 0.
93    return child->isRenderTableCol() && style->display() == TABLE_COLUMN;
94}
95
96bool RenderTableCol::canHaveChildren() const
97{
98    // Cols cannot have children. This is actually necessary to fix a bug
99    // with libraries.uc.edu, which makes a <p> be a table-column.
100    return isTableColumnGroup();
101}
102
103LayoutRect RenderTableCol::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const
104{
105    // For now, just paint invalidate the whole table.
106    // FIXME: Find a better way to do this, e.g., need to paint invalidate all the cells that we
107    // might have propagated a background color or borders into.
108    // FIXME: check for paintInvalidationContainer each time here?
109
110    RenderTable* parentTable = table();
111    if (!parentTable)
112        return LayoutRect();
113    return parentTable->clippedOverflowRectForPaintInvalidation(paintInvalidationContainer, paintInvalidationState);
114}
115
116void RenderTableCol::imageChanged(WrappedImagePtr, const IntRect*)
117{
118    // FIXME: Issue paint invalidation of only the rect the image paints in.
119    setShouldDoFullPaintInvalidation(true);
120}
121
122void RenderTableCol::clearPreferredLogicalWidthsDirtyBits()
123{
124    clearPreferredLogicalWidthsDirty();
125
126    for (RenderObject* child = firstChild(); child; child = child->nextSibling())
127        child->clearPreferredLogicalWidthsDirty();
128}
129
130RenderTable* RenderTableCol::table() const
131{
132    RenderObject* table = parent();
133    if (table && !table->isTable())
134        table = table->parent();
135    return table && table->isTable() ? toRenderTable(table) : 0;
136}
137
138RenderTableCol* RenderTableCol::enclosingColumnGroup() const
139{
140    if (!parent()->isRenderTableCol())
141        return 0;
142
143    RenderTableCol* parentColumnGroup = toRenderTableCol(parent());
144    ASSERT(parentColumnGroup->isTableColumnGroup());
145    ASSERT(isTableColumn());
146    return parentColumnGroup;
147}
148
149RenderTableCol* RenderTableCol::nextColumn() const
150{
151    // If |this| is a column-group, the next column is the colgroup's first child column.
152    if (RenderObject* firstChild = this->firstChild())
153        return toRenderTableCol(firstChild);
154
155    // Otherwise it's the next column along.
156    RenderObject* next = nextSibling();
157
158    // Failing that, the child is the last column in a column-group, so the next column is the next column/column-group after its column-group.
159    if (!next && parent()->isRenderTableCol())
160        next = parent()->nextSibling();
161
162    for (; next && !next->isRenderTableCol(); next = next->nextSibling()) { }
163
164    return toRenderTableCol(next);
165}
166
167const BorderValue& RenderTableCol::borderAdjoiningCellStartBorder(const RenderTableCell*) const
168{
169    return style()->borderStart();
170}
171
172const BorderValue& RenderTableCol::borderAdjoiningCellEndBorder(const RenderTableCell*) const
173{
174    return style()->borderEnd();
175}
176
177const BorderValue& RenderTableCol::borderAdjoiningCellBefore(const RenderTableCell* cell) const
178{
179    ASSERT_UNUSED(cell, table()->colElement(cell->col() + cell->colSpan()) == this);
180    return style()->borderStart();
181}
182
183const BorderValue& RenderTableCol::borderAdjoiningCellAfter(const RenderTableCell* cell) const
184{
185    ASSERT_UNUSED(cell, table()->colElement(cell->col() - 1) == this);
186    return style()->borderEnd();
187}
188
189}
190