Chromium Code Reviews| 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 |