Changed the AccessLevel of the classes in the network package and improved

the MessageBox system. Now it's threadsafe and multiple consumers are
possible.
- Added a message box when connecting fails.
- Change the version of the used purejavahidapi
This commit is contained in:
Maschell 2017-03-31 14:34:09 +02:00
parent 3a0261e3d5
commit ebe03a23c6
18 changed files with 248 additions and 137 deletions

View File

@ -119,7 +119,7 @@
<dependency>
<groupId>com.github.QuarkTheAwesome</groupId>
<artifactId>purejavahidapi</artifactId>
<version>94cdc9b</version>
<version>066842c</version>
</dependency>
</dependencies>
</project>

View File

@ -26,6 +26,7 @@ import javax.swing.SwingUtilities;
import net.ash.HIDToVPADNetworkClient.gui.GuiMain;
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
import net.ash.HIDToVPADNetworkClient.network.NetworkManager;
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
import net.ash.HIDToVPADNetworkClient.util.Settings;
/* Ash's todo list
@ -44,9 +45,13 @@ public class Main {
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GuiMain.createGUI();
GuiMain.getInstance();
}
});
MessageBoxManager.addMessageBoxListener(GuiMain.getInstance());
}
public static void fatal() {

View File

@ -34,6 +34,7 @@ import lombok.Getter;
import net.ash.HIDToVPADNetworkClient.controller.Controller;
import net.ash.HIDToVPADNetworkClient.network.NetworkManager;
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
public class GuiControllerListItem extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
@ -78,7 +79,7 @@ public class GuiControllerListItem extends JPanel implements ActionListener {
private void checkIfDisplayNoConfigMessage() {
if (hasConfigCache == false) {
MessageBox.show(new MessageBox("No configuration for this controller found on the console.", MessageBox.MESSAGE_ERROR));
MessageBoxManager.addMessageBox("No configuration for this controller found on the console.", MessageBox.MESSAGE_ERROR);
}
}

View File

@ -23,34 +23,36 @@ package net.ash.HIDToVPADNetworkClient.gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import lombok.extern.java.Log;
import net.ash.HIDToVPADNetworkClient.Main;
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
import net.ash.HIDToVPADNetworkClient.util.MessageBoxListener;
public class GuiMain extends JPanel {
@Log
public class GuiMain extends JPanel implements MessageBoxListener {
private static final long serialVersionUID = 1L;
private static GuiMain instance;
public static void createGUI() {
private static GuiMain createGUI() {
JFrame frame = new JFrame("HID To VPAD Network Client");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new GuiCloseListener());
instance = new GuiMain();
GuiMain instance = new GuiMain();
JComponent newContentPane = instance;
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
return instance;
}
private GuiControllerList leftControllerList;
@ -70,21 +72,22 @@ public class GuiMain extends JPanel {
Main.fatal();
}
add(rightSideControls, BorderLayout.LINE_END);
int delay = 100;
ActionListener messageBoxPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
MessageBox msg = MessageBox.getNextMessage();
if (msg != null) {
JOptionPane.showMessageDialog(GuiMain.instance(), msg.getMessage(), "HID To VPAD Network Client", msg.getType());
MessageBox.bumpQueue();
}
}
};
new Timer(delay, messageBoxPerformer).start();
}
public static GuiMain instance() {
public synchronized static GuiMain getInstance() {
if (instance == null) {
instance = createGUI();
}
return instance;
}
@Override
public void showMessageBox(MessageBox msg) {
if (msg == null || msg.getMessage() == null) {
log.info("Can't show the message box");
}
String real_title = "HID To VPAD Network Client";
JOptionPane.showMessageDialog(this, msg.getMessage(), real_title, msg.getType());
}
}

View File

@ -45,6 +45,7 @@ import net.ash.HIDToVPADNetworkClient.controller.XInput14Controller;
import net.ash.HIDToVPADNetworkClient.controller.XInputController;
import net.ash.HIDToVPADNetworkClient.exeption.ControllerInitializationFailedException;
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
import net.ash.HIDToVPADNetworkClient.util.PureJavaHidApiManager;
import net.ash.HIDToVPADNetworkClient.util.Settings;
import purejavahidapi.HidDeviceInfo;
@ -149,24 +150,27 @@ public class ControllerManager {
}
private static boolean threwUnsatisfiedLinkError = false;
private static Map<String, ControllerType> detectWindowsControllers() {
Map<String, ControllerType> result = new HashMap<String, ControllerType>();
ControllerType type = ControllerType.XINPUT13;
//Try and catch missing C++ redist
// Try and catch missing C++ redist
try {
XInputDevice.isAvailable();
XInputDevice.isAvailable();
} catch (UnsatisfiedLinkError e) {
if (!threwUnsatisfiedLinkError) {
e.printStackTrace();
log.info("This error can be fixed! Please install the Visual C++ Redistributables:");
log.info("https://www.microsoft.com/en-us/download/details.aspx?id=48145");
log.info("If that doesn't help, create an issue on GitHub.");
MessageBox.show(new MessageBox("There was a problem setting up XInput.\nTo fix this, try installing the Visual C++\nredistributables: https://tinyurl.com/vcredist2015.\n\nOther controller types should still work.", MessageBox.MESSAGE_ERROR));
threwUnsatisfiedLinkError = true;
}
if (!threwUnsatisfiedLinkError) {
e.printStackTrace();
log.info("This error can be fixed! Please install the Visual C++ Redistributables:");
log.info("https://www.microsoft.com/en-us/download/details.aspx?id=48145");
log.info("If that doesn't help, create an issue on GitHub.");
MessageBoxManager.addMessageBox(
"There was a problem setting up XInput.\nTo fix this, try installing the Visual C++\nredistributables: https://tinyurl.com/vcredist2015.\n\nOther controller types should still work.",
MessageBox.MESSAGE_ERROR);
threwUnsatisfiedLinkError = true;
}
}
if (XInputDevice.isAvailable() || XInputDevice14.isAvailable()) {
if (XInputDevice14.isAvailable()) {
type = ControllerType.XINPUT14;

View File

@ -19,16 +19,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
package net.ash.HIDToVPADNetworkClient.network.commands;
package net.ash.HIDToVPADNetworkClient.network;
import lombok.Getter;
import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice;
public class AttachCommand extends DeviceCommand {
class AttachCommand extends DeviceCommand {
@Getter private final short vid;
@Getter private final short pid;
public AttachCommand(int hidHandle, short vid, short pid, NetworkHIDDevice sender) {
protected AttachCommand(int hidHandle, short vid, short pid, NetworkHIDDevice sender) {
super(hidHandle, sender);
this.vid = vid;
this.pid = pid;

View File

@ -19,12 +19,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
package net.ash.HIDToVPADNetworkClient.network.commands;
package net.ash.HIDToVPADNetworkClient.network;
import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice;
public class DetachCommand extends DeviceCommand {
public DetachCommand(int hidHandle, NetworkHIDDevice sender) {
class DetachCommand extends DeviceCommand {
protected DetachCommand(int hidHandle, NetworkHIDDevice sender) {
super(hidHandle, sender);
}

View File

@ -19,13 +19,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
package net.ash.HIDToVPADNetworkClient.network.commands;
package net.ash.HIDToVPADNetworkClient.network;
import lombok.Data;
import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice;
@Data
public abstract class DeviceCommand {
abstract class DeviceCommand {
private final int handle;
private final NetworkHIDDevice sender;
private final Class<? extends DeviceCommand> type;

View File

@ -30,10 +30,6 @@ import java.util.List;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.ash.HIDToVPADNetworkClient.network.commands.AttachCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.DetachCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.DeviceCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.ReadCommand;
import net.ash.HIDToVPADNetworkClient.util.HandleFoundry;
import net.ash.HIDToVPADNetworkClient.util.Settings;
@ -88,7 +84,7 @@ public class NetworkHIDDevice {
}
}
public Collection<? extends DeviceCommand> getCommandList() {
protected Collection<? extends DeviceCommand> getCommandList() {
List<DeviceCommand> commands = new ArrayList<DeviceCommand>();
commands.addAll(getCommands());
DeviceCommand lastRead;

View File

@ -31,11 +31,8 @@ import lombok.Synchronized;
import lombok.extern.java.Log;
import net.ash.HIDToVPADNetworkClient.controller.Controller;
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
import net.ash.HIDToVPADNetworkClient.network.commands.AttachCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.DetachCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.DeviceCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.PingCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.ReadCommand;
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
import net.ash.HIDToVPADNetworkClient.util.Settings;
import net.ash.HIDToVPADNetworkClient.util.Utilities;
@ -97,7 +94,7 @@ public class NetworkManager implements Runnable {
if (isConnected() || tcpClient.isShouldRetry()) sendingCommand(new PingCommand());
}
public void proccessCommands() {
private void proccessCommands() {
List<DeviceCommand> commands = new ArrayList<DeviceCommand>();
commands.addAll(ownCommands); // TODO: Does this need a synchronized
// block? It _should_ be only access from
@ -347,12 +344,14 @@ public class NetworkManager implements Runnable {
result = true;
}
} catch (Exception e) {
log.info("Error while connecting: " + e.getMessage());
String error = "Error while connecting: " + e.getMessage();
log.info(error);
MessageBoxManager.addMessageBox(error, MessageBox.MESSAGE_WARNING);
}
return result;
}
public void addCommand(DeviceCommand command) {
private void addCommand(DeviceCommand command) {
this.ownCommands.add(command);
}

View File

@ -19,16 +19,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
package net.ash.HIDToVPADNetworkClient.network.commands;
package net.ash.HIDToVPADNetworkClient.network;
import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice;
public class PingCommand extends DeviceCommand {
public PingCommand() {
class PingCommand extends DeviceCommand {
protected PingCommand() {
this((short) 0, null);
}
private PingCommand(int hidHandle, NetworkHIDDevice sender) {
protected PingCommand(int hidHandle, NetworkHIDDevice sender) {
super(hidHandle, sender);
}
@ -36,4 +34,4 @@ public class PingCommand extends DeviceCommand {
public String toString() {
return "PingCommand []";
}
}
}

View File

@ -28,51 +28,47 @@ import java.nio.ByteBuffer;
import java.util.List;
import lombok.extern.java.Log;
import net.ash.HIDToVPADNetworkClient.network.commands.AttachCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.DetachCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.PingCommand;
import net.ash.HIDToVPADNetworkClient.network.commands.ReadCommand;
@Log
public class Protocol {
public static final int TCP_PORT = 8112;
public static final int UDP_PORT = 8113;
class Protocol {
protected static final int TCP_PORT = 8112;
protected static final int UDP_PORT = 8113;
public static final byte TCP_HANDSHAKE = 0x12;
public static final byte TCP_SAME_CLIENT = 0x20;
public static final byte TCP_NEW_CLIENT = 0x21;
protected static final byte TCP_HANDSHAKE = 0x12;
protected static final byte TCP_SAME_CLIENT = 0x20;
protected static final byte TCP_NEW_CLIENT = 0x21;
public static final byte TCP_CMD_ATTACH = 0x01;
public static final byte TCP_CMD_DETACH = 0x02;
public static final byte TCP_CMD_PING = (byte) 0xF0;
protected static final byte TCP_CMD_ATTACH = 0x01;
protected static final byte TCP_CMD_DETACH = 0x02;
protected static final byte TCP_CMD_PING = (byte) 0xF0;
public static final byte UDP_CMD_DATA = 0x03;
protected static final byte UDP_CMD_DATA = 0x03;
public static final byte TCP_CMD_ATTACH_CONFIG_FOUND = (byte) 0xE0;
public static final byte TCP_CMD_ATTACH_CONFIG_NOT_FOUND = (byte) 0xE1;
public static final byte TCP_CMD_ATTACH_USERDATA_OKAY = (byte) 0xE8;
public static final byte TCP_CMD_ATTACH_USERDATA_BAD = (byte) 0xE9;
protected static final byte TCP_CMD_ATTACH_CONFIG_FOUND = (byte) 0xE0;
protected static final byte TCP_CMD_ATTACH_CONFIG_NOT_FOUND = (byte) 0xE1;
protected static final byte TCP_CMD_ATTACH_USERDATA_OKAY = (byte) 0xE8;
protected static final byte TCP_CMD_ATTACH_USERDATA_BAD = (byte) 0xE9;
private Protocol() {
}
public enum HandshakeReturnCode {
protected enum HandshakeReturnCode {
GOOD_HANDSHAKE, BAD_HANDSHAKE
}
public static byte[] getRawAttachDataToSend(AttachCommand command) throws IOException {
protected static byte[] getRawAttachDataToSend(AttachCommand command) throws IOException {
return ByteBuffer.allocate(9).put(Protocol.TCP_CMD_ATTACH).putInt(command.getHandle()).putShort(command.getVid()).putShort(command.getPid()).array();
}
public static byte[] getRawDetachDataToSend(DetachCommand command) throws IOException {
protected static byte[] getRawDetachDataToSend(DetachCommand command) throws IOException {
return ByteBuffer.allocate(5).put(Protocol.TCP_CMD_DETACH).putInt(command.getHandle()).array();
}
public static byte[] getRawPingDataToSend(PingCommand command) {
protected static byte[] getRawPingDataToSend(PingCommand command) {
return new byte[] { Protocol.TCP_CMD_PING };
}
public static byte[] getRawReadDataToSend(List<ReadCommand> readCommands) throws IOException {
protected static byte[] getRawReadDataToSend(List<ReadCommand> readCommands) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(Protocol.UDP_CMD_DATA);

View File

@ -19,15 +19,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
package net.ash.HIDToVPADNetworkClient.network.commands;
package net.ash.HIDToVPADNetworkClient.network;
import lombok.Getter;
import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice;
public class ReadCommand extends DeviceCommand {
class ReadCommand extends DeviceCommand {
@Getter private final byte[] data;
public ReadCommand(int hidHandle, byte[] data, NetworkHIDDevice sender) {
protected ReadCommand(int hidHandle, byte[] data, NetworkHIDDevice sender) {
super(hidHandle, sender);
this.data = data;
}

View File

@ -37,7 +37,7 @@ import net.ash.HIDToVPADNetworkClient.network.Protocol.HandshakeReturnCode;
import net.ash.HIDToVPADNetworkClient.util.Settings;
@Log
public class TCPClient {
class TCPClient {
private Socket sock;
private DataInputStream in;
private DataOutputStream out;
@ -46,10 +46,10 @@ public class TCPClient {
private String ip;
public TCPClient() {
protected TCPClient() {
}
public synchronized void connect(String ip) throws Exception {
protected synchronized void connect(String ip) throws Exception {
sock = new Socket();
sock.connect(new InetSocketAddress(ip, Protocol.TCP_PORT), 2000);
in = new DataInputStream(sock.getInputStream());
@ -68,7 +68,7 @@ public class TCPClient {
}
}
public synchronized boolean abort() {
protected synchronized boolean abort() {
try {
shouldRetry = Settings.MAXIMUM_TRIES_FOR_RECONNECTING;
sock.close();
@ -79,7 +79,7 @@ public class TCPClient {
return true;
}
public synchronized void send(byte[] rawCommand) throws IOException {
protected synchronized void send(byte[] rawCommand) throws IOException {
try {
out.write(rawCommand);
out.flush();
@ -98,15 +98,15 @@ public class TCPClient {
}
}
public synchronized void send(int value) throws IOException {
protected synchronized void send(int value) throws IOException {
send(ByteBuffer.allocate(4).putInt(value).array());
}
public synchronized byte recvByte() throws IOException {
protected synchronized byte recvByte() throws IOException {
return in.readByte();
}
public synchronized short recvShort() throws IOException {
protected synchronized short recvShort() throws IOException {
try {
return in.readShort();
} catch (IOException e) {
@ -115,11 +115,11 @@ public class TCPClient {
}
}
public synchronized boolean isConnected() {
protected synchronized boolean isConnected() {
return (sock != null && sock.isConnected() && !sock.isClosed());
}
public boolean isShouldRetry() {
protected boolean isShouldRetry() {
return this.shouldRetry < Settings.MAXIMUM_TRIES_FOR_RECONNECTING;
}
}

View File

@ -28,7 +28,7 @@ import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class UDPClient {
class UDPClient {
private final DatagramSocket sock;
private final InetAddress host;
@ -37,7 +37,7 @@ public class UDPClient {
host = InetAddress.getByName(ip);
}
public static UDPClient createUDPClient(String ip) {
protected static UDPClient createUDPClient(String ip) {
UDPClient result = null;
try {
result = new UDPClient(ip);
@ -47,7 +47,7 @@ public class UDPClient {
return result;
}
public void send(byte[] data) throws IOException {
protected void send(byte[] data) throws IOException {
DatagramPacket packet = new DatagramPacket(data, data.length, host, Protocol.UDP_PORT);
sock.send(packet);
}

View File

@ -1,39 +1,45 @@
package net.ash.HIDToVPADNetworkClient.util;
/*******************************************************************************
* Copyright (c) 2017 Ash (QuarkTheAwesome) & Maschell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
import java.util.ArrayList;
import java.util.List;
package net.ash.HIDToVPADNetworkClient.util;
import javax.swing.JOptionPane;
import lombok.Getter;
public class MessageBox {
public static final int MESSAGE_INFO = JOptionPane.INFORMATION_MESSAGE;
public static final int MESSAGE_WARNING = JOptionPane.WARNING_MESSAGE;
public static final int MESSAGE_ERROR = JOptionPane.ERROR_MESSAGE;
@Getter
private String message;
@Getter
private int type;
public MessageBox(String message, int type) {
this.message = message;
this.type = type;
}
private static List<MessageBox> messageBoxQueue = new ArrayList<MessageBox>();
public static void show(MessageBox box) {
messageBoxQueue.add(box);
}
public static MessageBox getNextMessage() {
if (messageBoxQueue.size() > 0) {
return messageBoxQueue.get(0);
} else return null;
}
public static void bumpQueue() {
if (messageBoxQueue.size() > 0) {
messageBoxQueue.remove(0);
}
}
public static final int MESSAGE_INFO = JOptionPane.INFORMATION_MESSAGE;
public static final int MESSAGE_WARNING = JOptionPane.WARNING_MESSAGE;
public static final int MESSAGE_ERROR = JOptionPane.ERROR_MESSAGE;
@Getter private final String message;
@Getter private final int type;
public MessageBox(String message) {
this(message, MESSAGE_INFO);
}
public MessageBox(String message, int type) {
this.message = message;
this.type = type;
}
}

View File

@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2017 Ash (QuarkTheAwesome) & Maschell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
package net.ash.HIDToVPADNetworkClient.util;
public interface MessageBoxListener {
public void showMessageBox(MessageBox msgBox);
}

View File

@ -0,0 +1,81 @@
/*******************************************************************************
* Copyright (c) 2017 Ash (QuarkTheAwesome) & Maschell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
package net.ash.HIDToVPADNetworkClient.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class MessageBoxManager implements Runnable {
private static final Queue<MessageBox> messageBoxQueue = new ConcurrentLinkedQueue<MessageBox>();
private static List<MessageBoxListener> newList = Collections.synchronizedList(new ArrayList<MessageBoxListener>());
private static Object listenerListLock = new Object();
private static boolean threadStarted = false;
private final static MessageBoxManager instance = new MessageBoxManager();
private MessageBoxManager() {
}
@Override
public void run() {
while (true) {
MessageBox msg = getNextMessage();
if (msg != null) {
synchronized (listenerListLock) {
for (MessageBoxListener m : newList) {
m.showMessageBox(msg);
}
}
}
Utilities.sleep(500);
}
}
public static void addMessageBox(String message) {
addMessageBox(new MessageBox(message));
}
public static void addMessageBox(String message, int type) {
addMessageBox(new MessageBox(message, type));
}
public static void addMessageBox(MessageBox messagebox) {
messageBoxQueue.add(messagebox);
}
private static MessageBox getNextMessage() {
return messageBoxQueue.poll();
}
public static void addMessageBoxListener(MessageBoxListener msglistener) {
if (!threadStarted) {
new Thread(instance).start();
threadStarted = true;
}
newList.add(msglistener);
}
}