tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

InputButtonControlFrame.cpp (6517B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "ButtonControlFrame.h"
      8 #include "mozilla/PresShell.h"
      9 #include "mozilla/dom/HTMLInputElement.h"
     10 #include "nsContentUtils.h"
     11 #include "nsIFormControl.h"
     12 #include "nsTextNode.h"
     13 
     14 using namespace mozilla;
     15 
     16 namespace mozilla {
     17 
     18 /* A frame for <input type={button,reset,submit} */
     19 class InputButtonControlFrame final : public ButtonControlFrame {
     20 public:
     21  InputButtonControlFrame(ComputedStyle* aStyle, nsPresContext* aPc)
     22      : ButtonControlFrame(aStyle, aPc, kClassID) {}
     23 
     24  NS_DECL_FRAMEARENA_HELPERS(InputButtonControlFrame)
     25 
     26 #ifdef DEBUG_FRAME_DUMP
     27  nsresult GetFrameName(nsAString& aResult) const override {
     28    return MakeFrameName(u"InputButtonControl"_ns, aResult);
     29  }
     30 #endif
     31 
     32  void Destroy(DestroyContext&) override;
     33 
     34  // nsIAnonymousContentCreator
     35  nsresult CreateAnonymousContent(nsTArray<ContentInfo>&) override;
     36  void AppendAnonymousContentTo(nsTArray<nsIContent*>&,
     37                                uint32_t aFilter) override;
     38 
     39 protected:
     40  nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
     41                            AttrModType aModType) override;
     42  void GetDefaultLabel(nsAString&) const;
     43  void GetLabel(nsAString& aLabel);
     44  void UpdateLabel();
     45 
     46  RefPtr<nsTextNode> mTextContent;
     47 };
     48 
     49 NS_IMPL_FRAMEARENA_HELPERS(InputButtonControlFrame);
     50 
     51 void InputButtonControlFrame::Destroy(DestroyContext& aContext) {
     52  aContext.AddAnonymousContent(mTextContent.forget());
     53  ButtonControlFrame::Destroy(aContext);
     54 }
     55 
     56 // Create the text content used as label for the button.
     57 // The frame will be generated by the frame constructor.
     58 nsresult InputButtonControlFrame::CreateAnonymousContent(
     59    nsTArray<ContentInfo>& aElements) {
     60  nsAutoString label;
     61  GetLabel(label);
     62 
     63  // Add a child text content node for the label
     64  mTextContent = new (mContent->NodeInfo()->NodeInfoManager())
     65      nsTextNode(mContent->NodeInfo()->NodeInfoManager());
     66 
     67  // set the value of the text node and add it to the child list
     68  mTextContent->SetText(label, false);
     69  aElements.AppendElement(mTextContent);
     70  return NS_OK;
     71 }
     72 
     73 void InputButtonControlFrame::AppendAnonymousContentTo(
     74    nsTArray<nsIContent*>& aElements, uint32_t aFilter) {
     75  if (mTextContent) {
     76    aElements.AppendElement(mTextContent);
     77  }
     78 }
     79 
     80 // Initially we hardcoded the default strings here.
     81 // Next, we used html.css to store the default label for various types
     82 // of buttons. (nsGfxButtonControlFrame::DoNavQuirksReflow rev 1.20)
     83 // However, since html.css is not internationalized, we now grab the default
     84 // label from a string bundle as is done for all other UI strings.
     85 // See bug 16999 for further details.
     86 void InputButtonControlFrame::GetDefaultLabel(nsAString& aLabel) const {
     87  const auto* form = nsIFormControl::FromNode(mContent);
     88  MOZ_ASSERT(form);
     89 
     90  auto type = form->ControlType();
     91  nsCString prop;
     92  if (type == FormControlType::InputReset) {
     93    prop.AssignLiteral("Reset");
     94  } else if (type == FormControlType::InputSubmit) {
     95    prop.AssignLiteral("Submit");
     96  } else {
     97    aLabel.Truncate();
     98    return;
     99  }
    100 
    101  if (NS_FAILED(nsContentUtils::GetMaybeLocalizedString(
    102          nsContentUtils::eFORMS_PROPERTIES, prop.get(), mContent->OwnerDoc(),
    103          aLabel))) {
    104    // Use the non-localized version.
    105    CopyUTF8toUTF16(prop, aLabel);
    106  }
    107 }
    108 
    109 void InputButtonControlFrame::GetLabel(nsAString& aLabel) {
    110  // Get the text from the "value" property on our content if there is
    111  // one; otherwise set it to a default value (localized).
    112  auto* elt = dom::HTMLInputElement::FromNode(mContent);
    113  if (elt && elt->HasAttr(nsGkAtoms::value)) {
    114    elt->GetValue(aLabel, dom::CallerType::System);
    115  } else {
    116    // Generate localized label.
    117    // We can't make any assumption as to what the default would be
    118    // because the value is localized for non-english platforms, thus
    119    // it might not be the string "Reset", "Submit Query", or "Browse..."
    120    GetDefaultLabel(aLabel);
    121  }
    122 
    123  // Compress whitespace out of label if needed.
    124  if (!StyleText()->WhiteSpaceIsSignificant()) {
    125    aLabel.CompressWhitespace();
    126  } else if (aLabel.Length() > 2 && aLabel.First() == ' ' &&
    127             aLabel.CharAt(aLabel.Length() - 1) == ' ') {
    128    // This is a bit of a hack.  The reason this is here is as follows: we now
    129    // have default padding on our buttons to make them non-ugly.
    130    // Unfortunately, IE-windows does not have such padding, so people will
    131    // stick values like " ok " (with the spaces) in the buttons in an attempt
    132    // to make them look decent.  Unfortunately, if they do this the button
    133    // looks way too big in Mozilla.  Worse yet, if they do this _and_ set a
    134    // fixed width for the button we run into trouble because our focus-rect
    135    // border/padding and outer border take up 10px of the horizontal button
    136    // space or so; the result is that the text is misaligned.  So to solve
    137    // this, even if the whitespace is significant, single leading and trailing
    138    // _spaces_ (and not other whitespace) are removed.  The proper solution,
    139    // of course, is to not have the focus rect painting taking up 6px of
    140    // horizontal space. We should do that instead (changing the renderer) and
    141    // remove this.
    142    //
    143    // TODO(emilio): We should be able to remove this now, we no longer have
    144    // inner focus rects.
    145    aLabel.Cut(0, 1);
    146    aLabel.Truncate(aLabel.Length() - 1);
    147  }
    148 }
    149 
    150 void InputButtonControlFrame::UpdateLabel() {
    151  if (!mTextContent) {
    152    return;
    153  }
    154  nsAutoString label;
    155  GetLabel(label);
    156  mTextContent->SetText(label, true);
    157 }
    158 
    159 nsresult InputButtonControlFrame::AttributeChanged(int32_t aNameSpaceID,
    160                                                   nsAtom* aAttribute,
    161                                                   AttrModType aModType) {
    162  // If the value attribute is set, update the text of the label
    163  if (nsGkAtoms::value == aAttribute) {
    164    UpdateLabel();
    165  }
    166  return nsBlockFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
    167 }
    168 
    169 }  // namespace mozilla
    170 
    171 nsIFrame* NS_NewInputButtonControlFrame(PresShell* aPresShell,
    172                                        ComputedStyle* aStyle) {
    173  return new (aPresShell)
    174      InputButtonControlFrame(aStyle, aPresShell->GetPresContext());
    175 }