OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/bookmarks/bookmark_folder_view_controller.h" | 5 #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #import "base/ios/weak_nsobject.h" | |
11 #include "base/logging.h" | 10 #include "base/logging.h" |
12 #include "base/mac/objc_property_releaser.h" | |
13 #include "base/mac/scoped_nsobject.h" | |
14 #include "base/strings/sys_string_conversions.h" | 11 #include "base/strings/sys_string_conversions.h" |
15 #include "components/bookmarks/browser/bookmark_model.h" | 12 #include "components/bookmarks/browser/bookmark_model.h" |
16 #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.
h" | 13 #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.
h" |
17 #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_table_view_cell.h" | 14 #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_table_view_cell.h" |
18 #import "ios/chrome/browser/ui/bookmarks/bookmark_model_bridge_observer.h" | 15 #import "ios/chrome/browser/ui/bookmarks/bookmark_model_bridge_observer.h" |
19 #import "ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.h" | 16 #import "ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.h" |
20 #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" | 17 #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" |
21 #import "ios/chrome/browser/ui/icons/chrome_icon.h" | 18 #import "ios/chrome/browser/ui/icons/chrome_icon.h" |
22 #import "ios/chrome/browser/ui/material_components/utils.h" | 19 #import "ios/chrome/browser/ui/material_components/utils.h" |
23 #include "ios/chrome/grit/ios_strings.h" | 20 #include "ios/chrome/grit/ios_strings.h" |
24 #import "ios/third_party/material_components_ios/src/components/AppBar/src/Mater
ialAppBar.h" | 21 #import "ios/third_party/material_components_ios/src/components/AppBar/src/Mater
ialAppBar.h" |
25 #include "ui/base/l10n/l10n_util_mac.h" | 22 #include "ui/base/l10n/l10n_util_mac.h" |
26 | 23 |
| 24 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 25 #error "This file requires ARC support." |
| 26 #endif |
| 27 |
27 using bookmarks::BookmarkNode; | 28 using bookmarks::BookmarkNode; |
28 | 29 |
29 namespace { | 30 namespace { |
30 | 31 |
31 // The height of every folder cell. | 32 // The height of every folder cell. |
32 const CGFloat kFolderCellHeight = 48.0; | 33 const CGFloat kFolderCellHeight = 48.0; |
33 | 34 |
34 // Height of section headers/footers. | 35 // Height of section headers/footers. |
35 const CGFloat kSectionHeaderHeight = 8.0; | 36 const CGFloat kSectionHeaderHeight = 8.0; |
36 const CGFloat kSectionFooterHeight = 8.0; | 37 const CGFloat kSectionFooterHeight = 8.0; |
(...skipping 10 matching lines...) Expand all Loading... |
47 } // namespace | 48 } // namespace |
48 | 49 |
49 @interface BookmarkFolderViewController ()< | 50 @interface BookmarkFolderViewController ()< |
50 BookmarkFolderEditorViewControllerDelegate, | 51 BookmarkFolderEditorViewControllerDelegate, |
51 BookmarkModelBridgeObserver, | 52 BookmarkModelBridgeObserver, |
52 UITableViewDataSource, | 53 UITableViewDataSource, |
53 UITableViewDelegate> { | 54 UITableViewDelegate> { |
54 std::set<const BookmarkNode*> _editedNodes; | 55 std::set<const BookmarkNode*> _editedNodes; |
55 std::vector<const BookmarkNode*> _folders; | 56 std::vector<const BookmarkNode*> _folders; |
56 std::unique_ptr<bookmarks::BookmarkModelBridge> _modelBridge; | 57 std::unique_ptr<bookmarks::BookmarkModelBridge> _modelBridge; |
57 base::scoped_nsobject<MDCAppBar> _appBar; | 58 MDCAppBar* _appBar; |
58 base::mac::ObjCPropertyReleaser | |
59 _propertyReleaser_BookmarkFolderViewController; | |
60 } | 59 } |
61 | 60 |
62 // Should the controller setup Cancel and Done buttons instead of a back button. | 61 // Should the controller setup Cancel and Done buttons instead of a back button. |
63 @property(nonatomic, assign) BOOL allowsCancel; | 62 @property(nonatomic, assign) BOOL allowsCancel; |
64 | 63 |
65 // Should the controller setup a new-folder button. | 64 // Should the controller setup a new-folder button. |
66 @property(nonatomic, assign) BOOL allowsNewFolders; | 65 @property(nonatomic, assign) BOOL allowsNewFolders; |
67 | 66 |
68 // Reference to the main bookmark model. | 67 // Reference to the main bookmark model. |
69 @property(nonatomic, assign) bookmarks::BookmarkModel* bookmarkModel; | 68 @property(nonatomic, assign) bookmarks::BookmarkModel* bookmarkModel; |
70 | 69 |
71 // The currently selected folder. | 70 // The currently selected folder. |
72 @property(nonatomic, readonly) const BookmarkNode* selectedFolder; | 71 @property(nonatomic, readonly) const BookmarkNode* selectedFolder; |
73 | 72 |
74 // The view controller to present when creating a new folder. | 73 // The view controller to present when creating a new folder. |
75 @property(nonatomic, retain) | 74 @property(nonatomic, strong) |
76 BookmarkFolderEditorViewController* folderAddController; | 75 BookmarkFolderEditorViewController* folderAddController; |
77 | 76 |
78 // A linear list of folders. | 77 // A linear list of folders. |
79 @property(nonatomic, assign, readonly) | 78 @property(nonatomic, assign, readonly) |
80 const std::vector<const BookmarkNode*>& folders; | 79 const std::vector<const BookmarkNode*>& folders; |
81 | 80 |
82 // The table view that displays the options and folders. | 81 // The table view that displays the options and folders. |
83 @property(nonatomic, retain) UITableView* tableView; | 82 @property(nonatomic, strong) UITableView* tableView; |
84 | 83 |
85 // Returns the cell for the default section and the given |row|. | 84 // Returns the cell for the default section and the given |row|. |
86 - (BookmarkFolderTableViewCell*)defaultSectionCellForRow:(NSInteger)row; | 85 - (BookmarkFolderTableViewCell*)defaultSectionCellForRow:(NSInteger)row; |
87 | 86 |
88 // Returns a folder cell for the folder at |row| in |self.folders|. | 87 // Returns a folder cell for the folder at |row| in |self.folders|. |
89 - (BookmarkFolderTableViewCell*)folderSectionCellForRow:(NSInteger)row; | 88 - (BookmarkFolderTableViewCell*)folderSectionCellForRow:(NSInteger)row; |
90 | 89 |
91 // Reloads the folder list. | 90 // Reloads the folder list. |
92 - (void)reloadFolders; | 91 - (void)reloadFolders; |
93 | 92 |
(...skipping 25 matching lines...) Expand all Loading... |
119 allowsNewFolders:(BOOL)allowsNewFolders | 118 allowsNewFolders:(BOOL)allowsNewFolders |
120 editedNodes: | 119 editedNodes: |
121 (const std::set<const BookmarkNode*>&)nodes | 120 (const std::set<const BookmarkNode*>&)nodes |
122 allowsCancel:(BOOL)allowsCancel | 121 allowsCancel:(BOOL)allowsCancel |
123 selectedFolder:(const BookmarkNode*)selectedFolder { | 122 selectedFolder:(const BookmarkNode*)selectedFolder { |
124 DCHECK(bookmarkModel); | 123 DCHECK(bookmarkModel); |
125 DCHECK(bookmarkModel->loaded()); | 124 DCHECK(bookmarkModel->loaded()); |
126 DCHECK(selectedFolder == NULL || selectedFolder->is_folder()); | 125 DCHECK(selectedFolder == NULL || selectedFolder->is_folder()); |
127 self = [super initWithNibName:nil bundle:nil]; | 126 self = [super initWithNibName:nil bundle:nil]; |
128 if (self) { | 127 if (self) { |
129 _propertyReleaser_BookmarkFolderViewController.Init( | |
130 self, [BookmarkFolderViewController class]); | |
131 _allowsCancel = allowsCancel; | 128 _allowsCancel = allowsCancel; |
132 _allowsNewFolders = allowsNewFolders; | 129 _allowsNewFolders = allowsNewFolders; |
133 _bookmarkModel = bookmarkModel; | 130 _bookmarkModel = bookmarkModel; |
134 _editedNodes = nodes; | 131 _editedNodes = nodes; |
135 _selectedFolder = selectedFolder; | 132 _selectedFolder = selectedFolder; |
136 | 133 |
137 // Set up the bookmark model oberver. | 134 // Set up the bookmark model oberver. |
138 _modelBridge.reset( | 135 _modelBridge.reset( |
139 new bookmarks::BookmarkModelBridge(self, _bookmarkModel)); | 136 new bookmarks::BookmarkModelBridge(self, _bookmarkModel)); |
140 | 137 |
141 _appBar.reset([[MDCAppBar alloc] init]); | 138 _appBar = [[MDCAppBar alloc] init]; |
142 [self addChildViewController:[_appBar headerViewController]]; | 139 [self addChildViewController:[_appBar headerViewController]]; |
143 } | 140 } |
144 return self; | 141 return self; |
145 } | 142 } |
146 | 143 |
147 - (void)changeSelectedFolder:(const BookmarkNode*)selectedFolder { | 144 - (void)changeSelectedFolder:(const BookmarkNode*)selectedFolder { |
148 DCHECK(selectedFolder); | 145 DCHECK(selectedFolder); |
149 DCHECK(selectedFolder->is_folder()); | 146 DCHECK(selectedFolder->is_folder()); |
150 _selectedFolder = selectedFolder; | 147 _selectedFolder = selectedFolder; |
151 [self.tableView reloadData]; | 148 [self.tableView reloadData]; |
152 } | 149 } |
153 | 150 |
154 - (void)dealloc { | 151 - (void)dealloc { |
155 _tableView.dataSource = nil; | 152 _tableView.dataSource = nil; |
156 _tableView.delegate = nil; | 153 _tableView.delegate = nil; |
157 _folderAddController.delegate = nil; | 154 _folderAddController.delegate = nil; |
158 [super dealloc]; | |
159 } | 155 } |
160 | 156 |
161 - (UIStatusBarStyle)preferredStatusBarStyle { | 157 - (UIStatusBarStyle)preferredStatusBarStyle { |
162 return UIStatusBarStyleDefault; | 158 return UIStatusBarStyleDefault; |
163 } | 159 } |
164 | 160 |
165 #pragma mark - View lifecycle | 161 #pragma mark - View lifecycle |
166 | 162 |
167 - (void)viewDidLoad { | 163 - (void)viewDidLoad { |
168 [super viewDidLoad]; | 164 [super viewDidLoad]; |
169 if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) { | 165 if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) { |
170 [self setEdgesForExtendedLayout:UIRectEdgeNone]; | 166 [self setEdgesForExtendedLayout:UIRectEdgeNone]; |
171 } | 167 } |
172 self.view.backgroundColor = [UIColor whiteColor]; | 168 self.view.backgroundColor = [UIColor whiteColor]; |
173 self.view.accessibilityIdentifier = @"Folder Picker"; | 169 self.view.accessibilityIdentifier = @"Folder Picker"; |
174 | 170 |
175 self.title = l10n_util::GetNSString(IDS_IOS_BOOKMARK_CHOOSE_GROUP_BUTTON); | 171 self.title = l10n_util::GetNSString(IDS_IOS_BOOKMARK_CHOOSE_GROUP_BUTTON); |
176 | 172 |
177 base::scoped_nsobject<UIBarButtonItem> doneItem([[UIBarButtonItem alloc] | 173 UIBarButtonItem* doneItem = [[UIBarButtonItem alloc] |
178 initWithTitle:l10n_util::GetNSString( | 174 initWithTitle:l10n_util::GetNSString( |
179 IDS_IOS_BOOKMARK_EDIT_MODE_EXIT_MOBILE) | 175 IDS_IOS_BOOKMARK_EDIT_MODE_EXIT_MOBILE) |
180 style:UIBarButtonItemStylePlain | 176 style:UIBarButtonItemStylePlain |
181 target:self | 177 target:self |
182 action:@selector(done:)]); | 178 action:@selector(done:)]; |
183 doneItem.get().accessibilityIdentifier = @"Done"; | 179 doneItem.accessibilityIdentifier = @"Done"; |
184 self.navigationItem.rightBarButtonItem = doneItem; | 180 self.navigationItem.rightBarButtonItem = doneItem; |
185 | 181 |
186 if (self.allowsCancel) { | 182 if (self.allowsCancel) { |
187 UIBarButtonItem* cancelItem = | 183 UIBarButtonItem* cancelItem = |
188 [ChromeIcon templateBarButtonItemWithImage:[ChromeIcon closeIcon] | 184 [ChromeIcon templateBarButtonItemWithImage:[ChromeIcon closeIcon] |
189 target:self | 185 target:self |
190 action:@selector(cancel:)]; | 186 action:@selector(cancel:)]; |
191 cancelItem.accessibilityLabel = | 187 cancelItem.accessibilityLabel = |
192 l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_CANCEL_BUTTON_LABEL); | 188 l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_CANCEL_BUTTON_LABEL); |
193 cancelItem.accessibilityIdentifier = @"Cancel"; | 189 cancelItem.accessibilityIdentifier = @"Cancel"; |
194 self.navigationItem.leftBarButtonItem = cancelItem; | 190 self.navigationItem.leftBarButtonItem = cancelItem; |
195 } else { | 191 } else { |
196 UIBarButtonItem* backItem = | 192 UIBarButtonItem* backItem = |
197 [ChromeIcon templateBarButtonItemWithImage:[ChromeIcon backIcon] | 193 [ChromeIcon templateBarButtonItemWithImage:[ChromeIcon backIcon] |
198 target:self | 194 target:self |
199 action:@selector(back:)]; | 195 action:@selector(back:)]; |
200 backItem.accessibilityLabel = | 196 backItem.accessibilityLabel = |
201 l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_BACK_LABEL); | 197 l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_BACK_LABEL); |
202 backItem.accessibilityIdentifier = @"Back"; | 198 backItem.accessibilityIdentifier = @"Back"; |
203 self.navigationItem.leftBarButtonItem = backItem; | 199 self.navigationItem.leftBarButtonItem = backItem; |
204 } | 200 } |
205 | 201 |
206 // The table view. | 202 // The table view. |
207 base::scoped_nsobject<UITableView> tableView([[UITableView alloc] | 203 UITableView* tableView = |
208 initWithFrame:self.view.bounds | 204 [[UITableView alloc] initWithFrame:self.view.bounds |
209 style:UITableViewStylePlain]); | 205 style:UITableViewStylePlain]; |
210 tableView.get().dataSource = self; | 206 tableView.dataSource = self; |
211 tableView.get().delegate = self; | 207 tableView.delegate = self; |
212 tableView.get().autoresizingMask = | 208 tableView.autoresizingMask = |
213 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; | 209 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; |
214 tableView.get().separatorStyle = UITableViewCellSeparatorStyleNone; | 210 tableView.separatorStyle = UITableViewCellSeparatorStyleNone; |
215 [self.view addSubview:tableView]; | 211 [self.view addSubview:tableView]; |
216 [self.view sendSubviewToBack:tableView]; | 212 [self.view sendSubviewToBack:tableView]; |
217 self.tableView = tableView; | 213 self.tableView = tableView; |
218 | 214 |
219 // Add the app bar to the view hierarchy. This must be done last, so that the | 215 // Add the app bar to the view hierarchy. This must be done last, so that the |
220 // app bar's views are the frontmost. | 216 // app bar's views are the frontmost. |
221 ConfigureAppBarWithCardStyle(_appBar); | 217 ConfigureAppBarWithCardStyle(_appBar); |
222 [_appBar headerViewController].headerView.trackingScrollView = self.tableView; | 218 [_appBar headerViewController].headerView.trackingScrollView = self.tableView; |
223 [_appBar addSubviewsToParent]; | 219 [_appBar addSubviewsToParent]; |
224 } | 220 } |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 } | 326 } |
331 NOTREACHED(); | 327 NOTREACHED(); |
332 return 0; | 328 return 0; |
333 } | 329 } |
334 | 330 |
335 - (UIView*)tableView:(UITableView*)tableView | 331 - (UIView*)tableView:(UITableView*)tableView |
336 viewForHeaderInSection:(NSInteger)section { | 332 viewForHeaderInSection:(NSInteger)section { |
337 CGRect headerViewFrame = | 333 CGRect headerViewFrame = |
338 CGRectMake(0, 0, CGRectGetWidth(tableView.frame), | 334 CGRectMake(0, 0, CGRectGetWidth(tableView.frame), |
339 [self tableView:tableView heightForHeaderInSection:section]); | 335 [self tableView:tableView heightForHeaderInSection:section]); |
340 UIView* headerView = | 336 UIView* headerView = [[UIView alloc] initWithFrame:headerViewFrame]; |
341 [[[UIView alloc] initWithFrame:headerViewFrame] autorelease]; | |
342 if (section == BookmarkFolderSectionFolders && | 337 if (section == BookmarkFolderSectionFolders && |
343 [self shouldShowDefaultSection]) { | 338 [self shouldShowDefaultSection]) { |
344 CGRect separatorFrame = | 339 CGRect separatorFrame = |
345 CGRectMake(0, 0, CGRectGetWidth(headerView.bounds), | 340 CGRectMake(0, 0, CGRectGetWidth(headerView.bounds), |
346 1.0 / [[UIScreen mainScreen] scale]); // 1-pixel divider. | 341 1.0 / [[UIScreen mainScreen] scale]); // 1-pixel divider. |
347 base::scoped_nsobject<UIView> separator( | 342 UIView* separator = [[UIView alloc] initWithFrame:separatorFrame]; |
348 [[UIView alloc] initWithFrame:separatorFrame]); | 343 separator.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | |
349 separator.get().autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | | 344 UIViewAutoresizingFlexibleWidth; |
350 UIViewAutoresizingFlexibleWidth; | 345 separator.backgroundColor = bookmark_utils_ios::separatorColor(); |
351 separator.get().backgroundColor = bookmark_utils_ios::separatorColor(); | |
352 [headerView addSubview:separator]; | 346 [headerView addSubview:separator]; |
353 } | 347 } |
354 return headerView; | 348 return headerView; |
355 } | 349 } |
356 | 350 |
357 - (CGFloat)tableView:(UITableView*)tableView | 351 - (CGFloat)tableView:(UITableView*)tableView |
358 heightForFooterInSection:(NSInteger)section { | 352 heightForFooterInSection:(NSInteger)section { |
359 switch (static_cast<BookmarkFolderSection>(section)) { | 353 switch (static_cast<BookmarkFolderSection>(section)) { |
360 case BookmarkFolderSectionDefault: | 354 case BookmarkFolderSectionDefault: |
361 return [self shouldShowDefaultSection] ? kSectionFooterHeight : 0; | 355 return [self shouldShowDefaultSection] ? kSectionFooterHeight : 0; |
362 | 356 |
363 case BookmarkFolderSectionFolders: | 357 case BookmarkFolderSectionFolders: |
364 return kSectionFooterHeight; | 358 return kSectionFooterHeight; |
365 } | 359 } |
366 NOTREACHED(); | 360 NOTREACHED(); |
367 return 0; | 361 return 0; |
368 } | 362 } |
369 | 363 |
370 - (UIView*)tableView:(UITableView*)tableView | 364 - (UIView*)tableView:(UITableView*)tableView |
371 viewForFooterInSection:(NSInteger)section { | 365 viewForFooterInSection:(NSInteger)section { |
372 return [[[UIView alloc] init] autorelease]; | 366 return [[UIView alloc] init]; |
373 } | 367 } |
374 | 368 |
375 - (void)tableView:(UITableView*)tableView | 369 - (void)tableView:(UITableView*)tableView |
376 didSelectRowAtIndexPath:(NSIndexPath*)indexPath { | 370 didSelectRowAtIndexPath:(NSIndexPath*)indexPath { |
377 [tableView deselectRowAtIndexPath:indexPath animated:YES]; | 371 [tableView deselectRowAtIndexPath:indexPath animated:YES]; |
378 switch (static_cast<BookmarkFolderSection>(indexPath.section)) { | 372 switch (static_cast<BookmarkFolderSection>(indexPath.section)) { |
379 case BookmarkFolderSectionDefault: | 373 case BookmarkFolderSectionDefault: |
380 [self pushFolderAddViewController]; | 374 [self pushFolderAddViewController]; |
381 break; | 375 break; |
382 | 376 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 [BookmarkFolderEditorViewController | 525 [BookmarkFolderEditorViewController |
532 folderCreatorWithBookmarkModel:self.bookmarkModel | 526 folderCreatorWithBookmarkModel:self.bookmarkModel |
533 parentFolder:self.selectedFolder]; | 527 parentFolder:self.selectedFolder]; |
534 folderCreator.delegate = self; | 528 folderCreator.delegate = self; |
535 [self.navigationController pushViewController:folderCreator animated:YES]; | 529 [self.navigationController pushViewController:folderCreator animated:YES]; |
536 self.folderAddController = folderCreator; | 530 self.folderAddController = folderCreator; |
537 } | 531 } |
538 | 532 |
539 - (void)delayedNotifyDelegateOfSelection { | 533 - (void)delayedNotifyDelegateOfSelection { |
540 self.view.userInteractionEnabled = NO; | 534 self.view.userInteractionEnabled = NO; |
541 base::WeakNSObject<BookmarkFolderViewController> weakSelf(self); | 535 __weak BookmarkFolderViewController* weakSelf = self; |
542 dispatch_after( | 536 dispatch_after( |
543 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), | 537 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), |
544 dispatch_get_main_queue(), ^{ | 538 dispatch_get_main_queue(), ^{ |
545 base::scoped_nsobject<BookmarkFolderViewController> strongSelf( | 539 BookmarkFolderViewController* strongSelf = weakSelf; |
546 [weakSelf retain]); | |
547 // Early return if the controller has been deallocated. | 540 // Early return if the controller has been deallocated. |
548 if (!strongSelf) | 541 if (!strongSelf) |
549 return; | 542 return; |
550 strongSelf.get().view.userInteractionEnabled = YES; | 543 strongSelf.view.userInteractionEnabled = YES; |
551 [strongSelf done:nil]; | 544 [strongSelf done:nil]; |
552 }); | 545 }); |
553 } | 546 } |
554 | 547 |
555 @end | 548 @end |
OLD | NEW |