OLD | NEW |
1 | 1 |
2 // Copyright 2012 The Chromium Authors. All rights reserved. | 2 // Copyright 2012 The Chromium Authors. All rights reserved. |
3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
5 | 5 |
6 #import "ios/chrome/browser/ui/tabs/tab_view.h" | 6 #import "ios/chrome/browser/ui/tabs/tab_view.h" |
7 | 7 |
8 #include "base/i18n/rtl.h" | 8 #include "base/i18n/rtl.h" |
9 #include "base/ios/ios_util.h" | 9 #include "base/ios/ios_util.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/mac/objc_property_releaser.h" | 11 |
12 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
13 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" | 13 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" |
14 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" | 14 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" |
15 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h" | 15 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h" |
16 #import "ios/chrome/browser/ui/image_util.h" | 16 #import "ios/chrome/browser/ui/image_util.h" |
17 #include "ios/chrome/browser/ui/rtl_geometry.h" | 17 #include "ios/chrome/browser/ui/rtl_geometry.h" |
18 #include "ios/chrome/browser/ui/ui_util.h" | 18 #include "ios/chrome/browser/ui/ui_util.h" |
19 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 19 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
20 #include "ios/chrome/grit/ios_strings.h" | 20 #include "ios/chrome/grit/ios_strings.h" |
21 #import "ios/third_party/material_components_ios/src/components/ActivityIndicato
r/src/MaterialActivityIndicator.h" | 21 #import "ios/third_party/material_components_ios/src/components/ActivityIndicato
r/src/MaterialActivityIndicator.h" |
22 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" | 22 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" |
23 #include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h
" | 23 #include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h
" |
24 #include "ui/base/l10n/l10n_util.h" | 24 #include "ui/base/l10n/l10n_util.h" |
25 #include "ui/base/l10n/l10n_util_mac.h" | 25 #include "ui/base/l10n/l10n_util_mac.h" |
26 #include "ui/base/resource/resource_bundle.h" | 26 #include "ui/base/resource/resource_bundle.h" |
27 #include "ui/gfx/image/image.h" | 27 #include "ui/gfx/image/image.h" |
28 #import "ui/gfx/ios/uikit_util.h" | 28 #import "ui/gfx/ios/uikit_util.h" |
29 | 29 |
| 30 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 31 #error "This file requires ARC support." |
| 32 #endif |
| 33 |
30 namespace { | 34 namespace { |
31 | 35 |
32 // Tab close button insets. | 36 // Tab close button insets. |
33 const CGFloat kTabCloseTopInset = -1.0; | 37 const CGFloat kTabCloseTopInset = -1.0; |
34 const CGFloat kTabCloseLeftInset = 0.0; | 38 const CGFloat kTabCloseLeftInset = 0.0; |
35 const CGFloat kTabCloseBottomInset = 0.0; | 39 const CGFloat kTabCloseBottomInset = 0.0; |
36 const CGFloat kTabCloseRightInset = 0.0; | 40 const CGFloat kTabCloseRightInset = 0.0; |
37 const CGFloat kTabBackgroundLeftCapInset = 24.0; | 41 const CGFloat kTabBackgroundLeftCapInset = 24.0; |
38 const CGFloat kFaviconLeftInset = 23.5; | 42 const CGFloat kFaviconLeftInset = 23.5; |
39 const CGFloat kFaviconVerticalOffset = 2.0; | 43 const CGFloat kFaviconVerticalOffset = 2.0; |
40 const CGFloat kTabStripLineMargin = 2.5; | 44 const CGFloat kTabStripLineMargin = 2.5; |
41 const CGFloat kTabStripLineHeight = 0.5; | 45 const CGFloat kTabStripLineHeight = 0.5; |
42 const CGFloat kCloseButtonHorizontalShift = 15; | 46 const CGFloat kCloseButtonHorizontalShift = 15; |
43 const CGFloat kCloseButtonVerticalShift = 4.0; | 47 const CGFloat kCloseButtonVerticalShift = 4.0; |
44 const CGFloat kTitleLeftMargin = 8.0; | 48 const CGFloat kTitleLeftMargin = 8.0; |
45 const CGFloat kTitleRightMargin = 0.0; | 49 const CGFloat kTitleRightMargin = 0.0; |
46 | 50 |
47 const CGFloat kCloseButtonSize = 24.0; | 51 const CGFloat kCloseButtonSize = 24.0; |
48 const CGFloat kFaviconSize = 16.0; | 52 const CGFloat kFaviconSize = 16.0; |
49 } | 53 } |
50 | 54 |
51 @interface TabView () { | 55 @interface TabView () { |
52 // Close button for this tab. | 56 // Close button for this tab. |
53 UIButton* _closeButton; | 57 UIButton* _closeButton; |
54 | 58 |
55 // View that draws the tab title. | 59 // View that draws the tab title. |
56 GTMFadeTruncatingLabel* _titleLabel; | 60 GTMFadeTruncatingLabel* _titleLabel; |
57 | 61 |
58 // Background image for this tab. | 62 // Background image for this tab. |
59 base::scoped_nsobject<UIImageView> _backgroundImageView; | 63 UIImageView* _backgroundImageView; |
60 // This view is used to draw a separator line at the bottom of the tab view. | 64 // This view is used to draw a separator line at the bottom of the tab view. |
61 // This view is hidden when the tab view is in a selected state. | 65 // This view is hidden when the tab view is in a selected state. |
62 base::scoped_nsobject<UIView> _lineSeparator; | 66 UIView* _lineSeparator; |
63 BOOL _incognitoStyle; | 67 BOOL _incognitoStyle; |
64 | 68 |
65 // Set to YES when the layout constraints have been initialized. | 69 // Set to YES when the layout constraints have been initialized. |
66 BOOL _layoutConstraintsInitialized; | 70 BOOL _layoutConstraintsInitialized; |
67 | 71 |
68 // Image view used to draw the favicon and spinner. | 72 // Image view used to draw the favicon and spinner. |
69 base::scoped_nsobject<UIImageView> _faviconView; | 73 UIImageView* _faviconView; |
70 | 74 |
71 // If |YES|, this view will adjust its appearance and draw as a collapsed tab. | 75 // If |YES|, this view will adjust its appearance and draw as a collapsed tab. |
72 BOOL _collapsed; | 76 BOOL _collapsed; |
73 | 77 |
74 base::scoped_nsobject<MDCActivityIndicator> _activityIndicator; | 78 MDCActivityIndicator* _activityIndicator; |
75 | |
76 base::mac::ObjCPropertyReleaser _propertyReleaser_TabView; | |
77 } | 79 } |
78 @end | 80 @end |
79 | 81 |
80 @interface TabView (Private) | 82 @interface TabView (Private) |
81 | 83 |
82 // Creates the close button, favicon button, and title. | 84 // Creates the close button, favicon button, and title. |
83 - (void)createButtonsAndLabel; | 85 - (void)createButtonsAndLabel; |
84 | 86 |
85 // Updates this tab's line separator color based on the current incognito style. | 87 // Updates this tab's line separator color based on the current incognito style. |
86 - (void)updateLineSeparator; | 88 - (void)updateLineSeparator; |
(...skipping 21 matching lines...) Expand all Loading... |
108 @implementation TabView | 110 @implementation TabView |
109 | 111 |
110 @synthesize closeButton = _closeButton; | 112 @synthesize closeButton = _closeButton; |
111 @synthesize titleLabel = _titleLabel; | 113 @synthesize titleLabel = _titleLabel; |
112 @synthesize collapsed = _collapsed; | 114 @synthesize collapsed = _collapsed; |
113 @synthesize background = background_; | 115 @synthesize background = background_; |
114 @synthesize incognitoStyle = _incognitoStyle; | 116 @synthesize incognitoStyle = _incognitoStyle; |
115 | 117 |
116 - (id)initWithEmptyView:(BOOL)emptyView selected:(BOOL)selected { | 118 - (id)initWithEmptyView:(BOOL)emptyView selected:(BOOL)selected { |
117 if ((self = [super initWithFrame:CGRectZero])) { | 119 if ((self = [super initWithFrame:CGRectZero])) { |
118 _propertyReleaser_TabView.Init(self, [TabView class]); | |
119 [self setOpaque:NO]; | 120 [self setOpaque:NO]; |
120 [self createCommonViews]; | 121 [self createCommonViews]; |
121 // -setSelected only calls -updateBackgroundImage if the selected state | 122 // -setSelected only calls -updateBackgroundImage if the selected state |
122 // changes. |isSelected| defaults to NO, so if |selected| is also NO, | 123 // changes. |isSelected| defaults to NO, so if |selected| is also NO, |
123 // -updateBackgroundImage needs to be called explicitly. | 124 // -updateBackgroundImage needs to be called explicitly. |
124 [self setSelected:selected]; | 125 [self setSelected:selected]; |
125 [self updateLineSeparator]; | 126 [self updateLineSeparator]; |
126 [self updateBackgroundImage:selected]; | 127 [self updateBackgroundImage:selected]; |
127 if (!emptyView) | 128 if (!emptyView) |
128 [self createButtonsAndLabel]; | 129 [self createButtonsAndLabel]; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 // Account for the trapezoidal shape of the tab. Inset the tab bounds by | 230 // Account for the trapezoidal shape of the tab. Inset the tab bounds by |
230 // (y = -2.2x + 56), determined empirically from looking at the tab background | 231 // (y = -2.2x + 56), determined empirically from looking at the tab background |
231 // images. | 232 // images. |
232 CGFloat inset = MAX(0.0, (point.y - 56) / -2.2); | 233 CGFloat inset = MAX(0.0, (point.y - 56) / -2.2); |
233 return CGRectContainsPoint(CGRectInset([self bounds], inset, 0), point); | 234 return CGRectContainsPoint(CGRectInset([self bounds], inset, 0), point); |
234 } | 235 } |
235 | 236 |
236 #pragma mark - Private | 237 #pragma mark - Private |
237 | 238 |
238 - (void)createCommonViews { | 239 - (void)createCommonViews { |
239 _backgroundImageView.reset([[UIImageView alloc] init]); | 240 _backgroundImageView = [[UIImageView alloc] init]; |
240 [_backgroundImageView setTranslatesAutoresizingMaskIntoConstraints:NO]; | 241 [_backgroundImageView setTranslatesAutoresizingMaskIntoConstraints:NO]; |
241 [self addSubview:_backgroundImageView]; | 242 [self addSubview:_backgroundImageView]; |
242 | 243 |
243 _lineSeparator.reset([[UIView alloc] initWithFrame:CGRectZero]); | 244 _lineSeparator = [[UIView alloc] initWithFrame:CGRectZero]; |
244 [_lineSeparator setTranslatesAutoresizingMaskIntoConstraints:NO]; | 245 [_lineSeparator setTranslatesAutoresizingMaskIntoConstraints:NO]; |
245 [self addSubview:_lineSeparator]; | 246 [self addSubview:_lineSeparator]; |
246 } | 247 } |
247 | 248 |
248 - (void)addCommonConstraints { | 249 - (void)addCommonConstraints { |
249 NSDictionary* commonViewsDictionary = @{ | 250 NSDictionary* commonViewsDictionary = @{ |
250 @"backgroundImageView" : _backgroundImageView.get(), | 251 @"backgroundImageView" : _backgroundImageView, |
251 @"lineSeparator" : _lineSeparator.get() | 252 @"lineSeparator" : _lineSeparator |
252 }; | 253 }; |
253 NSArray* commonConstraints = @[ | 254 NSArray* commonConstraints = @[ |
254 @"H:|-0-[backgroundImageView]-0-|", | 255 @"H:|-0-[backgroundImageView]-0-|", |
255 @"V:|-0-[backgroundImageView]-0-|", | 256 @"V:|-0-[backgroundImageView]-0-|", |
256 @"H:|-tabStripLineMargin-[lineSeparator]-tabStripLineMargin-|", | 257 @"H:|-tabStripLineMargin-[lineSeparator]-tabStripLineMargin-|", |
257 @"V:[lineSeparator(==tabStripLineHeight)]-0-|", | 258 @"V:[lineSeparator(==tabStripLineHeight)]-0-|", |
258 ]; | 259 ]; |
259 NSDictionary* commonMetrics = @{ | 260 NSDictionary* commonMetrics = @{ |
260 @"tabStripLineMargin" : @(kTabStripLineMargin), | 261 @"tabStripLineMargin" : @(kTabStripLineMargin), |
261 @"tabStripLineHeight" : @(kTabStripLineHeight) | 262 @"tabStripLineHeight" : @(kTabStripLineHeight) |
262 }; | 263 }; |
263 ApplyVisualConstraintsWithMetrics(commonConstraints, commonViewsDictionary, | 264 ApplyVisualConstraintsWithMetrics(commonConstraints, commonViewsDictionary, |
264 commonMetrics, self); | 265 commonMetrics, self); |
265 } | 266 } |
266 | 267 |
267 - (void)createButtonsAndLabel { | 268 - (void)createButtonsAndLabel { |
268 _closeButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; | 269 _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; |
269 [_closeButton setTranslatesAutoresizingMaskIntoConstraints:NO]; | 270 [_closeButton setTranslatesAutoresizingMaskIntoConstraints:NO]; |
270 [_closeButton setImage:[UIImage imageNamed:@"tabstrip_tab_close"] | 271 [_closeButton setImage:[UIImage imageNamed:@"tabstrip_tab_close"] |
271 forState:UIControlStateNormal]; | 272 forState:UIControlStateNormal]; |
272 [_closeButton setImage:[UIImage imageNamed:@"tabstrip_tab_close_pressed"] | 273 [_closeButton setImage:[UIImage imageNamed:@"tabstrip_tab_close_pressed"] |
273 forState:UIControlStateHighlighted]; | 274 forState:UIControlStateHighlighted]; |
274 [_closeButton setContentEdgeInsets:UIEdgeInsetsMake(kTabCloseTopInset, | 275 [_closeButton setContentEdgeInsets:UIEdgeInsetsMake(kTabCloseTopInset, |
275 kTabCloseLeftInset, | 276 kTabCloseLeftInset, |
276 kTabCloseBottomInset, | 277 kTabCloseBottomInset, |
277 kTabCloseRightInset)]; | 278 kTabCloseRightInset)]; |
278 [_closeButton setAccessibilityLabel:l10n_util::GetNSString( | 279 [_closeButton setAccessibilityLabel:l10n_util::GetNSString( |
279 IDS_IOS_TOOLS_MENU_CLOSE_TAB)]; | 280 IDS_IOS_TOOLS_MENU_CLOSE_TAB)]; |
280 [self addSubview:_closeButton]; | 281 [self addSubview:_closeButton]; |
281 | 282 |
282 // Add fade truncating label. | 283 // Add fade truncating label. |
283 _titleLabel = [[GTMFadeTruncatingLabel alloc] initWithFrame:CGRectZero]; | 284 _titleLabel = [[GTMFadeTruncatingLabel alloc] initWithFrame:CGRectZero]; |
284 [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; | 285 [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; |
285 [_titleLabel setFont:[MDCTypography body1Font]]; | 286 [_titleLabel setFont:[MDCTypography body1Font]]; |
286 // Setting NSLineBreakByCharWrapping fixes an issue where the beginning of the | 287 // Setting NSLineBreakByCharWrapping fixes an issue where the beginning of the |
287 // text is truncated for RTL text writing direction. Anyway since the label is | 288 // text is truncated for RTL text writing direction. Anyway since the label is |
288 // only one line and the end of the text is faded behind a gradient mask, it | 289 // only one line and the end of the text is faded behind a gradient mask, it |
289 // is visually almost equivalent to NSLineBreakByClipping. | 290 // is visually almost equivalent to NSLineBreakByClipping. |
290 [_titleLabel setLineBreakMode:NSLineBreakByCharWrapping]; | 291 [_titleLabel setLineBreakMode:NSLineBreakByCharWrapping]; |
291 | 292 |
292 [_titleLabel setTextAlignment:NSTextAlignmentNatural]; | 293 [_titleLabel setTextAlignment:NSTextAlignmentNatural]; |
293 [self addSubview:_titleLabel]; | 294 [self addSubview:_titleLabel]; |
294 | 295 |
295 CGRect faviconFrame = CGRectMake(0, 0, kFaviconSize, kFaviconSize); | 296 CGRect faviconFrame = CGRectMake(0, 0, kFaviconSize, kFaviconSize); |
296 _faviconView.reset([[UIImageView alloc] initWithFrame:faviconFrame]); | 297 _faviconView = [[UIImageView alloc] initWithFrame:faviconFrame]; |
297 [_faviconView setTranslatesAutoresizingMaskIntoConstraints:NO]; | 298 [_faviconView setTranslatesAutoresizingMaskIntoConstraints:NO]; |
298 [_faviconView setContentMode:UIViewContentModeScaleAspectFit]; | 299 [_faviconView setContentMode:UIViewContentModeScaleAspectFit]; |
299 [_faviconView setImage:[self defaultFaviconImage]]; | 300 [_faviconView setImage:[self defaultFaviconImage]]; |
300 [_faviconView setAccessibilityIdentifier:@"Favicon"]; | 301 [_faviconView setAccessibilityIdentifier:@"Favicon"]; |
301 [self addSubview:_faviconView]; | 302 [self addSubview:_faviconView]; |
302 | 303 |
303 _activityIndicator.reset( | 304 _activityIndicator = |
304 [[MDCActivityIndicator alloc] initWithFrame:faviconFrame]); | 305 [[MDCActivityIndicator alloc] initWithFrame:faviconFrame]; |
305 [_activityIndicator setTranslatesAutoresizingMaskIntoConstraints:NO]; | 306 [_activityIndicator setTranslatesAutoresizingMaskIntoConstraints:NO]; |
306 [_activityIndicator | 307 [_activityIndicator |
307 setCycleColors:@[ [[MDCPalette cr_bluePalette] tint500] ]]; | 308 setCycleColors:@[ [[MDCPalette cr_bluePalette] tint500] ]]; |
308 [_activityIndicator setRadius:ui::AlignValueToUpperPixel(kFaviconSize / 2)]; | 309 [_activityIndicator setRadius:ui::AlignValueToUpperPixel(kFaviconSize / 2)]; |
309 [self addSubview:_activityIndicator]; | 310 [self addSubview:_activityIndicator]; |
310 } | 311 } |
311 | 312 |
312 - (void)addButtonsAndLabelConstraints { | 313 - (void)addButtonsAndLabelConstraints { |
313 // Constraints on the Top bar, snapshot view, and shadow view. | 314 // Constraints on the Top bar, snapshot view, and shadow view. |
314 NSDictionary* viewsDictionary = @{ | 315 NSDictionary* viewsDictionary = @{ |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 [_closeButton setImage:normalImage forState:UIControlStateNormal]; | 371 [_closeButton setImage:normalImage forState:UIControlStateNormal]; |
371 [_closeButton setImage:pressedImage forState:UIControlStateHighlighted]; | 372 [_closeButton setImage:pressedImage forState:UIControlStateHighlighted]; |
372 } | 373 } |
373 | 374 |
374 - (UIImage*)defaultFaviconImage { | 375 - (UIImage*)defaultFaviconImage { |
375 return self.incognitoStyle ? [UIImage imageNamed:@"default_favicon_incognito"] | 376 return self.incognitoStyle ? [UIImage imageNamed:@"default_favicon_incognito"] |
376 : [UIImage imageNamed:@"default_favicon"]; | 377 : [UIImage imageNamed:@"default_favicon"]; |
377 } | 378 } |
378 | 379 |
379 @end | 380 @end |
OLD | NEW |