Browse Source

feat(ChordSymbols): show all chordsymbols over a single note/staffEntry (spacing WIP) (#599)

part of #599 (feature implemented, but spacing would be nice)
sschmid 5 years ago
parent
commit
6eb97faab8

+ 1 - 1
src/MusicalScore/Graphical/GraphicalStaffEntry.ts

@@ -39,7 +39,7 @@ export abstract class GraphicalStaffEntry extends GraphicalObject {
         }
     }
 
-    public graphicalChordContainer: GraphicalChordSymbolContainer;
+    public graphicalChordContainers: GraphicalChordSymbolContainer[] = [];
     public graphicalLink: GraphicalStaffEntryLink;
 
     // Extra member needed, as tie notes have no direct source entry with the right time stamp.

+ 10 - 8
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -868,14 +868,16 @@ export abstract class MusicSheetCalculator {
                     const sbc: SkyBottomLineCalculator = staffLine.SkyBottomLineCalculator;
                     for (const measure of staffLine.Measures) {
                         for (const staffEntry of measure.staffEntries) {
-                            if (!staffEntry.graphicalChordContainer) {
+                            if (!staffEntry.graphicalChordContainers || staffEntry.graphicalChordContainers.length === 0) {
                                 continue;
                             }
-                            const sps: BoundingBox = staffEntry.PositionAndShape;
-                            const gps: BoundingBox = staffEntry.graphicalChordContainer.PositionAndShape;
-                            const start: number = gps.BorderMarginLeft + sps.AbsolutePosition.x;
-                            const end: number = gps.BorderMarginRight + sps.AbsolutePosition.x;
-                            sbc.updateSkyLineInRange(start, end, sps.BorderMarginTop);
+                            for (const graphicalChordContainer of staffEntry.graphicalChordContainers) {
+                                const sps: BoundingBox = staffEntry.PositionAndShape;
+                                const gps: BoundingBox = graphicalChordContainer.PositionAndShape;
+                                const start: number = gps.BorderMarginLeft + sps.AbsolutePosition.x;
+                                const end: number = gps.BorderMarginRight + sps.AbsolutePosition.x;
+                                sbc.updateSkyLineInRange(start, end, sps.BorderMarginTop);
+                            }
                         }
                     }
                 }
@@ -2047,9 +2049,9 @@ export abstract class MusicSheetCalculator {
                     const clefInstruction: ClefInstruction = <ClefInstruction>sourceStaffEntry.Instructions[0];
                     MusicSheetCalculator.symbolFactory.createInStaffClef(graphicalStaffEntry, clefInstruction);
                 }
-                if (sourceStaffEntry.ChordContainer !== undefined) {
+                if (sourceStaffEntry.ChordContainers && sourceStaffEntry.ChordContainers.length > 0) {
                     sourceStaffEntry.ParentStaff.ParentInstrument.HasChordSymbols = true;
-                    MusicSheetCalculator.symbolFactory.createChordSymbol(
+                    MusicSheetCalculator.symbolFactory.createChordSymbols(
                         sourceStaffEntry,
                         graphicalStaffEntry,
                         this.graphicalMusicSheet.ParentMusicSheet.Transpose);

+ 18 - 11
src/MusicalScore/Graphical/VexFlow/VexFlowGraphicalSymbolFactory.ts

@@ -155,17 +155,24 @@ export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
      * @param graphicalStaffEntry
      * @param transposeHalftones
      */
-    public createChordSymbol(sourceStaffEntry: SourceStaffEntry, graphicalStaffEntry: GraphicalStaffEntry, transposeHalftones: number): void {
-      const graphicalChordSymbolContainer: GraphicalChordSymbolContainer =
-        new GraphicalChordSymbolContainer(sourceStaffEntry.ChordContainer,
-                                          graphicalStaffEntry.PositionAndShape,
-                                          EngravingRules.Rules.ChordSymbolTextHeight,
-                                          transposeHalftones);
-      const graphicalLabel: GraphicalLabel = graphicalChordSymbolContainer.GetGraphicalLabel;
-      graphicalLabel.PositionAndShape.RelativePosition.y -= EngravingRules.Rules.ChordSymbolYOffset;
-      graphicalLabel.setLabelPositionAndShapeBorders();
-      graphicalChordSymbolContainer.PositionAndShape.calculateBoundingBox();
-      graphicalStaffEntry.graphicalChordContainer = graphicalChordSymbolContainer;
+    public createChordSymbols(sourceStaffEntry: SourceStaffEntry, graphicalStaffEntry: GraphicalStaffEntry, transposeHalftones: number): void {
+        let xShift: number = 0;
+        const chordSymbolSpacing: number = 1; // TODO add engravingrules variable, check for available space until next staffEntry
+        for (const chordSymbolContainer of sourceStaffEntry.ChordContainers) {
+            const graphicalChordSymbolContainer: GraphicalChordSymbolContainer =
+              new GraphicalChordSymbolContainer(chordSymbolContainer,
+                                                graphicalStaffEntry.PositionAndShape,
+                                                EngravingRules.Rules.ChordSymbolTextHeight,
+                                                transposeHalftones);
+            const graphicalLabel: GraphicalLabel = graphicalChordSymbolContainer.GetGraphicalLabel;
+            graphicalLabel.PositionAndShape.RelativePosition.y -= EngravingRules.Rules.ChordSymbolYOffset;
+            graphicalLabel.PositionAndShape.RelativePosition.x += xShift;
+            graphicalLabel.setLabelPositionAndShapeBorders();
+            graphicalChordSymbolContainer.PositionAndShape.calculateBoundingBox();
+            graphicalStaffEntry.graphicalChordContainers.push(graphicalChordSymbolContainer);
+
+            xShift += graphicalLabel.PositionAndShape.Size.width + chordSymbolSpacing;
+        }
     }
 
     /**

+ 5 - 3
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -240,9 +240,11 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
 
 
     private drawStaffEntry(staffEntry: GraphicalStaffEntry): void {
-        // Draw ChordSymbol
-        if (staffEntry.graphicalChordContainer !== undefined) {
-            this.drawLabel(staffEntry.graphicalChordContainer.GetGraphicalLabel, <number>GraphicalLayers.Notes);
+        // Draw ChordSymbols
+        if (staffEntry.graphicalChordContainers !== undefined && staffEntry.graphicalChordContainers.length > 0) {
+            for (const graphicalChordContainer of staffEntry.graphicalChordContainers) {
+                this.drawLabel(graphicalChordContainer.GetGraphicalLabel, <number>GraphicalLayers.Notes);
+            }
         }
         if (EngravingRules.Rules.RenderLyrics) {
             if (staffEntry.LyricsEntries.length > 0) {

+ 1 - 1
src/MusicalScore/Interfaces/IGraphicalSymbolFactory.ts

@@ -54,7 +54,7 @@ export interface IGraphicalSymbolFactory {
 
     createInStaffClef(graphicalStaffEntry: GraphicalStaffEntry, clefInstruction: ClefInstruction): void;
 
-    createChordSymbol(
+    createChordSymbols(
         sourceStaffEntry: SourceStaffEntry,
         graphicalStaffEntry: GraphicalStaffEntry,
         transposeHalftones: number): void;

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

@@ -354,7 +354,7 @@ export class InstrumentReader {
           );
           this.saveAbstractInstructionList(this.instrument.Staves.length, beginOfMeasure);
           if (this.openChordSymbolContainers.length !== 0) {
-            this.currentStaffEntry.ChordContainer = this.openChordSymbolContainers[0];
+            this.currentStaffEntry.ChordContainers = this.openChordSymbolContainers;
             // TODO handle multiple chords on one note/staffentry
             this.openChordSymbolContainers = [];
           }

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

@@ -24,7 +24,7 @@ export class SourceStaffEntry {
     private voiceEntries: VoiceEntry[] = [];
     private staffEntryLink: StaffEntryLink;
     private instructions: AbstractNotationInstruction[] = [];
-    private chordSymbolContainer: ChordSymbolContainer;
+    private chordSymbolContainers: ChordSymbolContainer[] = [];
 
     public get ParentStaff(): Staff {
         return this.parentStaff;
@@ -72,12 +72,12 @@ export class SourceStaffEntry {
         this.instructions = value;
     }
 
-    public get ChordContainer(): ChordSymbolContainer {
-        return this.chordSymbolContainer;
+    public get ChordContainers(): ChordSymbolContainer[] {
+        return this.chordSymbolContainers;
     }
 
-    public set ChordContainer(value: ChordSymbolContainer) {
-        this.chordSymbolContainer = value;
+    public set ChordContainers(value: ChordSymbolContainer[]) {
+        this.chordSymbolContainers = value;
     }
 
     // public removeAllInstructionsOfType(type: AbstractNotationInstruction): number {