Bläddra i källkod

feat(percussion_stafflines) Render number of lines in staff-lines MXML element
Utilize method found here: 0xfe/vexflow#597 (comment)
Creation of StaffLinesInstruction to relay specified # to renderer, defaulting to 5

Justin Litten 5 år sedan
förälder
incheckning
6290e43655

+ 8 - 0
src/MusicalScore/Graphical/GraphicalMeasure.ts

@@ -134,6 +134,14 @@ export abstract class GraphicalMeasure extends GraphicalObject {
     }
 
     /**
+     * Sets the number of stafflines that are rendered, so that they are centered properly
+     * @param lineNumber
+     */
+    public setLineNumber(lineNumber: number): void {
+        throw new Error("not implemented");
+    }
+
+    /**
      * Add the given key to the begin of the measure.
      * This has to update/increase BeginInstructionsWidth.
      * @param currentKey - The new valid key.

+ 19 - 2
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -20,6 +20,7 @@ import {MusicSheetCalculator} from "./MusicSheetCalculator";
 import {MidiInstrument} from "../VoiceData/Instructions/ClefInstruction";
 import {CollectionUtil} from "../../Util/CollectionUtil";
 import {SystemLinePosition} from "./SystemLinePosition";
+import { StaffLinesInstruction } from "../VoiceData/Instructions/StaffLinesInstruction";
 
 export class MusicSystemBuilder {
     protected measureList: GraphicalMeasure[][];
@@ -37,6 +38,7 @@ export class MusicSystemBuilder {
     protected activeRhythm: RhythmInstruction[];
     protected activeKeys: KeyInstruction[];
     protected activeClefs: ClefInstruction[];
+    protected activeStafflines: StaffLinesInstruction[];
     protected globalSystemIndex: number = 0;
     protected leadSheet: boolean = false;
 
@@ -50,6 +52,7 @@ export class MusicSystemBuilder {
         this.activeRhythm = new Array(this.numberOfVisibleStaffLines);
         this.activeKeys = new Array(this.numberOfVisibleStaffLines);
         this.activeClefs = new Array(this.numberOfVisibleStaffLines);
+        this.activeStafflines = new Array(this.numberOfVisibleStaffLines);
         this.initializeActiveInstructions(this.measureList[0]);
     }
 
@@ -363,6 +366,7 @@ export class MusicSystemBuilder {
                 keyInstruction = this.transposeKeyInstruction(keyInstruction, graphicalMeasure);
                 this.activeKeys[i] = keyInstruction;
                 this.activeRhythm[i] = <RhythmInstruction>firstSourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions[2];
+                this.activeStafflines[i] = <StaffLinesInstruction>firstSourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions[3];
             }
         }
     }
@@ -436,15 +440,18 @@ export class MusicSystemBuilder {
         let currentClef: ClefInstruction = undefined;
         let currentKey: KeyInstruction = undefined;
         let currentRhythm: RhythmInstruction = undefined;
+        let currentStafflines: StaffLinesInstruction = undefined;
         if (firstEntry !== undefined) {
             for (let idx: number = 0, len: number = firstEntry.Instructions.length; idx < len; ++idx) {
                 const abstractNotationInstruction: AbstractNotationInstruction = firstEntry.Instructions[idx];
                 if (abstractNotationInstruction instanceof ClefInstruction) {
                     currentClef = <ClefInstruction>abstractNotationInstruction;
                 } else if (abstractNotationInstruction instanceof KeyInstruction) {
-                    currentKey = KeyInstruction.copy(<KeyInstruction>abstractNotationInstruction);
+                    currentKey = <KeyInstruction>abstractNotationInstruction;
                 } else if (abstractNotationInstruction instanceof RhythmInstruction) {
                     currentRhythm = <RhythmInstruction>abstractNotationInstruction;
+                } else if (abstractNotationInstruction instanceof StaffLinesInstruction) {
+                    currentStafflines = <StaffLinesInstruction>abstractNotationInstruction;
                 }
             }
         }
@@ -453,15 +460,23 @@ export class MusicSystemBuilder {
                 currentClef = this.activeClefs[visibleStaffIdx];
             }
             if (currentKey === undefined) {
-                currentKey = KeyInstruction.copy(this.activeKeys[visibleStaffIdx]);
+                currentKey = this.activeKeys[visibleStaffIdx];
             }
             if (isFirstSourceMeasure && currentRhythm === undefined) {
                 currentRhythm = this.activeRhythm[visibleStaffIdx];
             }
         }
+        if (currentStafflines === undefined) {
+            currentStafflines = this.activeStafflines[visibleStaffIdx];
+        }
         let clefAdded: boolean = false;
         let keyAdded: boolean = false;
         let rhythmAdded: boolean = false;
+        //Instruction applies to entire staff, don't need to check for start
+        if (currentStafflines !== undefined) {
+            measure.setLineNumber(currentStafflines.NumberOfLines);
+        }
+
         if (currentClef !== undefined) {
             measure.addClefAtBegin(currentClef);
             clefAdded = true;
@@ -521,6 +536,8 @@ export class MusicSystemBuilder {
                         this.activeKeys[visStaffIdx] = <KeyInstruction>abstractNotationInstruction;
                     } else if (abstractNotationInstruction instanceof RhythmInstruction) {
                         this.activeRhythm[visStaffIdx] = <RhythmInstruction>abstractNotationInstruction;
+                    } else if (abstractNotationInstruction instanceof StaffLinesInstruction) {
+                        this.activeStafflines[visStaffIdx] = <StaffLinesInstruction>abstractNotationInstruction;
                     }
                 }
             }

+ 40 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -168,6 +168,46 @@ export class VexFlowMeasure extends GraphicalMeasure {
     }
 
     /**
+     * Sets the number of stafflines that are rendered, so that they are centered properly
+     * @param lineNumber
+     */
+    public setLineNumber(lineNumber: number): void {
+        if (lineNumber !== 5) {
+            if (lineNumber === 0) {
+                (this.stave as any).setNumLines(0);
+            } else if (lineNumber === 1) {
+                // Vex.Flow.Stave.setNumLines hides all but the top line.
+                // this is better
+                (this.stave.options as any).line_config = [
+                    { visible: false },
+                    { visible: false },
+                    { visible: true }, // show middle
+                    { visible: false },
+                    { visible: false },
+                ];
+            } else if (lineNumber === 2) {
+                (this.stave.options as any).line_config = [
+                    { visible: false },
+                    { visible: false },
+                    { visible: true }, // show middle
+                    { visible: true },
+                    { visible: false },
+                ];
+            } else if (lineNumber === 3) {
+                (this.stave.options as any).line_config = [
+                    { visible: false },
+                    { visible: true },
+                    { visible: true }, // show middle
+                    { visible: true },
+                    { visible: false },
+                ];
+            } else {
+                (this.stave as any).setNumLines(lineNumber);
+            }
+        }
+    }
+
+    /**
      * adds the given key to the begin of the measure.
      * This has to update/increase BeginInstructionsWidth.
      * @param currentKey the new valid key.

+ 39 - 0
src/MusicalScore/ScoreIO/InstrumentReader.ts

@@ -26,6 +26,7 @@ import {SlurReader} from "./MusicSymbolModules/SlurReader";
 import {StemDirectionType} from "../VoiceData/VoiceEntry";
 import {NoteType, NoteTypeHandler} from "../VoiceData";
 import {SystemLinesEnumHelper} from "../Graphical";
+import { StaffLinesInstruction } from "../VoiceData/Instructions/StaffLinesInstruction";
 //import Dictionary from "typescript-collections/dist/lib/Dictionary";
 
 // FIXME: The following classes are missing
@@ -86,6 +87,7 @@ export class InstrumentReader {
   private activeClefs: ClefInstruction[];
   private activeKey: KeyInstruction;
   private activeRhythm: RhythmInstruction;
+  private activeStafflines: StaffLinesInstruction;
   private activeClefsHaveBeenInitialized: boolean[];
   private activeKeyHasBeenInitialized: boolean = false;
   private abstractInstructions: [number, AbstractNotationInstruction][] = [];
@@ -832,6 +834,20 @@ export class InstrumentReader {
         const clefInstruction: ClefInstruction = new ClefInstruction(clefEnum, clefOctaveOffset, line);
         this.abstractInstructions.push([staffNumber, clefInstruction]);
       }
+
+      //default to 5 stafflines
+      const staffLinesInstruction: StaffLinesInstruction = new StaffLinesInstruction();
+      //check for different numbers of lines on the staff
+      const staffDetailsNode: IXmlElement = node.element("staff-details");
+      if (staffDetailsNode !== undefined) {
+        const staffLinesNode: IXmlElement = staffDetailsNode.element("staff-lines");
+        if (staffLinesNode !== undefined) {
+          //detected different number of stafflines
+          staffLinesInstruction.NumberOfLines = parseInt(staffLinesNode.value, 10);
+        }
+      }
+
+      this.abstractInstructions.push([1, staffLinesInstruction]);
     }
     if (node.element("key") !== undefined && this.instrument.MidiInstrumentId !== MidiInstrument.Percussion) {
       let key: number = 0;
@@ -1098,6 +1114,29 @@ export class InstrumentReader {
           this.abstractInstructions.splice(i, 1);
         }
       }
+      if (value instanceof StaffLinesInstruction) {
+        const stafflinesInstruction: StaffLinesInstruction = <StaffLinesInstruction>value;
+        if (this.activeStafflines === undefined || this.activeStafflines !== stafflinesInstruction) {
+          this.activeStafflines = stafflinesInstruction;
+          this.abstractInstructions.splice(i, 1);
+          if (this.currentMeasure !== undefined) {
+            for (let j: number = this.inSourceMeasureInstrumentIndex; j < this.inSourceMeasureInstrumentIndex + numberOfStaves; j++) {
+              const newStafflinesInstruction: StaffLinesInstruction = stafflinesInstruction;
+              let firstStaffEntry: SourceStaffEntry;
+              if (this.currentMeasure.FirstInstructionsStaffEntries[j] === undefined) {
+                firstStaffEntry = new SourceStaffEntry(undefined, undefined);
+                this.currentMeasure.FirstInstructionsStaffEntries[j] = firstStaffEntry;
+              } else {
+                firstStaffEntry = this.currentMeasure.FirstInstructionsStaffEntries[j];
+              }
+              newStafflinesInstruction.Parent = firstStaffEntry;
+              firstStaffEntry.Instructions.push(newStafflinesInstruction);
+            }
+          }
+        } else {
+          this.abstractInstructions.splice(i, 1);
+        }
+      }
     }
   }
 

+ 45 - 0
src/MusicalScore/VoiceData/Instructions/StaffLinesInstruction.ts

@@ -0,0 +1,45 @@
+import {AbstractNotationInstruction} from "./AbstractNotationInstruction";
+
+/**
+ * A [[StaffLinesInstruction]] is the number of note lines that are rendered for a staff.
+ */
+export class StaffLinesInstruction extends AbstractNotationInstruction {
+    constructor(numberOfLines: number = 5) {
+        super(undefined); // FIXME no parent SourceStaffEntry
+        this.numberOfLines = numberOfLines;
+    }
+
+    private numberOfLines: number = 5;
+
+    public get NumberOfLines(): number {
+        return this.numberOfLines;
+    }
+
+    public set NumberOfLines(value: number) {
+        this.numberOfLines = value;
+    }
+
+    public clone(): StaffLinesInstruction {
+        return new StaffLinesInstruction(this.numberOfLines);
+    }
+
+    public OperatorEquals(staffline2: StaffLinesInstruction): boolean {
+        const staffline1: StaffLinesInstruction = this;
+        if (staffline1 === staffline2) {
+            return true;
+        }
+        if ((<Object>staffline1 === undefined) || (<Object>staffline2 === undefined)) {
+            return false;
+        }
+        return (staffline1.NumberOfLines === staffline2.NumberOfLines);
+    }
+
+    public OperatorNotEqual(staffline2: StaffLinesInstruction): boolean {
+        const staffline1: StaffLinesInstruction = this;
+        return !(staffline1 === staffline2);
+    }
+
+    public ToString(): string {
+        return "Number of Stafflines: " + this.numberOfLines;
+    }
+}