package com.xenoage.zong.musiclayout.notation;
import com.xenoage.utils.annotations.Optimized;
import com.xenoage.zong.core.music.Pitch;
import com.xenoage.zong.core.music.chord.Chord;
import com.xenoage.zong.core.music.chord.StemDirection;
import com.xenoage.zong.core.position.MP;
import com.xenoage.zong.musiclayout.SLP;
import com.xenoage.zong.musiclayout.notation.chord.AccidentalsNotation;
import com.xenoage.zong.musiclayout.notation.chord.ArticulationsNotation;
import com.xenoage.zong.musiclayout.notation.chord.NotesNotation;
import com.xenoage.zong.musiclayout.notation.chord.StemNotation;
import com.xenoage.zong.musiclayout.spacing.ElementWidth;
import lombok.AllArgsConstructor;
import lombok.Getter;
import static com.xenoage.utils.collections.ArrayUtils.getFirst;
import static com.xenoage.utils.collections.ArrayUtils.getLast;
import static com.xenoage.utils.collections.CollectionUtils.getFirst;
import static com.xenoage.utils.collections.CollectionUtils.getLast;
import static com.xenoage.zong.core.music.chord.StemDirection.Up;
import static com.xenoage.zong.musiclayout.SLP.slp;
/**
* This class contains layout information about a chord, like its width and the
* alignment of the notes, dots, accidentals and articulations.
*
* @author Andreas Wenger
*/
@AllArgsConstructor
public class ChordNotation
implements Notation {
@Getter public Chord element;
/** The {@link MP}, stored for performance reasons. */
@Getter @Optimized(Optimized.Reason.Performance) public MP mp;
@Getter public ElementWidth width;
public int staff;
public NotesNotation notes;
public StemDirection stemDirection = StemDirection.Default;
public StemNotation stem;
public AccidentalsNotation accidentals;
public ArticulationsNotation articulations;
public ChordNotation(Chord element) {
this.element = element;
this.mp = element.getMP();
}
public ChordNotation(Chord element, ElementWidth width) {
this.element = element;
this.mp = element.getMP();
this.width = width;
}
public float getStemOffsetXIs() {
return accidentals.widthIs + notes.stemOffsetIs; //TODO: right?
}
/**
* Gets the {@link SLP} of the outermost note at the stem side.
* For upward stems, this is the highest note, and for
* downward stems or if there is no stem, this is the lowest note.
*/
public SLP getStemSideNoteSlp() {
return slp(staff, getStemSideNoteLp());
}
/**
* Gets the LP of the outermost note at the stem side.
* For upward stems, this is the highest note, and for
* downward stems or if there is no stem, this is the lowest note.
*/
public int getStemSideNoteLp() {
return (stemDirection == Up ? getLast(notes.notes) : getFirst(notes.notes)).lp;
}
/**
* Gets the pitch of the outermost note at the stem side.
* For upward stems, this is the highest note, and for
* downward stems or if there is no stem, this is the lowest note.
*/
public Pitch getStemSideNotePitch() {
return (stemDirection == Up ? getLast(element.getNotes()) : getFirst(element.getNotes())).getPitch();
}
public SLP getStemEndSlp() {
return stem.endSlp;
}
}