123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
- import {BoundingBox} from "./BoundingBox";
- import {Fraction} from "../../Common/DataObjects/Fraction";
- import {VerticalGraphicalStaffEntryContainer} from "./VerticalGraphicalStaffEntryContainer";
- import {Note} from "../VoiceData/Note";
- import {Slur} from "../VoiceData/Expressions/ContinuousExpressions/Slur";
- import {Voice} from "../VoiceData/Voice";
- import {VoiceEntry} from "../VoiceData/VoiceEntry";
- import {GraphicalTie} from "./GraphicalTie";
- import {GraphicalObject} from "./GraphicalObject";
- import {GraphicalMeasure} from "./GraphicalMeasure";
- import {GraphicalNote} from "./GraphicalNote";
- import {GraphicalChordSymbolContainer} from "./GraphicalChordSymbolContainer";
- import {GraphicalLyricEntry} from "./GraphicalLyricEntry";
- import {AbstractGraphicalInstruction} from "./AbstractGraphicalInstruction";
- import {GraphicalStaffEntryLink} from "./GraphicalStaffEntryLink";
- import {CollectionUtil} from "../../Util/CollectionUtil";
- import { GraphicalVoiceEntry } from "./GraphicalVoiceEntry";
- import { MusicSheetCalculator } from "./MusicSheetCalculator";
- /**
- * The graphical counterpart of a [[SourceStaffEntry]].
- */
- export abstract class GraphicalStaffEntry extends GraphicalObject {
- constructor(parentMeasure: GraphicalMeasure, sourceStaffEntry: SourceStaffEntry = undefined, staffEntryParent: GraphicalStaffEntry = undefined) {
- super();
- this.parentMeasure = parentMeasure;
- this.graphicalVoiceEntries = [];
- this.sourceStaffEntry = sourceStaffEntry;
- if (staffEntryParent !== undefined) {
- this.staffEntryParent = staffEntryParent;
- this.parentVerticalContainer = staffEntryParent.parentVerticalContainer;
- this.PositionAndShape = new BoundingBox(this, staffEntryParent.PositionAndShape);
- } else {
- this.PositionAndShape = new BoundingBox(this, parentMeasure.PositionAndShape);
- }
- if (sourceStaffEntry !== undefined) {
- this.relInMeasureTimestamp = sourceStaffEntry.Timestamp;
- }
- }
- public graphicalChordContainer: GraphicalChordSymbolContainer;
- public graphicalLink: GraphicalStaffEntryLink;
- // Extra member needed, as tie notes have no direct source entry with the right time stamp.
- public relInMeasureTimestamp: Fraction;
- public sourceStaffEntry: SourceStaffEntry;
- public parentMeasure: GraphicalMeasure;
- public graphicalVoiceEntries: GraphicalVoiceEntry[];
- public staffEntryParent: GraphicalStaffEntry;
- public parentVerticalContainer: VerticalGraphicalStaffEntryContainer;
- private graphicalInstructions: AbstractGraphicalInstruction[] = [];
- private graphicalTies: GraphicalTie[] = [];
- private lyricsEntries: GraphicalLyricEntry[] = [];
- public get GraphicalInstructions(): AbstractGraphicalInstruction[] {
- return this.graphicalInstructions;
- }
- public get GraphicalTies(): GraphicalTie[] {
- return this.graphicalTies;
- }
- public get LyricsEntries(): GraphicalLyricEntry[] {
- return this.lyricsEntries;
- }
- public set LyricsEntries(value: GraphicalLyricEntry[]) {
- this.lyricsEntries = value;
- }
- /**
- * Calculate the absolute Timestamp.
- * @returns {Fraction}
- */
- public getAbsoluteTimestamp(): Fraction {
- const result: Fraction = this.parentMeasure.parentSourceMeasure.AbsoluteTimestamp.clone();
- if (this.relInMeasureTimestamp !== undefined) {
- result.Add(this.relInMeasureTimestamp);
- }
- return result;
- }
- /**
- * Search through all the GraphicalNotes to find the suitable one for a TieEndNote.
- * @param tieNote
- * @returns {any}
- */
- public findEndTieGraphicalNoteFromNote(tieNote: Note): GraphicalNote {
- for (const gve of this.graphicalVoiceEntries) {
- for (const graphicalNote of gve.notes) {
- const note: Note = graphicalNote.sourceNote;
- if (!note.isRest()
- && note.Pitch.FundamentalNote === tieNote.Pitch.FundamentalNote
- && note.Pitch.Octave === tieNote.Pitch.Octave
- && note.getAbsoluteTimestamp().Equals(tieNote.getAbsoluteTimestamp())) {
- return graphicalNote;
- }
- }
- }
- return undefined;
- }
- /**
- * Search through all [[GraphicalNote]]s to find the suitable one for an StartSlurNote (that 's also an EndTieNote).
- * @param tieNote
- * @param slur
- * @returns {any}
- */
- public findEndTieGraphicalNoteFromNoteWithStartingSlur(tieNote: Note, slur: Slur): GraphicalNote {
- if (tieNote === undefined) {
- return undefined;
- }
- for (const gve of this.graphicalVoiceEntries) {
- if (gve.parentVoiceEntry !== tieNote.ParentVoiceEntry) {
- continue;
- }
- for (const graphicalNote of gve.notes) {
- const note: Note = graphicalNote.sourceNote;
- if (note.NoteTie !== undefined && note.NoteSlurs.indexOf(slur) !== -1) {
- return graphicalNote;
- }
- }
- }
- return undefined;
- }
- public findGraphicalNoteFromGraceNote(graceNote: Note): GraphicalNote {
- if (graceNote === undefined) {
- return undefined;
- }
- for (const gve of this.graphicalVoiceEntries) {
- if (gve.parentVoiceEntry !== graceNote.ParentVoiceEntry) {
- continue;
- }
- for (const graphicalNote of gve.notes) {
- if (graphicalNote.sourceNote === graceNote) {
- return graphicalNote;
- }
- }
- }
- return undefined;
- }
- public findGraphicalNoteFromNote(note: Note): GraphicalNote {
- if (note === undefined) {
- return undefined;
- }
- for (const gve of this.graphicalVoiceEntries) {
- if (gve.parentVoiceEntry !== note.ParentVoiceEntry) {
- continue;
- }
- for (const graphicalNote of gve.notes) {
- if (graphicalNote.sourceNote === note && this.getAbsoluteTimestamp().Equals(note.getAbsoluteTimestamp())) {
- return graphicalNote;
- }
- }
- }
- return undefined;
- }
- public getGraphicalNoteDurationFromVoice(voice: Voice): Fraction {
- for (const gve of this.graphicalVoiceEntries) {
- if (gve.parentVoiceEntry.ParentVoice !== voice) {
- continue;
- }
- return gve.notes[0].graphicalNoteLength;
- }
- return new Fraction(0, 1);
- }
- /**
- * Find the [[StaffEntry]]'s [[GraphicalNote]]s that correspond to the given [[VoiceEntry]]'s [[Note]]s.
- * @param voiceEntry
- * @returns {any}
- */
- public findVoiceEntryGraphicalNotes(voiceEntry: VoiceEntry): GraphicalNote[] {
- for (const gve of this.graphicalVoiceEntries) {
- if (gve.parentVoiceEntry === voiceEntry) {
- return gve.notes;
- }
- }
- return undefined;
- }
- /**
- * Check if the given [[VoiceEntry]] is part of the [[StaffEntry]]'s Linked [[VoiceEntry]].
- * @param voiceEntry
- * @returns {boolean}
- */
- public isVoiceEntryPartOfLinkedVoiceEntry(voiceEntry: VoiceEntry): boolean {
- if (this.sourceStaffEntry.Link !== undefined) {
- for (let idx: number = 0, len: number = this.sourceStaffEntry.Link.LinkStaffEntries.length; idx < len; ++idx) {
- const sEntry: SourceStaffEntry = this.sourceStaffEntry.Link.LinkStaffEntries[idx];
- if (sEntry.VoiceEntries.indexOf(voiceEntry) !== -1 && sEntry !== this.sourceStaffEntry) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * Return the [[StaffEntry]]'s Minimum NoteLength.
- * @returns {Fraction}
- */
- public findStaffEntryMinNoteLength(): Fraction {
- let minLength: Fraction = new Fraction(Number.MAX_VALUE, 1);
- for (const gve of this.graphicalVoiceEntries) {
- for (const graphicalNote of gve.notes) {
- const calNoteLen: Fraction = graphicalNote.graphicalNoteLength;
- if (calNoteLen.lt(minLength) && calNoteLen.GetExpandedNumerator() > 0) {
- minLength = calNoteLen;
- }
- }
- }
- return minLength;
- }
- public findStaffEntryMaxNoteLength(): Fraction {
- let maxLength: Fraction = new Fraction(0, 1);
- for (const gve of this.graphicalVoiceEntries) {
- for (const graphicalNote of gve.notes) {
- const calNoteLen: Fraction = graphicalNote.graphicalNoteLength;
- if (maxLength.lt(calNoteLen) && calNoteLen.GetExpandedNumerator() > 0) {
- maxLength = calNoteLen;
- }
- }
- }
- return maxLength;
- }
- /**
- * Find or creates the list of [[GraphicalNote]]s in case of a [[VoiceEntry]] (not from TiedNote).
- * @param voiceEntry
- * @returns {GraphicalNote[]}
- */
- public findOrCreateGraphicalVoiceEntry(voiceEntry: VoiceEntry): GraphicalVoiceEntry {
- for (const gve of this.graphicalVoiceEntries) {
- if (gve.parentVoiceEntry === voiceEntry) {
- return gve;
- }
- }
- // if not found in list, create new one and add to list:
- const graphicalVoiceEntry: GraphicalVoiceEntry = MusicSheetCalculator.symbolFactory.createVoiceEntry(voiceEntry, this);
- this.graphicalVoiceEntries.push(graphicalVoiceEntry);
- return graphicalVoiceEntry;
- }
- /**
- * Find or creates the list of [[GraphicalNote]]s in case of a TiedNote.
- * @param graphicalNote
- * @returns {GraphicalNote[]}
- */
- public findOrCreateGraphicalVoiceEntryFromGraphicalNote(graphicalNote: GraphicalNote): GraphicalVoiceEntry {
- for (const gve of this.graphicalVoiceEntries) {
- if (gve === graphicalNote.parentVoiceEntry) {
- return gve;
- }
- }
- // if not found in list, create new one and add to list:
- const graphicalVoiceEntry: GraphicalVoiceEntry = MusicSheetCalculator.symbolFactory.createVoiceEntry(graphicalNote.sourceNote.ParentVoiceEntry, this);
- this.graphicalVoiceEntries.push(graphicalVoiceEntry);
- return graphicalVoiceEntry;
- }
- /**
- * Insert the [[GraphicalNote]] to the correct index of the [[GraphicalNote]]s list,
- * so that the order of the [[GraphicalNote]]'s in the list corresponds to the [[VoiceEntry]]'s [[Note]]s order.
- * (needed when adding Tie-EndNotes).
- * @param graphicalNotes
- * @param graphicalNote
- */
- public addGraphicalNoteToListAtCorrectYPosition(gve: GraphicalVoiceEntry, graphicalNote: GraphicalNote): void {
- const graphicalNotes: GraphicalNote[] = gve.notes;
- if (graphicalNotes.length === 0 ||
- graphicalNote.PositionAndShape.RelativePosition.y < CollectionUtil.last(graphicalNotes).PositionAndShape.RelativePosition.Y) {
- graphicalNotes.push(graphicalNote);
- } else {
- for (let i: number = graphicalNotes.length - 1; i >= 0; i--) {
- if (graphicalNotes[i].PositionAndShape.RelativePosition.y > graphicalNote.PositionAndShape.RelativePosition.y) {
- graphicalNotes.splice(i + 1, 0, graphicalNote);
- break;
- }
- if (i === 0) {
- graphicalNotes.splice(0, 0, graphicalNote);
- break;
- }
- }
- }
- }
- /**
- * Returns true if this staff entry has only rests
- */
- public hasOnlyRests(): boolean {
- const hasOnlyRests: boolean = true;
- for (const gve of this.graphicalVoiceEntries) {
- for (const graphicalNote of gve.notes) {
- const note: Note = graphicalNote.sourceNote;
- if (!note.isRest()) {
- return false;
- }
- }
- }
- return hasOnlyRests;
- }
- }
|