How to prevent SeparatorList.Separator from being selected in JList?

I created a JList using GrazedLists, in particular an EventList, which I then pass to a SeparatorList using a special Comparator that sorts my EventList elements. I am using DefaultEventListModel as a JList model, passing my SeparatorList. And I use my own CellRenderer to decorate the SeparatorList.Separator cells. Everything displays beautifully, I see a beautifully formatted list, grouped as I like, similar to optgroups in HTML SELECT elements.

Now I would like to prevent the selection of Separator cells.

I see examples of overriding DefaultComboBoxModel. However, I do not know how to override DefaultListSelectionModel or DefaultEventListModel.

Here is an example of the code that I still have:

public class MyFrame extends javax.swing.JFrame { private final EventList<BibleVersion> bibleVersions; private final SeparatorList<BibleVersion> versionsByLang; public MyFrame(){ bibleVersions = new BasicEventList<>(); bibleVersions.add(new BibleVersion("CEI2008", "Testo della Conferenza Episcopale Italiana", "2008", "Italian")); bibleVersions.add(new BibleVersion("LUZZI", "Diodati Nuova Riveduta - Luzzi", "1927", "Italian")); bibleVersions.add(new BibleVersion("NVBSE", "Nova Vulgata - Bibliorum Sacrorum Editio", "1979", "Latin")); bibleVersions.add(new BibleVersion("NABRE", "New American Bible - Revised Edition", "2011", "English")); bibleVersions.add(new BibleVersion("KJV", "King James Version", "1611", "English")); versionsByLang = new SeparatorList<>(bibleVersions, new VersionComparator(),1, 1000); jList = new javax.swing.JList(); jList.setModel(new DefaultEventListModel<>(versionsByLang)); jList.setCellRenderer(new VersionCellRenderer()); } public static class BibleVersion { private String abbrev; private String fullname; private String year; private String lang; public BibleVersion(String abbrev, String fullname, String year, String lang) { this.abbrev = abbrev; this.fullname = fullname; this.year = year; this.lang = lang; } public String getAbbrev() { return abbrev; } public void setAbbrev(String abbrev) { this.abbrev = abbrev; } public String getFullname() { return fullname; } public void setFullname(String fullname) { this.fullname = fullname; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public String getLang() { return lang; } public void setLang(String lang) { this.lang = lang; } @Override public String toString() { return this.getAbbrev() + " — " + this.getFullname() + " (" + this.getYear() + ")"; //To change body of generated methods, choose Tools | Templates. } } private static class VersionComparator implements Comparator<BibleVersion> { @Override public int compare(BibleVersion o1, BibleVersion o2) { return o1.getLang().compareTo(o2.getLang()); } } private static class VersionCellRenderer extends DefaultListCellRenderer{ @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof SeparatorList.Separator) { SeparatorList.Separator separator = (SeparatorList.Separator) value; BibleVersion bibleversion = (BibleVersion)separator.getGroup().get(0); String lbl = "-- " + bibleversion.getLang() + " --"; label.setText(lbl); label.setFont(label.getFont().deriveFont(Font.BOLD)); label.setBackground(Color.LIGHT_GRAY); label.setBorder(BorderFactory.createEmptyBorder(0,5,0,0)); } else { label.setFont(label.getFont().deriveFont(Font.PLAIN)); label.setBorder(BorderFactory.createEmptyBorder(0,15,0,0)); } return label; } } } 

Now, how can I change the value of DefaultEventListModel (or ListSelectionModel)? Which of them do I need to override, or perhaps DefaultListSelectionModel? ListSelectionModel seems to have many methods that need to be overridden to handle the MULTIPLE_INTERVAL selection (this is my case). I'm not quite sure where to start ...

0
java override jlist selection glazedlists
source share
1 answer

Through some trial and error, based on the code suggestions that I found in https://stackoverflow.com/a/166642/2 and building them up, I was able to build something that now works quite well. I had to change the logic in a related example. Basically I go between the selected indexes and check one by one if they are "included" indexes, and if so, I am "addSelectionInterval" for that index only. I do this for both the setSelectionInterval method and the addSelectionInterval method. Thus, basically you never add a selection in the form of a block, always one at a time, iterating over the selection block and checking one by one if they are included for selection or not.

