package client;
import java.awt.BorderLayout;
import java.awt.Dimension;
//import java.awt.Font;
import java.awt.Image;
import java.awt.SystemColor;
import client.CustomEvents.ConnectToClientEvent;
import client.CustomEvents.SendMsgToClientEvent;
import client.CustomEvents.SettingsFilledEvent;
import chatown.Client;
import chatown.OpenMsg;
import CustomEvents.CustomEventSource;
import CustomEvents.DisconnectClientEvent;
import CustomEvents.ICustomEventListener;
import CustomEvents.OpenMsgClientEvent;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.Color;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Vector;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
//import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class ClientFrame extends JFrame {
private static final long serialVersionUID = -7181992228161884653L;
private static final String OPEN_ROOM = "open room";
private String _serverIP = null;
private String _serverPort = null;
private String _clientsPort = null;
private String _nickname = null;
private String _myClientID;
private CustomEventSource _eventSettingsFilled = new CustomEventSource();
private CustomEventSource _eventSendOpenMsg = new CustomEventSource();
private CustomEventSource _eventDisconnect = new CustomEventSource();
private CustomEventSource _eventConnectToClient = new CustomEventSource();
private CustomEventSource _eventSendMsgToClient = new CustomEventSource();
private HashMap<String, ClientRoom> _roomsMap = new HashMap<String, ClientRoom>(); // key is client ID
private JList<chatown.Client> clientsList;
private JTabbedPane tpClientsRooms;
private static JTextArea txtEnter;
private static Action enterAction;
private JLabel lblServer;
private Vector<Client> clientsListModel;
public void registerSettingsFilledEvent(ICustomEventListener listener) {
_eventSettingsFilled.addEventListener(listener);
}
public void registerSendOpenMsgEvent(ICustomEventListener listener) {
_eventSendOpenMsg.addEventListener(listener);
}
public void registerDisconnectEvent(ICustomEventListener listener) {
_eventDisconnect.addEventListener(listener);
}
public void registerConnectToClientEvent(ICustomEventListener listener) {
_eventConnectToClient.addEventListener(listener);
}
public void registerSendMsgToClientEvent(ICustomEventListener listener) {
_eventSendMsgToClient.addEventListener(listener);
}
public ClientFrame() {
loadIcon();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// send disconnect event to server
Client clt = new Client(null, _nickname, _myClientID);
_eventDisconnect.fireEvent(new DisconnectClientEvent(this, clt));
}
});
init_look();
getContentPane().setBackground(SystemColor.activeCaption);
getContentPane().setLayout(new BorderLayout(0, 0));
setMinimumSize(new Dimension(600, 400));
// ------------------------------------------------------
JPanel panel = new JPanel();
panel.setBorder(new EmptyBorder(4, 0, 0, 0));
getContentPane().add(panel, BorderLayout.NORTH);
JLabel lblSettings = new JLabel(" ");
lblSettings.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
openSettingsDialog(false);
}
});
lblServer = new JLabel(" ");
JLabel lblServer_1 = new JLabel("server ");
GroupLayout gl_panel = new GroupLayout(panel);
gl_panel.setHorizontalGroup(
gl_panel.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_panel.createSequentialGroup()
.addContainerGap()
.addComponent(lblServer_1)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(lblServer)
.addPreferredGap(ComponentPlacement.RELATED, 476, Short.MAX_VALUE)
.addComponent(lblSettings, GroupLayout.PREFERRED_SIZE, 30, GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
gl_panel.setVerticalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
.addComponent(lblSettings)
.addComponent(lblServer)
.addComponent(lblServer_1))
.addContainerGap())
);
panel.setLayout(gl_panel);
Image image = getToolkit().getImage(getClass().getResource("/resources/settings.png"));
Image scaledImage = image.getScaledInstance(30, 30, Image.SCALE_DEFAULT);
lblSettings.setIcon(new ImageIcon(scaledImage));
JSplitPane splitPane = new JSplitPane();
getContentPane().add(splitPane, BorderLayout.CENTER);
JPanel panel_2 = new JPanel();
splitPane.setRightComponent(panel_2);
panel_2.setLayout(new BorderLayout(0, 0));
JSplitPane splitPane_1 = new JSplitPane();
splitPane_1.setResizeWeight(1.0);
splitPane_1.setOrientation(JSplitPane.VERTICAL_SPLIT);
panel_2.add(splitPane_1, BorderLayout.CENTER);
JPanel panel_message = new JPanel();
splitPane_1.setRightComponent(panel_message);
panel_message.setBackground(new Color(176, 196, 222));
panel_message.setBorder(new EmptyBorder(0, 0, 7, 0));
JLabel lblSend = new JLabel(" ");
lblSend.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
sendMsg(txtEnter.getText());
}
});
Image imageSend = getToolkit().getImage(getClass().getResource("/resources/send_mail_1.png"));
Image scaledImageSend = imageSend.getScaledInstance(30, 30, Image.SCALE_DEFAULT);
lblSend.setIcon(new ImageIcon(scaledImageSend));
JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
GroupLayout gl_panel_message = new GroupLayout(panel_message);
gl_panel_message.setHorizontalGroup(
gl_panel_message.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_panel_message.createSequentialGroup()
.addContainerGap()
.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 501, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.UNRELATED)
.addComponent(lblSend)
.addGap(2))
);
gl_panel_message.setVerticalGroup(
gl_panel_message.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel_message.createSequentialGroup()
.addContainerGap()
.addGroup(gl_panel_message.createParallelGroup(Alignment.LEADING)
.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 52, Short.MAX_VALUE)
.addGroup(gl_panel_message.createSequentialGroup()
.addComponent(lblSend, GroupLayout.DEFAULT_SIZE, 41, Short.MAX_VALUE)
.addContainerGap())))
);
txtEnter = new JTextArea();
enterAction = new EnterAction();
// the following two lines do the magic of key binding. the first line
// gets the dataField's InputMap and pairs the "ENTER" key to the action "doEnterAction"
txtEnter.getInputMap().put( KeyStroke.getKeyStroke("ENTER"), "doEnterAction" );
txtEnter.getActionMap().put( "doEnterAction", enterAction );
txtEnter.setLineWrap(true);
txtEnter.setWrapStyleWord(true);
scrollPane.setViewportView(txtEnter);
panel_message.setLayout(gl_panel_message);
tpClientsRooms = new JTabbedPane(JTabbedPane.TOP);
splitPane_1.setLeftComponent(tpClientsRooms);
JPanel panelClientsList = new JPanel();
panelClientsList.setBackground(new Color(175, 238, 238));
panelClientsList.setPreferredSize(new Dimension(110, 10));
splitPane.setLeftComponent(panelClientsList);
clientsList = new JList<Client>();
clientsList.setBackground(new Color(175, 238, 238));
panelClientsList.add(clientsList);
clientsList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() == 2) {
int index = clientsList.locationToIndex(evt.getPoint());
OpenClientRoom(clientsList.getModel().getElementAt(index));
}
}
});
// -----------------------------------------
tpClientsRooms.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int index = tpClientsRooms.getSelectedIndex();
try{
((JPanel)tpClientsRooms.getTabComponentAt(index)).setOpaque(false);
} catch (NullPointerException e1) {}
}
});
OpenCommonRoom();
}
private void loadIcon() {
Image img = getToolkit().getImage(getClass().getResource("/resources/chat.png"));
this.setIconImage(img);
}
private void OpenCommonRoom () {
JPanel panel = new RoomPanel(OPEN_ROOM, true);
tpClientsRooms.addTab(OPEN_ROOM, null, panel, null);
tpClientsRooms.setSelectedComponent(panel);
_roomsMap.put(OPEN_ROOM, new ClientRoom(null, panel, null));
}
protected JPanel createClientRoom(final Client roomClient) {
// check if try to open room to myself - if so ignore request
if (roomClient.get_ID().equals(_myClientID)) { return null; }
JPanel panel;
if (_roomsMap.containsKey(roomClient.toString())) { // check if room is already open for this client
panel = _roomsMap.get(roomClient.toString()).get_panel();
if (tpClientsRooms.indexOfTab(roomClient.toString()) == -1) { // check if tab is hidden
tpClientsRooms.addTab(roomClient.toString(), null, panel, null);
TabHeader header = _roomsMap.get(roomClient.toString()).get_header();
int pnlIndex = tpClientsRooms.indexOfComponent(panel);
tpClientsRooms.setTabComponentAt(pnlIndex, header); // add X for closing tab
}
}
else { //create new room for client
panel = new RoomPanel(roomClient.get_ID(), false);
tpClientsRooms.addTab(roomClient.toString(), null, panel, null);
TabHeader tabHead = new TabHeader(roomClient.toString());
tabHead.lblIcon.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 1) {
tpClientsRooms.remove(_roomsMap.get(roomClient.toString()).get_panel()); //hide tab
}
if (!clientsListModel.contains(roomClient)) { // remove client if he is disconnected
_roomsMap.remove(roomClient.toString());
System.out.println("removed client " + roomClient.toString());
}
}
});
int tabIndex = tpClientsRooms.indexOfComponent(panel);
tpClientsRooms.setTabComponentAt(tabIndex, tabHead); // add X for closing tab
_roomsMap.put(roomClient.toString(), new ClientRoom(roomClient, panel, tabHead));
}
return panel;
}
protected void OpenClientRoom(final Client roomClient) {
JPanel panel = createClientRoom(roomClient);
if (panel != null) {
tpClientsRooms.setSelectedComponent(panel);
_eventConnectToClient.fireEvent(new ConnectToClientEvent(this, roomClient));
}
}
protected void openSettingsDialog(Boolean isFirst) {
SettingsDialog settings = new SettingsDialog();
if (!isFirst) {
settings.disableNickname();
settings.setNickname(_nickname);
} else {
settings.disableCancel();
}
settings.setVisible(true);
//if (settings.OK) {
if (isFirst) {
_serverPort = settings.getServerPort();
_serverIP = settings.getServerIP();
_clientsPort = settings.getClientsPort();
_nickname = settings.getNickname();
_eventSettingsFilled.fireEvent(new SettingsFilledEvent(this, _nickname, _serverIP, _serverPort, _clientsPort));
}
settings.dispose();
}
private void init_look() {
// try {
// UIManager.setLookAndFeel(new NimbusLookAndFeel() {
//
// private static final long serialVersionUID = 1L;
//
// @Override
// public UIDefaults getDefaults() {
// UIDefaults ret = super.getDefaults();
// ret.put("defaultFont", new Font(Font.SANS_SERIF, Font.PLAIN, 13));
// return ret;
// }
// });
// //} catch (UnsupportedLookAndFeelException e) {
// } catch (Exception e) {
// e.printStackTrace();
// }
}
public void setClientslist(Client[] clientsArray, String myClientID) {
clientsList.removeAll();
clientsListModel = new Vector<Client>(Arrays.asList(clientsArray));
_myClientID = myClientID;
clientsList.setListData(clientsListModel);
}
private void sendMsg(String text) {
if (text.length() == 0) { return; }
RoomPanel currRoom = (RoomPanel) tpClientsRooms.getSelectedComponent();
if (currRoom.get_clientID().equals(OPEN_ROOM)) { // open message - to server
sendOpenMsgToServer(text);
}
else { //send message to client
//check if receiver client connected
Client msgReceiver = null;
int i = 0;
for (; i < clientsList.getModel().getSize(); i++) {
Client clt = clientsList.getModel().getElementAt(i);
if (clt.get_ID().equals(currRoom.get_clientID())) {
msgReceiver = clt;
break;
}
}
if (!clientsListModel.contains(msgReceiver)) {
JOptionPane.showMessageDialog(null, "Client is disconnected");
txtEnter.setText("");
return;
}
_eventSendMsgToClient.fireEvent(new SendMsgToClientEvent(this, currRoom.get_clientID(), text));
// add text to UI
currRoom.addMsg("me", text);
}
txtEnter.setText("");
}
private void sendOpenMsgToServer(String text) {
Client clt = new Client(null, _nickname, _myClientID);
_eventSendOpenMsg.fireEvent(new OpenMsgClientEvent(this, new OpenMsg(clt, text)));
}
public void handleOpenMsg(OpenMsg openMsg) {
// add message to open room
String name;
if (openMsg.get_client().get_ID().equals(_myClientID)) {
name = "me";
} else {
name = openMsg.get_client().get_nickName();
}
RoomPanel openRoomPanel = (RoomPanel) _roomsMap.get(OPEN_ROOM).get_panel();
openRoomPanel.addMsg(name, openMsg.get_msg());
}
class EnterAction extends AbstractAction
{
private static final long serialVersionUID = -2227122387178072713L;
@Override
public void actionPerformed(ActionEvent e) {
sendMsg(txtEnter.getText());
}
}
public void handleClientMsg(String msg, String senderID) {
Client msgSender = null;
for (int i = 0; i < clientsList.getModel().getSize(); i++) {
Client clt = clientsList.getModel().getElementAt(i);
if (clt.get_ID().equals(senderID)) {
msgSender = clt;
break;
}
}
if (msgSender == null) {
System.out.println("received msg from unknown sender: " + msg);
return;
}
if (tpClientsRooms.indexOfTab(msgSender.toString()) == -1) { // check if room is visible
createClientRoom(msgSender);
}
RoomPanel openRoomPanel = (RoomPanel) _roomsMap.get(msgSender.toString()).get_panel();
openRoomPanel.addMsg(msgSender.get_nickName(), msg);
// check if currently selected tab is different from the tab of the message
if (tpClientsRooms.getSelectedIndex() != tpClientsRooms.indexOfTab(msgSender.toString())) {
_roomsMap.get(msgSender.toString()).get_header().setOpaque(true);
_roomsMap.get(msgSender.toString()).get_header().repaint();
}
}
public void handleServerConnection(boolean serverConnected) {
Image image;
if (serverConnected) {
image = getToolkit().getImage(getClass().getResource("/resources/green_ball.png"));
} else {
image = getToolkit().getImage(getClass().getResource("/resources/red_ball.png"));
}
Image scaledImage = image.getScaledInstance(30, 30, Image.SCALE_DEFAULT);
lblServer.setIcon(new ImageIcon(scaledImage));
}
public void clientDisconnect(String clientID) {
Client msgSender = null;
int i = 0;
for (; i < clientsList.getModel().getSize(); i++) {
Client clt = clientsList.getModel().getElementAt(i);
if (clt.get_ID().equals(clientID)) {
msgSender = clt;
break;
}
}
if (msgSender == null) {
System.out.println("ClientFrame: disconnected client not found : " + clientID);
return;
}
System.out.println("ClientFrame: disconnected client found : " + clientID);
clientsListModel.remove(i);
clientsList.repaint();
}
}