StaffMeasure.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import {MusicSystem} from "./MusicSystem";
  2. import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
  3. import {SourceMeasure} from "../VoiceData/SourceMeasure";
  4. import {StaffLine} from "./StaffLine";
  5. import {Staff} from "../VoiceData/Staff";
  6. import {GraphicalObject} from "./GraphicalObject";
  7. import {ClefInstruction} from "../VoiceData/Instructions/ClefInstruction";
  8. import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
  9. import {RhythmInstruction} from "../VoiceData/Instructions/RhythmInstruction";
  10. import {Fraction} from "../../Common/DataObjects/fraction";
  11. import {Voice} from "../VoiceData/Voice";
  12. import {VoiceEntry} from "../VoiceData/VoiceEntry";
  13. import {GraphicalNote} from "./GraphicalNote";
  14. import {SystemLinesEnum} from "./SystemLinesEnum";
  15. import {BoundingBox} from "./BoundingBox";
  16. import {PointF2D} from "../../Common/DataObjects/PointF2D";
  17. export class StaffMeasure extends GraphicalObject {
  18. protected firstInstructionStaffEntry: GraphicalStaffEntry;
  19. protected lastInstructionStaffEntry: GraphicalStaffEntry;
  20. constructor(staff: Staff = undefined, parentSourceMeasure: SourceMeasure = undefined, staffLine: StaffLine = undefined) {
  21. super();
  22. this.parentStaff = staff;
  23. this.parentSourceMeasure = parentSourceMeasure;
  24. this.parentStaffLine = staffLine;
  25. if (staffLine !== undefined) {
  26. this.parentStaff = staffLine.ParentStaff;
  27. this.PositionAndShape = new BoundingBox(this, staffLine.PositionAndShape);
  28. } else {
  29. this.PositionAndShape = new BoundingBox(this);
  30. }
  31. this.PositionAndShape.BorderBottom = 4;
  32. if (this.parentSourceMeasure !== undefined) {
  33. this.measureNumber = this.parentSourceMeasure.MeasureNumber;
  34. }
  35. this.staffEntries = [];
  36. }
  37. public parentSourceMeasure: SourceMeasure;
  38. public staffEntries: GraphicalStaffEntry[];
  39. public parentMusicSystem: MusicSystem;
  40. public beginInstructionsWidth: number;
  41. public minimumStaffEntriesWidth: number;
  42. public staffEntriesScaleFactor: number;
  43. public endInstructionsWidth: number;
  44. public hasError: boolean;
  45. private parentStaff: Staff;
  46. private measureNumber: number = -1;
  47. private parentStaffLine: StaffLine;
  48. public get ParentStaff(): Staff {
  49. return this.parentStaff;
  50. }
  51. public get MeasureNumber(): number {
  52. return this.measureNumber;
  53. }
  54. public get FirstInstructionStaffEntry(): GraphicalStaffEntry {
  55. return this.firstInstructionStaffEntry;
  56. }
  57. public set FirstInstructionStaffEntry(value: GraphicalStaffEntry) {
  58. this.firstInstructionStaffEntry = value;
  59. }
  60. public get LastInstructionStaffEntry(): GraphicalStaffEntry {
  61. return this.lastInstructionStaffEntry;
  62. }
  63. public set LastInstructionStaffEntry(value: GraphicalStaffEntry) {
  64. this.lastInstructionStaffEntry = value;
  65. }
  66. public get ParentStaffLine(): StaffLine {
  67. return this.parentStaffLine;
  68. }
  69. public set ParentStaffLine(value: StaffLine) {
  70. this.parentStaffLine = value;
  71. if (this.parentStaffLine !== undefined) {
  72. this.PositionAndShape.Parent = this.parentStaffLine.PositionAndShape;
  73. }
  74. }
  75. public resetLayout(): void {
  76. throw new Error("not implemented");
  77. }
  78. public getLineWidth(line: SystemLinesEnum): number {
  79. throw new Error("not implemented");
  80. }
  81. public addClefAtBegin(clef: ClefInstruction): void {
  82. throw new Error("not implemented");
  83. }
  84. public addKeyAtBegin(currentKey: KeyInstruction, previousKey: KeyInstruction, currentClef: ClefInstruction): void {
  85. throw new Error("not implemented");
  86. }
  87. public addRhythmAtBegin(rhythm: RhythmInstruction): void {
  88. throw new Error("not implemented");
  89. }
  90. public addClefAtEnd(clef: ClefInstruction): void {
  91. throw new Error("not implemented");
  92. }
  93. public setPositionInStaffline(xPos: number): void {
  94. this.PositionAndShape.RelativePosition = new PointF2D(xPos, 0);
  95. }
  96. public setWidth(width: number): void {
  97. this.PositionAndShape.BorderRight = width;
  98. }
  99. public layoutSymbols(): void {
  100. throw new Error("not implemented");
  101. }
  102. public findGraphicalStaffEntryFromTimestamp(relativeTimestamp: Fraction): GraphicalStaffEntry {
  103. for (let idx: number = 0, len: number = this.staffEntries.length; idx < len; ++idx) {
  104. let graphicalStaffEntry: GraphicalStaffEntry = this.staffEntries[idx];
  105. if (graphicalStaffEntry.relInMeasureTimestamp === relativeTimestamp) {
  106. return graphicalStaffEntry;
  107. }
  108. }
  109. return undefined;
  110. }
  111. public findGraphicalStaffEntryFromVerticalContainerTimestamp(absoluteTimestamp: Fraction): GraphicalStaffEntry {
  112. for (let idx: number = 0, len: number = this.staffEntries.length; idx < len; ++idx) {
  113. let graphicalStaffEntry: GraphicalStaffEntry = this.staffEntries[idx];
  114. if (graphicalStaffEntry.sourceStaffEntry.VerticalContainerParent.getAbsoluteTimestamp() === absoluteTimestamp) {
  115. return graphicalStaffEntry;
  116. }
  117. }
  118. return undefined;
  119. }
  120. public hasSameDurationWithSourceMeasureParent(): boolean {
  121. let duration: Fraction = new Fraction(0, 1);
  122. for (let idx: number = 0, len: number = this.staffEntries.length; idx < len; ++idx) {
  123. let graphicalStaffEntry: GraphicalStaffEntry = this.staffEntries[idx];
  124. duration.Add(graphicalStaffEntry.findStaffEntryMinNoteLength());
  125. }
  126. return duration === this.parentSourceMeasure.Duration;
  127. }
  128. public hasMultipleVoices(): boolean {
  129. if (this.staffEntries.length === 0) {
  130. return false;
  131. }
  132. let voices: Voice[] = [];
  133. for (let idx: number = 0, len: number = this.staffEntries.length; idx < len; ++idx) {
  134. let staffEntry: GraphicalStaffEntry = this.staffEntries[idx];
  135. for (let idx2: number = 0, len2: number = staffEntry.sourceStaffEntry.VoiceEntries.length; idx2 < len2; ++idx2) {
  136. let voiceEntry: VoiceEntry = staffEntry.sourceStaffEntry.VoiceEntries[idx2];
  137. if (voices.indexOf(voiceEntry.ParentVoice) < 0) {
  138. voices.push(voiceEntry.ParentVoice);
  139. }
  140. }
  141. }
  142. if (voices.length > 1) {
  143. return true;
  144. }
  145. return false;
  146. }
  147. public isVisible(): boolean {
  148. return this.ParentStaff.ParentInstrument.Visible;
  149. }
  150. public getGraphicalMeasureDurationFromStaffEntries(): Fraction {
  151. let duration: Fraction = new Fraction(0, 1);
  152. let voices: Voice[] = [];
  153. for (let idx: number = 0, len: number = this.staffEntries.length; idx < len; ++idx) {
  154. let graphicalStaffEntry: GraphicalStaffEntry = this.staffEntries[idx];
  155. for (let idx2: number = 0, len2: number = graphicalStaffEntry.sourceStaffEntry.VoiceEntries.length; idx2 < len2; ++idx2) {
  156. let voiceEntry: VoiceEntry = graphicalStaffEntry.sourceStaffEntry.VoiceEntries[idx2];
  157. if (voices.indexOf(voiceEntry.ParentVoice) < 0) {
  158. voices.push(voiceEntry.ParentVoice);
  159. }
  160. }
  161. }
  162. for (let idx: number = 0, len: number = voices.length; idx < len; ++idx) {
  163. let voice: Voice = voices[idx];
  164. let voiceDuration: Fraction = new Fraction(0, 1);
  165. for (let idx2: number = 0, len2: number = this.staffEntries.length; idx2 < len2; ++idx2) {
  166. let graphicalStaffEntry: GraphicalStaffEntry = this.staffEntries[idx2];
  167. for (let idx3: number = 0, len3: number = graphicalStaffEntry.notes.length; idx3 < len3; ++idx3) {
  168. let graphicalNotes: GraphicalNote[] = graphicalStaffEntry.notes[idx3];
  169. if (graphicalNotes.length > 0 && graphicalNotes[0].sourceNote.ParentVoiceEntry.ParentVoice === voice) {
  170. voiceDuration.Add(graphicalNotes[0].graphicalNoteLength);
  171. }
  172. }
  173. }
  174. if (voiceDuration > duration) {
  175. duration = Fraction.createFromFraction(voiceDuration);
  176. }
  177. }
  178. return duration;
  179. }
  180. public addGraphicalStaffEntry(graphicalStaffEntry: GraphicalStaffEntry): void {
  181. this.staffEntries.push(graphicalStaffEntry);
  182. this.PositionAndShape.ChildElements.push(graphicalStaffEntry.PositionAndShape);
  183. }
  184. public addGraphicalStaffEntryAtTimestamp(staffEntry: GraphicalStaffEntry): void {
  185. if (staffEntry !== undefined) {
  186. if (this.staffEntries.length === 0 || this.staffEntries[this.staffEntries.length - 1].relInMeasureTimestamp < staffEntry.relInMeasureTimestamp) {
  187. this.staffEntries.push(staffEntry);
  188. } else {
  189. for (let i: number = this.staffEntries.length - 1; i >= 0; i--) {
  190. if (this.staffEntries[i].relInMeasureTimestamp < staffEntry.relInMeasureTimestamp) {
  191. this.staffEntries.splice(i + 1, 0, staffEntry);
  192. break;
  193. }
  194. if (i === 0) {
  195. this.staffEntries.splice(i, 0, staffEntry);
  196. }
  197. }
  198. }
  199. this.PositionAndShape.ChildElements.push(staffEntry.PositionAndShape);
  200. }
  201. }
  202. public beginsWithLineRepetition(): boolean {
  203. let sourceMeasure: SourceMeasure = this.parentSourceMeasure;
  204. if (sourceMeasure === undefined) {
  205. return false;
  206. }
  207. return sourceMeasure.beginsWithLineRepetition();
  208. }
  209. public endsWithLineRepetition(): boolean {
  210. let sourceMeasure: SourceMeasure = this.parentSourceMeasure;
  211. if (sourceMeasure === undefined) {
  212. return false;
  213. }
  214. return sourceMeasure.endsWithLineRepetition();
  215. }
  216. public beginsWithWordRepetition(): boolean {
  217. let sourceMeasure: SourceMeasure = this.parentSourceMeasure;
  218. if (sourceMeasure === undefined) {
  219. return false;
  220. }
  221. return sourceMeasure.beginsWithWordRepetition();
  222. }
  223. public endsWithWordRepetition(): boolean {
  224. let sourceMeasure: SourceMeasure = this.parentSourceMeasure;
  225. if (sourceMeasure === undefined) {
  226. return false;
  227. }
  228. return sourceMeasure.endsWithWordRepetition();
  229. }
  230. }