Merge branch 'develop' into f/invalid_login
This commit is contained in:
		| @@ -127,7 +127,6 @@ public class Settings { | ||||
| 	 * @param themeName the name to set | ||||
| 	 * @since Envoy v0.2-alpha | ||||
| 	 */ | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	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. | ||||
| 	 * @since Envoy v0.2-alpha | ||||
| 	 */ | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	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. | ||||
| 	 * @since Envoy v0.3-alpha | ||||
| 	 */ | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	public void setCurrentOnCloseMode(boolean currentOnCloseMode) { ((SettingsItem<Boolean>) items.get("onCloseMode")).set(currentOnCloseMode); } | ||||
|  | ||||
| 	/** | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package envoy.client.event; | ||||
|  | ||||
| import envoy.data.Message; | ||||
| import envoy.event.Event; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>envoy-client</strong><br> | ||||
| @@ -10,7 +11,7 @@ import envoy.data.Message; | ||||
|  * @author Kai S. K. Engelbart | ||||
|  * @since Envoy v0.2-alpha | ||||
|  */ | ||||
| public class MessageCreationEvent extends MessageEvent { | ||||
| public class MessageCreationEvent extends Event<Message> { | ||||
|  | ||||
| 	private static final long serialVersionUID = -6451021678064566774L; | ||||
|  | ||||
|   | ||||
| @@ -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; } | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| package envoy.client.event; | ||||
|  | ||||
| import envoy.data.Message; | ||||
| import envoy.event.Event; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>envoy-client</strong><br> | ||||
| @@ -10,7 +11,7 @@ import envoy.data.Message; | ||||
|  * @author Kai S. K. Engelbart | ||||
|  * @since Envoy v0.2-alpha | ||||
|  */ | ||||
| public class MessageModificationEvent extends MessageEvent { | ||||
| public class MessageModificationEvent extends Event<Message> { | ||||
|  | ||||
| 	private static final long serialVersionUID = 4650039506439563116L; | ||||
|  | ||||
|   | ||||
							
								
								
									
										23
									
								
								src/main/java/envoy/client/event/SendEvent.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/main/java/envoy/client/event/SendEvent.java
									
									
									
									
									
										Normal 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äfer | ||||
|  *  | ||||
|  * @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); } | ||||
|  | ||||
| } | ||||
| @@ -11,10 +11,9 @@ import envoy.event.Event; | ||||
|  * @author Kai S. K. Engelbart | ||||
|  * @since Envoy v0.2-alpha | ||||
|  */ | ||||
| public class ThemeChangeEvent implements Event<Theme> { | ||||
| public class ThemeChangeEvent extends Event<Theme> { | ||||
|  | ||||
| 	private static final long	serialVersionUID	= 6756772448803774547L; | ||||
| 	private final Theme			theme; | ||||
|  | ||||
| 	/** | ||||
| 	 * 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 | ||||
| 	 * @since Envoy v0.2-alpha | ||||
| 	 */ | ||||
| 	public ThemeChangeEvent(Theme theme) { this.theme = theme; } | ||||
|  | ||||
| 	@Override | ||||
| 	public Theme get() { return theme; } | ||||
| 	public ThemeChangeEvent(Theme theme) { super(theme); } | ||||
| } | ||||
|   | ||||
| @@ -12,9 +12,11 @@ import javax.naming.TimeLimitExceededException; | ||||
| import envoy.client.data.Cache; | ||||
| import envoy.client.data.Config; | ||||
| import envoy.client.data.LocalDb; | ||||
| import envoy.client.event.SendEvent; | ||||
| import envoy.client.util.EnvoyLog; | ||||
| import envoy.data.*; | ||||
| import envoy.event.*; | ||||
| import envoy.event.ContactOperationEvent.Operation; | ||||
| import envoy.util.SerializationUtils; | ||||
|  | ||||
| /** | ||||
| @@ -109,11 +111,26 @@ public class Client implements Closeable { | ||||
| 		receiver.registerProcessor(MessageStatusChangeEvent.class, new MessageStatusChangeEventProcessor()); | ||||
|  | ||||
| 		// Process user status changes | ||||
| 		receiver.registerProcessor(UserStatusChangeEvent.class, new UserStatusChangeProcessor(this)); | ||||
| 		receiver.registerProcessor(UserStatusChangeEvent.class, new UserStatusChangeProcessor(localDb)); | ||||
|  | ||||
| 		// Process message ID generation | ||||
| 		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 | ||||
| 		if (!localDb.hasIdGenerator() || !localDb.getIdGenerator().hasNext()) requestIdGenerator(); | ||||
| 	} | ||||
|   | ||||
| @@ -30,9 +30,6 @@ public class MessageStatusChangeEventProcessor implements Consumer<MessageStatus | ||||
| 	@Override | ||||
| 	public void accept(MessageStatusChangeEvent evt) { | ||||
| 		if (evt.get().ordinal() < MessageStatus.RECEIVED.ordinal()) logger.info("Received invalid message status change " + evt); | ||||
| 		else { | ||||
| 			logger.info("Received " + evt.toString()); | ||||
| 			EventBus.getInstance().dispatch(evt); | ||||
| 		} | ||||
| 		else EventBus.getInstance().dispatch(evt); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -23,7 +23,6 @@ public class ReceivedMessageProcessor implements Consumer<Message> { | ||||
|  | ||||
| 	@Override | ||||
| 	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()); | ||||
| 		else { | ||||
| 			// Update status to RECEIVED | ||||
|   | ||||
| @@ -35,7 +35,6 @@ public class Receiver implements Runnable { | ||||
| 	 */ | ||||
| 	public Receiver(InputStream in) { this.in = in; } | ||||
|  | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	@Override | ||||
| 	public void run() { | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| package envoy.client.net; | ||||
|  | ||||
| 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.UserStatusChangeEvent; | ||||
|  | ||||
| @@ -17,21 +16,17 @@ import envoy.event.UserStatusChangeEvent; | ||||
|  */ | ||||
| public class UserStatusChangeProcessor implements Consumer<UserStatusChangeEvent> { | ||||
|  | ||||
| 	private Client client; | ||||
|  | ||||
| 	private static final Logger logger = EnvoyLog.getLogger(UserStatusChangeProcessor.class.getSimpleName()); | ||||
| 	private final LocalDb localDb; | ||||
|  | ||||
| 	/** | ||||
| 	 * @param client the {@link Client} who receives an | ||||
| 	 *               {@link UserStatusChangeEvent} | ||||
| 	 * @param localDb the local database in which status updates will by applied | ||||
| 	 * @since Envoy v0.3-alpha | ||||
| 	 */ | ||||
| 	public UserStatusChangeProcessor(Client client) { this.client = client; } | ||||
| 	public UserStatusChangeProcessor(LocalDb localDb) { this.localDb = localDb; } | ||||
|  | ||||
| 	@Override | ||||
| 	public void accept(UserStatusChangeEvent evt) { | ||||
| 		logger.info("Received " + evt); | ||||
| 		client.getContacts().getContacts().stream().filter((user) -> user.getId() == evt.getId()).findFirst().get().setStatus(evt.get()); | ||||
| 		localDb.getUsers().values().stream().filter(u -> u.getId() == evt.getId()).findFirst().get().setStatus(evt.get()); | ||||
| 		EventBus.getInstance().dispatch(evt); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -45,12 +45,14 @@ public class WriteProxy { | ||||
| 		// Initialize cache processors for messages and message status change events | ||||
| 		localDb.getMessageCache().setProcessor(msg -> { | ||||
| 			try { | ||||
| 				logger.info("Sending cached " + msg); | ||||
| 				client.sendMessage(msg); | ||||
| 			} catch (IOException e) { | ||||
| 				logger.log(Level.SEVERE, "Could not send cached message", e); | ||||
| 			} | ||||
| 		}); | ||||
| 		localDb.getStatusCache().setProcessor(evt -> { | ||||
| 			logger.info("Sending cached " + evt); | ||||
| 			try { | ||||
| 				client.sendEvent(evt); | ||||
| 			} catch (IOException e) { | ||||
| @@ -66,8 +68,6 @@ public class WriteProxy { | ||||
| 	 * @since Envoy v0.3-alpha | ||||
| 	 */ | ||||
| 	public void flushCache() { | ||||
| 		logger.info("Sending cached messages and message status change events..."); | ||||
|  | ||||
| 		// Send messages | ||||
| 		localDb.getMessageCache().relay(); | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,8 @@ import java.util.logging.Logger; | ||||
|  | ||||
| import javax.swing.*; | ||||
| import javax.swing.border.EmptyBorder; | ||||
| import javax.swing.event.DocumentEvent; | ||||
| import javax.swing.event.DocumentListener; | ||||
|  | ||||
| import envoy.client.Settings; | ||||
| import envoy.client.data.Chat; | ||||
| @@ -18,15 +20,14 @@ import envoy.client.event.ThemeChangeEvent; | ||||
| import envoy.client.net.Client; | ||||
| import envoy.client.net.WriteProxy; | ||||
| 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; | ||||
| import envoy.data.Message.MessageStatus; | ||||
| import envoy.data.MessageBuilder; | ||||
| import envoy.data.User; | ||||
| import envoy.event.EventBus; | ||||
| import envoy.event.MessageStatusChangeEvent; | ||||
| import envoy.event.UserStatusChangeEvent; | ||||
| import envoy.event.*; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>envoy-client</strong><br> | ||||
| @@ -49,6 +50,7 @@ public class ChatWindow extends JFrame { | ||||
| 	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(); | ||||
| @@ -56,6 +58,20 @@ public class ChatWindow extends JFrame { | ||||
| 	private PrimaryButton			postButton				= new PrimaryButton("Post"); | ||||
| 	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()); | ||||
|  | ||||
| 	// GUI component spacing | ||||
| @@ -81,16 +97,11 @@ public class ChatWindow extends JFrame { | ||||
| 		setContentPane(contentPane); | ||||
| 		GridBagLayout gbl_contentPane = new GridBagLayout(); | ||||
| 		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.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); | ||||
|  | ||||
| 		// 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)); | ||||
|  | ||||
| 		scrollPane.setViewportView(messageList); | ||||
| @@ -98,11 +109,13 @@ public class ChatWindow extends JFrame { | ||||
| 		GridBagConstraints gbc_scrollPane = new GridBagConstraints(); | ||||
| 		gbc_scrollPane.fill			= GridBagConstraints.BOTH; | ||||
| 		gbc_scrollPane.gridwidth	= 2; | ||||
| 		gbc_scrollPane.gridheight	= 2; | ||||
| 		gbc_scrollPane.gridx		= 1; | ||||
| 		gbc_scrollPane.gridy		= 1; | ||||
|  | ||||
| 		gbc_scrollPane.insets = insets; | ||||
| 		contentPane.add(scrollPane, gbc_scrollPane); | ||||
|  | ||||
| 		drawChatBox(gbc_scrollPane); | ||||
|  | ||||
| 		// Message enter field | ||||
| 		messageEnterTextArea.addKeyListener(new KeyAdapter() { | ||||
| @@ -118,7 +131,7 @@ public class ChatWindow extends JFrame { | ||||
| 		GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints(); | ||||
| 		gbc_messageEnterTextfield.fill	= GridBagConstraints.BOTH; | ||||
| 		gbc_messageEnterTextfield.gridx	= 1; | ||||
| 		gbc_messageEnterTextfield.gridy	= 2; | ||||
| 		gbc_messageEnterTextfield.gridy	= 3; | ||||
|  | ||||
| 		gbc_messageEnterTextfield.insets = insets; | ||||
|  | ||||
| @@ -129,7 +142,7 @@ public class ChatWindow extends JFrame { | ||||
|  | ||||
| 		gbc_moveSelectionPostButton.fill	= GridBagConstraints.BOTH; | ||||
| 		gbc_moveSelectionPostButton.gridx	= 2; | ||||
| 		gbc_moveSelectionPostButton.gridy	= 2; | ||||
| 		gbc_moveSelectionPostButton.gridy	= 3; | ||||
|  | ||||
| 		gbc_moveSelectionPostButton.insets = insets; | ||||
|  | ||||
| @@ -145,14 +158,7 @@ public class ChatWindow extends JFrame { | ||||
|  | ||||
| 		gbc_moveSelectionSettingsButton.insets = insets; | ||||
|  | ||||
| 		settingsButton.addActionListener((evt) -> { | ||||
| 			try { | ||||
| 				new SettingsScreen().setVisible(true); | ||||
| 			} catch (Exception e) { | ||||
| 				logger.log(Level.WARNING, "An error occured while opening the settings screen", e); | ||||
| 				e.printStackTrace(); | ||||
| 			} | ||||
| 		}); | ||||
| 		settingsButton.addActionListener(evt -> new SettingsScreen().setVisible(true)); | ||||
| 		contentPane.add(settingsButton, gbc_moveSelectionSettingsButton); | ||||
|  | ||||
| 		// Partner name display | ||||
| @@ -171,26 +177,30 @@ public class ChatWindow extends JFrame { | ||||
| 		userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | ||||
| 		userList.addListSelectionListener((listSelectionEvent) -> { | ||||
| 			if (client != null && localDb != null && !listSelectionEvent.getValueIsAdjusting()) { | ||||
| 				@SuppressWarnings("unchecked") | ||||
| 				final JList<User>	selectedUserList	= (JList<User>) listSelectionEvent.getSource(); | ||||
| 				final User			user				= selectedUserList.getSelectedValue(); | ||||
|  | ||||
| 				// Select current chat | ||||
| 				currentChat = localDb.getChats().stream().filter(chat -> chat.getRecipient().getId() == user.getId()).findFirst().get(); | ||||
| 				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(); | ||||
|  | ||||
| 				// Read current chat | ||||
| 				readCurrentChat(); | ||||
| 					// Read current chat | ||||
| 					readCurrentChat(); | ||||
|  | ||||
| 				// Set chat title | ||||
| 				textPane.setText(currentChat.getRecipient().getName()); | ||||
| 					// Set chat title | ||||
| 					textPane.setText(currentChat.getRecipient().getName()); | ||||
|  | ||||
| 				// Update model and scroll down | ||||
| 				messageList.setModel(currentChat.getModel()); | ||||
| 				scrollPane.setChatOpened(true); | ||||
| 					// Update model and scroll down | ||||
| 					messageList.setModel(currentChat.getModel()); | ||||
| 					scrollPane.setChatOpened(true); | ||||
|  | ||||
| 				messageList.synchronizeModel(); | ||||
| 				revalidate(); | ||||
| 				repaint(); | ||||
| 					messageList.synchronizeModel(); | ||||
| 					revalidate(); | ||||
| 					repaint(); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| @@ -198,26 +208,151 @@ public class ChatWindow extends JFrame { | ||||
| 		userList.setBorder(new EmptyBorder(space, space, space, space)); | ||||
|  | ||||
| 		GridBagConstraints gbc_userList = new GridBagConstraints(); | ||||
| 		gbc_userList.fill	= GridBagConstraints.VERTICAL; | ||||
| 		gbc_userList.gridx	= 0; | ||||
| 		gbc_userList.gridy	= 1; | ||||
| 		gbc_userList.anchor	= GridBagConstraints.PAGE_START; | ||||
| 		gbc_userList.insets	= insets; | ||||
|  | ||||
| 		applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); | ||||
| 		gbc_userList.fill		= GridBagConstraints.VERTICAL; | ||||
| 		gbc_userList.gridx		= 0; | ||||
| 		gbc_userList.gridy		= 2; | ||||
| 		gbc_userList.gridheight	= 2; | ||||
| 		gbc_userList.anchor		= GridBagConstraints.PAGE_START; | ||||
| 		gbc_userList.insets		= insets; | ||||
|  | ||||
| 		contentPane.add(userList, gbc_userList); | ||||
| 		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 | ||||
| 		EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme((Theme) evt.get())); | ||||
| 		EventBus.getInstance().register(ThemeChangeEvent.class, evt -> applyTheme(evt.get())); | ||||
|  | ||||
| 		// 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 | ||||
| 		EventBus.getInstance().register(MessageCreationEvent.class, (evt) -> { | ||||
| 			Message	message	= ((MessageCreationEvent) evt).get(); | ||||
| 		EventBus.getInstance().register(MessageCreationEvent.class, evt -> { | ||||
| 			Message	message	= evt.get(); | ||||
| 			Chat	chat	= localDb.getChats().stream().filter(c -> c.getRecipient().getId() == message.getSenderId()).findFirst().get(); | ||||
| 			chat.appendMessage(message); | ||||
|  | ||||
| @@ -229,9 +364,9 @@ public class ChatWindow extends JFrame { | ||||
| 		}); | ||||
|  | ||||
| 		// Listen to message status changes | ||||
| 		EventBus.getInstance().register(MessageStatusChangeEvent.class, (evt) -> { | ||||
| 			final long			id		= ((MessageStatusChangeEvent) evt).getId(); | ||||
| 			final MessageStatus	status	= (MessageStatus) evt.get(); | ||||
| 		EventBus.getInstance().register(MessageStatusChangeEvent.class, evt -> { | ||||
| 			final long			id		= evt.getId(); | ||||
| 			final MessageStatus	status	= evt.get(); | ||||
|  | ||||
| 			for (Chat c : localDb.getChats()) | ||||
| 				for (Message m : c.getModel()) | ||||
| @@ -251,7 +386,35 @@ public class ChatWindow extends JFrame { | ||||
| 			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(); | ||||
| 			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.setForeground(theme.getUserNameColor()); | ||||
| 		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() { | ||||
| @@ -336,7 +514,6 @@ public class ChatWindow extends JFrame { | ||||
| 	 */ | ||||
| 	private void loadUsersAndChats() { | ||||
| 		new Thread(() -> { | ||||
| 			DefaultListModel<User> userListModel = new DefaultListModel<>(); | ||||
| 			localDb.getUsers().values().forEach(user -> { | ||||
| 				userListModel.addElement(user); | ||||
|  | ||||
| @@ -345,6 +522,9 @@ public class ChatWindow extends JFrame { | ||||
| 					localDb.getChats().add(new Chat(user)); | ||||
| 			}); | ||||
| 			SwingUtilities.invokeLater(() -> userList.setModel(userListModel)); | ||||
|  | ||||
| 			revalidate(); | ||||
| 			repaint(); | ||||
| 		}).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 | ||||
| 	 * persistence.<br> | ||||
|   | ||||
							
								
								
									
										78
									
								
								src/main/java/envoy/client/ui/ContactsSearchRenderer.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/main/java/envoy/client/ui/ContactsSearchRenderer.java
									
									
									
									
									
										Normal 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ä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; | ||||
| 	} | ||||
| } | ||||
| @@ -9,6 +9,7 @@ import javax.swing.*; | ||||
| import javax.swing.border.EmptyBorder; | ||||
|  | ||||
| import envoy.client.event.HandshakeSuccessfulEvent; | ||||
| import envoy.client.Settings; | ||||
| import envoy.data.LoginCredentials; | ||||
| import envoy.event.EventBus; | ||||
| import envoy.event.HandshakeRejectionEvent; | ||||
| @@ -24,22 +25,29 @@ import envoy.event.HandshakeRejectionEvent; | ||||
|  */ | ||||
| public class LoginDialog extends JDialog { | ||||
|  | ||||
| 	private final JPanel contentPanel = new JPanel(); | ||||
|  | ||||
| 	private static final long	serialVersionUID	= 352021600833907468L; | ||||
| 	private final JPanel	contentPanel; | ||||
| 	private JTextField			textField; | ||||
| 	private JPasswordField		passwordField; | ||||
| 	private JPasswordField		repeatPasswordField; | ||||
|  | ||||
| 	private JPasswordField	repeatPasswordField; | ||||
| 	private JLabel			lblRepeatPassword; | ||||
| 	private JLabel			errorMessage; | ||||
|  | ||||
| 	private GridBagConstraints	gbc_errorMessage; | ||||
| 	private JLabel	lblUserName; | ||||
| 	private JLabel	lblPassword; | ||||
| 	private JLabel	lblRepeatPassword; | ||||
|   private JLabel			errorMessage; | ||||
|    | ||||
| 	private GridBagConstraints	gbc_lblRepeatPassword; | ||||
| 	private GridBagConstraints	gbc_repeatPasswordField; | ||||
|   private GridBagConstraints	gbc_errorMessage; | ||||
|  | ||||
| 	private JPanel buttonPane; | ||||
| 	private JTextPane		registerText; | ||||
| 	private JCheckBox		registerCheckBox; | ||||
| 	private PrimaryButton	okButton; | ||||
| 	private PrimaryButton	cancelButton; | ||||
|  | ||||
| 	private LoginCredentials credentials; | ||||
|  | ||||
| 	private static final long serialVersionUID = 352021600833907468L; | ||||
| 	/** | ||||
| 	 * Displays a dialog enabling the user to enter their user name and password. | ||||
| 	 * | ||||
| @@ -49,6 +57,7 @@ public class LoginDialog extends JDialog { | ||||
| 		setSize(338, 123); | ||||
| 		setLocationRelativeTo(null); | ||||
| 		getContentPane().setLayout(new BorderLayout()); | ||||
| 		contentPanel = new JPanel(); | ||||
| 		contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); | ||||
| 		getContentPane().add(contentPanel, BorderLayout.CENTER); | ||||
| 		GridBagLayout gbl_contentPanel = new GridBagLayout(); | ||||
| @@ -58,7 +67,7 @@ public class LoginDialog extends JDialog { | ||||
| 		gbl_contentPanel.rowWeights		= new double[] { 0.0, 0.0, Double.MIN_VALUE }; | ||||
| 		contentPanel.setLayout(gbl_contentPanel); | ||||
| 		{ | ||||
| 			JLabel				lblUserName		= new JLabel("User name:"); | ||||
| 			lblUserName = new JLabel("Username:"); | ||||
| 			GridBagConstraints	gbc_lblUserName	= new GridBagConstraints(); | ||||
| 			gbc_lblUserName.anchor	= GridBagConstraints.EAST; | ||||
| 			gbc_lblUserName.insets	= new Insets(0, 0, 5, 5); | ||||
| @@ -68,6 +77,7 @@ public class LoginDialog extends JDialog { | ||||
| 		} | ||||
| 		{ | ||||
| 			textField = new JTextField(); | ||||
| 			textField.setBorder(null); | ||||
| 			GridBagConstraints gbc_textField = new GridBagConstraints(); | ||||
| 			gbc_textField.insets	= new Insets(0, 0, 5, 0); | ||||
| 			gbc_textField.fill		= GridBagConstraints.HORIZONTAL; | ||||
| @@ -77,7 +87,7 @@ public class LoginDialog extends JDialog { | ||||
| 			textField.setColumns(10); | ||||
| 		} | ||||
| 		{ | ||||
| 			JLabel				lblPassword		= new JLabel("Password:"); | ||||
| 			lblPassword = new JLabel("Password:"); | ||||
| 			GridBagConstraints	gbc_lblPassword	= new GridBagConstraints(); | ||||
| 			gbc_lblPassword.anchor	= GridBagConstraints.EAST; | ||||
| 			gbc_lblPassword.insets	= new Insets(0, 0, 0, 5); | ||||
| @@ -87,6 +97,7 @@ public class LoginDialog extends JDialog { | ||||
| 		} | ||||
| 		{ | ||||
| 			passwordField = new JPasswordField(); | ||||
| 			passwordField.setBorder(null); | ||||
| 			GridBagConstraints gbc_passwordField = new GridBagConstraints(); | ||||
| 			gbc_passwordField.fill	= GridBagConstraints.HORIZONTAL; | ||||
| 			gbc_passwordField.gridx	= 1; | ||||
| @@ -124,22 +135,23 @@ public class LoginDialog extends JDialog { | ||||
| 			}); | ||||
| 		} | ||||
| 		{ | ||||
| 			JPanel buttonPane = new JPanel(); | ||||
| 			buttonPane = new JPanel(); | ||||
|  | ||||
| 			JTextPane registerText = new JTextPane(); | ||||
| 			registerText = new JTextPane(); | ||||
| 			registerText.setEditable(false); | ||||
| 			registerText.setText("Register?"); | ||||
| 			registerText.setFont(new Font("Arial", Font.BOLD, 12)); | ||||
| 			registerText.setAlignmentX(LEFT_ALIGNMENT); | ||||
| 			buttonPane.add(registerText); | ||||
|  | ||||
| 			JCheckBox registerCheckBox = new JCheckBox(); | ||||
| 			registerCheckBox = new JCheckBox(); | ||||
| 			registerCheckBox.setAlignmentX(LEFT_ALIGNMENT); | ||||
| 			registerCheckBox.addItemListener(e -> { | ||||
| 				switch (e.getStateChange()) { | ||||
| 					case ItemEvent.SELECTED: | ||||
| 						contentPanel.add(lblRepeatPassword, gbc_lblRepeatPassword); | ||||
| 						contentPanel.add(repeatPasswordField, gbc_repeatPasswordField); | ||||
| 						setSize(338, 160); | ||||
| 						setSize(338, 148); | ||||
| 						break; | ||||
|  | ||||
| 					case ItemEvent.DESELECTED: | ||||
| @@ -158,7 +170,7 @@ public class LoginDialog extends JDialog { | ||||
| 			buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); | ||||
| 			getContentPane().add(buttonPane, BorderLayout.SOUTH); | ||||
| 			{ | ||||
| 				JButton okButton = new JButton("OK"); | ||||
| 				okButton = new PrimaryButton("OK"); | ||||
| 				okButton.addActionListener((evt) -> { | ||||
| 					try { | ||||
| 						if (registerCheckBox.isSelected()) { | ||||
| @@ -179,12 +191,13 @@ public class LoginDialog extends JDialog { | ||||
| 				getRootPane().setDefaultButton(okButton); | ||||
| 			} | ||||
| 			{ | ||||
| 				JButton cancelButton = new JButton("Cancel"); | ||||
| 				cancelButton = new PrimaryButton("Cancel"); | ||||
| 				cancelButton.addActionListener((evt) -> dispose()); | ||||
| 				cancelButton.setActionCommand("Cancel"); | ||||
| 				buttonPane.add(cancelButton); | ||||
| 			} | ||||
| 		} | ||||
| 		setTheme(); | ||||
|  | ||||
| 		setModal(true); | ||||
| 		setVisible(true); | ||||
| @@ -201,6 +214,50 @@ public class LoginDialog extends JDialog { | ||||
| 		repeatPasswordField.setText(null); | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
| 	 *         the dialog has been cancelled | ||||
|   | ||||
| @@ -14,7 +14,7 @@ import envoy.data.Message; | ||||
|  * Defines how a message is displayed.<br> | ||||
|  * <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> | ||||
|  * | ||||
|  * @author Kai S. K. Engelbart | ||||
|   | ||||
| @@ -163,7 +163,7 @@ public class Startup { | ||||
| 				chatWindow.initContent(client, localDb, writeProxy); | ||||
|  | ||||
| 				// Relay unread messages from cache | ||||
| 				if (cache != null) cache.relay(); | ||||
| 				if (cache != null && client.isOnline()) cache.relay(); | ||||
|  | ||||
| 				try { | ||||
| 					new StatusTrayIcon(chatWindow).show(); | ||||
|   | ||||
| @@ -74,13 +74,10 @@ public class StatusTrayIcon { | ||||
| 		trayIcon.addActionListener((evt) -> { focusTarget.setVisible(true); focusTarget.requestFocus(); }); | ||||
|  | ||||
| 		// Start processing message events | ||||
| 		// TODO: Handle other message types | ||||
| 		EventBus.getInstance() | ||||
| 			.register(MessageCreationEvent.class, | ||||
| 					(evt) -> { | ||||
| 						// TODO: Handle other message types | ||||
| 						if (displayMessages) | ||||
| 							trayIcon.displayMessage("New message received", ((MessageCreationEvent) evt).get().getText(), MessageType.INFO); | ||||
| 					}); | ||||
| 					evt -> { if (displayMessages) trayIcon.displayMessage("New message received", evt.get().getText(), MessageType.INFO); }); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package envoy.client.ui; | ||||
|  | ||||
| import java.awt.Component; | ||||
| import java.awt.Dimension; | ||||
|  | ||||
| import javax.swing.JLabel; | ||||
| import javax.swing.JList; | ||||
| @@ -41,6 +42,8 @@ public class UserListRenderer extends JLabel implements ListCellRenderer<User> { | ||||
| 		final String		name	= value.getName(); | ||||
| 		final UserStatus	status	= value.getStatus(); | ||||
|  | ||||
| 		this.setPreferredSize(new Dimension(100, 35)); | ||||
|  | ||||
| 		// Getting the UserNameColor of the current theme | ||||
| 		String textColor = null; | ||||
| 		textColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor().toHex(); | ||||
|   | ||||
| @@ -62,8 +62,10 @@ public class ComponentList<E> extends JPanel { | ||||
|  | ||||
| 		// Synchronize with new model | ||||
| 		this.model = model; | ||||
| 		this.model.setComponentList(this); | ||||
| 		synchronizeModel(); | ||||
| 		if (model != null) { | ||||
| 			this.model.setComponentList(this); | ||||
| 			synchronizeModel(); | ||||
| 		} else removeAll(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
|   | ||||
| @@ -159,7 +159,7 @@ public class SettingsScreen extends JDialog { | ||||
| 		applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); | ||||
|  | ||||
| 		// 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); | ||||
| 		setModal(true); | ||||
|   | ||||
| @@ -47,7 +47,7 @@ public class ThemeCustomizationPanel extends SettingsPanel { | ||||
| 	 * Initializes a {@link ThemeCustomizationPanel} that enables the user to change | ||||
| 	 * the current {@link Theme} and create new themes as part of the | ||||
| 	 * {@link SettingsScreen}. | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param parent the {@link SettingsScreen} as a part of which this | ||||
| 	 *               {@link SettingsPanel} is displayed | ||||
| 	 * @since Envoy v0.2-alpha | ||||
| @@ -119,8 +119,8 @@ public class ThemeCustomizationPanel extends SettingsPanel { | ||||
| 		// Respond to theme changes | ||||
| 		EventBus.getInstance() | ||||
| 			.register(ThemeChangeEvent.class, | ||||
| 					(evt) -> { | ||||
| 						final Theme currentTheme = ((ThemeChangeEvent) evt).get(); | ||||
| 					evt -> { | ||||
| 						final Theme currentTheme = evt.get(); | ||||
| 						temporaryTheme = new Theme("temporaryTheme", currentTheme); | ||||
| 						applyTheme(currentTheme); | ||||
| 					}); | ||||
| @@ -130,7 +130,7 @@ public class ThemeCustomizationPanel extends SettingsPanel { | ||||
| 	public ActionListener getOkButtonAction() { | ||||
| 		return (evt) -> { | ||||
| 			if (themeChanged) { | ||||
| 				new NewThemeScreen(parent, (name) -> { | ||||
| 				new NewThemeScreen(parent, name -> { | ||||
| 					// Create new theme | ||||
| 					logger.log(Level.FINEST, name); | ||||
| 					Settings.getInstance().addNewThemeToMap(new Theme(name, temporaryTheme)); | ||||
| @@ -140,12 +140,12 @@ public class ThemeCustomizationPanel extends SettingsPanel { | ||||
|  | ||||
| 					// Select new theme name | ||||
| 					themes.setSelectedIndex(themesModel.getSize() - 1); | ||||
| 				}, (name) -> { | ||||
| 				}, name -> { | ||||
| 					// Modify theme | ||||
| 					Settings.getInstance().getThemes().replace(name, new Theme(name, temporaryTheme)); | ||||
| 					if(themes.getSelectedItem().equals(name)) { | ||||
| 					if (themes.getSelectedItem().equals(name)) { | ||||
| 						EventBus.getInstance().dispatch(new ThemeChangeEvent(Settings.getInstance().getTheme(name))); | ||||
| 					}else { | ||||
| 					} else { | ||||
| 						themes.setSelectedItem(name); | ||||
| 					} | ||||
| 				}).setVisible(true); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 GitHub
						GitHub