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

Side by Side Diff: ios/chrome/browser/ui/bookmarks/bookmark_collection_cells.mm

Issue 2586993002: Upstream Chrome on iOS source code [3/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 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/ui/bookmarks/bookmark_collection_cells.h"
6
7 #import <QuartzCore/QuartzCore.h>
8
9 #include "base/logging.h"
10 #include "base/mac/objc_property_releaser.h"
11 #include "base/mac/scoped_nsobject.h"
12 #import "ios/chrome/browser/ui/bookmarks/bookmark_extended_button.h"
13 #import "ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.h"
14 #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h"
15 #import "ios/chrome/browser/ui/rtl_geometry.h"
16 #import "ios/chrome/browser/ui/uikit_ui_util.h"
17 #include "ios/chrome/grit/ios_strings.h"
18 #include "ios/chrome/grit/ios_theme_resources.h"
19 #import "ios/third_party/material_components_ios/src/components/Ink/src/Material Ink.h"
20 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h"
21 #include "ui/base/l10n/l10n_util_mac.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #import "ui/gfx/ios/NSString+CrStringDrawing.h"
24 #include "url/gurl.h"
25
26 namespace {
27 const CGFloat kBookmarkItemCellDefaultImageSize = 40.0;
28 const CGFloat kBookmarkFolderCellDefaultImageSize = 24.0;
29 } // namespace
30
31 @interface BookmarkCell () {
32 @protected
33 // Subclasses should set these in the constructor with the wanted values.
34 CGFloat _imageSize;
35
36 @private
37 base::mac::ObjCPropertyReleaser _propertyReleaser_BookmarkCell;
38 }
39 // Redefined to be read-write.
40 @property(nonatomic, retain) UILabel* titleLabel;
41 // Redefined to readwrite.
42 @property(nonatomic, retain) UIImageView* imageView;
43 // Label to show placeholder text when there is no image displayed.
44 @property(nonatomic, retain) UILabel* placeholderLabel;
45 // When the cell is selected for editing, a cover is shown with a blue color.
46 // Subclasses should insert new views below this view.
47 @property(nonatomic, retain) UIView* highlightCover;
48 // Lists the accessibility elements that are to be seen by UIAccessibility.
49 @property(nonatomic, readonly) NSMutableArray* accessibilityElements;
50 // Location of the last touch on the cell.
51 @property(nonatomic, assign) CGPoint touchLocation;
52 // The view doing the highlight animation. Only set while the cell is
53 // highlighted.
54 @property(nonatomic, retain) MDCInkView* touchFeedbackView;
55 @property(nonatomic, retain) BookmarkExtendedButton* button;
56 @property(nonatomic, assign) SEL buttonAction;
57 @property(nonatomic, assign) id buttonTarget;
58 @end
59
60 @implementation BookmarkCell
61 @synthesize accessibilityElements = _accessibilityElements;
62 @synthesize titleLabel = _titleLabel;
63 @synthesize imageView = _imageView;
64 @synthesize highlightCover = _highlightCover;
65 @synthesize shouldAnimateImageChanges = _shouldAnimateImageChanges;
66 @synthesize touchLocation = _touchLocation;
67 @synthesize touchFeedbackView = _touchFeedbackView;
68 @synthesize button = _button;
69 @synthesize buttonAction = _buttonAction;
70 @synthesize buttonTarget = _buttonTarget;
71 @synthesize placeholderLabel = _placeholderLabel;
72
73 + (NSString*)reuseIdentifier {
74 NOTREACHED();
75 return nil;
76 }
77
78 - (instancetype)initWithFrame:(CGRect)frame {
79 self = [super initWithFrame:frame];
80 if (self) {
81 _propertyReleaser_BookmarkCell.Init(self, [BookmarkCell class]);
82 self.exclusiveTouch = YES;
83 self.backgroundColor = [UIColor whiteColor];
84
85 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
86 _titleLabel.textColor = bookmark_utils_ios::darkTextColor();
87 self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
88 [self.contentView addSubview:_titleLabel];
89
90 _imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
91 _imageView.clipsToBounds = YES;
92 self.imageView.translatesAutoresizingMaskIntoConstraints = NO;
93 [self.contentView addSubview:_imageView];
94
95 _placeholderLabel = [[UILabel alloc] init];
96 _placeholderLabel.textAlignment = NSTextAlignmentCenter;
97 [self.contentView addSubview:_placeholderLabel];
98
99 _highlightCover = [[UIView alloc] initWithFrame:CGRectZero];
100 _highlightCover.backgroundColor =
101 [bookmark_utils_ios::blueColor() colorWithAlphaComponent:0.7];
102 _highlightCover.hidden = YES;
103 _highlightCover.translatesAutoresizingMaskIntoConstraints = NO;
104 [self.contentView addSubview:_highlightCover];
105
106 self.button = base::scoped_nsobject<BookmarkExtendedButton>(
107 [[BookmarkExtendedButton alloc] init]);
108 self.button.contentMode = UIViewContentModeCenter;
109 self.button.backgroundColor = [UIColor clearColor];
110 [self.button addTarget:self
111 action:@selector(buttonTapped:)
112 forControlEvents:UIControlEventTouchUpInside];
113 self.button.translatesAutoresizingMaskIntoConstraints = NO;
114 [self.contentView insertSubview:self.button
115 belowSubview:self.highlightCover];
116
117 _accessibilityElements = [[NSMutableArray alloc] init];
118 self.contentView.isAccessibilityElement = YES;
119 self.contentView.accessibilityTraits |= UIAccessibilityTraitButton;
120 [_accessibilityElements addObject:self.contentView];
121 [self.accessibilityElements addObject:self.button];
122 }
123 return self;
124 }
125
126 + (BOOL)requiresConstraintBasedLayout {
127 return YES;
128 }
129
130 - (void)updateConstraints {
131 if (_imageSize) {
132 // Create constraints.
133
134 // Align all the views on the same horizontal line.
135 AddSameCenterYConstraint(self.contentView, self.titleLabel);
136 AddSameCenterYConstraint(self.contentView, self.imageView);
137 AddSameCenterYConstraint(self.contentView, self.button);
138
139 // clang-format off
140 ApplyVisualConstraintsWithMetrics(
141 @[
142 @"H:|-leadingImageMargin-[image(imageSize)]",
143 @"H:|-leadingMargin-[title]-[button(buttonSize)]|",
144 @"V:[image(imageSize)]",
145 @"V:[button(buttonSize)]",
146 @"H:|[highlight]|",
147 @"V:|[highlight]|"
148 ],
149 @{
150 @"title" : self.titleLabel,
151 @"image" : self.imageView,
152 @"button" : self.button,
153 @"highlight" : self.highlightCover
154 },
155 @{
156 @"buttonSize" : [NSNumber numberWithFloat:32.0],
157 @"leadingImageMargin" : [NSNumber numberWithFloat:16.0],
158 @"leadingMargin" : [NSNumber numberWithFloat:64.0],
159 @"imageSize" : [NSNumber numberWithFloat:_imageSize],
160 },
161 self.contentView);
162 // clang-format on
163 }
164
165 [NSLayoutConstraint activateConstraints:@[
166 [self.placeholderLabel.leadingAnchor
167 constraintEqualToAnchor:self.imageView.leadingAnchor],
168 [self.placeholderLabel.trailingAnchor
169 constraintEqualToAnchor:self.imageView.trailingAnchor],
170 [self.placeholderLabel.topAnchor
171 constraintEqualToAnchor:self.imageView.topAnchor],
172 [self.placeholderLabel.bottomAnchor
173 constraintEqualToAnchor:self.imageView.bottomAnchor]
174 ]];
175 self.placeholderLabel.translatesAutoresizingMaskIntoConstraints = NO;
176
177 [super updateConstraints];
178 }
179
180 - (void)setSelectedForEditing:(BOOL)selected animated:(BOOL)animated {
181 self.highlightCover.hidden = !selected;
182 if (selected)
183 self.contentView.accessibilityTraits |= UIAccessibilityTraitSelected;
184 else
185 self.contentView.accessibilityTraits &= ~UIAccessibilityTraitSelected;
186 }
187
188 - (void)setImage:(UIImage*)image {
189 self.imageView.image = image;
190 self.placeholderLabel.hidden = YES;
191 self.imageView.hidden = NO;
192
193 if (!self.shouldAnimateImageChanges)
194 return;
195
196 CATransition* transition = [CATransition animation];
197 transition.duration = 0.2f;
198 transition.timingFunction = [CAMediaTimingFunction
199 functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
200 transition.type = kCATransitionFade;
201 [self.imageView.layer addAnimation:transition forKey:nil];
202 }
203
204 - (void)setPlaceholderText:(NSString*)text
205 textColor:(UIColor*)textColor
206 backgroundColor:(UIColor*)backgroundColor {
207 self.placeholderLabel.hidden = NO;
208 self.imageView.hidden = YES;
209
210 self.placeholderLabel.backgroundColor = backgroundColor;
211 self.placeholderLabel.textColor = textColor;
212 self.placeholderLabel.text = text;
213 }
214
215 - (void)prepareForReuse {
216 self.imageView.image = nil;
217 self.imageView.backgroundColor = [UIColor whiteColor];
218 self.highlightCover.hidden = YES;
219 self.shouldAnimateImageChanges = NO;
220 [self.touchFeedbackView cancelAllAnimationsAnimated:NO];
221 [self.touchFeedbackView removeFromSuperview];
222 self.touchFeedbackView = nil;
223 [self updateWithTitle:nil];
224 self.placeholderLabel.hidden = YES;
225 self.imageView.hidden = NO;
226
227 [super prepareForReuse];
228 }
229
230 - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
231 UITouch* touch = [touches anyObject];
232 self.touchLocation = [touch locationInView:self];
233 [super touchesBegan:touches withEvent:event];
234 }
235
236 - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
237 UITouch* touch = [touches anyObject];
238 self.touchLocation = [touch locationInView:self];
239 [super touchesEnded:touches withEvent:event];
240 }
241
242 - (void)setHighlighted:(BOOL)highlighted {
243 [super setHighlighted:highlighted];
244
245 // To prevent selection messing up with ink, immediately remove ink.
246 [self.touchFeedbackView removeFromSuperview];
247 self.touchFeedbackView = nil;
248
249 if (highlighted) {
250 // Creates an ink feedback and animates it.
251 base::scoped_nsobject<MDCInkView> touchFeedbackView(
252 [[MDCInkView alloc] initWithFrame:self.bounds]);
253 [self addSubview:touchFeedbackView];
254 self.touchFeedbackView = touchFeedbackView;
255 [self.touchFeedbackView startTouchBeganAnimationAtPoint:self.touchLocation
256 completion:nil];
257 } else {
258 [self.touchFeedbackView startTouchEndedAnimationAtPoint:self.touchLocation
259 completion:nil];
260 }
261 }
262
263 - (void)updateWithTitle:(NSString*)title {
264 self.titleLabel.text = title;
265 [self setNeedsLayout];
266 [self updateAccessibilityValues];
267 }
268
269 #pragma mark - Button
270 - (void)setButtonTarget:(id)target action:(SEL)action {
271 self.buttonTarget = target;
272 self.buttonAction = action;
273 }
274
275 - (void)buttonTapped:(id)target {
276 [self.buttonTarget performSelector:self.buttonAction
277 withObject:self
278 withObject:target];
279 }
280
281 - (void)showButtonOfType:(bookmark_cell::ButtonType)buttonType
282 animated:(BOOL)animated {
283 switch (buttonType) {
284 case bookmark_cell::ButtonNone:
285 [self removeButtonAnimated:animated];
286 break;
287
288 case bookmark_cell::ButtonMenu: {
289 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
290 UIImage* bgImage =
291 rb.GetNativeImageNamed(IDR_IOS_TOOLBAR_LIGHT_TOOLS).ToUIImage();
292 [self addButtonWithImage:bgImage animated:animated];
293 break;
294 }
295 }
296 }
297
298 - (void)addButtonWithImage:(UIImage*)image animated:(BOOL)animated {
299 // Set the image.
300 [self.button setImage:image forState:UIControlStateNormal];
301
302 // Animates the button in.
303 [UIView animateWithDuration:animated ? 0.15 : 0
304 delay:0
305 options:UIViewAnimationOptionBeginFromCurrentState
306 animations:^{
307 self.button.alpha = 1.0;
308 }
309 completion:^(BOOL finished) {
310 if (finished) {
311 // If this method is called twice in succession, the button should
312 // only be added once to |self.accessibilityElements|.
313 if (![self.accessibilityElements containsObject:self.button])
314 [self.accessibilityElements addObject:self.button];
315 }
316 }];
317 }
318
319 - (void)removeButtonAnimated:(BOOL)animated {
320 if (!self.button)
321 return;
322
323 [UIView animateWithDuration:animated ? 0.15 : 0
324 delay:0
325 options:UIViewAnimationOptionBeginFromCurrentState
326 animations:^{
327 self.button.alpha = 0.0;
328 }
329 completion:^(BOOL finished) {
330 if (finished) {
331 [self.accessibilityElements removeObject:self.button];
332 }
333 }];
334 }
335
336 #pragma mark - Accessibility
337
338 - (void)updateAccessibilityValues {
339 self.button.accessibilityIdentifier =
340 [NSString stringWithFormat:@"%@ %@", self.titleLabel.text, @"Info"];
341 self.button.accessibilityLabel = l10n_util::GetNSString(
342 IDS_IOS_BOOKMARK_NEW_MORE_BUTTON_ACCESSIBILITY_LABEL);
343 }
344
345 - (NSInteger)accessibilityElementCount {
346 return [self.accessibilityElements count];
347 }
348
349 - (id)accessibilityElementAtIndex:(NSInteger)index {
350 return [self.accessibilityElements objectAtIndex:index];
351 }
352
353 - (NSInteger)indexOfAccessibilityElement:(id)element {
354 return [self.accessibilityElements indexOfObject:element];
355 }
356
357 @end
358
359 #pragma mark - BookmarkItemCell
360
361 @interface BookmarkItemCell () {
362 base::mac::ObjCPropertyReleaser _propertyReleaser_BookmarkItemCell;
363 }
364 @end
365
366 @implementation BookmarkItemCell
367
368 + (NSString*)reuseIdentifier {
369 return @"BookmarkItemCell";
370 }
371
372 + (CGFloat)preferredImageSize {
373 return kBookmarkItemCellDefaultImageSize;
374 }
375
376 - (instancetype)initWithFrame:(CGRect)frame {
377 self = [super initWithFrame:frame];
378 if (self) {
379 _propertyReleaser_BookmarkItemCell.Init(self, [BookmarkItemCell class]);
380
381 // Set the non-layout properties of the titles.
382 UIFont* font = [MDCTypography subheadFont];
383 self.titleLabel.font = font;
384 self.titleLabel.backgroundColor = [UIColor clearColor];
385 self.titleLabel.numberOfLines = 1;
386
387 _imageSize = kBookmarkItemCellDefaultImageSize;
388 }
389 return self;
390 }
391
392 - (void)updateWithTitle:(NSString*)title {
393 [super updateWithTitle:title];
394 [self updateAccessibilityValues];
395 }
396
397 - (void)updateAccessibilityValues {
398 [super updateAccessibilityValues];
399 self.contentView.accessibilityLabel =
400 [NSString stringWithFormat:@"%@", self.titleLabel.text];
401 self.contentView.accessibilityIdentifier = self.titleLabel.text;
402 }
403
404 - (void)prepareForReuse {
405 [super prepareForReuse];
406 [self updateAccessibilityValues];
407 }
408
409 @end
410
411 #pragma mark - BookmarkFolderCell
412
413 @interface BookmarkFolderCell () {
414 base::mac::ObjCPropertyReleaser _propertyReleaser_BookmarkFolderCell;
415 }
416
417 @end
418
419 @implementation BookmarkFolderCell
420
421 + (NSString*)reuseIdentifier {
422 return @"BookmarkFolderCell";
423 }
424
425 - (instancetype)initWithFrame:(CGRect)frame {
426 self = [super initWithFrame:frame];
427 if (self) {
428 _propertyReleaser_BookmarkFolderCell.Init(self, [BookmarkFolderCell class]);
429
430 self.imageView.image = [UIImage imageNamed:@"bookmark_gray_folder"];
431 self.titleLabel.font = [MDCTypography subheadFont];
432
433 _imageSize = kBookmarkFolderCellDefaultImageSize;
434 }
435 return self;
436 }
437
438 - (void)prepareForReuse {
439 [super prepareForReuse];
440 [self setImage:[UIImage imageNamed:@"bookmark_gray_folder"]];
441 }
442
443 - (void)updateWithTitle:(NSString*)title {
444 [super updateWithTitle:title];
445
446 self.contentView.accessibilityLabel = title;
447 self.contentView.accessibilityIdentifier = title;
448 }
449
450 @end
451
452 #pragma mark - BookmarkHeaderView
453
454 @interface BookmarkHeaderView () {
455 base::mac::ObjCPropertyReleaser _propertyReleaser_BookmarkHeaderView;
456 }
457 @property(nonatomic, retain) UILabel* titleLabel;
458 @end
459
460 @implementation BookmarkHeaderView
461 @synthesize titleLabel = _titleLabel;
462 + (NSString*)reuseIdentifier {
463 return @"BookmarkHeaderView";
464 }
465
466 + (CGFloat)handsetHeight {
467 return 47.0;
468 }
469
470 - (instancetype)initWithFrame:(CGRect)frame {
471 self = [super initWithFrame:frame];
472 if (self) {
473 _propertyReleaser_BookmarkHeaderView.Init(self, [BookmarkHeaderView class]);
474 base::scoped_nsobject<UILabel> titleLabel(
475 [[UILabel alloc] initWithFrame:CGRectZero]);
476 self.titleLabel = titleLabel;
477 UIFont* font = [MDCTypography body2Font];
478 self.titleLabel.font = font;
479 self.titleLabel.textColor = bookmark_utils_ios::lightTextColor();
480 self.titleLabel.backgroundColor = [UIColor clearColor];
481 self.titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader;
482 [self addSubview:self.titleLabel];
483 }
484 return self;
485 }
486
487 - (void)layoutSubviews {
488 [super layoutSubviews];
489
490 // On handsets the title is aligned with the icon in the navigation bar.
491 CGFloat margin = 16.0;
492 if (IsIPadIdiom())
493 margin = 24.0; // On tablets the alignment is the same as the tiles.
494 self.titleLabel.frame =
495 CGRectMake(margin, 0, self.bounds.size.width - margin * 2.0,
496 self.bounds.size.height);
497 }
498
499 - (void)setTitle:(NSString*)title {
500 self.titleLabel.text = title;
501 }
502
503 - (void)updateLayoutWithLeftMargin:(CGFloat)leftMargin {
504 self.titleLabel.frame =
505 CGRectMake(leftMargin, 0, self.bounds.size.width - leftMargin,
506 self.bounds.size.height);
507 }
508
509 @end
510
511 #pragma mark - BookmarkHeaderSeparatorView
512
513 @interface BookmarkHeaderSeparatorView () {
514 base::mac::ObjCPropertyReleaser _propertyReleaser_BookmarkHeaderSeparatorView;
515 }
516 // The bottom separator line.
517 @property(nonatomic, retain) UIView* lineView;
518 @end
519
520 @implementation BookmarkHeaderSeparatorView
521
522 @synthesize lineView = _lineView;
523
524 + (NSString*)reuseIdentifier {
525 return NSStringFromClass(self);
526 }
527
528 + (CGFloat)preferredHeight {
529 return 16;
530 }
531
532 - (instancetype)initWithFrame:(CGRect)frame {
533 self = [super initWithFrame:frame];
534 if (self) {
535 _propertyReleaser_BookmarkHeaderSeparatorView.Init(
536 self, [BookmarkHeaderSeparatorView class]);
537 _lineView = [[UIView alloc] init];
538 _lineView.backgroundColor = bookmark_utils_ios::separatorColor();
539 [self addSubview:_lineView];
540 }
541 return self;
542 }
543
544 - (void)layoutSubviews {
545 CGFloat lineHeight = 1;
546 CGFloat lineY = self.bounds.size.height - lineHeight - 8;
547 _lineView.frame = CGRectMake(0, lineY, self.bounds.size.width, lineHeight);
548 }
549
550 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698