1// Copyright 2017 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_whats_new_item.h" 6 7#import <MaterialComponents/MaterialTypography.h> 8 9#include "base/check_op.h" 10#import "ios/chrome/browser/ui/util/uikit_ui_util.h" 11#include "ios/chrome/common/string_util.h" 12#import "ios/chrome/common/ui/colors/semantic_color_names.h" 13#import "ios/chrome/common/ui/util/constraints_ui_util.h" 14 15#if !defined(__has_feature) || !__has_feature(objc_arc) 16#error "This file requires ARC support." 17#endif 18 19namespace { 20 21const CGFloat kLabelMargin = 14; 22const CGFloat kLabelLineSpacing = 4; 23const CGFloat kLabelIconMargin = 8; 24const CGFloat kLabelFontSize = 14; 25const CGFloat kIconSize = 24; 26const CGFloat kIconTopMargin = 10; 27 28} // namespace 29 30#pragma mark - ContentSuggestionsWhatsNewItem 31 32@implementation ContentSuggestionsWhatsNewItem 33 34@synthesize text = _text; 35@synthesize icon = _icon; 36@synthesize suggestionIdentifier = _suggestionIdentifier; 37@synthesize metricsRecorded = _metricsRecorded; 38 39- (instancetype)initWithType:(NSInteger)type { 40 self = [super initWithType:type]; 41 if (self) { 42 self.cellClass = [ContentSuggestionsWhatsNewCell class]; 43 } 44 return self; 45} 46 47- (void)configureCell:(ContentSuggestionsWhatsNewCell*)cell { 48 [super configureCell:cell]; 49 [cell setIcon:self.icon]; 50 [cell setText:self.text]; 51 cell.accessibilityIdentifier = [[self class] accessibilityIdentifier]; 52} 53 54- (CGFloat)cellHeightForWidth:(CGFloat)width { 55 return [self.cellClass heightForWidth:width withText:self.text]; 56} 57 58+ (NSString*)accessibilityIdentifier { 59 return @"ContentSuggestionsWhatsNewIdentifier"; 60} 61 62@end 63 64#pragma mark - ContentSuggestionsWhatsNewCell 65 66@interface ContentSuggestionsWhatsNewCell () 67 68@property(nonatomic, strong) UIImageView* iconView; 69@property(nonatomic, strong) UILabel* promoLabel; 70@property(nonatomic, strong) UIView* containerView; 71 72@end 73 74@implementation ContentSuggestionsWhatsNewCell 75 76@synthesize iconView = _iconView; 77@synthesize promoLabel = _promoLabel; 78@synthesize containerView = _containerView; 79 80- (instancetype)initWithFrame:(CGRect)frame { 81 self = [super initWithFrame:frame]; 82 if (self) { 83 _iconView = [[UIImageView alloc] init]; 84 _promoLabel = [[UILabel alloc] init]; 85 _containerView = [[UIView alloc] init]; 86 87 _iconView.translatesAutoresizingMaskIntoConstraints = NO; 88 _promoLabel.translatesAutoresizingMaskIntoConstraints = NO; 89 _containerView.translatesAutoresizingMaskIntoConstraints = NO; 90 91 [self.contentView addSubview:_containerView]; 92 [_containerView addSubview:_iconView]; 93 [_containerView addSubview:_promoLabel]; 94 95 ApplyVisualConstraintsWithMetrics( 96 @[ 97 @"V:|-margin-[promo]-margin-|", @"V:|-iconMargin-[icon(==iconSize)]", 98 @"V:|[container]|", @"H:|[icon(==iconSize)]-spacing-[promo]|", 99 @"H:|->=0-[container]->=0-|" 100 ], 101 @{ 102 @"icon" : _iconView, 103 @"promo" : _promoLabel, 104 @"container" : _containerView 105 }, 106 @{ 107 @"margin" : @(kLabelMargin), 108 @"iconMargin" : @(kIconTopMargin), 109 @"iconSize" : @(kIconSize), 110 @"spacing" : @(kLabelIconMargin) 111 }); 112 [NSLayoutConstraint activateConstraints:@[ 113 [_containerView.centerXAnchor 114 constraintEqualToAnchor:self.contentView.centerXAnchor] 115 ]]; 116 } 117 return self; 118} 119 120- (void)setIcon:(UIImage*)icon { 121 self.iconView.image = icon; 122} 123 124- (void)setText:(NSString*)text { 125 [[self class] configureLabel:self.promoLabel withText:text]; 126} 127 128+ (CGFloat)heightForWidth:(CGFloat)width withText:(NSString*)text { 129 UILabel* label = [[UILabel alloc] init]; 130 [self configureLabel:label withText:text]; 131 CGSize sizeForLabel = CGSizeMake(width - kLabelIconMargin - kIconSize, 500); 132 133 return 2 * kLabelMargin + [label sizeThatFits:sizeForLabel].height; 134} 135 136#pragma mark UIView 137 138// Implements -layoutSubviews as per instructions in documentation for 139// +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:]. 140- (void)layoutSubviews { 141 [super layoutSubviews]; 142 143 // Adjust the text label preferredMaxLayoutWidth when the parent's width 144 // changes, for instance on screen rotation. 145 CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds); 146 147 self.promoLabel.preferredMaxLayoutWidth = 148 parentWidth - kIconSize - kLabelIconMargin; 149 150 // Re-layout with the new preferred width to allow the label to adjust its 151 // height. 152 [super layoutSubviews]; 153} 154 155#pragma mark Private 156 157// Configures the |promoLabel| with the |text|. 158+ (void)configureLabel:(UILabel*)promoLabel withText:(NSString*)text { 159 promoLabel.font = 160 [[MDCTypography fontLoader] regularFontOfSize:kLabelFontSize]; 161 promoLabel.textColor = [UIColor colorNamed:kTextPrimaryColor]; 162 promoLabel.numberOfLines = 0; 163 164 NSRange linkRange; 165 NSString* strippedText = ParseStringWithLink(text, &linkRange); 166 DCHECK_NE(NSNotFound, static_cast<NSInteger>(linkRange.location)); 167 DCHECK_NE(0u, linkRange.length); 168 169 NSMutableAttributedString* attributedText = 170 [[NSMutableAttributedString alloc] initWithString:strippedText]; 171 172 // Sets the styling to mimic a link. 173 UIColor* linkColor = [UIColor colorNamed:kBlueColor]; 174 [attributedText addAttribute:NSForegroundColorAttributeName 175 value:linkColor 176 range:linkRange]; 177 [attributedText addAttribute:NSUnderlineStyleAttributeName 178 value:@(NSUnderlineStyleSingle) 179 range:linkRange]; 180 [attributedText addAttribute:NSUnderlineColorAttributeName 181 value:linkColor 182 range:linkRange]; 183 184 // Sets the line spacing on the attributed string. 185 NSInteger strLength = [strippedText length]; 186 NSMutableParagraphStyle* style = [[NSMutableParagraphStyle alloc] init]; 187 [style setLineSpacing:kLabelLineSpacing]; 188 [attributedText addAttribute:NSParagraphStyleAttributeName 189 value:style 190 range:NSMakeRange(0, strLength)]; 191 192 [promoLabel setAttributedText:attributedText]; 193} 194 195@end 196