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
This commit is contained in:
Kai S. K. Engelbart 2020-02-22 19:01:47 +01:00 committed by GitHub
parent fc7022834c
commit db0894dce9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 110 additions and 34 deletions

View File

@ -3,7 +3,9 @@ package envoy.client.ui;
import java.awt.Dimension; import java.awt.Dimension;
import java.text.SimpleDateFormat; 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.data.Settings;
import envoy.client.ui.list.ComponentList; import envoy.client.ui.list.ComponentList;
@ -24,18 +26,12 @@ import envoy.data.Message;
public class MessageListRenderer implements ComponentListCellRenderer<Message> { public class MessageListRenderer implements ComponentListCellRenderer<Message> {
@Override @Override
public JComponent getListCellComponent(ComponentList<? extends Message> list, Message value, boolean isSelected) { public JPanel getListCellComponent(ComponentList<? extends Message> list, Message value, boolean isSelected) {
final JPanel panel = new JPanel(); final JPanel panel = new JPanel();
if (isSelected) { final Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
panel.setBackground(Color.DARK_GRAY);
panel.setForeground(Color.RED); // Panel background
// TODO: Selection panel.setBackground(isSelected ? theme.getSelectionColor() : theme.getCellColor());
// setBackground(list.getSelectionBackground());
// setForeground(list.getSelectionForeground());
} else {
panel.setBackground(list.getBackground());
panel.setForeground(list.getForeground());
}
// TODO: Handle message attachments // TODO: Handle message attachments
@ -43,11 +39,11 @@ public class MessageListRenderer implements ComponentListCellRenderer<Message> {
final String state = value.getStatus().toString(); final String state = value.getStatus().toString();
final String date = new SimpleDateFormat("dd.MM.yyyy HH.mm").format(value.getCreationDate()); final String date = new SimpleDateFormat("dd.MM.yyyy HH.mm").format(value.getCreationDate());
// Getting the MessageColor in the Chat of the current theme // Message text color
String textColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat().toHex(); String textColor = theme.getMessageColorChat().toHex();
// Getting the DateColor in the Chat of the current theme // Message date color
String dateColor = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat().toHex(); String dateColor = theme.getDateColorChat().toHex();
panel.add(new JLabel(String.format("<html><p style=\"color:%s\"><b><small>%s</b></small><br><p style=\"color:%s\">%s :%s</html>", panel.add(new JLabel(String.format("<html><p style=\"color:%s\"><b><small>%s</b></small><br><p style=\"color:%s\">%s :%s</html>",
dateColor, dateColor,
@ -57,10 +53,10 @@ public class MessageListRenderer implements ComponentListCellRenderer<Message> {
state))); state)));
// Define some space to the messages below // 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 // Set the width to the list width
Dimension size = new Dimension(list.getWidth() - 25, 50); Dimension size = new Dimension(list.getWidth() - 25, panel.getPreferredSize().height);
panel.setMaximumSize(size); panel.setMaximumSize(size);
panel.setMinimumSize(size); panel.setMinimumSize(size);
panel.setPreferredSize(size); panel.setPreferredSize(size);

View File

@ -1,7 +1,10 @@
package envoy.client.ui.list; package envoy.client.ui.list;
import javax.swing.BoxLayout; import java.awt.event.MouseAdapter;
import javax.swing.JPanel; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
/** /**
* Provides a vertical list layout of components provided in a * Provides a vertical list layout of components provided in a
@ -21,6 +24,8 @@ public class ComponentList<E> extends JPanel {
private ComponentListModel<E> model; private ComponentListModel<E> model;
private ComponentListCellRenderer<E> renderer; private ComponentListCellRenderer<E> renderer;
private int currentSelection = -1;
private static final long serialVersionUID = 1759644503942876737L; private static final long serialVersionUID = 1759644503942876737L;
/** /**
@ -50,22 +55,22 @@ public class ComponentList<E> 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 * @param model the list model to set
* @since Envoy v0.3-alpha * @since Envoy v0.3-alpha
*/ */
public void setModel(ComponentListModel<E> model) { public void setModel(ComponentListModel<E> model) {
// Remove old model // Remove old model
if (this.model != null) if (this.model != null) this.model.setComponentList(null);
this.model.setComponentList(null);
// Synchronize with new model // Synchronize with new model
this.model = model; this.model = model;
if (model != null) { if (model != null) this.model.setComponentList(this);
this.model.setComponentList(this);
synchronizeModel(); synchronizeModel();
} else removeAll();
} }
/** /**
@ -76,8 +81,7 @@ public class ComponentList<E> extends JPanel {
*/ */
public void synchronizeModel() { public void synchronizeModel() {
removeAll(); removeAll();
if (model != null) for (E elem : model) if (model != null) model.forEach(this::add);
add(elem);
} }
/** /**
@ -87,7 +91,83 @@ 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) { void add(E elem) { add(elem, getComponentCount(), false); }
add(renderer.getListCellComponent(this, elem, 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.<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) {
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);
} }
} }

View File

@ -61,7 +61,7 @@ public class EnvoyLog {
* path to use the console and file handlers. * path to use the console and file handlers.
* *
* @param path the path to the loggers to configure * @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) { public static void attach(String path) {
// Get root logger // Get root logger