+2006-09-19 Adam Roben <aroben@apple.com>
+
+ Reviewed by Adele.
+
+ Fixes http://bugzilla.opendarwin.org/show_bug.cgi?id=10824
+ "no file selected" placeholder text missing from file upload control
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * rendering/RenderFileUploadControl.cpp: Remove class
+ RenderFileUploadInnerFileBox, rename defaultFilenameNumChars to
+ defaultWidthNumChars
+ (WebCore::RenderFileUploadControl::RenderFileUploadControl): Call
+ RenderBlock constructor instead of RenderFlexibleBox,
+ (WebCore::RenderFileUploadControl::setStyle): Remove references to
+ m_fileBox.
+ (WebCore::RenderFileUploadControl::valueChanged): Call repaint()
+ instead of updateIconAndFileName() (which has been removed)
+ (WebCore::RenderFileUploadControl::updateFromElement): Remove
+ references to m_fileBox, don't call updateIconAndFilename()
+ (WebCore::RenderFileUploadControl::maxFilenameWidth): Calculate width
+ without using m_fileBox
+ (WebCore::RenderFileUploadControl::createButtonStyle): Remove
+ now-unnecessary display:box rule.
+ (WebCore::RenderFileUploadControl::paintObject): Remove redundant call
+ to paintingDisabled() now that Icon::paint() does it, and add code to
+ paint the filename directly.
+ (WebCore::RenderFileUploadControl::calcMinMaxWidth): Move this method
+ out of RenderFileUploadInnerFileBox and into RenderFileUploadControl
+ * rendering/RenderFileUploadControl.h: Make RenderFileUploadControl a
+ subclass of RenderBlock instead of RenderFlexibleBox, remove
+ updateIconAndFilename() method, remove m_fileBox instance variable.
+
2006-09-19 Eric Seidel <eric@eseidel.com>
Reviewed by hyatt.
const int iconHeight = 16;
const int iconWidth = 16;
const int iconFilenameSpacing = 2;
-const int defaultFilenameNumChars = 22;
+const int defaultWidthNumChars = 34;
using namespace HTMLNames;
-class RenderFileUploadInnerFileBox : public RenderFlexibleBox {
-public:
- RenderFileUploadInnerFileBox(Node*, RenderFileUploadControl*);
-
- virtual void setStyle(RenderStyle*);
- virtual void calcMinMaxWidth();
- virtual void layout();
-
- void setHasIcon(bool hasIcon = true);
-
- void setFilename(const String&);
-
- virtual const char* renderName() const { return "RenderFileUploadInnerFileBox"; }
-
-private:
- RenderFileUploadControl* m_uploadControl;
- RenderText* m_filenameText;
-
- String m_filename;
-};
-
class HTMLFileUploadInnerButtonElement : public HTMLInputElement {
public:
HTMLFileUploadInnerButtonElement(Document*, Node* shadowParent = 0);
private:
Node* m_shadowParent;
};
-
+
RenderFileUploadControl::RenderFileUploadControl(Node* node)
- : RenderFlexibleBox(node)
+ : RenderBlock(node)
, m_button(0)
- , m_fileBox(0)
, m_fileChooser(new FileChooser(document(), this))
{
}
void RenderFileUploadControl::setStyle(RenderStyle* s)
{
- RenderFlexibleBox::setStyle(s);
+ RenderBlock::setStyle(s);
if (m_button)
m_button->renderer()->setStyle(createButtonStyle(s));
- if (m_fileBox) {
- RenderStyle* fileBoxStyle = new (renderArena()) RenderStyle();
- fileBoxStyle->inheritFrom(s);
- m_fileBox->setStyle(fileBoxStyle);
- }
+
setReplaced(isInline());
}
{
static_cast<HTMLInputElement*>(node())->setValueFromRenderer(m_fileChooser->filename());
static_cast<HTMLInputElement*>(node())->onChange();
- updateIconAndFilename();
-}
-
-void RenderFileUploadControl::updateIconAndFilename()
-{
- if (m_fileChooser->icon())
- m_fileBox->setHasIcon();
- else
- m_fileBox->setHasIcon(false);
-
- // FIXME: We don't actually seem to truncate the string when our width is less than the button width and we're in RTL
- m_fileBox->setFilename(m_fileChooser->basenameForWidth(maxFilenameWidth()));
+ repaint();
}
void RenderFileUploadControl::click(bool sendMouseEvents)
addChild(m_button->renderer());
}
-
- if (!m_fileBox) {
- m_fileBox = new (renderArena()) RenderFileUploadInnerFileBox(document(), this);
- RenderStyle* fileBoxStyle = new (renderArena()) RenderStyle();
- fileBoxStyle->inheritFrom(style());
- m_fileBox->setStyle(fileBoxStyle);
- addChild(m_fileBox);
- }
-
- updateIconAndFilename();
}
int RenderFileUploadControl::maxFilenameWidth()
{
- return max(0, m_fileBox->contentWidth());
+ return max(0, contentWidth() - m_button->renderer()->width() - afterButtonSpacing - (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0));
}
RenderStyle* RenderFileUploadControl::createButtonStyle(RenderStyle* parentStyle)
RenderStyle* style = getPseudoStyle(RenderStyle::FILE_UPLOAD_BUTTON);
if (!style)
style = new (renderArena()) RenderStyle();
-
+
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);
-
- // This makes the button block-level so that the flexbox layout works correctly.
- style->setDisplay(BOX);
-
+
return style;
}
void RenderFileUploadControl::paintObject(PaintInfo& i, int tx, int ty)
{
- // Since we draw the file icon without going through the graphics context,
- // we need to make sure painting is not disabled before drawing
- if (i.p->paintingDisabled())
- return;
-
// Push a clip.
if (i.phase == PaintPhaseForeground || i.phase == PaintPhaseChildBlockBackgrounds) {
IntRect clipRect(tx + borderLeft(), ty + borderTop(),
i.p->addClip(clipRect);
}
- if (i.phase == PaintPhaseForeground && m_fileChooser->icon()) {
- // Draw the file icon
- int top = m_fileBox->absoluteBoundingBoxRect().y() + (m_fileBox->absoluteBoundingBoxRect().height() - iconHeight) / 2;
- int left;
+ if (i.phase == PaintPhaseForeground) {
+ const String& displayedFilename = m_fileChooser->basenameForWidth(maxFilenameWidth());
+ TextRun textRun(displayedFilename.characters(), displayedFilename.length());
+
+ // Determine where the filename should be placed
+ int contentLeft = tx + borderLeft() + paddingLeft();
+ int buttonAndIconWidth = m_button->renderer()->width() + afterButtonSpacing + (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0);
+ int textX;
if (style()->direction() == LTR)
- left = m_fileBox->absoluteBoundingBoxRect().x() + afterButtonSpacing;
+ textX = contentLeft + buttonAndIconWidth;
else
- left = m_fileBox->absoluteBoundingBoxRect().right() - afterButtonSpacing - iconWidth;
- m_fileChooser->icon()->paint(i.p, IntRect(left, top, iconWidth, iconHeight));
+ textX = contentLeft + contentWidth() - buttonAndIconWidth;
+ // We want to match the button's baseline
+ RenderButton* buttonRenderer = static_cast<RenderButton*>(m_button->renderer());
+ int textY = buttonRenderer->absoluteBoundingBoxRect().y() + buttonRenderer->marginTop() + buttonRenderer->borderTop() + buttonRenderer->paddingTop() + buttonRenderer->baselinePosition(true, false);
+
+ i.p->setFont(style()->font());
+ i.p->setPen(style()->color());
+
+ // Draw the filename
+ i.p->drawText(textRun, IntPoint(textX, textY));
+
+ if (m_fileChooser->icon()) {
+ // Determine where the icon should be placed
+ int iconY = ty + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2;
+ int iconX;
+ if (style()->direction() == LTR)
+ iconX = contentLeft + m_button->renderer()->width() + afterButtonSpacing;
+ else
+ iconX = contentLeft + contentWidth() - m_button->renderer()->width() - afterButtonSpacing;
+
+ // Draw the file icon
+ m_fileChooser->icon()->paint(i.p, IntRect(iconX, iconY, iconWidth, iconHeight));
+ }
}
// Paint the children.
- RenderFlexibleBox::paintObject(i, tx, ty);
+ RenderBlock::paintObject(i, tx, ty);
// Pop the clip.
if (i.phase == PaintPhaseForeground || i.phase == PaintPhaseChildBlockBackgrounds)
i.p->restore();
}
-RenderFileUploadInnerFileBox::RenderFileUploadInnerFileBox(Node* node, RenderFileUploadControl* uploadControl)
- : RenderFlexibleBox(node)
- , m_uploadControl(uploadControl)
- , m_filenameText(0)
-{
-}
-
-void RenderFileUploadInnerFileBox::setStyle(RenderStyle* s)
-{
- if (m_filenameText)
- m_filenameText->setStyle(s);
-
- s->setBoxFlex(1.0f);
- s->setDisplay(BOX);
- s->setWhiteSpace(NOWRAP);
-
- if (s->direction() == LTR)
- s->setPaddingLeft(Length(afterButtonSpacing, Fixed));
- else
- s->setPaddingRight(Length(afterButtonSpacing, Fixed));
-
- setReplaced(isInline());
-
- RenderFlexibleBox::setStyle(s);
-}
-
-void RenderFileUploadInnerFileBox::layout()
-{
- RenderFlexibleBox::layout();
-
- ASSERT(minMaxKnown());
- // We should know our width now, so display the filename
- m_uploadControl->updateIconAndFilename();
-}
-
-void RenderFileUploadInnerFileBox::setHasIcon(bool hasIcon)
-{
- int padding = afterButtonSpacing;
-
- if (hasIcon)
- padding += iconWidth + iconFilenameSpacing;
-
- if (style()->direction() == LTR)
- style()->setPaddingLeft(Length(padding, Fixed));
- else
- style()->setPaddingRight(Length(padding, Fixed));
-}
-
-void RenderFileUploadInnerFileBox::setFilename(const String& filename)
-{
- if (!m_filenameText) {
- m_filenameText = new (renderArena()) RenderText(document(), String("").impl());
- m_filenameText->setStyle(style());
- addChild(m_filenameText);
- }
-
- if (filename != m_filename) {
- m_filenameText->setText(filename.impl());
- m_filename = filename;
- m_uploadControl->node()->setChanged();
- }
-}
-
-void RenderFileUploadInnerFileBox::calcMinMaxWidth()
+void RenderFileUploadControl::calcMinMaxWidth()
{
m_minWidth = 0;
m_maxWidth = 0;
// (using "0" as the nominal character).
const UChar ch = '0';
float charWidth = style()->font().floatWidth(TextRun(&ch, 1), TextStyle(0, 0, 0, false, false, false));
- m_maxWidth = (int)ceilf(charWidth * defaultFilenameNumChars);
+ m_maxWidth = (int)ceilf(charWidth * defaultWidthNumChars);
}
if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
#ifndef RenderFileUploadControl_H
#define RenderFileUploadControl_H
-#include "RenderFlexibleBox.h"
+#include "RenderBlock.h"
#include "FileChooser.h"
#include "HTMLInputElement.h"
namespace WebCore {
class HTMLFileUploadInnerButtonElement;
-class RenderFileUploadInnerFileBox;
+//class RenderFileUploadInnerFileBlock;
// RenderFileUploadControls contain a RenderButton (for opening the file chooser), and
-// a RenderFileUploadInnerFileBox (which contains a RenderText for the filename and sufficient padding to draw a file icon).
-// The RenderButton has an HTMLFileUploadInnerButtonElement shadow node associated with it to receive click/hover events.
+// sufficient space to draw a file icon and filename. The RenderButton has an
+// HTMLFileUploadInnerButtonElement shadow node associated with it to receive click/hover events.
-class RenderFileUploadControl : public RenderFlexibleBox {
+class RenderFileUploadControl : public RenderBlock {
public:
RenderFileUploadControl(Node*);
~RenderFileUploadControl();
virtual void setStyle(RenderStyle*);
virtual void updateFromElement();
+ virtual void calcMinMaxWidth();
virtual void paintObject(PaintInfo&, int tx, int ty);
virtual void click(bool sendMouseEvents);
void valueChanged();
- void updateIconAndFilename();
virtual const char* renderName() const { return "RenderFileUploadControl"; }
RenderStyle* createButtonStyle(RenderStyle* parentStyle = 0);
RefPtr<HTMLFileUploadInnerButtonElement> m_button;
- RenderFileUploadInnerFileBox* m_fileBox;
FileChooser* m_fileChooser;
};