package org.herac.tuxguitar.gui.table;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.herac.tuxguitar.gui.TuxGuitar;
import org.herac.tuxguitar.gui.actions.ActionLock;
import org.herac.tuxguitar.gui.actions.composition.ChangeInfoAction;
import org.herac.tuxguitar.gui.actions.track.GoToTrackAction;
import org.herac.tuxguitar.gui.actions.track.TrackPropertiesAction;
import org.herac.tuxguitar.gui.editors.TGRedrawListener;
import org.herac.tuxguitar.gui.editors.TGUpdateListener;
import org.herac.tuxguitar.gui.editors.TablatureEditor;
import org.herac.tuxguitar.gui.editors.tab.TGMeasureImpl;
import org.herac.tuxguitar.gui.editors.tab.TGTrackImpl;
import org.herac.tuxguitar.gui.system.config.TGConfigKeys;
import org.herac.tuxguitar.gui.system.language.LanguageLoader;
import org.herac.tuxguitar.player.base.MidiInstrument;
import org.herac.tuxguitar.song.models.TGBeat;
import org.herac.tuxguitar.song.models.TGMeasure;
import org.herac.tuxguitar.song.models.TGTrack;
public class TGTableViewer implements TGRedrawListener, TGUpdateListener,
LanguageLoader {
public static final Color[] BACKGROUNDS = new Color[] {
new Color(TuxGuitar.instance().getDisplay(), 255, 255, 255),
new Color(TuxGuitar.instance().getDisplay(), 238, 238, 238),
new Color(TuxGuitar.instance().getDisplay(), 192, 192, 192) };
public static void disposeColors() {
for (int i = 0; i < BACKGROUNDS.length; i++) {
BACKGROUNDS[i].dispose();
}
}
private boolean autoSizeEnabled;
private Composite composite;
private boolean followScroll;
private ScrollBar hSroll;
private int selectedMeasure;
private int selectedTrack;
private TGTable table;
private int trackCount = 0;
private boolean update;
public TGTableViewer() {
TuxGuitar.instance().getLanguageManager().addLoader(this);
TuxGuitar.instance().getEditorManager().addRedrawListener(this);
TuxGuitar.instance().getEditorManager().addUpdateListener(this);
}
private void addHScroll() {
this.hSroll = getComposite().getHorizontalBar();
this.hSroll.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
redrawLocked();
}
});
}
private void addLayout() {
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.marginTop = 0;
layout.marginBottom = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
getComposite().setLayout(layout);
}
private void addTable() {
MouseListener listener = mouseFocusListener();
this.table = new TGTable(getComposite());
this.table.getColumnNumber().getControl().addMouseListener(listener);
this.table.getColumnName().getControl().addMouseListener(listener);
this.table.getColumnInstrument().getControl().addMouseListener(listener);
this.table.getColumnCanvas().getControl().addMouseListener(listener);
this.table.getColumnCanvas().getControl().addMouseListener(
new MouseAdapter() {
public void mouseDoubleClick(MouseEvent e) {
TuxGuitar.instance().getAction(ChangeInfoAction.NAME).process(e);
}
});
this.fireUpdate(true);
this.loadProperties();
}
public void dispose() {
if (!isDisposed()) {
getComposite().dispose();
disposeColors();
}
}
public void doRedraw(int type) {
if (type == TGRedrawListener.NORMAL) {
this.redraw();
} else if (type == TGRedrawListener.PLAYING_NEW_BEAT) {
this.redrawPlayingMode();
}
}
public void doUpdate(int type) {
if (type == TGUpdateListener.SELECTION) {
this.updateItems();
} else if (type == TGUpdateListener.SONG_UPDATED) {
this.fireUpdate(false);
} else if (type == TGUpdateListener.SONG_LOADED) {
this.fireUpdate(true);
}
}
public void fireUpdate(boolean newSong) {
this.update = true;
if (newSong) {
this.trackCount = 0;
}
}
private void followHorizontalScroll(int selectedMeasure) {
int hScrollSelection = this.hSroll.getSelection();
int hScrollThumb = this.hSroll.getThumb();
int measureSize = this.table.getRowHeight();
int measurePosition = ((selectedMeasure * measureSize) - measureSize);
if ((measurePosition - hScrollSelection) < 0
|| (measurePosition + measureSize - hScrollSelection) > hScrollThumb) {
this.hSroll.setSelection(measurePosition);
}
}
public Composite getComposite() {
return this.composite;
}
public TablatureEditor getEditor() {
return TuxGuitar.instance().getTablatureEditor();
}
private int getHeight() {
Rectangle r1 = this.composite.getBounds();
Rectangle r2 = this.composite.getClientArea();
return (this.table.getMinHeight() + (r1.height - r2.height));
// return ( this.table.getMinHeight() +
// getComposite().getHorizontalBar().getSize().y );
}
public int getHScrollSelection() {
return this.hSroll.getSelection();
}
private String getInstrument(TGTrack track) {
if (track.isPercussionTrack()) {
return TuxGuitar.getProperty("track.name.default-percussion-name");
}
MidiInstrument[] list = TuxGuitar.instance().getPlayer().getInstruments();
int index = track.getChannel().getInstrument();
if (list != null && index >= 0 && index < list.length) {
return list[index].getName();
}
return new String();
}
protected int getSelectedTrack() {
return this.selectedTrack;
}
public TGTable getTable() {
return this.table;
}
public void init(Composite parent) {
this.composite = new Composite(parent, SWT.H_SCROLL);
this.addLayout();
this.addTable();
this.addHScroll();
this.loadConfig();
}
public boolean isDisposed() {
return (getComposite() == null || getComposite().isDisposed());
}
public void loadConfig() {
this.autoSizeEnabled = TuxGuitar.instance().getConfig()
.getBooleanConfigValue(TGConfigKeys.TABLE_AUTO_SIZE);
this.trackCount = 0;
}
public void loadProperties() {
this.table.getColumnNumber()
.setTitle(TuxGuitar.getProperty("track.number"));
this.table.getColumnName().setTitle(TuxGuitar.getProperty("track.name"));
this.table.getColumnInstrument().setTitle(
TuxGuitar.getProperty("track.instrument"));
}
private MouseListener mouseFocusListener() {
return new MouseAdapter() {
public void mouseUp(MouseEvent e) {
TGTable table = getTable();
if (table != null) {
TGTableRow row = table.getRow((getSelectedTrack() - 1));
if (row != null) {
row.getPainter().setFocus();
}
}
}
};
}
public void redraw() {
if (!isDisposed() && !TuxGuitar.instance().isLocked()) {
this.updateTable();
this.table.getColumnCanvas().setTitle(
TuxGuitar.instance().getSongManager().getSong().getName());
int selectedTrack = getEditor().getTablature().getCaret().getTrack()
.getNumber();
this.redrawRows(selectedTrack);
this.selectedTrack = selectedTrack;
this.selectedMeasure = 0;
this.updateHScroll();
if (this.followScroll) {
this.followHorizontalScroll(getEditor().getTablature().getCaret()
.getMeasure().getNumber());
this.followScroll = false;
}
getComposite().redraw();
}
}
public void redrawLocked() {
if (!TuxGuitar.instance().isLocked()) {
TuxGuitar.instance().lock();
redraw();
TuxGuitar.instance().unlock();
}
}
public void redrawPlayingMode() {
if (!isDisposed() && !TuxGuitar.instance().isLocked()) {
TGMeasure measure = TuxGuitar.instance().getEditorCache()
.getPlayMeasure();
if (measure != null && measure.getTrack() != null) {
this.updateTable();
int selectedTrack = measure.getTrack().getNumber();
int selectedMeasure = measure.getNumber();
if (this.selectedTrack != selectedTrack
|| this.selectedMeasure != selectedMeasure) {
this.redrawRows(selectedTrack);
this.followHorizontalScroll(selectedMeasure);
}
this.selectedTrack = selectedTrack;
this.selectedMeasure = selectedMeasure;
}
}
}
private void redrawRows(int selectedTrack) {
int rows = this.table.getRowCount();
for (int i = 0; i < rows; i++) {
TGTableRow row = this.table.getRow(i);
row.getPainter().redraw();
if (this.selectedTrack != selectedTrack) {
row.setBackground(((selectedTrack - 1) == i) ? BACKGROUNDS[2]
: BACKGROUNDS[i % 2]);
}
}
}
public void updateHScroll() {
int width = (getEditor().getTablature().getCaret().getTrack()
.countMeasures() * this.table.getRowHeight());
this.hSroll.setIncrement(this.table.getScrollIncrement());
this.hSroll.setMaximum(width);
this.hSroll.setThumb(Math.min(width, this.table.getColumnCanvas()
.getControl().getClientArea().width));
}
public void updateItems() {
this.followScroll = true;
}
private void updateTable() {
if (this.update) {
int count = TuxGuitar.instance().getSongManager().getSong().countTracks();
this.table.removeRowsAfter(count);
for (int i = this.table.getRowCount(); i < count; i++) {
this.table.newRow();
}
for (int i = 0; i < count; i++) {
final TGTrack track = TuxGuitar.instance().getSongManager().getSong()
.getTrack(i);
final TGTableRow row = this.table.getRow(i);
if (row != null) {
// Number
row.getNumber().setText(Integer.toString(track.getNumber()));
row.getNumber().setData(track);
// Name
row.getName().setText(track.getName());
row.getName().setData(track);
// Instrument
row.getInstrument().setText(getInstrument(track));
row.getInstrument().setData(track);
row.setMouseListenerLabel(new MouseAdapter() {
public void mouseDoubleClick(final MouseEvent e) {
new Thread(new Runnable() {
public void run() {
ActionLock.waitFor();
TuxGuitar.instance().getAction(TrackPropertiesAction.NAME)
.process(e);
}
}).start();
}
public void mouseDown(MouseEvent e) {
if (track.getNumber() != getEditor().getTablature().getCaret()
.getTrack().getNumber()) {
TuxGuitar.instance().getAction(GoToTrackAction.NAME).process(e);
}
}
public void mouseUp(MouseEvent e) {
row.getPainter().setFocus();
}
});
row.setMouseListenerCanvas(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
int index = ((e.x + getHScrollSelection()) / getTable()
.getRowHeight());
if (index >= 0 && index < track.countMeasures()) {
TGMeasureImpl measure = (TGMeasureImpl) track.getMeasure(index);
TGBeat beat = TuxGuitar.instance().getSongManager()
.getMeasureManager().getFirstBeat(measure.getBeats());
if (beat != null) {
getEditor().getTablature().getCaret().moveTo(
(TGTrackImpl) track, measure, beat, 1);
TuxGuitar.instance().updateCache(true);
}
}
}
public void mouseUp(MouseEvent e) {
row.getPainter().setFocus();
}
});
row.setPaintListenerCanvas(new TGTableCanvasPainter(this, track));
}
}
this.table.update();
this.selectedTrack = 0;
this.selectedMeasure = 0;
if (this.autoSizeEnabled && this.trackCount != count) {
TuxGuitar.instance().setTableHeight(getHeight());
this.trackCount = count;
}
}
this.update = false;
}
}