/*
* Created on 25-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;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Shell;
import org.herac.tuxguitar.gui.actions.Action;
import org.herac.tuxguitar.gui.actions.ActionLock;
import org.herac.tuxguitar.gui.actions.ActionManager;
import org.herac.tuxguitar.gui.actions.file.FileActionUtils;
import org.herac.tuxguitar.gui.actions.system.DisposeAction;
import org.herac.tuxguitar.gui.editors.EditorCache;
import org.herac.tuxguitar.gui.editors.FretBoardEditor;
import org.herac.tuxguitar.gui.editors.PianoEditor;
import org.herac.tuxguitar.gui.editors.TGEditorManager;
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.chord.CustomChordManager;
import org.herac.tuxguitar.gui.editors.lyric.LyricEditor;
import org.herac.tuxguitar.gui.editors.matrix.MatrixEditor;
import org.herac.tuxguitar.gui.helper.FileHistory;
import org.herac.tuxguitar.gui.helper.SyncThread;
import org.herac.tuxguitar.gui.items.ItemManager;
import org.herac.tuxguitar.gui.marker.MarkerList;
import org.herac.tuxguitar.gui.mixer.TGMixer;
import org.herac.tuxguitar.gui.system.config.TGConfigKeys;
import org.herac.tuxguitar.gui.system.config.TGConfigManager;
import org.herac.tuxguitar.gui.system.config.TGConfigManagerImpl;
import org.herac.tuxguitar.gui.system.icons.IconLoader;
import org.herac.tuxguitar.gui.system.icons.IconManager;
import org.herac.tuxguitar.gui.system.keybindings.KeyBindingActionManager;
import org.herac.tuxguitar.gui.system.language.LanguageManager;
import org.herac.tuxguitar.gui.system.plugins.TGPluginManager;
import org.herac.tuxguitar.gui.table.TGTableViewer;
import org.herac.tuxguitar.gui.tools.browser.dialog.TGBrowserDialog;
import org.herac.tuxguitar.gui.tools.scale.ScaleManager;
import org.herac.tuxguitar.gui.transport.TGTransport;
import org.herac.tuxguitar.gui.transport.TGTransportListener;
import org.herac.tuxguitar.gui.undo.UndoableManager;
import org.herac.tuxguitar.gui.util.TGFileUtils;
import org.herac.tuxguitar.gui.util.TGSplash;
import org.herac.tuxguitar.gui.util.WindowTitleUtil;
import org.herac.tuxguitar.player.base.MidiPlayer;
import org.herac.tuxguitar.player.base.MidiPlayerException;
import org.herac.tuxguitar.player.impl.sequencer.MidiSequencerProviderImpl;
import org.herac.tuxguitar.song.managers.TGSongManager;
import org.herac.tuxguitar.song.models.TGBeat;
import org.herac.tuxguitar.song.models.TGSong;
import org.herac.tuxguitar.util.TGLock;
import org.herac.tuxguitar.util.TGSynchronizer;
/**
* @author julian
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class TuxGuitar {
public static final String APPLICATION_NAME = "TuxGuitar";
private static TuxGuitar instance;
public static final int MARGIN_WIDTH = 5;
public static String getProperty(String key) {
return instance.getLanguageManager().getProperty(key);
}
public static String getProperty(String key, String[] arguments) {
return instance.getLanguageManager().getProperty(key, arguments);
}
public static TuxGuitar instance() {
if (instance == null) {
synchronized (TuxGuitar.class) {
instance = new TuxGuitar();
}
}
return instance;
}
public static boolean isDisposed() {
return instance.display.isDisposed() || instance.shell.isDisposed();
}
private ActionManager actionManager;
private TGBrowserDialog browser;
private TGConfigManager configManager;
private CustomChordManager customChordManager;
private Display display;
private EditorCache editorCache;
private TGEditorManager editorManager;
private FileHistory fileHistory;
private FretBoardEditor fretBoardEditor;
private IconManager iconManager;
private boolean initialized = false;
private ItemManager itemManager;
private KeyBindingActionManager keyBindingManager;
private LanguageManager languageManager;
private TGLock lock = new TGLock();
private LyricEditor lyricEditor;
private MatrixEditor matrixEditor;
private PianoEditor pianoEditor;
private MidiPlayer player;
private TGPluginManager pluginManager;
protected Sash sash;
protected Composite sashComposite;
private ScaleManager scaleManager;
private Shell shell;
private TGSongManager songManager;
private TGMixer songMixer;
private TGTransport songTransport;
private TablatureEditor tablatureEditor;
private TGTableViewer table;
private UndoableManager undoableManager;
public void createComposites(Composite composite) {
FormData data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(100, 0);
data.top = new FormAttachment(getItemManager().getCoolbar(), MARGIN_WIDTH);
data.bottom = new FormAttachment(100, 0);
this.sashComposite = new Composite(composite, SWT.NONE);
this.sashComposite.setLayout(new FormLayout());
this.sashComposite.setLayoutData(data);
data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(100, 0);
data.bottom = new FormAttachment(100, -150);
data.height = MARGIN_WIDTH;
this.sash = new Sash(this.sashComposite, SWT.HORIZONTAL);
this.sash.setLayoutData(data);
data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(100, 0);
data.top = new FormAttachment(0, 0);
data.bottom = new FormAttachment(this.sash, 0);
getTablatureEditor().showTablature(this.sashComposite);
getTablatureEditor().getTablature().setLayoutData(data);
data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(100, 0);
data.top = new FormAttachment(this.sash, 0);
data.bottom = new FormAttachment(100, 0);
getTable().init(this.sashComposite);
getTable().getComposite().setLayoutData(data);
data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(100, 0);
data.top = new FormAttachment(this.sashComposite, 0);
data.bottom = new FormAttachment(100, 0);
Composite footer = new Composite(composite, SWT.NONE);
footer.setLayout(new FormLayout());
footer.setLayoutData(data);
getFretBoardEditor().showFretBoard(footer);
this.sash.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent e) {
TuxGuitar.this.sashComposite.layout(true, true);
}
});
this.sash.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
int maximumHeight = (TuxGuitar.this.sashComposite.getBounds().height - TuxGuitar.this.sash
.getBounds().height);
int height = (maximumHeight - event.y);
height = Math.max(height, 0);
height = Math.min(height, maximumHeight);
((FormData) TuxGuitar.this.sash.getLayoutData()).bottom = new FormAttachment(
100, -height);
}
});
this.sash.addMouseTrackListener(new MouseTrackAdapter() {
@Override
public void mouseEnter(MouseEvent e) {
TuxGuitar.this.sash.setCursor(getDisplay().getSystemCursor(
SWT.CURSOR_SIZENS));
}
});
this.sashComposite.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event arg0) {
FormData data = ((FormData) TuxGuitar.this.sash.getLayoutData());
int height = -data.bottom.offset;
int maximumHeight = (TuxGuitar.this.sashComposite.getBounds().height - TuxGuitar.this.sash
.getBounds().height);
if (height > maximumHeight) {
data.bottom = new FormAttachment(100, -maximumHeight);
}
}
});
}
public TuxGuitar() {
this.parser.acceptsAll(Arrays.asList("h", "help"),
"print this help message");
this.parser.acceptsAll(Arrays.asList("v", "version"),
"print the version of this program");
}
/**
* The parser for command-line options. The options which this parser accepts
* are given in the constructor of this class.
*/
private final OptionParser parser = new OptionParser();
public void displayGUI(final String[] args) {
// checkeo los argumentos (parse the command-line options/arguments)
final OptionSet options = this.parser.parse(args);
/*
* ArgumentParser argumentParser = new ArgumentParser(args); if
* (argumentParser.processAndExit()) { return; }
*/
// Priority 1 ----------------------------------------------//
TGFileUtils.loadLibraries();
TGFileUtils.loadClasspath();
// Priority 2 ----------------------------------------------//
Display.setAppName(APPLICATION_NAME);
this.display = new Display();
this.initSynchronizer();
TGSplash.instance().init();
this.shell = new Shell(getDisplay());
this.shell.setLayout(getShellLayout());
this.shell.setImage(getIconManager().getAppIcon());
this.createComposites(getShell());
// Priority 3 ----------------------------------------------//
this.getPluginManager().openPlugins();
this.restoreControlsConfig();
this.restorePlayerConfig();
this.updateCache(true);
this.showTitle();
TGSplash.instance().finish();
// Priority 4 ----------------------------------------------//
this.shell.addShellListener(getAction(DisposeAction.NAME));
this.shell.open();
final List<String> nonOptionArguments = options.nonOptionArguments();
if (nonOptionArguments.size() == 0) {
LOG.debug("No file or URL was provided for a song to load.");
} else {
final String songLocation = nonOptionArguments.get(0);
this.startSong(songLocation);
}
this.setInitialized(true);
while (!getDisplay().isDisposed() && !getShell().isDisposed()) {
if (!getDisplay().readAndDispatch()) {
getDisplay().sleep();
}
}
getDisplay().dispose();
}
public void fireNewSong(TGSong song, URL url) {
this.lock();
TuxGuitar.instance().getSongManager().setSong(song);
getFileHistory().reset(url);
getPlayer().reset();
getPlayer().getMode().clear();
getEditorCache().reset();
getUndoableManager().discardAllEdits();
getEditorManager().doUpdate(TGUpdateListener.SONG_LOADED);
this.unlock();
updateCache(true);
showTitle();
}
public void fireSaveSong(URL url) {
this.lock();
getFileHistory().reset(url);
getEditorCache().reset();
getUndoableManager().discardAllEdits();
getEditorManager().doUpdate(TGUpdateListener.SONG_SAVED);
this.unlock();
updateCache(true);
showTitle();
}
public void fireUpdate() {
this.lock();
this.getEditorCache().reset();
this.getEditorManager().doUpdate(TGUpdateListener.SONG_UPDATED);
this.unlock();
}
public Action getAction(String name) {
return this.getActionManager().getAction(name);
}
public ActionManager getActionManager() {
if (this.actionManager == null) {
this.actionManager = new ActionManager();
}
return this.actionManager;
}
public TGBrowserDialog getBrowser() {
if (this.browser == null) {
this.browser = new TGBrowserDialog();
}
return this.browser;
}
public TGConfigManager getConfig() {
if (this.configManager == null) {
this.configManager = new TGConfigManagerImpl();
this.configManager.init();
}
return this.configManager;
}
public CustomChordManager getCustomChordManager() {
if (this.customChordManager == null) {
this.customChordManager = new CustomChordManager();
}
return this.customChordManager;
}
public Display getDisplay() {
return this.display;
}
public EditorCache getEditorCache() {
if (this.editorCache == null) {
this.editorCache = new EditorCache();
}
return this.editorCache;
}
public TGEditorManager getEditorManager() {
if (this.editorManager == null) {
this.editorManager = new TGEditorManager();
}
return this.editorManager;
}
public FileHistory getFileHistory() {
if (this.fileHistory == null) {
this.fileHistory = new FileHistory();
}
return this.fileHistory;
}
public FretBoardEditor getFretBoardEditor() {
if (this.fretBoardEditor == null) {
this.fretBoardEditor = new FretBoardEditor();
}
return this.fretBoardEditor;
}
public IconManager getIconManager() {
if (this.iconManager == null) {
this.iconManager = new IconManager();
this.iconManager.addLoader(new IconLoader() {
public void loadIcons() {
getShell().setImage(getIconManager().getAppIcon());
getShell().layout(true);
}
});
}
return this.iconManager;
}
public ItemManager getItemManager() {
if (this.itemManager == null) {
this.itemManager = new ItemManager();
}
return this.itemManager;
}
public KeyBindingActionManager getkeyBindingManager() {
if (this.keyBindingManager == null) {
this.keyBindingManager = new KeyBindingActionManager();
}
return this.keyBindingManager;
}
public LanguageManager getLanguageManager() {
if (this.languageManager == null) {
this.languageManager = new LanguageManager();
this.loadLanguage();
}
return this.languageManager;
}
public LyricEditor getLyricEditor() {
if (this.lyricEditor == null) {
this.lyricEditor = new LyricEditor();
}
return this.lyricEditor;
}
public MatrixEditor getMatrixEditor() {
if (this.matrixEditor == null) {
this.matrixEditor = new MatrixEditor();
}
return this.matrixEditor;
}
public TGMixer getMixer() {
if (this.songMixer == null) {
this.songMixer = new TGMixer();
}
return this.songMixer;
}
public PianoEditor getPianoEditor() {
if (this.pianoEditor == null) {
this.pianoEditor = new PianoEditor();
}
return this.pianoEditor;
}
public MidiPlayer getPlayer() {
if (this.player == null) {
this.player = new MidiPlayer();
this.player.init(getSongManager());
this.player.addListener(new TGTransportListener());
try {
getPlayer()
.addSequencerProvider(new MidiSequencerProviderImpl(), false);
} catch (MidiPlayerException e) {
LOG.error(e);
}
}
return this.player;
}
/** The Logger for this class. */
public static final transient Logger LOG = Logger.getLogger(TuxGuitar.class);
public TGPluginManager getPluginManager() {
if (this.pluginManager == null) {
this.pluginManager = new TGPluginManager();
}
return this.pluginManager;
}
public ScaleManager getScaleManager() {
if (this.scaleManager == null) {
this.scaleManager = new ScaleManager();
}
return this.scaleManager;
}
public Shell getShell() {
return this.shell;
}
private FormLayout getShellLayout() {
FormLayout layout = new FormLayout();
layout.marginWidth = MARGIN_WIDTH;
layout.marginHeight = MARGIN_WIDTH;
return layout;
}
public TGSongManager getSongManager() {
if (this.songManager == null) {
// this.songManager = new TGSongManager(new TGFactoryImpl());
this.songManager = new TGSongManager();
this.songManager.setSong(this.songManager.newSong());
}
return this.songManager;
}
public TablatureEditor getTablatureEditor() {
if (this.tablatureEditor == null) {
this.tablatureEditor = new TablatureEditor();
}
return this.tablatureEditor;
}
public TGTableViewer getTable() {
if (this.table == null) {
this.table = new TGTableViewer();
}
return this.table;
}
public TGTransport getTransport() {
if (this.songTransport == null) {
this.songTransport = new TGTransport();
}
return this.songTransport;
}
public UndoableManager getUndoableManager() {
if (this.undoableManager == null) {
this.undoableManager = new UndoableManager();
}
return this.undoableManager;
}
public void hideExternalBeat() {
if (!isDisposed() && !this.isLocked()) {
this.lock();
this.getEditorManager().hideExternalBeat();
this.updateCache(true);
this.unlock();
}
}
private void initSynchronizer() {
TGSynchronizer.instance().setController(
new TGSynchronizer.TGSynchronizerController() {
public void execute(final TGSynchronizer.TGSynchronizerTask task) {
final Display display = getDisplay();
if (display != null && !display.isDisposed()) {
display.syncExec(new Runnable() {
public void run() {
task.run();
}
});
}
}
public void executeLater(final TGSynchronizer.TGSynchronizerTask task) {
final Display display = getDisplay();
if (display != null && !display.isDisposed()) {
display.asyncExec(new Runnable() {
public void run() {
task.run();
}
});
}
}
});
}
public boolean isInitialized() {
return this.initialized;
}
public boolean isLocked() {
return this.lock.isLocked();
}
public void loadCursor(final Control control, final int style) {
try {
TGSynchronizer.instance().addRunnable(new TGSynchronizer.TGRunnable() {
public void run() throws Throwable {
if (!control.isDisposed()) {
control.setCursor(getDisplay().getSystemCursor(style));
}
}
});
} catch (Throwable e) {
LOG.error(e);
}
}
public void loadCursor(int style) {
this.loadCursor(getShell(), style);
}
public void loadLanguage() {
this.lock();
getLanguageManager().setLanguage(
getConfig().getStringConfigValue(TGConfigKeys.LANGUAGE));
this.unlock();
}
public void loadSkin() {
this.lock();
getIconManager().reloadIcons();
this.unlock();
}
public void loadStyles() {
this.lock();
getTablatureEditor().getTablature().reloadStyles();
this.unlock();
}
public void loadToolBars() {
this.lock();
getItemManager().createCoolbar();
this.unlock();
}
public void lock() {
this.lock.lock();
}
public void newSong() {
TuxGuitar.instance().fireNewSong(
TuxGuitar.instance().getSongManager().newSong(), null);
}
protected void redraw() {
if (!isDisposed() && !this.isLocked()) {
this.lock();
this.getEditorManager().doRedraw(TGRedrawListener.NORMAL);
this.unlock();
}
}
public void redrawPlayingMode() {
if (!isDisposed() && !this.isLocked()) {
this.lock();
this.getEditorCache().updatePlayMode();
this
.getEditorManager()
.doRedraw(
this.getEditorCache().shouldRedraw() ? TGRedrawListener.PLAYING_NEW_BEAT
: TGRedrawListener.PLAYING_THREAD);
this.unlock();
}
}
public void restoreControlsConfig() {
final TGConfigManager config = getConfig();
// ---Main Shell---
boolean maximized = config.getBooleanConfigValue(TGConfigKeys.MAXIMIZED);
getShell().setMaximized(maximized);
if (!maximized) {
int width = config.getIntConfigValue(TGConfigKeys.WIDTH);
int height = config.getIntConfigValue(TGConfigKeys.HEIGHT);
if (width > 0 && height > 0) {
getShell().setSize(width, height);
}
}
getShell().setMinimumSize(640, 480);
// ---Fretboard---
if (config.getBooleanConfigValue(TGConfigKeys.SHOW_FRETBOARD)) {
getFretBoardEditor().showFretBoard();
} else {
getFretBoardEditor().hideFretBoard();
}
// ---Mixer---
if (config.getBooleanConfigValue(TGConfigKeys.SHOW_MIXER)) {
new SyncThread(new Runnable() {
public void run() {
getMixer().show();
}
}).start();
}
// ---Transport---
if (config.getBooleanConfigValue(TGConfigKeys.SHOW_TRANSPORT)) {
new SyncThread(new Runnable() {
public void run() {
getTransport().show();
}
}).start();
}
// ---Matrix---
if (config.getBooleanConfigValue(TGConfigKeys.SHOW_MATRIX)) {
new SyncThread(new Runnable() {
public void run() {
getMatrixEditor().show();
}
}).start();
}
// ---Piano---
if (config.getBooleanConfigValue(TGConfigKeys.SHOW_PIANO)) {
new SyncThread(new Runnable() {
public void run() {
getPianoEditor().show();
}
}).start();
}
// ---Markers---
if (config.getBooleanConfigValue(TGConfigKeys.SHOW_MARKERS)) {
new SyncThread(new Runnable() {
public void run() {
MarkerList.instance().show();
}
}).start();
}
}
public void restorePlayerConfig() {
// check midi sequencer
getPlayer().openSequencer(
getConfig().getStringConfigValue(TGConfigKeys.MIDI_SEQUENCER), true);
// check midi port
getPlayer().openOutputPort(
getConfig().getStringConfigValue(TGConfigKeys.MIDI_PORT), true);
}
public void setInitialized(boolean initialized) {
this.initialized = initialized;
}
public void setTableHeight(int value) {
int offset = ((FormData) getTable().getComposite().getLayoutData()).top.offset;
int sashHeight = this.sash.getBounds().height;
int maximumHeight = (this.sashComposite.getBounds().height - sashHeight);
int height = (value + offset);
height = Math.max(height, 0);
height = Math.min(height, maximumHeight);
((FormData) TuxGuitar.this.sash.getLayoutData()).bottom = new FormAttachment(
100, -height);
this.sashComposite.layout(true, true);
}
public void showExternalBeat(TGBeat beat) {
if (!isDisposed() && !this.isLocked()) {
this.lock();
this.getEditorManager().showExternalBeat(beat);
this.updateCache(true);
this.unlock();
}
}
public void showTitle() {
new SyncThread(new Runnable() {
public void run() {
if (!isDisposed()) {
getShell().setText(WindowTitleUtil.parseTitle());
}
}
}).start();
}
private void startSong(final String songLocation) {
URL url = null;
final File file = new File(songLocation);
try {
if (file.exists()) {
url = file.toURI().toURL();
} else {
url = new URL(songLocation);
}
} catch (final MalformedURLException exception) {
LOG.error("Failed to find songLocation " + songLocation, exception);
}
if (url != null) {
ActionLock.lock();
new SongLoaderThread(url).start();
}
}
private class SongLoaderThread extends SyncThread {
public SongLoaderThread(final URL url) {
super(new Runnable() {
@Override
public void run() {
TuxGuitar.instance().loadCursor(SWT.CURSOR_WAIT);
new UrlLoaderThread(url).start();
}
});
}
}
private class UrlLoaderThread extends Thread {
public UrlLoaderThread(final URL url) {
super(new Runnable() {
@Override
public void run() {
if (!TuxGuitar.isDisposed()) {
FileActionUtils.open(url);
TuxGuitar.instance().loadCursor(SWT.CURSOR_ARROW);
ActionLock.unlock();
}
}
});
}
}
public void unlock() {
this.lock.unlock();
}
public void updateCache(final boolean updateItems) {
if (!this.isLocked()) {
this.lock();
this.getEditorCache().updateEditMode();
this.unlock();
new SyncThread(new Runnable() {
public void run() {
if (!isDisposed() && !isLocked()) {
if (updateItems) {
lock();
getEditorManager().doUpdate(TGUpdateListener.SELECTION);
unlock();
}
redraw();
}
}
}).start();
}
}
public void updateShellFooter(int offset, int minimumWith, int minimumHeight) {
FormData data = ((FormData) this.sashComposite.getLayoutData());
data.bottom.offset = -offset;
getShell().setMinimumSize(Math.max(640, minimumWith),
Math.max(480, minimumHeight));
getShell().layout(true, true);
getShell().redraw();
}
}