1 | /**
|
---|
2 | * Copyright (C) 2005 Apple Inc.
|
---|
3 | *
|
---|
4 | * This library is free software; you can redistribute it and/or
|
---|
5 | * modify it under the terms of the GNU Library General Public
|
---|
6 | * License as published by the Free Software Foundation; either
|
---|
7 | * version 2 of the License, or (at your option) any later version.
|
---|
8 | *
|
---|
9 | * This library is distributed in the hope that it will be useful,
|
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
12 | * Library General Public License for more details.
|
---|
13 | *
|
---|
14 | * You should have received a copy of the GNU Library General Public License
|
---|
15 | * along with this library; see the file COPYING.LIB. If not, write to
|
---|
16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
---|
17 | * Boston, MA 02110-1301, USA.
|
---|
18 | *
|
---|
19 | */
|
---|
20 |
|
---|
21 | #include "config.h"
|
---|
22 | #include "RenderButton.h"
|
---|
23 |
|
---|
24 | #include "Document.h"
|
---|
25 | #include "GraphicsContext.h"
|
---|
26 | #include "HTMLInputElement.h"
|
---|
27 | #include "HTMLNames.h"
|
---|
28 | #include "RenderTextFragment.h"
|
---|
29 | #include "RenderTheme.h"
|
---|
30 | #include "RenderTreeBuilder.h"
|
---|
31 | #include "StyleInheritedData.h"
|
---|
32 | #include <wtf/IsoMallocInlines.h>
|
---|
33 |
|
---|
34 | #if PLATFORM(IOS_FAMILY)
|
---|
35 | #include "RenderThemeIOS.h"
|
---|
36 | #endif
|
---|
37 |
|
---|
38 | namespace WebCore {
|
---|
39 |
|
---|
40 | using namespace HTMLNames;
|
---|
41 |
|
---|
42 | WTF_MAKE_ISO_ALLOCATED_IMPL(RenderButton);
|
---|
43 |
|
---|
44 | RenderButton::RenderButton(HTMLFormControlElement& element, RenderStyle&& style)
|
---|
45 | : RenderFlexibleBox(element, WTFMove(style))
|
---|
46 | {
|
---|
47 | }
|
---|
48 |
|
---|
49 | RenderButton::~RenderButton() = default;
|
---|
50 |
|
---|
51 | HTMLFormControlElement& RenderButton::formControlElement() const
|
---|
52 | {
|
---|
53 | return downcast<HTMLFormControlElement>(nodeForNonAnonymous());
|
---|
54 | }
|
---|
55 |
|
---|
56 | bool RenderButton::canBeSelectionLeaf() const
|
---|
57 | {
|
---|
58 | return formControlElement().hasEditableStyle();
|
---|
59 | }
|
---|
60 |
|
---|
61 | bool RenderButton::hasLineIfEmpty() const
|
---|
62 | {
|
---|
63 | return is<HTMLInputElement>(formControlElement());
|
---|
64 | }
|
---|
65 |
|
---|
66 | void RenderButton::setInnerRenderer(RenderBlock& innerRenderer)
|
---|
67 | {
|
---|
68 | ASSERT(!m_inner.get());
|
---|
69 | m_inner = innerRenderer;
|
---|
70 | updateAnonymousChildStyle(m_inner->mutableStyle());
|
---|
71 | }
|
---|
72 |
|
---|
73 | void RenderButton::updateAnonymousChildStyle(RenderStyle& childStyle) const
|
---|
74 | {
|
---|
75 | childStyle.setFlexGrow(1.0f);
|
---|
76 | // min-width: 0; is needed for correct shrinking.
|
---|
77 | childStyle.setMinWidth(Length(0, LengthType::Fixed));
|
---|
78 | // Use margin:auto instead of align-items:center to get safe centering, i.e.
|
---|
79 | // when the content overflows, treat it the same as align-items: flex-start.
|
---|
80 | childStyle.setMarginTop(Length());
|
---|
81 | childStyle.setMarginBottom(Length());
|
---|
82 | childStyle.setFlexDirection(style().flexDirection());
|
---|
83 | childStyle.setJustifyContent(style().justifyContent());
|
---|
84 | childStyle.setFlexWrap(style().flexWrap());
|
---|
85 | childStyle.setAlignItems(style().alignItems());
|
---|
86 | childStyle.setAlignContent(style().alignContent());
|
---|
87 | }
|
---|
88 |
|
---|
89 | void RenderButton::updateFromElement()
|
---|
90 | {
|
---|
91 | // If we're an input element, we may need to change our button text.
|
---|
92 | if (is<HTMLInputElement>(formControlElement())) {
|
---|
93 | HTMLInputElement& input = downcast<HTMLInputElement>(formControlElement());
|
---|
94 | String value = input.valueWithDefault();
|
---|
95 | setText(value);
|
---|
96 | }
|
---|
97 | }
|
---|
98 |
|
---|
99 | void RenderButton::setText(const String& str)
|
---|
100 | {
|
---|
101 | if (!m_buttonText && str.isEmpty())
|
---|
102 | return;
|
---|
103 |
|
---|
104 | if (!m_buttonText) {
|
---|
105 | auto newButtonText = createRenderer<RenderTextFragment>(document(), str);
|
---|
106 | m_buttonText = *newButtonText;
|
---|
107 | // FIXME: This mutation should go through the normal RenderTreeBuilder path.
|
---|
108 | if (RenderTreeBuilder::current())
|
---|
109 | RenderTreeBuilder::current()->attach(*this, WTFMove(newButtonText));
|
---|
110 | else
|
---|
111 | RenderTreeBuilder(*document().renderView()).attach(*this, WTFMove(newButtonText));
|
---|
112 | return;
|
---|
113 | }
|
---|
114 |
|
---|
115 | if (!str.isEmpty()) {
|
---|
116 | m_buttonText->setText(str.impl());
|
---|
117 | return;
|
---|
118 | }
|
---|
119 | if (RenderTreeBuilder::current())
|
---|
120 | RenderTreeBuilder::current()->destroy(*m_buttonText);
|
---|
121 | else
|
---|
122 | RenderTreeBuilder(*document().renderView()).destroy(*m_buttonText);
|
---|
123 | }
|
---|
124 |
|
---|
125 | String RenderButton::text() const
|
---|
126 | {
|
---|
127 | if (m_buttonText)
|
---|
128 | return m_buttonText->text();
|
---|
129 | return { };
|
---|
130 | }
|
---|
131 |
|
---|
132 | bool RenderButton::canHaveGeneratedChildren() const
|
---|
133 | {
|
---|
134 | // Input elements can't have generated children, but button elements can. We'll
|
---|
135 | // write the code assuming any other button types that might emerge in the future
|
---|
136 | // can also have children.
|
---|
137 | return !is<HTMLInputElement>(formControlElement());
|
---|
138 | }
|
---|
139 |
|
---|
140 | LayoutRect RenderButton::controlClipRect(const LayoutPoint& additionalOffset) const
|
---|
141 | {
|
---|
142 | // Clip to the padding box to at least give content the extra padding space.
|
---|
143 | return LayoutRect(additionalOffset.x() + borderLeft(), additionalOffset.y() + borderTop(), width() - borderLeft() - borderRight(), height() - borderTop() - borderBottom());
|
---|
144 | }
|
---|
145 |
|
---|
146 | static LayoutUnit synthesizedBaselineFromContentBox(const RenderBox& box, LineDirectionMode direction)
|
---|
147 | {
|
---|
148 | return direction == HorizontalLine ? box.borderTop() + box.paddingTop() + box.contentHeight() : box.borderRight() + box.paddingRight() + box.contentWidth();
|
---|
149 | }
|
---|
150 |
|
---|
151 | LayoutUnit RenderButton::baselinePosition(FontBaseline fontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode mode) const
|
---|
152 | {
|
---|
153 | if (shouldApplyLayoutContainment())
|
---|
154 | return RenderFlexibleBox::baselinePosition(fontBaseline, firstLine, direction, mode);
|
---|
155 | // We cannot rely on RenderFlexibleBox::baselinePosition() because of flexboxes have some special behavior
|
---|
156 | // regarding baselines that shouldn't apply to buttons.
|
---|
157 | LayoutUnit baseline = firstLineBaseline().value_or(synthesizedBaselineFromContentBox(*this, direction));
|
---|
158 | LayoutUnit marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
|
---|
159 | return baseline + marginAscent;
|
---|
160 | }
|
---|
161 |
|
---|
162 | #if PLATFORM(IOS_FAMILY)
|
---|
163 | void RenderButton::layout()
|
---|
164 | {
|
---|
165 | RenderFlexibleBox::layout();
|
---|
166 |
|
---|
167 | // FIXME: We should not be adjusting styles during layout. See <rdar://problem/7675493>.
|
---|
168 | RenderThemeIOS::adjustRoundBorderRadius(mutableStyle(), *this);
|
---|
169 | }
|
---|
170 | #endif
|
---|
171 |
|
---|
172 | } // namespace WebCore
|
---|