1 46 47 package edu.rice.cs.util.docnavigation; 48 49 import java.awt.*; 50 import javax.swing.*; 51 import javax.swing.event.*; 52 import java.util.*; 53 import edu.rice.cs.util.swing.Utilities; 54 56 65 66 class JListNavigator<ItemT extends INavigatorItem> extends JList implements IDocumentNavigator<ItemT> { 67 68 69 protected DefaultListModel _model; 70 71 72 private volatile ItemT _current = null; 73 74 77 78 private volatile CustomListCellRenderer _renderer; 79 80 81 private final Vector<INavigationListener<? super ItemT>> navListeners = new Vector<INavigationListener<? super ItemT>>(); 82 83 84 public JListNavigator() { 85 super(); 86 init(new DefaultListModel()); 87 } 88 89 private void init(DefaultListModel m) { 90 _model = m; 91 setModel(m); 92 setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 93 addListSelectionListener(new ListSelectionListener() { 94 97 public void valueChanged(final ListSelectionEvent e) { 98 Utilities.invokeLater( new Runnable () { 99 public void run() { 100 if (!e.getValueIsAdjusting() && !_model.isEmpty()) { 101 @SuppressWarnings ("unchecked") final ItemT newItem = (ItemT) getSelectedValue(); 102 if (_current != newItem) { 104 final ItemT oldItem = _current; 105 NodeData<ItemT> oldData = new NodeData<ItemT>() { 106 public <Ret> Ret execute(NodeDataVisitor<? super ItemT, Ret> v, Object ... p) { return v.itemCase(oldItem, p); } 107 }; 108 NodeData<ItemT> newData = new NodeData<ItemT>() { 109 public <Ret> Ret execute(NodeDataVisitor<? super ItemT, Ret> v, Object ... p) { return v.itemCase(newItem, p); } 110 }; 111 for(INavigationListener<? super ItemT> listener: navListeners) { 112 if (oldItem != null) listener.lostSelection(oldData, isNextChangeModelInitiated()); 113 if (newItem != null) listener.gainedSelection(newData, isNextChangeModelInitiated()); 114 } 115 setNextChangeModelInitiated(false); 116 _current = newItem; 117 } 119 } 120 } 121 }); 122 } 123 }); 124 125 _renderer = new CustomListCellRenderer(); 126 _renderer.setOpaque(true); 127 this.setCellRenderer(_renderer); 128 } 129 130 133 public void addDocument(ItemT doc) { synchronized(_model) { _model.addElement(doc); } } 134 135 140 public void addDocument(ItemT doc, String path) { addDocument(doc); } 141 142 146 protected ItemT getFromModel(int i) { 147 @SuppressWarnings ("unchecked") ItemT result = (ItemT) _model.get(i); 148 return result; 149 } 150 151 156 public ItemT getNext(ItemT doc) { 157 synchronized(_model) { 158 int i = _model.indexOf(doc); 159 if (i == -1) 160 throw new IllegalArgumentException ("No such document " + doc.toString() + " found in collection of open documents"); 161 if ( i + 1 == _model.size()) return doc; 162 163 return getFromModel(i + 1); 164 } 165 } 166 167 171 public ItemT getPrevious(ItemT doc) { 172 synchronized(_model) { 173 int i = _model.indexOf(doc); 174 if (i == -1) 175 throw new IllegalArgumentException ("No such document " + doc.toString() + " found in collection of open documents"); 176 if (i == 0) return doc; 177 return getFromModel(i - 1); 178 } 179 } 180 181 184 public ItemT getFirst() { synchronized(_model) { return getFromModel(0); } } 185 186 189 public ItemT getLast() { synchronized(_model) { return getFromModel(_model.size() - 1); } } 190 191 192 public ItemT getCurrent() { return _current; } 193 194 195 public Object getModelLock() { return _model; } 196 197 200 public ItemT removeDocument(ItemT doc) { 201 synchronized(_model) { 202 int i = _model.indexOf(doc); 204 if( i == -1 ) 205 throw new IllegalArgumentException ("Document " + doc + " not found in Document Navigator"); 206 ItemT result = getFromModel(i); 207 _model.remove(i); 208 return result; 209 } 210 } 211 212 218 public void refreshDocument(ItemT doc, String path) { 219 synchronized(_model) { 220 removeDocument(doc); 221 addDocument(doc); 222 } 223 } 224 225 228 public void setActiveDoc(ItemT doc) { 229 synchronized(_model) { 230 if (_current == doc) return; if (_model.contains(doc)) { 232 setSelectedValue(doc, true); 233 } 235 } 236 } 237 238 242 public boolean contains(ItemT doc) { 243 synchronized(_model) { return _model.contains(doc); } 244 } 245 246 251 public Enumeration<ItemT> getDocuments() { 252 synchronized(_model) { 253 @SuppressWarnings ("unchecked") Enumeration<ItemT> result = (Enumeration<ItemT>) _model.elements(); 255 return result; 256 } 257 } 258 259 260 public int getDocumentCount() { return _model.size(); } 261 262 263 public boolean isEmpty() { return _model.isEmpty(); } 264 265 268 public void addNavigationListener(INavigationListener<? super ItemT> listener) { 269 synchronized(_model) { navListeners.add(listener); } 270 } 271 272 275 public void removeNavigationListener(INavigationListener<? super ItemT> listener) { 276 synchronized(_model) { navListeners.remove(listener); } 277 } 278 279 280 public Collection<INavigationListener<? super ItemT>> getNavigatorListeners() { return navListeners; } 281 282 283 public void clear() { synchronized(_model) { _model.clear(); } } 284 285 289 public <InType, ReturnType> ReturnType execute(IDocumentNavigatorAlgo<ItemT, InType, ReturnType> algo, InType input) { 290 return algo.forList(this, input); 291 } 292 293 294 public Container asContainer() { return this; } 295 296 302 public boolean selectDocumentAt(final int x, final int y) { 303 synchronized(_model) { 304 final int idx = locationToIndex(new java.awt.Point (x,y)); 305 java.awt.Rectangle rect = getCellBounds(idx, idx); 306 if (rect.contains(x, y)) { 307 setActiveDoc(getFromModel(idx)); 308 return true; 309 } 310 return false; 311 } 312 } 313 314 315 316 public Component getRenderer(){ return _renderer; } 317 318 319 public boolean isGroupSelected() { return false; } 320 321 322 public boolean isSelectedInGroup(ItemT i) { return false; } 323 324 public void addTopLevelGroup(String name, INavigatorItemFilter<? super ItemT> f) { } 325 326 public boolean isTopLevelGroupSelected() { return false; } 327 328 public String getNameOfSelectedTopLevelGroup() throws GroupNotSelectedException{ 329 throw new GroupNotSelectedException("A top level group is not selected"); 330 } 331 332 335 public void requestSelectionUpdate(ItemT doc) { } 336 337 public String toString() { synchronized(_model) { return _model.toString(); } } 348 349 350 private static class CustomListCellRenderer extends DefaultListCellRenderer { 351 352 359 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) { 360 361 super.getListCellRendererComponent(list, value, index, isSelected, hasFocus); 362 setText(((INavigatorItem)value).getName()); 363 return this; 365 } 366 } 367 368 369 public void setNextChangeModelInitiated(boolean b) { 370 putClientProperty(MODEL_INITIATED_PROPERTY_NAME, b?Boolean.TRUE:null); 371 } 372 373 374 public boolean isNextChangeModelInitiated() { 375 return getClientProperty(MODEL_INITIATED_PROPERTY_NAME)!=null; 376 } 377 } 378 | Popular Tags |