From db0894dce903807ab18970a8c31752aa52709244 Mon Sep 17 00:00:00 2001 From: Haramus Samsamus Date: Sat, 22 Feb 2020 19:01:47 +0100 Subject: [PATCH] Added selection capability to ComponentList (#112) * Fixed Javadoc error in EnvoyLog * Added selection support to ComponentList using MouseListener injection * Added selection support to MessageListRenderer * Clearing selection when reselecting an already selected element --- .../envoy/client/ui/MessageListRenderer.java | 36 +++--- .../envoy/client/ui/list/ComponentList.java | 106 +++++++++++++++--- src/main/java/envoy/client/util/EnvoyLog.java | 2 +- 3 files changed, 110 insertions(+), 34 deletions(-) diff --git a/src/main/java/envoy/client/ui/MessageListRenderer.java b/src/main/java/envoy/client/ui/MessageListRenderer.java index a069721..fcb7c84 100644 --- a/src/main/java/envoy/client/ui/MessageListRenderer.java +++ b/src/main/java/envoy/client/ui/MessageListRenderer.java @@ -3,7 +3,9 @@ package envoy.client.ui; import java.awt.Dimension; import java.text.SimpleDateFormat; -import javax.swing.*; +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JPanel; import envoy.client.data.Settings; import envoy.client.ui.list.ComponentList; @@ -24,18 +26,12 @@ import envoy.data.Message; public class MessageListRenderer implements ComponentListCellRenderer { @Override - public JComponent getListCellComponent(ComponentList list, Message value, boolean isSelected) { - final JPanel panel = new JPanel(); - if (isSelected) { - panel.setBackground(Color.DARK_GRAY); - panel.setForeground(Color.RED); - // TODO: Selection - // setBackground(list.getSelectionBackground()); - // setForeground(list.getSelectionForeground()); - } else { - panel.setBackground(list.getBackground()); - panel.setForeground(list.getForeground()); - } + public JPanel getListCellComponent(ComponentList list, Message value, boolean isSelected) { + final JPanel panel = new JPanel(); + final Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); + + // Panel background + panel.setBackground(isSelected ? theme.getSelectionColor() : theme.getCellColor()); // TODO: Handle message attachments @@ -43,11 +39,11 @@ public class MessageListRenderer implements ComponentListCellRenderer { final String state = value.getStatus().toString(); final String date = new SimpleDateFormat("dd.MM.yyyy HH.mm").format(value.getCreationDate()); - // Getting the MessageColor in the Chat of the current theme - String textColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat().toHex(); + // Message text color + String textColor = theme.getMessageColorChat().toHex(); - // Getting the DateColor in the Chat of the current theme - String dateColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat().toHex(); + // Message date color + String dateColor = theme.getDateColorChat().toHex(); panel.add(new JLabel(String.format("

%s

%s :%s", dateColor, @@ -57,10 +53,10 @@ public class MessageListRenderer implements ComponentListCellRenderer { state))); // Define some space to the messages below - panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, 0, 15, 0), BorderFactory.createEtchedBorder())); + panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(), BorderFactory.createEtchedBorder())); - // Define a maximum height of 50px - Dimension size = new Dimension(list.getWidth() - 25, 50); + // Set the width to the list width + Dimension size = new Dimension(list.getWidth() - 25, panel.getPreferredSize().height); panel.setMaximumSize(size); panel.setMinimumSize(size); panel.setPreferredSize(size); diff --git a/src/main/java/envoy/client/ui/list/ComponentList.java b/src/main/java/envoy/client/ui/list/ComponentList.java index 4528b98..4b26978 100644 --- a/src/main/java/envoy/client/ui/list/ComponentList.java +++ b/src/main/java/envoy/client/ui/list/ComponentList.java @@ -1,7 +1,10 @@ package envoy.client.ui.list; -import javax.swing.BoxLayout; -import javax.swing.JPanel; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.*; /** * Provides a vertical list layout of components provided in a @@ -21,6 +24,8 @@ public class ComponentList extends JPanel { private ComponentListModel model; private ComponentListCellRenderer renderer; + private int currentSelection = -1; + private static final long serialVersionUID = 1759644503942876737L; /** @@ -50,22 +55,22 @@ public class ComponentList extends JPanel { } /** - * Sets the list model providing the list elements to render + * Sets the list model providing the list elements to render. The rendered + * components will be synchronized with the contents of the new model or removed + * if the new model is {@code null}. * * @param model the list model to set * @since Envoy v0.3-alpha */ public void setModel(ComponentListModel model) { + // Remove old model - if (this.model != null) - this.model.setComponentList(null); + if (this.model != null) this.model.setComponentList(null); // Synchronize with new model this.model = model; - if (model != null) { - this.model.setComponentList(this); - synchronizeModel(); - } else removeAll(); + if (model != null) this.model.setComponentList(this); + synchronizeModel(); } /** @@ -76,8 +81,7 @@ public class ComponentList extends JPanel { */ public void synchronizeModel() { removeAll(); - if (model != null) for (E elem : model) - add(elem); + if (model != null) model.forEach(this::add); } /** @@ -87,7 +91,83 @@ public class ComponentList extends JPanel { * @param elem the element to add * @since Envoy v0.3-alpha */ - void add(E elem) { - add(renderer.getListCellComponent(this, elem, false)); + void add(E elem) { add(elem, getComponentCount(), false); } + + /** + * Adds an object to the list by rendering it with the current + * {@link ComponentListRenderer}. + * + * @param elem the element to add + * @param index the index at which to add the element + * @param isSelected the selection state of the element + * @since Envoy v0.1-beta + */ + private void add(E elem, int index, boolean isSelected) { + final JComponent component = renderer.getListCellComponent(this, elem, isSelected); + component.addMouseListener(getSelectionListener(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.
+ *
+ * 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) { + if (index == currentSelection) { + + // Clear selection + update(currentSelection, false); + currentSelection = -1; + + } else { + + // Remove old selection + if (currentSelection >= 0) update(currentSelection, false); + + // Assign new selection + currentSelection = index; + + // Update current selection + update(currentSelection, true); + + } + + revalidate(); + repaint(); + } + + /** + * Replaces a list element with a newly rendered instance of its contents. + * + * @param index the index of the element to update + * @param isSelected the selection state passed to the {@link ListCellRenderer} + * @since Envoy v0.1-beta + */ + private void update(int index, boolean isSelected) { + remove(index); + add(model.get(index), index, isSelected); } } diff --git a/src/main/java/envoy/client/util/EnvoyLog.java b/src/main/java/envoy/client/util/EnvoyLog.java index 3cbb856..cf2818d 100644 --- a/src/main/java/envoy/client/util/EnvoyLog.java +++ b/src/main/java/envoy/client/util/EnvoyLog.java @@ -61,7 +61,7 @@ public class EnvoyLog { * path to use the console and file handlers. * * @param path the path to the loggers to configure - * @since Envoy Client v0.4-alpha + * @since Envoy Client v0.1-beta */ public static void attach(String path) { // Get root logger