VexFlowOctaveShift.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import Vex from "vexflow";
  2. import { GraphicalOctaveShift } from "../GraphicalOctaveShift";
  3. import { OctaveShift, OctaveEnum } from "../../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
  4. import { BoundingBox } from "../BoundingBox";
  5. import { GraphicalStaffEntry } from "../GraphicalStaffEntry";
  6. import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
  7. import log from "loglevel";
  8. /**
  9. * The vexflow adaptation of a graphical shift.
  10. */
  11. export class VexFlowOctaveShift extends GraphicalOctaveShift {
  12. /** Defines the note where the octave shift starts */
  13. public startNote: Vex.Flow.StemmableNote;
  14. /** Defines the note where the octave shift ends */
  15. public endNote: Vex.Flow.StemmableNote;
  16. /** Top or bottom of the staffline */
  17. private position: Vex.Flow.TextBracket.Positions;
  18. /** Supscript is a smaller text after the regular text (e.g. va after 8) */
  19. private supscript: string;
  20. /** Main text element */
  21. private text: string;
  22. /**
  23. * Create a new vexflow ocatve shift
  24. * @param octaveShift the object read by the ExpressionReader
  25. * @param parent the bounding box of the parent
  26. */
  27. constructor(octaveShift: OctaveShift, parent: BoundingBox) {
  28. super(octaveShift, parent);
  29. switch (octaveShift.Type) {
  30. case OctaveEnum.VA8:
  31. this.position = Vex.Flow.TextBracket.Positions.TOP;
  32. this.supscript = "va";
  33. this.text = "8";
  34. break;
  35. case OctaveEnum.MA15:
  36. this.position = Vex.Flow.TextBracket.Positions.TOP;
  37. this.supscript = "ma";
  38. this.text = "15";
  39. break;
  40. case OctaveEnum.VB8:
  41. this.position = Vex.Flow.TextBracket.Positions.BOTTOM;
  42. this.supscript = "vb";
  43. this.text = "8";
  44. break;
  45. case OctaveEnum.MB15:
  46. this.position = Vex.Flow.TextBracket.Positions.BOTTOM;
  47. this.supscript = "mb";
  48. this.text = "15";
  49. break;
  50. default:
  51. log.error("Unknown or NONE octaveshift. This should not be called!");
  52. break;
  53. }
  54. }
  55. /**
  56. * Set a start note using a staff entry
  57. * @param graphicalStaffEntry the staff entry that holds the start note
  58. */
  59. public setStartNote(graphicalStaffEntry: GraphicalStaffEntry): boolean {
  60. for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
  61. const vve: VexFlowVoiceEntry = (gve as VexFlowVoiceEntry);
  62. if (vve?.vfStaveNote) {
  63. this.startNote = vve.vfStaveNote;
  64. return true;
  65. }
  66. }
  67. return false; // couldn't find a startNote
  68. }
  69. /**
  70. * Set an end note using a staff entry
  71. * @param graphicalStaffEntry the staff entry that holds the end note
  72. */
  73. public setEndNote(graphicalStaffEntry: GraphicalStaffEntry): boolean {
  74. // this is duplicate code from setStartNote, but if we make one general method, we add a lot of branching.
  75. for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
  76. const vve: VexFlowVoiceEntry = (gve as VexFlowVoiceEntry);
  77. if (vve?.vfStaveNote) {
  78. this.endNote = vve.vfStaveNote;
  79. return true;
  80. }
  81. }
  82. return false; // couldn't find an endNote
  83. }
  84. /**
  85. * Get the actual vexflow text bracket used for drawing
  86. */
  87. public getTextBracket(): Vex.Flow.TextBracket {
  88. return new Vex.Flow.TextBracket({
  89. position: this.position,
  90. start: this.startNote,
  91. stop: this.endNote,
  92. superscript: this.supscript,
  93. text: this.text,
  94. });
  95. }
  96. }