//----------------------------------------------------------------------------// // // // S y s t e m N o d e // // // //----------------------------------------------------------------------------// // <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.glyph.facets.Glyph; import omr.math.GeoUtil; import omr.score.visitor.ScoreVisitor; import omr.util.Navigable; import omr.util.TreeNode; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.util.Collection; import java.util.Collections; /** * Class {@code SystemNode} is an abstract class that is subclassed * for any Node that is contained in a system, beginning by the system * itself. * So this class encapsulates a direct link to the enclosing system. * * @author Hervé Bitteur */ public abstract class SystemNode extends PageNode { //~ Enumerations ----------------------------------------------------------- /** Relative vertical position with respect to the staves of the system * or part at hand */ public enum StaffPosition { //~ Enumeration constant initializers ---------------------------------- /** Above the first real staff of this entity */ ABOVE_STAVES, /** Somewhere * within the staves of this entity (system or part) */ WITHIN_STAVES, /** Below the last staff of * this entity */ BELOW_STAVES; } //~ Instance fields -------------------------------------------------------- /** Containing system */ @Navigable(false) private final ScoreSystem system; /** Bounding box of this entity, WRT system top-left corner */ private Rectangle box; /** Location of the center of this entity, WRT system top-left corner */ protected Point center; //~ Constructors ----------------------------------------------------------- //------------// // SystemNode // //------------// /** * Create a SystemNode * * @param container the (direct) container of the node */ public SystemNode (PageNode container) { super(container); // Set the system link for (TreeNode c = this; c != null; c = c.getParent()) { if (c instanceof ScoreSystem) { system = (ScoreSystem) c; return; } } system = null; } //~ Methods ---------------------------------------------------------------- //--------// // accept // //--------// @Override public boolean accept (ScoreVisitor visitor) { return visitor.visit(this); } //----------// // addError // //----------// /** * Register a system-based error in the ErrorsWindow * * @param text the error message */ public void addError (String text) { addError(null, text); } //----------// // addError // //----------// /** * Register a system-based error in the ErrorsWindow, with the * related glyph * * @param glyph the related glyph * @param text the error message */ public void addError (Glyph glyph, String text) { if ((getPage() != null) && (getPage() .getSheet() != null)) { getPage() .getSheet() .addError(this, glyph, text); } } //--------------------// // computeGlyphCenter // //--------------------// /** * Compute the bounding center of a glyph * * @param glyph the glyph * @return the glyph center */ public Point computeGlyphCenter (Glyph glyph) { return computeGlyphsCenter(Collections.singleton(glyph)); } //--------// // getBox // //--------// /** * Report a copy of the bounding box of the entity. * * @return the box */ public Rectangle getBox () { if (box == null) { computeBox(); } if (box != null) { return (Rectangle) box.clone(); } else { return null; } } //-----------// // getCenter // //-----------// /** * Report a copy of the center of this entity. * * @return the center point */ public Point getCenter () { if (center == null) { computeCenter(); } if (center != null) { return (Point) center.clone(); } else { return null; } } //------------------// // getContextString // //------------------// @Override public String getContextString () { StringBuilder sb = new StringBuilder(super.getContextString()); sb.append("S") .append(system.getId()); return sb.toString(); } //--------------// // getDimension // //--------------// /** * Report the dimension of the entity * * @return the entity dimension */ public Dimension getDimension () { if (box == null) { computeBox(); } if (box != null) { return new Dimension(box.width, box.height); } else { return null; } } //-----------// // getSystem // //-----------// /** * Report the containing system * * @return the containing system */ public ScoreSystem getSystem () { return system; } //------------// // computeBox // //------------// /** * Compute the bounding box of this entity. * Unless overridden, this method raises an exception. */ protected void computeBox () { throw new RuntimeException( "computeBox() not implemented in " + getClass().getName()); } //---------------// // computeCenter // //---------------// /** * Compute the center of this entity. */ protected void computeCenter () { Rectangle theBox = getBox(); if (theBox != null) { setCenter(GeoUtil.centerOf(theBox)); } else { setCenter(null); } } //------------------// // computeGlyphsBox // //------------------// /** * Compute the bounding box of a collection of glyphs * * @param glyphs the collection of glyph components * @return the bounding box */ protected Rectangle computeGlyphsBox (Collection<? extends Glyph> glyphs) { if ((glyphs == null) || (getSystem() == null)) { return null; } Rectangle pixRect = null; for (Glyph glyph : glyphs) { if (pixRect == null) { pixRect = glyph.getBounds(); } else { pixRect = pixRect.union(glyph.getBounds()); } } return pixRect; } //---------------------// // computeGlyphsCenter // //---------------------// /** * Compute the bounding center of a collection of glyphs * * @param glyphs the collection of glyph components * @return the area center */ protected Point computeGlyphsCenter (Collection<? extends Glyph> glyphs) { if (glyphs == null) { return null; } Rectangle glyphsBox = computeGlyphsBox(glyphs); if (glyphsBox == null) { return null; } return new Point( glyphsBox.x + (glyphsBox.width / 2), glyphsBox.y + (glyphsBox.height / 2)); } //-------// // reset // //-------// /** * Invalidate cached data */ protected void reset () { box = null; center = null; } //--------// // setBox // //--------// /** * Assign the bounding box * * @param box the bounding box */ protected void setBox (Rectangle box) { this.box = box; } //-----------// // setCenter // //-----------// /** * Remember the center of this system node * * @param center the system-based center of the system node */ protected void setCenter (Point center) { this.center = center; } }