001: package prefuse.data.query;
002:
003: import java.util.ArrayList;
004:
005: import javax.swing.DefaultListSelectionModel;
006: import javax.swing.MutableComboBoxModel;
007: import javax.swing.event.ListDataEvent;
008: import javax.swing.event.ListDataListener;
009:
010: import prefuse.util.collections.CopyOnWriteArrayList;
011:
012: /**
013: * List data model supporting both data modeling and selection management.
014: * Though generally useful, this has been designed particularly to support
015: * dynamic queries.
016: *
017: * @author <a href="http://jheer.org">jeffrey heer</a>
018: */
019: public class ListModel extends DefaultListSelectionModel implements
020: MutableComboBoxModel {
021: private ArrayList m_items = new ArrayList();
022: private CopyOnWriteArrayList m_lstnrs = new CopyOnWriteArrayList();
023:
024: /**
025: * Create an empty ListModel.
026: */
027: public ListModel() {
028: // do nothing
029: }
030:
031: /**
032: * Create a ListModel with the provided items.
033: * @param items the items for the data model.
034: */
035: public ListModel(final Object[] items) {
036: for (int i = 0; i < items.length; ++i)
037: m_items.add(items[i]);
038: }
039:
040: // --------------------------------------------------------------------
041:
042: /**
043: * Indicates if the ListModel currently has multiple selections.
044: * @return true if there are multiple selections, false otherwise
045: */
046: private boolean isMultipleSelection() {
047: return getMaxSelectionIndex() - getMinSelectionIndex() > 0;
048: }
049:
050: /**
051: * @see javax.swing.ComboBoxModel#getSelectedItem()
052: */
053: public Object getSelectedItem() {
054: int idx = getMinSelectionIndex();
055: return (idx == -1 ? null : m_items.get(idx));
056: }
057:
058: /**
059: * @see javax.swing.ComboBoxModel#setSelectedItem(java.lang.Object)
060: */
061: public void setSelectedItem(Object item) {
062: int idx = m_items.indexOf(item);
063: if (idx < 0)
064: return;
065:
066: if (!isMultipleSelection() && idx == getMinSelectionIndex())
067: return;
068:
069: super .setSelectionInterval(idx, idx);
070: fireDataEvent(this , ListDataEvent.CONTENTS_CHANGED, -1, -1);
071: }
072:
073: /**
074: * @see javax.swing.ListModel#getSize()
075: */
076: public int getSize() {
077: return m_items.size();
078: }
079:
080: /**
081: * @see javax.swing.ListModel#getElementAt(int)
082: */
083: public Object getElementAt(int idx) {
084: return m_items.get(idx);
085: }
086:
087: /**
088: * @see javax.swing.MutableComboBoxModel#addElement(java.lang.Object)
089: */
090: public void addElement(Object item) {
091: m_items.add(item);
092: int sz = m_items.size() - 1;
093: fireDataEvent(this , ListDataEvent.INTERVAL_ADDED, sz, sz);
094: if (sz >= 0 && isSelectionEmpty() && item != null)
095: setSelectedItem(item);
096: }
097:
098: /**
099: * @see javax.swing.MutableComboBoxModel#insertElementAt(java.lang.Object, int)
100: */
101: public void insertElementAt(Object item, int idx) {
102: m_items.add(idx, item);
103: fireDataEvent(this , ListDataEvent.INTERVAL_ADDED, idx, idx);
104: }
105:
106: /**
107: * @see javax.swing.MutableComboBoxModel#removeElement(java.lang.Object)
108: */
109: public void removeElement(Object item) {
110: int idx = m_items.indexOf(item);
111: if (idx >= 0)
112: removeElementAt(idx);
113: }
114:
115: /**
116: * @see javax.swing.MutableComboBoxModel#removeElementAt(int)
117: */
118: public void removeElementAt(int idx) {
119: if (!isMultipleSelection() && idx == getMinSelectionIndex()) {
120: int sidx = (idx == 0 ? getSize() == 1 ? -1 : idx + 1
121: : idx - 1);
122: Object sel = (sidx == -1 ? null : m_items.get(sidx));
123: setSelectedItem(sel);
124: }
125:
126: m_items.remove(idx);
127: fireDataEvent(this , ListDataEvent.INTERVAL_REMOVED, idx, idx);
128: }
129:
130: // --------------------------------------------------------------------
131: // List Data Listeners
132:
133: /**
134: * @see javax.swing.ListModel#addListDataListener(javax.swing.event.ListDataListener)
135: */
136: public void addListDataListener(ListDataListener l) {
137: if (!m_lstnrs.contains(l))
138: m_lstnrs.add(l);
139: }
140:
141: /**
142: * @see javax.swing.ListModel#removeListDataListener(javax.swing.event.ListDataListener)
143: */
144: public void removeListDataListener(ListDataListener l) {
145: m_lstnrs.remove(l);
146: }
147:
148: /**
149: * Fires a change notification in response to changes in the ListModel.
150: */
151: protected void fireDataEvent(Object src, int type, int idx0,
152: int idx1) {
153: Object[] lstnrs = m_lstnrs.getArray();
154: if (lstnrs.length > 0) {
155: ListDataEvent e = new ListDataEvent(src, type, idx0, idx1);
156: for (int i = 0; i < lstnrs.length; ++i) {
157: ((ListDataListener) lstnrs[i]).contentsChanged(e);
158: }
159: }
160: }
161:
162: } // end of class ListModel
|