123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- //
- // KMRedactPDFView.swift
- // PDF Master
- //
- // Created by tangchao on 2023/12/18.
- //
- import Cocoa
- class KMRedactPDFView: CPDFView {
-
- /*
- typedef enum {
- KMPDFRedactViewOperationTypeNone,//没有进入任何模式
- KMPDFRedactViewOperationTypeRedact,//标记密文模式
- KMPDFRedactViewOperationTypeEidtText,//文本编辑
- }KMPDFRedactViewOperationType;
- @interface KMRedactPDFView : CPDFView
- @property (nonatomic,retain) CPDFAnnotation *mouseMoveAnnotation;
- @property (nonatomic,retain) CPDFRedactAnnotation *currentAnnotation;
- @property (nonatomic,retain) NSMutableArray *newAddAnnotation;
- @property (nonatomic,retain) NSMutableArray *activeAnnotations;
- @property (nonatomic,assign) KMPDFRedactViewOperationType operationType;
- @property (nonatomic,assign) BOOL isEidtImageModel;
- @property (nonatomic,assign) BOOL isEidtTextModel;
- @property (nonatomic, copy) void(^eventColorChanged)(NSColor *color);
- @property (nonatomic, copy) void(^eventFontChanged)(void);
- @property (nonatomic, copy) void(^exportBtnTaped)(NSInteger type);
- - (void)resignMonitor;
- */
-
- /*
- @property (nonatomic, retain) id localMonitor;
- */
- override func draw(_ dirtyRect: NSRect) {
- super.draw(dirtyRect)
- // Drawing code here.
- }
-
- /*
- - (void)dealloc {
- [_currentAnnotation release];
- [_mouseMoveAnnotation release];
- [_newAddAnnotation release];
- [_activeAnnotations release];
- [_localMonitor release];
- Block_release(_eventColorChanged);
- Block_release(_eventFontChanged);
-
- [super dealloc];
- }
- - (id)initWithFrame:(NSRect)frameRect {
- self = [super initWithFrame:frameRect];
- if (self) {
- self.operationType = KMPDFRedactViewOperationTypeNone;
- [self addTrackingArea];
- [self initMonitor];
- }
- return self;
- }
- - (id)initWithCoder:(NSCoder *)decoder {
- self = [super initWithCoder:decoder];
- if (self) {
- self.operationType = KMPDFRedactViewOperationTypeNone;
- [self addTrackingArea];
- [self initMonitor];
- }
- return self;
- }
- - (void)addTrackingArea
- {
- self.newAddAnnotation = [NSMutableArray array];
- self.activeAnnotations = [NSMutableArray array];
- NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect | NSTrackingActiveInKeyWindow | NSTrackingMouseMoved owner:self userInfo:nil];
- [self addTrackingArea:trackingArea];
- [trackingArea release];
- }
- - (void)initMonitor {
- NSEventMask mask = NSEventMaskKeyDown;
- if (!_localMonitor) {
- _localMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:mask handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
- unichar eventChar = [event firstCharacter];
- NSUInteger modifiers = [event standardModifierFlags];
- if ((eventChar == NSDeleteCharacter || eventChar == NSDeleteFunctionKey) &&
- (modifiers == 0)) {
- [self delete];
- }
- if ([event keyCode] == 36 && modifiers == 0) {
- [self corpImageDoneWithEnter];
- }
- return event;
- }];
- }
- }
- //注销检测器
- - (void)resignMonitor
- {
- [NSEvent removeMonitor:_localMonitor];
- _localMonitor = nil;
- }
- - (CGSize)getWidthFromText:(NSString *)text WithSize:(NSFont *)font AboutWidth:(CGFloat)width AndHeight:(CGFloat)height
- {
- if (!text) {
- return CGSizeMake(0, 0);
- }
- CGRect rect = [text boundingRectWithSize:CGSizeMake(width, height) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font} context:nil];
- return rect.size;
- }
- - (NSMenu *)menuForEvent:(NSEvent *)event {
- NSMenu *menu = [super menuForEvent:event];
- if (!menu) {
- menu = [[[NSMenu alloc] init] autorelease];
- }
- NSPoint pagePoint = NSZeroPoint;
- CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:event nearest:YES];
- CPDFAnnotation *annotation = [page annotationAtPoint:pagePoint];
- if(annotation && [annotation isKindOfClass:[CPDFRedactAnnotation class]] && self.operationType == KMPDFRedactViewOperationTypeRedact) {
- NSMenuItem *item = [menu insertItemWithTitle:NSLocalizedString(@"Delete", nil) action:@selector(deleteAnnotation:) target:self atIndex:0];
- [item setRepresentedObject:annotation];
- [menu insertItem:[NSMenuItem separatorItem] atIndex:1];
- NSMenuItem *itemDefault = [menu insertItemWithTitle:NSLocalizedString(@"Make Current Properties Default", nil) action:@selector(setPropertiesDefault:) target:self atIndex:2];
- [itemDefault setRepresentedObject:annotation];
- [menu insertItemWithTitle:NSLocalizedString(@"Properties...", nil) action:@selector(properties:) target:self atIndex:3];
- [menu insertItem:[NSMenuItem separatorItem] atIndex:4];
- [menu insertItemWithTitle:NSLocalizedString(@"Repeat Mark Across Pages", nil) action:@selector(repeatMark:) target:self atIndex:5];
- [menu insertItemWithTitle:NSLocalizedString(@"Apply Redactions", nil) action:@selector(applyRedact:) target:self atIndex:6];
- self.currentAnnotation = (CPDFRedactAnnotation *)annotation;
- }
- return menu;
- }
- #pragma mark Menu validation
- - (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
- if (!self.document || [self.document isLocked]) {
- return NO;
- }
- SEL action = [menuItem action];
- if (action == @selector(deleteAnnotation:)) {
- return YES;
- } else if (action == @selector(setPropertiesDefault:)) {
-
- return YES;
- } else if (action == @selector(properties:)) {
-
- return YES;
- } else if (action == @selector(repeatMark:)) {
- if(self.document.pageCount == 1)
- return NO;
- return YES;
- } else if (action == @selector(applyRedact:)) {
- return YES;
- } else {
- return [super validateMenuItem:menuItem];
- }
- }
- - (NSArray<NSMenuItem *> *)menuItemsEditingAtPoint:(CGPoint)point forPage:(CPDFPage *)page {
- NSMutableArray <NSMenuItem *>*menuItems = [super menuItemsEditingAtPoint:point forPage:page].mutableCopy;
- if (!menuItems) {
- menuItems = [NSMutableArray array];
- }
- if ([self isSelectEditCharRange] || [self isSelecteditAreaWithPoint:point]) {
- [menuItems insertObject:[NSMenuItem separatorItem] atIndex:0];
- [menuItems insertObject:[self fontColorMenuItem] atIndex:0];
- [menuItems insertObject:[self fontSizeMenuItem] atIndex:0];
- }
-
- if (self.editingArea) {
- if (self.editingArea.IsImageArea) {
- [menuItems insertObject:[NSMenuItem separatorItem] atIndex:0];
- // [menuItems insertObject:[self imageCutMenuItem] atIndex:0];
- // [menuItems insertObject:[self imagePasteMenuItem] atIndex:0];
- [menuItems insertObject:[self imageExportMenuItem] atIndex:0];
- [menuItems insertObject:[self imageRotateMenuItem] atIndex:0];
- }
- }
- return menuItems;
-
- }
- - (void)mouseMoved:(NSEvent *)theEvent {
- [self.window mouseMoved:theEvent];
- [super mouseMoved:theEvent];
- if(self.operationType != KMPDFRedactViewOperationTypeRedact) return;
- NSPoint pagePoint = NSZeroPoint;
- CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:theEvent nearest:YES];
- NSPoint newpoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
- CPDFAreaOfInterest area = [self areaOfInterestForPoint:newpoint];
- if (area & CPDFTextArea) {
- [[NSCursor IBeamCursor] set];
- }else{
- [[NSCursor arrowCursor] set];
- }
- CPDFAnnotation *newActiveAnnotation = [page annotationAtPoint:pagePoint];
- if (newActiveAnnotation && [newActiveAnnotation isKindOfClass:[CPDFRedactAnnotation class]] && (self.mouseMoveAnnotation == newActiveAnnotation)) {
- [(CPDFRedactAnnotation *)newActiveAnnotation setDrawRedactionsAsRedacted:YES];
- [self setNeedsDisplayAnnotationViewForPage:page];
- } else if(self.mouseMoveAnnotation && [self.mouseMoveAnnotation isKindOfClass:[CPDFRedactAnnotation class]]){
- [(CPDFRedactAnnotation *)self.mouseMoveAnnotation setDrawRedactionsAsRedacted:NO];
- [self setNeedsDisplayAnnotationViewForPage:page];
- }
- self.mouseMoveAnnotation = newActiveAnnotation;
- }
- - (void)mouseDown:(NSEvent *)theEvent {
- NSPoint pagePoint = NSZeroPoint;
- if(self.operationType != KMPDFRedactViewOperationTypeRedact) return;
- CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:theEvent nearest:YES];
- CPDFAnnotation *newActiveAnnotation = [page annotationAtPoint:pagePoint];
- NSPoint newpoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
- CPDFAreaOfInterest area = [self areaOfInterestForPoint:newpoint];
- [self.activeAnnotations removeAllObjects]; //预留
- if(newActiveAnnotation) {
- if(![self.activeAnnotations containsObject:newActiveAnnotation]) {
- [self.activeAnnotations addObject:newActiveAnnotation];
- }
- [self setNeedsDisplayAnnotationViewForPage:page];
- [self doDragMouseWithEvent:theEvent];
- } else if(area & CPDFTextArea) {
- [super mouseDown:theEvent];
- [self doMarkUpWithEvent:theEvent];
- self.currentSelection = nil;
- } else {
- [self doRedactWithEvent:theEvent];
- }
- }
- #pragma mark - keyDown
- - (void)delete {
- [self.activeAnnotations enumerateObjectsUsingBlock:^(CPDFAnnotation * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- if([obj isKindOfClass:[CPDFRedactAnnotation class]]) {
- [self removeAnnotation:obj];
- }
- }];
- }
- - (void)corpImageDoneWithEnter {
- if([self.editingArea isKindOfClass:[CPDFEditImageArea class]]) {
- CPDFEditImageArea *editImageArea = (CPDFEditImageArea *)self.editingArea;
- if(editImageArea.isCropMode) {
- [self cropEditImageArea:editImageArea withBounds:editImageArea.cropRect];
- [self exitCropWithEditImageArea:editImageArea];
- }
- }
- }
- #pragma mark - Rendering
- - (void)drawPage:(CPDFPage *)page toContext:(CGContextRef)context
- {
- [self.activeAnnotations enumerateObjectsUsingBlock:^(CPDFAnnotation *annotation, NSUInteger idx, BOOL * _Nonnull stop) {
- if (annotation.page && [annotation.page isEqual:page]) {
- [annotation drawSelectionHighlightForView:self inContext:context];
- }
- }];
- }
- - (BOOL)doDragMouseWithEvent:(NSEvent *)theEvent
- {
- BOOL didDrag = NO;;
- while (YES) {
- if ([[[self window] nextEventMatchingMask: NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged] type] == NSEventTypeLeftMouseUp)
- break;
- didDrag = YES;
- }
- return didDrag;
- }
- - (void)doMarkUpWithEvent:(NSEvent *)theEvent
- {
- NSUInteger eventMask = NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
-
- while (YES) {
- theEvent = [[self window] nextEventMatchingMask:eventMask];
- if ([theEvent type] == NSEventTypeLeftMouseUp) {
- if (self.currentSelection) {
- CPDFPage *page = self.currentSelection.page;
- CPDFAnnotation *annotation = [self addRedactPDFSelection:self.currentSelection];
- [annotation setModificationDate:[NSDate date]];
- NSString *userName = [[NSUserDefaults standardUserDefaults] stringForKey:@"SKUserName"];
- [annotation setUserName:userName ? : NSFullUserName()];
-
- if ([annotation isKindOfClass:[CPDFRedactAnnotation class]]) {
- [annotation setBorderWidth:10];
- [(CPDFRedactAnnotation *)annotation setBorderColor:[KMPDFAnnotationRedactConfig sharedInstance].redactOutlineColor];
- [(CPDFRedactAnnotation *)annotation setInteriorColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFillColor];
- [(CPDFRedactAnnotation *)annotation setFontColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFontColor];
- if([KMPDFAnnotationRedactConfig sharedInstance].overlayText) {
- [(CPDFRedactAnnotation *)annotation setAlignment:[KMPDFAnnotationRedactConfig sharedInstance].textAlignment];
- NSFont* font = [NSFont fontWithName:@"Helvetica" size:[KMPDFAnnotationRedactConfig sharedInstance].fontSize];
- [(CPDFRedactAnnotation *)annotation setFont:font];
- [(CPDFRedactAnnotation *)annotation setOverlayText:[KMPDFAnnotationRedactConfig sharedInstance].overlayTextString];
- }
- }
- [self addAnnotation:annotation toPage:page];
- [self.newAddAnnotation addObject:annotation];
- [self setNeedsDisplayForPage:page];
- }
- break;
- } else if([theEvent type] == NSEventTypeLeftMouseDragged) {
- [super mouseDragged:theEvent];
- }
- }
- }
- - (void)doRedactWithEvent:(NSEvent *)theEvent
- {
- NSPoint point = NSZeroPoint;
- CPDFPage *page = [self pageAndPoint:&point forEvent:theEvent nearest:YES];
- BOOL wasMouseCoalescingEnabled = [NSEvent isMouseCoalescingEnabled];
- NSWindow *window = [self window];
- NSBezierPath *bezierPath = nil;
- CAShapeLayer *layer = nil;
- NSRect boxBounds = page.bounds;
- CGAffineTransform t = CGAffineTransformRotate(CGAffineTransformMakeScale([self scaleFactor], [self scaleFactor]), -M_PI_2 * [page rotation] / 90.0);
- layer = [CAShapeLayer layer];
- [layer setBounds:NSRectToCGRect(boxBounds)];
- [layer setAnchorPoint:CGPointZero];
- [layer setPosition:NSPointToCGPoint([self convertPoint:boxBounds.origin fromPage:page])];
- [layer setAffineTransform:t];
- [layer setZPosition:1.0];
- [layer setMasksToBounds:YES];
- [layer setFillColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFillColor.CGColor];
- [layer setStrokeColor:CGColorGetConstantColor(kCGColorBlack)];
- [layer setLineJoin:kCALineJoinRound];
- [layer setLineCap:kCALineCapRound];
-
- NSEvent *lastMouseEvent = theEvent;
- SKRectEdges resizeHandle = SKMinYEdgeMask | SKMaxXEdgeMask;
- CGRect originalBounds = CGRectMake(point.x, point.y, 0, 0);
- [[self layer] addSublayer:layer];
-
- NSUInteger eventMask = NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
- CGRect rect = CGRectZero;
- while (YES) {
- theEvent = [window nextEventMatchingMask:eventMask];
- if ([theEvent type] == NSEventTypeLeftMouseUp) {
- if (rect.size.width < MIN_NOTE_SIZE || rect.size.height < MIN_NOTE_SIZE) {
- break;
- }
- NSMutableArray *quadrilateralPoints = [NSMutableArray array];
- CPDFRedactAnnotation *annotation = [[[CPDFRedactAnnotation alloc] initWithDocument:self.document] autorelease];
- CGRect bounds = rect;
- [quadrilateralPoints addObject:[NSValue valueWithPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))]];
- [quadrilateralPoints addObject:[NSValue valueWithPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))]];
- [quadrilateralPoints addObject:[NSValue valueWithPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))]];
- [quadrilateralPoints addObject:[NSValue valueWithPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))]];
- [annotation setQuadrilateralPoints:quadrilateralPoints];
- [annotation setModificationDate:[NSDate date]];
- NSString *userName = [[NSUserDefaults standardUserDefaults] stringForKey:@"SKUserName"];
- [annotation setUserName:userName ? : NSFullUserName()];
-
- if ([annotation isKindOfClass:[CPDFRedactAnnotation class]]) {
- [annotation setBorderWidth:10];
- [(CPDFRedactAnnotation *)annotation setBorderColor:[KMPDFAnnotationRedactConfig sharedInstance].redactOutlineColor];
- [(CPDFRedactAnnotation *)annotation setInteriorColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFillColor];
- [(CPDFRedactAnnotation *)annotation setFontColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFontColor];
- if([KMPDFAnnotationRedactConfig sharedInstance].overlayText) {
- [(CPDFRedactAnnotation *)annotation setAlignment:[KMPDFAnnotationRedactConfig sharedInstance].textAlignment];
- NSFont* font = [NSFont fontWithName:@"Helvetica" size:[KMPDFAnnotationRedactConfig sharedInstance].fontSize];
- [(CPDFRedactAnnotation *)annotation setFont:font];
- [(CPDFRedactAnnotation *)annotation setOverlayText:[KMPDFAnnotationRedactConfig sharedInstance].overlayTextString];
- }
- }
- [self addAnnotation:annotation toPage:page];
- [self.newAddAnnotation addObject:annotation];
- break;
- } else if ([theEvent type] == NSEventTypeLeftMouseDragged) {
- rect = [self doResizeLinkWithEvent:lastMouseEvent fromPoint:point originalBounds:originalBounds page:page resizeHandle:&resizeHandle];
- bezierPath = [NSBezierPath bezierPathWithRect:rect];
- [layer setPath:[bezierPath CGPath]];
- lastMouseEvent = theEvent;
- }
- }
-
- [layer removeFromSuperlayer];
- [NSEvent setMouseCoalescingEnabled:wasMouseCoalescingEnabled];
- }
- - (CPDFPage *)pageAndPoint:(NSPoint *)point forEvent:(NSEvent *)event nearest:(BOOL)nearest {
- NSPoint p = [event locationInView:self];
- CPDFPage *page = [self pageForPoint:p nearest:nearest];
- if (page && point)
- *point = [self convertPoint:p toPage:page];
- return page;
- }
- - (CGRect)doResizeLinkWithEvent:(NSEvent *)theEvent fromPoint:(NSPoint)originalPagePoint originalBounds:(NSRect)originalBounds page:(CPDFPage*)page resizeHandle:(SKRectEdges *)resizeHandlePtr
- {
- NSPoint currentPagePoint = [self convertPoint:[theEvent locationInView:self] toPage:page];
-
- NSRect newBounds = originalBounds;
- NSRect pageBounds = page.bounds;
- NSPoint relPoint = SKSubstractPoints(currentPagePoint, originalPagePoint);
- SKRectEdges resizeHandle = *resizeHandlePtr;
-
- if (NSEqualSizes(originalBounds.size, NSZeroSize)) {
- SKRectEdges currentResizeHandle = (relPoint.x < 0.0 ? SKMinXEdgeMask : SKMaxXEdgeMask) | (relPoint.y <= 0.0 ? SKMinYEdgeMask : SKMaxYEdgeMask);
- if (currentResizeHandle != resizeHandle) {
- *resizeHandlePtr = resizeHandle = currentResizeHandle;
- }
- }
- CGFloat minWidth = MIN_NOTE_SIZE;
- CGFloat minHeight = MIN_NOTE_SIZE;
-
- if ((resizeHandle & SKMaxXEdgeMask)) {
- newBounds.size.width += relPoint.x;
- if (NSMaxX(newBounds) > NSMaxX(pageBounds))
- newBounds.size.width = NSMaxX(pageBounds) - NSMinX(newBounds);
- if (NSWidth(newBounds) < minWidth) {
- newBounds.size.width = minWidth;
- }
- } else if ((resizeHandle & SKMinXEdgeMask)) {
- newBounds.origin.x += relPoint.x;
- newBounds.size.width -= relPoint.x;
- if (NSMinX(newBounds) < NSMinX(pageBounds)) {
- newBounds.size.width = NSMaxX(newBounds) - NSMinX(pageBounds);
- newBounds.origin.x = NSMinX(pageBounds);
- }
- if (NSWidth(newBounds) < minWidth) {
- newBounds.origin.x = NSMaxX(newBounds) - minWidth;
- newBounds.size.width = minWidth;
- }
- }
- if ((resizeHandle & SKMaxYEdgeMask)) {
- newBounds.size.height += relPoint.y;
- if (NSMaxY(newBounds) > NSMaxY(pageBounds)) {
- newBounds.size.height = NSMaxY(pageBounds) - NSMinY(newBounds);
- }
- if (NSHeight(newBounds) < minHeight) {
- newBounds.size.height = minHeight;
- }
- } else if ((resizeHandle & SKMinYEdgeMask)) {
- newBounds.origin.y += relPoint.y;
- newBounds.size.height -= relPoint.y;
- if (NSMinY(newBounds) < NSMinY(pageBounds)) {
- newBounds.size.height = NSMaxY(newBounds) - NSMinY(pageBounds);
- newBounds.origin.y = NSMinY(pageBounds);
- }
- if (NSHeight(newBounds) < minHeight) {
- newBounds.origin.y = NSMaxY(newBounds) - minHeight;
- newBounds.size.height = minHeight;
- }
- }
- return newBounds;
- }
- */
-
- }
|