OLD | NEW |
---|---|
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 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h" | 5 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h" |
6 | 6 |
7 #import <CoreText/CoreText.h> | 7 #import <CoreText/CoreText.h> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/ios/ios_util.h" | 10 #include "base/ios/ios_util.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/mac/foundation_util.h" | 12 #include "base/mac/foundation_util.h" |
13 #include "base/mac/objc_property_releaser.h" | 13 |
14 #include "base/mac/scoped_nsobject.h" | |
15 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
16 #include "components/grit/components_scaled_resources.h" | 15 #include "components/grit/components_scaled_resources.h" |
17 #include "components/omnibox/browser/autocomplete_input.h" | 16 #include "components/omnibox/browser/autocomplete_input.h" |
18 #include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h" | 17 #include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h" |
19 #import "ios/chrome/browser/ui/animation_util.h" | 18 #import "ios/chrome/browser/ui/animation_util.h" |
20 #include "ios/chrome/browser/ui/omnibox/omnibox_util.h" | 19 #include "ios/chrome/browser/ui/omnibox/omnibox_util.h" |
21 #import "ios/chrome/browser/ui/reversed_animation.h" | 20 #import "ios/chrome/browser/ui/reversed_animation.h" |
22 #include "ios/chrome/browser/ui/rtl_geometry.h" | 21 #include "ios/chrome/browser/ui/rtl_geometry.h" |
23 #include "ios/chrome/browser/ui/ui_util.h" | 22 #include "ios/chrome/browser/ui/ui_util.h" |
24 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 23 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
25 #import "ios/chrome/common/material_timing.h" | 24 #import "ios/chrome/common/material_timing.h" |
26 #include "ios/chrome/grit/ios_strings.h" | 25 #include "ios/chrome/grit/ios_strings.h" |
27 #include "ios/chrome/grit/ios_theme_resources.h" | 26 #include "ios/chrome/grit/ios_theme_resources.h" |
28 #include "skia/ext/skia_utils_ios.h" | 27 #include "skia/ext/skia_utils_ios.h" |
29 #include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h " | 28 #include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h " |
30 #include "ui/base/l10n/l10n_util_mac.h" | 29 #include "ui/base/l10n/l10n_util_mac.h" |
31 #include "ui/gfx/color_palette.h" | 30 #include "ui/gfx/color_palette.h" |
32 #include "ui/gfx/image/image.h" | 31 #include "ui/gfx/image/image.h" |
33 #import "ui/gfx/ios/NSString+CrStringDrawing.h" | 32 #import "ui/gfx/ios/NSString+CrStringDrawing.h" |
34 #include "ui/gfx/scoped_cg_context_save_gstate_mac.h" | 33 #include "ui/gfx/scoped_cg_context_save_gstate_mac.h" |
35 | 34 |
35 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
36 #error "This file requires ARC support." | |
37 #endif | |
38 | |
36 namespace { | 39 namespace { |
37 const CGFloat kFontSize = 16; | 40 const CGFloat kFontSize = 16; |
38 const CGFloat kEditingRectX = 16; | 41 const CGFloat kEditingRectX = 16; |
39 const CGFloat kEditingRectWidthInset = 10; | 42 const CGFloat kEditingRectWidthInset = 10; |
40 const CGFloat kTextInset = 8; | 43 const CGFloat kTextInset = 8; |
41 const CGFloat kTextInsetWithChip = 3; | 44 const CGFloat kTextInsetWithChip = 3; |
42 const CGFloat kTextInsetNoLeftView = 12; | 45 const CGFloat kTextInsetNoLeftView = 12; |
43 const CGFloat kImageInset = 9; | 46 const CGFloat kImageInset = 9; |
44 const CGFloat kClearButtonRightMarginIphone = 7; | 47 const CGFloat kClearButtonRightMarginIphone = 7; |
45 const CGFloat kClearButtonRightMarginIpad = 12; | 48 const CGFloat kClearButtonRightMarginIpad = 12; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
86 // conversion from NSString to base::string16 if possible. | 89 // conversion from NSString to base::string16 if possible. |
87 - (NSString*)nsDisplayedText; | 90 - (NSString*)nsDisplayedText; |
88 | 91 |
89 @end | 92 @end |
90 | 93 |
91 #pragma mark - | 94 #pragma mark - |
92 #pragma mark OmniboxTextFieldIOS | 95 #pragma mark OmniboxTextFieldIOS |
93 | 96 |
94 @implementation OmniboxTextFieldIOS { | 97 @implementation OmniboxTextFieldIOS { |
95 // Currently selected chip text. Nil if no chip. | 98 // Currently selected chip text. Nil if no chip. |
96 base::scoped_nsobject<NSString> _chipText; | 99 NSString* _chipText; |
97 base::scoped_nsobject<UILabel> _selection; | 100 UILabel* _selection; |
98 base::scoped_nsobject<UILabel> _preEditStaticLabel; | 101 UILabel* _preEditStaticLabel; |
99 NSString* _preEditText; | 102 NSString* _preEditText; |
rohitrao (ping after 24h)
2017/02/24 13:40:32
Should we just remove this and let the storage be
stkhapugin
2017/03/01 17:43:58
Removed every redeclaration that was backed by a p
| |
100 base::scoped_nsobject<UIFont> _font; | 103 UIFont* _font; |
101 base::scoped_nsobject<UIColor> _displayedTextColor; | 104 UIColor* _displayedTextColor; |
102 base::scoped_nsobject<UIColor> _displayedTintColor; | 105 UIColor* _displayedTintColor; |
103 UIColor* _selectedTextBackgroundColor; | 106 UIColor* _selectedTextBackgroundColor; |
rohitrao (ping after 24h)
2017/02/24 13:40:32
Should we remove this and _placeholderTextColor?
stkhapugin
2017/03/01 17:43:58
I can do this in a follow-up CL to reserve this on
| |
104 UIColor* _placeholderTextColor; | 107 UIColor* _placeholderTextColor; |
105 | 108 |
106 // The 'Copy URL' menu item is sometimes shown in the edit menu, so keep it | 109 // The 'Copy URL' menu item is sometimes shown in the edit menu, so keep it |
107 // around to make adding/removing easier. | 110 // around to make adding/removing easier. |
108 base::scoped_nsobject<UIMenuItem> _copyUrlMenuItem; | 111 UIMenuItem* _copyUrlMenuItem; |
109 | |
110 base::mac::ObjCPropertyReleaser _propertyReleaser_OmniboxTextFieldIOS; | |
111 } | 112 } |
112 | 113 |
113 @synthesize leftViewImageId = _leftViewImageId; | 114 @synthesize leftViewImageId = _leftViewImageId; |
114 @synthesize preEditText = _preEditText; | 115 @synthesize preEditText = _preEditText; |
115 @synthesize clearingPreEditText = _clearingPreEditText; | 116 @synthesize clearingPreEditText = _clearingPreEditText; |
116 @synthesize selectedTextBackgroundColor = _selectedTextBackgroundColor; | 117 @synthesize selectedTextBackgroundColor = _selectedTextBackgroundColor; |
117 @synthesize placeholderTextColor = _placeholderTextColor; | 118 @synthesize placeholderTextColor = _placeholderTextColor; |
118 @synthesize incognito = _incognito; | 119 @synthesize incognito = _incognito; |
119 | 120 |
120 // Overload to allow for code-based initialization. | 121 // Overload to allow for code-based initialization. |
121 - (instancetype)initWithFrame:(CGRect)frame { | 122 - (instancetype)initWithFrame:(CGRect)frame { |
122 return [self initWithFrame:frame | 123 return [self initWithFrame:frame |
123 font:[UIFont systemFontOfSize:kFontSize] | 124 font:[UIFont systemFontOfSize:kFontSize] |
124 textColor:TextColor() | 125 textColor:TextColor() |
125 tintColor:nil]; | 126 tintColor:nil]; |
126 } | 127 } |
127 | 128 |
128 - (instancetype)initWithFrame:(CGRect)frame | 129 - (instancetype)initWithFrame:(CGRect)frame |
129 font:(UIFont*)font | 130 font:(UIFont*)font |
130 textColor:(UIColor*)textColor | 131 textColor:(UIColor*)textColor |
131 tintColor:(UIColor*)tintColor { | 132 tintColor:(UIColor*)tintColor { |
132 self = [super initWithFrame:frame]; | 133 self = [super initWithFrame:frame]; |
133 if (self) { | 134 if (self) { |
134 _propertyReleaser_OmniboxTextFieldIOS.Init(self, | 135 _font = font; |
135 [OmniboxTextFieldIOS class]); | 136 _displayedTextColor = textColor; |
136 _font.reset([font retain]); | |
137 _displayedTextColor.reset([textColor retain]); | |
138 if (tintColor) { | 137 if (tintColor) { |
139 [self setTintColor:tintColor]; | 138 [self setTintColor:tintColor]; |
140 _displayedTintColor.reset([tintColor retain]); | 139 _displayedTintColor = tintColor; |
141 } else { | 140 } else { |
142 _displayedTintColor.reset([self.tintColor retain]); | 141 _displayedTintColor = self.tintColor; |
143 } | 142 } |
144 [self setFont:_font]; | 143 [self setFont:_font]; |
145 [self setTextColor:_displayedTextColor]; | 144 [self setTextColor:_displayedTextColor]; |
146 [self setClearButtonMode:UITextFieldViewModeNever]; | 145 [self setClearButtonMode:UITextFieldViewModeNever]; |
147 [self setRightViewMode:UITextFieldViewModeAlways]; | 146 [self setRightViewMode:UITextFieldViewModeAlways]; |
148 [self setAutocorrectionType:UITextAutocorrectionTypeNo]; | 147 [self setAutocorrectionType:UITextAutocorrectionTypeNo]; |
149 [self setAutocapitalizationType:UITextAutocapitalizationTypeNone]; | 148 [self setAutocapitalizationType:UITextAutocapitalizationTypeNone]; |
150 [self setEnablesReturnKeyAutomatically:YES]; | 149 [self setEnablesReturnKeyAutomatically:YES]; |
151 [self setReturnKeyType:UIReturnKeyGo]; | 150 [self setReturnKeyType:UIReturnKeyGo]; |
152 [self setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; | 151 [self setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 } | 203 } |
205 | 204 |
206 // Method called when the users touches the text input. This will accept the | 205 // Method called when the users touches the text input. This will accept the |
207 // autocompleted text. | 206 // autocompleted text. |
208 - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { | 207 - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { |
209 if ([self isPreEditing]) { | 208 if ([self isPreEditing]) { |
210 [self exitPreEditState]; | 209 [self exitPreEditState]; |
211 [super selectAll:nil]; | 210 [super selectAll:nil]; |
212 } | 211 } |
213 | 212 |
214 if (!_selection.get()) { | 213 if (!_selection) { |
215 [super touchesBegan:touches withEvent:event]; | 214 [super touchesBegan:touches withEvent:event]; |
216 return; | 215 return; |
217 } | 216 } |
218 | 217 |
219 // Only consider a single touch. | 218 // Only consider a single touch. |
220 UITouch* touch = [touches anyObject]; | 219 UITouch* touch = [touches anyObject]; |
221 if (!touch) | 220 if (!touch) |
222 return; | 221 return; |
223 | 222 |
224 // Accept selection. | 223 // Accept selection. |
225 base::scoped_nsobject<NSString> newText([[self nsDisplayedText] copy]); | 224 NSString* newText = [[self nsDisplayedText] copy]; |
226 [self clearAutocompleteText]; | 225 [self clearAutocompleteText]; |
227 [self setText:newText]; | 226 [self setText:newText]; |
228 } | 227 } |
229 | 228 |
230 // Gets the bounds of the rect covering the URL. | 229 // Gets the bounds of the rect covering the URL. |
231 - (CGRect)preEditLabelRectForBounds:(CGRect)bounds { | 230 - (CGRect)preEditLabelRectForBounds:(CGRect)bounds { |
232 return [self editingRectForBounds:self.bounds]; | 231 return [self editingRectForBounds:self.bounds]; |
233 } | 232 } |
234 | 233 |
235 // Creates a UILabel based on the current dimension of the text field and | 234 // Creates a UILabel based on the current dimension of the text field and |
236 // displays the URL in the UILabel so it appears properly aligned to the URL. | 235 // displays the URL in the UILabel so it appears properly aligned to the URL. |
237 - (void)enterPreEditState { | 236 - (void)enterPreEditState { |
238 // Empty omnibox should show the insertion point immediately. There is | 237 // Empty omnibox should show the insertion point immediately. There is |
239 // nothing to erase. | 238 // nothing to erase. |
240 if (!self.text.length || UIAccessibilityIsVoiceOverRunning()) | 239 if (!self.text.length || UIAccessibilityIsVoiceOverRunning()) |
241 return; | 240 return; |
242 | 241 |
243 // Remembers the initial text input to compute the diff of what was there | 242 // Remembers the initial text input to compute the diff of what was there |
244 // and what was typed. | 243 // and what was typed. |
245 [self setPreEditText:self.text]; | 244 [self setPreEditText:self.text]; |
246 | 245 |
247 // Adjusts the placement so static URL lines up perfectly with UITextField. | 246 // Adjusts the placement so static URL lines up perfectly with UITextField. |
248 DCHECK(!_preEditStaticLabel.get()); | 247 DCHECK(!_preEditStaticLabel); |
249 CGRect rect = [self preEditLabelRectForBounds:self.bounds]; | 248 CGRect rect = [self preEditLabelRectForBounds:self.bounds]; |
250 _preEditStaticLabel.reset([[UILabel alloc] initWithFrame:rect]); | 249 _preEditStaticLabel = [[UILabel alloc] initWithFrame:rect]; |
251 _preEditStaticLabel.get().backgroundColor = [UIColor clearColor]; | 250 _preEditStaticLabel.backgroundColor = [UIColor clearColor]; |
252 _preEditStaticLabel.get().opaque = YES; | 251 _preEditStaticLabel.opaque = YES; |
253 _preEditStaticLabel.get().font = _font; | 252 _preEditStaticLabel.font = _font; |
254 _preEditStaticLabel.get().textColor = _displayedTextColor; | 253 _preEditStaticLabel.textColor = _displayedTextColor; |
255 _preEditStaticLabel.get().lineBreakMode = NSLineBreakByTruncatingHead; | 254 _preEditStaticLabel.lineBreakMode = NSLineBreakByTruncatingHead; |
256 | 255 |
257 NSDictionary* attributes = | 256 NSDictionary* attributes = |
258 @{NSBackgroundColorAttributeName : [self selectedTextBackgroundColor]}; | 257 @{NSBackgroundColorAttributeName : [self selectedTextBackgroundColor]}; |
259 base::scoped_nsobject<NSAttributedString> preEditString( | 258 NSAttributedString* preEditString = |
260 [[NSAttributedString alloc] initWithString:self.text | 259 [[NSAttributedString alloc] initWithString:self.text |
261 attributes:attributes]); | 260 attributes:attributes]; |
262 [_preEditStaticLabel setAttributedText:preEditString]; | 261 [_preEditStaticLabel setAttributedText:preEditString]; |
263 _preEditStaticLabel.get().textAlignment = [self preEditTextAlignment]; | 262 _preEditStaticLabel.textAlignment = [self preEditTextAlignment]; |
264 [self addSubview:_preEditStaticLabel]; | 263 [self addSubview:_preEditStaticLabel]; |
265 } | 264 } |
266 | 265 |
267 - (NSTextAlignment)bestAlignmentForText:(NSString*)text { | 266 - (NSTextAlignment)bestAlignmentForText:(NSString*)text { |
268 if (text.length) { | 267 if (text.length) { |
269 NSString* lang = CFBridgingRelease(CFStringTokenizerCopyBestStringLanguage( | 268 NSString* lang = CFBridgingRelease(CFStringTokenizerCopyBestStringLanguage( |
270 (CFStringRef)text, CFRangeMake(0, text.length))); | 269 (CFStringRef)text, CFRangeMake(0, text.length))); |
271 | 270 |
272 if ([NSLocale characterDirectionForLanguage:lang] == | 271 if ([NSLocale characterDirectionForLanguage:lang] == |
273 NSLocaleLanguageDirectionRightToLeft) { | 272 NSLocaleLanguageDirectionRightToLeft) { |
274 return NSTextAlignmentRight; | 273 return NSTextAlignmentRight; |
275 } | 274 } |
276 } | 275 } |
277 return NSTextAlignmentLeft; | 276 return NSTextAlignmentLeft; |
278 } | 277 } |
279 | 278 |
280 - (NSTextAlignment)bestTextAlignment { | 279 - (NSTextAlignment)bestTextAlignment { |
281 if (!base::ios::IsRunningOnIOS9OrLater() || [self isFirstResponder]) { | 280 if (!base::ios::IsRunningOnIOS9OrLater() || [self isFirstResponder]) { |
282 return [self bestAlignmentForText:[self text]]; | 281 return [self bestAlignmentForText:[self text]]; |
283 } | 282 } |
284 return NSTextAlignmentNatural; | 283 return NSTextAlignmentNatural; |
285 } | 284 } |
286 | 285 |
287 - (NSTextAlignment)preEditTextAlignment { | 286 - (NSTextAlignment)preEditTextAlignment { |
288 // If the pre-edit text is wider than the omnibox, right-align the text so it | 287 // If the pre-edit text is wider than the omnibox, right-align the text so it |
289 // ends at the same x coord as the blue selection box. | 288 // ends at the same x coord as the blue selection box. |
290 CGSize textSize = | 289 CGSize textSize = |
291 [_preEditStaticLabel.get().text cr_pixelAlignedSizeWithFont:_font]; | 290 [_preEditStaticLabel.text cr_pixelAlignedSizeWithFont:_font]; |
292 BOOL isLTR = [self bestTextAlignment] == NSTextAlignmentLeft; | 291 BOOL isLTR = [self bestTextAlignment] == NSTextAlignmentLeft; |
293 return textSize.width < _preEditStaticLabel.get().frame.size.width | 292 return textSize.width < _preEditStaticLabel.frame.size.width |
294 ? (isLTR ? NSTextAlignmentLeft : NSTextAlignmentRight) | 293 ? (isLTR ? NSTextAlignmentLeft : NSTextAlignmentRight) |
295 : (isLTR ? NSTextAlignmentRight : NSTextAlignmentLeft); | 294 : (isLTR ? NSTextAlignmentRight : NSTextAlignmentLeft); |
296 } | 295 } |
297 | 296 |
298 - (void)layoutSubviews { | 297 - (void)layoutSubviews { |
299 [super layoutSubviews]; | 298 [super layoutSubviews]; |
300 if ([self isPreEditing]) { | 299 if ([self isPreEditing]) { |
301 CGRect rect = [self preEditLabelRectForBounds:self.bounds]; | 300 CGRect rect = [self preEditLabelRectForBounds:self.bounds]; |
302 [_preEditStaticLabel setFrame:rect]; | 301 [_preEditStaticLabel setFrame:rect]; |
303 | 302 |
304 // Update text alignment since the pre-edit label's frame changed. | 303 // Update text alignment since the pre-edit label's frame changed. |
305 _preEditStaticLabel.get().textAlignment = [self preEditTextAlignment]; | 304 _preEditStaticLabel.textAlignment = [self preEditTextAlignment]; |
306 [self hideTextAndCursor]; | 305 [self hideTextAndCursor]; |
307 } else if (!_selection) { | 306 } else if (!_selection) { |
308 [self showTextAndCursor]; | 307 [self showTextAndCursor]; |
309 } | 308 } |
310 } | 309 } |
311 | 310 |
312 // Finishes pre-edit state by removing the UILabel with the URL. | 311 // Finishes pre-edit state by removing the UILabel with the URL. |
313 - (void)exitPreEditState { | 312 - (void)exitPreEditState { |
314 [self setPreEditText:nil]; | 313 [self setPreEditText:nil]; |
315 if (_preEditStaticLabel) { | 314 if (_preEditStaticLabel) { |
316 [_preEditStaticLabel removeFromSuperview]; | 315 [_preEditStaticLabel removeFromSuperview]; |
317 _preEditStaticLabel.reset(nil); | 316 _preEditStaticLabel = nil; |
318 [self showTextAndCursor]; | 317 [self showTextAndCursor]; |
319 } | 318 } |
320 } | 319 } |
321 | 320 |
322 - (UIColor*)displayedTextColor { | 321 - (UIColor*)displayedTextColor { |
323 return _displayedTextColor; | 322 return _displayedTextColor; |
324 } | 323 } |
325 | 324 |
326 // Returns whether we are processing the first touch event on the text field. | 325 // Returns whether we are processing the first touch event on the text field. |
327 - (BOOL)isPreEditing { | 326 - (BOOL)isPreEditing { |
328 return !![self preEditText]; | 327 return !![self preEditText]; |
329 } | 328 } |
330 | 329 |
331 - (void)enableLeftViewButton:(BOOL)isEnabled { | 330 - (void)enableLeftViewButton:(BOOL)isEnabled { |
332 if ([self leftView]) | 331 if ([self leftView]) |
333 [(UIButton*)[self leftView] setEnabled:isEnabled]; | 332 [(UIButton*)[self leftView] setEnabled:isEnabled]; |
334 } | 333 } |
335 | 334 |
336 - (NSString*)nsDisplayedText { | 335 - (NSString*)nsDisplayedText { |
337 if (_selection.get()) | 336 if (_selection) |
338 return [_selection text]; | 337 return [_selection text]; |
339 return [self text]; | 338 return [self text]; |
340 } | 339 } |
341 | 340 |
342 - (base::string16)displayedText { | 341 - (base::string16)displayedText { |
343 return base::SysNSStringToUTF16([self nsDisplayedText]); | 342 return base::SysNSStringToUTF16([self nsDisplayedText]); |
344 } | 343 } |
345 | 344 |
346 - (base::string16)autocompleteText { | 345 - (base::string16)autocompleteText { |
347 DCHECK_LT([[self text] length], [[_selection text] length]) | 346 DCHECK_LT([[self text] length], [[_selection text] length]) |
348 << "[_selection text] and [self text] are out of sync. " | 347 << "[_selection text] and [self text] are out of sync. " |
349 << "Please email justincohen@ and rohitrao@ if you see this."; | 348 << "Please email justincohen@ and rohitrao@ if you see this."; |
350 if (_selection.get() && [[_selection text] length] > [[self text] length]) { | 349 if (_selection && [[_selection text] length] > [[self text] length]) { |
351 return base::SysNSStringToUTF16( | 350 return base::SysNSStringToUTF16( |
352 [[_selection text] substringFromIndex:[[self text] length]]); | 351 [[_selection text] substringFromIndex:[[self text] length]]); |
353 } | 352 } |
354 return base::string16(); | 353 return base::string16(); |
355 } | 354 } |
356 | 355 |
357 - (void)select:(id)sender { | 356 - (void)select:(id)sender { |
358 if ([self isPreEditing]) { | 357 if ([self isPreEditing]) { |
359 [self exitPreEditState]; | 358 [self exitPreEditState]; |
360 } | 359 } |
361 [super select:sender]; | 360 [super select:sender]; |
362 } | 361 } |
363 | 362 |
364 - (void)selectAll:(id)sender { | 363 - (void)selectAll:(id)sender { |
365 if ([self isPreEditing]) { | 364 if ([self isPreEditing]) { |
366 [self exitPreEditState]; | 365 [self exitPreEditState]; |
367 } | 366 } |
368 if (_selection.get()) { | 367 if (_selection) { |
369 base::scoped_nsobject<NSString> newText([[self nsDisplayedText] copy]); | 368 NSString* newText = [[self nsDisplayedText] copy]; |
370 [self clearAutocompleteText]; | 369 [self clearAutocompleteText]; |
371 [self setText:newText]; | 370 [self setText:newText]; |
372 } | 371 } |
373 [super selectAll:sender]; | 372 [super selectAll:sender]; |
374 } | 373 } |
375 | 374 |
376 // Creates the SelectedTextLabel if it doesn't already exist and adds it as a | 375 // Creates the SelectedTextLabel if it doesn't already exist and adds it as a |
377 // subview. | 376 // subview. |
378 - (void)createSelectionViewIfNecessary { | 377 - (void)createSelectionViewIfNecessary { |
379 if (_selection.get()) | 378 if (_selection) |
380 return; | 379 return; |
381 | 380 |
382 _selection.reset([[UILabel alloc] initWithFrame:CGRectZero]); | 381 _selection = [[UILabel alloc] initWithFrame:CGRectZero]; |
383 [_selection setFont:_font]; | 382 [_selection setFont:_font]; |
384 [_selection setTextColor:_displayedTextColor]; | 383 [_selection setTextColor:_displayedTextColor]; |
385 [_selection setOpaque:NO]; | 384 [_selection setOpaque:NO]; |
386 [_selection setBackgroundColor:[UIColor clearColor]]; | 385 [_selection setBackgroundColor:[UIColor clearColor]]; |
387 [self addSubview:_selection]; | 386 [self addSubview:_selection]; |
388 [self hideTextAndCursor]; | 387 [self hideTextAndCursor]; |
389 } | 388 } |
390 | 389 |
391 - (BOOL)isShowingQueryRefinementChip { | 390 - (BOOL)isShowingQueryRefinementChip { |
392 return (_chipText && ([self isFirstResponder] || [self isPreEditing])); | 391 return (_chipText && ([self isFirstResponder] || [self isPreEditing])); |
393 } | 392 } |
394 | 393 |
395 - (void)updateLeftView { | 394 - (void)updateLeftView { |
396 const CGFloat kChipTextTopInset = 3.0; | 395 const CGFloat kChipTextTopInset = 3.0; |
397 const CGFloat kChipTextLeftInset = 3.0; | 396 const CGFloat kChipTextLeftInset = 3.0; |
398 | 397 |
399 UIButton* leftViewButton = (UIButton*)self.leftView; | 398 UIButton* leftViewButton = (UIButton*)self.leftView; |
400 // Only set the chip image if the omnibox is in focus. | 399 // Only set the chip image if the omnibox is in focus. |
401 if ([self isShowingQueryRefinementChip]) { | 400 if ([self isShowingQueryRefinementChip]) { |
402 [leftViewButton setTitle:_chipText forState:UIControlStateNormal]; | 401 [leftViewButton setTitle:_chipText forState:UIControlStateNormal]; |
403 [leftViewButton setImage:nil forState:UIControlStateNormal]; | 402 [leftViewButton setImage:nil forState:UIControlStateNormal]; |
404 [leftViewButton | 403 [leftViewButton |
405 setTitleEdgeInsets:UIEdgeInsetsMake(kChipTextTopInset, | 404 setTitleEdgeInsets:UIEdgeInsetsMake(kChipTextTopInset, |
406 kChipTextLeftInset, 0, 0)]; | 405 kChipTextLeftInset, 0, 0)]; |
407 // For iPhone, the left view is only updated when not in editing mode (i.e. | 406 // For iPhone, the left view is only updated when not in editing mode (i.e. |
408 // the text field is not first responder). | 407 // the text field is not first responder). |
409 } else if (_leftViewImageId && (IsIPadIdiom() || ![self isFirstResponder])) { | 408 } else if (_leftViewImageId && (IsIPadIdiom() || ![self isFirstResponder])) { |
410 UIImage* image = [NativeImage(_leftViewImageId) | 409 UIImage* image = [NativeImage(_leftViewImageId) |
411 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; | 410 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; |
412 UIImageView* imageView = | 411 UIImageView* imageView = [[UIImageView alloc] initWithImage:image]; |
413 [[[UIImageView alloc] initWithImage:image] autorelease]; | |
414 [leftViewButton setImage:imageView.image forState:UIControlStateNormal]; | 412 [leftViewButton setImage:imageView.image forState:UIControlStateNormal]; |
415 [leftViewButton setTitle:nil forState:UIControlStateNormal]; | 413 [leftViewButton setTitle:nil forState:UIControlStateNormal]; |
416 UIColor* tint = [UIColor whiteColor]; | 414 UIColor* tint = [UIColor whiteColor]; |
417 if (!_incognito) { | 415 if (!_incognito) { |
418 switch (_leftViewImageId) { | 416 switch (_leftViewImageId) { |
419 case IDR_IOS_LOCATION_BAR_HTTP: | 417 case IDR_IOS_LOCATION_BAR_HTTP: |
420 tint = [UIColor darkGrayColor]; | 418 tint = [UIColor darkGrayColor]; |
421 break; | 419 break; |
422 case IDR_IOS_OMNIBOX_HTTPS_VALID: | 420 case IDR_IOS_OMNIBOX_HTTPS_VALID: |
423 tint = skia::UIColorFromSkColor(gfx::kGoogleGreen700); | 421 tint = skia::UIColorFromSkColor(gfx::kGoogleGreen700); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
469 // Extract substrings for the permanent text and the autocomplete text. The | 467 // Extract substrings for the permanent text and the autocomplete text. The |
470 // former needs to retain any text attributes from the original string. | 468 // former needs to retain any text attributes from the original string. |
471 NSRange fieldRange = NSMakeRange(0, [text length] - autocompleteLength); | 469 NSRange fieldRange = NSMakeRange(0, [text length] - autocompleteLength); |
472 NSAttributedString* fieldText = | 470 NSAttributedString* fieldText = |
473 [text attributedSubstringFromRange:fieldRange]; | 471 [text attributedSubstringFromRange:fieldRange]; |
474 | 472 |
475 if (autocompleteLength > 0) { | 473 if (autocompleteLength > 0) { |
476 // Creating |autocompleteText| from |[text string]| has the added bonus of | 474 // Creating |autocompleteText| from |[text string]| has the added bonus of |
477 // removing all the previously set attributes. This way the autocomplete | 475 // removing all the previously set attributes. This way the autocomplete |
478 // text doesn't have a highlighted protocol, etc. | 476 // text doesn't have a highlighted protocol, etc. |
479 base::scoped_nsobject<NSMutableAttributedString> autocompleteText( | 477 NSMutableAttributedString* autocompleteText = |
480 [[NSMutableAttributedString alloc] initWithString:[text string]]); | 478 [[NSMutableAttributedString alloc] initWithString:[text string]]; |
481 | 479 |
482 [self createSelectionViewIfNecessary]; | 480 [self createSelectionViewIfNecessary]; |
483 DCHECK(_selection.get()); | 481 DCHECK(_selection); |
484 [autocompleteText | 482 [autocompleteText |
485 addAttribute:NSBackgroundColorAttributeName | 483 addAttribute:NSBackgroundColorAttributeName |
486 value:[self selectedTextBackgroundColor] | 484 value:[self selectedTextBackgroundColor] |
487 range:NSMakeRange([fieldText length], autocompleteLength)]; | 485 range:NSMakeRange([fieldText length], autocompleteLength)]; |
488 [_selection setAttributedText:autocompleteText]; | 486 [_selection setAttributedText:autocompleteText]; |
489 [_selection setTextAlignment:[self bestTextAlignment]]; | 487 [_selection setTextAlignment:[self bestTextAlignment]]; |
490 } else { | 488 } else { |
491 [self clearAutocompleteText]; | 489 [self clearAutocompleteText]; |
492 } | 490 } |
493 | 491 |
(...skipping 12 matching lines...) Expand all Loading... | |
506 - (UIColor*)selectedTextBackgroundColor { | 504 - (UIColor*)selectedTextBackgroundColor { |
507 return _selectedTextBackgroundColor ? _selectedTextBackgroundColor | 505 return _selectedTextBackgroundColor ? _selectedTextBackgroundColor |
508 : [UIColor colorWithRed:204.0 / 255 | 506 : [UIColor colorWithRed:204.0 / 255 |
509 green:221.0 / 255 | 507 green:221.0 / 255 |
510 blue:237.0 / 255 | 508 blue:237.0 / 255 |
511 alpha:1.0]; | 509 alpha:1.0]; |
512 } | 510 } |
513 | 511 |
514 // Ensures that attributedText always uses the proper style attributes. | 512 // Ensures that attributedText always uses the proper style attributes. |
515 - (void)setAttributedText:(NSAttributedString*)attributedText { | 513 - (void)setAttributedText:(NSAttributedString*)attributedText { |
516 base::scoped_nsobject<NSMutableAttributedString> mutableText( | 514 NSMutableAttributedString* mutableText = [attributedText mutableCopy]; |
517 [attributedText mutableCopy]); | |
518 NSRange entireString = NSMakeRange(0, [mutableText length]); | 515 NSRange entireString = NSMakeRange(0, [mutableText length]); |
519 | 516 |
520 // Set the font. | 517 // Set the font. |
521 [mutableText addAttribute:NSFontAttributeName value:_font range:entireString]; | 518 [mutableText addAttribute:NSFontAttributeName value:_font range:entireString]; |
522 | 519 |
523 // When editing, use the default text color for all text. | 520 // When editing, use the default text color for all text. |
524 if (self.editing) { | 521 if (self.editing) { |
525 // Hide the text when the |_selection| label is displayed. | 522 // Hide the text when the |_selection| label is displayed. |
526 UIColor* textColor = | 523 UIColor* textColor = |
527 _selection ? [UIColor clearColor] : _displayedTextColor.get(); | 524 _selection ? [UIColor clearColor] : _displayedTextColor; |
528 [mutableText addAttribute:NSForegroundColorAttributeName | 525 [mutableText addAttribute:NSForegroundColorAttributeName |
529 value:textColor | 526 value:textColor |
530 range:entireString]; | 527 range:entireString]; |
531 } else { | 528 } else { |
532 base::scoped_nsobject<NSMutableParagraphStyle> style( | 529 NSMutableParagraphStyle* style = [[NSMutableParagraphStyle alloc] init]; |
533 [[NSMutableParagraphStyle alloc] init]); | |
534 // URLs have their text direction set to to LTR (avoids RTL characters | 530 // URLs have their text direction set to to LTR (avoids RTL characters |
535 // making the URL render from right to left, as per RFC 3987 Section 4.1). | 531 // making the URL render from right to left, as per RFC 3987 Section 4.1). |
536 [style setBaseWritingDirection:NSWritingDirectionLeftToRight]; | 532 [style setBaseWritingDirection:NSWritingDirectionLeftToRight]; |
537 | 533 |
538 // Set linebreak mode to 'clipping' to ensure the text is never elided. | 534 // Set linebreak mode to 'clipping' to ensure the text is never elided. |
539 // This is a workaround for iOS 6, where it appears that | 535 // This is a workaround for iOS 6, where it appears that |
540 // [self.attributedText size] is not wide enough for the string (e.g. a URL | 536 // [self.attributedText size] is not wide enough for the string (e.g. a URL |
541 // else ending with '.com' will be elided to end with '.c...'). It appears | 537 // else ending with '.com' will be elided to end with '.c...'). It appears |
542 // to be off by one point so clipping is acceptable as it doesn't actually | 538 // to be off by one point so clipping is acceptable as it doesn't actually |
543 // cut off any of the text. | 539 // cut off any of the text. |
(...skipping 29 matching lines...) Expand all Loading... | |
573 textRangeFromPosition:[self | 569 textRangeFromPosition:[self |
574 beginningOfDocument] | 570 beginningOfDocument] |
575 toPosition:[self endOfDocument]]]; | 571 toPosition:[self endOfDocument]]]; |
576 } | 572 } |
577 | 573 |
578 - (void)setPlaceholder:(NSString*)placeholder { | 574 - (void)setPlaceholder:(NSString*)placeholder { |
579 if (placeholder && _placeholderTextColor) { | 575 if (placeholder && _placeholderTextColor) { |
580 NSDictionary* attributes = | 576 NSDictionary* attributes = |
581 @{NSForegroundColorAttributeName : _placeholderTextColor}; | 577 @{NSForegroundColorAttributeName : _placeholderTextColor}; |
582 self.attributedPlaceholder = | 578 self.attributedPlaceholder = |
583 [[[NSAttributedString alloc] initWithString:placeholder | 579 [[NSAttributedString alloc] initWithString:placeholder |
584 attributes:attributes] autorelease]; | 580 attributes:attributes]; |
585 } else { | 581 } else { |
586 [super setPlaceholder:placeholder]; | 582 [super setPlaceholder:placeholder]; |
587 } | 583 } |
588 } | 584 } |
589 | 585 |
590 - (void)setText:(NSString*)text { | 586 - (void)setText:(NSString*)text { |
591 NSAttributedString* as = | 587 NSAttributedString* as = [[NSAttributedString alloc] initWithString:text]; |
592 [[[NSAttributedString alloc] initWithString:text] autorelease]; | |
593 if (self.text.length > 0 && as.length == 0) { | 588 if (self.text.length > 0 && as.length == 0) { |
594 // Remove the fade animations before the subviews are removed. | 589 // Remove the fade animations before the subviews are removed. |
595 [self cleanUpFadeAnimations]; | 590 [self cleanUpFadeAnimations]; |
596 } | 591 } |
597 [self setTextInternal:as autocompleteLength:0]; | 592 [self setTextInternal:as autocompleteLength:0]; |
598 } | 593 } |
599 | 594 |
600 - (void)setText:(NSAttributedString*)text | 595 - (void)setText:(NSAttributedString*)text |
601 userTextLength:(size_t)userTextLength { | 596 userTextLength:(size_t)userTextLength { |
602 DCHECK_LE(userTextLength, [text length]); | 597 DCHECK_LE(userTextLength, [text length]); |
603 | 598 |
604 NSUInteger autocompleteLength = [text length] - userTextLength; | 599 NSUInteger autocompleteLength = [text length] - userTextLength; |
605 [self setTextInternal:text autocompleteLength:autocompleteLength]; | 600 [self setTextInternal:text autocompleteLength:autocompleteLength]; |
606 } | 601 } |
607 | 602 |
608 - (void)setChipText:(NSString*)chipName { | 603 - (void)setChipText:(NSString*)chipName { |
609 _chipText.reset(); | 604 _chipText = nil; |
610 if ([chipName length]) { | 605 if ([chipName length]) { |
611 if ([self bestAlignmentForText:chipName] == NSTextAlignmentLeft) | 606 if ([self bestAlignmentForText:chipName] == NSTextAlignmentLeft) |
612 chipName = [chipName stringByAppendingString:@":"]; | 607 chipName = [chipName stringByAppendingString:@":"]; |
613 _chipText.reset([chipName copy]); | 608 _chipText = [chipName copy]; |
614 } | 609 } |
615 [self updateLeftView]; | 610 [self updateLeftView]; |
616 } | 611 } |
617 | 612 |
618 - (BOOL)hasAutocompleteText { | 613 - (BOOL)hasAutocompleteText { |
619 return !!_selection.get(); | 614 return !!_selection; |
620 } | 615 } |
621 | 616 |
622 - (void)clearAutocompleteText { | 617 - (void)clearAutocompleteText { |
623 if (_selection) { | 618 if (_selection) { |
624 [_selection removeFromSuperview]; | 619 [_selection removeFromSuperview]; |
625 _selection.reset(nil); | 620 _selection = nil; |
626 [self showTextAndCursor]; | 621 [self showTextAndCursor]; |
627 } | 622 } |
628 } | 623 } |
629 | 624 |
630 - (BOOL)isColorHidden:(UIColor*)color { | 625 - (BOOL)isColorHidden:(UIColor*)color { |
631 return ([color isEqual:[UIColor clearColor]] || | 626 return ([color isEqual:[UIColor clearColor]] || |
632 CGColorGetAlpha(color.CGColor) < 0.05); | 627 CGColorGetAlpha(color.CGColor) < 0.05); |
633 } | 628 } |
634 | 629 |
635 // Set the text field's text and cursor to their displayed colors. To be called | 630 // Set the text field's text and cursor to their displayed colors. To be called |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
986 [self offsetFromPosition:beginning toPosition:[selectedRange start]]; | 981 [self offsetFromPosition:beginning toPosition:[selectedRange start]]; |
987 NSInteger length = [self offsetFromPosition:[selectedRange start] | 982 NSInteger length = [self offsetFromPosition:[selectedRange start] |
988 toPosition:[selectedRange end]]; | 983 toPosition:[selectedRange end]]; |
989 return NSMakeRange(start, length); | 984 return NSMakeRange(start, length); |
990 } | 985 } |
991 | 986 |
992 - (BOOL)becomeFirstResponder { | 987 - (BOOL)becomeFirstResponder { |
993 if (![super becomeFirstResponder]) | 988 if (![super becomeFirstResponder]) |
994 return NO; | 989 return NO; |
995 | 990 |
996 if (!_copyUrlMenuItem.get()) { | 991 if (!_copyUrlMenuItem) { |
997 NSString* const kTitle = l10n_util::GetNSString(IDS_IOS_COPY_URL); | 992 NSString* const kTitle = l10n_util::GetNSString(IDS_IOS_COPY_URL); |
998 _copyUrlMenuItem.reset( | 993 _copyUrlMenuItem = |
999 [[UIMenuItem alloc] initWithTitle:kTitle action:@selector(copyUrl:)]); | 994 [[UIMenuItem alloc] initWithTitle:kTitle action:@selector(copyUrl:)]; |
1000 } | 995 } |
1001 | 996 |
1002 // Add the "Copy URL" menu item to the |sharedMenuController| if necessary. | 997 // Add the "Copy URL" menu item to the |sharedMenuController| if necessary. |
1003 UIMenuController* menuController = [UIMenuController sharedMenuController]; | 998 UIMenuController* menuController = [UIMenuController sharedMenuController]; |
1004 if (menuController.menuItems) { | 999 if (menuController.menuItems) { |
1005 if (![menuController.menuItems containsObject:_copyUrlMenuItem]) { | 1000 if (![menuController.menuItems containsObject:_copyUrlMenuItem]) { |
1006 menuController.menuItems = | 1001 menuController.menuItems = |
1007 [menuController.menuItems arrayByAddingObject:_copyUrlMenuItem]; | 1002 [menuController.menuItems arrayByAddingObject:_copyUrlMenuItem]; |
1008 } | 1003 } |
1009 } else { | 1004 } else { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1043 // Disable the RTL arrow menu item. The omnibox sets alignment based on the | 1038 // Disable the RTL arrow menu item. The omnibox sets alignment based on the |
1044 // text in the field, and should not be overridden. | 1039 // text in the field, and should not be overridden. |
1045 if ([NSStringFromSelector(action) hasPrefix:@"makeTextWritingDirection"]) { | 1040 if ([NSStringFromSelector(action) hasPrefix:@"makeTextWritingDirection"]) { |
1046 return NO; | 1041 return NO; |
1047 } | 1042 } |
1048 | 1043 |
1049 return [super canPerformAction:action withSender:sender]; | 1044 return [super canPerformAction:action withSender:sender]; |
1050 } | 1045 } |
1051 | 1046 |
1052 @end | 1047 @end |
OLD | NEW |