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