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

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

Issue 2150003005: Add grid/flex layout support for <fieldset> (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: updated TestExpectations and fixed legend-after-margin-vertical-writing-mode.html Created 4 years, 5 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.
(...skipping 17 matching lines...) Expand all
28 #include "core/html/HTMLLegendElement.h" 28 #include "core/html/HTMLLegendElement.h"
29 #include "core/paint/FieldsetPainter.h" 29 #include "core/paint/FieldsetPainter.h"
30 30
31 using namespace std; 31 using namespace std;
32 32
33 namespace blink { 33 namespace blink {
34 34
35 using namespace HTMLNames; 35 using namespace HTMLNames;
36 36
37 LayoutFieldset::LayoutFieldset(Element* element) 37 LayoutFieldset::LayoutFieldset(Element* element)
38 : LayoutBlockFlow(element) 38 : LayoutFlexibleBox(element), m_innerBlock(nullptr)
jfernandez 2016/07/20 14:59:57 What's the rationale of inheriting from Flexbox ?
cbiesinger 2016/07/20 20:30:49 LayoutButton inherits from flexbox for the same pu
Manuel Rego 2016/07/21 10:28:43 What are the actual reasons Flexbox will be needed
Gleb Lanbin 2016/07/21 18:25:31 The anonymous block needs to use all available hei
39 { 39 {
40 } 40 }
41 41
42 void LayoutFieldset::computePreferredLogicalWidths() 42 int LayoutFieldset::baselinePosition(FontBaseline baseline, bool firstLine, Line DirectionMode direction, LinePositionMode position) const
43 { 43 {
44 LayoutBlockFlow::computePreferredLogicalWidths(); 44 return LayoutBlock::baselinePosition(baseline, firstLine, direction, positio n);
jfernandez 2016/07/20 14:59:57 So you want to avoid the LayoutFlexibleBox::baseli
cbiesinger 2016/07/20 20:30:49 flexbox has a different baseline behavior which mo
45 }
46
47 void LayoutFieldset::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
48 {
49 if (m_innerBlock)
50 computeChildPreferredLogicalWidths(*m_innerBlock, minLogicalWidth, maxLo gicalWidth);
51
45 if (LayoutBox* legend = findInFlowLegend()) { 52 if (LayoutBox* legend = findInFlowLegend()) {
46 int legendMinWidth = legend->minPreferredLogicalWidth(); 53 LayoutUnit minPreferredLegendLogicalWidth;
54 LayoutUnit maxPreferredLegendLogicalWidth;
55 computeChildPreferredLogicalWidths(*legend, minPreferredLegendLogicalWid th, maxPreferredLegendLogicalWidth);
56 LayoutUnit margin = marginIntrinsicLogicalWidthForChild(*legend);
57 minPreferredLegendLogicalWidth += margin;
58 maxPreferredLegendLogicalWidth += margin;
59 minLogicalWidth = std::max(minLogicalWidth, minPreferredLegendLogicalWid th);
60 maxLogicalWidth = std::max(maxLogicalWidth, maxPreferredLegendLogicalWid th);
61 }
62 maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);
47 63
48 Length legendMarginLeft = legend->style()->marginLeft(); 64 // Due to negative margins, it is possible that we calculated a negative int rinsic width. Make sure that we
49 Length legendMarginRight = legend->style()->marginRight(); 65 // never return a negative width.
66 minLogicalWidth = std::max(LayoutUnit(), minLogicalWidth);
67 maxLogicalWidth = std::max(LayoutUnit(), maxLogicalWidth);
50 68
51 if (legendMarginLeft.isFixed()) 69 LayoutUnit scrollbarWidth(scrollbarLogicalWidth());
52 legendMinWidth += legendMarginLeft.value(); 70 maxLogicalWidth += scrollbarWidth;
71 minLogicalWidth += scrollbarWidth;
72 }
53 73
54 if (legendMarginRight.isFixed()) 74 void LayoutFieldset::setLogicalLeftForChild(LayoutBox& child, LayoutUnit logical Left)
55 legendMinWidth += legendMarginRight.value(); 75 {
56 76 if (isHorizontalWritingMode()) {
57 m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, legendMinWi dth + borderAndPaddingWidth()); 77 child.setX(logicalLeft);
78 } else {
79 child.setY(logicalLeft);
58 } 80 }
59 } 81 }
60 82
83 void LayoutFieldset::setLogicalTopForChild(LayoutBox& child, LayoutUnit logicalT op)
84 {
85 if (isHorizontalWritingMode()) {
86 child.setY(logicalTop);
87 } else {
88 child.setX(logicalTop);
89 }
90 }
91
61 LayoutObject* LayoutFieldset::layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&) 92 LayoutObject* LayoutFieldset::layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&)
62 { 93 {
63 LayoutBox* legend = findInFlowLegend(); 94 LayoutBox* legend = findInFlowLegend();
64 if (legend) { 95 if (legend) {
65 LayoutRect oldLegendFrameRect = legend->frameRect(); 96 LayoutRect oldLegendFrameRect = legend->frameRect();
66 97
67 if (relayoutChildren) 98 if (relayoutChildren)
68 legend->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationRea son::FieldsetChanged); 99 legend->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationRea son::FieldsetChanged);
69 legend->layoutIfNeeded(); 100 legend->layoutIfNeeded();
70 101
(...skipping 28 matching lines...) Expand all
99 } 130 }
100 } 131 }
101 132
102 setLogicalLeftForChild(*legend, logicalLeft); 133 setLogicalLeftForChild(*legend, logicalLeft);
103 134
104 LayoutUnit fieldsetBorderBefore = LayoutUnit(borderBefore()); 135 LayoutUnit fieldsetBorderBefore = LayoutUnit(borderBefore());
105 LayoutUnit legendLogicalHeight = logicalHeightForChild(*legend); 136 LayoutUnit legendLogicalHeight = logicalHeightForChild(*legend);
106 137
107 LayoutUnit legendLogicalTop; 138 LayoutUnit legendLogicalTop;
108 LayoutUnit collapsedLegendExtent; 139 LayoutUnit collapsedLegendExtent;
140 LayoutUnit innerBlockPadding;
109 // FIXME: We need to account for the legend's margin before too. 141 // FIXME: We need to account for the legend's margin before too.
110 if (fieldsetBorderBefore > legendLogicalHeight) { 142 if (fieldsetBorderBefore > legendLogicalHeight) {
111 // The <legend> is smaller than the associated fieldset before borde r 143 // The <legend> is smaller than the associated fieldset before borde r
112 // so the latter determines positioning of the <legend>. The sizing depends 144 // 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. 145 // 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. 146 // Firefox completely ignores the margins in this case which seems w rong.
115 legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2; 147 legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2;
116 collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legend LogicalTop + legendLogicalHeight + marginAfterForChild(*legend)); 148 collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legend LogicalTop + legendLogicalHeight + marginAfterForChild(*legend));
149 innerBlockPadding = marginAfterForChild(*legend) ? marginAfterForChi ld(*legend) - legendLogicalTop : LayoutUnit();
117 } else { 150 } else {
118 collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(*l egend); 151 collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(*l egend);
152 innerBlockPadding = legendLogicalHeight - borderAfter() + marginAfte rForChild(*legend);
153 }
154
155 if (isHorizontalWritingMode()) {
156 m_innerBlock->mutableStyleRef().setPaddingTop(Length(innerBlockPaddi ng, Fixed));
157 } else {
158 m_innerBlock->mutableStyleRef().setPaddingLeft(Length(innerBlockPadd ing, Fixed));
119 } 159 }
120 160
121 setLogicalTopForChild(*legend, legendLogicalTop); 161 setLogicalTopForChild(*legend, legendLogicalTop);
122 setLogicalHeight(paddingBefore() + collapsedLegendExtent); 162 setLogicalHeight(paddingBefore() + collapsedLegendExtent);
123 163
124 if (legend->frameRect() != oldLegendFrameRect) { 164 if (legend->frameRect() != oldLegendFrameRect) {
125 // We need to invalidate the fieldset border if the legend's frame c hanged. 165 // We need to invalidate the fieldset border if the legend's frame c hanged.
126 setShouldDoFullPaintInvalidation(); 166 setShouldDoFullPaintInvalidation();
127 } 167 }
128 } 168 }
(...skipping 17 matching lines...) Expand all
146 void LayoutFieldset::paintBoxDecorationBackground(const PaintInfo& paintInfo, co nst LayoutPoint& paintOffset) const 186 void LayoutFieldset::paintBoxDecorationBackground(const PaintInfo& paintInfo, co nst LayoutPoint& paintOffset) const
147 { 187 {
148 FieldsetPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset); 188 FieldsetPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset);
149 } 189 }
150 190
151 void LayoutFieldset::paintMask(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) const 191 void LayoutFieldset::paintMask(const PaintInfo& paintInfo, const LayoutPoint& pa intOffset) const
152 { 192 {
153 FieldsetPainter(*this).paintMask(paintInfo, paintOffset); 193 FieldsetPainter(*this).paintMask(paintInfo, paintOffset);
154 } 194 }
155 195
196 void LayoutFieldset::styleDidChange(StyleDifference diff, const ComputedStyle* o ldStyle)
197 {
198 LayoutFlexibleBox::styleDidChange(diff, oldStyle);
199 adjustInnerStyle();
200 }
201
202 void LayoutFieldset::updateLogicalWidth()
203 {
204 LayoutFlexibleBox::updateLogicalWidth();
205 LogicalExtentComputedValues computedValues;
206 computeLogicalWidth(computedValues);
207
208 ComputedStyle& innerStyle = m_innerBlock->mutableStyleRef();
jfernandez 2016/07/20 14:59:57 Altering the ComputedStyle during layout is not a
cbiesinger 2016/07/20 20:30:49 Yeah, I don't understand why this is necessary? Do
Gleb Lanbin 2016/07/21 18:25:31 done, removed I needed it to pass //src/third_par
209 if (style()->isHorizontalWritingMode())
210 innerStyle.setWidth(Length(computedValues.m_extent, Fixed));
211 else
212 innerStyle.setHeight(Length(computedValues.m_extent, Fixed));
213 }
214
215 void LayoutFieldset::addChild(LayoutObject* newChild, LayoutObject* beforeChild)
216 {
217 if (!m_innerBlock)
218 createInnerBlock();
219
220 if (isHTMLLegendElement(newChild->node())) {
221 LayoutFlexibleBox::addChild(newChild);
222 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::Fieldse tChanged);
223 } else {
224 m_innerBlock->addChild(newChild, beforeChild);
225 DCHECK(m_innerBlock == firstChild());
226 }
227
228 if (AXObjectCache* cache = document().existingAXObjectCache())
cbiesinger 2016/07/20 20:30:49 Hm, why is this necessary? We don't call it in oth
Gleb Lanbin 2016/07/21 18:25:31 done. I copied it from LayoutMenuList as I was un
cbiesinger 2016/07/21 19:54:16 Interesting. Looking at some archaeology: https://
229 cache->childrenChanged(this);
230 }
231
232 void LayoutFieldset::adjustInnerStyle()
233 {
234 if (!m_innerBlock)
235 createInnerBlock();
236
237 ComputedStyle& innerStyle = m_innerBlock->mutableStyleRef();
jfernandez 2016/07/20 14:59:57 Ditto.
Gleb Lanbin 2016/07/21 18:25:31 this is similar to LayoutButton::updateAnonymousCh
238 innerStyle.setFlexShrink(1);
cbiesinger 2016/07/20 20:30:49 Use 1.0f, since these are floats, not ints.
Gleb Lanbin 2016/07/21 18:25:31 Done.
239 innerStyle.setFlexGrow(1);
cbiesinger 2016/07/20 20:30:49 I think you'll want to setMinWidth to Length(0, Fi
Gleb Lanbin 2016/07/21 18:25:31 Done.
240 }
241
242 void LayoutFieldset::createInnerBlock()
243 {
244 if (m_innerBlock) {
245 DCHECK(firstChild() == m_innerBlock);
246 return;
247 }
248 m_innerBlock = createAnonymousBlock(style()->display());
249 LayoutFlexibleBox::addChild(m_innerBlock);
250 }
251
252 void LayoutFieldset::removeChild(LayoutObject* oldChild)
253 {
Manuel Rego 2016/07/20 06:00:23 I didn't review all the changes in this file, but
Gleb Lanbin 2016/07/21 18:25:31 done. after submitting this patch for review I f
Manuel Rego 2016/07/22 06:16:06 Shouldn't we add tests to check that this kind of
Gleb Lanbin 2016/07/22 22:16:15 we already have test to check this src/third_party
254 if (isHTMLLegendElement(oldChild->node())) {
255 LayoutFlexibleBox::removeChild(oldChild);
256 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::Fieldse tChanged);
cbiesinger 2016/07/20 20:30:49 Admittedly I don't fully understand our invalidati
Gleb Lanbin 2016/07/21 18:25:31 so usually <fieldset> looks like this +-- Legend -
cbiesinger 2016/07/21 19:54:16 Hm... I see. But, in general when we remove a chil
Gleb Lanbin 2016/07/21 20:49:01 done. removed. you're right. I don't need it anym
257 } else if (oldChild == m_innerBlock) {
258 LayoutFlexibleBox::removeChild(oldChild);
259 m_innerBlock = nullptr;
260 } else if (m_innerBlock) {
261 m_innerBlock->removeChild(oldChild);
262 }
263 }
264
156 } // namespace blink 265 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698