Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(570)

Side by Side Diff: ios/chrome/browser/translate/before_translate_infobar_controller.mm

Issue 809333003: Upstream //ios/chrome/browser/translate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update grit whitelist Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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 #include "ios/chrome/browser/translate/before_translate_infobar_controller.h"
6
7 #import <UIKit/UIKit.h>
8
9 #include "base/logging.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/translate/core/browser/translate_infobar_delegate.h"
13 #include "grit/components_strings.h"
14 #include "ios/chrome/browser/translate/translate_infobar_tags.h"
15 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
16 #import "ios/public/provider/chrome/browser/ui/infobar_view_delegate.h"
17 #import "ios/public/provider/chrome/browser/ui/infobar_view_protocol.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/gfx/image/image.h"
20
21 namespace {
22
23 CGFloat kNavigationBarHeight = 44;
24 CGFloat kUIPickerHeight = 216;
25 CGFloat kUIPickerFontSize = 26;
26 NSTimeInterval kPickerAnimationDurationInSeconds = 0.2;
27
28 } // namespace
29
30 // The class is a data source and delegate to the UIPickerView that contains the
31 // language list.
32 @interface LanguagePickerController
33 : UIViewController<UIPickerViewDataSource, UIPickerViewDelegate> {
34 __weak translate::TranslateInfoBarDelegate* translateInfoBarDelegate_;
35 NSInteger initialRow_; // Displayed in bold font.
36 NSInteger disabledRow_; // Grayed out.
37 }
38 @end
39
40 @implementation LanguagePickerController
41
42 - (instancetype)initWithDelegate:(translate::TranslateInfoBarDelegate*)
43 translateInfoBarDelegate
44 initialRow:(NSInteger)initialRow
45 disabledRow:(NSInteger)disabledRow {
46 if ((self = [super init])) {
47 translateInfoBarDelegate_ = translateInfoBarDelegate;
48 initialRow_ = initialRow;
49 disabledRow_ = disabledRow;
50 }
51 return self;
52 }
53
54 #pragma mark -
55 #pragma mark UIPickerViewDataSource
56
57 - (NSInteger)pickerView:(UIPickerView*)pickerView
58 numberOfRowsInComponent:(NSInteger)component {
59 NSUInteger numRows = translateInfoBarDelegate_->num_languages();
60 return numRows;
61 }
62
63 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView*)pickerView {
64 return 1;
65 }
66
67 #pragma mark -
68 #pragma mark UIPickerViewDelegate
69
70 - (UIView*)pickerView:(UIPickerView*)pickerView
71 viewForRow:(NSInteger)row
72 forComponent:(NSInteger)component
73 reusingView:(UIView*)view {
74 DCHECK_EQ(0, component);
75 UILabel* label = [view isKindOfClass:[UILabel class]]
76 ? (UILabel*)view
77 : [[[UILabel alloc] init] autorelease];
78 [label setText:base::SysUTF16ToNSString(
79 translateInfoBarDelegate_->language_name_at(row))];
80 [label setTextAlignment:NSTextAlignmentCenter];
81 UIFont* font = [UIFont systemFontOfSize:kUIPickerFontSize];
82 BOOL enabled = YES;
83 if (row == initialRow_)
84 font = [UIFont boldSystemFontOfSize:kUIPickerFontSize];
85 else if (row == disabledRow_)
86 enabled = NO;
87 [label setFont:font];
88 [label setEnabled:enabled];
89 return label;
90 }
91
92 @end
93
94 @interface BeforeTranslateInfoBarController ()
95
96 // Action for any of the user defined buttons.
97 - (void)infoBarButtonDidPress:(id)sender;
98 // Action for any of the user defined links.
99 - (void)infobarLinkDidPress:(NSNumber*)tag;
100 // Action for the language selection "Done" button.
101 - (void)languageSelectionDone;
102 // Dismisses the language selection view.
103 - (void)dismissLanguageSelectionView;
104
105 @end
106
107 @implementation BeforeTranslateInfoBarController {
108 __weak translate::TranslateInfoBarDelegate* translateInfoBarDelegate_;
109 // A fullscreen view that catches all touch events and contains a UIPickerView
110 // and a UINavigationBar.
111 base::scoped_nsobject<UIView> languageSelectionView_;
112 // Stores whether the user is currently choosing in the UIPickerView the
113 // original language, or the target language.
114 NSUInteger languageSelectionType_;
115 // The language picker.
116 base::scoped_nsobject<UIPickerView> languagePicker_;
117 // Navigation bar associated with the picker with "Done" and "Cancel" buttons.
118 base::scoped_nsobject<UINavigationBar> navigationBar_;
119 // The controller of the languagePicker. Needs to be an ivar because
120 // |languagePicker_| does not retain it.
121 base::scoped_nsobject<LanguagePickerController> languagePickerController_;
122 }
123
124 #pragma mark -
125 #pragma mark InfoBarControllerProtocol
126
127 - (void)layoutForDelegate:(infobars::InfoBarDelegate*)delegate
128 frame:(CGRect)frame {
129 translateInfoBarDelegate_ = delegate->AsTranslateInfoBarDelegate();
130 infobars::InfoBarDelegate* infoBarDelegate =
131 static_cast<infobars::InfoBarDelegate*>(translateInfoBarDelegate_);
132 DCHECK(!infoBarView_);
133 infoBarView_.reset([ios::GetChromeBrowserProvider()->CreateInfoBarView()
134 initWithFrame:frame
135 delegate:delegate_
136 isWarning:infoBarDelegate->GetInfoBarType() ==
137 infobars::InfoBarDelegate::WARNING_TYPE]);
138 // Icon
139 gfx::Image icon = translateInfoBarDelegate_->GetIcon();
140 if (!icon.IsEmpty())
141 [infoBarView_ addLeftIcon:icon.ToUIImage()];
142
143 // Main text.
144 [self updateInfobarLabel];
145
146 // Close button.
147 [infoBarView_ addCloseButtonWithTag:TranslateInfoBarIos::BEFORE_DENY
148 target:self
149 action:@selector(infoBarButtonDidPress:)];
150 // Other buttons.
151 NSString* buttonAccept = l10n_util::GetNSString(IDS_TRANSLATE_INFOBAR_ACCEPT);
152 NSString* buttonDeny = l10n_util::GetNSString(IDS_TRANSLATE_INFOBAR_DENY);
153 [infoBarView_ addButton1:buttonAccept
154 tag1:TranslateInfoBarIos::BEFORE_ACCEPT
155 button2:buttonDeny
156 tag2:TranslateInfoBarIos::BEFORE_DENY
157 target:self
158 action:@selector(infoBarButtonDidPress:)];
159 }
160
161 - (void)updateInfobarLabel {
162 NSString* originalLanguage =
163 base::SysUTF16ToNSString(translateInfoBarDelegate_->language_name_at(
164 translateInfoBarDelegate_->original_language_index()));
165 NSString* targetLanguage =
166 base::SysUTF16ToNSString(translateInfoBarDelegate_->language_name_at(
167 translateInfoBarDelegate_->target_language_index()));
168 base::string16 originalLanguageWithLink =
169 base::SysNSStringToUTF16([[infoBarView_ class]
170 stringAsLink:originalLanguage
171 tag:TranslateInfoBarIos::BEFORE_SOURCE_LANGUAGE]);
172 base::string16 targetLanguageWithLink =
173 base::SysNSStringToUTF16([[infoBarView_ class]
174 stringAsLink:targetLanguage
175 tag:TranslateInfoBarIos::BEFORE_TARGET_LANGUAGE]);
176 NSString* label =
177 l10n_util::GetNSStringF(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE_IOS,
178 originalLanguageWithLink, targetLanguageWithLink);
179 [infoBarView_ addLabel:label
180 target:self
181 action:@selector(infobarLinkDidPress:)];
182 }
183
184 - (void)languageSelectionDone {
185 size_t selectedRow = [languagePicker_ selectedRowInComponent:0];
186 if (languageSelectionType_ == TranslateInfoBarIos::BEFORE_SOURCE_LANGUAGE &&
187 selectedRow != translateInfoBarDelegate_->target_language_index()) {
188 translateInfoBarDelegate_->UpdateOriginalLanguageIndex(selectedRow);
189 }
190 if (languageSelectionType_ == TranslateInfoBarIos::BEFORE_TARGET_LANGUAGE &&
191 selectedRow != translateInfoBarDelegate_->original_language_index()) {
192 translateInfoBarDelegate_->UpdateTargetLanguageIndex(selectedRow);
193 }
194 // TODO(translate): Update the position of the infobar.
sdefresne 2015/01/08 09:22:33 nit: is this still relevant? is there a tracking b
195 [self updateInfobarLabel];
196 [self dismissLanguageSelectionView];
197 }
198
199 - (void)dismissLanguageSelectionView {
200 DCHECK_EQ(languagePicker_ == nil, navigationBar_ == nil);
201 if (languagePicker_ == nil)
202 return;
203 // Sets the picker's delegate and data source to nil, because the
204 // |languagePickerController_| may be destroyed before the picker is hidden,
205 // and even though the interactions with the picker are disabled, it might
206 // still be turning and requesting data from the data source or calling the
207 // delegate.
208 [languagePicker_ setDataSource:nil];
209 [languagePicker_ setDelegate:nil];
210 languagePickerController_.reset();
211 // Animate the picker away.
212 CGRect languagePickerFrame = [languagePicker_ frame];
213 CGRect navigationBarFrame = [navigationBar_ frame];
214 const CGFloat animationHeight =
215 languagePickerFrame.size.height + navigationBarFrame.size.height;
216 languagePickerFrame.origin.y += animationHeight;
217 navigationBarFrame.origin.y += animationHeight;
218 UIView* blockLanguagePicker = languagePicker_.get();
219 UIView* blockNavigationBar = navigationBar_.get();
220 languagePicker_.reset();
sdefresne 2015/01/08 09:22:33 I'm afraid that this may lead to blockLanguagePick
droger 2015/01/08 11:57:33 Right. I think it's not a problem in practice beca
221 navigationBar_.reset();
222 void (^animations)(void) = ^{
223 blockLanguagePicker.frame = languagePickerFrame;
224 blockNavigationBar.frame = navigationBarFrame;
225 };
226 void (^completion)(BOOL finished) = ^(BOOL finished) {
227 [languageSelectionView_ removeFromSuperview];
sdefresne 2015/01/08 09:22:33 animations block goes to great length to avoid kee
droger 2015/01/08 11:57:33 I would rather not change this one as part of upst
228 languageSelectionView_.reset();
229 };
230 [UIView animateWithDuration:kPickerAnimationDurationInSeconds
231 animations:animations
232 completion:completion];
233 }
234
235 #pragma mark - Handling of User Events
236
237 - (void)infoBarButtonDidPress:(id)sender {
238 // This press might have occurred after the user has already pressed a button,
239 // in which case the view has been detached from the delegate and this press
240 // should be ignored.
241 if (!delegate_) {
242 return;
243 }
244 if ([sender isKindOfClass:[UIButton class]]) {
245 NSUInteger buttonId = static_cast<UIButton*>(sender).tag;
246 DCHECK(buttonId == TranslateInfoBarIos::BEFORE_ACCEPT ||
247 buttonId == TranslateInfoBarIos::BEFORE_DENY);
248 delegate_->InfoBarButtonDidPress(buttonId);
249 }
250 }
251
252 - (void)infobarLinkDidPress:(NSNumber*)tag {
253 DCHECK([tag isKindOfClass:[NSNumber class]]);
254 languageSelectionType_ = [tag unsignedIntegerValue];
255 DCHECK(languageSelectionType_ ==
256 TranslateInfoBarIos::BEFORE_SOURCE_LANGUAGE ||
257 languageSelectionType_ == TranslateInfoBarIos::BEFORE_TARGET_LANGUAGE);
258 if (languagePicker_ != nil)
259 return; // The UIPickerView is already up.
260
261 // Creates and adds the view containing the UIPickerView and the
262 // UINavigationBar.
263 UIView* parentView =
264 [[UIApplication sharedApplication] keyWindow].rootViewController.view;
265 // Convert the parent frame to handle device rotation.
266 CGRect parentFrame =
267 CGRectApplyAffineTransform([parentView frame], [parentView transform]);
268 const CGFloat totalPickerHeight = kUIPickerHeight + kNavigationBarHeight;
269 CGRect languageSelectionViewFrame =
270 CGRectMake(0, parentFrame.size.height - totalPickerHeight,
271 parentFrame.size.width, totalPickerHeight);
272 languageSelectionView_.reset(
273 [[UIView alloc] initWithFrame:languageSelectionViewFrame]);
274 [languageSelectionView_
275 setAutoresizingMask:UIViewAutoresizingFlexibleWidth |
276 UIViewAutoresizingFlexibleTopMargin];
277 [parentView addSubview:languageSelectionView_];
278
279 // Creates the navigation bar and its buttons.
280 CGRect finalPickerFrame = CGRectMake(
281 0, [languageSelectionView_ frame].size.height - kUIPickerHeight,
282 [languageSelectionView_ frame].size.width, kUIPickerHeight);
283 CGRect finalNavigationBarFrame = CGRectMake(
284 0, 0, [languageSelectionView_ frame].size.width, kNavigationBarHeight);
285 // The language picker animates from the bottom of the screen.
286 CGRect initialPickerFrame = finalPickerFrame;
287 initialPickerFrame.origin.y += totalPickerHeight;
288 CGRect initialNavigationBarFrame = finalNavigationBarFrame;
289 initialNavigationBarFrame.origin.y += totalPickerHeight;
290
291 navigationBar_.reset(
292 [[UINavigationBar alloc] initWithFrame:initialNavigationBarFrame]);
293 const UIViewAutoresizing resizingMask =
294 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
295 [navigationBar_ setAutoresizingMask:resizingMask];
296 base::scoped_nsobject<UIBarButtonItem> doneButton([[UIBarButtonItem alloc]
297 initWithBarButtonSystemItem:UIBarButtonSystemItemDone
298 target:self
299 action:@selector(languageSelectionDone)]);
300 base::scoped_nsobject<UIBarButtonItem> cancelButton([[UIBarButtonItem alloc]
301 initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
302 target:self
303 action:@selector(dismissLanguageSelectionView)]);
304 base::scoped_nsobject<UINavigationItem> item(
305 [[UINavigationItem alloc] initWithTitle:nil]);
306 [item setRightBarButtonItem:doneButton];
307 [item setLeftBarButtonItem:cancelButton];
308 [item setHidesBackButton:YES];
309 [navigationBar_ pushNavigationItem:item animated:NO];
310
311 // Creates the PickerView and its controller.
312 NSInteger selectedRow;
313 NSInteger disabledRow;
314 if (languageSelectionType_ == TranslateInfoBarIos::BEFORE_SOURCE_LANGUAGE) {
315 selectedRow = translateInfoBarDelegate_->original_language_index();
316 disabledRow = translateInfoBarDelegate_->target_language_index();
317 } else {
318 selectedRow = translateInfoBarDelegate_->target_language_index();
319 disabledRow = translateInfoBarDelegate_->original_language_index();
320 }
321 languagePickerController_.reset([[LanguagePickerController alloc]
322 initWithDelegate:translateInfoBarDelegate_
323 initialRow:selectedRow
324 disabledRow:disabledRow]);
325 languagePicker_.reset(
326 [[UIPickerView alloc] initWithFrame:initialPickerFrame]);
327 [languagePicker_ setAutoresizingMask:resizingMask];
328 [languagePicker_ setShowsSelectionIndicator:YES];
329 [languagePicker_ setDataSource:languagePickerController_];
330 [languagePicker_ setDelegate:languagePickerController_];
331 [languagePicker_ setShowsSelectionIndicator:YES];
332 [languagePicker_ setBackgroundColor:[infoBarView_ backgroundColor]];
333 [languagePicker_ selectRow:selectedRow inComponent:0 animated:NO];
334
335 [UIView animateWithDuration:kPickerAnimationDurationInSeconds
336 animations:^{
337 languagePicker_.get().frame = finalPickerFrame;
338 navigationBar_.get().frame = finalNavigationBarFrame;
339 }];
340
341 // Add the subviews.
342 [languageSelectionView_ addSubview:languagePicker_];
343 [languageSelectionView_ addSubview:navigationBar_];
344 }
345
346 - (void)removeView {
347 [super removeView];
348 [self dismissLanguageSelectionView];
349 }
350
351 - (void)detachView {
352 [super detachView];
353 [self dismissLanguageSelectionView];
354 }
355
356 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698