CPDFDigtalView.m 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. //
  2. // CPDFDigtalView.m
  3. // Cisdem PDFMaster
  4. //
  5. // Created by Niehaoyu on 2023/10/10.
  6. //
  7. #import "CPDFDigtalView.h"
  8. #import "CPDFAnnotation+PDFListView.h"
  9. #import "NSGeometry+PDFListView.h"
  10. #import "CPDFListViewConfig.h"
  11. #define HANDLE_SIZE 4.0
  12. #define MIN_NOTE_SIZE 8.0
  13. @implementation CPDFDigtalView
  14. - (void)drawRect:(NSRect)dirtyRect {
  15. [super drawRect:dirtyRect];
  16. // Drawing code here.
  17. }
  18. - (id)initWithFrame:(NSRect)frameRect {
  19. self = [super initWithFrame:frameRect];
  20. if (self) {
  21. [self setUp];
  22. }
  23. return self;
  24. }
  25. - (id)initWithCoder:(NSCoder *)decoder {
  26. self = [super initWithCoder:decoder];
  27. if (self) {
  28. [self setUp];
  29. }
  30. return self;
  31. }
  32. - (void)setUp {
  33. self.annotationType = CAnnotationTypeSignature;
  34. self.activeAnnotations = [NSMutableArray array];
  35. }
  36. - (void)setDocument:(CPDFDocument *)document {
  37. [super setDocument:document];
  38. NSArray *signatures = document.signatures;
  39. NSMutableArray *tempArr = [NSMutableArray array];
  40. for (CPDFSignature *signature in signatures) {
  41. if(signature.signers.count > 0) {
  42. [signature verifySignatureWithDocument:document];
  43. [tempArr addObject:signature];
  44. }
  45. }
  46. self.signatures = tempArr;
  47. }
  48. - (CPDFPage *)pageAndPoint:(NSPoint *)point forEvent:(NSEvent *)event nearest:(BOOL)nearest {
  49. NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil];
  50. CPDFPage *page = [self pageForPoint:p nearest:nearest];
  51. if (page && point)
  52. *point = [self convertPoint:p toPage:page];
  53. return page;
  54. }
  55. - (void)setCursorForMouse:(NSEvent *)theEvent {
  56. if (theEvent == nil)
  57. theEvent = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
  58. location:[[self window] mouseLocationOutsideOfEventStream]
  59. modifierFlags:[NSEvent standardPDFListViewModifierFlags]
  60. timestamp:0
  61. windowNumber:[[self window] windowNumber]
  62. context:nil
  63. eventNumber:0
  64. clickCount:1
  65. pressure:0.0];
  66. [self setCursorForAreaOfInterest:[self areaOfInterestForMouse:theEvent]];
  67. }
  68. - (CPDFAnnotation *)activeAnnotation {
  69. return self.activeAnnotations.lastObject;
  70. }
  71. - (void)mouseDown:(NSEvent *)theEvent {
  72. [self setCursorForMouse:theEvent];
  73. NSPoint point = NSZeroPoint;
  74. CPDFAreaOfInterest area = [self areaOfInterestForMouse:theEvent];
  75. NSPoint newpoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
  76. area = [self areaOfInterestForPoint:newpoint];
  77. CPDFAnnotation *newActiveAnnotation = nil;
  78. if ([[self document] isLocked]) {
  79. [super mouseDown:theEvent];
  80. } else if ([self doClickAnnotationWithEvent:theEvent forAnnotation:&newActiveAnnotation]) {
  81. [self doDragAnnotationWithEvent:theEvent forAnnotation:newActiveAnnotation];
  82. } else {
  83. [self doDragAddAnnotationWithEvent:theEvent];
  84. }
  85. }
  86. - (BOOL)doClickAnnotationWithEvent:(NSEvent *)theEvent forAnnotation:(CPDFAnnotation **)annotation{
  87. CPDFAnnotation *newActiveAnnotation = nil;
  88. NSPoint point = NSZeroPoint;
  89. CPDFPage *page = [self pageAndPoint:&point forEvent:theEvent nearest:YES];
  90. NSMutableArray *currentActiveAnnotations = [NSMutableArray array];
  91. for (CPDFAnnotation *an in self.activeAnnotations) {
  92. if([an.page isEqual:page]) {
  93. if(!([an isKindOfClass:[CPDFMarkupAnnotation class]] || [an isKindOfClass:[CPDFTextAnnotation class]])) {
  94. [currentActiveAnnotations addObject:an];
  95. }
  96. }
  97. }
  98. newActiveAnnotation = [self doSelectAnnotationWithEvent:theEvent];
  99. *annotation = newActiveAnnotation;
  100. return !!newActiveAnnotation;
  101. }
  102. - (CPDFAnnotation *)doSelectAnnotationWithEvent:(NSEvent *)theEvent {
  103. CPDFAnnotation *newActiveAnnotation = nil;
  104. NSPoint point = NSZeroPoint;
  105. CPDFPage *page = [self pageAndPoint:&point forEvent:theEvent nearest:YES];
  106. id annotations = [page annotations];
  107. for (CPDFAnnotation *annotation in annotations) {
  108. if ([annotation hitTest:point] && [annotation annotationShouldDisplay] ) {
  109. newActiveAnnotation = annotation;
  110. break;
  111. }
  112. }
  113. return newActiveAnnotation;
  114. }
  115. - (void)doDragAnnotationWithEvent:(NSEvent *)theEvent forAnnotation:(CPDFAnnotation *)newActiveAnnotation {
  116. BOOL isContains = YES;
  117. if (self.activeAnnotations.count == 0 || ![self.activeAnnotations containsObject:newActiveAnnotation]) {
  118. isContains = NO;
  119. }
  120. NSRect originalBounds = [newActiveAnnotation bounds];
  121. BOOL isLine = [newActiveAnnotation isKindOfClass:[CPDFLineAnnotation class]];
  122. NSPoint pagePoint = NSZeroPoint;
  123. CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:theEvent nearest:YES];
  124. NSPoint originalStartPoint = NSZeroPoint;
  125. NSPoint originalEndPoint = NSZeroPoint;
  126. BOOL draggedAnnotation = NO;
  127. NSEvent *lastMouseEvent = theEvent;
  128. NSPoint offset = CPDFListViewSubstractPoints(pagePoint, originalBounds.origin);
  129. NSUInteger eventMask = NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
  130. CGFloat mouseOffset = [self unitWidthOnPage:page];
  131. while (YES) {
  132. theEvent = [[self window] nextEventMatchingMask:eventMask];
  133. if ([theEvent type] == NSEventTypeLeftMouseUp) {
  134. if(draggedAnnotation) {
  135. if (!isContains)
  136. [self.selectAnnotations removeAllObjects];
  137. } else {
  138. if(self.activeAnnotations.count == 1 &&
  139. self.activeAnnotation == newActiveAnnotation &&
  140. ([newActiveAnnotation isKindOfClass:[CPDFTextAnnotation class]] || [newActiveAnnotation isKindOfClass:[CPDFFreeTextAnnotation class]])) {
  141. [self editAnnotation:newActiveAnnotation];
  142. break;
  143. }
  144. if(!isContains) {
  145. [self updateActiveAnnotations:@[newActiveAnnotation]];
  146. }
  147. [self editAnnotation:newActiveAnnotation];
  148. }
  149. [self setNeedsDisplayAnnotationViewForPage:page];
  150. break;
  151. } else if ([theEvent type] == NSEventTypeLeftMouseDragged) {
  152. NSPoint point = NSZeroPoint;
  153. [self pageAndPoint:&point forEvent:theEvent nearest:YES];
  154. CGRect zRect = CGRectMake(pagePoint.x-2*mouseOffset, pagePoint.y-2*mouseOffset, 4*mouseOffset, 4*mouseOffset);
  155. if (CGRectContainsPoint(zRect, point)) {continue;}
  156. lastMouseEvent = theEvent;
  157. draggedAnnotation = YES;
  158. if(!isContains) {
  159. [self dragAnnotationReferenceLine:newActiveAnnotation];
  160. [self.selectAnnotations removeAllObjects];
  161. [self.selectAnnotations addObject:newActiveAnnotation];
  162. [self doMoveAnnotation:newActiveAnnotation withEvent:lastMouseEvent offset:offset];
  163. } else {
  164. if ([newActiveAnnotation isKindOfClass:[CPDFStampAnnotation class]] ||
  165. [newActiveAnnotation isKindOfClass:[CPDFFreeTextAnnotation class]] ||
  166. [newActiveAnnotation isKindOfClass:[CPDFSignatureAnnotation class]] ||
  167. [newActiveAnnotation isKindOfClass:[CPDFWidgetAnnotation class]]) {
  168. [newActiveAnnotation updateAppearanceStream];
  169. }
  170. }
  171. [self dragAnnotationReferenceLine:newActiveAnnotation];
  172. [self setNeedsDisplayAnnotationViewForPage:page];
  173. }
  174. }
  175. [self performSelector:@selector(setCursorForMouse:) withObject:theEvent afterDelay:0];
  176. }
  177. - (void)doMoveAnnotation:(CPDFAnnotation *)activeAnnotation withEvent:(NSEvent *)theEvent offset:(NSPoint)offset {
  178. // Move annotation.
  179. [[[self documentView] contentView] autoscroll:theEvent];
  180. NSPoint point = NSZeroPoint;
  181. CPDFPage *newActivePage = [self pageAndPoint:&point forEvent:theEvent nearest:YES];
  182. if (newActivePage) { // newActivePage should never be nil, but just to be sure
  183. if (newActivePage != [activeAnnotation page]) {
  184. return;
  185. }
  186. NSRect newBounds = [activeAnnotation bounds];
  187. newBounds.origin = CPDFListViewIntegralPoint(CPDFListViewSubstractPoints(point, offset));
  188. // constrain bounds inside page bounds
  189. }
  190. }
  191. - (void)dragAnnotationReferenceLine:(CPDFAnnotation *)annotation {
  192. }
  193. - (void)editAnnotation:(CPDFAnnotation *)annotation {
  194. if ([annotation isKindOfClass:[CPDFFreeTextAnnotation class]]) {
  195. [self editAnnotationFreeText:(CPDFFreeTextAnnotation *)annotation];
  196. [[self window] makeFirstResponder:self];
  197. [self setNeedsDisplayAnnotation:annotation];
  198. } else {
  199. if([annotation isKindOfClass:[CPDFSignatureWidgetAnnotation class]]) {
  200. if([self.pdfListViewDelegate respondsToSelector:@selector(PDFListViewEditAnnotation:forAnnotation:)]) {
  201. [self.pdfListViewDelegate PDFListViewEditAnnotation:self forAnnotation:annotation];
  202. }
  203. }
  204. }
  205. }
  206. - (void)doDragAddAnnotationWithEvent:(NSEvent *)theEvent {
  207. NSPoint pagePoint = NSZeroPoint;
  208. CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:theEvent nearest:YES];
  209. NSRect originalBounds = CGRectZero;
  210. CGFloat mouseOffset = [self unitWidthOnPage:page];
  211. // [self setCursorForAreaOfInterest:CAreaOfInterestForResizeHandle(CMaxXEdgeMask | CMinYEdgeMask, page)];
  212. CPDFAnnotation *annotation = nil;
  213. originalBounds = CPDFListViewRectFromCenterAndSquareSize(CPDFListViewIntegralPoint(pagePoint), 0.0);
  214. CRectEdges resizeHandle = CMaxXEdgeMask | CMinYEdgeMask;
  215. BOOL draggedAnnotation = NO;
  216. NSEvent *lastMouseEvent = theEvent;
  217. NSUInteger eventMask = NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
  218. while (YES) {
  219. theEvent = [[self window] nextEventMatchingMask:eventMask];
  220. if ([theEvent type] == NSEventTypeLeftMouseUp) {
  221. if (!draggedAnnotation) {
  222. if (annotation) {
  223. break;
  224. }
  225. if(CAnnotationTypeLine == self.annotationType ||
  226. CAnnotationTypeArrow == self.annotationType) {
  227. } else {
  228. CGFloat defaultWidth = 72;
  229. CGFloat defaultHeight = 32;
  230. NSSize defaultSize = ([page rotation] % 180 == 0) ? NSMakeSize(defaultWidth, defaultHeight) : NSMakeSize(defaultHeight, defaultWidth);
  231. CGRect bounds = CGRectZero;
  232. bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize);
  233. bounds = CPDFListViewConstrainRect(bounds, page.bounds,[CPDFListViewConfig defaultManager].annotationBorderOffset.floatValue);
  234. annotation = [self addAnnotationWithType:self.annotationType selection:nil page:page bounds:bounds];
  235. originalBounds = [annotation bounds];
  236. if(annotation) {
  237. [self updateActiveAnnotations:@[annotation]];
  238. [self setNeedsDisplayAnnotation:annotation];
  239. } else if(self.activeAnnotations.count >0) {
  240. [self updateActiveAnnotations:@[]];
  241. [self setNeedsDisplayAnnotationViewForPage:page];
  242. }
  243. }
  244. } else {
  245. }
  246. break;
  247. } else if ([theEvent type] == NSEventTypeLeftMouseDragged) {
  248. CGPoint zPoint = pagePoint;
  249. [self pageAndPoint:&zPoint forEvent:theEvent nearest:YES];
  250. CGRect zRect = CGRectMake(pagePoint.x-2*mouseOffset, pagePoint.y-2*mouseOffset, 4*mouseOffset, 4*mouseOffset);
  251. if (CGRectContainsPoint(zRect, zPoint)) {continue;}
  252. if (annotation == nil)
  253. annotation = [self addAnnotationWithType:self.annotationType selection:nil page:page bounds:CPDFListViewRectFromCenterAndSquareSize(originalBounds.origin, 0.0)];
  254. if(annotation) {
  255. [self updateActiveAnnotations:@[annotation]];
  256. } else if(self.activeAnnotations.count >0) {
  257. [self updateActiveAnnotations:@[]];
  258. [self setNeedsDisplayAnnotationViewForPage:page];
  259. }
  260. lastMouseEvent = theEvent;
  261. draggedAnnotation = YES;
  262. [self setNeedsDisplayAnnotationViewForPage:page];
  263. }
  264. [self doResizeAnnotationWithEvent:lastMouseEvent fromPoint:pagePoint originalBounds:originalBounds resizeHandle:&resizeHandle];
  265. }
  266. if (annotation) {
  267. [self setNeedsDisplayAnnotation:annotation];
  268. if ([self.pdfListViewDelegate respondsToSelector:@selector(PDFListViewAddAnnotation:forAddAnnotation:inPage:)]) {
  269. [self.pdfListViewDelegate PDFListViewAddAnnotation:self forAddAnnotation:annotation inPage:page];
  270. }
  271. }
  272. [self performSelector:@selector(setCursorForMouse:) withObject:theEvent afterDelay:0];
  273. }
  274. - (void)setNeedsDisplayAnnotation:(CPDFAnnotation *)annotation {
  275. if (annotation) {
  276. [self setNeedsDisplayAnnotationViewForPage:annotation.page];
  277. } else {
  278. [self setNeedsDisplayAnnotationViewForVisiblePages];
  279. }
  280. }
  281. - (CGFloat)unitWidthOnPage:(CPDFPage *)page {
  282. return NSWidth([self convertRect:NSMakeRect(0.0, 0.0, 1.0, 1.0) toPage:page]);
  283. }
  284. - (CPDFAnnotation *)addAnnotationWithType:(CAnnotationType)annotationType selection:(CPDFSelection *)selection page:(CPDFPage *)page bounds:(NSRect)bounds {
  285. CPDFAnnotation *annotation = nil;
  286. NSString *text = [selection PDFListViewCleanedString];
  287. BOOL isInitial = NO;
  288. if(selection) {
  289. CGRect noteRect = selection.bounds;
  290. isInitial = NSEqualSizes(noteRect.size, NSZeroSize);
  291. } else {
  292. isInitial = NSEqualSizes(bounds.size, NSZeroSize);
  293. }
  294. if (isInitial)
  295. bounds = CPDFListViewRectFromCenterAndSquareSize(bounds.origin, 8.0);
  296. switch (annotationType) {
  297. case CAnnotationTypeSignature:
  298. annotation = [[CPDFSignatureWidgetAnnotation alloc] initPDFListViewNoteWithDocument:self.document];
  299. annotation.bounds = bounds;
  300. break;
  301. default:
  302. break;
  303. }
  304. if (annotation) {
  305. if (annotationType != CAnnotationTypeLine && annotationType != CAnnotationTypeArrow && annotationType != CAnnotationTypeInk && [text length] > 0)
  306. [annotation setString:text];
  307. [self addAnnotation:annotation toPage:page];
  308. }
  309. return annotation;
  310. }
  311. - (void)updateActiveAnnotations:(NSArray<CPDFAnnotation *> *)activeAnnotations {
  312. [self refreshActiveAnnotations:activeAnnotations isRight:NO];
  313. }
  314. - (void)addAnnotation:(CPDFAnnotation *)annotation toPage:(CPDFPage *)page {
  315. // [[[self undoManager] prepareWithInvocationTarget:self] removeAnnotation:annotation];
  316. [annotation setModificationDate:[NSDate date]];
  317. //widget设置作者与fieldName冲突
  318. if (![annotation isKindOfClass:[CPDFWidgetAnnotation class]]) {
  319. [annotation setUserName:CPDFKitShareConfig.annotationAuthor?:NSFullUserName()];
  320. }
  321. [page addAnnotation:annotation];
  322. [self setNeedsDisplayAnnotation:annotation];
  323. [[self undoManager] setActionName:NSLocalizedString(@"Add Note", @"Undo action name")];
  324. }
  325. - (void)refreshActiveAnnotations:(NSArray<CPDFAnnotation *> *)activeAnnotations isRight:(BOOL)isRight {
  326. if(activeAnnotations) {
  327. NSArray *selectTure = [activeAnnotations filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF in %@", self.activeAnnotations]];
  328. BOOL isSame = NO;
  329. if(self.activeAnnotations.count == activeAnnotations.count && self.activeAnnotations.count == selectTure.count) isSame = YES;
  330. if(!isSame) {
  331. self.activeAnnotations = [NSMutableArray arrayWithArray:activeAnnotations];
  332. }
  333. } else if (!activeAnnotations && self.activeAnnotations.count > 0) {
  334. [self.activeAnnotations removeAllObjects];
  335. }
  336. }
  337. - (void)doResizeAnnotationWithEvent:(NSEvent *)theEvent fromPoint:(NSPoint)originalPagePoint originalBounds:(NSRect)originalBounds resizeHandle:(CRectEdges *)resizeHandlePtr {
  338. CPDFAnnotation *activeAnnotation = self.activeAnnotation;
  339. NSPoint pagePoint = NSZeroPoint;
  340. CPDFPage *page = activeAnnotation?activeAnnotation.page:[self pageAndPoint:&pagePoint forEvent:theEvent nearest:YES];
  341. NSRect newBounds = originalBounds;
  342. NSRect pageBounds = [page boundsForBox:[self displayBox]];
  343. NSPoint currentPagePoint = [self convertPoint:[theEvent locationInPDFListView:self] toPage:page];
  344. NSPoint relPoint = CPDFListViewSubstractPoints(currentPagePoint, originalPagePoint);
  345. CRectEdges resizeHandle = *resizeHandlePtr;
  346. if (NSEqualSizes(originalBounds.size, NSZeroSize)) {
  347. CRectEdges currentResizeHandle = (relPoint.x < 0.0 ? CMinXEdgeMask : CMaxXEdgeMask) | (relPoint.y <= 0.0 ? CMinYEdgeMask : CMaxYEdgeMask);
  348. if (currentResizeHandle != resizeHandle) {
  349. *resizeHandlePtr = resizeHandle = currentResizeHandle;
  350. // [self setCursorForAreaOfInterest:CAreaOfInterestForResizeHandle(resizeHandle, page)];
  351. }
  352. }
  353. BOOL isRadioOrCheckButton = NO;
  354. if ([activeAnnotation isKindOfClass:[CPDFButtonWidgetAnnotation class]]) {
  355. CPDFButtonWidgetAnnotation *annotation = (CPDFButtonWidgetAnnotation *)activeAnnotation;
  356. if (CPDFWidgetRadioButtonControl == annotation.controlType ||
  357. CPDFWidgetCheckBoxControl == annotation.controlType) {
  358. isRadioOrCheckButton = YES;
  359. }
  360. }
  361. CGFloat minWidth = MIN_NOTE_SIZE;
  362. CGFloat minHeight = MIN_NOTE_SIZE;
  363. CGFloat offsetPageSet = 2;
  364. if ((resizeHandle & CMaxXEdgeMask)) {
  365. newBounds.size.width += relPoint.x;
  366. if (NSMaxX(newBounds)+offsetPageSet > NSMaxX(pageBounds))
  367. newBounds.size.width = NSMaxX(pageBounds) - NSMinX(newBounds)-offsetPageSet;
  368. if (NSWidth(newBounds) < minWidth) {
  369. newBounds.size.width = minWidth;
  370. }
  371. } else if ((resizeHandle & CMinXEdgeMask)) {
  372. newBounds.origin.x += relPoint.x;
  373. newBounds.size.width -= relPoint.x;
  374. if (NSMinX(newBounds)-offsetPageSet < NSMinX(pageBounds)) {
  375. newBounds.size.width = NSMaxX(newBounds) - NSMinX(pageBounds)-offsetPageSet;
  376. newBounds.origin.x = NSMinX(pageBounds)+offsetPageSet;
  377. }
  378. if (NSWidth(newBounds) < minWidth) {
  379. newBounds.origin.x = NSMaxX(newBounds) - minWidth;
  380. newBounds.size.width = minWidth;
  381. }
  382. }
  383. if ((resizeHandle & CMaxYEdgeMask)) {
  384. newBounds.size.height += relPoint.y;
  385. if (NSMaxY(newBounds)+ offsetPageSet > NSMaxY(pageBounds)) {
  386. newBounds.size.height = NSMaxY(pageBounds) - NSMinY(newBounds)- offsetPageSet;
  387. }
  388. if (NSHeight(newBounds) < minHeight) {
  389. newBounds.size.height = minHeight;
  390. }
  391. } else if ((resizeHandle & CMinYEdgeMask)) {
  392. newBounds.origin.y += relPoint.y;
  393. newBounds.size.height -= relPoint.y;
  394. if (NSMinY(newBounds)-offsetPageSet < NSMinY(pageBounds)) {
  395. newBounds.size.height = NSMaxY(newBounds) - NSMinY(pageBounds)-offsetPageSet;
  396. newBounds.origin.y = NSMinY(pageBounds)+offsetPageSet;
  397. }
  398. if (NSHeight(newBounds) < minHeight) {
  399. newBounds.origin.y = NSMaxY(newBounds) - minHeight;
  400. newBounds.size.height = minHeight;
  401. }
  402. }
  403. [activeAnnotation setBounds:NSIntegralRect(newBounds)];
  404. if ([activeAnnotation isKindOfClass:[CPDFFreeTextAnnotation class]]) {
  405. [self updateAnnotationFreeTextBounds:(CPDFFreeTextAnnotation *)activeAnnotation];
  406. }
  407. }
  408. #pragma mark - NSMenu
  409. - (NSMenu *)menuForEvent:(NSEvent *)event {
  410. if (self.annotationType == CAnnotationTypeInk || self.annotationType == CAnnotationTypeEraser) {
  411. return nil;
  412. }
  413. NSMenu *menu = [super menuForEvent:event];
  414. if(!menu)
  415. menu = [[NSMenu alloc] init];
  416. NSPoint pagePoint = NSZeroPoint;
  417. CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:event nearest:YES];
  418. NSMenuItem * copyItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Copy", @"PDFListView") action:@selector(copy:) keyEquivalent:@"c"];
  419. NSMenuItem * pasteItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Paste", @"PDFListView") action:@selector(menuItemClick_Paste:) keyEquivalent:@"v"];
  420. pasteItem.representedObject = event;
  421. NSMenuItem * cutItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Cut", @"PDFListView") action:@selector(cut:) keyEquivalent:@"x"];
  422. NSMenuItem * deleteItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Delete", @"PDFListView") action:@selector(delete:) keyEquivalent:@""];
  423. NSMenu *subMenu = nil;
  424. NSMenuItem * arrangementItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Arrangement", @"PDFListView") action:nil keyEquivalent:@""];
  425. subMenu = [[NSMenu alloc] init];
  426. NSMenuItem * bringForwardItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Bring Forward", @"PDFListView") action:@selector(menuItemClick_BringForward:) keyEquivalent:@""];
  427. NSMenuItem * sendBackForwardItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Send Backward", @"PDFListView") action:@selector(menuItemClick_SendBackward:) keyEquivalent:@""];
  428. NSMenuItem * bringFrontItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Bring to Front", @"PDFListView") action:@selector(menuItemClick_BringFront:) keyEquivalent:@""];
  429. NSMenuItem * sendBackItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Send to Back", @"PDFListView") action:@selector(menuItemClick_SendBack:) keyEquivalent:@""];
  430. [subMenu addItem:bringForwardItem];
  431. [subMenu addItem:sendBackForwardItem];
  432. [subMenu addItem:bringFrontItem];
  433. [subMenu addItem:sendBackItem];
  434. arrangementItem.submenu = subMenu;
  435. NSMenuItem * editNoteItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Edit Note", @"PDFListView") action:@selector(menuItemClick_EditNote:) keyEquivalent:@""];
  436. if(0) {
  437. } else {
  438. CPDFAnnotation *annotation = nil;
  439. for (CPDFAnnotation *tAnnotation in page.annotations) {
  440. if ([tAnnotation hitTest:pagePoint]) {
  441. annotation = tAnnotation;
  442. break;
  443. }
  444. }
  445. if (annotation && [annotation isKindOfClass:[CPDFWidgetAnnotation class]] ){
  446. }
  447. if(annotation) {
  448. if(![self.activeAnnotations containsObject:annotation]) {
  449. [self updateIsRightActiveAnnotations:@[annotation]];
  450. [self setNeedsDisplayAnnotation:annotation];
  451. }
  452. }
  453. if(annotation && [annotation isKindOfClass:[CPDFWidgetAnnotation class]]) {
  454. annotation = nil;
  455. } else if(annotation && [annotation isKindOfClass:[CPDFRedactAnnotation class]]) {
  456. annotation = nil;
  457. } else if (annotation && [annotation isKindOfClass:[CPDFInkAnnotation class]] && [self annotationType] == CAnnotationTypeInk) {
  458. annotation = nil;
  459. }
  460. CPDFSelection *selection = [self creatImageCurrentSelectionForPoint:[event locationInPDFListView:self]];
  461. if(selection && CPDFSelectionTypeImage == [selection selectionType] && !self.activeAnnotation){
  462. self.currentSelection = selection;
  463. }
  464. NSMenu *subMenu = [[NSMenu alloc] init];
  465. if(self.activeAnnotations.count == 1) {
  466. // NSMenuItem * lineStyleItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Line Style", @"PDFListView") action:@selector(menuItemClick_LineStyle:) keyEquivalent:@""];
  467. //
  468. // subMenu = [[NSMenu alloc] init];
  469. // NSMenuItem * lineSolidItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Solid", @"PDFListView") action:@selector(menuItemClick_LineStyle:) keyEquivalent:@""];
  470. // lineSolidItem.tag = CPDFBorderStyleSolid;
  471. // NSMenuItem * lineDashedItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Dashed", @"PDFListView") action:@selector(menuItemClick_LineStyle:) keyEquivalent:@""];
  472. // lineDashedItem.tag = CPDFBorderStyleDashed;
  473. //
  474. // [subMenu addItem:lineSolidItem];
  475. // [subMenu addItem:lineDashedItem];
  476. // lineStyleItem.submenu = subMenu;
  477. //
  478. // NSMenuItem * changeColorItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Color...", @"PDFListView") action:@selector(menuItemClick_ChangeColor:) keyEquivalent:@""];
  479. // [menu insertItem:arrangementItem atIndex:0];
  480. // [menu insertItem:[NSMenuItem separatorItem] atIndex:0];
  481. // if([self.activeAnnotation isKindOfClass:[CPDFMarkupAnnotation class]] ||
  482. // [self.activeAnnotation isKindOfClass:[CPDFStampAnnotation class]] ||
  483. // [self.activeAnnotation isKindOfClass:[CPDFSignatureAnnotation class]]) {
  484. // [menu insertItem:editNoteItem atIndex:0];
  485. // } else if ([self.activeAnnotation isKindOfClass:[CPDFInkAnnotation class]]) {
  486. // [menu insertItem:editNoteItem atIndex:0];
  487. // [menu insertItem:lineStyleItem atIndex:0];
  488. // [menu insertItem:changeColorItem atIndex:0];
  489. // } else if ([self.activeAnnotation isKindOfClass:[CPDFTextAnnotation class]]) {
  490. // [menu insertItem:editNoteItem atIndex:0];
  491. // [menu insertItem:changeColorItem atIndex:0];
  492. // } else if ([self.activeAnnotation isKindOfClass:[CPDFSquareAnnotation class]] ||
  493. // [self.activeAnnotation isKindOfClass:[CPDFCircleAnnotation class]] ||
  494. // [self.activeAnnotation isKindOfClass:[CPDFLineAnnotation class]]) {
  495. // [menu insertItem:editNoteItem atIndex:0];
  496. // if([self.activeAnnotation isKindOfClass:[CPDFLineAnnotation class]]) {
  497. // NSMenuItem * directionItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Direction", @"PDFListView") action:nil keyEquivalent:@""];
  498. // subMenu = [[NSMenu alloc]init];
  499. //
  500. // NSMenuItem * lineHorizontalItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Horizontal", @"PDFListView") action:@selector(menuItemClick_LineHorizontal:) keyEquivalent:@""];
  501. // NSMenuItem * lineVerticalItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Vertical", @"PDFListView") action:@selector(menuItemClick_LineVertical:) keyEquivalent:@""];
  502. // [subMenu addItem:lineHorizontalItem];
  503. // [subMenu addItem:lineVerticalItem];
  504. // directionItem.submenu = subMenu;
  505. //
  506. // [menu insertItem:directionItem atIndex:0];
  507. // }
  508. // [menu insertItem:lineStyleItem atIndex:0];
  509. // [menu insertItem:changeColorItem atIndex:0];
  510. // }
  511. if ([self.activeAnnotation isKindOfClass:[CPDFSignatureWidgetAnnotation class]]) {
  512. CPDFSignatureWidgetAnnotation *aa = (CPDFSignatureWidgetAnnotation *)self.activeAnnotation;
  513. CPDFSignature *aaa = aa.signature;
  514. [menu insertItem:[NSMenuItem separatorItem] atIndex:0];
  515. [menu insertItem:deleteItem atIndex:0];
  516. }
  517. // if(![self.activeAnnotation isKindOfClass:[CPDFMarkupAnnotation class]]) {
  518. // if ([[NSPasteboard generalPasteboard] canReadObjectForClasses:[NSArray arrayWithObjects:[CPDFAnnotation class], [NSString class],[NSImage class], nil] options:[NSDictionary dictionary]]) {
  519. // [menu insertItem:pasteItem atIndex:0];
  520. // }
  521. // [menu insertItem:cutItem atIndex:0];
  522. // }
  523. // [menu insertItem:copyItem atIndex:0];
  524. __block typeof(self) blockSelf = self;
  525. } else if (self.activeAnnotations.count > 1) {
  526. BOOL isMarkupAn = NO;
  527. for (CPDFAnnotation *annotation in self.activeAnnotations) {
  528. if([annotation isKindOfClass:[CPDFMarkupAnnotation class]]) {
  529. isMarkupAn = YES;
  530. break;
  531. }
  532. }
  533. // [menu insertItem:arrangementItem atIndex:0];
  534. [menu insertItem:[NSMenuItem separatorItem] atIndex:0];
  535. [menu insertItem:deleteItem atIndex:0];
  536. if(!isMarkupAn) {
  537. [menu insertItem:cutItem atIndex:0];
  538. [menu insertItem:copyItem atIndex:0];
  539. }
  540. } else if (self.currentSelection) {
  541. if(CPDFSelectionTypeImage == [self.currentSelection selectionType]) {
  542. NSMenuItem * exportImageItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Export…", nil) action:@selector(menuItemClick_ExportImage:) keyEquivalent:@""];
  543. [menu insertItem:exportImageItem atIndex:0];
  544. [menu insertItem:[NSMenuItem separatorItem] atIndex:0];
  545. }
  546. if ([[NSPasteboard generalPasteboard] canReadObjectForClasses:[NSArray arrayWithObjects:[CPDFAnnotation class], [NSString class],[NSImage class], nil] options:[NSDictionary dictionary]]) {
  547. [menu insertItem:pasteItem atIndex:0];
  548. }
  549. [menu insertItem:copyItem atIndex:0];
  550. } else if (!self.activeAnnotation) {
  551. // NSMenuItem * pageDisplayItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Page Display", @"PDFListView") action:nil keyEquivalent:@""];
  552. // subMenu = [[NSMenu alloc] init];
  553. //
  554. // NSMenuItem * twoPagesContinuousItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Two Pages Continuous", @"PDFListView") action:@selector(menuItemClick_TwoPagesContinuous:) keyEquivalent:@""];
  555. // NSMenuItem * twoPagesItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Two Pages", @"PDFListView") action:@selector(menuItemClick_TwoPages:) keyEquivalent:@""];
  556. // NSMenuItem * singlePageContinuousItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Single Page Continuous", @"PDFListView") action:@selector(menuItemClick_SinglePagesContinuous:) keyEquivalent:@""];
  557. // NSMenuItem * singlePageItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Single Page", @"PDFListView") action:@selector(menuItemClick_SinglePage:) keyEquivalent:@""];
  558. // NSMenuItem * bookModeItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Book Mode", @"PDFListView") action:@selector(menuItemClick_BookMode:) keyEquivalent:@""];
  559. // switch (self.displayViewMode) {
  560. // case CPDFDisplayViewSinglePageContinuous:
  561. // singlePageContinuousItem.state = NSControlStateValueOn;
  562. // break;
  563. // case CPDFDisplayViewTwoUp:
  564. // if (self.displaysAsBook)
  565. // bookModeItem.state = NSControlStateValueOn;
  566. // else
  567. // twoPagesItem.state = NSControlStateValueOn;
  568. // break;
  569. // case CPDFDisplayViewTwoUpContinuous:
  570. // if (self.displaysAsBook)
  571. // bookModeItem.state = NSControlStateValueOn;
  572. // else
  573. // twoPagesContinuousItem.state = NSControlStateValueOn;
  574. // break;
  575. // default:
  576. // case CPDFDisplayViewSinglePage:
  577. // singlePageItem.state = NSControlStateValueOn;
  578. // break;
  579. // }
  580. //
  581. // [subMenu addItem:singlePageItem];
  582. // [subMenu addItem:singlePageContinuousItem];
  583. // [subMenu addItem:twoPagesItem];
  584. // [subMenu addItem:twoPagesContinuousItem];
  585. // [subMenu addItem:bookModeItem];
  586. // pageDisplayItem.submenu = subMenu;
  587. //
  588. // [menu insertItem:pageDisplayItem atIndex:0];
  589. //
  590. // NSMenuItem *zoomItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Zoom", @"PDFListView") action:nil keyEquivalent:@""];
  591. // subMenu = [[NSMenu alloc]init];
  592. //
  593. // NSMenuItem * fitWidthItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Fit Width", @"PDFListView") action:@selector(menuItemClick_FitWidth:) keyEquivalent:@""];
  594. // NSMenuItem * automaticallyItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Automatically Resize", @"PDFListView") action:@selector(menuItemClick_AutomaticallyResize:) keyEquivalent:@""];
  595. // NSMenuItem * actualSizeItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Actual Size", @"PDFListView") action:@selector(menuItemClick_ActualSize:) keyEquivalent:@""];
  596. // NSMenuItem * zoomInItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Zoom In", @"PDFListView") action:@selector(menuItemClick_ZoomIn:) keyEquivalent:@""];
  597. // NSMenuItem * zoomOutItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Zoom Out", @"PDFListView") action:@selector(menuItemClick_ZoomOut:) keyEquivalent:@""];
  598. //
  599. // NSMenuItem * hidenShowNoteItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Hide Notes", @"PDFListView") action:@selector(menuItemClick_HidenorShowNote:) keyEquivalent:@""];
  600. //
  601. // if (self.autoScales) {
  602. // automaticallyItem.state = NSControlStateValueOn;
  603. // } else if (self.scaleFactor == 1.0) {
  604. // actualSizeItem.state = NSControlStateValueOn;
  605. // }
  606. //
  607. //
  608. //
  609. // [subMenu addItem:fitWidthItem];
  610. // [subMenu addItem:automaticallyItem];
  611. // [subMenu addItem:actualSizeItem];
  612. // [subMenu addItem:zoomInItem];
  613. // [subMenu addItem:zoomOutItem];
  614. // zoomItem.submenu = subMenu;
  615. // [menu insertItem:zoomItem atIndex:0];
  616. //
  617. // [menu insertItem:[NSMenuItem separatorItem] atIndex:0];
  618. // [menu insertItem:hidenShowNoteItem atIndex:0];
  619. // [menu insertItem:[NSMenuItem separatorItem] atIndex:0];
  620. // [menu insertItem:pasteItem atIndex:0];
  621. }
  622. }
  623. // if ([self.pdfListViewDelegate respondsToSelector:@selector(PDFListViewMenuForEvent:forEvent:clickMenu:)]) {
  624. // [self.pdfListViewDelegate PDFListViewMenuForEvent:self forEvent:event clickMenu:&menu];
  625. // }
  626. return menu;
  627. }
  628. - (void)updateIsRightActiveAnnotations:(NSArray<CPDFAnnotation *> *)activeAnnotations {
  629. [self refreshActiveAnnotations:activeAnnotations isRight:YES];
  630. }
  631. - (IBAction)delete:(id)sender {
  632. if (self.activeAnnotations.count > 0 ) {
  633. NSMutableArray *tarr = [NSMutableArray arrayWithArray:self.activeAnnotations];
  634. for (CPDFAnnotation * an in tarr) {
  635. // if(self.hoverAnnotation == an) {
  636. // self.hoverAnnotation = nil;
  637. // }
  638. [self removeAnnotation:an];
  639. [[self undoManager] setActionName:NSLocalizedString(@"Remove Note", @"Undo action name")];
  640. if([an isKindOfClass:[CPDFFreeTextAnnotation class]]) {
  641. CPDFFreeTextAnnotation *freeTextAn = (CPDFFreeTextAnnotation *)an;
  642. if ([self isEditWithCurrentFreeText:freeTextAn]) {
  643. [self commitEditAnnotationFreeText:freeTextAn];
  644. }
  645. }
  646. }
  647. [self removeActiveAnnotations:tarr];
  648. } else {
  649. NSBeep();
  650. }
  651. }
  652. - (void)removeAnnotation:(CPDFAnnotation *)annotation {
  653. CPDFAnnotation *wasAnnotation = annotation;
  654. CPDFPage *page = wasAnnotation.page;
  655. [[[self undoManager] prepareWithInvocationTarget:self] addAnnotation:wasAnnotation toPage:page];
  656. [page removeAnnotation:wasAnnotation];
  657. [self annotationsChangedOnPage:page];
  658. [self setNeedsDisplayAnnotation:wasAnnotation];
  659. // dispatch_async(dispatch_get_main_queue(), ^{
  660. // [[NSNotificationCenter defaultCenter] postNotificationName:CPDFListViewDidRemoveAnnotationNotification object:self
  661. // userInfo:[NSDictionary dictionaryWithObjectsAndKeys:wasAnnotation, CPDFListViewAnnotationKey, page, CPDFListViewPageKey, nil]];
  662. // });
  663. //
  664. // if([self.pdfListViewDelegate respondsToSelector:@selector(PDFListViewRemoveAnnotations:forRemoveAnnotations:inPage:)])
  665. // [self.pdfListViewDelegate PDFListViewRemoveAnnotations:self forRemoveAnnotations:@[annotation] inPage:page];
  666. }
  667. - (void)removeActiveAnnotations:(NSArray<CPDFAnnotation *> *)removeAnnotations {
  668. BOOL isContains = NO;
  669. NSMutableArray *tarr = [NSMutableArray arrayWithArray:self.activeAnnotations];
  670. [tarr removeObjectsInArray:removeAnnotations];
  671. self.activeAnnotations = tarr;
  672. isContains = YES;
  673. if(isContains) {
  674. if([self.pdfListViewDelegate respondsToSelector:@selector(PDFListViewDeleteAnnotation:forAnnotation:)])
  675. [self.pdfListViewDelegate PDFListViewDeleteAnnotation:self forAnnotation:removeAnnotations.firstObject];
  676. dispatch_async(dispatch_get_main_queue(), ^{
  677. [[NSNotificationCenter defaultCenter] postNotificationName:CPDFListViewActiveAnnotationsChangeNotification object:self];
  678. });
  679. }
  680. // if(isContains) {
  681. // if([self.pdfListViewDelegate respondsToSelector:@selector(PDFListViewChangeatioActiveAnnotations:forActiveAnnotations:isRightMenu:)])
  682. // [self.pdfListViewDelegate PDFListViewChangeatioActiveAnnotations:self forActiveAnnotations:self.activeAnnotations isRightMenu:NO];
  683. //
  684. // dispatch_async(dispatch_get_main_queue(), ^{
  685. // [[NSNotificationCenter defaultCenter] postNotificationName:CPDFListViewActiveAnnotationsChangeNotification object:self];
  686. // });
  687. // }
  688. }
  689. @end