/** Return the previous dot for this Notehead, or null if this is the first one. * Don't set the anchor to the previous dot, because the anchor should * always be the Notehead. */ private AugmentationDot getPreviousDot() { if (_gotPreviousDot) { return(_previousDot); } // Search for the previous AugmentationDot before a Notehead _previousDot = null; for (int i = getIndex() - 1; i >= 0; --i) { MusicSymbol symbol = getParentTimeSlice().getMusicSymbol(i); if (symbol is Notehead) { break; } if (symbol is AugmentationDot) { _previousDot = (AugmentationDot)symbol; break; } } _gotPreviousDot = true; return(_previousDot); }
/** This is a utility function to return the screen X position of * a left-positioned symbol (as defined by isLeftPositioned()). * This finds the hotspot of the next symbol in the time slice * which isLeftPositioned() (or the hotspot of the time slice itself * if there are no more) and subtracts from its X value * the (measure width - 10) / (the measure symbol count - 1). */ protected int findLeftPositionedX() { FinalPoint nextHotspot = null; for (int i = getIndex() + 1; i < getParentTimeSlice().getMusicSymbolCount(); ++i) { MusicSymbol nextSymbol = getParentTimeSlice().getMusicSymbol(i); if (nextSymbol.isLeftPositionedSymbol()) { nextHotspot = nextSymbol.getScreenHotspot(); break; } } if (nextHotspot == null) { // No next left positioned symbol, so use the time slice nextHotspot = getParentTimeSlice().getScreenHotspot(); } MeasureStartTimeSlice measure = getParentTimeSlice().getParentMeasureStart(); // Note that we know measure.getSymbolCount() is at least one return(nextHotspot.x - (measure.getWidth() - 10) / (measure.getSymbolCount() - 1)); }
/** Return the number of noteheads which have been found for this * stem. * Even though this is private, we always use getNoteheadCount() instead of * looking at _noteheads directly, because this allows us to * delay computing it as long as possible. */ private int getNoteheadCount() { if (_noteheads == null) { // Set _noteheads to all noteheads belonging to this stem _noteheads = new List <Notehead>(); for (int i = getIndex() + 1; i < getParentTimeSlice().getMusicSymbolCount(); ++i) { MusicSymbol musicSymbol = getParentTimeSlice().getMusicSymbol(i); if (musicSymbol is Stem) { // We have started a new Stem break; } if (musicSymbol is Notehead) { _noteheads.Add((Notehead)musicSymbol); } } } return(_noteheads.Count); }
/** Return the previous instance of the given class type looking * backwards from this MusicSymbol at all previous MusicSymbols * in the same staff. * For example, previousInstanceOfInStaff(Notehead.class) gets the * previous Notehead in the staff. * * @param desiredClass Class object for the MusicSymbol being sought * @return the previous MusicSymbol of the desired class in the * same staff, or null if not found. */ public MusicSymbol previousInstanceOfInStaff(Type desiredClass) { MusicSymbol previous = previousInstanceOfInScore(desiredClass); // Check if this is the same staff if (getParentTimeSlice().getParentMeasureStart().getParentStaff() == previous.getParentTimeSlice().getParentMeasureStart().getParentStaff()) { return(previous); } // There was none in the same staff. return(null); }
/** This is a utility method which returns a list of nodes in this ID group for * objects of the same type. If there is no numberOfNodes tag * (which defines the first node in the multi-node symbol), this returns * a new empty Vector. If there is a numberOfNodes tag, this creates a new Vector * and adds the given number of nodes of the same type and with the * same ID tag, including this first node, and stops searching after that * number have been found. If this reaches the end of the Score before * the required number have been found, this also stops, and the returned * Vector will not be complete. If a subsequent node of * the same type and ID, which also has a numberOfNodes tag, is encountered * before the number of nodes are found, this does not add it and stops searching. */ protected IList <MusicSymbol> findMultiNodes() { var result = new List <MusicSymbol>(); if (_tags.numberOfNodes() == null) { // This is not a starting node. return(result); } if (_tags.id() == null) { // This shouldn't really happen, so just return null. return(result); } int numberOfNodes = _tags.numberOfNodes().Value; int id = _tags.id().Value; // Add this as the first one. result.Add(this); // Note that nextInstanceOfInScore(getClass()) only returns the same type for (MusicSymbol node = nextInstanceOfInScore(GetType()); node != null && result.Count < numberOfNodes; node = node.nextInstanceOfInScore(GetType())) { if (!node.getTags().id().HasValue || node.getTags().id().Value != id) { continue; } if (node.getTags().numberOfNodes() != null) { // Unexpectedly starting a new multi-node symbol. Just // return what we have so far. return(result); } result.Add(node); } return(result); }
/** Return the anchor as the previous Notehead. * Even though this is private, we always use getAnchor() instead of * looking at _anchor directly, because this allows us to * delay computing it as long as possible. */ private Anchored getAnchor() { if (_anchor != null) { return(_anchor); } MusicSymbol previousNotehead = previousInstanceOf(typeof(Notehead)); if (previousNotehead == null) { // DEBUG: maybe this should be an error _anchor = findDefaultAnchor(); } else { _anchor = previousNotehead; } return(_anchor); }
/** Return the anchor as the previous Notehead or Rest. * Even though this is private, we always use getAnchor() instead of * looking at _anchor directly, because this allows us to * delay computing it as long as possible. */ private Anchored getAnchor() { if (_anchor != null) { return(_anchor); } MusicSymbol previousNotehead = previousInstanceOf(typeof(Notehead)); MusicSymbol previousRest = previousInstanceOf(typeof(Rest)); if (previousNotehead == null && previousRest == null) { // DEBUG: maybe this should be an error _anchor = findDefaultAnchor(); } else if (previousRest == null) { // There is only a notehead _anchor = previousNotehead; } else if (previousNotehead == null) { // There is only a rest _anchor = previousRest; } else { // Use the most recent notehead or rest if (previousNotehead.getIndex() > previousRest.getIndex()) { _anchor = previousNotehead; } else { _anchor = previousRest; } } return(_anchor); }
/** This reads chunks from parentInput's input stream until the next * NIFF time slice or no more bytesRemaining in the input, * adding the chunks to the timeSlice's music symbol list. If a music * symbol is not recognized, this skips it. * This stops at either a measure start or an event time slice. * * @param parentInput the parent RIFF object being used to read the input stream * @param timeSlice the TimeSlice to which MusicSymbol objects are added. * @see MusicSymbol */ static public void addMusicSymbols(Riff parentInput, TimeSlice timeSlice) { while (parentInput.getBytesRemaining() > 0) { if (parentInput.peekFOURCC().Equals(RIFF_ID)) { // encoutered the next time slice, so quit // Note that this stops at either a measure start or an event time slice. return; } MusicSymbol musicSymbol = maybeNewAnyMusicSymbol(parentInput); if (musicSymbol != null) { timeSlice.addMusicSymbol(musicSymbol); } else { // Did not recognize the music symbol, so skip parentInput.skipChunk(); } } }
/** Add the given mysicSymbol to the MusicSymbol list. * This does not call invalidate(), but you may need to before displaying. * * @param mysicSymbol the MusicSymbol to add. It is an error if * this is already the child of an object. * @throws HeirarchyException if the mysicSymbol has already * been added as a child to another object. * @see #invalidate */ public void addMusicSymbol(MusicSymbol mysicSymbol) { addChild(mysicSymbol); }