package com.xenoage.zong.core.util; import static com.xenoage.zong.core.position.MP.atBeat; import static com.xenoage.zong.core.position.MP.atMeasure; import static com.xenoage.zong.core.position.MP.mp0; import static com.xenoage.zong.core.position.MP.unknown; import static com.xenoage.zong.core.position.MP.unknownMp; import java.util.Iterator; import java.util.NoSuchElementException; import lombok.Getter; import com.xenoage.zong.core.Score; import com.xenoage.zong.core.music.MeasureElement; import com.xenoage.zong.core.music.util.BeatEList; import com.xenoage.zong.core.position.MP; /** * An iterator over all {@link MeasureElement}s in a score. * * Iterates over the staves, measures and its measure elements. * The elements within a measure may be unsorted by beat. * * @author Andreas Wenger */ public class MeasureElementIterator implements Iterator<MeasureElement>, Iterable<MeasureElement> { private final Score score; @Getter private MP mp = unknownMp; private BeatEList<MeasureElement> elements; private int nextElementIndex = 0; private MP nextMp = mp0; public MeasureElementIterator(Score score) { this.score = score; elements = score.getMeasure(nextMp).getMeasureElements(); findNext(); } @Override public boolean hasNext() { return nextMp != null; } @Override public MeasureElement next() { if (!hasNext()) throw new NoSuchElementException(); mp = nextMp; MeasureElement element = elements.getElements().get(nextElementIndex).element; nextElementIndex++; findNext(); return element; } private void findNext() { while (true) { if (nextElementIndex < elements.size()) { //next element within measure exists nextMp = atBeat(nextMp.staff, nextMp.measure, unknown, elements.getElements().get(nextElementIndex).beat); break; } else { nextElementIndex = 0; if (nextMp.measure + 1 < score.getMeasuresCount()) { //next measure within staff nextMp = atMeasure(nextMp.staff, nextMp.measure + 1); } else if (nextMp.staff + 1 < score.getStavesCount()) { //next staff nextMp = atMeasure(nextMp.staff + 1, 0); } else { //finished nextMp = null; break; } elements = score.getMeasure(nextMp).getMeasureElements(); } } } @Override public Iterator<MeasureElement> iterator() { return this; } @Override public void remove() { throw new UnsupportedOperationException(); } }