Refactored construction of Swing player controls to their own class.

This commit is contained in:
neviyn 2016-03-29 16:05:08 +01:00
parent ab0680b5ee
commit 05cebf59fb
11 changed files with 188 additions and 99 deletions

View File

@ -32,7 +32,7 @@
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>musicplayer.PlayerGUI</mainClass>
<mainClass>musicplayer.Main</mainClass>
</manifest>
</archive>
</configuration>

View File

@ -0,0 +1,29 @@
package musicplayer;
import com.google.inject.Guice;
import com.google.inject.Injector;
import musicplayer.swingui.PlayerGUI;
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
runSwingUIMode();
}
/**
* Start the application with injection bindings contained in SwingUIModule
*/
private static void runSwingUIMode() {
Injector injector = Guice.createInjector(new SwingUIModule());
PlayerGUI playerGUI = injector.getInstance(PlayerGUI.class);
JFrame frame = new JFrame();
frame.setMinimumSize(new Dimension(600, 400));
frame.setContentPane(playerGUI);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}

View File

@ -2,6 +2,7 @@ package musicplayer;
import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import musicplayer.callbacks.PlayerCallbackInterface;
import musicplayer.db.HibernateDatabase;
import musicplayer.db.IDatabase;
import musicplayer.library.ILibrary;
@ -10,6 +11,7 @@ import musicplayer.player.GStreamerPlayer;
import musicplayer.player.IPlayer;
import musicplayer.playlist.IPlaylist;
import musicplayer.playlist.JTablePlaylist;
import musicplayer.swingui.PlayerGUI;
class SwingUIModule extends AbstractModule {
@ -19,5 +21,6 @@ class SwingUIModule extends AbstractModule {
bind(IDatabase.class).to(HibernateDatabase.class).in(Singleton.class);
bind(IPlaylist.class).to(JTablePlaylist.class).in(Singleton.class);
bind(ILibrary.class).to(JTreeLibrary.class).in(Singleton.class);
bind(PlayerCallbackInterface.class).to(PlayerGUI.class);
}
}

View File

@ -1,9 +1,5 @@
package musicplayer.callbacks;
import com.google.inject.ImplementedBy;
import musicplayer.PlayerGUI;
@ImplementedBy(PlayerGUI.class)
public interface PlayerCallbackInterface {
/**

View File

@ -0,0 +1,119 @@
package musicplayer.swingui;
import musicplayer.StartPlayingException;
import musicplayer.player.IPlayer;
import musicplayer.util.Icons;
import javax.swing.*;
import java.awt.*;
public class ControlBar extends JPanel {
IPlayer player;
public ControlBar(IPlayer player){
this.player = player;
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(playButton());
add(pauseButton());
add(stopButton());
add(previousButton());
add(nextButton());
add(repeatButton());
}
private JButton playButton(){
JButton playButton = new ControlButton(Icons.playIcon);
playButton.setName("playButton");
playButton.setMnemonic('P');
playButton.addActionListener(e -> {
try {
player.play();
} catch (StartPlayingException e1) {
showError(e1);
}
});
return playButton;
}
private JButton pauseButton(){
JButton pauseButton = new ControlButton(Icons.pauseIcon);
pauseButton.setMnemonic('E');
pauseButton.addActionListener(e -> player.pause());
return pauseButton;
}
private JButton stopButton(){
JButton stopButton = new ControlButton(Icons.stopIcon);
stopButton.setMnemonic('S');
stopButton.addActionListener(e -> player.stop());
return stopButton;
}
private JButton previousButton(){
JButton previousButton = new ControlButton(Icons.prevIcon);
previousButton.setMnemonic('R');
previousButton.addActionListener(e -> {
try {
player.previous();
} catch (StartPlayingException e1) {
showError(e1);
}
});
return previousButton;
}
private JButton nextButton(){
JButton nextButton = new ControlButton(Icons.nextIcon);
nextButton.setMnemonic('N');
nextButton.addActionListener(e -> {
try {
player.next();
} catch (StartPlayingException e1) {
showError(e1);
}
});
return nextButton;
}
private JButton repeatButton(){
JButton repeatButton = new ControlButton(Icons.repeatMultiIcon);
repeatButton.setToolTipText("Repeating playlist.");
repeatButton.addActionListener(e -> {
player.setRepeat(!player.isRepeating());
if(player.isRepeating()) {
repeatButton.setIcon(Icons.repeatSingleIcon);
repeatButton.setToolTipText("Repeating song.");
}
else {
repeatButton.setIcon(Icons.repeatMultiIcon);
repeatButton.setToolTipText("Repeating playlist.");
}
});
return repeatButton;
}
private void showError(StartPlayingException ex) {
JOptionPane.showMessageDialog(this, "Failed to play " + ex.getSong().toString() + ".\n" +
"If file path contains non-ASCII characters, please restart the application with UTF-8 encoding.");
}
/**
* Button for performing some control action on the player
*/
private class ControlButton extends JButton {
public ControlButton(Icon icon){
setIcon(icon);
}
final Dimension buttonSize = new Dimension(40, 40);
@Override
public Dimension getPreferredSize() {
return buttonSize;
}
@Override
public Dimension getMaximumSize() {
return buttonSize;
}
}
}

