Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm

Issue 15197003: Fix RTL issues in javascript alerts. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: title too Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h" 5 #include "chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 8
9 #include "base/i18n/rtl.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
11 #import "base/mac/foundation_util.h"
10 #include "base/strings/sys_string_conversions.h" 12 #include "base/strings/sys_string_conversions.h"
11 #import "chrome/browser/chrome_browser_application_mac.h" 13 #import "chrome/browser/chrome_browser_application_mac.h"
12 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" 14 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
13 #include "grit/generated_resources.h" 15 #include "grit/generated_resources.h"
14 #include "grit/ui_strings.h" 16 #include "grit/ui_strings.h"
15 #include "ui/base/l10n/l10n_util_mac.h" 17 #include "ui/base/l10n/l10n_util_mac.h"
16 #include "ui/base/ui_base_types.h" 18 #include "ui/base/ui_base_types.h"
17 19
18 // Helper object that receives the notification that the dialog/sheet is 20 // Helper object that receives the notification that the dialog/sheet is
19 // going away. Is responsible for cleaning itself up. 21 // going away. Is responsible for cleaning itself up.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 137
136 // Show the modal dialog. 138 // Show the modal dialog.
137 alert_ = [helper_ alert]; 139 alert_ = [helper_ alert];
138 NSTextField* field = nil; 140 NSTextField* field = nil;
139 if (text_field) { 141 if (text_field) {
140 field = [helper_ textField]; 142 field = [helper_ textField];
141 [field setStringValue:base::SysUTF16ToNSString( 143 [field setStringValue:base::SysUTF16ToNSString(
142 dialog_->default_prompt_text())]; 144 dialog_->default_prompt_text())];
143 } 145 }
144 [alert_ setDelegate:helper_]; 146 [alert_ setDelegate:helper_];
145 [alert_ setInformativeText:base::SysUTF16ToNSString(dialog_->message_text())]; 147 NSString* informative_text =
146 [alert_ setMessageText:base::SysUTF16ToNSString(dialog_->title())]; 148 base::SysUTF16ToNSString(dialog_->message_text());
149 [alert_ setInformativeText:informative_text];
150 NSString* message_text =
151 base::SysUTF16ToNSString(dialog_->title());
152 [alert_ setMessageText:message_text];
147 [alert_ addButtonWithTitle:default_button]; 153 [alert_ addButtonWithTitle:default_button];
148 if (!one_button) { 154 if (!one_button) {
149 NSButton* other = [alert_ addButtonWithTitle:other_button]; 155 NSButton* other = [alert_ addButtonWithTitle:other_button];
150 [other setKeyEquivalent:@"\e"]; 156 [other setKeyEquivalent:@"\e"];
151 } 157 }
152 if (dialog_->display_suppress_checkbox()) { 158 if (dialog_->display_suppress_checkbox()) {
153 [alert_ setShowsSuppressionButton:YES]; 159 [alert_ setShowsSuppressionButton:YES];
154 NSString* suppression_title = l10n_util::GetNSStringWithFixup( 160 NSString* suppression_title = l10n_util::GetNSStringWithFixup(
155 IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION); 161 IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION);
156 [[alert_ suppressionButton] setTitle:suppression_title]; 162 [[alert_ suppressionButton] setTitle:suppression_title];
157 } 163 }
164
165 // Fix RTL dialogs.
166 //
167 // Mac OS X will always display NSAlert strings as LTR. A workaround is to
168 // manually set the text as attributed strings in the implementing
169 // NSTextFields. This is a basic correctness issue.
170 //
171 // In addition, for readability, the overall alignment is set based on the
172 // directionality of the first strongly-directional character.
173 //
174 // If the dialog fields are selectable then they will scramble when clicked.
175 // Therefore, selectability is disabled.
176 //
177 // See http://crbug.com/70806 for more details.
178
179 bool message_has_rtl =
180 base::i18n::StringContainsStrongRTLChars(dialog_->title());
181 bool informative_has_rtl =
182 base::i18n::StringContainsStrongRTLChars(dialog_->message_text());
183
184 NSTextField* message_text_field = nil;
185 NSTextField* informative_text_field = nil;
186 if (message_has_rtl || informative_has_rtl) {
187 // Force layout of the dialog. NSAlert leaves its dialog alone once laid
188 // out; if this is not done then all the modifications that are to come will
189 // be un-done when the dialog is finally displayed.
190 [alert_ layout];
191
192 // Locate the NSTextFields that implement the text display. These are
193 // actually available as the ivars |_messageField| and |_informationField|
194 // of the NSAlert, but it is safer (and more forward-compatible) to search
195 // for them in the subviews.
196 for (NSView* view in [[[alert_ window] contentView] subviews]) {
197 NSTextField* text_field = base::mac::ObjCCast<NSTextField>(view);
198 if ([[text_field stringValue] isEqualTo:message_text])
199 message_text_field = text_field;
200 else if ([[text_field stringValue] isEqualTo:informative_text])
201 informative_text_field = text_field;
202 }
203
204 // This may fail in future OS releases, but it will still work for shipped
205 // versions of Chromium.
206 DCHECK(message_text_field);
207 DCHECK(informative_text_field);
208 }
209
210 if (message_has_rtl && message_text_field) {
211 scoped_nsobject<NSMutableParagraphStyle> alignment(
212 [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
213 [alignment setAlignment:NSRightTextAlignment];
214
215 NSDictionary* alignment_attributes =
216 @{ NSParagraphStyleAttributeName : alignment };
217 scoped_nsobject<NSAttributedString> attr_string(
218 [[NSAttributedString alloc] initWithString:message_text
219 attributes:alignment_attributes]);
220
221 [message_text_field setAttributedStringValue:attr_string];
222 [message_text_field setSelectable:NO];
223 }
224
225 if (informative_has_rtl && informative_text_field) {
226 base::i18n::TextDirection direction =
227 base::i18n::GetFirstStrongCharacterDirection(dialog_->message_text());
228 scoped_nsobject<NSMutableParagraphStyle> alignment(
229 [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
230 [alignment setAlignment:
231 (direction == base::i18n::RIGHT_TO_LEFT) ? NSRightTextAlignment
232 : NSLeftTextAlignment];
233
234 NSDictionary* alignment_attributes =
235 @{ NSParagraphStyleAttributeName : alignment };
236 scoped_nsobject<NSAttributedString> attr_string(
237 [[NSAttributedString alloc] initWithString:informative_text
238 attributes:alignment_attributes]);
239
240 [informative_text_field setAttributedStringValue:attr_string];
241 [informative_text_field setSelectable:NO];
242 }
158 } 243 }
159 244
160 JavaScriptAppModalDialogCocoa::~JavaScriptAppModalDialogCocoa() { 245 JavaScriptAppModalDialogCocoa::~JavaScriptAppModalDialogCocoa() {
161 } 246 }
162 247
163 //////////////////////////////////////////////////////////////////////////////// 248 ////////////////////////////////////////////////////////////////////////////////
164 // JavaScriptAppModalDialogCocoa, NativeAppModalDialog implementation: 249 // JavaScriptAppModalDialogCocoa, NativeAppModalDialog implementation:
165 250
166 int JavaScriptAppModalDialogCocoa::GetAppModalDialogButtons() const { 251 int JavaScriptAppModalDialogCocoa::GetAppModalDialogButtons() const {
167 // From the above, it is the case that if there is 1 button, it is always the 252 // From the above, it is the case that if there is 1 button, it is always the
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 298
214 //////////////////////////////////////////////////////////////////////////////// 299 ////////////////////////////////////////////////////////////////////////////////
215 // NativeAppModalDialog, public: 300 // NativeAppModalDialog, public:
216 301
217 // static 302 // static
218 NativeAppModalDialog* NativeAppModalDialog::CreateNativeJavaScriptPrompt( 303 NativeAppModalDialog* NativeAppModalDialog::CreateNativeJavaScriptPrompt(
219 JavaScriptAppModalDialog* dialog, 304 JavaScriptAppModalDialog* dialog,
220 gfx::NativeWindow parent_window) { 305 gfx::NativeWindow parent_window) {
221 return new JavaScriptAppModalDialogCocoa(dialog); 306 return new JavaScriptAppModalDialogCocoa(dialog);
222 } 307 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698