소스 검색

Added VexFlowVoiceEntry which carries the vexFlow.StaveNote -> no need of two synced lists in measure (simpler code)

Matthias Uiberacker 7 년 전
부모
커밋
0ca9d0198e

+ 4 - 9
src/MusicalScore/Graphical/AccidentalCalculator.ts

@@ -1,25 +1,20 @@
-import {IGraphicalSymbolFactory} from "../Interfaces/IGraphicalSymbolFactory";
 import {AccidentalEnum} from "../../Common/DataObjects/Pitch";
 import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
 import {GraphicalNote} from "./GraphicalNote";
 import {Pitch} from "../../Common/DataObjects/Pitch";
 import {NoteEnum} from "../../Common/DataObjects/Pitch";
 import Dictionary from "typescript-collections/dist/lib/Dictionary";
+import { MusicSheetCalculator } from "./MusicSheetCalculator";
 
 /**
  * Compute the accidentals for notes according to the current key instruction
  */
 export class AccidentalCalculator {
-    private symbolFactory: IGraphicalSymbolFactory;
     private keySignatureNoteAlterationsDict: Dictionary<number, AccidentalEnum> = new Dictionary<number, AccidentalEnum>();
     private currentAlterationsComparedToKeyInstructionList: number[] = [];
     private currentInMeasureNoteAlterationsDict: Dictionary<number, AccidentalEnum> = new Dictionary<number, AccidentalEnum>();
     private activeKeyInstruction: KeyInstruction;
 
-    constructor(symbolFactory: IGraphicalSymbolFactory) {
-        this.symbolFactory = symbolFactory;
-    }
-
     public get ActiveKeyInstruction(): KeyInstruction {
         return this.activeKeyInstruction;
     }
@@ -77,7 +72,7 @@ export class AccidentalCalculator {
                 } else {
                     this.currentInMeasureNoteAlterationsDict.remove(pitchKey);
                 }
-                this.symbolFactory.addGraphicalAccidental(graphicalNote, pitch, grace, graceScalingFactor);
+                MusicSheetCalculator.symbolFactory.addGraphicalAccidental(graphicalNote, pitch, grace, graceScalingFactor);
             }
         } else {
             if (pitch.Accidental !== AccidentalEnum.NONE) {
@@ -85,11 +80,11 @@ export class AccidentalCalculator {
                     this.currentAlterationsComparedToKeyInstructionList.push(pitchKey);
                 }
                 this.currentInMeasureNoteAlterationsDict.setValue(pitchKey, pitch.Accidental);
-                this.symbolFactory.addGraphicalAccidental(graphicalNote, pitch, grace, graceScalingFactor);
+                MusicSheetCalculator.symbolFactory.addGraphicalAccidental(graphicalNote, pitch, grace, graceScalingFactor);
             } else {
                 if (isInCurrentAlterationsToKeyList) {
                     this.currentAlterationsComparedToKeyInstructionList.splice(this.currentAlterationsComparedToKeyInstructionList.indexOf(pitchKey), 1);
-                    this.symbolFactory.addGraphicalAccidental(graphicalNote, pitch, grace, graceScalingFactor);
+                    MusicSheetCalculator.symbolFactory.addGraphicalAccidental(graphicalNote, pitch, grace, graceScalingFactor);
                 }
             }
         }

+ 3 - 2
src/MusicalScore/Graphical/GraphicalStaffEntry.ts

@@ -16,6 +16,7 @@ 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]].
@@ -237,7 +238,7 @@ export abstract class GraphicalStaffEntry extends GraphicalObject {
             }
         }
         // if not found in list, create new one and add to list:
-        const graphicalVoiceEntry: GraphicalVoiceEntry = new GraphicalVoiceEntry(voiceEntry, this);
+        const graphicalVoiceEntry: GraphicalVoiceEntry = MusicSheetCalculator.symbolFactory.createVoiceEntry(voiceEntry, this);
         this.graphicalVoiceEntries.push(graphicalVoiceEntry);
 
         return graphicalVoiceEntry;
@@ -255,7 +256,7 @@ export abstract class GraphicalStaffEntry extends GraphicalObject {
             }
         }
         // if not found in list, create new one and add to list:
