package cryodex.widget; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.SpringLayout; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; public class DoubleList<T extends Comparable<T>> extends JPanel { private static final long serialVersionUID = 1L; private static final String filterHint = "Filter Player List"; private JList<T> list1; private JList<T> list2; private DefaultListModel<T> listModel1; private DefaultListModel<T> listModel2; private JButton to2; private JButton to1; private JButton allTo2; private JButton allTo1; private JLabel list1Label; private JLabel list2Label; private JPanel buttonPanel; private String list1LabelText = ""; private String list2LabelText = ""; private JTextField filterList1; private List<T> list1Prefiltered = new ArrayList<>(); private List<T> list1Filtered = new ArrayList<>(); private boolean filtering = false; public DoubleList() { this(null, null, "", ""); } public DoubleList(List<T> values1, List<T> values2, String label1, String label2) { super(new BorderLayout()); list1LabelText = label1; list2LabelText = label2; if (values1 != null) { Collections.sort(values1); for (T element : values1) { getModel1().addElement(element); } } if (values2 != null) { Collections.sort(values2); for (T element : values2) { getModel2().addElement(element); } } updateLabels(); buildWidget(); } public void setValues(List<T> values1, List<T> values2) { getModel1().removeAllElements(); getModel2().removeAllElements(); if (values1 != null) { for (T element : values1) { getModel1().addElement(element); } } if (values2 != null) { for (T element : values2) { getModel2().addElement(element); } } updateLabels(); } private void buildWidget() { JScrollPane listScroller1 = new JScrollPane(getList1()); listScroller1.setPreferredSize(new Dimension(150, 250)); JScrollPane listScroller2 = new JScrollPane(getList2()); listScroller2.setPreferredSize(new Dimension(150, 250)); this.add(ComponentUtils.addToVerticalBorderLayout(getList1Label(), listScroller1, null), BorderLayout.WEST); this.add(ComponentUtils.addToVerticalBorderLayout(null, new JLabel(), getButtonPanel()), BorderLayout.CENTER); this.add(ComponentUtils.addToVerticalBorderLayout(getList2Label(), listScroller2, null), BorderLayout.EAST); } private JPanel getButtonPanel() { if (buttonPanel == null) { buttonPanel = new JPanel(new SpringLayout()); buttonPanel.add(ComponentUtils.addToFlowLayout(getList1FilterInput(), FlowLayout.CENTER)); buttonPanel.add(ComponentUtils.addToFlowLayout(getTo2(), FlowLayout.CENTER)); buttonPanel.add(ComponentUtils.addToFlowLayout(getAllTo2(), FlowLayout.CENTER)); buttonPanel.add(ComponentUtils.addToFlowLayout(getAllTo1(), FlowLayout.CENTER)); buttonPanel.add(ComponentUtils.addToFlowLayout(getTo1(), FlowLayout.CENTER)); SpringUtilities.makeCompactGrid(buttonPanel, buttonPanel.getComponentCount(), 1, 1, 1, 1, 20); } return buttonPanel; } public JLabel getList1Label() { if (list1Label == null) { list1Label = new JLabel(list1LabelText); } return list1Label; } public JLabel getList2Label() { if (list2Label == null) { list2Label = new JLabel(list2LabelText); } return list2Label; } public void setList1LabelText(String labelText) { list1LabelText = labelText; } public void setList2LabelText(String labelText) { list2LabelText = labelText; } public void updateLabels() { getList1Label().setText(list1LabelText + "(" + getModel1().getSize() + ")"); getList2Label().setText(list2LabelText + "(" + getModel2().getSize() + ")"); } private JButton getTo2() { if (to2 == null) { to2 = new JButton("Selected >"); to2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { List<T> list1 = getList1Values(); List<T> list2 = getList2Values(); List<T> selected = getList1().getSelectedValuesList(); getList1().clearSelection(); list1.removeAll(selected); list2.addAll(selected); getModel1().removeAllElements(); getModel2().removeAllElements(); Collections.sort(list1); Collections.sort(list2); for (T element : list1) { getModel1().addElement(element); } for (T element : list2) { getModel2().addElement(element); } updateLabels(); list1Prefiltered = getList1Values(); } }); } return to2; } private JButton getTo1() { if (to1 == null) { to1 = new JButton("< Selected"); to1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { List<T> list1 = getList1Values(); List<T> list2 = getList2Values(); List<T> selected = getList2().getSelectedValuesList(); getList2().clearSelection(); list2.removeAll(selected); list1.addAll(selected); getModel1().removeAllElements(); getModel2().removeAllElements(); Collections.sort(list1); Collections.sort(list2); for (T element : list1) { getModel1().addElement(element); } for (T element : list2) { getModel2().addElement(element); } updateLabels(); list1Prefiltered = getList1Values(); } }); } return to1; } private JButton getAllTo2() { if (allTo2 == null) { allTo2 = new JButton("All >>"); allTo2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { List<T> list1 = getList1Values(); List<T> list2 = getList2Values(); list2.addAll(list1); getModel1().removeAllElements(); getModel2().removeAllElements(); Collections.sort(list2); for (T element : list2) { getModel2().addElement(element); } updateLabels(); list1Prefiltered = getList1Values(); } }); } return allTo2; } private JButton getAllTo1() { if (allTo1 == null) { allTo1 = new JButton("<< All"); allTo1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { List<T> list1 = getList1Values(); List<T> list2 = getList2Values(); list1.addAll(list2); getModel1().removeAllElements(); getModel2().removeAllElements(); Collections.sort(list1); for (T element : list1) { getModel1().addElement(element); } updateLabels(); list1Prefiltered = getList1Values(); } }); } return allTo1; } private DefaultListModel<T> getModel1() { if (listModel1 == null) { listModel1 = new DefaultListModel<T>(); } return listModel1; } private DefaultListModel<T> getModel2() { if (listModel2 == null) { listModel2 = new DefaultListModel<T>(); } return listModel2; } private JList<T> getList1() { if (list1 == null) { list1 = new JList<T>(getModel1()); list1.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); list1.setLayoutOrientation(JList.VERTICAL); list1.setVisibleRowCount(-1); } return list1; } private JList<T> getList2() { if (list2 == null) { list2 = new JList<T>(getModel2()); list2.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); list2.setLayoutOrientation(JList.VERTICAL); list2.setVisibleRowCount(-1); } return list2; } public List<T> getList1Values() { return Collections.list(getModel1().elements()); } public List<T> getList2Values() { return Collections.list(getModel2().elements()); } public JTextField getList1FilterInput() { if (filterList1 == null) { list1Prefiltered = getList1Values(); filterList1 = new JTextField(filterHint, 10); filterList1.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { if (filterList1.getText().equals(filterHint)) { filterList1.setText(""); } } @Override public void focusLost(FocusEvent e) { if (filterList1.getText().trim().equals("")) { filterList1.setText(filterHint); } } }); filterList1.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { filterList1(filterList1.getText().toLowerCase().trim()); } @Override public void removeUpdate(DocumentEvent e) { filterList1(filterList1.getText().toLowerCase().trim()); } @Override public void changedUpdate(DocumentEvent e) { filterList1(filterList1.getText().toLowerCase().trim()); } }); } return filterList1; } /** * Filter list to only include elements whose toString function contains the filterText. Elements that have a word * that starts with the filter text are given priority. */ private void filterList1(String filterText) { // Prevent the function from multiple simultaneous executions if (!filtering) { filtering = true; getModel1().removeAllElements(); // Reset list for blank filter if (filterText.equals("") || filterText.equalsIgnoreCase(filterHint)) { for (T element : list1Prefiltered) { getModel1().addElement(element); } updateLabels(); } else { list1Filtered.clear(); // Check the beginning of each word for (T element : list1Prefiltered) { String[] name = element.toString().toLowerCase().split(" "); for (String s : name) { if (s.startsWith(filterText)) { list1Filtered.add(element); break; } } } // Check if the element contains the text for (T element : list1Prefiltered) { if (element.toString().contains(filterText) && !list1Filtered.contains(element)) { list1Filtered.add(element); } } // Add all matching elements to the list for (T element : list1Filtered) { getModel1().addElement(element); } updateLabels(); } filtering = false; } } }