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