|
@@ -0,0 +1,480 @@
|
|
|
|
+//
|
|
|
|
+// 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;
|
|
|
|
+ }
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+}
|