VexFlowPedal.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import Vex from "vexflow";
  2. import { BoundingBox } from "../BoundingBox";
  3. import { GraphicalStaffEntry } from "../GraphicalStaffEntry";
  4. import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
  5. import { GraphicalPedal } from "../GraphicalPedal";
  6. import { Pedal } from "../../VoiceData/Expressions/ContinuousExpressions/Pedal";
  7. import { MusicSymbol } from "../MusicSymbol";
  8. import { GraphicalMeasure } from "../GraphicalMeasure";
  9. import { VexFlowMeasure } from "./VexFlowMeasure";
  10. /**
  11. * The vexflow adaptation of a pedal marking
  12. */
  13. export class VexFlowPedal extends GraphicalPedal {
  14. /** Defines the note where the pedal starts */
  15. public startNote: Vex.Flow.StemmableNote;
  16. /** Defines the note where the pedal ends */
  17. public endNote: Vex.Flow.StemmableNote;
  18. private vfStyle: Vex.Flow.PedalMarking.Styles = Vex.Flow.PedalMarking.Styles.BRACKET;
  19. public DepressText: string;
  20. public ReleaseText: string;
  21. public startVfVoiceEntry: VexFlowVoiceEntry;
  22. public endVfVoiceEntry: VexFlowVoiceEntry;
  23. public endMeasure: GraphicalMeasure;
  24. private line: number = -3;
  25. public EndSymbolPositionAndShape: BoundingBox = undefined;
  26. /**
  27. * Create a new vexflow pedal marking
  28. * @param pedal the object read by the ExpressionReader
  29. * @param parent the bounding box of the parent
  30. */
  31. constructor(pedal: Pedal, parent: BoundingBox, openBegin: boolean = false, openEnd: boolean = false) {
  32. super(pedal, parent);
  33. switch (this.pedalSymbol) {
  34. case MusicSymbol.PEDAL_SYMBOL:
  35. //This renders the pedal symbols in VF.
  36. this.vfStyle = Vex.Flow.PedalMarking.Styles.TEXT;
  37. this.EndSymbolPositionAndShape = new BoundingBox(this, parent);
  38. break;
  39. case MusicSymbol.PEDAL_MIXED:
  40. if (openBegin && openEnd) {
  41. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_BOTH;
  42. } else if (openBegin) {
  43. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_BEGIN;
  44. } else if (openEnd) {
  45. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).MIXED_OPEN_END;
  46. } else {
  47. this.vfStyle = Vex.Flow.PedalMarking.Styles.MIXED;
  48. }
  49. break;
  50. case MusicSymbol.PEDAL_BRACKET:
  51. default:
  52. if (openBegin && openEnd) {
  53. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_BOTH;
  54. } else if (openBegin) {
  55. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_BEGIN;
  56. } else if (openEnd) {
  57. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_END;
  58. } else {
  59. this.vfStyle = Vex.Flow.PedalMarking.Styles.BRACKET;
  60. }
  61. break;
  62. }
  63. }
  64. /**
  65. * Set a start note using a staff entry
  66. * @param graphicalStaffEntry the staff entry that holds the start note
  67. */
  68. public setStartNote(graphicalStaffEntry: GraphicalStaffEntry): boolean {
  69. for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
  70. const vve: VexFlowVoiceEntry = (gve as VexFlowVoiceEntry);
  71. if (vve?.vfStaveNote) {
  72. this.startNote = vve.vfStaveNote;
  73. this.startVfVoiceEntry = vve;
  74. return true;
  75. }
  76. }
  77. return false; // couldn't find a startNote
  78. }
  79. /**
  80. * Set an end note using a staff entry
  81. * @param graphicalStaffEntry the staff entry that holds the end note
  82. */
  83. public setEndNote(graphicalStaffEntry: GraphicalStaffEntry): boolean {
  84. // this is duplicate code from setStartNote, but if we make one general method, we add a lot of branching.
  85. if (!graphicalStaffEntry) {
  86. return false;
  87. }
  88. for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
  89. const vve: VexFlowVoiceEntry = (gve as VexFlowVoiceEntry);
  90. if (vve?.vfStaveNote) {
  91. this.endNote = vve.vfStaveNote;
  92. this.endVfVoiceEntry = vve;
  93. return true;
  94. }
  95. }
  96. return false; // couldn't find an endNote
  97. }
  98. public setEndMeasure(graphicalMeasure: GraphicalMeasure): void {
  99. this.endMeasure = graphicalMeasure;
  100. }
  101. public CalculateBoundingBox(): void {
  102. //TODO?
  103. }
  104. public setLine(line: number): void {
  105. this.line = line;
  106. }
  107. /**
  108. * Get the actual vexflow Pedal Marking used for drawing
  109. */
  110. public getPedalMarking(): Vex.Flow.PedalMarking {
  111. const pedalMarking: Vex.Flow.PedalMarking = new Vex.Flow.PedalMarking([this.startNote, this.endNote]);
  112. if (this.endMeasure) {
  113. (pedalMarking as any).setEndStave((this.endMeasure as VexFlowMeasure).getVFStave());
  114. }
  115. pedalMarking.setStyle(this.vfStyle);
  116. pedalMarking.setLine(this.line);
  117. pedalMarking.setCustomText(this.DepressText, this.ReleaseText);
  118. //If our end note is at the end of a stave, set that value
  119. if(this.endVfVoiceEntry?.parentStaffEntry?.parentMeasure?.parentSourceMeasure?.VerticalSourceStaffEntryContainers?.last() ===
  120. this.endVfVoiceEntry?.parentVoiceEntry?.ParentSourceStaffEntry?.VerticalContainerParent){
  121. (pedalMarking as any).EndsStave = true;
  122. }
  123. return pedalMarking;
  124. }
  125. }