Selaa lähdekoodia

Merge branch 'develop' of https://github.com/opensheetmusicdisplay/opensheetmusicdisplay into develop

Andrea Condoluci 9 vuotta sitten
vanhempi
commit
310c639ef0
43 muutettua tiedostoa jossa 730 lisäystä ja 163 poistoa
  1. 1 0
      dist/src/Common/FileIO/Mxl.d.ts
  2. 11 1
      dist/src/Common/FileIO/Mxl.js
  3. 2 3
      dist/src/Common/logging.d.ts
  4. 16 4
      dist/src/Common/logging.js
  5. 2 2
      dist/src/MusicalScore/Graphical/EngravingRules.js
  6. 1 0
      dist/src/MusicalScore/Graphical/GraphicalLabel.d.ts
  7. 3 0
      dist/src/MusicalScore/Graphical/GraphicalLabel.js
  8. 14 15
      dist/src/MusicalScore/Graphical/GraphicalMusicSheet.js
  9. 1 1
      dist/src/MusicalScore/Graphical/GraphicalStaffEntry.js
  10. 7 7
      dist/src/MusicalScore/Graphical/MusicSheetCalculator.js
  11. 0 1
      dist/src/MusicalScore/Graphical/VerticalGraphicalStaffEntryContainer.d.ts
  12. 4 3
      dist/src/MusicalScore/Graphical/VerticalGraphicalStaffEntryContainer.js
  13. 5 0
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowConverter.d.ts
  14. 37 0
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowConverter.js
  15. 1 3
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.d.ts
  16. 48 33
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.js
  17. 11 6
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.js
  18. 13 5
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.d.ts
  19. 49 21
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.js
  20. 5 0
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.d.ts
  21. 16 0
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.js
  22. 3 3
      dist/src/MusicalScore/Graphical/VexFlow/VexFlowTextMeasurer.js
  23. 2 1
      dist/src/MusicalScore/MusicParts/MusicPartManagerIterator.js
  24. 6 3
      dist/src/MusicalScore/MusicSheet.js
  25. 2 1
      dist/src/MusicalScore/MusicSource/Repetition.js
  26. 11 11
      dist/src/MusicalScore/ScoreIO/InstrumentReader.js
  27. 15 24
      dist/src/MusicalScore/ScoreIO/MusicSheetReader.js
  28. 3 3
      dist/src/MusicalScore/ScoreIO/VoiceGenerator.js
  29. 2 1
      dist/src/MusicalScore/SubInstrument.js
  30. 2 2
      dist/src/MusicalScore/VoiceData/Expressions/instantaniousDynamicExpression.js
  31. 5 3
      dist/src/MusicalScore/VoiceData/SourceMeasure.js
  32. 28 0
      dist/src/OSMD/Cursor.d.ts
  33. 118 0
      dist/src/OSMD/Cursor.js
  34. 44 0
      dist/src/OSMD/OSMD.d.ts
  35. 167 0
      dist/src/OSMD/OSMD.js
  36. 9 0
      dist/src/OSMD/ResizeHandler.d.ts
  37. 43 0
      dist/src/OSMD/ResizeHandler.js
  38. 2 1
      dist/test/Common/DataObjects/fraction_Test.js
  39. 0 0
      dist/test/Common/OSMD/OSMD.d.ts
  40. 18 0
      dist/test/Common/OSMD/OSMD.js
  41. 2 3
      dist/test/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.js
  42. 0 1
      dist/test/MusicalScore/ScoreIO/MusicSheetReader.js
  43. 1 1
      package.json

+ 1 - 0
dist/src/Common/FileIO/Mxl.d.ts

@@ -1,2 +1,3 @@
 import { Promise } from "es6-promise";
 export declare function extractSheetFromMxl(data: string): Promise<any>;
+export declare function openMxl(data: string): Promise<any>;

+ 11 - 1
dist/src/Common/FileIO/Mxl.js