 public class MyFrame extends javax.swing.JFrame { private final EventList<BibleVersion> bibleVersions; private final SeparatorList<BibleVersion> versionsByLang; private boolean[] enabledFlags; public MyFrame(){ bibleVersions = new BasicEventList<>(); bibleVersions.add(new BibleVersion("CEI2008", "Testo della Conferenza Episcopale Italiana", "2008", "Italian")); bibleVersions.add(new BibleVersion("LUZZI", "Diodati Nuova Riveduta - Luzzi", "1927", "Italian")); bibleVersions.add(new BibleVersion("NVBSE", "Nova Vulgata - Bibliorum Sacrorum Editio", "1979", "Latin")); bibleVersions.add(new BibleVersion("NABRE", "New American Bible - Revised Edition", "2011", "English")); bibleVersions.add(new BibleVersion("KJV", "King James Version", "1611", "English")); versionsByLang = new SeparatorList<>(bibleVersions, new VersionComparator(),1, 1000); int listLength = versionsByLang.size(); enabledFlags = new boolean[listLength]; ListIterator itr = versionsByLang.listIterator(); while(itr.hasNext()){ enabledFlags[itr.nextIndex()] = !(itr.next().getClass().getSimpleName().equals("GroupSeparator")); } jList = new javax.swing.JList(); jList.setModel(new DefaultEventListModel<>(versionsByLang)); jList.setCellRenderer(new VersionCellRenderer()); jList.setSelectionModel(new DisabledItemSelectionModel()); ListSelectionModel listSelectionModel = jList.getSelectionModel(); listSelectionModel.addListSelectionListener(new SharedListSelectionHandler()); } public static class BibleVersion { private String abbrev; private String fullname; private String year; private String lang; public BibleVersion(String abbrev, String fullname, String year, String lang) { this.abbrev = abbrev; this.fullname = fullname; this.year = year; this.lang = lang; } public String getAbbrev() { return abbrev; } public void setAbbrev(String abbrev) { this.abbrev = abbrev; } public String getFullname() { return fullname; } public void setFullname(String fullname) { this.fullname = fullname; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public String getLang() { return lang; } public void setLang(String lang) { this.lang = lang; } @Override public String toString() { return this.getAbbrev() + " — " + this.getFullname() + " (" + this.getYear() + ")"; //To change body of generated methods, choose Tools | Templates. } } private static class VersionComparator implements Comparator<BibleVersion> { @Override public int compare(BibleVersion o1, BibleVersion o2) { return o1.getLang().compareTo(o2.getLang()); } } private static class VersionCellRenderer extends DefaultListCellRenderer{ @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof SeparatorList.Separator) { SeparatorList.Separator separator = (SeparatorList.Separator) value; BibleVersion bibleversion = (BibleVersion)separator.getGroup().get(0); String lbl = "-- " + bibleversion.getLang() + " --"; label.setText(lbl); label.setFont(label.getFont().deriveFont(Font.BOLD)); label.setBackground(Color.decode("#004400")); label.setBorder(BorderFactory.createEmptyBorder(0,5,0,0)); label.setEnabled(false); } else { label.setFont(label.getFont().deriveFont(Font.PLAIN)); label.setBorder(BorderFactory.createEmptyBorder(0,15,0,0)); } return label; } } private class DisabledItemSelectionModel extends DefaultListSelectionModel { private static final long serialVersionUID = 1L; @Override public void setSelectionInterval(int index0, int index1) { if(index0 < index1){ for (int i = index0; i <= index1; i++){ if(enabledFlags[i]){ super.addSelectionInterval(i, i); } } } else if(index1 < index0){ for (int i = index1; i <= index0; i++){ if(enabledFlags[i]){ super.addSelectionInterval(i, i); } } } else if(index0 == index1){ if(enabledFlags[index0]){ super.setSelectionInterval(index0,index0); } } } @Override public void addSelectionInterval(int index0, int index1) { if(index0 < index1){ for (int i = index0; i <= index1; i++){ if(enabledFlags[i]){ super.addSelectionInterval(i, i); } } } else if(index1 < index0){ for (int i = index1; i <= index0; i++){ if(enabledFlags[i]){ super.addSelectionInterval(i, i); } } } else if(index0 == index1){ if(enabledFlags[index0]){ super.addSelectionInterval(index0,index0); } } } } private class SharedListSelectionHandler implements ListSelectionListener { @Override public void valueChanged(ListSelectionEvent e) { ListSelectionModel lsm = (ListSelectionModel)e.getSource(); StringBuilder output = new StringBuilder(); int firstIndex = e.getFirstIndex(); int lastIndex = e.getLastIndex(); boolean isAdjusting = e.getValueIsAdjusting(); output.append("Event for indexes "); output.append(firstIndex); output.append(" - "); output.append(lastIndex); output.append("; isAdjusting is "); output.append(isAdjusting); output.append("; selected indexes:"); if (lsm.isSelectionEmpty()) { output.append(" <none>"); } else { // Find out which indexes are selected. int minIndex = lsm.getMinSelectionIndex(); int maxIndex = lsm.getMaxSelectionIndex(); for (int i = minIndex; i <= maxIndex; i++) { if (lsm.isSelectedIndex(i)) { output.append(" "); output.append(i); } } } output.append(System.getProperty("line.separator")); System.out.println(output.toString()); } } } 

Written in such a way that it works perfectly, disabled cells are not selected with a CTRL click, and a SHIFT click works very well. One click clears the list and selects only the item with a click if it is included for selection.

0
source share

All Articles