text: // [VexFlow](http://vexflow.com) - Copyright (c) Mohit Muthanna 2010.
  //
  // ## Description
  //
  // `Modifier` is an abstract interface for notational elements that modify
  // a `Note`. Examples of modifiers are `Accidental`, `Annotation`, `Stroke`, etc.
  //
  // For a `Modifier` instance to be positioned correctly, it must be part of
  // a `ModifierContext`. All modifiers in the same context are rendered relative to
  // one another.
  //
  // Typically, all modifiers to a note are part of the same `ModifierContext` instance. Also,
  // in multi-voice staves, all modifiers to notes on the same `tick` are part of the same
  // `ModifierContext`. This ensures that multiple voices don't trample all over each other.
  
  Vex.Flow.Modifier = (function() {
    function Modifier() { this.init(); }
      // To enable logging for this class. Set `Vex.Flow.Modifier.DEBUG` to `true`.
    function L() { if (Modifier.DEBUG) Vex.L("Vex.Flow.Modifier", arguments); }
  
    // Modifiers can be positioned almost anywhere, relative to a note.
    Modifier.Position = {
      LEFT: 1,
      RIGHT: 2,
      ABOVE: 3,
      BELOW: 4
    };
  
    // ## Prototype Methods
    Modifier.prototype = {
  
      // The constructor sets initial widhts and constants.
      init: function() {
        this.width = 0;
        this.context = null;
  
        // Modifiers are attached to a note and an index. An index is a
        // specific head in a chord.
        this.note = null;
        this.index = null;
  
        // The `text_line` is reserved space above or below a stave.
        this.text_line = 0;
        this.position = Modifier.Position.LEFT;
        this.modifier_context = null;
        this.x_shift = 0;
        this.y_shift = 0;
        L("Created new modifier");
      },
  
      // Every modifier has a category. The `ModifierContext` uses this to determine
      // the type and order of the modifiers.
      getCategory: function() { return "none"; },
  
      // Get and set modifier widths.
      getWidth: function() { return this.width; },
      setWidth: function(width) { this.width = width; return this; },
  
      // Get and set attached note (`StaveNote`, `TabNote`, etc.)
      getNote: function() { return this.note; },
      setNote: function(note) { this.note = note; return this; },
  
      // Get and set note index, which is a specific note in a chord.
      getIndex: function() { return this.index; },
      setIndex: function(index) { this.index = index; return this; },
  
      // Get and set rendering context.
      getContext: function() { return this.context; },
      setContext: function(context) { this.context = context; return this; },
  
      // Every modifier must be part of a `ModifierContext`.
      getModifierContext: function() { return this.modifier_context; },
      setModifierContext: function(c) { this.modifier_context = c; return this; },
  
      // Get and set articulation position.
      getPosition: function() { return this.position; },
      setPosition: function(position) { this.position = position; return this; },
  
      // Set the `text_line` for the modifier.
      setTextLine: function(line) { this.text_line = line; return this; },
  
      // Shift modifier down `y` pixels. Negative values shift up.
      setYShift: function(y) { this.y_shift = y; return this; },
  
      // Shift modifier `x` pixels in the direction of the modifier. Negative values
      // shift reverse.
      setXShift: function(x) {
        this.x_shift = 0;
        if (this.position == Modifier.Position.LEFT) {
          this.x_shift -= x;
        } else {
          this.x_shift += x;
        }
      },
  
      // Render the modifier onto the canvas.
      draw: function() {
        if (!this.context) throw new Vex.RERR("NoCanvasContext",
            "Can't draw without a canvas context.");
        throw new Vex.RERR("MethodNotImplemented",
            "Draw() not implemented for this modifier.");
      }
    };
  
    return Modifier;
  }());
  