-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUI.java
More file actions
294 lines (239 loc) · 8.76 KB
/
Copy pathUI.java
File metadata and controls
294 lines (239 loc) · 8.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.Insets;
import java.awt.Font;
import javax.swing.JButton;
import java.awt.Dimension;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.text.DefaultCaret;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenuBar;
import java.awt.Component;
import javax.swing.Box;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* The UI class is intended to generate and control the main UI for the application.
* A note that the majority of the actual code controlling connections and communication
* with the server is actually controlled and executed by the Client object.
*
* @author Maxence Weyrich
*
*/
public class UI extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private static final String INTRO_MESSAGE = "Welcome to JavaChat... to begin connect to a server, or host your own!\n\n";
private static final int MAX_CHARS = 250000;
private Client client;
private ConnectionUI connectionDialog;
private JPanel contentPane;
private JTextField messageBox;
private JTextPane messageArchive;
private JButton sendButton;
private StyledDocument archiveDoc;
private JMenuBar menuBar;
private JButton newConnection;
private Component horizontalGlue;
private Component horizontalGlue_1;
private JButton disconnect;
private Component horizontalStrut;
private JScrollPane messageArchivePanel;
/**
* Create the main UI frame.
* @param client a Client object.
*/
public UI(Client client) {
this.client = client;
this.connectionDialog = new ConnectionUI(client);
contentPane = new JPanel();
contentPane.setFont(new Font("Tahoma", Font.PLAIN, 14));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
menuBar = new JMenuBar();
contentPane.add(menuBar, BorderLayout.NORTH);
horizontalGlue = Box.createHorizontalGlue();
menuBar.add(horizontalGlue);
newConnection = new JButton("New Connection...");
newConnection.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
connectionDialog.setVisible(true);
connectionDialog.requestFocus();
}
});
newConnection.setMargin(new Insets(3, 40, 3, 40));
menuBar.add(newConnection);
newConnection.setFont(new Font("Tahoma", Font.PLAIN, 14));
horizontalStrut = Box.createHorizontalStrut(20);
menuBar.add(horizontalStrut);
disconnect = new JButton("Disconnect");
disconnect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
client.close();
}
});
disconnect.setEnabled(false);
disconnect.setMargin(new Insets(3, 40, 3, 40));
disconnect.setFont(new Font("Tahoma", Font.PLAIN, 14));
menuBar.add(disconnect);
horizontalGlue_1 = Box.createHorizontalGlue();
menuBar.add(horizontalGlue_1);
JPanel subPanel = new JPanel();
contentPane.add(subPanel, BorderLayout.SOUTH);
subPanel.setLayout(new BorderLayout(0, 0));
messageBox = new JTextField();
messageBox.setEnabled(false);
messageBox.addActionListener(this);
subPanel.add(messageBox, BorderLayout.CENTER);
messageBox.setMargin(new Insets(10, 10, 10, 10));
messageBox.setFont(new Font("Trebuchet MS", Font.PLAIN, 14));
messageBox.setColumns(8);
sendButton = new JButton("Send");
sendButton.setEnabled(false);
sendButton.addActionListener(this);
sendButton.setFont(new Font("Trebuchet MS", Font.PLAIN, 14));
sendButton.setPreferredSize(new Dimension(80, 23));
sendButton.setActionCommand("send");
subPanel.add(sendButton, BorderLayout.EAST);
messageArchivePanel = new JScrollPane();
messageArchivePanel.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
contentPane.add(messageArchivePanel, BorderLayout.CENTER);
messageArchive = new JTextPane();
messageArchive.setFont(new Font("Trebuchet MS", Font.PLAIN, 14));
messageArchive.setDragEnabled(true);
messageArchive.setEditable(false);
((DefaultCaret)messageArchive.getCaret()).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
// Define the document styles that are available to choose from
archiveDoc = messageArchive.getStyledDocument();
Style s = archiveDoc.addStyle("bold", null);
StyleConstants.setBold(s, true);
s = archiveDoc.addStyle("italic", null);
StyleConstants.setItalic(s, true);
s = archiveDoc.addStyle("command", null);
StyleConstants.setFontFamily(s, "Monospaced");
s = archiveDoc.addStyle("error", null);
StyleConstants.setFontFamily(s, "Monospaced");
StyleConstants.setForeground(s, Color.RED);
messageArchivePanel.setViewportView(messageArchive);
try {
archiveDoc.insertString(0, INTRO_MESSAGE, null);
} catch(Exception e) {
e.printStackTrace();
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1000, 600);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
client.close();
}
});
this.setVisible(true);
messageBox.requestFocusInWindow();
}
/**
* Adds the specified text into the document with the given style.
* @param text String of the text to add
* @param style String of the style of the text. Ensure that the style has been defined ahead of time in the constructor.
*/
private void addText(String text, String style) {
Style textStyle;
if(style == null) {
textStyle = null;
} else {
textStyle = archiveDoc.getStyle(style);
}
try {
archiveDoc.insertString(archiveDoc.getLength(), text, textStyle);
if(archiveDoc.getLength() + text.length() > MAX_CHARS) {
archiveDoc.remove(0, Math.min(archiveDoc.getLength(), archiveDoc.getLength() + messageBox.getText().length() - MAX_CHARS));
}
} catch(Exception ex) {
ex.printStackTrace();
}
messageArchive.setCaretPosition(archiveDoc.getLength()); //set position to end
}
/**
* Handle the Send button press or the press of the return key while still in the message box
* Will process the message, update UI, and send it to the server.
*/
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(sendButton) || e.getSource().equals(messageBox)) {
if(messageBox.getText().startsWith("//")) { //if a server command (starts with "//")
client.sendCommand(messageBox.getText().substring(2));
addText(messageBox.getText() + '\n', "command");
messageBox.setText("");
} else if(messageBox.getText().length() > 0) { //if normal text; then it's a normal message
client.sendMessage(messageBox.getText());
addText("Me: ", "bold");
addText(messageBox.getText() + '\n', null);
messageBox.setText("");
}
messageBox.requestFocusInWindow();
} else {
System.out.println(e.toString());
}
}
/**
* Adds the specified message to the UI with the user as the sender of the message
* @param newMessage String message to add to the screen
* @param user String user that send the new message.
*/
public void addMessage(String newMessage, String user) {
addText(user + ": ", "bold");
addText(newMessage.trim() + '\n', "normal");
}
/**
* Adds the specified text to the UI with the "error" style
* @param notif String error message to add to the screen
*/
public void addError(String notif) {
addText("Error - " + notif + '\n', "error");
}
/**
* Adds the specified text to the UI with the formatting for a server command response (to differentiate from normal messages)
* @param notif String text to add to the UI
*/
public void addCommandResponse(String notif) {
addText(notif + '\n', "command");
}
/**
* Adds a "notification" to the UI, it has a different formatting to indicate that is it not a normal message.
* This is used whenever the server sends a message or notification to a user to differentiate it form a normal message.
* @param notif String message to send the user.
*/
public void addNotification(String notif) {
addText(notif.trim() + '\n', "italic");
}
/**
* Sets the result text for the connection dialog
* @param result String result message
*/
public void showConnectionResult(String result) {
connectionDialog.setConnectionResult(result);
}
/**
* Updates the UI based on the value of connected.
* E.g. will enable buttons that would normally be disabled when the connection turns on
* @param connected
*/
public void setConnected(boolean connected) {
messageBox.setEnabled(connected);
sendButton.setEnabled(connected);
newConnection.setEnabled(!connected);
disconnect.setEnabled(connected);
if(connected) {
connectionDialog.setVisible(false);
connectionDialog.reset();
}
}
}