View File

@ -1,4 +1,4 @@
package musicplayer;
package musicplayer.swingui;
import musicplayer.util.ConfigManager;

View File

@ -1,14 +1,12 @@
package musicplayer;
package musicplayer.swingui;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import musicplayer.StartPlayingException;
import musicplayer.callbacks.PlayerCallbackInterface;
import musicplayer.library.ILibrary;
import musicplayer.player.IPlayer;
import musicplayer.playlist.IPlaylist;
import musicplayer.util.ConfigManager;
import musicplayer.util.Icons;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
@ -61,7 +59,7 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
}
});
Runtime.getRuntime().addShutdownHook(hookShutdown);
} catch(RuntimeException | NativeHookException |UnsatisfiedLinkError ex){
} catch (RuntimeException | NativeHookException | UnsatisfiedLinkError ex) {
System.out.println("Keyboard hook failed, global shortcuts will not work this session.");
System.out.println(ex.getMessage());
System.out.println(Arrays.toString(ex.getStackTrace()));
@ -69,17 +67,6 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
library.refreshLibrary();
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new SwingUIModule());
PlayerGUI playerGUI = injector.getInstance(PlayerGUI.class);
JFrame frame = new JFrame();
frame.setMinimumSize(new Dimension(600, 400));
frame.setContentPane(playerGUI);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
/**
* Set the value of seekBar.
*
@ -87,7 +74,7 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
*/
public void setSeekBarPosition(int position) {
SwingUtilities.invokeLater(() -> {
if(!seeking.get())
if (!seeking.get())
seekBar.setValue(position);
});
}
@ -101,7 +88,7 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
SwingUtilities.invokeLater(() -> seekBar.setMaximum(seconds));
}
private void showError(StartPlayingException ex){
private void showError(StartPlayingException ex) {
JOptionPane.showMessageDialog(this, "Failed to play " + ex.getSong().toString() + ".\n" +
"If file path contains non-ASCII characters, please restart the application with UTF-8 encoding.");
}
@ -123,9 +110,9 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
this.setLayout(new BorderLayout(0, 0));
final JSplitPane libraryAndPlaylistPane = new JSplitPane();
libraryAndPlaylistPane.setDividerLocation(240);
libraryAndPlaylistPane.setRightComponent((JScrollPane)playlist);
libraryAndPlaylistPane.setRightComponent((JScrollPane) playlist);
this.add(libraryAndPlaylistPane, BorderLayout.CENTER);
libraryAndPlaylistPane.setLeftComponent((JPanel)library);
libraryAndPlaylistPane.setLeftComponent((JPanel) library);
final JPanel controlPane = new JPanel();
controlPane.setLayout(new BorderLayout(0, 0));
this.add(controlPane, BorderLayout.SOUTH);
@ -144,52 +131,7 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
private JToolBar createControlButtons() {
JToolBar toolBar = new JToolBar();
toolBar.setFloatable(false);
JPanel controlBar = new JPanel(new GridLayout(1, 5));
JButton playButton = new JButton();
playButton.setName("playButton");
playButton.setIcon(Icons.playIcon);
playButton.setMnemonic('P');
playButton.addActionListener(e -> {
try {
player.play();
} catch (StartPlayingException e1) {
showError(e1);
}
});
controlBar.add(playButton);
JButton pauseButton = new JButton();
pauseButton.setIcon(Icons.pauseIcon);
pauseButton.setMnemonic('E');
pauseButton.addActionListener(e -> player.pause());
controlBar.add(pauseButton);
JButton stopButton = new JButton();
stopButton.setIcon(Icons.stopIcon);
stopButton.setMnemonic('S');
stopButton.addActionListener(e -> player.stop());
controlBar.add(stopButton);
JButton previousButton = new JButton();
previousButton.setIcon(Icons.prevIcon);
previousButton.setMnemonic('R');
previousButton.addActionListener(e -> {
try {
player.previous();
} catch (StartPlayingException e1) {
showError(e1);
}
});
controlBar.add(previousButton);
JButton nextButton = new JButton();
nextButton.setIcon(Icons.nextIcon);
nextButton.setMnemonic('N');
nextButton.addActionListener(e -> {
try {
player.next();
} catch (StartPlayingException e1) {
showError(e1);
}
});
controlBar.add(nextButton);
toolBar.add(controlBar);
toolBar.add(new ControlBar(player));
toolBar.add(createVolumeControls());
return toolBar;
}
@ -252,7 +194,7 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
FileNameExtensionFilter m3uExtensionFilter = new FileNameExtensionFilter("m3u playlist", "m3u");
menuItem = new JMenuItem("Save Playlist");
menuItem.addActionListener(e -> {
if(!playlist.isEmpty()) {
if (!playlist.isEmpty()) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
fileChooser.setSelectedFile(new File("playlist.m3u"));
@ -276,7 +218,7 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
fileChooser.setFileFilter(m3uExtensionFilter);
if(fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION){
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
IPlaylist.readPlaylistFromFile(fileChooser.getSelectedFile()).stream().forEach(playlist::addSong);
}
});
@ -288,7 +230,7 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
JMenu helpMenu = new JMenu("Help");
menuItem = new JMenuItem("About");
menuItem.addActionListener(e -> {
try(BufferedReader reader = new BufferedReader(new InputStreamReader(PlayerGUI.class.getClassLoader().getResourceAsStream("LICENSE.txt")))) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(PlayerGUI.class.getClassLoader().getResourceAsStream("LICENSE.txt")))) {
JEditorPane messagePane = new JEditorPane("text/html", reader.lines().collect(Collectors.toList()).get(0));
messagePane.setEditable(false);
messagePane.addHyperlinkListener(hl ->
@ -319,10 +261,14 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
*/
private class SeekbarMouseListener implements MouseListener {
@Override
public void mouseClicked(MouseEvent e) { seeking.set(true); }
public void mouseClicked(MouseEvent e) {
seeking.set(true);
}
@Override
public void mousePressed(MouseEvent e) { seeking.set(true); }
public void mousePressed(MouseEvent e) {
seeking.set(true);
}
@Override
public void mouseReleased(MouseEvent e) {
@ -331,10 +277,12 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
}
@Override
public void mouseEntered(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {}
public void mouseExited(MouseEvent e) {
}
}
private class GlobalKeyboardShortcuts implements NativeKeyListener {
@ -346,19 +294,19 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
@Override
public void nativeKeyPressed(NativeKeyEvent nativeKeyEvent) {
if(nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_ALT_L)
if (nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_ALT_L)
modified = true;
}
@Override
public void nativeKeyReleased(NativeKeyEvent nativeKeyEvent) {
if(nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_ALT_L)
if (nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_ALT_L)
modified = false;
}
@Override
public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) {
if(modified){
if (modified) {
try {
switch (nativeKeyEvent.getRawCode()) {
case playPause:
@ -378,7 +326,7 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
player.next();
break;
}
}catch (StartPlayingException ex){
} catch (StartPlayingException ex) {
showError(ex);
}
}

View File

@ -42,11 +42,7 @@ public final class ConfigManager {
*/
public static void saveLibraryDirectories(List<File> folderList){
librarySettings.setProperty(foldersKey, folderList.stream().map(File::toString).collect(Collectors.joining(",")));
try(FileWriter fileWriter = new FileWriter(settingsFilename)){
librarySettings.store(fileWriter, "");
} catch (IOException e) {
e.printStackTrace();
}
writeSettings();
}
/**
@ -61,11 +57,7 @@ public final class ConfigManager {
} catch (IOException ignored) {
}
librarySettings.setProperty(databaseKey, "musicDB");
try(FileWriter fileWriter = new FileWriter(settingsFilename)){
librarySettings.store(fileWriter, "");
} catch (IOException e) {
e.printStackTrace();
}
writeSettings();
return "jdbc:hsqldb:file:" + new File("musicDB").getAbsolutePath() + ";shutdown=true"; //Use relative file by default
}
@ -89,11 +81,7 @@ public final class ConfigManager {
*/
public static void setLastDisplayTypeIndex(Integer index){
librarySettings.setProperty(libraryDisplayKey, index.toString());
try(FileWriter fileWriter = new FileWriter(settingsFilename)){
librarySettings.store(fileWriter, "");
} catch (IOException e) {
e.printStackTrace();
}
writeSettings();
}
public static int getLastVolume(){
@ -109,6 +97,10 @@ public final class ConfigManager {
public static void setLastVolume(Integer index){
librarySettings.setProperty(lastVolumeKey, index.toString());
writeSettings();
}
private static void writeSettings(){
try(FileWriter fileWriter = new FileWriter(settingsFilename)){
librarySettings.store(fileWriter, "");
} catch (IOException e) {

View File

@ -11,4 +11,6 @@ public final class Icons {
public static final Icon stopIcon = new ImageIcon(classLoader.getResource("glyphicons-176-stop.png"));
public static final Icon prevIcon = new ImageIcon(classLoader.getResource("glyphicons-171-step-backward.png"));
public static final Icon nextIcon = new ImageIcon(classLoader.getResource("glyphicons-179-step-forward.png"));
public static final Icon repeatSingleIcon = new ImageIcon(classLoader.getResource("glyphicons-86-repeat.png"));
public static final Icon repeatMultiIcon = new ImageIcon(classLoader.getResource("glyphicons-83-roundabout.png"));
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB