//----------------------------------------------------------------------------// // // // M e a s u r e E l e m e n t // // // //----------------------------------------------------------------------------// // <editor-fold defaultstate="collapsed" desc="hdr"> // // Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. // // This software is released under the GNU General Public License. // // Goto http://kenai.com/projects/audiveris to report bugs or suggestions. // //----------------------------------------------------------------------------// // </editor-fold> package omr.score.entity; import omr.constant.ConstantSet; import omr.glyph.Glyphs; import omr.glyph.Shape; import omr.glyph.facets.Glyph; import omr.sheet.Scale; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.Point; import java.awt.geom.Line2D; import java.util.Collections; import java.util.List; /** * Class {@code MeasureElement} is the basis for measure elements * (directions, notations, etc.) * * <p>For some elements (such as wedge, dashes, pedal, slur, tuplet), we may * have two "events": the starting event and the stopping event. * Both will trigger the creation of a MeasureElement instance, the difference * being made by the "start" boolean. * * @author Hervé Bitteur */ public abstract class MeasureElement extends MeasureNode { //~ Static fields/initializers --------------------------------------------- /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger( MeasureElement.class); /** Specific application parameters */ private static final Constants constants = new Constants(); //~ Instance fields -------------------------------------------------------- /** The precise shape */ private Shape shape; /** Is this a start (rather than a stop) */ private final boolean start; /** Related chord if any (in containing measure) */ private final Chord chord; //~ Constructors ----------------------------------------------------------- /** * Creates a new instance * * @param measure the containing measure * @param start is this a starting element (of a two-piece entity) * @param referencePoint the reference location within the system * @param chord the related chord, if any * @param glyph the underlying glyph */ public MeasureElement (Measure measure, boolean start, Point referencePoint, Chord chord, Glyph glyph) { super(measure); if (glyph != null) { addGlyph(glyph); } this.start = start; setReferencePoint(referencePoint); this.chord = chord; } //~ Methods ---------------------------------------------------------------- //----------// // getChord // //----------// public Chord getChord () { return chord; } //----------// // getGlyph // //----------// public Glyph getGlyph () { return glyphs.first(); } //----------// // getShape // //----------// public Shape getShape () { if (shape == null) { shape = computeShape(); } return shape; } //---------------------// // getTranslationLinks // //---------------------// @Override public List<Line2D> getTranslationLinks (Glyph glyph) { if (chord != null) { return chord.getTranslationLinks(glyph); } else { return Collections.emptyList(); } } //---------// // isStart // //---------// public boolean isStart () { return start; } //----------// // toString // //----------// @Override public String toString () { StringBuilder sb = new StringBuilder(); // Actual element class name String name = getClass() .getName(); int period = name.lastIndexOf('.'); sb.append("{") .append((period != -1) ? name.substring(period + 1) : name); try { // Shape sb.append(" ") .append(getShape()); // Start ? if (!isStart()) { sb.append("/stop"); } // Point sb.append(" ref[x=") .append(getReferencePoint().x) .append(",y=") .append(getReferencePoint().y) .append("]"); // Box sb.append(" box[x=") .append(getBox().x) .append(",y=") .append(getBox().y) .append(",w=") .append(getBox().width) .append(",h=") .append(getBox().height) .append("]"); // Glyphs sb.append(" ") .append(Glyphs.toString(glyphs)); // Chord sb.append(" ") .append(chord.getContextString()) .append(" ") .append(chord); } catch (NullPointerException e) { sb.append(" INVALID"); } sb.append(internalsString()) .append("}"); return sb.toString(); } //--------------// // computeShape // //--------------// protected Shape computeShape () { return getGlyph() .getShape(); } //-----------// // findChord // //-----------// protected static Chord findChord (Measure measure, Point point) { // Shift on abscissa (because of left side of note heads) int dx = measure.getSystem() .getScale() .toPixels(constants.slotShift); return measure.getEventChord(new Point(point.x + dx, point.y)); } //-----------------// // internalsString // //-----------------// /** * Return the string of the internals of this class, for inclusion in a * toString * * @return the string of internals */ protected String internalsString () { return ""; } //-------// // reset // //-------// @Override protected void reset () { super.reset(); shape = null; setReferencePoint(null); } //~ Inner Classes ---------------------------------------------------------- //-----------// // Constants // //-----------// private static final class Constants extends ConstantSet { //~ Instance fields ---------------------------------------------------- /** Abscissa shift when looking for time slot (half a note head) */ Scale.Fraction slotShift = new Scale.Fraction( 0.5, "Abscissa shift when looking for time slot " + "(half a note head)"); } }