// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_text_item.h"
#import <stdlib.h>
#import "base/apple/foundation_util.h"
#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/ui/popup_menu/public/popup_menu_ui_constants.h"
#import "ios/chrome/browser/ui/reading_list/number_badge_view.h"
#import "ios/chrome/browser/ui/reading_list/text_badge_view.h"
#import "ios/chrome/common/material_timing.h"
#import "ios/chrome/common/string_util.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
namespace {
const CGFloat kCellHeight = 32;
const CGFloat kMargin = 15;
const CGFloat kTopMargin = 8;
const CGFloat kMaxHeight = 100;
NSMutableAttributedString* GetAttributedString(NSString* imageName,
NSString* message) {
NSDictionary* textAttributes = @{
NSForegroundColorAttributeName : [UIColor colorNamed:kTextSecondaryColor],
NSFontAttributeName :
[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]
};
NSDictionary* linkAttributes = @{
NSForegroundColorAttributeName : [UIColor colorNamed:kBlueColor],
NSFontAttributeName :
[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]
};
// Add a space to have a distance with the leading icon.
NSAttributedString* attributedString = AttributedStringFromStringWithLink(
[@" " stringByAppendingString:message], textAttributes, linkAttributes);
// Create the leading enterprise icon.
NSTextAttachment* attachment = [[NSTextAttachment alloc] init];
attachment.image = [UIImage imageNamed:imageName];
// Making sure the image is well centered vertically relative to the text,
// and also that the image scales with the text size.
CGFloat height = attributedString.size.height;
CGFloat capHeight =
[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote].capHeight;
CGFloat verticalOffset = roundf(capHeight - height) / 2.f;
attachment.bounds = CGRectMake(0, verticalOffset, height, height);
NSMutableAttributedString* outputString = [[NSAttributedString
attributedStringWithAttachment:attachment] mutableCopy];
[outputString appendAttributedString:attributedString];
return outputString;
}
} // namespace
@implementation PopupMenuTextItem
@synthesize actionIdentifier = _actionIdentifier;
- (instancetype)initWithType:(NSInteger)type {
self = [super initWithType:type];
if (self) {
self.cellClass = [PopupMenuTextCell class];
}
return self;
}
- (void)configureCell:(PopupMenuTextCell*)cell
withStyler:(ChromeTableViewStyler*)styler {
[super configureCell:cell withStyler:styler];
cell.userInteractionEnabled = YES;
NSMutableAttributedString* StringOfCell =
GetAttributedString(self.imageName, self.message);
cell.messageAttributedString = StringOfCell;
cell.messageLabel.attributedText = StringOfCell;
}
#pragma mark - PopupMenuItem
- (CGSize)cellSizeForWidth:(CGFloat)width {
// TODO(crbug.com/41380449): This should be done at the table view level.
static PopupMenuTextCell* cell;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cell = [[PopupMenuTextCell alloc] init];
[cell registerForContentSizeUpdates];
});
[self configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
cell.frame = CGRectMake(0, 0, width, kMaxHeight);
[cell setNeedsLayout];
[cell layoutIfNeeded];
return [cell systemLayoutSizeFittingSize:CGSizeMake(width, kMaxHeight)];
}
@end
#pragma mark - PopupMenuTextCell
@implementation PopupMenuTextCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString*)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UIView* selectedBackgroundView = [[UIView alloc] init];
selectedBackgroundView.backgroundColor =
[UIColor colorNamed:kTableViewRowHighlightColor];
self.selectedBackgroundView = selectedBackgroundView;
_messageLabel = [[UILabel alloc] init];
_messageLabel.numberOfLines = 0;
_messageLabel.translatesAutoresizingMaskIntoConstraints = NO;
_messageLabel.adjustsFontForContentSizeCategory = YES;
[self.contentView addSubview:_messageLabel];
[NSLayoutConstraint activateConstraints:@[
[_messageLabel.centerYAnchor
constraintEqualToAnchor:self.contentView.centerYAnchor],
[self.contentView.heightAnchor
constraintGreaterThanOrEqualToConstant:kCellHeight],
]];
ApplyVisualConstraintsWithMetrics(
@[
@"H:|-(margin)-[label]-(>=margin)-|",
@"V:|-(>=topMargin)-[label]-(>=topMargin)-|"
],
@{
@"label" : self.messageLabel,
},
@{
@"margin" : @(kMargin),
@"topMargin" : @(kTopMargin),
});
// The height constraint is used to have something as small as possible when
// calculating the size of the prototype cell.
NSLayoutConstraint* heightConstraint =
[self.contentView.heightAnchor constraintEqualToConstant:kCellHeight];
heightConstraint.priority = UILayoutPriorityDefaultLow;
heightConstraint.active = YES;
}
return self;
}
- (void)registerForContentSizeUpdates {
// This is needed because if the cell is static (used for height),
// adjustsFontForContentSizeCategory isn't working.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(preferredContentSizeDidChange:)
name:UIContentSizeCategoryDidChangeNotification
object:nil];
}
#pragma mark - UIView
- (void)layoutSubviews {
[super layoutSubviews];
// Adjust the text label preferredMaxLayoutWidth when the parent's width
// changes, for instance on screen rotation.
CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds);
self.messageLabel.preferredMaxLayoutWidth = parentWidth - kMargin * 2;
// Re-layout with the new preferred width to allow the label to adjust its
// height.
[super layoutSubviews];
}
#pragma mark - UITableViewCell
- (void)prepareForReuse {
[super prepareForReuse];
self.userInteractionEnabled = NO;
self.accessibilityTraits &= ~UIAccessibilityTraitNotEnabled;
}
#pragma mark - Accessibility
- (NSString*)accessibilityLabel {
return self.messageAttributedString.string;
}
#pragma mark - Private
// Callback when the preferred Content Size change.
- (void)preferredContentSizeDidChange:(NSNotification*)notification {
self.messageLabel.attributedText = self.messageAttributedString;
}
@end