Implemented ComponentList rendering and integration of message list
This commit is contained in:
		| @@ -12,7 +12,6 @@ import javax.swing.border.EmptyBorder; | ||||
| import envoy.client.*; | ||||
| import envoy.client.event.ThemeChangeEvent; | ||||
| import envoy.client.ui.list.ComponentList; | ||||
| import envoy.client.ui.list.ComponentListModel; | ||||
| import envoy.client.ui.settings.SettingsScreen; | ||||
| import envoy.client.util.EnvoyLog; | ||||
| import envoy.data.Message; | ||||
| @@ -32,27 +31,29 @@ import envoy.event.EventBus; | ||||
|  */ | ||||
| public class ChatWindow extends JFrame { | ||||
|  | ||||
| 	private static final long serialVersionUID = 6865098428255463649L; | ||||
|  | ||||
| 	// User specific objects | ||||
| 	private Client	client; | ||||
| 	private LocalDB	localDB; | ||||
|  | ||||
| 	// GUI components | ||||
| 	private JPanel				contentPane				= new JPanel(); | ||||
| 	private PrimaryTextArea		messageEnterTextArea	= new PrimaryTextArea(space); | ||||
| 	private JList<User>			userList				= new JList<>(); | ||||
| 	private Chat				currentChat; | ||||
| 	private ComponentList<Message>	messageList; | ||||
| 	private PrimaryScrollPane	scrollPane				= new PrimaryScrollPane(); | ||||
| 	private JTextPane			textPane				= new JTextPane(); | ||||
| 	private PrimaryButton		postButton				= new PrimaryButton("Post"); | ||||
| 	private PrimaryButton		settingsButton			= new PrimaryButton("Settings"); | ||||
|  | ||||
| 	private static int space = 4; | ||||
| 	private JPanel					contentPane				= new JPanel(); | ||||
| 	private PrimaryTextArea			messageEnterTextArea	= new PrimaryTextArea(space); | ||||
| 	private JList<User>				userList				= new JList<>(); | ||||
| 	private Chat					currentChat; | ||||
| 	private ComponentList<Message>	messageList				= new ComponentList<>(new MessageListRenderer()); | ||||
| 	private PrimaryScrollPane		scrollPane				= new PrimaryScrollPane(); | ||||
| 	private JTextPane				textPane				= new JTextPane(); | ||||
| 	private PrimaryButton			postButton				= new PrimaryButton("Post"); | ||||
| 	private PrimaryButton			settingsButton			= new PrimaryButton("Settings"); | ||||
|  | ||||
| 	private static final Logger logger = EnvoyLog.getLogger(ChatWindow.class.getSimpleName()); | ||||
|  | ||||
| 	// GUI component spacing | ||||
| 	private final static int	space	= 4; | ||||
| 	private static final Insets	insets	= new Insets(space, space, space, space); | ||||
|  | ||||
| 	private static final long serialVersionUID = 6865098428255463649L; | ||||
|  | ||||
| 	/** | ||||
| 	 * Initializes a {@link JFrame} with UI elements used to send and read messages | ||||
| 	 * to different users. | ||||
| @@ -75,7 +76,6 @@ public class ChatWindow extends JFrame { | ||||
| 		gbl_contentPane.rowWeights		= new double[] { 0.05, 1.0, 0.07 }; | ||||
| 		contentPane.setLayout(gbl_contentPane); | ||||
|  | ||||
| 		messageList = new ComponentList<>(new ComponentListModel<>(), new MessageListRenderer()); | ||||
| 		// TODO: messageList.setFocusTraversalKeysEnabled(false); | ||||
| 		// messageList.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); | ||||
|  | ||||
| @@ -91,7 +91,7 @@ public class ChatWindow extends JFrame { | ||||
| 		gbc_scrollPane.gridx		= 1; | ||||
| 		gbc_scrollPane.gridy		= 1; | ||||
|  | ||||
| 		gbc_scrollPane.insets = new Insets(space, space, space, space); | ||||
| 		gbc_scrollPane.insets = insets; | ||||
| 		contentPane.add(scrollPane, gbc_scrollPane); | ||||
|  | ||||
| 		// Message enter field | ||||
| @@ -100,7 +100,7 @@ public class ChatWindow extends JFrame { | ||||
| 			@Override | ||||
| 			public void keyReleased(KeyEvent e) { | ||||
| 				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(); | ||||
| 			} | ||||
| 		}); | ||||
| @@ -110,7 +110,7 @@ public class ChatWindow extends JFrame { | ||||
| 		gbc_messageEnterTextfield.gridx	= 1; | ||||
| 		gbc_messageEnterTextfield.gridy	= 2; | ||||
|  | ||||
| 		gbc_messageEnterTextfield.insets = new Insets(space, space, space, space); | ||||
| 		gbc_messageEnterTextfield.insets = insets; | ||||
|  | ||||
| 		contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield); | ||||
|  | ||||
| @@ -121,7 +121,7 @@ public class ChatWindow extends JFrame { | ||||
| 		gbc_moveSelectionPostButton.gridx	= 2; | ||||
| 		gbc_moveSelectionPostButton.gridy	= 2; | ||||
|  | ||||
| 		gbc_moveSelectionPostButton.insets = new Insets(space, space, space, space); | ||||
| 		gbc_moveSelectionPostButton.insets = insets; | ||||
|  | ||||
| 		postButton.addActionListener((evt) -> { postMessage(); }); | ||||
| 		contentPane.add(postButton, gbc_moveSelectionPostButton); | ||||
| @@ -133,7 +133,7 @@ public class ChatWindow extends JFrame { | ||||
| 		gbc_moveSelectionSettingsButton.gridx	= 2; | ||||
| 		gbc_moveSelectionSettingsButton.gridy	= 0; | ||||
|  | ||||
| 		gbc_moveSelectionSettingsButton.insets = new Insets(space, space, space, space); | ||||
| 		gbc_moveSelectionSettingsButton.insets = insets; | ||||
|  | ||||
| 		settingsButton.addActionListener((evt) -> { | ||||
| 			try { | ||||
| @@ -154,7 +154,7 @@ public class ChatWindow extends JFrame { | ||||
| 		gbc_partnerName.gridx	= 1; | ||||
| 		gbc_partnerName.gridy	= 0; | ||||
|  | ||||
| 		gbc_partnerName.insets = new Insets(space, space, space, space); | ||||
| 		gbc_partnerName.insets = insets; | ||||
| 		contentPane.add(textPane, gbc_partnerName); | ||||
|  | ||||
| 		userList.setCellRenderer(new UserListRenderer()); | ||||
| @@ -187,7 +187,7 @@ public class ChatWindow extends JFrame { | ||||
| 		gbc_userList.gridx	= 0; | ||||
| 		gbc_userList.gridy	= 1; | ||||
| 		gbc_userList.anchor	= GridBagConstraints.PAGE_START; | ||||
| 		gbc_userList.insets	= new Insets(space, space, space, space); | ||||
| 		gbc_userList.insets	= insets; | ||||
|  | ||||
| 		applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); | ||||
|  | ||||
| @@ -252,15 +252,18 @@ public class ChatWindow extends JFrame { | ||||
| 				.build(); | ||||
|  | ||||
| 			// Send message | ||||
| 			// TODO: Store offline messages | ||||
| 			client.sendMessage(message); | ||||
|  | ||||
| 			// Add message to LocalDB and update UI | ||||
| 			currentChat.appendMessage(message); | ||||
| 			messageList.setModel(currentChat.getModel()); | ||||
| 			// messageList.setModel(currentChat.getModel()); | ||||
|  | ||||
| 			// Clear text field | ||||
| 			messageEnterTextArea.setText(""); | ||||
| 			contentPane.revalidate(); | ||||
|  | ||||
| 			revalidate(); | ||||
| 			repaint(); | ||||
| 		} catch (Exception e) { | ||||
| 			JOptionPane.showMessageDialog(this, | ||||
| 					"An exception occured while sending a message. See the log for more details.", | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| package envoy.client.ui; | ||||
|  | ||||
| import java.awt.Component; | ||||
| import java.text.SimpleDateFormat; | ||||
|  | ||||
| import javax.swing.JComponent; | ||||
| import javax.swing.JLabel; | ||||
| import javax.swing.border.EmptyBorder; | ||||
|  | ||||
| import envoy.client.Settings; | ||||
| import envoy.client.ui.list.ComponentList; | ||||
| @@ -21,23 +22,22 @@ import envoy.data.Message; | ||||
|  * @author Maximilian Käfer | ||||
|  * @since Envoy v0.1-alpha | ||||
|  */ | ||||
| public class MessageListRenderer extends JLabel implements ComponentListCellRenderer<Message> { | ||||
|  | ||||
| 	private static final long serialVersionUID = 5164417379767181198L; | ||||
| public class MessageListRenderer implements ComponentListCellRenderer<Message> { | ||||
|  | ||||
| 	@Override | ||||
| 	public Component getListCellComponent(ComponentList<? extends Message> list, Message value, boolean isSelected) { | ||||
| 	public JComponent getListCellComponent(ComponentList<? extends Message> list, Message value, boolean isSelected) { | ||||
| 		final JLabel label = new JLabel(); | ||||
| 		if (isSelected) { | ||||
| 			setBackground(Color.DARK_GRAY); | ||||
| 			setForeground(Color.RED); | ||||
| //			setBackground(list.getSelectionBackground()); | ||||
| //			setForeground(list.getSelectionForeground()); | ||||
| 			label.setBackground(Color.DARK_GRAY); | ||||
| 			label.setForeground(Color.RED); | ||||
| 			// setBackground(list.getSelectionBackground()); | ||||
| 			// setForeground(list.getSelectionForeground()); | ||||
| 		} else { | ||||
| 			setBackground(list.getBackground()); | ||||
| 			setForeground(list.getForeground()); | ||||
| 			label.setBackground(list.getBackground()); | ||||
| 			label.setForeground(list.getForeground()); | ||||
| 		} | ||||
|  | ||||
| 		setOpaque(true); | ||||
| 		label.setOpaque(true); | ||||
|  | ||||
| 		// TODO: Handle message attachments | ||||
|  | ||||
| @@ -51,12 +51,16 @@ public class MessageListRenderer extends JLabel implements ComponentListCellRend | ||||
| 		// Getting the DateColor in the Chat of the current theme | ||||
| 		String dateColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat().toHex(); | ||||
|  | ||||
| 		setText(String.format("<html><p style=\"color:%s\"><b><small>%s</b></small><br><p style=\"color:%s\">%s :%s</html>", | ||||
| 		label.setText(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)); | ||||
| 		return this; | ||||
|  | ||||
| 		// Define some space to the components above and below | ||||
| 		label.setBorder(new EmptyBorder(0, 0, 15, 0)); | ||||
|  | ||||
| 		return label; | ||||
| 	} | ||||
| } | ||||
| @@ -7,28 +7,34 @@ import javax.swing.JPanel; | ||||
|  * Project: <strong>envoy-client</strong><br> | ||||
|  * File: <strong>ComponentList.java</strong><br> | ||||
|  * Created: <strong>25.01.2020</strong><br> | ||||
|  *  | ||||
|  * | ||||
|  * @author Kai S. K. Engelbart | ||||
|  * @since Envoy v0.3-alpha | ||||
|  */ | ||||
| public class ComponentList<E> extends JPanel { | ||||
|  | ||||
| 	private ComponentListModel<E>			model; | ||||
| 	private ComponentListCellRenderer<E> renderer; | ||||
| 	private ComponentListCellRenderer<E>	renderer; | ||||
|  | ||||
| 	private static final long serialVersionUID = 1759644503942876737L; | ||||
|  | ||||
| 	public ComponentList(ComponentListModel<E> model, ComponentListCellRenderer<E> renderer) { | ||||
| 	public ComponentList(ComponentListCellRenderer<E> renderer) { | ||||
| 		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); | ||||
| 		this.model		= model; | ||||
| 		this.renderer	= renderer; | ||||
| 		this.renderer = renderer; | ||||
| 	} | ||||
|  | ||||
| 	public ComponentList(ComponentListModel<E> model, ComponentListCellRenderer<E> renderer) { | ||||
| 		this(renderer); | ||||
| 		this.model = model; | ||||
| 		setModel(model); | ||||
| 	} | ||||
|  | ||||
| 	public void setModel(ComponentListModel<E> model) { | ||||
| 		// Remove old model | ||||
| 		this.model.clear(); | ||||
| 		this.model.setComponentList(null); | ||||
| 		if (this.model != null) { | ||||
| 			this.model.clear(); | ||||
| 			this.model.setComponentList(null); | ||||
| 		} | ||||
|  | ||||
| 		// Synchronize with new model | ||||
| 		this.model = model; | ||||
| @@ -40,9 +46,10 @@ public class ComponentList<E> extends JPanel { | ||||
| 		add(renderer.getListCellComponent(this, elem, false)); | ||||
| 	} | ||||
|  | ||||
| 	private void synchronizeModel() { | ||||
| 	void synchronizeModel() { | ||||
| 		removeAll(); | ||||
| 		for (E elem : model) | ||||
| 			add(renderer.getListCellComponent(this, elem, false)); | ||||
| 		if (model != null) | ||||
| 			for (E elem : model) | ||||
| 				add(renderer.getListCellComponent(this, elem, false)); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| package envoy.client.ui.list; | ||||
|  | ||||
| import java.awt.Component; | ||||
| import javax.swing.JComponent; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>envoy-client</strong><br> | ||||
|  * File: <strong>ComponentListCellRenderer.java</strong><br> | ||||
|  * Created: <strong>25.01.2020</strong><br> | ||||
|  *  | ||||
|  * | ||||
|  * @author Kai S. K. Engelbart | ||||
|  * @since Envoy v0.3-alpha | ||||
|  */ | ||||
| public interface ComponentListCellRenderer<E> { | ||||
|  | ||||
| 	Component getListCellComponent(ComponentList<? extends E> list, E value, boolean isSelected); | ||||
| 	JComponent getListCellComponent(ComponentList<? extends E> list, E value, boolean isSelected); | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package envoy.client.ui.list; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
| @@ -8,19 +9,21 @@ import java.util.List; | ||||
|  * Project: <strong>envoy-client</strong><br> | ||||
|  * File: <strong>ComponentListModel.java</strong><br> | ||||
|  * Created: <strong>25.01.2020</strong><br> | ||||
|  *  | ||||
|  * | ||||
|  * @author Kai S. K. Engelbart | ||||
|  * @since Envoy v0.3-alpha | ||||
|  */ | ||||
| public final class ComponentListModel<E> implements Iterable<E> { | ||||
| public final class ComponentListModel<E> implements Iterable<E>, Serializable { | ||||
|  | ||||
| 	private List<E>				elements	= new ArrayList<>(); | ||||
| 	private ComponentList<E>	componentList; | ||||
| 	private List<E>						elements	= new ArrayList<>(); | ||||
| 	transient private ComponentList<E>	componentList; | ||||
|  | ||||
| 	private static final long serialVersionUID = 4815005915255497331L; | ||||
|  | ||||
| 	/** | ||||
| 	 * Adds an element to this model and notifies the associated | ||||
| 	 * {@link ComponentList} to add the corresponding component. | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param e the element to add | ||||
| 	 * @return {@code true} | ||||
| 	 * @see java.util.List#add(java.lang.Object) | ||||
| @@ -33,7 +36,7 @@ public final class ComponentListModel<E> implements Iterable<E> { | ||||
| 	/** | ||||
| 	 * Removes all elements from this model and clears the associated | ||||
| 	 * {@link ComponentList}. | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @see java.util.List#clear() | ||||
| 	 * @since Envoy v0.3-alpha | ||||
| 	 */ | ||||
| @@ -52,7 +55,7 @@ public final class ComponentListModel<E> implements Iterable<E> { | ||||
| 	/** | ||||
| 	 * Removes the element at a specific index from this model and the corresponding | ||||
| 	 * component from the {@link ComponentList}. | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param index | ||||
| 	 * @return the removed element | ||||
| 	 * @see java.util.List#remove(int) | ||||
| @@ -66,6 +69,7 @@ public final class ComponentListModel<E> implements Iterable<E> { | ||||
| 	 * @return | ||||
| 	 * @see java.util.List#iterator() | ||||
| 	 */ | ||||
| 	@Override | ||||
| 	public Iterator<E> iterator() { | ||||
| 		return new Iterator<E>() { | ||||
|  | ||||
| @@ -81,6 +85,6 @@ public final class ComponentListModel<E> implements Iterable<E> { | ||||
|  | ||||
| 	void setComponentList(ComponentList<E> componentList) { | ||||
| 		this.componentList = componentList; | ||||
| 		if (componentList != null) elements.forEach(componentList::add); | ||||
| 		if (componentList != null) componentList.synchronizeModel(); | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user