VexFlowMeasure.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import {StaffMeasure} from "../StaffMeasure";
  2. import {SourceMeasure} from "../../VoiceData/SourceMeasure";
  3. import {Staff} from "../../VoiceData/Staff";
  4. import {StaffLine} from "../StaffLine";
  5. import {SystemLinesEnum} from "../SystemLinesEnum";
  6. import {ClefInstruction} from "../../VoiceData/Instructions/ClefInstruction";
  7. import {KeyInstruction} from "../../VoiceData/Instructions/KeyInstruction";
  8. import {RhythmInstruction} from "../../VoiceData/Instructions/RhythmInstruction";
  9. import {ClefEnum} from "../../VoiceData/Instructions/ClefInstruction";
  10. import {RhythmSymbolEnum} from "../../VoiceData/Instructions/RhythmInstruction";
  11. import {KeyEnum} from "../../VoiceData/Instructions/KeyInstruction";
  12. import {VoiceEntry} from "../../VoiceData/VoiceEntry";
  13. export class VexFlowMeasure extends StaffMeasure {
  14. constructor(staff: Staff, staffLine: StaffLine = undefined, sourceMeasure: SourceMeasure = undefined) {
  15. super(staff, sourceMeasure, staffLine);
  16. // this.MinimumStaffEntriesWidth =
  17. }
  18. private static majorMap: {[_: number]: string; } = {
  19. "0": "C", 1: "G", 2: "D", 3: "A", 4: "E", 5: "B", 6: "F#", 7: "C#",
  20. 8: "G#", "-1": "F", "-8": "Fb", "-7": "Cb", "-6": "Gb", "-5": "Db", "-4": "Ab", "-3": "Eb", "-2": "Bb",
  21. };
  22. private static minorMap: {[_: number]: string; } = {
  23. "1": "E", "7": "A#", "0": "A", "6": "D#", "3": "F#", "-5": "Bb", "-4": "F", "-7": "Ab", "-6": "Eb",
  24. "-1": "D", "4": "C#", "-3": "C", "-2": "G", "2": "B", "5": "G#", "-8": "Db", "8": "E#",
  25. };
  26. private stave: Vex.Flow.Stave;
  27. private static toVFStaveNote(voiceEntry: VoiceEntry): Vex.Flow.StaveNote {
  28. return undefined;
  29. }
  30. private static toVFClef(clef: ClefInstruction) {
  31. let type: string;
  32. switch (clef.ClefType) {
  33. case ClefEnum.G:
  34. type = "treble";
  35. break;
  36. case ClefEnum.F:
  37. type = "bass";
  38. break;
  39. case ClefEnum.C:
  40. type = "baritone-c";
  41. break;
  42. case ClefEnum.percussion:
  43. type = "percussion";
  44. break;
  45. case ClefEnum.TAB:
  46. type = "tab";
  47. break;
  48. default:
  49. }
  50. return new Vex.Flow.Clef(type);
  51. }
  52. private static toVFTimeSignature(rhythm: RhythmInstruction): Vex.Flow.TimeSignature {
  53. let timeSpec: string;
  54. switch (rhythm.SymbolEnum) {
  55. case RhythmSymbolEnum.NONE:
  56. timeSpec = rhythm.Rhythm.Numerator + "/" + rhythm.Rhythm.Denominator;
  57. break;
  58. case RhythmSymbolEnum.COMMON:
  59. timeSpec = "C";
  60. break;
  61. case RhythmSymbolEnum.CUT:
  62. timeSpec = "C|";
  63. break;
  64. default:
  65. }
  66. return new Vex.Flow.TimeSignature(timeSpec);
  67. }
  68. private static toKeySignatureString(key: KeyInstruction): string {
  69. switch (key.Mode) {
  70. case KeyEnum.none:
  71. return undefined;
  72. case KeyEnum.minor:
  73. return VexFlowMeasure.minorMap[key.Key];
  74. case KeyEnum.major:
  75. return VexFlowMeasure.majorMap[key.Key] + "m";
  76. default:
  77. }
  78. }
  79. /**
  80. * Reset all the geometric values and parameters of this measure and put it in an initialized state.
  81. * This is needed to evaluate a measure a second time by system builder.
  82. */
  83. public resetLayout(): void {
  84. this.beginInstructionsWidth = 0;
  85. }
  86. /**
  87. * returns the x-width of a given measure line.
  88. * @param line
  89. * @returns {SystemLinesEnum} the x-width
  90. */
  91. public getLineWidth(line: SystemLinesEnum): number {
  92. // FIXME: See values in VexFlow's stavebarline.js
  93. switch (line) {
  94. case SystemLinesEnum.SingleThin:
  95. return 5;
  96. case SystemLinesEnum.DoubleThin:
  97. return 5;
  98. case SystemLinesEnum.ThinBold:
  99. return 5;
  100. case SystemLinesEnum.BoldThinDots:
  101. return 5;
  102. case SystemLinesEnum.DotsThinBold:
  103. return 5;
  104. case SystemLinesEnum.DotsBoldBoldDots:
  105. return 5;
  106. case SystemLinesEnum.None:
  107. return 0;
  108. default:
  109. return 0;
  110. }
  111. }
  112. /**
  113. * adds the given clef to the begin of the measure.
  114. * This has to update/increase BeginInstructionsWidth.
  115. * @param clef
  116. */
  117. public addClefAtBegin(clef: ClefInstruction): void {
  118. let vfclef: Vex.Flow.Clef = VexFlowMeasure.toVFClef(clef);
  119. this.stave.addClef(vfclef, undefined, undefined, Vex.Flow.StaveModifier.Position.BEGIN);
  120. this.increaseBeginInstructionWidth(vfclef);
  121. }
  122. /**
  123. * adds the given key to the begin of the measure.
  124. * This has to update/increase BeginInstructionsWidth.
  125. * @param currentKey the new valid key.
  126. * @param previousKey the old cancelled key. Needed to show which accidentals are not valid any more.
  127. * @param currentClef the valid clef. Needed to put the accidentals on the right y-positions.
  128. */
  129. public addKeyAtBegin(currentKey: KeyInstruction, previousKey: KeyInstruction, currentClef: ClefInstruction): void {
  130. let keySig: Vex.Flow.KeySignature = new Vex.Flow.KeySignature(
  131. VexFlowMeasure.toKeySignatureString(currentKey),
  132. VexFlowMeasure.toKeySignatureString(previousKey)
  133. );
  134. this.stave.addModifier(keySig, Vex.Flow.StaveModifier.Position.BEGIN);
  135. }
  136. /**
  137. * adds the given rhythm to the begin of the measure.
  138. * This has to update/increase BeginInstructionsWidth.
  139. * @param rhythm
  140. */
  141. public addRhythmAtBegin(rhythm: RhythmInstruction): void {
  142. let timeSig: Vex.Flow.TimeSignature = VexFlowMeasure.toVFTimeSignature(rhythm);
  143. this.stave.addModifier(
  144. timeSig,
  145. Vex.Flow.StaveModifier.Position.BEGIN
  146. );
  147. this.increaseBeginInstructionWidth(timeSig);
  148. }
  149. /**
  150. * adds the given clef to the end of the measure.
  151. * This has to update/increase EndInstructionsWidth.
  152. * @param clef
  153. */
  154. public addClefAtEnd(clef: ClefInstruction): void {
  155. let vfclef: Vex.Flow.Clef = VexFlowMeasure.toVFClef(clef);
  156. this.stave.addClef(vfclef, undefined, undefined, Vex.Flow.StaveModifier.Position.END);
  157. this.increaseBeginInstructionWidth(vfclef);
  158. }
  159. /**
  160. * This method sets the x-position relative to the staffline. (y-Position is always 0 relative to the staffline)
  161. * @param x
  162. */
  163. public setPositionInStaffline(x: number): void {
  164. this.stave.setX(x);
  165. }
  166. /**
  167. * Sets the overall x-width of the measure.
  168. * @param width
  169. */
  170. public setWidth(width: number): void {
  171. // FIXME: this should consider modifiers!
  172. this.stave.setWidth(width);
  173. }
  174. /**
  175. * This method is called after the StaffEntriesScaleFactor has been set.
  176. * Here the final x-positions of the staff entries have to be set.
  177. * (multiply the minimal positions with the scaling factor, considering the BeginInstructionsWidth)
  178. */
  179. public layoutSymbols(): void {
  180. let min: number = 0;
  181. this.setWidth(min * this.staffEntriesScaleFactor);
  182. this.stave.format();
  183. this.stave.draw();
  184. }
  185. public getVexFlowVoices(): { [id: number]: Vex.Flow.Voice; } {
  186. let notes: { [id: number]: Vex.Flow.StaveNote[]; } = {};
  187. for (let entry of this.staffEntries) {
  188. for (let voiceEntry of entry.sourceStaffEntry.VoiceEntries) {
  189. let id: number = voiceEntry.ParentVoice.VoiceId;
  190. if (!(id in notes)) {
  191. notes[id] = [];
  192. }
  193. notes[id].push(VexFlowMeasure.toVFStaveNote(voiceEntry));
  194. }
  195. }
  196. let voices: { [id: number]: Vex.Flow.Voice; } = {};
  197. for (let id in notes) {
  198. if (notes.hasOwnProperty(id)) {
  199. let voice: Vex.Flow.Voice = new Vex.Flow.Voice({
  200. beat_value: 4,
  201. num_beats: 4,
  202. resolution: Vex.Flow.RESOLUTION,
  203. });
  204. voice.addTickables(notes[id]);
  205. voices[id] = voice;
  206. }
  207. }
  208. return voices;
  209. }
  210. private increaseBeginInstructionWidth(modifier: any): void {
  211. // FIXME: Check possible paddings...
  212. //this.beginInstructionsWidth += modifier.getWidth();
  213. this.beginInstructionsWidth = this.stave.getNoteStartX();
  214. }
  215. }