/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ButtonControlFrame.h" #include "mozilla/PresShell.h" #include "mozilla/dom/HTMLInputElement.h" #include "nsContentUtils.h" #include "nsIFormControl.h" #include "nsTextNode.h" using namespace mozilla; namespace mozilla { /* A frame for &) override; void AppendAnonymousContentTo(nsTArray&, uint32_t aFilter) override; protected: nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, AttrModType aModType) override; void GetDefaultLabel(nsAString&) const; void GetLabel(nsAString& aLabel); void UpdateLabel(); RefPtr mTextContent; }; NS_IMPL_FRAMEARENA_HELPERS(InputButtonControlFrame); void InputButtonControlFrame::Destroy(DestroyContext& aContext) { aContext.AddAnonymousContent(mTextContent.forget()); ButtonControlFrame::Destroy(aContext); } // Create the text content used as label for the button. // The frame will be generated by the frame constructor. nsresult InputButtonControlFrame::CreateAnonymousContent( nsTArray& aElements) { nsAutoString label; GetLabel(label); // Add a child text content node for the label mTextContent = new (mContent->NodeInfo()->NodeInfoManager()) nsTextNode(mContent->NodeInfo()->NodeInfoManager()); // set the value of the text node and add it to the child list mTextContent->SetText(label, false); aElements.AppendElement(mTextContent); return NS_OK; } void InputButtonControlFrame::AppendAnonymousContentTo( nsTArray& aElements, uint32_t aFilter) { if (mTextContent) { aElements.AppendElement(mTextContent); } } // Initially we hardcoded the default strings here. // Next, we used html.css to store the default label for various types // of buttons. (nsGfxButtonControlFrame::DoNavQuirksReflow rev 1.20) // However, since html.css is not internationalized, we now grab the default // label from a string bundle as is done for all other UI strings. // See bug 16999 for further details. void InputButtonControlFrame::GetDefaultLabel(nsAString& aLabel) const { const auto* form = nsIFormControl::FromNode(mContent); MOZ_ASSERT(form); auto type = form->ControlType(); nsCString prop; if (type == FormControlType::InputReset) { prop.AssignLiteral("Reset"); } else if (type == FormControlType::InputSubmit) { prop.AssignLiteral("Submit"); } else { aLabel.Truncate(); return; } if (NS_FAILED(nsContentUtils::GetMaybeLocalizedString( nsContentUtils::eFORMS_PROPERTIES, prop.get(), mContent->OwnerDoc(), aLabel))) { // Use the non-localized version. CopyUTF8toUTF16(prop, aLabel); } } void InputButtonControlFrame::GetLabel(nsAString& aLabel) { // Get the text from the "value" property on our content if there is // one; otherwise set it to a default value (localized). auto* elt = dom::HTMLInputElement::FromNode(mContent); if (elt && elt->HasAttr(nsGkAtoms::value)) { elt->GetValue(aLabel, dom::CallerType::System); } else { // Generate localized label. // We can't make any assumption as to what the default would be // because the value is localized for non-english platforms, thus // it might not be the string "Reset", "Submit Query", or "Browse..." GetDefaultLabel(aLabel); } // Compress whitespace out of label if needed. if (!StyleText()->WhiteSpaceIsSignificant()) { aLabel.CompressWhitespace(); } else if (aLabel.Length() > 2 && aLabel.First() == ' ' && aLabel.CharAt(aLabel.Length() - 1) == ' ') { // This is a bit of a hack. The reason this is here is as follows: we now // have default padding on our buttons to make them non-ugly. // Unfortunately, IE-windows does not have such padding, so people will // stick values like " ok " (with the spaces) in the buttons in an attempt // to make them look decent. Unfortunately, if they do this the button // looks way too big in Mozilla. Worse yet, if they do this _and_ set a // fixed width for the button we run into trouble because our focus-rect // border/padding and outer border take up 10px of the horizontal button // space or so; the result is that the text is misaligned. So to solve // this, even if the whitespace is significant, single leading and trailing // _spaces_ (and not other whitespace) are removed. The proper solution, // of course, is to not have the focus rect painting taking up 6px of // horizontal space. We should do that instead (changing the renderer) and // remove this. // // TODO(emilio): We should be able to remove this now, we no longer have // inner focus rects. aLabel.Cut(0, 1); aLabel.Truncate(aLabel.Length() - 1); } } void InputButtonControlFrame::UpdateLabel() { if (!mTextContent) { return; } nsAutoString label; GetLabel(label); mTextContent->SetText(label, true); } nsresult InputButtonControlFrame::AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, AttrModType aModType) { // If the value attribute is set, update the text of the label if (nsGkAtoms::value == aAttribute) { UpdateLabel(); } return nsBlockFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType); } } // namespace mozilla nsIFrame* NS_NewInputButtonControlFrame(PresShell* aPresShell, ComputedStyle* aStyle) { return new (aPresShell) InputButtonControlFrame(aStyle, aPresShell->GetPresContext()); }