package com.jesseweiman.RPChat.gui;
import com.jesseweiman.RPChat.Message;
import com.jesseweiman.RPChat.Properties;
import com.jesseweiman.RPChat.Utils;
import com.jesseweiman.RPChat.chat.ChatManager;
import com.jesseweiman.RPChat.manager.ConfigManager;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created with IntelliJ IDEA.
* User: Jesse
* Date: 10/2/12
* Time: 1:04 AM
* To change this template use File | Settings | File Templates.
*/
public class GUI extends JFrame implements ActionListener {
ConfigManager configManager = new ConfigManager();
ChatManager chatManager = new ChatManager(this, configManager);
GridBagLayout chatLayout = new GridBagLayout();
JPanel chatPanel = new JPanel(chatLayout);
JTextPane statusPane = new JTextPane();
JScrollPane statusView = new JScrollPane(statusPane);
JTextPane recentChat = new JTextPane();
JScrollPane chatView = new JScrollPane(recentChat);
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, chatPanel, statusView);
JTextField inputField = new JTextField();
JButton sendButton = new JButton("Send");
JMenuBar menuBar = new JMenuBar();
JMenu logMenu = new JMenu("Logs");
JMenu homeMenu = new JMenu("RPChat");
JMenuItem setNameItem = new JMenuItem("Set Name");
JMenuItem quitItem = new JMenuItem("Quit");
JMenu networkMenu = new JMenu("Network");
JMenuItem setPortItem = new JMenuItem("Set Listening Port");
JMenuItem setAddrItem = new JMenuItem("Set Buddy's Address");
public GUI(){
setupMenu();
setupChatPanel();
setupStatusPanel();
setupSplitPane();
setupListeners();
setSize(600, 400);
setJMenuBar(menuBar);
add(splitPane);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
private void sendMessage(){
String message = inputField.getText().trim();
if(!message.isEmpty()){
chatManager.sendMessage(message);
updateChat();
}
inputField.setText("");
inputField.requestFocusInWindow();
}
public synchronized void updateChat(){
final JScrollBar scrollBar = chatView.getVerticalScrollBar();
boolean scrollBarVisible = scrollBar.isVisible();
boolean scrollBottom = false;
final int scrollValue = scrollBar.getValue();
if(scrollBarVisible){
scrollBottom = scrollBar.getMaximum() == scrollBar.getValue() + scrollBar.getVisibleAmount();
}
appendText();
// if(!scrollBarVisible && scrollBar.isVisible() || scrollBottom) {
// scrollToBottom();
// }
if( scrollBottom )
{
// force the slider to the bottom
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
scrollBar.setValue(scrollBar.getMaximum());
}
});
}
else
{
// keep the slider where it is
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
scrollBar.setValue(scrollValue);
}
});
}
}
private void appendText(){
Message[] messages = chatManager.getMessages();
try{
recentChat.getDocument().insertString(recentChat.getDocument().getLength(), Utils.buildMessageString(messages[messages.length - 1]) + "\n", null);
}
catch(BadLocationException e){
//this will never happen
e.printStackTrace();
}
}
private void scrollToBottom()
{
Rectangle visible = recentChat.getVisibleRect();
Rectangle bounds = recentChat.getBounds();
// You need to add some kind of offset to scroll it to
// the end; I put 50, but even some smaller values will do
visible.y = bounds.height - visible.height + 50;
recentChat.scrollRectToVisible(visible);
}
@Override
public void actionPerformed(ActionEvent e) {
JComponent component = (JComponent)e.getSource();
if(component instanceof JMenuItem){
if(component == quitItem)
System.exit(0);
else if(component == setNameItem){
InputDialog nameDialogue = new InputDialog(this, configManager, "Name", "Please enter your name", configManager.getString(Properties.NAME_KEY, ChatManager.DEFAULT_NAME));
nameDialogue.display();
if(nameDialogue.clickedOK() && !nameDialogue.getInput().trim().isEmpty()){
configManager.setProperty(Properties.NAME_KEY, nameDialogue.getInput());
}
}
else if(component == setAddrItem){
InputDialog nameDialogue = new InputDialog(this, configManager, "Name", "Please enter your name", configManager.getString(Properties.ADDRESS_KEY, "localhost"));
nameDialogue.display();
if(nameDialogue.clickedOK() && !nameDialogue.getInput().trim().isEmpty()){
configManager.setProperty(Properties.ADDRESS_KEY, nameDialogue.getInput());
}
}
}
else if(component == sendButton || component == inputField)
sendMessage();
}
/*****************************************
* BORING BOILER PLATE CODE
******************************************/
private void setupListeners() {
sendButton.addActionListener(this);
inputField.addActionListener(this);
}
private void setupStatusPanel() {
statusPane.setEditable(false);
}
private void setupSplitPane() {
splitPane.setResizeWeight(0.75);
}
private void setupMenu(){
homeMenu.add(setNameItem);
homeMenu.add(quitItem);
networkMenu.add(setPortItem);
networkMenu.add(setAddrItem);
menuBar.add(homeMenu);
menuBar.add(logMenu);
menuBar.add(networkMenu);
setNameItem.addActionListener(this);
quitItem.addActionListener(this);
setPortItem.addActionListener(this);
setAddrItem.addActionListener(this);
}
private void setupChatPanel(){
chatPanel.setBackground(Color.BLUE);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 2;
c.weightx = 1.0;
c.weighty = 1.0;
recentChat.setMinimumSize(new Dimension(75, 100));
recentChat.setEditable(false);
chatLayout.setConstraints(chatView, c);
chatPanel.add(chatView);
c.gridwidth = 1;
c.gridx = 0;
c.gridy = 1;
c.weightx = 1.0;
c.weighty = 0.0;
inputField.setMinimumSize(new Dimension(0, 25));
chatLayout.setConstraints(inputField, c);
chatPanel.add(inputField);
c.gridx = 1;
c.weightx = 0;
chatLayout.setConstraints(sendButton, c);
chatPanel.add(sendButton);
}
}