package com.limegroup.gnutella.gui.chat;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import com.limegroup.gnutella.chat.Chatter;
import com.limegroup.gnutella.gui.BoxPanel;
import com.limegroup.gnutella.gui.ButtonRow;
import com.limegroup.gnutella.gui.GUIConstants;
import com.limegroup.gnutella.gui.GUIMediator;
import com.limegroup.gnutella.gui.PaddedPanel;
import com.limegroup.gnutella.gui.themes.ThemeObserver;
/**
* the gui front end for the chat class. it is a subclass of
* JFrame, and displays both user's messages, as well as allowing
* message input for one user.
*/
//2345678|012345678|012345678|012345678|012345678|012345678|012345678|012345678|
public class ChatFrame extends JFrame implements ThemeObserver {
/**
* Constant for the locale-specific resource key for the label of the
* chat block sender button.
*/
private final String BLOCK_BUTTON_LABEL = "CHAT_BLOCK_BUTTON_LABEL";
/**
* Constant for the locale-specific resource key for the label of the
* chat send button.
*/
private final String SEND_BUTTON_LABEL = "CHAT_SEND_BUTTON_LABEL";
/**
* Constant for the locale-specific resource key for the toolTip of the
* chat block sender button.
*/
private final String BLOCK_BUTTON_TIP = "CHAT_BLOCK_BUTTON_TIP";
/**
* Constant for the locale-specific resource key for the toolTip of the
* chat send button.
*/
private final String SEND_BUTTON_TIP = "CHAT_SEND_BUTTON_TIP";
private final String WITH_LABEL = "CHAT_WITH_LABEL";
private final String UNAVAILABLE_LABEL = "CHAT_HOST_UNAVAILABLE";
private final String YOU_LABEL = "CHAT_YOU";
private final int WINDOW_WIDTH = 500;
private final int WINDOW_HEIGHT = 300;
/**
* Constants for preventing resizing the frame to an unusable size
*/
private final int WINDOW_MIN_WIDTH = 250;
private final int WINDOW_MIN_HEIGHT = 200;
private final int TEXT_FIELD_LIMIT = 500;
private boolean _connected = true;
JTextArea _area; /* where the conversation is displayed */
JTextField _field; /* where the user enters the message to send */
JTextField _connectField;
Chatter _chat; /* the interface to the backend */
ButtonRow _buttons; /* block and send buttons */
public ChatFrame(Chatter chat) {
super();
setTitle(GUIMediator.getStringResource(WITH_LABEL) + " "
+ chat.getHost());
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
_chat = chat;
Frame parentFrame = GUIMediator.getAppFrame();
int mwidth = parentFrame.getSize().width / 2;
int mheight = parentFrame.getSize().height / 2;
int fwidth = getSize().width / 2;
int fheight = getSize().height / 2;
int xlocation = mwidth - fwidth;
int ylocation = mheight - fheight;
int xstart = parentFrame.getLocation().x;
int ystart = parentFrame.getLocation().y;
setLocation(xstart+xlocation, ystart+ylocation);
BlockListener blockListener = new BlockListener();
ActionListener sendListener = new SendListener();
String[] buttonLabels = {
BLOCK_BUTTON_LABEL,
SEND_BUTTON_LABEL
};
String[] buttonTips = {
BLOCK_BUTTON_TIP,
SEND_BUTTON_TIP
};
ActionListener[] buttonListeners = {
blockListener, sendListener
};
_buttons = new ButtonRow(buttonLabels,
buttonTips,
buttonListeners,
ButtonRow.X_AXIS,
ButtonRow.NO_GLUE);
_buttons.setButtonEnabled(1, false);
TextPanel tp = new TextPanel();
BoxPanel mainPanel = new BoxPanel(BoxLayout.Y_AXIS);
PaddedPanel myPanel = new PaddedPanel();
myPanel.setPreferredSize(new Dimension(1000,1000));
myPanel.add(tp);
mainPanel.add(myPanel);
mainPanel.add(Box.createVerticalStrut(GUIConstants.SEPARATOR));
mainPanel.add(_buttons);
mainPanel.add(Box.createVerticalStrut(GUIConstants.SEPARATOR));
getContentPane().add(mainPanel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
_chat.stop();
ChatUIManager.instance().removeChat(_chat);
}
});
// establish minimum size of the chat window
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
JFrame src = (JFrame)e.getSource();
int width = src.getWidth();
int height = src.getHeight();
int newWidth = Math.max(width, WINDOW_MIN_WIDTH);
int newHeight = Math.max(height, WINDOW_MIN_HEIGHT);
if(newWidth != width || newHeight != height)
src.setSize(newWidth, newHeight);
}
});
updateTheme();
}
// inherit doc comment
public void updateTheme() {
ImageIcon plugIcon = GUIMediator.getThemeImage(GUIConstants.LIMEWIRE_ICON);
setIconImage(plugIcon.getImage());
}
/** displays an incoming message from a specific host */
public void addResponse(String str) {
String host = _chat.getHost();
_area.setText(_area.getText() + host + ": " + str + "\n");
}
/** sets the interface to the back end */
public void setChat(Chatter chat) {
_chat = chat;
}
public void chatUnavailable() {
_area.setForeground(Color.red);
_area.setText(_area.getText() +
GUIMediator.getStringResource(UNAVAILABLE_LABEL)
+ "\n");
_connected = false;
_buttons.setButtonEnabled(1, false);
}
/** display an error message in red in the chat gui */
public void displayErrorMessage(String str) {
_area.setForeground(Color.red);
_area.setText(str);
}
/*****************************************************************
* PRIVATE METHODS
*
*****************************************************************/
/** displays your message on the screen, and sends it to
your chat partner. */
private void send() {
if (!_connected)
return;
String str = _field.getText();
if (str.length() == 0)
return;
_field.setText("");
_buttons.setButtonEnabled(1, false);
_area.setText(_area.getText() +
GUIMediator.getStringResource(YOU_LABEL) +
": " + str + "\n");
try {
_chat.send(str);
} catch (Exception eeee) {
}
}
/*****************************************************************
* PRIVATE CLASSES
*
*****************************************************************/
/**
* limits the JTextField input to the specified number of characters,
* including pastes
*/
private class JTextFieldLimit extends PlainDocument {
private int limit;
public JTextFieldLimit(int limit) {
super();
this.limit = limit;
}
public void insertString(int offset, String str, AttributeSet attr)
throws BadLocationException {
if (str == null) return;
if ((getLength() + str.length()) <= limit)
super.insertString(offset, str, attr);
}
}
private class TextPanel extends JPanel {
public TextPanel() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
BoxPanel fieldPanel = new BoxPanel(BoxLayout.X_AXIS);
_area = new JTextArea();
_area.setLineWrap(true);
_field = new JTextField();
_field.setDocument(new JTextFieldLimit(TEXT_FIELD_LIMIT));
JScrollPane areaScrollPane = new JScrollPane(_area);
_area.setEditable(false);
_field.addKeyListener(new JTextFieldKeyListener());
fieldPanel.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR));
fieldPanel.add(_field);
fieldPanel.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR));
fieldPanel.setPreferredSize(new Dimension(1000,20));
fieldPanel.setMaximumSize(new Dimension(1000, 20));
add(areaScrollPane);
add(Box.createVerticalStrut(GUIConstants.SEPARATOR));
add(fieldPanel);
}
}
/*****************************************************************
* LISTENERS
*
*****************************************************************/
/** end the chat session with the current host */
private class EndListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
_chat.stop();
ChatUIManager.instance().removeChat(_chat);
}
}
/** send a message to the specified host */
private class SendListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
send();
}
}
/** connect to the specified host */
private class BlockListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String host = _chat.getHost();
_chat.blockHost(host);
_chat.stop();
}
}
/** enable state for the send button */
private class JTextFieldKeyListener implements KeyListener {
public void keyTyped(KeyEvent k) {
if (k.getKeyChar() == KeyEvent.VK_ENTER)
send(); // send the message
}
public void keyPressed(KeyEvent k) {}
public void keyReleased(KeyEvent k) {
String text = _field.getText();
if (text.length() == 0)
_buttons.setButtonEnabled(1, false); // disable send button
else if (_connected) {
_buttons.setButtonEnabled(1, true); // enable send button
}
}
}
}