package com.xenoage.zong.musiclayout.notator.chord.stem;
import static com.xenoage.utils.collections.CollectionUtils.map;
import static com.xenoage.utils.kernel.Range.range;
import static com.xenoage.zong.core.music.util.Interval.Before;
import static com.xenoage.zong.core.music.util.Interval.BeforeOrAt;
import static com.xenoage.zong.musiclayout.notator.chord.stem.beam.BeamedStemDirector.beamedStemDirector;
import static com.xenoage.zong.musiclayout.notator.chord.stem.single.SingleStemDirector.singleStemDirector;
import java.util.Map;
import com.xenoage.zong.core.Score;
import com.xenoage.zong.core.music.beam.Beam;
import com.xenoage.zong.core.music.chord.Chord;
import com.xenoage.zong.core.music.chord.StemDirection;
import com.xenoage.zong.core.position.MP;
/**
* Computes the {@link StemDirection} of chords.
*
* @author Andreas Wenger
*/
public final class StemDirector {
public static StemDirector stemDirector = new StemDirector();
/**
* Computes the {@link StemDirection} of the given chord (and maybe connected
* ones) and returns them. The chord must be part of a score.
*/
public Map<Chord, StemDirection> compute(Chord chord) {
Map<Chord, StemDirection> ret = map();
Beam beam = chord.getBeam();
Score score = chord.getScore();
if (beam != null) {
//compute stem directions for all chords of the beam
StemDirection[] beamedStems = beamedStemDirector.compute(beam, score);
for (int iChord : range(beam.size()))
ret.put(beam.getChord(iChord), beamedStems[iChord]);
}
else {
//compute stem direction for single chord
MP mp = MP.getMP(chord);
StemDirection stem = singleStemDirector.compute(chord,
score.getMusicContext(mp, BeforeOrAt, Before));
ret.put(chord, stem);
}
//TODO: add another strategy for measures with two voices. we had one already,
//but it was bad and outdated, so we removed it.
return ret;
}
}