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