VexFlowStaffEntry.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import Vex = require("vexflow");
  2. import { GraphicalStaffEntry } from "../GraphicalStaffEntry";
  3. import { VexFlowMeasure } from "./VexFlowMeasure";
  4. import { SourceStaffEntry } from "../../VoiceData/SourceStaffEntry";
  5. import { unitInPixels } from "./VexFlowMusicSheetDrawer";
  6. import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
  7. import { Note } from "../../VoiceData/Note";
  8. export class VexFlowStaffEntry extends GraphicalStaffEntry {
  9. constructor(measure: VexFlowMeasure, sourceStaffEntry: SourceStaffEntry, staffEntryParent: VexFlowStaffEntry) {
  10. super(measure, sourceStaffEntry, staffEntryParent);
  11. }
  12. // if there is a in-measure clef given before this staffEntry,
  13. // it will be converted to a Vex.Flow.ClefNote and assigned to this variable:
  14. public vfClefBefore: Vex.Flow.ClefNote;
  15. /**
  16. * Calculates the staff entry positions from the VexFlow stave information and the tickabels inside the staff.
  17. * This is needed in order to set the OSMD staff entries (which are almost the same as tickables) to the correct positionts.
  18. * It is also needed to be done after formatting!
  19. */
  20. public calculateXPosition(): void {
  21. const stave: Vex.Flow.Stave = (this.parentMeasure as VexFlowMeasure).getVFStave();
  22. // sets the vexflow x positions back into the bounding boxes of the staff entries in the osmd object model.
  23. // The positions are needed for cursor placement and mouse/tap interactions
  24. let lastBorderLeft: number = 0;
  25. for (const gve of this.graphicalVoiceEntries as VexFlowVoiceEntry[]) {
  26. if (gve.vfStaveNote) {
  27. gve.vfStaveNote.setStave(stave);
  28. if (!gve.vfStaveNote.preFormatted) {
  29. continue;
  30. }
  31. gve.applyBordersFromVexflow();
  32. if (this.parentMeasure.ParentStaff.isTab) {
  33. // the x-position could be finetuned for the cursor.
  34. // somehow, gve.vfStaveNote.getBoundingBox() is null for a TabNote (which is a StemmableNote).
  35. this.PositionAndShape.RelativePosition.x = (gve.vfStaveNote.getAbsoluteX() + (<any>gve.vfStaveNote).glyph.getWidth()) / unitInPixels;
  36. } else {
  37. this.PositionAndShape.RelativePosition.x = gve.vfStaveNote.getBoundingBox().getX() / unitInPixels;
  38. }
  39. const sourceNote: Note = gve.notes[0].sourceNote;
  40. if (sourceNote.isRest() && sourceNote.Length.RealValue === this.parentMeasure.parentSourceMeasure.ActiveTimeSignature.RealValue) {
  41. // whole rest: length = measure length. (4/4 in a 4/4 time signature, 3/4 in a 3/4 time signature, 1/4 in a 1/4 time signature, etc.)
  42. // see Note.isWholeRest(), which is currently not safe
  43. this.PositionAndShape.RelativePosition.x +=
  44. this.parentMeasure.parentSourceMeasure.Rules.WholeRestXShiftVexflow - 0.1; // xShift from VexFlowConverter
  45. gve.PositionAndShape.BorderLeft = -0.7;
  46. gve.PositionAndShape.BorderRight = 0.7;
  47. }
  48. if (gve.PositionAndShape.BorderLeft < lastBorderLeft) {
  49. lastBorderLeft = gve.PositionAndShape.BorderLeft;
  50. }
  51. }
  52. }
  53. this.PositionAndShape.RelativePosition.x -= lastBorderLeft;
  54. this.PositionAndShape.calculateBoundingBox();
  55. }
  56. }