Index: ios/chrome/browser/translate/before_translate_infobar_controller.mm |
diff --git a/ios/chrome/browser/translate/before_translate_infobar_controller.mm b/ios/chrome/browser/translate/before_translate_infobar_controller.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..635ce0e382d3f33e8dea8cef67ba6f75dfe35590 |
--- /dev/null |
+++ b/ios/chrome/browser/translate/before_translate_infobar_controller.mm |
@@ -0,0 +1,359 @@ |
+// 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. |
+ |
+#include "ios/chrome/browser/translate/before_translate_infobar_controller.h" |
+ |
+#import <UIKit/UIKit.h> |
+ |
+#include "base/logging.h" |
+#include "base/strings/sys_string_conversions.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "components/translate/core/browser/translate_infobar_delegate.h" |
+#include "grit/components_strings.h" |
+#include "ios/chrome/browser/translate/translate_infobar_tags.h" |
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" |
+#import "ios/public/provider/chrome/browser/ui/infobar_view_delegate.h" |
+#import "ios/public/provider/chrome/browser/ui/infobar_view_protocol.h" |
+#include "ui/base/l10n/l10n_util.h" |
+#include "ui/gfx/image/image.h" |
+ |
+namespace { |
+ |
+CGFloat kNavigationBarHeight = 44; |
+CGFloat kUIPickerHeight = 216; |
+CGFloat kUIPickerFontSize = 26; |
+NSTimeInterval kPickerAnimationDurationInSeconds = 0.2; |
+ |
+} // namespace |
+ |
+// The class is a data source and delegate to the UIPickerView that contains the |
+// language list. |
+@interface LanguagePickerController |
+ : UIViewController<UIPickerViewDataSource, UIPickerViewDelegate> { |
+ __weak translate::TranslateInfoBarDelegate* translateInfoBarDelegate_; |
+ NSInteger initialRow_; // Displayed in bold font. |
+ NSInteger disabledRow_; // Grayed out. |
+} |
+@end |
+ |
+@implementation LanguagePickerController |
+ |
+- (instancetype)initWithDelegate:(translate::TranslateInfoBarDelegate*) |
+ translateInfoBarDelegate |
+ initialRow:(NSInteger)initialRow |
+ disabledRow:(NSInteger)disabledRow { |
+ if ((self = [super init])) { |
+ translateInfoBarDelegate_ = translateInfoBarDelegate; |
+ initialRow_ = initialRow; |
+ disabledRow_ = disabledRow; |
+ } |
+ return self; |
+} |
+ |
+#pragma mark - |
+#pragma mark UIPickerViewDataSource |
+ |
+- (NSInteger)pickerView:(UIPickerView*)pickerView |
+ numberOfRowsInComponent:(NSInteger)component { |
+ NSUInteger numRows = translateInfoBarDelegate_->num_languages(); |
+ return numRows; |
+} |
+ |
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView*)pickerView { |
+ return 1; |
+} |
+ |
+#pragma mark - |
+#pragma mark UIPickerViewDelegate |
+ |
+- (UIView*)pickerView:(UIPickerView*)pickerView |
+ viewForRow:(NSInteger)row |
+ forComponent:(NSInteger)component |
+ reusingView:(UIView*)view { |
+ DCHECK_EQ(0, component); |
+ UILabel* label = [view isKindOfClass:[UILabel class]] |
+ ? (UILabel*)view |
+ : [[[UILabel alloc] init] autorelease]; |
+ [label setText:base::SysUTF16ToNSString( |
+ translateInfoBarDelegate_->language_name_at(row))]; |
+ [label setTextAlignment:NSTextAlignmentCenter]; |
+ UIFont* font = [UIFont systemFontOfSize:kUIPickerFontSize]; |
+ BOOL enabled = YES; |
+ if (row == initialRow_) |
+ font = [UIFont boldSystemFontOfSize:kUIPickerFontSize]; |
+ else if (row == disabledRow_) |
+ enabled = NO; |
+ [label setFont:font]; |
+ [label setEnabled:enabled]; |
+ return label; |
+} |
+ |
+@end |
+ |
+@interface BeforeTranslateInfoBarController () |
+ |
+// Action for any of the user defined buttons. |
+- (void)infoBarButtonDidPress:(id)sender; |
+// Action for any of the user defined links. |
+- (void)infobarLinkDidPress:(NSNumber*)tag; |
+// Action for the language selection "Done" button. |
+- (void)languageSelectionDone; |
+// Dismisses the language selection view. |
+- (void)dismissLanguageSelectionView; |
+ |
+@end |
+ |
+@implementation BeforeTranslateInfoBarController { |
+ __weak translate::TranslateInfoBarDelegate* translateInfoBarDelegate_; |
+ // A fullscreen view that catches all touch events and contains a UIPickerView |
+ // and a UINavigationBar. |
+ base::scoped_nsobject<UIView> languageSelectionView_; |
+ // Stores whether the user is currently choosing in the UIPickerView the |
+ // original language, or the target language. |
+ NSUInteger languageSelectionType_; |
+ // The language picker. |
+ base::scoped_nsobject<UIPickerView> languagePicker_; |
+ // Navigation bar associated with the picker with "Done" and "Cancel" buttons. |
+ base::scoped_nsobject<UINavigationBar> navigationBar_; |
+ // The controller of the languagePicker. Needs to be an ivar because |
+ // |languagePicker_| does not retain it. |
+ base::scoped_nsobject<LanguagePickerController> languagePickerController_; |
+} |
+ |
+#pragma mark - |
+#pragma mark InfoBarControllerProtocol |
+ |
+- (void)layoutForDelegate:(infobars::InfoBarDelegate*)delegate |
+ frame:(CGRect)frame { |
+ translateInfoBarDelegate_ = delegate->AsTranslateInfoBarDelegate(); |
+ infobars::InfoBarDelegate* infoBarDelegate = |
+ static_cast<infobars::InfoBarDelegate*>(translateInfoBarDelegate_); |
+ DCHECK(!infoBarView_); |
+ infoBarView_.reset([ios::GetChromeBrowserProvider()->CreateInfoBarView() |
+ initWithFrame:frame |
+ delegate:delegate_ |
+ isWarning:infoBarDelegate->GetInfoBarType() == |
+ infobars::InfoBarDelegate::WARNING_TYPE]); |
+ // Icon |
+ gfx::Image icon = translateInfoBarDelegate_->GetIcon(); |
+ if (!icon.IsEmpty()) |
+ [infoBarView_ addLeftIcon:icon.ToUIImage()]; |
+ |
+ // Main text. |
+ [self updateInfobarLabel]; |
+ |
+ // Close button. |
+ [infoBarView_ addCloseButtonWithTag:TranslateInfoBarIOSTag::BEFORE_DENY |
+ target:self |
+ action:@selector(infoBarButtonDidPress:)]; |
+ // Other buttons. |
+ NSString* buttonAccept = l10n_util::GetNSString(IDS_TRANSLATE_INFOBAR_ACCEPT); |
+ NSString* buttonDeny = l10n_util::GetNSString(IDS_TRANSLATE_INFOBAR_DENY); |
+ [infoBarView_ addButton1:buttonAccept |
+ tag1:TranslateInfoBarIOSTag::BEFORE_ACCEPT |
+ button2:buttonDeny |
+ tag2:TranslateInfoBarIOSTag::BEFORE_DENY |
+ target:self |
+ action:@selector(infoBarButtonDidPress:)]; |
+} |
+ |
+- (void)updateInfobarLabel { |
+ NSString* originalLanguage = |
+ base::SysUTF16ToNSString(translateInfoBarDelegate_->language_name_at( |
+ translateInfoBarDelegate_->original_language_index())); |
+ NSString* targetLanguage = |
+ base::SysUTF16ToNSString(translateInfoBarDelegate_->language_name_at( |
+ translateInfoBarDelegate_->target_language_index())); |
+ base::string16 originalLanguageWithLink = |
+ base::SysNSStringToUTF16([[infoBarView_ class] |
+ stringAsLink:originalLanguage |
+ tag:TranslateInfoBarIOSTag::BEFORE_SOURCE_LANGUAGE]); |
+ base::string16 targetLanguageWithLink = |
+ base::SysNSStringToUTF16([[infoBarView_ class] |
+ stringAsLink:targetLanguage |
+ tag:TranslateInfoBarIOSTag::BEFORE_TARGET_LANGUAGE]); |
+ NSString* label = |
+ l10n_util::GetNSStringF(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE_IOS, |
+ originalLanguageWithLink, targetLanguageWithLink); |
+ [infoBarView_ addLabel:label |
+ target:self |
+ action:@selector(infobarLinkDidPress:)]; |
+} |
+ |
+- (void)languageSelectionDone { |
+ size_t selectedRow = [languagePicker_ selectedRowInComponent:0]; |
+ if (languageSelectionType_ == |
+ TranslateInfoBarIOSTag::BEFORE_SOURCE_LANGUAGE && |
+ selectedRow != translateInfoBarDelegate_->target_language_index()) { |
+ translateInfoBarDelegate_->UpdateOriginalLanguageIndex(selectedRow); |
+ } |
+ if (languageSelectionType_ == |
+ TranslateInfoBarIOSTag::BEFORE_TARGET_LANGUAGE && |
+ selectedRow != translateInfoBarDelegate_->original_language_index()) { |
+ translateInfoBarDelegate_->UpdateTargetLanguageIndex(selectedRow); |
+ } |
+ [self updateInfobarLabel]; |
+ [self dismissLanguageSelectionView]; |
+} |
+ |
+- (void)dismissLanguageSelectionView { |
+ DCHECK_EQ(languagePicker_ == nil, navigationBar_ == nil); |
+ if (languagePicker_ == nil) |
+ return; |
+ // Sets the picker's delegate and data source to nil, because the |
+ // |languagePickerController_| may be destroyed before the picker is hidden, |
+ // and even though the interactions with the picker are disabled, it might |
+ // still be turning and requesting data from the data source or calling the |
+ // delegate. |
+ [languagePicker_ setDataSource:nil]; |
+ [languagePicker_ setDelegate:nil]; |
+ languagePickerController_.reset(); |
+ // Animate the picker away. |
+ CGRect languagePickerFrame = [languagePicker_ frame]; |
+ CGRect navigationBarFrame = [navigationBar_ frame]; |
+ const CGFloat animationHeight = |
+ languagePickerFrame.size.height + navigationBarFrame.size.height; |
+ languagePickerFrame.origin.y += animationHeight; |
+ navigationBarFrame.origin.y += animationHeight; |
+ UIView* blockLanguagePicker = languagePicker_.get(); |
+ UIView* blockNavigationBar = navigationBar_.get(); |
+ void (^animations)(void) = ^{ |
+ blockLanguagePicker.frame = languagePickerFrame; |
+ blockNavigationBar.frame = navigationBarFrame; |
+ }; |
+ languagePicker_.reset(); |
+ navigationBar_.reset(); |
+ void (^completion)(BOOL finished) = ^(BOOL finished) { |
+ [languageSelectionView_ removeFromSuperview]; |
+ languageSelectionView_.reset(); |
+ }; |
+ [UIView animateWithDuration:kPickerAnimationDurationInSeconds |
+ animations:animations |
+ completion:completion]; |
+} |
+ |
+#pragma mark - Handling of User Events |
+ |
+- (void)infoBarButtonDidPress:(id)sender { |
+ // This press might have occurred after the user has already pressed a button, |
+ // in which case the view has been detached from the delegate and this press |
+ // should be ignored. |
+ if (!delegate_) { |
+ return; |
+ } |
+ if ([sender isKindOfClass:[UIButton class]]) { |
+ NSUInteger buttonId = static_cast<UIButton*>(sender).tag; |
+ DCHECK(buttonId == TranslateInfoBarIOSTag::BEFORE_ACCEPT || |
+ buttonId == TranslateInfoBarIOSTag::BEFORE_DENY); |
+ delegate_->InfoBarButtonDidPress(buttonId); |
+ } |
+} |
+ |
+- (void)infobarLinkDidPress:(NSNumber*)tag { |
+ DCHECK([tag isKindOfClass:[NSNumber class]]); |
+ languageSelectionType_ = [tag unsignedIntegerValue]; |
+ DCHECK(languageSelectionType_ == |
+ TranslateInfoBarIOSTag::BEFORE_SOURCE_LANGUAGE || |
+ languageSelectionType_ == |
+ TranslateInfoBarIOSTag::BEFORE_TARGET_LANGUAGE); |
+ if (languagePicker_ != nil) |
+ return; // The UIPickerView is already up. |
+ |
+ // Creates and adds the view containing the UIPickerView and the |
+ // UINavigationBar. |
+ UIView* parentView = |
+ [[UIApplication sharedApplication] keyWindow].rootViewController.view; |
+ // Convert the parent frame to handle device rotation. |
+ CGRect parentFrame = |
+ CGRectApplyAffineTransform([parentView frame], [parentView transform]); |
+ const CGFloat totalPickerHeight = kUIPickerHeight + kNavigationBarHeight; |
+ CGRect languageSelectionViewFrame = |
+ CGRectMake(0, parentFrame.size.height - totalPickerHeight, |
+ parentFrame.size.width, totalPickerHeight); |
+ languageSelectionView_.reset( |
+ [[UIView alloc] initWithFrame:languageSelectionViewFrame]); |
+ [languageSelectionView_ |
+ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | |
+ UIViewAutoresizingFlexibleTopMargin]; |
+ [parentView addSubview:languageSelectionView_]; |
+ |
+ // Creates the navigation bar and its buttons. |
+ CGRect finalPickerFrame = CGRectMake( |
+ 0, [languageSelectionView_ frame].size.height - kUIPickerHeight, |
+ [languageSelectionView_ frame].size.width, kUIPickerHeight); |
+ CGRect finalNavigationBarFrame = CGRectMake( |
+ 0, 0, [languageSelectionView_ frame].size.width, kNavigationBarHeight); |
+ // The language picker animates from the bottom of the screen. |
+ CGRect initialPickerFrame = finalPickerFrame; |
+ initialPickerFrame.origin.y += totalPickerHeight; |
+ CGRect initialNavigationBarFrame = finalNavigationBarFrame; |
+ initialNavigationBarFrame.origin.y += totalPickerHeight; |
+ |
+ navigationBar_.reset( |
+ [[UINavigationBar alloc] initWithFrame:initialNavigationBarFrame]); |
+ const UIViewAutoresizing resizingMask = |
+ UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; |
+ [navigationBar_ setAutoresizingMask:resizingMask]; |
+ base::scoped_nsobject<UIBarButtonItem> doneButton([[UIBarButtonItem alloc] |
+ initWithBarButtonSystemItem:UIBarButtonSystemItemDone |
+ target:self |
+ action:@selector(languageSelectionDone)]); |
+ base::scoped_nsobject<UIBarButtonItem> cancelButton([[UIBarButtonItem alloc] |
+ initWithBarButtonSystemItem:UIBarButtonSystemItemCancel |
+ target:self |
+ action:@selector(dismissLanguageSelectionView)]); |
+ base::scoped_nsobject<UINavigationItem> item( |
+ [[UINavigationItem alloc] initWithTitle:nil]); |
+ [item setRightBarButtonItem:doneButton]; |
+ [item setLeftBarButtonItem:cancelButton]; |
+ [item setHidesBackButton:YES]; |
+ [navigationBar_ pushNavigationItem:item animated:NO]; |
+ |
+ // Creates the PickerView and its controller. |
+ NSInteger selectedRow; |
+ NSInteger disabledRow; |
+ if (languageSelectionType_ == |
+ TranslateInfoBarIOSTag::BEFORE_SOURCE_LANGUAGE) { |
+ selectedRow = translateInfoBarDelegate_->original_language_index(); |
+ disabledRow = translateInfoBarDelegate_->target_language_index(); |
+ } else { |
+ selectedRow = translateInfoBarDelegate_->target_language_index(); |
+ disabledRow = translateInfoBarDelegate_->original_language_index(); |
+ } |
+ languagePickerController_.reset([[LanguagePickerController alloc] |
+ initWithDelegate:translateInfoBarDelegate_ |
+ initialRow:selectedRow |
+ disabledRow:disabledRow]); |
+ languagePicker_.reset( |
+ [[UIPickerView alloc] initWithFrame:initialPickerFrame]); |
+ [languagePicker_ setAutoresizingMask:resizingMask]; |
+ [languagePicker_ setShowsSelectionIndicator:YES]; |
+ [languagePicker_ setDataSource:languagePickerController_]; |
+ [languagePicker_ setDelegate:languagePickerController_]; |
+ [languagePicker_ setShowsSelectionIndicator:YES]; |
+ [languagePicker_ setBackgroundColor:[infoBarView_ backgroundColor]]; |
+ [languagePicker_ selectRow:selectedRow inComponent:0 animated:NO]; |
+ |
+ [UIView animateWithDuration:kPickerAnimationDurationInSeconds |
+ animations:^{ |
+ languagePicker_.get().frame = finalPickerFrame; |
+ navigationBar_.get().frame = finalNavigationBarFrame; |
+ }]; |
+ |
+ // Add the subviews. |
+ [languageSelectionView_ addSubview:languagePicker_]; |
+ [languageSelectionView_ addSubview:navigationBar_]; |
+} |
+ |
+- (void)removeView { |
+ [super removeView]; |
+ [self dismissLanguageSelectionView]; |
+} |
+ |
+- (void)detachView { |
+ [super detachView]; |
+ [self dismissLanguageSelectionView]; |
+} |
+ |
+@end |