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