VexFlow - Copyright (c) Mohit Muthanna 2010.
This class implements various types of modifiers to notes (e.g. bends, fingering positions etc.)
import { Vex } from './vex';
import { StaveNote } from './stavenote';
import { Dot } from './dot';
import { FretHandFinger } from './frethandfinger';
import { Accidental } from './accidental';
import { NoteSubGroup } from './notesubgroup';
import { GraceNoteGroup } from './gracenotegroup';
import { Stroke } from './strokes';
import { StringNumber } from './stringnumber';
import { Articulation } from './articulation';
import { Ornament } from './ornament';
import { Annotation } from './annotation';
import { Bend } from './bend';
import { Vibrato } from './vibrato';
To enable logging for this class. Set Vex.Flow.ModifierContext.DEBUG
to true
.
function L(...args) { if (ModifierContext.DEBUG) Vex.L('Vex.Flow.ModifierContext', args); }
export class ModifierContext {
constructor() {
Current modifiers
this.modifiers = {};
Formatting data.
this.preFormatted = false;
this.postFormatted = false;
this.width = 0;
this.spacing = 0;
this.state = {
left_shift: 0,
right_shift: 0,
text_line: 0,
top_text_line: 0,
};
Add new modifiers to this array. The ordering is significant – lower modifiers are formatted and rendered before higher ones.
this.PREFORMAT = [
StaveNote,
Dot,
FretHandFinger,
Accidental,
GraceNoteGroup,
NoteSubGroup,
Stroke,
StringNumber,
Articulation,
Ornament,
Annotation,
Bend,
Vibrato,
];
If post-formatting is required for an element, add it to this array.
this.POSTFORMAT = [StaveNote];
}
addModifier(modifier) {
const type = modifier.getCategory();
if (!this.modifiers[type]) this.modifiers[type] = [];
this.modifiers[type].push(modifier);
modifier.setModifierContext(this);
this.preFormatted = false;
return this;
}
getModifiers(type) { return this.modifiers[type]; }
getWidth() { return this.width; }
getExtraLeftPx() { return this.state.left_shift; }
getExtraRightPx() { return this.state.right_shift; }
getState() { return this.state; }
getMetrics() {
if (!this.formatted) {
throw new Vex.RERR('UnformattedModifier', 'Unformatted modifier has no metrics.');
}
return {
width: this.state.left_shift + this.state.right_shift + this.spacing,
spacing: this.spacing,
extra_left_px: this.state.left_shift,
extra_right_px: this.state.right_shift,
};
}
preFormat() {
if (this.preFormatted) return;
this.PREFORMAT.forEach((modifier) => {
L('Preformatting ModifierContext: ', modifier.CATEGORY);
modifier.format(this.getModifiers(modifier.CATEGORY), this.state, this);
});
Update width of this modifier context
this.width = this.state.left_shift + this.state.right_shift;
this.preFormatted = true;
}
postFormat() {
if (this.postFormatted) return;
this.POSTFORMAT.forEach((modifier) => {
L('Postformatting ModifierContext: ', modifier.CATEGORY);
modifier.postFormat(this.getModifiers(modifier.CATEGORY), this);
});
}
}