package com.xenoage.zong.core.util; import static com.xenoage.zong.core.position.MP.atBeat; import static com.xenoage.zong.core.position.MP.unknown; import static com.xenoage.zong.core.position.MP.unknownBeat; import static com.xenoage.zong.core.position.MP.unknownMp; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import lombok.Getter; import com.xenoage.utils.math.Fraction; import com.xenoage.zong.core.Score; import com.xenoage.zong.core.music.ColumnElement; import com.xenoage.zong.core.music.util.BeatE; import com.xenoage.zong.core.music.util.BeatEList; import com.xenoage.zong.core.position.MP; /** * An iterator over all {@link ColumnElement}s in a score. * * The elements within a column may be unsorted by beat, but * first the elements with known beats are returned, then * the elements without beats. * * @author Andreas Wenger */ public class ColumnElementIterator implements Iterator<ColumnElement>, Iterable<ColumnElement> { private final Score score; @Getter private MP mp = unknownMp; private BeatEList<ColumnElement> elementsWithBeats; private List<ColumnElement> elementsWithoutBeats; private int nextList = 0; private int nextElement = 0; private int nextMeasure = 0; public ColumnElementIterator(Score score) { this.score = score; getNextLists(); findNext(); } @Override public boolean hasNext() { return nextMeasure != -1; } @Override public ColumnElement next() { if (!hasNext()) throw new NoSuchElementException(); ColumnElement element; Fraction beat = unknownBeat; if (nextList == 0) { BeatE<ColumnElement> e = elementsWithBeats.getElements().get(nextElement); element = e.element; beat = e.beat; } else { element = elementsWithoutBeats.get(nextElement); } mp = atBeat(unknown, nextMeasure, unknown, beat); nextElement += 1; findNext(); return element; } private void findNext() { while (true) { if (nextList == 0) { //current list is with beats if (nextElement < elementsWithBeats.size()) { //next element with beat exists break; } else { //go to next list nextList += 1; nextElement = 0; } } else if (nextList == 1 && nextElement < elementsWithoutBeats.size()) { //next element without beat exists break; } else if (nextMeasure + 1 < score.getMeasuresCount()) { //next measure column nextMeasure += 1; nextList = 0; nextElement = 0; getNextLists(); } else { //finished nextMeasure = -1; break; } } } private void getNextLists() { elementsWithBeats = score.getColumnHeader(nextMeasure).getColumnElementsWithBeats(); elementsWithoutBeats = score.getColumnHeader(nextMeasure).getColumnElementsWithoutBeats(); } @Override public Iterator<ColumnElement> iterator() { return this; } @Override public void remove() { throw new UnsupportedOperationException(); } }