DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (cdf352f02ac4)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
/* -*- 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 "nsGfxButtonControlFrame.h"
#include "nsIFormControl.h"
#include "nsGkAtoms.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "nsContentUtils.h"
#include "nsTextNode.h"

using namespace mozilla;

nsGfxButtonControlFrame::nsGfxButtonControlFrame(ComputedStyle* aStyle,
                                                 nsPresContext* aPresContext)
    : nsHTMLButtonControlFrame(aStyle, aPresContext, kClassID) {}

nsContainerFrame* NS_NewGfxButtonControlFrame(PresShell* aPresShell,
                                              ComputedStyle* aStyle) {
  return new (aPresShell)
      nsGfxButtonControlFrame(aStyle, aPresShell->GetPresContext());
}

NS_IMPL_FRAMEARENA_HELPERS(nsGfxButtonControlFrame)

void nsGfxButtonControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
                                          PostDestroyData& aPostDestroyData) {
  aPostDestroyData.AddAnonymousContent(mTextContent.forget());
  nsHTMLButtonControlFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}

#ifdef DEBUG_FRAME_DUMP
nsresult nsGfxButtonControlFrame::GetFrameName(nsAString& aResult) const {
  return MakeFrameName(NS_LITERAL_STRING("ButtonControl"), aResult);
}
#endif

// Create the text content used as label for the button.
// The frame will be generated by the frame constructor.
nsresult nsGfxButtonControlFrame::CreateAnonymousContent(
    nsTArray<ContentInfo>& aElements) {
  nsAutoString label;
  nsresult rv = GetLabel(label);
  NS_ENSURE_SUCCESS(rv, rv);

  // 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 nsGfxButtonControlFrame::AppendAnonymousContentTo(
    nsTArray<nsIContent*>& aElements, uint32_t aFilter) {
  if (mTextContent) {
    aElements.AppendElement(mTextContent);
  }
}

NS_QUERYFRAME_HEAD(nsGfxButtonControlFrame)
  NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsHTMLButtonControlFrame)

// 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.
nsresult nsGfxButtonControlFrame::GetDefaultLabel(nsAString& aString) const {
  nsCOMPtr<nsIFormControl> form = do_QueryInterface(mContent);
  NS_ENSURE_TRUE(form, NS_ERROR_UNEXPECTED);

  int32_t type = form->ControlType();
  const char* prop;
  if (type == NS_FORM_INPUT_RESET) {
    prop = "Reset";
  } else if (type == NS_FORM_INPUT_SUBMIT) {
    prop = "Submit";
  } else {
    aString.Truncate();
    return NS_OK;
  }

  return nsContentUtils::GetMaybeLocalizedString(
      nsContentUtils::eFORMS_PROPERTIES, prop, mContent->OwnerDoc(), aString);
}

nsresult nsGfxButtonControlFrame::GetLabel(nsString& aLabel) {
  // Get the text from the "value" property on our content if there is
  // one; otherwise set it to a default value (localized).
  dom::HTMLInputElement* elt = dom::HTMLInputElement::FromNode(mContent);
  if (elt && elt->HasAttr(kNameSpaceID_None, 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..."
    nsresult rv;
    rv = GetDefaultLabel(aLabel);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // 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, even with the
    // recentering we do in nsHTMLButtonControlFrame::Reflow.  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 (via XBL form controls or
    // changing the renderer) and remove this.
    aLabel.Cut(0, 1);
    aLabel.Truncate(aLabel.Length() - 1);
  }

  return NS_OK;
}

nsresult nsGfxButtonControlFrame::AttributeChanged(int32_t aNameSpaceID,
                                                   nsAtom* aAttribute,
                                                   int32_t aModType) {
  nsresult rv = NS_OK;

  // If the value attribute is set, update the text of the label
  if (nsGkAtoms::value == aAttribute) {
    if (mTextContent && mContent) {
      nsAutoString label;
      rv = GetLabel(label);
      NS_ENSURE_SUCCESS(rv, rv);

      mTextContent->SetText(label, true);
    } else {
      rv = NS_ERROR_UNEXPECTED;
    }

    // defer to HTMLButtonControlFrame
  } else {
    rv = nsHTMLButtonControlFrame::AttributeChanged(aNameSpaceID, aAttribute,
                                                    aModType);
  }
  return rv;
}

nsContainerFrame* nsGfxButtonControlFrame::GetContentInsertionFrame() {
  return this;
}

nsresult nsGfxButtonControlFrame::HandleEvent(nsPresContext* aPresContext,
                                              WidgetGUIEvent* aEvent,
                                              nsEventStatus* aEventStatus) {
  // Override the HandleEvent to prevent the nsFrame::HandleEvent
  // from being called. The nsFrame::HandleEvent causes the button label
  // to be selected (Drawn with an XOR rectangle over the label)

  if (IsContentDisabled()) {
    return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
  }
  return NS_OK;
}