Implemented ComponentList rendering and integration of message list

This commit is contained in:
Kai S. K. Engelbart 2020-01-27 20:11:47 +01:00
parent 0c1c3f6fce
commit 063f5798dc
5 changed files with 77 additions and 59 deletions

View File

@ -12,7 +12,6 @@ import javax.swing.border.EmptyBorder;
import envoy.client.*; import envoy.client.*;
import envoy.client.event.ThemeChangeEvent; import envoy.client.event.ThemeChangeEvent;
import envoy.client.ui.list.ComponentList; import envoy.client.ui.list.ComponentList;
import envoy.client.ui.list.ComponentListModel;
import envoy.client.ui.settings.SettingsScreen; import envoy.client.ui.settings.SettingsScreen;
import envoy.client.util.EnvoyLog; import envoy.client.util.EnvoyLog;
import envoy.data.Message; import envoy.data.Message;
@ -32,27 +31,29 @@ import envoy.event.EventBus;
*/ */
public class ChatWindow extends JFrame { public class ChatWindow extends JFrame {
private static final long serialVersionUID = 6865098428255463649L;
// User specific objects // User specific objects
private Client client; private Client client;
private LocalDB localDB; private LocalDB localDB;
// 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 Chat currentChat; private Chat currentChat;
private ComponentList<Message> messageList; 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();
private PrimaryButton postButton = new PrimaryButton("Post"); private PrimaryButton postButton = new PrimaryButton("Post");
private PrimaryButton settingsButton = new PrimaryButton("Settings"); private PrimaryButton settingsButton = new PrimaryButton("Settings");
private static int space = 4;
private static final Logger logger = EnvoyLog.getLogger(ChatWindow.class.getSimpleName()); 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 * Initializes a {@link JFrame} with UI elements used to send and read messages
* to different users. * to different users.
@ -75,7 +76,6 @@ public class ChatWindow extends JFrame {
gbl_contentPane.rowWeights = new double[] { 0.05, 1.0, 0.07 }; gbl_contentPane.rowWeights = new double[] { 0.05, 1.0, 0.07 };
contentPane.setLayout(gbl_contentPane); contentPane.setLayout(gbl_contentPane);
messageList = new ComponentList<>(new ComponentListModel<>(), new MessageListRenderer());
// TODO: messageList.setFocusTraversalKeysEnabled(false); // TODO: messageList.setFocusTraversalKeysEnabled(false);
// messageList.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); // messageList.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
@ -91,7 +91,7 @@ public class ChatWindow extends JFrame {
gbc_scrollPane.gridx = 1; gbc_scrollPane.gridx = 1;
gbc_scrollPane.gridy = 1; gbc_scrollPane.gridy = 1;
gbc_scrollPane.insets = new Insets(space, space, space, space); gbc_scrollPane.insets = insets;
contentPane.add(scrollPane, gbc_scrollPane); contentPane.add(scrollPane, gbc_scrollPane);
// Message enter field // Message enter field
@ -100,7 +100,7 @@ public class ChatWindow extends JFrame {
@Override @Override
public void keyReleased(KeyEvent e) { public void keyReleased(KeyEvent e) {
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();
} }
}); });
@ -110,7 +110,7 @@ public class ChatWindow extends JFrame {
gbc_messageEnterTextfield.gridx = 1; gbc_messageEnterTextfield.gridx = 1;
gbc_messageEnterTextfield.gridy = 2; gbc_messageEnterTextfield.gridy = 2;
gbc_messageEnterTextfield.insets = new Insets(space, space, space, space); gbc_messageEnterTextfield.insets = insets;
contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield); contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield);
@ -121,7 +121,7 @@ public class ChatWindow extends JFrame {
gbc_moveSelectionPostButton.gridx = 2; gbc_moveSelectionPostButton.gridx = 2;
gbc_moveSelectionPostButton.gridy = 2; gbc_moveSelectionPostButton.gridy = 2;
gbc_moveSelectionPostButton.insets = new Insets(space, space, space, space); gbc_moveSelectionPostButton.insets = insets;
postButton.addActionListener((evt) -> { postMessage(); }); postButton.addActionListener((evt) -> { postMessage(); });
contentPane.add(postButton, gbc_moveSelectionPostButton); contentPane.add(postButton, gbc_moveSelectionPostButton);
@ -133,7 +133,7 @@ public class ChatWindow extends JFrame {
gbc_moveSelectionSettingsButton.gridx = 2; gbc_moveSelectionSettingsButton.gridx = 2;
gbc_moveSelectionSettingsButton.gridy = 0; gbc_moveSelectionSettingsButton.gridy = 0;
gbc_moveSelectionSettingsButton.insets = new Insets(space, space, space, space); gbc_moveSelectionSettingsButton.insets = insets;
settingsButton.addActionListener((evt) -> { settingsButton.addActionListener((evt) -> {
try { try {
@ -154,7 +154,7 @@ public class ChatWindow extends JFrame {
gbc_partnerName.gridx = 1; gbc_partnerName.gridx = 1;
gbc_partnerName.gridy = 0; gbc_partnerName.gridy = 0;
gbc_partnerName.insets = new Insets(space, space, space, space); gbc_partnerName.insets = insets;
contentPane.add(textPane, gbc_partnerName); contentPane.add(textPane, gbc_partnerName);
userList.setCellRenderer(new UserListRenderer()); userList.setCellRenderer(new UserListRenderer());
@ -187,7 +187,7 @@ public class ChatWindow extends JFrame {
gbc_userList.gridx = 0; gbc_userList.gridx = 0;
gbc_userList.gridy = 1; gbc_userList.gridy = 1;
gbc_userList.anchor = GridBagConstraints.PAGE_START; 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())); applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()));
@ -252,15 +252,18 @@ public class ChatWindow extends JFrame {
.build(); .build();
// Send message // Send message
// TODO: Store offline messages
client.sendMessage(message); client.sendMessage(message);
// Add message to LocalDB and update UI // Add message to LocalDB and update UI
currentChat.appendMessage(message); currentChat.appendMessage(message);
messageList.setModel(currentChat.getModel()); // messageList.setModel(currentChat.getModel());
// Clear text field // Clear text field
messageEnterTextArea.setText(""); messageEnterTextArea.setText("");
contentPane.revalidate();
revalidate();
repaint();
} catch (Exception e) { } catch (Exception e) {
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
"An exception occured while sending a message. See the log for more details.", "An exception occured while sending a message. See the log for more details.",

View File

@ -1,9 +1,10 @@
package envoy.client.ui; package envoy.client.ui;
import java.awt.Component;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import javax.swing.JComponent;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.border.EmptyBorder;
import envoy.client.Settings; import envoy.client.Settings;
import envoy.client.ui.list.ComponentList; import envoy.client.ui.list.ComponentList;
@ -21,23 +22,22 @@ import envoy.data.Message;
* @author Maximilian K&auml;fer * @author Maximilian K&auml;fer
* @since Envoy v0.1-alpha * @since Envoy v0.1-alpha
*/ */
public class MessageListRenderer extends JLabel implements ComponentListCellRenderer<Message> { public class MessageListRenderer implements ComponentListCellRenderer<Message> {
private static final long serialVersionUID = 5164417379767181198L;
@Override @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) { if (isSelected) {
setBackground(Color.DARK_GRAY); label.setBackground(Color.DARK_GRAY);
setForeground(Color.RED); label.setForeground(Color.RED);
// setBackground(list.getSelectionBackground()); // setBackground(list.getSelectionBackground());
// setForeground(list.getSelectionForeground()); // setForeground(list.getSelectionForeground());
} else { } else {
setBackground(list.getBackground()); label.setBackground(list.getBackground());
setForeground(list.getForeground()); label.setForeground(list.getForeground());
} }
setOpaque(true); label.setOpaque(true);
// TODO: Handle message attachments // 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 // Getting the DateColor in the Chat of the current theme
String dateColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat().toHex(); 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, dateColor,
date, date,
textColor, textColor,
text, text,
state)); state));
return this;
// Define some space to the components above and below
label.setBorder(new EmptyBorder(0, 0, 15, 0));
return label;
} }
} }

