001package jmri.jmrix.can.cbus.swing;
002
003import java.awt.datatransfer.DataFlavor;
004import java.awt.datatransfer.Transferable;
005import java.awt.datatransfer.UnsupportedFlavorException;
006import java.awt.event.ActionEvent;
007import java.io.IOException;
008import javax.swing.*;
009
010import jmri.NamedBean;
011import jmri.jmrix.can.cbus.CbusAddress;
012import jmri.jmrix.can.swing.CanPanel;
013import jmri.jmrix.can.cbus.CbusMessage;
014import jmri.jmrix.can.cbus.CbusNameService;
015import jmri.util.swing.JmriJOptionPane;
016
017/**
018 * Panel to Create Turnouts, Sensor and Lights from CBUS event via drop action.
019 *
020 * @author Steve Young Copyright (C) 2020
021 */
022public class CbusCreateBeanPane extends JPanel {
023
024    private final CanPanel _mainPane;
025    private JLabel beanLabel;
026    private JPanel editPanel;
027    private JTextField beanUsername;
028    private final CbusNameService nameservice;
029    private NamedBean bean;
030    private JButton editUserNameButton;
031    protected CbTransferHandler[] transferArray;
032
033    public CbusCreateBeanPane(CanPanel mainPane){
034        super();
035        _mainPane = mainPane;
036        nameservice = new CbusNameService(mainPane.getMemo());
037        init();
038    }
039
040    private void init() {
041
042        transferArray = new CbTransferHandler[3];
043
044        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
045        setBorder(BorderFactory.createTitledBorder(
046            BorderFactory.createEtchedBorder(), Bundle.getMessage("CreateNew"))); // NOI18N
047
048        add(getNewDragPanel());
049        add(getEditPane());
050    }
051
052    private JPanel getNewDragPanel(){
053
054        JPanel dragContainer = new JPanel();
055        dragContainer.setToolTipText(Bundle.getMessage("DragHereForNew")); // NOI18N
056        dragContainer.setLayout(new BoxLayout(dragContainer, BoxLayout.X_AXIS));
057
058        for (int i =0; i<3; i++){
059            StringBuilder sb = new StringBuilder();
060            sb.append("<html><h2>")
061            .append(getManagerByIndex(i).getBeanTypeHandled() )
062            .append("</h2></html>"); // NOI18N
063            JLabel newBealLabel = new JLabel(sb.toString());
064            newBealLabel.setBorder(BorderFactory.createEtchedBorder());
065            newBealLabel.setHorizontalAlignment(SwingConstants.CENTER);
066            transferArray[i] = new CbTransferHandler();
067            newBealLabel.setTransferHandler(transferArray[i]);
068            dragContainer.add(newBealLabel);
069        }
070        return dragContainer;
071    }
072
073    private JPanel getEditPane(){
074
075        editPanel = new JPanel();
076        editPanel.setLayout(new BoxLayout(editPanel, BoxLayout.X_AXIS));
077        editPanel.setBorder(BorderFactory.createTitledBorder(
078            BorderFactory.createEtchedBorder(), Bundle.getMessage("TslDetails"))); // NOI18N
079
080        beanUsername = new JTextField(20);
081        beanUsername.setDropTarget(null);
082        beanUsername.setMinimumSize(new java.awt.Dimension(60,16));
083
084        beanLabel = new JLabel();
085
086        editUserNameButton = new JButton(Bundle.getMessage("EditUserName")); // NOI18N
087        editUserNameButton.setToolTipText(Bundle.getMessage("EditUNameTip")); // NOI18N
088        editUserNameButton.addActionListener((ActionEvent e) -> {
089            String newUname = beanUsername.getText();
090            bean.setUserName(newUname);
091            showSaveReminder();
092        });
093
094        setEditPaneActive(false);
095
096        editPanel.add(beanLabel);
097        editPanel.add(beanUsername);
098        editPanel.add(editUserNameButton);
099        return editPanel;
100    }
101
102    private void setEditPaneActive( boolean enabled){
103        editPanel.setEnabled(enabled);
104        beanUsername.setEnabled(enabled);
105        editUserNameButton.setEnabled(enabled);
106    }
107
108    /**
109     * Handles drop actions containing CBUS event.
110     */
111    protected class CbTransferHandler extends javax.swing.TransferHandler {
112        /**
113         * {@inheritDoc}
114         */
115        @Override
116        public boolean canImport(JComponent c, DataFlavor[] transferFlavors) {
117            for (DataFlavor flavor : transferFlavors) {
118                if (DataFlavor.stringFlavor.equals(flavor)) {
119                    return true;
120                }
121            }
122            return false;
123        }
124
125        /**
126         * {@inheritDoc}
127         */
128        @Override
129        public boolean importData(JComponent c, Transferable t) {
130            if (canImport(c, t.getTransferDataFlavors())) {
131
132                String validatedAddr;
133                jmri.ProvidingManager<?> mgrClass;
134
135                // do some validation on the input string
136                // processed in the same way as a sensor, turnout or light so less chance of breaking in future
137                // and can also accept the Hex "X9001020304;X9101020304" format
138                try {
139                    validatedAddr = CbusAddress.validateSysName(
140                        (String) t.getTransferData(DataFlavor.stringFlavor) );
141                    mgrClass = classMgrInString(((JLabel)c).getText());
142                } catch (UnsupportedFlavorException | IOException | IllegalArgumentException | ClassCastException e) {
143                    return false;
144                }
145
146                int nn = CbusMessage.getNodeNumber(new CbusAddress(validatedAddr).makeMessage(0));
147                int en = CbusMessage.getEvent(new CbusAddress(validatedAddr).makeMessage(0));
148
149                boolean dirty = false;
150
151                bean = mgrClass.getBySystemName(validatedAddr);
152                if ( bean == null) {
153                    dirty = true;
154                    bean = mgrClass.provide(validatedAddr);
155                    bean.setUserName(nameservice.getEventName(nn, en));
156                }
157                setEditPaneActive(true);
158                resetBeanText(bean, dirty, nn, en );
159                return true;
160            }
161            return false;
162        }
163    }
164
165    private jmri.ProvidingManager<?> classMgrInString(String dropLocation){
166        for (int i =0; i<3; i++){
167            if (dropLocation.contains(
168                getManagerByIndex(i).getBeanTypeHandled())){
169                return getManagerByIndex(i);
170            }
171        }
172        throw new IllegalArgumentException("Unable to get Bean Type");
173    }
174
175    private jmri.ProvidingManager<?> getManagerByIndex(int index){
176        switch (index) {
177            case 0:
178                return _mainPane.getMemo().get(jmri.TurnoutManager.class);
179            case 1:
180                return _mainPane.getMemo().get(jmri.SensorManager.class);
181            case 2:
182                return _mainPane.getMemo().get(jmri.LightManager.class);
183            default:
184                throw new IllegalArgumentException("Unable to get Manager from Index" + index);
185        }
186    }
187
188    private void resetBeanText(NamedBean bean, boolean tableChanged, int nn, int en ){
189
190        beanLabel.setText(bean.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME));
191        editPanel.setBorder(BorderFactory.createTitledBorder(
192      BorderFactory.createEtchedBorder(), nameservice.getEventNodeString(nn,en)));
193        beanUsername.setText(bean.getUserName());
194
195        if (tableChanged) {
196            showSaveReminder();
197        }
198    }
199
200    private boolean showReminder = true;
201    private final boolean checkEnabled = jmri.InstanceManager.getDefault(jmri.configurexml.ShutdownPreferences.class).isStoreCheckEnabled();
202
203    /**
204     * Show reminder to save Bean Table.
205     */
206    private void showSaveReminder() {
207        if (showReminder && !checkEnabled) {
208            JCheckBox checkbox = new JCheckBox(Bundle.getMessage("HideFurtherDialog"));
209            Object[] params = {Bundle.getMessage("SavePanelReminder"), checkbox};
210            JmriJOptionPane.showMessageDialog (_mainPane, params,
211          Bundle.getMessage("ReminderTitle"), JmriJOptionPane.INFORMATION_MESSAGE);
212            showReminder=!checkbox.isSelected();
213        }
214    }
215
216    // private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusCreateBeanPane.class);
217}