protected void hit(float x, float y) {
    if (!TuxGuitar.instance().getPlayer().isRunning()) {
      TGMeasure measure = getMeasure();
      Caret caret = getCaret();
      int value = getValueAt(y);
      long start = getStartAt(x);

      if (start >= measure.getStart() && start < (measure.getStart() + measure.getLength())) {
        caret.update(caret.getTrack().getNumber(), start, caret.getStringNumber());
        TuxGuitar.instance().updateCache(true);
      }
      if (value >= this.minNote || value <= this.maxNote) {
        if (start >= measure.getStart()) {
          TGVoice voice =
              TuxGuitar.instance()
                  .getSongManager()
                  .getMeasureManager()
                  .getVoiceIn(measure, start, caret.getVoice());
          if (voice != null) {
            if (!removeNote(voice.getBeat(), value)) {
              addNote(voice.getBeat(), start, value);
            }
          }
        } else {
          play(value);
        }
      }
    }
  }
 private void setTiedNoteValue(TGNote note, Caret caret) {
   TGMeasure measure = caret.getMeasure();
   TGVoice voice =
       getSongManager()
           .getMeasureManager()
           .getPreviousVoice(measure.getBeats(), caret.getSelectedBeat(), caret.getVoice());
   while (measure != null) {
     while (voice != null) {
       if (voice.isRestVoice()) {
         note.setValue(0);
         return;
       }
       // Check if is there any note at same string.
       Iterator it = voice.getNotes().iterator();
       while (it.hasNext()) {
         TGNote current = (TGNote) it.next();
         if (current.getString() == note.getString()) {
           note.setValue(current.getValue());
           return;
         }
       }
       voice =
           getSongManager()
               .getMeasureManager()
               .getPreviousVoice(measure.getBeats(), voice.getBeat(), caret.getVoice());
     }
     measure = getSongManager().getTrackManager().getPrevMeasure(measure);
     if (measure != null) {
       voice =
           getSongManager().getMeasureManager().getLastVoice(measure.getBeats(), caret.getVoice());
     }
   }
 }
  private boolean removeNote(TGBeat beat, int value) {
    Caret caret = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret();
    TGMeasure measure = getMeasure();

    for (int v = 0; v < beat.countVoices(); v++) {
      TGVoice voice = beat.getVoice(v);
      Iterator it = voice.getNotes().iterator();
      while (it.hasNext()) {
        TGNoteImpl note = (TGNoteImpl) it.next();
        if (note.getRealValue() == value) {
          caret.update(measure.getTrack().getNumber(), beat.getStart(), note.getString());

          // comienza el undoable
          UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();

          TGSongManager manager = TuxGuitar.instance().getSongManager();
          manager.getMeasureManager().removeNote(note);

          // termia el undoable
          TuxGuitar.instance().getUndoableManager().addEdit(undoable.endUndo());
          TuxGuitar.instance().getFileHistory().setUnsavedFile();

          this.afterAction();

          return true;
        }
      }
    }
    return false;
  }
  protected void paintPosition(TGPainter painter, float fromX, float fromY) {
    if (this.clientArea != null && !TuxGuitar.instance().getPlayer().isRunning()) {
      Caret caret = getCaret();
      TGMeasure measure = getMeasure();
      TGBeat beat = caret.getSelectedBeat();
      if (beat != null) {
        float x =
            (((beat.getStart() - measure.getStart())
                    * (this.timeWidth * measure.getTimeSignature().getNumerator()))
                / measure.getLength());
        float width =
            ((beat.getVoice(caret.getVoice()).getDuration().getTime() * this.timeWidth)
                / measure.getTimeSignature().getDenominator().getTime());
        painter.setBackground(new TGColorImpl(this.config.getColorPosition()));
        painter.initPath(TGPainter.PATH_FILL);
        painter.setAntialias(false);
        painter.addRectangle(fromX + (this.leftSpacing + x), fromY, width, BORDER_HEIGHT);
        painter.closePath();

        painter.initPath(TGPainter.PATH_FILL);
        painter.setAntialias(false);
        painter.addRectangle(
            fromX + (this.leftSpacing + x),
            fromY + (this.clientArea.height - BORDER_HEIGHT),
            width,
            BORDER_HEIGHT);
        painter.closePath();
      }
    }
  }
  public void cleanMeasures(int m1, int m2) {
    if (m1 > 0 && m1 <= m2) {
      // comienza el undoable
      UndoableJoined undoable = new UndoableJoined();

      Caret caret = getEditor().getTablature().getCaret();
      for (int number = m1; number <= m2; number++) {
        TGMeasure measure = getSongManager().getTrackManager().getMeasure(caret.getTrack(), number);
        if (measure != null) {
          // comienza el undoable
          UndoableMeasureGeneric mUndoable = UndoableMeasureGeneric.startUndo(measure);

          getSongManager().getMeasureManager().cleanMeasure(measure);

          // termia el undoable
          undoable.addUndoableEdit(mUndoable.endUndo(measure));
        }
      }

      // termia el undoable
      if (!undoable.isEmpty()) {
        addUndoableEdit(undoable.endUndo());
      }
      TuxGuitar.instance().getFileHistory().setUnsavedFile();

      updateTablature();
    }
  }
  public static UndoableChangeAlternativeRepeat startUndo() {
    UndoableChangeAlternativeRepeat undoable = new UndoableChangeAlternativeRepeat();
    Caret caret = getCaret();
    undoable.doAction = UNDO_ACTION;
    undoable.undoCaret = new UndoableCaretHelper();
    undoable.position = caret.getPosition();
    undoable.undoRepeatAlternative = caret.getMeasure().getHeader().getRepeatAlternative();

    return undoable;
  }
 private void moveToNext() {
   if (TuxGuitar.instance().getPlayer().isRunning()) {
     TuxGuitar.instance().getTransport().gotoNext();
   } else {
     Caret caret = getEditor().getTablature().getCaret();
     TGTrackImpl track = caret.getTrack();
     TGMeasure measure = getSongManager().getTrackManager().getNextMeasure(caret.getMeasure());
     if (track != null && measure != null) {
       caret.update(track.getNumber(), measure.getStart(), caret.getSelectedString().getNumber());
     }
   }
 }
  protected int execute(ActionData actionData) {
    // comienza el undoable
    UndoableCloneTrack undoable = UndoableCloneTrack.startUndo();
    TuxGuitar.instance().getFileHistory().setUnsavedFile();

    Caret caret = getEditor().getTablature().getCaret();

    getSongManager().cloneTrack(caret.getTrack());
    updateTablature();

    // termia el undoable
    addUndoableEdit(undoable.endUndo());

    return 0;
  }
  protected void processAction(TGActionContext context) {
    // comienza el undoable
    UndoableMoveTrackUp undoable = UndoableMoveTrackUp.startUndo();

    Caret caret = getEditor().getTablature().getCaret();
    TGTrack track = caret.getTrack();

    if (getSongManager().moveTrackUp(track)) {
      updateTablature();

      // termia el undoable
      addUndoableEdit(undoable.endUndo(track));
      TuxGuitar.instance().getFileHistory().setUnsavedFile();
    }
  }
  private boolean addNote(TGBeat beat, long start, int value) {
    if (beat != null) {
      TGMeasure measure = getMeasure();
      Caret caret = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret();

      List strings = measure.getTrack().getStrings();
      for (int i = 0; i < strings.size(); i++) {
        TGString string = (TGString) strings.get(i);
        if (value >= string.getValue()) {
          boolean emptyString = true;

          for (int v = 0; v < beat.countVoices(); v++) {
            TGVoice voice = beat.getVoice(v);
            Iterator it = voice.getNotes().iterator();
            while (it.hasNext()) {
              TGNoteImpl note = (TGNoteImpl) it.next();
              if (note.getString() == string.getNumber()) {
                emptyString = false;
                break;
              }
            }
          }
          if (emptyString) {
            TGSongManager manager = TuxGuitar.instance().getSongManager();

            // comienza el undoable
            UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();

            TGNote note = manager.getFactory().newNote();
            note.setValue((value - string.getValue()));
            note.setVelocity(caret.getVelocity());
            note.setString(string.getNumber());

            TGDuration duration = manager.getFactory().newDuration();
            caret.getDuration().copy(duration);

            manager.getMeasureManager().addNote(beat, note, duration, start, caret.getVoice());

            caret.moveTo(
                caret.getTrack(), caret.getMeasure(), note.getVoice().getBeat(), note.getString());

            // termia el undoable
            TuxGuitar.instance().getUndoableManager().addEdit(undoable.endUndo());
            TuxGuitar.instance().getFileHistory().setUnsavedFile();

            // reprodusco las notas en el pulso
            TuxGuitar.instance().playBeat(caret.getSelectedBeat());

            this.afterAction();

            return true;
          }
        }
      }
    }
    return false;
  }
  protected int execute(TypedEvent e) {
    // comienza el undoable
    UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();

    Caret caret = getEditor().getTablature().getCaret();
    getSongManager()
        .getMeasureManager()
        .changePopping(
            caret.getMeasure(), caret.getPosition(), caret.getSelectedString().getNumber());
    TuxGuitar.instance().getFileHistory().setUnsavedFile();
    updateTablature();

    // termia el undoable
    addUndoableEdit(undoable.endUndo());

    return 0;
  }
  protected void setTripletFeel(int tripletFeel, boolean toEnd) {
    // comienza el undoable
    UndoableChangeTripletFeel undoable = UndoableChangeTripletFeel.startUndo();

    Caret caret = getEditor().getTablature().getCaret();
    TGMeasureImpl measure = caret.getMeasure();

    getSongManager().changeTripletFeel(measure.getStart(), tripletFeel, toEnd);

    TuxGuitar.instance().getFileHistory().setUnsavedFile();

    // actualizo la tablatura
    updateTablature();

    // termia el undoable
    addUndoableEdit(undoable.endUndo(tripletFeel, toEnd));
  }
  protected void processAction(TGActionContext context) {
    Caret caret = getEditor().getTablature().getCaret();
    // si es el ultimo compas, agrego uno nuevo
    if (getSongManager().getTrackManager().isLastMeasure(caret.getMeasure())) {
      int number = (getSongManager().getSong().countMeasureHeaders() + 1);

      // comienza el undoable
      UndoableAddMeasure undoable = UndoableAddMeasure.startUndo(number);

      this.getSongManager().addNewMeasure(number);
      this.fireUpdate(number);
      this.moveToNext();

      // termia el undoable
      this.addUndoableEdit(undoable.endUndo());
    } else {
      this.moveToNext();
    }
  }
  protected int execute(TypedEvent e) {
    Caret caret = getEditor().getTablature().getCaret();
    if (caret.getSelectedNote() != null) {
      // comienza el undoable
      UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();

      getSongManager().getMeasureManager().changeTieNote(caret.getSelectedNote());

      // termia el undoable
      addUndoableEdit(undoable.endUndo());
    } else {
      TGNote note = getSongManager().getFactory().newNote();
      note.setValue(0);
      note.setVelocity(caret.getVelocity());
      note.setString(caret.getSelectedString().getNumber());
      note.setTiedNote(true);

      TGDuration duration = getSongManager().getFactory().newDuration();
      caret.getDuration().copy(duration);

      setTiedNoteValue(note, caret);

      // comienza el undoable
      UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();

      getSongManager()
          .getMeasureManager()
          .addNote(caret.getSelectedBeat(), note, duration, caret.getVoice());

      // termia el undoable
      addUndoableEdit(undoable.endUndo());
    }
    TuxGuitar.instance().getFileHistory().setUnsavedFile();
    updateTablature();
    return 0;
  }