package com.ibm.nmon.gui.interval; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; import javax.swing.AbstractListModel; import javax.swing.ComboBoxModel; import com.ibm.nmon.interval.Interval; import com.ibm.nmon.interval.IntervalListener; import com.ibm.nmon.interval.IntervalManager; /** * <p> * Model for selecting from a list of Intervals. Intervals are added and removed only by listening * to the IntervalManager. * </p> * * <p> * This model maintains the intervals in sorted order. * </p> */ final class IntervalComboBoxModel extends AbstractListModel<Interval> implements ComboBoxModel<Interval>, PropertyChangeListener, IntervalListener { private static final long serialVersionUID = -5885429600547069451L; private final IntervalManager manager; private final List<Interval> intervals = new java.util.LinkedList<Interval>(); private Interval selected; public IntervalComboBoxModel(IntervalManager manager) { this.manager = manager; // potential race condition here in that intervals could be added between construction and // the time this model is added as a listener // not worrying about this under the assumption that the user cannot add intervals when then // gui is still being built for (Interval interval : manager.getIntervals()) { intervals.add(interval); } java.util.Collections.sort(intervals); selected = manager.getCurrentInterval(); manager.addListener(this); } @Override public Interval getElementAt(int index) { if (index == 0) { return Interval.DEFAULT; } else { return intervals.get(index - 1); } } @Override public int getSize() { return intervals.size() + 1; } @Override public Object getSelectedItem() { return selected; } @Override public void setSelectedItem(Object anItem) { if (selectionChanged(anItem)) { manager.setCurrentInterval(selected); } } @Override public void intervalAdded(Interval interval) { for (int i = 0; i < intervals.size(); i++) { if (intervals.get(i).compareTo(interval) >= 0) { intervals.add(i, interval); // + 1 to count for DEFAULT fireIntervalAdded(this, i + 1, i + 1); return; } } // have not added yet, just add at the end intervals.add(interval); fireIntervalAdded(this, intervals.size(), intervals.size()); } @Override public void intervalRemoved(Interval interval) { for (int i = 0; i < intervals.size(); i++) { if (intervals.get(i).equals(interval)) { intervals.remove(i); // + 1 to count for DEFAULT fireIntervalRemoved(this, i + 1, i + 1); return; } } } @Override public void intervalsCleared() { intervals.clear(); selected = Interval.DEFAULT; fireContentsChanged(this, 1, Integer.MAX_VALUE); } @Override public void currentIntervalChanged(Interval interval) { if (selectionChanged(interval)) { fireContentsChanged(this, 0, 0); } } @Override public void intervalRenamed(Interval interval) { for (int i = 0; i < intervals.size(); i++) { if (intervals.get(i).equals(interval)) { // + 1 to count for DEFAULT fireContentsChanged(this, i + 1, i + 1); return; } } } private boolean selectionChanged(Object anItem) { // avoid infinite loops in that setSelectedItem needs to call currentIntervalChanged to // alert other listeners but currentIntervalChanged also needs to update the selected item // if the event is coming from another component if (selected.equals(anItem)) { return false; } else if (intervals.contains(anItem)) { selected = (Interval) anItem; return true; } else if (Interval.DEFAULT.equals(anItem)) { selected = Interval.DEFAULT; return true; } else { return false; } } @Override public void propertyChange(PropertyChangeEvent evt) { fireContentsChanged(this, 0, getSize() - 1); } }