1- using Syncfusion . Drawing ;
2- using Syncfusion . Pdf ;
1+ using Syncfusion . Pdf . Graphics ;
32using Syncfusion . Pdf . Interactive ;
43using Syncfusion . Pdf . Parsing ;
4+
55class Program
66{
77 static void Main ( string [ ] args )
88 {
9- // Load the PDF document from disk.
10- using ( FileStream docStream = new FileStream ( Path . GetFullPath ( @"Data/Input.pdf" ) , FileMode . Open , FileAccess . Read ) )
9+ // Load the PDF document
10+ using ( PdfLoadedDocument loadedDocument = new PdfLoadedDocument ( Path . GetFullPath ( @"Data/Input.pdf" ) ) )
1111 {
12- // Load the PDF document into memory.
13- PdfLoadedDocument loadedDocument = new PdfLoadedDocument ( docStream ) ;
14-
15- // Access the root bookmark collection of the document.
1612 PdfBookmarkBase bookmarks = loadedDocument . Bookmarks ;
17-
18- // Move a bookmark from index 2 to index 0 (reorder).
19- MoveBookmark ( bookmarks , 2 , 0 , loadedDocument ) ;
20-
21- // Remove a bookmark by its title (removes the first match found in hierarchy).
13+ // Reorder: move bookmark from index
14+ if ( bookmarks . Count > 2 )
15+ MoveBookmark ( bookmarks , 2 , 0 , loadedDocument ) ;
16+ // Remove bookmark by title.
2217 RemoveBookmarkByTitle ( bookmarks , "Bookmark To Remove" ) ;
23-
24- //Create file stream.
25- using ( FileStream outputFileStream = new FileStream ( Path . GetFullPath ( @"Output/Output.pdf" ) , FileMode . Create , FileAccess . ReadWrite ) )
26- {
27- loadedDocument . Save ( outputFileStream ) ;
28- }
29-
30- loadedDocument . Close ( true ) ;
18+ loadedDocument . Save ( Path . GetFullPath ( @"Output/Output.pdf" ) ) ;
3119 }
3220 }
3321
3422 // Moves a bookmark from one index to another within its parent collection.
3523 static void MoveBookmark ( PdfBookmarkBase parentCollection , int fromIndex , int toIndex , PdfLoadedDocument document )
3624 {
37- if ( fromIndex == toIndex ) return ; // No move required if indices are the same.
38-
39- // Safely cast the bookmark to be moved.
40- PdfLoadedBookmark bookmarkToMove = parentCollection [ fromIndex ] as PdfLoadedBookmark ;
41- if ( bookmarkToMove == null ) return ;
42-
43- // Remove the bookmark from its original location.
25+ if ( fromIndex == toIndex || fromIndex < 0 || fromIndex >= parentCollection . Count )
26+ return ;
27+ PdfLoadedBookmark sourceBookmark = parentCollection [ fromIndex ] as PdfLoadedBookmark ;
28+ if ( sourceBookmark == null )
29+ return ;
30+ // Store bookmark details.
31+ string title = sourceBookmark . Title ;
32+ PdfTextStyle textStyle = sourceBookmark . TextStyle ;
33+ PdfColor color = sourceBookmark . Color ;
34+ PdfDestination destination = sourceBookmark . Destination ?? new PdfDestination ( document . Pages [ 0 ] ) ;
35+ List < PdfBookmark > children = new List < PdfBookmark > ( ) ;
36+ foreach ( PdfBookmark child in sourceBookmark )
37+ children . Add ( child ) ;
38+ // Remove from original position.
4439 parentCollection . RemoveAt ( fromIndex ) ;
45-
46- // Remove any existing bookmark with the same title at the new location to avoid duplicates.
47- RemoveBookmarkByTitle ( parentCollection , bookmarkToMove . Title ) ;
48-
49- // Insert the bookmark at the new index.
50- PdfBookmark newBookmark = parentCollection . Insert ( toIndex , bookmarkToMove . Title ) ;
51- newBookmark . TextStyle = bookmarkToMove . TextStyle ;
52- newBookmark . Color = bookmarkToMove . Color ;
53-
54- // Set the destination (page location/zoom) for the moved bookmark.
55- newBookmark . Destination = bookmarkToMove . Destination ?? new PdfDestination ( document . Pages [ 0 ] )
56- {
57- Location = bookmarkToMove . Destination ? . Location ?? new PointF ( 0 , 0 ) ,
58- Zoom = bookmarkToMove . Destination ? . Zoom ?? 1F
59- } ;
60-
61- // Move all child bookmarks recursively.
62- foreach ( PdfBookmark child in bookmarkToMove )
63- {
64- AddBookmark ( newBookmark , child , document ) ;
65- }
40+ // Adjust target index.
41+ int adjustedIndex = toIndex > fromIndex ? toIndex - 1 : toIndex ;
42+ adjustedIndex = Math . Max ( 0 , Math . Min ( adjustedIndex , parentCollection . Count ) ) ;
43+ // Insert at new position.
44+ var movedBookmark = parentCollection . Insert ( adjustedIndex , title ) ;
45+ movedBookmark . TextStyle = textStyle ;
46+ movedBookmark . Color = color ;
47+ movedBookmark . Destination = destination ;
48+ // Re-add children.
49+ foreach ( var child in children )
50+ AddBookmark ( movedBookmark , child , document ) ;
6651 }
6752
6853 // Clones an existing bookmark (including all descendants) and adds it to a parent.
69- static void AddBookmark ( PdfBookmark parent , PdfBookmark bookmark , PdfLoadedDocument document )
54+ static void AddBookmark ( PdfBookmark parent , PdfBookmark sourceBookmark , PdfLoadedDocument document )
7055 {
71- // Remove any even-closer duplicate title children before insertion.
72- RemoveBookmarkByTitle ( parent , bookmark . Title ) ;
73-
74- PdfBookmark newChild = parent . Insert ( parent . Count , bookmark . Title ) ;
75- newChild . Destination = bookmark . Destination ?? new PdfDestination ( document . Pages [ 0 ] )
76- {
77- Location = new PointF ( 0 , 0 ) ,
78- Zoom = 1F
79- } ;
80- newChild . TextStyle = bookmark . TextStyle ;
81- newChild . Color = bookmark . Color ;
82-
83- // Recursively clone and add children.
84- foreach ( PdfBookmark child in bookmark )
85- {
86- AddBookmark ( newChild , child , document ) ;
87- }
56+ if ( parent == null || sourceBookmark == null )
57+ return ;
58+ PdfBookmark newBookmark = parent . Insert ( parent . Count , sourceBookmark . Title ) ;
59+ newBookmark . TextStyle = sourceBookmark . TextStyle ;
60+ newBookmark . Color = sourceBookmark . Color ;
61+ newBookmark . Destination = sourceBookmark . Destination ?? new PdfDestination ( document . Pages [ 0 ] ) ;
62+ foreach ( PdfBookmark child in sourceBookmark )
63+ AddBookmark ( newBookmark , child , document ) ;
8864 }
8965
9066 // Removes the first occurrence of a bookmark with the specified title from a parent (searches recursively).
9167 static void RemoveBookmarkByTitle ( PdfBookmarkBase parent , string title )
9268 {
93- for ( int i = 0 ; i < parent . Count ; )
69+ if ( parent == null || string . IsNullOrWhiteSpace ( title ) )
70+ return ;
71+
72+ for ( int i = parent . Count - 1 ; i >= 0 ; i -- )
9473 {
95- if ( parent [ i ] . Title == title )
96- {
97- parent . RemoveAt ( i ) ;
98- continue ;
99- }
100- if ( parent [ i ] is PdfBookmark child )
74+ PdfBookmark bookmark = parent [ i ] as PdfBookmark ;
75+ if ( bookmark != null )
10176 {
102- RemoveBookmarkByTitle ( child , title ) ; // Recurse for children
77+ RemoveBookmarkByTitle ( bookmark , title ) ;
78+ if ( bookmark . Title == title )
79+ parent . RemoveAt ( i ) ;
10380 }
104- i ++ ;
10581 }
10682 }
10783}
0 commit comments