@@ -14,7 +14,6 @@ var JSZip = require("jszip");
 // )
 function extractSheetFromMxl(data) {
     "use strict";
-    // _zip_ must be of type 'any' for now, since typings for JSZip are not up-to-date
     var zip = new JSZip();
     // asynchronously load zip file and process it - with Promises
     return zip.loadAsync(data).then(function (_) {
@@ -42,3 +41,14 @@ function extractSheetFromMxl(data) {
     });
 }
 exports.extractSheetFromMxl = extractSheetFromMxl;
+function openMxl(data) {
+    "use strict";
+    var zip = new JSZip();
+    // asynchronously load zip file and process it - with Promises
+    return zip.loadAsync(data).then(function (_) {
+        return zip.file("META-INF/container.xml").async("string");
+    }, function (err) {
+        throw err;
+    });
+}
+exports.openMxl = openMxl;

+ 2 - 3
dist/src/Common/logging.d.ts

@@ -1,7 +1,6 @@
-/**
- * Created by acondolu on 26/04/16.
- */
 export declare class Logging {
     static debug(...args: any[]): void;
     static log(...args: any[]): void;
+    static error(...args: any[]): void;
+    static warn(...args: any[]): void;
 }

+ 16 - 4
dist/src/Common/logging.js

@@ -1,6 +1,4 @@
-/**
- * Created by acondolu on 26/04/16.
- */
+/* tslint:disable:no-console */
 "use strict";
 var Logging = (function () {
     function Logging() {
@@ -10,7 +8,7 @@ var Logging = (function () {
         for (var _i = 0; _i < arguments.length; _i++) {
             args[_i - 0] = arguments[_i];
         }
-        console.log("[OSMD] DEBUG: ", args.join(" "));
+        console.debug("[OSMD] ", args.join(" "));
     };
     Logging.log = function () {
         var args = [];
@@ -19,6 +17,20 @@ var Logging = (function () {
         }
         console.log("[OSMD] ", args.join(" "));
     };
+    Logging.error = function () {
+        var args = [];
+        for (var _i = 0; _i < arguments.length; _i++) {
+            args[_i - 0] = arguments[_i];
+        }
+        console.error("[OSMD] ", args.join(" "));
+    };
+    Logging.warn = function () {
+        var args = [];
+        for (var _i = 0; _i < arguments.length; _i++) {
+            args[_i - 0] = arguments[_i];
+        }
+        console.warn("[OSMD] ", args.join(" "));
+    };
     return Logging;
 }());
 exports.Logging = Logging;

+ 2 - 2
dist/src/MusicalScore/Graphical/EngravingRules.js

@@ -1,7 +1,7 @@
 "use strict";
 var GraphicalMusicPage_1 = require("./GraphicalMusicPage");
 //import {MusicSymbol} from "./MusicSymbol";
-var logging_1 = require("../../Common/logging");
+var Logging_1 = require("../../Common/Logging");
 var EngravingRules = (function () {
     function EngravingRules() {
         this.noteDistances = [1.0, 1.0, 1.3, 1.6, 2.0, 2.5, 3.0, 4.0];
@@ -138,7 +138,7 @@ var EngravingRules = (function () {
             this.maxInstructionsConstValue = this.ClefLeftMargin + this.ClefRightMargin + this.KeyRightMargin + this.RhythmRightMargin + 11;
         }
         catch (ex) {
-            logging_1.Logging.log("EngravingRules()", ex);
+            Logging_1.Logging.log("EngravingRules()", ex);
         }
     }
     Object.defineProperty(EngravingRules, "Rules", {

+ 1 - 0
dist/src/MusicalScore/Graphical/GraphicalLabel.d.ts

@@ -6,5 +6,6 @@ export declare class GraphicalLabel extends Clickable {
     private label;
     constructor(label: Label, textHeight: number, alignment: TextAlignment, parent?: BoundingBox);
     Label: Label;
+    toString(): string;
     setLabelPositionAndShapeBorders(): void;
 }

+ 3 - 0
dist/src/MusicalScore/Graphical/GraphicalLabel.js

@@ -26,6 +26,9 @@ var GraphicalLabel = (function (_super) {
         enumerable: true,
         configurable: true
     });
+    GraphicalLabel.prototype.toString = function () {
+        return this.label.text;
+    };
     GraphicalLabel.prototype.setLabelPositionAndShapeBorders = function () {
         if (this.Label.text.trim() === "") {
             return;

+ 14 - 15
dist/src/MusicalScore/Graphical/GraphicalMusicSheet.js

@@ -6,7 +6,7 @@ var ClefInstruction_1 = require("../VoiceData/Instructions/ClefInstruction");
 var KeyInstruction_1 = require("../VoiceData/Instructions/KeyInstruction");
 var fraction_1 = require("../../Common/DataObjects/fraction");
 var BoundingBox_1 = require("./BoundingBox");
-var logging_1 = require("../../Common/logging");
+var Logging_1 = require("../../Common/Logging");
 var Dictionary_1 = require("typescript-collections/dist/lib/Dictionary");
 var collectionUtil_1 = require("../../Util/collectionUtil");
 var GraphicalMusicSheet = (function () {
@@ -292,19 +292,18 @@ var GraphicalMusicSheet = (function () {
     };
     GraphicalMusicSheet.prototype.getOrCreateVerticalContainer = function (timestamp) {
         if (this.verticalGraphicalStaffEntryContainers.length === 0 ||
-            timestamp > collectionUtil_1.CollectionUtil.getLastElement(this.verticalGraphicalStaffEntryContainers).AbsoluteTimestamp) {
+            timestamp.lt(collectionUtil_1.CollectionUtil.getLastElement(this.verticalGraphicalStaffEntryContainers).AbsoluteTimestamp)) {
             var verticalGraphicalStaffEntryContainer = new VerticalGraphicalStaffEntryContainer_1.VerticalGraphicalStaffEntryContainer(this.numberOfStaves, timestamp);
             this.verticalGraphicalStaffEntryContainers.push(verticalGraphicalStaffEntryContainer);
             return verticalGraphicalStaffEntryContainer;
         }
-        var i;
-        for (; i >= 0; i--) {
-            if (this.verticalGraphicalStaffEntryContainers[i].AbsoluteTimestamp < timestamp) {
+        for (var i = this.verticalGraphicalStaffEntryContainers.length - 1; i >= 0; i--) {
+            if (this.verticalGraphicalStaffEntryContainers[i].AbsoluteTimestamp.lt(timestamp)) {
                 var verticalGraphicalStaffEntryContainer = new VerticalGraphicalStaffEntryContainer_1.VerticalGraphicalStaffEntryContainer(this.numberOfStaves, timestamp);
                 this.verticalGraphicalStaffEntryContainers.splice(i + 1, 0, verticalGraphicalStaffEntryContainer);
                 return verticalGraphicalStaffEntryContainer;
             }
-            if (this.verticalGraphicalStaffEntryContainers[i].AbsoluteTimestamp === timestamp) {
+            if (this.verticalGraphicalStaffEntryContainers[i].AbsoluteTimestamp.Equals(timestamp)) {
                 return this.verticalGraphicalStaffEntryContainers[i];
             }
         }
@@ -325,21 +324,21 @@ var GraphicalMusicSheet = (function () {
         var foundIndex;
         var leftTS = undefined;
         var rightTS = undefined;
-        if (musicTimestamp <= containers[containers.length - 1].AbsoluteTimestamp) {
+        if (musicTimestamp.lte(containers[containers.length - 1].AbsoluteTimestamp)) {
             while (rightIndex - leftIndex > 1) {
-                var middleIndex = (rightIndex + leftIndex) / 2;
-                if (containers[leftIndex].AbsoluteTimestamp === musicTimestamp) {
+                var middleIndex = Math.floor((rightIndex + leftIndex) / 2);
+                if (containers[leftIndex].AbsoluteTimestamp.Equals(musicTimestamp)) {
                     rightIndex = leftIndex;
                     break;
                 }
-                else if (containers[rightIndex].AbsoluteTimestamp === musicTimestamp) {
+                else if (containers[rightIndex].AbsoluteTimestamp.Equals(musicTimestamp)) {
                     leftIndex = rightIndex;
                     break;
                 }
-                else if (containers[middleIndex].AbsoluteTimestamp === musicTimestamp) {
+                else if (containers[middleIndex].AbsoluteTimestamp.Equals(musicTimestamp)) {
                     return this.verticalGraphicalStaffEntryContainers.indexOf(containers[middleIndex]);
                 }
-                else if (containers[middleIndex].AbsoluteTimestamp > musicTimestamp) {
+                else if (musicTimestamp.lt(containers[middleIndex].AbsoluteTimestamp)) {
                     rightIndex = middleIndex;
                 }
                 else {
@@ -547,7 +546,7 @@ var GraphicalMusicSheet = (function () {
             return this.GetClickableLabel(positionOnMusicSheet);
         }
         catch (ex) {
-            logging_1.Logging.log("GraphicalMusicSheet.tryGetClickableObject", "positionOnMusicSheet: " + positionOnMusicSheet, ex);
+            Logging_1.Logging.log("GraphicalMusicSheet.tryGetClickableObject", "positionOnMusicSheet: " + positionOnMusicSheet, ex);
         }
         return undefined;
     };
@@ -560,7 +559,7 @@ var GraphicalMusicSheet = (function () {
             return entry.getAbsoluteTimestamp();
         }
         catch (ex) {
-            logging_1.Logging.log("GraphicalMusicSheet.tryGetTimeStampFromPosition", "positionOnMusicSheet: " + positionOnMusicSheet, ex);
+            Logging_1.Logging.log("GraphicalMusicSheet.tryGetTimeStampFromPosition", "positionOnMusicSheet: " + positionOnMusicSheet, ex);
         }
         return undefined;
     };
@@ -584,7 +583,7 @@ var GraphicalMusicSheet = (function () {
             }
         }
         catch (ex) {
-            logging_1.Logging.log("GraphicalMusicSheet.getStaffEntry", ex);
+            Logging_1.Logging.log("GraphicalMusicSheet.getStaffEntry", ex);
         }
         return staffEntry;
     };

+ 1 - 1
dist/src/MusicalScore/Graphical/GraphicalStaffEntry.js

@@ -57,7 +57,7 @@ var GraphicalStaffEntry = (function (_super) {
         configurable: true
     });
     GraphicalStaffEntry.prototype.getAbsoluteTimestamp = function () {
-        var result = fraction_1.Fraction.createFromFraction(this.parentMeasure.parentSourceMeasure.AbsoluteTimestamp);
+        var result = this.parentMeasure.parentSourceMeasure.AbsoluteTimestamp.clone();
         if (this.relInMeasureTimestamp !== undefined) {
             result.Add(this.relInMeasureTimestamp);
         }

+ 7 - 7
dist/src/MusicalScore/Graphical/MusicSheetCalculator.js

@@ -17,7 +17,7 @@ var BoundingBox_1 = require("./BoundingBox");
 var OctaveShiftParams_1 = require("./OctaveShiftParams");
 var AccidentalCalculator_1 = require("./AccidentalCalculator");
 var ClefInstruction_3 = require("../VoiceData/Instructions/ClefInstruction");
-var logging_1 = require("../../Common/logging");
+var Logging_1 = require("../../Common/Logging");
 var Dictionary_1 = require("typescript-collections/dist/lib/Dictionary");
 var collectionUtil_1 = require("../../Util/collectionUtil");
 var MusicSheetCalculator = (function () {
@@ -189,10 +189,10 @@ var MusicSheetCalculator = (function () {
         throw new Error("abstract, not implemented");
     };
     MusicSheetCalculator.prototype.clearRecreatedObjects = function () {
-        logging_1.Logging.log("clearRecreatedObjects not implemented");
+        Logging_1.Logging.debug("clearRecreatedObjects not implemented");
     };
     MusicSheetCalculator.prototype.handleStaffEntryLink = function (graphicalStaffEntry, staffEntryLinks) {
-        logging_1.Logging.log("handleStaffEntryLink not implemented");
+        Logging_1.Logging.debug("handleStaffEntryLink not implemented");
     };
     MusicSheetCalculator.prototype.calculateMusicSystems = function () {
         if (this.graphicalMusicSheet.MeasureList === undefined) {
@@ -314,16 +314,16 @@ var MusicSheetCalculator = (function () {
         }
     };
     MusicSheetCalculator.prototype.updateSkyBottomLine = function (staffLine) {
-        logging_1.Logging.log("updateSkyBottomLine not implemented");
+        Logging_1.Logging.debug("updateSkyBottomLine not implemented");
     };
     MusicSheetCalculator.prototype.calculateSkyBottomLine = function (staffLine) {
-        logging_1.Logging.log("calculateSkyBottomLine not implemented");
+        Logging_1.Logging.debug("calculateSkyBottomLine not implemented");
     };
     MusicSheetCalculator.prototype.calculateMarkedAreas = function () {
-        logging_1.Logging.log("calculateMarkedAreas not implemented");
+        Logging_1.Logging.debug("calculateMarkedAreas not implemented");
     };
     MusicSheetCalculator.prototype.calculateComments = function () {
-        logging_1.Logging.log("calculateComments not implemented");
+        Logging_1.Logging.debug("calculateComments not implemented");
     };
     MusicSheetCalculator.prototype.optimizeStaffLineDynamicExpressionsPositions = function () {
         return;

+ 0 - 1
dist/src/MusicalScore/Graphical/VerticalGraphicalStaffEntryContainer.d.ts

@@ -2,7 +2,6 @@ import { Fraction } from "../../Common/DataObjects/fraction";
 import { GraphicalStaffEntry } from "./GraphicalStaffEntry";
 export declare class VerticalGraphicalStaffEntryContainer {
     constructor(numberOfEntries: number, absoluteTimestamp: Fraction);
-    relativeInMeasureTimestamp: Fraction;
     private index;
     private absoluteTimestamp;
     private staffEntries;

+ 4 - 3
dist/src/MusicalScore/Graphical/VerticalGraphicalStaffEntryContainer.js

@@ -21,13 +21,14 @@ var VerticalGraphicalStaffEntryContainer = (function () {
         get: function () {
             return this.absoluteTimestamp;
         },
-        set: function (value) {
-            this.absoluteTimestamp = value;
-        },
         enumerable: true,
         configurable: true
     });
     Object.defineProperty(VerticalGraphicalStaffEntryContainer.prototype, "StaffEntries", {
+        //
+        //public set AbsoluteTimestamp(value: Fraction) {
+        //    this.absoluteTimestamp = value;
+        //}
         get: function () {
             return this.staffEntries;
         },

+ 5 - 0
dist/src/MusicalScore/Graphical/VexFlow/VexFlowConverter.d.ts

@@ -7,6 +7,9 @@ import { KeyInstruction } from "../../VoiceData/Instructions/KeyInstruction";
 import { AccidentalEnum } from "../../../Common/DataObjects/pitch";
 import { GraphicalNote } from "../GraphicalNote";
 import { SystemLinesEnum } from "../SystemLinesEnum";
+import { FontStyles } from "../../../Common/Enums/FontStyles";
+import { Fonts } from "../../../Common/Enums/Fonts";
+import { OutlineAndFillStyleEnum } from "../DrawingEnums";
 export declare class VexFlowConverter {
     private static majorMap;
     private static minorMap;
@@ -29,4 +32,6 @@ export declare class VexFlowConverter {
     static TimeSignature(rhythm: RhythmInstruction): Vex.Flow.TimeSignature;
     static keySignature(key: KeyInstruction): string;
     static line(lineType: SystemLinesEnum): any;
+    static font(fontSize: number, fontStyle?: FontStyles, font?: Fonts): string;
+    static style(styleId: OutlineAndFillStyleEnum): string;
 }

+ 37 - 0
dist/src/MusicalScore/Graphical/VexFlow/VexFlowConverter.js

@@ -6,6 +6,8 @@ var KeyInstruction_1 = require("../../VoiceData/Instructions/KeyInstruction");
 var pitch_1 = require("../../../Common/DataObjects/pitch");
 var pitch_2 = require("../../../Common/DataObjects/pitch");
 var SystemLinesEnum_1 = require("../SystemLinesEnum");
+var FontStyles_1 = require("../../../Common/Enums/FontStyles");
+var Fonts_1 = require("../../../Common/Enums/Fonts");
 var VexFlowConverter = (function () {
     function VexFlowConverter() {
     }
@@ -185,6 +187,41 @@ var VexFlowConverter = (function () {
             default:
         }
     };
+    VexFlowConverter.font = function (fontSize, fontStyle, font) {
+        if (fontStyle === void 0) { fontStyle = FontStyles_1.FontStyles.Regular; }
+        if (font === void 0) { font = Fonts_1.Fonts.TimesNewRoman; }
+        var style = "normal";
+        var weight = "normal";
+        var family = "'Times New Roman'";
+        switch (fontStyle) {
+            case FontStyles_1.FontStyles.Bold:
+                weight = "bold";
+                break;
+            case FontStyles_1.FontStyles.Italic:
+                style = "italic";
+                break;
+            case FontStyles_1.FontStyles.BoldItalic:
+                style = "italic";
+                weight = "bold";
+                break;
+            case FontStyles_1.FontStyles.Underlined:
+                // TODO
+                break;
+            default:
+                break;
+        }
+        switch (font) {
+            case Fonts_1.Fonts.Kokila:
+                // TODO Not Supported
+                break;
+            default:
+        }
+        return style + " " + weight + " " + Math.floor(fontSize) + "px " + family;
+    };
+    VexFlowConverter.style = function (styleId) {
+        // TODO
+        return "purple";
+    };
     VexFlowConverter.majorMap = {
         "0": "C", 1: "G", 2: "D", 3: "A", 4: "E", 5: "B", 6: "F#", 7: "C#",
         8: "G#", "-1": "F", "-8": "Fb", "-7": "Cb", "-6": "Gb", "-5": "Db", "-4": "Ab", "-3": "Eb", "-2": "Bb",

+ 1 - 3
dist/src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.d.ts

@@ -17,7 +17,6 @@ export declare class VexFlowMeasure extends StaffMeasure {
         [voiceID: number]: Vex.Flow.Voice;
     };
     formatVoices: (width: number) => void;
-    unit: number;
     private stave;
     private connectors;
     private beams;
@@ -95,6 +94,5 @@ export declare class VexFlowMeasure extends StaffMeasure {
      */
     lineTo(top: VexFlowMeasure, lineType: any): void;
     getVFStave(): Vex.Flow.Stave;
-    private increaseBeginInstructionWidth();
-    private increaseEndInstructionWidth();
+    private updateInstructionWidth();
 }

+ 48 - 33
dist/src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.js

@@ -7,6 +7,7 @@ var __extends = (this && this.__extends) || function (d, b) {
 var Vex = require("vexflow");
 var StaffMeasure_1 = require("../StaffMeasure");
 var VexFlowConverter_1 = require("./VexFlowConverter");
+var Logging_1 = require("../../../Common/Logging");
 var VexFlowMeasure = (function (_super) {
     __extends(VexFlowMeasure, _super);
     function VexFlowMeasure(staff, staffLine, sourceMeasure) {
@@ -17,14 +18,10 @@ var VexFlowMeasure = (function (_super) {
         this.octaveOffset = 3;
         // The VexFlow Voices in the measure
         this.vfVoices = {};
-        // The unit
-        this.unit = 10.0;
         // VexFlow StaveConnectors (vertical lines)
         this.connectors = [];
         // Intermediate object to construct beams
         this.beams = {};
-        // VexFlow Beams
-        this.vfbeams = {};
         this.minimumStaffEntriesWidth = -1;
         this.resetLayout();
     }
@@ -39,15 +36,20 @@ var VexFlowMeasure = (function (_super) {
     VexFlowMeasure.prototype.resetLayout = function () {
         // Take into account some space for the begin and end lines of the stave
         // Will be changed when repetitions will be implemented
-        this.beginInstructionsWidth = 20 / this.unit;
-        this.endInstructionsWidth = 20 / this.unit;
-        this.stave = new Vex.Flow.Stave(0, 0, 0);
+        //this.beginInstructionsWidth = 20 / 10.0;
+        //this.endInstructionsWidth = 20 / 10.0;
+        this.stave = new Vex.Flow.Stave(0, 0, 0, {
+            space_above_staff_ln: 0,
+            space_below_staff_ln: 0,
+        });
+        this.updateInstructionWidth();
     };
     VexFlowMeasure.prototype.clean = function () {
         //this.beams = {};
-        //this.vfbeams = {};
+        //this.vfbeams = undefined;
         this.connectors = [];
-        console.log("clean!");
+        // Clean up instructions
+        this.resetLayout();
     };
     /**
      * returns the x-width of a given measure line.
@@ -59,9 +61,9 @@ var VexFlowMeasure = (function (_super) {
         var vfline = VexFlowConverter_1.VexFlowConverter.line(line);
         switch (vfline) {
             case Vex.Flow.StaveConnector.type.SINGLE:
-                return 1.0 / this.unit;
+                return 1.0 / 10.0;
             case Vex.Flow.StaveConnector.type.DOUBLE:
-                return 3.0 / this.unit;
+                return 3.0 / 10.0;
             default:
                 return 0;
         }
@@ -75,7 +77,7 @@ var VexFlowMeasure = (function (_super) {
         this.octaveOffset = clef.OctaveOffset;
         var vfclef = VexFlowConverter_1.VexFlowConverter.Clef(clef);
         this.stave.addClef(vfclef, undefined, undefined, Vex.Flow.Modifier.Position.BEGIN);
-        this.increaseBeginInstructionWidth();
+        this.updateInstructionWidth();
     };
     /**
      * adds the given key to the begin of the measure.
@@ -96,7 +98,7 @@ var VexFlowMeasure = (function (_super) {
     VexFlowMeasure.prototype.addRhythmAtBegin = function (rhythm) {
         var timeSig = VexFlowConverter_1.VexFlowConverter.TimeSignature(rhythm);
         this.stave.addModifier(timeSig, Vex.Flow.Modifier.Position.BEGIN);
-        this.increaseBeginInstructionWidth();
+        this.updateInstructionWidth();
     };
     /**
      * adds the given clef to the end of the measure.
@@ -106,7 +108,7 @@ var VexFlowMeasure = (function (_super) {
     VexFlowMeasure.prototype.addClefAtEnd = function (clef) {
         var vfclef = VexFlowConverter_1.VexFlowConverter.Clef(clef);
         this.stave.setEndClef(vfclef, undefined, undefined);
-        this.increaseEndInstructionWidth();
+        this.updateInstructionWidth();
     };
     /**
      * Sets the overall x-width of the measure.
@@ -115,12 +117,14 @@ var VexFlowMeasure = (function (_super) {
     VexFlowMeasure.prototype.setWidth = function (width) {
         _super.prototype.setWidth.call(this, width);
         // Set the width of the Vex.Flow.Stave
-        this.stave.setWidth(width * this.unit);
+        this.stave.setWidth(width * 10.0);
+        // Force the width of the Begin Instructions
+        this.stave.setNoteStartX(this.beginInstructionsWidth * 10.0);
         // If this is the first stave in the vertical measure, call the format
         // method to set the width of all the voices
         if (this.formatVoices) {
             // The width of the voices does not include the instructions (StaveModifiers)
-            this.formatVoices((width - this.beginInstructionsWidth - this.endInstructionsWidth) * this.unit);
+            this.formatVoices((width - this.beginInstructionsWidth - this.endInstructionsWidth) * 10.0);
         }
     };
     /**
@@ -198,6 +202,10 @@ var VexFlowMeasure = (function (_super) {
      * Complete the creation of VexFlow Beams in this measure
      */
     VexFlowMeasure.prototype.finalizeBeams = function () {
+        // The following line resets the created Vex.Flow Beams and
+        // created them brand new. Is this needed? And more importantly,
+        // should the old beams be removed manually by the notes?
+        this.vfbeams = {};
         for (var voiceID in this.beams) {
             if (this.beams.hasOwnProperty(voiceID)) {
                 var vfbeams = this.vfbeams[voiceID];
@@ -215,7 +223,7 @@ var VexFlowMeasure = (function (_super) {
                         vfbeams.push(new Vex.Flow.Beam(notes, true));
                     }
                     else {
-                        console.log("Warning! Beam with no notes! Trying to ignore, but this is a serious problem.");
+                        Logging_1.Logging.log("Warning! Beam with no notes! Trying to ignore, but this is a serious problem.");
                     }
                 }
             }
@@ -228,8 +236,8 @@ var VexFlowMeasure = (function (_super) {
             if (gnotes.hasOwnProperty(voiceID)) {
                 if (!(voiceID in vfVoices)) {
                     vfVoices[voiceID] = new Vex.Flow.Voice({
-                        beat_value: 4,
-                        num_beats: 3,
+                        beat_value: this.parentSourceMeasure.Duration.Denominator,
+                        num_beats: this.parentSourceMeasure.Duration.Numerator,
                         resolution: Vex.Flow.RESOLUTION,
                     }).setMode(Vex.Flow.Voice.Mode.SOFT);
                 }
@@ -252,20 +260,27 @@ var VexFlowMeasure = (function (_super) {
     VexFlowMeasure.prototype.getVFStave = function () {
         return this.stave;
     };
-    VexFlowMeasure.prototype.increaseBeginInstructionWidth = function () {
-        var modifiers = this.stave.getModifiers();
-        var modifier = modifiers[modifiers.length - 1];
-        //let padding: number = modifier.getCategory() === "keysignatures" ? modifier.getPadding(2) : 0;
-        var padding = modifier.getPadding(20);
-        var width = modifier.getWidth();
-        this.beginInstructionsWidth += (padding + width) / this.unit;
-    };
-    VexFlowMeasure.prototype.increaseEndInstructionWidth = function () {
-        var modifiers = this.stave.getModifiers();
-        var modifier = modifiers[modifiers.length - 1];
-        var padding = 0;
-        var width = modifier.getWidth();
-        this.endInstructionsWidth += (padding + width) / this.unit;
+    //private increaseBeginInstructionWidth(): void {
+    //    let modifiers: StaveModifier[] = this.stave.getModifiers();
+    //    let modifier: StaveModifier = modifiers[modifiers.length - 1];
+    //    //let padding: number = modifier.getCategory() === "keysignatures" ? modifier.getPadding(2) : 0;
+    //    let padding: number = modifier.getPadding(20);
+    //    let width: number = modifier.getWidth();
+    //    this.beginInstructionsWidth += (padding + width) / 10.0;
+    //}
+    //
+    //private increaseEndInstructionWidth(): void {
+    //    let modifiers: StaveModifier[] = this.stave.getModifiers();
+    //    let modifier: StaveModifier = modifiers[modifiers.length - 1];
+    //    let padding: number = 0;
+    //    let width: number = modifier.getWidth();
+    //    this.endInstructionsWidth += (padding + width) / 10.0;
+    //
+    //}
+    VexFlowMeasure.prototype.updateInstructionWidth = function () {
+        this.stave.format();
+        this.beginInstructionsWidth = this.stave.getNoteStartX() / 10.0;
+        this.endInstructionsWidth = this.stave.getNoteEndX() / 10.0;
     };
     return VexFlowMeasure;
 }(StaffMeasure_1.StaffMeasure));

+ 11 - 6
dist/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.js

@@ -8,6 +8,7 @@ var MusicSheetCalculator_1 = require("../MusicSheetCalculator");
 var VexFlowGraphicalSymbolFactory_1 = require("./VexFlowGraphicalSymbolFactory");
 var VexFlowTextMeasurer_1 = require("./VexFlowTextMeasurer");
 var Vex = require("vexflow");
+var Logging_1 = require("../../../Common/Logging");
 var VexFlowMusicSheetCalculator = (function (_super) {
     __extends(VexFlowMusicSheetCalculator, _super);
     function VexFlowMusicSheetCalculator() {
@@ -46,7 +47,9 @@ var VexFlowMusicSheetCalculator = (function (_super) {
         }
         // Format the voices
         var allVoices = [];
-        var formatter = new Vex.Flow.Formatter();
+        var formatter = new Vex.Flow.Formatter({
+            align_rests: true,
+        });
         for (var _a = 0, measures_2 = measures; _a < measures_2.length; _a++) {
             var measure = measures_2[_a];
             var mvoices = measure.vfVoices;
@@ -58,13 +61,15 @@ var VexFlowMusicSheetCalculator = (function (_super) {
                 }
             }
             if (voices.length === 0) {
-                console.warn("Found a measure with no voices... Continuing anyway.", mvoices);
+                Logging_1.Logging.warn("Found a measure with no voices... Continuing anyway.", mvoices);
                 continue;
             }
             formatter.joinVoices(voices);
         }
         var firstMeasure = measures[0];
-        var width = formatter.preCalculateMinTotalWidth(allVoices) / firstMeasure.unit;
+        // FIXME: The following ``+ 5.0'' is temporary: it was added as a workaround for
+        // FIXME: a more relaxed formatting of voices
+        var width = formatter.preCalculateMinTotalWidth(allVoices) / 10.0 + 5.0;
         for (var _b = 0, measures_3 = measures; _b < measures_3.length; _b++) {
             var measure = measures_3[_b];
             measure.minimumStaffEntriesWidth = width;
@@ -114,16 +119,16 @@ var VexFlowMusicSheetCalculator = (function (_super) {
                 for (var idx2 = 0, len2 = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
                     var musicSystem = graphicalMusicPage.MusicSystems[idx2];
                     // calculate y positions of stafflines within system
-                    var y = 0;
+                    var y = 10;
                     for (var _i = 0, _a = musicSystem.StaffLines; _i < _a.length; _i++) {
                         var line = _a[_i];
                         line.PositionAndShape.RelativePosition.y = y;
                         y += 10;
                     }
                     // set y positions of systems using the previous system and a fixed distance.
-                    musicSystem.PositionAndShape.BorderBottom = y + 10;
+                    musicSystem.PositionAndShape.BorderBottom = y + 0;
                     musicSystem.PositionAndShape.RelativePosition.y = globalY;
-                    globalY += y + 10;
+                    globalY += y + 0;
                 }
             }
         }

+ 13 - 5
dist/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.d.ts

@@ -1,17 +1,25 @@
 import { MusicSheetDrawer } from "../MusicSheetDrawer";
 import { RectangleF2D } from "../../../Common/DataObjects/RectangleF2D";
 import { VexFlowMeasure } from "./VexFlowMeasure";
-import { ITextMeasurer } from "../../Interfaces/ITextMeasurer";
 import { PointF2D } from "../../../Common/DataObjects/PointF2D";
 import { GraphicalLabel } from "../GraphicalLabel";
-/**
- * Created by Matthias on 22.06.2016.
- */
 export declare class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
     private renderer;
+    private vfctx;
     private ctx;
-    constructor(canvas: HTMLCanvasElement, textMeasurer: ITextMeasurer, isPreviewImageDrawer?: boolean);
+    private titles;
+    private zoom;
+    constructor(titles: HTMLElement, canvas: HTMLCanvasElement, isPreviewImageDrawer?: boolean);
+    /**
+     * Zoom the rendering areas
+     * @param k is the zoom factor
+     */
     scale(k: number): void;
+    /**
+     * Resize the rendering areas
+     * @param x
+     * @param y
+     */
     resize(x: number, y: number): void;
     translate(x: number, y: number): void;
     /**

+ 49 - 21
dist/src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.js

@@ -8,26 +8,40 @@ var Vex = require("vexflow");
 var MusicSheetDrawer_1 = require("../MusicSheetDrawer");
 var RectangleF2D_1 = require("../../../Common/DataObjects/RectangleF2D");
 var PointF2D_1 = require("../../../Common/DataObjects/PointF2D");
-/**
- * Created by Matthias on 22.06.2016.
- */
+var VexFlowConverter_1 = require("./VexFlowConverter");
+var VexFlowTextMeasurer_1 = require("./VexFlowTextMeasurer");
 var VexFlowMusicSheetDrawer = (function (_super) {
     __extends(VexFlowMusicSheetDrawer, _super);
-    function VexFlowMusicSheetDrawer(canvas, textMeasurer, isPreviewImageDrawer) {
+    function VexFlowMusicSheetDrawer(titles, canvas, isPreviewImageDrawer) {
         if (isPreviewImageDrawer === void 0) { isPreviewImageDrawer = false; }
-        _super.call(this, textMeasurer, isPreviewImageDrawer);
+        _super.call(this, new VexFlowTextMeasurer_1.VexFlowTextMeasurer(), isPreviewImageDrawer);
+        this.zoom = 1.0;
         this.renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
-        this.ctx = this.renderer.getContext();
+        this.vfctx = this.renderer.getContext();
+        // The following is a hack to retrieve the actual canvas' drawing context
+        // Not supposed to work forever....
+        this.ctx = this.vfctx.vexFlowCanvasContext;
+        this.titles = titles;
     }
+    /**
+     * Zoom the rendering areas
+     * @param k is the zoom factor
+     */
     VexFlowMusicSheetDrawer.prototype.scale = function (k) {
-        this.ctx.scale(k, k);
+        this.zoom = k;
+        this.vfctx.scale(k, k);
     };
+    /**
+     * Resize the rendering areas
+     * @param x
+     * @param y
+     */
     VexFlowMusicSheetDrawer.prototype.resize = function (x, y) {
         this.renderer.resize(x, y);
     };
     VexFlowMusicSheetDrawer.prototype.translate = function (x, y) {
-        // FIXME
-        this.ctx.vexFlowCanvasContext.translate(x, y);
+        // Translation seems not supported by VexFlow
+        this.ctx.translate(x, y);
     };
     /**
      * Converts a distance from unit to pixel space.
@@ -35,12 +49,11 @@ var VexFlowMusicSheetDrawer = (function (_super) {
      * @returns {number} the distance in pixels
      */
     VexFlowMusicSheetDrawer.prototype.calculatePixelDistance = function (unitDistance) {
-        // ToDo: implement!
         return unitDistance * 10.0;
     };
     VexFlowMusicSheetDrawer.prototype.drawMeasure = function (measure) {
-        measure.setAbsoluteCoordinates(measure.PositionAndShape.AbsolutePosition.x * measure.unit, measure.PositionAndShape.AbsolutePosition.y * measure.unit);
-        return measure.draw(this.ctx);
+        measure.setAbsoluteCoordinates(measure.PositionAndShape.AbsolutePosition.x * 10.0, measure.PositionAndShape.AbsolutePosition.y * 10.0);
+        return measure.draw(this.vfctx);
     };
     /**
      * Renders a Label to the screen (e.g. Title, composer..)
@@ -52,11 +65,25 @@ var VexFlowMusicSheetDrawer = (function (_super) {
      * @param screenPosition the position of the lower left corner of the text in screen coordinates
      */
     VexFlowMusicSheetDrawer.prototype.renderLabel = function (graphicalLabel, layer, bitmapWidth, bitmapHeight, heightInPixel, screenPosition) {
-        // ToDo: implement!
-        var ctx = this.ctx.vexFlowCanvasContext;
-        ctx.font = Math.floor(graphicalLabel.Label.fontHeight * 10) + "px 'Times New Roman'";
-        console.log(graphicalLabel.Label.text, screenPosition.x, screenPosition.y);
-        ctx.fillText(graphicalLabel.Label.text, screenPosition.x, screenPosition.y);
+        if (screenPosition.y < 0) {
+            // Temportary solution for title labels
+            var div = document.createElement("div");
+            div.style.fontSize = (graphicalLabel.Label.fontHeight * this.zoom * 10.0) + "px";
+            //span.style.width = (bitmapWidth * this.zoom * 1.1) + "px";
+            //span.style.height = (bitmapHeight * this.zoom * 1.1) + "px";
+            //span.style.overflow = "hidden";
+            div.style.fontFamily = "Times New Roman";
+            //span.style.marginLeft = (screenPosition.x * this.zoom) + "px";
+            div.style.textAlign = "center";
+            div.appendChild(document.createTextNode(graphicalLabel.Label.text));
+            this.titles.appendChild(div);
+            return;
+        }
+        var ctx = this.vfctx.vexFlowCanvasContext;
+        var old = ctx.font;
+        ctx.font = VexFlowConverter_1.VexFlowConverter.font(graphicalLabel.Label.fontHeight * 10.0, graphicalLabel.Label.fontStyle, graphicalLabel.Label.font);
+        ctx.fillText(graphicalLabel.Label.text, screenPosition.x, screenPosition.y + heightInPixel);
+        ctx.font = old;
     };
     /**
      * Renders a rectangle with the given style to the screen.
@@ -66,7 +93,10 @@ var VexFlowMusicSheetDrawer = (function (_super) {
      * @param styleId the style id
      */
     VexFlowMusicSheetDrawer.prototype.renderRectangle = function (rectangle, layer, styleId) {
-        // ToDo: implement!
+        var old = this.ctx.fillStyle;
+        this.ctx.fillStyle = VexFlowConverter_1.VexFlowConverter.style(styleId);
+        this.ctx.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+        this.ctx.fillStyle = old;
     };
     /**
      * Converts a point from unit to pixel space.
@@ -74,7 +104,6 @@ var VexFlowMusicSheetDrawer = (function (_super) {
      * @returns {PointF2D}
      */
     VexFlowMusicSheetDrawer.prototype.applyScreenTransformation = function (point) {
-        // ToDo: implement!
         return new PointF2D_1.PointF2D(point.x * 10.0, point.y * 10.0);
     };
     /**
@@ -83,8 +112,7 @@ var VexFlowMusicSheetDrawer = (function (_super) {
      * @returns {RectangleF2D}
      */
     VexFlowMusicSheetDrawer.prototype.applyScreenTransformationForRect = function (rectangle) {
-        // FIXME Check if correct
-        return new RectangleF2D_1.RectangleF2D(rectangle.x * 10, rectangle.y * 10, rectangle.width * 10, rectangle.height * 10);
+        return new RectangleF2D_1.RectangleF2D(rectangle.x * 10.0, rectangle.y * 10.0, rectangle.width * 10.0, rectangle.height * 10.0);
     };
     return VexFlowMusicSheetDrawer;
 }(MusicSheetDrawer_1.MusicSheetDrawer));

+ 5 - 0
dist/src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.d.ts

@@ -10,4 +10,9 @@ export declare class VexFlowStaffEntry extends GraphicalStaffEntry {
     vfNotes: {
         [voiceID: number]: Vex.Flow.StaveNote;
     };
+    /**
+     *
+     * @returns {number} the x-position (in units) of this Staff Entry
+     */
+    getX(): number;
 }

+ 16 - 0
dist/src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.js

@@ -14,6 +14,22 @@ var VexFlowStaffEntry = (function (_super) {
         // The corresponding VexFlow.StaveNotes
         this.vfNotes = {};
     }
+    /**
+     *
+     * @returns {number} the x-position (in units) of this Staff Entry
+     */
+    VexFlowStaffEntry.prototype.getX = function () {
+        var x = 0;
+        var n = 0;
+        var vfNotes = this.vfNotes;
+        for (var voiceId in vfNotes) {
+            if (vfNotes.hasOwnProperty(voiceId)) {
+                x += (vfNotes[voiceId].getNoteHeadBeginX() + vfNotes[voiceId].getNoteHeadEndX()) / 2;
+                n += 1;
+            }
+        }
+        return x / n / 10.0;
+    };
     return VexFlowStaffEntry;
 }(GraphicalStaffEntry_1.GraphicalStaffEntry));
 exports.VexFlowStaffEntry = VexFlowStaffEntry;

+ 3 - 3
dist/src/MusicalScore/Graphical/VexFlow/VexFlowTextMeasurer.js

@@ -1,4 +1,5 @@
 "use strict";
+var VexFlowConverter_1 = require("./VexFlowConverter");
 /**
  * Created by Matthias on 21.06.2016.
  */
@@ -6,11 +7,10 @@ var VexFlowTextMeasurer = (function () {
     function VexFlowTextMeasurer() {
         var canvas = document.createElement("canvas");
         this.context = canvas.getContext("2d");
-        this.context.font = "20px 'Times New Roman'";
     }
     VexFlowTextMeasurer.prototype.computeTextWidthToHeightRatio = function (text, font, style) {
-        var size = this.context.measureText(text);
-        return size.width / 20;
+        this.context.font = VexFlowConverter_1.VexFlowConverter.font(20, style, font);
+        return this.context.measureText(text).width / 20;
     };
     return VexFlowTextMeasurer;
 }());

+ 2 - 1
dist/src/MusicalScore/MusicParts/MusicPartManagerIterator.js

@@ -3,6 +3,7 @@ var fraction_1 = require("../../Common/DataObjects/fraction");
 var DynamicsContainer_1 = require("../VoiceData/HelperObjects/DynamicsContainer");
 var RhythmInstruction_1 = require("../VoiceData/Instructions/RhythmInstruction");
 var continuousDynamicExpression_1 = require("../VoiceData/Expressions/ContinuousExpressions/continuousDynamicExpression");
+var Logging_1 = require("../../Common/Logging");
 var MusicPartManagerIterator = (function () {
     function MusicPartManagerIterator(manager, startTimestamp, endTimestamp) {
         this.currentMeasureIndex = 0;
@@ -51,7 +52,7 @@ var MusicPartManagerIterator = (function () {
             this.currentTempoChangingExpression = this.activeTempoExpression;
         }
         catch (err) {
-            console.log("MusicPartManagerIterator: Exception." + err); // FIXME
+            Logging_1.Logging.log("MusicPartManagerIterator: " + err);
         }
     }
     Object.defineProperty(MusicPartManagerIterator.prototype, "EndReached", {

+ 6 - 3
dist/src/MusicalScore/MusicSheet.js

@@ -6,6 +6,7 @@ var Voice_1 = require("./VoiceData/Voice");
 var MusicSheetErrors_1 = require("../Common/DataObjects/MusicSheetErrors");
 var EngravingRules_1 = require("./Graphical/EngravingRules");
 var DrawingEnums_1 = require("./Graphical/DrawingEnums");
+var Logging_1 = require("../Common/Logging");
 // FIXME
 //type MusicSheetParameters = any;
 //type MultiTempoExpression = any;
@@ -46,7 +47,9 @@ var MusicSheet /*implements ISettableMusicSheet, IComparable<MusicSheet>*/ = (fu
         this.hasBeenOpenedForTheFirstTime = false;
         this.currentEnrolledPosition = new fraction_1.Fraction(0, 1);
         this.rules = EngravingRules_1.EngravingRules.Rules;
-        // (*) this.playbackSettings = new PlaybackSettings(new Fraction(4, 4, false), 100);
+        this.playbackSettings = new PlaybackSettings();
+        // FIXME:
+        this.playbackSettings.rhythm = new fraction_1.Fraction(4, 4, false);
         this.userStartTempoInBPM = 100;
         this.pageWidth = 120;
         this.MusicPartManager = new MusicPartManager_1.MusicPartManager(this);
@@ -472,7 +475,7 @@ var MusicSheet /*implements ISettableMusicSheet, IComparable<MusicSheet>*/ = (fu
                 return this.getFirstSourceMeasure().MeasureNumber;
             }
             catch (ex) {
-                console.log(/* FIXME LogLevel.NORMAL, */ "MusicSheet.FirstMeasureNumber: ", ex);
+                Logging_1.Logging.log("MusicSheet.FirstMeasureNumber: ", ex);
                 return 0;
             }
         },
@@ -485,7 +488,7 @@ var MusicSheet /*implements ISettableMusicSheet, IComparable<MusicSheet>*/ = (fu
                 return this.getLastSourceMeasure().MeasureNumber;
             }
             catch (ex) {
-                console.log(/* FIXME LogLevel.NORMAL, */ "MusicSheet.LastMeasureNumber: ", ex);
+                Logging_1.Logging.log("MusicSheet.LastMeasureNumber: ", ex);
                 return 0;
             }
         },

+ 2 - 1
dist/src/MusicalScore/MusicSource/Repetition.js

@@ -7,6 +7,7 @@ var __extends = (this && this.__extends) || function (d, b) {
 var SourceMusicPart_1 = require("./SourceMusicPart");
 var fraction_1 = require("../../Common/DataObjects/fraction");
 var PartListEntry_1 = require("./PartListEntry");
+var Logging_1 = require("../../Common/Logging");
 var Repetition = (function (_super) {
     __extends(Repetition, _super);
     function Repetition(musicSheet, virtualOverallRepetition) {
@@ -107,7 +108,7 @@ var Repetition = (function (_super) {
                 }
             }
             catch (err) {
-                console.log("Repetition: Exception."); // FIXME
+                Logging_1.Logging.error("Repetition: Exception.", err);
             }
         }
     };

+ 11 - 11
dist/src/MusicalScore/ScoreIO/InstrumentReader.js

@@ -10,7 +10,7 @@ var Exceptions_1 = require("../Exceptions");
 var ClefInstruction_2 = require("../VoiceData/Instructions/ClefInstruction");
 var RhythmInstruction_2 = require("../VoiceData/Instructions/RhythmInstruction");
 var KeyInstruction_2 = require("../VoiceData/Instructions/KeyInstruction");
-var logging_1 = require("../../Common/logging");
+var Logging_1 = require("../../Common/Logging");
 var ClefInstruction_3 = require("../VoiceData/Instructions/ClefInstruction");
 var InstrumentReader = (function () {
     function InstrumentReader(repetitionInstructionReader, xmlMeasureList, instrument) {
@@ -83,7 +83,7 @@ var InstrumentReader = (function () {
                         if (xmlNode.element("staff") !== undefined) {
                             noteStaff = parseInt(xmlNode.element("staff").value, 10);
                             if (isNaN(noteStaff)) {
-                                logging_1.Logging.debug("InstrumentReader.readNextXmlMeasure.get staff number");
+                                Logging_1.Logging.debug("InstrumentReader.readNextXmlMeasure.get staff number");
                                 noteStaff = 1;
                             }
                         }
@@ -117,7 +117,7 @@ var InstrumentReader = (function () {
                         else {
                             var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/NoteDurationError", "Invalid Note Duration.");
                             this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                            logging_1.Logging.debug("InstrumentReader.readNextXmlMeasure", errorMsg);
+                            Logging_1.Logging.debug("InstrumentReader.readNextXmlMeasure", errorMsg);
                             continue;
                         }
                     }
@@ -169,7 +169,7 @@ var InstrumentReader = (function () {
                         this.divisions = parseInt(divisionsNode.value, 10);
                         if (isNaN(this.divisions)) {
                             var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/DivisionError", "Invalid divisions value at Instrument: ");
-                            logging_1.Logging.debug("InstrumentReader.readNextXmlMeasure", errorMsg);
+                            Logging_1.Logging.debug("InstrumentReader.readNextXmlMeasure", errorMsg);
                             this.divisions = this.readDivisionsFromNotes();
                             if (this.divisions > 0) {
                                 this.musicSheet.SheetErrors.push(errorMsg + this.instrument.Name);
@@ -256,7 +256,7 @@ var InstrumentReader = (function () {
             }
             var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/MeasureError", "Error while reading Measure.");
             this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-            logging_1.Logging.debug("InstrumentReader.readNextXmlMeasure", errorMsg, e);
+            Logging_1.Logging.debug("InstrumentReader.readNextXmlMeasure", errorMsg, e);
         }
         this.previousMeasure = this.currentMeasure;
         this.currentXmlMeasureIndex += 1;
@@ -424,7 +424,7 @@ var InstrumentReader = (function () {
                         errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/ClefLineError", "Invalid clef line given -> using default clef line.");
                         this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
                         line = 2;
-                        logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
+                        Logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
                     }
                 }
                 var signNode = nodeList.element("sign");
@@ -446,7 +446,7 @@ var InstrumentReader = (function () {
                         this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
                         clefEnum = ClefInstruction_2.ClefEnum.G;
                         line = 2;
-                        logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, e);
+                        Logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, e);
                     }
                 }
                 var clefOctaveNode = nodeList.element("clef-octave-change");
@@ -485,7 +485,7 @@ var InstrumentReader = (function () {
                     errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/KeyError", "Invalid key found -> set to default.");
                     this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
                     key = 0;
-                    logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
+                    Logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
                 }
             }
             var keyEnum = KeyInstruction_2.KeyEnum.none;
@@ -501,7 +501,7 @@ var InstrumentReader = (function () {
                     errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/KeyError", "Invalid key found -> set to default.");
                     this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
                     keyEnum = KeyInstruction_2.KeyEnum.major;
-                    logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
+                    Logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
                 }
             }
             var keyInstruction = new KeyInstruction_1.KeyInstruction(undefined, key, keyEnum);
@@ -575,7 +575,7 @@ var InstrumentReader = (function () {
                     this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
                     num = 4;
                     denom = 4;
-                    logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
+                    Logging_1.Logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
                 }
                 if ((num === 4 && denom === 4) || (num === 2 && denom === 2)) {
                     symbolEnum = RhythmInstruction_2.RhythmSymbolEnum.NONE;
@@ -818,7 +818,7 @@ var InstrumentReader = (function () {
                                 noteDuration = parseInt(durationNode.value, 10);
                             }
                             catch (ex) {
-                                logging_1.Logging.debug("InstrumentReader.readDivisionsFromNotes", ex);
+                                Logging_1.Logging.debug("InstrumentReader.readDivisionsFromNotes", ex);
                                 continue;
                             }
                             switch (type) {

+ 15 - 24
dist/src/MusicalScore/ScoreIO/MusicSheetReader.js

@@ -6,7 +6,7 @@ var InstrumentReader_1 = require("./InstrumentReader");
 var Instrument_1 = require("../Instrument");
 var ITextTranslation_1 = require("../Interfaces/ITextTranslation");
 var Exceptions_1 = require("../Exceptions");
-var logging_1 = require("../../Common/logging");
+var Logging_1 = require("../../Common/Logging");
 var RhythmInstruction_1 = require("../VoiceData/Instructions/RhythmInstruction");
 var RhythmInstruction_2 = require("../VoiceData/Instructions/RhythmInstruction");
 var SourceStaffEntry_1 = require("../VoiceData/SourceStaffEntry");
@@ -36,7 +36,7 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
             return this._createMusicSheet(root, path);
         }
         catch (e) {
-            logging_1.Logging.log("MusicSheetReader.CreateMusicSheet", e);
+            Logging_1.Logging.log("MusicSheetReader.CreateMusicSheet", e);
         }
     };
     MusicSheetReader /*implements IMusicSheetReader*/.prototype._removeFromArray = function (list, elem) {
@@ -92,11 +92,8 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
             throw new Exceptions_1.MusicSheetReadingException("Undefined partListNode");
         }
         var partInst = root.elements("part");
-        console.log(partInst.length + " parts");
         var partList = partlistNode.elements();
-        //Logging.debug("Starting initializeReading");
         this.initializeReading(partList, partInst, instrumentReaders);
-        //Logging.debug("Done initializeReading");
         var couldReadMeasure = true;
         this.currentFraction = new fraction_1.Fraction(0, 1);
         var guitarPro = false;
@@ -126,17 +123,11 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
                 }
             }
             if (couldReadMeasure) {
-                //Logging.debug("couldReadMeasure: 1");
                 this.musicSheet.addMeasure(this.currentMeasure);
-                //Logging.debug("couldReadMeasure: 2");
                 this.checkIfRhythmInstructionsAreSetAndEqual(instrumentReaders);
-                //Logging.debug("couldReadMeasure: 3");
                 this.checkSourceMeasureForundefinedEntries();
-                //Logging.debug("couldReadMeasure: 4");
                 this.setSourceMeasureDuration(instrumentReaders, sourceMeasureCounter);
-                //Logging.debug("couldReadMeasure: 5");
                 MusicSheetReader.doCalculationsAfterDurationHasBeenSet(instrumentReaders);
-                //Logging.debug("couldReadMeasure: 6");
                 this.currentMeasure.AbsoluteTimestamp = this.currentFraction.clone();
                 this.musicSheet.SheetErrors.finalizeMeasure(this.currentMeasure.MeasureNumber);
                 this.currentFraction.Add(this.currentMeasure.Duration);
@@ -276,19 +267,19 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
     MusicSheetReader /*implements IMusicSheetReader*/.prototype.setSourceMeasureDuration = function (instrumentReaders, sourceMeasureCounter) {
         var activeRhythm = new fraction_1.Fraction(0, 1);
         var instrumentsMaxTieNoteFractions = [];
-        for (var idx = 0, len = instrumentReaders.length; idx < len; ++idx) {
-            var instrumentReader = instrumentReaders[idx];
+        for (var _i = 0, instrumentReaders_3 = instrumentReaders; _i < instrumentReaders_3.length; _i++) {
+            var instrumentReader = instrumentReaders_3[_i];
             instrumentsMaxTieNoteFractions.push(instrumentReader.MaxTieNoteFraction);
             var activeRythmMeasure = instrumentReader.ActiveRhythm.Rhythm;
-            if (activeRhythm < activeRythmMeasure) {
+            if (activeRhythm.lt(activeRythmMeasure)) {
                 activeRhythm = new fraction_1.Fraction(activeRythmMeasure.Numerator, activeRythmMeasure.Denominator, false);
             }
         }
         var instrumentsDurations = this.currentMeasure.calculateInstrumentsDuration(this.musicSheet, instrumentsMaxTieNoteFractions);
         var maxInstrumentDuration = new fraction_1.Fraction(0, 1);
-        for (var idx = 0, len = instrumentsDurations.length; idx < len; ++idx) {
-            var instrumentsDuration = instrumentsDurations[idx];
-            if (maxInstrumentDuration < instrumentsDuration) {
+        for (var _a = 0, instrumentsDurations_1 = instrumentsDurations; _a < instrumentsDurations_1.length; _a++) {
+            var instrumentsDuration = instrumentsDurations_1[_a];
+            if (maxInstrumentDuration.lt(instrumentsDuration)) {
                 maxInstrumentDuration = instrumentsDuration;
             }
         }
@@ -296,7 +287,7 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
             this.checkFractionsForEquivalence(maxInstrumentDuration, activeRhythm);
         }
         else {
-            if (maxInstrumentDuration < activeRhythm) {
+            if (maxInstrumentDuration.lt(activeRhythm)) {
                 maxInstrumentDuration = this.currentMeasure.reverseCheck(this.musicSheet, maxInstrumentDuration);
                 this.checkFractionsForEquivalence(maxInstrumentDuration, activeRhythm);
             }
@@ -310,7 +301,7 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
         for (var i = 0; i < instrumentsDurations.length; i++) {
             var instrumentsDuration = instrumentsDurations[i];
             if ((this.currentMeasure.ImplicitMeasure && instrumentsDuration !== maxInstrumentDuration) ||
-                instrumentsDuration !== activeRhythm &&
+                !fraction_1.Fraction.Equal(instrumentsDuration, activeRhythm) &&
                     !this.allInstrumentsHaveSameDuration(instrumentsDurations, maxInstrumentDuration)) {
                 var firstStaffIndexOfInstrument = this.musicSheet.getGlobalStaffIndexOfFirstStaff(this.musicSheet.Instruments[i]);
                 for (var staffIndex = 0; staffIndex < this.musicSheet.Instruments[i].Staves.length; staffIndex++) {
@@ -402,7 +393,7 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
                 this.musicSheet.Title = new Label_1.Label(filenameSplits[0]);
             }
             catch (ex) {
-                logging_1.Logging.log("MusicSheetReader.pushSheetLabels: ", ex);
+                Logging_1.Logging.log("MusicSheetReader.pushSheetLabels: ", ex);
             }
         }
     };
@@ -648,7 +639,7 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
                                                 subInstrument.volume = result / 127.0;
                                             }
                                             catch (ex) {
-                                                logging_1.Logging.debug("ExpressionReader.readExpressionParameters", "read volume", ex);
+                                                Logging_1.Logging.debug("ExpressionReader.readExpressionParameters", "read volume", ex);
                                             }
                                         }
                                         else if (instrumentElement.name === "pan") {
@@ -657,18 +648,18 @@ var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
                                                 subInstrument.pan = result / 64.0;
                                             }
                                             catch (ex) {
-                                                logging_1.Logging.debug("ExpressionReader.readExpressionParameters", "read pan", ex);
+                                                Logging_1.Logging.debug("ExpressionReader.readExpressionParameters", "read pan", ex);
                                             }
                                         }
                                     }
                                     catch (ex) {
-                                        logging_1.Logging.log("MusicSheetReader.createInstrumentGroups midi settings: ", ex);
+                                        Logging_1.Logging.log("MusicSheetReader.createInstrumentGroups midi settings: ", ex);
                                     }
                                 }
                             }
                         }
                         catch (ex) {
-                            logging_1.Logging.log("MusicSheetReader.createInstrumentGroups: ", ex);
+                            Logging_1.Logging.log("MusicSheetReader.createInstrumentGroups: ", ex);
                         }
                     }
                     if (instrument.SubInstruments.length === 0) {

+ 3 - 3
dist/src/MusicalScore/ScoreIO/VoiceGenerator.js

@@ -14,7 +14,7 @@ var Exceptions_1 = require("../Exceptions");
 var pitch_1 = require("../../Common/DataObjects/pitch");
 var pitch_2 = require("../../Common/DataObjects/pitch");
 var StaffEntryLink_1 = require("../VoiceData/StaffEntryLink");
-var logging_1 = require("../../Common/logging");
+var Logging_1 = require("../../Common/Logging");
 var pitch_3 = require("../../Common/DataObjects/pitch");
 var collectionUtil_1 = require("../../Util/collectionUtil");
 var VoiceGenerator = (function () {
@@ -275,7 +275,7 @@ var VoiceGenerator = (function () {
                             }
                         }
                         catch (ex) {
-                            logging_1.Logging.log("VoiceGenerator.addSingleNote read Step: ", ex.message);
+                            Logging_1.Logging.log("VoiceGenerator.addSingleNote read Step: ", ex.message);
                         }
                     }
                 }
@@ -299,7 +299,7 @@ var VoiceGenerator = (function () {
                 }
             }
             catch (ex) {
-                logging_1.Logging.log("VoiceGenerator.addSingleNote: ", ex);
+                Logging_1.Logging.log("VoiceGenerator.addSingleNote: ", ex);
             }
         }
         noteOctave -= pitch_3.Pitch.OctaveXmlDifference;

+ 2 - 1
dist/src/MusicalScore/SubInstrument.js

@@ -1,5 +1,6 @@
 "use strict";
 var ClefInstruction_1 = require("./VoiceData/Instructions/ClefInstruction");
+var Logging_1 = require("../Common/Logging");
 var SubInstrument = (function () {
     function SubInstrument(parentInstrument) {
         this.parentInstrument = parentInstrument;
@@ -46,7 +47,7 @@ var SubInstrument = (function () {
             }
         }
         catch (e) {
-            console.log("Error parsing MIDI Instrument. Default to Grand Piano."); // FIXME
+            Logging_1.Logging.error("Error parsing MIDI Instrument. Default to Grand Piano.");
         }
         return "unnamed";
     };

+ 2 - 2
dist/src/MusicalScore/VoiceData/Expressions/instantaniousDynamicExpression.js

@@ -8,7 +8,7 @@ var abstractExpression_1 = require("./abstractExpression");
 var dynamicExpressionSymbolEnum_1 = require("./dynamicExpressionSymbolEnum");
 //import {ArgumentOutOfRangeException} from "../../Exceptions";
 var Exceptions_1 = require("../../Exceptions");
-var logging_1 = require("../../../Common/logging");
+var Logging_1 = require("../../../Common/Logging");
 var InstantaniousDynamicExpression = (function (_super) {
     __extends(InstantaniousDynamicExpression, _super);
     function InstantaniousDynamicExpression(dynamicExpression, soundDynamics, placement, staffNumber) {
@@ -137,7 +137,7 @@ var InstantaniousDynamicExpression = (function (_super) {
         //    length += FontInfo.Info.getBoundingBox(symbol).Width;
         //}
         //return length;
-        logging_1.Logging.debug("[Andrea] instantaniousDynamicExpression: not implemented: calculateLength!");
+        Logging_1.Logging.debug("[Andrea] instantaniousDynamicExpression: not implemented: calculateLength!");
         return 0.0;
     };
     InstantaniousDynamicExpression.dynamicToRelativeVolumeDict = {

+ 5 - 3
dist/src/MusicalScore/VoiceData/SourceMeasure.js

@@ -391,12 +391,14 @@ var SourceMeasure = (function () {
         return undefined;
     };
     SourceMeasure.prototype.getLastSourceStaffEntryForInstrument = function (instrumentIndex) {
+        var entry;
         for (var i = this.verticalSourceStaffEntryContainers.length - 1; i >= 0; i--) {
-            if (this.verticalSourceStaffEntryContainers[i][instrumentIndex] !== undefined) {
-                return this.verticalSourceStaffEntryContainers[i][instrumentIndex];
+            entry = this.verticalSourceStaffEntryContainers[i].StaffEntries[instrumentIndex];
+            if (entry) {
+                break;
             }
         }
-        return undefined;
+        return entry;
     };
     return SourceMeasure;
 }());

+ 28 - 0
dist/src/OSMD/Cursor.d.ts

@@ -0,0 +1,28 @@
+import { MusicPartManager } from "../MusicalScore/MusicParts/MusicPartManager";
+import { OSMD } from "./OSMD";
+import { GraphicalMusicSheet } from "../MusicalScore/Graphical/GraphicalMusicSheet";
+export declare class Cursor {
+    constructor(container: HTMLElement, osmd: OSMD);
+    private container;
+    private osmd;
+    private iterator;
+    private graphic;
+    private hidden;
+    private cursorElement;
+    init(manager: MusicPartManager, graphic: GraphicalMusicSheet): void;
+    show(): void;
+    update(): void;
+    /**
+     * Hide the cursor
+     */
+    hide(): void;
+    /**
+     * Go to next entry
+     */
+    next(): void;
+    /**
+     * Go to previous entry. Not implemented.
+     */
+    prev(): void;
+    private updateStyle(width, color?);
+}

+ 118 - 0
dist/src/OSMD/Cursor.js

@@ -0,0 +1,118 @@
+"use strict";
+var Cursor = (function () {
+    function Cursor(container, osmd) {
+        this.hidden = true;
+        this.container = container;
+        this.osmd = osmd;
+        var curs = document.createElement("img");
+        curs.style.position = "absolute";
+        curs.style.zIndex = "-1";
+        this.cursorElement = curs;
+        container.appendChild(curs);
+    }
+    Cursor.prototype.init = function (manager, graphic) {
+        this.iterator = manager.getIterator();
+        this.graphic = graphic;
+        this.hidden = true;
+        this.hide();
+    };
+    Cursor.prototype.show = function () {
+        this.hidden = false;
+        this.update();
+        // Forcing the sheet to re-render is not necessary anymore
+        //this.osmd.render();
+    };
+    Cursor.prototype.update = function () {
+        // Should NEVER call this.osmd.render()
+        if (this.hidden) {
+            return;
+        }
+        this.graphic.Cursors.length = 0;
+        var iterator = this.iterator;
+        if (iterator.EndReached || iterator.CurrentVoiceEntries === undefined) {
+            return;
+        }
+        var x = 0, y = 0, height = 0;
+        for (var idx = 0, len = iterator.CurrentVoiceEntries.length; idx < len; ++idx) {
+            var voiceEntry = iterator.CurrentVoiceEntries[idx];
+            var measureIndex = voiceEntry.ParentSourceStaffEntry.VerticalContainerParent.ParentMeasure.MeasureNumber;
+            var staffIndex = voiceEntry.ParentSourceStaffEntry.ParentStaff.idInMusicSheet;
+            var gse = this.graphic.findGraphicalStaffEntryFromMeasureList(staffIndex, measureIndex, voiceEntry.ParentSourceStaffEntry);
+            if (idx === 0) {
+                x = gse.getX();
+                var musicSystem = gse.parentMeasure.parentMusicSystem;
+                y = musicSystem.PositionAndShape.AbsolutePosition.y + musicSystem.StaffLines[0].PositionAndShape.RelativePosition.y;
+                var endY = musicSystem.PositionAndShape.AbsolutePosition.y +
+                    musicSystem.StaffLines[musicSystem.StaffLines.length - 1].PositionAndShape.RelativePosition.y + 4.0;
+                height = endY - y;
+            }
+        }
+        // Update the graphical cursor
+        // The following is the legacy cursor rendered on the canvas:
+        // // let cursor: GraphicalLine = new GraphicalLine(new PointF2D(x, y), new PointF2D(x, y + height), 3, OutlineAndFillStyleEnum.PlaybackCursor);
+        // This the current HTML Cursor:
+        var cursorElement = this.cursorElement;
+        cursorElement.style.top = (y * 10.0 * this.osmd.zoom) + "px";
+        cursorElement.style.left = ((x - 1.5) * 10.0 * this.osmd.zoom) + "px";
+        cursorElement.height = (height * 10.0 * this.osmd.zoom);
+        var newWidth = 3 * 10.0 * this.osmd.zoom;
+        if (newWidth !== cursorElement.width) {
+            cursorElement.width = newWidth;
+            this.updateStyle(newWidth);
+        }
+        // Show cursors
+        // // Old cursor: this.graphic.Cursors.push(cursor);
+        this.cursorElement.style.display = "";
+    };
+    /**
+     * Hide the cursor
+     */
+    Cursor.prototype.hide = function () {
+        // Hide the actual cursor element
+        this.cursorElement.style.display = "none";
+        //this.graphic.Cursors.length = 0;
+        // Forcing the sheet to re-render is not necessary anymore
+        //if (!this.hidden) {
+        //    this.osmd.render();
+        //}
+        this.hidden = true;
+    };
+    /**
+     * Go to next entry
+     */
+    Cursor.prototype.next = function () {
+        this.iterator.moveToNext();
+        if (!this.hidden) {
+            this.show();
+        }
+    };
+    /**
+     * Go to previous entry. Not implemented.
+     */
+    Cursor.prototype.prev = function () {
+        // TODO
+        // Previous does not seem to be implemented in the MusicPartManager iterator...
+    };
+    Cursor.prototype.updateStyle = function (width, color) {
+        if (color === void 0) { color = "#33e02f"; }
+        // Create a dummy canvas to generate the gradient for the cursor
+        // FIXME This approach needs to be improved
+        var c = document.createElement("canvas");
+        c.width = this.cursorElement.width;
+        c.height = 1;
+        var ctx = c.getContext("2d");
+        ctx.globalAlpha = 0.5;
+        // Generate the gradient
+        var gradient = ctx.createLinearGradient(0, 0, this.cursorElement.width, 0);
+        gradient.addColorStop(0, "white"); // it was: "transparent"
+        gradient.addColorStop(0.2, color);
+        gradient.addColorStop(0.8, color);
+        gradient.addColorStop(1, "white"); // it was: "transparent"
+        ctx.fillStyle = gradient;
+        ctx.fillRect(0, 0, width, 1);
+        // Set the actual image
+        this.cursorElement.src = c.toDataURL("image/png");
+    };
+    return Cursor;
+}());
+exports.Cursor = Cursor;

+ 44 - 0
dist/src/OSMD/OSMD.d.ts

@@ -0,0 +1,44 @@
+import { Cursor } from "./Cursor";
+export declare class OSMD {
+    /**
+     * The easy way of displaying a MusicXML sheet music file
+     * @param container is either the ID, or the actual "div" element which will host the music sheet
+     * @autoResize automatically resize the sheet to full page width on window resize
+     */
+    constructor(container: string | HTMLElement, autoResize?: boolean);
+    cursor: Cursor;
+    zoom: number;
+    private container;
+    private heading;
+    private canvas;
+    private sheet;
+    private drawer;
+    private graphic;
+    /**
+     * Load a MusicXML file
+     * @param content is either the url of a file, or the root node of a MusicXML document, or the string content of a .xml/.mxl file
+     */
+    load(content: string | Document): void;
+    /**
+     * Render the music sheet in the container
+     */
+    render(): void;
+    /**
+     *
+     * @param url
+     */
+    private openURL(url);
+    /**
+     * Clear all the titles from the headings element
+     */
+    private resetHeadings();
+    /**
+     * Initialize this object to default values
+     * FIXME: Probably unnecessary
+     */
+    private reset();
+    /**
+     * Attach the appropriate handler to the window.onResize event
+     */
+    private autoResize();
+}

+ 167 - 0
dist/src/OSMD/OSMD.js

@@ -0,0 +1,167 @@
+"use strict";
+var Xml_1 = require("./../Common/FileIO/Xml");
+var VexFlowMusicSheetCalculator_1 = require("./../MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator");
+var MusicSheetReader_1 = require("./../MusicalScore/ScoreIO/MusicSheetReader");
+var GraphicalMusicSheet_1 = require("./../MusicalScore/Graphical/GraphicalMusicSheet");
+var VexFlowMusicSheetDrawer_1 = require("./../MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer");
+var Cursor_1 = require("./Cursor");
+var Mxl_1 = require("../Common/FileIO/Mxl");
+//import {Promise} from "es6-promise";
+var ResizeHandler_1 = require("./ResizeHandler");
+var OSMD = (function () {
+    /**
+     * The easy way of displaying a MusicXML sheet music file
+     * @param container is either the ID, or the actual "div" element which will host the music sheet
+     * @autoResize automatically resize the sheet to full page width on window resize
+     */
+    function OSMD(container, autoResize) {
+        if (autoResize === void 0) { autoResize = false; }
+        this.zoom = 1.0;
+        // Store container element
+        if (typeof container === "string") {
+            // ID passed
+            this.container = document.getElementById(container);
+        }
+        else if (container && "appendChild" in container) {
+            // Element passed
+            this.container = container;
+        }
+        if (!this.container) {
+            throw new Error("Please pass a valid div container to OSMD");
+        }
+        // Create the elements inside the container
+        this.heading = document.createElement("div");
+        this.canvas = document.createElement("canvas");
+        this.canvas.style.zIndex = "0";
+        var inner = document.createElement("div");
+        inner.style.position = "relative";
+        this.container.appendChild(this.heading);
+        inner.appendChild(this.canvas);
+        this.container.appendChild(inner);
+        // Create the drawer
+        this.drawer = new VexFlowMusicSheetDrawer_1.VexFlowMusicSheetDrawer(this.heading, this.canvas);
+        // Create the cursor
+        this.cursor = new Cursor_1.Cursor(inner, this);
+        if (autoResize) {
+            this.autoResize();
+        }
+    }
+    /**
+     * Load a MusicXML file
+     * @param content is either the url of a file, or the root node of a MusicXML document, or the string content of a .xml/.mxl file
+     */
+    OSMD.prototype.load = function (content) {
+        // Warning! This function is asynchronous! No error handling is done here.
+        // FIXME TODO Refactor with Promises
+        this.reset();
+        var path = "Unknown path";
+        if (typeof content === "string") {
+            var str = content;
+            if (str.substr(0, 4) === "http") {
+                // Retrieve the file at the url
+                path = str;
+                this.openURL(path);
+                return;
+            }
+            if (str.substr(0, 4) === "\x04\x03\x4b\x50") {
+                // This is a zip file, unpack it first
+                Mxl_1.openMxl(str).then(this.load, function (err) {
+                    throw new Error("OSMD: Invalid MXL file");
+                });
+                return;
+            }
+            if (str.substr(0, 5) === "<?xml") {
+                // Parse the string representing an xml file
+                var parser = new DOMParser();
+                content = parser.parseFromString(str, "text/xml");
+            }
+        }
+        if (!content || !content.nodeName) {
+            throw new Error("OSMD: Document provided is not valid");
+        }
+        var elem = content.getElementsByTagName("score-partwise")[0];
+        if (elem === undefined) {
+            throw new Error("OSMD: Document is not valid partwise MusicXML");
+        }
+        var score = new Xml_1.IXmlElement(elem);
+        var calc = new VexFlowMusicSheetCalculator_1.VexFlowMusicSheetCalculator();
+        var reader = new MusicSheetReader_1.MusicSheetReader();
+        this.sheet = reader.createMusicSheet(score, path);
+        this.graphic = new GraphicalMusicSheet_1.GraphicalMusicSheet(this.sheet, calc);
+        this.cursor.init(this.sheet.MusicPartManager, this.graphic);
+        return; // Promise.resolve();
+    };
+    /**
+     * Render the music sheet in the container
+     */
+    OSMD.prototype.render = function () {
+        this.resetHeadings();
+        if (!this.graphic) {
+            throw new Error("OSMD: Before rendering a music sheet, please load a MusicXML file");
+        }
+        var width = this.container.offsetWidth;
+        if (isNaN(width)) {
+            throw new Error("OSMD: Before rendering a music sheet, please give the container a width");
+        }
+        // Set page width
+        this.sheet.pageWidth = width / this.zoom / 10.0;
+        // Calculate again
+        this.graphic.reCalculate();
+        // Update Sheet Page
+        var height = this.graphic.MusicPages[0].PositionAndShape.BorderBottom * 10.0 * this.zoom;
+        this.drawer.resize(width, height);
+        this.drawer.scale(this.zoom);
+        // Finally, draw
+        this.drawer.drawSheet(this.graphic);
+        // Update the cursor position
+        this.cursor.update();
+    };
+    /**
+     *
+     * @param url
+     */
+    OSMD.prototype.openURL = function (url) {
+        throw new Error("OSMD: Not implemented: Load sheet from URL");
+        //let JSZipUtils: any;
+        //let self: OSMD = this;
+        //JSZipUtils.getBinaryContent(url, function (err, data) {
+        //    if(err) {
+        //        throw err;
+        //    }
+        //    return self.load(data);
+        //});
+    };
+    /**
+     * Clear all the titles from the headings element
+     */
+    OSMD.prototype.resetHeadings = function () {
+        while (this.heading.firstChild) {
+            this.heading.removeChild(this.heading.firstChild);
+        }
+    };
+    /**
+     * Initialize this object to default values
+     * FIXME: Probably unnecessary
+     */
+    OSMD.prototype.reset = function () {
+        this.sheet = undefined;
+        this.graphic = undefined;
+        this.zoom = 1.0;
+        this.resetHeadings();
+    };
+    /**
+     * Attach the appropriate handler to the window.onResize event
+     */
+    OSMD.prototype.autoResize = function () {
+        var self = this;
+        ResizeHandler_1.handleResize(function () {
+            // empty
+        }, function () {
+            var width = Math.max(document.documentElement.clientWidth, document.body.scrollWidth, document.documentElement.scrollWidth, document.body.offsetWidth, document.documentElement.offsetWidth);
+            self.container.style.width = width + "px";
+            self.render();
+        });
+    };
+    return OSMD;
+}());
+exports.OSMD = OSMD;

+ 9 - 0
dist/src/OSMD/ResizeHandler.d.ts

@@ -0,0 +1,9 @@
+/**
+ * Created by acondolu on 15/07/16.
+ */
+/**
+ * Helper function for managing window's onResize events
+ * @param startCallback
+ * @param endCallback
+ */
+export declare function handleResize(startCallback: () => void, endCallback: () => void): void;

+ 43 - 0
dist/src/OSMD/ResizeHandler.js

@@ -0,0 +1,43 @@
+/**
+ * Created by acondolu on 15/07/16.
+ */
+"use strict";
+/**
+ * Helper function for managing window's onResize events
+ * @param startCallback
+ * @param endCallback
+ */
+function handleResize(startCallback, endCallback) {
+    "use strict";
+    var rtime;
+    var timeout = undefined;
+    var delta = 200;
+    function resizeEnd() {
+        //timeout = undefined;
+        window.clearTimeout(timeout);
+        if ((new Date()).getTime() - rtime < delta) {
+            timeout = window.setTimeout(resizeEnd, delta);
+        }
+        else {
+            endCallback();
+        }
+    }
+    function resizeStart() {
+        rtime = (new Date()).getTime();
+        if (!timeout) {
+            startCallback();
+            rtime = (new Date()).getTime();
+            timeout = window.setTimeout(resizeEnd, delta);
+        }
+    }
+    if (window.attachEvent) {
+        // Support IE<9
+        window.attachEvent("onresize", resizeStart);
+    }
+    else {
+        window.addEventListener("resize", resizeStart);
+    }
+    window.setTimeout(startCallback, 0);
+    window.setTimeout(endCallback, 1);
+}
+exports.handleResize = handleResize;

+ 2 - 1
dist/test/Common/DataObjects/fraction_Test.js

@@ -4,6 +4,7 @@
  */
 var fraction_1 = require("../../../src/Common/DataObjects/fraction");
 var Dictionary_1 = require("typescript-collections/dist/lib/Dictionary");
+var Logging_1 = require("../../../src/Common/Logging");
 describe("Fraction Unit Tests:", function () {
     describe("Construct Fraction, check properties", function () {
         var f1 = new fraction_1.Fraction(2, 6);
@@ -51,7 +52,7 @@ describe("Fraction Unit Tests:", function () {
                 var key = keys[i];
                 var value = values[i];
                 //console.log(values[i].toString() + "== " + dict.getValue(key));
-                console.log(values[i].toString() + "== " + dict.getValue(new fraction_1.Fraction(key.Numerator, key.Denominator)));
+                Logging_1.Logging.debug(values[i].toString() + "== " + dict.getValue(new fraction_1.Fraction(key.Numerator, key.Denominator)));
                 // chai.expect(dict.getValue(key)).to.equal(value);
                 chai.expect(dict.getValue(new fraction_1.Fraction(key.Numerator, key.Denominator))).to.equal(value);
             }

+ 0 - 0
dist/test/Common/OSMD/OSMD.d.ts


+ 18 - 0
dist/test/Common/OSMD/OSMD.js

@@ -0,0 +1,18 @@
+"use strict";
+var chai = require("chai");
+var OSMD_1 = require("../../../src/OSMD/OSMD");
+describe("OSMD Main Export", function () {
+    it("no container", function (done) {
+        chai.expect(function () {
+            return new OSMD_1.OSMD(undefined);
+        }).to.throw(/container/);
+        done();
+    });
+    it("container", function (done) {
+        var div = document.createElement("div");
+        chai.expect(function () {
+            return new OSMD_1.OSMD(div);
+        }).to.not.throw(Error);
+        done();
+    });
+});

+ 2 - 3
dist/test/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.js

@@ -4,7 +4,6 @@ var GraphicalMusicSheet_1 = require("../../../../src/MusicalScore/Graphical/Grap
 var MusicSheetReader_1 = require("../../../../src/MusicalScore/ScoreIO/MusicSheetReader");
 var VexFlowMusicSheetCalculator_1 = require("../../../../src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator");
 var TestUtils_1 = require("../../../Util/TestUtils");
-var VexFlowTextMeasurer_1 = require("../../../../src/MusicalScore/Graphical/VexFlow/VexFlowTextMeasurer");
 var fraction_1 = require("../../../../src/Common/DataObjects/fraction");
 var DrawingEnums_1 = require("../../../../src/MusicalScore/Graphical/DrawingEnums");
 describe("VexFlow Music Sheet Drawer", function () {
@@ -20,12 +19,12 @@ describe("VexFlow Music Sheet Drawer", function () {
         gms.Cursors.push(gms.calculateCursorLineAtTimestamp(new fraction_1.Fraction(), DrawingEnums_1.OutlineAndFillStyleEnum.PlaybackCursor));
         // Create heading in the test page
         var h1 = document.createElement("h1");
-        h1.textContent = "VexFlowMusicSheetDrawer Output";
+        h1.textContent = "VexFlowMusicSheetDrawer Test Output";
         document.body.appendChild(h1);
         // Create the canvas in the document:
         var canvas = document.createElement("canvas");
         document.body.appendChild(canvas);
-        (new VexFlowMusicSheetDrawer_1.VexFlowMusicSheetDrawer(canvas, new VexFlowTextMeasurer_1.VexFlowTextMeasurer())).drawSheet(gms);
+        (new VexFlowMusicSheetDrawer_1.VexFlowMusicSheetDrawer(document.body, canvas)).drawSheet(gms);
         done();
     });
 });

+ 0 - 1
dist/test/MusicalScore/ScoreIO/MusicSheetReader.js

@@ -34,7 +34,6 @@ describe("Music Sheet Reader Tests", function () {
     });
     it("Measures", function (done) {
         chai.expect(sheet.SourceMeasures.length).to.equal(38);
-        console.log("First Measure: ", sheet.SourceMeasures[0]);
         done();
     });
     it("Instruments", function (done) {

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "opensheetmusicdisplay",
-  "version": "0.0.1-alpha.0",
+  "version": "0.0.1-alpha.1",
   "description": "An open source JavaScript engine for displaying MusicXML based on VexFlow.",
   "main": "dist/src/OSMD/OSMD.js",
   "typings": "dist/src/OSMD/OSMD",