VexFlowPedal.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. public ChangeBegin: boolean = false;
  25. public ChangeEnd: boolean = false;
  26. private line: number = -3;
  27. public EndSymbolPositionAndShape: BoundingBox = undefined;
  28. /**
  29. * Create a new vexflow pedal marking
  30. * @param pedal the object read by the ExpressionReader
  31. * @param parent the bounding box of the parent
  32. */
  33. constructor(pedal: Pedal, parent: BoundingBox, openBegin: boolean = false, openEnd: boolean = false) {
  34. super(pedal, parent);
  35. this.ChangeBegin = pedal.ChangeBegin;
  36. this.ChangeEnd = pedal.ChangeEnd;
  37. switch (this.pedalSymbol) {
  38. case MusicSymbol.PEDAL_SYMBOL:
  39. //This renders the pedal symbols in VF.
  40. this.vfStyle = Vex.Flow.PedalMarking.Styles.TEXT;
  41. this.EndSymbolPositionAndShape = new BoundingBox(this, parent);
  42. break;
  43. case MusicSymbol.PEDAL_MIXED:
  44. if (openBegin && openEnd) {
  45. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_BOTH;
  46. } else if (openBegin) {
  47. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_BEGIN;
  48. } else if (openEnd) {
  49. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).MIXED_OPEN_END;
  50. } else {
  51. this.vfStyle = Vex.Flow.PedalMarking.Styles.MIXED;
  52. }
  53. break;
  54. case MusicSymbol.PEDAL_BRACKET:
  55. default:
  56. if (openBegin && openEnd) {
  57. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_BOTH;
  58. } else if (openBegin) {
  59. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_BEGIN;
  60. } else if (openEnd) {
  61. this.vfStyle = (Vex.Flow.PedalMarking.Styles as any).BRACKET_OPEN_END;
  62. } else {
  63. this.vfStyle = Vex.Flow.PedalMarking.Styles.BRACKET;
  64. }
  65. break;
  66. }
  67. }
  68. /**
  69. * Set a start note using a staff entry
  70. * @param graphicalStaffEntry the staff entry that holds the start note
  71. */
  72. public setStartNote(graphicalStaffEntry: GraphicalStaffEntry): boolean {
  73. if(!graphicalStaffEntry){
  74. return false;
  75. }
  76. for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
  77. const vve: VexFlowVoiceEntry = (gve as VexFlowVoiceEntry);
  78. if (vve?.vfStaveNote) {
  79. this.startNote = vve.vfStaveNote;
  80. this.startVfVoiceEntry = vve;
  81. return true;
  82. }
  83. }
  84. return false; // couldn't find a startNote
  85. }
  86. /**
  87. * Set an end note using a staff entry
  88. * @param graphicalStaffEntry the staff entry that holds the end note
  89. */
  90. public setEndNote(graphicalStaffEntry: GraphicalStaffEntry): boolean {
  91. // this is duplicate code from setStartNote, but if we make one general method, we add a lot of branching.
  92. if (!graphicalStaffEntry) {
  93. return false;
  94. }
  95. for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
  96. const vve: VexFlowVoiceEntry = (gve as VexFlowVoiceEntry);
  97. if (vve?.vfStaveNote) {
  98. this.endNote = vve.vfStaveNote;
  99. this.endVfVoiceEntry = vve;
  100. return true;
  101. }
  102. }
  103. return false; // couldn't find an endNote
  104. }
  105. public setEndMeasure(graphicalMeasure: GraphicalMeasure): void {
  106. this.endMeasure = graphicalMeasure;
  107. }
  108. public CalculateBoundingBox(): void {
  109. //TODO?
  110. }
  111. public setLine(line: number): void {
  112. this.line = line;
  113. }
  114. /**
  115. * Get the actual vexflow Pedal Marking used for drawing
  116. */
  117. public getPedalMarking(): Vex.Flow.PedalMarking {
  118. const pedalMarking: Vex.Flow.PedalMarking = new Vex.Flow.PedalMarking([this.startNote, this.endNote]);
  119. if (this.endMeasure) {
  120. (pedalMarking as any).setEndStave((this.endMeasure as VexFlowMeasure).getVFStave());
  121. }
  122. pedalMarking.setStyle(this.vfStyle);
  123. pedalMarking.setLine(this.line);
  124. pedalMarking.setCustomText(this.DepressText, this.ReleaseText);
  125. //If our end note is at the end of a stave, set that value
  126. if(this.endVfVoiceEntry?.parentStaffEntry === this.endVfVoiceEntry?.parentStaffEntry?.parentMeasure?.staffEntries.last() ||
  127. !this.endVfVoiceEntry){
  128. (pedalMarking as any).EndsStave = true;
  129. }
  130. (pedalMarking as any).ChangeBegin = this.ChangeBegin;
  131. (pedalMarking as any).ChangeEnd = this.ChangeEnd;
  132. return pedalMarking;
  133. }
  134. }