package com.xenoage.zong.commands.core.music;
import com.xenoage.utils.annotations.Untested;
import com.xenoage.utils.document.command.Command;
import com.xenoage.utils.document.command.Undoability;
import com.xenoage.zong.commands.core.music.beam.BeamRemove;
import com.xenoage.zong.commands.core.music.slur.SlurRemove;
import com.xenoage.zong.commands.core.music.tuplet.TupletRemove;
import com.xenoage.zong.core.music.Voice;
import com.xenoage.zong.core.music.VoiceElement;
import com.xenoage.zong.core.music.beam.Beam;
import com.xenoage.zong.core.music.chord.Chord;
import com.xenoage.zong.core.music.slur.Slur;
import com.xenoage.zong.core.music.tuplet.Tuplet;
import java.util.ArrayList;
import java.util.List;
import static com.xenoage.utils.iterators.ReverseIterator.reverseIt;
import static com.xenoage.utils.kernel.Range.rangeReverse;
/**
* Removes the given {@link VoiceElement}.
*
* All {@link Slur}s, the {@link Beam} and the {@link Tuplet} belonging to this element
* are removed, too.
*
* @author Andreas Wenger
*/
@Untested public class VoiceElementRemove
implements Command {
//data
private VoiceElement element;
//backup data
private int elementIndex = 0;
private List<Command> backupCmds = null;
public VoiceElementRemove(VoiceElement element) {
this.element = element;
}
@Override public void execute() {
Voice voice = element.getParent();
if (voice == null)
throw new IllegalStateException("element is not part of a voice");
//remove slurs, beam and tuplet, if it is a chord
if (element instanceof Chord) {
Chord chord = (Chord) element;
//remove slurs
for (int i : rangeReverse(chord.getSlurs()))
executeAndRemember(new SlurRemove(chord.getSlurs().get(i)));
//remove beam
if (chord.getBeam() != null)
executeAndRemember(new BeamRemove(chord.getBeam()));
//remove tuplet
if (chord.getTuplet() != null)
executeAndRemember(new TupletRemove(chord.getTuplet()));
}
//remove element, and remember its position
elementIndex = voice.removeElement(element);
}
@Override public Undoability getUndoability() {
return Undoability.Undoable;
}
@Override public void undo() {
Voice voice = element.getParent();
//add element
voice.addElement(elementIndex, element);
//restore slurs, beam and tuplet
if (backupCmds != null) {
for (Command cmd : reverseIt(backupCmds))
cmd.undo();
}
}
private void executeAndRemember(Command cmd) {
if (backupCmds == null)
backupCmds = new ArrayList<>();
cmd.execute();
backupCmds.add(cmd);
}
}