001package arcommon.ui.component; 002 003import java.awt.Dimension; 004import java.util.ArrayList; 005import java.util.Iterator; 006import java.util.List; 007 008import javax.swing.AbstractListModel; 009import javax.swing.JComponent; 010import javax.swing.JList; 011import javax.swing.ListModel; 012import javax.swing.ListSelectionModel; 013import javax.swing.event.ListDataEvent; 014import javax.swing.event.ListDataListener; 015import javax.swing.event.ListSelectionEvent; 016import javax.swing.event.ListSelectionListener; 017 018import arcommon.ArrayUtil; 019 020/** 021 * A {@link javax.swing.JList<String>} that is wrapped in a {@link javax.swing.JScrollPane}. 022 * <br> 023 * NOTE: The {@link #removeAll()} method has been overwritten to remove all items, which is NOT what the API says!! 024 */ 025public class MyJList extends AbstractDelegatingJScrollPane { 026 027 private ArrayList<ListSelectionListener> listSelectionListeners; 028 private ListSelectionListener myListSelectionListener; 029 private boolean updateInProgress; 030 private JList<String> jlist; 031 private ArrayList<String> items; 032 private AbstractListModel<String> listModel; 033 034 public MyJList() { 035 jlist = new JList<String>(); 036 037 initActionMap(); 038 039 setViewportView(jlist); 040 041 items = new ArrayList<String>(); 042 043 listModel = new AbstractListModel<String>() { 044 private static final long serialVersionUID = -8769269893116663354L; 045 046 public String getElementAt(int index) { 047 return items.get(index); 048 } 049 050 public int getSize() { 051 return items.size(); 052 } 053 }; 054 055 jlist.setModel(listModel); 056 jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 057 058 setPreferredSize(new Dimension(25, 25)); 059 } 060 061 public void addListSelectionListener(ListSelectionListener plistSelectionListener) { 062 if (myListSelectionListener == null) { 063 myListSelectionListener = new ListSelectionListener() { 064 public void valueChanged(ListSelectionEvent e) { 065 eventListValueChanged(e); 066 } 067 }; 068 jlist.addListSelectionListener(myListSelectionListener); 069 } 070 if (listSelectionListeners == null) { 071 listSelectionListeners = new ArrayList<ListSelectionListener>(); 072 } 073 listSelectionListeners.add(plistSelectionListener); 074 } 075 076 public void removeListSelectionListener(ListSelectionListener plistSelectionListener) { 077 if (listSelectionListeners == null) { 078 return ; 079 } 080 listSelectionListeners.remove(plistSelectionListener); 081 if (listSelectionListeners.size() == 0) { 082 listSelectionListeners = null; 083 jlist.removeListSelectionListener(myListSelectionListener); 084 listSelectionListeners = null; 085 } 086 } 087 088 private void eventListValueChanged(ListSelectionEvent e) { 089 if (listSelectionListeners == null || updateInProgress || e.getValueIsAdjusting()) { 090 return ; 091 } 092 093 Iterator<ListSelectionListener> i = listSelectionListeners.iterator(); 094 while (i.hasNext()) { 095 ListSelectionListener tempListSelectionListener = i.next(); 096 tempListSelectionListener.valueChanged(e); 097 } 098 } 099 100 public void addAll(List<String> newItems) { 101 items.addAll(newItems); 102 update(); 103 } 104 105 public void add(String item) { 106 items.add(item); 107 update(); 108 } 109 110 public void add(int index, String item) { 111 items.add(index, item); 112 update(); 113 } 114 115 public void remove(String item) { 116 items.remove(item); 117 update(); 118 } 119 120 public String removeItem(int index) { 121 String removed = items.remove(index); 122 update(); 123 return removed; 124 } 125 126 public ListModel<String> getModel() { 127 return listModel; 128 } 129 130 private void update() { 131 ListDataEvent e = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, 0); 132 ListDataListener[] listListDataListeners = listModel.getListDataListeners(); 133 for (int i = 0; i < listListDataListeners.length; i++) { 134 listListDataListeners[i].contentsChanged(e); 135 } 136 } 137 138 public int getItemCount() { 139 return items.size(); 140 } 141 142 public String getItem(int index) { 143 return items.get(index); 144 } 145 146 public int getSelectedIndex() { 147 int index = jlist.getSelectedIndex(); 148 if (index >= getItemCount()) { 149 return -1; 150 } 151 return index; 152 } 153 154 public int[] getSelectedIndices() { 155 return jlist.getSelectedIndices(); 156 } 157 158 public String getSelectedValue() { 159 if (getSelectedIndex() == -1) { 160 return null; 161 } 162 return jlist.getSelectedValue(); 163 } 164 165 public List<String> getSelectedValuesList() { 166 return jlist.getSelectedValuesList(); 167 } 168 169 public void setSelectedIndex(int index) { 170 updateInProgress = true; 171 if (index == -1) { 172 jlist.removeSelectionInterval(0, items.size() - 1); 173 } else { 174 jlist.setSelectedIndex(index); 175 } 176 updateInProgress = false; 177 } 178 179 public void addSelectedIndex(int index) { 180 updateInProgress = true; 181 if (index == -1) { 182 throw new RuntimeException("index == -1"); 183 } 184 jlist.addSelectionInterval(index, index); 185 updateInProgress = false; 186 } 187 188 public void setSelectedIndices(int[] indices) { 189 updateInProgress = true; 190 jlist.clearSelection(); 191 for (int index : indices) { 192 jlist.addSelectionInterval(index, index); 193 } 194 updateInProgress = false; 195 } 196 197 public void ensureSelectedIsVisible() { 198 int[] selectedIndices = getSelectedIndices(); 199 if (selectedIndices.length == 0) { 200 return ; 201 } 202 203 int firstVisibleIndex = jlist.getFirstVisibleIndex(); 204 int lastVisibleIndex = jlist.getLastVisibleIndex(); 205 if (firstVisibleIndex == -1 || lastVisibleIndex == -1) { 206 return ; 207 } 208 209 int minimum = ArrayUtil.min(selectedIndices); 210 int maximum = ArrayUtil.max(selectedIndices); 211 int selectedDiff = maximum - minimum; 212 int visibleDiff = lastVisibleIndex - firstVisibleIndex; 213 if (selectedDiff < visibleDiff) { 214 ensureIndexIsVisible(minimum - 1); 215 ensureIndexIsVisible(maximum + 1); 216 return ; 217 } 218 219 for (int i = 0; i < selectedIndices.length; i++) { 220 if (selectedIndices[i] >= firstVisibleIndex && selectedIndices[i] <= lastVisibleIndex) { 221 return ; 222 } 223 } 224 225 if (firstVisibleIndex > maximum) { 226 ensureIndexIsVisible(maximum - 1); 227 return ; 228 } 229 230 if (lastVisibleIndex < minimum) { 231 ensureIndexIsVisible(minimum + 1); 232 return ; 233 } 234 235 ensureIndexIsVisible(minimum - 1); 236 } 237 238 public void ensureIndexIsVisible(int index) { 239 if (index < 0) { 240 index = 0; 241 } 242 if (index > items.size() - 1) { 243 index = items.size() - 1; 244 } 245 jlist.ensureIndexIsVisible(index); 246 } 247 248 public void removeAll() { 249 items.clear(); 250 update(); 251 } 252 253 public void setSelectMulti(boolean selectMulti) { 254 if (selectMulti) { 255 jlist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 256 } else { 257 jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 258 } 259 } 260 261 @Override 262 protected JComponent getDelegatingJComponent() { 263 return jlist; 264 } 265 266 private static final long serialVersionUID = -6971893970210035428L; 267}