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
	 delvh
					delvh