13
13
using Openize . Slides . Common ;
14
14
using System . Dynamic ;
15
15
using P15 = DocumentFormat . OpenXml . Office2013 . PowerPoint ;
16
+ using DocumentFormat . OpenXml . Drawing . Charts ;
16
17
17
18
namespace Openize . Slides . Facade
18
19
{
19
20
public class PresentationDocumentFacade : IDisposable
20
21
{
21
- private static PresentationDocumentFacade _instance = null ;
22
+ private static readonly Dictionary < string , PresentationDocumentFacade > _instances = new Dictionary < string , PresentationDocumentFacade > ( ) ;
23
+ private static PresentationDocumentFacade _lastInstance ;
24
+ private static string _FilePath = null ;
22
25
private static MemoryStream _MemoryStream = null ;
23
26
private PKG . PresentationDocument _PresentationDocument = null ;
24
27
private bool disposedValue ;
@@ -31,6 +34,8 @@ public class PresentationDocumentFacade : IDisposable
31
34
private bool isNewPresentation = false ;
32
35
private List < SlideFacade > _SlideFacades = null ;
33
36
private CommentAuthorsPart _CommentAuthorPart ;
37
+ private Int32Value _slideWidth ;
38
+ private Int32Value _slideHeight ;
34
39
35
40
36
41
@@ -43,6 +48,9 @@ public class PresentationDocumentFacade : IDisposable
43
48
public List < SlideFacade > SlideFacades { get => _SlideFacades ; set => _SlideFacades = value ; }
44
49
public bool IsNewPresentation { get => isNewPresentation ; set => isNewPresentation = value ; }
45
50
public CommentAuthorsPart CommentAuthorPart { get => _CommentAuthorPart ; set => _CommentAuthorPart = value ; }
51
+ public Int32Value SlideWidth { get => _slideWidth ; set => _slideWidth = value ; }
52
+ public Int32Value SlideHeight { get => _slideHeight ; set => _slideHeight = value ; }
53
+ public static string FilePath { get => _FilePath ; set => _FilePath = value ; }
46
54
47
55
public PKG . PresentationPart GetPresentationPart ( )
48
56
{
@@ -55,6 +63,7 @@ private PresentationDocumentFacade (String FilePath, bool isNewFile)
55
63
{
56
64
if ( isNewFile )
57
65
{
66
+ _FilePath = FilePath ;
58
67
IsNewPresentation = isNewFile ;
59
68
SlideMasterIdList slideMasterIdList = new SlideMasterIdList ( new SlideMasterId ( ) { Id = ( UInt32Value ) 2147483648U , RelationshipId = "rId1" } ) ;
60
69
@@ -70,6 +79,7 @@ private PresentationDocumentFacade (String FilePath, bool isNewFile)
70
79
}
71
80
else
72
81
{
82
+ _FilePath = FilePath ;
73
83
_PresentationDocument = PKG . PresentationDocument . Open ( FilePath , true ) ;
74
84
_PresentationPart = _PresentationDocument . PresentationPart ;
75
85
_PresentationSlideParts = GetSlideParts ( _PresentationPart ) ;
@@ -167,47 +177,51 @@ public void RemoveCommentAuthor(int id)
167
177
public static PresentationDocumentFacade Create ( String FilePath )
168
178
{
169
179
170
- if ( _instance == null )
180
+ if ( ! _instances . ContainsKey ( FilePath ) )
171
181
{
172
- _instance = new PresentationDocumentFacade ( FilePath , true ) ;
173
- return _instance ;
182
+ _instances [ FilePath ] = new PresentationDocumentFacade ( FilePath , true ) ;
174
183
}
175
- return _instance ;
184
+ _lastInstance = _instances [ FilePath ] ;
185
+ return _instances [ FilePath ] ;
186
+ }
187
+
188
+ public static PresentationDocumentFacade Create ( String FilePath , int SlideWidth , int SlideHeight )
189
+ {
190
+
191
+ if ( ! _instances . ContainsKey ( FilePath ) )
192
+ {
193
+ _instances [ FilePath ] = new PresentationDocumentFacade ( FilePath , true ) ;
194
+ }
195
+ _lastInstance = _instances [ FilePath ] ;
196
+ return _instances [ FilePath ] ;
176
197
}
177
198
public static PresentationDocumentFacade Open ( string FilePath )
178
199
{
179
- if ( _instance == null )
200
+ if ( ! _instances . ContainsKey ( FilePath ) )
180
201
{
181
- try
182
- {
183
- _MemoryStream = new MemoryStream ( ) ;
184
- using ( FileStream fs = new FileStream ( FilePath , FileMode . Open ) )
185
- {
186
- fs . CopyTo ( _MemoryStream ) ;
187
- }
188
- }
189
- catch ( Exception ex )
190
- {
191
- string errorMessage = Common . OpenizeException . ConstructMessage ( ex , "Loading Document" ) ;
192
- throw new Common . OpenizeException ( errorMessage , ex ) ;
193
- }
194
-
195
- _instance = new PresentationDocumentFacade ( FilePath , false ) ;
196
- return _instance ;
202
+ _instances [ FilePath ] = new PresentationDocumentFacade ( FilePath , false ) ;
197
203
}
198
- return _instance ;
204
+ _lastInstance = _instances [ FilePath ] ;
205
+ return _instances [ FilePath ] ;
199
206
}
200
207
201
- public static PresentationDocumentFacade getInstance ( )
208
+ public static PresentationDocumentFacade getInstance ( string FilePath = null )
202
209
{
203
- return _instance ;
210
+ return FilePath != null ? _instances . GetValueOrDefault ( FilePath ) : _lastInstance ;
204
211
}
205
212
206
213
private void CreatePresentationParts ( )
207
214
{
215
+ // Default values in EMUs
216
+ const int defaultWidth = 9144000 ; // 10 inches
217
+ const int defaultHeight = 6858000 ; // 7.5 inches
218
+
219
+ // Use the class-level values if set, otherwise use defaults
220
+ Int32Value slideWidth = _slideWidth ?? defaultWidth ;
221
+ Int32Value slideHeight = _slideHeight ?? defaultHeight ;
208
222
209
223
//SlideIdList slideIdList1 = new SlideIdList(new SlideId() { Id = (UInt32Value)256U, RelationshipId = "rId2" });
210
- SlideSize slideSize1 = new SlideSize ( ) { Cx = 9144000 , Cy = 6858000 , Type = SlideSizeValues . Custom } ;
224
+ SlideSize slideSize1 = new SlideSize ( ) { Cx = slideWidth , Cy = slideHeight , Type = SlideSizeValues . Custom } ;
211
225
NotesSize notesSize1 = new NotesSize ( ) { Cx = 6858000 , Cy = 9144000 } ;
212
226
DefaultTextStyle defaultTextStyle1 = new DefaultTextStyle ( ) ;
213
227
@@ -537,6 +551,15 @@ public void AppendSlide (SlideFacade slideFacade)
537
551
slideFacade . PresentationSlide . Save ( slideFacade . SlidePart ) ;
538
552
_PresentationSlideParts . Add ( slideFacade . SlidePart ) ;
539
553
554
+
555
+ }
556
+ public void Clone ( SlideFacade slideFacade )
557
+ {
558
+
559
+ slideFacade . PresentationSlide . Save ( slideFacade . SlidePart ) ;
560
+ _PresentationSlideParts . Add ( slideFacade . SlidePart ) ;
561
+
562
+
540
563
}
541
564
public void InsertSlide ( int index , SlideFacade slideFacade )
542
565
{
@@ -563,50 +586,111 @@ public void MoveSlideToIndex (int currentIndex, int newIndex)
563
586
}
564
587
}
565
588
566
- /// <summary>
567
- /// This method releases unmanaged resources.
568
- /// </summary>
569
- /// <param name="disposing">A boolean value.</param>
570
- protected virtual void Dispose ( bool disposing )
589
+ public void CopySlide ( SlideFacade slideFacade )
571
590
{
572
- if ( ! disposedValue )
591
+ // Open source and target presentations
592
+
593
+ var targetPresentation = this ;
594
+
595
+ // Get the source slide part
596
+ SlidePart sourceSlidePart = slideFacade . SlidePart ;
597
+
598
+ // Get the target presentation part
599
+ PresentationPart targetPresentationPart = getInstance ( FilePath ) . GetPresentationPart ( ) ;
600
+ SlideIdList targetSlideIdList = targetPresentationPart . Presentation . SlideIdList ;
601
+ uint newSlideId = _SlideIdList . Elements < SlideId > ( ) . Max ( s => s . Id . Value ) + 1 ;
602
+
603
+
604
+ SlidePart newSlidePart = CopySlidePart ( sourceSlidePart , targetPresentationPart ) ;
605
+
606
+ SlideId newSlideIdElement = new SlideId ( )
573
607
{
574
- if ( disposing )
608
+ Id = newSlideId ,
609
+ RelationshipId = _PresentationPart . GetIdOfPart ( newSlidePart )
610
+ } ;
611
+ _SlideIdList . Append ( newSlideIdElement ) ;
612
+
613
+
614
+ }
615
+ public static SlidePart CopySlidePart ( SlidePart sourceSlidePart , PresentationPart destinationPresentationPart )
616
+ {
617
+ SlidePart newSlidePart = destinationPresentationPart . AddNewPart < SlidePart > ( ) ;
618
+
619
+ // Clone slide but prevent locking issues
620
+ newSlidePart . Slide = ( P . Slide ) sourceSlidePart . Slide . CloneNode ( true ) ;
621
+
622
+ // Handle Slide Layout properly
623
+ if ( sourceSlidePart . SlideLayoutPart != null )
624
+ {
625
+ SlideLayoutPart destLayoutPart = destinationPresentationPart . SlideMasterParts
626
+ . SelectMany ( master => master . SlideLayoutParts )
627
+ . FirstOrDefault ( layout => layout . Uri == sourceSlidePart . SlideLayoutPart . Uri ) ;
628
+
629
+ if ( destLayoutPart != null )
575
630
{
576
- // TODO: dispose managed state (managed objects)
577
- _PresentationDocument . Dispose ( ) ;
578
- _MemoryStream . Dispose ( ) ;
631
+ newSlidePart . AddPart ( destLayoutPart ) ;
579
632
}
633
+ }
580
634
635
+ newSlidePart . Slide . Save ( ) ;
636
+ return newSlidePart ;
637
+ }
581
638
582
- disposedValue = true ;
583
- }
639
+
640
+ public static void Save ( string FilePath = null )
641
+ {
642
+ var instance = getInstance ( FilePath ) ;
643
+ instance ? . Save ( ) ;
584
644
}
585
- public void Save ( )
645
+
646
+ private void RemoveParts ( )
586
647
{
587
- if ( IsNewPresentation )
648
+ _PresentationDocument = null ;
649
+ _PresentationPart = null ;
650
+ _PresentationSlideParts = null ;
651
+ _CommentAuthorPart = null ;
652
+ _PresentationSlideLayoutParts = null ;
653
+ _SlideIdList = null ;
654
+ _PresentationSlideMasterPart = null ;
655
+
656
+ }
657
+ public void Close ( string FilePath = null )
658
+ {
659
+ if ( FilePath == null )
588
660
{
589
- CreatePresentationParts ( ) ;
661
+ FilePath = _instances . FirstOrDefault ( kvp => kvp . Value == _lastInstance ) . Key ;
590
662
}
591
- else
663
+ if ( FilePath != null && _instances . ContainsKey ( FilePath ) )
592
664
{
593
- _PresentationDocument . Save ( ) ;
665
+ _instances [ FilePath ] . Save ( ) ; // Ensure saving before closing
666
+ _instances [ FilePath ] . Dispose ( ) ;
667
+ _instances . Remove ( FilePath ) ;
668
+ if ( _lastInstance == _instances . GetValueOrDefault ( FilePath ) )
669
+ {
670
+ _lastInstance = null ;
671
+ }
594
672
}
595
- _PresentationDocument . Dispose ( ) ;
673
+ }
596
674
675
+ public void Save ( )
676
+ {
677
+ _PresentationDocument ? . PresentationPart ? . Presentation . Save ( ) ;
678
+ _PresentationDocument ? . Save ( ) ;
597
679
}
598
- public void Save ( String FilePath )
680
+ protected virtual void Dispose ( bool disposing )
599
681
{
600
- _PresentationDocument . Save ( ) ;
601
-
682
+ if ( ! disposedValue )
683
+ {
684
+ if ( disposing )
685
+ {
686
+ _PresentationDocument ? . Dispose ( ) ;
687
+ }
688
+ disposedValue = true ;
689
+ }
602
690
}
603
691
604
- /// <summary>
605
- /// This method releases unmanaged resources.
606
- /// </summary>
607
- public void Dispose ( )
692
+ public void Dispose ( )
608
693
{
609
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
610
694
Dispose ( disposing : true ) ;
611
695
GC . SuppressFinalize ( this ) ;
612
696
}
0 commit comments