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

Reply via email to