package client;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import util.Constants;
import util.Globals;
import network.HostUDPClient;
import network.HostUDPServer;
import network.HostsLocator;
import network.NetworkServer;
import network.StatusManager;
public class Isytok implements ActionListener
{
/** Instancias para el uso del system tray */
private SystemTray systemTray;
private TrayIcon trayIcon;
/** Servicio de escucha */
private NetworkServer listener;
/** Frame, panel, y menu principal de la aplicación para gestion de mensajes */
private JFrame main;
private JPanel panel;
private Menu menu;
private PopupMenu popupMenu;
private ChatFrame mainFrame;
/** Flag que almacena si la plataforma soporta system tray */
private boolean sysTray = true;
/** Imagen de la tray */
private Image iconImage;
/** Instancia de la aplicación */
private Isytok instance;
/**
* Entrada principal a la aplicación
* @param args
*/
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
new Isytok();
}
catch (Exception e) {
System.out.println("Error en run de Isytok: " + e.getMessage());
}
}
});
}
/**
* TODO: Refactory pending...
* @throws Exception
*/
public Isytok() throws Exception
{
// permite system tray la plataforma?
checkSystemTray();
// inicializar red
init();
// iniciar listener de mensajes entrantes
startServer();
// armar menu de la aplicacion
prepareSystemTray();
// mi estado actual deberia ser online
trayIcon.setToolTip("Isytok - Online");
StatusManager.broadCastNewStatus(true);
}
/**
* Valida instancia e incializa hosts
*/
private void init()
{
System.out.println("Initializing...");
HostUDPServer server = new HostUDPServer();
server.start();
HostUDPClient client = new HostUDPClient();
client.start();
// App-singleton
System.out.println("Chequeando instancia de aplicación...");
if (!HostsLocator.isPortAvailable())
{
System.out.println("Ya existe una instancia de Isytok abierta (puerto en uso)... ");
JOptionPane.showMessageDialog(null, "Ya existe una instancia de Isytok abierta (puerto en uso)... ", Constants.APPLICATION_NAME_MSG, JOptionPane.INFORMATION_MESSAGE);
System.exit(-1);
}
System.out.println("OK!");
instance = this;
}
/**
* Iniciar el framework para chat
* @return true si pudo levantar el server, o falso en caso contrario
*/
private void startServer() throws Exception
{
// Iniciar el server
listener = new NetworkServer(Constants.PORT_TCP);
new Thread(listener).start();
// Frame de chat
mainFrame = new ChatFrame(listener, this);
}
/**
* Verifica si puede usarse el systray
* @throws Exception
*/
private void checkSystemTray() throws Exception
{
// Chequear si el SO soporta SystemTray
/** http://www.mail-archive.com/openjdk@lists.launchpad.net/msg01949.html */
/** Fixed, usar AWT_TOOLKIT = XToolkit */
if (!SystemTray.isSupported()) {
System.out.println("Your operating system does not support SystemTray.");
// System.exit(-1);
sysTray = false;
}
else
systemTray = SystemTray.getSystemTray();
}
/**
* Carga las opciones del menu
* @throws Exception
*/
private void prepareSystemTray() throws Exception
{
menu = new Menu();
/* Patch debido a incompatibilidad entre Java y Compiz */
if (!sysTray)
{
main = new JFrame(Constants.APPLICATION_NAME_MSG);
main.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
panel = new JPanel();
popupMenu = menu.createPopupMenu(this);
popupMenu.setActionCommand(Constants.TRAY_ICON_ACTION_COMMAND);
JButton boton = new JButton("MENU");
boton.setPreferredSize(new Dimension(100, 100));
boton.addMouseListener(new MouseListener() {
public void mouseReleased(MouseEvent arg0) { }
public void mousePressed(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void mouseEntered(MouseEvent arg0) {}
public void mouseClicked(MouseEvent arg0) {
popupMenu.show(panel, arg0.getX(), arg0.getY());
}
});
panel.add(popupMenu);
panel.add(boton);
main.setSize(100,100);
main.add(panel);
main.setVisible(true);
main.setResizable(false);
return;
}
// Crear el TrayIcon
iconImage = getIcon();
trayIcon = new TrayIcon(iconImage, Constants.APPLICATION_NAME_MSG, menu.createPopupMenu(this));
// Evento de doble click izquierdo
trayIcon.setActionCommand(Constants.TRAY_ICON_ACTION_COMMAND);
trayIcon.setToolTip(Constants.TRAY_ICON_TOOL_TIP_MSG);
trayIcon.addActionListener(this);
systemTray.add(trayIcon);
}
/**
* Procesa los eventos sobre el tray-icon
*/
public void actionPerformed(ActionEvent aEvt) {
//Nombre del evento
String cmd = aEvt.getActionCommand();
// Acciones a realizar
if (cmd.equals(Constants.TRAY_ICON_ACTION_COMMAND) || cmd.equals(Constants.MENU_ACTION_SEND_TEXT_CMD)) {
mainFrame.toggleViewState(null);
}
else if (cmd.equals(Constants.TRAY_ICON_ACTION_COMMAND) || cmd.equals(Constants.MENU_ACTION_SEND_FAST_TEXT_CMD)) {
mainFrame.toggleViewState(((MenuItem)aEvt.getSource()).getLabel());
}
else if (cmd.equals(Constants.MENU_ACTION_SEND_IMAGE_CMD)) {
ImageFrame.showImage(null);
}
else if (cmd.equals(Constants.MENU_ACTION_SEND_FAST_IMAGE_CMD)) {
ImageFrame.showImage(((MenuItem)aEvt.getSource()).getLabel());
}
else if (cmd.equals(Constants.MENU_ACTION_SET_ONLINE_CMD)) {
trayIcon.setToolTip("Isytok - Online");
StatusManager.broadCastNewStatus(true);
}
else if (cmd.equals(Constants.MENU_ACTION_SET_OFFLINE_CMD)) {
trayIcon.setToolTip("Isytok - Offline");
StatusManager.broadCastNewStatus(false);
}
else if (cmd.equals(Constants.MENU_ACTION_EXIT_APP_CMD)) {
handleApplicationFinalize();
}
}
protected void handleApplicationFinalize()
{
try
{
StatusManager.broadCastNewStatus(false);
Globals.running = false;
// JOptionPane.showMessageDialog(null, Constants.APPLICATION_BYEBYE_MSG, Constants.APPLICATION_NAME_MSG, JOptionPane.INFORMATION_MESSAGE);
Thread.yield(); // darle tiempo a que los threads terminen - TODO: mejorar
Thread.sleep(Constants.STATUS_REFRESH_TIME_MS + Constants.FIRST_REFRESH_TIME_MS);
System.exit(0);
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Realiza la carga del icono
* @return la imagen
* @throws Exception cuando fallan las cosas... :)
*/
public static Image getIcon() throws Exception {
Image icon = null;
ClassLoader loader = Isytok.class.getClassLoader();
InputStream is = loader.getResourceAsStream(Constants.TRAY_LOGO_IMAGE);
icon = ImageIO.read(is);
is.close();
return (icon);
}
public Menu getMenu() {
return menu;
}
}