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 "RenderTableCol.h" |
28 | |
29 | #include "HTMLNames.h" |
30 | #include "HTMLTableColElement.h" |
31 | #include "RenderChildIterator.h" |
32 | #include "RenderIterator.h" |
33 | #include "RenderTable.h" |
34 | #include "RenderTableCaption.h" |
35 | #include "RenderTableCell.h" |
36 | #include <wtf/IsoMallocInlines.h> |
37 | |
38 | namespace WebCore { |
39 | |
40 | using namespace HTMLNames; |
41 | |
42 | WTF_MAKE_ISO_ALLOCATED_IMPL(RenderTableCol); |
43 | |
44 | RenderTableCol::RenderTableCol(Element& element, RenderStyle&& style) |
45 | : RenderBox(element, WTFMove(style), 0) |
46 | { |
47 | // init RenderObject attributes |
48 | setInline(true); // our object is not Inline |
49 | updateFromElement(); |
50 | } |
51 | |
52 | void RenderTableCol::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) |
53 | { |
54 | RenderBox::styleDidChange(diff, oldStyle); |
55 | RenderTable* table = this->table(); |
56 | if (!table) |
57 | return; |
58 | // If border was changed, notify table. |
59 | if (oldStyle && oldStyle->border() != style().border()) |
60 | table->invalidateCollapsedBorders(); |
61 | else if (oldStyle->width() != style().width()) { |
62 | table->recalcSectionsIfNeeded(); |
63 | for (auto& section : childrenOfType<RenderTableSection>(*table)) { |
64 | unsigned nEffCols = table->numEffCols(); |
65 | for (unsigned j = 0; j < nEffCols; j++) { |
66 | unsigned rowCount = section.numRows(); |
67 | for (unsigned i = 0; i < rowCount; i++) { |
68 | RenderTableCell* cell = section.primaryCellAt(i, j); |
69 | if (!cell) |
70 | continue; |
71 | cell->setPreferredLogicalWidthsDirty(true); |
72 | } |
73 | } |
74 | } |
75 | } |
76 | } |
77 | |
78 | void RenderTableCol::updateFromElement() |
79 | { |
80 | unsigned oldSpan = m_span; |
81 | if (element().hasTagName(colTag) || element().hasTagName(colgroupTag)) { |
82 | HTMLTableColElement& tc = static_cast<HTMLTableColElement&>(element()); |
83 | m_span = tc.span(); |
84 | } else |
85 | m_span = !(hasInitializedStyle() && style().display() == DisplayType::TableColumnGroup); |
86 | if (m_span != oldSpan && hasInitializedStyle() && parent()) |
87 | setNeedsLayoutAndPrefWidthsRecalc(); |
88 | } |
89 | |
90 | void RenderTableCol::insertedIntoTree() |
91 | { |
92 | RenderBox::insertedIntoTree(); |
93 | table()->addColumn(this); |
94 | } |
95 | |
96 | void RenderTableCol::willBeRemovedFromTree() |
97 | { |
98 | RenderBox::willBeRemovedFromTree(); |
99 | table()->removeColumn(this); |
100 | } |
101 | |
102 | bool RenderTableCol::isChildAllowed(const RenderObject& child, const RenderStyle& style) const |
103 | { |
104 | // We cannot use isTableColumn here as style() may return 0. |
105 | return style.display() == DisplayType::TableColumn && child.isRenderTableCol(); |
106 | } |
107 | |
108 | bool RenderTableCol::canHaveChildren() const |
109 | { |
110 | // Cols cannot have children. This is actually necessary to fix a bug |
111 | // with libraries.uc.edu, which makes a <p> be a table-column. |
112 | return isTableColumnGroup(); |
113 | } |
114 | |
115 | LayoutRect RenderTableCol::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const |
116 | { |
117 | // For now, just repaint the whole table. |
118 | // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we |
119 | // might have propagated a background color or borders into. |
120 | // FIXME: check for repaintContainer each time here? |
121 | |
122 | RenderTable* parentTable = table(); |
123 | if (!parentTable) |
124 | return LayoutRect(); |
125 | return parentTable->clippedOverflowRectForRepaint(repaintContainer); |
126 | } |
127 | |
128 | void RenderTableCol::imageChanged(WrappedImagePtr, const IntRect*) |
129 | { |
130 | // FIXME: Repaint only the rect the image paints in. |
131 | repaint(); |
132 | } |
133 | |
134 | void RenderTableCol::clearPreferredLogicalWidthsDirtyBits() |
135 | { |
136 | setPreferredLogicalWidthsDirty(false); |
137 | |
138 | for (auto& child : childrenOfType<RenderObject>(*this)) |
139 | child.setPreferredLogicalWidthsDirty(false); |
140 | } |
141 | |
142 | RenderTable* RenderTableCol::table() const |
143 | { |
144 | auto table = parent(); |
145 | if (table && !is<RenderTable>(*table)) |
146 | table = table->parent(); |
147 | return is<RenderTable>(table) ? downcast<RenderTable>(table) : nullptr; |
148 | } |
149 | |
150 | RenderTableCol* RenderTableCol::enclosingColumnGroup() const |
151 | { |
152 | if (!is<RenderTableCol>(*parent())) |
153 | return nullptr; |
154 | |
155 | RenderTableCol& parentColumnGroup = downcast<RenderTableCol>(*parent()); |
156 | ASSERT(parentColumnGroup.isTableColumnGroup()); |
157 | ASSERT(isTableColumn()); |
158 | return &parentColumnGroup; |
159 | } |
160 | |
161 | RenderTableCol* RenderTableCol::nextColumn() const |
162 | { |
163 | // If |this| is a column-group, the next column is the colgroup's first child column. |
164 | if (RenderObject* firstChild = this->firstChild()) |
165 | return downcast<RenderTableCol>(firstChild); |
166 | |
167 | // Otherwise it's the next column along. |
168 | RenderObject* next = nextSibling(); |
169 | |
170 | // 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. |
171 | if (!next && is<RenderTableCol>(*parent())) |
172 | next = parent()->nextSibling(); |
173 | |
174 | for (; next && !is<RenderTableCol>(*next); next = next->nextSibling()) { |
175 | // We allow captions mixed with columns and column-groups. |
176 | if (is<RenderTableCaption>(*next)) |
177 | continue; |
178 | |
179 | return nullptr; |
180 | } |
181 | |
182 | return downcast<RenderTableCol>(next); |
183 | } |
184 | |
185 | const BorderValue& RenderTableCol::borderAdjoiningCellStartBorder() const |
186 | { |
187 | return style().borderStart(); |
188 | } |
189 | |
190 | const BorderValue& RenderTableCol::borderAdjoiningCellEndBorder() const |
191 | { |
192 | return style().borderEnd(); |
193 | } |
194 | |
195 | const BorderValue& RenderTableCol::borderAdjoiningCellBefore(const RenderTableCell& cell) const |
196 | { |
197 | ASSERT_UNUSED(cell, table()->colElement(cell.col() + cell.colSpan()) == this); |
198 | return style().borderStart(); |
199 | } |
200 | |
201 | const BorderValue& RenderTableCol::borderAdjoiningCellAfter(const RenderTableCell& cell) const |
202 | { |
203 | ASSERT_UNUSED(cell, table()->colElement(cell.col() - 1) == this); |
204 | return style().borderEnd(); |
205 | } |
206 | |
207 | LayoutUnit RenderTableCol::offsetLeft() const |
208 | { |
209 | return table()->offsetLeftForColumn(*this); |
210 | } |
211 | |
212 | LayoutUnit RenderTableCol::offsetTop() const |
213 | { |
214 | return table()->offsetTopForColumn(*this); |
215 | } |
216 | |
217 | LayoutUnit RenderTableCol::offsetWidth() const |
218 | { |
219 | return table()->offsetWidthForColumn(*this); |
220 | } |
221 | |
222 | LayoutUnit RenderTableCol::offsetHeight() const |
223 | { |
224 | return table()->offsetHeightForColumn(*this); |
225 | } |
226 | |
227 | } |
228 | |