package net.sf.openrocket.gui.adaptors; import java.util.EventObject; import java.util.HashMap; import java.util.Map; import javax.swing.ComboBoxModel; import javax.swing.event.EventListenerList; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import net.sf.openrocket.formatting.RocketDescriptor; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.Configuration; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.StateChangeListener; /** * A ComboBoxModel that contains a list of flight configurations. The list can * optionally contain a last element that opens up the configuration edit dialog. */ public class FlightConfigurationModel implements ComboBoxModel, StateChangeListener { private static final Translator trans = Application.getTranslator(); private RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class); private EventListenerList listenerList = new EventListenerList(); private final Configuration config; private final Rocket rocket; private Map<String, ID> map = new HashMap<String, ID>(); public FlightConfigurationModel(Configuration config) { this.config = config; this.rocket = config.getRocket(); config.addChangeListener(this); } @Override public Object getElementAt(int index) { String[] ids = rocket.getFlightConfigurationIDs(); if (index < 0) return null; if ( index >= ids.length) return null; return get(ids[index]); } @Override public int getSize() { return rocket.getFlightConfigurationIDs().length; } @Override public Object getSelectedItem() { return get(config.getFlightConfigurationID()); } @Override public void setSelectedItem(Object item) { if (item == null) { // Clear selection - huh? return; } if (!(item instanceof ID)) { throw new IllegalArgumentException("MotorConfigurationModel item=" + item); } ID idObject = (ID) item; config.setFlightConfigurationID(idObject.getID()); } //////////////// Event/listener handling //////////////// @Override public void addListDataListener(ListDataListener l) { listenerList.add(ListDataListener.class, l); } @Override public void removeListDataListener(ListDataListener l) { listenerList.remove(ListDataListener.class, l); } protected void fireListDataEvent() { Object[] listeners = listenerList.getListenerList(); ListDataEvent e = null; for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ListDataListener.class) { if (e == null) e = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, getSize()); ((ListDataListener) listeners[i + 1]).contentsChanged(e); } } } @Override public void stateChanged(EventObject e) { if (e instanceof ComponentChangeEvent) { // Ignore unnecessary changes if (!((ComponentChangeEvent) e).isMotorChange()) return; } fireListDataEvent(); } /* * The ID class is an adapter, that contains the actual configuration ID, * but gives the configuration description as its String representation. * The get(id) method retrieves ID objects and caches them for reuse. */ private ID get(String id) { ID idObject = map.get(id); if (idObject != null) return idObject; idObject = new ID(id); map.put(id, idObject); return idObject; } private class ID { private final String id; public ID(String id) { this.id = id; } public String getID() { return id; } @Override public String toString() { return descriptor.format(rocket, id); } } }