diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..13e4bb7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,133 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+
+[Dd]ebug/
+[Rr]elease/
+x64/
+[Bb]in/
+[Oo]bj/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.log
+*.svclog
+*.scc
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.Publish.xml
+*.pubxml
+*.azurePubxml
+
+# NuGet Packages Directory
+## TODO: If you have NuGet Package Restore enabled, uncomment the next line
+packages/
+## TODO: If the tool you use requires repositories.config, also uncomment the next line
+!packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+![Ss]tyle[Cc]op.targets
+~$*
+*~
+*.dbmdl
+*.[Pp]ublish.xml
+
+*.publishsettings
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+App_Data/*.mdf
+App_Data/*.ldf
+
+# =========================
+# Windows detritus
+# =========================
+
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Mac desktop service store files
+.DS_Store
+
+_NCrunch*
\ No newline at end of file
diff --git a/FileFormat.Slides-Test/Program.cs b/FileFormat.Slides-Test/Program.cs
index 826cd3c..39711fd 100644
--- a/FileFormat.Slides-Test/Program.cs
+++ b/FileFormat.Slides-Test/Program.cs
@@ -2,7 +2,7 @@
using PKG = DocumentFormat.OpenXml.Packaging;
using P = DocumentFormat.OpenXml.Presentation;
using System;
-using GeneratedCode;
+//using GeneratedCode;
using FileFormat.Slides;
using System.Collections.Generic;
using FileFormat.Slides.Common;
diff --git a/FileFormat.Slides.Common/FileFormat.Slides.Common.csproj b/FileFormat.Slides.Common/FileFormat.Slides.Common.csproj
index 49c4d01..f8485ba 100644
--- a/FileFormat.Slides.Common/FileFormat.Slides.Common.csproj
+++ b/FileFormat.Slides.Common/FileFormat.Slides.Common.csproj
@@ -4,8 +4,17 @@
netcoreapp3.1
+
+
+
+
+
+
diff --git a/FileFormat.Slides.Facade/PresentationDocumentFacade.cs b/FileFormat.Slides.Facade/PresentationDocumentFacade.cs
index 5338004..15e2208 100644
--- a/FileFormat.Slides.Facade/PresentationDocumentFacade.cs
+++ b/FileFormat.Slides.Facade/PresentationDocumentFacade.cs
@@ -564,8 +564,12 @@ public void InsertSlide (int index, SlideFacade slideFacade)
{
slideFacade.PresentationSlide.Save(slideFacade.SlidePart);
_PresentationSlideParts.Add(slideFacade.SlidePart);
- MoveSlideToIndex(slideFacade.SlideIndex, index);
+ // find the current index of the slide in the list and then move it to the specified index
+ var relationshipId = slideFacade.RelationshipId;
+ var currentIndex = _SlideIdList.Elements().ToList().FindIndex(item => item.RelationshipId == relationshipId);
+
+ MoveSlideToIndex(slideFacade.SlideIndex, index);
}
public void MoveSlideToIndex (int currentIndex, int newIndex)
diff --git a/FileFormat.Slides.Tests/FileFormat.Slides.Tests.csproj b/FileFormat.Slides.Tests/FileFormat.Slides.Tests.csproj
new file mode 100644
index 0000000..6757b9f
--- /dev/null
+++ b/FileFormat.Slides.Tests/FileFormat.Slides.Tests.csproj
@@ -0,0 +1,22 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FileFormat.Slides.Tests/InsertSlideTests.cs b/FileFormat.Slides.Tests/InsertSlideTests.cs
new file mode 100644
index 0000000..043f084
--- /dev/null
+++ b/FileFormat.Slides.Tests/InsertSlideTests.cs
@@ -0,0 +1,222 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections.Generic;
+
+namespace FileFormat.Slides.Tests
+{
+ [TestClass]
+ public class InsertSlideTests
+ {
+ protected List tempFileList = new List();
+
+ protected Presentation GetSimplePresentation(int numberOfSlides = 3)
+ {
+ var tempFile = Path.GetTempFileName();
+ var tempPresentationFilename = $"{tempFile}.pptx";
+
+ // track our mess
+ tempFileList.Add(tempFile);
+ tempFileList.Add(tempPresentationFilename);
+
+ Presentation presentation = Presentation.Create(tempPresentationFilename);
+
+ for (var i = 0; i < numberOfSlides; i++)
+ {
+ var slideId = $"{i + 1}".PadLeft(3, '0');
+ Slide slide = new Slide();
+ slide.AddTextShapes(new TextShape()
+ {
+ Text = $"this is is slide: {slideId}",
+ FontSize = 80
+
+ });
+ presentation.AppendSlide(slide);
+ }
+
+ return presentation;
+ }
+
+ protected Slide BuildSimpleSlide()
+ {
+ Slide slide = new Slide();
+ slide.AddTextShapes(new TextShape()
+ {
+ Text = "this is is slide: 009",
+ FontSize = 80
+
+ });
+ return slide;
+ }
+
+ protected string[] GetRelationshipIdsInOrder(Presentation presentation)
+ {
+ return presentation.Facade.SlideIdList.ChildElements
+ .Select(s => (s as DocumentFormat.OpenXml.Presentation.SlideId).RelationshipId.Value)
+ .ToArray();
+ }
+
+ [TestCleanup]
+ public void CleanUp()
+ {
+ if (tempFileList.Any())
+ {
+ foreach(var file in tempFileList)
+ {
+ try {
+ File.Delete(file);
+ }
+ catch {
+ Console.WriteLine($"Failed to delete: {file}");
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ public void InsertSlideAtPositionZero()
+ {
+ var presentation = GetSimplePresentation();
+ var idList = GetRelationshipIdsInOrder(presentation);
+
+ // insert a new slide at the begining of the presentation
+ Slide slide = BuildSimpleSlide();
+ presentation.InsertSlideAt(0, slide);
+
+ // get the new relationship id from it to build out the expected list
+ var newSlideRelationshipId = slide.RelationshipId;
+ var expectedIds = new string[] { newSlideRelationshipId, idList[0], idList[1], idList[2] };
+
+ // Get the current list post insert
+ var updatedIdList = GetRelationshipIdsInOrder(presentation);
+
+ // validate the slide is where we expext it to be
+ CollectionAssert.AreEqual(expectedIds, updatedIdList);
+
+ presentation.Save();
+ presentation.close();
+ }
+
+ [TestMethod]
+ public void InsertSlideAtPositionOne()
+ {
+ var presentation = GetSimplePresentation();
+ var idList = GetRelationshipIdsInOrder(presentation);
+
+ // insert a new slide at the begining of the presentation
+ Slide slide = BuildSimpleSlide();
+ presentation.InsertSlideAt(1, slide);
+
+ // get the new relationship id from it to build out the expected list
+ var newSlideRelationshipId = slide.RelationshipId;
+ var expectedIds = new string[] { idList[0], newSlideRelationshipId, idList[1], idList[2] };
+
+ // Get the current list post insert
+ var updatedIdList = GetRelationshipIdsInOrder(presentation);
+
+ // validate the slide is where we expext it to be
+ CollectionAssert.AreEqual(expectedIds, updatedIdList);
+
+ presentation.Save();
+ presentation.close();
+ }
+
+ [TestMethod]
+ public void InsertSlideAtPositionTwo()
+ {
+ var presentation = GetSimplePresentation();
+ var idList = GetRelationshipIdsInOrder(presentation);
+
+ // insert a new slide at the begining of the presentation
+ Slide slide = BuildSimpleSlide();
+ presentation.InsertSlideAt(2, slide);
+
+ // get the new relationship id from it to build out the expected list
+ var newSlideRelationshipId = slide.RelationshipId;
+ var expectedIds = new string[] { idList[0], idList[1], newSlideRelationshipId, idList[2] };
+
+ // Get the current list post insert
+ var updatedIdList = GetRelationshipIdsInOrder(presentation);
+
+ // validate the slide is where we expext it to be
+ CollectionAssert.AreEqual(expectedIds, updatedIdList);
+
+ presentation.Save();
+ presentation.close();
+ }
+
+ [TestMethod]
+ public void InsertSlideAtPositionThree()
+ {
+ var presentation = GetSimplePresentation();
+ var idList = GetRelationshipIdsInOrder(presentation);
+
+ // insert a new slide at the begining of the presentation
+ Slide slide = BuildSimpleSlide();
+ presentation.InsertSlideAt(3, slide);
+
+ // get the new relationship id from it to build out the expected list
+ var newSlideRelationshipId = slide.RelationshipId;
+ var expectedIds = new string[] { idList[0], idList[1], idList[2], newSlideRelationshipId };
+
+ // Get the current list post insert
+ var updatedIdList = GetRelationshipIdsInOrder(presentation);
+
+ // validate the slide is where we expext it to be
+ CollectionAssert.AreEqual(expectedIds, updatedIdList);
+
+ presentation.Save();
+ presentation.close();
+ }
+
+ [TestMethod]
+ public void InsertSlideAtPositionOutOfRangeHigh()
+ {
+ var presentation = GetSimplePresentation();
+ var idList = GetRelationshipIdsInOrder(presentation);
+
+ // insert a new slide at the begining of the presentation
+ Slide slide = BuildSimpleSlide();
+ presentation.InsertSlideAt(99, slide);
+
+ // get the new relationship id from it to build out the expected list
+ var newSlideRelationshipId = slide.RelationshipId;
+ var expectedIds = new string[] { idList[0], idList[1], idList[2], newSlideRelationshipId };
+
+ // Get the current list post insert
+ var updatedIdList = GetRelationshipIdsInOrder(presentation);
+
+ // validate the slide is where we expext it to be
+ CollectionAssert.AreEqual(expectedIds, updatedIdList);
+
+ presentation.Save();
+ presentation.close();
+ }
+
+ [TestMethod]
+ public void InsertSlideAtPositionOutOfRangeLow()
+ {
+ var presentation = GetSimplePresentation();
+ var idList = GetRelationshipIdsInOrder(presentation);
+
+ // insert a new slide at the begining of the presentation
+ Slide slide = BuildSimpleSlide();
+ presentation.InsertSlideAt(-5, slide);
+
+ // get the new relationship id from it to build out the expected list
+ var newSlideRelationshipId = slide.RelationshipId;
+ var expectedIds = new string[] { idList[0], idList[1], idList[2], newSlideRelationshipId };
+
+ // Get the current list post insert
+ var updatedIdList = GetRelationshipIdsInOrder(presentation);
+
+ // validate the slide is where we expext it to be
+ CollectionAssert.AreEqual(expectedIds, updatedIdList);
+
+ presentation.Save();
+ presentation.close();
+ }
+
+ }
+}
diff --git a/FileFormat.Slides.sln b/FileFormat.Slides.sln
index d91020f..2b07a0e 100644
--- a/FileFormat.Slides.sln
+++ b/FileFormat.Slides.sln
@@ -1,43 +1,49 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.33130.400
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides", "FileFormat.Slides\FileFormat.Slides.csproj", "{17F3D657-D3AB-406E-AA9C-FF8613FB81E9}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides.Common", "FileFormat.Slides.Common\FileFormat.Slides.Common.csproj", "{A8EAE068-8E31-4866-A600-5CC17FE1F423}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides.Facade", "Fileformat.Slides.Facade\FileFormat.Slides.Facade.csproj", "{42D256AA-5DB9-4CC9-B290-BA7C86108BEF}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides-Test", "FileFormat.Slides-Test\FileFormat.Slides-Test.csproj", "{10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {17F3D657-D3AB-406E-AA9C-FF8613FB81E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {17F3D657-D3AB-406E-AA9C-FF8613FB81E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {17F3D657-D3AB-406E-AA9C-FF8613FB81E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {17F3D657-D3AB-406E-AA9C-FF8613FB81E9}.Release|Any CPU.Build.0 = Release|Any CPU
- {A8EAE068-8E31-4866-A600-5CC17FE1F423}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A8EAE068-8E31-4866-A600-5CC17FE1F423}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A8EAE068-8E31-4866-A600-5CC17FE1F423}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A8EAE068-8E31-4866-A600-5CC17FE1F423}.Release|Any CPU.Build.0 = Release|Any CPU
- {42D256AA-5DB9-4CC9-B290-BA7C86108BEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {42D256AA-5DB9-4CC9-B290-BA7C86108BEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {42D256AA-5DB9-4CC9-B290-BA7C86108BEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {42D256AA-5DB9-4CC9-B290-BA7C86108BEF}.Release|Any CPU.Build.0 = Release|Any CPU
- {10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {3AB71A27-7437-4743-B8BB-D37886E02DC2}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.33130.400
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides", "FileFormat.Slides\FileFormat.Slides.csproj", "{17F3D657-D3AB-406E-AA9C-FF8613FB81E9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides.Common", "FileFormat.Slides.Common\FileFormat.Slides.Common.csproj", "{A8EAE068-8E31-4866-A600-5CC17FE1F423}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides.Facade", "Fileformat.Slides.Facade\FileFormat.Slides.Facade.csproj", "{42D256AA-5DB9-4CC9-B290-BA7C86108BEF}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides-Test", "FileFormat.Slides-Test\FileFormat.Slides-Test.csproj", "{10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileFormat.Slides.Tests", "FileFormat.Slides.Tests\FileFormat.Slides.Tests.csproj", "{A87C0119-FA6E-465A-AA7B-5D30FFA8A5B9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {17F3D657-D3AB-406E-AA9C-FF8613FB81E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {17F3D657-D3AB-406E-AA9C-FF8613FB81E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {17F3D657-D3AB-406E-AA9C-FF8613FB81E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {17F3D657-D3AB-406E-AA9C-FF8613FB81E9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A8EAE068-8E31-4866-A600-5CC17FE1F423}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A8EAE068-8E31-4866-A600-5CC17FE1F423}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A8EAE068-8E31-4866-A600-5CC17FE1F423}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A8EAE068-8E31-4866-A600-5CC17FE1F423}.Release|Any CPU.Build.0 = Release|Any CPU
+ {42D256AA-5DB9-4CC9-B290-BA7C86108BEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {42D256AA-5DB9-4CC9-B290-BA7C86108BEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {42D256AA-5DB9-4CC9-B290-BA7C86108BEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {42D256AA-5DB9-4CC9-B290-BA7C86108BEF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {10A9AE59-4C5D-4D6B-82FB-4F066EA7CA53}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A87C0119-FA6E-465A-AA7B-5D30FFA8A5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A87C0119-FA6E-465A-AA7B-5D30FFA8A5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A87C0119-FA6E-465A-AA7B-5D30FFA8A5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A87C0119-FA6E-465A-AA7B-5D30FFA8A5B9}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3AB71A27-7437-4743-B8BB-D37886E02DC2}
+ EndGlobalSection
+EndGlobal
diff --git a/FileFormat.Slides/FileFormat.Slides.csproj b/FileFormat.Slides/FileFormat.Slides.csproj
index aedc70f..afcf32f 100644
--- a/FileFormat.Slides/FileFormat.Slides.csproj
+++ b/FileFormat.Slides/FileFormat.Slides.csproj
@@ -5,9 +5,14 @@
True
+
+