001package jmri.jmrit.display;
002
003import java.awt.Dimension;
004import java.awt.datatransfer.DataFlavor;
005import java.awt.datatransfer.Transferable;
006import java.awt.datatransfer.UnsupportedFlavorException;
007import java.awt.dnd.DnDConstants;
008import java.awt.dnd.DropTarget;
009import java.awt.dnd.DropTargetDragEvent;
010import java.awt.dnd.DropTargetDropEvent;
011import java.awt.dnd.DropTargetEvent;
012import java.awt.dnd.DropTargetListener;
013import java.awt.event.ActionListener;
014import java.io.IOException;
015import java.util.HashMap;
016
017import javax.swing.BorderFactory;
018import javax.swing.Box;
019import javax.swing.BoxLayout;
020import javax.swing.ButtonGroup;
021import javax.swing.JComponent;
022import javax.swing.JLabel;
023import javax.swing.JPanel;
024import javax.swing.JRadioButton;
025import javax.swing.TransferHandler;
026import javax.swing.event.ListSelectionEvent;
027
028import jmri.NamedBeanHandle;
029import jmri.Turnout;
030import jmri.jmrit.catalog.NamedIcon;
031import jmri.util.swing.JmriJOptionPane;
032
033/**
034 * Provides a simple editor for creating a Single or Double Slip Icon object.
035 * Allows drops from icons dragged from a Catalog preview pane. Also implements
036 * dragging a row from the turnout table to be dropped on a turnout label
037 * <p>
038 * To work right, the SlipTurnoutIcon needs to have all images the same size.
039 * Based upon MultiSensorIconAdder by Bob Jacobsen and Pete Cressman
040 *
041 * @author Bob Jacobsen Copyright (c) 2007
042 * @author Kevin Dickerson Copyright (c) 2010
043 *
044 */
045public class SlipIconAdder extends IconAdder {
046
047    HashMap<String, NamedBeanHandle<Turnout>> _turnoutMap = new HashMap<>();
048    int _lastIndex = 0;
049
050    public static final String NamedBeanFlavorMime = DataFlavor.javaJVMLocalObjectMimeType
051            + ";class=jmri.NamedBean";
052
053    public SlipIconAdder() {
054        super();
055    }
056
057    public SlipIconAdder(String type) {
058        super(type);
059    }
060
061    int doubleSlip = 0x00;
062
063    public void setTurnoutType(int dblSlip) {
064        doubleSlip = dblSlip;
065        doubleSlipButton.setSelected(false);
066        singleSlipButton.setSelected(false);
067        threeWayButton.setSelected(false);
068        scissorButton.setSelected(false);
069        switch (dblSlip) {
070            case 0x00:
071                doubleSlipButton.setSelected(true);
072                break;
073            case 0x02:
074                singleSlipButton.setSelected(true);
075                break;
076            case 0x04:
077                threeWayButton.setSelected(true);
078                break;
079            case 0x08:
080                scissorButton.setSelected(true);
081                break;
082            default:
083                log.warn("Unhandled dbslip code: {}", dblSlip);
084                break;
085        }
086    }
087
088    public int getTurnoutType() {
089        return doubleSlip;
090    }
091
092    /** {@inheritDoc} */
093    @Override
094    public void reset() {
095        _turnoutMap = new HashMap<>();
096        _lastIndex = 0;
097        super.reset();
098    }
099
100    JRadioButton doubleSlipButton = new JRadioButton(Bundle.getMessage("DoubleSlip"));
101    JRadioButton singleSlipButton = new JRadioButton(Bundle.getMessage("SingleSlip"));
102    JRadioButton threeWayButton = new JRadioButton(Bundle.getMessage("ThreeWay"));
103    JRadioButton scissorButton = new JRadioButton(Bundle.getMessage("Scissor"));
104
105    JRadioButton singleDirection = new JRadioButton(Bundle.getMessage("SingleSlipRoute"));
106    JRadioButton lowerWestToLowerEastButton = new JRadioButton(Bundle.getMessage("LowerWestToLowerEast"));
107    JRadioButton upperWestToUpperEastButton = new JRadioButton(Bundle.getMessage("UpperWestToUpperEast"));
108
109    /**
110     * {@inheritDoc} First look for a table selection to set the sensor. If not,
111     * then look to change the icon image (super).
112     */
113    @Override
114    public void makeIconPanel(boolean useDefaults) {
115        if (_iconPanel != null) {
116            this.remove(_iconPanel);
117        }
118        //super.makeIconPanel();
119        Dimension dim = null;
120        _iconPanel = new JPanel();
121        _iconPanel.setLayout(new BoxLayout(_iconPanel, BoxLayout.Y_AXIS));
122
123        ButtonGroup typeGroup = new ButtonGroup();
124        typeGroup.add(doubleSlipButton);
125        typeGroup.add(singleSlipButton);
126        typeGroup.add(threeWayButton);
127        typeGroup.add(scissorButton);
128        JPanel _typePanel = new JPanel();
129        _typePanel.add(doubleSlipButton);
130        _typePanel.add(singleSlipButton);
131        _typePanel.add(threeWayButton);
132        _typePanel.add(scissorButton);
133        _iconPanel.add(_typePanel);
134        doubleSlipButton.addActionListener(actionEvent -> slipUpdate(0x00));
135        singleSlipButton.addActionListener(actionEvent -> slipUpdate(0x02));
136        threeWayButton.addActionListener(actionEvent -> slipUpdate(0x04));
137        scissorButton.addActionListener(actionEvent -> slipUpdate(0x08));
138
139        if (lowerWestToLowerEastButton.getActionListeners().length > 0) {
140            lowerWestToLowerEastButton.removeActionListener(lowerWestToLowerEastButton.getActionListeners()[0]);
141        }
142        if (upperWestToUpperEastButton.getActionListeners().length > 0) {
143            upperWestToUpperEastButton.removeActionListener(upperWestToUpperEastButton.getActionListeners()[0]);
144        }
145        if (getTurnoutType() == 0x02) {
146            ButtonGroup group = new ButtonGroup();
147            group.add(lowerWestToLowerEastButton);
148            group.add(upperWestToUpperEastButton);
149            lowerWestToLowerEastButton.setText(Bundle.getMessage("LowerWestToLowerEast"));
150            upperWestToUpperEastButton.setText(Bundle.getMessage("UpperWestToUpperEast"));
151            JPanel _buttonSlipPanel = new JPanel();
152            _buttonSlipPanel.add(lowerWestToLowerEastButton);
153            _buttonSlipPanel.add(upperWestToUpperEastButton);
154            _iconPanel.add(_buttonSlipPanel);
155            lowerWestToLowerEastButton.addActionListener(actionEvent -> updateSingleSlipRoute(false));
156            upperWestToUpperEastButton.addActionListener(actionEvent -> updateSingleSlipRoute(true));
157        } else if (getTurnoutType() == 0x04) {
158            ButtonGroup group = new ButtonGroup();
159            lowerWestToLowerEastButton.setText(Bundle.getMessage("ToLower"));
160            upperWestToUpperEastButton.setText(Bundle.getMessage("ToUpper"));
161            group.add(lowerWestToLowerEastButton);
162            group.add(upperWestToUpperEastButton);
163            JPanel _buttonSlipPanel = new JPanel();
164            _buttonSlipPanel.add(lowerWestToLowerEastButton);
165            _buttonSlipPanel.add(upperWestToUpperEastButton);
166            _iconPanel.add(_buttonSlipPanel);
167        } else if (getTurnoutType() == 0x08) {
168            ButtonGroup group = new ButtonGroup();
169            lowerWestToLowerEastButton.setText("4 Turnouts");
170            upperWestToUpperEastButton.setText("2 Turnouts");
171            group.add(lowerWestToLowerEastButton);
172            group.add(upperWestToUpperEastButton);
173            JPanel _buttonSlipPanel = new JPanel();
174            _buttonSlipPanel.add(lowerWestToLowerEastButton);
175            _buttonSlipPanel.add(upperWestToUpperEastButton);
176            _iconPanel.add(_buttonSlipPanel);
177            lowerWestToLowerEastButton.addActionListener(actionEvent -> changeNumScissorTurnouts());
178            upperWestToUpperEastButton.addActionListener(actionEvent -> changeNumScissorTurnouts());
179        }
180
181        JPanel rowPanel = null;
182        int cnt = 0;
183        int numTurnoutPanels = 2;
184        if ((doubleSlip == 0x08) && (lowerWestToLowerEastButton.isSelected())) {
185            numTurnoutPanels = 4;
186        }
187        for (int i = 0; i < numTurnoutPanels; i++) {
188            if (rowPanel == null) {
189                rowPanel = new JPanel();
190                rowPanel.setLayout(new BoxLayout(rowPanel, BoxLayout.X_AXIS));
191                rowPanel.add(Box.createHorizontalStrut(STRUT_SIZE));
192            }
193
194            JPanel p3 = new DropPanel();
195            p3.setLayout(new BoxLayout(p3, BoxLayout.Y_AXIS));
196            JPanel p4 = new JPanel();
197            String label;
198            String key;
199            NamedBeanHandle<Turnout> turnout;
200            if (i == 0) {
201                if (doubleSlip == 0x04) {
202                    label = Bundle.getMessage("FirstTurnout");
203                } else if (doubleSlip == 0x08) {
204                    if (lowerWestToLowerEastButton.isSelected()) {
205                        label = Bundle.getMessage("UpperWestTurnout");
206                    } else {
207                        label = Bundle.getMessage("RHCrossing");
208                    }
209                } else {
210                    label = Bundle.getMessage("WestTurnout");
211                }
212                key = "west";
213            } else if (i == 1) {
214                key = "east";
215                if (doubleSlip == 0x04) {
216                    label = Bundle.getMessage("SecondTurnout");
217                } else if (doubleSlip == 0x08) {
218                    if (lowerWestToLowerEastButton.isSelected()) {
219                        label = Bundle.getMessage("UpperEastTurnout");
220                    } else {
221                        label = Bundle.getMessage("LHCrossing");
222                    }
223                } else {
224                    label = Bundle.getMessage("EastTurnout");
225                }
226            } else if (i == 2) {
227                key = "lowerwest";
228                label = Bundle.getMessage("LowerWestTurnout");
229            } else {
230                key = "lowereast";
231                label = Bundle.getMessage("LowerEastTurnout");
232            }
233
234            turnout = _turnoutMap.get(key);
235            JLabel k = new JLabel(key);
236            k.setName(key);
237            k.setVisible(false);
238            p3.add(k);
239            p4.add(new JLabel(label));
240            p3.add(p4);
241            p4 = new JPanel();
242            String name = Bundle.getMessage("notSet");
243            java.awt.Color color = java.awt.Color.RED;
244            if (turnout != null) {
245                name = turnout.getName();
246                color = java.awt.Color.BLACK;
247            }
248            p4.setBorder(BorderFactory.createLineBorder(color));
249            p4.add(new JLabel(name));
250            p4.setMaximumSize(p4.getPreferredSize());
251            p3.add(p4);
252
253            JPanel p13 = new JPanel();
254            p13.setLayout(new BoxLayout(p13, BoxLayout.X_AXIS));
255            p13.add(p3);
256
257            JPanel panel = new JPanel();
258            panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
259            panel.add(p13);
260            panel.setBorder(BorderFactory.createLineBorder(java.awt.Color.BLACK));
261
262            rowPanel.add(panel);
263            rowPanel.add(Box.createHorizontalStrut(STRUT_SIZE));
264
265            cnt++;
266            if ((cnt % 2) == 0) {
267                _iconPanel.add(rowPanel);
268                rowPanel = null;
269            }
270            dim = panel.getPreferredSize();
271        }
272        while ((cnt % 2) != 0) {
273            java.util.Objects.requireNonNull(rowPanel, "rowPanel should have been non-null in this case");
274            rowPanel.add(Box.createRigidArea(dim));
275            cnt++;
276        }
277        if (rowPanel != null) {
278            _iconPanel.add(rowPanel);
279            _iconPanel.add(Box.createVerticalStrut(STRUT_SIZE));
280        }
281        rowPanel = new JPanel();
282        rowPanel.setLayout(new BoxLayout(rowPanel, BoxLayout.X_AXIS));
283        rowPanel.add(Box.createHorizontalStrut(STRUT_SIZE));
284        JPanel panel = null;
285        cnt = 0;
286        for (int i = _iconOrderList.size() - 1; i >= 0; i--) {
287            if (panel == null) {
288                panel = new JPanel();
289                panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
290                panel.add(Box.createHorizontalStrut(STRUT_SIZE));
291            }
292            String key = _iconOrderList.get(i);
293            JPanel p = new JPanel();
294            p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
295            p.add(new JLabel(Bundle.getMessage(key)));
296            p.add(_iconMap.get(key));
297            panel.add(p);
298            panel.add(Box.createHorizontalStrut(STRUT_SIZE));
299            if ((cnt & 1) != 0) {
300                _iconPanel.add(panel);
301                _iconPanel.add(Box.createVerticalStrut(STRUT_SIZE));
302                panel = null;
303            }
304            cnt++;
305        }
306        if (panel != null) {
307            _iconPanel.add(panel);
308            _iconPanel.add(Box.createVerticalStrut(STRUT_SIZE));
309        }
310        this.add(_iconPanel, 0);
311        valueChanged(null);
312
313        pack();
314    }
315
316    void changeNumScissorTurnouts() {
317        if (upperWestToUpperEastButton.isSelected()) {
318            _turnoutMap.remove("lowerwest");
319            _turnoutMap.remove("lowereast");
320        }
321        makeIconPanel(true);
322    }
323
324    void slipUpdate(int slip) {
325        //If what we are setting to is the same as already set do nothing.
326        if (slip == doubleSlip) {
327            return;
328        }
329        if ((doubleSlip == 0x04) || (doubleSlip == 0x08)) {
330            delete(4);
331            delete(3);
332            delete(2);
333            _turnoutMap.remove("lowerwest");
334            _turnoutMap.remove("lowereast");
335            //We need to reset the icons back for a slip
336            setIcon(3, "LowerWestToUpperEast",
337                    "resources/icons/smallschematics/tracksegments/os-slip-lower-west-upper-east.gif");
338            setIcon(2, "UpperWestToLowerEast",
339                    "resources/icons/smallschematics/tracksegments/os-slip-upper-west-lower-east.gif");
340            setIcon(4, "LowerWestToLowerEast",
341                    "resources/icons/smallschematics/tracksegments/os-slip-lower-west-lower-east.gif");
342            setIcon(0, "BeanStateInconsistent",
343                    "resources/icons/smallschematics/tracksegments/os-slip-error-full.gif");
344            setIcon(1, "BeanStateUnknown",
345                    "resources/icons/smallschematics/tracksegments/os-slip-unknown-full.gif");
346        }
347
348        if (slip == 0x04) {
349            //We need to setup the base icons for a three way.
350            delete(5);
351            delete(4);
352            delete(3);
353            delete(2);
354            setIcon(3, "Upper",
355                    "resources/icons/smallschematics/tracksegments/os-3way-upper.gif");
356            setIcon(2, "Middle",
357                    "resources/icons/smallschematics/tracksegments/os-3way-middle.gif");
358            setIcon(4, "Lower",
359                    "resources/icons/smallschematics/tracksegments/os-3way-lower.gif");
360            setIcon(0, "BeanStateInconsistent",
361                    "resources/icons/smallschematics/tracksegments/os-3way-error.gif");
362            setIcon(1, "BeanStateUnknown",
363                    "resources/icons/smallschematics/tracksegments/os-3way-unknown.gif");
364            upperWestToUpperEastButton.setSelected(true);
365        } else if (slip == 0x08) {
366            //We need to setup the base icons for a Scissor.
367            delete(5);
368            setIcon(3, "LowerWestToUpperEast",
369                    "resources/icons/smallschematics/tracksegments/os-double-crossover-lower-west-upper-east.gif");
370            setIcon(2, "UpperWestToLowerEast",
371                    "resources/icons/smallschematics/tracksegments/os-double-crossover-upper-west-lower-east.gif");
372            setIcon(4, "LowerWestToLowerEast",
373                    "resources/icons/smallschematics/tracksegments/os-double-crossover-closed.gif");
374
375            setIcon(0, "BeanStateInconsistent",
376                    "resources/icons/smallschematics/tracksegments/os-double-crossover-error.gif");
377            setIcon(1, "BeanStateUnknown",
378                    "resources/icons/smallschematics/tracksegments/os-double-crossover-unknown.gif");
379
380            upperWestToUpperEastButton.setSelected(true);
381        }
382
383        switch (slip) {
384            case 0x00:
385                delete(4);
386                setIcon(4, "LowerWestToLowerEast",
387                        "resources/icons/smallschematics/tracksegments/os-slip-lower-west-lower-east.gif");
388                setIcon(5, "UpperWestToUpperEast",
389                        "resources/icons/smallschematics/tracksegments/os-slip-upper-west-upper-east.gif");
390                break;
391            case 0x02:
392                delete(5);
393                updateSingleSlipRoute(false);
394                break;
395            default:
396                log.warn("Unhandled slip code: {}", slip);
397                break;
398        }
399        doubleSlip = slip;
400        makeIconPanel(true);
401    }
402
403    /**
404     * {@inheritDoc}
405     */
406    @Override
407    public void complete(ActionListener addIconAction, boolean changeIconAction,
408            boolean addToTable, boolean update) {
409        super.complete(addIconAction, changeIconAction, addToTable, update);
410        _table.setDragEnabled(true);
411        _table.setTransferHandler(new ExportHandler());
412        valueChanged(null);
413    }
414
415    class ExportHandler extends TransferHandler {
416
417        /** {@inheritDoc} */
418        @Override
419        public int getSourceActions(JComponent c) {
420            return COPY;
421        }
422
423        /** {@inheritDoc} */
424        @Override
425        public Transferable createTransferable(JComponent c) {
426            return new TransferableNamedBean();
427        }
428
429        /** {@inheritDoc} */
430        @Override
431        public void exportDone(JComponent c, Transferable t, int action) {
432        }
433    }
434
435    class TransferableNamedBean implements Transferable {
436
437        DataFlavor dataFlavor;
438
439        TransferableNamedBean() {
440            try {
441                dataFlavor = new DataFlavor(NamedBeanFlavorMime);
442            } catch (ClassNotFoundException cnfe) {
443                log.error("Unable to find class supporting {}", NamedBeanFlavorMime, cnfe);
444            }
445        }
446
447        /** {@inheritDoc} */
448        @Override
449        public DataFlavor[] getTransferDataFlavors() {
450            //if (log.isDebugEnabled()) log.debug("TransferableNamedBean.getTransferDataFlavors ");
451            return new DataFlavor[]{dataFlavor};
452        }
453
454        /** {@inheritDoc} */
455        @Override
456        public boolean isDataFlavorSupported(DataFlavor flavor) {
457            //if (log.isDebugEnabled()) log.debug("TransferableNamedBean.isDataFlavorSupported ");
458            return dataFlavor.equals(flavor);
459        }
460
461        /** {@inheritDoc} */
462        @Override
463        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
464            if (log.isDebugEnabled()) {
465                log.debug("TransferableNamedBean.getTransferData ");
466            }
467            if (isDataFlavorSupported(flavor)) {
468                return getTableSelection();
469            }
470            return null;
471        }
472    }
473
474    /**
475     * {@inheritDoc} Activate Add to Panel button when all icons are assigned
476     * sensors.
477     */
478    @Override
479    public void valueChanged(ListSelectionEvent e) {
480        if (_addButton == null) {
481            return;
482        }
483        int numTurnouts = 2;
484        if ((doubleSlip == SlipTurnoutIcon.SCISSOR) && (lowerWestToLowerEastButton.isSelected())) {
485            numTurnouts = 4;
486        }
487        if (_turnoutMap.size() == numTurnouts) {
488            _addButton.setEnabled(true);
489            _addButton.setToolTipText(null);
490            //checkIconSizes();
491        } else {
492            _addButton.setEnabled(false);
493            _addButton.setToolTipText(Bundle.getMessage("ToolTipAssignTurnouts"));
494        }
495    }
496
497    void delete(int index) {
498        if (index >= _iconOrderList.size()) {
499            return;
500        }
501        String key = _iconOrderList.get(index);
502        if (log.isDebugEnabled()) {
503            log.debug("delete({}) Sizes: _iconMap= {}, _iconOrderList= {}", index, _iconMap.size(), _iconOrderList.size());
504        }
505        _iconMap.remove(key);
506        _iconOrderList.remove(index);
507    }
508
509    /**
510     * Returns a new NamedIcon object for your own use. see NamedIcon
511     * getIcon(String key) in super
512     *
513     * @param index of key
514     * @return Unique object
515     */
516    public NamedIcon getIcon(int index) {
517        return (NamedIcon) _iconMap.get(_iconOrderList.get(index)).getIcon();
518    }
519
520    /**
521     * Returns a Turnout object for your own use. see NamedIcon getIcon(String
522     * key) in super
523     *
524     * @param index of key
525     * @return Unique object
526     */
527    public NamedBeanHandle<Turnout> getTurnout(String index) {
528        return _turnoutMap.get(index);
529    }
530
531    public void setTurnout(String key, NamedBeanHandle<Turnout> turnout) {
532        _turnoutMap.put(key, turnout);
533    }
534
535    void updateSingleSlipRoute(boolean single) {
536        delete(4);
537        if (single) {
538            upperWestToUpperEastButton.setSelected(true);
539            setIcon(4, "Slip",
540                    "resources/icons/smallschematics/tracksegments/os-slip-upper-west-upper-east.gif");
541        } else {
542            lowerWestToLowerEastButton.setSelected(true);
543            setIcon(4, "Slip",
544                    "resources/icons/smallschematics/tracksegments/os-slip-lower-west-lower-east.gif");
545        }
546        makeIconPanel(true);
547    }
548
549    public void setSingleSlipRoute(boolean single) {
550        if (single) {
551            upperWestToUpperEastButton.setSelected(true);
552        } else {
553            lowerWestToLowerEastButton.setSelected(true);
554        }
555    }
556
557    public boolean getSingleSlipRoute() {
558        if (upperWestToUpperEastButton.isSelected()) {
559            return true;
560        } else {
561            return false;
562        }
563    }
564
565    private boolean putTurnout(String key, Turnout turnout) {
566        String name = turnout.getUserName();
567        if (name == null) {
568            name = turnout.getSystemName();
569        }
570        for (NamedBeanHandle<Turnout> turnoutNamedBeanHandle : _turnoutMap.values()) {
571            if (name.equals(turnoutNamedBeanHandle.getName())) {
572                JmriJOptionPane.showMessageDialog(this, java.text.MessageFormat.format(Bundle.getMessage("DupTurnoutName"), name),
573                    Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE);
574                return false;
575            }
576        }
577        _turnoutMap.put(key, jmri.InstanceManager.getDefault(jmri.NamedBeanHandleManager.class).getNamedBeanHandle(name, turnout));
578        return true;
579    }
580
581    /**
582     * Enables the active Slip icons to receive dragged icons
583     */
584    class DropPanel extends JPanel implements DropTargetListener {
585
586        DataFlavor dataFlavor;
587
588        DropPanel() {
589            try {
590                dataFlavor = new DataFlavor(NamedBeanFlavorMime);
591            } catch (ClassNotFoundException cnfe) {
592                log.error("Unable to find class supporting {}", NamedBeanFlavorMime, cnfe);
593            }
594            new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
595        }
596
597        /** {@inheritDoc} */
598        @Override
599        public void dragExit(DropTargetEvent dte) {
600        }
601
602        /** {@inheritDoc} */
603        @Override
604        public void dragEnter(DropTargetDragEvent dtde) {
605        }
606
607        /** {@inheritDoc} */
608        @Override
609        public void dragOver(DropTargetDragEvent dtde) {
610            //if (log.isDebugEnabled()) log.debug("DropPanel.dragOver");
611        }
612
613        /** {@inheritDoc} */
614        @Override
615        public void dropActionChanged(DropTargetDragEvent dtde) {
616        }
617
618        /** {@inheritDoc} */
619        @Override
620        public void drop(DropTargetDropEvent e) {
621            try {
622                Transferable tr = e.getTransferable();
623                if (e.isDataFlavorSupported(dataFlavor)) {
624                    Turnout turnout = (Turnout) tr.getTransferData(dataFlavor);
625                    if (turnout != null) {
626                        e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
627                        DropTarget target = (DropTarget) e.getSource();
628                        JPanel panel = (JPanel) target.getComponent();
629                        JComponent comp = (JLabel) panel.getComponent(0);
630                        if (putTurnout(comp.getName(), turnout)) {
631                            makeIconPanel(true);
632                        }
633                        e.dropComplete(true);
634                        if (log.isDebugEnabled()) {
635                            log.debug("DropPanel.drop COMPLETED for {}", comp.getName());
636                        }
637                    } else {
638                        if (log.isDebugEnabled()) {
639                            log.debug("DropPanel.drop REJECTED!");
640                        }
641                        e.rejectDrop();
642                    }
643                }
644            } catch (IOException | UnsupportedFlavorException ioe) {
645                if (log.isDebugEnabled()) {
646                    log.debug("DropPanel.drop REJECTED!");
647                }
648                e.rejectDrop();
649            }
650        }
651    }
652
653    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SlipIconAdder.class);
654
655}