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:
		@@ -1,8 +1,7 @@
 | 
			
		||||
package envoy.client.ui;
 | 
			
		||||
 | 
			
		||||
import java.awt.*;
 | 
			
		||||
import java.awt.event.KeyAdapter;
 | 
			
		||||
import java.awt.event.KeyEvent;
 | 
			
		||||
import java.awt.event.*;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
@@ -41,17 +40,25 @@ import envoy.util.EnvoyLog;
 | 
			
		||||
 */
 | 
			
		||||
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
 | 
			
		||||
	private Client		client;
 | 
			
		||||
	private WriteProxy	writeProxy;
 | 
			
		||||
	private LocalDb		localDb;
 | 
			
		||||
	private Chat		currentChat;
 | 
			
		||||
 | 
			
		||||
	// GUI components
 | 
			
		||||
	private JPanel					contentPane				= new JPanel();
 | 
			
		||||
	private PrimaryTextArea			messageEnterTextArea	= new PrimaryTextArea(space);
 | 
			
		||||
	private JList<User>				userList				= new JList<>();
 | 
			
		||||
	private DefaultListModel<User>	userListModel			= new DefaultListModel<>();
 | 
			
		||||
	private Chat					currentChat;
 | 
			
		||||
	private ComponentList<Message>	messageList				= new ComponentList<>(new MessageListRenderer());
 | 
			
		||||
	private PrimaryScrollPane		scrollPane				= new PrimaryScrollPane();
 | 
			
		||||
	private JTextPane				textPane				= new JTextPane();
 | 
			
		||||
@@ -64,13 +71,13 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
	private PrimaryButton	addContact		= new PrimaryButton("+");
 | 
			
		||||
 | 
			
		||||
	// Search Contacts
 | 
			
		||||
	private final JPanel					searchPane			= new JPanel();
 | 
			
		||||
	private final PrimaryButton				cancelButton		= new PrimaryButton("x");
 | 
			
		||||
	private final PrimaryTextArea			searchField			= new PrimaryTextArea(space);
 | 
			
		||||
	private final PrimaryScrollPane			possibleContacts	= new PrimaryScrollPane();
 | 
			
		||||
	private final ContactsSearchRenderer	contactRenderer		= new ContactsSearchRenderer();
 | 
			
		||||
	private final ComponentListModel<User>	contactsModel		= new ComponentListModel<>();
 | 
			
		||||
	private final ComponentList<User>		contactList			= new ComponentList<>(contactRenderer);
 | 
			
		||||
	private final JPanel					searchPane					= new JPanel();
 | 
			
		||||
	private final PrimaryButton				cancelButton				= new PrimaryButton("x");
 | 
			
		||||
	private final PrimaryTextArea			searchField					= new PrimaryTextArea(space);
 | 
			
		||||
	private final PrimaryScrollPane			scrollForPossibleContacts	= new PrimaryScrollPane();
 | 
			
		||||
	private final ContactsSearchRenderer	contactRenderer				= new ContactsSearchRenderer();
 | 
			
		||||
	private final ComponentListModel<User>	contactsModel				= new ComponentListModel<>();
 | 
			
		||||
	private final ComponentList<User>		contactList					= new ComponentList<>(contactRenderer);
 | 
			
		||||
 | 
			
		||||
	private static final Logger logger = EnvoyLog.getLogger(ChatWindow.class);
 | 
			
		||||
 | 
			
		||||
@@ -98,13 +105,20 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
		GridBagLayout gbl_contentPane = new GridBagLayout();
 | 
			
		||||
		gbl_contentPane.columnWidths	= new int[] { 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 };
 | 
			
		||||
		contentPane.setLayout(gbl_contentPane);
 | 
			
		||||
 | 
			
		||||
		messageList.setBorder(new EmptyBorder(space, space, space, space));
 | 
			
		||||
 | 
			
		||||
		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();
 | 
			
		||||
		gbc_scrollPane.fill			= GridBagConstraints.BOTH;
 | 
			
		||||
@@ -117,7 +131,16 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
 | 
			
		||||
		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() {
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
@@ -125,29 +148,31 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
				if (e.getKeyCode() == KeyEvent.VK_ENTER
 | 
			
		||||
						&& (Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0 || e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))
 | 
			
		||||
					postMessage();
 | 
			
		||||
				// Checking if text is too long
 | 
			
		||||
				checkMessageTextLength();
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints();
 | 
			
		||||
		gbc_messageEnterTextfield.fill	= GridBagConstraints.BOTH;
 | 
			
		||||
		gbc_messageEnterTextfield.gridx	= 1;
 | 
			
		||||
		gbc_messageEnterTextfield.gridy	= 3;
 | 
			
		||||
		GridBagConstraints gbc_scrollPaneForTextInput = new GridBagConstraints();
 | 
			
		||||
		gbc_scrollPaneForTextInput.fill		= GridBagConstraints.BOTH;
 | 
			
		||||
		gbc_scrollPaneForTextInput.gridx	= 1;
 | 
			
		||||
		gbc_scrollPaneForTextInput.gridy	= 3;
 | 
			
		||||
 | 
			
		||||
		gbc_messageEnterTextfield.insets = insets;
 | 
			
		||||
		gbc_scrollPaneForTextInput.insets = insets;
 | 
			
		||||
 | 
			
		||||
		contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield);
 | 
			
		||||
		contentPane.add(messageEnterTextArea, gbc_scrollPaneForTextInput);
 | 
			
		||||
 | 
			
		||||
		// Post Button
 | 
			
		||||
		GridBagConstraints gbc_moveSelectionPostButton = new GridBagConstraints();
 | 
			
		||||
		GridBagConstraints gbc_postButton = new GridBagConstraints();
 | 
			
		||||
 | 
			
		||||
		gbc_moveSelectionPostButton.fill	= GridBagConstraints.BOTH;
 | 
			
		||||
		gbc_moveSelectionPostButton.gridx	= 2;
 | 
			
		||||
		gbc_moveSelectionPostButton.gridy	= 3;
 | 
			
		||||
		gbc_postButton.fill		= GridBagConstraints.BOTH;
 | 
			
		||||
		gbc_postButton.gridx	= 2;
 | 
			
		||||
		gbc_postButton.gridy	= 3;
 | 
			
		||||
 | 
			
		||||
		gbc_moveSelectionPostButton.insets = insets;
 | 
			
		||||
		gbc_postButton.insets = insets;
 | 
			
		||||
 | 
			
		||||
		postButton.addActionListener((evt) -> { postMessage(); });
 | 
			
		||||
		contentPane.add(postButton, gbc_moveSelectionPostButton);
 | 
			
		||||
		contentPane.add(postButton, gbc_postButton);
 | 
			
		||||
 | 
			
		||||
		// Settings Button
 | 
			
		||||
		GridBagConstraints gbc_moveSelectionSettingsButton = new GridBagConstraints();
 | 
			
		||||
