public void redrawPlayingMode() {
    if (!isDisposed()
        && !TuxGuitar.instance().isLocked()
        && TuxGuitar.instance().getPlayer().isRunning()) {
      // TuxGuitar.instance().lock();

      TGMeasure measure = TuxGuitar.instance().getEditorCache().getPlayMeasure();
      TGBeat beat = TuxGuitar.instance().getEditorCache().getPlayBeat();
      if (measure != null && beat != null) {
        int currentMeasure = measure.getNumber();
        int currentTrack = measure.getTrack().getNumber();
        boolean changed =
            (currentMeasure != this.playedMeasure || currentTrack != this.playedTrack);
        if (changed) {
          this.resetPlayed();
          this.editor.redraw();
        } else {
          TGPainter painter = new TGPainterImpl(new GC(this.editor));
          int scrollX = this.editor.getHorizontalBar().getSelection();
          int scrollY = this.editor.getVerticalBar().getSelection();
          if (this.playedBeat != null) {
            this.paintBeat(
                painter, measure, this.playedBeat, (-scrollX), (BORDER_HEIGHT - scrollY));
          }
          this.paintBeat(painter, measure, beat, (-scrollX), (BORDER_HEIGHT - scrollY));
          painter.dispose();
        }
        this.playedMeasure = currentMeasure;
        this.playedTrack = currentTrack;
        this.playedBeat = beat;
      }
      // TuxGuitar.instance().unlock();
    }
  }
 public void selectionFinish() {
   if (this.selectionBackBuffer != null && !this.selectionBackBuffer.isDisposed()) {
     TGPainter painter = new TGPainterImpl(new GC(this.editor));
     painter.drawImage(this.selectionBackBuffer, this.selectionX, this.selectionY);
     painter.dispose();
   }
   disposeSelectionBuffer();
 }
  protected void paintBeat(
      TGPainter painter, TGMeasure measure, TGBeat beat, float fromX, float fromY) {
    if (this.clientArea != null) {
      int minimumY = BORDER_HEIGHT;
      int maximumY = (this.clientArea.height - BORDER_HEIGHT);

      for (int v = 0; v < beat.countVoices(); v++) {
        TGVoice voice = beat.getVoice(v);
        for (int i = 0; i < voice.countNotes(); i++) {
          TGNoteImpl note = (TGNoteImpl) voice.getNote(i);
          float x1 =
              (fromX
                  + this.leftSpacing
                  + (((beat.getStart() - measure.getStart())
                          * (this.timeWidth * measure.getTimeSignature().getNumerator()))
                      / measure.getLength())
                  + 1);
          float y1 =
              (fromY
                  + (((this.maxNote - this.minNote) - (note.getRealValue() - this.minNote))
                      * this.lineHeight)
                  + 1);
          float x2 =
              (x1
                  + ((voice.getDuration().getTime() * this.timeWidth)
                      / measure.getTimeSignature().getDenominator().getTime())
                  - 2);
          float y2 = (y1 + this.lineHeight - 2);

          if (y1 >= maximumY || y2 <= minimumY) {
            continue;
          }

          y1 = (y1 < minimumY ? minimumY : y1);
          y2 = (y2 > maximumY ? maximumY : y2);

          if ((x2 - x1) > 0 && (y2 - y1) > 0) {
            painter.setBackground(
                new TGColorImpl(
                    (note.getBeatImpl()
                            .isPlaying(
                                TuxGuitar.instance()
                                    .getTablatureEditor()
                                    .getTablature()
                                    .getViewLayout())
                        ? this.config.getColorPlay()
                        : this.config.getColorNote())));
            painter.initPath(TGPainter.PATH_FILL);
            painter.setAntialias(false);
            painter.addRectangle(x1, y1, (x2 - x1), (y2 - y1));
            painter.closePath();
          }
        }
      }
    }
  }
  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();
      }
    }
  }
  protected void updateSelection(float y) {
    if (!TuxGuitar.instance().getPlayer().isRunning()) {
      int selection = getValueAt(y);

      if (this.selection != selection) {
        this.selection = selection;

        int scrollX = this.editor.getHorizontalBar().getSelection();
        int scrollY = this.editor.getVerticalBar().getSelection();

        TGPainter painter = new TGPainterImpl(new GC(this.editor));
        this.paintSelection(painter, (-scrollX), (BORDER_HEIGHT - scrollY));
        painter.dispose();
      }
    }
  }
  protected void paintBorders(TGPainter painter, float fromX, float fromY) {
    if (this.clientArea != null) {
      painter.setBackground(new TGColorImpl(this.config.getColorBorder()));
      painter.initPath(TGPainter.PATH_FILL);
      painter.setAntialias(false);
      painter.addRectangle(fromX, fromY, this.bufferWidth, BORDER_HEIGHT);
      painter.addRectangle(
          fromX, fromY + (this.clientArea.height - BORDER_HEIGHT), this.bufferWidth, BORDER_HEIGHT);
      painter.closePath();

      painter.initPath();
      painter.setAntialias(false);
      painter.addRectangle(fromX, fromY, this.width, this.clientArea.height);
      painter.closePath();
    }
  }
  protected void paintEditor(TGPainter painter) {
    if (!TuxGuitar.instance().getPlayer().isRunning()) {
      this.resetPlayed();
    }

    this.disposeSelectionBuffer();
    this.clientArea = this.editor.getClientArea();

    if (this.clientArea != null) {
      TGImage buffer = getBuffer();

      this.width = this.bufferWidth;
      this.height = (this.bufferHeight + (BORDER_HEIGHT * 2));

      this.updateScroll();
      int scrollX = this.editor.getHorizontalBar().getSelection();
      int scrollY = this.editor.getVerticalBar().getSelection();

      painter.drawImage(buffer, -scrollX, (BORDER_HEIGHT - scrollY));
      this.paintMeasure(painter, (-scrollX), (BORDER_HEIGHT - scrollY));
      this.paintBorders(painter, (-scrollX), 0);
      this.paintPosition(painter, (-scrollX), 0);

      this.paintSelection(painter, (-scrollX), (BORDER_HEIGHT - scrollY));
    }
  }
  protected void paintSelection(TGPainter painter, float fromX, float fromY) {
    if (!this.selectionPaintDisabled
        && this.clientArea != null
        && !TuxGuitar.instance().getPlayer().isRunning()) {
      selectionFinish();
      if (this.selection >= 0) {
        this.selectionPaintDisabled = true;

        int x = Math.round(fromX);
        int y = Math.round(fromY + ((this.maxNote - this.selection) * this.lineHeight));
        int width = Math.round(this.bufferWidth);
        int height = Math.round(this.lineHeight);

        TGImage selectionArea = new TGImageImpl(this.editor.getDisplay(), width, height);
        painter.copyArea(selectionArea, x, y);
        painter.setAlpha(100);
        painter.setBackground(new TGColorImpl(this.config.getColorLine(2)));
        painter.initPath(TGPainter.PATH_FILL);
        painter.setAntialias(false);
        painter.addRectangle(x, y, width, height);
        painter.closePath();

        this.selectionX = x;
        this.selectionY = y;
        this.selectionBackBuffer = selectionArea;
        this.selectionPaintDisabled = false;
      }
    }
  }
  protected TGImage getBuffer() {
    if (this.clientArea != null) {
      this.bufferDisposer.update(this.clientArea.width, this.clientArea.height);
      if (this.buffer == null || this.buffer.isDisposed()) {
        String[] names = null;
        TGMeasure measure = getMeasure();
        this.maxNote = 0;
        this.minNote = 127;
        if (TuxGuitar.instance()
            .getSongManager()
            .isPercussionChannel(measure.getTrack().getChannelId())) {
          names = new String[PERCUSSIONS.length];
          for (int i = 0; i < names.length; i++) {
            this.minNote = Math.min(this.minNote, PERCUSSIONS[i].getValue());
            this.maxNote = Math.max(this.maxNote, PERCUSSIONS[i].getValue());
            names[i] = PERCUSSIONS[names.length - i - 1].getName();
          }
        } else {
          for (int sNumber = 1; sNumber <= measure.getTrack().stringCount(); sNumber++) {
            TGString string = measure.getTrack().getString(sNumber);
            this.minNote = Math.min(this.minNote, string.getValue());
            this.maxNote = Math.max(this.maxNote, (string.getValue() + 20));
          }
          names = new String[this.maxNote - this.minNote + 1];
          for (int i = 0; i < names.length; i++) {
            names[i] = (NOTE_NAMES[(this.maxNote - i) % 12] + ((this.maxNote - i) / 12));
          }
        }

        int minimumNameWidth = 110;
        int minimumNameHeight = 0;
        TGPainter painter = new TGPainterImpl(new GC(this.dialog.getDisplay()));
        painter.setFont(new TGFontImpl(this.config.getFont()));
        for (int i = 0; i < names.length; i++) {
          int fmWidth = painter.getFMWidth(names[i]);
          if (fmWidth > minimumNameWidth) {
            minimumNameWidth = fmWidth;
          }
          int fmHeight = painter.getFMHeight();
          if (fmHeight > minimumNameHeight) {
            minimumNameHeight = fmHeight;
          }
        }
        painter.dispose();

        int cols = measure.getTimeSignature().getNumerator();
        int rows = (this.maxNote - this.minNote);

        this.leftSpacing = minimumNameWidth + 10;
        this.lineHeight =
            Math.max(
                minimumNameHeight,
                ((this.clientArea.height - (BORDER_HEIGHT * 2.0f)) / (rows + 1.0f)));
        this.timeWidth =
            Math.max(
                (10
                    * (TGDuration.SIXTY_FOURTH
                        / measure.getTimeSignature().getDenominator().getValue())),
                ((this.clientArea.width - this.leftSpacing) / cols));
        this.bufferWidth = this.leftSpacing + (this.timeWidth * cols);
        this.bufferHeight = (this.lineHeight * (rows + 1));
        this.buffer =
            new TGImageImpl(
                this.editor.getDisplay(),
                Math.round(this.bufferWidth),
                Math.round(this.bufferHeight));

        painter = this.buffer.createPainter();
        painter.setFont(new TGFontImpl(this.config.getFont()));
        painter.setForeground(new TGColorImpl(this.config.getColorForeground()));
        for (int i = 0; i <= rows; i++) {
          painter.setBackground(new TGColorImpl(this.config.getColorLine(i % 2)));
          painter.initPath(TGPainter.PATH_FILL);
          painter.setAntialias(false);
          painter.addRectangle(0, (i * this.lineHeight), this.bufferWidth, this.lineHeight);
          painter.closePath();
          painter.drawString(
              names[i],
              5,
              (Math.round((i * this.lineHeight))
                  + Math.round((this.lineHeight - minimumNameHeight) / 2)));
        }
        for (int i = 0; i < cols; i++) {
          float colX = this.leftSpacing + (i * this.timeWidth);
          float divisionWidth = (this.timeWidth / this.grids);
          for (int j = 0; j < this.grids; j++) {
            if (j == 0) {
              painter.setLineStyleSolid();
            } else {
              painter.setLineStyleDot();
            }
            painter.initPath();
            painter.setAntialias(false);
            painter.moveTo(Math.round(colX + (j * divisionWidth)), 0);
            painter.lineTo(Math.round(colX + (j * divisionWidth)), this.bufferHeight);
            painter.closePath();
          }
        }
        painter.dispose();
      }
    }
    return this.buffer;
  }