Merge pull request #108 from informatik-ag-ngl/f/contacts

Contacts handling
This commit is contained in:
Kai S. K. Engelbart 2020-02-12 06:14:11 +01:00 committed by GitHub
commit a01c34d999
23 changed files with 474 additions and 145 deletions

View File

@ -92,12 +92,13 @@ org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning

View File

@ -127,7 +127,6 @@ public class Settings {
* @param themeName the name to set * @param themeName the name to set
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
@SuppressWarnings("unchecked")
public void setCurrentTheme(String themeName) { ((SettingsItem<String>) items.get("currentTheme")).set(themeName); } public void setCurrentTheme(String themeName) { ((SettingsItem<String>) items.get("currentTheme")).set(themeName); }
/** /**
@ -146,7 +145,6 @@ public class Settings {
* conjunction with the {@code Control} key. * conjunction with the {@code Control} key.
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
@SuppressWarnings("unchecked")
public void setEnterToSend(boolean enterToSend) { ((SettingsItem<Boolean>) items.get("enterToSend")).set(enterToSend); } public void setEnterToSend(boolean enterToSend) { ((SettingsItem<Boolean>) items.get("enterToSend")).set(enterToSend); }
/** /**
@ -161,7 +159,6 @@ public class Settings {
* @param currentOnCloseMode the on close mode that should be set. * @param currentOnCloseMode the on close mode that should be set.
* @since Envoy v0.3-alpha * @since Envoy v0.3-alpha
*/ */
@SuppressWarnings("unchecked")
public void setCurrentOnCloseMode(boolean currentOnCloseMode) { ((SettingsItem<Boolean>) items.get("onCloseMode")).set(currentOnCloseMode); } public void setCurrentOnCloseMode(boolean currentOnCloseMode) { ((SettingsItem<Boolean>) items.get("onCloseMode")).set(currentOnCloseMode); }
/** /**

View File

@ -1,6 +1,7 @@
package envoy.client.event; package envoy.client.event;
import envoy.data.Message; import envoy.data.Message;
import envoy.event.Event;
/** /**
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
@ -10,7 +11,7 @@ import envoy.data.Message;
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
public class MessageCreationEvent extends MessageEvent { public class MessageCreationEvent extends Event<Message> {
private static final long serialVersionUID = -6451021678064566774L; private static final long serialVersionUID = -6451021678064566774L;

View File

@ -1,34 +0,0 @@
package envoy.client.event;
import envoy.data.Message;
import envoy.event.Event;
/**
* Project: <strong>envoy-client</strong><br>
* File: <strong>MessageCreationEvent.java</strong><br>
* Created: <strong>4 Dec 2019</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy v0.2-alpha
*/
public class MessageEvent implements Event<Message> {
private static final long serialVersionUID = 7658989461923112804L;
/**
* the {@link Message} attached to this {@link MessageEvent}.
*/
protected final Message message;
/**
* Initializes a {@link MessageEvent} conveying information about a
* {@link Message} object.
*
* @param message the {@link Message} object to attach to this event
* @since Envoy v0.2-alpha
*/
public MessageEvent(Message message) { this.message = message; }
@Override
public Message get() { return message; }
}

View File

@ -1,6 +1,7 @@
package envoy.client.event; package envoy.client.event;
import envoy.data.Message; import envoy.data.Message;
import envoy.event.Event;
/** /**
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
@ -10,7 +11,7 @@ import envoy.data.Message;
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
public class MessageModificationEvent extends MessageEvent { public class MessageModificationEvent extends Event<Message> {
private static final long serialVersionUID = 4650039506439563116L; private static final long serialVersionUID = 4650039506439563116L;

View File

@ -0,0 +1,23 @@
package envoy.client.event;
import envoy.event.Event;
/**
* Project: <strong>envoy-client</strong><br>
* File: <strong>SendEvent.java</strong><br>
* Created: <strong>11.02.2020</strong><br>
*
* @author: Maximilian K&aumlfer
*
* @since Envoy v0.3-alpha
*/
public class SendEvent extends Event<Event<?>> {
private static final long serialVersionUID = 8372746924138839060L;
/**
* @param value the event to send to the server
*/
public SendEvent(Event<?> value) { super(value); }
}

View File

@ -11,10 +11,9 @@ import envoy.event.Event;
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
public class ThemeChangeEvent implements Event<Theme> { public class ThemeChangeEvent extends Event<Theme> {
private static final long serialVersionUID = 6756772448803774547L; private static final long serialVersionUID = 6756772448803774547L;
private final Theme theme;
/** /**
* Initializes a {@link ThemeChangeEvent} conveying information about the change * Initializes a {@link ThemeChangeEvent} conveying information about the change
@ -23,8 +22,5 @@ public class ThemeChangeEvent implements Event<Theme> {
* @param theme the new currently used {@link Theme} object * @param theme the new currently used {@link Theme} object
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
public ThemeChangeEvent(Theme theme) { this.theme = theme; } public ThemeChangeEvent(Theme theme) { super(theme); }
@Override
public Theme get() { return theme; }
} }

View File

@ -12,9 +12,11 @@ import javax.naming.TimeLimitExceededException;
import envoy.client.data.Cache; import envoy.client.data.Cache;
import envoy.client.data.Config; import envoy.client.data.Config;
import envoy.client.data.LocalDb; import envoy.client.data.LocalDb;
import envoy.client.event.SendEvent;
import envoy.client.util.EnvoyLog; import envoy.client.util.EnvoyLog;
import envoy.data.*; import envoy.data.*;
import envoy.event.*; import envoy.event.*;
import envoy.event.ContactOperationEvent.Operation;
import envoy.util.SerializationUtils; import envoy.util.SerializationUtils;
/** /**
@ -108,11 +110,26 @@ public class Client implements Closeable {
receiver.registerProcessor(MessageStatusChangeEvent.class, new MessageStatusChangeEventProcessor()); receiver.registerProcessor(MessageStatusChangeEvent.class, new MessageStatusChangeEventProcessor());
// Process user status changes // Process user status changes
receiver.registerProcessor(UserStatusChangeEvent.class, new UserStatusChangeProcessor(this)); receiver.registerProcessor(UserStatusChangeEvent.class, new UserStatusChangeProcessor(localDb));
// Process message ID generation // Process message ID generation
receiver.registerProcessor(IdGenerator.class, localDb::setIdGenerator); receiver.registerProcessor(IdGenerator.class, localDb::setIdGenerator);
// Process contact searches
receiver.registerProcessor(ContactSearchResult.class, EventBus.getInstance()::dispatch);
receiver.registerProcessor(Contacts.class,
contacts -> EventBus.getInstance().dispatch(new ContactOperationEvent(contacts.getContacts().get(0), Operation.ADD)));
// Send event
EventBus.getInstance().register(SendEvent.class, evt -> {
try {
sendEvent(evt.get());
} catch (IOException e) {
e.printStackTrace();
}
});
// Request a generator if none is present or the existing one is consumed // Request a generator if none is present or the existing one is consumed
if (!localDb.hasIdGenerator() || !localDb.getIdGenerator().hasNext()) requestIdGenerator(); if (!localDb.hasIdGenerator() || !localDb.getIdGenerator().hasNext()) requestIdGenerator();
} }

View File

@ -30,9 +30,6 @@ public class MessageStatusChangeEventProcessor implements Consumer<MessageStatus
@Override @Override
public void accept(MessageStatusChangeEvent evt) { public void accept(MessageStatusChangeEvent evt) {
if (evt.get().ordinal() < MessageStatus.RECEIVED.ordinal()) logger.info("Received invalid message status change " + evt); if (evt.get().ordinal() < MessageStatus.RECEIVED.ordinal()) logger.info("Received invalid message status change " + evt);
else { else EventBus.getInstance().dispatch(evt);
logger.info("Received " + evt.toString());
EventBus.getInstance().dispatch(evt);
}
} }
} }

View File

@ -23,7 +23,6 @@ public class ReceivedMessageProcessor implements Consumer<Message> {
@Override @Override
public void accept(Message message) { public void accept(Message message) {
logger.info("Received message object " + message);
if (message.getStatus() != MessageStatus.SENT) logger.warning("The message has the unexpected status " + message.getStatus()); if (message.getStatus() != MessageStatus.SENT) logger.warning("The message has the unexpected status " + message.getStatus());
else { else {
// Update status to RECEIVED // Update status to RECEIVED

View File

@ -35,7 +35,6 @@ public class Receiver implements Runnable {
*/ */
public Receiver(InputStream in) { this.in = in; } public Receiver(InputStream in) { this.in = in; }
@SuppressWarnings("unchecked")
@Override @Override
public void run() { public void run() {

View File

@ -1,9 +1,8 @@
package envoy.client.net; package envoy.client.net;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.logging.Logger;
import envoy.client.util.EnvoyLog; import envoy.client.data.LocalDb;
import envoy.event.EventBus; import envoy.event.EventBus;
import envoy.event.UserStatusChangeEvent; import envoy.event.UserStatusChangeEvent;
@ -17,21 +16,17 @@ import envoy.event.UserStatusChangeEvent;
*/ */
public class UserStatusChangeProcessor implements Consumer<UserStatusChangeEvent> { public class UserStatusChangeProcessor implements Consumer<UserStatusChangeEvent> {
private Client client; private final LocalDb localDb;
private static final Logger logger = EnvoyLog.getLogger(UserStatusChangeProcessor.class.getSimpleName());
/** /**
* @param client the {@link Client} who receives an * @param localDb the local database in which status updates will by applied
* {@link UserStatusChangeEvent}
* @since Envoy v0.3-alpha * @since Envoy v0.3-alpha
*/ */
public UserStatusChangeProcessor(Client client) { this.client = client; } public UserStatusChangeProcessor(LocalDb localDb) { this.localDb = localDb; }
@Override @Override
public void accept(UserStatusChangeEvent evt) { public void accept(UserStatusChangeEvent evt) {
logger.info("Received " + evt); localDb.getUsers().values().stream().filter(u -> u.getId() == evt.getId()).findFirst().get().setStatus(evt.get());
client.getContacts().getContacts().stream().filter((user) -> user.getId() == evt.getId()).findFirst().get().setStatus(evt.get());
EventBus.getInstance().dispatch(evt); EventBus.getInstance().dispatch(evt);
} }
} }

View File

@ -45,12 +45,14 @@ public class WriteProxy {
// Initialize cache processors for messages and message status change events // Initialize cache processors for messages and message status change events
localDb.getMessageCache().setProcessor(msg -> { localDb.getMessageCache().setProcessor(msg -> {
try { try {
logger.info("Sending cached " + msg);
client.sendMessage(msg); client.sendMessage(msg);
} catch (IOException e) { } catch (IOException e) {
logger.log(Level.SEVERE, "Could not send cached message", e); logger.log(Level.SEVERE, "Could not send cached message", e);
} }
}); });
localDb.getStatusCache().setProcessor(evt -> { localDb.getStatusCache().setProcessor(evt -> {
logger.info("Sending cached " + evt);
try { try {
client.sendEvent(evt); client.sendEvent(evt);
} catch (IOException e) { } catch (IOException e) {
@ -66,8 +68,6 @@ public class WriteProxy {
* @since Envoy v0.3-alpha * @since Envoy v0.3-alpha
*/ */
public void flushCache() { public void flushCache() {
logger.info("Sending cached messages and message status change events...");
// Send messages // Send messages
localDb.getMessageCache().relay(); localDb.getMessageCache().relay();

View File

@ -9,6 +9,8 @@ import java.util.logging.Logger;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import envoy.client.Settings; import envoy.client.Settings;
import envoy.client.data.Chat; import envoy.client.data.Chat;
@ -18,15 +20,14 @@ import envoy.client.event.ThemeChangeEvent;
import envoy.client.net.Client; import envoy.client.net.Client;
import envoy.client.net.WriteProxy; import envoy.client.net.WriteProxy;
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;
import envoy.data.Message.MessageStatus; import envoy.data.Message.MessageStatus;
import envoy.data.MessageBuilder; import envoy.data.MessageBuilder;
import envoy.data.User; import envoy.data.User;
import envoy.event.EventBus; import envoy.event.*;
import envoy.event.MessageStatusChangeEvent;
import envoy.event.UserStatusChangeEvent;
/** /**
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
@ -49,6 +50,7 @@ public class ChatWindow extends JFrame {
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 Chat currentChat; 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();
@ -56,6 +58,20 @@ public class ChatWindow extends JFrame {
private PrimaryButton postButton = new PrimaryButton("Post"); private PrimaryButton postButton = new PrimaryButton("Post");
private PrimaryButton settingsButton = new PrimaryButton("Settings"); private PrimaryButton settingsButton = new PrimaryButton("Settings");
// Contacts Header
private JPanel contactsHeader = new JPanel();
private JTextPane contactsDisplay = new JTextPane();
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 static final Logger logger = EnvoyLog.getLogger(ChatWindow.class.getSimpleName()); private static final Logger logger = EnvoyLog.getLogger(ChatWindow.class.getSimpleName());
// GUI component spacing // GUI component spacing
@ -81,16 +97,11 @@ public class ChatWindow extends JFrame {
setContentPane(contentPane); setContentPane(contentPane);
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 }; 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.3, 1.0, 0.1 };
gbl_contentPane.rowWeights = new double[] { 0.05, 1.0, 0.07 }; gbl_contentPane.rowWeights = new double[] { 0.03, 0.001, 1.0, 0.005 };
contentPane.setLayout(gbl_contentPane); contentPane.setLayout(gbl_contentPane);
// TODO: messageList.setFocusTraversalKeysEnabled(false);
// messageList.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
// messageList.setFont(new Font("Arial", Font.PLAIN, 17));
// messageList.setFixedCellHeight(60);
messageList.setBorder(new EmptyBorder(space, space, space, space)); messageList.setBorder(new EmptyBorder(space, space, space, space));
scrollPane.setViewportView(messageList); scrollPane.setViewportView(messageList);
@ -98,11 +109,13 @@ public class ChatWindow extends JFrame {
GridBagConstraints gbc_scrollPane = new GridBagConstraints(); GridBagConstraints gbc_scrollPane = new GridBagConstraints();
gbc_scrollPane.fill = GridBagConstraints.BOTH; gbc_scrollPane.fill = GridBagConstraints.BOTH;
gbc_scrollPane.gridwidth = 2; gbc_scrollPane.gridwidth = 2;
gbc_scrollPane.gridheight = 2;
gbc_scrollPane.gridx = 1; gbc_scrollPane.gridx = 1;
gbc_scrollPane.gridy = 1; gbc_scrollPane.gridy = 1;
gbc_scrollPane.insets = insets; gbc_scrollPane.insets = insets;
contentPane.add(scrollPane, gbc_scrollPane);
drawChatBox(gbc_scrollPane);
// Message enter field // Message enter field
messageEnterTextArea.addKeyListener(new KeyAdapter() { messageEnterTextArea.addKeyListener(new KeyAdapter() {
@ -118,7 +131,7 @@ public class ChatWindow extends JFrame {
GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints(); GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints();
gbc_messageEnterTextfield.fill = GridBagConstraints.BOTH; gbc_messageEnterTextfield.fill = GridBagConstraints.BOTH;
gbc_messageEnterTextfield.gridx = 1; gbc_messageEnterTextfield.gridx = 1;
gbc_messageEnterTextfield.gridy = 2; gbc_messageEnterTextfield.gridy = 3;
gbc_messageEnterTextfield.insets = insets; gbc_messageEnterTextfield.insets = insets;
@ -129,7 +142,7 @@ public class ChatWindow extends JFrame {
gbc_moveSelectionPostButton.fill = GridBagConstraints.BOTH; gbc_moveSelectionPostButton.fill = GridBagConstraints.BOTH;
gbc_moveSelectionPostButton.gridx = 2; gbc_moveSelectionPostButton.gridx = 2;
gbc_moveSelectionPostButton.gridy = 2; gbc_moveSelectionPostButton.gridy = 3;
gbc_moveSelectionPostButton.insets = insets; gbc_moveSelectionPostButton.insets = insets;
@ -145,14 +158,7 @@ public class ChatWindow extends JFrame {
gbc_moveSelectionSettingsButton.insets = insets; gbc_moveSelectionSettingsButton.insets = insets;
settingsButton.addActionListener((evt) -> { settingsButton.addActionListener(evt -> new SettingsScreen().setVisible(true));
try {
new SettingsScreen().setVisible(true);
} catch (Exception e) {
logger.log(Level.WARNING, "An error occured while opening the settings screen", e);
e.printStackTrace();
}
});
contentPane.add(settingsButton, gbc_moveSelectionSettingsButton); contentPane.add(settingsButton, gbc_moveSelectionSettingsButton);
// Partner name display // Partner name display
@ -171,10 +177,13 @@ public class ChatWindow extends JFrame {
userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
userList.addListSelectionListener((listSelectionEvent) -> { userList.addListSelectionListener((listSelectionEvent) -> {
if (client != null && localDb != null && !listSelectionEvent.getValueIsAdjusting()) { if (client != null && localDb != null && !listSelectionEvent.getValueIsAdjusting()) {
@SuppressWarnings("unchecked")
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++) {
if (contentPane.getComponent(i).equals(searchPane)) { drawChatBox(gbc_scrollPane); }
}
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();
@ -192,6 +201,7 @@ public class ChatWindow extends JFrame {
revalidate(); revalidate();
repaint(); repaint();
} }
}
}); });
userList.setFont(new Font("Arial", Font.PLAIN, 17)); userList.setFont(new Font("Arial", Font.PLAIN, 17));
@ -200,24 +210,149 @@ public class ChatWindow extends JFrame {
GridBagConstraints gbc_userList = new GridBagConstraints(); GridBagConstraints gbc_userList = new GridBagConstraints();
gbc_userList.fill = GridBagConstraints.VERTICAL; gbc_userList.fill = GridBagConstraints.VERTICAL;
gbc_userList.gridx = 0; gbc_userList.gridx = 0;
gbc_userList.gridy = 1; gbc_userList.gridy = 2;
gbc_userList.gridheight = 2;
gbc_userList.anchor = GridBagConstraints.PAGE_START; gbc_userList.anchor = GridBagConstraints.PAGE_START;
gbc_userList.insets = insets; gbc_userList.insets = insets;
applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()));
contentPane.add(userList, gbc_userList); contentPane.add(userList, gbc_userList);
contentPane.revalidate(); contentPane.revalidate();
// Contacts Search
GridBagConstraints gbc_searchPane = new GridBagConstraints();
gbc_searchPane.fill = GridBagConstraints.BOTH;
gbc_searchPane.gridwidth = 2;
gbc_searchPane.gridheight = 2;
gbc_searchPane.gridx = 1;
gbc_searchPane.gridy = 1;
gbc_searchPane.insets = insets;
GridBagLayout gbl_contactsSearch = new GridBagLayout();
gbl_contactsSearch.columnWidths = new int[] { 1, 1 };
gbl_contactsSearch.rowHeights = new int[] { 1, 1 };
gbl_contactsSearch.columnWeights = new double[] { 1, 0.1 };
gbl_contactsSearch.rowWeights = new double[] { 0.001, 1 };
searchPane.setLayout(gbl_contactsSearch);
GridBagConstraints gbc_searchField = new GridBagConstraints();
gbc_searchField.fill = GridBagConstraints.BOTH;
gbc_searchField.gridx = 0;
gbc_searchField.gridy = 0;
gbc_searchField.insets = new Insets(7, 4, 4, 4);
searchPane.add(searchField, gbc_searchField);
// Sends event to server, if input has changed
searchField.getDocument().addDocumentListener(new DocumentListener() {
@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();
}
}
}
}
@Override
public void insertUpdate(DocumentEvent evt) {
if (client.isOnline()) {
try {
client.sendEvent(new ContactSearchRequest(searchField.getText()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void changedUpdate(DocumentEvent evt) {}
});
GridBagConstraints gbc_cancelButton = new GridBagConstraints();
gbc_cancelButton.fill = GridBagConstraints.BOTH;
gbc_cancelButton.gridx = 1;
gbc_cancelButton.gridy = 0;
gbc_cancelButton.insets = new Insets(7, 4, 4, 4);
cancelButton.addActionListener((evt) -> { drawChatBox(gbc_scrollPane); });
searchPane.add(cancelButton, gbc_cancelButton);
contactList.setModel(contactsModel);
possibleContacts.setBorder(new EmptyBorder(space, space, space, space));
possibleContacts.setViewportView(contactList);
GridBagConstraints gbc_possibleContacts = new GridBagConstraints();
gbc_possibleContacts.fill = GridBagConstraints.BOTH;
gbc_possibleContacts.gridwidth = 2;
gbc_possibleContacts.gridx = 0;
gbc_possibleContacts.gridy = 1;
gbc_possibleContacts.insets = insets;
searchPane.add(possibleContacts, gbc_possibleContacts);
// Contacts Header
GridBagConstraints gbc_contactsHeader = new GridBagConstraints();
gbc_contactsHeader.fill = GridBagConstraints.BOTH;
gbc_contactsHeader.gridx = 0;
gbc_contactsHeader.gridy = 1;
gbc_contactsHeader.insets = insets;
GridBagLayout gbl_contactHeader = new GridBagLayout();
gbl_contactHeader.columnWidths = new int[] { 1, 1 };
gbl_contactHeader.rowHeights = new int[] { 1 };
gbl_contactHeader.columnWeights = new double[] { 1, 1 };
gbl_contactHeader.rowWeights = new double[] { 1 };
contactsHeader.setLayout(gbl_contactHeader);
contactsDisplay.setEditable(false);
contactsDisplay.setFont(new Font("Arial", Font.PLAIN, 12));
contactsDisplay.setText("Contacts");
GridBagConstraints gbc_contactsDisplay = new GridBagConstraints();
gbc_contactsDisplay.fill = GridBagConstraints.BOTH;
gbc_contactsDisplay.gridx = 0;
gbc_contactsDisplay.gridy = 0;
contactsHeader.add(contactsDisplay, gbc_contactsDisplay);
addContact.setFont(new Font("Arial", Font.PLAIN, 15));
GridBagConstraints gbc_addContact = new GridBagConstraints();
gbc_addContact.fill = GridBagConstraints.BOTH;
gbc_addContact.gridx = 1;
gbc_addContact.gridy = 0;
gbc_addContact.insets = insets;
addContact.addActionListener((evt) -> { drawContactSearch(gbc_searchPane); });
contactsHeader.add(addContact, gbc_addContact);
applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()));
contentPane.add(contactsHeader, gbc_contactsHeader);
contentPane.revalidate();
// Listen to theme changes // Listen to theme changes
EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme((Theme) evt.get())); EventBus.getInstance().register(ThemeChangeEvent.class, evt -> applyTheme(evt.get()));
// Listen to user status changes // Listen to user status changes
EventBus.getInstance().register(UserStatusChangeEvent.class, (evt) -> { userList.revalidate(); userList.repaint(); }); EventBus.getInstance().register(UserStatusChangeEvent.class, evt -> { userList.revalidate(); userList.repaint(); });
// Listen to received messages // Listen to received messages
EventBus.getInstance().register(MessageCreationEvent.class, (evt) -> { EventBus.getInstance().register(MessageCreationEvent.class, evt -> {
Message message = ((MessageCreationEvent) evt).get(); Message message = evt.get();
Chat chat = localDb.getChats().stream().filter(c -> c.getRecipient().getId() == message.getSenderId()).findFirst().get(); Chat chat = localDb.getChats().stream().filter(c -> c.getRecipient().getId() == message.getSenderId()).findFirst().get();
chat.appendMessage(message); chat.appendMessage(message);
@ -229,9 +364,9 @@ public class ChatWindow extends JFrame {
}); });
// Listen to message status changes // Listen to message status changes
EventBus.getInstance().register(MessageStatusChangeEvent.class, (evt) -> { EventBus.getInstance().register(MessageStatusChangeEvent.class, evt -> {
final long id = ((MessageStatusChangeEvent) evt).getId(); final long id = evt.getId();
final MessageStatus status = (MessageStatus) evt.get(); final MessageStatus status = evt.get();
for (Chat c : localDb.getChats()) for (Chat c : localDb.getChats())
for (Message m : c.getModel()) for (Message m : c.getModel())
@ -251,7 +386,35 @@ public class ChatWindow extends JFrame {
repaint(); repaint();
}); });
// Listen to contact search results
EventBus.getInstance().register(ContactSearchResult.class, evt -> {
contactsModel.clear();
final java.util.List<User> contacts = evt.get();
logger.info("Received contact search result " + contacts);
contacts.forEach(contactsModel::add);
revalidate(); revalidate();
repaint();
});
// Add new contacts to the contact list
EventBus.getInstance().register(ContactOperationEvent.class, evt -> {
User contact = evt.get();
// Clearing the search field and the searchResultList
searchField.setText("");
contactsModel.clear();
// Update LocalDB
userListModel.addElement(contact);
localDb.getUsers().put(contact.getName(), contact);
localDb.getChats().add(new Chat(contact));
revalidate();
repaint();
});
revalidate();
repaint();
} }
/** /**
@ -291,6 +454,21 @@ public class ChatWindow extends JFrame {
userList.setSelectionBackground(theme.getSelectionColor()); userList.setSelectionBackground(theme.getSelectionColor());
userList.setForeground(theme.getUserNameColor()); userList.setForeground(theme.getUserNameColor());
userList.setBackground(theme.getCellColor()); userList.setBackground(theme.getCellColor());
// contacts header
contactsHeader.setBackground(theme.getCellColor());
contactsDisplay.setBackground(theme.getCellColor());
contactsDisplay.setForeground(theme.getUserNameColor());
addContact.setBackground(theme.getInteractableBackgroundColor());
addContact.setForeground(theme.getInteractableForegroundColor());
// SearchPane
searchPane.setBackground(theme.getCellColor());
searchField.setBackground(theme.getBackgroundColor());
searchField.setForeground(theme.getUserNameColor());
cancelButton.setBackground(theme.getInteractableBackgroundColor());
cancelButton.setForeground(theme.getInteractableForegroundColor());
contactList.setForeground(theme.getMessageColorChat());
contactList.setBackground(theme.getCellColor());
possibleContacts.applyTheme(theme);
} }
private void postMessage() { private void postMessage() {
@ -336,7 +514,6 @@ public class ChatWindow extends JFrame {
*/ */
private void loadUsersAndChats() { private void loadUsersAndChats() {
new Thread(() -> { new Thread(() -> {
DefaultListModel<User> userListModel = new DefaultListModel<>();
localDb.getUsers().values().forEach(user -> { localDb.getUsers().values().forEach(user -> {
userListModel.addElement(user); userListModel.addElement(user);
@ -345,6 +522,9 @@ public class ChatWindow extends JFrame {
localDb.getChats().add(new Chat(user)); localDb.getChats().add(new Chat(user));
}); });
SwingUtilities.invokeLater(() -> userList.setModel(userListModel)); SwingUtilities.invokeLater(() -> userList.setModel(userListModel));
revalidate();
repaint();
}).start(); }).start();
} }
@ -358,6 +538,24 @@ public class ChatWindow extends JFrame {
} }
} }
private void drawChatBox(GridBagConstraints gbc_scrollPane) {
contentPane.remove(searchPane);
contentPane.add(scrollPane, gbc_scrollPane);
contentPane.revalidate();
contentPane.repaint();
}
private void drawContactSearch(GridBagConstraints gbc_searchPane) {
currentChat = null;
userList.removeSelectionInterval(0, userList.getModel().getSize() - 1);
messageList.setModel(null);
textPane.setText("");
contentPane.remove(scrollPane);
contentPane.add(searchPane, gbc_searchPane);
contentPane.revalidate();
contentPane.repaint();
}
/** /**
* Initializes the components responsible server communication and * Initializes the components responsible server communication and
* persistence.<br> * persistence.<br>

View File

@ -0,0 +1,78 @@
package envoy.client.ui;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.*;
import envoy.client.Settings;
import envoy.client.event.SendEvent;
import envoy.client.ui.list.ComponentList;
import envoy.client.ui.list.ComponentListCellRenderer;
import envoy.data.User;
import envoy.event.ContactOperationEvent;
import envoy.event.EventBus;
/**
* Defines how a contact is displayed.<br>
* <br>
* Project: <strong>envoy-client</strong><br>
* File: <strong>ContactsSearchRenderer.java</strong><br>
* Created: <strong>08.02.2020</strong><br>
*
* @author Maximilian K&auml;fer
* @author Kai S. K. Engelbart
* @since Envoy v0.3-alpha
*/
public class ContactsSearchRenderer implements ComponentListCellRenderer<User> {
@Override
public JComponent getListCellComponent(ComponentList<? extends User> list, User user, boolean isSelected) {
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
if (isSelected) {
panel.setBackground(Color.DARK_GRAY);
panel.setForeground(Color.RED);
} else {
panel.setBackground(list.getBackground());
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()));
display.setAlignmentX(Component.LEFT_ALIGNMENT);
display.setAlignmentY(Component.CENTER_ALIGNMENT);
display.setFont(new Font("Arial", Font.PLAIN, 16));
panel.add(display);
PrimaryButton add = new PrimaryButton("+");
add.setFont(new Font("Arial", Font.PLAIN, 19));
add.setPreferredSize(new Dimension(45, 45));
add.setMinimumSize(new Dimension(45, 45));
add.setMaximumSize(new Dimension(45, 45));
add.setBackground(list.getBackground());
add.setForeground(list.getForeground());
add.addActionListener(evt -> {
ContactOperationEvent contactsOperationEvent = new ContactOperationEvent(user, ContactOperationEvent.Operation.ADD);
EventBus.getInstance().dispatch(contactsOperationEvent);
EventBus.getInstance().dispatch(new SendEvent(contactsOperationEvent));
});
panel.add(add);
// Define some space to the messages below
panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, 0, 15, 0), BorderFactory.createEtchedBorder()));
// Define a maximum height of 50px
Dimension size = new Dimension(435, 50);
panel.setMaximumSize(size);
panel.setMinimumSize(size);
panel.setPreferredSize(size);
return panel;
}
}

View File

@ -9,6 +9,7 @@ import java.util.Arrays;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import envoy.client.Settings;
import envoy.data.LoginCredentials; import envoy.data.LoginCredentials;
/** /**
@ -22,19 +23,27 @@ import envoy.data.LoginCredentials;
*/ */
public class LoginDialog extends JDialog { public class LoginDialog extends JDialog {
private final JPanel contentPanel = new JPanel(); private final JPanel contentPanel;
private static final long serialVersionUID = 352021600833907468L;
private JTextField textField; private JTextField textField;
private JPasswordField passwordField; private JPasswordField passwordField;
private JPasswordField repeatPasswordField; private JPasswordField repeatPasswordField;
private JLabel lblUserName;
private JLabel lblPassword;
private JLabel lblRepeatPassword; private JLabel lblRepeatPassword;
private GridBagConstraints gbc_lblRepeatPassword; private GridBagConstraints gbc_lblRepeatPassword;
private GridBagConstraints gbc_repeatPasswordField; private GridBagConstraints gbc_repeatPasswordField;
private JPanel buttonPane;
private JTextPane registerText;
private JCheckBox registerCheckBox;
private PrimaryButton okButton;
private PrimaryButton cancelButton;
private LoginCredentials credentials; private LoginCredentials credentials;
private static final long serialVersionUID = 352021600833907468L;
/** /**
* Displays a dialog enabling the user to enter their user name and password. * Displays a dialog enabling the user to enter their user name and password.
* *
@ -44,6 +53,7 @@ public class LoginDialog extends JDialog {
setSize(338, 123); setSize(338, 123);
setLocationRelativeTo(null); setLocationRelativeTo(null);
getContentPane().setLayout(new BorderLayout()); getContentPane().setLayout(new BorderLayout());
contentPanel = new JPanel();
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER); getContentPane().add(contentPanel, BorderLayout.CENTER);
GridBagLayout gbl_contentPanel = new GridBagLayout(); GridBagLayout gbl_contentPanel = new GridBagLayout();
@ -53,7 +63,7 @@ public class LoginDialog extends JDialog {
gbl_contentPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE }; gbl_contentPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
contentPanel.setLayout(gbl_contentPanel); contentPanel.setLayout(gbl_contentPanel);
{ {
JLabel lblUserName = new JLabel("User name:"); lblUserName = new JLabel("Username:");
GridBagConstraints gbc_lblUserName = new GridBagConstraints(); GridBagConstraints gbc_lblUserName = new GridBagConstraints();
gbc_lblUserName.anchor = GridBagConstraints.EAST; gbc_lblUserName.anchor = GridBagConstraints.EAST;
gbc_lblUserName.insets = new Insets(0, 0, 5, 5); gbc_lblUserName.insets = new Insets(0, 0, 5, 5);
@ -63,6 +73,7 @@ public class LoginDialog extends JDialog {
} }
{ {
textField = new JTextField(); textField = new JTextField();
textField.setBorder(null);
GridBagConstraints gbc_textField = new GridBagConstraints(); GridBagConstraints gbc_textField = new GridBagConstraints();
gbc_textField.insets = new Insets(0, 0, 5, 0); gbc_textField.insets = new Insets(0, 0, 5, 0);
gbc_textField.fill = GridBagConstraints.HORIZONTAL; gbc_textField.fill = GridBagConstraints.HORIZONTAL;
@ -72,7 +83,7 @@ public class LoginDialog extends JDialog {
textField.setColumns(10); textField.setColumns(10);
} }
{ {
JLabel lblPassword = new JLabel("Password:"); lblPassword = new JLabel("Password:");
GridBagConstraints gbc_lblPassword = new GridBagConstraints(); GridBagConstraints gbc_lblPassword = new GridBagConstraints();
gbc_lblPassword.anchor = GridBagConstraints.EAST; gbc_lblPassword.anchor = GridBagConstraints.EAST;
gbc_lblPassword.insets = new Insets(0, 0, 0, 5); gbc_lblPassword.insets = new Insets(0, 0, 0, 5);
@ -82,6 +93,7 @@ public class LoginDialog extends JDialog {
} }
{ {
passwordField = new JPasswordField(); passwordField = new JPasswordField();
passwordField.setBorder(null);
GridBagConstraints gbc_passwordField = new GridBagConstraints(); GridBagConstraints gbc_passwordField = new GridBagConstraints();
gbc_passwordField.fill = GridBagConstraints.HORIZONTAL; gbc_passwordField.fill = GridBagConstraints.HORIZONTAL;
gbc_passwordField.gridx = 1; gbc_passwordField.gridx = 1;
@ -98,21 +110,23 @@ public class LoginDialog extends JDialog {
} }
{ {
repeatPasswordField = new JPasswordField(); repeatPasswordField = new JPasswordField();
repeatPasswordField.setBorder(null);
gbc_repeatPasswordField = new GridBagConstraints(); gbc_repeatPasswordField = new GridBagConstraints();
gbc_repeatPasswordField.fill = GridBagConstraints.HORIZONTAL; gbc_repeatPasswordField.fill = GridBagConstraints.HORIZONTAL;
gbc_repeatPasswordField.gridx = 1; gbc_repeatPasswordField.gridx = 1;
gbc_repeatPasswordField.gridy = 2; gbc_repeatPasswordField.gridy = 2;
} }
{ {
JPanel buttonPane = new JPanel(); buttonPane = new JPanel();
JTextPane registerText = new JTextPane(); registerText = new JTextPane();
registerText.setEditable(false);
registerText.setText("Register?"); registerText.setText("Register?");
registerText.setFont(new Font("Arial", Font.BOLD, 12)); registerText.setFont(new Font("Arial", Font.BOLD, 12));
registerText.setAlignmentX(LEFT_ALIGNMENT); registerText.setAlignmentX(LEFT_ALIGNMENT);
buttonPane.add(registerText); buttonPane.add(registerText);
JCheckBox registerCheckBox = new JCheckBox(); registerCheckBox = new JCheckBox();
registerCheckBox.setAlignmentX(LEFT_ALIGNMENT); registerCheckBox.setAlignmentX(LEFT_ALIGNMENT);
registerCheckBox.addItemListener(new ItemListener() { registerCheckBox.addItemListener(new ItemListener() {
@ -122,7 +136,7 @@ public class LoginDialog extends JDialog {
case ItemEvent.SELECTED: case ItemEvent.SELECTED:
contentPanel.add(lblRepeatPassword, gbc_lblRepeatPassword); contentPanel.add(lblRepeatPassword, gbc_lblRepeatPassword);
contentPanel.add(repeatPasswordField, gbc_repeatPasswordField); contentPanel.add(repeatPasswordField, gbc_repeatPasswordField);
setSize(338, 160); setSize(338, 148);
contentPanel.revalidate(); contentPanel.revalidate();
contentPanel.repaint(); contentPanel.repaint();
break; break;
@ -144,7 +158,7 @@ public class LoginDialog extends JDialog {
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH); getContentPane().add(buttonPane, BorderLayout.SOUTH);
{ {
JButton okButton = new JButton("OK"); okButton = new PrimaryButton("OK");
okButton.addActionListener((evt) -> { okButton.addActionListener((evt) -> {
try { try {
if (registerCheckBox.isSelected()) { if (registerCheckBox.isSelected()) {
@ -169,17 +183,62 @@ public class LoginDialog extends JDialog {
getRootPane().setDefaultButton(okButton); getRootPane().setDefaultButton(okButton);
} }
{ {
JButton cancelButton = new JButton("Cancel"); cancelButton = new PrimaryButton("Cancel");
cancelButton.addActionListener((evt) -> dispose()); cancelButton.addActionListener((evt) -> dispose());
cancelButton.setActionCommand("Cancel"); cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton); buttonPane.add(cancelButton);
} }
} }
setTheme();
setModal(true); setModal(true);
setVisible(true); setVisible(true);
} }
private void setTheme() {
Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
// Panels
contentPanel.setBackground(theme.getBackgroundColor());
contentPanel.setForeground(theme.getBackgroundColor());
buttonPane.setBackground(theme.getBackgroundColor());
buttonPane.setForeground(theme.getBackgroundColor());
// Input Fields
textField.setBackground(theme.getCellColor());
textField.setForeground(theme.getUserNameColor());
passwordField.setBackground(theme.getCellColor());
passwordField.setForeground(theme.getUserNameColor());
repeatPasswordField.setBackground(theme.getCellColor());
repeatPasswordField.setForeground(theme.getUserNameColor());
// JLabels
lblUserName.setBackground(theme.getCellColor());
lblUserName.setForeground(theme.getUserNameColor());
lblPassword.setBackground(theme.getCellColor());
lblPassword.setForeground(theme.getUserNameColor());
lblRepeatPassword.setBackground(theme.getCellColor());
lblRepeatPassword.setForeground(theme.getUserNameColor());
// Register
registerText.setBackground(theme.getCellColor());
registerText.setForeground(theme.getUserNameColor());
registerCheckBox.setBackground(theme.getCellColor());
// Buttons
okButton.setBackground(theme.getInteractableBackgroundColor());
okButton.setForeground(theme.getInteractableForegroundColor());
cancelButton.setBackground(theme.getInteractableBackgroundColor());
cancelButton.setForeground(theme.getInteractableForegroundColor());
}
/** /**
* @return the {@link LoginCredentials} entered by the user, or {@code null} if * @return the {@link LoginCredentials} entered by the user, or {@code null} if
* the dialog has been cancelled * the dialog has been cancelled

View File

@ -14,7 +14,7 @@ import envoy.data.Message;
* Defines how a message is displayed.<br> * Defines how a message is displayed.<br>
* <br> * <br>
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
* File: <strong>UserListRenderer.java</strong><br> * File: <strong>MessageListRenderer.java</strong><br>
* Created: <strong>19 Oct 2019</strong><br> * Created: <strong>19 Oct 2019</strong><br>
* *
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart

View File

@ -163,7 +163,7 @@ public class Startup {
chatWindow.initContent(client, localDb, writeProxy); chatWindow.initContent(client, localDb, writeProxy);
// Relay unread messages from cache // Relay unread messages from cache
if (cache != null) cache.relay(); if (cache != null && client.isOnline()) cache.relay();
try { try {
new StatusTrayIcon(chatWindow).show(); new StatusTrayIcon(chatWindow).show();

View File

@ -74,13 +74,10 @@ public class StatusTrayIcon {
trayIcon.addActionListener((evt) -> { focusTarget.setVisible(true); focusTarget.requestFocus(); }); trayIcon.addActionListener((evt) -> { focusTarget.setVisible(true); focusTarget.requestFocus(); });
// Start processing message events // Start processing message events
// TODO: Handle other message types
EventBus.getInstance() EventBus.getInstance()
.register(MessageCreationEvent.class, .register(MessageCreationEvent.class,
(evt) -> { evt -> { if (displayMessages) trayIcon.displayMessage("New message received", evt.get().getText(), MessageType.INFO); });
// TODO: Handle other message types
if (displayMessages)
trayIcon.displayMessage("New message received", ((MessageCreationEvent) evt).get().getText(), MessageType.INFO);
});
} }
/** /**

View File

@ -1,6 +1,7 @@
package envoy.client.ui; package envoy.client.ui;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JList; import javax.swing.JList;
@ -41,6 +42,8 @@ public class UserListRenderer extends JLabel implements ListCellRenderer<User> {
final String name = value.getName(); final String name = value.getName();
final UserStatus status = value.getStatus(); final UserStatus status = value.getStatus();
this.setPreferredSize(new Dimension(100, 35));
// Getting the UserNameColor of the current theme // Getting the UserNameColor of the current theme
String textColor = null; String textColor = null;
textColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor().toHex(); textColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor().toHex();

View File

@ -62,8 +62,10 @@ public class ComponentList<E> extends JPanel {
// Synchronize with new model // Synchronize with new model
this.model = model; this.model = model;
if (model != null) {
this.model.setComponentList(this); this.model.setComponentList(this);
synchronizeModel(); synchronizeModel();
} else removeAll();
} }
/** /**

View File

@ -159,7 +159,7 @@ public class SettingsScreen extends JDialog {
applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()));
// Respond to theme changes // Respond to theme changes
EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme(((ThemeChangeEvent) evt).get())); EventBus.getInstance().register(ThemeChangeEvent.class, evt -> applyTheme(evt.get()));
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModal(true); setModal(true);

View File

@ -119,8 +119,8 @@ public class ThemeCustomizationPanel extends SettingsPanel {
// Respond to theme changes // Respond to theme changes
EventBus.getInstance() EventBus.getInstance()
.register(ThemeChangeEvent.class, .register(ThemeChangeEvent.class,
(evt) -> { evt -> {
final Theme currentTheme = ((ThemeChangeEvent) evt).get(); final Theme currentTheme = evt.get();
temporaryTheme = new Theme("temporaryTheme", currentTheme); temporaryTheme = new Theme("temporaryTheme", currentTheme);
applyTheme(currentTheme); applyTheme(currentTheme);
}); });
@ -130,7 +130,7 @@ public class ThemeCustomizationPanel extends SettingsPanel {
public ActionListener getOkButtonAction() { public ActionListener getOkButtonAction() {
return (evt) -> { return (evt) -> {
if (themeChanged) { if (themeChanged) {
new NewThemeScreen(parent, (name) -> { new NewThemeScreen(parent, name -> {
// Create new theme // Create new theme
logger.log(Level.FINEST, name); logger.log(Level.FINEST, name);
Settings.getInstance().addNewThemeToMap(new Theme(name, temporaryTheme)); Settings.getInstance().addNewThemeToMap(new Theme(name, temporaryTheme));
@ -140,7 +140,7 @@ public class ThemeCustomizationPanel extends SettingsPanel {
// Select new theme name // Select new theme name
themes.setSelectedIndex(themesModel.getSize() - 1); themes.setSelectedIndex(themesModel.getSize() - 1);
}, (name) -> { }, name -> {
// Modify theme // Modify theme
Settings.getInstance().getThemes().replace(name, new Theme(name, temporaryTheme)); Settings.getInstance().getThemes().replace(name, new Theme(name, temporaryTheme));
if (themes.getSelectedItem().equals(name)) { if (themes.getSelectedItem().equals(name)) {