nsGfxButtonControlFrame.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsGfxButtonControlFrame.h"
  6. #include "nsIFormControl.h"
  7. #include "nsGkAtoms.h"
  8. #include "mozilla/StyleSetHandle.h"
  9. #include "mozilla/StyleSetHandleInlines.h"
  10. #include "nsContentUtils.h"
  11. // MouseEvent suppression in PP
  12. #include "nsContentList.h"
  13. #include "nsIDOMHTMLInputElement.h"
  14. #include "nsTextNode.h"
  15. using namespace mozilla;
  16. nsGfxButtonControlFrame::nsGfxButtonControlFrame(nsStyleContext* aContext):
  17. nsHTMLButtonControlFrame(aContext)
  18. {
  19. }
  20. nsContainerFrame*
  21. NS_NewGfxButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
  22. {
  23. return new (aPresShell) nsGfxButtonControlFrame(aContext);
  24. }
  25. NS_IMPL_FRAMEARENA_HELPERS(nsGfxButtonControlFrame)
  26. void nsGfxButtonControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
  27. {
  28. nsContentUtils::DestroyAnonymousContent(&mTextContent);
  29. nsHTMLButtonControlFrame::DestroyFrom(aDestructRoot);
  30. }
  31. nsIAtom*
  32. nsGfxButtonControlFrame::GetType() const
  33. {
  34. return nsGkAtoms::gfxButtonControlFrame;
  35. }
  36. #ifdef DEBUG_FRAME_DUMP
  37. nsresult
  38. nsGfxButtonControlFrame::GetFrameName(nsAString& aResult) const
  39. {
  40. return MakeFrameName(NS_LITERAL_STRING("ButtonControl"), aResult);
  41. }
  42. #endif
  43. // Create the text content used as label for the button.
  44. // The frame will be generated by the frame constructor.
  45. nsresult
  46. nsGfxButtonControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
  47. {
  48. nsXPIDLString label;
  49. GetLabel(label);
  50. // Add a child text content node for the label
  51. mTextContent = new nsTextNode(mContent->NodeInfo()->NodeInfoManager());
  52. // set the value of the text node and add it to the child list
  53. mTextContent->SetText(label, false);
  54. aElements.AppendElement(mTextContent);
  55. return NS_OK;
  56. }
  57. void
  58. nsGfxButtonControlFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
  59. uint32_t aFilter)
  60. {
  61. if (mTextContent) {
  62. aElements.AppendElement(mTextContent);
  63. }
  64. }
  65. NS_QUERYFRAME_HEAD(nsGfxButtonControlFrame)
  66. NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
  67. NS_QUERYFRAME_TAIL_INHERITING(nsHTMLButtonControlFrame)
  68. // Initially we hardcoded the default strings here.
  69. // Next, we used html.css to store the default label for various types
  70. // of buttons. (nsGfxButtonControlFrame::DoNavQuirksReflow rev 1.20)
  71. // However, since html.css is not internationalized, we now grab the default
  72. // label from a string bundle as is done for all other UI strings.
  73. // See bug 16999 for further details.
  74. nsresult
  75. nsGfxButtonControlFrame::GetDefaultLabel(nsXPIDLString& aString) const
  76. {
  77. nsCOMPtr<nsIFormControl> form = do_QueryInterface(mContent);
  78. NS_ENSURE_TRUE(form, NS_ERROR_UNEXPECTED);
  79. int32_t type = form->GetType();
  80. const char *prop;
  81. if (type == NS_FORM_INPUT_RESET) {
  82. prop = "Reset";
  83. }
  84. else if (type == NS_FORM_INPUT_SUBMIT) {
  85. prop = "Submit";
  86. }
  87. else {
  88. aString.Truncate();
  89. return NS_OK;
  90. }
  91. return nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
  92. prop, aString);
  93. }
  94. nsresult
  95. nsGfxButtonControlFrame::GetLabel(nsXPIDLString& aLabel)
  96. {
  97. // Get the text from the "value" property on our content if there is
  98. // one; otherwise set it to a default value (localized).
  99. nsresult rv;
  100. nsCOMPtr<nsIDOMHTMLInputElement> elt = do_QueryInterface(mContent);
  101. if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::value) && elt) {
  102. rv = elt->GetValue(aLabel);
  103. } else {
  104. // Generate localized label.
  105. // We can't make any assumption as to what the default would be
  106. // because the value is localized for non-english platforms, thus
  107. // it might not be the string "Reset", "Submit Query", or "Browse..."
  108. rv = GetDefaultLabel(aLabel);
  109. }
  110. NS_ENSURE_SUCCESS(rv, rv);
  111. // Compress whitespace out of label if needed.
  112. if (!StyleText()->WhiteSpaceIsSignificant()) {
  113. aLabel.CompressWhitespace();
  114. } else if (aLabel.Length() > 2 && aLabel.First() == ' ' &&
  115. aLabel.CharAt(aLabel.Length() - 1) == ' ') {
  116. // This is a bit of a hack. The reason this is here is as follows: we now
  117. // have default padding on our buttons to make them non-ugly.
  118. // Unfortunately, IE-windows does not have such padding, so people will
  119. // stick values like " ok " (with the spaces) in the buttons in an attempt
  120. // to make them look decent. Unfortunately, if they do this the button
  121. // looks way too big in Mozilla. Worse yet, if they do this _and_ set a
  122. // fixed width for the button we run into trouble because our focus-rect
  123. // border/padding and outer border take up 10px of the horizontal button
  124. // space or so; the result is that the text is misaligned, even with the
  125. // recentering we do in nsHTMLButtonControlFrame::Reflow. So to solve
  126. // this, even if the whitespace is significant, single leading and trailing
  127. // _spaces_ (and not other whitespace) are removed. The proper solution,
  128. // of course, is to not have the focus rect painting taking up 6px of
  129. // horizontal space. We should do that instead (via XBL form controls or
  130. // changing the renderer) and remove this.
  131. aLabel.Cut(0, 1);
  132. aLabel.Truncate(aLabel.Length() - 1);
  133. }
  134. return NS_OK;
  135. }
  136. nsresult
  137. nsGfxButtonControlFrame::AttributeChanged(int32_t aNameSpaceID,
  138. nsIAtom* aAttribute,
  139. int32_t aModType)
  140. {
  141. nsresult rv = NS_OK;
  142. // If the value attribute is set, update the text of the label
  143. if (nsGkAtoms::value == aAttribute) {
  144. if (mTextContent && mContent) {
  145. nsXPIDLString label;
  146. rv = GetLabel(label);
  147. NS_ENSURE_SUCCESS(rv, rv);
  148. mTextContent->SetText(label, true);
  149. } else {
  150. rv = NS_ERROR_UNEXPECTED;
  151. }
  152. // defer to HTMLButtonControlFrame
  153. } else {
  154. rv = nsHTMLButtonControlFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
  155. }
  156. return rv;
  157. }
  158. bool
  159. nsGfxButtonControlFrame::IsLeaf() const
  160. {
  161. return true;
  162. }
  163. nsContainerFrame*
  164. nsGfxButtonControlFrame::GetContentInsertionFrame()
  165. {
  166. return this;
  167. }
  168. nsresult
  169. nsGfxButtonControlFrame::HandleEvent(nsPresContext* aPresContext,
  170. WidgetGUIEvent* aEvent,
  171. nsEventStatus* aEventStatus)
  172. {
  173. // Override the HandleEvent to prevent the nsFrame::HandleEvent
  174. // from being called. The nsFrame::HandleEvent causes the button label
  175. // to be selected (Drawn with an XOR rectangle over the label)
  176. // do we have user-input style?
  177. const nsStyleUserInterface* uiStyle = StyleUserInterface();
  178. if (uiStyle->mUserInput == StyleUserInput::None ||
  179. uiStyle->mUserInput == StyleUserInput::Disabled) {
  180. return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
  181. }
  182. return NS_OK;
  183. }