View File

@ -14,21 +14,27 @@ import javax.swing.JPanel;
public class ComponentList<E> extends JPanel { public class ComponentList<E> extends JPanel {
private ComponentListModel<E> model; private ComponentListModel<E> model;
private ComponentListCellRenderer<E> renderer; private ComponentListCellRenderer<E> renderer;
private static final long serialVersionUID = 1759644503942876737L; 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)); 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); setModel(model);
} }
public void setModel(ComponentListModel<E> model) { public void setModel(ComponentListModel<E> model) {
// Remove old model // Remove old model
this.model.clear(); if (this.model != null) {
this.model.setComponentList(null); this.model.clear();
this.model.setComponentList(null);
}
// Synchronize with new model // Synchronize with new model
this.model = model; this.model = model;
@ -40,9 +46,10 @@ public class ComponentList<E> extends JPanel {
add(renderer.getListCellComponent(this, elem, false)); add(renderer.getListCellComponent(this, elem, false));
} }
private void synchronizeModel() { void synchronizeModel() {
removeAll(); removeAll();
for (E elem : model) if (model != null)
add(renderer.getListCellComponent(this, elem, false)); for (E elem : model)
add(renderer.getListCellComponent(this, elem, false));
} }
} }

View File

@ -1,6 +1,6 @@
package envoy.client.ui.list; package envoy.client.ui.list;
import java.awt.Component; import javax.swing.JComponent;
/** /**
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
@ -12,5 +12,5 @@ import java.awt.Component;
*/ */
public interface ComponentListCellRenderer<E> { public interface ComponentListCellRenderer<E> {
Component getListCellComponent(ComponentList<? extends E> list, E value, boolean isSelected); JComponent getListCellComponent(ComponentList<? extends E> list, E value, boolean isSelected);
} }

View File

@ -1,5 +1,6 @@
package envoy.client.ui.list; package envoy.client.ui.list;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -12,10 +13,12 @@ import java.util.List;
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @since Envoy v0.3-alpha * @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 List<E> elements = new ArrayList<>();
private ComponentList<E> componentList; transient private ComponentList<E> componentList;
private static final long serialVersionUID = 4815005915255497331L;
/** /**
* Adds an element to this model and notifies the associated * Adds an element to this model and notifies the associated
@ -66,6 +69,7 @@ public final class ComponentListModel<E> implements Iterable<E> {
* @return * @return
* @see java.util.List#iterator() * @see java.util.List#iterator()
*/ */
@Override
public Iterator<E> iterator() { public Iterator<E> iterator() {
return new Iterator<E>() { return new Iterator<E>() {
@ -81,6 +85,6 @@ public final class ComponentListModel<E> implements Iterable<E> {
void setComponentList(ComponentList<E> componentList) { void setComponentList(ComponentList<E> componentList) {
this.componentList = componentList; this.componentList = componentList;
if (componentList != null) elements.forEach(componentList::add); if (componentList != null) componentList.synchronizeModel();
} }
} }