001package jmri.jmrix.swing;
002
003import java.beans.IndexedPropertyChangeEvent;
004import java.beans.PropertyChangeEvent;
005import java.beans.PropertyChangeListener;
006import java.util.List;
007import javax.swing.AbstractListModel;
008import javax.swing.ComboBoxModel;
009import javax.swing.JComboBox;
010import jmri.InstanceManager;
011import jmri.SystemConnectionMemo;
012
013/**
014 * JComboBox that provides a list of SystemConnectionMemos by user name.
015 *
016 * @author Randall Wood Copyright 2017
017 */
018public class SystemConnectionComboBox extends JComboBox<SystemConnectionMemo> {
019
020    private final SystemConnectionComboBoxModel model = new SystemConnectionComboBoxModel();
021
022    public SystemConnectionComboBox() {
023        super();
024        super.setModel(this.model);
025    }
026
027    public void dispose() {
028        this.model.dispose();
029    }
030
031    private static class SystemConnectionComboBoxModel extends AbstractListModel<SystemConnectionMemo> 
032                        implements ComboBoxModel<SystemConnectionMemo> {
033
034        SystemConnectionMemo selectedItem = null;
035        PropertyChangeListener memoListener = (PropertyChangeEvent evt) -> {
036            switch (evt.getPropertyName()) {
037                case SystemConnectionMemo.USER_NAME:
038                    int index = this.getSource().indexOf(evt.getSource());
039                    this.fireContentsChanged(this, index, index);
040                    break;
041                default:
042                    // do nothing
043                    break;
044            }
045        };
046        PropertyChangeListener imListener = (PropertyChangeEvent evt) -> {
047            if (evt.getSource().equals(InstanceManager.getDefault())) {
048                if (evt instanceof IndexedPropertyChangeEvent) {
049                    IndexedPropertyChangeEvent event = (IndexedPropertyChangeEvent) evt;
050                    if (event.getNewValue() != null) {
051                        ((SystemConnectionMemo) event.getNewValue()).addPropertyChangeListener(memoListener);
052                        this.fireIntervalAdded(this, event.getIndex(), event.getIndex());
053                    } else if (event.getOldValue() != null) {
054                        ((SystemConnectionMemo) event.getOldValue()).removePropertyChangeListener(memoListener);
055                        this.fireIntervalRemoved(this, event.getIndex(), event.getIndex());
056                    }
057                    this.fireContentsChanged(this, event.getIndex(), event.getIndex());
058                } else {
059                    Object item = evt.getNewValue();
060                    if (item == null || item instanceof SystemConnectionMemo) {
061                        SystemConnectionMemo memo = (SystemConnectionMemo) item;
062                        if (memo == null || this.getSource().contains(memo)) {
063                            this.setSelectedItem(memo);
064                        }
065                    }
066                }
067            }
068        };
069
070        public SystemConnectionComboBoxModel() {
071            InstanceManager.addPropertyChangeListener(InstanceManager.getListPropertyName(SystemConnectionMemo.class), imListener);
072            InstanceManager.addPropertyChangeListener(InstanceManager.getDefaultsPropertyName(SystemConnectionMemo.class), imListener);
073            this.getSource().forEach((memo) -> {
074                memo.addPropertyChangeListener(memoListener);
075            });
076        }
077
078        /** {@inheritDoc} */
079        @Override
080        public void setSelectedItem(Object anItem) {  // Object parameter required by interface
081            if ((anItem == null || anItem instanceof SystemConnectionMemo) // anItem is valid in this model
082                    && ((selectedItem != null && !selectedItem.equals(anItem)) // anItem is not selectedItem
083                    || selectedItem == null && anItem != null)) {
084                this.selectedItem = (SystemConnectionMemo) anItem;
085                this.fireContentsChanged(this, -1, -1);
086            }
087        }
088
089        /** {@inheritDoc} */
090        @Override
091        public SystemConnectionMemo getSelectedItem() {
092            return this.selectedItem;
093        }
094
095        /** {@inheritDoc} */
096        @Override
097        public int getSize() {
098            return this.getSource().size();
099        }
100
101        /** {@inheritDoc} */
102        @Override
103        public SystemConnectionMemo getElementAt(int index) {
104            return this.getSource().get(index);
105        }
106
107        public void dispose() {
108            InstanceManager.removePropertyChangeListener(InstanceManager.getListPropertyName(SystemConnectionMemo.class), imListener);
109            InstanceManager.removePropertyChangeListener(InstanceManager.getDefaultsPropertyName(SystemConnectionMemo.class), imListener);
110        }
111
112        private List<SystemConnectionMemo> getSource() {
113            return InstanceManager.getList(SystemConnectionMemo.class);
114        }
115    }
116
117}