Browse Source

Merged from porting branch

Andrea Condoluci 9 năm trước cách đây
mục cha
commit
02750c1743
28 tập tin đã thay đổi với 277 bổ sung207 xóa
  1. 2 2
      Gruntfile.js
  2. 21 0
      src/Common/DataObjects/pitch.ts
  3. 1 0
      src/MusicalScore/Graphical/AbstractGraphicalInstruction.ts
  4. 6 5
      src/MusicalScore/Graphical/AccidentalCalculator.ts
  5. 6 31
      src/MusicalScore/Graphical/BoundingBox.ts
  6. 2 1
      src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts
  7. 3 9
      src/MusicalScore/Graphical/GraphicalLabel.ts
  8. 2 1
      src/MusicalScore/Graphical/GraphicalMusicPage.ts
  9. 15 44
      src/MusicalScore/Graphical/GraphicalMusicSheet.ts
  10. 1 0
      src/MusicalScore/Graphical/GraphicalNote.ts
  11. 8 5
      src/MusicalScore/Graphical/GraphicalStaffEntry.ts
  12. 41 39
      src/MusicalScore/Graphical/MusicSheetCalculator.ts
  13. 14 13
      src/MusicalScore/Graphical/MusicSystem.ts
  14. 16 7
      src/MusicalScore/Graphical/MusicSystemBuilder.ts
  15. 2 1
      src/MusicalScore/Graphical/StaffLine.ts
  16. 2 1
      src/MusicalScore/Graphical/StaffLineActivitySymbol.ts
  17. 2 1
      src/MusicalScore/Graphical/StaffMeasure.ts
  18. 14 5
      src/MusicalScore/Graphical/VerticalGraphicalStaffEntryContainer.ts
  19. 1 1
      src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts
  20. 2 1
      src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts
  21. 17 3
      src/MusicalScore/Interfaces/IGraphicalSymbolFactory.ts
  22. 8 10
      src/MusicalScore/ScoreIO/VoiceGenerator.ts
  23. 6 5
      src/MusicalScore/VoiceData/ChordSymbolContainer.ts
  24. 4 4
      src/MusicalScore/VoiceData/SourceStaffEntry.ts
  25. 7 9
      src/MusicalScore/VoiceData/VoiceEntry.ts
  26. 31 8
      src/Util/collectionUtil.ts
  27. 1 1
      test/Common/DataObjects/fraction_Test.ts
  28. 42 0
      test/MusicalScore/ScoreCalculation/MusicSheetCalculator_Test.ts

+ 2 - 2
Gruntfile.js

