/// <summary> /// Removes a specified slide from this part (can be undone). /// </summary> /// <param name="slide"></param> public void RemoveSlide(SongSlide slide) { if (slide == null) { throw new ArgumentNullException("slide"); } if (Slides.Count <= 1) { throw new InvalidOperationException("Can't remove last slide in a part."); } int i = Slides.IndexOf(slide); if (i < 0) { throw new InvalidOperationException("Slide is not in this part."); } Undo.ChangeFactory.OnChanging(this, () => { slides.Insert(i, slide); }, () => { slides.Remove(slide); }, "RemoveSlide"); slides.Remove(slide); }
/// <summary> /// Splits a slide at a specified index. The first part remains in the original slide /// and the rest is moved to a new slide (can be undone). /// </summary> /// <param name="slide">The slide to split.</param> /// <param name="splitIndex">The index to split at.</param> /// <returns>A new slide containing the rest of the text after the split index.</returns> public SongSlide SplitSlide(SongSlide slide, int splitIndex) { SongSlide newSlide; using (Undo.ChangeFactory.Batch(this, "SplitSlide")) { var textBefore = slide.Text.Substring(0, splitIndex); if (textBefore.EndsWith("\r\n")) { textBefore = textBefore.Substring(0, textBefore.Length - 2); } else if (textBefore.EndsWith("\n")) { textBefore = textBefore.Substring(0, textBefore.Length - 1); } var textAfter = slide.Text.Substring(splitIndex); if (textAfter.StartsWith("\r\n")) { textAfter = textAfter.Substring(2); } else if (textAfter.StartsWith("\n")) { textAfter = textAfter.Substring(1); } newSlide = DuplicateSlide(slide); slide.Text = textBefore; newSlide.Text = textAfter; } return(newSlide); }
/// <summary> /// Adds an existing slide to this part (can be undone). /// </summary> /// <param name="slide">The slide to add.</param> public void AddSlide(SongSlide slide) { Undo.ChangeFactory.OnChanging(this, () => { slides.Remove(slide); }, () => { slides.Add(slide); }, "AddSlide"); slides.Add(slide); }
/// <summary> /// Adds an empty slide to the part (can be undone). /// </summary> /// <returns>The newly created slide.</returns> public SongSlide AddSlide() { SongSlide slide; slide = new SongSlide(Root); AddSlide(slide); return(slide); }
/// <summary> /// Copies this slide. /// </summary> /// <returns>A copy of this slide.</returns> public SongSlide Copy() { var s = new SongSlide(Root); s.Text = Text; s.Translation = Translation; s.BackgroundIndex = BackgroundIndex; s.Size = Size; return(s); }
/// <summary> /// Moves a slide to another part (can be undone). /// </summary> /// <param name="slide">The slide to move.</param> /// <param name="target">The target part.</param> public void MoveSlide(SongSlide slide, SongPart target) { var part = FindPartWithSlide(slide); using (Undo.ChangeFactory.Batch(this, "MoveSlide")) { part.RemoveSlide(slide); target.AddSlide(slide); } }
/// <summary> /// Copies the specified slide into a given part. /// The copy will be appended to the part's slide list /// (can be undone). /// </summary> /// <param name="slide">The slide to copy.</param> /// <param name="target">The part where the copy will be inserted.</param> /// <returns>The copy.</returns> public SongSlide CopySlide(SongSlide slide, SongPart target) { SongSlide s; var part = FindPartWithSlide(slide); using (Undo.ChangeFactory.Batch(this, "CopySlide")) { s = slide.Copy(); target.AddSlide(s); } return(s); }
/// <summary> /// Copies a slide and inserts it after another slide (can be undone). /// </summary> /// <param name="slide">The slide to copy</param> /// <param name="target">The slide after which the copy will be inserted.</param> /// <returns>The copy.</returns> public SongSlide CopySlideAfter(SongSlide slide, SongSlide target) { SongSlide s; var part = FindPartWithSlide(slide); var targetPart = FindPartWithSlide(target); using (Undo.ChangeFactory.Batch(this, "CopySlideAfter")) { s = slide.Copy(); targetPart.InsertSlideAfter(s, target); } return(s); }
public void PartAddSlideExistingUndoRedo() { var slide = new SongSlide(song) { Text = "NewSlide" }; ClearUndoRedoStack(); part.AddSlide(slide); Assert.Equal(2, part.Slides.Count); Assert.Equal(1, UndoStackSize); Undo(); Assert.Equal(1, part.Slides.Count); Assert.Equal("SimpleLine", part.Slides[0].Text); Redo(); Assert.Equal(2, part.Slides.Count); Assert.Equal("NewSlide", part.Slides[1].Text); }
/// <summary> /// Moves a slide to the position directly after another slide (can be undone). /// </summary> /// <param name="slide">The slide to move.</param> /// <param name="target">The target slide.</param> public void MoveSlideAfter(SongSlide slide, SongSlide target) { if (slide == target) { return; } var part = FindPartWithSlide(slide); var targetPart = FindPartWithSlide(target); using (Undo.ChangeFactory.Batch(this, "MoveSlide")) { part.RemoveSlide(slide); targetPart.InsertSlideAfter(slide, target); } }
/// <summary> /// Duplicates the specified part and inserts the copy /// directly after the original slide in the same part (can be undone). /// </summary> /// <param name="slide">The slide to duplicate.</param> /// <returns>The created duplicate.</returns> public SongSlide DuplicateSlide(SongSlide slide) { SongSlide s; int i = Slides.IndexOf(slide); using (Undo.ChangeFactory.Batch(this, "DuplicateSlide")) { s = slide.Copy(); Undo.ChangeFactory.OnChanging(this, () => { slides.Remove(s); }, () => { slides.Insert(i + 1, s); }, "DuplicateSlide"); slides.Insert(i + 1, s); } return(s); }
/// <summary> /// Inserts a slide after a specified target slide in this part (can be undone). /// </summary> /// <param name="slide">The slide to insert.</param> /// <param name="target">The target slide. Must be contained in this part.</param> public void InsertSlideAfter(SongSlide slide, SongSlide target) { var index = Slides.IndexOf(target); if (index < 0) { throw new InvalidOperationException("Slide is not in this part."); } if (index >= Slides.Count - 1) { AddSlide(slide); } else { Undo.ChangeFactory.OnChanging(this, () => { slides.Remove(slide); }, () => { slides.Insert(index + 1, slide); }, "InsertSlideAfter"); slides.Insert(index + 1, slide); } }
public void PartRemoveSlideDisconnected() { var slide1 = new SongSlide(song); Assert.Throws<InvalidOperationException>(() => part.RemoveSlide(slide1)); }
/// <summary> /// Removes a specified slide from this part (can be undone). /// </summary> /// <param name="slide"></param> public void RemoveSlide(SongSlide slide) { if (slide == null) throw new ArgumentNullException("slide"); if (Slides.Count <= 1) throw new InvalidOperationException("Can't remove last slide in a part."); int i = Slides.IndexOf(slide); if (i < 0) throw new InvalidOperationException("Slide is not in this part."); Undo.ChangeFactory.OnChanging(this, () => { slides.Insert(i, slide); }, () => { slides.Remove(slide); }, "RemoveSlide"); slides.Remove(slide); }
/// <summary> /// Inserts a slide after a specified target slide in this part (can be undone). /// </summary> /// <param name="slide">The slide to insert.</param> /// <param name="target">The target slide. Must be contained in this part.</param> public void InsertSlideAfter(SongSlide slide, SongSlide target) { var index = Slides.IndexOf(target); if (index < 0) throw new InvalidOperationException("Slide is not in this part."); if (index >= Slides.Count - 1) { AddSlide(slide); } else { Undo.ChangeFactory.OnChanging(this, () => { slides.Remove(slide); }, () => { slides.Insert(index + 1, slide); }, "InsertSlideAfter"); slides.Insert(index + 1, slide); } }
public override void Init() { base.Init(); part = song.Parts.Single(); slide = part.Slides.Single(); }
/// <summary> /// Duplicates the specified part and inserts the copy /// directly after the original slide in the same part (can be undone). /// </summary> /// <param name="slide">The slide to duplicate.</param> /// <returns>The created duplicate.</returns> public SongSlide DuplicateSlide(SongSlide slide) { SongSlide s; int i = Slides.IndexOf(slide); using (Undo.ChangeFactory.Batch(this, "DuplicateSlide")) { s = slide.Copy(); Undo.ChangeFactory.OnChanging(this, () => { slides.Remove(s); }, () => { slides.Insert(i + 1, s); }, "DuplicateSlide"); slides.Insert(i + 1, s); } return s; }
/// <summary> /// Copies this slide. /// </summary> /// <returns>A copy of this slide.</returns> public SongSlide Copy() { var s = new SongSlide(Root); s.Text = Text; s.Translation = Translation; s.BackgroundIndex = BackgroundIndex; s.Size = Size; return s; }
/// <summary> /// Copies a slide and inserts it after another slide (can be undone). /// </summary> /// <param name="slide">The slide to copy</param> /// <param name="target">The slide after which the copy will be inserted.</param> /// <returns>The copy.</returns> public SongSlide CopySlideAfter(SongSlide slide, SongSlide target) { SongSlide s; var part = FindPartWithSlide(slide); var targetPart = FindPartWithSlide(target); using (Undo.ChangeFactory.Batch(this, "CopySlideAfter")) { s = slide.Copy(); targetPart.InsertSlideAfter(s, target); } return s; }
/// <summary> /// Moves a slide to the position directly after another slide (can be undone). /// </summary> /// <param name="slide">The slide to move.</param> /// <param name="target">The target slide.</param> public void MoveSlideAfter(SongSlide slide, SongSlide target) { if (slide == target) return; var part = FindPartWithSlide(slide); var targetPart = FindPartWithSlide(target); using (Undo.ChangeFactory.Batch(this, "MoveSlide")) { part.RemoveSlide(slide); targetPart.InsertSlideAfter(slide, target); } }
/// <summary> /// Splits a slide at a specified index. The first part remains in the original slide /// and the rest is moved to a new slide (can be undone). /// </summary> /// <param name="slide">The slide to split.</param> /// <param name="splitIndex">The index to split at.</param> /// <returns>A new slide containing the rest of the text after the split index.</returns> public SongSlide SplitSlide(SongSlide slide, int splitIndex) { SongSlide newSlide; using (Undo.ChangeFactory.Batch(this, "SplitSlide")) { var textBefore = slide.Text.Substring(0, splitIndex); if (textBefore.EndsWith("\r\n")) textBefore = textBefore.Substring(0, textBefore.Length - 2); else if (textBefore.EndsWith("\n")) textBefore = textBefore.Substring(0, textBefore.Length - 1); var textAfter = slide.Text.Substring(splitIndex); if (textAfter.StartsWith("\r\n")) textAfter = textAfter.Substring(2); else if (textAfter.StartsWith("\n")) textAfter = textAfter.Substring(1); newSlide = DuplicateSlide(slide); slide.Text = textBefore; newSlide.Text = textAfter; } return newSlide; }
/// <summary> /// Finds the part that contains a given slide. /// </summary> /// <param name="slide">The slide. Slide instances must always be unique in a song structure.</param> /// <returns>The part that contains the slide.</returns> public SongPart FindPartWithSlide(SongSlide slide) { return(Parts.Where(p => p.Slides.Contains(slide)).SingleOrDefault()); }
/// <summary> /// Copies the specified slide into a given part. /// The copy will be appended to the part's slide list /// (can be undone). /// </summary> /// <param name="slide">The slide to copy.</param> /// <param name="target">The part where the copy will be inserted.</param> /// <returns>The copy.</returns> public SongSlide CopySlide(SongSlide slide, SongPart target) { SongSlide s; var part = FindPartWithSlide(slide); using (Undo.ChangeFactory.Batch(this, "CopySlide")) { s = slide.Copy(); target.AddSlide(s); } return s; }
public void FindPartWithSlide() { var slide1 = new SongSlide(song); var slide2 = new SongSlide(song); song.AddPart(new SongPart(song, "NewPart1", new SongSlide[] { slide1 })); song.AddPart(new SongPart(song, "NewPart2", new SongSlide[] { slide2 })); Assert.Equal("NewPart2", song.FindPartWithSlide(slide2).Name); }
/// <summary> /// Finds the part that contains a given slide. /// </summary> /// <param name="slide">The slide. Slide instances must always be unique in a song structure.</param> /// <returns>The part that contains the slide.</returns> public SongPart FindPartWithSlide(SongSlide slide) { return Parts.Where(p => p.Slides.Contains(slide)).SingleOrDefault(); }
public void PartInsertSlideAfterUndoRedo() { var slide0 = part.Slides.Single(); var slide1 = new SongSlide(song); var slide2 = new SongSlide(song); part.AddSlide(slide1); ClearUndoRedoStack(); part.InsertSlideAfter(slide2, slide0); Assert.Equal(3, part.Slides.Count); Assert.Same(slide0, part.Slides[0]); Assert.Same(slide2, part.Slides[1]); Assert.Same(slide1, part.Slides[2]); Assert.Equal(1, UndoStackSize); Undo(); Assert.Equal(2, part.Slides.Count); Redo(); Assert.Equal(3, part.Slides.Count); }
public void ShowSlide(SongSlide slide) { if (slide == null) return; // slide might be null if the song has no parts var s = new { Text = slide.Text, Translation = slide.TranslationWithoutChords, // TODO: does the display controller need to know about chords in the translation? Size = slide.Size, Background = slide.Background, Source = showSource, Copyright = showCopyright }; control.ExecuteJavascript("presentation.showSlide(" + JsonConvert.SerializeObject(s) + ")"); }
/// <summary> /// Adds an empty slide to the part (can be undone). /// </summary> /// <returns>The newly created slide.</returns> public SongSlide AddSlide() { SongSlide slide; slide = new SongSlide(Root); AddSlide(slide); return slide; }
public void CopySlideUndoRedo() { var part0 = song.Parts.Single(); var slide = new SongSlide(song); var part1 = new SongPart(song, "NewPart", new SongSlide[] { slide }); song.AddPart(part1); ClearUndoRedoStack(); song.CopySlide(part0.Slides.Single(), part1); Assert.Equal(2, part1.Slides.Count); Assert.Equal("SimpleLine", part1.Slides[1].Text); Assert.Equal(1, UndoStackSize); Undo(); Assert.Same(slide, part1.Slides.Single()); Redo(); Assert.Equal(2, part1.Slides.Count); Assert.Equal(1, part0.Slides.Count); }
public void MoveSlideAfter() { var part1 = song.Parts.Single(); var slide0 = part1.Slides.Single(); var slide1 = part1.AddSlide(); var slide2 = new SongSlide(song); var part2 = new SongPart(song, "NewPart", new SongSlide[] { slide2 }); song.AddPart(part2); ClearUndoRedoStack(); song.MoveSlideAfter(slide0, slide2); Assert.Equal(1, part1.Slides.Count); Assert.Equal(2, part2.Slides.Count); Assert.Same(slide0, part2.Slides[1]); Assert.Equal(1, UndoStackSize); Undo(); Assert.Equal(2, part1.Slides.Count); Assert.Equal(1, part2.Slides.Count); }
public void PartInsertSlideAfter3() { var slide0 = part.Slides.Single(); var slide1 = new SongSlide(song); var slide2 = new SongSlide(song); ClearUndoRedoStack(); Assert.Throws<InvalidOperationException>(() => part.InsertSlideAfter(slide2, slide1)); }