• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1997 Martin Jones (mjones@kde.org)
5  *           (C) 1997 Torben Weis (weis@kde.org)
6  *           (C) 1998 Waldo Bastian (bastian@kde.org)
7  *           (C) 1999 Lars Knoll (knoll@kde.org)
8  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
9  * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26 
27 #include "config.h"
28 #include "RenderTableRow.h"
29 
30 #include "CachedImage.h"
31 #include "Document.h"
32 #include "HTMLNames.h"
33 #include "RenderTableCell.h"
34 #include "RenderView.h"
35 
36 namespace WebCore {
37 
38 using namespace HTMLNames;
39 
RenderTableRow(Node * node)40 RenderTableRow::RenderTableRow(Node* node)
41     : RenderBox(node)
42 {
43     // init RenderObject attributes
44     setInline(false);   // our object is not Inline
45 }
46 
destroy()47 void RenderTableRow::destroy()
48 {
49     RenderTableSection* recalcSection = section();
50 
51     RenderBox::destroy();
52 
53     if (recalcSection)
54         recalcSection->setNeedsCellRecalc();
55 }
56 
styleWillChange(StyleDifference diff,const RenderStyle * newStyle)57 void RenderTableRow::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
58 {
59     if (section() && style() && style()->height() != newStyle->height())
60         section()->setNeedsCellRecalc();
61 
62     ASSERT(newStyle->display() == TABLE_ROW);
63 
64     RenderBox::styleWillChange(diff, newStyle);
65 }
66 
addChild(RenderObject * child,RenderObject * beforeChild)67 void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
68 {
69     // Make sure we don't append things after :after-generated content if we have it.
70     if (!beforeChild && isAfterContent(lastChild()))
71         beforeChild = lastChild();
72 
73     if (!child->isTableCell()) {
74         RenderObject* last = beforeChild;
75         if (!last)
76             last = lastChild();
77         if (last && last->isAnonymous() && last->isTableCell()) {
78             last->addChild(child);
79             return;
80         }
81 
82         // If beforeChild is inside an anonymous cell, insert into the cell.
83         if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) {
84             last->parent()->addChild(child, beforeChild);
85             return;
86         }
87 
88         RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
89         RefPtr<RenderStyle> newStyle = RenderStyle::create();
90         newStyle->inheritFrom(style());
91         newStyle->setDisplay(TABLE_CELL);
92         cell->setStyle(newStyle.release());
93         addChild(cell, beforeChild);
94         cell->addChild(child);
95         return;
96     }
97 
98     // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that.
99     while (beforeChild && beforeChild->parent() != this)
100         beforeChild = beforeChild->parent();
101 
102     RenderTableCell* cell = toRenderTableCell(child);
103 
104     // Generated content can result in us having a null section so make sure to null check our parent.
105     if (parent())
106         section()->addCell(cell, this);
107 
108     ASSERT(!beforeChild || beforeChild->isTableCell());
109     RenderBox::addChild(cell, beforeChild);
110 
111     if (beforeChild || nextSibling())
112         section()->setNeedsCellRecalc();
113 }
114 
layout()115 void RenderTableRow::layout()
116 {
117     ASSERT(needsLayout());
118 
119     // Table rows do not add translation.
120     LayoutStateMaintainer statePusher(view(), this, IntSize());
121 
122     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
123         if (child->isTableCell()) {
124             RenderTableCell* cell = toRenderTableCell(child);
125             if (child->needsLayout()) {
126                 cell->calcVerticalMargins();
127                 cell->layout();
128             }
129         }
130     }
131 
132     // We only ever need to repaint if our cells didn't, which menas that they didn't need
133     // layout, so we know that our bounds didn't change. This code is just making up for
134     // the fact that we did not repaint in setStyle() because we had a layout hint.
135     // We cannot call repaint() because our clippedOverflowRectForRepaint() is taken from the
136     // parent table, and being mid-layout, that is invalid. Instead, we repaint our cells.
137     if (selfNeedsLayout() && checkForRepaintDuringLayout()) {
138         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
139             if (child->isTableCell())
140                 child->repaint();
141         }
142     }
143 
144     statePusher.pop();
145     setNeedsLayout(false);
146 }
147 
clippedOverflowRectForRepaint(RenderBoxModelObject * repaintContainer)148 IntRect RenderTableRow::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
149 {
150     ASSERT(parent());
151 
152     if (repaintContainer == this)
153         return RenderBox::clippedOverflowRectForRepaint(repaintContainer);
154 
155     // For now, just repaint the whole table.
156     // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
157     // might have propagated a background color into.
158     // FIXME: do repaintContainer checks here
159     if (RenderTable* parentTable = table())
160         return parentTable->clippedOverflowRectForRepaint(repaintContainer);
161 
162     return IntRect();
163 }
164 
165 // Hit Testing
nodeAtPoint(const HitTestRequest & request,HitTestResult & result,int x,int y,int tx,int ty,HitTestAction action)166 bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
167 {
168     // Table rows cannot ever be hit tested.  Effectively they do not exist.
169     // Just forward to our children always.
170     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
171         // FIXME: We have to skip over inline flows, since they can show up inside table rows
172         // at the moment (a demoted inline <form> for example). If we ever implement a
173         // table-specific hit-test method (which we should do for performance reasons anyway),
174         // then we can remove this check.
175         if (child->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
176             updateHitTestResult(result, IntPoint(x - tx, y - ty));
177             return true;
178         }
179     }
180 
181     return false;
182 }
183 
paint(PaintInfo & paintInfo,int tx,int ty)184 void RenderTableRow::paint(PaintInfo& paintInfo, int tx, int ty)
185 {
186     ASSERT(hasSelfPaintingLayer());
187     if (!layer())
188         return;
189     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
190         if (child->isTableCell()) {
191             // Paint the row background behind the cell.
192             if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackground) {
193                 RenderTableCell* cell = toRenderTableCell(child);
194                 cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);
195             }
196             if (!toRenderBox(child)->hasSelfPaintingLayer())
197                 child->paint(paintInfo, tx, ty);
198         }
199     }
200 }
201 
imageChanged(WrappedImagePtr,const IntRect *)202 void RenderTableRow::imageChanged(WrappedImagePtr, const IntRect*)
203 {
204     // FIXME: Examine cells and repaint only the rect the image paints in.
205     repaint();
206 }
207 
208 } // namespace WebCore
209