package com.xenoage.zong.musiclayout.stamper;
import static com.xenoage.utils.collections.CollectionUtils.alist;
import static com.xenoage.utils.collections.CollectionUtils.getFirst;
import static com.xenoage.utils.kernel.Range.range;
import static com.xenoage.zong.core.music.format.SP.sp;
import static com.xenoage.zong.core.text.FormattedText.fText;
import java.util.List;
import com.xenoage.zong.core.Score;
import com.xenoage.zong.core.format.MeasureNumbering;
import com.xenoage.zong.core.header.ColumnHeader;
import com.xenoage.zong.core.music.barline.Barline;
import com.xenoage.zong.core.music.barline.BarlineStyle;
import com.xenoage.zong.core.music.group.BarlineGroup;
import com.xenoage.zong.core.music.util.BeatE;
import com.xenoage.zong.core.text.Alignment;
import com.xenoage.zong.core.text.FormattedText;
import com.xenoage.zong.core.text.FormattedTextStyle;
import com.xenoage.zong.musiclayout.spacing.SystemSpacing;
import com.xenoage.zong.musiclayout.stampings.BarlineStamping;
import com.xenoage.zong.musiclayout.stampings.StaffStamping;
import com.xenoage.zong.musiclayout.stampings.StaffTextStamping;
import com.xenoage.zong.musiclayout.stampings.Stamping;
/**
* Creates the {@link BarlineStamping}s and bar number stampings
* for a given system.
*
* @author Andreas Wenger
*/
public class BarlinesStamper {
public static final BarlinesStamper barlinesStamper = new BarlinesStamper();
public List<Stamping> stamp(SystemSpacing system, List<StaffStamping> systemStaves, Score score) {
List<Stamping> ret = alist();
StaffStamping firstStaff = getFirst(systemStaves);
int stavesCount = systemStaves.size();
int systemIndex = system.getSystemIndexInFrame();
float xOffset = firstStaff.positionMm.x;
//common barline at the beginning, when system has at least one measure
if (system.columns.size() > 0) {
ret.add(new BarlineStamping(Barline.barlineRegular(), systemStaves, xOffset,
BarlineGroup.Style.Common));
}
//barlines within the system and measure numbers
for (int iMeasure : range(system.columns)) {
float xLeft = xOffset;
//measure numbering
MeasureNumbering measureNumbering = score.getFormat().getMeasureNumbering();
int globalMeasureIndex = system.getStartMeasure() + iMeasure;
boolean showMeasureNumber = false;
if (measureNumbering == MeasureNumbering.System) {
//measure number at the beginning of each system (except the first one)
showMeasureNumber = (iMeasure == 0 && globalMeasureIndex > 0);
}
else if (measureNumbering == MeasureNumbering.Measure) {
//measure number at each measure (except the first one)
showMeasureNumber = (globalMeasureIndex > 0);
}
if (showMeasureNumber) {
FormattedText text = fText("" + (globalMeasureIndex + 1),
new FormattedTextStyle(8), Alignment.Left);
ret.add(new StaffTextStamping(text, sp(xLeft, firstStaff.linesCount * 2),
firstStaff, null));
}
//for the first measure in the system: begin after leading spacing
if (iMeasure == 0)
xLeft += system.columns.get(iMeasure).getLeadingWidthMm();
xOffset += system.columns.get(iMeasure).getWidthMm();
float xRight = xOffset;
//regard the groups of the score
for (int iStaff : range(stavesCount)) {
ColumnHeader columnHeader = score.getColumnHeader(globalMeasureIndex);
BarlineGroup.Style barlineGroupStyle = BarlineGroup.Style.Single;
BarlineGroup group = score.getStavesList().getBarlineGroupByStaff(iStaff);
if (group != null)
barlineGroupStyle = group.getStyle();
List<StaffStamping> groupStaves = getBarlineGroupStaves(systemStaves, group);
//start barline
Barline startBarline = columnHeader.getStartBarline();
if (startBarline != null) {
//don't draw a regular barline at the left side of first measure of a system
if ((startBarline.getStyle() == BarlineStyle.Regular && systemIndex == 0) == false)
ret.add(new BarlineStamping(startBarline, groupStaves, xLeft,
barlineGroupStyle));
}
//end barline. if none is set, use a regular one.
Barline endBarline = columnHeader.getEndBarline();
if (endBarline == null)
endBarline = Barline.barlineRegular();
ret.add(new BarlineStamping(endBarline, groupStaves, xRight, barlineGroupStyle));
//middle barlines
for (BeatE<Barline> middleBarline : columnHeader.getMiddleBarlines()) {
ret.add(new BarlineStamping(middleBarline.element, groupStaves, xLeft +
system.columns.get(iMeasure).getBarlineOffsetMm(middleBarline.beat),
barlineGroupStyle));
}
//go to next group
if (group != null)
iStaff = group.getStaves().getStop();
}
}
return ret;
}
/**
* Gets the staves of the given group, using the given list of all staves.
* If the given group is null, all staves are returned.
*/
private List<StaffStamping> getBarlineGroupStaves(List<StaffStamping> systemStaves,
BarlineGroup barlineGroup) {
if (barlineGroup == null)
return systemStaves;
else {
//use efficient sublist
return systemStaves.subList(barlineGroup.getStaves().getStart(),
barlineGroup.getStaves().getStop() + 1);
}
}
}