Commit d50bc756 authored by dglazkov@chromium.org's avatar dglazkov@chromium.org

2011-06-03 Dimitri Glazkov <dglazkov@chromium.org>

        Reviewed by Darin Adler.

        Convert file <input> to use the new shadow DOM model
        https://bugs.webkit.org/show_bug.cgi?id=59005

        Refactoring, covered by existing tests.

        * css/CSSSelector.cpp:
        (WebCore::CSSSelector::pseudoId): Removed FILE_UPLOAD_BUTTON pseudoId and all references to it.
        (WebCore::nameToPseudoTypeMap): Ditto.
        (WebCore::CSSSelector::extractPseudoType): Ditto.
        * css/CSSSelector.h: Ditto.
        * css/html.css:
        (input[type="button"], input[type="submit"], input[type="reset"]): Moved -webkit-file-upload-button to its own rule.
        (input[type="file"]::-webkit-file-upload-button): Added and moved all previously hard-coded properties there.
        * html/FileInputType.cpp:
        (WebCore::UploadButtonElement::create): Added.
        (WebCore::UploadButtonElement::UploadButtonElement): Added.
        (WebCore::UploadButtonElement::shadowPseudoId): Added.
        (WebCore::FileInputType::createShadowSubtree): Added.
        * html/FileInputType.h: Added createShadowSubtree decl.
        * page/DragController.cpp:
        (WebCore::asFileInput): Changed the logic to use new shadow DOM.
        * rendering/RenderFileUploadControl.cpp: Removed UploadButton class.
        (WebCore::RenderFileUploadControl::~RenderFileUploadControl): Removed initializer for m_button.
        (WebCore::RenderFileUploadControl::updateFromElement): Removed attachment logic that's no longer necessary.
        (WebCore::nodeWidth): Added a helper.
        (WebCore::RenderFileUploadControl::maxFilenameWidth): Changed to use uploadButton and nodeWidth.
        (WebCore::RenderFileUploadControl::paintObject): Ditto.
        (WebCore::RenderFileUploadControl::uploadButton): Added a helper to retrieve the button.
        (WebCore::RenderFileUploadControl::buttonValue): Changed to use uploadButton.
        * rendering/RenderFileUploadControl.h: Changed decls.
        * rendering/style/RenderStyleConstants.h: Removed FILE_UPLOAD_BUTTON decls.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@88115 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 937a9a28
