//----------------------------------------------------------------------------// // // // B a s i c C o m p o s i t i o n // // // //----------------------------------------------------------------------------// // <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.glyph.facets; import omr.check.Result; import omr.check.SuccessResult; import omr.glyph.Shape; import omr.lag.Section; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import omr.sheet.SystemInfo; import java.awt.Point; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; /** * Class {@code BasicComposition} implements the composition facet of * a glyph made of sections (and possibly of other sub-glyphs). * These member sections may belong to different lags. * * @author Hervé Bitteur */ class BasicComposition extends BasicFacet implements GlyphComposition { /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger(BasicComposition.class); /** * Sections that compose this glyph. * The collection is kept sorted on natural Section order (abscissa then * ordinate, even with mixed section orientations). */ private final SortedSet<Section> members = new TreeSet<>(); /** Unmodifiable view on members */ private final SortedSet<Section> unmodifiableMembers = Collections.unmodifiableSortedSet(members); /** Link to the compound, if any, this one is a part of */ private Glyph partOf; /** Result of analysis wrt this glyph */ private Result result; //------------------// // BasicComposition // //------------------// /** * Create a new BasicComposition object. * * @param glyph our glyph */ public BasicComposition (Glyph glyph) { super(glyph); } //------------// // addSection // //------------// @Override public void addSection (Section section, Linking link) { if (section == null) { throw new IllegalArgumentException("Cannot add a null section"); } // if (!glyph.isTransient()) { // logger.error("Adding section to registered glyph"); // } // Nota: We must include the section in the glyph members before // linking back the section to the containing glyph. // Otherwise, there is a risk of using the glyph box (which depends on // its member sections) before the section is in the glyph members. // This phenomenum was sometimes observed when using parallelism. /** First, update glyph data */ members.add(section); /** Second, update section data, if so desired */ if (link == Linking.LINK_BACK) { section.setGlyph(glyph); } glyph.invalidateCache(); } //-------------// // addSections // //-------------// public void addSections (Glyph other, Linking linkSections) { // Update glyph info in other sections for (Section section : other.getMembers()) { addSection(section, linkSections); } } //-----------------// // containsSection // //-----------------// @Override public boolean containsSection (int id) { for (Section section : glyph.getMembers()) { if (section.getId() == id) { return true; } } return false; } //-------------// // cutSections // //-------------// @Override public void cutSections () { for (Section section : glyph.getMembers()) { if (section.getGlyph() == glyph) { section.setGlyph(null); } } } //--------// // dumpOf // //--------// @Override public String dumpOf () { StringBuilder sb = new StringBuilder(); sb.append(String.format(" members=%s%n", members)); if (partOf != null) { sb.append(String.format(" partOf=%s%n", partOf)); } if (result != null) { sb.append(String.format(" result=%s%n", result)); } return sb.toString(); } //----------------// // getAlienSystem // //----------------// @Override public SystemInfo getAlienSystem (SystemInfo system) { // Direct members for (Section section : glyph.getMembers()) { if (section.getSystem() != system) { return section.getSystem(); } } // No other system found return null; } //-------------// // getAncestor // //-------------// @Override public Glyph getAncestor () { Glyph g = this.glyph; while (g.getPartOf() != null) { g = g.getPartOf(); } return g; } //-----------------// // getFirstSection // //-----------------// @Override public Section getFirstSection () { return glyph.getMembers().first(); } //------------// // getMembers // //------------// @Override public SortedSet<Section> getMembers () { return unmodifiableMembers; } //-----------// // getPartOf // //-----------// @Override public Glyph getPartOf () { return partOf; } //-----------// // getResult // //-----------// @Override public Result getResult () { return result; } //----------// // isActive // //----------// @Override public boolean isActive () { if (glyph.getShape() == Shape.GLYPH_PART) { return false; } for (Section section : glyph.getMembers()) { if (section.getGlyph() != glyph) { return false; } } return true; } //--------------// // isSuccessful // //--------------// @Override public boolean isSuccessful () { return result instanceof SuccessResult; } //-----------------// // linkAllSections // //-----------------// @Override public void linkAllSections () { for (Section section : glyph.getMembers()) { section.setGlyph(glyph); } } //---------------// // removeSection // //---------------// @Override public boolean removeSection (Section section, Linking link) { if (link == Linking.LINK_BACK) { section.setGlyph(null); } boolean bool = members.remove(section); glyph.invalidateCache(); return bool; } //-----------// // setPartOf // //-----------// @Override public void setPartOf (Glyph compound) { partOf = compound; } //-----------// // setResult // //-----------// @Override public void setResult (Result result) { this.result = result; } //---------------// // stealSections // //---------------// @Override public void stealSections (Glyph that) { for (Section section : that.getMembers()) { addSection(section, Linking.LINK_BACK); } that.setPartOf(glyph); } //-----------// // translate // //-----------// /** * Apply the provided translation vector to all composing sections. * * @param vector the provided translation vector */ public void translate (Point vector) { for (Section section : glyph.getMembers()) { section.translate(vector); } } }