CPDFBookmarkViewController.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. //
  2. // CPDFBookmarkViewController.m
  3. // ComPDFKit_Tools
  4. //
  5. // Copyright © 2014-2024 PDF Technologies, Inc. All Rights Reserved.
  6. //
  7. // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
  8. // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
  9. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
  10. //
  11. #import "CPDFBookmarkViewController.h"
  12. #import "CPDFBookmarkViewCell.h"
  13. #import <ComPDFKit/ComPDFKit.h>
  14. @interface CPDFBookmarkViewController () <UITableViewDelegate, UITableViewDataSource>
  15. @property (nonatomic, strong) NSArray *bookmarks;
  16. @property (nonatomic, strong) UITableView *tableView;
  17. @property (nonatomic, strong) UILabel *noDataLabel;
  18. @property (nonatomic, strong) UIButton *addBookmarkBtn;
  19. @end
  20. @implementation CPDFBookmarkViewController
  21. #pragma mark - Initializers
  22. - (instancetype)initWithPDFView:(CPDFView *)pdfView {
  23. if (self = [super init]) {
  24. _pdfView = pdfView;
  25. }
  26. return self;
  27. }
  28. #pragma mark - UIViewController Methods
  29. - (void)viewDidLoad {
  30. [super viewDidLoad];
  31. // Do any additional setup after loading the view.
  32. _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
  33. _tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  34. _tableView.delegate = self;
  35. _tableView.dataSource = self;
  36. _tableView.rowHeight = UITableViewAutomaticDimension;
  37. _tableView.estimatedRowHeight = 60;
  38. _tableView.tableFooterView = [[UIView alloc] init];
  39. [_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
  40. [self.view addSubview:self.tableView];
  41. _noDataLabel = [[UILabel alloc] init];
  42. _noDataLabel.textColor = [UIColor grayColor];
  43. _noDataLabel.text = NSLocalizedString(@"No Bookmarks", nil);
  44. [_noDataLabel sizeToFit];
  45. _noDataLabel.center = CGPointMake(self.view.bounds.size.width/2.0, self.view.bounds.size.height/2.0);
  46. _noDataLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
  47. [self.view addSubview:self.noDataLabel];
  48. if (@available(iOS 11.0, *)) {
  49. _addBookmarkBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width - self.view.safeAreaInsets.right - 50 - 20, self.view.frame.size.height - self.view.safeAreaInsets.bottom - 50, 50, 50)];
  50. } else {
  51. _addBookmarkBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width - 20 - 50, self.view.frame.size.height - 50 - 50, 50, 50)];
  52. }
  53. _addBookmarkBtn.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
  54. [_addBookmarkBtn setImage:[UIImage imageNamed:@"CPDFBookmarkImageAdd" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil] forState:UIControlStateNormal];
  55. [_addBookmarkBtn addTarget:self action:@selector(buttonItemClicked_add:) forControlEvents:UIControlEventTouchUpInside];
  56. [self.view addSubview:self.addBookmarkBtn];
  57. [self createGestureRecognizer];
  58. }
  59. - (void)viewDidAppear:(BOOL)animated {
  60. [super viewDidAppear:animated];
  61. [self reloadData];
  62. }
  63. #pragma mark - Private Methods
  64. - (void)reloadData {
  65. if ([self.pdfView.document bookmarks].count > 0) {
  66. self.bookmarks = [self.pdfView.document bookmarks];
  67. self.tableView.hidden = NO;
  68. self.noDataLabel.hidden = YES;
  69. } else {
  70. self.tableView.hidden = YES;
  71. self.noDataLabel.hidden = NO;
  72. }
  73. [self.tableView reloadData];
  74. }
  75. - (void)createGestureRecognizer {
  76. [self.addBookmarkBtn setUserInteractionEnabled:YES];
  77. UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panaddBookmarkBtn:)];
  78. [self.addBookmarkBtn addGestureRecognizer:panRecognizer];
  79. }
  80. - (void)panaddBookmarkBtn:(UIPanGestureRecognizer *)gestureRecognizer {
  81. CGPoint point = [gestureRecognizer translationInView:self.view];
  82. CGFloat newX = self.addBookmarkBtn.center.x + point.x;
  83. CGFloat newY = self.addBookmarkBtn.center.y + point.y;
  84. if (CGRectContainsPoint(self.view.frame, CGPointMake(newX, newY))) {
  85. self.addBookmarkBtn.center = CGPointMake(newX, newY);
  86. }
  87. [gestureRecognizer setTranslation:CGPointZero inView:self.view];
  88. }
  89. #pragma mark - Action
  90. - (void)buttonItemClicked_add:(id)sender {
  91. if (![self.pdfView.document bookmarkForPageIndex:self.pdfView.currentPageIndex]) {
  92. UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Add Bookmarks", nil) message:nil preferredStyle:UIAlertControllerStyleAlert];
  93. [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
  94. textField.placeholder = NSLocalizedString(@"Bookmark Title", nil);
  95. }];
  96. UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil];
  97. UIAlertAction *addAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Add", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  98. if(alert.textFields.firstObject.text.length > 0) {
  99. [self.pdfView.document addBookmark:alert.textFields.firstObject.text forPageIndex:self.pdfView.currentPageIndex];
  100. CPDFPage *page = [self.pdfView.document pageAtIndex:self.pdfView.currentPageIndex];
  101. [self.pdfView setNeedsDisplayForPage:page];
  102. [self reloadData];
  103. }
  104. }];
  105. [alert addAction:cancelAction];
  106. [alert addAction:addAction];
  107. [self presentViewController:alert animated:YES completion:nil];
  108. } else {
  109. UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
  110. style:UIAlertActionStyleDefault
  111. handler:^(UIAlertAction * _Nonnull action) {
  112. [self.pdfView.document removeBookmarkForPageIndex:self.pdfView.currentPageIndex];
  113. CPDFPage *page = [self.pdfView.document pageAtIndex:self.pdfView.currentPageIndex];
  114. [self.pdfView setNeedsDisplayForPage:page];
  115. [self.tableView setEditing:NO animated:YES];
  116. [self.tableView setUserInteractionEnabled:YES];
  117. [self reloadData];
  118. }];
  119. UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil];
  120. UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
  121. message:NSLocalizedString(@"Do you want to remove old mark?", nil)
  122. preferredStyle:UIAlertControllerStyleAlert];
  123. [alert addAction:cancelAction];
  124. [alert addAction:okAction];
  125. [self presentViewController:alert animated:YES completion:nil];
  126. }
  127. }
  128. #pragma mark - UITableViewDataSource
  129. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  130. if (self.bookmarks.count > 0) {
  131. self.noDataLabel.hidden = YES;
  132. } else {
  133. self.noDataLabel.hidden = NO;
  134. }
  135. return self.bookmarks.count;
  136. }
  137. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  138. CPDFBookmarkViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
  139. if (cell == nil) {
  140. cell = [[CPDFBookmarkViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
  141. }
  142. CPDFBookmark *bookmark = self.bookmarks[indexPath.row];
  143. cell.pageIndexLabel.text = [NSString stringWithFormat:@"%@ %ld",NSLocalizedString(@"Page", nil) ,bookmark.pageIndex+1];
  144. cell.titleLabel.text = bookmark.label;
  145. return cell;
  146. }
  147. #pragma mark - UITableViewDelegate
  148. - (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
  149. UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
  150. CPDFBookmarkViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
  151. [self.pdfView.document removeBookmarkForPageIndex:cell.pageIndexLabel.text.floatValue - 1];
  152. NSMutableArray *bookmarks = (NSMutableArray *)self.bookmarks;
  153. [bookmarks removeObjectAtIndex:indexPath.row];
  154. [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:YES];
  155. [self.tableView setEditing:NO animated:YES];
  156. [self.tableView setUserInteractionEnabled:YES];
  157. [self reloadData];
  158. }];
  159. UITableViewRowAction *editAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:NSLocalizedString(@"Edit",nil) handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
  160. UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Edit BookMark",nil) message:nil preferredStyle:UIAlertControllerStyleAlert];
  161. [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
  162. textField.placeholder = NSLocalizedString(@"Bookmark Title", nil);
  163. }];
  164. UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil];
  165. UIAlertAction *addAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Create", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  166. CPDFBookmarkViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
  167. cell.titleLabel.text = alert.textFields.firstObject.text;
  168. self.pdfView.document.bookmarks[indexPath.row].label = alert.textFields.firstObject.text;
  169. }];
  170. [alert addAction:cancelAction];
  171. [alert addAction:addAction];
  172. [self presentViewController:alert animated:YES completion:nil];
  173. [tableView setEditing:NO animated:YES];
  174. [tableView setUserInteractionEnabled:YES];
  175. }];
  176. deleteAction.backgroundColor = [UIColor redColor];
  177. editAction.backgroundColor = [UIColor blueColor];
  178. return @[deleteAction, editAction];
  179. }
  180. - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath{
  181. UIContextualAction * deleteAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:nil handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
  182. CPDFBookmark *bookmark = self.bookmarks[indexPath.row];
  183. [self.pdfView.document removeBookmarkForPageIndex:bookmark.pageIndex];
  184. CPDFPage *page = [self.pdfView.document pageAtIndex:bookmark.pageIndex];
  185. [self.pdfView setNeedsDisplayForPage:page];
  186. NSMutableArray *bookmarks = (NSMutableArray *)self.bookmarks;
  187. [bookmarks removeObjectAtIndex:indexPath.row];
  188. [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:YES];
  189. [self.tableView setEditing:NO animated:YES];
  190. [self.tableView setUserInteractionEnabled:YES];
  191. [self reloadData];
  192. }];
  193. UIContextualAction * editAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:nil handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
  194. UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Edit BookMark",nil) message:nil preferredStyle:UIAlertControllerStyleAlert];
  195. [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
  196. textField.placeholder = NSLocalizedString(@"Bookmark Title", nil);
  197. }];
  198. UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil];
  199. UIAlertAction *addAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Add", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  200. CPDFBookmarkViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
  201. cell.titleLabel.text = alert.textFields.firstObject.text;
  202. self.pdfView.document.bookmarks[indexPath.row].label = alert.textFields.firstObject.text;
  203. }];
  204. [alert addAction:cancelAction];
  205. [alert addAction:addAction];
  206. [self presentViewController:alert animated:YES completion:nil];
  207. [tableView setEditing:NO animated:YES];
  208. [tableView setUserInteractionEnabled:YES];
  209. }];
  210. deleteAction.image = [UIImage imageNamed:@"CPDFBookmarkImageDelete" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];
  211. deleteAction.backgroundColor = [UIColor redColor];
  212. editAction.image = [UIImage imageNamed:@"CPDFBookmarkImageEraser" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];
  213. return [UISwipeActionsConfiguration configurationWithActions: @[deleteAction, editAction]];
  214. }
  215. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  216. CPDFBookmark *bookmark = self.bookmarks[indexPath.row];
  217. if ([self.delegate respondsToSelector:@selector(boomarkViewController:pageIndex:)]) {
  218. [self.delegate boomarkViewController:self pageIndex:bookmark.pageIndex];
  219. }
  220. }
  221. @end