WebCore/rendering/RenderButton.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /**
       
     2  * Copyright (C) 2005 Apple Computer, 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 
       
    31 #if ENABLE(WML)
       
    32 #include "WMLDoElement.h"
       
    33 #include "WMLNames.h"
       
    34 #endif
       
    35 
       
    36 namespace WebCore {
       
    37 
       
    38 using namespace HTMLNames;
       
    39 
       
    40 RenderButton::RenderButton(Node* node)
       
    41     : RenderFlexibleBox(node)
       
    42     , m_buttonText(0)
       
    43     , m_inner(0)
       
    44     , m_default(false)
       
    45 {
       
    46 }
       
    47 
       
    48 void RenderButton::addChild(RenderObject* newChild, RenderObject* beforeChild)
       
    49 {
       
    50     if (!m_inner) {
       
    51         // Create an anonymous block.
       
    52         ASSERT(!firstChild());
       
    53         bool isFlexibleBox = style()->display() == BOX || style()->display() == INLINE_BOX;
       
    54         m_inner = createAnonymousBlock(isFlexibleBox);
       
    55         setupInnerStyle(m_inner->style());
       
    56         RenderFlexibleBox::addChild(m_inner);
       
    57     }
       
    58     
       
    59     m_inner->addChild(newChild, beforeChild);
       
    60 }
       
    61 
       
    62 void RenderButton::removeChild(RenderObject* oldChild)
       
    63 {
       
    64     if (oldChild == m_inner || !m_inner) {
       
    65         RenderFlexibleBox::removeChild(oldChild);
       
    66         m_inner = 0;
       
    67     } else
       
    68         m_inner->removeChild(oldChild);
       
    69 }
       
    70 
       
    71 void RenderButton::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
       
    72 {
       
    73     if (m_inner) {
       
    74         // RenderBlock::setStyle is going to apply a new style to the inner block, which
       
    75         // will have the initial box flex value, 0. The current value is 1, because we set
       
    76         // it right below. Here we change it back to 0 to avoid getting a spurious layout hint
       
    77         // because of the difference.
       
    78         m_inner->style()->setBoxFlex(0);
       
    79     }
       
    80     RenderBlock::styleWillChange(diff, newStyle);
       
    81 }
       
    82 
       
    83 void RenderButton::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
       
    84 {
       
    85     RenderBlock::styleDidChange(diff, oldStyle);
       
    86 
       
    87     if (m_buttonText)
       
    88         m_buttonText->setStyle(style());
       
    89     if (m_inner) // RenderBlock handled updating the anonymous block's style.
       
    90         setupInnerStyle(m_inner->style());
       
    91     setReplaced(isInline());
       
    92 
       
    93     if (!m_default && theme()->isDefault(this)) {
       
    94         if (!m_timer)
       
    95             m_timer.set(new Timer<RenderButton>(this, &RenderButton::timerFired));
       
    96         m_timer->startRepeating(0.03);
       
    97         m_default = true;
       
    98     } else if (m_default && !theme()->isDefault(this)) {
       
    99         m_default = false;
       
   100         m_timer.clear();
       
   101     }
       
   102 }
       
   103 
       
   104 void RenderButton::setupInnerStyle(RenderStyle* innerStyle) 
       
   105 {
       
   106     ASSERT(innerStyle->refCount() == 1);
       
   107     // RenderBlock::createAnonymousBlock creates a new RenderStyle, so this is
       
   108     // safe to modify.
       
   109     innerStyle->setBoxFlex(1.0f);
       
   110     innerStyle->setBoxOrient(style()->boxOrient());
       
   111 }
       
   112 
       
   113 void RenderButton::updateFromElement()
       
   114 {
       
   115     // If we're an input element, we may need to change our button text.
       
   116     if (node()->hasTagName(inputTag)) {
       
   117         HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
       
   118         String value = input->valueWithDefault();
       
   119         setText(value);
       
   120     }
       
   121 
       
   122 
       
   123 #if ENABLE(WML)
       
   124     else if (node()->hasTagName(WMLNames::doTag)) {
       
   125         WMLDoElement* doElement = static_cast<WMLDoElement*>(node());
       
   126 
       
   127         String value = doElement->label();
       
   128         if (value.isEmpty())
       
   129             value = doElement->name();
       
   130 
       
   131         setText(value);
       
   132     }
       
   133 #endif
       
   134 }
       
   135 
       
   136 bool RenderButton::canHaveChildren() const
       
   137 {
       
   138     // Input elements can't have children, but button elements can.  We'll
       
   139     // write the code assuming any other button types that might emerge in the future
       
   140     // can also have children.
       
   141     return !node()->hasTagName(inputTag);
       
   142 }
       
   143 
       
   144 void RenderButton::setText(const String& str)
       
   145 {
       
   146     if (str.isEmpty()) {
       
   147         if (m_buttonText) {
       
   148             m_buttonText->destroy();
       
   149             m_buttonText = 0;
       
   150         }
       
   151     } else {
       
   152         if (m_buttonText)
       
   153             m_buttonText->setText(str.impl());
       
   154         else {
       
   155             m_buttonText = new (renderArena()) RenderTextFragment(document(), str.impl());
       
   156             m_buttonText->setStyle(style());
       
   157             addChild(m_buttonText);
       
   158         }
       
   159     }
       
   160 }
       
   161 
       
   162 String RenderButton::text() const
       
   163 {
       
   164     return m_buttonText ? m_buttonText->text() : 0;
       
   165 }
       
   166 
       
   167 void RenderButton::updateBeforeAfterContent(PseudoId type)
       
   168 {
       
   169     if (m_inner)
       
   170         m_inner->children()->updateBeforeAfterContent(m_inner, type, this);
       
   171     else
       
   172         children()->updateBeforeAfterContent(this, type);
       
   173 }
       
   174 
       
   175 IntRect RenderButton::controlClipRect(int tx, int ty) const
       
   176 {
       
   177     // Clip to the padding box to at least give content the extra padding space.
       
   178     return IntRect(tx + borderLeft(), ty + borderTop(), width() - borderLeft() - borderRight(), height() - borderTop() - borderBottom());
       
   179 }
       
   180 
       
   181 void RenderButton::timerFired(Timer<RenderButton>*)
       
   182 {
       
   183     // FIXME Bug 25110: Ideally we would stop our timer when our Document
       
   184     // enters the page cache. But we currently have no way of being notified
       
   185     // when that happens, so we'll just ignore the timer firing as long as
       
   186     // we're in the cache.
       
   187     if (document()->inPageCache())
       
   188         return;
       
   189 
       
   190     repaint();
       
   191 }
       
   192 
       
   193 } // namespace WebCore