This source file includes following definitions.
- m_canReceiveDroppedFiles
- updateFromElement
- nodeWidth
- maxFilenameWidth
- paintObject
- computeIntrinsicLogicalWidths
- computePreferredLogicalWidths
- positionForPoint
- uploadButton
- buttonValue
- fileTextValue
#include "config.h"
#include "core/rendering/RenderFileUploadControl.h"
#include <math.h>
#include "HTMLNames.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/fileapi/FileList.h"
#include "core/html/HTMLInputElement.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderButton.h"
#include "core/rendering/RenderTheme.h"
#include "platform/fonts/Font.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/text/PlatformLocale.h"
#include "platform/text/TextRun.h"
using namespace std;
namespace WebCore {
using namespace HTMLNames;
const int afterButtonSpacing = 4;
const int defaultWidthNumChars = 34;
const int buttonShadowHeight = 2;
RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input)
: RenderBlockFlow(input)
, m_canReceiveDroppedFiles(input->canReceiveDroppedFiles())
{
}
RenderFileUploadControl::~RenderFileUploadControl()
{
}
void RenderFileUploadControl::updateFromElement()
{
HTMLInputElement* input = toHTMLInputElement(node());
ASSERT(input->isFileUpload());
if (HTMLInputElement* button = uploadButton()) {
bool newCanReceiveDroppedFilesState = input->canReceiveDroppedFiles();
if (m_canReceiveDroppedFiles != newCanReceiveDroppedFilesState) {
m_canReceiveDroppedFiles = newCanReceiveDroppedFilesState;
button->setActive(newCanReceiveDroppedFilesState);
}
}
FileList* files = input->files();
ASSERT(files);
if (files && files->isEmpty())
repaint();
}
static int nodeWidth(Node* node)
{
return (node && node->renderBox()) ? node->renderBox()->pixelSnappedWidth() : 0;
}
int RenderFileUploadControl::maxFilenameWidth() const
{
return max(0, contentBoxRect().pixelSnappedWidth() - nodeWidth(uploadButton()) - afterButtonSpacing);
}
void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
if (style()->visibility() != VISIBLE)
return;
GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
IntRect clipRect = enclosingIntRect(LayoutRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(),
width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight));
if (clipRect.isEmpty())
return;
stateSaver.save();
paintInfo.context->clip(clipRect);
}
if (paintInfo.phase == PaintPhaseForeground) {
const String& displayedFilename = fileTextValue();
const Font& font = style()->font();
TextRun textRun = constructTextRun(this, font, displayedFilename, style(), TextRun::AllowTrailingExpansion, RespectDirection | RespectDirectionOverride);
textRun.disableRoundingHacks();
LayoutUnit contentLeft = paintOffset.x() + borderLeft() + paddingLeft();
HTMLInputElement* button = uploadButton();
if (!button)
return;
LayoutUnit buttonWidth = nodeWidth(button);
LayoutUnit buttonAndSpacingWidth = buttonWidth + afterButtonSpacing;
float textWidth = font.width(textRun);
LayoutUnit textX;
if (style()->isLeftToRightDirection())
textX = contentLeft + buttonAndSpacingWidth;
else
textX = contentLeft + contentWidth() - buttonAndSpacingWidth - textWidth;
LayoutUnit textY = 0;
if (RenderButton* buttonRenderer = toRenderButton(button->renderer()))
textY = paintOffset.y() + borderTop() + paddingTop() + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
else
textY = baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
TextRunPaintInfo textRunPaintInfo(textRun);
textRunPaintInfo.bounds = FloatRect(textX.toFloat(), textY.toFloat() - style()->fontMetrics().ascent(),
textWidth, style()->fontMetrics().height());
paintInfo.context->setFillColor(resolveColor(CSSPropertyColor));
paintInfo.context->drawBidiText(font, textRunPaintInfo, IntPoint(roundToInt(textX), roundToInt(textY)));
}
RenderBlockFlow::paintObject(paintInfo, paintOffset);
}
void RenderFileUploadControl::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
const UChar character = '0';
const String characterAsString = String(&character, 1);
const Font& font = style()->font();
RenderFileUploadControl* renderer = const_cast<RenderFileUploadControl*>(this);
float minDefaultLabelWidth = defaultWidthNumChars * font.width(constructTextRun(renderer, font, characterAsString, style(), TextRun::AllowTrailingExpansion));
const String label = toHTMLInputElement(node())->locale().queryString(blink::WebLocalizedString::FileButtonNoFileSelectedLabel);
float defaultLabelWidth = font.width(constructTextRun(renderer, font, label, style(), TextRun::AllowTrailingExpansion));
if (HTMLInputElement* button = uploadButton())
if (RenderObject* buttonRenderer = button->renderer())
defaultLabelWidth += buttonRenderer->maxPreferredLogicalWidth() + afterButtonSpacing;
maxLogicalWidth = static_cast<int>(ceilf(max(minDefaultLabelWidth, defaultLabelWidth)));
if (!style()->width().isPercent())
minLogicalWidth = maxLogicalWidth;
}
void RenderFileUploadControl::computePreferredLogicalWidths()
{
ASSERT(preferredLogicalWidthsDirty());
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
if (style()->width().isFixed() && style()->width().value() > 0)
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
else
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
}
if (style()->maxWidth().isFixed()) {
m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
}
int toAdd = borderAndPaddingWidth();
m_minPreferredLogicalWidth += toAdd;
m_maxPreferredLogicalWidth += toAdd;
clearPreferredLogicalWidthsDirty();
}
PositionWithAffinity RenderFileUploadControl::positionForPoint(const LayoutPoint&)
{
return PositionWithAffinity();
}
HTMLInputElement* RenderFileUploadControl::uploadButton() const
{
HTMLInputElement* input = toHTMLInputElement(node());
Node* buttonNode = input->userAgentShadowRoot()->firstChild();
return isHTMLInputElement(buttonNode) ? toHTMLInputElement(buttonNode) : 0;
}
String RenderFileUploadControl::buttonValue()
{
if (HTMLInputElement* button = uploadButton())
return button->value();
return String();
}
String RenderFileUploadControl::fileTextValue() const
{
HTMLInputElement* input = toHTMLInputElement(node());
ASSERT(input->files());
return RenderTheme::theme().fileListNameForWidth(input->locale(), input->files(), style()->font(), maxFilenameWidth());
}
}