Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutFieldset.cpp

Issue 2215133005: Add grid/flex layout support for <fieldset> (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed comments: removed LayoutFlexibleBox::styleDidChange, fixed layoutSpecialExcludedChild formatt… Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. 5 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * 11 *
12 * This library is distributed in the hope that it will be useful, 12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details. 15 * Library General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU Library General Public License 17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to 18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA. 20 * Boston, MA 02110-1301, USA.
21 * 21 *
22 */ 22 */
23 23
24 #include "core/layout/LayoutFieldset.h" 24 #include "core/layout/LayoutFieldset.h"
25 25
26 #include "core/CSSPropertyNames.h" 26 #include "core/CSSPropertyNames.h"
27 #include "core/HTMLNames.h" 27 #include "core/HTMLNames.h"
28 #include "core/dom/AXObjectCache.h"
28 #include "core/html/HTMLLegendElement.h" 29 #include "core/html/HTMLLegendElement.h"
29 #include "core/paint/FieldsetPainter.h" 30 #include "core/paint/FieldsetPainter.h"
30 31
31 using namespace std; 32 using namespace std;
32 33
33 namespace blink { 34 namespace blink {
34 35
35 using namespace HTMLNames; 36 using namespace HTMLNames;
36 37
38 namespace {
39
40 void setInnerBlockPadding(bool isHorizontalWritingMode, const LayoutObject* inne rBlock, const LayoutUnit& padding)
41 {
42 if (isHorizontalWritingMode)
43 innerBlock->mutableStyleRef().setPaddingTop(Length(padding, Fixed));
44 else
45 innerBlock->mutableStyleRef().setPaddingLeft(Length(padding, Fixed));
46 }
47
48 void resetInnerBlockPadding(bool isHorizontalWritingMode, const LayoutObject* in nerBlock)
49 {
50 if (isHorizontalWritingMode)
51 innerBlock->mutableStyleRef().setPaddingTop(Length(0, Fixed));
52 else
53 innerBlock->mutableStyleRef().setPaddingLeft(Length(0, Fixed));
54 }
55
56 } // namespace
57
37 LayoutFieldset::LayoutFieldset(Element* element) 58 LayoutFieldset::LayoutFieldset(Element* element)
38 : LayoutBlockFlow(element) 59 : LayoutFlexibleBox(element)
60 , m_innerBlock(nullptr)
39 { 61 {
40 } 62 }
41 63
42 void LayoutFieldset::computePreferredLogicalWidths() 64 int LayoutFieldset::baselinePosition(FontBaseline baseline, bool firstLine, Line DirectionMode direction, LinePositionMode position) const
43 { 65 {
44 LayoutBlockFlow::computePreferredLogicalWidths(); 66 return LayoutBlock::baselinePosition(baseline, firstLine, direction, positio n);
45 if (LayoutBox* legend = findInFlowLegend()) { 67 }
46 int legendMinWidth = legend->minPreferredLogicalWidth();
47 68
48 Length legendMarginLeft = legend->style()->marginLeft(); 69 void LayoutFieldset::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
49 Length legendMarginRight = legend->style()->marginRight(); 70 {
71 for (LayoutBox* child = firstChildBox(); child; child = child->nextSiblingBo x()) {
72 if (child->isOutOfFlowPositioned())
73 continue;
50 74
51 if (legendMarginLeft.isFixed()) 75 LayoutUnit margin = marginIntrinsicLogicalWidthForChild(*child);
52 legendMinWidth += legendMarginLeft.value();
53 76
54 if (legendMarginRight.isFixed()) 77 LayoutUnit minPreferredLogicalWidth;
55 legendMinWidth += legendMarginRight.value(); 78 LayoutUnit maxPreferredLogicalWidth;
79 computeChildPreferredLogicalWidths(*child, minPreferredLogicalWidth, max PreferredLogicalWidth);
80 DCHECK_GE(minPreferredLogicalWidth, LayoutUnit());
81 DCHECK_GE(maxPreferredLogicalWidth, LayoutUnit());
82 minPreferredLogicalWidth += margin;
83 maxPreferredLogicalWidth += margin;
84 minLogicalWidth = std::max(minPreferredLogicalWidth, minLogicalWidth);
85 maxLogicalWidth = std::max(maxPreferredLogicalWidth, maxLogicalWidth);
86 }
56 87
57 m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, legendMinWi dth + borderAndPaddingWidth()); 88 maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);
89
90 // Due to negative margins, it is possible that we calculated a negative int rinsic width. Make sure that we
91 // never return a negative width.
92 minLogicalWidth = std::max(LayoutUnit(), minLogicalWidth);
93 maxLogicalWidth = std::max(LayoutUnit(), maxLogicalWidth);
94
95 LayoutUnit scrollbarWidth(scrollbarLogicalWidth());
96 maxLogicalWidth += scrollbarWidth;
97 minLogicalWidth += scrollbarWidth;
98 }
99
100 void LayoutFieldset::setLogicalLeftForChild(LayoutBox& child, LayoutUnit logical Left)
101 {
102 if (isHorizontalWritingMode()) {
103 child.setX(logicalLeft);
104 } else {
105 child.setY(logicalLeft);
58 } 106 }
59 } 107 }
60 108
109 void LayoutFieldset::setLogicalTopForChild(LayoutBox& child, LayoutUnit logicalT op)
110 {
111 if (isHorizontalWritingMode()) {
112 child.setY(logicalTop);
113 } else {
114 child.setX(logicalTop);
115 }
116 }
117
61 LayoutObject* LayoutFieldset::layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&) 118 LayoutObject* LayoutFieldset::layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&)
62 { 119 {
63 LayoutBox* legend = findInFlowLegend(); 120 LayoutBox* legend = findInFlowLegend();
64 if (legend) { 121 if (legend) {
65 LayoutRect oldLegendFrameRect = legend->frameRect(); 122 LayoutRect oldLegendFrameRect = legend->frameRect();
66 123
67 if (relayoutChildren) 124 if (relayoutChildren)
68 legend->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationRea son::FieldsetChanged); 125 legend->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationRea son::FieldsetChanged);
69 legend->layoutIfNeeded(); 126 legend->layoutIfNeeded();
70 127
(...skipping 28 matching lines...) Expand all
99 } 156 }
100 } 157 }
101 158
102 setLogicalLeftForChild(*legend, logicalLeft); 159 setLogicalLeftForChild(*legend, logicalLeft);
103 160
104 LayoutUnit fieldsetBorderBefore = LayoutUnit(borderBefore()); 161 LayoutUnit fieldsetBorderBefore = LayoutUnit(borderBefore());
105 LayoutUnit legendLogicalHeight = logicalHeightForChild(*legend); 162 LayoutUnit legendLogicalHeight = logicalHeightForChild(*legend);
106 163
107 LayoutUnit legendLogicalTop; 164 LayoutUnit legendLogicalTop;
108 LayoutUnit collapsedLegendExtent; 165 LayoutUnit collapsedLegendExtent;
166 LayoutUnit innerBlockPadding;
109 // FIXME: We need to account for the legend's margin before too. 167 // FIXME: We need to account for the legend's margin before too.
110 if (fieldsetBorderBefore > legendLogicalHeight) { 168 if (fieldsetBorderBefore > legendLogicalHeight) {
111 // The <legend> is smaller than the associated fieldset before borde r 169 // The <legend> is smaller than the associated fieldset before borde r
112 // so the latter determines positioning of the <legend>. The sizing depends 170 // so the latter determines positioning of the <legend>. The sizing depends
113 // on the legend's margins as we want to still follow the author's c ues. 171 // on the legend's margins as we want to still follow the author's c ues.
114 // Firefox completely ignores the margins in this case which seems w rong. 172 // Firefox completely ignores the margins in this case which seems w rong.
115 legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2; 173 legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2;
116 collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legend LogicalTop + legendLogicalHeight + marginAfterForChild(*legend)); 174 collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legend LogicalTop + legendLogicalHeight + marginAfterForChild(*legend));
175 innerBlockPadding = marginAfterForChild(*legend) ? marginAfterForChi ld(*legend) - legendLogicalTop : LayoutUnit();
117 } else { 176 } else {
118 collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(*l egend); 177 collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(*l egend);
178 innerBlockPadding = legendLogicalHeight - borderAfter() + marginAfte rForChild(*legend);
119 } 179 }
120 180
181 if (m_innerBlock)
182 setInnerBlockPadding(isHorizontalWritingMode(), m_innerBlock, innerB lockPadding);
121 setLogicalTopForChild(*legend, legendLogicalTop); 183 setLogicalTopForChild(*legend, legendLogicalTop);
122 setLogicalHeight(paddingBefore() + collapsedLegendExtent); 184 setLogicalHeight(paddingBefore() + collapsedLegendExtent);
123 185
124 if (legend->frameRect() != oldLegendFrameRect) { 186 if (legend->frameRect() != oldLegendFrameRect) {
125 // We need to invalidate the fieldset border if the legend's frame c hanged. 187 // We need to invalidate the fieldset border if the legend's frame c hanged.
126 setShouldDoFullPaintInvalidation(); 188 setShouldDoFullPaintInvalidation();
189 if (m_innerBlock)
190 m_innerBlock->setNeedsLayout(LayoutInvalidationReason::FieldsetC hanged, MarkOnlyThis);
127 } 191 }
128 } 192 }
129 return legend; 193 return legend;
130 } 194 }
131 195
132 LayoutBox* LayoutFieldset::findInFlowLegend() const 196 LayoutBox* LayoutFieldset::findInFlowLegend() const
133 { 197 {
134 for (LayoutObject* legend = firstChild(); legend; legend = legend->nextSibli ng()) { 198 for (LayoutObject* legend = firstChild(); legend; legend = legend->nextSibli ng()) {
135 if (legend->isFloatingOrOutOfFlowPositioned()) 199 if (legend->isFloatingOrOutOfFlowPositioned())
136 continue; 200 continue;
137 201
138 if (isHTMLLegendElement(legend->node())) { 202 if (isHTMLLegendElement(legend->node())) {
139 if (legend->isBox()) 203 if (legend->isBox())
140 return toLayoutBox(legend); 204 return toLayoutBox(legend);
141 } 205 }
142 } 206 }
143 return nullptr; 207 return nullptr;
144 } 208 }
145 209
146 void LayoutFieldset::paintBoxDecorationBackground(const PaintInfo& paintInfo, co nst LayoutPoint& paintOffset) const 210 void LayoutFieldset::paintBoxDecorationBackground(const PaintInfo& paintInfo, co nst LayoutPoint& paintOffset) const
147 { 211 {
148 FieldsetPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset); 212 FieldsetPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset);
149 } 213 }
150 214
151 void LayoutFieldset::paintMask(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) const 215 void LayoutFieldset::paintMask(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) const
152 { 216 {
153 FieldsetPainter(*this).paintMask(paintInfo, paintOffset); 217 FieldsetPainter(*this).paintMask(paintInfo, paintOffset);
154 } 218 }
155 219
220 void LayoutFieldset::updateAnonymousChildStyle(const LayoutObject& child, Comput edStyle& childStyle) const
221 {
222 childStyle.setFlexShrink(1.0f);
223 childStyle.setFlexGrow(1.0f);
224 // min-width: 0; is needed for correct shrinking.
225 childStyle.setMinWidth(Length(0, Fixed));
226 childStyle.setFlexDirection(style()->flexDirection());
227 childStyle.setJustifyContent(style()->justifyContent());
228 childStyle.setFlexWrap(style()->flexWrap());
229 childStyle.setAlignItems(style()->alignItems());
230 childStyle.setAlignContent(style()->alignContent());
231 // Let anonymous block to be the 1st for correct layout positioning.
232 childStyle.setOrder(1);
cbiesinger 2016/08/08 17:29:32 Oh sorry, I should have pointed this one out too -
233 }
234
235 void LayoutFieldset::addChild(LayoutObject* newChild, LayoutObject* beforeChild)
236 {
237 if (!m_innerBlock)
238 createInnerBlock();
239
240 if (isHTMLLegendElement(newChild->node())) {
241 LayoutFlexibleBox::addChild(newChild, m_innerBlock);
242 } else {
243 m_innerBlock->addChild(newChild, beforeChild);
244 if (AXObjectCache* cache = document().existingAXObjectCache())
245 cache->childrenChanged(this);
246 }
247 }
248
249 void LayoutFieldset::createInnerBlock()
250 {
251 if (m_innerBlock) {
252 DCHECK(firstChild() == m_innerBlock);
253 return;
254 }
255 m_innerBlock = createAnonymousBlock(style()->display());
256 LayoutFlexibleBox::addChild(m_innerBlock);
257 }
258
259 void LayoutFieldset::removeChild(LayoutObject* oldChild)
260 {
261 if (isHTMLLegendElement(oldChild->node())) {
262 LayoutFlexibleBox::removeChild(oldChild);
263 if (m_innerBlock)
264 resetInnerBlockPadding(isHorizontalWritingMode(), m_innerBlock);
265 } else if (oldChild == m_innerBlock) {
266 LayoutFlexibleBox::removeChild(oldChild);
267 m_innerBlock = nullptr;
268 } else if (oldChild->parent() == this) {
269 LayoutFlexibleBox::removeChild(oldChild);
270 } else if (m_innerBlock) {
271 m_innerBlock->removeChild(oldChild);
272 }
273 }
274
156 } // namespace blink 275 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutFieldset.h ('k') | third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698