2011-06-03 Dimitri Glazkov <dglazkov@chromium.org>
Reviewed by Darin Adler.
Convert file <input> to use the new shadow DOM model
https://bugs.webkit.org/show_bug.cgi?id=59005
Refactoring, covered by existing tests.
* css/CSSSelector.cpp:
(WebCore::CSSSelector::pseudoId): Removed FILE_UPLOAD_BUTTON pseudoId and all references to it.
(WebCore::nameToPseudoTypeMap): Ditto.
(WebCore::CSSSelector::extractPseudoType): Ditto.
* css/CSSSelector.h: Ditto.
* css/html.css:
(input[type="button"], input[type="submit"], input[type="reset"]): Moved -webkit-file-upload-button to its own rule.
(input[type="file"]::-webkit-file-upload-button): Added and moved all previously hard-coded properties there.
* html/FileInputType.cpp:
(WebCore::UploadButtonElement::create): Added.
(WebCore::UploadButtonElement::UploadButtonElement): Added.
(WebCore::UploadButtonElement::shadowPseudoId): Added.
(WebCore::FileInputType::createShadowSubtree): Added.
* html/FileInputType.h: Added createShadowSubtree decl.
* page/DragController.cpp:
(WebCore::asFileInput): Changed the logic to use new shadow DOM.
* rendering/RenderFileUploadControl.cpp: Removed UploadButton class.
(WebCore::RenderFileUploadControl::~RenderFileUploadControl): Removed initializer for m_button.
(WebCore::RenderFileUploadControl::updateFromElement): Removed attachment logic that's no longer necessary.
(WebCore::nodeWidth): Added a helper.
(WebCore::RenderFileUploadControl::maxFilenameWidth): Changed to use uploadButton and nodeWidth.
(WebCore::RenderFileUploadControl::paintObject): Ditto.
(WebCore::RenderFileUploadControl::uploadButton): Added a helper to retrieve the button.
(WebCore::RenderFileUploadControl::buttonValue): Changed to use uploadButton.
* rendering/RenderFileUploadControl.h: Changed decls.
* rendering/style/RenderStyleConstants.h: Removed FILE_UPLOAD_BUTTON decls.
2011-06-04 Alexey Proskuryakov <ap@apple.com>
Reviewed by Darin Adler.
......@@ -126,8 +126,6 @@ PseudoId CSSSelector::pseudoId(PseudoType type)
return BEFORE;
case PseudoAfter:
return AFTER;
case PseudoFileUploadButton:
return FILE_UPLOAD_BUTTON;
case PseudoInputPlaceholder:
return INPUT_PLACEHOLDER;
case PseudoScrollbar:
......@@ -233,7 +231,6 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap(
DEFINE_STATIC_LOCAL(AtomicString, autofill, ("-webkit-autofill"));
DEFINE_STATIC_LOCAL(AtomicString, before, ("before"));
DEFINE_STATIC_LOCAL(AtomicString, checked, ("checked"));
DEFINE_STATIC_LOCAL(AtomicString, fileUploadButton, ("-webkit-file-upload-button"));
DEFINE_STATIC_LOCAL(AtomicString, defaultString, ("default"));
DEFINE_STATIC_LOCAL(AtomicString, disabled, ("disabled"));
DEFINE_STATIC_LOCAL(AtomicString, readOnly, ("read-only"));
......@@ -314,7 +311,6 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap(
nameToPseudoType->set(autofill.impl(), CSSSelector::PseudoAutofill);
nameToPseudoType->set(before.impl(), CSSSelector::PseudoBefore);
nameToPseudoType->set(checked.impl(), CSSSelector::PseudoChecked);
nameToPseudoType->set(fileUploadButton.impl(), CSSSelector::PseudoFileUploadButton);
nameToPseudoType->set(defaultString.impl(), CSSSelector::PseudoDefault);
nameToPseudoType->set(disabled.impl(), CSSSelector::PseudoDisabled);
nameToPseudoType->set(readOnly.impl(), CSSSelector::PseudoReadOnly);
......@@ -413,7 +409,6 @@ void CSSSelector::extractPseudoType() const
case PseudoFirstLetter:
case PseudoFirstLine:
compat = true;
case PseudoFileUploadButton:
case PseudoInputListButton:
case PseudoInputPlaceholder:
case PseudoResizer:
......
......@@ -172,7 +172,6 @@ namespace WebCore {
PseudoSingleButton,
PseudoNoButton,
PseudoSelection,
PseudoFileUploadButton,
PseudoInputListButton,
PseudoLeftPage,
PseudoRightPage,
......
......@@ -517,11 +517,17 @@ input[type="radio"], input[type="checkbox"] {
border: initial;
}
input[type="button"], input[type="submit"], input[type="reset"], input[type="file"]::-webkit-file-upload-button {
input[type="button"], input[type="submit"], input[type="reset"] {
-webkit-appearance: push-button;
white-space: pre
}
input[type="file"]::-webkit-file-upload-button {
-webkit-appearance: push-button;
white-space: nowrap;
margin: 0;
}
input[type="button"], input[type="submit"], input[type="reset"], input[type="file"]::-webkit-file-upload-button, button {
-webkit-box-align: center;
text-align: center;
......
......@@ -31,6 +31,7 @@
#include "HTMLNames.h"
#include "LocalizedStrings.h"
#include "RenderFileUploadControl.h"
#include "ShadowRoot.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/text/WTFString.h>
......@@ -38,6 +39,36 @@ namespace WebCore {
using namespace HTMLNames;
class UploadButtonElement : public HTMLInputElement {
public:
static PassRefPtr<UploadButtonElement> create(Document*);
private:
UploadButtonElement(Document*);
virtual const AtomicString& shadowPseudoId() const;
};
PassRefPtr<UploadButtonElement> UploadButtonElement::create(Document* document)
{
RefPtr<UploadButtonElement> button = adoptRef(new UploadButtonElement(document));
button->setType("button");
button->setValue(fileButtonChooseFileLabel());
return button.release();
}
UploadButtonElement::UploadButtonElement(Document* document)
: HTMLInputElement(inputTag, document, 0, false)
{
}
const AtomicString& UploadButtonElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, pseudoId, ("-webkit-file-upload-button"));
return pseudoId;
}
inline FileInputType::FileInputType(HTMLInputElement* element)
: BaseButtonInputType(element)
, m_fileList(FileList::create())
......@@ -193,4 +224,10 @@ bool FileInputType::isFileUpload() const
return true;
}
void FileInputType::createShadowSubtree()
{
ExceptionCode ec = 0;
element()->ensureShadowRoot()->appendChild(UploadButtonElement::create(element()->document()), ec);
}
} // namespace WebCore
......@@ -59,6 +59,7 @@ private:
virtual bool storesValueSeparateFromAttribute();
virtual void setFileList(const Vector<String>& paths);
virtual bool isFileUpload() const;
virtual void createShadowSubtree();
RefPtr<FileList> m_fileList;
};
......
......@@ -253,20 +253,13 @@ static HTMLInputElement* asFileInput(Node* node)
{
ASSERT(node);
// The button for a FILE input is a sub element with no set input type
// In order to get around this problem we assume any non-FILE input element
// is this internal button, and try querying the shadow parent node.
if (node->hasTagName(HTMLNames::inputTag) && node->isShadowRoot() && !static_cast<HTMLInputElement*>(node)->isFileUpload())
node = node->shadowHost();
HTMLInputElement* inputElement = node->toInputElement();
if (!node || !node->hasTagName(HTMLNames::inputTag))
return 0;
HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node);
if (!inputElement->isFileUpload())
return 0;
// If this is a button inside of the a file input, move up to the file input.
if (inputElement && inputElement->isTextButton() && inputElement->treeScope()->isShadowBoundary())
inputElement = inputElement->treeScope()->shadowHost()->toInputElement();
return inputElement;
return inputElement && inputElement->isFileUpload() ? inputElement : 0;
}
// This can return null if an empty document is loaded.
......
......@@ -36,6 +36,7 @@
#include "RenderText.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "ShadowRoot.h"
#include "TextRun.h"
#include <math.h>
......@@ -52,32 +53,6 @@ const int iconFilenameSpacing = 2;
const int defaultWidthNumChars = 34;
const int buttonShadowHeight = 2;
class UploadButton : public HTMLInputElement {
public:
static PassRefPtr<UploadButton> create(HTMLInputElement*);
virtual void detach();
private:
UploadButton(HTMLInputElement*);
};
PassRefPtr<UploadButton> UploadButton::create(HTMLInputElement* shadowParent)
{
return adoptRef(new UploadButton(shadowParent));
}
void UploadButton::detach()
{
HTMLInputElement::detach();
setShadowHost(0);
}
UploadButton::UploadButton(HTMLInputElement* shadowParent)
: HTMLInputElement(inputTag, shadowParent->document(), 0, false)
{
setShadowHost(shadowParent);
}
RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input)
: RenderBlock(input)
{
......@@ -91,18 +66,9 @@ RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input)
RenderFileUploadControl::~RenderFileUploadControl()
{
if (m_button)
m_button->detach();
m_fileChooser->disconnectClient();
}
void RenderFileUploadControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
if (m_button)
m_button->renderer()->setStyle(createButtonStyle(style()));
}
void RenderFileUploadControl::valueChanged()
{
// dispatchFormControlChangeEvent may destroy this renderer
......@@ -177,23 +143,10 @@ void RenderFileUploadControl::updateFromElement()
{
HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node());
ASSERT(inputElement->isFileUpload());
if (!m_button) {
m_button = UploadButton::create(inputElement);
m_button->setType("button");
m_button->setValue(fileButtonChooseFileLabel());
RefPtr<RenderStyle> buttonStyle = createButtonStyle(style());
RenderObject* renderer = m_button->createRenderer(renderArena(), buttonStyle.get());
m_button->setRenderer(renderer);
renderer->setStyle(buttonStyle.release());
renderer->updateFromElement();
m_button->setAttached();
m_button->setInDocument();
addChild(renderer);
}
m_button->setDisabled(!theme()->isEnabled(this));
if (HTMLInputElement* button = uploadButton())
button->setDisabled(!theme()->isEnabled(this));
// This only supports clearing out the files, but that's OK because for
// security reasons that's the only change the DOM is allowed to make.
......@@ -205,26 +158,15 @@ void RenderFileUploadControl::updateFromElement()
}
}
int RenderFileUploadControl::maxFilenameWidth() const
static int nodeWidth(Node* node)
{
return max(0, contentWidth() - m_button->renderBox()->width() - afterButtonSpacing
- (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0));
return node ? node->renderBox()->width() : 0;
}
PassRefPtr<RenderStyle> RenderFileUploadControl::createButtonStyle(const RenderStyle* parentStyle) const
int RenderFileUploadControl::maxFilenameWidth() const
{
RefPtr<RenderStyle> style = getCachedPseudoStyle(FILE_UPLOAD_BUTTON);
if (!style) {
style = RenderStyle::create();
if (parentStyle)
style->inheritFrom(parentStyle);
}
// Button text will wrap on file upload controls with widths smaller than the intrinsic button width
// without this setWhiteSpace.
style->setWhiteSpace(NOWRAP);
return style.release();
return max(0, contentWidth() - nodeWidth(uploadButton()) - afterButtonSpacing
- (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0));
}
void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const IntPoint& paintOffset)
......@@ -251,7 +193,12 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const IntPoint&
// Determine where the filename should be placed
int contentLeft = paintOffset.x() + borderLeft() + paddingLeft();
int buttonAndIconWidth = m_button->renderBox()->width() + afterButtonSpacing
HTMLInputElement* button = uploadButton();
if (!button)
return;
int buttonWidth = nodeWidth(button);
int buttonAndIconWidth = buttonWidth + afterButtonSpacing
+ (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0);
int textX;
if (style()->isLeftToRightDirection())
......@@ -259,7 +206,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const IntPoint&
else
textX = contentLeft + contentWidth() - buttonAndIconWidth - font.width(textRun);
// We want to match the button's baseline
RenderButton* buttonRenderer = toRenderButton(m_button->renderer());
RenderButton* buttonRenderer = toRenderButton(button->renderer());
int textY = buttonRenderer->absoluteBoundingBoxRect().y()
+ buttonRenderer->marginTop() + buttonRenderer->borderTop() + buttonRenderer->paddingTop()
+ buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
......@@ -274,9 +221,9 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const IntPoint&
int iconY = paintOffset.y() + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2;
int iconX;
if (style()->isLeftToRightDirection())
iconX = contentLeft + m_button->renderBox()->width() + afterButtonSpacing;
iconX = contentLeft + buttonWidth + afterButtonSpacing;
else
iconX = contentLeft + contentWidth() - m_button->renderBox()->width() - afterButtonSpacing - iconWidth;
iconX = contentLeft + contentWidth() - buttonWidth - afterButtonSpacing - iconWidth;
// Draw the file icon
m_fileChooser->icon()->paint(paintInfo.context, IntRect(iconX, iconY, iconWidth, iconHeight));
......@@ -333,6 +280,16 @@ VisiblePosition RenderFileUploadControl::positionForPoint(const IntPoint&)
return VisiblePosition();
}
HTMLInputElement* RenderFileUploadControl::uploadButton() const
{
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
ASSERT(input->shadowRoot());
Node* buttonNode = input->shadowRoot()->firstChild();
return buttonNode && buttonNode->isHTMLElement() && buttonNode->hasTagName(inputTag) ? static_cast<HTMLInputElement*>(buttonNode) : 0;
}
void RenderFileUploadControl::receiveDroppedFiles(const Vector<String>& paths)
{
#if ENABLE(DIRECTORY_UPLOAD)
......@@ -350,10 +307,10 @@ void RenderFileUploadControl::receiveDroppedFiles(const Vector<String>& paths)
String RenderFileUploadControl::buttonValue()
{
if (!m_button)
return String();
if (HTMLInputElement* button = uploadButton())
return button->value();
return m_button->value();
return String();
}
String RenderFileUploadControl::fileTextValue() const
......
......@@ -54,8 +54,6 @@ private:
virtual void computePreferredLogicalWidths();
virtual void paintObject(PaintInfo&, const IntPoint&);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
// FileChooserClient methods.
......@@ -75,7 +73,8 @@ private:
virtual VisiblePosition positionForPoint(const IntPoint&);
RefPtr<HTMLInputElement> m_button;
HTMLInputElement* uploadButton() const;
RefPtr<FileChooser> m_fileChooser;
};
......
......@@ -74,13 +74,13 @@ enum PseudoId {
// The order must be NOP ID, public IDs, and then internal IDs.
NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR,
// Internal IDs follow:
FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER,
INPUT_PLACEHOLDER,
SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
INPUT_LIST_BUTTON, VISITED_LINK,
AFTER_LAST_INTERNAL_PSEUDOID,
FULL_SCREEN, FULL_SCREEN_DOCUMENT, FULL_SCREEN_ANCESTOR, ANIMATING_FULL_SCREEN_TRANSITION,
FIRST_PUBLIC_PSEUDOID = FIRST_LINE,
FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON,
FIRST_INTERNAL_PSEUDOID = INPUT_PLACEHOLDER,
PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1)
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment