Added the display of multi-line messages (#115)
* Added multi-line messages * Added shutdown method for LoginDialog * Fixed login bug in LoginDialog * Added a maximum length for messages * Implemented update of component list elements on resizing * Improved visual appearance of some files
This commit is contained in:
parent
9896339f92
commit
349ffeaa25
@ -1,8 +1,7 @@
|
|||||||
package envoy.client.ui;
|
package envoy.client.ui;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.KeyAdapter;
|
import java.awt.event.*;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -41,17 +40,25 @@ import envoy.util.EnvoyLog;
|
|||||||
*/
|
*/
|
||||||
public class ChatWindow extends JFrame {
|
public class ChatWindow extends JFrame {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This int defines the maximum amount of chars allowed per message. Currently
|
||||||
|
* set at 200.
|
||||||
|
*
|
||||||
|
* @since Envoy 0.1-beta
|
||||||
|
*/
|
||||||
|
public static final int MAX_MESSEAGE_LENGTH = 200;
|
||||||
|
|
||||||
// User specific objects
|
// User specific objects
|
||||||
private Client client;
|
private Client client;
|
||||||
private WriteProxy writeProxy;
|
private WriteProxy writeProxy;
|
||||||
private LocalDb localDb;
|
private LocalDb localDb;
|
||||||
|
private Chat currentChat;
|
||||||
|
|
||||||
// GUI components
|
// GUI components
|
||||||
private JPanel contentPane = new JPanel();
|
private JPanel contentPane = new JPanel();
|
||||||
private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space);
|
private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space);
|
||||||
private JList<User> userList = new JList<>();
|
private JList<User> userList = new JList<>();
|
||||||
private DefaultListModel<User> userListModel = new DefaultListModel<>();
|
private DefaultListModel<User> userListModel = new DefaultListModel<>();
|
||||||
private Chat currentChat;
|
|
||||||
private ComponentList<Message> messageList = new ComponentList<>(new MessageListRenderer());
|
private ComponentList<Message> messageList = new ComponentList<>(new MessageListRenderer());
|
||||||
private PrimaryScrollPane scrollPane = new PrimaryScrollPane();
|
private PrimaryScrollPane scrollPane = new PrimaryScrollPane();
|
||||||
private JTextPane textPane = new JTextPane();
|
private JTextPane textPane = new JTextPane();
|
||||||
@ -67,7 +74,7 @@ public class ChatWindow extends JFrame {
|
|||||||
private final JPanel searchPane = new JPanel();
|
private final JPanel searchPane = new JPanel();
|
||||||
private final PrimaryButton cancelButton = new PrimaryButton("x");
|
private final PrimaryButton cancelButton = new PrimaryButton("x");
|
||||||
private final PrimaryTextArea searchField = new PrimaryTextArea(space);
|
private final PrimaryTextArea searchField = new PrimaryTextArea(space);
|
||||||
private final PrimaryScrollPane possibleContacts = new PrimaryScrollPane();
|
private final PrimaryScrollPane scrollForPossibleContacts = new PrimaryScrollPane();
|
||||||
private final ContactsSearchRenderer contactRenderer = new ContactsSearchRenderer();
|
private final ContactsSearchRenderer contactRenderer = new ContactsSearchRenderer();
|
||||||
private final ComponentListModel<User> contactsModel = new ComponentListModel<>();
|
private final ComponentListModel<User> contactsModel = new ComponentListModel<>();
|
||||||
private final ComponentList<User> contactList = new ComponentList<>(contactRenderer);
|
private final ComponentList<User> contactList = new ComponentList<>(contactRenderer);
|
||||||
@ -98,13 +105,20 @@ public class ChatWindow extends JFrame {
|
|||||||
GridBagLayout gbl_contentPane = new GridBagLayout();
|
GridBagLayout gbl_contentPane = new GridBagLayout();
|
||||||
gbl_contentPane.columnWidths = new int[] { 1, 1, 1 };
|
gbl_contentPane.columnWidths = new int[] { 1, 1, 1 };
|
||||||
gbl_contentPane.rowHeights = new int[] { 1, 1, 1, 1 };
|
gbl_contentPane.rowHeights = new int[] { 1, 1, 1, 1 };
|
||||||
gbl_contentPane.columnWeights = new double[] { 0.3, 1.0, 0.1 };
|
gbl_contentPane.columnWeights = new double[] { 0.03, 1.0, 0.1 };
|
||||||
gbl_contentPane.rowWeights = new double[] { 0.03, 0.001, 1.0, 0.005 };
|
gbl_contentPane.rowWeights = new double[] { 0.03, 0.001, 1.0, 0.005 };
|
||||||
contentPane.setLayout(gbl_contentPane);
|
contentPane.setLayout(gbl_contentPane);
|
||||||
|
|
||||||
messageList.setBorder(new EmptyBorder(space, space, space, space));
|
messageList.setBorder(new EmptyBorder(space, space, space, space));
|
||||||
|
|
||||||
scrollPane.setViewportView(messageList);
|
scrollPane.setViewportView(messageList);
|
||||||
|
scrollPane.addComponentListener(new ComponentAdapter() {
|
||||||
|
|
||||||
|
// updates list elements when list is resized
|
||||||
|
@Override
|
||||||
|
public void componentResized(ComponentEvent e) { messageList.synchronizeModel(); }
|
||||||
|
});
|
||||||
|
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
|
||||||
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
|
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
|
||||||
gbc_scrollPane.fill = GridBagConstraints.BOTH;
|
gbc_scrollPane.fill = GridBagConstraints.BOTH;
|
||||||
@ -117,7 +131,16 @@ public class ChatWindow extends JFrame {
|
|||||||
|
|
||||||
drawChatBox(gbc_scrollPane);
|
drawChatBox(gbc_scrollPane);
|
||||||
|
|
||||||
// Message enter field
|
// MessageEnterTextArea
|
||||||
|
messageEnterTextArea.addInputMethodListener(new InputMethodListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void inputMethodTextChanged(InputMethodEvent event) { checkMessageTextLength(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void caretPositionChanged(InputMethodEvent event) {}
|
||||||
|
});
|
||||||
|
|
||||||
messageEnterTextArea.addKeyListener(new KeyAdapter() {
|
messageEnterTextArea.addKeyListener(new KeyAdapter() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -125,29 +148,31 @@ public class ChatWindow extends JFrame {
|
|||||||
if (e.getKeyCode() == KeyEvent.VK_ENTER
|
if (e.getKeyCode() == KeyEvent.VK_ENTER
|
||||||
&& (Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0 || e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))
|
&& (Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0 || e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))
|
||||||
postMessage();
|
postMessage();
|
||||||
|
// Checking if text is too long
|
||||||
|
checkMessageTextLength();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints();
|
GridBagConstraints gbc_scrollPaneForTextInput = new GridBagConstraints();
|
||||||
gbc_messageEnterTextfield.fill = GridBagConstraints.BOTH;
|
gbc_scrollPaneForTextInput.fill = GridBagConstraints.BOTH;
|
||||||
gbc_messageEnterTextfield.gridx = 1;
|
gbc_scrollPaneForTextInput.gridx = 1;
|
||||||
gbc_messageEnterTextfield.gridy = 3;
|
gbc_scrollPaneForTextInput.gridy = 3;
|
||||||
|
|
||||||
gbc_messageEnterTextfield.insets = insets;
|
gbc_scrollPaneForTextInput.insets = insets;
|
||||||
|
|
||||||
contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield);
|
contentPane.add(messageEnterTextArea, gbc_scrollPaneForTextInput);
|
||||||
|
|
||||||
// Post Button
|
// Post Button
|
||||||
GridBagConstraints gbc_moveSelectionPostButton = new GridBagConstraints();
|
GridBagConstraints gbc_postButton = new GridBagConstraints();
|
||||||
|
|
||||||
gbc_moveSelectionPostButton.fill = GridBagConstraints.BOTH;
|
gbc_postButton.fill = GridBagConstraints.BOTH;
|
||||||
gbc_moveSelectionPostButton.gridx = 2;
|
gbc_postButton.gridx = 2;
|
||||||
gbc_moveSelectionPostButton.gridy = 3;
|
gbc_postButton.gridy = 3;
|
||||||
|
|
||||||
gbc_moveSelectionPostButton.insets = insets;
|
gbc_postButton.insets = insets;
|
||||||
|
|
||||||
postButton.addActionListener((evt) -> { postMessage(); });
|
postButton.addActionListener((evt) -> { postMessage(); });
|
||||||
contentPane.add(postButton, gbc_moveSelectionPostButton);
|
contentPane.add(postButton, gbc_postButton);
|
||||||
|
|
||||||
// Settings Button
|
// Settings Button
|
||||||
GridBagConstraints gbc_moveSelectionSettingsButton = new GridBagConstraints();
|
GridBagConstraints gbc_moveSelectionSettingsButton = new GridBagConstraints();
|
||||||
@ -180,9 +205,8 @@ public class ChatWindow extends JFrame {
|
|||||||
final JList<User> selectedUserList = (JList<User>) listSelectionEvent.getSource();
|
final JList<User> selectedUserList = (JList<User>) listSelectionEvent.getSource();
|
||||||
final User user = selectedUserList.getSelectedValue();
|
final User user = selectedUserList.getSelectedValue();
|
||||||
|
|
||||||
for (int i = 0; i < contentPane.getComponents().length; i++) {
|
for (int i = 0; i < contentPane.getComponents().length; i++)
|
||||||
if (contentPane.getComponent(i).equals(searchPane)) { drawChatBox(gbc_scrollPane); }
|
if (contentPane.getComponent(i).equals(searchPane)) drawChatBox(gbc_scrollPane);
|
||||||
}
|
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
// Select current chat
|
// Select current chat
|
||||||
currentChat = localDb.getChats().stream().filter(chat -> chat.getRecipient().getId() == user.getId()).findFirst().get();
|
currentChat = localDb.getChats().stream().filter(chat -> chat.getRecipient().getId() == user.getId()).findFirst().get();
|
||||||
@ -248,31 +272,25 @@ public class ChatWindow extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeUpdate(DocumentEvent evt) {
|
public void removeUpdate(DocumentEvent evt) {
|
||||||
if (client.isOnline()) {
|
if (client.isOnline()) if (searchField.getText().isEmpty()) {
|
||||||
if (searchField.getText().isEmpty()) {
|
|
||||||
contactsModel.clear();
|
contactsModel.clear();
|
||||||
revalidate();
|
revalidate();
|
||||||
repaint();
|
repaint();
|
||||||
} else {
|
} else try {
|
||||||
try {
|
|
||||||
client.sendEvent(new ContactSearchRequest(searchField.getText()));
|
client.sendEvent(new ContactSearchRequest(searchField.getText()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void insertUpdate(DocumentEvent evt) {
|
public void insertUpdate(DocumentEvent evt) {
|
||||||
if (client.isOnline()) {
|
if (client.isOnline()) try {
|
||||||
try {
|
|
||||||
client.sendEvent(new ContactSearchRequest(searchField.getText()));
|
client.sendEvent(new ContactSearchRequest(searchField.getText()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changedUpdate(DocumentEvent evt) {}
|
public void changedUpdate(DocumentEvent evt) {}
|
||||||
@ -289,8 +307,8 @@ public class ChatWindow extends JFrame {
|
|||||||
searchPane.add(cancelButton, gbc_cancelButton);
|
searchPane.add(cancelButton, gbc_cancelButton);
|
||||||
|
|
||||||
contactList.setModel(contactsModel);
|
contactList.setModel(contactsModel);
|
||||||
possibleContacts.setBorder(new EmptyBorder(space, space, space, space));
|
scrollForPossibleContacts.setBorder(new EmptyBorder(space, space, space, space));
|
||||||
possibleContacts.setViewportView(contactList);
|
scrollForPossibleContacts.setViewportView(contactList);
|
||||||
|
|
||||||
GridBagConstraints gbc_possibleContacts = new GridBagConstraints();
|
GridBagConstraints gbc_possibleContacts = new GridBagConstraints();
|
||||||
gbc_possibleContacts.fill = GridBagConstraints.BOTH;
|
gbc_possibleContacts.fill = GridBagConstraints.BOTH;
|
||||||
@ -300,7 +318,7 @@ public class ChatWindow extends JFrame {
|
|||||||
|
|
||||||
gbc_possibleContacts.insets = insets;
|
gbc_possibleContacts.insets = insets;
|
||||||
|
|
||||||
searchPane.add(possibleContacts, gbc_possibleContacts);
|
searchPane.add(scrollForPossibleContacts, gbc_possibleContacts);
|
||||||
|
|
||||||
// Contacts Header
|
// Contacts Header
|
||||||
GridBagConstraints gbc_contactsHeader = new GridBagConstraints();
|
GridBagConstraints gbc_contactsHeader = new GridBagConstraints();
|
||||||
@ -387,7 +405,9 @@ public class ChatWindow extends JFrame {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Listen to contact search results
|
// Listen to contact search results
|
||||||
EventBus.getInstance().register(ContactSearchResult.class, evt -> {
|
EventBus.getInstance()
|
||||||
|
.register(ContactSearchResult.class,
|
||||||
|
evt -> {
|
||||||
contactsModel.clear();
|
contactsModel.clear();
|
||||||
final java.util.List<User> contacts = evt.get();
|
final java.util.List<User> contacts = evt.get();
|
||||||
contacts.forEach(contactsModel::add);
|
contacts.forEach(contactsModel::add);
|
||||||
@ -427,14 +447,11 @@ public class ChatWindow extends JFrame {
|
|||||||
contentPane.setBackground(theme.getBackgroundColor());
|
contentPane.setBackground(theme.getBackgroundColor());
|
||||||
contentPane.setForeground(theme.getUserNameColor());
|
contentPane.setForeground(theme.getUserNameColor());
|
||||||
// messageList
|
// messageList
|
||||||
// messageList.setSelectionForeground(theme.getUserNameColor());
|
messageList.setForeground(theme.getMessageTextColor());
|
||||||
// messageList.setSelectionBackground(theme.getSelectionColor());
|
|
||||||
messageList.setForeground(theme.getMessageColorChat());
|
|
||||||
messageList.setBackground(theme.getCellColor());
|
messageList.setBackground(theme.getCellColor());
|
||||||
// scrollPane
|
// scrollPane
|
||||||
scrollPane.applyTheme(theme);
|
scrollPane.applyTheme(theme);
|
||||||
scrollPane.autoscroll();
|
scrollPane.autoscroll();
|
||||||
|
|
||||||
// messageEnterTextArea
|
// messageEnterTextArea
|
||||||
messageEnterTextArea.setCaretColor(theme.getTypingMessageColor());
|
messageEnterTextArea.setCaretColor(theme.getTypingMessageColor());
|
||||||
messageEnterTextArea.setForeground(theme.getTypingMessageColor());
|
messageEnterTextArea.setForeground(theme.getTypingMessageColor());
|
||||||
@ -465,9 +482,9 @@ public class ChatWindow extends JFrame {
|
|||||||
searchField.setForeground(theme.getUserNameColor());
|
searchField.setForeground(theme.getUserNameColor());
|
||||||
cancelButton.setBackground(theme.getInteractableBackgroundColor());
|
cancelButton.setBackground(theme.getInteractableBackgroundColor());
|
||||||
cancelButton.setForeground(theme.getInteractableForegroundColor());
|
cancelButton.setForeground(theme.getInteractableForegroundColor());
|
||||||
contactList.setForeground(theme.getMessageColorChat());
|
contactList.setForeground(theme.getMessageTextColor());
|
||||||
contactList.setBackground(theme.getCellColor());
|
contactList.setBackground(theme.getCellColor());
|
||||||
possibleContacts.applyTheme(theme);
|
scrollForPossibleContacts.applyTheme(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postMessage() {
|
private void postMessage() {
|
||||||
@ -477,7 +494,7 @@ public class ChatWindow extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!messageEnterTextArea.getText().isEmpty()) try {
|
if (!messageEnterTextArea.getText().isEmpty()) try {
|
||||||
|
checkMessageTextLength();
|
||||||
// Create message
|
// Create message
|
||||||
final Message message = new MessageBuilder(localDb.getUser().getId(), currentChat.getRecipient().getId(), localDb.getIdGenerator())
|
final Message message = new MessageBuilder(localDb.getUser().getId(), currentChat.getRecipient().getId(), localDb.getIdGenerator())
|
||||||
.setText(messageEnterTextArea.getText())
|
.setText(messageEnterTextArea.getText())
|
||||||
@ -575,4 +592,24 @@ public class ChatWindow extends JFrame {
|
|||||||
this.writeProxy = writeProxy;
|
this.writeProxy = writeProxy;
|
||||||
loadUsersAndChats();
|
loadUsersAndChats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the length of the text inside messageEnterTextArea >=
|
||||||
|
* {@link ChatWindow#MAX_MESSEAGE_LENGTH}
|
||||||
|
* and splits the text into the allowed part, if that is the case.
|
||||||
|
*
|
||||||
|
* @since Envoy v0.1-beta
|
||||||
|
*/
|
||||||
|
private void checkMessageTextLength() {
|
||||||
|
String input = messageEnterTextArea.getText();
|
||||||
|
if (input.length() >= MAX_MESSEAGE_LENGTH) {
|
||||||
|
messageEnterTextArea.setText(input.substring(0, MAX_MESSEAGE_LENGTH - 1));
|
||||||
|
// TODO: current notification is like being hit with a hammer, maybe it should
|
||||||
|
// be replaced with a more subtle notification
|
||||||
|
JOptionPane.showMessageDialog(messageEnterTextArea,
|
||||||
|
"the maximum length for a message has been reached",
|
||||||
|
"maximum message length reached",
|
||||||
|
JOptionPane.WARNING_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,15 @@ package envoy.client.ui;
|
|||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.ColorSpace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>envoy-clientChess</strong><br>
|
* This class further develops {@link java.awt.Color} by adding extra methods
|
||||||
* File: <strong>Color.javaEvent.java</strong><br>
|
* and more default colors.
|
||||||
|
*
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>Color.java</strong><br>
|
||||||
* Created: <strong>23.12.2019</strong><br>
|
* Created: <strong>23.12.2019</strong><br>
|
||||||
*
|
*
|
||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since Envoy v0.3-alpha
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("javadoc")
|
@SuppressWarnings("javadoc")
|
||||||
public class Color extends java.awt.Color {
|
public class Color extends java.awt.Color {
|
||||||
@ -98,11 +102,13 @@ public class Color extends java.awt.Color {
|
|||||||
/**
|
/**
|
||||||
* @return the inversion of this {@link Color} by replacing the red, green and
|
* @return the inversion of this {@link Color} by replacing the red, green and
|
||||||
* blue values by subtracting them form 255
|
* blue values by subtracting them form 255
|
||||||
|
* @since Envoy v0.3-alpha
|
||||||
*/
|
*/
|
||||||
public Color invert() { return new Color(255 - getRed(), 255 - getGreen(), 255 - getBlue()); }
|
public Color invert() { return new Color(255 - getRed(), 255 - getGreen(), 255 - getBlue()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the hex value of this {@link Color}
|
* @return the hex value of this {@link Color}
|
||||||
|
* @since Envoy v0.3-alpha
|
||||||
*/
|
*/
|
||||||
public String toHex() { return String.format("#%02x%02x%02x", getRed(), getGreen(), getBlue()); }
|
public String toHex() { return String.format("#%02x%02x%02x", getRed(), getGreen(), getBlue()); }
|
||||||
}
|
}
|
@ -39,9 +39,8 @@ public class ContactsSearchRenderer implements ComponentListCellRenderer<User> {
|
|||||||
panel.setForeground(list.getForeground());
|
panel.setForeground(list.getForeground());
|
||||||
}
|
}
|
||||||
|
|
||||||
JLabel display = new JLabel(String.format("<html><p style=\"color:%s\">%s</html>",
|
JLabel display = new JLabel(user.getName());
|
||||||
Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat().toHex(),
|
display.setForeground(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageTextColor());
|
||||||
user.getName()));
|
|
||||||
display.setAlignmentX(Component.LEFT_ALIGNMENT);
|
display.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
display.setAlignmentY(Component.CENTER_ALIGNMENT);
|
display.setAlignmentY(Component.CENTER_ALIGNMENT);
|
||||||
display.setFont(new Font("Arial", Font.PLAIN, 16));
|
display.setFont(new Font("Arial", Font.PLAIN, 16));
|
||||||
|
@ -2,6 +2,8 @@ package envoy.client.ui;
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ItemEvent;
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -80,20 +82,29 @@ public class LoginDialog extends JDialog {
|
|||||||
// Prepare handshake
|
// Prepare handshake
|
||||||
localDb.loadIdGenerator();
|
localDb.loadIdGenerator();
|
||||||
|
|
||||||
|
addWindowListener(new WindowAdapter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void windowClosing(WindowEvent e) { abortLogin(); }
|
||||||
|
});
|
||||||
|
|
||||||
initUi();
|
initUi();
|
||||||
|
|
||||||
okButton.addActionListener((evt) -> {
|
okButton.addActionListener((evt) -> {
|
||||||
try {
|
try {
|
||||||
if (registerCheckBox.isSelected()) {
|
if (registerCheckBox.isSelected()) {
|
||||||
// Check password equality
|
// Check password equality
|
||||||
if (Arrays.equals(passwordField.getPassword(), repeatPasswordField.getPassword()))
|
if (Arrays.equals(passwordField.getPassword(), repeatPasswordField.getPassword())) {
|
||||||
credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), true);
|
credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), true);
|
||||||
else {
|
performHandshake();
|
||||||
JOptionPane.showMessageDialog(this, "The repeated password is not the origional password!");
|
} else {
|
||||||
|
JOptionPane.showMessageDialog(this, "The repeated password is not the original password!");
|
||||||
clearPasswordFields();
|
clearPasswordFields();
|
||||||
}
|
}
|
||||||
} else credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
|
} else {
|
||||||
|
credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
|
||||||
performHandshake();
|
performHandshake();
|
||||||
|
}
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -105,7 +116,7 @@ public class LoginDialog extends JDialog {
|
|||||||
evt -> { clearPasswordFields(); errorMessage.setVisible(true); errorMessage.setText(evt.get()); });
|
evt -> { clearPasswordFields(); errorMessage.setVisible(true); errorMessage.setText(evt.get()); });
|
||||||
|
|
||||||
// Exit the application when the dialog is cancelled
|
// Exit the application when the dialog is cancelled
|
||||||
cancelButton.addActionListener(evt -> { logger.info("The login process has been cancelled. Exiting..."); System.exit(0); });
|
cancelButton.addActionListener(evt -> abortLogin());
|
||||||
|
|
||||||
// Log in directly if configured
|
// Log in directly if configured
|
||||||
if (config.hasLoginCredentials()) {
|
if (config.hasLoginCredentials()) {
|
||||||
@ -320,4 +331,14 @@ public class LoginDialog extends JDialog {
|
|||||||
cancelButton.setBackground(theme.getInteractableBackgroundColor());
|
cancelButton.setBackground(theme.getInteractableBackgroundColor());
|
||||||
cancelButton.setForeground(theme.getInteractableForegroundColor());
|
cancelButton.setForeground(theme.getInteractableForegroundColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuts the system down properly if the login was aborted.
|
||||||
|
*
|
||||||
|
* @since Envoy v0.1-beta
|
||||||
|
*/
|
||||||
|
private void abortLogin() {
|
||||||
|
logger.info("The login process has been cancelled. Exiting...");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,11 +1,10 @@
|
|||||||
package envoy.client.ui;
|
package envoy.client.ui;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Font;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.*;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
|
|
||||||
import envoy.client.data.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.ui.list.ComponentList;
|
import envoy.client.ui.list.ComponentList;
|
||||||
@ -21,13 +20,17 @@ import envoy.data.Message;
|
|||||||
*
|
*
|
||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @author Maximilian Käfer
|
* @author Maximilian Käfer
|
||||||
|
* @author Leon Hofmeister
|
||||||
* @since Envoy v0.1-alpha
|
* @since Envoy v0.1-alpha
|
||||||
*/
|
*/
|
||||||
public class MessageListRenderer implements ComponentListCellRenderer<Message> {
|
public class MessageListRenderer implements ComponentListCellRenderer<Message> {
|
||||||
|
|
||||||
|
private JTextArea messageTextArea;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JPanel getListCellComponent(ComponentList<? extends Message> list, Message value, boolean isSelected) {
|
public JPanel getListCellComponent(ComponentList<? extends Message> list, Message value, boolean isSelected) {
|
||||||
final JPanel panel = new JPanel();
|
final JPanel panel = new JPanel();
|
||||||
|
panel.setLayout(new BorderLayout());
|
||||||
final Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
|
final Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
|
||||||
|
|
||||||
// Panel background
|
// Panel background
|
||||||
@ -35,32 +38,56 @@ public class MessageListRenderer implements ComponentListCellRenderer<Message> {
|
|||||||
|
|
||||||
// TODO: Handle message attachments
|
// TODO: Handle message attachments
|
||||||
|
|
||||||
final String text = value.getText();
|
|
||||||
final String state = value.getStatus().toString();
|
final String state = value.getStatus().toString();
|
||||||
final String date = new SimpleDateFormat("dd.MM.yyyy HH.mm").format(value.getCreationDate());
|
final String date = new SimpleDateFormat("dd.MM.yyyy HH:mm").format(value.getCreationDate());
|
||||||
|
final String text = value.getText();
|
||||||
|
|
||||||
// Message text color
|
// The Label that displays the creation date of a message
|
||||||
String textColor = theme.getMessageColorChat().toHex();
|
JLabel dateLabel = new JLabel(date);
|
||||||
|
// Set the date color to be the value of DateColorChat
|
||||||
|
dateLabel.setForeground(theme.getDateColor());
|
||||||
|
|
||||||
// Message date color
|
panel.add(dateLabel, BorderLayout.NORTH);
|
||||||
String dateColor = theme.getDateColorChat().toHex();
|
|
||||||
|
|
||||||
panel.add(new JLabel(String.format("<html><p style=\"color:%s\"><b><small>%s</b></small><br><p style=\"color:%s\">%s :%s</html>",
|
// The JTextArea that displays the text content of a message and its status
|
||||||
dateColor,
|
messageTextArea = new JTextArea(text + System.getProperty("line.separator"));
|
||||||
date,
|
messageTextArea.setLineWrap(true);
|
||||||
textColor,
|
messageTextArea.setWrapStyleWord(true);
|
||||||
text,
|
messageTextArea.setAlignmentX(0.5f);
|
||||||
state)));
|
messageTextArea.setForeground(theme.getMessageTextColor());
|
||||||
|
messageTextArea.setBackground(panel.getBackground());
|
||||||
|
messageTextArea.setEditable(false);
|
||||||
|
|
||||||
|
panel.add(messageTextArea, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JLabel statusLabel = new JLabel(state);
|
||||||
|
statusLabel.setFont(new Font("Arial", Font.BOLD, 14));
|
||||||
|
Color statusColor;
|
||||||
|
switch (value.getStatus()) {
|
||||||
|
case WAITING:
|
||||||
|
statusColor = Color.gray;
|
||||||
|
break;
|
||||||
|
case SENT:
|
||||||
|
statusColor = Color.blue;
|
||||||
|
break;
|
||||||
|
case RECEIVED:
|
||||||
|
statusColor = Color.yellow;
|
||||||
|
break;
|
||||||
|
case READ:
|
||||||
|
statusColor = Color.green;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
statusColor = theme.getMessageTextColor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
statusLabel.setForeground(statusColor);
|
||||||
|
statusLabel.setBackground(panel.getBackground());
|
||||||
|
|
||||||
|
panel.add(statusLabel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
// Define some space to the messages below
|
// Define some space to the messages below
|
||||||
panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(), BorderFactory.createEtchedBorder()));
|
panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(), BorderFactory.createEtchedBorder()));
|
||||||
|
|
||||||
// Set the width to the list width
|
|
||||||
Dimension size = new Dimension(list.getWidth() - 25, panel.getPreferredSize().height);
|
|
||||||
panel.setMaximumSize(size);
|
|
||||||
panel.setMinimumSize(size);
|
|
||||||
panel.setPreferredSize(size);
|
|
||||||
|
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -51,7 +51,6 @@ public class Startup {
|
|||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
ClientConfig config = ClientConfig.getInstance();
|
ClientConfig config = ClientConfig.getInstance();
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> chatWindow = new ChatWindow());
|
SwingUtilities.invokeLater(() -> chatWindow = new ChatWindow());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -85,16 +85,18 @@ public class Theme implements Serializable {
|
|||||||
public Color getInteractableForegroundColor() { return colors.get("interactableForegroundColor"); }
|
public Color getInteractableForegroundColor() { return colors.get("interactableForegroundColor"); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return messageColorChat
|
* @return the {@link Color} in which the text content of a message should be
|
||||||
|
* displayed
|
||||||
* @since Envoy v0.2-alpha
|
* @since Envoy v0.2-alpha
|
||||||
*/
|
*/
|
||||||
public Color getMessageColorChat() { return colors.get("messageColorChat"); }
|
public Color getMessageTextColor() { return colors.get("messageColorChat"); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return dateColorChat
|
* @return the {@link Color} in which the creation date of a message should be
|
||||||
|
* displayed
|
||||||
* @since Envoy v0.2-alpha
|
* @since Envoy v0.2-alpha
|
||||||
*/
|
*/
|
||||||
public Color getDateColorChat() { return colors.get("dateColorChat"); }
|
public Color getDateColor() { return colors.get("dateColorChat"); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return selectionColor
|
* @return selectionColor
|
||||||
|
@ -82,6 +82,7 @@ public class ComponentList<E> extends JPanel {
|
|||||||
public void synchronizeModel() {
|
public void synchronizeModel() {
|
||||||
removeAll();
|
removeAll();
|
||||||
if (model != null) model.forEach(this::add);
|
if (model != null) model.forEach(this::add);
|
||||||
|
revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,7 +121,7 @@ public class ComponentList<E> extends JPanel {
|
|||||||
return new MouseAdapter() {
|
return new MouseAdapter() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { componentSelected(componentIndex); } }
|
public void mouseClicked(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) componentSelected(componentIndex); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +142,6 @@ public class ComponentList<E> extends JPanel {
|
|||||||
// Clear selection
|
// Clear selection
|
||||||
update(currentSelection, false);
|
update(currentSelection, false);
|
||||||
currentSelection = -1;
|
currentSelection = -1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Remove old selection
|
// Remove old selection
|
||||||
@ -152,7 +152,6 @@ public class ComponentList<E> extends JPanel {
|
|||||||
|
|
||||||
// Update current selection
|
// Update current selection
|
||||||
update(currentSelection, true);
|
update(currentSelection, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidate();
|
revalidate();
|
||||||
|
@ -34,6 +34,7 @@ public final class ComponentListModel<E> implements Iterable<E>, Serializable {
|
|||||||
*/
|
*/
|
||||||
public boolean add(E e) {
|
public boolean add(E e) {
|
||||||
if (componentList != null) componentList.add(e);
|
if (componentList != null) componentList.add(e);
|
||||||
|
componentList.revalidate();
|
||||||
return elements.add(e);
|
return elements.add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,8 +181,8 @@ public class ThemeCustomizationPanel extends SettingsPanel {
|
|||||||
buildCustomizeElement(theme, theme.getCellColor(), "Cells", "cellColor", 2);
|
buildCustomizeElement(theme, theme.getCellColor(), "Cells", "cellColor", 2);
|
||||||
buildCustomizeElement(theme, theme.getInteractableForegroundColor(), "Interactable Foreground", "interactableForegroundColor", 3);
|
buildCustomizeElement(theme, theme.getInteractableForegroundColor(), "Interactable Foreground", "interactableForegroundColor", 3);
|
||||||
buildCustomizeElement(theme, theme.getInteractableBackgroundColor(), "Interactable Background", "interactableBackgroundColor", 4);
|
buildCustomizeElement(theme, theme.getInteractableBackgroundColor(), "Interactable Background", "interactableBackgroundColor", 4);
|
||||||
buildCustomizeElement(theme, theme.getMessageColorChat(), "Messages Chat", "messageColorChat", 5);
|
buildCustomizeElement(theme, theme.getMessageTextColor(), "Messages Chat", "messageColorChat", 5);
|
||||||
buildCustomizeElement(theme, theme.getDateColorChat(), "Date Chat", "dateColorChat", 6);
|
buildCustomizeElement(theme, theme.getDateColor(), "Date Chat", "dateColorChat", 6);
|
||||||
buildCustomizeElement(theme, theme.getSelectionColor(), "Selection", "selectionColor", 7);
|
buildCustomizeElement(theme, theme.getSelectionColor(), "Selection", "selectionColor", 7);
|
||||||
buildCustomizeElement(theme, theme.getTypingMessageColor(), "Typing Message", "typingMessageColor", 8);
|
buildCustomizeElement(theme, theme.getTypingMessageColor(), "Typing Message", "typingMessageColor", 8);
|
||||||
buildCustomizeElement(theme, theme.getUserNameColor(), "User Names", "userNameColor", 9);
|
buildCustomizeElement(theme, theme.getUserNameColor(), "User Names", "userNameColor", 9);
|
||||||
|
Reference in New Issue
Block a user