Преглед на файлове

Trying to fix saveAbstractInstructionList

Andrea Condoluci преди 9 години
родител
ревизия
05221cc1b2

+ 12 - 2
external/vexflow/vexflow.d.ts

@@ -65,7 +65,7 @@ declare namespace Vex {
       public getNumLines(): number;
       public getLineForY(y: number): number;
       public getModifiers(pos: any, cat: any): Clef[]; // FIXME
-      public setContext(ctx: any): Stave;
+      public setContext(ctx: CanvasContext): Stave;
       public addModifier(mod: any, pos: any): void;
       public draw(): void;
       public addTimeSignature(sig: string): void;
@@ -98,7 +98,7 @@ declare namespace Vex {
 
       public static Backends: any;
       public resize(a: number, b: number): void;
-      public getContext(): any;
+      public getContext(): CanvasContext;
     }
 
     export class TimeSignature {
@@ -112,6 +112,16 @@ declare namespace Vex {
       constructor(type: string);
     }
 
+    export class Beam {
+      constructor(notes: StaveNote[]);
+      public setContext(ctx: CanvasContext): Beam;
+      public draw(): void;
+    }
+
+    export class CanvasContext {
+
+    }
+
   }
 }
 

+ 3 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowConverter.ts

@@ -50,7 +50,6 @@ export class VexFlowConverter {
     public static pitch(pitch: Pitch, octaveOffset: number): [string, string] {
         let fund: string = NoteEnum[pitch.FundamentalNote].toLowerCase();
         let octave: number = pitch.Octave + octaveOffset + 3;
-        console.log("pitch", pitch.Octave, octaveOffset);
         let acc: string = "";
 
         switch (pitch.Accidental) {
@@ -89,6 +88,8 @@ export class VexFlowConverter {
             accidentals.push(res[1]);
         }
         let vfnote: Vex.Flow.StaveNote = new Vex.Flow.StaveNote({
+            auto_stem: true,
+            clef: "treble", // FIXME!!
             duration: duration,
             keys: keys,
         });
@@ -121,6 +122,7 @@ export class VexFlowConverter {
                 break;
             default:
         }
+        console.log("CLEF", clef, type);
         return type;
     }
 
@@ -158,7 +160,6 @@ export class VexFlowConverter {
                 break;
             default:
         }
-        //console.log("keySignature", key, ret);
         return ret;
     }
 }

+ 1 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowGraphicalSymbolFactory.ts

@@ -97,7 +97,7 @@ export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
         let graphicalNote: GraphicalNote = new VexFlowGraphicalNote(note, graphicalStaffEntry, activeClef);
         // Adds the note to the right (graphical) voice (mynotes)
         let voiceID: number = note.ParentVoiceEntry.ParentVoice.VoiceId;
-        let mynotes: { [id: number]: GraphicalNote[]; } = (graphicalStaffEntry as VexFlowStaffEntry).mynotes;
+        let mynotes: { [id: number]: GraphicalNote[]; } = (graphicalStaffEntry as VexFlowStaffEntry).graphicalNotes;
         if (!(voiceID in mynotes)) {
             mynotes[voiceID] = [];
         }

+ 78 - 8
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -9,21 +9,27 @@ import {KeyInstruction} from "../../VoiceData/Instructions/KeyInstruction";
 import {RhythmInstruction} from "../../VoiceData/Instructions/RhythmInstruction";
 import {VexFlowConverter} from "./VexFlowConverter";
 import {VexFlowStaffEntry} from "./VexFlowStaffEntry";
