Add WTF::move()
[WebKit-https.git] / Source / WebCore / rendering / RenderButton.cpp
index a87e688..e067884 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 Apple Computer, Inc.
+ * Copyright (C) 2005 Apple Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #include "HTMLNames.h"
 #include "RenderTextFragment.h"
 #include "RenderTheme.h"
+#include "StyleInheritedData.h"
+
+#if PLATFORM(IOS)
+#include "RenderThemeIOS.h"
+#endif
 
 namespace WebCore {
 
 using namespace HTMLNames;
 
-RenderButton::RenderButton(Node* node)
-    : RenderDeprecatedFlexibleBox(node)
+RenderButton::RenderButton(HTMLFormControlElement& element, PassRef<RenderStyle> style)
+    : RenderFlexibleBox(element, WTF::move(style))
     , m_buttonText(0)
     , m_inner(0)
     , m_default(false)
@@ -44,37 +49,59 @@ RenderButton::~RenderButton()
 {
 }
 
+HTMLFormControlElement& RenderButton::formControlElement() const
+{
+    return toHTMLFormControlElement(nodeForNonAnonymous());
+}
+
+bool RenderButton::canBeSelectionLeaf() const
+{
+    return formControlElement().hasEditableStyle();
+}
+
+bool RenderButton::hasLineIfEmpty() const
+{
+    return formControlElement().toInputElement();
+}
+
 void RenderButton::addChild(RenderObject* newChild, RenderObject* beforeChild)
 {
     if (!m_inner) {
         // Create an anonymous block.
         ASSERT(!firstChild());
-        bool isFlexibleBox = style()->display() == BOX || style()->display() == INLINE_BOX;
-        m_inner = createAnonymousBlock(isFlexibleBox);
-        setupInnerStyle(m_inner->style());
-        RenderDeprecatedFlexibleBox::addChild(m_inner);
+        m_inner = createAnonymousBlock(style().display());
+        setupInnerStyle(&m_inner->style());
+        RenderFlexibleBox::addChild(m_inner);
     }
     
     m_inner->addChild(newChild, beforeChild);
 }
 
-void RenderButton::removeChild(RenderObject* oldChild)
+RenderObject* RenderButton::removeChild(RenderObject& oldChild)
 {
-    if (oldChild == m_inner || !m_inner) {
-        RenderDeprecatedFlexibleBox::removeChild(oldChild);
-        m_inner = 0;
+    // m_inner should be the only child, but checking for direct children who
+    // are not m_inner prevents security problems when that assumption is
+    // violated.
+    if (&oldChild == m_inner || !m_inner || oldChild.parent() == this) {
+        ASSERT(&oldChild == m_inner || !m_inner);
+        RenderObject* next = RenderFlexibleBox::removeChild(oldChild);
+        m_inner = nullptr;
+        return next;
     } else
-        m_inner->removeChild(oldChild);
+        return m_inner->removeChild(oldChild);
 }
 
-void RenderButton::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderButton::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
 {
     if (m_inner) {
         // RenderBlock::setStyle is going to apply a new style to the inner block, which
-        // will have the initial box flex value, 0. The current value is 1, because we set
+        // will have the initial flex value, 0. The current value is 1, because we set
         // it right below. Here we change it back to 0 to avoid getting a spurious layout hint
-        // because of the difference.
-        m_inner->style()->setBoxFlex(0);
+        // because of the difference. Same goes for the other properties.
+        // FIXME: Make this hack unnecessary.
+        m_inner->style().setFlexGrow(newStyle.initialFlexGrow());
+        m_inner->style().setMarginTop(newStyle.initialMargin());
+        m_inner->style().setMarginBottom(newStyle.initialMargin());
     }
     RenderBlock::styleWillChange(diff, newStyle);
 }
@@ -83,19 +110,17 @@ void RenderButton::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
 {
     RenderBlock::styleDidChange(diff, oldStyle);
 
-    if (m_buttonText)
-        m_buttonText->setStyle(style());
     if (m_inner) // RenderBlock handled updating the anonymous block's style.
-        setupInnerStyle(m_inner->style());
+        setupInnerStyle(&m_inner->style());
 
-    if (!m_default && theme()->isDefault(this)) {
+    if (!m_default && theme().isDefault(*this)) {
         if (!m_timer)
-            m_timer = adoptPtr(new Timer<RenderButton>(this, &RenderButton::timerFired));
+            m_timer = std::make_unique<Timer<RenderButton>>(this, &RenderButton::timerFired);
         m_timer->startRepeating(0.03);
         m_default = true;
-    } else if (m_default && !theme()->isDefault(this)) {
+    } else if (m_default && !theme().isDefault(*this)) {
         m_default = false;
-        m_timer.clear();
+        m_timer = nullptr;
     }
 }
 
@@ -104,16 +129,22 @@ void RenderButton::setupInnerStyle(RenderStyle* innerStyle)
     ASSERT(innerStyle->refCount() == 1);
     // RenderBlock::createAnonymousBlock creates a new RenderStyle, so this is
     // safe to modify.
-    innerStyle->setBoxFlex(1.0f);
-    innerStyle->setBoxOrient(style()->boxOrient());
+    // FIXME: I don't see how the comment above is accurate when this is called
+    // from the RenderButton::styleDidChange function.
+    innerStyle->setFlexGrow(1.0f);
+    // Use margin:auto instead of align-items:center to get safe centering, i.e.
+    // when the content overflows, treat it the same as align-items: flex-start.
+    innerStyle->setMarginTop(Length());
+    innerStyle->setMarginBottom(Length());
+    innerStyle->setFlexDirection(style().flexDirection());
 }
 
 void RenderButton::updateFromElement()
 {
     // If we're an input element, we may need to change our button text.
-    if (node()->hasTagName(inputTag)) {
-        HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
-        String value = input->valueWithDefault();
+    if (isHTMLInputElement(formControlElement())) {
+        HTMLInputElement& input = toHTMLInputElement(formControlElement());
+        String value = input.valueWithDefault();
         setText(value);
     }
 }
@@ -129,8 +160,7 @@ void RenderButton::setText(const String& str)
         if (m_buttonText)
             m_buttonText->setText(str.impl());
         else {
-            m_buttonText = new (renderArena()) RenderTextFragment(document(), str.impl());
-            m_buttonText->setStyle(style());
+            m_buttonText = new RenderTextFragment(document(), str);
             addChild(m_buttonText);
         }
     }
@@ -141,12 +171,12 @@ String RenderButton::text() const
     return m_buttonText ? m_buttonText->text() : 0;
 }
 
-void RenderButton::updateBeforeAfterContent(PseudoId type)
+bool RenderButton::canHaveGeneratedChildren() const
 {
-    if (m_inner)
-        m_inner->children()->updateBeforeAfterContent(m_inner, type, this);
-    else
-        children()->updateBeforeAfterContent(this, type);
+    // Input elements can't have generated children, but button elements can. We'll
+    // write the code assuming any other button types that might emerge in the future
+    // can also have children.
+    return !isHTMLInputElement(formControlElement());
 }
 
 LayoutRect RenderButton::controlClipRect(const LayoutPoint& additionalOffset) const
@@ -155,16 +185,26 @@ LayoutRect RenderButton::controlClipRect(const LayoutPoint& additionalOffset) co
     return LayoutRect(additionalOffset.x() + borderLeft(), additionalOffset.y() + borderTop(), width() - borderLeft() - borderRight(), height() - borderTop() - borderBottom());
 }
 
-void RenderButton::timerFired(Timer<RenderButton>*)
+void RenderButton::timerFired(Timer<RenderButton>&)
 {
     // FIXME Bug 25110: Ideally we would stop our timer when our Document
     // enters the page cache. But we currently have no way of being notified
     // when that happens, so we'll just ignore the timer firing as long as
     // we're in the cache.
-    if (document()->inPageCache())
+    if (document().inPageCache())
         return;
 
     repaint();
 }
 
+#if PLATFORM(IOS)
+void RenderButton::layout()
+{
+    RenderFlexibleBox::layout();
+
+    // FIXME: We should not be adjusting styles during layout. See <rdar://problem/7675493>.
+    RenderThemeIOS::adjustRoundBorderRadius(style(), *this);
+}
+#endif
+
 } // namespace WebCore