@@ -180,9 +205,8 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
				final JList<User>	selectedUserList	= (JList<User>) listSelectionEvent.getSource();
 | 
			
		||||
				final User			user				= selectedUserList.getSelectedValue();
 | 
			
		||||
 | 
			
		||||
				for (int i = 0; i < contentPane.getComponents().length; i++) {
 | 
			
		||||
					if (contentPane.getComponent(i).equals(searchPane)) { drawChatBox(gbc_scrollPane); }
 | 
			
		||||
				}
 | 
			
		||||
				for (int i = 0; i < contentPane.getComponents().length; i++)
 | 
			
		||||
					if (contentPane.getComponent(i).equals(searchPane)) drawChatBox(gbc_scrollPane);
 | 
			
		||||
				if (user != null) {
 | 
			
		||||
					// Select current chat
 | 
			
		||||
					currentChat = localDb.getChats().stream().filter(chat -> chat.getRecipient().getId() == user.getId()).findFirst().get();
 | 
			
		||||
@@ -248,29 +272,23 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
			public void removeUpdate(DocumentEvent evt) {
 | 
			
		||||
				if (client.isOnline()) {
 | 
			
		||||
					if (searchField.getText().isEmpty()) {
 | 
			
		||||
						contactsModel.clear();
 | 
			
		||||
						revalidate();
 | 
			
		||||
						repaint();
 | 
			
		||||
					} else {
 | 
			
		||||
						try {
 | 
			
		||||
							client.sendEvent(new ContactSearchRequest(searchField.getText()));
 | 
			
		||||
						} catch (IOException e) {
 | 
			
		||||
							e.printStackTrace();
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				if (client.isOnline()) if (searchField.getText().isEmpty()) {
 | 
			
		||||
					contactsModel.clear();
 | 
			
		||||
					revalidate();
 | 
			
		||||
					repaint();
 | 
			
		||||
				} else try {
 | 
			
		||||
					client.sendEvent(new ContactSearchRequest(searchField.getText()));
 | 
			
		||||
				} catch (IOException e) {
 | 
			
		||||
					e.printStackTrace();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
			public void insertUpdate(DocumentEvent evt) {
 | 
			
		||||
				if (client.isOnline()) {
 | 
			
		||||
					try {
 | 
			
		||||
						client.sendEvent(new ContactSearchRequest(searchField.getText()));
 | 
			
		||||
					} catch (IOException e) {
 | 
			
		||||
						e.printStackTrace();
 | 
			
		||||
					}
 | 
			
		||||
				if (client.isOnline()) try {
 | 
			
		||||
					client.sendEvent(new ContactSearchRequest(searchField.getText()));
 | 
			
		||||
				} catch (IOException e) {
 | 
			
		||||
					e.printStackTrace();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -289,8 +307,8 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
		searchPane.add(cancelButton, gbc_cancelButton);
 | 
			
		||||
 | 
			
		||||
		contactList.setModel(contactsModel);
 | 
			
		||||
		possibleContacts.setBorder(new EmptyBorder(space, space, space, space));
 | 
			
		||||
		possibleContacts.setViewportView(contactList);
 | 
			
		||||
		scrollForPossibleContacts.setBorder(new EmptyBorder(space, space, space, space));
 | 
			
		||||
		scrollForPossibleContacts.setViewportView(contactList);
 | 
			
		||||
 | 
			
		||||
		GridBagConstraints gbc_possibleContacts = new GridBagConstraints();
 | 
			
		||||
		gbc_possibleContacts.fill		= GridBagConstraints.BOTH;
 | 
			
		||||
@@ -300,7 +318,7 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
 | 
			
		||||
		gbc_possibleContacts.insets = insets;
 | 
			
		||||
 | 
			
		||||
		searchPane.add(possibleContacts, gbc_possibleContacts);
 | 
			
		||||
		searchPane.add(scrollForPossibleContacts, gbc_possibleContacts);
 | 
			
		||||
 | 
			
		||||
		// Contacts Header
 | 
			
		||||
		GridBagConstraints gbc_contactsHeader = new GridBagConstraints();
 | 
			
		||||
@@ -387,13 +405,15 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		// Listen to contact search results
 | 
			
		||||
		EventBus.getInstance().register(ContactSearchResult.class, evt -> {
 | 
			
		||||
			contactsModel.clear();
 | 
			
		||||
			final java.util.List<User> contacts = evt.get();
 | 
			
		||||
			contacts.forEach(contactsModel::add);
 | 
			
		||||
			revalidate();
 | 
			
		||||
			repaint();
 | 
			
		||||
		});
 | 
			
		||||
		EventBus.getInstance()
 | 
			
		||||
			.register(ContactSearchResult.class,
 | 
			
		||||
					evt -> {
 | 
			
		||||
						contactsModel.clear();
 | 
			
		||||
						final java.util.List<User> contacts = evt.get();
 | 
			
		||||
						contacts.forEach(contactsModel::add);
 | 
			
		||||
						revalidate();
 | 
			
		||||
						repaint();
 | 
			
		||||
					});
 | 
			
		||||
 | 
			
		||||
		// Add new contacts to the contact list
 | 
			
		||||
		EventBus.getInstance().register(ContactOperationEvent.class, evt -> {
 | 
			
		||||
@@ -427,14 +447,11 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
		contentPane.setBackground(theme.getBackgroundColor());
 | 
			
		||||
		contentPane.setForeground(theme.getUserNameColor());
 | 
			
		||||
		// messageList
 | 
			
		||||
		// messageList.setSelectionForeground(theme.getUserNameColor());
 | 
			
		||||
		// messageList.setSelectionBackground(theme.getSelectionColor());
 | 
			
		||||
		messageList.setForeground(theme.getMessageColorChat());
 | 
			
		||||
		messageList.setForeground(theme.getMessageTextColor());
 | 
			
		||||
		messageList.setBackground(theme.getCellColor());
 | 
			
		||||
		// scrollPane
 | 
			
		||||
		scrollPane.applyTheme(theme);
 | 
			
		||||
		scrollPane.autoscroll();
 | 
			
		||||
 | 
			
		||||
		// messageEnterTextArea
 | 
			
		||||
		messageEnterTextArea.setCaretColor(theme.getTypingMessageColor());
 | 
			
		||||
		messageEnterTextArea.setForeground(theme.getTypingMessageColor());
 | 
			
		||||
@@ -465,9 +482,9 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
		searchField.setForeground(theme.getUserNameColor());
 | 
			
		||||
		cancelButton.setBackground(theme.getInteractableBackgroundColor());
 | 
			
		||||
		cancelButton.setForeground(theme.getInteractableForegroundColor());
 | 
			
		||||
		contactList.setForeground(theme.getMessageColorChat());
 | 
			
		||||
		contactList.setForeground(theme.getMessageTextColor());
 | 
			
		||||
		contactList.setBackground(theme.getCellColor());
 | 
			
		||||
		possibleContacts.applyTheme(theme);
 | 
			
		||||
		scrollForPossibleContacts.applyTheme(theme);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void postMessage() {
 | 
			
		||||
@@ -477,7 +494,7 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!messageEnterTextArea.getText().isEmpty()) try {
 | 
			
		||||
 | 
			
		||||
			checkMessageTextLength();
 | 
			
		||||
			// Create message
 | 
			
		||||
			final Message message = new MessageBuilder(localDb.getUser().getId(), currentChat.getRecipient().getId(), localDb.getIdGenerator())
 | 
			
		||||
				.setText(messageEnterTextArea.getText())
 | 
			
		||||
@@ -575,4 +592,24 @@ public class ChatWindow extends JFrame {
 | 
			
		||||
		this.writeProxy	= writeProxy;
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Project: <strong>envoy-clientChess</strong><br>
 | 
			
		||||
 * File: <strong>Color.javaEvent.java</strong><br>
 | 
			
		||||
 * This class further develops {@link java.awt.Color} by adding extra methods
 | 
			
		||||
 * and more default colors.
 | 
			
		||||
 *
 | 
			
		||||
 * Project: <strong>envoy-client</strong><br>
 | 
			
		||||
 * File: <strong>Color.java</strong><br>
 | 
			
		||||
 * Created: <strong>23.12.2019</strong><br>
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * @author Kai S. K. Engelbart
 | 
			
		||||
 * @since Envoy v0.3-alpha
 | 
			
		||||
 */
 | 
			
		||||
@SuppressWarnings("javadoc")
 | 
			
		||||
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
 | 
			
		||||
	 *         blue values by subtracting them form 255
 | 
			
		||||
	 * @since Envoy v0.3-alpha
 | 
			
		||||
	 */
 | 
			
		||||
	public Color invert() { return new Color(255 - getRed(), 255 - getGreen(), 255 - getBlue()); }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @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()); }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,8 @@ public class ContactsSearchRenderer implements ComponentListCellRenderer<User> {
 | 
			
		||||
			panel.setForeground(list.getForeground());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		JLabel display = new JLabel(String.format("<html><p style=\"color:%s\">%s</html>",
 | 
			
		||||
				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat().toHex(),
 | 
			
		||||
				user.getName()));
 | 
			
		||||
		JLabel display = new JLabel(user.getName());
 | 
			
		||||
		display.setForeground(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageTextColor());
 | 
			
		||||
		display.setAlignmentX(Component.LEFT_ALIGNMENT);
 | 
			
		||||
		display.setAlignmentY(Component.CENTER_ALIGNMENT);
 | 
			
		||||
		display.setFont(new Font("Arial", Font.PLAIN, 16));
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,8 @@ package envoy.client.ui;
 | 
			
		||||
 | 
			
		||||
import java.awt.*;
 | 
			
		||||
import java.awt.event.ItemEvent;
 | 
			
		||||
import java.awt.event.WindowAdapter;
 | 
			
		||||
import java.awt.event.WindowEvent;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.security.NoSuchAlgorithmException;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
@@ -80,20 +82,29 @@ public class LoginDialog extends JDialog {
 | 
			
		||||
		// Prepare handshake
 | 
			
		||||
		localDb.loadIdGenerator();
 | 
			
		||||
 | 
			
		||||
		addWindowListener(new WindowAdapter() {
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
			public void windowClosing(WindowEvent e) { abortLogin(); }
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		initUi();
 | 
			
		||||
 | 
			
		||||
		okButton.addActionListener((evt) -> {
 | 
			
		||||
			try {
 | 
			
		||||
				if (registerCheckBox.isSelected()) {
 | 
			
		||||
					// 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);
 | 
			
		||||
					else {
 | 
			
		||||
						JOptionPane.showMessageDialog(this, "The repeated password is not the origional password!");
 | 
			
		||||
						performHandshake();
 | 
			
		||||
					} else {
 | 
			
		||||
						JOptionPane.showMessageDialog(this, "The repeated password is not the original password!");
 | 
			
		||||
						clearPasswordFields();
 | 
			
		||||
					}
 | 
			
		||||
				} else credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
 | 
			
		||||
				performHandshake();
 | 
			
		||||
				} else {
 | 
			
		||||
					credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
 | 
			
		||||
					performHandshake();
 | 
			
		||||
				}
 | 
			
		||||
			} catch (NoSuchAlgorithmException e) {
 | 
			
		||||
				e.printStackTrace();
 | 
			
		||||
			}
 | 
			
		||||
@@ -105,7 +116,7 @@ public class LoginDialog extends JDialog {
 | 
			
		||||
					evt -> { clearPasswordFields(); errorMessage.setVisible(true); errorMessage.setText(evt.get()); });
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		if (config.hasLoginCredentials()) {
 | 
			
		||||
@@ -320,4 +331,14 @@ public class LoginDialog extends JDialog {
 | 
			
		||||
		cancelButton.setBackground(theme.getInteractableBackgroundColor());
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
import java.awt.Dimension;
 | 
			
		||||
import java.awt.BorderLayout;
 | 
			
		||||
import java.awt.Font;
 | 
			
		||||
import java.text.SimpleDateFormat;
 | 
			
		||||
 | 
			
		||||
import javax.swing.BorderFactory;
 | 
			
		||||
import javax.swing.JLabel;
 | 
			
		||||
import javax.swing.JPanel;
 | 
			
		||||
import javax.swing.*;
 | 
			
		||||
 | 
			
		||||
import envoy.client.data.Settings;
 | 
			
		||||
import envoy.client.ui.list.ComponentList;
 | 
			
		||||
@@ -21,46 +20,74 @@ import envoy.data.Message;
 | 
			
		||||
 *
 | 
			
		||||
 * @author Kai S. K. Engelbart
 | 
			
		||||
 * @author Maximilian Käfer
 | 
			
		||||
 * @author Leon Hofmeister
 | 
			
		||||
 * @since Envoy v0.1-alpha
 | 
			
		||||
 */
 | 
			
		||||
public class MessageListRenderer implements ComponentListCellRenderer<Message> {
 | 
			
		||||
 | 
			
		||||
	private JTextArea messageTextArea;
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public JPanel getListCellComponent(ComponentList<? extends Message> list, Message value, boolean isSelected) {
 | 
			
		||||
		final JPanel	panel	= new JPanel();
 | 
			
		||||
		final Theme		theme	= Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
 | 
			
		||||
		final JPanel panel = new JPanel();
 | 
			
		||||
		panel.setLayout(new BorderLayout());
 | 
			
		||||
		final Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
 | 
			
		||||
 | 
			
		||||
		// Panel background
 | 
			
		||||
		panel.setBackground(isSelected ? theme.getSelectionColor() : theme.getCellColor());
 | 
			
		||||
 | 
			
		||||
		// TODO: Handle message attachments
 | 
			
		||||
 | 
			
		||||
		final String	text	= value.getText();
 | 
			
		||||
		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
 | 
			
		||||
		String textColor = theme.getMessageColorChat().toHex();
 | 
			
		||||
		// The Label that displays the creation date of a message
 | 
			
		||||
		JLabel dateLabel = new JLabel(date);
 | 
			
		||||
		// Set the date color to be the value of DateColorChat
 | 
			
		||||
		dateLabel.setForeground(theme.getDateColor());
 | 
			
		||||
 | 
			
		||||
		// Message date color
 | 
			
		||||
		String dateColor = theme.getDateColorChat().toHex();
 | 
			
		||||
		panel.add(dateLabel, BorderLayout.NORTH);
 | 
			
		||||
 | 
			
		||||
		panel.add(new JLabel(String.format("<html><p style=\"color:%s\"><b><small>%s</b></small><br><p style=\"color:%s\">%s :%s</html>",
 | 
			
		||||
				dateColor,
 | 
			
		||||
				date,
 | 
			
		||||
				textColor,
 | 
			
		||||
				text,
 | 
			
		||||
				state)));
 | 
			
		||||
		// The JTextArea that displays the text content of a message and its status
 | 
			
		||||
		messageTextArea = new JTextArea(text + System.getProperty("line.separator"));
 | 
			
		||||
		messageTextArea.setLineWrap(true);
 | 
			
		||||
		messageTextArea.setWrapStyleWord(true);
 | 
			
		||||
		messageTextArea.setAlignmentX(0.5f);
 | 
			
		||||
		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
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,6 @@ public class Startup {
 | 
			
		||||
	 */
 | 
			
		||||
	public static void main(String[] args) {
 | 
			
		||||
		ClientConfig config = ClientConfig.getInstance();
 | 
			
		||||
 | 
			
		||||
		SwingUtilities.invokeLater(() -> chatWindow = new ChatWindow());
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
 
 | 
			
		||||
@@ -85,16 +85,18 @@ public class Theme implements Serializable {
 | 
			
		||||
	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
 | 
			
		||||
	 */
 | 
			
		||||
	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
 | 
			
		||||
	 */
 | 
			
		||||
	public Color getDateColorChat() { return colors.get("dateColorChat"); }
 | 
			
		||||
	public Color getDateColor() { return colors.get("dateColorChat"); }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @return selectionColor
 | 
			
		||||
 
 | 
			
		||||
@@ -82,6 +82,7 @@ public class ComponentList<E> extends JPanel {
 | 
			
		||||
	public void synchronizeModel() {
 | 
			
		||||
		removeAll();
 | 
			
		||||
		if (model != null) model.forEach(this::add);
 | 
			
		||||
		revalidate();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
@@ -120,7 +121,7 @@ public class ComponentList<E> extends JPanel {
 | 
			
		||||
		return new MouseAdapter() {
 | 
			
		||||
 | 
			
		||||
			@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
 | 
			
		||||
			update(currentSelection, false);
 | 
			
		||||
			currentSelection = -1;
 | 
			
		||||
			
 | 
			
		||||
		} else {
 | 
			
		||||
 | 
			
		||||
			// Remove old selection
 | 
			
		||||
@@ -152,7 +152,6 @@ public class ComponentList<E> extends JPanel {
 | 
			
		||||
 | 
			
		||||
			// Update current selection
 | 
			
		||||
			update(currentSelection, true);
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		revalidate();
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ public final class ComponentListModel<E> implements Iterable<E>, Serializable {
 | 
			
		||||
	 */
 | 
			
		||||
	public boolean add(E e) {
 | 
			
		||||
		if (componentList != null) componentList.add(e);
 | 
			
		||||
		componentList.revalidate();
 | 
			
		||||
		return elements.add(e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -181,8 +181,8 @@ public class ThemeCustomizationPanel extends SettingsPanel {
 | 
			
		||||
		buildCustomizeElement(theme, theme.getCellColor(), "Cells", "cellColor", 2);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getInteractableForegroundColor(), "Interactable Foreground", "interactableForegroundColor", 3);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getInteractableBackgroundColor(), "Interactable Background", "interactableBackgroundColor", 4);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getMessageColorChat(), "Messages Chat", "messageColorChat", 5);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getDateColorChat(), "Date Chat", "dateColorChat", 6);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getMessageTextColor(), "Messages Chat", "messageColorChat", 5);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getDateColor(), "Date Chat", "dateColorChat", 6);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getSelectionColor(), "Selection", "selectionColor", 7);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getTypingMessageColor(), "Typing Message", "typingMessageColor", 8);
 | 
			
		||||
		buildCustomizeElement(theme, theme.getUserNameColor(), "User Names", "userNameColor", 9);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user