package org.herac.tuxguitar.gui.editors.tab;
import java.util.ArrayList;
import java.util.List;
import org.herac.tuxguitar.gui.editors.tab.layout.ViewLayout;
import org.herac.tuxguitar.song.models.Clef;
import org.herac.tuxguitar.song.models.Direction;
import org.herac.tuxguitar.song.models.TGVoice;
public class TGBeatGroup {
private static final int DOWN_OFFSET = 35;
private static final int SCORE_FLAT_POSITIONS[] = new int[] { 7, 6, 6, 5, 5,
4, 3, 3, 2, 2, 1, 1 };
private static final int SCORE_MIDDLE_KEYS[] = new int[] { 55, 40, 40, 50 };
private static final int SCORE_SHARP_POSITIONS[] = new int[] { 7, 7, 6, 6, 5,
4, 4, 3, 3, 2, 2, 1 };
private static final int UP_OFFSET = 28;
public static float getDownOffset(ViewLayout layout) {
float scale = (layout.getScoreLineSpacing() / 8.0f);
return (DOWN_OFFSET * scale);
}
public static float getUpOffset(ViewLayout layout) {
float scale = (layout.getScoreLineSpacing() / 8.0f);
return (UP_OFFSET * scale);
}
private Direction direction=Direction.NONE;
private TGNoteImpl firstMaxNote=null;
private TGNoteImpl firstMinNote=null;
private TGNoteImpl lastMaxNote=null;
private TGNoteImpl lastMinNote=null;
private TGNoteImpl maxNote=null;
private TGNoteImpl minNote=null;
private int voice;
private List<TGVoice> voices=new ArrayList<TGVoice>();
public TGBeatGroup(int voice) {
this.voice = voice;
}
private void check(TGNoteImpl note) {
int value = note.getRealValue();
// FIRST MIN NOTE
if (this.firstMinNote == null
|| note.getVoice().getBeat().getStart() < this.firstMinNote.getVoice()
.getBeat().getStart()) {
this.firstMinNote = note;
} else if (note.getVoice().getBeat().getStart() == this.firstMinNote
.getVoice().getBeat().getStart()) {
if (note.getRealValue() < this.firstMinNote.getRealValue()) {
this.firstMinNote = note;
}
}
// FIRST MAX NOTE
if (this.firstMaxNote == null
|| note.getVoice().getBeat().getStart() < this.firstMaxNote.getVoice()
.getBeat().getStart()) {
this.firstMaxNote = note;
} else if (note.getVoice().getBeat().getStart() == this.firstMaxNote
.getVoice().getBeat().getStart()) {
if (note.getRealValue() > this.firstMaxNote.getRealValue()) {
this.firstMaxNote = note;
}
}
// LAST MIN NOTE
if (this.lastMinNote == null
|| note.getVoice().getBeat().getStart() > this.lastMinNote.getVoice()
.getBeat().getStart()) {
this.lastMinNote = note;
} else if (note.getVoice().getBeat().getStart() == this.lastMinNote
.getVoice().getBeat().getStart()) {
if (note.getRealValue() < this.lastMinNote.getRealValue()) {
this.lastMinNote = note;
}
}
// LAST MIN NOTE
if (this.lastMaxNote == null
|| note.getVoice().getBeat().getStart() > this.lastMaxNote.getVoice()
.getBeat().getStart()) {
this.lastMaxNote = note;
} else if (note.getVoice().getBeat().getStart() == this.lastMaxNote
.getVoice().getBeat().getStart()) {
if (note.getRealValue() > this.lastMaxNote.getRealValue()) {
this.lastMaxNote = note;
}
}
if (this.maxNote == null || value > this.maxNote.getRealValue()) {
this.maxNote = note;
}
if (this.minNote == null || value < this.minNote.getRealValue()) {
this.minNote = note;
}
}
public void check(TGVoiceImpl voice) {
this.check(voice.getMaxNote());
this.check(voice.getMinNote());
this.voices.add(voice);
if (voice.getDirection() != Direction.NONE) {
if (voice.getDirection() == Direction.UP) {
this.direction = Direction.UP;
} else if (voice.getDirection() == Direction.DOWN) {
this.direction = Direction.DOWN;
}
}
}
public void finish(ViewLayout layout, TGMeasureImpl measure) {
if (this.direction == Direction.NONE) {
if (measure.getNotEmptyVoices() > 1) {
this.direction = this.voice == 0 ? Direction.UP : Direction.DOWN;
} else if ((layout.getStyle() & ViewLayout.DISPLAY_SCORE) == 0) {
this.direction = Direction.DOWN;
} else {
int selection = 0;
switch (measure.getClef()) {
case ALTO:
selection = 3;
break;
case BASS:
selection = 1;
break;
case TENOR:
selection = 2;
break;
case TREBLE:
selection = 0;
break;
}
int max = Math.abs(this.minNote.getRealValue()
- (SCORE_MIDDLE_KEYS[selection] + 100));
int min = Math.abs(this.maxNote.getRealValue()
- (SCORE_MIDDLE_KEYS[selection] - 100));
if (max > min) {
this.direction = Direction.UP;
} else {
this.direction = Direction.DOWN;
}
}
}
}
public Direction getDirection() {
return this.direction;
}
public TGNoteImpl getMaxNote() {
return this.maxNote;
}
public TGNoteImpl getMinNote() {
return this.minNote;
}
public List<TGVoice> getVoices() {
return this.voices;
}
public int getY1(ViewLayout layout, TGNoteImpl note, int key, Clef clef) {
double scale = (layout.getScoreLineSpacing() / 2.00);
int noteValue = note.getRealValue();
int scoreLineY = 0;
if (key <= 7) {
scoreLineY = (int) ((SCORE_SHARP_POSITIONS[noteValue % 12]) * scale - (7 * (noteValue / 12))
* scale);
} else {
scoreLineY = (int) ((SCORE_FLAT_POSITIONS[noteValue % 12]) * scale - (7 * (noteValue / 12))
* scale);
}
int selection = 0;
switch (clef) {
case ALTO:
selection = 3;
break;
case BASS:
selection = 1;
break;
case TENOR:
selection = 2;
break;
case TREBLE:
selection = 0;
break;
}
scoreLineY += TGMeasureImpl.SCORE_KEY_OFFSETS[selection] * scale;
return scoreLineY;
}
public int getY2(ViewLayout layout, int x, int key, Clef clef) {
int maxDistance = 10;
float upOffset = TGBeatGroup.getUpOffset(layout);
float downOffset = TGBeatGroup.getDownOffset(layout);
if (this.direction == Direction.NONE) {
if (this.minNote != this.firstMinNote && this.minNote != this.lastMinNote) {
return (int) (getY1(layout, this.minNote, key, clef) + downOffset);
}
int y = 0;
int x1 = this.firstMinNote.getPosX()
+ this.firstMinNote.getBeatImpl().getSpacing();
int x2 = this.lastMinNote.getPosX()
+ this.lastMinNote.getBeatImpl().getSpacing();
int y1 = (int) (getY1(layout, this.firstMinNote, key, clef) + downOffset);
int y2 = (int) (getY1(layout, this.lastMinNote, key, clef) + downOffset);
if (y1 > y2 && (y1 - y2) > maxDistance)
y2 = (y1 - maxDistance);
if (y2 > y1 && (y2 - y1) > maxDistance)
y1 = (y2 - maxDistance);
// int y = (int)((((double)y1 -(double)y2) / ((double)x1 - (double)x2)) *
// ((double)x1 - (double)x));
if ((y1 - y2) != 0 && (x1 - x2) != 0 && (x1 - x) != 0) {
y = (int) ((((double) y1 - (double) y2) / ((double) x1 - (double) x2)) * ((double) x1 - (double) x));
}
return y1 - y;
} else if (this.maxNote != this.firstMaxNote
&& this.maxNote != this.lastMaxNote) {
return (int) (getY1(layout, this.maxNote, key, clef) - upOffset);
} else {
int y = 0;
int x1 = this.firstMaxNote.getPosX()
+ this.firstMaxNote.getBeatImpl().getSpacing();
int x2 = this.lastMaxNote.getPosX()
+ this.lastMaxNote.getBeatImpl().getSpacing();
int y1 = (int) (getY1(layout, this.firstMaxNote, key, clef) - upOffset);
int y2 = (int) (getY1(layout, this.lastMaxNote, key, clef) - upOffset);
if (y1 < y2 && (y2 - y1) > maxDistance)
y2 = (y1 + maxDistance);
if (y2 < y1 && (y1 - y2) > maxDistance)
y1 = (y2 + maxDistance);
if ((y1 - y2) != 0 && (x1 - x2) != 0 && (x1 - x) != 0) {
y = (int) ((((double) y1 - (double) y2) / ((double) x1 - (double) x2)) * ((double) x1 - (double) x));
}
return y1 - y;
}
}
}