// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "ios/chrome/browser/autofill/form_suggestion_label.h" #import <QuartzCore/QuartzCore.h> #include <stddef.h> #include <cmath> #include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" #include "components/autofill/core/browser/credit_card.h" #import "components/autofill/ios/browser/form_suggestion.h" #import "ios/chrome/browser/autofill/form_suggestion_view_client.h" #include "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util.h" namespace { // The button corner radius. const CGFloat kCornerRadius = 2.0f; // Font size of button titles. const CGFloat kIpadFontSize = 15.0f; const CGFloat kIphoneFontSize = 14.0f; // The alpha values of the suggestion's main and description labels. const CGFloat kMainLabelAlpha = 0.87f; const CGFloat kDescriptionLabelAlpha = 0.55f; // The horizontal space between the edge of the background and the text. const CGFloat kBorderWidth = 8.0f; // The space between items in the label. const CGFloat kSpacing = 4.0f; // RGB button color when the button is not pressed. const int kBackgroundNormalColor = 0xeceff1; // RGB button color when the button is pressed. const int kBackgroundPressedColor = 0xc4cbcf; // Structure that record the image for each icon. struct IconImageMap { const char* const icon_name; NSString* image_name; }; const IconImageMap kCreditCardIconImageMap[] = { {autofill::kAmericanExpressCard, @"autofill_card_american_express"}, {autofill::kDiscoverCard, @"autofill_card_discover"}, {autofill::kMasterCard, @"autofill_card_mastercard"}, {autofill::kVisaCard, @"autofill_card_visa"}, {autofill::kDinersCard, @"autofill_card_diners"}, {autofill::kGenericCard, @"autofill_card_generic"}, {autofill::kJCBCard, @"autofill_card_jcb"}, {autofill::kUnionPay, @"autofill_card_unionpay"}, }; // Creates a label with the given |text| and |alpha| suitable for use in a // suggestion button in the keyboard accessory view. UILabel* TextLabel(NSString* text, CGFloat alpha, BOOL bold) { base::scoped_nsobject<UILabel> label([[UILabel alloc] init]); [label setText:text]; CGFloat fontSize = IsIPadIdiom() ? kIpadFontSize : kIphoneFontSize; UIFont* font = bold ? [UIFont boldSystemFontOfSize:fontSize] : [UIFont systemFontOfSize:fontSize]; [label setFont:font]; [label setTextColor:[UIColor colorWithWhite:0.0f alpha:alpha]]; [label setBackgroundColor:[UIColor clearColor]]; [label sizeToFit]; return label.autorelease(); } } // namespace @interface FormSuggestionLabel () // Returns the name of the image for credit card icon. + (NSString*)imageNameForCreditCardIcon:(NSString*)icon; @end @implementation FormSuggestionLabel { // Client of this view. base::WeakNSProtocol<id<FormSuggestionViewClient>> client_; base::scoped_nsobject<FormSuggestion> suggestion_; } - (id)initWithSuggestion:(FormSuggestion*)suggestion proposedFrame:(CGRect)proposedFrame index:(NSUInteger)index numSuggestions:(NSUInteger)numSuggestions client:(id<FormSuggestionViewClient>)client { // TODO(jimblackler): implement sizeThatFits: and layoutSubviews, and perform // layout in those methods instead of in the designated initializer. self = [super initWithFrame:CGRectZero]; if (self) { suggestion_.reset([suggestion retain]); client_.reset(client); const CGFloat frameHeight = CGRectGetHeight(proposedFrame); CGFloat currentX = kBorderWidth; // [UIImage imageNamed:] writes error message if nil is passed. Prevent // console spam by checking the name first. NSString* iconImageName = [FormSuggestionLabel imageNameForCreditCardIcon:suggestion.icon]; UIImage* iconImage = nil; if (iconImageName) iconImage = [UIImage imageNamed:iconImageName]; if (iconImage) { UIImageView* iconView = [[[UIImageView alloc] initWithImage:iconImage] autorelease]; const CGFloat iconY = std::floor((frameHeight - iconImage.size.height) / 2.0f); iconView.frame = CGRectMake(currentX, iconY, iconImage.size.width, iconImage.size.height); [self addSubview:iconView]; currentX += CGRectGetWidth(iconView.frame) + kSpacing; } UILabel* label = TextLabel(suggestion.value, kMainLabelAlpha, YES); const CGFloat labelY = std::floor(frameHeight / 2.0f - CGRectGetMidY(label.frame)); label.frame = CGRectMake(currentX, labelY, CGRectGetWidth(label.frame), CGRectGetHeight(label.frame)); [self addSubview:label]; currentX += CGRectGetWidth(label.frame); if ([suggestion.displayDescription length] > 0) { currentX += kSpacing; UILabel* description = TextLabel(suggestion.displayDescription, kDescriptionLabelAlpha, NO); const CGFloat descriptionY = std::floor(frameHeight / 2.0f - CGRectGetMidY(description.frame)); description.frame = CGRectMake(currentX, descriptionY, CGRectGetWidth(description.frame), CGRectGetHeight(description.frame)); [self addSubview:description]; currentX += CGRectGetWidth(description.frame); } currentX += kBorderWidth; self.frame = CGRectMake(proposedFrame.origin.x, proposedFrame.origin.y, currentX, proposedFrame.size.height); [self setBackgroundColor:UIColorFromRGB(kBackgroundNormalColor)]; [[self layer] setCornerRadius:kCornerRadius]; [self setClipsToBounds:YES]; [self setUserInteractionEnabled:YES]; [self setIsAccessibilityElement:YES]; [self setAccessibilityLabel:l10n_util::GetNSStringF( IDS_IOS_AUTOFILL_ACCNAME_SUGGESTION, base::SysNSStringToUTF16(suggestion.value), base::SysNSStringToUTF16( suggestion.displayDescription), base::IntToString16(index + 1), base::IntToString16(numSuggestions))]; } return self; } - (id)initWithFrame:(CGRect)frame { NOTREACHED(); return nil; } #pragma mark - #pragma mark UIResponder - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { [self setBackgroundColor:UIColorFromRGB(kBackgroundPressedColor)]; } - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { [self setBackgroundColor:UIColorFromRGB(kBackgroundNormalColor)]; } - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { [self setBackgroundColor:UIColorFromRGB(kBackgroundNormalColor)]; [client_ didSelectSuggestion:suggestion_]; } #pragma mark - #pragma mark Private + (NSString*)imageNameForCreditCardIcon:(NSString*)icon { if (!icon || [icon length] == 0) { return nil; } std::string iconName(base::SysNSStringToUTF8(icon)); for (size_t i = 0; i < arraysize(kCreditCardIconImageMap); ++i) { if (iconName.compare(kCreditCardIconImageMap[i].icon_name) == 0) { return kCreditCardIconImageMap[i].image_name; } } return nil; } @end