001package jmri.jmrit.display.palette;
002
003import java.awt.BorderLayout;
004import java.awt.datatransfer.DataFlavor;
005import java.awt.datatransfer.UnsupportedFlavorException;
006import java.io.IOException;
007import java.util.HashMap;
008import java.util.Map.Entry;
009import javax.swing.JButton;
010import javax.swing.JLabel;
011import javax.swing.JOptionPane;
012import javax.swing.JPanel;
013import javax.swing.JScrollPane;
014import javax.swing.SwingConstants;
015import javax.swing.event.ListSelectionEvent;
016import jmri.SignalHead;
017import jmri.jmrit.catalog.DragJLabel;
018import jmri.jmrit.catalog.NamedIcon;
019import jmri.jmrit.display.DisplayFrame;
020import jmri.jmrit.display.Editor;
021import jmri.jmrit.display.SignalHeadIcon;
022import jmri.jmrit.picker.PickListModel;
023import org.slf4j.Logger;
024import org.slf4j.LoggerFactory;
025
026public class SignalHeadItemPanel extends TableItemPanel<SignalHead> {
027
028    public SignalHeadItemPanel(DisplayFrame parentFrame, String type, String family, PickListModel<SignalHead> model) {
029        super(parentFrame, type, family, model);
030    }
031
032    @Override
033    protected JPanel initTablePanel(PickListModel<SignalHead> model) {
034        _table = model.makePickTable();
035        JPanel topPanel = new JPanel();
036        topPanel.setLayout(new BorderLayout());
037        topPanel.add(new JLabel(model.getName(), SwingConstants.CENTER), BorderLayout.NORTH);
038        _scrollPane = new JScrollPane(_table);
039        topPanel.add(_scrollPane, BorderLayout.CENTER);
040        _table.getSelectionModel().addListSelectionListener(this);
041        _table.setToolTipText(Bundle.getMessage("ToolTipDragTableRow"));
042        _scrollPane.setToolTipText(Bundle.getMessage("ToolTipDragTableRow"));
043        topPanel.setToolTipText(Bundle.getMessage("ToolTipDragTableRow"));
044        JPanel panel = new JPanel();
045        JButton clearSelectionButton = new JButton(Bundle.getMessage("ClearSelection"));
046        clearSelectionButton.addActionListener(a -> _table.clearSelection());
047        clearSelectionButton.setToolTipText(Bundle.getMessage("ToolTipClearSelection"));
048        panel.add(clearSelectionButton);
049        topPanel.add(panel, BorderLayout.SOUTH);
050        return topPanel;
051    }
052
053    @Override
054    protected String getDisplayKey() {
055        return "SignalHeadStateGreen";
056    }
057
058    /**
059     * ListSelectionListener action.
060     */
061    @Override
062    public void valueChanged(ListSelectionEvent e) {
063        if (_table == null || _updateButton == null) {
064            return;
065        }
066        int row = _table.getSelectedRow();
067        // Index error if only one row
068        if (_table.getRowCount() < 2) {
069            log.debug("Table valueChanged: row= {}, {}({})",
070                    row, _table.getValueAt(row, 0), _table.getValueAt(row, 1));
071        }
072        if (row >= 0) {
073            _updateButton.setEnabled(true);
074            _updateButton.setToolTipText(null);
075            if (_family != null) {
076                // get raw map of all appearances for row's head type.
077                HashMap<String, NamedIcon> fullmap = getFilteredIconMap(makeNewIconMap(_itemType));
078                // icon map of appearances for type of current bean.
079                HashMap<String, NamedIcon> currentmap = (getIconMap());
080                log.debug("currentmap keys = {}", currentmap.keySet().toString());
081                // use current images for as many of the fullMap's members as possible
082                HashMap<String, NamedIcon> iconMap = new HashMap<>();
083                for (Entry<String, NamedIcon> entry : fullmap.entrySet()) {
084                    String key = entry.getKey();
085                    String newKey = ItemPalette.convertText(key);
086                    log.debug("fullmap key = {}, converts to {}", key, newKey);
087                    NamedIcon icon = currentmap.get(newKey);
088                    if (icon != null) {
089                        iconMap.put(newKey, icon);
090                    } else {
091                        iconMap.put(newKey, entry.getValue());
092                    }
093                }
094                log.debug("set Signal Head {} map size= {}", _table.getValueAt(row, 0), iconMap.size());
095//                _currentIconMap = iconMap;
096                updateFamiliesPanel();
097            }
098        } else {
099            _updateButton.setEnabled(false);
100            _updateButton.setToolTipText(Bundle.getMessage("ToolTipPickFromTable"));
101        }
102        if (_iconPanel.isVisible()) {
103            showIcons();
104        }
105    }
106
107    protected HashMap<String, NamedIcon> getFilteredIconMap(HashMap<String, NamedIcon> allIconsMap) {
108        if (allIconsMap == null) {
109            JOptionPane.showMessageDialog(_frame,
110                    Bundle.getMessage("FamilyNotFound", _itemType, _family),
111                    Bundle.getMessage("WarningTitle"), JOptionPane.WARNING_MESSAGE);
112            return null;
113        }
114        if (_table == null || _table.getSelectedRow() < 0) {
115            return allIconsMap;
116        }
117
118        SignalHead sh = getDeviceNamedBean();
119        if (sh != null) {
120            String[] states = sh.getValidStateNames();
121            if (states.length == 0) {
122                return allIconsMap;
123            }
124            HashMap<String, NamedIcon> iconMap = new HashMap<>();
125            for (Entry<String, NamedIcon> entry : allIconsMap.entrySet()) {
126                String name = entry.getKey();
127                String borderName = ItemPalette.convertText(name);
128                for (String state : states) {
129                    if (borderName.equals(state) || name.equals("SignalHeadStateDark") 
130                            || name.equals(ItemPalette.convertText("SignalHeadStateDark")) 
131                            || name.equals("SignalHeadStateHeld") 
132                            || name.equals(ItemPalette.convertText("SignalHeadStateHeld"))) {
133                        iconMap.put(name, entry.getValue());
134                        break;
135                    }
136                }
137            }
138            log.debug("filteredMap size= {}", iconMap.size());
139            return iconMap;
140        }
141        log.debug("Map NOT filtered, size= {}", allIconsMap.size());
142        return allIconsMap;
143    }
144
145    @Override
146    protected JLabel getDragger(DataFlavor flavor, HashMap<String,
147            NamedIcon> map, NamedIcon icon) {
148        return new IconDragJLabel(flavor, map, icon);
149    }
150
151    protected class IconDragJLabel extends DragJLabel {
152
153        HashMap<String, NamedIcon> iMap;
154
155        public IconDragJLabel(DataFlavor flavor, HashMap<String, NamedIcon> map,
156                NamedIcon icon) {
157            super(flavor, icon);
158            iMap = map;
159        }
160
161        @Override
162        protected boolean okToDrag() {
163            SignalHead bean = getDeviceNamedBean();
164            if (bean == null) {
165                JOptionPane.showMessageDialog(this, Bundle.getMessage("noRowSelected"),
166                        Bundle.getMessage("WarningTitle"), JOptionPane.WARNING_MESSAGE);
167                return false;
168            }
169            return true;
170        }
171
172        @Override
173        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
174            if (!isDataFlavorSupported(flavor)) {
175                return null;
176            }
177            SignalHead bean = getDeviceNamedBean();
178            if (bean == null) {
179                return null;
180            }
181
182            if (flavor.isMimeTypeEqual(Editor.POSITIONABLE_FLAVOR)) {
183                SignalHeadIcon sh = new SignalHeadIcon(_frame.getEditor());
184                sh.setSignalHead(bean.getDisplayName());
185                HashMap<String, NamedIcon> map = getFilteredIconMap(iMap);
186                for (Entry<String, NamedIcon> ent : map.entrySet()) {
187                    sh.setIcon(ent.getKey(), new NamedIcon(ent.getValue()));
188                }
189                sh.setFamily(_family);
190                sh.setLevel(Editor.SIGNALS);
191                return sh;
192            } else if (DataFlavor.stringFlavor.equals(flavor)) {
193                return _itemType + " icons for \"" + bean.getDisplayName() + "\"";
194            }
195            return null;
196        }
197    }
198
199    private final static Logger log = LoggerFactory.getLogger(SignalHeadItemPanel.class);
200}