/*
* Created on 30-nov-2005
*
* TODO To change the template for this generated file go to Window -
* Preferences - Java - Code Style - Code Templates
*/
package org.herac.tuxguitar.gui.editors.tab;
import org.herac.tuxguitar.gui.TuxGuitar;
import org.herac.tuxguitar.gui.editors.TGPainter;
import org.herac.tuxguitar.gui.editors.tab.layout.ViewLayout;
import org.herac.tuxguitar.gui.util.MidiTickUtil;
import org.herac.tuxguitar.song.managers.TGMeasureManager;
import org.herac.tuxguitar.song.managers.TGSongManager;
import org.herac.tuxguitar.song.models.TGBeat;
import org.herac.tuxguitar.song.models.TGDuration;
import org.herac.tuxguitar.song.models.TGNote;
import org.herac.tuxguitar.song.models.TGString;
import org.herac.tuxguitar.song.models.TGVelocities;
import org.herac.tuxguitar.song.models.TGVoice;
/**
* @author julian
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class Caret {
private boolean changes;
private long position;
private boolean restBeat;
private TGBeat selectedBeat;
private TGDuration selectedDuration;
private TGMeasureImpl selectedMeasure;
private TGNote selectedNote;
private TGTrackImpl selectedTrack;
private int string;
private Tablature tablature;
private int velocity;
private int voice;
public Caret(Tablature tablature) {
this.tablature = tablature;
this.selectedDuration = new TGDuration();
this.string = 1;
this.velocity = TGVelocities.DEFAULT;
this.changes = false;
}
public void changeDuration(TGDuration duration) {
getSongManager().getMeasureManager().changeDuration(getMeasure(),
getSelectedBeat(), duration, getVoice(), true);
setChanges(true);
}
private void checkTransport() {
TuxGuitar.instance().getTransport().gotoMeasure(getMeasure().getHeader());
}
private TGBeat findBeat(long position, TGMeasureImpl measure) {
TGBeat beat = null;
if (measure != null) {
TGMeasureManager manager = getSongManager().getMeasureManager();
TGVoice voice = manager.getVoiceIn(measure, position, getVoice());
if (voice != null) {
beat = voice.getBeat();
}
if (beat == null) {
beat = manager.getFirstBeat(measure.getBeats());
}
}
return beat;
}
private TGMeasureImpl findMeasure(long position, TGTrackImpl track) {
TGMeasureImpl measure = null;
if (track != null) {
measure = (TGMeasureImpl) getSongManager().getTrackManager()
.getMeasureAt(track, position);
if (measure == null) {
measure = (TGMeasureImpl) getSongManager().getTrackManager()
.getFirstMeasure(track);
}
}
return measure;
}
private TGTrackImpl findTrack(int number) {
TGTrackImpl track = (TGTrackImpl) getSongManager().getTrack(number);
if (track == null) {
track = (TGTrackImpl) getSongManager().getFirstTrack();
}
return track;
}
public TGDuration getDuration() {
return this.selectedDuration;
}
public TGMeasureImpl getMeasure() {
return this.selectedMeasure;
}
public long getPosition() {
return this.position;
}
public TGBeatImpl getSelectedBeat() {
return (TGBeatImpl) this.selectedBeat;
}
public TGNote getSelectedNote() {
return this.selectedNote;
}
public TGString getSelectedString() {
for (final TGString instrumentString : this.selectedTrack.getStrings()) {
if (instrumentString.getNumber() == this.string) {
return instrumentString;
}
}
return null;
}
public TGSongManager getSongManager() {
return this.tablature.getSongManager();
}
public int getStringNumber() {
return this.string;
}
public TGTrackImpl getTrack() {
return this.selectedTrack;
}
public int getVelocity() {
return this.velocity;
}
public int getVoice() {
return this.voice;
}
public synchronized void goToTickPosition() {
long start = MidiTickUtil.getStart(TuxGuitar.instance().getPlayer()
.getTickPosition());
this.update(this.selectedTrack.getNumber(), start, this.string);
this.setChanges(true);
}
public boolean hasChanges() {
return this.changes;
}
public boolean isRestBeatSelected() {
return this.restBeat;
}
public void moveDown() {
int stringCount = this.selectedTrack.stringCount();
int nextString = ((this.string % stringCount) + 1);
setStringNumber(nextString);
}
public void moveLeft() {
if (getSelectedBeat() != null) {
TGMeasureImpl measure = getMeasure();
TGVoice voice = getSongManager().getMeasureManager().getPreviousVoice(
measure.getBeats(), getSelectedBeat(), getVoice());
TGBeat beat = (voice != null ? voice.getBeat() : null);
if (beat == null) {
// si no habia mas componentes. busco el compas anterior
measure = (TGMeasureImpl) getSongManager().getTrackManager()
.getPrevMeasure(getMeasure());
if (measure == null) {
return;
}
voice = getSongManager().getMeasureManager().getLastVoice(
measure.getBeats(), getVoice());
beat = (voice != null ? voice.getBeat() : null);
if (beat == null) {
beat = getSongManager().getMeasureManager().getFirstBeat(
measure.getBeats());
}
}
if (beat != null) {
moveTo(getTrack(), measure, beat, getStringNumber());
}
}
}
public boolean moveRight() {
if (getSelectedBeat() != null) {
TGMeasureImpl measure = getMeasure();
TGVoice voice = getSongManager().getMeasureManager().getNextVoice(
measure.getBeats(), getSelectedBeat(), getVoice());
TGBeat beat = (voice != null ? voice.getBeat() : null);
if (beat == null) {
// si no habia mas componentes. busco el siguiente compas
measure = (TGMeasureImpl) getSongManager().getTrackManager()
.getNextMeasure(getMeasure());
if (measure == null) {
return false;
}
voice = getSongManager().getMeasureManager().getFirstVoice(
measure.getBeats(), getVoice());
beat = (voice != null ? voice.getBeat() : null);
if (beat == null) {
beat = getSongManager().getMeasureManager().getFirstBeat(
measure.getBeats());
}
}
if (beat != null) {
moveTo(getTrack(), measure, beat, getStringNumber());
}
}
return true;
}
public void moveTo(TGTrackImpl selectedTrack, TGMeasureImpl selectedMeasure,
TGBeat selectedBeat, int string) {
this.selectedTrack = selectedTrack;
this.selectedMeasure = selectedMeasure;
this.selectedBeat = selectedBeat;
this.string = string;
this.updatePosition();
this.updateDuration();
this.updateString();
this.updateNote();
this.updateBeat();
this.checkTransport();
this.setChanges(true);
}
public void moveUp() {
int stringCount = this.selectedTrack.stringCount();
int nextString = (((this.string - 2 + stringCount) % stringCount) + 1);
setStringNumber(nextString);
}
public void paintCaret(ViewLayout layout, TGPainter painter) {
if (!TuxGuitar.instance().getPlayer().isRunning()) {
if (this.selectedMeasure != null
&& this.selectedBeat instanceof TGBeatImpl) {
TGBeatImpl beat = (TGBeatImpl) this.selectedBeat;
if ((layout.getStyle() & ViewLayout.DISPLAY_TABLATURE) != 0) {
boolean expectedVoice = (getSelectedNote() == null || getSelectedNote()
.getVoice().getIndex() == getVoice());
int stringSpacing = this.tablature.getViewLayout().getStringSpacing();
int leftSpacing = beat.getMeasureImpl().getHeaderImpl()
.getLeftSpacing(layout);
int x = this.selectedMeasure.getPosX() + beat.getPosX()
+ beat.getSpacing() + leftSpacing - 5;
int y = this.selectedMeasure.getPosY()
+ this.selectedMeasure.getTs().getPosition(
TGTrackSpacing.POSITION_TABLATURE)
+ ((this.string * stringSpacing) - stringSpacing) - 7;
int width = 14;
int height = 14;
layout.setCaretStyle(painter, expectedVoice);
painter.initPath();
painter.setAntialias(false);
painter.addRectangle(x, y, width, height);
painter.closePath();
} else if ((layout.getStyle() & ViewLayout.DISPLAY_SCORE) != 0) {
int line = this.tablature.getViewLayout().getScoreLineSpacing();
int leftSpacing = beat.getMeasureImpl().getHeaderImpl()
.getLeftSpacing(layout);
float xMargin = (2.0f * layout.getScale());
float x1 = this.selectedMeasure.getPosX() + beat.getPosX()
+ beat.getSpacing() + leftSpacing - xMargin;
float x2 = (x1 + layout.getResources().getScoreNoteWidth() + xMargin);
float y1 = this.selectedMeasure.getPosY()
+ this.selectedMeasure.getTs().getPosition(
TGTrackSpacing.POSITION_TOP) - line;
float y2 = this.selectedMeasure.getPosY()
+ this.selectedMeasure.getTs().getPosition(
TGTrackSpacing.POSITION_BOTTOM);
layout.setCaretStyle(painter, true);
painter.initPath();
painter.moveTo(x1, y1);
painter.lineTo(x1 + ((x2 - x1) / 2f), y1 + (line / 2f));
painter.lineTo(x2, y1);
painter.moveTo(x1, y2 + line);
painter.lineTo(x1 + ((x2 - x1) / 2f), y2 + (line / 2f));
painter.lineTo(x2, y2 + line);
painter.closePath();
}
}
}
}
public void setChanges(boolean changes) {
this.changes = changes;
}
public void setSelectedDuration(TGDuration selectedDuration) {
this.selectedDuration = selectedDuration;
}
public void setStringNumber(int number) {
this.string = number;
this.updateNote();
}
public void setVelocity(int velocity) {
this.velocity = velocity;
}
public void setVoice(int voice) {
this.voice = voice;
this.update();
}
public synchronized void update() {
int trackNumber = (this.selectedTrack != null) ? this.selectedTrack
.getNumber() : 1;
update(trackNumber, this.position, this.string);
}
public synchronized void update(int trackNumber) {
update(trackNumber, this.position, this.string);
}
public synchronized void update(int trackNumber, long position, int string) {
update(trackNumber, position, string, getVelocity());
}
public synchronized void update(int trackNumber, long position, int string,
int velocity) {
long realPosition = ((TuxGuitar.instance().getPlayer().isRunning()) ? MidiTickUtil
.getStart(TuxGuitar.instance().getPlayer().getTickPosition())
: position);
TGTrackImpl track = findTrack(trackNumber);
TGMeasureImpl measure = findMeasure(realPosition, track);
TGBeat beat = findBeat(realPosition, measure);
if (track != null && measure != null && beat != null) {
moveTo(track, measure, beat, string);
}
setVelocity(velocity);
}
private void updateBeat() {
this.restBeat = this.selectedBeat.isRestBeat();
}
/**
* Luego de mover el Caret. cambia la duracion seleccionada por la del
* componente. solo si lo que resta del compas no esta vacio
*/
private void updateDuration() {
if (this.selectedBeat != null
&& !this.selectedBeat.getVoice(getVoice()).isRestVoice()) {
this.selectedDuration = this.selectedBeat.getVoice(this.voice)
.getDuration().clone();
}
}
private void updateNote() {
this.selectedNote = null;
TGString string = getSelectedString();
if (string != null) {
this.selectedNote = getSongManager().getMeasureManager().getNote(
getMeasure(), getPosition(), string.getNumber());
}
}
private void updatePosition() {
this.position = getSelectedBeat().getStart();
}
private void updateString() {
if (this.string < 1 || this.string > getTrack().stringCount()) {
this.string = 1;
}
}
}