|
|
|
@ -3,8 +3,8 @@ package envoy.client.ui.list;
|
|
|
|
|
import java.awt.event.MouseAdapter;
|
|
|
|
|
import java.awt.event.MouseEvent;
|
|
|
|
|
import java.awt.event.MouseListener;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
|
|
import javax.swing.*;
|
|
|
|
|
|
|
|
|
@ -25,15 +25,17 @@ public class ComponentList<E> extends JPanel {
|
|
|
|
|
|
|
|
|
|
private ComponentListModel<E> model;
|
|
|
|
|
private ComponentListCellRenderer<E> renderer;
|
|
|
|
|
private boolean multipleSelectionEnabled = false;
|
|
|
|
|
|
|
|
|
|
private List<Integer> currentSelections = new ArrayList<>();
|
|
|
|
|
private SelectionMode selectionMode = SelectionMode.NONE;
|
|
|
|
|
private Set<Integer> selection = new HashSet<>();
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
* BoxLayout.
|
|
|
|
|
* Initializes a default {@link ComponentList} without a model or a renderer.
|
|
|
|
|
*
|
|
|
|
|
* @since Envoy v0.1-beta
|
|
|
|
|
*/
|
|
|
|
@ -79,8 +81,8 @@ public class ComponentList<E> extends JPanel {
|
|
|
|
|
|
|
|
|
|
// Synchronize with new model
|
|
|
|
|
this.model = model;
|
|
|
|
|
if (model != null) this.model.setComponentList(this);
|
|
|
|
|
if (renderer != null) synchronizeModel();
|
|
|
|
|
if (model != null) model.setComponentList(this);
|
|
|
|
|
synchronizeModel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -92,11 +94,53 @@ public class ComponentList<E> extends JPanel {
|
|
|
|
|
public void synchronizeModel() {
|
|
|
|
|
if (model != null && renderer != null) {
|
|
|
|
|
removeAll();
|
|
|
|
|
model.forEach(this::add);
|
|
|
|
|
model.forEach(this::addElement);
|
|
|
|
|
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
|
|
|
|
|
* {@link ComponentListCellRenderer}.
|
|
|
|
@ -104,89 +148,26 @@ public class ComponentList<E> extends JPanel {
|
|
|
|
|
* @param elem the element to add
|
|
|
|
|
* @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
|
|
|
|
|
* {@link ComponentListRenderer}.
|
|
|
|
|
* {@link ComponentListRenderer}. If the renderer is {@code null}, no action is
|
|
|
|
|
* performed.
|
|
|
|
|
*
|
|
|
|
|
* @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) {
|
|
|
|
|
if (isSelected && !multipleSelectionEnabled) {
|
|
|
|
|
clearSelections();
|
|
|
|
|
currentSelections.add(index);
|
|
|
|
|
}
|
|
|
|
|
private void addElement(E elem, int index, boolean isSelected) {
|
|
|
|
|
if (renderer != null) {
|
|
|
|
|
final JComponent component = renderer.getListCellComponent(this, elem, isSelected);
|
|
|
|
|
component.addMouseListener(getSelectionListener(index));
|
|
|
|
|
add(component, index);
|
|
|
|
|
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) {
|
|
|
|
|
// 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.
|
|
|
|
|
*
|
|
|
|
@ -194,21 +175,33 @@ public class ComponentList<E> extends JPanel {
|
|
|
|
|
* @param isSelected the selection state passed to the {@link ListCellRenderer}
|
|
|
|
|
* @since Envoy v0.1-beta
|
|
|
|
|
*/
|
|
|
|
|
private void updateSelection(int index, boolean isSelected) {
|
|
|
|
|
private void updateElement(int index, boolean isSelected) {
|
|
|
|
|
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
|
|
|
|
|
*/
|
|
|
|
|
public List<E> getSelected() {
|
|
|
|
|
List<E> selected = new ArrayList<>();
|
|
|
|
|
currentSelections.forEach(index -> selected.add(model.get(index)));
|
|
|
|
|
return selected;
|
|
|
|
|
private MouseListener getSelectionListener(int componentIndex) {
|
|
|
|
|
return new MouseAdapter() {
|
|
|
|
|
|
|
|
|
|
@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
|
|
|
|
|
* @since Envoy v0.1-beta
|
|
|
|
@ -228,37 +221,14 @@ public class ComponentList<E> extends JPanel {
|
|
|
|
|
public void setRenderer(ComponentListCellRenderer<E> renderer) { this.renderer = renderer; }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return the multipleSelectionEnabled
|
|
|
|
|
* @return the selectionMode
|
|
|
|
|
* @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
|
|
|
|
|
* the component list
|
|
|
|
|
* @param selectionMode the selectionMode to set
|
|
|
|
|
* @since Envoy v0.1-beta
|
|
|
|
|
*/
|
|
|
|
|
public void setMultipleSelectionEnabled(boolean multipleSelectionEnabled) {
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
public void setSelectionMode(SelectionMode selectionMode) { this.selectionMode = selectionMode; }
|
|
|
|
|
}
|
|
|
|
|