-        const graphicalVoiceEntry: GraphicalVoiceEntry = new GraphicalVoiceEntry(graphicalNote.sourceNote.ParentVoiceEntry, this);
+        const graphicalVoiceEntry: GraphicalVoiceEntry = MusicSheetCalculator.symbolFactory.createVoiceEntry(graphicalNote.sourceNote.ParentVoiceEntry, this);
         this.graphicalVoiceEntries.push(graphicalVoiceEntry);
 
         return graphicalVoiceEntry;

+ 24 - 24
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -60,6 +60,7 @@ import { GraphicalVoiceEntry } from "./GraphicalVoiceEntry";
  * Class used to do all the calculations in a MusicSheet, which in the end populates a GraphicalMusicSheet.
  */
 export abstract class MusicSheetCalculator {
+    public static symbolFactory: IGraphicalSymbolFactory;
     public static transposeCalculator: ITransposeCalculator;
     protected static textMeasurer: ITextMeasurer;
 
@@ -73,11 +74,7 @@ export abstract class MusicSheetCalculator {
 
     protected graphicalMusicSheet: GraphicalMusicSheet;
     protected rules: EngravingRules;
-    protected symbolFactory: IGraphicalSymbolFactory;
-
-    constructor(symbolFactory: IGraphicalSymbolFactory) {
-        this.symbolFactory = symbolFactory;
-    }
+    //protected symbolFactory: IGraphicalSymbolFactory;
 
     public static get TextMeasurer(): ITextMeasurer {
         return MusicSheetCalculator.textMeasurer;
@@ -656,7 +653,7 @@ export abstract class MusicSheetCalculator {
 
         // build the MusicSystems
         const musicSystemBuilder: MusicSystemBuilder = new MusicSystemBuilder();
-        musicSystemBuilder.initialize(this.graphicalMusicSheet, visibleMeasureList, numberOfStaffLines, this.symbolFactory);
+        musicSystemBuilder.initialize(this.graphicalMusicSheet, visibleMeasureList, numberOfStaffLines);
         musicSystemBuilder.buildMusicSystems();
 
         // check for Measures with only WholeRestNotes and correct their X-Position (middle of Measure)
@@ -938,9 +935,9 @@ export abstract class MusicSheetCalculator {
             }
             let graphicalNote: GraphicalNote;
             if (grace) {
-                graphicalNote = this.symbolFactory.createGraceNote(note, gve, activeClef, octaveShiftValue);
+                graphicalNote = MusicSheetCalculator.symbolFactory.createGraceNote(note, gve, activeClef, octaveShiftValue);
             } else {
-                graphicalNote = this.symbolFactory.createNote(note, gve, activeClef, octaveShiftValue, undefined);
+                graphicalNote = MusicSheetCalculator.symbolFactory.createNote(note, gve, activeClef, octaveShiftValue, undefined);
             }
             if (note.NoteTie !== undefined) {
                 MusicSheetCalculator.addTieToTieTimestampsDict(tieTimestampListDict, note);
@@ -983,7 +980,7 @@ export abstract class MusicSheetCalculator {
         if (graceEntries !== undefined) {
             for (let idx: number = 0, len: number = graceEntries.length; idx < len; ++idx) {
                 const graceVoiceEntry: VoiceEntry = graceEntries[idx];
-                const graceStaffEntry: GraphicalStaffEntry = this.symbolFactory.createGraceStaffEntry(
+                const graceStaffEntry: GraphicalStaffEntry = MusicSheetCalculator.symbolFactory.createGraceStaffEntry(
                     graphicalStaffEntry,
                     graphicalStaffEntry.parentMeasure
                 );
@@ -1041,8 +1038,8 @@ export abstract class MusicSheetCalculator {
                             graphicalStaffEntry.findOrCreateGraphicalVoiceEntry(openTie.Start.ParentVoiceEntry);
 
                         // GraphicalNote points to tieStartNote, but must get the correct Length (eg the correct Fraction of tieStartNote's Length)
-                        const tiedGraphicalNote: GraphicalNote = thisPointer.symbolFactory.createNote(openTie.Start, gve, activeClef,
-                                                                                                      octaveShiftValue, tieFraction);
+                        const tiedGraphicalNote: GraphicalNote = MusicSheetCalculator.symbolFactory.createNote( openTie.Start, gve, activeClef,
+                                                                                                                octaveShiftValue, tieFraction);
 
                         graphicalStaffEntry.addGraphicalNoteToListAtCorrectYPosition(gve, tiedGraphicalNote);
 
@@ -1052,7 +1049,7 @@ export abstract class MusicSheetCalculator {
                         const tieStartNote: Note = openTie.Start;
                         if (isLastTieNote && tieStartNote.ParentVoiceEntry.Articulations.length === 1 &&
                             tieStartNote.ParentVoiceEntry.Articulations[0] === ArticulationEnum.fermata) {
-                            thisPointer.symbolFactory.addFermataAtTiedEndNote(tieStartNote, graphicalStaffEntry);
+                                MusicSheetCalculator.symbolFactory.addFermataAtTiedEndNote(tieStartNote, graphicalStaffEntry);
                         }
                         openTie.NoteHasBeenCreated[k] = true;
                         if (openTie.allGraphicalNotesHaveBeenCreated()) {
@@ -1362,7 +1359,7 @@ export abstract class MusicSheetCalculator {
         const firstSourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.getFirstSourceMeasure();
         if (firstSourceMeasure !== undefined) {
             for (let i: number = 0; i < firstSourceMeasure.CompleteNumberOfStaves; i++) {
-                const accidentalCalculator: AccidentalCalculator = new AccidentalCalculator(this.symbolFactory);
+                const accidentalCalculator: AccidentalCalculator = new AccidentalCalculator();
                 accidentalCalculators.push(accidentalCalculator);
                 if (firstSourceMeasure.FirstInstructionsStaffEntries[i] !== undefined) {
                     for (let idx: number = 0, len: number = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions.length; idx < len; ++idx) {
@@ -1428,7 +1425,7 @@ export abstract class MusicSheetCalculator {
                                    openOctaveShifts: OctaveShiftParams[], openLyricWords: LyricWord[], staffIndex: number,
                                    staffEntryLinks: StaffEntryLink[]): StaffMeasure {
         const staff: Staff = this.graphicalMusicSheet.ParentMusicSheet.getStaffFromIndex(staffIndex);
-        const measure: StaffMeasure = this.symbolFactory.createStaffMeasure(sourceMeasure, staff);
+        const measure: StaffMeasure = MusicSheetCalculator.symbolFactory.createStaffMeasure(sourceMeasure, staff);
         measure.hasError = sourceMeasure.getErrorInMeasure(staffIndex);
         if (sourceMeasure.FirstInstructionsStaffEntries[staffIndex] !== undefined) {
             for (let idx: number = 0, len: number = sourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions.length; idx < len; ++idx) {
@@ -1465,7 +1462,7 @@ export abstract class MusicSheetCalculator {
                         activeClefs[staffIndex] = <ClefInstruction>abstractNotationInstruction;
                     }
                 }
-                const graphicalStaffEntry: GraphicalStaffEntry = this.symbolFactory.createStaffEntry(sourceStaffEntry, measure);
+                const graphicalStaffEntry: GraphicalStaffEntry = MusicSheetCalculator.symbolFactory.createStaffEntry(sourceStaffEntry, measure);
                 if (measure.staffEntries.length > entryIndex) {
                     measure.addGraphicalStaffEntryAtTimestamp(graphicalStaffEntry);
                 } else {
@@ -1507,11 +1504,14 @@ export abstract class MusicSheetCalculator {
                 }
                 if (sourceStaffEntry.Instructions.length > 0) {
                     const clefInstruction: ClefInstruction = <ClefInstruction>sourceStaffEntry.Instructions[0];
-                    this.symbolFactory.createInStaffClef(graphicalStaffEntry, clefInstruction);
+                    MusicSheetCalculator.symbolFactory.createInStaffClef(graphicalStaffEntry, clefInstruction);
                 }
                 if (sourceStaffEntry.ChordContainer !== undefined) {
                     sourceStaffEntry.ParentStaff.ParentInstrument.HasChordSymbols = true;
-                    this.symbolFactory.createChordSymbol(sourceStaffEntry, graphicalStaffEntry, this.graphicalMusicSheet.ParentMusicSheet.Transpose);
+                    MusicSheetCalculator.symbolFactory.createChordSymbol(
+                        sourceStaffEntry,
+                        graphicalStaffEntry,
+                        this.graphicalMusicSheet.ParentMusicSheet.Transpose);
                 }
             }
         }
@@ -1544,15 +1544,15 @@ export abstract class MusicSheetCalculator {
             const voiceEntry: VoiceEntry = new VoiceEntry(new Fraction(0, 1), staff.Voices[0], sourceStaffEntry);
             const note: Note = new Note(voiceEntry, sourceStaffEntry, Fraction.createFromFraction(sourceMeasure.Duration), undefined);
             voiceEntry.Notes.push(note);
-            const graphicalStaffEntry: GraphicalStaffEntry = this.symbolFactory.createStaffEntry(sourceStaffEntry, measure);
+            const graphicalStaffEntry: GraphicalStaffEntry = MusicSheetCalculator.symbolFactory.createStaffEntry(sourceStaffEntry, measure);
             measure.addGraphicalStaffEntry(graphicalStaffEntry);
             graphicalStaffEntry.relInMeasureTimestamp = voiceEntry.Timestamp;
-            const gve: GraphicalVoiceEntry = new GraphicalVoiceEntry(voiceEntry, graphicalStaffEntry);
+            const gve: GraphicalVoiceEntry = MusicSheetCalculator.symbolFactory.createVoiceEntry(voiceEntry, graphicalStaffEntry);
             graphicalStaffEntry.graphicalVoiceEntries.push(gve);
-            const graphicalNote: GraphicalNote = this.symbolFactory.createNote( note,
-                                                                                gve,
-                                                                                new ClefInstruction(),
-                                                                                OctaveEnum.NONE, undefined);
+            const graphicalNote: GraphicalNote = MusicSheetCalculator.symbolFactory.createNote( note,
+                                                                                                gve,
+                                                                                                new ClefInstruction(),
+                                                                                                OctaveEnum.NONE, undefined);
             gve.notes.push(graphicalNote);
         }
         return measure;
@@ -1584,7 +1584,7 @@ export abstract class MusicSheetCalculator {
     private createStaffEntryForTieNote(measure: StaffMeasure, absoluteTimestamp: Fraction, openTie: Tie): GraphicalStaffEntry {
         /* tslint:enable:no-unused-variable */
         let graphicalStaffEntry: GraphicalStaffEntry;
-        graphicalStaffEntry = this.symbolFactory.createStaffEntry(openTie.Start.ParentStaffEntry, measure);
+        graphicalStaffEntry = MusicSheetCalculator.symbolFactory.createStaffEntry(openTie.Start.ParentStaffEntry, measure);
         graphicalStaffEntry.relInMeasureTimestamp = Fraction.minus(absoluteTimestamp, measure.parentSourceMeasure.AbsoluteTimestamp);
         this.resetYPositionForLeadSheet(graphicalStaffEntry.PositionAndShape);
         measure.addGraphicalStaffEntryAtTimestamp(graphicalStaffEntry);

+ 4 - 8
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -16,7 +16,6 @@ import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
 import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
 import {SystemLinesEnum} from "./SystemLinesEnum";
 import {GraphicalMusicSheet} from "./GraphicalMusicSheet";
-import {IGraphicalSymbolFactory} from "../Interfaces/IGraphicalSymbolFactory";
 import {MusicSheetCalculator} from "./MusicSheetCalculator";
 import {MidiInstrument} from "../VoiceData/Instructions/ClefInstruction";
 import {CollectionUtil} from "../../Util/CollectionUtil";
@@ -41,16 +40,13 @@ export class MusicSystemBuilder {
     private activeClefs: ClefInstruction[];
     private globalSystemIndex: number = 0;
     private leadSheet: boolean = false;
-    private symbolFactory: IGraphicalSymbolFactory;
 
     public initialize(
-        graphicalMusicSheet: GraphicalMusicSheet, measureList: StaffMeasure[][], numberOfStaffLines: number, symbolFactory: IGraphicalSymbolFactory
-    ): void {
+        graphicalMusicSheet: GraphicalMusicSheet, measureList: StaffMeasure[][], numberOfStaffLines: number): void {
         this.leadSheet = graphicalMusicSheet.LeadSheet;
         this.graphicalMusicSheet = graphicalMusicSheet;
         this.rules = this.graphicalMusicSheet.ParentMusicSheet.rules;
         this.measureList = measureList;
-        this.symbolFactory = symbolFactory;
         this.currentMusicPage = this.createMusicPage();
         this.currentPageHeight = 0.0;
         this.numberOfVisibleStaffLines = numberOfStaffLines;
@@ -257,7 +253,7 @@ export class MusicSystemBuilder {
      * @returns {MusicSystem}
      */
     private initMusicSystem(): MusicSystem {
-        const musicSystem: MusicSystem = this.symbolFactory.createMusicSystem(this.currentMusicPage, this.globalSystemIndex++);
+        const musicSystem: MusicSystem = MusicSheetCalculator.symbolFactory.createMusicSystem(this.currentMusicPage, this.globalSystemIndex++);
         this.currentMusicPage.MusicSystems.push(musicSystem);
         return musicSystem;
     }
@@ -329,7 +325,7 @@ export class MusicSystemBuilder {
      */
     private addStaffLineToMusicSystem(musicSystem: MusicSystem, relativeYPosition: number, staff: Staff): void {
         if (musicSystem !== undefined) {
-            const staffLine: StaffLine = this.symbolFactory.createStaffLine(musicSystem, staff);
+            const staffLine: StaffLine = MusicSheetCalculator.symbolFactory.createStaffLine(musicSystem, staff);
             musicSystem.StaffLines.push(staffLine);
             const boundingBox: BoundingBox = staffLine.PositionAndShape;
             const relativePosition: PointF2D = new PointF2D();
@@ -613,7 +609,7 @@ export class MusicSystemBuilder {
     private addExtraInstructionMeasure(visStaffIdx: number, keyInstruction: KeyInstruction, rhythmInstruction: RhythmInstruction): number {
         const currentSystem: MusicSystem = this.currentSystemParams.currentSystem;
         const measures: StaffMeasure[] = [];
-        const measure: StaffMeasure = this.symbolFactory.createExtraStaffMeasure(currentSystem.StaffLines[visStaffIdx]);
+        const measure: StaffMeasure = MusicSheetCalculator.symbolFactory.createExtraStaffMeasure(currentSystem.StaffLines[visStaffIdx]);
         measures.push(measure);
         if (keyInstruction !== undefined) {
             measure.addKeyAtBegin(keyInstruction, this.activeKeys[visStaffIdx], this.activeClefs[visStaffIdx]);

+ 6 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowGraphicalSymbolFactory.ts

@@ -23,6 +23,8 @@ import {GraphicalLabel} from "../GraphicalLabel";
 import {EngravingRules} from "../EngravingRules";
 import { TechnicalInstruction } from "../../VoiceData/Instructions/TechnicalInstruction";
 import { GraphicalVoiceEntry } from "../GraphicalVoiceEntry";
+import { VoiceEntry } from "../../VoiceData/VoiceEntry";
+import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
 
 export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
     /**
@@ -87,6 +89,10 @@ export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
         return new VexFlowStaffEntry(<VexFlowMeasure>measure, undefined, <VexFlowStaffEntry>staffEntryParent);
     }
 
+    public createVoiceEntry(parentVoiceEntry: VoiceEntry, parentStaffEntry: GraphicalStaffEntry): GraphicalVoiceEntry {
+        return new VexFlowVoiceEntry(parentVoiceEntry, parentStaffEntry);
+    }
+
     /**
      * Create a Graphical Note for given note and clef and as part of graphicalStaffEntry.
      * @param note

+ 22 - 34
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -21,6 +21,7 @@ import { RepetitionInstructionEnum } from "../../VoiceData/Instructions/Repetiti
 import { SystemLinePosition } from "../SystemLinePosition";
 import { StemDirectionType } from "../../VoiceData/VoiceEntry";
 import { GraphicalVoiceEntry } from "../GraphicalVoiceEntry";
+import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
 
 export class VexFlowMeasure extends StaffMeasure {
     constructor(staff: Staff, staffLine: StaffLine = undefined, sourceMeasure: SourceMeasure = undefined) {
@@ -45,11 +46,11 @@ export class VexFlowMeasure extends StaffMeasure {
     // VexFlow StaveConnectors (vertical lines)
     private connectors: Vex.Flow.StaveConnector[] = [];
     // Intermediate object to construct beams
-    private beams: { [voiceID: number]: [Beam, VexFlowStaffEntry[]][]; } = {};
+    private beams: { [voiceID: number]: [Beam, VexFlowVoiceEntry[]][]; } = {};
     // VexFlow Beams
     private vfbeams: { [voiceID: number]: Vex.Flow.Beam[]; };
     // Intermediate object to construct tuplets
-    private tuplets: { [voiceID: number]: [Tuplet, VexFlowStaffEntry[]][]; } = {};
+    private tuplets: { [voiceID: number]: [Tuplet, VexFlowVoiceEntry[]][]; } = {};
     // VexFlow Tuplets
     private vftuplets: { [voiceID: number]: Vex.Flow.Tuplet[]; } = {};
 
@@ -275,18 +276,9 @@ export class VexFlowMeasure extends StaffMeasure {
      * (multiply the minimal positions with the scaling factor, considering the BeginInstructionsWidth)
      */
     public layoutSymbols(): void {
-        //this.stave.format();
+        // vexflow does the x-layout
     }
 
-    //public addGraphicalStaffEntry(entry: VexFlowStaffEntry): void {
-    //    super.addGraphicalStaffEntry(entry);
-    //}
-    //
-    //public addGraphicalStaffEntryAtTimestamp(entry: VexFlowStaffEntry): void {
-    //    super.addGraphicalStaffEntryAtTimestamp(entry);
-    //    // TODO
-    //}
-
     /**
      * Draw this measure on a VexFlow CanvasContext
      * @param ctx
@@ -349,11 +341,11 @@ export class VexFlowMeasure extends StaffMeasure {
      */
     public handleBeam(graphicalNote: GraphicalNote, beam: Beam): void {
         const voiceID: number = graphicalNote.sourceNote.ParentVoiceEntry.ParentVoice.VoiceId;
-        let beams: [Beam, VexFlowStaffEntry[]][] = this.beams[voiceID];
+        let beams: [Beam, VexFlowVoiceEntry[]][] = this.beams[voiceID];
         if (beams === undefined) {
             beams = this.beams[voiceID] = [];
         }
-        let data: [Beam, VexFlowStaffEntry[]];
+        let data: [Beam, VexFlowVoiceEntry[]];
         for (const mybeam of beams) {
             if (mybeam[0] === beam) {
                 data = mybeam;
@@ -363,7 +355,7 @@ export class VexFlowMeasure extends StaffMeasure {
             data = [beam, []];
             beams.push(data);
         }
-        const parent: VexFlowStaffEntry = graphicalNote.parentVoiceEntry.parentStaffEntry as VexFlowStaffEntry;
+        const parent: VexFlowVoiceEntry = graphicalNote.parentVoiceEntry as VexFlowVoiceEntry;
         if (data[1].indexOf(parent) < 0) {
             data[1].push(parent);
         }
@@ -372,11 +364,11 @@ export class VexFlowMeasure extends StaffMeasure {
     public handleTuplet(graphicalNote: GraphicalNote, tuplet: Tuplet): void {
         const voiceID: number = graphicalNote.sourceNote.ParentVoiceEntry.ParentVoice.VoiceId;
         tuplet = graphicalNote.sourceNote.NoteTuplet;
-        let tuplets: [Tuplet, VexFlowStaffEntry[]][] = this.tuplets[voiceID];
+        let tuplets: [Tuplet, VexFlowVoiceEntry[]][] = this.tuplets[voiceID];
         if (tuplets === undefined) {
             tuplets = this.tuplets[voiceID] = [];
         }
-        let currentTupletBuilder: [Tuplet, VexFlowStaffEntry[]];
+        let currentTupletBuilder: [Tuplet, VexFlowVoiceEntry[]];
         for (const t of tuplets) {
             if (t[0] === tuplet) {
                 currentTupletBuilder = t;
@@ -386,7 +378,7 @@ export class VexFlowMeasure extends StaffMeasure {
             currentTupletBuilder = [tuplet, []];
             tuplets.push(currentTupletBuilder);
         }
-        const parent: VexFlowStaffEntry = graphicalNote.parentVoiceEntry.parentStaffEntry as VexFlowStaffEntry;
+        const parent: VexFlowVoiceEntry = graphicalNote.parentVoiceEntry as VexFlowVoiceEntry;
         if (currentTupletBuilder[1].indexOf(parent) < 0) {
             currentTupletBuilder[1].push(parent);
         }
@@ -409,17 +401,17 @@ export class VexFlowMeasure extends StaffMeasure {
                 for (const beam of this.beams[voiceID]) {
                     const notes: Vex.Flow.StaveNote[] = [];
                     const psBeam: Beam = beam[0];
-                    const staffEntries: VexFlowStaffEntry[] = beam[1];
+                    const voiceEntries: VexFlowVoiceEntry[] = beam[1];
 
                     let autoStemBeam: boolean = true;
-                    for (const gve of staffEntries[0].graphicalVoiceEntries) {
+                    for (const gve of voiceEntries) {
                         if (gve.parentVoiceEntry.ParentVoice === psBeam.Notes[0].ParentVoiceEntry.ParentVoice) {
                             autoStemBeam = gve.parentVoiceEntry.StemDirection === StemDirectionType.Undefined;
                         }
                     }
 
-                    for (const entry of staffEntries) {
-                        const note: Vex.Flow.StaveNote = (<VexFlowStaffEntry>entry).vfNotes[voiceID];
+                    for (const entry of voiceEntries) {
+                        const note: Vex.Flow.StaveNote = (<VexFlowVoiceEntry>entry).vfStaveNote;
                         if (note !== undefined) {
                           notes.push(note);
                         }
@@ -455,9 +447,9 @@ export class VexFlowMeasure extends StaffMeasure {
                 }
                 for (const tupletBuilder of this.tuplets[voiceID]) {
                     const tupletStaveNotes: Vex.Flow.StaveNote[] = [];
-                    const tupletStaffEntries: VexFlowStaffEntry[] = tupletBuilder[1];
-                    for (const tupletStaffEntry of tupletStaffEntries) {
-                      tupletStaveNotes.push((tupletStaffEntry).vfNotes[voiceID]);
+                    const tupletVoiceEntries: VexFlowVoiceEntry[] = tupletBuilder[1];
+                    for (const tupletVoiceEntry of tupletVoiceEntries) {
+                      tupletStaveNotes.push((tupletVoiceEntry).vfStaveNote);
                     }
                     if (tupletStaveNotes.length > 1) {
                       const notesOccupied: number = 2;
@@ -480,10 +472,9 @@ export class VexFlowMeasure extends StaffMeasure {
 
     public staffMeasureCreatedCalculations(): void {
         for (const graphicalStaffEntry of this.staffEntries) {
-            // create vex flow Notes:
+            // create vex flow Stave Notes:
             for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
-                const vfnote: StaveNote = VexFlowConverter.StaveNote(gve.notes);
-                (graphicalStaffEntry as VexFlowStaffEntry).vfNotes[gve.parentVoiceEntry.ParentVoice.VoiceId] = vfnote;
+                (gve as VexFlowVoiceEntry).vfStaveNote = VexFlowConverter.StaveNote(gve.notes);
             }
         }
 
@@ -504,7 +495,7 @@ export class VexFlowMeasure extends StaffMeasure {
                     }).setMode(Vex.Flow.Voice.Mode.SOFT);
                 }
 
-                this.vfVoices[voiceID].addTickable(graphicalStaffEntry.vfNotes[voiceID]);
+                this.vfVoices[voiceID].addTickable((gve as VexFlowVoiceEntry).vfStaveNote);
             }
         }
         this.createArticulations();
@@ -517,9 +508,8 @@ export class VexFlowMeasure extends StaffMeasure {
             // create vex flow articulation:
             const graphicalVoiceEntries: GraphicalVoiceEntry[] = graphicalStaffEntry.graphicalVoiceEntries;
             for (const gve of graphicalVoiceEntries) {
-                const voiceID: number = gve.parentVoiceEntry.ParentVoice.VoiceId;
-                const vfnote: StaveNote = (graphicalStaffEntry as VexFlowStaffEntry).vfNotes[voiceID];
-                VexFlowConverter.generateArticulations(vfnote, gve.notes[0].sourceNote.ParentVoiceEntry.Articulations);
+                const vfStaveNote: StaveNote = (gve as VexFlowVoiceEntry).vfStaveNote;
+                VexFlowConverter.generateArticulations(vfStaveNote, gve.notes[0].sourceNote.ParentVoiceEntry.Articulations);
             }
         }
     }
@@ -561,7 +551,5 @@ export class VexFlowMeasure extends StaffMeasure {
 
         this.beginInstructionsWidth = beginInstructionsWidth / unitInPixels;
         this.endInstructionsWidth = endInstructionsWidth / unitInPixels;
-        //this.beginInstructionsWidth =  (this.stave.getNoteStartX() - this.stave.getX()) / unitInPixels;
-        //this.endInstructionsWidth = (this.stave.getX() + this.stave.getWidth() - this.stave.getNoteEndX()) / unitInPixels;
     }
 }

+ 3 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -35,8 +35,10 @@ import {GraphicalLyricWord} from "../GraphicalLyricWord";
 import {VexFlowStaffEntry} from "./VexFlowStaffEntry";
 
 export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
+
   constructor() {
-    super(new VexFlowGraphicalSymbolFactory());
+    super();
+    MusicSheetCalculator.symbolFactory = new VexFlowGraphicalSymbolFactory();
     MusicSheetCalculator.TextMeasurer = new VexFlowTextMeasurer();
   }
 

+ 9 - 14
src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.ts

@@ -2,35 +2,30 @@ import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
 import {VexFlowMeasure} from "./VexFlowMeasure";
 import {SourceStaffEntry} from "../../VoiceData/SourceStaffEntry";
 import {unitInPixels} from "./VexFlowMusicSheetDrawer";
+import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
 
 export class VexFlowStaffEntry extends GraphicalStaffEntry {
     constructor(measure: VexFlowMeasure, sourceStaffEntry: SourceStaffEntry, staffEntryParent: VexFlowStaffEntry) {
         super(measure, sourceStaffEntry, staffEntryParent);
     }
 
-    // The corresponding VexFlow.StaveNotes
-    public vfNotes: { [voiceID: number]: Vex.Flow.StaveNote; } = {};
-
     /**
      * Calculates the staff entry positions from the VexFlow stave information and the tickabels inside the staff.
      * This is needed in order to set the OSMD staff entries (which are almost the same as tickables) to the correct positionts.
      * It is also needed to be done after formatting!
      */
     public calculateXPosition(): void {
-        const vfNotes: { [voiceID: number]: Vex.Flow.StaveNote; } = this.vfNotes;
         const stave: Vex.Flow.Stave = (this.parentMeasure as VexFlowMeasure).getVFStave();
         let tickablePosition: number = 0;
         let numberOfValidTickables: number = 0;
-        for (const voiceId in vfNotes) {
-            if (vfNotes.hasOwnProperty(voiceId)) {
-                const tickable: Vex.Flow.StaveNote = vfNotes[voiceId];
-                // This will let the tickable know how to calculate it's bounding box
-                tickable.setStave(stave);
-                // The middle of the tickable is also the OSMD BoundingBox center
-                const staveNote: Vex.Flow.StaveNote = (<Vex.Flow.StaveNote>tickable);
-                tickablePosition += staveNote.getNoteHeadEndX() - staveNote.getGlyphWidth() / 2;
-                numberOfValidTickables++;
-            }
+        for (const gve of this.graphicalVoiceEntries) {
+            const tickable: Vex.Flow.StaveNote = (gve as VexFlowVoiceEntry).vfStaveNote;
+            // This will let the tickable know how to calculate it's bounding box
+            tickable.setStave(stave);
+            // The middle of the tickable is also the OSMD BoundingBox center
+            const staveNote: Vex.Flow.StaveNote = (<Vex.Flow.StaveNote>tickable);
+            tickablePosition += staveNote.getNoteHeadEndX() - staveNote.getGlyphWidth() / 2;
+            numberOfValidTickables++;
         }
         tickablePosition = tickablePosition / numberOfValidTickables;
         // Calculate parent absolute position and reverse calculate the relative position

+ 3 - 0
src/MusicalScore/Interfaces/IGraphicalSymbolFactory.ts

@@ -14,6 +14,7 @@ import {StaffLine} from "../Graphical/StaffLine";
 import {StaffMeasure} from "../Graphical/StaffMeasure";
 import { TechnicalInstruction } from "../VoiceData/Instructions/TechnicalInstruction";
 import { GraphicalVoiceEntry } from "../Graphical/GraphicalVoiceEntry";
+import { VoiceEntry } from "../VoiceData/VoiceEntry";
 
 export interface IGraphicalSymbolFactory {
 
@@ -29,6 +30,8 @@ export interface IGraphicalSymbolFactory {
 
     createGraceStaffEntry(staffEntryParent: GraphicalStaffEntry, measure: StaffMeasure): GraphicalStaffEntry;
 
+    createVoiceEntry(parentVoiceEntry: VoiceEntry, parentStaffEntry: GraphicalStaffEntry): GraphicalVoiceEntry;
+
     createNote(
         note: Note,
         graphicalVoiceEntry: GraphicalVoiceEntry,