OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/browser/ui/util/transparent_link_button.h" | 5 #import "ios/chrome/browser/ui/util/transparent_link_button.h" |
6 | 6 |
7 #include "base/ios/ios_util.h" | 7 #include "base/ios/ios_util.h" |
8 #import "base/ios/weak_nsobject.h" | |
9 #import "base/logging.h" | 8 #import "base/logging.h" |
10 #import "base/mac/scoped_nsobject.h" | |
11 #import "base/strings/sys_string_conversions.h" | 9 #import "base/strings/sys_string_conversions.h" |
12 #include "url/gurl.h" | 10 #include "url/gurl.h" |
13 | 11 |
| 12 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 13 #error "This file requires ARC support." |
| 14 #endif |
| 15 |
14 // Minimum tap area dimension, as specified by Apple guidelines. | 16 // Minimum tap area dimension, as specified by Apple guidelines. |
15 const CGFloat kLinkTapAreaMinimum = 44.0; | 17 const CGFloat kLinkTapAreaMinimum = 44.0; |
16 | 18 |
17 namespace { | 19 namespace { |
18 // The corner radius of the highlight view. | 20 // The corner radius of the highlight view. |
19 const CGFloat kHighlightViewCornerRadius = 2.0; | 21 const CGFloat kHighlightViewCornerRadius = 2.0; |
20 // The alpha of the highlight view's background color (base color is black). | 22 // The alpha of the highlight view's background color (base color is black). |
21 const CGFloat kHighlightViewBackgroundAlpha = 0.25; | 23 const CGFloat kHighlightViewBackgroundAlpha = 0.25; |
22 } | 24 } |
23 | 25 |
24 @interface TransparentLinkButton () { | 26 @interface TransparentLinkButton () |
25 // Backing objects for properties of the same name. | |
26 base::scoped_nsobject<UIView> _highlightView; | |
27 base::WeakNSObject<TransparentLinkButton> _previousLinkButton; | |
28 base::WeakNSObject<TransparentLinkButton> _nextLinkButton; | |
29 } | |
30 | 27 |
31 // The link frame passed upon initialization. | 28 // The link frame passed upon initialization. |
32 @property(nonatomic, readonly) CGRect linkFrame; | 29 @property(nonatomic, readonly) CGRect linkFrame; |
33 | 30 |
34 // Semi-transparent overlay that is shown to highlight the link text when the | 31 // Semi-transparent overlay that is shown to highlight the link text when the |
35 // button's highlight state is set to YES. | 32 // button's highlight state is set to YES. |
36 @property(nonatomic, readonly) UIView* highlightView; | 33 @property(nonatomic, strong, readonly) UIView* highlightView; |
37 | 34 |
38 // Links that span multiple lines require more than one TransparentLinkButton. | 35 // Links that span multiple lines require more than one TransparentLinkButton. |
39 // These properties are used to populate the highlight state from one button to | 36 // These properties are used to populate the highlight state from one button to |
40 // the other buttons corresponding with the same link. | 37 // the other buttons corresponding with the same link. |
41 @property(nonatomic, weak) TransparentLinkButton* previousLinkButton; | 38 @property(nonatomic, weak) TransparentLinkButton* previousLinkButton; |
42 @property(nonatomic, weak) TransparentLinkButton* nextLinkButton; | 39 @property(nonatomic, weak) TransparentLinkButton* nextLinkButton; |
43 | 40 |
44 // Designated initializer. |linkFrame| is the frame of the link text; this may | 41 // Designated initializer. |linkFrame| is the frame of the link text; this may |
45 // differ from the actual frame of the resulting TransparentLinkButton, which is | 42 // differ from the actual frame of the resulting TransparentLinkButton, which is |
46 // guaranteed to be at least |kLinkTapAreaMinimum| in each dimension. |URL| is | 43 // guaranteed to be at least |kLinkTapAreaMinimum| in each dimension. |URL| is |
(...skipping 11 matching lines...) Expand all Loading... |
58 // state. | 55 // state. |
59 - (void)updateHighlightView; | 56 - (void)updateHighlightView; |
60 | 57 |
61 @end | 58 @end |
62 | 59 |
63 @implementation TransparentLinkButton | 60 @implementation TransparentLinkButton |
64 | 61 |
65 @synthesize URL = _URL; | 62 @synthesize URL = _URL; |
66 @synthesize debug = _debug; | 63 @synthesize debug = _debug; |
67 @synthesize linkFrame = _linkFrame; | 64 @synthesize linkFrame = _linkFrame; |
| 65 @synthesize highlightView = _highlightView; |
| 66 @synthesize previousLinkButton = _previousLinkButton; |
| 67 @synthesize nextLinkButton = _nextLinkButton; |
68 | 68 |
69 - (instancetype)initWithLinkFrame:(CGRect)linkFrame URL:(const GURL&)URL { | 69 - (instancetype)initWithLinkFrame:(CGRect)linkFrame URL:(const GURL&)URL { |
70 CGFloat linkHeightExpansion = | 70 CGFloat linkHeightExpansion = |
71 MAX(0, (kLinkTapAreaMinimum - linkFrame.size.height) / 2.0); | 71 MAX(0, (kLinkTapAreaMinimum - linkFrame.size.height) / 2.0); |
72 CGFloat linkWidthExpansion = | 72 CGFloat linkWidthExpansion = |
73 MAX(0, (kLinkTapAreaMinimum - linkFrame.size.width) / 2.0); | 73 MAX(0, (kLinkTapAreaMinimum - linkFrame.size.width) / 2.0); |
74 // Expand the frame as necessary to meet the minimum tap area dimensions. | 74 // Expand the frame as necessary to meet the minimum tap area dimensions. |
75 CGRect frame = | 75 CGRect frame = |
76 CGRectInset(linkFrame, -linkWidthExpansion, -linkHeightExpansion); | 76 CGRectInset(linkFrame, -linkWidthExpansion, -linkHeightExpansion); |
77 if ((self = [super initWithFrame:frame])) { | 77 if ((self = [super initWithFrame:frame])) { |
78 DCHECK(URL.is_valid()); | 78 DCHECK(URL.is_valid()); |
79 self.contentEdgeInsets = | 79 self.contentEdgeInsets = |
80 UIEdgeInsetsMake(linkHeightExpansion, linkWidthExpansion, | 80 UIEdgeInsetsMake(linkHeightExpansion, linkWidthExpansion, |
81 linkHeightExpansion, linkWidthExpansion); | 81 linkHeightExpansion, linkWidthExpansion); |
82 self.backgroundColor = [UIColor clearColor]; | 82 self.backgroundColor = [UIColor clearColor]; |
83 _linkFrame = linkFrame; | 83 _linkFrame = linkFrame; |
84 _URL = URL; | 84 _URL = URL; |
85 // These buttons are positioned absolutely based on the the position of | 85 // These buttons are positioned absolutely based on the the position of |
86 // regions of text that is already correctly aligned for RTL if necessary. | 86 // regions of text that is already correctly aligned for RTL if necessary. |
87 self.semanticContentAttribute = UISemanticContentAttributeSpatial; | 87 self.semanticContentAttribute = UISemanticContentAttributeSpatial; |
88 } | 88 } |
89 return self; | 89 return self; |
90 } | 90 } |
91 | 91 |
92 #pragma mark - Accessors | 92 #pragma mark - Accessors |
93 | 93 |
94 - (void)setPreviousLinkButton:(TransparentLinkButton*)previousLinkButton { | |
95 _previousLinkButton.reset(previousLinkButton); | |
96 } | |
97 | |
98 - (TransparentLinkButton*)previousLinkButton { | |
99 return _previousLinkButton.get(); | |
100 } | |
101 | |
102 - (void)setNextLinkButton:(TransparentLinkButton*)nextLinkButton { | |
103 _nextLinkButton.reset(nextLinkButton); | |
104 } | |
105 | |
106 - (TransparentLinkButton*)nextLinkButton { | |
107 return _nextLinkButton.get(); | |
108 } | |
109 | |
110 - (void)setDebug:(BOOL)debug { | 94 - (void)setDebug:(BOOL)debug { |
111 _debug = debug; | 95 _debug = debug; |
112 self.layer.borderWidth = _debug ? 1.0 : 0.0; | 96 self.layer.borderWidth = _debug ? 1.0 : 0.0; |
113 self.layer.borderColor = | 97 self.layer.borderColor = |
114 _debug ? [UIColor greenColor].CGColor : [UIColor clearColor].CGColor; | 98 _debug ? [UIColor greenColor].CGColor : [UIColor clearColor].CGColor; |
115 self.backgroundColor = _debug ? [UIColor redColor] : [UIColor clearColor]; | 99 self.backgroundColor = _debug ? [UIColor redColor] : [UIColor clearColor]; |
116 self.alpha = _debug ? 0.15 : 1.0; | 100 self.alpha = _debug ? 0.15 : 1.0; |
117 } | 101 } |
118 | 102 |
119 - (UIView*)highlightView { | 103 - (UIView*)highlightView { |
120 if (!_highlightView) { | 104 if (!_highlightView) { |
121 CGRect linkFrame = | 105 CGRect linkFrame = |
122 [self convertRect:self.linkFrame fromView:self.superview]; | 106 [self convertRect:self.linkFrame fromView:self.superview]; |
123 linkFrame = CGRectInset(linkFrame, -kHighlightViewCornerRadius, 0); | 107 linkFrame = CGRectInset(linkFrame, -kHighlightViewCornerRadius, 0); |
124 _highlightView.reset([[UIView alloc] initWithFrame:linkFrame]); | 108 _highlightView = [[UIView alloc] initWithFrame:linkFrame]; |
125 [_highlightView | 109 [_highlightView |
126 setBackgroundColor:[UIColor | 110 setBackgroundColor:[UIColor |
127 colorWithWhite:0.0 | 111 colorWithWhite:0.0 |
128 alpha:kHighlightViewBackgroundAlpha]]; | 112 alpha:kHighlightViewBackgroundAlpha]]; |
129 [_highlightView layer].cornerRadius = kHighlightViewCornerRadius; | 113 [_highlightView layer].cornerRadius = kHighlightViewCornerRadius; |
130 [_highlightView setClipsToBounds:YES]; | 114 [_highlightView setClipsToBounds:YES]; |
131 [self addSubview:_highlightView]; | 115 [self addSubview:_highlightView]; |
132 } | 116 } |
133 return _highlightView.get(); | 117 return _highlightView; |
134 } | 118 } |
135 | 119 |
136 - (void)setHighlighted:(BOOL)highlighted { | 120 - (void)setHighlighted:(BOOL)highlighted { |
137 [self setHighlighted:highlighted sender:nil]; | 121 [self setHighlighted:highlighted sender:nil]; |
138 } | 122 } |
139 | 123 |
140 - (void)setSelected:(BOOL)selected { | 124 - (void)setSelected:(BOOL)selected { |
141 [self setSelected:selected sender:nil]; | 125 [self setSelected:selected sender:nil]; |
142 } | 126 } |
143 | 127 |
144 #pragma mark - | 128 #pragma mark - |
145 | 129 |
146 + (NSArray*)buttonsForLinkFrames:(NSArray*)linkFrames | 130 + (NSArray*)buttonsForLinkFrames:(NSArray*)linkFrames |
147 URL:(const GURL&)URL | 131 URL:(const GURL&)URL |
148 accessibilityLabel:(NSString*)label { | 132 accessibilityLabel:(NSString*)label { |
149 if (!linkFrames.count) | 133 if (!linkFrames.count) |
150 return @[]; | 134 return @[]; |
151 base::scoped_nsobject<NSMutableArray> buttons( | 135 NSMutableArray* buttons = |
152 [[NSMutableArray alloc] initWithCapacity:linkFrames.count]); | 136 [[NSMutableArray alloc] initWithCapacity:linkFrames.count]; |
153 for (NSValue* linkFrameValue in linkFrames) { | 137 for (NSValue* linkFrameValue in linkFrames) { |
154 CGRect linkFrame = [linkFrameValue CGRectValue]; | 138 CGRect linkFrame = [linkFrameValue CGRectValue]; |
155 base::scoped_nsobject<TransparentLinkButton> button( | 139 TransparentLinkButton* button = |
156 [[TransparentLinkButton alloc] initWithLinkFrame:linkFrame URL:URL]); | 140 [[TransparentLinkButton alloc] initWithLinkFrame:linkFrame URL:URL]; |
157 TransparentLinkButton* previousButton = [buttons lastObject]; | 141 TransparentLinkButton* previousButton = [buttons lastObject]; |
158 previousButton.nextLinkButton = button; | 142 previousButton.nextLinkButton = button; |
159 [button setPreviousLinkButton:previousButton]; | 143 [button setPreviousLinkButton:previousButton]; |
160 // Make buttons not accessible by default, but provide label for tests. | 144 // Make buttons not accessible by default, but provide label for tests. |
161 [button setIsAccessibilityElement:NO]; | 145 [button setIsAccessibilityElement:NO]; |
162 [button setAccessibilityLabel:label]; | 146 [button setAccessibilityLabel:label]; |
163 [buttons addObject:button]; | 147 [buttons addObject:button]; |
164 } | 148 } |
165 // Make the first button accessible. | 149 // Make the first button accessible. |
166 [buttons[0] setIsAccessibilityElement:YES]; | 150 [buttons[0] setIsAccessibilityElement:YES]; |
(...skipping 16 matching lines...) Expand all Loading... |
183 if (self.nextLinkButton != sender) | 167 if (self.nextLinkButton != sender) |
184 [self.nextLinkButton setSelected:selected sender:self]; | 168 [self.nextLinkButton setSelected:selected sender:self]; |
185 [self updateHighlightView]; | 169 [self updateHighlightView]; |
186 } | 170 } |
187 | 171 |
188 - (void)updateHighlightView { | 172 - (void)updateHighlightView { |
189 self.highlightView.hidden = !self.highlighted && !self.selected; | 173 self.highlightView.hidden = !self.highlighted && !self.selected; |
190 } | 174 } |
191 | 175 |
192 @end | 176 @end |
OLD | NEW |