+import {Beam} from "../../VoiceData/Beam";
+import {GraphicalNote} from "../GraphicalNote";
+import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
 
 export class VexFlowMeasure extends StaffMeasure {
     constructor(staff: Staff, staffLine: StaffLine = undefined, sourceMeasure: SourceMeasure = undefined) {
         super(staff, sourceMeasure, staffLine);
         this.minimumStaffEntriesWidth = -1;
         this.stave = new Vex.Flow.Stave(0, 0, 0);
-        this.voices = {};
+        this.vfVoices = {};
         //this.duration = this.parentSourceMeasure.Duration;
     }
 
     public octaveOffset: number = 3; // FIXME
-    public voices: { [voiceID: number]: Vex.Flow.Voice; };
+    public vfVoices: { [voiceID: number]: Vex.Flow.Voice; };
     public formatVoices: (width: number) => void;
     public unit: number = 10.0;
     private stave: Vex.Flow.Stave;
+
+    private beams: { [voiceID: number]: [Beam, VexFlowStaffEntry[]][]; } = {};
+    private vfbeams: { [voiceID: number]: Vex.Flow.Beam[]; } = {};
     //private duration: Fraction;
 
     public setAbsoluteCoordinates(x: number, y: number): void {
@@ -156,13 +162,77 @@ export class VexFlowMeasure extends StaffMeasure {
         // TODO
     }
 
-    public draw(canvas: HTMLCanvasElement): void {
-        let renderer: Vex.Flow.Renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
-        let ctx: any = renderer.getContext();
+    public draw(ctx: Vex.Flow.CanvasContext): void {
         this.stave.setContext(ctx).draw();
-        for (let voiceID in this.voices) {
-            if (this.voices.hasOwnProperty(voiceID)) {
-                this.voices[voiceID].draw(ctx, this.stave);
+        for (let voiceID in this.vfVoices) {
+            if (this.vfVoices.hasOwnProperty(voiceID)) {
+                this.vfVoices[voiceID].draw(ctx, this.stave);
+            }
+        }
+        for (let voiceID in this.vfbeams) {
+            if (this.vfbeams.hasOwnProperty(voiceID)) {
+                for (let beam of this.vfbeams[voiceID]) {
+                    beam.setContext(ctx).draw();
+                }
+            }
+        }
+    }
+
+    public handleBeam(graphicalNote: GraphicalNote, beam: Beam): void {
+        let voiceID: number = graphicalNote.sourceNote.ParentVoiceEntry.ParentVoice.VoiceId;
+        let beams: [Beam, VexFlowStaffEntry[]][] = this.beams[voiceID];
+        if (beams === undefined) {
+            beams = this.beams[voiceID] = [];
+        }
+        let data: [Beam, VexFlowStaffEntry[]];
+        for (let mybeam of beams) {
+            if (mybeam[0] === beam) {
+                data = mybeam;
+            }
+        }
+        if (data === undefined) {
+            data = [beam, []];
+            beams.push(data);
+        }
+        let parent: VexFlowStaffEntry = graphicalNote.parentStaffEntry as VexFlowStaffEntry;
+        if (data[1].indexOf(parent) === -1) {
+            data[1].push(parent);
+        }
+    }
+
+    public finalizeBeams(): void {
+        for (let voiceID in this.beams) {
+            if (this.beams.hasOwnProperty(voiceID)) {
+                let vfbeams: Vex.Flow.Beam[] = this.vfbeams[voiceID];
+                if (vfbeams === undefined) {
+                    vfbeams = this.vfbeams[voiceID] = [];
+                }
+                for (let beam of this.beams[voiceID]) {
+                    let notes: Vex.Flow.StaveNote[] = [];
+                    for (let entry of beam[1]) {
+                        notes.push((entry as VexFlowStaffEntry).vfNotes[voiceID]);
+                    }
+                    vfbeams.push(new Vex.Flow.Beam(notes));
+                }
+            }
+        }
+    }
+
+    public layoutStaffEntry(graphicalStaffEntry: GraphicalStaffEntry): void {
+        let gnotes: { [voiceID: number]: GraphicalNote[]; } = (graphicalStaffEntry as VexFlowStaffEntry).graphicalNotes;
+        let vfVoices: { [voiceID: number]: Vex.Flow.Voice; } = this.vfVoices;
+        for (let voiceID in gnotes) {
+            if (gnotes.hasOwnProperty(voiceID)) {
+                if (!(voiceID in vfVoices)) {
+                    vfVoices[voiceID] = new Vex.Flow.Voice({
+                        beat_value: this.parentSourceMeasure.Duration.Denominator,
+                        num_beats: this.parentSourceMeasure.Duration.Numerator,
+                        resolution: Vex.Flow.RESOLUTION,
+                    }).setMode(Vex.Flow.Voice.Mode.SOFT);
+                }
+                let vfnote: Vex.Flow.StaveNote = VexFlowConverter.StaveNote(gnotes[voiceID]);
+                (graphicalStaffEntry as VexFlowStaffEntry).vfNotes[voiceID] = vfnote;
+                vfVoices[voiceID].addTickable(vfnote);
             }
         }
     }

+ 8 - 22
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -29,8 +29,6 @@ import {VexFlowTextMeasurer} from "./VexFlowTextMeasurer";
 //import {VexFlowMeasure} from "./VexFlowMeasure";
 
 import Vex = require("vexflow");
-import {VexFlowStaffEntry} from "./VexFlowStaffEntry";
-import {VexFlowConverter} from "./VexFlowConverter";
 
 export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
     constructor() {
@@ -61,12 +59,15 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
      * @returns the minimum required x width of the source measure (=list of staff measures)
      */
     protected calculateMeasureXLayout(measures: StaffMeasure[]): number {
-        // layout the measures in x.
-        // return the minimum required x width of this vertically aligned measure set:
+        // Finalize beams
+        for (let measure of measures) {
+            (measure as VexFlowMeasure).finalizeBeams();
+        }
+        // Format the voices
         let allVoices: Vex.Flow.Voice[] = [];
         let formatter: Vex.Flow.Formatter = new Vex.Flow.Formatter();
         for (let measure of measures) {
-            let mvoices:  { [voiceID: number]: Vex.Flow.Voice; } = (measure as VexFlowMeasure).voices;
+            let mvoices:  { [voiceID: number]: Vex.Flow.Voice; } = (measure as VexFlowMeasure).vfVoices;
             let voices: Vex.Flow.Voice[] = [];
             for (let voiceID in mvoices) {
                 if (mvoices.hasOwnProperty(voiceID)) {
@@ -148,22 +149,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
      * @param graphicalStaffEntry
      */
     protected layoutStaffEntry(graphicalStaffEntry: GraphicalStaffEntry): void {
-        let vfnotes: { [voiceID: number]: GraphicalNote[]; } = (graphicalStaffEntry as VexFlowStaffEntry).mynotes;
-        console.log("Unfortunately empty: ", vfnotes);
-        let measure: VexFlowMeasure = graphicalStaffEntry.parentMeasure as VexFlowMeasure;
-        let voices: { [voiceID: number]: Vex.Flow.Voice; } = measure.voices;
-        for (let id in vfnotes) {
-            if (vfnotes.hasOwnProperty(id)) {
-                if (!(id in voices)) {
-                    voices[id] = new Vex.Flow.Voice({
-                        beat_value: measure.parentSourceMeasure.Duration.Denominator,
-                        num_beats: measure.parentSourceMeasure.Duration.Numerator,
-                        resolution: Vex.Flow.RESOLUTION,
-                    }).setMode(Vex.Flow.Voice.Mode.SOFT);
-                }
-                voices[id].addTickable(VexFlowConverter.StaveNote(vfnotes[id]));
-            }
-        }
+        (graphicalStaffEntry.parentMeasure as VexFlowMeasure).layoutStaffEntry(graphicalStaffEntry);
     }
 
     /**
@@ -236,7 +222,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
      * @param openBeams a list of all currently open beams
      */
     protected handleBeam(graphicalNote: GraphicalNote, beam: Beam, openBeams: Beam[]): void {
-        return;
+        (graphicalNote.parentStaffEntry.parentMeasure as VexFlowMeasure).handleBeam(graphicalNote, beam);
     }
 
     protected handleVoiceEntryLyrics(lyricsEntries: Dictionary<number, LyricsEntry>, voiceEntry: VoiceEntry,

+ 20 - 9
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -1,3 +1,4 @@
+import Vex = require("vexflow");
 import {MusicSheetDrawer} from "../MusicSheetDrawer";
 import {RectangleF2D} from "../../../Common/DataObjects/RectangleF2D";
 import {VexFlowMeasure} from "./VexFlowMeasure";
@@ -8,29 +9,39 @@ import {GraphicalMusicSheet} from "../GraphicalMusicSheet";
 export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
     constructor() {
         super();
+        // Create heading (FIXME)
+        let h1: Element = document.createElement("h1");
+        h1.textContent = "VexFlowMusicSheetDrawer Output";
+        document.body.appendChild(h1);
         // Create the canvas in the document:
-        this.canvas = document.createElement("canvas");
-        document.body.appendChild(this.canvas);
+        let canvas: HTMLCanvasElement = document.createElement("canvas");
+        document.body.appendChild(canvas);
+        this.renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
+        this.ctx = this.renderer.getContext();
+
     }
 
-    private canvas: HTMLCanvasElement;
+    private renderer: Vex.Flow.Renderer;
+    private ctx: Vex.Flow.CanvasContext;
+    private counter: number = 0;
 
     public drawSheet(graphicalMusicSheet: GraphicalMusicSheet): void {
-        let h1: Element = document.createElement("h1");
-        h1.textContent = "VexFlowMusicSheetDrawer Output";
-        document.body.appendChild(h1);
         // FIXME units
+        // FIXME actual page size
         let unit: number = 10;
-        this.canvas.width = this.canvas.height = unit * graphicalMusicSheet.ParentMusicSheet.pageWidth;
+        this.renderer.resize(
+            unit * graphicalMusicSheet.ParentMusicSheet.pageWidth,
+            unit * graphicalMusicSheet.ParentMusicSheet.pageWidth
+        );
         super.drawSheet(graphicalMusicSheet);
     }
 
     protected drawMeasure(measure: VexFlowMeasure): void {
         measure.setAbsoluteCoordinates(
             measure.PositionAndShape.AbsolutePosition.x * (measure as VexFlowMeasure).unit,
-            measure.PositionAndShape.AbsolutePosition.y * (measure as VexFlowMeasure).unit
+            measure.PositionAndShape.AbsolutePosition.y * (measure as VexFlowMeasure).unit + (this.counter += 5)
         );
-        return measure.draw(this.canvas);
+        return measure.draw(this.ctx);
     }
 
     protected applyScreenTransformation(rectangle: RectangleF2D): RectangleF2D {

+ 4 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.ts

@@ -8,5 +8,8 @@ export class VexFlowStaffEntry extends GraphicalStaffEntry {
         super(measure, sourceStaffEntry, staffEntryParent);
     }
 
-    public mynotes: { [id: number]: GraphicalNote[]; } = {};
+    // The Graphical Notes belonging to this StaffEntry, sorted by voiceID
+    public graphicalNotes: { [voiceID: number]: GraphicalNote[]; } = {};
+    // The corresponding VexFlow.StaveNotes
+    public vfNotes: { [voiceID: number]: Vex.Flow.StaveNote; } = {};
 }

+ 43 - 43
src/MusicalScore/ScoreIO/InstrumentReader.ts

@@ -19,7 +19,7 @@ import {IXmlAttribute} from "../../Common/FileIO/Xml";
 import {ChordSymbolContainer} from "../VoiceData/ChordSymbolContainer";
 import {Logging} from "../../Common/logging";
 import {MidiInstrument} from "../VoiceData/Instructions/ClefInstruction";
-import Dictionary from "typescript-collections/dist/lib/Dictionary";
+//import Dictionary from "typescript-collections/dist/lib/Dictionary";
 
 // FIXME: The following classes are missing
 //type repetitionInstructionReader = any;
@@ -78,7 +78,7 @@ export class InstrumentReader {
   private activeRhythm: RhythmInstruction;
   private activeClefsHaveBeenInitialized: boolean[];
   private activeKeyHasBeenInitialized: boolean = false;
-  private abstractInstructions: Dictionary<number, AbstractNotationInstruction> = new Dictionary<number, AbstractNotationInstruction>();
+  private abstractInstructions: [number, AbstractNotationInstruction][] = [];
   private openChordSymbolContainer: ChordSymbolContainer;
   // (*) private expressionReaders: ExpressionReader[];
   private currentVoiceGenerator: VoiceGenerator;
@@ -522,8 +522,8 @@ export class InstrumentReader {
             line = parseInt(lineNode.value, 10);
           } catch (ex) {
             errorMsg = ITextTranslation.translateText(
-              "ReaderErrorMessages/ClefLineError",
-              "Invalid clef line given -> using default clef line."
+                "ReaderErrorMessages/ClefLineError",
+                "Invalid clef line given -> using default clef line."
             );
             this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
             line = 2;
@@ -540,8 +540,8 @@ export class InstrumentReader {
                 clefOctaveOffset = -1;
               }
               errorMsg = ITextTranslation.translateText(
-                "ReaderErrorMessages/ClefError",
-                "Unsupported clef found -> using default clef."
+                  "ReaderErrorMessages/ClefError",
+                  "Unsupported clef found -> using default clef."
               );
               this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
               clefEnum = ClefEnum.G;
@@ -549,8 +549,8 @@ export class InstrumentReader {
             }
           } catch (e) {
             errorMsg = ITextTranslation.translateText(
-              "ReaderErrorMessages/ClefError",
-              "Invalid clef found -> using default clef."
+                "ReaderErrorMessages/ClefError",
+                "Invalid clef found -> using default clef."
             );
             this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
             clefEnum = ClefEnum.G;
@@ -565,8 +565,8 @@ export class InstrumentReader {
             clefOctaveOffset = parseInt(clefOctaveNode.value, 10);
           } catch (e) {
             errorMsg = ITextTranslation.translateText(
-              "ReaderErrorMessages/ClefOctaveError",
-              "Invalid clef octave found -> using default clef octave."
+                "ReaderErrorMessages/ClefOctaveError",
+                "Invalid clef octave found -> using default clef octave."
             );
             this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
             clefOctaveOffset = 0;
@@ -578,8 +578,8 @@ export class InstrumentReader {
             staffNumber = parseInt(nodeList.attributes()[0].value, 10);
           } catch (err) {
             errorMsg = ITextTranslation.translateText(
-              "ReaderErrorMessages/ClefError",
-              "Invalid clef found -> using default clef."
+                "ReaderErrorMessages/ClefError",
+                "Invalid clef found -> using default clef."
             );
             this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
             staffNumber = 1;
@@ -587,7 +587,7 @@ export class InstrumentReader {
         }
 
         let clefInstruction: ClefInstruction = new ClefInstruction(clefEnum, clefOctaveOffset, line);
-        this.abstractInstructions[staffNumber] = clefInstruction;
+        this.abstractInstructions.push([staffNumber, clefInstruction]);
       }
     }
     if (node.element("key") !== undefined && this.instrument.MidiInstrumentId !== MidiInstrument.Percussion) {
@@ -598,8 +598,8 @@ export class InstrumentReader {
           key = parseInt(keyNode.value, 10);
         } catch (ex) {
           errorMsg = ITextTranslation.translateText(
-            "ReaderErrorMessages/KeyError",
-            "Invalid key found -> set to default."
+              "ReaderErrorMessages/KeyError",
+              "Invalid key found -> set to default."
           );
           this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
           key = 0;
@@ -615,8 +615,8 @@ export class InstrumentReader {
           keyEnum = KeyEnum[modeNode.value];
         } catch (ex) {
           errorMsg = ITextTranslation.translateText(
-            "ReaderErrorMessages/KeyError",
-            "Invalid key found -> set to default."
+              "ReaderErrorMessages/KeyError",
+              "Invalid key found -> set to default."
           );
           this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
           keyEnum = KeyEnum.major;
@@ -625,7 +625,7 @@ export class InstrumentReader {
 
       }
       let keyInstruction: KeyInstruction = new KeyInstruction(undefined, key, keyEnum);
-      this.abstractInstructions[1] = keyInstruction;
+      this.abstractInstructions.push([1, keyInstruction]);
     }
     if (node.element("time") !== undefined) {
       let symbolEnum: RhythmSymbolEnum = RhythmSymbolEnum.NONE;
@@ -696,19 +696,20 @@ export class InstrumentReader {
         if ((num === 4 && denom === 4) || (num === 2 && denom === 2)) {
           symbolEnum = RhythmSymbolEnum.NONE;
         }
-        this.abstractInstructions[1] = new RhythmInstruction(
+        this.abstractInstructions.push([1, new RhythmInstruction(
             new Fraction(num, denom, false), num, denom, symbolEnum
-        );
+        )]);
       } else {
-        this.abstractInstructions[1] = new RhythmInstruction(new Fraction(4, 4, false), 4, 4, RhythmSymbolEnum.NONE);
+        this.abstractInstructions.push([1, new RhythmInstruction(new Fraction(4, 4, false), 4, 4, RhythmSymbolEnum.NONE)]);
       }
     }
   }
 
   private saveAbstractInstructionList(numberOfStaves: number, beginOfMeasure: boolean): void {
-    for (let i: number = this.abstractInstructions.keys().length - 1; i >= 0; i--) {
-      let key: number = this.abstractInstructions.keys()[i];
-      let value: AbstractNotationInstruction = this.abstractInstructions.getValue(key);
+    for (let i: number = this.abstractInstructions.length - 1; i >= 0; i--) {
+      let pair: [number, AbstractNotationInstruction] = this.abstractInstructions[i];
+      let key: number = pair[0];
+      let value: AbstractNotationInstruction = pair[1];
       if (value instanceof ClefInstruction) {
         let clefInstruction: ClefInstruction = <ClefInstruction>value;
         if (this.currentXmlMeasureIndex === 0 || (key <= this.activeClefs.length && clefInstruction !== this.activeClefs[key - 1])) {
@@ -719,7 +720,7 @@ export class InstrumentReader {
             this.currentStaffEntry.removeFirstInstructionOfType<ClefInstruction>();
             this.currentStaffEntry.Instructions.push(newClefInstruction);
             this.activeClefs[key - 1] = clefInstruction;
-            this.abstractInstructions.remove(key);
+            this.abstractInstructions.splice(i, 1);
           } else if (beginOfMeasure) {
             let firstStaffEntry: SourceStaffEntry;
             if (this.currentMeasure !== undefined) {
@@ -764,19 +765,19 @@ export class InstrumentReader {
                 lastStaffEntry.Instructions.push(newClefInstruction);
               }
               this.activeClefs[key - 1] = clefInstruction;
-              this.abstractInstructions.remove(key);
+              this.abstractInstructions.splice(i, 1);
             }
           }
         }
         if (key <= this.activeClefs.length && clefInstruction === this.activeClefs[key - 1]) {
-          this.abstractInstructions.remove(key);
+          this.abstractInstructions.splice(i, 1);
         }
       }
       if (value instanceof KeyInstruction) {
         let keyInstruction: KeyInstruction = <KeyInstruction>value;
         if (this.activeKey === undefined || this.activeKey.Key !== keyInstruction.Key) {
           this.activeKey = keyInstruction;
-          this.abstractInstructions.remove(key);
+          this.abstractInstructions.splice(i, 1);
           let sourceMeasure: SourceMeasure;
           if (!this.activeKeyHasBeenInitialized) {
             this.activeKeyHasBeenInitialized = true;
@@ -814,14 +815,14 @@ export class InstrumentReader {
           }
         }
         if (this.activeKey !== undefined && this.activeKey === keyInstruction) {
-          this.abstractInstructions.remove(key);
+          this.abstractInstructions.splice(i, 1);
         }
       }
       if (value instanceof RhythmInstruction) {
         let rhythmInstruction: RhythmInstruction = <RhythmInstruction>value;
         if (this.activeRhythm === undefined || this.activeRhythm !== rhythmInstruction) {
           this.activeRhythm = rhythmInstruction;
-          this.abstractInstructions.remove(key);
+          this.abstractInstructions.splice(i, 1);
           if (this.currentMeasure !== undefined) {
             for (let j: number = this.inSourceMeasureInstrumentIndex; j < this.inSourceMeasureInstrumentIndex + numberOfStaves; j++) {
               let newRhythmInstruction: RhythmInstruction = rhythmInstruction;
@@ -839,33 +840,32 @@ export class InstrumentReader {
           }
         }
         if (this.activeRhythm !== undefined && this.activeRhythm === rhythmInstruction) {
-          this.abstractInstructions.remove(key);
+          this.abstractInstructions.splice(i, 1);
         }
       }
     }
   }
 
   private saveClefInstructionAtEndOfMeasure(): void {
-    for (let key in this.abstractInstructions) {
-      if (this.abstractInstructions.hasOwnProperty(key)) {
-        let value: AbstractNotationInstruction = this.abstractInstructions[key];
-        if (value instanceof ClefInstruction) {
+    for (let i: number = this.abstractInstructions.length - 1; i >= 0; i--) {
+      let key: number = this.abstractInstructions[i][0];
+      let value: AbstractNotationInstruction = this.abstractInstructions[i][1];
+      if (value instanceof ClefInstruction) {
           let clefInstruction: ClefInstruction = <ClefInstruction>value;
           if (
-            (this.activeClefs[+key - 1] === undefined) ||
-            (clefInstruction.ClefType !== this.activeClefs[+key - 1].ClefType || (
-              clefInstruction.ClefType === this.activeClefs[+key - 1].ClefType &&
-              clefInstruction.Line !== this.activeClefs[+key - 1].Line
+            (this.activeClefs[key - 1] === undefined) ||
+            (clefInstruction.ClefType !== this.activeClefs[key - 1].ClefType || (
+              clefInstruction.ClefType === this.activeClefs[key - 1].ClefType &&
+              clefInstruction.Line !== this.activeClefs[key - 1].Line
             ))) {
             let lastStaffEntry: SourceStaffEntry = new SourceStaffEntry(undefined, undefined);
-            this.currentMeasure.LastInstructionsStaffEntries[this.inSourceMeasureInstrumentIndex + (+key) - 1] = lastStaffEntry;
+            this.currentMeasure.LastInstructionsStaffEntries[this.inSourceMeasureInstrumentIndex + key - 1] = lastStaffEntry;
             let newClefInstruction: ClefInstruction = clefInstruction;
             newClefInstruction.Parent = lastStaffEntry;
             lastStaffEntry.Instructions.push(newClefInstruction);
-            this.activeClefs[+key - 1] = clefInstruction;
-            delete this.abstractInstructions[+key]; // FIXME Andrea: might hurt performance?
+            this.activeClefs[key - 1] = clefInstruction;
+            this.abstractInstructions.splice(i, 1);
           }
-        }
       }
     }
   }

+ 47 - 47
test/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -1,47 +1,47 @@
-import {GraphicalMusicSheet} from "../../../../src/MusicalScore/Graphical/GraphicalMusicSheet";
-import {IXmlElement} from "../../../../src/Common/FileIO/Xml";
-import {MusicSheet} from "../../../../src/MusicalScore/MusicSheet";
-import {MusicSheetReader} from "../../../../src/MusicalScore/ScoreIO/MusicSheetReader";
-import {VexFlowMusicSheetCalculator} from "../../../../src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator";
-import {TestUtils} from "../../../Util/TestUtils";
-
-describe("VexFlow Measure", () => {
-
-    //it("GraphicalMusicSheet", (done: MochaDone) => {
-    //    let path: string = "test/data/MuzioClementi_SonatinaOpus36No1_Part1.xml";
-    //    let score: IXmlElement = TestUtils.getScore(path);
-    //    chai.expect(score).to.not.be.undefined;
-    //    let calc: VexFlowMusicSheetCalculator = new VexFlowMusicSheetCalculator();
-    //    let reader: MusicSheetReader = new MusicSheetReader();
-    //    let sheet: MusicSheet = reader.createMusicSheet(score, path);
-    //    let gms: GraphicalMusicSheet = new GraphicalMusicSheet(sheet, calc);
-    //    console.log(gms);
-    //    done();
-    //});
-
-    //it("Simple Measure", (done: MochaDone) => {
-    //    let sheet: MusicSheet = new MusicSheet();
-    //    let measure: SourceMeasure = new SourceMeasure(1);
-    //    sheet.addMeasure(measure);
-    //    let calc: MusicSheetCalculator = new VexFlowMusicSheetCalculator();
-    //    let gms: GraphicalMusicSheet = new GraphicalMusicSheet(sheet, calc);
-    //    chai.expect(gms.MeasureList.length).to.equal(1);
-    //    chai.expect(gms.MeasureList[0].length).to.equal(1);
-    //    let gm: StaffMeasure = gms.MeasureList[0][0];
-    //    console.log(gm);
-    //    done();
-    //});
-
-    //it("Empty Measure", (done: MochaDone) => {
-    //    let sheet: MusicSheet = new MusicSheet();
-    //    let measure: SourceMeasure = new SourceMeasure(1);
-    //    measure.FirstInstructionsStaffEntries[0] = new SourceStaffEntry(undefined, undefined);
-    //    sheet.addMeasure(measure);
-    //    let calc: MusicSheetCalculator = new VexFlowMusicSheetCalculator();
-    //    let gms: GraphicalMusicSheet = new GraphicalMusicSheet(sheet, calc);
-    //    chai.expect(gms.MeasureList.length).to.equal(1);
-    //    chai.expect(gms.MeasureList[0].length).to.equal(0);
-    //    done();
-    //});
-
-});
+//import {GraphicalMusicSheet} from "../../../../src/MusicalScore/Graphical/GraphicalMusicSheet";
+//import {IXmlElement} from "../../../../src/Common/FileIO/Xml";
+//import {MusicSheet} from "../../../../src/MusicalScore/MusicSheet";
+//import {MusicSheetReader} from "../../../../src/MusicalScore/ScoreIO/MusicSheetReader";
+//import {VexFlowMusicSheetCalculator} from "../../../../src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator";
+//import {TestUtils} from "../../../Util/TestUtils";
+//
+//describe("VexFlow Measure", () => {
+//
+//    //it("GraphicalMusicSheet", (done: MochaDone) => {
+//    //    let path: string = "test/data/MuzioClementi_SonatinaOpus36No1_Part1.xml";
+//    //    let score: IXmlElement = TestUtils.getScore(path);
+//    //    chai.expect(score).to.not.be.undefined;
+//    //    let calc: VexFlowMusicSheetCalculator = new VexFlowMusicSheetCalculator();
+//    //    let reader: MusicSheetReader = new MusicSheetReader();
+//    //    let sheet: MusicSheet = reader.createMusicSheet(score, path);
+//    //    let gms: GraphicalMusicSheet = new GraphicalMusicSheet(sheet, calc);
+//    //    console.log(gms);
+//    //    done();
+//    //});
+//
+//    //it("Simple Measure", (done: MochaDone) => {
+//    //    let sheet: MusicSheet = new MusicSheet();
+//    //    let measure: SourceMeasure = new SourceMeasure(1);
+//    //    sheet.addMeasure(measure);
+//    //    let calc: MusicSheetCalculator = new VexFlowMusicSheetCalculator();
+//    //    let gms: GraphicalMusicSheet = new GraphicalMusicSheet(sheet, calc);
+//    //    chai.expect(gms.MeasureList.length).to.equal(1);
+//    //    chai.expect(gms.MeasureList[0].length).to.equal(1);
+//    //    let gm: StaffMeasure = gms.MeasureList[0][0];
+//    //    console.log(gm);
+//    //    done();
+//    //});
+//
+//    //it("Empty Measure", (done: MochaDone) => {
+//    //    let sheet: MusicSheet = new MusicSheet();
+//    //    let measure: SourceMeasure = new SourceMeasure(1);
+//    //    measure.FirstInstructionsStaffEntries[0] = new SourceStaffEntry(undefined, undefined);
+//    //    sheet.addMeasure(measure);
+//    //    let calc: MusicSheetCalculator = new VexFlowMusicSheetCalculator();
+//    //    let gms: GraphicalMusicSheet = new GraphicalMusicSheet(sheet, calc);
+//    //    chai.expect(gms.MeasureList.length).to.equal(1);
+//    //    chai.expect(gms.MeasureList[0].length).to.equal(0);
+//    //    done();
+//    //});
+//
+//});

+ 1 - 0
test/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -19,4 +19,5 @@ describe("VexFlow Music Sheet Drawer", () => {
         (new VexFlowMusicSheetDrawer()).drawSheet(gms);
         done();
     });
+
 });