OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |