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" | |
29 #include "core/html/HTMLLegendElement.h" | 28 #include "core/html/HTMLLegendElement.h" |
30 #include "core/paint/FieldsetPainter.h" | 29 #include "core/paint/FieldsetPainter.h" |
31 | 30 |
32 using namespace std; | 31 using namespace std; |
33 | 32 |
34 namespace blink { | 33 namespace blink { |
35 | 34 |
36 using namespace HTMLNames; | 35 using namespace HTMLNames; |
37 | 36 |
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 | |
58 LayoutFieldset::LayoutFieldset(Element* element) | 37 LayoutFieldset::LayoutFieldset(Element* element) |
59 : LayoutFlexibleBox(element) | 38 : LayoutBlockFlow(element) |
60 , m_innerBlock(nullptr) | |
61 { | 39 { |
62 } | 40 } |
63 | 41 |
64 int LayoutFieldset::baselinePosition(FontBaseline baseline, bool firstLine, Line
DirectionMode direction, LinePositionMode position) const | 42 void LayoutFieldset::computePreferredLogicalWidths() |
65 { | 43 { |
66 return LayoutBlock::baselinePosition(baseline, firstLine, direction, positio
n); | 44 LayoutBlockFlow::computePreferredLogicalWidths(); |
67 } | 45 if (LayoutBox* legend = findInFlowLegend()) { |
| 46 int legendMinWidth = legend->minPreferredLogicalWidth(); |
68 | 47 |
69 void LayoutFieldset::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth,
LayoutUnit& maxLogicalWidth) const | 48 Length legendMarginLeft = legend->style()->marginLeft(); |
70 { | 49 Length legendMarginRight = legend->style()->marginRight(); |
71 if (m_innerBlock) | |
72 computeChildPreferredLogicalWidths(*m_innerBlock, minLogicalWidth, maxLo
gicalWidth); | |
73 | 50 |
74 if (LayoutBox* legend = findInFlowLegend()) { | 51 if (legendMarginLeft.isFixed()) |
75 LayoutUnit minPreferredLegendLogicalWidth; | 52 legendMinWidth += legendMarginLeft.value(); |
76 LayoutUnit maxPreferredLegendLogicalWidth; | |
77 computeChildPreferredLogicalWidths(*legend, minPreferredLegendLogicalWid
th, maxPreferredLegendLogicalWidth); | |
78 LayoutUnit margin = marginIntrinsicLogicalWidthForChild(*legend); | |
79 minPreferredLegendLogicalWidth += margin; | |
80 maxPreferredLegendLogicalWidth += margin; | |
81 minLogicalWidth = std::max(minLogicalWidth, minPreferredLegendLogicalWid
th); | |
82 maxLogicalWidth = std::max(maxLogicalWidth, maxPreferredLegendLogicalWid
th); | |
83 } | |
84 maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth); | |
85 | 53 |
86 // Due to negative margins, it is possible that we calculated a negative int
rinsic width. Make sure that we | 54 if (legendMarginRight.isFixed()) |
87 // never return a negative width. | 55 legendMinWidth += legendMarginRight.value(); |
88 minLogicalWidth = std::max(LayoutUnit(), minLogicalWidth); | |
89 maxLogicalWidth = std::max(LayoutUnit(), maxLogicalWidth); | |
90 | 56 |
91 LayoutUnit scrollbarWidth(scrollbarLogicalWidth()); | 57 m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, legendMinWi
dth + borderAndPaddingWidth()); |
92 maxLogicalWidth += scrollbarWidth; | |
93 minLogicalWidth += scrollbarWidth; | |
94 } | |
95 | |
96 void LayoutFieldset::setLogicalLeftForChild(LayoutBox& child, LayoutUnit logical
Left) | |
97 { | |
98 if (isHorizontalWritingMode()) { | |
99 child.setX(logicalLeft); | |
100 } else { | |
101 child.setY(logicalLeft); | |
102 } | 58 } |
103 } | 59 } |
104 | 60 |
105 void LayoutFieldset::setLogicalTopForChild(LayoutBox& child, LayoutUnit logicalT
op) | |
106 { | |
107 if (isHorizontalWritingMode()) { | |
108 child.setY(logicalTop); | |
109 } else { | |
110 child.setX(logicalTop); | |
111 } | |
112 } | |
113 | |
114 LayoutObject* LayoutFieldset::layoutSpecialExcludedChild(bool relayoutChildren,
SubtreeLayoutScope&) | 61 LayoutObject* LayoutFieldset::layoutSpecialExcludedChild(bool relayoutChildren,
SubtreeLayoutScope&) |
115 { | 62 { |
116 LayoutBox* legend = findInFlowLegend(); | 63 LayoutBox* legend = findInFlowLegend(); |
117 if (legend) { | 64 if (legend) { |
118 LayoutRect oldLegendFrameRect = legend->frameRect(); | 65 LayoutRect oldLegendFrameRect = legend->frameRect(); |
119 | 66 |
120 if (relayoutChildren) | 67 if (relayoutChildren) |
121 legend->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationRea
son::FieldsetChanged); | 68 legend->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationRea
son::FieldsetChanged); |
122 legend->layoutIfNeeded(); | 69 legend->layoutIfNeeded(); |
123 | 70 |
(...skipping 28 matching lines...) Expand all Loading... |
152 } | 99 } |
153 } | 100 } |
154 | 101 |
155 setLogicalLeftForChild(*legend, logicalLeft); | 102 setLogicalLeftForChild(*legend, logicalLeft); |
156 | 103 |
157 LayoutUnit fieldsetBorderBefore = LayoutUnit(borderBefore()); | 104 LayoutUnit fieldsetBorderBefore = LayoutUnit(borderBefore()); |
158 LayoutUnit legendLogicalHeight = logicalHeightForChild(*legend); | 105 LayoutUnit legendLogicalHeight = logicalHeightForChild(*legend); |
159 | 106 |
160 LayoutUnit legendLogicalTop; | 107 LayoutUnit legendLogicalTop; |
161 LayoutUnit collapsedLegendExtent; | 108 LayoutUnit collapsedLegendExtent; |
162 LayoutUnit innerBlockPadding; | |
163 // FIXME: We need to account for the legend's margin before too. | 109 // FIXME: We need to account for the legend's margin before too. |
164 if (fieldsetBorderBefore > legendLogicalHeight) { | 110 if (fieldsetBorderBefore > legendLogicalHeight) { |
165 // The <legend> is smaller than the associated fieldset before borde
r | 111 // The <legend> is smaller than the associated fieldset before borde
r |
166 // so the latter determines positioning of the <legend>. The sizing
depends | 112 // so the latter determines positioning of the <legend>. The sizing
depends |
167 // on the legend's margins as we want to still follow the author's c
ues. | 113 // on the legend's margins as we want to still follow the author's c
ues. |
168 // Firefox completely ignores the margins in this case which seems w
rong. | 114 // Firefox completely ignores the margins in this case which seems w
rong. |
169 legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2; | 115 legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2; |
170 collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legend
LogicalTop + legendLogicalHeight + marginAfterForChild(*legend)); | 116 collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legend
LogicalTop + legendLogicalHeight + marginAfterForChild(*legend)); |
171 innerBlockPadding = marginAfterForChild(*legend) ? marginAfterForChi
ld(*legend) - legendLogicalTop : LayoutUnit(); | |
172 } else { | 117 } else { |
173 collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(*l
egend); | 118 collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(*l
egend); |
174 innerBlockPadding = legendLogicalHeight - borderAfter() + marginAfte
rForChild(*legend); | |
175 } | 119 } |
176 | 120 |
177 setInnerBlockPadding(isHorizontalWritingMode(), m_innerBlock, innerBlock
Padding); | |
178 setLogicalTopForChild(*legend, legendLogicalTop); | 121 setLogicalTopForChild(*legend, legendLogicalTop); |
179 setLogicalHeight(paddingBefore() + collapsedLegendExtent); | 122 setLogicalHeight(paddingBefore() + collapsedLegendExtent); |
180 | 123 |
181 if (legend->frameRect() != oldLegendFrameRect) { | 124 if (legend->frameRect() != oldLegendFrameRect) { |
182 // We need to invalidate the fieldset border if the legend's frame c
hanged. | 125 // We need to invalidate the fieldset border if the legend's frame c
hanged. |
183 setShouldDoFullPaintInvalidation(); | 126 setShouldDoFullPaintInvalidation(); |
184 } | 127 } |
185 } | 128 } |
186 return legend; | 129 return legend; |
187 } | 130 } |
(...skipping 15 matching lines...) Expand all Loading... |
203 void LayoutFieldset::paintBoxDecorationBackground(const PaintInfo& paintInfo, co
nst LayoutPoint& paintOffset) const | 146 void LayoutFieldset::paintBoxDecorationBackground(const PaintInfo& paintInfo, co
nst LayoutPoint& paintOffset) const |
204 { | 147 { |
205 FieldsetPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset); | 148 FieldsetPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset); |
206 } | 149 } |
207 | 150 |
208 void LayoutFieldset::paintMask(const PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) const | 151 void LayoutFieldset::paintMask(const PaintInfo& paintInfo, const LayoutPoint& pa
intOffset) const |
209 { | 152 { |
210 FieldsetPainter(*this).paintMask(paintInfo, paintOffset); | 153 FieldsetPainter(*this).paintMask(paintInfo, paintOffset); |
211 } | 154 } |
212 | 155 |
213 void LayoutFieldset::styleDidChange(StyleDifference diff, const ComputedStyle* o
ldStyle) | |
214 { | |
215 LayoutFlexibleBox::styleDidChange(diff, oldStyle); | |
216 adjustInnerStyle(); | |
217 } | |
218 | |
219 void LayoutFieldset::addChild(LayoutObject* newChild, LayoutObject* beforeChild) | |
220 { | |
221 if (!m_innerBlock) | |
222 createInnerBlock(); | |
223 | |
224 if (isHTMLLegendElement(newChild->node())) { | |
225 // Let legend block to be the 2nd for correct layout positioning. | |
226 newChild->mutableStyle()->setOrder(2); | |
227 LayoutFlexibleBox::addChild(newChild, m_innerBlock); | |
228 } else { | |
229 m_innerBlock->addChild(newChild, beforeChild); | |
230 if (AXObjectCache* cache = document().existingAXObjectCache()) | |
231 cache->childrenChanged(this); | |
232 } | |
233 } | |
234 | |
235 void LayoutFieldset::adjustInnerStyle() | |
236 { | |
237 if (!m_innerBlock) | |
238 createInnerBlock(); | |
239 | |
240 ComputedStyle& innerStyle = m_innerBlock->mutableStyleRef(); | |
241 innerStyle.setFlexShrink(1.0f); | |
242 innerStyle.setFlexGrow(1.0f); | |
243 // min-width: 0; is needed for correct shrinking. | |
244 innerStyle.setMinWidth(Length(0, Fixed)); | |
245 innerStyle.setFlexDirection(style()->flexDirection()); | |
246 innerStyle.setJustifyContent(style()->justifyContent()); | |
247 innerStyle.setFlexWrap(style()->flexWrap()); | |
248 innerStyle.setAlignItems(style()->alignItems()); | |
249 innerStyle.setAlignContent(style()->alignContent()); | |
250 // Let anonymous block to be the 1st for correct layout positioning. | |
251 innerStyle.setOrder(1); | |
252 } | |
253 | |
254 void LayoutFieldset::createInnerBlock() | |
255 { | |
256 if (m_innerBlock) { | |
257 DCHECK(firstChild() == m_innerBlock); | |
258 return; | |
259 } | |
260 m_innerBlock = createAnonymousBlock(style()->display()); | |
261 LayoutFlexibleBox::addChild(m_innerBlock); | |
262 } | |
263 | |
264 void LayoutFieldset::removeChild(LayoutObject* oldChild) | |
265 { | |
266 if (isHTMLLegendElement(oldChild->node())) { | |
267 LayoutFlexibleBox::removeChild(oldChild); | |
268 if (m_innerBlock) | |
269 resetInnerBlockPadding(isHorizontalWritingMode(), m_innerBlock); | |
270 } else if (oldChild == m_innerBlock) { | |
271 LayoutFlexibleBox::removeChild(oldChild); | |
272 m_innerBlock = nullptr; | |
273 } else if (oldChild->parent() == this) { | |
274 LayoutFlexibleBox::removeChild(oldChild); | |
275 } else if (m_innerBlock) { | |
276 m_innerBlock->removeChild(oldChild); | |
277 } | |
278 } | |
279 | |
280 } // namespace blink | 156 } // namespace blink |
OLD | NEW |