// // CPDFTextViewController.m // PDFViewer // // Created by kdan on 2022/11/19. // #import "CPDFTextViewController.h" #import "CPDFTextView.h" #import "CPDFDataModel.h" #import "CPDFDrawView.h" #import "CPDFClipView.h" #import "Masonry.h" @interface CPDFTextViewController () @property (nonatomic,strong) CPDFDrawView *drawView; @property (nonatomic,strong) CPDFClipView *cliView; @end @implementation CPDFTextViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. _textPreview = [[CPDFTextPreview alloc] init]; _textView = [[CPDFTextView alloc] init]; _textView.verticalField.delegate = self; _textView.horizontalField.delegate = self; _dataModel = [[CPDFDataModel alloc] init]; _alertController = [UIAlertController alertControllerWithTitle:@"Watermark Content" message:nil preferredStyle:UIAlertControllerStyleAlert]; [self.view addSubview:_textPreview]; [self.view addSubview:_textView]; [self.view setBackgroundColor:UIColor.systemGray5Color]; [self addConstraint]; [self initDataModel]; [self addTargets]; [self createGestureRecognizer]; } #pragma mark - Initializers - (void)initDataModel { _dataModel.textColor = UIColor.blackColor; _dataModel.watermarkOpacity = 1; _dataModel.text = @"Watermark"; _dataModel.watermarkScale = 1; _dataModel.isTile = NO; _dataModel.watermarkRotation = 0; _dataModel.verticalSpacing = 100; _dataModel.horizontalSpacing = 100; _textPreview.watermarkLabel.text = _dataModel.text; _textView.horizontalField.text = 0; _textView.verticalField.text = 0; _textView.horizontalField.enabled = NO; _textView.verticalField.enabled = NO; } - (void)addConstraint { [_textPreview mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.width.equalTo(self.view.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(-205); }]; [_textView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_textPreview.mas_bottom).offset(0); make.width.equalTo(_textPreview.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(0); }]; } - (void)addTargets { for (NSInteger i = 0; i < _textView.colorArray.count; ++i) { [_textView.colorArray[i] addTarget:self action:@selector(onColorBtnClicked:) forControlEvents:UIControlEventTouchDown]; } __block CPDFTextViewController *strongBlock = self; [_alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { }]; [_alertController addAction:[UIAlertAction actionWithTitle:@"Done" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { strongBlock.dataModel.text = strongBlock.alertController.textFields.firstObject.text; strongBlock.textPreview.watermarkLabel.text = strongBlock.alertController.textFields.firstObject.text; [strongBlock.textPreview.watermarkLabel sizeToFit]; }]]; [_alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { strongBlock.alertController.view.hidden = YES; }]]; [_textView.opacitySlider addTarget:self action:@selector(onOpacityChanged:) forControlEvents:UIControlEventValueChanged]; [_textView.textScaleSlider addTarget:self action:@selector(onTextScaleChanged:) forControlEvents:UIControlEventValueChanged]; [_textView.tileSwitch addTarget:self action:@selector(onTileSwitchChanged:) forControlEvents:UIControlEventValueChanged]; [_textView.pageBtn addTarget:self action:@selector(onSelectPageRange:) forControlEvents:UIControlEventTouchDown]; [_textView.horizontalField addTarget:self action:@selector(horizontalChange:) forControlEvents:UIControlEventEditingDidEnd]; [_textView.verticalField addTarget:self action:@selector(verticalChage:) forControlEvents:UIControlEventEditingDidEnd]; } #pragma mark - UI Functions - (void)onColorBtnClicked:(UIButton *)sender { _textPreview.watermarkLabel.textColor = sender.backgroundColor; [_dataModel setTextColor:sender.backgroundColor]; } - (void)onOpacityChanged:(UISlider *)sender { _textPreview.watermarkLabel.alpha = 1 - sender.value; [_dataModel setWatermarkOpacity:1 - sender.value]; } - (void)onTextScaleChanged:(UISlider *)sender { if (!_dataModel.isTile) { sender.minimumValue = 12; sender.maximumValue = 36; _textPreview.watermarkLabel.font = [_textPreview.watermarkLabel.font fontWithSize:sender.value]; [_textPreview.watermarkLabel sizeToFit]; [_dataModel setWatermarkScale:sender.value / 24]; } } - (void)onTileSwitchChanged:(UISwitch *) sender { if ([sender isOn]) { _dataModel.isTile = YES; _textView.horizontalField.enabled = YES; _textView.verticalField.enabled = YES; _textView.textScaleSlider.enabled = NO; _drawView = [[CPDFDrawView alloc] initWithFrame:self.textPreview.bounds]; [_drawView setDataModel:self.dataModel]; [_drawView setWaterLabelRect:self.textPreview.watermarkLabel.frame]; [_drawView setDocumentViewRect:self.textPreview.documentView.frame]; [self.view addSubview:_drawView]; [self.textPreview bringSubviewToFront:_drawView]; _cliView = [[CPDFClipView alloc] initWithFrame:self.textPreview.bounds]; _cliView.delegate = self; [self.view addSubview:_cliView]; [self.drawView bringSubviewToFront:_cliView]; } else { _dataModel.isTile = NO; _textView.horizontalField.enabled = NO; _textView.verticalField.enabled = NO; _textView.textScaleSlider.enabled = YES; [_drawView removeFromSuperview]; [_cliView removeFromSuperview]; } } - (void)onSelectPageRange:(UIButton *)sender { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertAction *defaultRange = [UIAlertAction actionWithTitle:@"All Pages" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { self.textView.rangeLabel.text = @"Page Range: ALL"; }]; UIAlertAction *customRange = [UIAlertAction actionWithTitle:@"Custom Page Range" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self createCustomRangeAlert]; }]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]; [alertController addAction:defaultRange]; [alertController addAction:customRange]; [alertController addAction:cancelAction]; [self presentViewController:alertController animated:YES completion:nil]; } - (void)createCustomRangeAlert { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Custom Page Range" message:nil preferredStyle:UIAlertControllerStyleAlert]; [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.placeholder = @"such as:1,3-5,10"; }]; [alertController addAction:[UIAlertAction actionWithTitle:@"Done" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { self.dataModel.pageString = alertController.textFields.firstObject.text; self.textView.rangeLabel.text = @"Page Range:Custom"; }]]; [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]]; [self presentViewController:alertController animated:YES completion:nil]; } - (void)horizontalChange:(UITextField *)text { [_drawView setHorizontal:[text.text floatValue]]; _dataModel.horizontalSpacing = [text.text floatValue]; [_drawView setNeedsDisplay]; } - (void)verticalChage:(UITextField *)text { [_drawView setVertical:[text.text floatValue]]; _dataModel.verticalSpacing = [text.text floatValue]; [_drawView setNeedsDisplay]; } #pragma mark - Gesture - (void)createGestureRecognizer { [_textPreview.documentView setUserInteractionEnabled:YES]; [_textPreview.watermarkLabel setUserInteractionEnabled:YES]; [_textPreview.rotationBtn setUserInteractionEnabled:YES]; UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapWatermarkLabel:)]; [_textPreview.watermarkLabel addGestureRecognizer:tapGestureRecognizer]; UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panWatermarkLabel:)]; [_textPreview.watermarkLabel addGestureRecognizer:panRecognizer]; UIPanGestureRecognizer *panRotationBtnRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(rotationWatermarkLabel:)]; [_textPreview.rotationBtn addGestureRecognizer:panRotationBtnRecognizer]; } - (void)tapWatermarkLabel:(UITapGestureRecognizer *)recognizer { _alertController.view.hidden = NO; _alertController.textFields.firstObject.text = _textPreview.watermarkLabel.text; [self presentViewController:_alertController animated:true completion:nil]; } - (void)panWatermarkLabel:(UIPanGestureRecognizer *)recognizer { CGPoint point = [recognizer translationInView:_textPreview.documentView]; CGRect documentFrame = _textPreview.documentView.frame; documentFrame.origin.x -= _textPreview.documentView.frame.origin.x; documentFrame.origin.y -= _textPreview.documentView.frame.origin.y; [_textPreview.watermarkLabel setCenter:CGPointMake(_textPreview.watermarkLabel.center.x + point.x, _textPreview.watermarkLabel.center.y + point.y)]; [_textPreview.rotationBtn setCenter:CGPointMake(_textPreview.rotationBtn.center.x + point.x, _textPreview.rotationBtn.center.y + point.y)]; if (!CGRectContainsRect(documentFrame,_textPreview.watermarkLabel.frame)) { [_textPreview.watermarkLabel setCenter:CGPointMake(_textPreview.watermarkLabel.center.x - point.x, _textPreview.watermarkLabel.center.y - point.y)]; [_textPreview.rotationBtn setCenter:CGPointMake(_textPreview.rotationBtn.center.x - point.x, _textPreview.rotationBtn.center.y - point.y)]; } _dataModel.tx = _textPreview.watermarkLabel.center.x - (_textPreview.documentView.center.x - _textPreview.documentView.frame.origin.x); _dataModel.ty = _textPreview.documentView.center.y - _textPreview.documentView.frame.origin.y - _textPreview.watermarkLabel.center.y; [recognizer setTranslation:CGPointZero inView:_textPreview.documentView]; } - (void)rotationWatermarkLabel:(UIPanGestureRecognizer *)recognizer { CGPoint point = [recognizer translationInView:_textPreview]; CGFloat radian = atan2(point.x + _textPreview.center.x - _textPreview.watermarkLabel.center.x, point.y + _textPreview.center.y - _textPreview.watermarkLabel.center.y); _textPreview.watermarkLabel.transform = CGAffineTransformMakeRotation(-radian); _dataModel.watermarkRotation = (-radian) * 180 / M_PI; } #pragma mark - Orientation - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) { [_textView mas_remakeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.view.mas_right).offset(-38); make.left.equalTo(_textPreview.mas_right).offset(0); make.height.equalTo(@205); make.width.equalTo(@(self.view.bounds.size.width)); make.bottom.equalTo(self.view.mas_bottom).offset(-40); }]; [_textPreview mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(10); make.right.equalTo(_textView.mas_left).offset(-5); make.left.equalTo(self.view.mas_left).offset(0); make.bottom.equalTo(self.view.mas_bottom).offset(0); }]; } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationPortrait) { [_textPreview mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.width.equalTo(self.view.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(-205); }]; [_textView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_textPreview.mas_bottom).offset(0); make.width.equalTo(_textPreview.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(0); }]; } } #pragma mark - CPDFClipTextPreviewDelegate - (void)clipText:(CGContextRef)context { CGContextSetFillColorWithColor(context, [UIColor systemGray5Color].CGColor); CGContextFillRect(context, self.textPreview.bounds); CGContextClearRect(context, self.textPreview.documentView.frame); } #pragma mark - UITextFieldDelegate - (void)textFieldDidBeginEditing:(UITextField *)textField { self.cliView.hidden = YES; self.drawView.hidden = YES; if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight || [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft || [UIDevice currentDevice].orientation == UIDeviceOrientationPortraitUpsideDown) { } else { [_textView mas_remakeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(205); make.width.equalTo(_textPreview.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(-300); }]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.textView.center = CGPointMake(self.textView.center.x, self.textView.center.y - 300); } completion:nil]; } } - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; self.cliView.hidden = NO; self.drawView.hidden = NO; if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight || [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft || [UIDevice currentDevice].orientation == UIDeviceOrientationPortraitUpsideDown) { } else { [_textView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_textPreview.mas_bottom).offset(0); make.width.equalTo(_textPreview.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(0); make.height.mas_equalTo(205); }]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.textView.center = CGPointMake(self.textView.center.x, self.textView.center.y + 300); } completion:nil]; } return YES; } @end