private void doMoveSlides(int index, List <SlideInfo> sortedSlides)
        {
            int actualInsertIndex = index;

            foreach (SlideInfo slideInfo in sortedSlides)
            {
                if (slideInfo.Index <= index && actualInsertIndex > 0)
                {
                    --actualInsertIndex;
                }
                slideshow.removeSlide(slideInfo.Slide);
                if (SlideRemoved != null)
                {
                    SlideRemoved.Invoke(slideInfo.Slide);
                }

                slideshow.insertSlide(actualInsertIndex, slideInfo.Slide);
                if (SlideAdded != null)
                {
                    SlideAdded.Invoke(slideInfo.Slide, actualInsertIndex);
                }
                ++actualInsertIndex;
            }
            if (SlideSelected != null)
            {
                Slide primarySelection = lastEditSlide;
                if (primarySelection == null)
                {
                    //Double check the last edit slide if the user moved a slide without actually clicking and releasing that slide will be null,
                    //in this case use the slide that was moved.
                    primarySelection = sortedSlides[0].Slide;
                }
                SlideSelected.Invoke(primarySelection, secondarySlideSelections(sortedSlides, primarySelection));
            }
        }
        public void moveSlides(IEnumerable <Slide> slides, int index)
        {
            List <SlideInfo> sortedSlides = new List <SlideInfo>(from slide in slides select new SlideInfo(slide, slideshow.indexOf(slide)));

            sortedSlides.Sort(SlideInfo.Sort);

            bool wasAllowingUndo = allowUndoCreation;

            allowUndoCreation = false;
            doMoveSlides(index, sortedSlides);
            allowUndoCreation = wasAllowingUndo;

            if (allowUndoCreation)
            {
                undoBuffer.pushAndSkip(new TwoWayDelegateCommand(
                                           new TwoWayDelegateCommand.Funcs()
                {
                    ExecuteFunc = () =>     //Execute
                    {
                        allowUndoCreation = false;
                        doMoveSlides(index, sortedSlides);
                        allowUndoCreation = true;
                    },
                    UndoFunc = () =>     //Undo
                    {
                        allowUndoCreation = false;
                        foreach (SlideInfo info in sortedSlides)
                        {
                            int formerIndex = slideshow.indexOf(info.Slide);
                            slideshow.removeAt(formerIndex);
                            if (SlideRemoved != null)
                            {
                                SlideRemoved.Invoke(info.Slide);
                            }
                        }
                        //Can't think of how to do this without two loops, have to compensate for other things
                        //that need to be undone or else this won't put things back, two loops makes sure
                        //all items are removed and we can just insert back to original indices.
                        foreach (SlideInfo info in sortedSlides)
                        {
                            slideshow.insertSlide(info.Index, info.Slide);
                            if (SlideAdded != null)
                            {
                                SlideAdded.Invoke(info.Slide, info.Index);
                            }
                        }
                        if (SlideSelected != null)
                        {
                            SlideSelected.Invoke(lastEditSlide, secondarySlideSelections(sortedSlides, lastEditSlide));
                        }
                        allowUndoCreation = true;
                    }
                }));
            }
        }
        public void addSlide(Slide slide, int index = -1)
        {
            if (index == -1)
            {
                slideshow.addSlide(slide);
            }
            else
            {
                slideshow.insertSlide(index, slide);
            }

            if (!editorController.ResourceProvider.exists(slide.UniqueName))
            {
                editorController.ResourceProvider.createDirectory("", slide.UniqueName);
            }

            if (SlideAdded != null)
            {
                SlideAdded.Invoke(slide, index);
            }

            //Delay this till the next frame, so the rml has actually been rendererd
            ThreadManager.invoke(new Action(delegate()
            {
                if (slideEditorContext != null)
                {
                    slideEditorContext.updateThumbnail();
                }
            }));

            if (allowUndoCreation)
            {
                if (lastEditSlide == null)
                {
                    undoBuffer.pushAndSkip(new TwoWayDelegateCommand <SlideInfo>(new SlideInfo(slide, slideshow.indexOf(slide)),
                                                                                 new TwoWayDelegateCommand <SlideInfo> .Funcs()
                    {
                        ExecuteFunc = (executeSlide) =>
                        {
                            allowUndoCreation = false;
                            addSlide(executeSlide.Slide, executeSlide.Index);
                            allowUndoCreation = true;
                        },
                        UndoFunc = (undoSlide) =>
                        {
                            allowUndoCreation = false;
                            removeSlide(undoSlide.Slide);
                            allowUndoCreation = true;
                        },
                        TrimmedFunc = cleanupThumbnail,
                    }
                                                                                 ));
                }
                else
                {
                    undoBuffer.pushAndSkip(new TwoWayDelegateCommand <RemoveSlideInfo>(new RemoveSlideInfo(slide, index, lastEditSlide),
                                                                                       new TwoWayDelegateCommand <RemoveSlideInfo> .Funcs()
                    {
                        ExecuteFunc = (executeSlide) =>
                        {
                            //Hacky, but we cannot modify the active slide without messing up the classes that triggered this.
                            ThreadManager.invoke(new Action(delegate()
                            {
                                allowUndoCreation = false;
                                addSlide(executeSlide.Slide, executeSlide.Index);
                                if (SlideSelected != null)
                                {
                                    SlideSelected.Invoke(executeSlide.Slide, IEnumerableUtil <Slide> .EmptyIterator);
                                }
                                allowUndoCreation = true;
                            }));
                        },
                        UndoFunc = (undoSlide) =>
                        {
                            //Hacky, but we cannot modify the active slide without messing up the classes that triggered this.
                            ThreadManager.invoke(new Action(delegate()
                            {
                                allowUndoCreation = false;
                                if (SlideSelected != null)
                                {
                                    SlideSelected.Invoke(undoSlide.ChangeToSlide, IEnumerableUtil <Slide> .EmptyIterator);
                                }
                                removeSlide(undoSlide.Slide);
                                allowUndoCreation = true;
                            }));
                        },
                        TrimmedFunc = cleanupThumbnail
                    }));
                }
            }

            bool wasAllowingUndo = allowUndoCreation;

            allowUndoCreation = false;
            if (SlideSelected != null)
            {
                SlideSelected.Invoke(slide, IEnumerableUtil <Slide> .EmptyIterator);
            }
            allowUndoCreation = wasAllowingUndo;
        }
        public void removeSlides(IEnumerable <Slide> slides, Slide primarySelection)
        {
            int slideIndex = slideshow.indexOf(primarySelection);
            List <SlideInfo> removedSlides = new List <SlideInfo>(from slide in slides select new SlideInfo(slide, slideshow.indexOf(slide)));

            if (removedSlides.Count > 0)
            {
                removedSlides.Sort(SlideInfo.Sort);

                doRemoveSlides(removedSlides);

                Slide changeToSlide = null;
                if (primarySelection == lastEditSlide)
                {
                    if (slideIndex < slideshow.Count)
                    {
                        changeToSlide = slideshow.get(slideIndex);
                    }
                    else if (slideIndex - 1 >= 0)
                    {
                        changeToSlide = slideshow.get(slideIndex - 1);
                    }
                }

                bool wasAllowingUndo = allowUndoCreation;
                allowUndoCreation = false;
                if (changeToSlide != null && SlideSelected != null)
                {
                    SlideSelected.Invoke(changeToSlide, IEnumerableUtil <Slide> .EmptyIterator);
                }
                allowUndoCreation = wasAllowingUndo;

                if (allowUndoCreation)
                {
                    undoBuffer.pushAndSkip(new TwoWayDelegateCommand(
                                               new TwoWayDelegateCommand.Funcs()
                    {
                        ExecuteFunc = () =>     //Execute
                        {
                            ThreadManager.invoke(new Action(() =>
                            {
                                allowUndoCreation = false;
                                doRemoveSlides(removedSlides);
                                if (changeToSlide != null && SlideSelected != null)
                                {
                                    SlideSelected.Invoke(changeToSlide, IEnumerableUtil <Slide> .EmptyIterator);
                                }
                                allowUndoCreation = true;
                            }));
                        },
                        UndoFunc = () =>     //Undo
                        {
                            ThreadManager.invoke(new Action(() =>
                            {
                                allowUndoCreation = false;
                                foreach (SlideInfo slide in removedSlides)
                                {
                                    slideshow.insertSlide(slide.Index, slide.Slide);
                                    if (SlideAdded != null)
                                    {
                                        SlideAdded.Invoke(slide.Slide, slide.Index);
                                    }
                                }
                                if (SlideSelected != null)
                                {
                                    SlideSelected.Invoke(primarySelection, secondarySlideSelections(removedSlides, primarySelection));
                                }
                                allowUndoCreation = true;
                            }));
                        },
                        PoppedFrontFunc = () =>
                        {
                            foreach (SlideInfo slideInfo in removedSlides)
                            {
                                cleanupThumbnail(slideInfo);
                            }
                        }
                    }));
                }
            }
        }