feat: Add Speedlink and NES controllers to the USB controller dialog

This commit is contained in:
lantzelot-swe 2024-04-22 22:39:55 +02:00
parent 291ed4068f
commit 23c7c923d9
15 changed files with 1303 additions and 4 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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("<html><h3>Nintendo NES USB controller</h3><p>Inspired by original consoles that changed gaming history forever, these NES-inspired USB button-bashers work great with TheC64 and TheVIC20.<p><p>The following string in gamecontrollerdb.txt maps the buttons below:<br><br></html>");
}
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("<html><br>Below are the functions for THEC64 Joystick shown in parenthesis for comparison.<br></html>");
}
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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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("<html><h3>Speedlink Competition Pro Extra</h3><p>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.<p><p>The following string in gamecontrollerdb.txt maps the buttons below:<br><br></html>");
}
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("<html><br>Below are the functions for THEC64 Joystick shown in parenthesis for comparison.<br></html>");
}
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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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)
{

View File

@ -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)
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB