| 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/infobars/infobar_view.h" | 5 #import "ios/chrome/browser/ui/infobars/infobar_view.h" |
| 6 | 6 |
| 7 #import <CoreGraphics/CoreGraphics.h> | 7 #import <CoreGraphics/CoreGraphics.h> |
| 8 #import <QuartzCore/QuartzCore.h> | 8 #import <QuartzCore/QuartzCore.h> |
| 9 | 9 |
| 10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
| 11 #include "base/i18n/rtl.h" | 11 #include "base/i18n/rtl.h" |
| 12 #include "base/ios/weak_nsobject.h" | |
| 13 #include "base/logging.h" | 12 #include "base/logging.h" |
| 14 #include "base/mac/foundation_util.h" | 13 #include "base/mac/foundation_util.h" |
| 15 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 16 #include "components/strings/grit/components_strings.h" | 15 #include "components/strings/grit/components_strings.h" |
| 17 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" | 16 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" |
| 18 #import "ios/chrome/browser/ui/infobars/infobar_view_delegate.h" | 17 #import "ios/chrome/browser/ui/infobars/infobar_view_delegate.h" |
| 19 #include "ios/chrome/browser/ui/ui_util.h" | 18 #include "ios/chrome/browser/ui/ui_util.h" |
| 20 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 19 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
| 21 #import "ios/chrome/browser/ui/util/label_link_controller.h" | 20 #import "ios/chrome/browser/ui/util/label_link_controller.h" |
| 22 #import "ios/third_party/material_components_ios/src/components/Buttons/src/Mate
rialButtons.h" | 21 #import "ios/third_party/material_components_ios/src/components/Buttons/src/Mate
rialButtons.h" |
| 23 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" | 22 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" |
| 24 #include "ui/base/l10n/l10n_util.h" | 23 #include "ui/base/l10n/l10n_util.h" |
| 25 #import "ui/gfx/ios/NSString+CrStringDrawing.h" | 24 #import "ui/gfx/ios/NSString+CrStringDrawing.h" |
| 26 #import "ui/gfx/ios/uikit_util.h" | 25 #import "ui/gfx/ios/uikit_util.h" |
| 27 #include "url/gurl.h" | 26 #include "url/gurl.h" |
| 28 | 27 |
| 28 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 29 #error "This file requires ARC support." |
| 30 #endif |
| 31 |
| 29 namespace { | 32 namespace { |
| 30 | 33 |
| 31 const char kChromeInfobarURL[] = "chromeinternal://infobar/"; | 34 const char kChromeInfobarURL[] = "chromeinternal://infobar/"; |
| 32 | 35 |
| 33 // UX configuration constants for the shadow/rounded corners on the icon. | 36 // UX configuration constants for the shadow/rounded corners on the icon. |
| 34 const CGFloat kBaseSizeForEffects = 57.0; | 37 const CGFloat kBaseSizeForEffects = 57.0; |
| 35 const CGFloat kCornerRadius = 10.0; | 38 const CGFloat kCornerRadius = 10.0; |
| 36 const CGFloat kShadowVerticalOffset = 1.0; | 39 const CGFloat kShadowVerticalOffset = 1.0; |
| 37 const CGFloat kShadowOpacity = 0.5; | 40 const CGFloat kShadowOpacity = 0.5; |
| 38 const CGFloat kShadowRadius = 0.8; | 41 const CGFloat kShadowRadius = 0.8; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 // If |layout| is yes, it sets the frame of the label and the switch to fit | 78 // If |layout| is yes, it sets the frame of the label and the switch to fit |
| 76 // |width|. | 79 // |width|. |
| 77 - (CGFloat)heightRequiredForSwitchWithWidth:(CGFloat)width layout:(BOOL)layout; | 80 - (CGFloat)heightRequiredForSwitchWithWidth:(CGFloat)width layout:(BOOL)layout; |
| 78 | 81 |
| 79 // Returns the preferred width. A smaller width requires eliding the text. | 82 // Returns the preferred width. A smaller width requires eliding the text. |
| 80 - (CGFloat)preferredWidth; | 83 - (CGFloat)preferredWidth; |
| 81 | 84 |
| 82 @end | 85 @end |
| 83 | 86 |
| 84 @implementation SwitchView { | 87 @implementation SwitchView { |
| 85 base::scoped_nsobject<UILabel> label_; | 88 UILabel* label_; |
| 86 base::scoped_nsobject<UISwitch> switch_; | 89 UISwitch* switch_; |
| 87 CGFloat preferredTotalWidth_; | 90 CGFloat preferredTotalWidth_; |
| 88 CGFloat preferredLabelWidth_; | 91 CGFloat preferredLabelWidth_; |
| 89 } | 92 } |
| 90 | 93 |
| 91 - (id)initWithLabel:(NSString*)labelText isOn:(BOOL)isOn { | 94 - (id)initWithLabel:(NSString*)labelText isOn:(BOOL)isOn { |
| 92 // Creates switch and label. | 95 // Creates switch and label. |
| 93 base::scoped_nsobject<UILabel> tempLabel( | 96 UILabel* tempLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| 94 [[UILabel alloc] initWithFrame:CGRectZero]); | |
| 95 [tempLabel setTextAlignment:NSTextAlignmentNatural]; | 97 [tempLabel setTextAlignment:NSTextAlignmentNatural]; |
| 96 [tempLabel setFont:[MDCTypography body1Font]]; | 98 [tempLabel setFont:[MDCTypography body1Font]]; |
| 97 [tempLabel setText:labelText]; | 99 [tempLabel setText:labelText]; |
| 98 [tempLabel setBackgroundColor:[UIColor clearColor]]; | 100 [tempLabel setBackgroundColor:[UIColor clearColor]]; |
| 99 [tempLabel setLineBreakMode:NSLineBreakByWordWrapping]; | 101 [tempLabel setLineBreakMode:NSLineBreakByWordWrapping]; |
| 100 [tempLabel setNumberOfLines:0]; | 102 [tempLabel setNumberOfLines:0]; |
| 101 [tempLabel setAdjustsFontSizeToFitWidth:NO]; | 103 [tempLabel setAdjustsFontSizeToFitWidth:NO]; |
| 102 base::scoped_nsobject<UISwitch> tempSwitch( | 104 UISwitch* tempSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; |
| 103 [[UISwitch alloc] initWithFrame:CGRectZero]); | |
| 104 [tempSwitch setExclusiveTouch:YES]; | 105 [tempSwitch setExclusiveTouch:YES]; |
| 105 [tempSwitch setAccessibilityLabel:labelText]; | 106 [tempSwitch setAccessibilityLabel:labelText]; |
| 106 [tempSwitch setOnTintColor:[[MDCPalette cr_bluePalette] tint500]]; | 107 [tempSwitch setOnTintColor:[[MDCPalette cr_bluePalette] tint500]]; |
| 107 [tempSwitch setOn:isOn]; | 108 [tempSwitch setOn:isOn]; |
| 108 | 109 |
| 109 // Computes the size and initializes the view. | 110 // Computes the size and initializes the view. |
| 110 CGSize maxSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX); | 111 CGSize maxSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX); |
| 111 CGSize labelSize = | 112 CGSize labelSize = |
| 112 [[tempLabel text] cr_boundingSizeWithSize:maxSize font:[tempLabel font]]; | 113 [[tempLabel text] cr_boundingSizeWithSize:maxSize font:[tempLabel font]]; |
| 113 CGSize switchSize = [tempSwitch frame].size; | 114 CGSize switchSize = [tempSwitch frame].size; |
| 114 CGRect frameRect = CGRectMake( | 115 CGRect frameRect = CGRectMake( |
| 115 0, 0, labelSize.width + kSpaceBetweenWidgets + switchSize.width, | 116 0, 0, labelSize.width + kSpaceBetweenWidgets + switchSize.width, |
| 116 std::max(labelSize.height, switchSize.height)); | 117 std::max(labelSize.height, switchSize.height)); |
| 117 self = [super initWithFrame:frameRect]; | 118 self = [super initWithFrame:frameRect]; |
| 118 if (!self) | 119 if (!self) |
| 119 return nil; | 120 return nil; |
| 120 label_.reset([tempLabel retain]); | 121 label_ = tempLabel; |
| 121 switch_.reset([tempSwitch retain]); | 122 switch_ = tempSwitch; |
| 122 | 123 |
| 123 // Sets the position of the label and the switch. The label is left aligned | 124 // Sets the position of the label and the switch. The label is left aligned |
| 124 // and the switch is right aligned. Both are vertically centered. | 125 // and the switch is right aligned. Both are vertically centered. |
| 125 CGRect labelFrame = | 126 CGRect labelFrame = |
| 126 CGRectMake(0, (self.frame.size.height - labelSize.height) / 2, | 127 CGRectMake(0, (self.frame.size.height - labelSize.height) / 2, |
| 127 labelSize.width, labelSize.height); | 128 labelSize.width, labelSize.height); |
| 128 CGRect switchFrame = | 129 CGRect switchFrame = |
| 129 CGRectMake(self.frame.size.width - switchSize.width, | 130 CGRectMake(self.frame.size.width - switchSize.width, |
| 130 (self.frame.size.height - switchSize.height) / 2, | 131 (self.frame.size.height - switchSize.height) / 2, |
| 131 switchSize.width, switchSize.height); | 132 switchSize.width, switchSize.height); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 | 217 |
| 217 // Returns the marker delimiting the start of a link. | 218 // Returns the marker delimiting the start of a link. |
| 218 + (NSString*)openingMarkerForLink; | 219 + (NSString*)openingMarkerForLink; |
| 219 // Returns the marker delimiting the end of a link. | 220 // Returns the marker delimiting the end of a link. |
| 220 + (NSString*)closingMarkerForLink; | 221 + (NSString*)closingMarkerForLink; |
| 221 | 222 |
| 222 @end | 223 @end |
| 223 | 224 |
| 224 @implementation InfoBarView { | 225 @implementation InfoBarView { |
| 225 // Delegates UIView events. | 226 // Delegates UIView events. |
| 226 InfoBarViewDelegate* delegate_; // weak | 227 InfoBarViewDelegate* delegate_; // weak. |
| 227 // The current height of this infobar (used for animations where part of the | 228 // The current height of this infobar (used for animations where part of the |
| 228 // infobar is hidden). | 229 // infobar is hidden). |
| 229 CGFloat visibleHeight_; | 230 CGFloat visibleHeight_; |
| 230 // The height of this infobar when fully visible. | 231 // The height of this infobar when fully visible. |
| 231 CGFloat targetHeight_; | 232 CGFloat targetHeight_; |
| 232 // View containing |imageView_|. Exists to apply drop shadows to the view. | 233 // View containing |imageView_|. Exists to apply drop shadows to the view. |
| 233 base::scoped_nsobject<UIView> imageViewContainer_; | 234 UIView* imageViewContainer_; |
| 234 // View containing the icon. | 235 // View containing the icon. |
| 235 base::scoped_nsobject<UIImageView> imageView_; | 236 UIImageView* imageView_; |
| 236 // Close button. | 237 // Close button. |
| 237 base::scoped_nsobject<UIButton> closeButton_; | 238 UIButton* closeButton_; |
| 238 // View containing the switch and its label. | 239 // View containing the switch and its label. |
| 239 base::scoped_nsobject<SwitchView> switchView_; | 240 SwitchView* switchView_; |
| 240 // We are using a LabelLinkController with an UILabel to be able to have | 241 // We are using a LabelLinkController with an UILabel to be able to have |
| 241 // parts of the label underlined and clickable. This label_ may be nil if | 242 // parts of the label underlined and clickable. This label_ may be nil if |
| 242 // the delegate returns an empty string for GetMessageText(). | 243 // the delegate returns an empty string for GetMessageText(). |
| 243 base::scoped_nsobject<LabelLinkController> labelLinkController_; | 244 LabelLinkController* labelLinkController_; |
| 244 UILabel* label_; // Weak. | 245 UILabel* label_; |
| 245 // Array of range information. The first element of the pair is the tag of | 246 // Array of range information. The first element of the pair is the tag of |
| 246 // the action and the second element is the range defining the link. | 247 // the action and the second element is the range defining the link. |
| 247 std::vector<std::pair<NSUInteger, NSRange>> linkRanges_; | 248 std::vector<std::pair<NSUInteger, NSRange>> linkRanges_; |
| 248 // Text for the label with link markers included. | 249 // Text for the label with link markers included. |
| 249 base::scoped_nsobject<NSString> markedLabel_; | 250 NSString* markedLabel_; |
| 250 // Buttons. | 251 // Buttons. |
| 251 // button1_ is tagged with ConfirmInfoBarDelegate::BUTTON_OK . | 252 // button1_ is tagged with ConfirmInfoBarDelegate::BUTTON_OK . |
| 252 // button2_ is tagged with ConfirmInfoBarDelegate::BUTTON_CANCEL . | 253 // button2_ is tagged with ConfirmInfoBarDelegate::BUTTON_CANCEL . |
| 253 base::scoped_nsobject<UIButton> button1_; | 254 UIButton* button1_; |
| 254 base::scoped_nsobject<UIButton> button2_; | 255 UIButton* button2_; |
| 255 // Drop shadow. | 256 // Drop shadow. |
| 256 base::scoped_nsobject<UIImageView> shadow_; | 257 UIImageView* shadow_; |
| 257 } | 258 } |
| 258 | 259 |
| 259 @synthesize visibleHeight = visibleHeight_; | 260 @synthesize visibleHeight = visibleHeight_; |
| 260 | 261 |
| 261 - (instancetype)initWithFrame:(CGRect)frame | 262 - (instancetype)initWithFrame:(CGRect)frame |
| 262 delegate:(InfoBarViewDelegate*)delegate { | 263 delegate:(InfoBarViewDelegate*)delegate { |
| 263 self = [super initWithFrame:frame]; | 264 self = [super initWithFrame:frame]; |
| 264 if (self) { | 265 if (self) { |
| 265 delegate_ = delegate; | 266 delegate_ = delegate; |
| 266 // Make the drop shadow. | 267 // Make the drop shadow. |
| 267 UIImage* shadowImage = [UIImage imageNamed:@"infobar_shadow"]; | 268 UIImage* shadowImage = [UIImage imageNamed:@"infobar_shadow"]; |
| 268 shadow_.reset([[UIImageView alloc] initWithImage:shadowImage]); | 269 shadow_ = [[UIImageView alloc] initWithImage:shadowImage]; |
| 269 [self addSubview:shadow_]; | 270 [self addSubview:shadow_]; |
| 270 [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | | 271 [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | |
| 271 UIViewAutoresizingFlexibleHeight]; | 272 UIViewAutoresizingFlexibleHeight]; |
| 272 [self setAccessibilityViewIsModal:YES]; | 273 [self setAccessibilityViewIsModal:YES]; |
| 273 } | 274 } |
| 274 return self; | 275 return self; |
| 275 } | 276 } |
| 276 | 277 |
| 277 - (void)dealloc { | |
| 278 [super dealloc]; | |
| 279 } | |
| 280 | 278 |
| 281 - (NSString*)markedLabel { | 279 - (NSString*)markedLabel { |
| 282 return markedLabel_; | 280 return markedLabel_; |
| 283 } | 281 } |
| 284 | 282 |
| 285 - (void)resetDelegate { | 283 - (void)resetDelegate { |
| 286 delegate_ = NULL; | 284 delegate_ = NULL; |
| 287 } | 285 } |
| 288 | 286 |
| 289 // Returns the width reserved for the icon. | 287 // Returns the width reserved for the icon. |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 } | 654 } |
| 657 | 655 |
| 658 - (void)addCloseButtonWithTag:(NSInteger)tag | 656 - (void)addCloseButtonWithTag:(NSInteger)tag |
| 659 target:(id)target | 657 target:(id)target |
| 660 action:(SEL)action { | 658 action:(SEL)action { |
| 661 DCHECK(!closeButton_); | 659 DCHECK(!closeButton_); |
| 662 // TODO(crbug/228611): Add IDR_ constant and use GetNativeImageNamed(). | 660 // TODO(crbug/228611): Add IDR_ constant and use GetNativeImageNamed(). |
| 663 NSString* imagePath = | 661 NSString* imagePath = |
| 664 [[NSBundle mainBundle] pathForResource:@"infobar_close" ofType:@"png"]; | 662 [[NSBundle mainBundle] pathForResource:@"infobar_close" ofType:@"png"]; |
| 665 UIImage* image = [UIImage imageWithContentsOfFile:imagePath]; | 663 UIImage* image = [UIImage imageWithContentsOfFile:imagePath]; |
| 666 closeButton_.reset([[UIButton buttonWithType:UIButtonTypeCustom] retain]); | 664 closeButton_ = [UIButton buttonWithType:UIButtonTypeCustom]; |
| 667 [closeButton_ setExclusiveTouch:YES]; | 665 [closeButton_ setExclusiveTouch:YES]; |
| 668 [closeButton_ setImage:image forState:UIControlStateNormal]; | 666 [closeButton_ setImage:image forState:UIControlStateNormal]; |
| 669 [closeButton_ addTarget:target | 667 [closeButton_ addTarget:target |
| 670 action:action | 668 action:action |
| 671 forControlEvents:UIControlEventTouchUpInside]; | 669 forControlEvents:UIControlEventTouchUpInside]; |
| 672 [closeButton_ setTag:tag]; | 670 [closeButton_ setTag:tag]; |
| 673 [closeButton_ setAccessibilityLabel:l10n_util::GetNSString(IDS_CLOSE)]; | 671 [closeButton_ setAccessibilityLabel:l10n_util::GetNSString(IDS_CLOSE)]; |
| 674 [self addSubview:closeButton_]; | 672 [self addSubview:closeButton_]; |
| 675 } | 673 } |
| 676 | 674 |
| 677 - (void)addSwitchWithLabel:(NSString*)label | 675 - (void)addSwitchWithLabel:(NSString*)label |
| 678 isOn:(BOOL)isOn | 676 isOn:(BOOL)isOn |
| 679 tag:(NSInteger)tag | 677 tag:(NSInteger)tag |
| 680 target:(id)target | 678 target:(id)target |
| 681 action:(SEL)action { | 679 action:(SEL)action { |
| 682 switchView_.reset([[SwitchView alloc] initWithLabel:label isOn:isOn]); | 680 switchView_ = [[SwitchView alloc] initWithLabel:label isOn:isOn]; |
| 683 [switchView_ setTag:tag target:target action:action]; | 681 [switchView_ setTag:tag target:target action:action]; |
| 684 [self addSubview:switchView_]; | 682 [self addSubview:switchView_]; |
| 685 } | 683 } |
| 686 | 684 |
| 687 - (void)addLeftIcon:(UIImage*)image { | 685 - (void)addLeftIcon:(UIImage*)image { |
| 688 if (!imageViewContainer_) { | 686 if (!imageViewContainer_) { |
| 689 imageViewContainer_.reset([[UIView alloc] init]); | 687 imageViewContainer_ = [[UIView alloc] init]; |
| 690 [self addSubview:imageViewContainer_]; | 688 [self addSubview:imageViewContainer_]; |
| 691 } | 689 } |
| 692 imageView_.reset([[UIImageView alloc] initWithImage:image]); | 690 imageView_ = [[UIImageView alloc] initWithImage:image]; |
| 693 [imageViewContainer_ addSubview:imageView_]; | 691 [imageViewContainer_ addSubview:imageView_]; |
| 694 } | 692 } |
| 695 | 693 |
| 696 - (void)addPlaceholderTransparentIcon:(CGSize const&)imageSize { | 694 - (void)addPlaceholderTransparentIcon:(CGSize const&)imageSize { |
| 697 UIGraphicsBeginImageContext(imageSize); | 695 UIGraphicsBeginImageContext(imageSize); |
| 698 UIImage* placeholder = UIGraphicsGetImageFromCurrentImageContext(); | 696 UIImage* placeholder = UIGraphicsGetImageFromCurrentImageContext(); |
| 699 UIGraphicsEndImageContext(); | 697 UIGraphicsEndImageContext(); |
| 700 [self addLeftIcon:placeholder]; | 698 [self addLeftIcon:placeholder]; |
| 701 } | 699 } |
| 702 | 700 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 719 } | 717 } |
| 720 | 718 |
| 721 - (NSString*)stripMarkersFromString:(NSString*)string { | 719 - (NSString*)stripMarkersFromString:(NSString*)string { |
| 722 linkRanges_.clear(); | 720 linkRanges_.clear(); |
| 723 for (;;) { | 721 for (;;) { |
| 724 // Find the opening marker, followed by the tag between parentheses. | 722 // Find the opening marker, followed by the tag between parentheses. |
| 725 NSRange startingRange = | 723 NSRange startingRange = |
| 726 [string rangeOfString:[[InfoBarView openingMarkerForLink] | 724 [string rangeOfString:[[InfoBarView openingMarkerForLink] |
| 727 stringByAppendingString:@"("]]; | 725 stringByAppendingString:@"("]]; |
| 728 if (!startingRange.length) | 726 if (!startingRange.length) |
| 729 return [[string copy] autorelease]; | 727 return [string copy]; |
| 730 // Read the tag. | 728 // Read the tag. |
| 731 NSUInteger beginTag = NSMaxRange(startingRange); | 729 NSUInteger beginTag = NSMaxRange(startingRange); |
| 732 NSRange closingParenthesis = [string | 730 NSRange closingParenthesis = [string |
| 733 rangeOfString:@")" | 731 rangeOfString:@")" |
| 734 options:NSLiteralSearch | 732 options:NSLiteralSearch |
| 735 range:NSMakeRange(beginTag, [string length] - beginTag)]; | 733 range:NSMakeRange(beginTag, [string length] - beginTag)]; |
| 736 if (closingParenthesis.location == NSNotFound) | 734 if (closingParenthesis.location == NSNotFound) |
| 737 return [[string copy] autorelease]; | 735 return [string copy]; |
| 738 NSInteger tag = [[string | 736 NSInteger tag = [[string |
| 739 substringWithRange:NSMakeRange(beginTag, closingParenthesis.location - | 737 substringWithRange:NSMakeRange(beginTag, closingParenthesis.location - |
| 740 beginTag)] integerValue]; | 738 beginTag)] integerValue]; |
| 741 // If the parsing fails, |tag| is 0. Negative values are not allowed. | 739 // If the parsing fails, |tag| is 0. Negative values are not allowed. |
| 742 if (tag <= 0) | 740 if (tag <= 0) |
| 743 return [[string copy] autorelease]; | 741 return [string copy]; |
| 744 // Find the closing marker. | 742 // Find the closing marker. |
| 745 startingRange.length = | 743 startingRange.length = |
| 746 closingParenthesis.location - startingRange.location + 1; | 744 closingParenthesis.location - startingRange.location + 1; |
| 747 NSRange endingRange = | 745 NSRange endingRange = |
| 748 [string rangeOfString:[InfoBarView closingMarkerForLink]]; | 746 [string rangeOfString:[InfoBarView closingMarkerForLink]]; |
| 749 DCHECK(endingRange.length); | 747 DCHECK(endingRange.length); |
| 750 // Compute range of link in stripped string and add it to the array. | 748 // Compute range of link in stripped string and add it to the array. |
| 751 NSRange rangeOfLinkInStrippedString = | 749 NSRange rangeOfLinkInStrippedString = |
| 752 NSMakeRange(startingRange.location, | 750 NSMakeRange(startingRange.location, |
| 753 endingRange.location - NSMaxRange(startingRange)); | 751 endingRange.location - NSMaxRange(startingRange)); |
| 754 linkRanges_.push_back(std::make_pair(tag, rangeOfLinkInStrippedString)); | 752 linkRanges_.push_back(std::make_pair(tag, rangeOfLinkInStrippedString)); |
| 755 // Creates a new string without the markers. | 753 // Creates a new string without the markers. |
| 756 NSString* beforeLink = [string substringToIndex:startingRange.location]; | 754 NSString* beforeLink = [string substringToIndex:startingRange.location]; |
| 757 NSRange rangeOfLink = | 755 NSRange rangeOfLink = |
| 758 NSMakeRange(NSMaxRange(startingRange), | 756 NSMakeRange(NSMaxRange(startingRange), |
| 759 endingRange.location - NSMaxRange(startingRange)); | 757 endingRange.location - NSMaxRange(startingRange)); |
| 760 NSString* link = [string substringWithRange:rangeOfLink]; | 758 NSString* link = [string substringWithRange:rangeOfLink]; |
| 761 NSString* afterLink = [string substringFromIndex:NSMaxRange(endingRange)]; | 759 NSString* afterLink = [string substringFromIndex:NSMaxRange(endingRange)]; |
| 762 string = [NSString stringWithFormat:@"%@%@%@", beforeLink, link, afterLink]; | 760 string = [NSString stringWithFormat:@"%@%@%@", beforeLink, link, afterLink]; |
| 763 } | 761 } |
| 764 } | 762 } |
| 765 | 763 |
| 766 - (void)addLabel:(NSString*)label { | 764 - (void)addLabel:(NSString*)label { |
| 767 [self addLabel:label action:nil]; | 765 [self addLabel:label action:nil]; |
| 768 } | 766 } |
| 769 | 767 |
| 770 - (void)addLabel:(NSString*)text action:(void (^)(NSUInteger))action { | 768 - (void)addLabel:(NSString*)text action:(void (^)(NSUInteger))action { |
| 771 markedLabel_.reset([text copy]); | 769 markedLabel_ = [text copy]; |
| 772 if (action) | 770 if (action) |
| 773 text = [self stripMarkersFromString:text]; | 771 text = [self stripMarkersFromString:text]; |
| 774 if ([label_ superview]) { | 772 if ([label_ superview]) { |
| 775 [label_ removeFromSuperview]; | 773 [label_ removeFromSuperview]; |
| 776 } | 774 } |
| 777 | 775 |
| 778 label_ = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; | 776 label_ = [[UILabel alloc] initWithFrame:CGRectZero]; |
| 779 | 777 |
| 780 UIFont* font = [MDCTypography subheadFont]; | 778 UIFont* font = [MDCTypography subheadFont]; |
| 781 | 779 |
| 782 [label_ setBackgroundColor:[UIColor clearColor]]; | 780 [label_ setBackgroundColor:[UIColor clearColor]]; |
| 783 | 781 |
| 784 NSMutableParagraphStyle* paragraphStyle = | 782 NSMutableParagraphStyle* paragraphStyle = |
| 785 [[[NSMutableParagraphStyle alloc] init] autorelease]; | 783 [[NSMutableParagraphStyle alloc] init]; |
| 786 paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; | 784 paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; |
| 787 paragraphStyle.lineSpacing = kLabelLineSpacing; | 785 paragraphStyle.lineSpacing = kLabelLineSpacing; |
| 788 NSDictionary* attributes = @{ | 786 NSDictionary* attributes = @{ |
| 789 NSParagraphStyleAttributeName : paragraphStyle, | 787 NSParagraphStyleAttributeName : paragraphStyle, |
| 790 NSFontAttributeName : font, | 788 NSFontAttributeName : font, |
| 791 }; | 789 }; |
| 792 [label_ setNumberOfLines:0]; | 790 [label_ setNumberOfLines:0]; |
| 793 | 791 |
| 794 [label_ setAttributedText:[[[NSAttributedString alloc] | 792 [label_ |
| 795 initWithString:text | 793 setAttributedText:[[NSAttributedString alloc] initWithString:text |
| 796 attributes:attributes] autorelease]]; | 794 attributes:attributes]]; |
| 797 | 795 |
| 798 [self addSubview:label_]; | 796 [self addSubview:label_]; |
| 799 | 797 |
| 800 if (linkRanges_.empty()) | 798 if (linkRanges_.empty()) |
| 801 return; | 799 return; |
| 802 | 800 |
| 803 labelLinkController_.reset([[LabelLinkController alloc] | 801 labelLinkController_ = [[LabelLinkController alloc] |
| 804 initWithLabel:label_ | 802 initWithLabel:label_ |
| 805 action:^(const GURL& gurl) { | 803 action:^(const GURL& gurl) { |
| 806 if (action) { | 804 if (action) { |
| 807 NSUInteger actionTag = [base::SysUTF8ToNSString( | 805 NSUInteger actionTag = [base::SysUTF8ToNSString( |
| 808 gurl.ExtractFileName()) integerValue]; | 806 gurl.ExtractFileName()) integerValue]; |
| 809 action(actionTag); | 807 action(actionTag); |
| 810 } | 808 } |
| 811 }]); | 809 }]; |
| 812 | 810 |
| 813 [labelLinkController_ setLinkUnderlineStyle:NSUnderlineStyleSingle]; | 811 [labelLinkController_ setLinkUnderlineStyle:NSUnderlineStyleSingle]; |
| 814 [labelLinkController_ setLinkColor:[UIColor blackColor]]; | 812 [labelLinkController_ setLinkColor:[UIColor blackColor]]; |
| 815 | 813 |
| 816 std::vector<std::pair<NSUInteger, NSRange>>::const_iterator it; | 814 std::vector<std::pair<NSUInteger, NSRange>>::const_iterator it; |
| 817 for (it = linkRanges_.begin(); it != linkRanges_.end(); ++it) { | 815 for (it = linkRanges_.begin(); it != linkRanges_.end(); ++it) { |
| 818 // The last part of the URL contains the tag, so it can be retrieved in the | 816 // The last part of the URL contains the tag, so it can be retrieved in the |
| 819 // callback. This tag is generally a command ID. | 817 // callback. This tag is generally a command ID. |
| 820 std::string url = std::string(kChromeInfobarURL) + | 818 std::string url = std::string(kChromeInfobarURL) + |
| 821 std::string(std::to_string((int)it->first)); | 819 std::string(std::to_string((int)it->first)); |
| 822 [labelLinkController_ addLinkWithRange:it->second url:GURL(url)]; | 820 [labelLinkController_ addLinkWithRange:it->second url:GURL(url)]; |
| 823 } | 821 } |
| 824 } | 822 } |
| 825 | 823 |
| 826 - (void)addButton1:(NSString*)title1 | 824 - (void)addButton1:(NSString*)title1 |
| 827 tag1:(NSInteger)tag1 | 825 tag1:(NSInteger)tag1 |
| 828 button2:(NSString*)title2 | 826 button2:(NSString*)title2 |
| 829 tag2:(NSInteger)tag2 | 827 tag2:(NSInteger)tag2 |
| 830 target:(id)target | 828 target:(id)target |
| 831 action:(SEL)action { | 829 action:(SEL)action { |
| 832 button1_.reset([[self infoBarButton:title1 | 830 button1_ = [self infoBarButton:title1 |
| 833 palette:[MDCPalette cr_bluePalette] | 831 palette:[MDCPalette cr_bluePalette] |
| 834 customTitleColor:[UIColor whiteColor] | 832 customTitleColor:[UIColor whiteColor] |
| 835 tag:tag1 | 833 tag:tag1 |
| 836 target:target | 834 target:target |
| 837 action:action] retain]); | 835 action:action]; |
| 838 [self addSubview:button1_]; | 836 [self addSubview:button1_]; |
| 839 | 837 |
| 840 button2_.reset([[self infoBarButton:title2 | 838 button2_ = [self infoBarButton:title2 |
| 841 palette:nil | 839 palette:nil |
| 842 customTitleColor:UIColorFromRGB(kButton2TitleColor) | 840 customTitleColor:UIColorFromRGB(kButton2TitleColor) |
| 843 tag:tag2 | 841 tag:tag2 |
| 844 target:target | 842 target:target |
| 845 action:action] retain]); | 843 action:action]; |
| 846 [self addSubview:button2_]; | 844 [self addSubview:button2_]; |
| 847 } | 845 } |
| 848 | 846 |
| 849 - (void)addButton:(NSString*)title | 847 - (void)addButton:(NSString*)title |
| 850 tag:(NSInteger)tag | 848 tag:(NSInteger)tag |
| 851 target:(id)target | 849 target:(id)target |
| 852 action:(SEL)action { | 850 action:(SEL)action { |
| 853 if (![title length]) | 851 if (![title length]) |
| 854 return; | 852 return; |
| 855 button1_.reset([[self infoBarButton:title | 853 button1_ = [self infoBarButton:title |
| 856 palette:[MDCPalette cr_bluePalette] | 854 palette:[MDCPalette cr_bluePalette] |
| 857 customTitleColor:[UIColor whiteColor] | 855 customTitleColor:[UIColor whiteColor] |
| 858 tag:tag | 856 tag:tag |
| 859 target:target | 857 target:target |
| 860 action:action] retain]); | 858 action:action]; |
| 861 [self addSubview:button1_]; | 859 [self addSubview:button1_]; |
| 862 } | 860 } |
| 863 | 861 |
| 864 // Initializes and returns a button for the infobar, with the specified | 862 // Initializes and returns a button for the infobar, with the specified |
| 865 // |message| and colors. | 863 // |message| and colors. |
| 866 - (UIButton*)infoBarButton:(NSString*)message | 864 - (UIButton*)infoBarButton:(NSString*)message |
| 867 palette:(MDCPalette*)palette | 865 palette:(MDCPalette*)palette |
| 868 customTitleColor:(UIColor*)customTitleColor | 866 customTitleColor:(UIColor*)customTitleColor |
| 869 tag:(NSInteger)tag | 867 tag:(NSInteger)tag |
| 870 target:(id)target | 868 target:(id)target |
| 871 action:(SEL)action { | 869 action:(SEL)action { |
| 872 base::scoped_nsobject<MDCFlatButton> button([[MDCFlatButton alloc] init]); | 870 MDCFlatButton* button = [[MDCFlatButton alloc] init]; |
| 873 button.get().inkColor = [[palette tint300] colorWithAlphaComponent:0.5f]; | 871 button.inkColor = [[palette tint300] colorWithAlphaComponent:0.5f]; |
| 874 [button setBackgroundColor:[palette tint500] forState:UIControlStateNormal]; | 872 [button setBackgroundColor:[palette tint500] forState:UIControlStateNormal]; |
| 875 [button setBackgroundColor:[UIColor colorWithWhite:0.8f alpha:1.0f] | 873 [button setBackgroundColor:[UIColor colorWithWhite:0.8f alpha:1.0f] |
| 876 forState:UIControlStateDisabled]; | 874 forState:UIControlStateDisabled]; |
| 877 if (palette) | 875 if (palette) |
| 878 button.get().hasOpaqueBackground = YES; | 876 button.hasOpaqueBackground = YES; |
| 879 if (customTitleColor) { | 877 if (customTitleColor) { |
| 880 button.get().tintAdjustmentMode = UIViewTintAdjustmentModeNormal; | 878 button.tintAdjustmentMode = UIViewTintAdjustmentModeNormal; |
| 881 button.get().customTitleColor = customTitleColor; | 879 button.customTitleColor = customTitleColor; |
| 882 } | 880 } |
| 883 button.get().titleLabel.adjustsFontSizeToFitWidth = YES; | 881 button.titleLabel.adjustsFontSizeToFitWidth = YES; |
| 884 button.get().titleLabel.minimumScaleFactor = 0.6f; | 882 button.titleLabel.minimumScaleFactor = 0.6f; |
| 885 [button setTitle:message forState:UIControlStateNormal]; | 883 [button setTitle:message forState:UIControlStateNormal]; |
| 886 [button setTag:tag]; | 884 [button setTag:tag]; |
| 887 [button addTarget:target | 885 [button addTarget:target |
| 888 action:action | 886 action:action |
| 889 forControlEvents:UIControlEventTouchUpInside]; | 887 forControlEvents:UIControlEventTouchUpInside]; |
| 890 // Without the call to layoutIfNeeded, |button| returns an incorrect | 888 // Without the call to layoutIfNeeded, |button| returns an incorrect |
| 891 // titleLabel the first time it is accessed in |narrowestWidthOfButton|. | 889 // titleLabel the first time it is accessed in |narrowestWidthOfButton|. |
| 892 [button layoutIfNeeded]; | 890 [button layoutIfNeeded]; |
| 893 return button.autorelease(); | 891 return button; |
| 894 } | 892 } |
| 895 | 893 |
| 896 - (CGRect)frameOfCloseButton:(BOOL)singleLineMode { | 894 - (CGRect)frameOfCloseButton:(BOOL)singleLineMode { |
| 897 DCHECK(closeButton_); | 895 DCHECK(closeButton_); |
| 898 // Add padding to increase the touchable area. | 896 // Add padding to increase the touchable area. |
| 899 CGSize closeButtonSize = [closeButton_ imageView].image.size; | 897 CGSize closeButtonSize = [closeButton_ imageView].image.size; |
| 900 closeButtonSize.width += kCloseButtonInnerPadding * 2; | 898 closeButtonSize.width += kCloseButtonInnerPadding * 2; |
| 901 closeButtonSize.height += kCloseButtonInnerPadding * 2; | 899 closeButtonSize.height += kCloseButtonInnerPadding * 2; |
| 902 CGFloat x = CGRectGetMaxX(self.frame) - closeButtonSize.width; | 900 CGFloat x = CGRectGetMaxX(self.frame) - closeButtonSize.width; |
| 903 // Aligns the close button at the top (height includes touch padding). | 901 // Aligns the close button at the top (height includes touch padding). |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 945 | 943 |
| 946 - (CGFloat)buttonMargin { | 944 - (CGFloat)buttonMargin { |
| 947 return kButtonMargin; | 945 return kButtonMargin; |
| 948 } | 946 } |
| 949 | 947 |
| 950 - (const std::vector<std::pair<NSUInteger, NSRange>>&)linkRanges { | 948 - (const std::vector<std::pair<NSUInteger, NSRange>>&)linkRanges { |
| 951 return linkRanges_; | 949 return linkRanges_; |
| 952 } | 950 } |
| 953 | 951 |
| 954 @end | 952 @end |
| OLD | NEW |