Added SelectionMode enum to ComponentList, prepared integration
These changes are not ready to build yet, as ChatWindow and ContactsChooserDialog have to be adjusted first.
This commit is contained in:
		@@ -131,12 +131,12 @@ public class ChatWindow extends JFrame {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				put("forward selected message",
 | 
									put("forward selected message",
 | 
				
			||||||
						evt -> forwardMessageToMultipleUsers(messageList.getSelected().get(0),
 | 
											evt -> forwardMessageToMultipleUsers(messageList.getSelection().get(0),
 | 
				
			||||||
								ContactsChooserDialog.showForwardingDialog("Forward selected message to", messageList.getSelected().get(0), client)));
 | 
													ContactsChooserDialog.showForwardingDialog("Forward selected message to", messageList.getSelection().get(0), client)));
 | 
				
			||||||
				put("copy", evt -> {
 | 
									put("copy", evt -> {
 | 
				
			||||||
					// TODO should be enhanced to allow also copying of message attachments,
 | 
										// TODO should be enhanced to allow also copying of message attachments,
 | 
				
			||||||
					// especially pictures
 | 
										// especially pictures
 | 
				
			||||||
					StringSelection copy = new StringSelection(messageList.getSelected().get(0).getText());
 | 
										StringSelection copy = new StringSelection(messageList.getSelection().get(0).getText());
 | 
				
			||||||
					Toolkit.getDefaultToolkit().getSystemClipboard().setContents(copy, copy);
 | 
										Toolkit.getDefaultToolkit().getSystemClipboard().setContents(copy, copy);
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
				// TODO insert implementation to edit and delete messages
 | 
									// TODO insert implementation to edit and delete messages
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,7 +69,7 @@ public class ContactsChooserDialog extends JDialog {
 | 
				
			|||||||
		dialog.getContentPanel()
 | 
							dialog.getContentPanel()
 | 
				
			||||||
			.add(new MessageListRenderer(client.getSender().getId()).getListCellComponent(null, message, false), BorderLayout.NORTH);
 | 
								.add(new MessageListRenderer(client.getSender().getId()).getListCellComponent(null, message, false), BorderLayout.NORTH);
 | 
				
			||||||
		List<User> results = new ArrayList<>();
 | 
							List<User> results = new ArrayList<>();
 | 
				
			||||||
		dialog.addOkButtonActionListener(e -> { results.addAll(dialog.getContactList().getSelected()); dialog.dispose(); });
 | 
							dialog.addOkButtonActionListener(e -> { results.addAll(dialog.getContactList().getSelection()); dialog.dispose(); });
 | 
				
			||||||
		ComponentListModel<User> contactListModel = dialog.getContactList().getModel();
 | 
							ComponentListModel<User> contactListModel = dialog.getContactList().getModel();
 | 
				
			||||||
		client.getContacts().getContacts().forEach(user -> contactListModel.add(user));
 | 
							client.getContacts().getContacts().forEach(user -> contactListModel.add(user));
 | 
				
			||||||
		dialog.setVisible(true);
 | 
							dialog.setVisible(true);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,8 @@ package envoy.client.ui.list;
 | 
				
			|||||||
import java.awt.event.MouseAdapter;
 | 
					import java.awt.event.MouseAdapter;
 | 
				
			||||||
import java.awt.event.MouseEvent;
 | 
					import java.awt.event.MouseEvent;
 | 
				
			||||||
import java.awt.event.MouseListener;
 | 
					import java.awt.event.MouseListener;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.swing.*;
 | 
					import javax.swing.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,15 +25,17 @@ public class ComponentList<E> extends JPanel {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	private ComponentListModel<E>			model;
 | 
						private ComponentListModel<E>			model;
 | 
				
			||||||
	private ComponentListCellRenderer<E>	renderer;
 | 
						private ComponentListCellRenderer<E>	renderer;
 | 
				
			||||||
	private boolean							multipleSelectionEnabled	= false;
 | 
						private SelectionMode					selectionMode	= SelectionMode.NONE;
 | 
				
			||||||
 | 
						private Set<Integer>					selection		= new HashSet<>();
 | 
				
			||||||
	private List<Integer> currentSelections = new ArrayList<>();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private static final long serialVersionUID = 1759644503942876737L;
 | 
						private static final long serialVersionUID = 1759644503942876737L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static enum SelectionMode {
 | 
				
			||||||
 | 
							NONE, SINGLE, MULTIPLE
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Sets the layout of this {@link ComponentList} to be a vertically oriented
 | 
						 * Initializes a default {@link ComponentList} without a model or a renderer.
 | 
				
			||||||
	 * BoxLayout.
 | 
					 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
@@ -79,8 +81,8 @@ 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);
 | 
							if (model != null) model.setComponentList(this);
 | 
				
			||||||
		if (renderer != null) synchronizeModel();
 | 
							synchronizeModel();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
@@ -92,11 +94,53 @@ public class ComponentList<E> extends JPanel {
 | 
				
			|||||||
	public void synchronizeModel() {
 | 
						public void synchronizeModel() {
 | 
				
			||||||
		if (model != null && renderer != null) {
 | 
							if (model != null && renderer != null) {
 | 
				
			||||||
			removeAll();
 | 
								removeAll();
 | 
				
			||||||
			model.forEach(this::add);
 | 
								model.forEach(this::addElement);
 | 
				
			||||||
			revalidate();
 | 
								revalidate();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Selects a list element by index. If the element is already selected, it is
 | 
				
			||||||
 | 
						 * removed from the selection.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param index the index of the selected component
 | 
				
			||||||
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void selectElement(int index) {
 | 
				
			||||||
 | 
							if (selection.contains(index)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Remove selection of element at index
 | 
				
			||||||
 | 
								updateElement(index, false);
 | 
				
			||||||
 | 
								selection.remove(index);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Remove old selection if single selection is enabled
 | 
				
			||||||
 | 
								if (selectionMode == SelectionMode.SINGLE) clearSelection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (selectionMode != SelectionMode.NONE) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Assign new selection
 | 
				
			||||||
 | 
									selection.add(index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Update element
 | 
				
			||||||
 | 
									updateElement(index, true);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							revalidate();
 | 
				
			||||||
 | 
							repaint();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Removes the current selection.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @since Envoy v0.1-alpha
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void clearSelection() {
 | 
				
			||||||
 | 
							selection.forEach(i -> updateElement(i, false));
 | 
				
			||||||
 | 
							selection.clear();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Adds an object to the list by rendering it with the current
 | 
						 * Adds an object to the list by rendering it with the current
 | 
				
			||||||
	 * {@link ComponentListCellRenderer}.
 | 
						 * {@link ComponentListCellRenderer}.
 | 
				
			||||||
@@ -104,89 +148,26 @@ public class ComponentList<E> extends JPanel {
 | 
				
			|||||||
	 * @param elem the element to add
 | 
						 * @param elem the element to add
 | 
				
			||||||
	 * @since Envoy v0.3-alpha
 | 
						 * @since Envoy v0.3-alpha
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	void add(E elem) { add(elem, getComponentCount(), false); }
 | 
						void addElement(E elem) { addElement(elem, getComponentCount(), false); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Adds an object to the list by rendering it with the current
 | 
						 * Adds an object to the list by rendering it with the current
 | 
				
			||||||
	 * {@link ComponentListRenderer}.
 | 
						 * {@link ComponentListRenderer}. If the renderer is {@code null}, no action is
 | 
				
			||||||
 | 
						 * performed.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @param elem       the element to add
 | 
						 * @param elem       the element to add
 | 
				
			||||||
	 * @param index      the index at which to add the element
 | 
						 * @param index      the index at which to add the element
 | 
				
			||||||
	 * @param isSelected the selection state of the element
 | 
						 * @param isSelected the selection state of the element
 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	private void add(E elem, int index, boolean isSelected) {
 | 
						private void addElement(E elem, int index, boolean isSelected) {
 | 
				
			||||||
		if (isSelected && !multipleSelectionEnabled) {
 | 
					 | 
				
			||||||
			clearSelections();
 | 
					 | 
				
			||||||
			currentSelections.add(index);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (renderer != null) {
 | 
							if (renderer != null) {
 | 
				
			||||||
		final JComponent component = renderer.getListCellComponent(this, elem, isSelected);
 | 
								final JComponent component = renderer.getListCellComponent(this, elem, isSelected);
 | 
				
			||||||
		component.addMouseListener(getSelectionListener(index));
 | 
								component.addMouseListener(getSelectionListener(index));
 | 
				
			||||||
		add(component, index);
 | 
								add(component, index);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * @param componentIndex the index of the list component to which the mouse
 | 
					 | 
				
			||||||
	 *                       listener will be added
 | 
					 | 
				
			||||||
	 * @return a mouse listener calling the
 | 
					 | 
				
			||||||
	 *         {@link ComponentList#componentSelected(int)} method with the
 | 
					 | 
				
			||||||
	 *         component's index when a left click is performed by the user
 | 
					 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private MouseListener getSelectionListener(int componentIndex) {
 | 
					 | 
				
			||||||
		return new MouseAdapter() {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			@Override
 | 
					 | 
				
			||||||
			public void mouseClicked(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) componentSelected(componentIndex); }
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Gets called when a list component has been clicked on by the user. Any
 | 
					 | 
				
			||||||
	 * previous selections are then removed and the selected component gets
 | 
					 | 
				
			||||||
	 * redrawn.<br>
 | 
					 | 
				
			||||||
	 * <br>
 | 
					 | 
				
			||||||
	 * If the currently selected component gets selected again, the selection is
 | 
					 | 
				
			||||||
	 * removed.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * @param index the index of the selected component
 | 
					 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private void componentSelected(int index) {
 | 
					 | 
				
			||||||
		// removing selection of element at index
 | 
					 | 
				
			||||||
		if (currentSelections.contains(index)) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Clear selection
 | 
					 | 
				
			||||||
			updateSelection(index, false);
 | 
					 | 
				
			||||||
			currentSelections.remove(Integer.valueOf(index));
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Remove old selection if multipleSelection is disabled
 | 
					 | 
				
			||||||
			if (!multipleSelectionEnabled && currentSelections.size() > 0) clearSelections();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Assign new selection
 | 
					 | 
				
			||||||
			currentSelections.add(index);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Update current selection
 | 
					 | 
				
			||||||
			updateSelection(index, true);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		revalidate();
 | 
					 | 
				
			||||||
		repaint();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Clears all currently active selections.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	private void clearSelections() {
 | 
					 | 
				
			||||||
		currentSelections.forEach(index -> updateSelection(index, false));
 | 
					 | 
				
			||||||
		currentSelections.clear();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Replaces a list element with a newly rendered instance of its contents.
 | 
						 * Replaces a list element with a newly rendered instance of its contents.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
@@ -194,21 +175,33 @@ public class ComponentList<E> extends JPanel {
 | 
				
			|||||||
	 * @param isSelected the selection state passed to the {@link ListCellRenderer}
 | 
						 * @param isSelected the selection state passed to the {@link ListCellRenderer}
 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	private void updateSelection(int index, boolean isSelected) {
 | 
						private void updateElement(int index, boolean isSelected) {
 | 
				
			||||||
		remove(index);
 | 
							remove(index);
 | 
				
			||||||
		add(model.get(index), index, isSelected);
 | 
							addElement(model.get(index), index, isSelected);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @return the selected elements or null if none is selected
 | 
						 * @param componentIndex the index of the list component to which the mouse
 | 
				
			||||||
 | 
						 *                       listener will be added
 | 
				
			||||||
 | 
						 * @return a mouse listener calling the
 | 
				
			||||||
 | 
						 *         {@link ComponentList#selectElement(int)} method with the
 | 
				
			||||||
 | 
						 *         component's index when a left click is performed by the user
 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public List<E> getSelected() {
 | 
						private MouseListener getSelectionListener(int componentIndex) {
 | 
				
			||||||
		List<E> selected = new ArrayList<>();
 | 
							return new MouseAdapter() {
 | 
				
			||||||
		currentSelections.forEach(index -> selected.add(model.get(index)));
 | 
					
 | 
				
			||||||
		return selected;
 | 
								@Override
 | 
				
			||||||
 | 
								public void mouseClicked(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) selectElement(componentIndex); }
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return a set of all selected indices
 | 
				
			||||||
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Set<Integer> getSelection() { return selection; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @return the model
 | 
						 * @return the model
 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
@@ -228,37 +221,14 @@ public class ComponentList<E> extends JPanel {
 | 
				
			|||||||
	public void setRenderer(ComponentListCellRenderer<E> renderer) { this.renderer = renderer; }
 | 
						public void setRenderer(ComponentListCellRenderer<E> renderer) { this.renderer = renderer; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @return the multipleSelectionEnabled
 | 
						 * @return the selectionMode
 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public boolean isMultipleSelectionEnabled() { return multipleSelectionEnabled; }
 | 
						public SelectionMode getSelectionMode() { return selectionMode; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @param multipleSelectionEnabled if true, multiple elements can be selected in
 | 
						 * @param selectionMode the selectionMode to set
 | 
				
			||||||
	 *                                 the component list
 | 
					 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
						 * @since Envoy v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void setMultipleSelectionEnabled(boolean multipleSelectionEnabled) {
 | 
						public void setSelectionMode(SelectionMode selectionMode) { this.selectionMode = selectionMode; }
 | 
				
			||||||
		this.multipleSelectionEnabled = multipleSelectionEnabled;
 | 
					 | 
				
			||||||
		if (!multipleSelectionEnabled) clearSelections();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Enables the selection of multiple elements.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * @see ComponentList#disableMultipleSelection
 | 
					 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public void enableMultipleSelection() { this.multipleSelectionEnabled = true; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Allows only one element to be selected. True by default.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * @see ComponentList#enableMultipleSelection
 | 
					 | 
				
			||||||
	 * @since Envoy v0.1-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public void disableMultipleSelection() {
 | 
					 | 
				
			||||||
		this.multipleSelectionEnabled = false;
 | 
					 | 
				
			||||||
		clearSelections();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@ public final class ComponentListModel<E> implements Iterable<E>, Serializable {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public boolean add(E e) {
 | 
						public boolean add(E e) {
 | 
				
			||||||
		if (componentList != null) {
 | 
							if (componentList != null) {
 | 
				
			||||||
			componentList.add(e);
 | 
								componentList.addElement(e);
 | 
				
			||||||
			componentList.revalidate();
 | 
								componentList.revalidate();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return elements.add(e);
 | 
							return elements.add(e);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user