From 23c7c923d995479df2159f0e1bf8b45928e8e7eb Mon Sep 17 00:00:00 2001 From: lantzelot-swe <75668734+lantzelot-swe@users.noreply.github.com> Date: Mon, 22 Apr 2024 22:39:55 +0200 Subject: [PATCH] feat: Add Speedlink and NES controllers to the USB controller dialog --- .../se/lantz/gui/gamepad/GamePadDialog.java | 26 ++- .../lantz/gui/gamepad/NesBackgroundPanel.java | 66 ++++++ .../se/lantz/gui/gamepad/NesImagePanel.java | 117 +++++++++++ .../se/lantz/gui/gamepad/NesInfoPanel.java | 103 +++++++++ .../gui/gamepad/NesMappingComponent.java | 196 ++++++++++++++++++ .../se/lantz/gui/gamepad/NesMappingPanel.java | 110 ++++++++++ .../gui/gamepad/SpeedlinkBackgroundPanel.java | 66 ++++++ .../gui/gamepad/SpeedlinkImagePanel.java | 189 +++++++++++++++++ .../lantz/gui/gamepad/SpeedlinkInfoPanel.java | 103 +++++++++ .../gamepad/SpeedlinkMappingComponent.java | 196 ++++++++++++++++++ .../gui/gamepad/SpeedlinkMappingPanel.java | 131 ++++++++++++ .../gui/gamepad/TheGamepadImagePanel.java | 2 +- .../gui/gamepad/USBControllerImagePanel.java | 2 +- src/main/resources/se/lantz/nesController.png | Bin 0 -> 65439 bytes src/main/resources/se/lantz/speedlink.png | Bin 0 -> 39935 bytes 15 files changed, 1303 insertions(+), 4 deletions(-) create mode 100644 src/main/java/se/lantz/gui/gamepad/NesBackgroundPanel.java create mode 100644 src/main/java/se/lantz/gui/gamepad/NesImagePanel.java create mode 100644 src/main/java/se/lantz/gui/gamepad/NesInfoPanel.java create mode 100644 src/main/java/se/lantz/gui/gamepad/NesMappingComponent.java create mode 100644 src/main/java/se/lantz/gui/gamepad/NesMappingPanel.java create mode 100644 src/main/java/se/lantz/gui/gamepad/SpeedlinkBackgroundPanel.java create mode 100644 src/main/java/se/lantz/gui/gamepad/SpeedlinkImagePanel.java create mode 100644 src/main/java/se/lantz/gui/gamepad/SpeedlinkInfoPanel.java create mode 100644 src/main/java/se/lantz/gui/gamepad/SpeedlinkMappingComponent.java create mode 100644 src/main/java/se/lantz/gui/gamepad/SpeedlinkMappingPanel.java create mode 100644 src/main/resources/se/lantz/nesController.png create mode 100644 src/main/resources/se/lantz/speedlink.png diff --git a/src/main/java/se/lantz/gui/gamepad/GamePadDialog.java b/src/main/java/se/lantz/gui/gamepad/GamePadDialog.java index 9df8e6b..5c51af0 100644 --- a/src/main/java/se/lantz/gui/gamepad/GamePadDialog.java +++ b/src/main/java/se/lantz/gui/gamepad/GamePadDialog.java @@ -14,6 +14,8 @@ public class GamePadDialog extends BaseDialog private JTabbedPane tabbedPane; private USBControllerBackgroundPanel usbControlerBackroundPanel; private TheGamepadBackgroundPanel theGamePadBackroundPanel; + private NesBackgroundPanel nesBackroundPanel; + private SpeedlinkBackgroundPanel speedlinkBackgroundPanel; private JoystickModel model; private Dimension dialogSize = new Dimension(660, 810); @@ -22,7 +24,7 @@ public class GamePadDialog extends BaseDialog super(owner); //Create a separate model so that changes can be cancelled this.model = new JoystickModel(model.isPort1()); - setTitle("Edit THEGamepad/USB Controller configuration"); + setTitle("Edit USB Controller configuration"); addContent(getTabbedPane()); this.setPreferredSize(dialogSize); this.setResizable(false); @@ -47,7 +49,25 @@ public class GamePadDialog extends BaseDialog } return theGamePadBackroundPanel; } - + + private NesBackgroundPanel getNesBackroundPanel() + { + if (nesBackroundPanel == null) + { + nesBackroundPanel = new NesBackgroundPanel(model); + } + return nesBackroundPanel; + } + + private SpeedlinkBackgroundPanel getSpeedlinkBackroundPanel() + { + if (speedlinkBackgroundPanel == null) + { + speedlinkBackgroundPanel = new SpeedlinkBackgroundPanel(model); + } + return speedlinkBackgroundPanel; + } + public String getJoyConfigString() { return this.model.getConfigString(); @@ -59,6 +79,8 @@ public class GamePadDialog extends BaseDialog { tabbedPane = new JTabbedPane(); tabbedPane.addTab("THEGamepad", getTheGamepadBackgroundPanel()); + tabbedPane.addTab("Speedlink Comp. Pro", getSpeedlinkBackroundPanel()); + tabbedPane.addTab("NES controller", getNesBackroundPanel()); tabbedPane.addTab("Alternative USB controller", getUSBControllerBackgroundPanel()); } return tabbedPane; diff --git a/src/main/java/se/lantz/gui/gamepad/NesBackgroundPanel.java b/src/main/java/se/lantz/gui/gamepad/NesBackgroundPanel.java new file mode 100644 index 0000000..5cfb059 --- /dev/null +++ b/src/main/java/se/lantz/gui/gamepad/NesBackgroundPanel.java @@ -0,0 +1,66 @@ +package se.lantz.gui.gamepad; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +import javax.swing.JPanel; + +import se.lantz.model.JoystickModel; + +public class NesBackgroundPanel extends JPanel +{ + private NesInfoPanel gamePadInfoPanel; + private NesImagePanel gamePadImagePanel; + private NesMappingPanel gamePadMappingPanel; + private JoystickModel model; + public NesBackgroundPanel(JoystickModel model) { + this.model = model; + GridBagLayout gridBagLayout = new GridBagLayout(); + setLayout(gridBagLayout); + GridBagConstraints gbc_gamePadInfoPanel = new GridBagConstraints(); + gbc_gamePadInfoPanel.gridwidth = 2; + gbc_gamePadInfoPanel.insets = new Insets(0, 0, 5, 0); + gbc_gamePadInfoPanel.anchor = GridBagConstraints.NORTHWEST; + gbc_gamePadInfoPanel.weightx = 1.0; + gbc_gamePadInfoPanel.fill = GridBagConstraints.BOTH; + gbc_gamePadInfoPanel.gridx = 0; + gbc_gamePadInfoPanel.gridy = 0; + add(getGamePadInfoPanel(), gbc_gamePadInfoPanel); + GridBagConstraints gbc_gamePadImagePanel = new GridBagConstraints(); + gbc_gamePadImagePanel.anchor = GridBagConstraints.NORTHWEST; + gbc_gamePadImagePanel.insets = new Insets(0, 0, 5, 10); + gbc_gamePadImagePanel.weightx = 1.0; + gbc_gamePadImagePanel.fill = GridBagConstraints.BOTH; + gbc_gamePadImagePanel.gridx = 1; + gbc_gamePadImagePanel.gridy = 1; + add(getNesImagePanel(), gbc_gamePadImagePanel); + GridBagConstraints gbc_gamePadMappingPanel = new GridBagConstraints(); + gbc_gamePadMappingPanel.insets = new Insets(0, 10, 0, 0); + gbc_gamePadMappingPanel.weighty = 1.0; + gbc_gamePadMappingPanel.weightx = 1.0; + gbc_gamePadMappingPanel.anchor = GridBagConstraints.NORTHWEST; + gbc_gamePadMappingPanel.fill = GridBagConstraints.BOTH; + gbc_gamePadMappingPanel.gridx = 0; + gbc_gamePadMappingPanel.gridy = 1; + add(getNesMappingPanel(), gbc_gamePadMappingPanel); + } + private NesInfoPanel getGamePadInfoPanel() { + if (gamePadInfoPanel == null) { + gamePadInfoPanel = new NesInfoPanel(); + } + return gamePadInfoPanel; + } + private NesImagePanel getNesImagePanel() { + if (gamePadImagePanel == null) { + gamePadImagePanel = new NesImagePanel(); + } + return gamePadImagePanel; + } + private NesMappingPanel getNesMappingPanel() { + if (gamePadMappingPanel == null) { + gamePadMappingPanel = new NesMappingPanel(model, getNesImagePanel()); + } + return gamePadMappingPanel; + } +} diff --git a/src/main/java/se/lantz/gui/gamepad/NesImagePanel.java b/src/main/java/se/lantz/gui/gamepad/NesImagePanel.java new file mode 100644 index 0000000..dfa8564 --- /dev/null +++ b/src/main/java/se/lantz/gui/gamepad/NesImagePanel.java @@ -0,0 +1,117 @@ +package se.lantz.gui.gamepad; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; + +public class NesImagePanel extends JPanel +{ + public enum NesButton + { + UP("Up", Character.toString(0x1f815)), DOWN("Down", Character.toString(0x1f817)), + LEFT("Left", Character.toString(0x1f814)), RIGHT("Right", Character.toString(0x1f816)), A("A", "Left fire"), B("B", "TL"), + START("Start", "B"); + + public final String label; + public final String joyMapping; + + private NesButton(String label, String joyMapping) + { + this.label = label; + this.joyMapping = joyMapping; + } + } + + ImageIcon gamepadImage = new ImageIcon(getClass().getResource("/se/lantz/nesController.png")); + private JLabel imageLabel; + + private NesButton currentButton = null; + + public NesImagePanel() + { + GridBagLayout gridBagLayout = new GridBagLayout(); + setLayout(gridBagLayout); + GridBagConstraints gbc_imageLabel = new GridBagConstraints(); + gbc_imageLabel.insets = new Insets(20, 0, 0, 0); + gbc_imageLabel.weightx = 1.0; + gbc_imageLabel.weighty = 1.0; + gbc_imageLabel.anchor = GridBagConstraints.NORTH; + gbc_imageLabel.gridx = 0; + gbc_imageLabel.gridy = 0; + add(getImageLabel(), gbc_imageLabel); + } + + private JLabel getImageLabel() + { + if (imageLabel == null) + { + imageLabel = new JLabel() + { + + @Override + protected void paintComponent(Graphics g) + { + super.paintComponent(g); + //Draw for currently focused button + drawForButton(g); + } + + }; + imageLabel.setIcon(gamepadImage); + } + return imageLabel; + } + + public void setCurrentButtonAndRepaint(NesButton button) + { + this.currentButton = button; + this.repaint(); + } + + private void drawForButton(Graphics g) + { + if (currentButton == null) + { + return; + } + + Graphics2D graphics2D = (Graphics2D) g; + graphics2D.setStroke(new BasicStroke(3.0f)); + graphics2D.setColor(Color.green); + + switch (currentButton) + { + case UP: + graphics2D.fillRect(51, 78, 22, 20); + break; + case DOWN: + graphics2D.fillRect(51, 118, 22, 20); + break; + case LEFT: + graphics2D.fillRect(32, 98, 22, 20); + break; + case RIGHT: + graphics2D.fillRect(70, 98, 22, 20); + break; + case A: + graphics2D.fillRect(254, 108, 30, 30); + break; + case B: + graphics2D.fillRect(214, 108, 30, 30); + break; + case START: + graphics2D.fillRect(163, 116, 25, 15); + break; + default: + break; + } + } +} diff --git a/src/main/java/se/lantz/gui/gamepad/NesInfoPanel.java b/src/main/java/se/lantz/gui/gamepad/NesInfoPanel.java new file mode 100644 index 0000000..58dbfdf --- /dev/null +++ b/src/main/java/se/lantz/gui/gamepad/NesInfoPanel.java @@ -0,0 +1,103 @@ +package se.lantz.gui.gamepad; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextArea; + +public class NesInfoPanel extends JPanel +{ + private static final String dbControllerString = "030000001008000001e5000010010000,NEXT SNES Controller,lefttrigger:b2,righttrigger:b1,b:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b8,x:b3,y:b0,platform:Linux,"; + + private JLabel infoLabel; + private JTextArea controlerConfTextField; + private JLabel extraButtonsInfoLabel; + private JButton copyButton; + + public NesInfoPanel() + { + setBackground(Color.WHITE); + GridBagLayout gridBagLayout = new GridBagLayout(); + setLayout(gridBagLayout); + GridBagConstraints gbc_infoLabel = new GridBagConstraints(); + gbc_infoLabel.fill = GridBagConstraints.HORIZONTAL; + gbc_infoLabel.weightx = 1.0; + gbc_infoLabel.insets = new Insets(0, 10, 0, 10); + gbc_infoLabel.gridx = 0; + gbc_infoLabel.gridy = 0; + add(getInfoLabel(), gbc_infoLabel); + GridBagConstraints gbc_compImageLabel = new GridBagConstraints(); + gbc_compImageLabel.anchor = GridBagConstraints.NORTHWEST; + gbc_compImageLabel.fill = GridBagConstraints.HORIZONTAL; + gbc_compImageLabel.insets = new Insets(0, 10, 5, 10); + gbc_compImageLabel.weightx = 1.0; + gbc_compImageLabel.gridx = 0; + gbc_compImageLabel.gridy = 1; + add(getCompImageLabel(), gbc_compImageLabel); + GridBagConstraints gbc_copyButton = new GridBagConstraints(); + gbc_copyButton.weighty = 1.0; + gbc_copyButton.anchor = GridBagConstraints.NORTHEAST; + gbc_copyButton.insets = new Insets(0, 5, 5, 5); + gbc_copyButton.gridx = 0; + gbc_copyButton.gridy = 2; + add(getCopyButton(), gbc_copyButton); + GridBagConstraints gbc_extraButtonsInfoLabel = new GridBagConstraints(); + gbc_extraButtonsInfoLabel.insets = new Insets(0, 10, 10, 10); + gbc_extraButtonsInfoLabel.fill = GridBagConstraints.HORIZONTAL; + gbc_extraButtonsInfoLabel.gridx = 0; + gbc_extraButtonsInfoLabel.gridy = 3; + add(getExtraButtonsInfoLabel(), gbc_extraButtonsInfoLabel); + } + + private JLabel getInfoLabel() + { + if (infoLabel == null) + { + infoLabel = + new JLabel("
Inspired by original consoles that changed gaming history forever, these NES-inspired USB button-bashers work great with TheC64 and TheVIC20.
The following string in gamecontrollerdb.txt maps the buttons below:
");
+ }
+ return infoLabel;
+ }
+
+ private JTextArea getCompImageLabel()
+ {
+ if (controlerConfTextField == null)
+ {
+ controlerConfTextField = new JTextArea();
+ controlerConfTextField.setBackground(Color.WHITE);
+ controlerConfTextField.setEditable(false);
+ controlerConfTextField.setText(dbControllerString);
+ controlerConfTextField.setLineWrap(true);
+ }
+ return controlerConfTextField;
+ }
+
+ private JLabel getExtraButtonsInfoLabel()
+ {
+ if (extraButtonsInfoLabel == null)
+ {
+ extraButtonsInfoLabel =
+ new JLabel("
Below are the functions for THEC64 Joystick shown in parenthesis for comparison.
");
+ }
+ return extraButtonsInfoLabel;
+ }
+ private JButton getCopyButton() {
+ if (copyButton == null) {
+ copyButton = new JButton("Copy to clipboard");
+ copyButton.addActionListener(e -> {
+ StringSelection stringSelection = new StringSelection(dbControllerString);
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ clipboard.setContents(stringSelection, null);
+ });
+ }
+ return copyButton;
+ }
+}
diff --git a/src/main/java/se/lantz/gui/gamepad/NesMappingComponent.java b/src/main/java/se/lantz/gui/gamepad/NesMappingComponent.java
new file mode 100644
index 0000000..6c1c950
--- /dev/null
+++ b/src/main/java/se/lantz/gui/gamepad/NesMappingComponent.java
@@ -0,0 +1,196 @@
+package se.lantz.gui.gamepad;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.KeyboardFocusManager;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.beans.Beans;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import se.lantz.gui.KeySelectionComboBox;
+import se.lantz.gui.gamepad.NesImagePanel.NesButton;
+import se.lantz.model.JoystickModel;
+
+public class NesMappingComponent extends JPanel
+{
+ private JLabel buttonTextLabel;
+ private KeySelectionComboBox keySelectionComboBox;
+ private JLabel joyMapLabel;
+ private NesButton button;
+ private JoystickModel model;
+ private NesImagePanel imagePanel;
+
+ public NesMappingComponent(NesButton button, JoystickModel model, NesImagePanel imagePanel)
+ {
+ this.button = button;
+ this.model = model;
+ this.imagePanel = imagePanel;
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ setLayout(gridBagLayout);
+ GridBagConstraints gbc_buttonTextLabel = new GridBagConstraints();
+ gbc_buttonTextLabel.anchor = GridBagConstraints.WEST;
+ gbc_buttonTextLabel.insets = new Insets(5, 5, 0, 5);
+ gbc_buttonTextLabel.gridx = 0;
+ gbc_buttonTextLabel.gridy = 0;
+ add(getButtonTextLabel(), gbc_buttonTextLabel);
+ GridBagConstraints gbc_keySelectionComboBox = new GridBagConstraints();
+ gbc_keySelectionComboBox.weighty = 1.0;
+ gbc_keySelectionComboBox.gridwidth = 2;
+ gbc_keySelectionComboBox.insets = new Insets(0, 4, 5, 5);
+ gbc_keySelectionComboBox.anchor = GridBagConstraints.NORTHWEST;
+ gbc_keySelectionComboBox.gridx = 0;
+ gbc_keySelectionComboBox.gridy = 1;
+ add(getKeySelectionComboBox(), gbc_keySelectionComboBox);
+ GridBagConstraints gbc_joyMapLabel = new GridBagConstraints();
+ gbc_joyMapLabel.anchor = GridBagConstraints.WEST;
+ gbc_joyMapLabel.weightx = 1.0;
+ gbc_joyMapLabel.insets = new Insets(5, 0, 0, 5);
+ gbc_joyMapLabel.gridx = 1;
+ gbc_joyMapLabel.gridy = 0;
+ add(getJoyMapLabel(), gbc_joyMapLabel);
+
+ if (!Beans.isDesignTime())
+ {
+ model.addPropertyChangeListener((e) -> modelChanged());
+ }
+ }
+
+ private void modelChanged()
+ {
+ switch (button)
+ {
+ case UP:
+ getKeySelectionComboBox().setSelectedCode(model.getUp());
+ break;
+ case DOWN:
+ getKeySelectionComboBox().setSelectedCode(model.getDown());
+ break;
+ case LEFT:
+ getKeySelectionComboBox().setSelectedCode(model.getLeft());
+ break;
+ case RIGHT:
+ getKeySelectionComboBox().setSelectedCode(model.getRight());
+ break;
+ case A:
+ getKeySelectionComboBox().setSelectedCode(model.getLeftFire());
+ break;
+ case B:
+ getKeySelectionComboBox().setSelectedCode(model.getTl());
+ break;
+ case START:
+ getKeySelectionComboBox().setSelectedCode(model.getB());
+ break;
+ default:
+ break;
+ }
+ }
+
+ private JLabel getButtonTextLabel()
+ {
+ if (buttonTextLabel == null)
+ {
+ buttonTextLabel = new JLabel(button.label);
+ }
+ return buttonTextLabel;
+ }
+
+ private KeySelectionComboBox getKeySelectionComboBox()
+ {
+ if (keySelectionComboBox == null)
+ {
+ keySelectionComboBox = new KeySelectionComboBox(model);
+ keySelectionComboBox.addActionListener(e -> {
+ switch (button)
+ {
+ case UP:
+ model.setUp(keySelectionComboBox.getSelectedCode());
+ break;
+ case DOWN:
+ model.setDown(keySelectionComboBox.getSelectedCode());
+ break;
+ case LEFT:
+ model.setLeft(keySelectionComboBox.getSelectedCode());
+ break;
+ case RIGHT:
+ model.setRight(keySelectionComboBox.getSelectedCode());
+ break;
+ case B:
+ model.setTl(keySelectionComboBox.getSelectedCode());
+ break;
+ case A:
+ model.setLeftFire(keySelectionComboBox.getSelectedCode());
+ break;
+ case START:
+ model.setB(keySelectionComboBox.getSelectedCode());
+ break;
+
+ default:
+ break;
+ }
+ });
+ keySelectionComboBox.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseExited(MouseEvent e)
+ {
+ if (!keySelectionComboBox.hasFocus())
+ {
+ Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
+ if (focusOwner instanceof KeySelectionComboBox)
+ {
+ NesMappingComponent focusedMappingComponent =
+ (NesMappingComponent) SwingUtilities.getAncestorOfClass(NesMappingComponent.class, focusOwner);
+ if (focusedMappingComponent != null)
+ {
+ imagePanel.setCurrentButtonAndRepaint(focusedMappingComponent.button);
+ }
+ }
+ else
+ {
+ imagePanel.setCurrentButtonAndRepaint(null);
+ }
+ }
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent me)
+ {
+ imagePanel.setCurrentButtonAndRepaint(button);
+ }
+ });
+ keySelectionComboBox.addFocusListener(new FocusAdapter()
+ {
+ @Override
+ public void focusGained(FocusEvent e)
+ {
+ imagePanel.setCurrentButtonAndRepaint(button);
+ }
+
+ @Override
+ public void focusLost(FocusEvent e)
+ {
+ imagePanel.setCurrentButtonAndRepaint(null);
+ }
+ });
+ }
+ return keySelectionComboBox;
+ }
+
+ private JLabel getJoyMapLabel()
+ {
+ if (joyMapLabel == null)
+ {
+ joyMapLabel = new JLabel("(" + button.joyMapping + ")");
+ }
+ return joyMapLabel;
+ }
+
+}
diff --git a/src/main/java/se/lantz/gui/gamepad/NesMappingPanel.java b/src/main/java/se/lantz/gui/gamepad/NesMappingPanel.java
new file mode 100644
index 0000000..4e2abd1
--- /dev/null
+++ b/src/main/java/se/lantz/gui/gamepad/NesMappingPanel.java
@@ -0,0 +1,110 @@
+package se.lantz.gui.gamepad;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JPanel;
+
+import se.lantz.gui.gamepad.NesImagePanel.NesButton;
+import se.lantz.model.JoystickModel;
+
+public class NesMappingPanel extends JPanel
+{
+ private NesMappingComponent upComponent;
+ private JoystickModel model;
+ private NesMappingComponent downComponent;
+ private NesMappingComponent leftComponent;
+ private NesMappingComponent rightComponent;
+ private NesMappingComponent xComponent;
+ private NesMappingComponent aComponent;
+ private NesMappingComponent bComponent;
+ private NesImagePanel imagePanel;
+
+ public NesMappingPanel(JoystickModel model, NesImagePanel imagePanel)
+ {
+ this.model = model;
+ this.imagePanel = imagePanel;
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0};
+ gridBagLayout.columnWeights = new double[]{1.0, 1.0};
+ setLayout(gridBagLayout);
+ GridBagConstraints gbc_upComponent = new GridBagConstraints();
+ gbc_upComponent.fill = GridBagConstraints.BOTH;
+ gbc_upComponent.gridx = 0;
+ gbc_upComponent.gridy = 0;
+ add(getUpComponent(), gbc_upComponent);
+ GridBagConstraints gbc_downgComponent = new GridBagConstraints();
+ gbc_downgComponent.fill = GridBagConstraints.BOTH;
+ gbc_downgComponent.gridx = 0;
+ gbc_downgComponent.gridy = 1;
+ add(getDowngComponent(), gbc_downgComponent);
+ GridBagConstraints gbc_leftComponent = new GridBagConstraints();
+ gbc_leftComponent.fill = GridBagConstraints.BOTH;
+ gbc_leftComponent.gridx = 0;
+ gbc_leftComponent.gridy = 2;
+ add(getMappingComponent_2(), gbc_leftComponent);
+ GridBagConstraints gbc_rightComponent = new GridBagConstraints();
+ gbc_rightComponent.weighty = 1.0;
+ gbc_rightComponent.fill = GridBagConstraints.BOTH;
+ gbc_rightComponent.gridx = 0;
+ gbc_rightComponent.gridy = 3;
+ add(getRightComponent(), gbc_rightComponent);
+ GridBagConstraints gbc_xComponent = new GridBagConstraints();
+ gbc_xComponent.fill = GridBagConstraints.BOTH;
+ gbc_xComponent.gridx = 1;
+ gbc_xComponent.gridy = 2;
+ add(getXComponent(), gbc_xComponent);
+ GridBagConstraints gbc_aComponent = new GridBagConstraints();
+ gbc_aComponent.fill = GridBagConstraints.BOTH;
+ gbc_aComponent.gridx = 1;
+ gbc_aComponent.gridy = 0;
+ add(getAComponent(), gbc_aComponent);
+ GridBagConstraints gbc_bComponent = new GridBagConstraints();
+ gbc_bComponent.fill = GridBagConstraints.BOTH;
+ gbc_bComponent.gridx = 1;
+ gbc_bComponent.gridy = 1;
+ add(getBComponent(), gbc_bComponent);
+ }
+ private NesMappingComponent getUpComponent() {
+ if (upComponent == null) {
+ upComponent = new NesMappingComponent(NesButton.UP, model, imagePanel);
+ }
+ return upComponent;
+ }
+ private NesMappingComponent getDowngComponent() {
+ if (downComponent == null) {
+ downComponent = new NesMappingComponent(NesButton.DOWN, model, imagePanel);
+ }
+ return downComponent;
+ }
+ private NesMappingComponent getMappingComponent_2() {
+ if (leftComponent == null) {
+ leftComponent = new NesMappingComponent(NesButton.LEFT, model, imagePanel);
+ }
+ return leftComponent;
+ }
+ private NesMappingComponent getRightComponent() {
+ if (rightComponent == null) {
+ rightComponent = new NesMappingComponent(NesButton.RIGHT, model, imagePanel);
+ }
+ return rightComponent;
+ }
+ private NesMappingComponent getXComponent() {
+ if (xComponent == null) {
+ xComponent = new NesMappingComponent(NesButton.START, model, imagePanel);
+ }
+ return xComponent;
+ }
+ private NesMappingComponent getAComponent() {
+ if (aComponent == null) {
+ aComponent = new NesMappingComponent(NesButton.A, model, imagePanel);
+ }
+ return aComponent;
+ }
+ private NesMappingComponent getBComponent() {
+ if (bComponent == null) {
+ bComponent = new NesMappingComponent(NesButton.B, model, imagePanel);
+ }
+ return bComponent;
+ }
+}
diff --git a/src/main/java/se/lantz/gui/gamepad/SpeedlinkBackgroundPanel.java b/src/main/java/se/lantz/gui/gamepad/SpeedlinkBackgroundPanel.java
new file mode 100644
index 0000000..19ffe02
--- /dev/null
+++ b/src/main/java/se/lantz/gui/gamepad/SpeedlinkBackgroundPanel.java
@@ -0,0 +1,66 @@
+package se.lantz.gui.gamepad;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JPanel;
+
+import se.lantz.model.JoystickModel;
+
+public class SpeedlinkBackgroundPanel extends JPanel
+{
+ private SpeedlinkInfoPanel gamePadInfoPanel;
+ private SpeedlinkImagePanel gamePadImagePanel;
+ private SpeedlinkMappingPanel gamePadMappingPanel;
+ private JoystickModel model;
+ public SpeedlinkBackgroundPanel(JoystickModel model) {
+ this.model = model;
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ setLayout(gridBagLayout);
+ GridBagConstraints gbc_gamePadInfoPanel = new GridBagConstraints();
+ gbc_gamePadInfoPanel.gridwidth = 2;
+ gbc_gamePadInfoPanel.insets = new Insets(0, 0, 5, 0);
+ gbc_gamePadInfoPanel.anchor = GridBagConstraints.NORTHWEST;
+ gbc_gamePadInfoPanel.weightx = 1.0;
+ gbc_gamePadInfoPanel.fill = GridBagConstraints.BOTH;
+ gbc_gamePadInfoPanel.gridx = 0;
+ gbc_gamePadInfoPanel.gridy = 0;
+ add(getGamePadInfoPanel(), gbc_gamePadInfoPanel);
+ GridBagConstraints gbc_gamePadImagePanel = new GridBagConstraints();
+ gbc_gamePadImagePanel.anchor = GridBagConstraints.NORTHWEST;
+ gbc_gamePadImagePanel.insets = new Insets(0, 0, 5, 10);
+ gbc_gamePadImagePanel.weightx = 1.0;
+ gbc_gamePadImagePanel.fill = GridBagConstraints.BOTH;
+ gbc_gamePadImagePanel.gridx = 1;
+ gbc_gamePadImagePanel.gridy = 1;
+ add(getSpeedlinkImagePanel(), gbc_gamePadImagePanel);
+ GridBagConstraints gbc_gamePadMappingPanel = new GridBagConstraints();
+ gbc_gamePadMappingPanel.insets = new Insets(0, 10, 0, 0);
+ gbc_gamePadMappingPanel.weighty = 1.0;
+ gbc_gamePadMappingPanel.weightx = 1.0;
+ gbc_gamePadMappingPanel.anchor = GridBagConstraints.NORTHWEST;
+ gbc_gamePadMappingPanel.fill = GridBagConstraints.BOTH;
+ gbc_gamePadMappingPanel.gridx = 0;
+ gbc_gamePadMappingPanel.gridy = 1;
+ add(getSpeedlinkMappingPanel(), gbc_gamePadMappingPanel);
+ }
+ private SpeedlinkInfoPanel getGamePadInfoPanel() {
+ if (gamePadInfoPanel == null) {
+ gamePadInfoPanel = new SpeedlinkInfoPanel();
+ }
+ return gamePadInfoPanel;
+ }
+ private SpeedlinkImagePanel getSpeedlinkImagePanel() {
+ if (gamePadImagePanel == null) {
+ gamePadImagePanel = new SpeedlinkImagePanel();
+ }
+ return gamePadImagePanel;
+ }
+ private SpeedlinkMappingPanel getSpeedlinkMappingPanel() {
+ if (gamePadMappingPanel == null) {
+ gamePadMappingPanel = new SpeedlinkMappingPanel(model, getSpeedlinkImagePanel());
+ }
+ return gamePadMappingPanel;
+ }
+}
diff --git a/src/main/java/se/lantz/gui/gamepad/SpeedlinkImagePanel.java b/src/main/java/se/lantz/gui/gamepad/SpeedlinkImagePanel.java
new file mode 100644
index 0000000..7adabea
--- /dev/null
+++ b/src/main/java/se/lantz/gui/gamepad/SpeedlinkImagePanel.java
@@ -0,0 +1,189 @@
+package se.lantz.gui.gamepad;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Polygon;
+import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+public class SpeedlinkImagePanel extends JPanel
+{
+ public enum SpeedlinkButton
+ {
+ UP("Up", Character.toString(0x1f815)), DOWN("Down", Character.toString(0x1f817)),
+ LEFT("Left", Character.toString(0x1f814)), RIGHT("Right", Character.toString(0x1f816)), LEFT_FIRE("Left fire", "Left fire"),
+ RIGHT_FIRE("Right Fire", "A"), LT("Left triangle", "B");
+
+ public final String label;
+ public final String joyMapping;
+
+ private SpeedlinkButton(String label, String joyMapping)
+ {
+ this.label = label;
+ this.joyMapping = joyMapping;
+ }
+ }
+
+ ImageIcon gamepadImage = new ImageIcon(getClass().getResource("/se/lantz/speedlink.png"));
+ private JLabel imageLabel;
+
+ private SpeedlinkButton currentButton = null;
+
+ public SpeedlinkImagePanel()
+ {
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ setLayout(gridBagLayout);
+ GridBagConstraints gbc_imageLabel = new GridBagConstraints();
+ gbc_imageLabel.insets = new Insets(20, 0, 0, 0);
+ gbc_imageLabel.weightx = 1.0;
+ gbc_imageLabel.weighty = 1.0;
+ gbc_imageLabel.anchor = GridBagConstraints.NORTH;
+ gbc_imageLabel.gridx = 0;
+ gbc_imageLabel.gridy = 0;
+ add(getImageLabel(), gbc_imageLabel);
+ }
+
+ private JLabel getImageLabel()
+ {
+ if (imageLabel == null)
+ {
+ imageLabel = new JLabel()
+ {
+
+ @Override
+ protected void paintComponent(Graphics g)
+ {
+ super.paintComponent(g);
+ //Draw for currently focused button
+ drawForButton(g);
+ }
+
+ };
+ imageLabel.setIcon(gamepadImage);
+ }
+ return imageLabel;
+ }
+
+ public void setCurrentButtonAndRepaint(SpeedlinkButton button)
+ {
+ this.currentButton = button;
+ this.repaint();
+ }
+
+ private void drawForButton(Graphics g)
+ {
+ if (currentButton == null)
+ {
+ return;
+ }
+
+ Graphics2D graphics2D = (Graphics2D) g;
+ graphics2D.setStroke(new BasicStroke(3.0f));
+ graphics2D.setColor(Color.green);
+
+ switch (currentButton)
+ {
+ case UP:
+ drawArrow(graphics2D,
+ new Point2D.Double(77, 50),
+ new Point2D.Double(77, 5),
+ new BasicStroke(3.0f),
+ new BasicStroke(1.0f),
+ 25f);
+ break;
+ case DOWN:
+ drawArrow(graphics2D,
+ new Point2D.Double(77, 5),
+ new Point2D.Double(77, 50),
+ new BasicStroke(3.0f),
+ new BasicStroke(1.0f),
+ 25f);
+ break;
+ case LEFT:
+ drawArrow(graphics2D,
+ new Point2D.Double(100, 25),
+ new Point2D.Double(55, 25),
+ new BasicStroke(3.0f),
+ new BasicStroke(1.0f),
+ 25f);
+ break;
+ case RIGHT:
+ drawArrow(graphics2D,
+ new Point2D.Double(55, 25),
+ new Point2D.Double(100, 25),
+ new BasicStroke(3.0f),
+ new BasicStroke(1.0f),
+ 25f);
+ break;
+ case LEFT_FIRE:
+ graphics2D.fillOval(18, 82, 35, 17);
+ break;
+ case RIGHT_FIRE:
+ graphics2D.fillOval(97, 82, 35, 17);
+ break;
+ case LT:
+ graphics2D.fillRect(30, 100, 15, 10);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void drawArrow(final Graphics2D gfx,
+ final Point2D start,
+ final Point2D end,
+ final Stroke lineStroke,
+ final Stroke arrowStroke,
+ final float arrowSize)
+ {
+
+ final double startx = start.getX();
+ final double starty = start.getY();
+
+ gfx.setStroke(arrowStroke);
+ final double deltax = startx - end.getX();
+ final double result;
+ if (deltax == 0.0d)
+ {
+ result = starty < end.getY() ? -(Math.PI / 2) : (Math.PI / 2);
+ }
+ else
+ {
+ result = Math.atan((starty - end.getY()) / deltax) + (startx < end.getX() ? Math.PI : 0);
+ }
+
+ final double angle = result;
+
+ final double arrowAngle = Math.PI / 12.0d;
+
+ final double x1 = arrowSize * Math.cos(angle - arrowAngle);
+ final double y1 = arrowSize * Math.sin(angle - arrowAngle);
+ final double x2 = arrowSize * Math.cos(angle + arrowAngle);
+ final double y2 = arrowSize * Math.sin(angle + arrowAngle);
+
+ final double cx = (arrowSize / 2.0f) * Math.cos(angle);
+ final double cy = (arrowSize / 2.0f) * Math.sin(angle);
+
+ final GeneralPath polygon = new GeneralPath();
+ polygon.moveTo(end.getX(), end.getY());
+ polygon.lineTo(end.getX() + x1, end.getY() + y1);
+ polygon.lineTo(end.getX() + x2, end.getY() + y2);
+ polygon.closePath();
+ gfx.fill(polygon);
+
+ gfx.setStroke(lineStroke);
+ gfx.drawLine((int) startx, (int) starty, (int) (end.getX() + cx), (int) (end.getY() + cy));
+ }
+}
diff --git a/src/main/java/se/lantz/gui/gamepad/SpeedlinkInfoPanel.java b/src/main/java/se/lantz/gui/gamepad/SpeedlinkInfoPanel.java
new file mode 100644
index 0000000..0487708
--- /dev/null
+++ b/src/main/java/se/lantz/gui/gamepad/SpeedlinkInfoPanel.java
@@ -0,0 +1,103 @@
+package se.lantz.gui.gamepad;
+
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+
+public class SpeedlinkInfoPanel extends JPanel
+{
+ private static final String dbControllerString = "03000000790000001c18000011010000,SPEEDLINK COMPETITION PRO Game Controller for Android,a:b0,b:b4,lefttrigger:b3,leftx:a0,lefty:a1,start:b1,platform:Linux,";
+
+ private JLabel infoLabel;
+ private JTextArea controlerConfTextField;
+ private JLabel extraButtonsInfoLabel;
+ private JButton copyButton;
+
+ public SpeedlinkInfoPanel()
+ {
+ setBackground(Color.WHITE);
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ setLayout(gridBagLayout);
+ GridBagConstraints gbc_infoLabel = new GridBagConstraints();
+ gbc_infoLabel.fill = GridBagConstraints.HORIZONTAL;
+ gbc_infoLabel.weightx = 1.0;
+ gbc_infoLabel.insets = new Insets(0, 10, 0, 10);
+ gbc_infoLabel.gridx = 0;
+ gbc_infoLabel.gridy = 0;
+ add(getInfoLabel(), gbc_infoLabel);
+ GridBagConstraints gbc_compImageLabel = new GridBagConstraints();
+ gbc_compImageLabel.anchor = GridBagConstraints.NORTHWEST;
+ gbc_compImageLabel.fill = GridBagConstraints.HORIZONTAL;
+ gbc_compImageLabel.insets = new Insets(0, 10, 5, 10);
+ gbc_compImageLabel.weightx = 1.0;
+ gbc_compImageLabel.gridx = 0;
+ gbc_compImageLabel.gridy = 1;
+ add(getCompImageLabel(), gbc_compImageLabel);
+ GridBagConstraints gbc_copyButton = new GridBagConstraints();
+ gbc_copyButton.weighty = 1.0;
+ gbc_copyButton.anchor = GridBagConstraints.NORTHEAST;
+ gbc_copyButton.insets = new Insets(0, 5, 5, 5);
+ gbc_copyButton.gridx = 0;
+ gbc_copyButton.gridy = 2;
+ add(getCopyButton(), gbc_copyButton);
+ GridBagConstraints gbc_extraButtonsInfoLabel = new GridBagConstraints();
+ gbc_extraButtonsInfoLabel.insets = new Insets(0, 10, 10, 10);
+ gbc_extraButtonsInfoLabel.fill = GridBagConstraints.HORIZONTAL;
+ gbc_extraButtonsInfoLabel.gridx = 0;
+ gbc_extraButtonsInfoLabel.gridy = 3;
+ add(getExtraButtonsInfoLabel(), gbc_extraButtonsInfoLabel);
+ }
+
+ private JLabel getInfoLabel()
+ {
+ if (infoLabel == null)
+ {
+ infoLabel =
+ new JLabel("
The COMPETITION PRO EXTRA USB joystick is an ode to nostalgic computer games. Its design with its unmistakable arcade machine stick and technology – such as the iconic micro switches with their loud click – is a throwback to the original COMPETITION PRO from the 80s, the famously popular joystick for home computers.
The following string in gamecontrollerdb.txt maps the buttons below: w3l3YuW4p+M4V_UCoh{`+*ATm4P_tQIT3V#pi$&oDh0=i;i3LzfzD0BlWdGvD
ziwx%!!3E*61JM-v5iB0BN~N^w3
");
+ }
+ return infoLabel;
+ }
+
+ private JTextArea getCompImageLabel()
+ {
+ if (controlerConfTextField == null)
+ {
+ controlerConfTextField = new JTextArea();
+ controlerConfTextField.setBackground(Color.WHITE);
+ controlerConfTextField.setEditable(false);
+ controlerConfTextField.setText(dbControllerString);
+ controlerConfTextField.setLineWrap(true);
+ }
+ return controlerConfTextField;
+ }
+
+ private JLabel getExtraButtonsInfoLabel()
+ {
+ if (extraButtonsInfoLabel == null)
+ {
+ extraButtonsInfoLabel =
+ new JLabel("
Below are the functions for THEC64 Joystick shown in parenthesis for comparison.
");
+ }
+ return extraButtonsInfoLabel;
+ }
+ private JButton getCopyButton() {
+ if (copyButton == null) {
+ copyButton = new JButton("Copy to clipboard");
+ copyButton.addActionListener(e -> {
+ StringSelection stringSelection = new StringSelection(dbControllerString);
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ clipboard.setContents(stringSelection, null);
+ });
+ }
+ return copyButton;
+ }
+}
diff --git a/src/main/java/se/lantz/gui/gamepad/SpeedlinkMappingComponent.java b/src/main/java/se/lantz/gui/gamepad/SpeedlinkMappingComponent.java
new file mode 100644
index 0000000..8887a91
--- /dev/null
+++ b/src/main/java/se/lantz/gui/gamepad/SpeedlinkMappingComponent.java
@@ -0,0 +1,196 @@
+package se.lantz.gui.gamepad;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.KeyboardFocusManager;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.beans.Beans;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import se.lantz.gui.KeySelectionComboBox;
+import se.lantz.gui.gamepad.SpeedlinkImagePanel.SpeedlinkButton;
+import se.lantz.model.JoystickModel;
+
+public class SpeedlinkMappingComponent extends JPanel
+{
+ private JLabel buttonTextLabel;
+ private KeySelectionComboBox keySelectionComboBox;
+ private JLabel joyMapLabel;
+ private SpeedlinkButton button;
+ private JoystickModel model;
+ private SpeedlinkImagePanel imagePanel;
+
+ public SpeedlinkMappingComponent(SpeedlinkButton button, JoystickModel model, SpeedlinkImagePanel imagePanel)
+ {
+ this.button = button;
+ this.model = model;
+ this.imagePanel = imagePanel;
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ setLayout(gridBagLayout);
+ GridBagConstraints gbc_buttonTextLabel = new GridBagConstraints();
+ gbc_buttonTextLabel.anchor = GridBagConstraints.WEST;
+ gbc_buttonTextLabel.insets = new Insets(5, 5, 0, 5);
+ gbc_buttonTextLabel.gridx = 0;
+ gbc_buttonTextLabel.gridy = 0;
+ add(getButtonTextLabel(), gbc_buttonTextLabel);
+ GridBagConstraints gbc_keySelectionComboBox = new GridBagConstraints();
+ gbc_keySelectionComboBox.weighty = 1.0;
+ gbc_keySelectionComboBox.gridwidth = 2;
+ gbc_keySelectionComboBox.insets = new Insets(0, 4, 5, 5);
+ gbc_keySelectionComboBox.anchor = GridBagConstraints.NORTHWEST;
+ gbc_keySelectionComboBox.gridx = 0;
+ gbc_keySelectionComboBox.gridy = 1;
+ add(getKeySelectionComboBox(), gbc_keySelectionComboBox);
+ GridBagConstraints gbc_joyMapLabel = new GridBagConstraints();
+ gbc_joyMapLabel.anchor = GridBagConstraints.WEST;
+ gbc_joyMapLabel.weightx = 1.0;
+ gbc_joyMapLabel.insets = new Insets(5, 0, 0, 5);
+ gbc_joyMapLabel.gridx = 1;
+ gbc_joyMapLabel.gridy = 0;
+ add(getJoyMapLabel(), gbc_joyMapLabel);
+
+ if (!Beans.isDesignTime())
+ {
+ model.addPropertyChangeListener((e) -> modelChanged());
+ }
+ }
+
+ private void modelChanged()
+ {
+ switch (button)
+ {
+ case UP:
+ getKeySelectionComboBox().setSelectedCode(model.getUp());
+ break;
+ case DOWN:
+ getKeySelectionComboBox().setSelectedCode(model.getDown());
+ break;
+ case LEFT:
+ getKeySelectionComboBox().setSelectedCode(model.getLeft());
+ break;
+ case RIGHT:
+ getKeySelectionComboBox().setSelectedCode(model.getRight());
+ break;
+ case LEFT_FIRE:
+ getKeySelectionComboBox().setSelectedCode(model.getLeftFire());
+ break;
+ case RIGHT_FIRE:
+ getKeySelectionComboBox().setSelectedCode(model.getA());
+ break;
+ case LT:
+ getKeySelectionComboBox().setSelectedCode(model.getB());
+ break;
+ default:
+ break;
+ }
+ }
+
+ private JLabel getButtonTextLabel()
+ {
+ if (buttonTextLabel == null)
+ {
+ buttonTextLabel = new JLabel(button.label);
+ }
+ return buttonTextLabel;
+ }
+
+ private KeySelectionComboBox getKeySelectionComboBox()
+ {
+ if (keySelectionComboBox == null)
+ {
+ keySelectionComboBox = new KeySelectionComboBox(model);
+ keySelectionComboBox.addActionListener(e -> {
+ switch (button)
+ {
+ case UP:
+ model.setUp(keySelectionComboBox.getSelectedCode());
+ break;
+ case DOWN:
+ model.setDown(keySelectionComboBox.getSelectedCode());
+ break;
+ case LEFT:
+ model.setLeft(keySelectionComboBox.getSelectedCode());
+ break;
+ case RIGHT:
+ model.setRight(keySelectionComboBox.getSelectedCode());
+ break;
+ case RIGHT_FIRE:
+ model.setA(keySelectionComboBox.getSelectedCode());
+ break;
+ case LEFT_FIRE:
+ model.setLeftFire(keySelectionComboBox.getSelectedCode());
+ break;
+ case LT:
+ model.setB(keySelectionComboBox.getSelectedCode());
+ break;
+
+ default:
+ break;
+ }
+ });
+ keySelectionComboBox.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseExited(MouseEvent e)
+ {
+ if (!keySelectionComboBox.hasFocus())
+ {
+ Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
+ if (focusOwner instanceof KeySelectionComboBox)
+ {
+ SpeedlinkMappingComponent focusedMappingComponent =
+ (SpeedlinkMappingComponent) SwingUtilities.getAncestorOfClass(SpeedlinkMappingComponent.class, focusOwner);
+ if (focusedMappingComponent != null)
+ {
+ imagePanel.setCurrentButtonAndRepaint(focusedMappingComponent.button);
+ }
+ }
+ else
+ {
+ imagePanel.setCurrentButtonAndRepaint(null);
+ }
+ }
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent me)
+ {
+ imagePanel.setCurrentButtonAndRepaint(button);
+ }
+ });
+ keySelectionComboBox.addFocusListener(new FocusAdapter()
+ {
+ @Override
+ public void focusGained(FocusEvent e)
+ {
+ imagePanel.setCurrentButtonAndRepaint(button);
+ }
+
+ @Override
+ public void focusLost(FocusEvent e)
+ {
+ imagePanel.setCurrentButtonAndRepaint(null);
+ }
+ });
+ }
+ return keySelectionComboBox;
+ }
+
+ private JLabel getJoyMapLabel()
+ {
+ if (joyMapLabel == null)
+ {
+ joyMapLabel = new JLabel("(" + button.joyMapping + ")");
+ }
+ return joyMapLabel;
+ }
+
+}
diff --git a/src/main/java/se/lantz/gui/gamepad/SpeedlinkMappingPanel.java b/src/main/java/se/lantz/gui/gamepad/SpeedlinkMappingPanel.java
new file mode 100644
index 0000000..a46185a
--- /dev/null
+++ b/src/main/java/se/lantz/gui/gamepad/SpeedlinkMappingPanel.java
@@ -0,0 +1,131 @@
+package se.lantz.gui.gamepad;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JPanel;
+
+import se.lantz.gui.gamepad.SpeedlinkImagePanel.SpeedlinkButton;
+import se.lantz.model.JoystickModel;
+
+public class SpeedlinkMappingPanel extends JPanel
+{
+ private SpeedlinkMappingComponent upComponent;
+ private JoystickModel model;
+ private SpeedlinkMappingComponent downComponent;
+ private SpeedlinkMappingComponent leftComponent;
+ private SpeedlinkMappingComponent rightComponent;
+ private SpeedlinkMappingComponent xComponent;
+ private SpeedlinkMappingComponent aComponent;
+ private SpeedlinkMappingComponent bComponent;
+ private SpeedlinkImagePanel imagePanel;
+
+ public SpeedlinkMappingPanel(JoystickModel model, SpeedlinkImagePanel imagePanel)
+ {
+ this.model = model;
+ this.imagePanel = imagePanel;
+ GridBagLayout gridBagLayout = new GridBagLayout();
+ gridBagLayout.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0 };
+ gridBagLayout.columnWeights = new double[] { 1.0, 1.0 };
+ setLayout(gridBagLayout);
+ GridBagConstraints gbc_upComponent = new GridBagConstraints();
+ gbc_upComponent.fill = GridBagConstraints.BOTH;
+ gbc_upComponent.gridx = 0;
+ gbc_upComponent.gridy = 0;
+ add(getUpComponent(), gbc_upComponent);
+ GridBagConstraints gbc_downgComponent = new GridBagConstraints();
+ gbc_downgComponent.fill = GridBagConstraints.BOTH;
+ gbc_downgComponent.gridx = 0;
+ gbc_downgComponent.gridy = 1;
+ add(getDowngComponent(), gbc_downgComponent);
+ GridBagConstraints gbc_leftComponent = new GridBagConstraints();
+ gbc_leftComponent.fill = GridBagConstraints.BOTH;
+ gbc_leftComponent.gridx = 0;
+ gbc_leftComponent.gridy = 2;
+ add(getMappingComponent_2(), gbc_leftComponent);
+ GridBagConstraints gbc_rightComponent = new GridBagConstraints();
+ gbc_rightComponent.weighty = 1.0;
+ gbc_rightComponent.fill = GridBagConstraints.BOTH;
+ gbc_rightComponent.gridx = 0;
+ gbc_rightComponent.gridy = 3;
+ add(getRightComponent(), gbc_rightComponent);
+ GridBagConstraints gbc_xComponent = new GridBagConstraints();
+ gbc_xComponent.fill = GridBagConstraints.BOTH;
+ gbc_xComponent.gridx = 1;
+ gbc_xComponent.gridy = 2;
+ add(getXComponent(), gbc_xComponent);
+ GridBagConstraints gbc_aComponent = new GridBagConstraints();
+ gbc_aComponent.fill = GridBagConstraints.BOTH;
+ gbc_aComponent.gridx = 1;
+ gbc_aComponent.gridy = 0;
+ add(getAComponent(), gbc_aComponent);
+ GridBagConstraints gbc_bComponent = new GridBagConstraints();
+ gbc_bComponent.fill = GridBagConstraints.BOTH;
+ gbc_bComponent.gridx = 1;
+ gbc_bComponent.gridy = 1;
+ add(getBComponent(), gbc_bComponent);
+ }
+
+ private SpeedlinkMappingComponent getUpComponent()
+ {
+ if (upComponent == null)
+ {
+ upComponent = new SpeedlinkMappingComponent(SpeedlinkButton.UP, model, imagePanel);
+ }
+ return upComponent;
+ }
+
+ private SpeedlinkMappingComponent getDowngComponent()
+ {
+ if (downComponent == null)
+ {
+ downComponent = new SpeedlinkMappingComponent(SpeedlinkButton.DOWN, model, imagePanel);
+ }
+ return downComponent;
+ }
+
+ private SpeedlinkMappingComponent getMappingComponent_2()
+ {
+ if (leftComponent == null)
+ {
+ leftComponent = new SpeedlinkMappingComponent(SpeedlinkButton.LEFT, model, imagePanel);
+ }
+ return leftComponent;
+ }
+
+ private SpeedlinkMappingComponent getRightComponent()
+ {
+ if (rightComponent == null)
+ {
+ rightComponent = new SpeedlinkMappingComponent(SpeedlinkButton.RIGHT, model, imagePanel);
+ }
+ return rightComponent;
+ }
+
+ private SpeedlinkMappingComponent getXComponent()
+ {
+ if (xComponent == null)
+ {
+ xComponent = new SpeedlinkMappingComponent(SpeedlinkButton.LT, model, imagePanel);
+ }
+ return xComponent;
+ }
+
+ private SpeedlinkMappingComponent getAComponent()
+ {
+ if (aComponent == null)
+ {
+ aComponent = new SpeedlinkMappingComponent(SpeedlinkButton.LEFT_FIRE, model, imagePanel);
+ }
+ return aComponent;
+ }
+
+ private SpeedlinkMappingComponent getBComponent()
+ {
+ if (bComponent == null)
+ {
+ bComponent = new SpeedlinkMappingComponent(SpeedlinkButton.RIGHT_FIRE, model, imagePanel);
+ }
+ return bComponent;
+ }
+}
diff --git a/src/main/java/se/lantz/gui/gamepad/TheGamepadImagePanel.java b/src/main/java/se/lantz/gui/gamepad/TheGamepadImagePanel.java
index e60b846..9f184ff 100644
--- a/src/main/java/se/lantz/gui/gamepad/TheGamepadImagePanel.java
+++ b/src/main/java/se/lantz/gui/gamepad/TheGamepadImagePanel.java
@@ -85,7 +85,7 @@ public class TheGamepadImagePanel extends JPanel
Graphics2D graphics2D = (Graphics2D) g;
graphics2D.setStroke(new BasicStroke(3.0f));
- graphics2D.setColor(Color.red);
+ graphics2D.setColor(Color.green);
switch (currentButton)
{
diff --git a/src/main/java/se/lantz/gui/gamepad/USBControllerImagePanel.java b/src/main/java/se/lantz/gui/gamepad/USBControllerImagePanel.java
index 0b31547..04c6d7d 100644
--- a/src/main/java/se/lantz/gui/gamepad/USBControllerImagePanel.java
+++ b/src/main/java/se/lantz/gui/gamepad/USBControllerImagePanel.java
@@ -92,7 +92,7 @@ public class USBControllerImagePanel extends JPanel
Graphics2D graphics2D = (Graphics2D) g;
graphics2D.setStroke(new BasicStroke(3.0f));
- graphics2D.setColor(Color.red);
+ graphics2D.setColor(Color.green);
switch (currentButton)
{
diff --git a/src/main/resources/se/lantz/nesController.png b/src/main/resources/se/lantz/nesController.png
new file mode 100644
index 0000000000000000000000000000000000000000..fbf5374634908a4bc92b049992ea71ee13765b51
GIT binary patch
literal 65439
zcmV)#K##wPP)