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

Side by Side Diff: ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm

Issue 2588733002: Upstream Chrome on iOS source code [9/11]. (Closed)
Patch Set: Created 4 years 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 2015 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/tab_switcher/tab_switcher_panel_cell.h"
6
7 #include "base/mac/scoped_nsobject.h"
8 #import "ios/chrome/browser/tabs/tab.h"
9 #import "ios/chrome/browser/ui/fade_truncated_label.h"
10 #import "ios/chrome/browser/ui/image_util.h"
11 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_button.h"
12 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_cache.h"
13 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_utils.h"
14 #import "ios/chrome/browser/ui/uikit_ui_util.h"
15 #include "ios/chrome/grit/ios_strings.h"
16 #include "ios/chrome/grit/ios_theme_resources.h"
17 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat erialPalettes.h"
18 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoF ontLoader.h"
19 #import "ios/third_party/material_text_accessibility_ios/src/src/MDFTextAccessib ility.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/image/image.h"
23 #include "url/gurl.h"
24
25 namespace gfx {
26 class ImageSkia;
27 }
28
29 namespace {
30 const CGFloat kFontSize = 16;
31 const CGFloat kCellCornerRadius = 2;
32 const CGFloat kBarHeight = 44;
33 const CGFloat kTitleLabelTextAlpha = .54;
34 const CGFloat kNewTabIconAlpha = .87;
35 } // Anonymous namespace
36
37 CGFloat tabSwitcherLocalSessionCellTopBarHeight() {
38 return kBarHeight;
39 }
40
41 @interface TabSwitcherSessionCell ()
42
43 // Returns the container view with rounded corners to which all cell subviews
44 // should be added.
45 - (UIView*)containerView;
46
47 @end
48
49 @implementation TabSwitcherSessionCell {
50 base::scoped_nsobject<UIView> _containerView;
51 CGSize _cachedShadowSize;
52 }
53
54 // Returns the cell's identifier used for the cell's re-use.
55 + (NSString*)identifier {
56 return NSStringFromClass([self class]);
57 }
58
59 - (instancetype)initWithFrame:(CGRect)frame {
60 self = [super initWithFrame:frame];
61 if (self) {
62 [self contentView].isAccessibilityElement = YES;
63 _containerView.reset([[UIView alloc] initWithFrame:self.bounds]);
64 [_containerView setAutoresizingMask:UIViewAutoresizingFlexibleHeight |
65 UIViewAutoresizingFlexibleWidth];
66 [[_containerView layer] setCornerRadius:kCellCornerRadius];
67 [[_containerView layer] setMasksToBounds:YES];
68 [[self contentView] addSubview:_containerView];
69 [self updateShadow];
70 [[[self contentView] layer] setShouldRasterize:YES];
71 [[[self contentView] layer]
72 setRasterizationScale:[[UIScreen mainScreen] scale]];
73 }
74 return self;
75 }
76
77 - (void)layoutSubviews {
78 [super layoutSubviews];
79 [self updateShadow];
80 }
81
82 - (void)updateShadow {
83 if (!CGSizeEqualToSize(_cachedShadowSize, self.bounds.size)) {
84 CGRect offsetedRectangle = CGRectOffset(self.bounds, 0, 6);
85 UIBezierPath* shadowPath =
86 [UIBezierPath bezierPathWithRoundedRect:offsetedRectangle
87 cornerRadius:kCellCornerRadius];
88 [[self contentView].layer setShadowPath:shadowPath.CGPath];
89 [[self contentView].layer setShadowColor:[UIColor blackColor].CGColor];
90 [[self contentView].layer setShadowOpacity:0.5];
91 _cachedShadowSize = self.bounds.size;
92 }
93 }
94
95 - (UIView*)containerView {
96 return _containerView.get();
97 }
98
99 @end
100
101 @implementation TabSwitcherLocalSessionCell {
102 base::scoped_nsobject<UIView> _topBar;
103 base::scoped_nsobject<UILabel> _titleLabel;
104 base::scoped_nsobject<UIImageView> _favicon;
105 base::scoped_nsobject<UIButton> _closeButton;
106 base::scoped_nsobject<UIImageView> _shadow;
107 base::scoped_nsobject<UIImageView> _snapshot;
108 base::scoped_nsobject<TabSwitcherButton> _snapshotButton;
109 PendingSnapshotRequest _currentPendingSnapshotRequest;
110 id<SessionCellDelegate> _delegate; // weak
111 }
112
113 - (instancetype)initWithFrame:(CGRect)frame {
114 self = [super initWithFrame:frame];
115 if (self) {
116 // Top bar.
117 _topBar.reset([[UIView alloc] initWithFrame:CGRectZero]);
118 [_topBar setTranslatesAutoresizingMaskIntoConstraints:NO];
119 [[self containerView] addSubview:_topBar];
120
121 // Snapshot view.
122 _snapshot.reset([[UIImageView alloc] initWithFrame:CGRectZero]);
123 [_snapshot setTranslatesAutoresizingMaskIntoConstraints:NO];
124 [_snapshot setContentMode:UIViewContentModeScaleAspectFill];
125 [_snapshot setClipsToBounds:YES];
126 [[self containerView] addSubview:_snapshot];
127
128 // Cell button.
129 _snapshotButton.reset([[TabSwitcherButton alloc] initWithFrame:CGRectZero]);
130 [_snapshotButton setTranslatesAutoresizingMaskIntoConstraints:NO];
131 [_snapshotButton addTarget:self
132 action:@selector(snapshotPressed)
133 forControlEvents:UIControlEventTouchUpInside];
134 [[self containerView] addSubview:_snapshotButton];
135
136 // Shadow view.
137 _shadow.reset([[UIImageView alloc] initWithFrame:CGRectZero]);
138 [_shadow setTranslatesAutoresizingMaskIntoConstraints:NO];
139 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
140 gfx::Image shadow = rb.GetNativeImageNamed(IDR_IOS_TOOLBAR_SHADOW);
141 [_shadow setImage:shadow.ToUIImage()];
142 [[self containerView] addSubview:_shadow];
143
144 // Constraints on the Top bar, snapshot view, and shadow view.
145 NSDictionary* viewsDictionary = @{
146 @"bar" : _topBar.get(),
147 @"shadow" : _shadow.get(),
148 @"snapshot" : _snapshot.get(),
149 @"snapshotButton" : _snapshotButton.get(),
150 };
151 NSArray* constraints = @[
152 @"H:|-0-[bar]-0-|",
153 @"H:|-0-[shadow]-0-|",
154 @"H:|-0-[snapshot]-0-|",
155 @"H:|-0-[snapshotButton]-0-|",
156 @"V:|-0-[bar(==barHeight)]-0-[snapshot]-0-|",
157 @"V:[bar]-0-[snapshotButton]-0-|",
158 @"V:[bar]-0-[shadow]",
159 ];
160 NSDictionary* metrics =
161 @{ @"barHeight" : @(tabSwitcherLocalSessionCellTopBarHeight()) };
162 ApplyVisualConstraintsWithMetrics(constraints, viewsDictionary, metrics,
163 [self containerView]);
164
165 // Create and add subviews to the cell bar.
166 // Title label.
167 _titleLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]);
168 [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
169 [_titleLabel setFont:[[MDFRobotoFontLoader sharedInstance]
170 regularFontOfSize:kFontSize]];
171 [_topBar addSubview:_titleLabel];
172
173 // Favicon.
174 _favicon.reset([[UIImageView alloc] initWithFrame:CGRectZero]);
175 [_favicon setTranslatesAutoresizingMaskIntoConstraints:NO];
176 [_topBar addSubview:_favicon];
177
178 // Close button.
179 _closeButton.reset([[UIButton alloc] initWithFrame:CGRectZero]);
180 [_closeButton
181 setImage:[[UIImage imageNamed:@"card_close_button"]
182 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]
183 forState:UIControlStateNormal];
184 [_closeButton setTranslatesAutoresizingMaskIntoConstraints:NO];
185 [_closeButton addTarget:self
186 action:@selector(closeButtonPressed)
187 forControlEvents:UIControlEventTouchUpInside];
188 [_closeButton setExclusiveTouch:YES];
189 [_topBar addSubview:_closeButton];
190
191 // Constraints on the title label, favicon, and close button.
192 NSDictionary* barViewsDictionary = @{
193 @"favicon" : _favicon.get(),
194 @"title" : _titleLabel.get(),
195 @"closeButton" : _closeButton.get()
196 };
197 NSArray* barConstraints = @[
198 @"H:|-16-[favicon(==24)]-8-[title]-0-[closeButton(==32)]-8-|",
199 @"V:[favicon(==24)]",
200 @"V:[closeButton(==32)]",
201 ];
202 ApplyVisualConstraints(barConstraints, barViewsDictionary, _topBar);
203 AddSameCenterYConstraint(_topBar, _favicon);
204 AddSameCenterYConstraint(_topBar, _titleLabel);
205 AddSameCenterYConstraint(_topBar, _closeButton);
206 }
207 return self;
208 }
209
210 - (UIView*)topBar {
211 return _topBar.get();
212 }
213
214 - (UIImage*)screenshot {
215 return [_snapshot image];
216 }
217
218 - (void)setSnapshot:(UIImage*)image {
219 DCHECK(!ImageHasAlphaChannel(image));
220 [_snapshot setImage:image];
221 }
222
223 - (void)setAppearanceForTab:(Tab*)tab cellSize:(CGSize)cellSize {
224 [_titleLabel setText:tab.title];
225 [self contentView].accessibilityLabel = tab.title;
226 if (tab.favicon) {
227 [_favicon setImage:tab.favicon];
228 } else {
229 // No favicon is available, use placeholder instead.
230 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
231 [_favicon
232 setImage:rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_HTTP).ToUIImage()];
233 }
234
235 CGSize snapshotSize = cellSize;
236 snapshotSize.height -= tabSwitcherLocalSessionCellTopBarHeight();
237 base::WeakNSObject<TabSwitcherLocalSessionCell> weakCell(self);
238 _currentPendingSnapshotRequest =
239 [[self cache] requestSnapshotForTab:tab
240 withSize:snapshotSize
241 completionBlock:^(UIImage* image) {
242 DCHECK([NSThread isMainThread]);
243 [weakCell setSnapshot:image];
244 _currentPendingSnapshotRequest = {};
245 }];
246 }
247
248 - (void)setSessionType:(ios_internal::SessionType)type {
249 UIColor* topBarBackgroundColor;
250 UIColor* closeButtonTintColor;
251 UIColor* textColor;
252 UIColor* snapshotBackgroundColor;
253 if (type == ios_internal::SessionType::OFF_THE_RECORD_SESSION) {
254 topBarBackgroundColor = [[MDCPalette greyPalette] tint700];
255 closeButtonTintColor = [[MDCPalette greyPalette] tint100];
256 textColor = [[MDCPalette greyPalette] tint100];
257 snapshotBackgroundColor = [[MDCPalette greyPalette] tint900];
258 } else {
259 topBarBackgroundColor = [[MDCPalette greyPalette] tint100];
260 closeButtonTintColor = [[MDCPalette greyPalette] tint700];
261 textColor = [[MDCPalette greyPalette] tint700];
262 snapshotBackgroundColor = [UIColor whiteColor];
263 }
264 [_topBar setBackgroundColor:topBarBackgroundColor];
265 [[_closeButton imageView] setTintColor:closeButtonTintColor];
266 [_titleLabel setTextColor:textColor];
267 [_titleLabel setBackgroundColor:topBarBackgroundColor];
268 [_snapshot setBackgroundColor:snapshotBackgroundColor];
269 }
270
271 - (void)setDelegate:(id<SessionCellDelegate>)delegate {
272 _delegate = delegate;
273 }
274
275 - (void)snapshotPressed {
276 [_delegate cellPressed:self];
277 }
278
279 - (void)closeButtonPressed {
280 [_delegate deleteButtonPressedForCell:self];
281 }
282
283 - (void)prepareForReuse {
284 [[self cache] cancelPendingSnapshotRequest:_currentPendingSnapshotRequest];
285 _currentPendingSnapshotRequest.clear();
286 [_snapshot setImage:nil];
287 [_snapshotButton resetState];
288 [super prepareForReuse];
289 }
290
291 - (TabSwitcherCache*)cache {
292 return [_delegate tabSwitcherCache];
293 }
294
295 #pragma mark - UIAccessibilityAction
296
297 - (NSArray*)accessibilityCustomActions {
298 base::scoped_nsobject<NSMutableArray> customActions(
299 [[NSMutableArray alloc] init]);
300 base::scoped_nsobject<UIAccessibilityCustomAction> customAction(
301 [[UIAccessibilityCustomAction alloc]
302 initWithName:l10n_util::GetNSString(IDS_IOS_TAB_SWITCHER_CLOSE_TAB)
303 target:self
304 selector:@selector(closeButtonPressed)]);
305 [customActions addObject:customAction.autorelease()];
306 return customActions.autorelease();
307 }
308
309 @end
310
311 @implementation TabSwitcherDistantSessionCell {
312 base::scoped_nsobject<UILabel> _titleLabel;
313 base::scoped_nsobject<UIImageView> _favicon;
314 base::scoped_nsobject<UIImageView> _newTabIcon;
315 base::scoped_nsobject<UIView> _verticallyCenteredView;
316 base::scoped_nsobject<TabSwitcherButton> _raisedButton;
317 base::scoped_nsobject<NSOperation> _faviconObtainer;
318 id<SessionCellDelegate> _delegate; // weak
319 }
320
321 - (instancetype)initWithFrame:(CGRect)frame {
322 self = [super initWithFrame:frame];
323 if (self) {
324 // Create and add the button that contains all other subviews.
325 _raisedButton.reset([[TabSwitcherButton alloc] initWithFrame:CGRectZero]);
326 [_raisedButton setTranslatesAutoresizingMaskIntoConstraints:NO];
327 [_raisedButton addTarget:self
328 action:@selector(cellPressed)
329 forControlEvents:UIControlEventTouchUpInside];
330 [[self containerView] addSubview:_raisedButton];
331 ApplyVisualConstraints(@[ @"H:|-0-[button]-0-|", @"V:|-0-[button]-0-|" ],
332 @{ @"button" : _raisedButton.get() },
333 [self containerView]);
334
335 // Create and add view that will be vertically centered in the space over
336 // the favicon.
337 _verticallyCenteredView.reset([[UIView alloc] initWithFrame:CGRectZero]);
338 [_verticallyCenteredView setTranslatesAutoresizingMaskIntoConstraints:NO];
339 [_verticallyCenteredView setUserInteractionEnabled:NO];
340 [_raisedButton addSubview:_verticallyCenteredView];
341
342 // Create and add title label to |_verticallyCenteredContent|.
343 _titleLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]);
344 [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
345 [_titleLabel setNumberOfLines:5];
346 [_titleLabel setTextAlignment:NSTextAlignmentCenter];
347 [_titleLabel setFont:[[MDFRobotoFontLoader sharedInstance]
348 regularFontOfSize:kFontSize]];
349 [_verticallyCenteredView addSubview:_titleLabel];
350
351 // Create and add new tab icon to |_verticallyCenteredContent|.
352 UIImage* newTabIcon = [[UIImage imageNamed:@"tabswitcher_new_tab"]
353 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
354 _newTabIcon.reset([[UIImageView alloc] initWithImage:newTabIcon]);
355 [_newTabIcon setAlpha:0];
356 [_newTabIcon setTranslatesAutoresizingMaskIntoConstraints:NO];
357 [_verticallyCenteredView addSubview:_newTabIcon];
358
359 // Create and add favicon image container.
360 _favicon.reset([[UIImageView alloc] initWithFrame:CGRectZero]);
361 [_favicon setTranslatesAutoresizingMaskIntoConstraints:NO];
362 [_raisedButton addSubview:_favicon];
363
364 // Add constraints to the button's subviews.
365 NSDictionary* viewsDictionary = @{
366 @"newTabIcon" : _newTabIcon.get(),
367 @"title" : _titleLabel.get(),
368 @"favicon" : _favicon.get(),
369 @"centeredView" : _verticallyCenteredView.get(),
370 };
371 NSArray* constraintsInButton = @[
372 @"H:|-0-[centeredView]-0-|",
373 @"H:[favicon(==16)]",
374 @"V:|-(>=16)-[centeredView]-(>=16)-[favicon(==16)]-16-|",
375 ];
376 ApplyVisualConstraints(constraintsInButton, viewsDictionary, _raisedButton);
377 AddSameCenterXConstraint(_raisedButton, _favicon.get());
378 [_raisedButton
379 addConstraint:[NSLayoutConstraint
380 constraintWithItem:_verticallyCenteredView.get()
381 attribute:NSLayoutAttributeCenterY
382 relatedBy:NSLayoutRelationEqual
383 toItem:_favicon.get()
384 attribute:NSLayoutAttributeCenterY
385 multiplier:0.5
386 constant:0]];
387
388 // Add constraints to the subviews of the vertically centered view.
389 NSArray* constraintsInVerticallyCenteredView = @[
390 @"H:|-16-[title]-16-|",
391 @"V:|-0-[newTabIcon(==24)]-16-[title(>=16)]-0-|",
392 ];
393 ApplyVisualConstraints(constraintsInVerticallyCenteredView, viewsDictionary,
394 _verticallyCenteredView);
395 AddSameCenterXConstraint(_verticallyCenteredView, _newTabIcon.get());
396 }
397 return self;
398 }
399
400 - (void)setTitle:(NSString*)titleString {
401 [_titleLabel setText:titleString];
402 [self contentView].accessibilityLabel = titleString;
403 }
404
405 - (void)setSessionGURL:(GURL const&)gurl
406 withBrowserState:(ios::ChromeBrowserState*)browserState {
407 ios_internal::FaviconGetterCompletionBlock block = ^(UIImage* favicon) {
408 UIColor* imageDominantColor =
409 DominantColorForImage(gfx::Image(favicon), 1.0);
410 MDCPalette* dominantPalette =
411 [MDCPalette paletteGeneratedFromColor:imageDominantColor];
412 UIColor* backgroundColor = dominantPalette.tint300;
413 UIColor* textColor =
414 [MDFTextAccessibility textColorOnBackgroundColor:backgroundColor
415 targetTextAlpha:kTitleLabelTextAlpha
416 font:[_titleLabel font]];
417 UIColor* iconColor =
418 [MDFTextAccessibility textColorOnBackgroundColor:backgroundColor
419 targetTextAlpha:kNewTabIconAlpha
420 font:[_titleLabel font]];
421 [_raisedButton setBackgroundColor:backgroundColor];
422 [_titleLabel setTextColor:textColor];
423 [_newTabIcon setTintColor:iconColor];
424 [_newTabIcon setAlpha:1.0];
425 [_favicon setImage:favicon];
426 [UIView animateWithDuration:0.2
427 animations:^{
428 [_raisedButton setAlpha:1.0];
429 }];
430 };
431 GURL gurlCopy = gurl;
432 _faviconObtainer.reset([[NSBlockOperation blockOperationWithBlock:^{
433 ios_internal::GetFavicon(gurlCopy, browserState, block);
434 }] retain]);
435 NSOperationQueue* operationQueue = [NSOperationQueue mainQueue];
436 [operationQueue addOperation:_faviconObtainer];
437 }
438
439 - (void)setDelegate:(id<SessionCellDelegate>)delegate {
440 _delegate = delegate;
441 }
442
443 - (void)cellPressed {
444 [_delegate cellPressed:self];
445 }
446
447 - (void)prepareForReuse {
448 [_newTabIcon setAlpha:0];
449 [_faviconObtainer cancel];
450 _faviconObtainer.reset();
451 [_raisedButton setAlpha:0];
452 [_raisedButton resetState];
453 [super prepareForReuse];
454 }
455
456 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698