Revision: 15397 http://sourceforge.net/p/skim-app/code/15397 Author: hofman Date: 2025-06-07 16:04:20 +0000 (Sat, 07 Jun 2025) Log Message: ----------- Undo adding and removing of notes also in bulk
Modified Paths: -------------- trunk/SKMainWindowController.h trunk/SKMainWindowController.m Modified: trunk/SKMainWindowController.h =================================================================== --- trunk/SKMainWindowController.h 2025-06-07 15:11:08 UTC (rev 15396) +++ trunk/SKMainWindowController.h 2025-06-07 16:04:20 UTC (rev 15397) @@ -242,6 +242,7 @@ - (void)insertObject:(PDFAnnotation *)note inNotesAtIndex:(NSUInteger)theIndex; - (void)insertNotes:(NSArray *)newNotes atIndexes:(NSIndexSet *)theIndexes; - (void)removeObjectFromNotesAtIndex:(NSUInteger)theIndex; +- (void)removeNotesAtIndexes:(NSIndexSet *)theIndexes; - (void)removeAllObjectsFromNotes; @property (nonatomic, copy) NSArray<SKThumbnail *> *thumbnails; Modified: trunk/SKMainWindowController.m =================================================================== --- trunk/SKMainWindowController.m 2025-06-07 15:11:08 UTC (rev 15396) +++ trunk/SKMainWindowController.m 2025-06-07 16:04:20 UTC (rev 15397) @@ -965,20 +965,19 @@ return properties; } -- (void)addAnnotations:(NSArray *)notesToAdd removeAnnotations:(NSArray *)notesToRemove { +- (void)addAnnotations:(NSArray *)notesAndPagesToAdd removeAnnotations:(NSArray *)notesToRemove { PDFDocument *pdfDoc = [pdfView document]; NSMutableIndexSet *pageIndexes = [NSMutableIndexSet indexSet]; - NSMutableArray *added = [NSMutableArray array]; - NSMutableArray *removed = [NSMutableArray array]; - NSMutableArray *addedSkimNotes = [NSMutableArray array]; - NSMutableIndexSet *removedIndexes = [NSMutableIndexSet indexSet]; + NSMutableArray *addedNotes = [NSMutableArray array]; + NSMutableArray *removedNotesAndPages = [NSMutableArray array]; + NSMutableIndexSet *removedIndexes = [[notesToRemove firstObject] isSkimNote] ? [NSMutableIndexSet indexSet] : nil; mwcFlags.addOrRemoveNotesInBulk = 1; if ([notesToRemove count]) { for (PDFAnnotation *annotation in notesToRemove) { - [removed addObject:@[annotation, [annotation page]]]; - if ([annotation isSkimNote]) + [removedNotesAndPages addObject:@[annotation, [annotation page]]]; + if (removedIndexes) [removedIndexes addIndex:[notes indexOfObject:annotation]]; [pageIndexes addIndex:[annotation pageIndex]]; [pdfDoc removeAnnotation:annotation]; @@ -985,12 +984,10 @@ } } - if ([notesToAdd count]) { - for (NSArray *annotationAndPage in notesToAdd) { + if ([notesAndPagesToAdd count]) { + for (NSArray *annotationAndPage in notesAndPagesToAdd) { PDFAnnotation *annotation = [annotationAndPage firstObject]; - [added addObject:annotation]; - if ([annotation isSkimNote]) - [addedSkimNotes addObject:annotation]; + [addedNotes addObject:annotation]; [pageIndexes addIndex:[annotation pageIndex]]; [pdfDoc addAnnotation:annotation toPage:[annotationAndPage lastObject]]; } @@ -998,12 +995,14 @@ mwcFlags.addOrRemoveNotesInBulk = 0; - [[[self undoManager] prepareWithInvocationTarget:self] addAnnotations:removed removeAnnotations:added]; + [[[self undoManager] prepareWithInvocationTarget:self] addAnnotations:removedNotesAndPages removeAnnotations:addedNotes]; + [removedIndexes removeIndex:NSNotFound]; + if ([removedIndexes count]) - [[self mutableArrayValueForKey:NOTES_KEY] removeObjectsAtIndexes:removedIndexes]; - if ([addedSkimNotes count]) - [self insertNotes:addedSkimNotes atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange([notes count], [addedSkimNotes count])]]; + [self removeNotesAtIndexes:removedIndexes]; + if ([[addedNotes firstObject] isSkimNote]) + [self insertNotes:addedNotes atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange([addedNotes count], [addedNotes count])]]; // make sure we clear the undo handling undoGroupOldPropertiesPerNote = nil; @@ -1017,18 +1016,16 @@ [pdfView resetPDFToolTipRects]; } -- (void)addAnnotationsFromDictionaries:(NSArray *)noteDicts toDocument:(PDFDocument *)pdfDoc pageIndexes:(NSMutableIndexSet *)pageIndexes autoUpdate:(BOOL)autoUpdate { - NSMutableArray *notesToAdd = [NSMutableArray array]; +- (NSArray *)annotationsAndPagesFromDictionaries:(NSArray *)noteDicts forDocument:(PDFDocument *)pdfDoc autoUpdate:(BOOL)autoUpdate widgetDictionaries:(NSMutableArray *)widgetDicts { + NSMutableArray *notesAndPagesToAdd = [NSMutableArray array]; BOOL shouldDisplay = [pdfView hideNotes] == NO; - // disable automatic add/remove from the notification handlers - // we want to do this in bulk as binding can be very slow and there are potentially many notes - mwcFlags.addOrRemoveNotesInBulk = 1; - - // create new annotations from the dictionary and add them to their page and to the document + // create new annotations from the dictionary and get the page to add to for (NSDictionary *dict in noteDicts) { - if ([[dict objectForKey:SKNPDFAnnotationTypeKey] isEqualToString:SKNWidgetString]) + if ([[dict objectForKey:SKNPDFAnnotationTypeKey] isEqualToString:SKNWidgetString]) { + [widgetDicts addObject:dict]; continue; + } @autoreleasepool{ PDFAnnotation *annotation = [PDFAnnotation newSkimNoteWithProperties:dict]; if (annotation) { @@ -1037,59 +1034,43 @@ pageIndex = 0; else if (pageIndex >= [pdfDoc pageCount]) pageIndex = [pdfDoc pageCount] - 1; - [pageIndexes addIndex:pageIndex]; [annotation setShouldDisplay:shouldDisplay]; [annotation setShouldPrint:shouldDisplay]; PDFPage *page = [pdfDoc pageAtIndex:pageIndex]; if (autoUpdate && [[annotation contents] length] == 0) [annotation autoUpdateStringWithPage:page]; - [pdfDoc addAnnotation:annotation toPage:page]; - [notesToAdd addObject:annotation]; + [notesAndPagesToAdd addObject:@[annotation, page]]; } } } - mwcFlags.addOrRemoveNotesInBulk = 0; - - if ([notesToAdd count] > 0) - [self insertNotes:notesToAdd atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange([notes count], [notesToAdd count])]]; + return notesAndPagesToAdd; } - (void)addAnnotationsFromDictionaries:(NSArray *)noteDicts removeAnnotations:(NSArray *)notesToRemove { + // notesToRemove is either [self notes], nil, or non Skim notes BOOL isAddOrReplace = [notesToRemove count] == 0 || [[notesToRemove firstObject] isSkimNote]; PDFDocument *pdfDoc = [pdfView document]; - NSMutableIndexSet *pageIndexes = [NSMutableIndexSet indexSet]; + NSMutableArray *widgetDicts = [NSMutableArray array]; - if ([notesToRemove count]) { - // notesToRemove is either [self notes], nil, or non Skim notes - if (isAddOrReplace) { - [pdfView removePDFToolTipRects]; - // remove the current annotations - [pdfView setCurrentAnnotation:nil]; - } - mwcFlags.addOrRemoveNotesInBulk = 1; - for (PDFAnnotation *annotation in [notesToRemove copy]) { - [pageIndexes addIndex:[annotation pageIndex]]; - [pdfDoc removeAnnotation:annotation]; - } - mwcFlags.addOrRemoveNotesInBulk = 0; - if (isAddOrReplace) - [self removeAllObjectsFromNotes]; + NSArray *notesAndPagesToAdd = [self annotationsAndPagesFromDictionaries:noteDicts forDocument:pdfDoc autoUpdate:isAddOrReplace == NO widgetDictionaries:widgetDicts]; + + if ([notesToRemove count] && isAddOrReplace) { + [pdfView removePDFToolTipRects]; + // remove the current annotations + [pdfView setCurrentAnnotation:nil]; } - if (notesToRemove && isAddOrReplace && [widgets count]) { - for (PDFAnnotation *widget in widgets) { - id origValue = [widgetValues objectForKey:widget]; - if ([([widget objectValue] ?: @"") isEqual:(origValue ?: @"")] == NO) - [widget setObjectValue:origValue]; - } - } - [self addAnnotationsFromDictionaries:noteDicts toDocument:pdfDoc pageIndexes:pageIndexes autoUpdate:isAddOrReplace == NO]; - if (isAddOrReplace) { - NSArray *widgetProperties = [noteDicts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"type = \"Widget\""]]; - if ([widgetProperties count]) - [self changeWidgetsFromDictionaries:widgetProperties]; + if (notesToRemove && [widgets count]) { + for (PDFAnnotation *widget in widgets) { + id origValue = [widgetValues objectForKey:widget]; + if ([([widget objectValue] ?: @"") isEqual:(origValue ?: @"")] == NO) + [widget setObjectValue:origValue]; + } + } + if ([widgetDicts count]) + [self changeWidgetsFromDictionaries:widgetDicts]; } else if ([widgets count]) { NSMapTable *values = [NSMapTable strongToStrongObjectsMapTable]; for (PDFAnnotation *widget in widgets) @@ -1098,16 +1079,7 @@ [self setWidgetValues:values]; } - // make sure we clear the undo handling - undoGroupOldPropertiesPerNote = nil; - [rightSideController.noteArrayController rearrangeObjects]; // doesn't seem to be done automatically - [rightSideController.noteOutlineView reloadData]; - [self updateThumbnailsAtPageIndexes:pageIndexes]; - for (SKSnapshotWindowController *wc in snapshots) { - if ([wc isPageInIndexesVisible:pageIndexes]) - [self snapshotNeedsUpdate:wc lowPriority:NO]; - } - [pdfView resetPDFToolTipRects]; + [self addAnnotations:notesAndPagesToAdd removeAnnotations:notesToRemove]; } - (void)setPdfDocument:(PDFDocument *)pdfDocument addAnnotationsFromDictionaries:(NSArray *)noteDicts { @@ -1185,7 +1157,18 @@ [self applyChangedCropBoxes:cropBoxes inDocument:pdfDocument]; } - [self addAnnotationsFromDictionaries:noteDicts toDocument:pdfDoc pageIndexes:nil autoUpdate:NO]; + if ([noteDicts count]) { + NSArray *notesAndPagesToAdd = [self annotationsAndPagesFromDictionaries:noteDicts forDocument:pdfDoc autoUpdate:NO widgetDictionaries:nil]; + NSMutableArray *addedNotes = [NSMutableArray array]; + + for (NSArray *annotationAndPage in notesAndPagesToAdd) { + PDFAnnotation *annotation = [annotationAndPage firstObject]; + [pdfDoc addAnnotation:annotation toPage:[annotationAndPage lastObject]]; + [addedNotes addObject:annotation]; + } + + [self insertNotes:addedNotes atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [addedNotes count])]]; + } [pdfView setDocument:pdfDocument]; [pdfDocument setDelegate:self]; @@ -1419,6 +1402,23 @@ [notes removeObjectAtIndex:theIndex]; } +- (void)removeNotesAtIndexes:(NSIndexSet *)theIndexes { + NSArray *removedNotes = [notes objectsAtIndexes:theIndexes]; + + for (PDFAnnotation *note in removedNotes) { + [[self windowControllerForNote:note] close]; + + if ([note hasNoteText]) + [rightSideController.noteOutlineView setRowHeight:0.0 forItem:[note noteText]]; + [rightSideController.noteOutlineView setRowHeight:0.0 forItem:note]; + } + + // Stop observing the removed notes + [self stopObservingNotes:removedNotes]; + + [notes removeObjectsAtIndexes:theIndexes]; +} + - (void)removeAllObjectsFromNotes { if ([notes count]) { NSArray *wcs = [[[self document] windowControllers] copy]; @@ -2254,9 +2254,9 @@ [self updateThumbnailAtPageIndex:[page pageIndex]]; [presentationView setNeedsDisplayForPage:page]; } else { - [[undoManager prepareWithInvocationTarget:[notification object]] removeAnnotation:annotation]; - if (mwcFlags.addOrRemoveNotesInBulk == 0) { + [[undoManager prepareWithInvocationTarget:[notification object]] removeAnnotation:annotation]; + if ([annotation isSkimNote]) { [annotation setShouldDisplay:[pdfView hideNotes] == NO]; [annotation setShouldPrint:[pdfView hideNotes] == NO]; @@ -2297,9 +2297,9 @@ [self updateThumbnailAtPageIndex:[page pageIndex]]; } } else { - [[undoManager prepareWithInvocationTarget:[notification object]] addAnnotation:annotation toPage:page]; - if (mwcFlags.addOrRemoveNotesInBulk == 0) { + [[undoManager prepareWithInvocationTarget:[notification object]] addAnnotation:annotation toPage:page]; + if ([annotation isSkimNote]) { if ([[self selectedNotes] containsObject:annotation]) [rightSideController.noteOutlineView deselectAll:self]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. _______________________________________________ Skim-app-commit mailing list Skim-app-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/skim-app-commit