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

Side by Side Diff: ios/chrome/browser/autofill/form_input_accessory_view.mm

Issue 1022463002: [iOS] Upstream files in //ios/chrome/browser/autofill (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 9 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 2014 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/autofill/form_input_accessory_view.h"
6
7 #import <QuartzCore/QuartzCore.h>
8
9 #include "base/i18n/rtl.h"
10 #include "base/ios/weak_nsobject.h"
11 #include "base/mac/scoped_nsobject.h"
12 #import "ios/chrome/browser/autofill/form_input_accessory_view_delegate.h"
13 #import "ios/chrome/browser/ui/image_util.h"
14 #include "ios/chrome/browser/ui/ui_util.h"
15
16 namespace {
17
18 // The alpha value of the background color.
19 const CGFloat kBackgroundColorAlpha = 1.0;
20
21 // Horizontal margin around the custom view.
22 const CGFloat kCustomViewHorizontalMargin = 2;
23
24 // The width of the previous and next buttons.
25 const CGFloat kNavigationButtonWidth = 44;
26
27 // The width of the separators of the previous and next buttons.
28 const CGFloat kNavigationButtonSeparatorWidth = 1;
29
30 // The width of the shadow part of the navigation area separator.
31 const CGFloat kNavigationAreaSeparatorShadowWidth = 2;
32
33 // The width of the navigation area / custom view separator asset.
34 const CGFloat kNavigationAreaSeparatorWidth = 1;
35
36 // Returns YES if the keyboard close button should be shown on the accessory.
37 BOOL ShouldShowCloseButton() {
38 return !IsIPadIdiom();
39 }
40
41 // Returns the width of navigation view.
42 CGFloat GetNavigationViewWidth() {
43 // The number of naviation buttons (includes close button if shown).
44 NSUInteger numberNavigationButtons = 2;
45 if (ShouldShowCloseButton())
46 numberNavigationButtons++;
47 return numberNavigationButtons * kNavigationButtonWidth +
48 (numberNavigationButtons - 1) * kNavigationButtonSeparatorWidth +
49 kNavigationAreaSeparatorWidth;
50 }
51
52 } // namespace
53
54 @interface FormInputAccessoryView ()
55
56 // Initializes the view with the given |customView|.
57 // If the size of |rightFrame| is non-zero, the view will be split into two
58 // parts with |leftFrame| and |rightFrame|. Otherwise the Autofill view will
59 // be shown in |leftFrame|.
60 - (void)initializeViewWithCustomView:(UIView*)customView
61 leftFrame:(CGRect)leftFrame
62 rightFrame:(CGRect)rightFrame;
63
64 // Returns a view that shows navigation buttons in the |frame|.
65 - (UIView*)viewForNavigationButtonsInFrame:(CGRect)frame;
66
67 // Returns a navigation button for Autofill that has |normalImage| for state
68 // UIControlStateNormal, a |pressedImage| for states UIControlStateSelected and
69 // UIControlStateHighlighted, and an optional |disabledImage| for
70 // UIControlStateDisabled.
71 - (UIButton*)keyboardNavButtonWithNormalImage:(UIImage*)normalImage
72 pressedImage:(UIImage*)pressedImage
73 disabledImage:(UIImage*)disabledImage
74 target:(id)target
75 action:(SEL)action
76 enabled:(BOOL)enabled
77 originX:(CGFloat)originX
78 originY:(CGFloat)originY
79 height:(CGFloat)height;
80
81 // Adds a background image to |view|. The supplied image is stretched to fit the
82 // space by stretching the content its horizontal and vertical centers.
83 + (void)addBackgroundImageInView:(UIView*)view
84 withImageName:(NSString*)imageName;
85
86 // Adds an image view in |view| with an image named |imageName| at
87 // (|originX|, 0). The width is |width| and the height is the height of |view|.
88 + (void)addImageViewWithImageName:(NSString*)imageName
89 originX:(CGFloat)originX
90 originY:(CGFloat)originY
91 width:(CGFloat)width
92 inView:(UIView*)view;
93
94 @end
95
96 @implementation FormInputAccessoryView {
97 // The custom view that is displayed in the input accessory view.
98 base::scoped_nsobject<UIView> _customView;
99
100 // Delegate of this view.
101 base::WeakNSProtocol<id<FormInputAccessoryViewDelegate>> _delegate;
102 }
103
104 - (instancetype)initWithFrame:(CGRect)frame
105 delegate:(id<FormInputAccessoryViewDelegate>)delegate
106 customView:(UIView*)customView
107 leftFrame:(CGRect)leftFrame
108 rightFrame:(CGRect)rightFrame {
109 DCHECK(delegate);
110 self = [super initWithFrame:frame];
111 if (self) {
112 _delegate.reset(delegate);
113 _customView.reset([customView retain]);
114 [self initializeViewWithCustomView:_customView
115 leftFrame:leftFrame
116 rightFrame:rightFrame];
117 }
118 return self;
119 }
120
121 #pragma mark -
122 #pragma mark UIInputViewAudioFeedback
123
124 - (BOOL)enableInputClicksWhenVisible {
125 return YES;
126 }
127
128 #pragma mark -
129 #pragma mark Private Methods
130
131 - (void)initializeViewWithCustomView:(UIView*)customView
132 leftFrame:(CGRect)leftFrame
133 rightFrame:(CGRect)rightFrame {
134 UIView* customViewContainer = [[[UIView alloc] init] autorelease];
135 [self addSubview:customViewContainer];
136 UIView* navView = [[[UIView alloc] init] autorelease];
137 [self addSubview:navView];
138
139 bool splitKeyboard = CGRectGetWidth(rightFrame) != 0;
140 BOOL isRTL = base::i18n::IsRTL();
141
142 // The computed frame for |customView|.
143 CGRect customViewFrame;
144 // Frame of a subview of |navView| in which navigation buttons will be shown.
145 CGRect navFrame = CGRectZero;
146 if (splitKeyboard) {
147 NSString* navViewBackgroundImageName = nil;
148 NSString* customViewContainerBackgroundImageName = nil;
149 NSUInteger navFrameOriginX = 0;
150 if (isRTL) {
151 navView.frame = leftFrame;
152 navViewBackgroundImageName = @"autofill_keyboard_background_left";
153 customViewContainer.frame = rightFrame;
154 customViewContainerBackgroundImageName =
155 @"autofill_keyboard_background_right";
156 // Navigation buttons will be shown on the left side.
157 navFrameOriginX = 0;
158 } else {
159 customViewContainer.frame = leftFrame;
160 customViewContainerBackgroundImageName =
161 @"autofill_keyboard_background_left";
162 navView.frame = rightFrame;
163 navViewBackgroundImageName = @"autofill_keyboard_background_right";
164 // Navigation buttons will be shown on the right side.
165 navFrameOriginX =
166 CGRectGetWidth(navView.frame) - GetNavigationViewWidth();
167 }
168
169 [[self class]
170 addBackgroundImageInView:customViewContainer
171 withImageName:customViewContainerBackgroundImageName];
172 [[self class] addBackgroundImageInView:navView
173 withImageName:navViewBackgroundImageName];
174
175 // For RTL, the custom view is the right view; the padding should be at the
176 // left side of this view. Otherwise, the custom view is the left view
177 // and the space is at the right side.
178 customViewFrame = CGRectMake(isRTL ? kCustomViewHorizontalMargin : 0, 0,
179 CGRectGetWidth(customViewContainer.bounds) -
180 kCustomViewHorizontalMargin,
181 CGRectGetHeight(customViewContainer.bounds));
182 navFrame = CGRectMake(navFrameOriginX, 0, GetNavigationViewWidth(),
183 CGRectGetHeight(navView.frame));
184 } else {
185 NSUInteger navViewFrameOriginX = 0;
186 NSUInteger customViewContainerFrameOrginX = 0;
187 if (isRTL) {
188 navViewFrameOriginX = kNavigationAreaSeparatorShadowWidth;
189 customViewContainerFrameOrginX = GetNavigationViewWidth();
190 } else {
191 navViewFrameOriginX =
192 CGRectGetWidth(leftFrame) - GetNavigationViewWidth();
193 }
194
195 customViewContainer.frame =
196 CGRectMake(customViewContainerFrameOrginX, 0,
197 CGRectGetWidth(leftFrame) - GetNavigationViewWidth() +
198 kNavigationAreaSeparatorShadowWidth,
199 CGRectGetHeight(leftFrame));
200 navView.frame = CGRectMake(navViewFrameOriginX, 0, GetNavigationViewWidth(),
201 CGRectGetHeight(leftFrame));
202
203 customViewFrame = customViewContainer.bounds;
204 navFrame = navView.bounds;
205 [[self class] addBackgroundImageInView:self
206 withImageName:@"autofill_keyboard_background"];
207 }
208
209 [customView setFrame:customViewFrame];
210 [customViewContainer addSubview:customView];
211 [navView addSubview:[self viewForNavigationButtonsInFrame:navFrame]];
212 }
213
214 UIImage* ButtonImage(NSString* name) {
215 UIImage* rawImage = [UIImage imageNamed:name];
216 return StretchableImageFromUIImage(rawImage, 1, 0);
217 }
218
219 - (UIView*)viewForNavigationButtonsInFrame:(CGRect)frame {
220 UIView* navView = [[[UIView alloc] initWithFrame:frame] autorelease];
221
222 BOOL isRTL = base::i18n::IsRTL();
223
224 // Vertical space is left for a dividing line.
225 CGFloat firstRow = 1;
226
227 CGFloat currentX = 0;
228
229 // Navigation view is at the right side if not RTL. Add a left separator in
230 // this case.
231 if (!isRTL) {
232 [[self class] addImageViewWithImageName:@"autofill_left_sep"
233 originX:currentX
234 originY:firstRow
235 width:kNavigationAreaSeparatorWidth
236 inView:navView];
237 currentX = kNavigationAreaSeparatorWidth;
238 }
239
240 UIButton* previousButton = [self
241 keyboardNavButtonWithNormalImage:ButtonImage(@"autofill_prev")
242 pressedImage:ButtonImage(@"autofill_prev_pressed")
243 disabledImage:ButtonImage(@"autofill_prev_inactive")
244 target:_delegate
245 action:@selector(selectPreviousElement)
246 enabled:NO
247 originX:currentX
248 originY:firstRow
249 height:CGRectGetHeight(frame)];
250 [navView addSubview:previousButton];
251 currentX += kNavigationButtonWidth;
252
253 // Add internal separator.
254 [[self class] addImageViewWithImageName:@"autofill_middle_sep"
255 originX:currentX
256 originY:firstRow
257 width:kNavigationButtonSeparatorWidth
258 inView:navView];
259 currentX += kNavigationButtonSeparatorWidth;
260
261 UIButton* nextButton = [self
262 keyboardNavButtonWithNormalImage:ButtonImage(@"autofill_next")
263 pressedImage:ButtonImage(@"autofill_next_pressed")
264 disabledImage:ButtonImage(@"autofill_next_inactive")
265 target:_delegate
266 action:@selector(selectNextElement)
267 enabled:NO
268 originX:currentX
269 originY:firstRow
270 height:CGRectGetHeight(frame)];
271 [navView addSubview:nextButton];
272 currentX += kNavigationButtonWidth;
273
274 [_delegate fetchPreviousAndNextElementsPresenceWithCompletionHandler:
275 ^(BOOL hasPreviousElement, BOOL hasNextElement) {
276 previousButton.enabled = hasPreviousElement;
277 nextButton.enabled = hasNextElement;
278 }];
279
280 if (ShouldShowCloseButton()) {
281 // Add internal separator.
282 [[self class] addImageViewWithImageName:@"autofill_middle_sep"
283 originX:currentX
284 originY:firstRow
285 width:kNavigationButtonSeparatorWidth
286 inView:navView];
287 currentX += kNavigationButtonSeparatorWidth;
288
289 [navView addSubview:[self
290 keyboardNavButtonWithNormalImage:ButtonImage(@"autofill_close")
291 pressedImage:ButtonImage(@"autofill_close_pressed")
292 disabledImage:nil
293 target:_delegate
294 action:@selector(closeKeyboard)
295 enabled:YES
296 originX:currentX
297 originY:firstRow
298 height:CGRectGetHeight(frame)]];
299 currentX += kNavigationButtonWidth;
300 }
301
302 // Navigation view is at the left side for RTL. Add a right separator in
303 // this case.
304 if (isRTL) {
305 [[self class] addImageViewWithImageName:@"autofill_right_sep"
306 originX:currentX
307 originY:firstRow
308 width:kNavigationAreaSeparatorWidth
309 inView:navView];
310 }
311
312 return navView;
313 }
314
315 - (UIButton*)keyboardNavButtonWithNormalImage:(UIImage*)normalImage
316 pressedImage:(UIImage*)pressedImage
317 disabledImage:(UIImage*)disabledImage
318 target:(id)target
319 action:(SEL)action
320 enabled:(BOOL)enabled
321 originX:(CGFloat)originX
322 originY:(CGFloat)originY
323 height:(CGFloat)height {
324 UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
325
326 button.frame =
327 CGRectMake(originX, originY, kNavigationButtonWidth, height - originY);
328
329 [button setBackgroundImage:normalImage forState:UIControlStateNormal];
330 [button setBackgroundImage:pressedImage forState:UIControlStateSelected];
331 [button setBackgroundImage:pressedImage forState:UIControlStateHighlighted];
332 if (disabledImage)
333 [button setBackgroundImage:disabledImage forState:UIControlStateDisabled];
334
335 CALayer* layer = [button layer];
336 layer.borderWidth = 0;
337 layer.borderColor = [[UIColor blackColor] CGColor];
338 button.enabled = enabled;
339 [button addTarget:target
340 action:action
341 forControlEvents:UIControlEventTouchUpInside];
342 return button;
343 }
344
345 + (void)addBackgroundImageInView:(UIView*)view
346 withImageName:(NSString*)imageName {
347 UIImage* backgroundImage = StretchableImageNamed(imageName);
348
349 UIImageView* backgroundImageView =
350 [[[UIImageView alloc] initWithFrame:view.bounds] autorelease];
351 [backgroundImageView setImage:backgroundImage];
352 [backgroundImageView setAlpha:kBackgroundColorAlpha];
353 [view addSubview:backgroundImageView];
354 [view sendSubviewToBack:backgroundImageView];
355 }
356
357 + (void)addImageViewWithImageName:(NSString*)imageName
358 originX:(CGFloat)originX
359 originY:(CGFloat)originY
360 width:(CGFloat)width
361 inView:(UIView*)view {
362 UIImage* image =
363 StretchableImageFromUIImage([UIImage imageNamed:imageName], 0, 0);
364 base::scoped_nsobject<UIImageView> imageView(
365 [[UIImageView alloc] initWithImage:image]);
366 [imageView setFrame:CGRectMake(originX, originY, width,
367 CGRectGetHeight(view.bounds) - originY)];
368 [view addSubview:imageView];
369 }
370
371 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698