// // CPDFViewController.m // PDFViewer // // Created by kdan on 2022/11/15. // #import #import #import #import "PDFViewController.h" #import "PDFWatermarkTextPreview.h" #import "PDFWatermarkImagePreview.h" #import "PDFDataModel.h" #import "PDFBackgroundModel.h" #import "Masonry.h" #import "PDFAddWaterMarkViewController.h" #import "PDFBackgroundSettingViewController.h" #import "PDFHeaderFooterAddController.h" #import "PDFBatesAddViewController.h" #import "PDFHeaderFooterSettingView.h" @interface PDFViewController () @property (nonatomic,strong) CPDFView *pdfView; @property (nonatomic,strong) CPDFDocument *pdfDocument; @property (nonatomic,strong) PDFAddWaterMarkViewController *addWaterMarkViewController; @property (nonatomic,strong) UIImage *image; @property (nonatomic,strong) PDFHeaderFooterSettingView *headerFooterSetting; @property (nonatomic,strong) PDFHeaderFooterSettingView *batesSetting; @end @implementation PDFViewController #pragma mark - Initializers - (instancetype)initWithPath:(NSString *)inPath { if (self = [super init]) { _path = inPath; } return self; } #pragma mark - UIViewController Methods - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //add UIBarButtonItem in Navigation self.navigationController.toolbarHidden = YES; UIImage *btnMore = [UIImage imageNamed:@"btn_more"]; UIBarButtonItem *ringhtBarItem = [[UIBarButtonItem alloc] initWithImage:btnMore style:UIBarButtonItemStylePlain target:self action:@selector(PDFViewPerformOnClickedOkbtn)]; self.navigationItem.rightBarButtonItem = ringhtBarItem; //setting URL NSURL *url = [NSURL fileURLWithPath:_path]; _pdfDocument = [[CPDFDocument alloc] initWithURL:url]; _pdfView = [[CPDFView alloc] initWithFrame:self.view.bounds]; _pdfView.document = _pdfDocument; _pdfView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:_pdfView]; CPDFPage *pdfPage = [_pdfView.document pageAtIndex:0]; CGSize imageSize = [_pdfView.document pageSizeAtIndex:0]; _image = [pdfPage thumbnailOfSize:imageSize]; _headerFooterSetting = [[PDFHeaderFooterSettingView alloc] init]; [_headerFooterSetting setText]; _batesSetting = [[PDFHeaderFooterSettingView alloc] init]; [_batesSetting setText]; } #pragma mark - PDFViewer - More : Import HeaderFooter, Bates, Watermark, Background - (void)PDFViewPerformOnClickedOkbtn { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertAction *addWatermarkAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Add Watermark",nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { self.addWaterMarkViewController = [[PDFAddWaterMarkViewController alloc] initWithDocument:self.pdfDocument]; self.addWaterMarkViewController.delegate = self; [self.navigationController pushViewController:self.addWaterMarkViewController animated:YES]; }]; // Setting headerfooter action UIAlertAction *settingHeaderFooter = [UIAlertAction actionWithTitle:NSLocalizedString(@"Setting Headerfooter", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self PDFViewPerformSettingHeaderFooter]; }]; // Seeting bates action UIAlertAction *settingBatesAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Setting Bates",nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self PDFViewPerformSettingBates]; }]; UIAlertAction *addBackgroundAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Add Background", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { PDFBackgroundSettingViewController * addBackgroundViewController = [[PDFBackgroundSettingViewController alloc] initWithDocument:self.pdfDocument]; addBackgroundViewController.delegate = self; [self.navigationController pushViewController:addBackgroundViewController animated:YES]; }]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]; [alertController addAction:addWatermarkAction]; [alertController addAction:settingHeaderFooter]; [alertController addAction:settingBatesAction]; [alertController addAction:addBackgroundAction]; [alertController addAction:cancelAction]; [self presentViewController:alertController animated:YES completion:nil]; } #pragma mark - PDFViewer - More :Add / Delete images HeaderFooter and Bates - (void)PDFViewPerformSettingHeaderFooter { [self.view addSubview:_headerFooterSetting]; [_headerFooterSetting mas_remakeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(self.view.mas_bottom); make.left.equalTo(self.view.mas_left); make.right.equalTo(self.view.mas_right); make.height.mas_equalTo(100); }]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.headerFooterSetting.center = CGPointMake(self.headerFooterSetting.center.x, self.headerFooterSetting.center.y - 100); } completion:nil]; [_headerFooterSetting.addButton addTarget:self action:@selector(PDFViewPerformAddHeaderFooter:) forControlEvents:UIControlEventTouchUpInside]; [_headerFooterSetting.deleteButton addTarget:self action:@selector(PDFViewPerformDeleteHeaderFooter:) forControlEvents:UIControlEventTouchUpInside]; } - (void)PDFViewPerformSettingBates { [self.view addSubview:_batesSetting]; [_batesSetting mas_remakeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(self.view.mas_bottom); make.left.equalTo(self.view.mas_left); make.right.equalTo(self.view.mas_right); make.height.mas_equalTo(100); }]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.batesSetting.center = CGPointMake(self.batesSetting.center.x, self.batesSetting.center.y - 100); } completion:nil]; [_batesSetting.addButton addTarget:self action:@selector(PDFViewPerformAddBates:) forControlEvents:UIControlEventTouchUpInside]; [_batesSetting.deleteButton addTarget:self action:@selector(PDFViewPerformDeleteBates:) forControlEvents:UIControlEventTouchUpInside]; } - (void)PDFViewPerformAddHeaderFooter:(UIButton *)btn { PDFHeaderFooterAddController *headerFooterControl = [[PDFHeaderFooterAddController alloc] initWithImage:self.image]; headerFooterControl.delegate = self; [self.navigationController pushViewController:headerFooterControl animated:NO]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.headerFooterSetting.center = CGPointMake(self.headerFooterSetting.center.x, self.headerFooterSetting.center.y + 100); } completion:nil]; } - (void)PDFViewPerformDeleteHeaderFooter:(UIButton *)btn { [self PDFViewPerformDeleteHeaderFooterAction]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.headerFooterSetting.center = CGPointMake(self.headerFooterSetting.center.x, self.headerFooterSetting.center.y + 100); } completion:nil]; } - (void)PDFViewPerformAddBates:(UIButton *)btn { PDFBatesAddViewController *batesAddControl = [[PDFBatesAddViewController alloc] initWithImage:self.image]; batesAddControl.delegate = self; [self.navigationController pushViewController:batesAddControl animated:NO]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.batesSetting.center = CGPointMake(self.batesSetting.center.x, self.batesSetting.center.y + 100); } completion:nil]; } - (void)PDFViewPerformDeleteBates:(UIButton *)btn { [self PDFViewPerformDeleteBatesAction]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.batesSetting.center = CGPointMake(self.batesSetting.center.x, self.batesSetting.center.y + 100); } completion:nil]; } // Detele headerfootr action - (void)PDFViewPerformDeleteHeaderFooterAction { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Delete Page Number", nil) message:NSLocalizedString(@"Are you sure delete all pages number", nil) preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self PDFViewPerformDeleteHeaderFooter]; }]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel",nil) style:UIAlertActionStyleCancel handler:nil]; [alertController addAction:okAction]; [alertController addAction:cancelAction]; [self presentViewController:alertController animated:YES completion:nil]; } // Delete bates action - (void)PDFViewPerformDeleteBatesAction { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Delete Bates", nil) message:NSLocalizedString(@"Are you sure delete all Bates",nil) preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self PDFViewPerformDeleteBates]; }]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]; [alertController addAction:okAction]; [alertController addAction:cancelAction]; [self presentViewController:alertController animated:YES completion:nil]; } #pragma mark - CPDFModelDataDelegate // Get headerfooter' model to setting page headerfooter's add functional property - (void)PDFViewPerformChangeHeaderFooter:(PDFHeaderFooterModel *)modelData { CPDFHeaderFooter *headerFooter = [self.pdfDocument headerFooter]; NSString *pageIndex = [NSString stringWithFormat:@"0-%lu",self.pdfDocument.pageCount - 1]; NSString *text = [[NSString alloc] init]; switch (modelData.fontSelcet) { case 0: text = [NSString stringWithFormat:@"<<%@>>",modelData.pageStart]; break; case 1: text = [NSString stringWithFormat:@"page <<%@>>",modelData.pageStart]; break; case 2: text = [NSString stringWithFormat:@"<<%@>>/%lu",modelData.pageStart,self.pdfDocument.pageCount]; break; case 3: text = [NSString stringWithFormat:@"<<%@>> of %lu",modelData.pageStart,self.pdfDocument.pageCount]; break; case 4: text = [NSString stringWithFormat:@"page <<%@>> of %lu",modelData.pageStart,self.pdfDocument.pageCount]; break; default: break; } headerFooter.pageString = pageIndex; [headerFooter setText:text atIndex:modelData.fontPosition]; [headerFooter setFontSize:modelData.fontSize atIndex:modelData.fontPosition]; [headerFooter setTextColor:modelData.fontColor atIndex:modelData.fontPosition]; [headerFooter update]; [self pdfViewUpdate]; } // Get bates' model to setting page bates's add functional property - (void)PDFViewPerformChangBates:(PDFHeaderFooterModel *)modelData { PDFHeaderFooterModel *modelBatesData = modelData; CPDFBates *bates = [self.pdfDocument bates]; NSString *pageIndex = [NSString stringWithFormat:@"%@-%lu",modelBatesData.pageStart,self.pdfDocument.pageCount - 1]; bates.pageString = pageIndex; NSString *text = [NSString stringWithFormat:@"<<%@>>",modelBatesData.fontText]; [bates setText:text atIndex:modelBatesData.fontPosition]; [bates setFontName:modelBatesData.fontName atIndex:modelBatesData.fontPosition]; [bates setFontSize:15.0 atIndex:modelBatesData.fontPosition]; [bates setTextColor:modelBatesData.fontColor atIndex:modelBatesData.fontPosition]; [bates update]; [self pdfViewUpdate]; } #pragma mark - PDF View Update - (void)pdfViewUpdate { [self.pdfView.document writeToURL:self.pdfView.document.documentURL]; [self loadDocumentWithFilePath:self.pdfView.document.documentURL.path completion:nil]; } - (void)pdfViewDelete { NSURL *url = [NSURL fileURLWithPath:_path]; [_pdfView.document writeToURL:url]; _pdfDocument = [[CPDFDocument alloc] initWithURL:url]; _pdfView = [[CPDFView alloc] initWithFrame:self.view.bounds]; _pdfView.document = _pdfDocument; _pdfView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:_pdfView]; } - (void)loadDocumentWithFilePath:(NSString *)filePath completion:(void (^)(BOOL result))completion { self.title = [[filePath lastPathComponent] stringByDeletingPathExtension]; self.pdfView.document = nil; [self.navigationController.view setUserInteractionEnabled:NO]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSURL *url = [NSURL fileURLWithPath:self.path]; CPDFDocument *document = [[CPDFDocument alloc] initWithURL:url]; dispatch_async(dispatch_get_main_queue(), ^{ [self.navigationController.view setUserInteractionEnabled:YES]; if (document.error && document.error.code != CPDFDocumentPasswordError) { UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self.navigationController popViewControllerAnimated:YES]; }]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:NSLocalizedString(@"Sorry PDF Reader Can't open this pdf file!", nil) preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:okAction]; [self presentViewController:alert animated:YES completion:nil]; if (completion) { completion(NO); } } else { self.pdfView.document = document; if (completion) { completion(YES); } } }); }); } #pragma mark - Delete Methods // Get headerfooter' model to setting page headerfooter's delete functional property - (void)PDFViewPerformDeleteHeaderFooter { CPDFHeaderFooter *headerFooter = [self.pdfDocument headerFooter]; [headerFooter clear]; [self pdfViewDelete]; } // Get bates' model to setting page bates's delete functional property - (void)PDFViewPerformDeleteBates { CPDFBates *bates = [self.pdfDocument bates]; [bates clear]; [self pdfViewDelete]; } #pragma mark - WaterMarkModelDataDelegate - (void)PDFViewPerformChangeTextWatermark:(PDFDataModel *)dataModel { CPDFWatermark *textWatermark = [[CPDFWatermark alloc] initWithDocument:_pdfDocument type:CPDFWatermarkTypeText]; textWatermark.text = dataModel.text; textWatermark.textColor = dataModel.textColor; textWatermark.opacity = dataModel.watermarkOpacity; textWatermark.scale = dataModel.watermarkScale * 2.5; textWatermark.isTilePage = dataModel.isTile; textWatermark.tx = dataModel.tx * (_image.size.width / 3) / self.addWaterMarkViewController.textViewController.textPreview.documentImageView.frame.size.width; textWatermark.ty = dataModel.ty * (_image.size.height / 3) / self.addWaterMarkViewController.textViewController.textPreview.documentImageView.frame.size.height; textWatermark.rotation = dataModel.watermarkRotation; if (textWatermark.isTilePage) { textWatermark.verticalSpacing = dataModel.verticalSpacing; textWatermark.horizontalSpacing = dataModel.horizontalSpacing; } if (dataModel.pageString) { textWatermark.pageString = dataModel.pageString; } [_pdfView.document addWatermark:textWatermark]; [self pdfViewUpdate]; } - (void)PDFViewPerformChangeImageWatermark:(PDFDataModel *)dataModel { CPDFWatermark *imageWatermark = [[CPDFWatermark alloc] initWithDocument:_pdfDocument type:CPDFWatermarkTypeImage]; imageWatermark.image = dataModel.image; imageWatermark.opacity = dataModel.watermarkOpacity; imageWatermark.scale = dataModel.watermarkScale * 2; imageWatermark.isTilePage = dataModel.isTile; imageWatermark.tx = dataModel.tx * (_image.size.width / 3) / self.addWaterMarkViewController.imageViewController.imagePreview.documentImageView.frame.size.width; imageWatermark.ty = dataModel.ty * (_image.size.height / 3) / self.addWaterMarkViewController.imageViewController.imagePreview.documentImageView.frame.size.height; imageWatermark.rotation = dataModel.watermarkRotation; if (imageWatermark.isTilePage) { imageWatermark.verticalSpacing = dataModel.verticalSpacing; imageWatermark.horizontalSpacing = dataModel.horizontalSpacing; } if (dataModel.pageString) { imageWatermark.pageString = dataModel.pageString; } [_pdfView.document addWatermark:imageWatermark]; [self pdfViewUpdate]; } - (void)PDFViewPerformDeleteWatermark:(CPDFWatermark *)waterMark { [self.pdfDocument removeWatermark:waterMark]; [self pdfViewDelete]; } #pragma mark - BackgroundDataModelDelegate - (void)PDFViewPerformChangeBackground:(PDFBackgroundModel *)dataModel { CPDFBackground *pageBackground = [_pdfDocument background]; pageBackground.color = dataModel.backgroundColor; pageBackground.scale = dataModel.backgroudScale; pageBackground.rotation = dataModel.backgroundRotation; pageBackground.opacity = dataModel.backgroundOpacity; pageBackground.pageString = dataModel.pageString; pageBackground.xOffset = dataModel.horizontalSpacing; pageBackground.yOffset = dataModel.verticalSpacing; pageBackground.isAllowsView = YES; pageBackground.isAllowsPrint = YES; [pageBackground setImage:dataModel.image]; [pageBackground update]; [self pdfViewUpdate]; } - (void)PDFViewPerformDeleteBackground { CPDFBackground *pageBackground = [_pdfDocument background]; [pageBackground clear]; [self pdfViewDelete]; } @end