Extracted MessageComponent from MessageListRenderer
This commit is contained in:
		| @@ -50,7 +50,6 @@ public class ContextMenu extends JPopupMenu { | |||||||
|  |  | ||||||
| 	private ButtonGroup	radioButtonGroup	= new ButtonGroup(); | 	private ButtonGroup	radioButtonGroup	= new ButtonGroup(); | ||||||
| 	private boolean		built				= false; | 	private boolean		built				= false; | ||||||
| 	private boolean		visible				= false; |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @param parent the component which will call this | 	 * @param parent the component which will call this | ||||||
| @@ -110,8 +109,10 @@ public class ContextMenu extends JPopupMenu { | |||||||
| 			if (mnemonics.containsKey(text)) item.setMnemonic(mnemonics.get(text)); | 			if (mnemonics.containsKey(text)) item.setMnemonic(mnemonics.get(text)); | ||||||
| 			add(item); | 			add(item); | ||||||
| 		}); | 		}); | ||||||
| 		getInvoker().addMouseListener(getShowingListener()); | 		if (getInvoker() != null) { | ||||||
| 		built = true; | 			getInvoker().addMouseListener(getShowingListener()); | ||||||
|  | 			built = true; | ||||||
|  | 		} | ||||||
| 		return this; | 		return this; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -138,10 +139,8 @@ public class ContextMenu extends JPopupMenu { | |||||||
| 				if (!built) build(); | 				if (!built) build(); | ||||||
| 				if (e.isPopupTrigger()) { | 				if (e.isPopupTrigger()) { | ||||||
| 					// hides the menu if already visible | 					// hides the menu if already visible | ||||||
| 					visible = !visible; | 					if (!isVisible()) show(e.getComponent(), e.getX(), e.getY()); | ||||||
| 					if (visible) show(e.getComponent(), e.getX(), e.getY()); |  | ||||||
| 					else setVisible(false); | 					else setVisible(false); | ||||||
|  |  | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
|   | |||||||
							
								
								
									
										120
									
								
								src/main/java/envoy/client/ui/MessageComponent.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/main/java/envoy/client/ui/MessageComponent.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | |||||||
|  | package envoy.client.ui; | ||||||
|  |  | ||||||
|  | import java.awt.*; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.text.SimpleDateFormat; | ||||||
|  | import java.util.EnumMap; | ||||||
|  |  | ||||||
|  | import javax.swing.*; | ||||||
|  |  | ||||||
|  | import envoy.client.data.Settings; | ||||||
|  | import envoy.client.ui.list.ComponentList; | ||||||
|  | import envoy.data.Message; | ||||||
|  | import envoy.data.Message.MessageStatus; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Project: <strong>envoy-client</strong> | ||||||
|  |  * File: <strong>MessageComponent.java</strong> | ||||||
|  |  * Created: <strong>21.03.2020</strong> | ||||||
|  |  * | ||||||
|  |  * @author Kai S. K. Engelbart | ||||||
|  |  * @since Envoy v0.1-beta | ||||||
|  |  */ | ||||||
|  | public class MessageComponent extends JPanel { | ||||||
|  |  | ||||||
|  | 	private static final long serialVersionUID = 103920706139926996L; | ||||||
|  |  | ||||||
|  | 	private static EnumMap<MessageStatus, ImageIcon>	statusIcons; | ||||||
|  | 	private static ImageIcon							forwardIcon; | ||||||
|  |  | ||||||
|  | 	static { | ||||||
|  | 		try { | ||||||
|  | 			statusIcons	= IconUtil.loadByEnum(MessageStatus.class, 16); | ||||||
|  | 			forwardIcon	= IconUtil.load("/icons/forward.png", 16); | ||||||
|  | 		} catch (IOException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public MessageComponent(ComponentList<? extends Message> list, Message message, boolean isSelected, long senderId) { | ||||||
|  | 		this(list.getMaximumSize().width, message, isSelected, senderId); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public MessageComponent(int width, Message message, boolean isSelected, long senderId) { | ||||||
|  | 		final var	theme	= Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); | ||||||
|  | 		final int	padding	= (int) (width * 0.35); | ||||||
|  |  | ||||||
|  | 		GridBagLayout gbl_panel = new GridBagLayout(); | ||||||
|  | 		gbl_panel.columnWidths	= new int[] { 1, 1 }; | ||||||
|  | 		gbl_panel.rowHeights	= new int[] { 1, 1 }; | ||||||
|  | 		gbl_panel.columnWeights	= new double[] { 1, 1 }; | ||||||
|  | 		gbl_panel.rowWeights	= new double[] { 1, 1 }; | ||||||
|  |  | ||||||
|  | 		setLayout(gbl_panel); | ||||||
|  | 		setBackground(isSelected ? theme.getSelectionColor() : theme.getCellColor()); | ||||||
|  |  | ||||||
|  | 		// Date Label - The Label that displays the creation date of a message | ||||||
|  | 		var dateLabel = new JLabel(new SimpleDateFormat("dd.MM.yyyy HH:mm").format(message.getCreationDate())); | ||||||
|  | 		dateLabel.setForeground(theme.getDateColor()); | ||||||
|  | 		dateLabel.setAlignmentX(1f); | ||||||
|  | 		dateLabel.setFont(new Font("Arial", Font.PLAIN, 12)); | ||||||
|  | 		dateLabel.setPreferredSize(dateLabel.getPreferredSize()); | ||||||
|  |  | ||||||
|  | 		var gbc_dateLabel = new GridBagConstraints(); | ||||||
|  | 		gbc_dateLabel.fill	= GridBagConstraints.BOTH; | ||||||
|  | 		gbc_dateLabel.gridx	= 0; | ||||||
|  | 		gbc_dateLabel.gridy	= 0; | ||||||
|  | 		add(dateLabel, gbc_dateLabel); | ||||||
|  |  | ||||||
|  | 		// Message area - The JTextArea that displays the text content of a message. | ||||||
|  | 		var messageTextArea = new JTextArea(message.getText()); | ||||||
|  | 		messageTextArea.setLineWrap(true); | ||||||
|  | 		messageTextArea.setWrapStyleWord(true); | ||||||
|  | 		messageTextArea.setForeground(theme.getMessageTextColor()); | ||||||
|  | 		messageTextArea.setAlignmentX(0.5f); | ||||||
|  | 		messageTextArea.setBackground(theme.getCellColor()); | ||||||
|  | 		messageTextArea.setEditable(false); | ||||||
|  | 		var font = new Font("Arial", Font.PLAIN, 14); | ||||||
|  | 		messageTextArea.setFont(font); | ||||||
|  | 		messageTextArea.setSize(width - padding - 16, 10); | ||||||
|  |  | ||||||
|  | 		var gbc_messageTextArea = new GridBagConstraints(); | ||||||
|  | 		gbc_messageTextArea.fill	= GridBagConstraints.HORIZONTAL; | ||||||
|  | 		gbc_messageTextArea.gridx	= 0; | ||||||
|  | 		gbc_messageTextArea.gridy	= 1; | ||||||
|  | 		add(messageTextArea, gbc_messageTextArea); | ||||||
|  |  | ||||||
|  | 		// Status Label - displays the status of the message | ||||||
|  | 		var statusLabel = new JLabel(statusIcons.get(message.getStatus())); | ||||||
|  |  | ||||||
|  | 		var gbc_statusLabel = new GridBagConstraints(); | ||||||
|  | 		gbc_statusLabel.gridx	= 1; | ||||||
|  | 		gbc_statusLabel.gridy	= 1; | ||||||
|  | 		add(statusLabel, gbc_statusLabel); | ||||||
|  |  | ||||||
|  | 		// Forwarding | ||||||
|  | 		if (message.isForwarded()) { | ||||||
|  | 			var forwardLabel = new JLabel("Forwarded", forwardIcon, SwingConstants.CENTER); | ||||||
|  | 			forwardLabel.setBackground(getBackground()); | ||||||
|  | 			forwardLabel.setForeground(Color.lightGray); | ||||||
|  |  | ||||||
|  | 			var gbc_forwardLabel = new GridBagConstraints(); | ||||||
|  | 			gbc_forwardLabel.fill	= GridBagConstraints.BOTH; | ||||||
|  | 			gbc_forwardLabel.gridx	= 1; | ||||||
|  | 			gbc_forwardLabel.gridy	= 0; | ||||||
|  | 			add(forwardLabel, gbc_forwardLabel); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Define an etched border and some space to the messages below | ||||||
|  | 		var ours = senderId == message.getSenderId(); | ||||||
|  | 		setBorder(BorderFactory.createCompoundBorder( | ||||||
|  | 				BorderFactory.createEmptyBorder(0, ours ? padding : 10, 10, ours ? 0 : padding), | ||||||
|  | 				BorderFactory.createEtchedBorder())); | ||||||
|  |  | ||||||
|  | 		var size = new Dimension(width - 50, getPreferredSize().height); | ||||||
|  |  | ||||||
|  | 		setPreferredSize(size); | ||||||
|  | 		setMinimumSize(size); | ||||||
|  | 		setMaximumSize(size); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -125,16 +125,14 @@ public class ChatWindow extends JFrame { | |||||||
| 		gbl_contentPane.rowWeights		= new double[] { 0.03, 0.001, 1.0, 0.005 }; | 		gbl_contentPane.rowWeights		= new double[] { 0.03, 0.001, 1.0, 0.005 }; | ||||||
| 		contentPane.setLayout(gbl_contentPane); | 		contentPane.setLayout(gbl_contentPane); | ||||||
|  |  | ||||||
| 		messageList.setBorder(new EmptyBorder(space, space, space, space)); | 		// ContextMenu | ||||||
| 		messageList.setSelectionMode(SelectionMode.SINGLE); |  | ||||||
| 		Map<String, ActionListener> commands = new HashMap<>() { | 		Map<String, ActionListener> commands = new HashMap<>() { | ||||||
|  |  | ||||||
| 			private static final long serialVersionUID = -2755235774946990126L; | 			private static final long serialVersionUID = -2755235774946990126L; | ||||||
|  |  | ||||||
| 			{ | 			{ | ||||||
| 				put("forward selected message", | 				put("forward selected message", | ||||||
| 						evt -> forwardMessageToMultipleUsers(messageList | 						evt -> forwardMessageToMultipleUsers(messageList.getSingleSelectedElement(), | ||||||
| 							.getSingleSelectedElement(), |  | ||||||
| 								ContactsChooserDialog | 								ContactsChooserDialog | ||||||
| 									.showForwardingDialog("Forward selected message to", messageList.getSingleSelectedElement(), client))); | 									.showForwardingDialog("Forward selected message to", messageList.getSingleSelectedElement(), client))); | ||||||
| 				put("copy", evt -> { | 				put("copy", evt -> { | ||||||
| @@ -151,6 +149,11 @@ public class ChatWindow extends JFrame { | |||||||
| 		}; | 		}; | ||||||
| 		contextMenu = new ContextMenu(null, messageList, commands, null, null).build(); | 		contextMenu = new ContextMenu(null, messageList, commands, null, null).build(); | ||||||
|  |  | ||||||
|  | 		messageList.setBorder(new EmptyBorder(space, space, space, space)); | ||||||
|  | 		messageList.setSelectionMode(SelectionMode.SINGLE); | ||||||
|  | 		messageList.setSelectionListener((list, comp) ->  | ||||||
|  | 		contextMenu.show(comp, 0, 0)); | ||||||
|  |  | ||||||
| 		scrollPane.setViewportView(messageList); | 		scrollPane.setViewportView(messageList); | ||||||
| 		scrollPane.addComponentListener(new ComponentAdapter() { | 		scrollPane.addComponentListener(new ComponentAdapter() { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -76,7 +76,7 @@ public class ContactsChooserDialog extends JDialog { | |||||||
| 		dialog.setVisible(true); | 		dialog.setVisible(true); | ||||||
| 		dialog.repaint(); | 		dialog.repaint(); | ||||||
| 		dialog.revalidate(); | 		dialog.revalidate(); | ||||||
| 		return results.size() > 0 ? results : null; | 		return results; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import java.awt.event.MouseEvent; | |||||||
| import java.awt.event.MouseListener; | import java.awt.event.MouseListener; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
|  | import java.util.function.BiConsumer; | ||||||
|  |  | ||||||
| import javax.swing.*; | import javax.swing.*; | ||||||
|  |  | ||||||
| @@ -23,10 +24,11 @@ import javax.swing.*; | |||||||
|  */ |  */ | ||||||
| public class ComponentList<E> extends JPanel { | public class ComponentList<E> extends JPanel { | ||||||
|  |  | ||||||
| 	private ComponentListModel<E>			model; | 	private ComponentListModel<E>						model; | ||||||
| 	private ComponentListCellRenderer<E>	renderer; | 	private ComponentListCellRenderer<E>				renderer; | ||||||
| 	private SelectionMode					selectionMode	= SelectionMode.NONE; | 	private SelectionMode								selectionMode	= SelectionMode.NONE; | ||||||
| 	private Set<Integer>					selection		= new HashSet<>(); | 	private Set<Integer>								selection		= new HashSet<>(); | ||||||
|  | 	private BiConsumer<ComponentList<E>, JComponent>	selectionListener; | ||||||
|  |  | ||||||
| 	private static final long serialVersionUID = 1759644503942876737L; | 	private static final long serialVersionUID = 1759644503942876737L; | ||||||
|  |  | ||||||
| @@ -142,6 +144,9 @@ public class ComponentList<E> extends JPanel { | |||||||
|  |  | ||||||
| 				// Update element | 				// Update element | ||||||
| 				updateElement(index, true); | 				updateElement(index, true); | ||||||
|  |  | ||||||
|  | 				// Trigger selection listener | ||||||
|  | 				if (selectionListener != null) selectionListener.accept(this, (JComponent) getComponents()[index]); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -273,4 +278,14 @@ public class ComponentList<E> extends JPanel { | |||||||
| 	 * @since Envoy v0.1-beta | 	 * @since Envoy v0.1-beta | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setSelectionMode(SelectionMode selectionMode) { this.selectionMode = selectionMode; } | 	public void setSelectionMode(SelectionMode selectionMode) { this.selectionMode = selectionMode; } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @return the selectionListener | ||||||
|  | 	 */ | ||||||
|  | 	public BiConsumer<ComponentList<E>, JComponent> getSelectionListener() { return selectionListener; } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @param selectionListener the selectionListener to set | ||||||
|  | 	 */ | ||||||
|  | 	public void setSelectionListener(BiConsumer<ComponentList<E>, JComponent> selectionListener) { this.selectionListener = selectionListener; } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,19 +1,11 @@ | |||||||
| package envoy.client.ui.renderer; | package envoy.client.ui.renderer; | ||||||
|  |  | ||||||
| import java.awt.*; | import javax.swing.JPanel; | ||||||
| import java.io.IOException; |  | ||||||
| import java.text.SimpleDateFormat; |  | ||||||
| import java.util.EnumMap; |  | ||||||
|  |  | ||||||
| import javax.swing.*; | import envoy.client.ui.MessageComponent; | ||||||
|  |  | ||||||
| import envoy.client.data.Settings; |  | ||||||
| import envoy.client.ui.Color; |  | ||||||
| import envoy.client.ui.IconUtil; |  | ||||||
| import envoy.client.ui.list.ComponentList; | import envoy.client.ui.list.ComponentList; | ||||||
| import envoy.client.ui.list.ComponentListCellRenderer; | import envoy.client.ui.list.ComponentListCellRenderer; | ||||||
| import envoy.data.Message; | import envoy.data.Message; | ||||||
| import envoy.data.Message.MessageStatus; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Defines how a message is displayed.<br> |  * Defines how a message is displayed.<br> | ||||||
| @@ -29,18 +21,6 @@ import envoy.data.Message.MessageStatus; | |||||||
|  */ |  */ | ||||||
| public class MessageListRenderer implements ComponentListCellRenderer<Message> { | public class MessageListRenderer implements ComponentListCellRenderer<Message> { | ||||||
|  |  | ||||||
| 	private static EnumMap<MessageStatus, ImageIcon>	statusIcons; |  | ||||||
| 	private static ImageIcon							forwardIcon; |  | ||||||
|  |  | ||||||
| 	static { |  | ||||||
| 		try { |  | ||||||
| 			statusIcons = IconUtil.loadByEnum(MessageStatus.class, 16); |  | ||||||
| 			forwardIcon	= IconUtil.load("/icons/forward.png", 16); |  | ||||||
| 		} catch (IOException e) { |  | ||||||
| 			e.printStackTrace(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private final long senderId; | 	private final long senderId; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -57,84 +37,6 @@ public class MessageListRenderer implements ComponentListCellRenderer<Message> { | |||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public JPanel getListCellComponent(ComponentList<? extends Message> list, Message message, boolean isSelected) { | 	public JPanel getListCellComponent(ComponentList<? extends Message> list, Message message, boolean isSelected) { | ||||||
| 		final var theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); | 		return new MessageComponent(list, message, isSelected, senderId); | ||||||
|  |  | ||||||
| 		// Panel |  | ||||||
| 		final var	panel	= new JPanel(); |  | ||||||
| 		final int	padding	= (int) (list.getWidth() * 0.35); |  | ||||||
|  |  | ||||||
| 		GridBagLayout gbl_panel = new GridBagLayout(); |  | ||||||
| 		gbl_panel.columnWidths	= new int[] { 1, 1 }; |  | ||||||
| 		gbl_panel.rowHeights	= new int[] { 1, 1 }; |  | ||||||
| 		gbl_panel.columnWeights	= new double[] { 1, 1 }; |  | ||||||
| 		gbl_panel.rowWeights	= new double[] { 1, 1 }; |  | ||||||
|  |  | ||||||
| 		panel.setLayout(gbl_panel); |  | ||||||
| 		panel.setBackground(isSelected ? theme.getSelectionColor() : theme.getCellColor()); |  | ||||||
|  |  | ||||||
| 		// Date Label - The Label that displays the creation date of a message |  | ||||||
| 		var dateLabel = new JLabel(new SimpleDateFormat("dd.MM.yyyy HH:mm").format(message.getCreationDate())); |  | ||||||
| 		dateLabel.setForeground(theme.getDateColor()); |  | ||||||
| 		dateLabel.setAlignmentX(1f); |  | ||||||
| 		dateLabel.setFont(new Font("Arial", Font.PLAIN, 12)); |  | ||||||
| 		dateLabel.setPreferredSize(dateLabel.getPreferredSize()); |  | ||||||
|  |  | ||||||
| 		var gbc_dateLabel = new GridBagConstraints(); |  | ||||||
| 		gbc_dateLabel.fill	= GridBagConstraints.BOTH; |  | ||||||
| 		gbc_dateLabel.gridx	= 0; |  | ||||||
| 		gbc_dateLabel.gridy	= 0; |  | ||||||
| 		panel.add(dateLabel, gbc_dateLabel); |  | ||||||
|  |  | ||||||
| 		// Message area - The JTextArea that displays the text content of a message. |  | ||||||
| 		var messageTextArea = new JTextArea(message.getText()); |  | ||||||
| 		messageTextArea.setLineWrap(true); |  | ||||||
| 		messageTextArea.setWrapStyleWord(true); |  | ||||||
| 		messageTextArea.setForeground(theme.getMessageTextColor()); |  | ||||||
| 		messageTextArea.setAlignmentX(0.5f); |  | ||||||
| 		messageTextArea.setBackground(theme.getCellColor()); |  | ||||||
| 		messageTextArea.setEditable(false); |  | ||||||
| 		var font = new Font("Arial", Font.PLAIN, 14); |  | ||||||
| 		messageTextArea.setFont(font); |  | ||||||
| 		messageTextArea.setSize(list.getMaximumSize().width - padding - 16, 10); |  | ||||||
|  |  | ||||||
| 		var gbc_messageTextArea = new GridBagConstraints(); |  | ||||||
| 		gbc_messageTextArea.fill	= GridBagConstraints.HORIZONTAL; |  | ||||||
| 		gbc_messageTextArea.gridx	= 0; |  | ||||||
| 		gbc_messageTextArea.gridy	= 1; |  | ||||||
| 		panel.add(messageTextArea, gbc_messageTextArea); |  | ||||||
|  |  | ||||||
| 		// Status Label - displays the status of the message |  | ||||||
| 		var statusLabel = new JLabel(statusIcons.get(message.getStatus())); |  | ||||||
|  |  | ||||||
| 		var gbc_statusLabel = new GridBagConstraints(); |  | ||||||
| 		gbc_statusLabel.gridx	= 1; |  | ||||||
| 		gbc_statusLabel.gridy	= 1; |  | ||||||
| 		panel.add(statusLabel, gbc_statusLabel); |  | ||||||
|  |  | ||||||
| 		// Forwarding |  | ||||||
| 		if (message.isForwarded()) { |  | ||||||
| 			var forwardLabel = new JLabel("Forwarded", forwardIcon, SwingConstants.CENTER); |  | ||||||
| 			forwardLabel.setBackground(panel.getBackground()); |  | ||||||
| 			forwardLabel.setForeground(Color.lightGray); |  | ||||||
|  |  | ||||||
| 			var gbc_forwardLabel = new GridBagConstraints(); |  | ||||||
| 			gbc_forwardLabel.fill	= GridBagConstraints.BOTH; |  | ||||||
| 			gbc_forwardLabel.gridx	= 1; |  | ||||||
| 			gbc_forwardLabel.gridy	= 0; |  | ||||||
| 			panel.add(forwardLabel, gbc_forwardLabel); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// Define an etched border and some space to the messages below |  | ||||||
| 		var ours = senderId == message.getSenderId(); |  | ||||||
| 		panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, ours ? padding : 0, 10, ours ? 0 : padding), |  | ||||||
| 				BorderFactory.createEtchedBorder())); |  | ||||||
|  |  | ||||||
| 		var size = new Dimension(list.getMaximumSize().width - 50, panel.getPreferredSize().height); |  | ||||||
|  |  | ||||||
| 		panel.setPreferredSize(size); |  | ||||||
| 		panel.setMinimumSize(size); |  | ||||||
| 		panel.setMaximumSize(size); |  | ||||||
|  |  | ||||||
| 		return panel; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user