@@ -153,8 +153,8 @@ module.exports = function (grunt) {
     // Register tasks
     grunt.registerTask('all',     ['typings', 'default']);
     grunt.registerTask('start',   ['typings']);
-    grunt.registerTask('default', ['lint', 'browserify', 'karma:ci', 'uglify']);
-    grunt.registerTask('test',    ['lint', 'browserify:debug', 'karma:ci']);
+    grunt.registerTask('default', ['browserify', 'lint', 'karma:ci', 'uglify']);
+    grunt.registerTask('test',    ['browserify:debug', 'lint', 'karma:ci']);
     grunt.registerTask('fasttest', ['browserify:debug', 'karma:ci']);
     grunt.registerTask('rebuild', ['clean', 'default']);
     grunt.registerTask('publish', ['clean', 'browserify:dist', 'docco']);

+ 21 - 0
src/Common/DataObjects/pitch.ts

@@ -33,6 +33,27 @@ export class Pitch {
     private frequency: number;
     private halfTone: number;
 
+    public static getNoteEnumString(note: NoteEnum): string {
+        switch (note) {
+            case NoteEnum.C:
+                return "C";
+            case NoteEnum.D:
+                return "D";
+            case NoteEnum.E:
+                return "E";
+            case NoteEnum.F:
+                return "F";
+            case NoteEnum.G:
+                return "G";
+            case NoteEnum.A:
+                return "A";
+            case NoteEnum.B:
+                return "B";
+            default:
+                return "";
+        }
+    }
+
     /**
      * @param the input pitch
      * @param the number of halftones to transpose with

+ 1 - 0
src/MusicalScore/Graphical/AbstractGraphicalInstruction.ts

@@ -4,6 +4,7 @@ import {GraphicalObject} from "./GraphicalObject";
 export class AbstractGraphicalInstruction extends GraphicalObject {
     protected parent: GraphicalStaffEntry;
     constructor(parent: GraphicalStaffEntry) {
+        super();
         this.parent = parent;
     }
     public get Parent(): GraphicalStaffEntry {

+ 6 - 5
src/MusicalScore/Graphical/AccidentalCalculator.ts

@@ -4,12 +4,13 @@ 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";
 
 export class AccidentalCalculator {
     private symbolFactory: IGraphicalSymbolFactory;
-    private keySignatureNoteAlterationsDict: { [_: number]: AccidentalEnum; } = {};
+    private keySignatureNoteAlterationsDict: Dictionary<number, AccidentalEnum> = new Dictionary<number, AccidentalEnum>();
     private currentAlterationsComparedToKeyInstructionDict: number[] = [];
-    private currentInMeasureNoteAlterationsDict: { [_: number]: AccidentalEnum; } = {};
+    private currentInMeasureNoteAlterationsDict: Dictionary<number, AccidentalEnum> = new Dictionary<number, AccidentalEnum>();
     private activeKeyInstruction: KeyInstruction;
 
     constructor(symbolFactory: IGraphicalSymbolFactory) {
@@ -26,7 +27,7 @@ export class AccidentalCalculator {
     }
 
     public doCalculationsAtEndOfMeasure(): void {
-        this.currentInMeasureNoteAlterationsDict = {};
+        this.currentInMeasureNoteAlterationsDict.clear();
         for (let key in this.keySignatureNoteAlterationsDict) {
             if (this.keySignatureNoteAlterationsDict.hasOwnProperty(key)) {
                 this.currentInMeasureNoteAlterationsDict[key] = this.keySignatureNoteAlterationsDict[key];
@@ -39,7 +40,7 @@ export class AccidentalCalculator {
             return;
         }
         let pitchKey: number = <number>pitch.FundamentalNote + pitch.Octave * 12;
-        let pitchKeyGivenInMeasureDict: boolean = this.currentInMeasureNoteAlterationsDict.hasOwnProperty(pitchKey as string);
+        let pitchKeyGivenInMeasureDict: boolean = this.currentInMeasureNoteAlterationsDict.containsKey(pitchKey);
         if (
             (pitchKeyGivenInMeasureDict && this.currentInMeasureNoteAlterationsDict[pitchKey] !== pitch.Accidental)
             || (!pitchKeyGivenInMeasureDict && pitch.Accidental !== AccidentalEnum.NONE)
@@ -68,7 +69,7 @@ export class AccidentalCalculator {
         } else {
             keyAccidentalType = AccidentalEnum.FLAT;
         }
-        this.keySignatureNoteAlterationsDict = {};
+        this.keySignatureNoteAlterationsDict.clear();
         this.currentAlterationsComparedToKeyInstructionDict.length = 0;
         for (let octave: number = -9; octave < 9; octave++) {
             for (let i: number = 0; i < noteEnums.length; i++) {

+ 6 - 31
src/MusicalScore/Graphical/BoundingBox.ts

@@ -28,17 +28,13 @@ export class BoundingBox {
     protected parent: BoundingBox;
     protected dataObject: Object;
 
-    constructor(dataObject: Object) {
+    constructor(dataObject: Object = undefined, parent: BoundingBox = undefined) {
+        this.parent = parent;
         this.dataObject = dataObject;
         this.xBordersHaveBeenSet = false;
         this.yBordersHaveBeenSet = false;
     }
 
-    constructor(parent: BoundingBox, dataObject: Object) {
-        this(dataObject);
-        this.parent = parent;
-    }
-
     public get RelativePositionHasBeenSet(): boolean {
         return this.relativePositionHasBeenSet;
     }
@@ -307,10 +303,6 @@ export class BoundingBox {
         this.calculateMarginRectangle();
     }
 
-    public computeNonOverlappingPositionWithMargin(placementPsi: BoundingBox, direction: ColDirEnum): void {
-        this.computeNonOverlappingPositionWithMargin(placementPsi, direction, new PointF2D(0.0, 0.0));
-    }
-
     public computeNonOverlappingPositionWithMargin(placementPsi: BoundingBox, direction: ColDirEnum, position: PointF2D): void {
         this.RelativePosition = new PointF2D(position.x, position.y);
         this.setAbsolutePositionFromParent();
@@ -365,20 +357,7 @@ export class BoundingBox {
         return false;
     }
 
-    public liesInsideBorders(psi: BoundingBox, leftBorderInside: boolean, rightBorderInside: boolean,
-                             topBorderInside: boolean, bottomBorderInside: boolean): boolean {
-        leftBorderInside = (this.AbsolutePosition.x + this.borderLeft) <= (psi.absolutePosition.x + psi.borderLeft)
-            && (psi.absolutePosition.x + psi.borderLeft) <= (this.AbsolutePosition.x + this.borderRight);
-        rightBorderInside = (this.AbsolutePosition.x + this.borderLeft) <= (psi.absolutePosition.x + psi.borderRight)
-            && (psi.absolutePosition.x + psi.borderRight) <= (this.AbsolutePosition.x + this.borderRight);
-        topBorderInside = (this.AbsolutePosition.y + this.borderTop) <= (psi.absolutePosition.y + psi.borderTop)
-            && (psi.absolutePosition.y + psi.borderTop) <= (this.AbsolutePosition.y + this.borderBottom);
-        bottomBorderInside = (this.AbsolutePosition.y + this.borderTop) <= (psi.absolutePosition.y + psi.borderBottom)
-            && (psi.absolutePosition.y + psi.borderBottom) <= (this.AbsolutePosition.y + this.borderBottom);
-        return topBorderInside && bottomBorderInside && leftBorderInside && rightBorderInside;
-    }
-
-    public liesInsideBorders(position: PointF2D): boolean {
+    public pointLiesInsideBorders(position: PointF2D): boolean {
         let xInside: boolean = (this.AbsolutePosition.x + this.borderLeft) <= position.x && position.x <= (this.AbsolutePosition.x + this.borderRight);
         if (xInside) {
             let yInside: boolean = (this.AbsolutePosition.y + this.borderTop) <= position.y && position.y <= (this.AbsolutePosition.y + this.borderBottom);
@@ -417,7 +396,7 @@ export class BoundingBox {
         return false;
     }
 
-    public liesInsideMargins(position: PointF2D): boolean {
+    public pointLiesInsideMargins(position: PointF2D): boolean {
         let xInside: boolean = (this.AbsolutePosition.x + this.borderMarginLeft) <= position.x
             && position.x <= (this.AbsolutePosition.x + this.borderMarginRight);
         if (xInside) {
@@ -430,10 +409,6 @@ export class BoundingBox {
         return false;
     }
 
-    public computeNonOverlappingPosition(placementPsi: BoundingBox, direction: ColDirEnum, margin: number): void {
-        this.computeNonOverlappingPosition(placementPsi, direction, new PointF2D(0.0, 0.0));
-    }
-
     public computeNonOverlappingPosition(placementPsi: BoundingBox, direction: ColDirEnum, position: PointF2D): void {
         this.RelativePosition = new PointF2D(position.x, position.y);
         this.setAbsolutePositionFromParent();
@@ -462,7 +437,7 @@ export class BoundingBox {
 
     public getClickedObjectOfType<T>(clickPosition: PointF2D): T {
         let obj: Object = this.dataObject;
-        if (this.liesInsideBorders(clickPosition) && (obj instanceof T)) {
+        if (this.pointLiesInsideBorders(clickPosition) && (<T>obj !== undefined)) {
             return (obj as T);
         }
         for (let idx: number = 0, len: number = this.childElements.length; idx < len; ++idx) {
@@ -476,7 +451,7 @@ export class BoundingBox {
     }
 
     public getObjectsInRegion<T>(region: BoundingBox, liesInside: boolean = true): T[] {
-        if (this.dataObject instanceof T) {
+        if (<T>this.dataObject !== undefined) {
             if (liesInside) {
                 if (region.liesInsideBorders(this)) {
                     return [this.dataObject as T];

+ 2 - 1
src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts

@@ -10,8 +10,9 @@ export class GraphicalChordSymbolContainer extends GraphicalObject {
     private chordSymbolContainer: ChordSymbolContainer;
     private graphicalLabel: GraphicalLabel;
     constructor(chordSymbolContainer: ChordSymbolContainer, parent: BoundingBox, textHeight: number, transposeHalftones: number) {
+        super();
         this.chordSymbolContainer = chordSymbolContainer;
-        this.boundingBox = new BoundingBox(parent, this);
+        this.boundingBox = new BoundingBox(this, parent);
         this.calculateLabel(textHeight, transposeHalftones);
     }
     public get GetChordSymbolContainer(): ChordSymbolContainer {

+ 3 - 9
src/MusicalScore/Graphical/GraphicalLabel.ts

@@ -8,16 +8,10 @@ import {MusicSheetCalculator} from "./MusicSheetCalculator";
 export class GraphicalLabel extends Clickable {
     private label: Label;
 
-    constructor(label: Label, textHeight: number, alignment: TextAlignment) {
+    constructor(label: Label, textHeight: number, alignment: TextAlignment, parent: BoundingBox = undefined) {
+        super();
         this.label = label;
-        this.boundingBox = new BoundingBox(this);
-        this.label.fontHeight = textHeight;
-        this.label.textAlignment = alignment;
-    }
-
-    constructor(label: Label, textHeight: number, alignment: TextAlignment, parent: BoundingBox) {
-        this.label = label;
-        this.boundingBox = new BoundingBox(parent, this);
+        this.boundingBox = new BoundingBox(this, parent);
         this.label.fontHeight = textHeight;
         this.label.textAlignment = alignment;
     }

+ 2 - 1
src/MusicalScore/Graphical/GraphicalMusicPage.ts

@@ -12,8 +12,9 @@ export class GraphicalMusicPage extends GraphicalObject {
     private parent: GraphicalMusicSheet;
 
     constructor(parent: GraphicalMusicSheet) {
+        super();
         this.parent = parent;
-        this.boundingBox = new BoundingBox(undefined, this);
+        this.boundingBox = new BoundingBox(this, undefined);
     }
 
     public get MusicSystems(): MusicSystem[] {

+ 15 - 44
src/MusicalScore/Graphical/GraphicalMusicSheet.ts

@@ -16,11 +16,10 @@ import {Fraction} from "../../Common/DataObjects/fraction";
 import {GraphicalNote} from "./GraphicalNote";
 import {Instrument} from "../Instrument";
 import {BoundingBox} from "./BoundingBox";
-import {VoiceEntry} from "../VoiceData/VoiceEntry";
 import {Note} from "../VoiceData/Note";
 import {MusicSheetCalculator} from "./MusicSheetCalculator";
 import {Logging} from "../../Common/logging";
-import {Dictionary} from 'typescript-collections/dist/lib/Dictionary';
+import Dictionary from "typescript-collections/dist/lib/Dictionary";
 import {CollectionUtil} from "../../Util/collectionUtil";
 
 export class GraphicalMusicSheet {
@@ -282,7 +281,8 @@ export class GraphicalMusicSheet {
     }
 
     public getOrCreateVerticalContainer(timestamp: Fraction): VerticalGraphicalStaffEntryContainer {
-        if (this.verticalGraphicalStaffEntryContainers.length === 0 || timestamp > CollectionUtil.getLastElement(this.verticalGraphicalStaffEntryContainers).AbsoluteTimestamp) {
+        if (this.verticalGraphicalStaffEntryContainers.length === 0 ||
+            timestamp > CollectionUtil.getLastElement(this.verticalGraphicalStaffEntryContainers).AbsoluteTimestamp) {
             let verticalGraphicalStaffEntryContainer: VerticalGraphicalStaffEntryContainer =
                 new VerticalGraphicalStaffEntryContainer(this.numberOfStaves, timestamp);
             this.verticalGraphicalStaffEntryContainers.push(verticalGraphicalStaffEntryContainer);
@@ -303,24 +303,12 @@ export class GraphicalMusicSheet {
         return undefined;
     }
 
-    public GetVerticalContainerFromTimestamp(timestamp: Fraction, startIndex: number): VerticalGraphicalStaffEntryContainer {
-        let index: number = this.verticalGraphicalStaffEntryContainers.BinarySearch(
-            startIndex,
-            this.verticalGraphicalStaffEntryContainers.length - startIndex,
-            new VerticalGraphicalStaffEntryContainer(0, timestamp),
-            new VerticalGraphicalStaffEntryContainer.VgseContainerTimestampComparer()
-        );
-        if (index >= 0) {
-            return this.verticalGraphicalStaffEntryContainers[index];
-        }
-        return undefined;
-    }
-
-    public GetVerticalContainerFromTimestamp(timestamp: Fraction): VerticalGraphicalStaffEntryContainer {
-        let index: number = this.verticalGraphicalStaffEntryContainers.BinarySearch(
-            new VerticalGraphicalStaffEntryContainer(0, timestamp),
-            new VerticalGraphicalStaffEntryContainer.VgseContainerTimestampComparer()
-        );
+    public GetVerticalContainerFromTimestamp(timestamp: Fraction, startIndex: number = 0): VerticalGraphicalStaffEntryContainer {
+        let index: number = CollectionUtil.binarySearch(this.verticalGraphicalStaffEntryContainers,
+                                                        new VerticalGraphicalStaffEntryContainer(0, timestamp),
+                                                        VerticalGraphicalStaffEntryContainer.compareByTimestamp,
+                                                        startIndex,
+                                                        this.verticalGraphicalStaffEntryContainers.length - startIndex);
         if (index >= 0) {
             return this.verticalGraphicalStaffEntryContainers[index];
         }
@@ -358,7 +346,7 @@ export class GraphicalMusicSheet {
             rightTS = containers[rightIndex].AbsoluteTimestamp;
         } else {
             leftTS = containers[containers.length - 1].AbsoluteTimestamp;
-            rightTS = new Fraction(this.getLongestStaffEntryDuration(containers.length - 1) + leftTS);
+            rightTS = Fraction.plus(this.getLongestStaffEntryDuration(containers.length - 1), leftTS);
             rightIndex = containers.length;
         }
         let diff: number = rightTS.RealValue - leftTS.RealValue;
@@ -410,14 +398,10 @@ export class GraphicalMusicSheet {
         return false;
     }
 
-    public getMeasureIndex(entry: GraphicalStaffEntry, measureIndex: number, inListIndex: number): boolean {
-        return this.getMeasureIndex(entry.parentMeasure, measureIndex, inListIndex);
-    }
-
     public GetNearesNote(clickPosition: PointF2D, maxClickDist: PointF2D): GraphicalNote {
         let initialSearchArea: number = 10;
         let foundNotes: GraphicalNote[] = [];
-        let region: BoundingBox = new BoundingBox(undefined);
+        let region: BoundingBox = new BoundingBox();
         region.BorderLeft = clickPosition.x - initialSearchArea;
         region.BorderTop = clickPosition.y - initialSearchArea;
         region.BorderRight = clickPosition.x + initialSearchArea;
@@ -464,7 +448,7 @@ export class GraphicalMusicSheet {
     public GetClickableLabel(clickPosition: PointF2D): GraphicalLabel {
         let initialSearchAreaX: number = 4;
         let initialSearchAreaY: number = 4;
-        let region: BoundingBox = new BoundingBox(undefined);
+        let region: BoundingBox = new BoundingBox();
         region.BorderLeft = clickPosition.x - initialSearchAreaX;
         region.BorderTop = clickPosition.y - initialSearchAreaY;
         region.BorderRight = clickPosition.x + initialSearchAreaX;
@@ -583,10 +567,7 @@ export class GraphicalMusicSheet {
     }
 
     public getStaffEntry(index: number): GraphicalStaffEntry {
-        return this.getStaffEntry(this.VerticalGraphicalStaffEntryContainers[index]);
-    }
-
-    public getStaffEntry(container: VerticalGraphicalStaffEntryContainer): GraphicalStaffEntry {
+        let container: VerticalGraphicalStaffEntryContainer = this.VerticalGraphicalStaffEntryContainers[index];
         let staffEntry: GraphicalStaffEntry = undefined;
         try {
             for (let idx: number = 0, len: number = container.StaffEntries.length; idx < len; ++idx) {
@@ -704,10 +685,9 @@ export class GraphicalMusicSheet {
             } else if (nextStaffEntry === undefined) {
                 previousStaffEntryPositionX = previousStaffEntry.PositionAndShape.AbsolutePosition.x;
                 nextStaffEntryPositionX = currentMusicSystem.GetRightBorderAbsoluteXPosition();
+                let sm: SourceMeasure = previousStaffEntry.parentMeasure.parentSourceMeasure;
                 fraction = (currentTimeStamp - previousStaffEntry.getAbsoluteTimestamp().RealValue) / (
-                    (previousStaffEntry.parentMeasure.parentSourceMeasure.AbsoluteTimestamp
-                    + previousStaffEntry.parentMeasure.parentSourceMeasure.Duration).RealValue - previousStaffEntry.getAbsoluteTimestamp().RealValue
-                    );
+                    Fraction.plus(sm.AbsoluteTimestamp, sm.Duration).RealValue - previousStaffEntry.getAbsoluteTimestamp().RealValue);
             } else {
                 previousStaffEntryPositionX = previousStaffEntry.PositionAndShape.AbsolutePosition.x;
                 nextStaffEntryPositionX = nextStaffEntry.PositionAndShape.AbsolutePosition.x;
@@ -778,15 +758,6 @@ export class GraphicalMusicSheet {
         return graphicalMeasure.findGraphicalStaffEntryFromTimestamp(sourceStaffEntry.Timestamp);
     }
 
-    public GetGraphicalFromSourceStaffEntry(voiceEntries: VoiceEntry[]): GraphicalStaffEntry {
-        if (voiceEntries.length === 0) {
-            return undefined;
-        }
-        let sse: SourceStaffEntry = voiceEntries[0].ParentSourceStaffEntry;
-        let graphicalMeasure: StaffMeasure = this.GetGraphicalFromSourceMeasure(sse.VerticalContainerParent.ParentMeasure)[sse.ParentStaff.idInMusicSheet];
-        return graphicalMeasure.findGraphicalStaffEntryFromTimestamp(sse.Timestamp);
-    }
-
     public GetGraphicalNoteFromSourceNote(note: Note, containingGse: GraphicalStaffEntry): GraphicalNote {
         for (let idx: number = 0, len: number = containingGse.notes.length; idx < len; ++idx) {
             let graphicalNotes: GraphicalNote[] = containingGse.notes[idx];

+ 1 - 0
src/MusicalScore/Graphical/GraphicalNote.ts

@@ -10,6 +10,7 @@ import {MusicSheetCalculator} from "./MusicSheetCalculator";
 
 export class GraphicalNote extends GraphicalObject {
     constructor(note: Note, parent: GraphicalStaffEntry) {
+        super();
         this.sourceNote = note;
         this.parentStaffEntry = parent;
     }

+ 8 - 5
src/MusicalScore/Graphical/GraphicalStaffEntry.ts

@@ -15,9 +15,11 @@ import {GraphicalChordSymbolContainer} from "./GraphicalChordSymbolContainer";
 import {GraphicalLyricEntry} from "./GraphicalLyricEntry";
 import {AbstractGraphicalInstruction} from "./AbstractGraphicalInstruction";
 import {GraphicalStaffEntryLink} from "./GraphicalStaffEntryLink";
+import {CollectionUtil} from "../../Util/collectionUtil";
 
 export class GraphicalStaffEntry extends GraphicalObject {
     constructor(parentMeasure: StaffMeasure, sourceStaffEntry: SourceStaffEntry = undefined, staffEntryParent: GraphicalStaffEntry = undefined) {
+        super();
         this.parentMeasure = parentMeasure;
         this.notes = [];
         this.graceStaffEntriesBefore = [];
@@ -26,9 +28,9 @@ export class GraphicalStaffEntry extends GraphicalObject {
         if (staffEntryParent !== undefined) {
             this.staffEntryParent = staffEntryParent;
             this.parentVerticalContainer = staffEntryParent.parentVerticalContainer;
-            this.PositionAndShape = new BoundingBox(staffEntryParent.PositionAndShape, this);
+            this.PositionAndShape = new BoundingBox(this, staffEntryParent.PositionAndShape);
         } else {
-            this.PositionAndShape = new BoundingBox(parentMeasure.PositionAndShape, this);
+            this.PositionAndShape = new BoundingBox(this, parentMeasure.PositionAndShape);
         }
         if (sourceStaffEntry !== undefined) {
             this.relInMeasureTimestamp = sourceStaffEntry.Timestamp;
@@ -65,7 +67,7 @@ export class GraphicalStaffEntry extends GraphicalObject {
     public getAbsoluteTimestamp(): Fraction {
         let result: Fraction = Fraction.createFromFraction(this.parentMeasure.parentSourceMeasure.AbsoluteTimestamp);
         if (this.relInMeasureTimestamp !== undefined) {
-            result += this.relInMeasureTimestamp;
+            result.Add(this.relInMeasureTimestamp);
         }
         return result;
     }
@@ -196,7 +198,7 @@ export class GraphicalStaffEntry extends GraphicalObject {
     public getMainVoice(): Voice {
         for (let idx: number = 0, len: number = this.sourceStaffEntry.VoiceEntries.length; idx < len; ++idx) {
             let voiceEntry: VoiceEntry = this.sourceStaffEntry.VoiceEntries[idx];
-            if (voiceEntry.ParentVoice.GetType() !== /*typeof*/LinkedVoice) {
+            if (!(voiceEntry.ParentVoice instanceof LinkedVoice)) {
                 return voiceEntry.ParentVoice;
             }
         }
@@ -273,7 +275,8 @@ export class GraphicalStaffEntry extends GraphicalObject {
     }
 
     public addGraphicalNoteToListAtCorrectYPosition(graphicalNotes: GraphicalNote[], graphicalNote: GraphicalNote): void {
-        if (graphicalNotes.length === 0 || graphicalNote.PositionAndShape.RelativePosition.y < graphicalNotes.Last().PositionAndShape.RelativePosition.Y) {
+        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--) {

+ 41 - 39
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -50,7 +50,7 @@ import {MidiInstrument} from "../VoiceData/Instructions/ClefInstruction";
 import {Staff} from "../VoiceData/Staff";
 import {OctaveShift} from "../VoiceData/Expressions/ContinuousExpressions/octaveShift";
 import {Logging} from "../../Common/logging";
-import {Dictionary} from 'typescript-collections/dist/lib/Dictionary';
+import Dictionary from "typescript-collections/dist/lib/Dictionary";
 import {CollectionUtil} from "../../Util/collectionUtil";
 
 export class MusicSheetCalculator {
@@ -87,14 +87,15 @@ export class MusicSheetCalculator {
         for (let m: number = 0; m < note.NoteTie.Fractions.length; m++) {
             let musicTimestamp: Fraction;
             if (m === 0) {
-                musicTimestamp = new Fraction(note.calculateNoteLengthWithoutTie() + note.getAbsoluteTimestamp());
+                musicTimestamp = Fraction.plus(note.calculateNoteLengthWithoutTie(), note.getAbsoluteTimestamp());
             } else {
-                musicTimestamp = new Fraction(tieTimestampList[m - 1] + note.NoteTie.Fractions[m - 1]);
+                musicTimestamp = Fraction.plus(tieTimestampList[m - 1], note.NoteTie.Fractions[m - 1]);
             }
             tieTimestampList.push(musicTimestamp);
         }
         tieTimestampListDict.setValue(note.NoteTie, tieTimestampList);
     }
+
     private static setMeasuresMinStaffEntriesWidth(measures: StaffMeasure[], minimumStaffEntriesWidth: number): void {
         for (let idx: number = 0, len: number = measures.length; idx < len; ++idx) {
             let measure: StaffMeasure = measures[idx];
@@ -178,90 +179,90 @@ export class MusicSheetCalculator {
     }
 
     protected calculateMeasureXLayout(measures: StaffMeasure[]): number {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected calculateSystemYLayout(): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected initStaffMeasuresCreation(): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected handleBeam(graphicalNote: GraphicalNote, beam: Beam, openBeams: Beam[]): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected createGraphicalTieNote(beams: Beam[], activeClef: ClefInstruction,
                                      octaveShiftValue: OctaveEnum,
                                      graphicalStaffEntry: GraphicalStaffEntry, duration: Fraction, numberOfDots: number,
                                      openTie: Tie, isLastTieNote: boolean): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
-    protected handleVoiceEntryLyrics(lyricsEntries: { [_: number]: LyricsEntry; }, voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry,
+    protected handleVoiceEntryLyrics(lyricsEntries: Dictionary<number, LyricsEntry>, voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry,
                                      openLyricWords: LyricWord[]): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected handleVoiceEntryOrnaments(ornamentContainer: OrnamentContainer, voiceEntry: VoiceEntry,
                                         graphicalStaffEntry: GraphicalStaffEntry): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected handleVoiceEntryArticulations(articulations: ArticulationEnum[],
                                             voiceEntry: VoiceEntry,
                                             graphicalStaffEntry: GraphicalStaffEntry): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected handleTuplet(graphicalNote: GraphicalNote, tuplet: Tuplet, openTuplets: Tuplet[]): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected layoutVoiceEntry(voiceEntry: VoiceEntry, graphicalNotes: GraphicalNote[],
                                graphicalStaffEntry: GraphicalStaffEntry, hasPitchedNote: boolean, isGraceStaffEntry: boolean): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected layoutStaffEntry(graphicalStaffEntry: GraphicalStaffEntry): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected handleTie(tie: Tie, startGraphicalStaffEntry: GraphicalStaffEntry, staffIndex: number,
                         measureIndex: number): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected updateStaffLineBorders(staffLine: StaffLine): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected calculateMeasureNumberPlacement(musicSystem: MusicSystem): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected layoutGraphicalTie(tie: GraphicalTie, tieIsAtSystemBreak: boolean): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected calculateSingleStaffLineLyricsPosition(staffLine: StaffLine, lyricVersesNumber: number[]): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected calculateSingleOctaveShift(sourceMeasure: SourceMeasure, multiExpression: MultiExpression,
                                          measureIndex: number, staffIndex: number): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected calculateWordRepetitionInstruction(repetitionInstruction: RepetitionInstruction,
                                                  measureIndex: number): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected calculateMoodAndUnknownExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
-        throw new Error("not implemented");
+        throw new Error("abstract, not implemented");
     }
 
     protected clearRecreatedObjects(): void {
@@ -452,11 +453,6 @@ export class MusicSheetCalculator {
         return;
     }
 
-    protected layoutFingering(staffLine: StaffLine, skyBottomLineCalculator: SkyBottomLineCalculator,
-                              staffEntry: GraphicalStaffEntry, measureRelativePosition: PointF2D): void {
-        return;
-    }
-
     protected calculateDynamicExpressionsForSingleMultiExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
         return;
     }
@@ -561,7 +557,7 @@ export class MusicSheetCalculator {
         if (voiceEntry.TechnicalInstructions.length > 0) {
             this.checkVoiceEntriesForTechnicalInstructions(voiceEntry, graphicalStaffEntry);
         }
-        if (voiceEntry.LyricsEntries.size > 0) {
+        if (voiceEntry.LyricsEntries.size() > 0) {
             this.handleVoiceEntryLyrics(voiceEntry.LyricsEntries, voiceEntry, graphicalStaffEntry, openLyricWords);
         }
         if (voiceEntry.OrnamentContainer !== undefined) {
@@ -595,8 +591,7 @@ export class MusicSheetCalculator {
 
     protected handleOpenTies(measure: StaffMeasure, beams: Beam[], tieTimestampListDict: Dictionary<Tie, Fraction[]>,
                              activeClef: ClefInstruction, octaveShiftParams: OctaveShiftParams): void {
-
-        CollectionUtil.removeDictElementIfTrue(tieTimestampListDict, function(openTie: Tie, tieTimestamps: Fraction[]): boolean {
+        CollectionUtil.removeDictElementIfTrue(tieTimestampListDict, function (openTie: Tie, tieTimestamps: Fraction[]): boolean {
             // for (let m: number = tieTimestampListDict.size() - 1; m >= 0; m--) {
             //     let keyValuePair: KeyValuePair<Tie, Fraction[]> = tieTimestampListDict.ElementAt(m);
             //     let openTie: Tie = keyValuePair.Key;
@@ -607,7 +602,7 @@ export class MusicSheetCalculator {
             for (; k < tieTimestamps.length; k++) {
                 if (!openTie.NoteHasBeenCreated[k]) {
                     absoluteTimestamp = tieTimestamps[k];
-                    if (absoluteTimestamp >= (measure.parentSourceMeasure.AbsoluteTimestamp + measure.parentSourceMeasure.Duration)) {
+                    if (absoluteTimestamp >= Fraction.plus(measure.parentSourceMeasure.AbsoluteTimestamp, measure.parentSourceMeasure.Duration)) {
                         continue;
                     }
                     let graphicalStaffEntry: GraphicalStaffEntry = undefined;
@@ -808,8 +803,8 @@ export class MusicSheetCalculator {
             if (leftStaffEntry !== rightStaffEntry) {
                 let leftTimestamp: Fraction = leftStaffEntry.getAbsoluteTimestamp();
                 let rightTimestamp: Fraction = rightStaffEntry.getAbsoluteTimestamp();
-                let leftDifference: Fraction = new Fraction(timestamp - leftTimestamp);
-                timestampQuotient = leftDifference.RealValue / (rightTimestamp - leftTimestamp).RealValue;
+                let leftDifference: Fraction = Fraction.minus(timestamp, leftTimestamp);
+                timestampQuotient = leftDifference.RealValue / Fraction.minus(rightTimestamp, leftTimestamp).RealValue;
             }
             if (leftStaffEntry.parentMeasure.ParentStaffLine !== rightStaffEntry.parentMeasure.ParentStaffLine) {
                 if (leftStaffEntry.parentMeasure.ParentStaffLine === staffLine) {
@@ -893,7 +888,7 @@ export class MusicSheetCalculator {
             );
             verticalMeasureList.push(measure);
         }
-        this.graphicalMusicSheet.sourceToGraphicalMeasureLinks[sourceMeasure] = verticalMeasureList;
+        this.graphicalMusicSheet.sourceToGraphicalMeasureLinks.setValue(sourceMeasure, verticalMeasureList);
         return verticalMeasureList;
     }
 
@@ -989,7 +984,7 @@ export class MusicSheetCalculator {
                 }
             }
         }
-        if (tieTimestampListDict.size > 0) {
+        if (tieTimestampListDict.size() > 0) {
             this.handleOpenTies(
                 measure, openBeams,
                 tieTimestampListDict, activeClefs[staffIndex], openOctaveShifts[staffIndex]
@@ -1021,7 +1016,11 @@ export class MusicSheetCalculator {
             let graphicalNotes: GraphicalNote[] = [];
             graphicalStaffEntry.notes.push(graphicalNotes);
             let numberOfDots: number = note.calculateNumberOfNeededDots();
-            let graphicalNote: GraphicalNote = this.symbolFactory.createNote(note, numberOfDots, graphicalStaffEntry, new ClefInstruction(ClefEnum.G, 0, 2));
+            let graphicalNote: GraphicalNote = this.symbolFactory.createNote(   note,
+                                                                                numberOfDots,
+                                                                                graphicalStaffEntry,
+                                                                                new ClefInstruction(ClefEnum.G, 0, 2),
+                                                                                OctaveEnum.NONE);
             graphicalNotes.push(graphicalNote);
             graphicalStaffEntry.PositionAndShape.ChildElements.push(graphicalNote.PositionAndShape);
         }
@@ -1101,11 +1100,14 @@ export class MusicSheetCalculator {
         }
         accidentalCalculator.checkAccidental(graphicalNote, pitch, grace, scalingFactor);
     }
-
+    // needed to disable linter, as it doesn't recognize the existing usage of this method.
+    // ToDo: check if a newer version doesn't have the problem.
+    /* tslint:disable:no-unused-variable */
     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.relInMeasureTimestamp = new Fraction(absoluteTimestamp - measure.parentSourceMeasure.AbsoluteTimestamp);
+        graphicalStaffEntry.relInMeasureTimestamp = Fraction.minus(absoluteTimestamp, measure.parentSourceMeasure.AbsoluteTimestamp);
         this.resetYPositionForLeadSheet(graphicalStaffEntry.PositionAndShape);
         measure.addGraphicalStaffEntry(graphicalStaffEntry);
         return graphicalStaffEntry;

+ 14 - 13
src/MusicalScore/Graphical/MusicSystem.ts

@@ -13,6 +13,8 @@ import {EngravingRules} from "./EngravingRules";
 import {PointF2D} from "../../Common/DataObjects/PointF2D";
 import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
 import {SystemLinesEnum} from "./SystemLinesEnum";
+import Dictionary from "typescript-collections/dist/lib/Dictionary";
+import {CollectionUtil} from "../../Util/collectionUtil";
 
 export class MusicSystem extends GraphicalObject {
     public needsToBeRedrawn: boolean = true;
@@ -26,9 +28,10 @@ export class MusicSystem extends GraphicalObject {
     protected objectsToRedraw: [Object[], Object][] = [];
 
     constructor(parent: GraphicalMusicPage, id: number) {
+        super();
         this.parent = parent;
         this.id = id;
-        this.boundingBox = new BoundingBox(parent.PositionAndShape, this);
+        this.boundingBox = new BoundingBox(this, parent.PositionAndShape);
         this.maxLabelLength = 0.0;
     }
 
@@ -53,7 +56,7 @@ export class MusicSystem extends GraphicalObject {
     }
 
     public get Labels(): GraphicalLabel[] {
-        return this.labels.GetKeys();
+        return this.labels.keys();
     }
 
     public get ObjectsToRedraw(): [Object[], Object][] {
@@ -106,7 +109,7 @@ export class MusicSystem extends GraphicalObject {
 
     public GetSystemsLastTimeStamp(): Fraction {
         let m: SourceMeasure = this.graphicalMeasures[this.graphicalMeasures.length - 1][0].parentSourceMeasure;
-        return m.AbsoluteTimestamp + m.Duration;
+        return Fraction.plus(m.AbsoluteTimestamp, m.Duration);
     }
 
     public createInstrumentBrackets(instruments: Instrument[], staffHeight: number): void {
@@ -155,7 +158,7 @@ export class MusicSystem extends GraphicalObject {
                 if (staffLine.ParentStaff === instrument1.Staves[0]) {
                     firstStaffLine = staffLine;
                 }
-                if (staffLine.ParentStaff === instrument2.Staves.Last()) {
+                if (staffLine.ParentStaff === CollectionUtil.last(instrument2.Staves)) {
                     lastStaffLine = staffLine;
                 }
             }
@@ -186,12 +189,12 @@ export class MusicSystem extends GraphicalObject {
                     instrument.NameLabel, instrumentLabelTextHeight, TextAlignment.LeftCenter, this.boundingBox
                 );
                 graphicalLabel.setLabelPositionAndShapeBorders();
-                this.labels.push(graphicalLabel, instrument);
+                this.labels.setValue(graphicalLabel, instrument);
                 this.boundingBox.ChildElements.push(graphicalLabel.PositionAndShape);
                 graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0.0, 0.0);
             }
             this.maxLabelLength = 0.0;
-            let labels: GraphicalLabel[] = this.labels.Keys;
+            let labels: GraphicalLabel[] = this.labels.keys();
             for (let idx: number = 0, len: number = labels.length; idx < len; ++idx) {
                 let label: GraphicalLabel = labels[idx];
                 if (label.PositionAndShape.Size.width > this.maxLabelLength) {
@@ -204,16 +207,14 @@ export class MusicSystem extends GraphicalObject {
 
     public setMusicSystemLabelsYPosition(): void {
         if (this.parent === this.parent.Parent.MusicPages[0] && this === this.parent.MusicSystems[0]) {
-            let labels: KeyValuePair<GraphicalLabel, Instrument>[] = this.labels;
-            for (let idx: number = 0, len: number = labels.length; idx < len; ++idx) {
-                let entry: KeyValuePair<GraphicalLabel, Instrument> = labels[idx];
+            this.labels.forEach((key: GraphicalLabel, value: Instrument): void => {
                 let ypositionSum: number = 0;
                 let staffCounter: number = 0;
                 for (let i: number = 0; i < this.staffLines.length; i++) {
-                    if (this.staffLines[i].ParentStaff.ParentInstrument === entry.Value) {
+                    if (this.staffLines[i].ParentStaff.ParentInstrument === value) {
                         for (let j: number = i; j < this.staffLines.length; j++) {
                             let staffLine: StaffLine = this.staffLines[j];
-                            if (staffLine.ParentStaff.ParentInstrument !== entry.Value) {
+                            if (staffLine.ParentStaff.ParentInstrument !== value) {
                                 break;
                             }
                             ypositionSum += staffLine.PositionAndShape.RelativePosition.y;
@@ -223,9 +224,9 @@ export class MusicSystem extends GraphicalObject {
                     }
                 }
                 if (staffCounter > 0) {
-                    entry.Key.PositionAndShape.RelativePosition = new PointF2D(0.0, ypositionSum / staffCounter + 2.0);
+                    key.PositionAndShape.RelativePosition = new PointF2D(0.0, ypositionSum / staffCounter + 2.0);
                 }
-            }
+            });
         }
     }
 

+ 16 - 7
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -8,7 +8,6 @@ import {SourceMeasure} from "../VoiceData/SourceMeasure";
 import {MusicSystem} from "./MusicSystem";
 import {BoundingBox} from "./BoundingBox";
 import {Staff} from "../VoiceData/Staff";
-import {MusicSheet} from "../MusicSheet";
 import {Instrument} from "../Instrument";
 import {PointF2D} from "../../Common/DataObjects/PointF2D";
 import {StaffLine} from "./StaffLine";
@@ -20,6 +19,7 @@ import {GraphicalMusicSheet} from "./GraphicalMusicSheet";
 import {IGraphicalSymbolFactory} from "../Interfaces/IGraphicalSymbolFactory";
 import {MusicSheetCalculator} from "./MusicSheetCalculator";
 import {MidiInstrument} from "../VoiceData/Instructions/ClefInstruction";
+import {CollectionUtil} from "../../Util/collectionUtil";
 
 export class MusicSystemBuilder {
     private measureList: StaffMeasure[][];
@@ -68,7 +68,14 @@ export class MusicSystemBuilder {
             this.rules.LabelMarginBorderFactor
         );
         this.currentPageHeight += this.currentSystemParams.currentSystem.PositionAndShape.RelativePosition.y;
-        let numberOfMeasures: number = this.measureList.length(m => m.Any());
+
+        let numberOfMeasures: number = 0;
+        for (let idx: number = 0, len: number = this.measureList.length; idx < len; ++idx) {
+            if (this.measureList[idx].length > 0) {
+                numberOfMeasures++;
+            }
+        }
+
         while (this.measureListIndex < numberOfMeasures) {
             let staffMeasures: StaffMeasure[] = this.measureList[this.measureListIndex];
             for (let idx: number = 0, len: number = staffMeasures.length; idx < len; ++idx) {
@@ -222,10 +229,12 @@ export class MusicSystemBuilder {
         boundingBox.BorderRight = systemWidth;
         boundingBox.BorderTop = 0.0;
         let staffList: Staff[] = [];
-        let musicSheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
-        let instruments: Instrument[] = musicSheet.Instruments.Where(i => i.Voices.length > 0 && i.Voices[0].Visible);
+        let instruments: Instrument[] = this.graphicalMusicSheet.ParentMusicSheet.Instruments;
         for (let idx: number = 0, len: number = instruments.length; idx < len; ++idx) {
             let instrument: Instrument = instruments[idx];
+            if (instrument.Voices.length === 0 || !instrument.Visible) {
+                continue;
+            }
             for (let idx2: number = 0, len2: number = instrument.Staves.length; idx2 < len2; ++idx2) {
                 let staff: Staff = instrument.Staves[idx2];
                 staffList.push(staff);
@@ -581,7 +590,7 @@ export class MusicSystemBuilder {
         if (this.thisMeasureEndsLineRepetition()) {
             return SystemLinesEnum.DotsThinBold;
         }
-        if (this.measureListIndex === this.measureList.length - 1 || this.measureList[this.measureListIndex][0].parentSourceMeasure.EndsPiece) {
+        if (this.measureListIndex === this.measureList.length - 1 || this.measureList[this.measureListIndex][0].parentSourceMeasure.endsPiece) {
             return SystemLinesEnum.ThinBold;
         }
         if (this.nextMeasureHasKeyInstructionChange() || this.thisMeasureEndsWordRepetition() || this.nextMeasureBeginsWordRepetition()) {
@@ -755,8 +764,8 @@ export class MusicSystemBuilder {
 
     private decreaseMusicSystemBorders(): void {
         let currentSystem: MusicSystem = this.currentSystemParams.currentSystem;
-        let width: number = currentSystem.StaffLines[0].Measures.Last().PositionAndShape.RelativePosition.x
-            + currentSystem.StaffLines[0].Measures.Last().PositionAndShape.Size.width;
+        let bb: BoundingBox = CollectionUtil.last(currentSystem.StaffLines[0].Measures).PositionAndShape;
+        let width: number = bb.RelativePosition.x + bb.Size.width;
         for (let idx: number = 0, len: number = currentSystem.StaffLines.length; idx < len; ++idx) {
             let staffLine: StaffLine = currentSystem.StaffLines[idx];
             staffLine.PositionAndShape.BorderRight = width;

+ 2 - 1
src/MusicalScore/Graphical/StaffLine.ts

@@ -18,9 +18,10 @@ export class StaffLine extends GraphicalObject {
     protected bottomLine: number[];
 
     constructor(parentSystem: MusicSystem, parentStaff: Staff) {
+        super();
         this.parentMusicSystem = parentSystem;
         this.parentStaff = parentStaff;
-        this.boundingBox = new BoundingBox(parentSystem.PositionAndShape, this);
+        this.boundingBox = new BoundingBox(this, parentSystem.PositionAndShape);
     }
 
     public get Measures(): StaffMeasure[] {

+ 2 - 1
src/MusicalScore/Graphical/StaffLineActivitySymbol.ts

@@ -4,9 +4,10 @@ import {BoundingBox} from "./BoundingBox";
 
 export class StaffLineActivitySymbol extends GraphicalObject {
     constructor(staffLine: StaffLine) {
+        super();
         this.parentStaffLine = staffLine;
         let staffLinePsi: BoundingBox = staffLine.PositionAndShape;
-        this.boundingBox = new BoundingBox(staffLinePsi, this);
+        this.boundingBox = new BoundingBox(this, staffLinePsi);
         this.boundingBox.BorderRight = 6;
         this.boundingBox.BorderBottom = 4.5;
         this.boundingBox.BorderLeft = -1.5;

+ 2 - 1
src/MusicalScore/Graphical/StaffMeasure.ts

@@ -19,12 +19,13 @@ export class StaffMeasure extends GraphicalObject {
     protected lastInstructionStaffEntry: GraphicalStaffEntry;
 
     constructor(staff: Staff = undefined, parentSourceMeasure: SourceMeasure = undefined, staffLine: StaffLine = undefined) {
+        super();
         this.parentStaff = staff;
         this.parentSourceMeasure = parentSourceMeasure;
         this.parentStaffLine = staffLine;
         if (staffLine !== undefined) {
             this.parentStaff = staffLine.ParentStaff;
-            this.PositionAndShape = new BoundingBox(staffLine.PositionAndShape, this);
+            this.PositionAndShape = new BoundingBox(this, staffLine.PositionAndShape);
         } else {
             this.PositionAndShape = new BoundingBox(this);
         }

+ 14 - 5
src/MusicalScore/Graphical/VerticalGraphicalStaffEntryContainer.ts

@@ -38,6 +38,19 @@ export class VerticalGraphicalStaffEntryContainer {
         this.staffEntries = value;
     }
 
+    public static compareByTimestamp(x: VerticalGraphicalStaffEntryContainer, y: VerticalGraphicalStaffEntryContainer): number {
+        let xValue: number = x.absoluteTimestamp.RealValue;
+        let yValue: number = y.absoluteTimestamp.RealValue;
+
+        if (xValue < yValue) {
+            return -1;
+        } else if (xValue > yValue) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+
     public getFirstNonNullStaffEntry(): GraphicalStaffEntry {
         for (let idx: number = 0, len: number = this.staffEntries.length; idx < len; ++idx) {
             let graphicalStaffEntry: GraphicalStaffEntry = this.staffEntries[idx];
@@ -49,8 +62,4 @@ export class VerticalGraphicalStaffEntryContainer {
     }
 }
 
-export class VgseContainerTimestampComparer implements IComparer<VerticalGraphicalStaffEntryContainer> {
-    public Compare(x: VerticalGraphicalStaffEntryContainer, y: VerticalGraphicalStaffEntryContainer): number {
-        return Comparer.Default.Compare(x.AbsoluteTimestamp.RealValue, y.AbsoluteTimestamp.RealValue);
-    }
-}
+

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

@@ -1,4 +1,4 @@
-import {StaffMeasure} from "../StaffMeasure";
+import {StaffMeasure} from "../StaffMeasure";
 import {SourceMeasure} from "../../VoiceData/SourceMeasure";
 import {Staff} from "../../VoiceData/Staff";
 import {StaffLine} from "../StaffLine";

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

@@ -23,6 +23,7 @@ import {LyricWord} from "../../VoiceData/Lyrics/LyricsWord";
 import {OrnamentContainer} from "../../VoiceData/OrnamentContainer";
 import {ArticulationEnum} from "../../VoiceData/VoiceEntry";
 import {Tuplet} from "../../VoiceData/Tuplet";
+import Dictionary from "typescript-collections/dist/lib/Dictionary";
 //import {VexFlowMeasure} from "./VexFlowMeasure";
 
 export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
@@ -183,7 +184,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
         return;
     }
 
-    protected handleVoiceEntryLyrics(lyricsEntries: { [_: number]: LyricsEntry; }, voiceEntry: VoiceEntry,
+    protected handleVoiceEntryLyrics(lyricsEntries: Dictionary<number, LyricsEntry>, voiceEntry: VoiceEntry,
                                      graphicalStaffEntry: GraphicalStaffEntry, openLyricWords: LyricWord[]): void {
         return;
     }

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

@@ -1,4 +1,18 @@
-export interface IGraphicalSymbolFactory {
+import {GraphicalMusicPage} from "../Graphical/GraphicalMusicPage";
+import {MusicSystem} from "../Graphical/MusicSystem";
+import {Staff} from "../VoiceData/Staff";
+import {StaffLine} from "../Graphical/StaffLine";
+import {SourceMeasure} from "../VoiceData/SourceMeasure";
+import {StaffMeasure} from "../Graphical/StaffMeasure";
+import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
+import {GraphicalStaffEntry} from "../Graphical/GraphicalStaffEntry";
+import {Note} from "../VoiceData/Note";
+import {ClefInstruction} from "../VoiceData/Instructions/ClefInstruction";
+import {OctaveEnum} from "../VoiceData/Expressions/ContinuousExpressions/octaveShift";
+import {GraphicalNote} from "../Graphical/GraphicalNote";
+import {Pitch} from "../../Common/DataObjects/pitch";
+import {TechnicalInstruction} from "../VoiceData/Instructions/TechnicalInstruction";
+export interface IGraphicalSymbolFactory {
     createMusicSystem(page: GraphicalMusicPage, systemIndex: number): MusicSystem;
     createStaffLine(parentSystem: MusicSystem, parentStaff: Staff): StaffLine;
     createStaffMeasure(sourceMeasure: SourceMeasure, staff: Staff): StaffMeasure;
@@ -6,9 +20,9 @@
     createStaffEntry(sourceStaffEntry: SourceStaffEntry, measure: StaffMeasure): GraphicalStaffEntry;
     createGraceStaffEntry(staffEntryParent: GraphicalStaffEntry, measure: StaffMeasure): GraphicalStaffEntry;
     createNote(note: Note, numberOfDots: number, graphicalStaffEntry: GraphicalStaffEntry, activeClef: ClefInstruction,
-        octaveShift: OctaveEnum = OctaveEnum.NONE): GraphicalNote;
+        octaveShift: OctaveEnum): GraphicalNote;
     createGraceNote(note: Note, numberOfDots: number, graphicalStaffEntry: GraphicalStaffEntry, activeClef: ClefInstruction,
-        octaveShift: OctaveEnum = OctaveEnum.NONE): GraphicalNote;
+        octaveShift: OctaveEnum): GraphicalNote;
     addGraphicalAccidental(graphicalNote: GraphicalNote, pitch: Pitch, grace: boolean, graceScalingFactor: number): void;
     addFermataAtTiedEndNote(tiedNote: Note, graphicalStaffEntry: GraphicalStaffEntry): void;
     createGraphicalTechnicalInstruction(technicalInstruction: TechnicalInstruction,

+ 8 - 10
src/MusicalScore/ScoreIO/VoiceGenerator.ts

@@ -26,6 +26,7 @@ import {Logging} from "../../Common/logging";
 import {Pitch} from "../../Common/DataObjects/pitch";
 import {IXmlAttribute} from "../../Common/FileIO/Xml";
 import {CollectionUtil} from "../../Util/collectionUtil";
+import Dictionary from "typescript-collections/dist/lib/Dictionary";
 
 type SlurReader = any;
 
@@ -758,7 +759,7 @@ export class VoiceGenerator {
                                         slur.EndNote.NoteSlurs.push(slur);
                                     }
                                 }
-                                let lyricsEntries: { [n: number]: LyricsEntry; } = this.currentVoiceEntry.LyricsEntries;
+                                let lyricsEntries: Dictionary<number, LyricsEntry> = this.currentVoiceEntry.LyricsEntries;
                                 for (let lyricsEntry in lyricsEntries) {
                                     if (lyricsEntries.hasOwnProperty(lyricsEntry)) {
                                         let val: LyricsEntry = this.currentVoiceEntry.LyricsEntries[lyricsEntry];
@@ -804,16 +805,13 @@ export class VoiceGenerator {
                             slur.EndNote.NoteSlurs.push(slur);
                         }
                     }
-                    let lyricsEntries: { [_: number]: LyricsEntry; } = this.currentVoiceEntry.LyricsEntries;
-                    for (let key in lyricsEntries) {
-                        if (lyricsEntries.hasOwnProperty(key)) {
-                            let lyricsEntry: LyricsEntry = lyricsEntries[key];
-                            if (!tieStartNote.ParentVoiceEntry.LyricsEntries.hasOwnProperty(key)) {
-                                tieStartNote.ParentVoiceEntry.LyricsEntries[key] = lyricsEntry;
-                                lyricsEntry.Parent = tieStartNote.ParentVoiceEntry;
-                            }
+
+                    this.currentVoiceEntry.LyricsEntries.forEach((key: number, value: LyricsEntry): void => {
+                        if (!tieStartNote.ParentVoiceEntry.LyricsEntries.containsKey(key)) {
+                            tieStartNote.ParentVoiceEntry.LyricsEntries.setValue(key, value);
+                            value.Parent = tieStartNote.ParentVoiceEntry;
                         }
-                    }
+                    });
                     if (maxTieNoteFraction.lt(Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length))) {
                         maxTieNoteFraction = Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length);
                     }

+ 6 - 5
src/MusicalScore/VoiceData/ChordSymbolContainer.ts

@@ -40,13 +40,13 @@ export class ChordSymbolContainer {
     public static calculateChordText(chordSymbol: ChordSymbolContainer, transposeHalftones: number): string {
         let transposedRootPitch: Pitch = chordSymbol.RootPitch;
         if (MusicSheetCalculator.transposeCalculator !== undefined) {
-            transposedRootPitch = MusicSheetCalculator.transposeCalculator.TransposePitch(
+            transposedRootPitch = MusicSheetCalculator.transposeCalculator.transposePitch(
                 chordSymbol.RootPitch,
                 chordSymbol.KeyInstruction,
                 transposeHalftones
             );
         }
-        let text: string = transposedRootPitch.FundamentalNote.ToString();
+        let text: string = Pitch.getNoteEnumString(transposedRootPitch.FundamentalNote);
         if (transposedRootPitch.Accidental !== AccidentalEnum.NONE) {
             text += this.getTextForAccidental(transposedRootPitch.Accidental);
         }
@@ -54,14 +54,14 @@ export class ChordSymbolContainer {
         if (chordSymbol.BassPitch !== undefined) {
             let transposedBassPitch: Pitch = chordSymbol.BassPitch;
             if (MusicSheetCalculator.transposeCalculator !== undefined) {
-                transposedBassPitch = MusicSheetCalculator.transposeCalculator.TransposePitch(
+                transposedBassPitch = MusicSheetCalculator.transposeCalculator.transposePitch(
                     chordSymbol.BassPitch,
                     chordSymbol.KeyInstruction,
                     transposeHalftones
                 );
             }
             text += "/";
-            text += transposedBassPitch.FundamentalNote.ToString();
+            text += Pitch.getNoteEnumString(transposedBassPitch.FundamentalNote);
             text += this.getTextForAccidental(transposedBassPitch.Accidental);
         }
         if (chordSymbol.ChordDegree !== undefined) {
@@ -187,7 +187,8 @@ export class ChordSymbolContainer {
             case ChordSymbolEnum.power:
             case ChordSymbolEnum.Tristan:
                 break;
-            default
+            default:
+                break;
         }
         return text;
     }

+ 4 - 4
src/MusicalScore/VoiceData/SourceStaffEntry.ts

@@ -147,8 +147,8 @@ export class SourceStaffEntry {
           if (duration > note.calculateNoteLengthWithoutTie()) {
             duration = note.calculateNoteLengthWithoutTie();
           }
-        } else if (duration > note.length) {
-            duration = note.length;
+        } else if (duration > note.Length) {
+            duration = note.Length;
         }
       }
     }
@@ -165,10 +165,10 @@ export class SourceStaffEntry {
             duration = note.calculateNoteLengthWithoutTie();
             for (let idx3: number = 0, len3: number = note.NoteTie.Fractions.length; idx3 < len3; ++idx3) {
               let fraction: Fraction = note.NoteTie.Fractions[idx3];
-              duration.push(fraction);
+              duration.Add(fraction);
             }
           }
-        } else if (duration < note.length) { duration = note.length; }
+        } else if (duration < note.Length) { duration = note.Length; }
       }
     }
     return duration;

+ 7 - 9
src/MusicalScore/VoiceData/VoiceEntry.ts

@@ -9,7 +9,7 @@ import {OrnamentContainer} from "./OrnamentContainer";
 import {KeyInstruction} from "./Instructions/KeyInstruction";
 import {OrnamentEnum} from "./OrnamentContainer";
 import {AccidentalEnum} from "../../Common/DataObjects/pitch";
-import {Dictionary} from 'typescript-collections/dist/lib/Dictionary';
+import Dictionary from "typescript-collections/dist/lib/Dictionary";
 
 export class VoiceEntry {
     constructor(timestamp: Fraction, parentVoice: Voice, parentSourceStaffEntry: SourceStaffEntry) {
@@ -119,15 +119,13 @@ export class VoiceEntry {
         return false;
     }
     public getVerseNumberForLyricEntry(lyricsEntry: LyricsEntry): number {
-        let lyricsEntries: { [n: number]: LyricsEntry; } = this.lyricsEntries;
-        for (let key in lyricsEntries) {
-            if (lyricsEntries.hasOwnProperty(key)) { // FIXME check has own property
-                if (lyricsEntry === this.lyricsEntries[key]) {
-                    return +key;
-                }
+        let verseNumber: number = 1;
+        this.lyricsEntries.forEach((key: number, value: LyricsEntry): void => {
+            if (lyricsEntry === value) {
+                verseNumber = key;
             }
-        }
-        return 1;
+        });
+        return verseNumber;
     }
     //public createVoiceEntriesForOrnament(activeKey: KeyInstruction): VoiceEntry[] {
     //    return this.createVoiceEntriesForOrnament(this, activeKey);

+ 31 - 8
src/Util/collectionUtil.ts

@@ -1,4 +1,4 @@
-import {Dictionary} from 'typescript-collections/dist/lib/Dictionary';
+import Dictionary from "typescript-collections/dist/lib/Dictionary";
 
 export class CollectionUtil {
 
@@ -23,21 +23,44 @@ export class CollectionUtil {
      * @param dict
      * @param iterationFunction
      */
-    public static removeDictElementIfTrue<T, V>(dict: Dictionary<T, V>, iterationFunction: (key: T, value: V) => boolean): void
-    {
+    public static removeDictElementIfTrue<T, V>(dict: Dictionary<T, V>, iterationFunction: (key: T, value: V) => boolean): void {
         let toDeleteEntries: T[] = [];
-        dict.forEach(function(key: T, value: V) {
+        dict.forEach(function (key: T, value: V): void {
             let shallDelete: boolean = iterationFunction(key, value);
-            if (shallDelete)
+            if (shallDelete) {
                 toDeleteEntries.push(key);
+            }
         });
 
         for (let i: number = 0; i < toDeleteEntries.length; i++) {
             dict.remove(toDeleteEntries[i]);
         }
     }
-    
-    public static getLastElement<T>(array: T[]): T{
-        return array[array.length-1];
+
+    public static getLastElement<T>(array: T[]): T {
+        return array[array.length - 1];
+    }
+
+    public static binarySearch<T>(array: T[],
+                                  element: T,
+                                  cmp: (elem1: T, elem2: T) => number,
+                                  startIndex: number = 0,
+                                  endIndex: number = array.length): number {
+        let mid: number = 1;
+        while (startIndex < endIndex) {
+            mid = Math.floor((startIndex + endIndex) / 2);
+            let c: number = cmp(array[mid], element);
+            if (c === 0) {
+                return mid;
+            }
+            if (c < 0) {
+                startIndex = mid + 1;
+            }
+            if (0 < c) {
+                endIndex = mid;
+            }
+        }
+
+        return -mid;
     }
 }

+ 1 - 1
test/Common/DataObjects/fraction_Test.ts

@@ -2,7 +2,7 @@
  * Created by Oliver on 16.03.2016.
  */
 import { Fraction } from "../../../src/Common/DataObjects/fraction";
-import {Dictionary} from 'typescript-collections/dist/lib/Dictionary';
+import Dictionary from "typescript-collections/dist/lib/Dictionary";
 
 describe("Fraction Unit Tests:", () => {
     describe("Construct Fraction, check properties", () => {

+ 42 - 0
test/MusicalScore/ScoreCalculation/MusicSheetCalculator_Test.ts

@@ -0,0 +1,42 @@
+/**
+ * Created by Matthias on 21.06.2016.
+ */
+import {MusicSheetReader} from "../../../src/MusicalScore/ScoreIO/MusicSheetReader";
+import {MusicSheet} from "../../../src/MusicalScore/MusicSheet";
+import {IXmlElement} from "../../../src/Common/FileIO/Xml";
+import {MusicSheetCalculator} from "../../../src/MusicalScore/Graphical/MusicSheetCalculator";
+import {VexFlowMusicSheetCalculator} from "../../../src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator";
+import {GraphicalMusicSheet} from "../../../src/MusicalScore/Graphical/GraphicalMusicSheet";
+
+
+describe("Music Sheet Reader Tests", () => {
+    // Initialize variables
+    let path: string = "test/data/MuzioClementi_SonatinaOpus36No1_Part1.xml";
+    let reader: MusicSheetReader = new MusicSheetReader();
+    let calculator: MusicSheetCalculator = new VexFlowMusicSheetCalculator();
+    let score: IXmlElement;
+    let sheet: MusicSheet;
+
+    function getSheet(filename: string): Document {
+        return ((window as any).__xml__)[filename];
+    }
+
+    before((): void => {
+        // Load the xml file
+        let doc: Document = getSheet(path);
+        chai.expect(doc).to.not.be.undefined;
+        score = new IXmlElement(doc.getElementsByTagName("score-partwise")[0]);
+        // chai.expect(score).to.not.be.undefined;
+        sheet = reader.createMusicSheet(score, path);
+        let graphicalSheet: GraphicalMusicSheet = new GraphicalMusicSheet(sheet, calculator);
+        graphicalSheet.reCalculate();
+    });
+
+    beforeEach((): void => {
+        // ???
+    });
+
+    afterEach((): void => {
+        // cleanup?
+    });
+});