001package jmri.jmrit.display.controlPanelEditor;
002
003import java.awt.Component;
004import java.awt.Dimension;
005import java.beans.PropertyChangeEvent;
006import java.beans.PropertyChangeListener;
007import java.util.ArrayList;
008import java.util.List;
009import javax.swing.AbstractListModel;
010import javax.swing.JLabel;
011import javax.swing.JList;
012import javax.swing.ListCellRenderer;
013
014import org.slf4j.Logger;
015import org.slf4j.LoggerFactory;
016
017import jmri.NamedBean;
018import jmri.jmrit.logix.OBlock;
019import jmri.jmrit.logix.Portal;
020
021/**
022 *
023 * @author Pete Cressman Copyright: Copyright (c) 2020
024 *
025 */
026public class SignalList extends JList<SignalPair> {
027
028    private final SignalListModel _signalListModel;
029
030    SignalList(OBlock block, EditFrame parent) {
031        super();
032        _signalListModel = new SignalListModel(block, parent);
033        setModel(_signalListModel);
034        setCellRenderer(new SignalCellRenderer());
035        setPreferredSize(new Dimension(300, 120));
036        setVisibleRowCount(5);
037    }
038
039    void dataChange() {
040        _signalListModel.dataChange();
041    }
042
043    void setSelected(Portal portal) {
044        for (SignalPair sp : _signalListModel._list) {
045            if (sp._portal.equals(portal)) {
046                setSelectedValue(sp, true);
047                return;
048            }
049        }
050        clearSelection();
051    }
052
053    private static class SignalCellRenderer extends JLabel implements ListCellRenderer<SignalPair>{
054
055        @Override
056        public Component getListCellRendererComponent(
057                JList<? extends SignalPair> list, // the list
058                SignalPair value, // value to display
059                int index, // cell index
060                boolean isSelected, // is the cell selected
061                boolean cellHasFocus) // does the cell have focus
062        {
063            setText(value.getDiscription());
064            if (isSelected) {
065                setBackground(list.getSelectionBackground());
066                setForeground(list.getSelectionForeground());
067            } else {
068                setBackground(list.getBackground());
069                setForeground(list.getForeground());
070            }
071            setEnabled(list.isEnabled());
072            setFont(list.getFont());
073            setOpaque(true);
074            return this;
075        }
076    }
077
078    static class SignalListModel extends AbstractListModel<SignalPair> implements PropertyChangeListener {
079
080        OBlock _homeBlock;
081        private final EditFrame _parent;
082        List<SignalPair> _list = new ArrayList<>();
083
084        SignalListModel(OBlock block, EditFrame parent) {
085            _homeBlock = block;
086            _parent = parent;
087            _homeBlock.addPropertyChangeListener(this);
088            makeList();
089        }
090
091        private void makeList() {
092            for (SignalPair sp : _list) {
093                sp._portal.removePropertyChangeListener(this);
094            }
095            _list.clear();
096            for (Portal portal : _homeBlock.getPortals()) {
097                NamedBean signal = portal.getSignalProtectingBlock(_homeBlock);
098                if (signal != null) {
099                    _list.add(new SignalPair(signal, portal));
100                }
101            }
102            for (SignalPair sp : _list) {
103                sp._portal.addPropertyChangeListener(this);
104            }
105        }
106
107        @Override
108        public int getSize() {
109            return _list.size();
110        }
111
112        @Override
113        public SignalPair getElementAt(int index) {
114            if (index < getSize()) {
115                return _list.get(index);
116            }
117            return null;
118        }
119
120        public void dataChange() {
121            fireContentsChanged(this, 0, 0);
122        }
123
124        @Override
125        public void propertyChange(PropertyChangeEvent e) {
126            Object source = e.getSource();
127            String property = e.getPropertyName();
128            if (log.isDebugEnabled()) {
129                log.debug("property = {} source= {}", property, source.getClass().getName());                
130            }
131            if (source instanceof OBlock && property.equals("deleted")) {
132                _homeBlock.removePropertyChangeListener(this);
133                _parent.closingEvent(true);
134            } else {
135                makeList();
136                fireContentsChanged(this, 0, 0);
137                if (property.equals("signalChange") || property.equals("NameChange")) {
138                    _parent.clearListSelection();
139                }
140            }
141        }
142    }
143    private final static Logger log = LoggerFactory.getLogger(SignalList.class);
144}