package com.larocheent.photomouseserver;
import java.awt.EventQueue;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Robot;
import java.awt.Toolkit;
import javax.swing.JButton;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.Hashtable;
import javax.swing.JLabel;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Color;
import javax.swing.JTextArea;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.awt.FlowLayout;
import javax.swing.JTextField;
public class ServerStart {
private JFrame frmPhotoMouse;
private String line;
private StartServer st;
private Dimension dim;
private JButton btnSavePort, btnQuit;
final static String SETTINGS_PANEL = "Settings Panel";
final static String MAIN_PANEL = "Main Panel";
private JTextArea textArea;
private JScrollPane sbrText;
private JLabel qrLabel;
private JPanel panel;
private JTextField txtPort;
private JLabel lblNewLabel;
private SettingsSaver settingsSaver;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ServerStart window = new ServerStart();
window.frmPhotoMouse.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ServerStart() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
settingsSaver = new SettingsSaver();
frmPhotoMouse = new JFrame();
frmPhotoMouse.setResizable(false);
frmPhotoMouse.setTitle("Photo Mouse");
frmPhotoMouse.setBounds(100, 100, 338, 306);
frmPhotoMouse.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel holder_panel = new JPanel();
frmPhotoMouse.getContentPane().add(holder_panel, BorderLayout.CENTER);
holder_panel.setLayout(new CardLayout(0, 0));
@SuppressWarnings("unused")
final CardLayout cardLayout;
cardLayout = (CardLayout) holder_panel.getLayout();
panel = new JPanel();
panel.setBackground(Color.WHITE);
holder_panel.add(panel, MAIN_PANEL);
panel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JLabel picLabel = new JLabel(new ImageIcon(getClass().getResource("server_logo.png")));
picLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add( picLabel );
qrLabel = new JLabel(new ImageIcon(generateQRCode()));
qrLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add( qrLabel );
btnSavePort = new JButton("Save Port");
btnSavePort.setAlignmentX(Component.CENTER_ALIGNMENT);
btnSavePort.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
st.interrupt();
st = new StartServer(Integer.parseInt(txtPort.getText()));
st.start();
settingsSaver.savePortNumber(txtPort.getText());
qrLabel.setIcon(new ImageIcon(generateQRCode()));
}
});
lblNewLabel = new JLabel("Port:");
panel.add(lblNewLabel);
txtPort = new JTextField();
SettingsSaver settingsSaver = new SettingsSaver();
txtPort.setText(settingsSaver.getPortNumber());
txtPort.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent arg0) {
}
@Override
public void keyReleased(KeyEvent keyEvent) {
if(!Character.isDigit(keyEvent.getKeyChar())) {
String input = txtPort.getText();
String corrected = input.substring(0, input.length() - 1);
txtPort.setText(corrected);
}
}
@Override
public void keyTyped(KeyEvent keyEvent) {
}
});
panel.add(txtPort);
txtPort.setColumns(5);
panel.add(btnSavePort);
btnQuit = new JButton("Quit");
btnQuit.setAlignmentX(Component.CENTER_ALIGNMENT);
btnQuit.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
System.exit(0);
}
});
panel.add(btnQuit);
textArea = new JTextArea("Click the Start Server button above.", 10, 5);
textArea.setEditable(false);
textArea.setSize(new Dimension(250, 75));
textArea.setPreferredSize(new Dimension(100, 70));
textArea.setMaximumSize(new Dimension(100, 70));
textArea.setLineWrap(true);
sbrText = new JScrollPane(textArea);
sbrText.setPreferredSize(new Dimension(275, 75));
sbrText.setMaximumSize(new Dimension(275, 75));
sbrText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
panel.add(sbrText);
st = new StartServer(Integer.parseInt(settingsSaver.getPortNumber()));
st.start();
textArea.setText("Waiting for a connection...\n");
dim = Toolkit.getDefaultToolkit().getScreenSize();
}
private String getNetworkInfo() {
InetAddress thisIp = null;
try {
thisIp = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return thisIp.getHostAddress();
}
private BufferedImage generateQRCode() {
Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix byteMatrix = null;
try {
SettingsSaver settingsSaver = new SettingsSaver();
byteMatrix = qrCodeWriter.encode("IP:" + getNetworkInfo() + ",PORT:" + settingsSaver.getPortNumber(), BarcodeFormat.QR_CODE, 150, 150, hintMap);
} catch (WriterException e) {
System.out.println(e);
}
int matrixWidth = byteMatrix.getWidth();
BufferedImage image = new BufferedImage(matrixWidth, matrixWidth, BufferedImage.TYPE_INT_RGB);
image.createGraphics();
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, matrixWidth, matrixWidth);
graphics.setColor(Color.BLACK);
for (int i = 0; i < matrixWidth; i++) {
for (int j = 0; j < matrixWidth; j++) {
if (byteMatrix.get(i, j)) {
graphics.fillRect(i, j, 1, 1);
}
}
}
return image;
}
class StartServer extends Thread {
protected boolean running = true;
private ServerSocket connection = null;
private Thread connectionThread = null;
private int portNumber;
public StartServer(int portNumber) {
this.portNumber = portNumber;
}
public void run() {
try{
connection = new ServerSocket(portNumber);
connection.setPerformancePreferences(1, 0, 0);
textArea.setText("Server started on port: " + portNumber);
} catch (IOException e) {
System.out.println("Could not listen on port " + portNumber);
JOptionPane.showMessageDialog(frmPhotoMouse, "This port is already in use. Please choose a different port number!");
}
while(running){
try {
connectionThread = new ConnectionThread(connection.accept());
connectionThread.start();
} catch (IOException e) {
System.out.println(e);
}
}
connectionThread.interrupt();
try {
connection.close();
} catch (IOException e) {
System.out.println("Could not close ServerSocket");
}
}
public void interrupt() {
this.running = false;
if(connectionThread != null) {
connectionThread.interrupt();
}
Thread.currentThread().interrupt();
super.interrupt();
}
}
class ConnectionThread extends Thread {
protected Socket clientSocket = null;
protected BufferedReader input = null;
protected boolean running = true;
private Robot computerController = null;
private double widthScaleFactor, heightScaleFactor;
public ConnectionThread(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void run() {
try {
computerController = new Robot();
} catch (AWTException e1) {
System.out.println(e1);
}
try {
input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "US-ASCII"), 2028);
while (running == true) {
line = input.readLine();
handleCommand(line);
}
} catch (IOException e) {
System.out.println(e);
}
}
public void interrupt() {
this.running = false;
Thread.currentThread().interrupt();
super.interrupt();
}
private void handleCommand(String command) {
String[] splitString = command.split("=");
String commandType = splitString[0];
if(commandType.contentEquals("Move_Mouse")) {
handleMoveMouse(splitString[1]);
} else if(commandType.contentEquals("Left_Click")) {
handleLeftClick();
} else if(commandType.contentEquals("Right_Click")) {
handleRightClick();
} else if(commandType.contentEquals("Client_Screen_Size")) {
handleScreenSize(splitString[1]);
} else if(commandType.contentEquals("Left_Click_Held")) {
handleLeftClickHeld(splitString[1]);
} else if(commandType.contentEquals("Right_Click_Held")) {
handleRightClickHeld(splitString[1]);
} else if(commandType.contentEquals("Slider_Position")) {
handleSliderChange(splitString[1]);
} else if(commandType.contentEquals("Scale_Up")) {
handleScaleUp();
}
}
private void handleScaleUp() {
computerController.keyPress(KeyEvent.VK_ALT);
computerController.mouseWheel(-1);
computerController.keyRelease(KeyEvent.VK_ALT);
}
private void handleSliderChange(String command) {
if(command.contentEquals("100")) {
computerController.keyPress(KeyEvent.VK_0);
computerController.keyRelease(KeyEvent.VK_0);
} else {
if(command.length() == 1) {
controlOpacity(Integer.parseInt(command.substring(0, 1)));
} else if(command.length() == 2) {
int firstNumber = Integer.parseInt(command.substring(0, 1));
int secondNumber = Integer.parseInt(command.substring(1, 2));
controlOpacity(firstNumber);
controlOpacity(secondNumber);
}
}
}
private void controlOpacity(int level) {
switch(level) {
case 0:
computerController.keyPress(KeyEvent.VK_0);
computerController.keyRelease(KeyEvent.VK_0);
break;
case 1:
computerController.keyPress(KeyEvent.VK_1);
computerController.keyRelease(KeyEvent.VK_1);
break;
case 2:
computerController.keyPress(KeyEvent.VK_2);
computerController.keyRelease(KeyEvent.VK_2);
break;
case 3:
computerController.keyPress(KeyEvent.VK_3);
computerController.keyRelease(KeyEvent.VK_3);
break;
case 4:
computerController.keyPress(KeyEvent.VK_4);
computerController.keyRelease(KeyEvent.VK_4);
break;
case 5:
computerController.keyPress(KeyEvent.VK_5);
computerController.keyRelease(KeyEvent.VK_5);
break;
case 6:
computerController.keyPress(KeyEvent.VK_6);
computerController.keyRelease(KeyEvent.VK_6);
break;
case 7:
computerController.keyPress(KeyEvent.VK_7);
computerController.keyRelease(KeyEvent.VK_7);
break;
case 8:
computerController.keyPress(KeyEvent.VK_8);
computerController.keyRelease(KeyEvent.VK_8);
break;
case 9:
computerController.keyPress(KeyEvent.VK_9);
computerController.keyRelease(KeyEvent.VK_9);
break;
}
}
private void handleLeftClickHeld(String command) {
if(command.contentEquals("true")) {
computerController.mousePress(InputEvent.BUTTON1_MASK);
}
if(command.contentEquals("false")) {
computerController.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
private void handleRightClickHeld(String command) {
if(command.contentEquals("true")) {
computerController.mousePress(InputEvent.BUTTON3_MASK);
}
if(command.contentEquals("false")) {
computerController.mouseRelease(InputEvent.BUTTON3_MASK);
}
}
private void handleScreenSize(String command) {
String[] incomingSplit = command.split(",");
String[] xSplit = incomingSplit[0].split(":");
String[] ySplit = incomingSplit[1].split(":");
System.out.println(xSplit[0]);
double padWidth = Double.parseDouble(xSplit[1]);
double padHeight = Double.parseDouble(ySplit[1]);
double screenWidth = (int)dim.getWidth();
double screenHeight = (int)dim.getHeight();
widthScaleFactor = screenWidth / padWidth;
heightScaleFactor = screenHeight / padHeight;
System.out.println("Computer Width: " + screenWidth + ", Computer Height: " + screenHeight);
System.out.println("Pad Width: " + padWidth + ", Pad Height: " + padHeight);
System.out.println("Scaled Width: " + widthScaleFactor + ", Scaled Height: " + heightScaleFactor);
}
private void handleMoveMouse(String command) {
String[] splitString = command.split(",");
String[] xPortion = splitString[0].split(":");
String[] yPortion = splitString[1].split(":");
int xCord = Integer.parseInt(xPortion[1]);
int yCord = Integer.parseInt(yPortion[1]);
double x = xCord * widthScaleFactor;
double y = yCord * heightScaleFactor;
computerController.mouseMove((int) x, (int) y);
}
private void handleLeftClick() {
computerController.mousePress(InputEvent.BUTTON1_MASK);
computerController.mouseRelease(InputEvent.BUTTON1_MASK);
}
private void handleRightClick() {
computerController.mousePress(InputEvent.BUTTON3_MASK);
computerController.mouseRelease(InputEvent.BUTTON3_MASK);
}
}
}