Browse Source

feat(API): Allow updating the graphical sheet from the music sheet (#622)

* Make available (re-)creation of GraphicalMusicSheet

this enables adding notes to the MusicSheet,
then creating a new GraphicalMusicSheet,
then having OSMD render the new sheet (and notes) without a new load() call
cmonspqr 5 năm trước cách đây
mục cha
commit
55c3d8ad34

+ 12 - 3
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -142,19 +142,28 @@ export class OpenSheetMusicDisplay {
             return Promise.reject(new Error("OpenSheetMusicDisplay: Document is not a valid 'partwise' MusicXML"));
         }
         const score: IXmlElement = new IXmlElement(scorePartwiseElement);
-        const calc: MusicSheetCalculator = new VexFlowMusicSheetCalculator();
         const reader: MusicSheetReader = new MusicSheetReader();
         this.sheet = reader.createMusicSheet(score, "Untitled Score");
         if (this.sheet === undefined) {
             // error loading sheet, probably already logged, do nothing
             return Promise.reject(new Error("given music sheet was incomplete or could not be loaded."));
         }
+        log.info(`[OSMD] Loaded sheet ${this.sheet.TitleString} successfully.`);
+
+        this.updateGraphic();
+
+        return Promise.resolve({});
+    }
+
+    /**
+     * (Re-)creates the graphic sheet from the music sheet
+     */
+    public updateGraphic(): void {
+        const calc: MusicSheetCalculator = new VexFlowMusicSheetCalculator();
         this.graphic = new GraphicalMusicSheet(this.sheet, calc);
         if (this.drawingParameters.drawCursors && this.cursor) {
             this.cursor.init(this.sheet.MusicPartManager, this.graphic);
         }
-        log.info(`[OSMD] Loaded sheet ${this.sheet.TitleString} successfully.`);
-        return Promise.resolve({});
     }
 
     /**

+ 34 - 1
test/Common/OSMD/OSMD_Test.ts

@@ -1,7 +1,7 @@
 import chai = require("chai");
 import { OpenSheetMusicDisplay } from "../../../src/OpenSheetMusicDisplay/OpenSheetMusicDisplay";
 import { TestUtils } from "../../Util/TestUtils";
-import { VoiceEntry, Instrument, Note } from "../../../src";
+import { VoiceEntry, Instrument, Note, Staff, Voice, GraphicalStaffEntry, GraphicalNote, Fraction, Pitch, AccidentalEnum } from "../../../src";
 
 describe("OpenSheetMusicDisplay Main Export", () => {
     let container1: HTMLElement;
@@ -277,6 +277,39 @@ describe("OpenSheetMusicDisplay Main Export", () => {
                 chai.expect(notes.length).to.equal(2);
             });
         });
+
+        describe("updateGraphic", () => {
+            it("updates the graphical sheet with mutations on the music sheet", () => {
+                const staff: Staff = opensheetmusicdisplay.Sheet.Staves[0];
+                const voice: Voice = staff.Voices[0];
+                const voiceEntry: VoiceEntry = voice.VoiceEntries[0];
+                const numNotesBefore: number = voiceEntry.Notes.length;
+
+                // Validate current state
+                {
+                    const graphicalStaffEntry: GraphicalStaffEntry = opensheetmusicdisplay.GraphicSheet.getStaffEntry(0);
+                    const graphicalNotes: GraphicalNote[] = graphicalStaffEntry.findVoiceEntryGraphicalNotes(voiceEntry);
+
+                    chai.expect(graphicalNotes.length).to.equal(numNotesBefore);
+                }
+
+                const newNote: Note = new Note(
+                    voiceEntry,
+                    voiceEntry.ParentSourceStaffEntry,
+                    new Fraction(1),
+                    new Pitch(11, 1, AccidentalEnum.NATURAL));
+                voiceEntry.Notes.push(newNote);
+
+                opensheetmusicdisplay.updateGraphic();
+
+                {
+                    const graphicalStaffEntry: GraphicalStaffEntry = opensheetmusicdisplay.GraphicSheet.getStaffEntry(0);
+                    const graphicalNotes: GraphicalNote[] = graphicalStaffEntry.findVoiceEntryGraphicalNotes(voiceEntry);
+
+                    chai.expect(graphicalNotes.length).to.equal(numNotesBefore + 1);
+                }
+            });
+        });
     });
 
 });